所以我试图拍摄一个图像并指定四个角 - 然后将这四个角移动到图像中间的(近似)完美的正方形。
更新1(底部):9/10/13 @格林威治标准时间晚上8:20 数学&此更新添加了矩阵标记。 (如果您在8:20之前阅读此更新,我必须道歉,我给了你真的错误的信息!)
我不需要它超级准确,但我目前的结果显然不起作用,但在看了其他多个例子后,我看不出我做错了什么。
这是我的模拟:
通过一些神奇的过程,我获得了坐标。对于这个640x480模型,分数如下:
Corners:
Upper-Left: 186, 87
Upper-Right: 471, 81
Lower-Left: 153, 350
Lower-Right: 500, 352
我想要移动角落的点如下:
Upper-Left: 176, 96
Upper-Right: 464, 96
Lower-Left: 176, 384
Lower-Right: 464, 384
现在,这里的最终目标是获得黑点相对于角点的坐标。我不是要让整个图像填满整个图像,因为中心的那个点可以在给出不同图片的框外,所以我想保留足够的“开箱即用”空间来概括整个过程。我知道我可以在它被移动之后得到重点,我只是在移动它正确时遇到了麻烦。我目前的warpPerspective尝试提供了以下结果:
好吧,所以它看起来似乎正在努力使事情适当,但角落实际上并没有达到我们认为的那样。左上角太远了。左下角太高了,右边的两个太右了,太靠近了。好吧,好吧......让我们尝试扩展目标坐标,使其填满屏幕。
看起来似乎放大了?我的坐标是否以某种方式关闭?我需要为它提供新坐标吗?来源,目的地或两者兼而有之?
这是我的代码:(这显然是根据关键信息进行编辑,但如果我遗漏了某些内容,请让我重新加入。)
Mat frame = inputPicture;
Point2f sourceCoords[4], destinationCoords[4];
// These values were pre-determined, and given above for this image.
sourceCoords[0].x = UpperLeft.X;
sourceCoords[0].y = UpperLeft.Y;
sourceCoords[1].x = UpperRight.X;
sourceCoords[1].y = UpperRight.Y;
sourceCoords[2].x = LowerLeft.X;
sourceCoords[2].y = LowerLeft.Y;
sourceCoords[3].x = LowerRight.X;
sourceCoords[3].y = LowerRight.Y;
// We need to make a square in the image. The 'if' is just in case the
// picture used is not longer left-to-right than it is top-to-bottom.
int top = 0;
int bottom = 0;
int left = 0;
int right = 0;
if (frame.cols >= frame.rows)
{
int longSideMidpoint = frame.cols/2.0;
int shortSideFifthpoint = frame.rows/5.0;
int shortSideTenthpoint = frame.rows/10.0;
top = shortSideFifthpoint;
bottom = shortSideFifthpoint*4;
left = longSideMidpoint - (3*shortSideTenthpoint);
right = longSideMidpoint + (3*shortSideTenthpoint);
}
else
{
int longSideMidpoint = frame.rows/2.0;
int shortSideFifthpoint = fFrame.cols/5.0;
int shortSideTenthpoint = frame.cols/10.0;
top = longSideMidpoint - (3*shortSideTenthpoint);
bottom = longSideMidpoint + (3*shortSideTenthpoint);
left = shortSideFifthpoint;
right = shortSideFifthpoint*4;
}
// This code was used instead when putting the destination coords on the edges.
//top = 0;
//bottom = frame.rows-1;
//left = 0;
//right = frame.cols-1;
destinationCoords[0].y = left; // UpperLeft
destinationCoords[0].x = top; // UL
destinationCoords[1].y = right; // UpperRight
destinationCoords[1].x = top; // UR
destinationCoords[2].y = left; // LowerLeft
destinationCoords[2].x = bottom; // LL
destinationCoords[3].y = right; // LowerRight
destinationCoords[3].x = bottom; // LR
Mat warp_matrix = cvCreateMat(3, 3, CV_32FC1);
warp_matrix = getPerspectiveTransform(sourceCoords, destinationCoords); // This seems to set the warp_matrix to 3x3 even if it isn't.
warpPerspective(frame, frame, warp_matrix, frame.size(), CV_INTER_LINEAR, 0);
IplImage *savePic = new IplImage(frame);
sprintf(fileName, "test/%s/photo%i-7_warp.bmp", startupTime, Count);
cvSaveImage(fileName, savePic);
delete savePic;
我也尝试过使用perspectiveTransform,但这会导致错误:
OpenCV错误:断言失败(scn + 1 == m.cols&&(depth == CV_32F) ||深度== CV_64F))在未知函数,文件中 C:\ slace \构建\ WinInstallerMegaPack \ SRC \的OpenCV \模块\芯\ SRC \ matmul.cpp, 第1926行
导致我尝试使用getHomography导致此错误:
OpenCV错误:断言失败(npoints> = 0&& points2.checkVector(2) == npoints&& points1.type())在未知函数中,文件C:\ slave \ builds \ WinInstallerMegaPack \ src \ opencv \ modules \ calib3d \ src \ fundam.cpp, 第1074行
(我检查过 - npoints IS大于零,因为它等于points1.checkVector(2) - 它失败了因为points1.checkVector(2)和points2.checkVector(2)不匹配 - 但我不明白checkVector(2)做了什么.points1和point2取自我尝试喂养getHomography的坐标 - 这与上面的坐标相同。
知道如何获得我正在寻找的输出吗?我已经困惑了一段时间了。 :/
的 ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ - ^ 的
更新1: 好的,所以我已经弄清楚它应该如何计算。 getPerspectiveTransform应该找到一个3x3矩阵,以便:
|M00 M10 M20| |X| |c*X'|
|M01 M11 M21| * |Y| = |c*Y'|
|M02 M12 M22| |1| | c |
MXX是常数矩阵,X& Y是输入坐标,X'和& Y'是输出坐标。这必须适用于所有四个输入/输出坐标组合。 (这个想法很简单,即使要达到那里的数学可能不是 - 我仍然不确定如何他们应该得到那个矩阵...这里的输入将不胜感激 - 因为我只需要一个实际坐标,我不介意完全绕过getPerspectiveTransform和WarpPerspective,只需使用数学解决方案。)
获得透视变换矩阵后,WarpPerspective基本上只是通过相乘来移动每个像素的坐标:
|M00 M10 M20| |X|
|M01 M11 M21| * |Y|
|M02 M12 M22| |1|
每个坐标。然后划分c X'& c Y'都是c(显然)。然后需要进行一些平均,因为结果不太可能是完美的整数。
好的,基本想法很简单,但这就是问题所在; getPerspectiveTransform似乎不起作用! 在上面的例子中,我修改了程序,打印出从getPerspectiveTransform获取的矩阵。它给了我这个:
|1.559647 0.043635 -37.808761|
|0.305521 1.174385 -50.688854|
|0.000915 0.000132 1.000000|
在上面的例子中,我给左上角坐标186,87移动到176,96。不幸的是,当我将上面的warp_matrix与输入坐标(186,87)相乘时,我得不到176,96 - 但是217,92!这与WarpPerspective得到的结果相同。所以至少我们知道WarpPerspective正在运作......
答案 0 :(得分:1)
你的X&您的Source 和目标坐标上的Y坐标相反。
换句话说:
sourceCoords[0].x = UpperLeft.X;
sourceCoords[0].y = UpperLeft.Y;
应该是
sourceCoords[0].x = UpperLeft.Y;
sourceCoords[0].y = UpperLeft.X;
和
destinationCoords[0].y = top;
destinationCoords[0].x = left;
应该是
destinationCoords[0].y = left;
destinationCoords[0].x = top;
Jus'以为你想知道。