或者,也许,不够扭曲......
所以我正在尝试拍摄一张图像并指定四个角 - 然后将这四个角移动到图像中间的一个(接近)完美的正方形中。
更新 1(底部):格林威治标准时间 2013 年 9 月 10 日下午 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 || depth == CV_64F)) 未知函数,文件 C:\slace\builds\WinInstallerMegaPack\src\opencv\modules\core\ 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 大于零,因为它等于 points1.checkVector(2) - 它失败了,因为 points1.checkVector(2) 和 points2.checkVector(2) 不匹配 - 但我不明白什么 checkVector( 2) 确实,points1 和 points2 取自我尝试输入 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 正在工作......