我正在研究一个利用光流技术来估计无人机位置的项目.我目前有一个代码,它使用来自远背的OpenCV算法。当摄像机总是指向地面时,当前的代码工作正常。
现在,我想增加对情况的支持,当相机不是直接指向向下--这意味着四翼直升机现在有一个俯仰/滚动/偏航(欧拉角)。四边形欧拉角已知,我正在寻找一种方法,以计算和应用所需的转换,根据已知的欧拉角。这样,结果图像就会像从上面获取的图像一样(见下面的图像)。
我发现了通过findHomography或getPerspectiveTransform函数从OpenCV获得4个角的2组(源和目的地)时计算转换的方法。但是我找不到任何方法可以只知道Euler角(因为我不知道目标图像corenrs)。
因此,我的问题是,我可以使用什么方法,以及如何将一个框架转换成好像是从上面取下来的,如果有必要的话,只使用欧拉角和摄像机的高度?
为了证明我所需要的:

我当前代码的相关部分如下:
for(;;)
{
Mat m, disp, warp;
vector<Point2f> corners;
// take out frame- still distorted
cap >> origFrame;
// undistort the frame using the calibration parameters
cv::undistort(origFrame, undistortFrame, cameraMatrix, distCoeffs, noArray());
// lower the process effort by transforming the picture to gray
cvtColor(undistortFrame, gray, COLOR_BGR2GRAY);
if( !prevgray.empty() )
{
// calculate flow
calcOpticalFlowFarneback(prevgray, gray, uflow, 0.5, 3/*def 3 */, 10/* def 15*/, 3, 3, 1.2 /* def 1.2*/, 0);
uflow.copyTo(flow);
// get average
calcAvgOpticalFlow(flow, 16, corners);
// calculate range of view - 2*tan(fov/2)*distance
rovX = 2*0.44523*distanceSonar*100; // 2 * tan(48/2) * dist(cm)
rovY = 2*0.32492*distanceSonar*100; // 2 * tan(36/2) * dist(cm)
// calculate final x, y location
location[0] += (currLocation.x/WIDTH_RES)*rovX;
location[1] += (currLocation.y/HEIGHT_RES)*rovY;
}
//break conditions
if(waitKey(1)>=0)
break;
if(end_run)
break;
std::swap(prevgray, gray);
} 更新:
成功地添加了旋转后,我仍然需要我的图像是居中的(并且不要超出框架窗口,如下所示)。我想我需要翻译一下。--我希望源图像的中心位于目标图像的中心。,我也可以添加这个吗?
工作的旋转功能:
void rotateFrame(const Mat &input, Mat &output, Mat &A , double roll, double pitch, double yaw){
Mat Rx = (Mat_<double>(3, 3) <<
1, 0, 0,
0, cos(roll), -sin(roll),
0, sin(roll), cos(roll));
Mat Ry = (Mat_<double>(3, 3) <<
cos(pitch), 0, sin(pitch),
0, 1, 0,
-sin(pitch), 0, cos(pitch));
Mat Rz = (Mat_<double>(3, 3) <<
cos(yaw), -sin(yaw), 0,
sin(yaw), cos(yaw), 0,
0, 0, 1);
Mat R = Rx*Ry*Rz;
Mat trans = A*R*A.inv();
warpPerspective(input, output, trans, input.size());
}当我使用rotateFrame(origFrame, processedFrame, cameraMatrix, 0, 0, 0);运行它时,我得到了预期的映像:

但是当我以10度的滚动rotateFrame(origFrame, processedFrame, cameraMatrix, 20*(M_PI/180), 0, 0);运行它时。图像正在从框架窗口中移出:

发布于 2016-05-17 14:55:42
我得出的结论是,为了得到我想要的东西,我必须使用4x4单形矩阵。为了找到正确的同形矩阵,我们需要:
R。A1及其逆矩阵A2。T通过乘以X,Y,Z轴的旋转矩阵,我们可以合成三维旋转矩阵R:
Mat R = RZ * RY * RX 为了将转换应用于图像并保持其中心位置,我们需要添加由4x4矩阵提供的转换,其中dx=0; dy=0; dz=1:
Mat T = (Mat_<double>(4, 4) <<
1, 0, 0, dx,
0, 1, 0, dy,
0, 0, 1, dz,
0, 0, 0, 1);给定所有这些矩阵,我们可以组成我们的同形矩阵H。
Mat H = A2 * (T * (R * A1))有了这个同形矩阵,我们就可以使用来自OpenCV的warpPerspective函数来应用转换。
warpPerspective(input, output, H, input.size(), INTER_LANCZOS4);关于这个解决方案的结论和完整性,这里是完整的代码:
void rotateImage(const Mat &input, UMat &output, double roll, double pitch, double yaw,
double dx, double dy, double dz, double f, double cx, double cy)
{
// Camera Calibration Intrinsics Matrix
Mat A2 = (Mat_<double>(3,4) <<
f, 0, cx, 0,
0, f, cy, 0,
0, 0, 1, 0);
// Inverted Camera Calibration Intrinsics Matrix
Mat A1 = (Mat_<double>(4,3) <<
1/f, 0, -cx/f,
0, 1/f, -cy/f,
0, 0, 0,
0, 0, 1);
// Rotation matrices around the X, Y, and Z axis
Mat RX = (Mat_<double>(4, 4) <<
1, 0, 0, 0,
0, cos(roll), -sin(roll), 0,
0, sin(roll), cos(roll), 0,
0, 0, 0, 1);
Mat RY = (Mat_<double>(4, 4) <<
cos(pitch), 0, sin(pitch), 0,
0, 1, 0, 0,
-sin(pitch), 0, cos(pitch), 0,
0, 0, 0, 1);
Mat RZ = (Mat_<double>(4, 4) <<
cos(yaw), -sin(yaw), 0, 0,
sin(yaw), cos(yaw), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1);
// Translation matrix
Mat T = (Mat_<double>(4, 4) <<
1, 0, 0, dx,
0, 1, 0, dy,
0, 0, 1, dz,
0, 0, 0, 1);
// Compose rotation matrix with (RX, RY, RZ)
Mat R = RZ * RY * RX;
// Final transformation matrix
Mat H = A2 * (T * (R * A1));
// Apply matrix transformation
warpPerspective(input, output, H, input.size(), INTER_LANCZOS4);
}结果:

发布于 2016-05-13 11:43:38
如果您有一个校准本质矩阵A (3x3),并且没有在camara体式之间进行转换,那么您只需要找到对应的H (3x3)到从欧拉角度构造旋转矩阵R (3x3)并应用以下公式:
H = A * R * A.inv()其中.inv()是矩阵逆。
更新:
如果您想要对图像进行居中,您应该以这样的方式添加翻译:(这是找到中心的扭曲位置,并将这一点翻译回中心)。
|dx| | 320 / 2 |
|dy| = H * | 240 / 2 |
|1 | | 1 |
| 1 0 (320/2-dx) |
W = | 0 1 (240/2-dy) | * H
| 0 0 1 |W是你最后的转变。
发布于 2016-05-09 14:38:57
这是我在本征中所做的,并使用4个角落:
// Desired four corners
std::vector<Eigen::Vector2f> Normalized_Reference_Pattern = { Eigen::Vector2f(0, 0), Eigen::Vector2f(0, 2), Eigen::Vector2f(2, 0), Eigen::Vector2f(2, 2) };
// Current four points
std::vector<Eigen::Vector2f> CurrentCentroids = { /* Whatever four corners you want, but relative sueqnece to above */ };
// Transform for current to desired
auto Master_Transform = get_perspective_transform(CurrentCentroids, Normalized_Reference_Pattern);
// abilitu to use the same tranformation for other points (other than the corners) in the image
Eigen::Vector2f Master_Transform_Centroid = Master_Transform * Eigen::Vector2f(currentX, currentY);这是我的黑匣子:
Eigen::Matrix3f get_perspective_transform(const std::vector<Eigen::Vector2f>& points_from,const std::vector<Eigen::Vector2f>& points_to)
{
cv::Mat transform_cv = cv::getPerspectiveTransform(
convert::to_cv(points_from),
convert::to_cv(points_to));
Eigen::Matrix3f transform_eigen;
cv::cv2eigen(transform_cv, transform_eigen);
return transform_eigen;
}https://stackoverflow.com/questions/37117939
复制相似问题