我的解决方法是进行一些空间计算。为此,我需要将2D像素值转换为世界坐标,使用向量计算一个新的3D位置,再将这些坐标转换回2D,并检查该位置的颜色/形状。
此外,我还需要知道增强现实添加的3D位置。
我通过此链接create opencv camera matrix for iPhone 5 solvepnp获得了相机矩阵。
相机的旋转矩阵来自Core Motion。
如果可能的话,我不想使用Aruco标记,因为我无法得到所需的效果。
现在我的问题是,如果我知道例如数字5上圆圈的位置和距离,我不能进行计算吗?我不需要以毫米/英寸作为单位的测量,我可以使用没有测量的向量。
相机需要能够自由旋转。
我尝试反转计算sm'=A[R|t]M'以便能够在3D中计算2D坐标。但是我在纸上反转[R|t]时卡住了,而且我也不知道该如何在Swift或C++中做到这一点。
我已经阅读了许多不同的论坛帖子、书籍等,但我完全陷入困境,感激您能给我的任何帮助/意见。否则我就完蛋了。
非常感谢您的帮助。
更新:
通过使用Micka建议的solvePnP,我能够获得摄像机角度的旋转和平移向量。这意味着如果您能够识别图像中的多个2D点并知道它们各自的3D世界坐标(以毫米、厘米、英寸等为单位),那么您可以获得将点从已知的3D世界坐标投影到相应的2D坐标的机制(使用opencv projectPoints函数)。
接下来我需要解决的是从2D到3D坐标的转换,其中我需要遵循ozlsn的方法,使用从solvePnP得到的矩阵的逆矩阵。 更新2: 通过俯视图,我已经能够很好地检测到瓦片及其在3D世界中的位置: 俯视图下的瓦片
然而,如果我现在倾斜视图,我的计算就不再有效了。例如,我会检查一个9个点组的底部边缘和黑色分割线的中心是否为90°角。如果Corner1->Middle Edge->Bar Center和Corner2->Middle Edge->Bar Center都是90°角,则可以找到中间的条形码并找到瓷砖的位置。
当视图被倾斜时,由于透视关系,这些角度将被移动到130°和50°左右(稍后我会提供一张图片)。
我现在的想法是使用4个点(底部边缘加中间点)进行solvePNP计算,并将需要的点和中心条从2D位置旋转到3D位置(高度应该无关紧要?)。然后,我可以用翻译后的点检查角度是否为90°,并进行其他必要的距离计算。
这是我所要实现的图片: Markings for Problem
首先找到九个点并将它们排列。对于每条边,我会尝试找到黑色的线条。如上所述,从顶部看,蓝色角、绿色中间边缘到黄色线条中心的角度为90°。然而,由于摄像头的角度不同,这个角度不再是90°了。我也不能检查两个角度是否加起来等于180°,这会给我带来错误的结果。所以我想执行以下步骤:
- 检测中心点
- 检测边缘(3个点)
- 使用这4个点进行SolvePnP求解
- 将边缘和中心点(坐标)旋转到3D位置
- 测量角度(检查两者是否都为90°)
现在我想知道如何将这些点的2D坐标转换成3D坐标。我不关心距离,因为我只是与其他点相对计算(例如,中间-边缘的距离是1.4倍),如果我能测量距离(以毫米为单位),那就更好了,可以得到更好的结果。
使用solvePnP可以得到rvec,然后用Rodrigues()将其转换为旋转矩阵。测量角度时,我的理解是不需要应用solvePnP中的平移(tvec)。这带来了我的最后一个问题,当使用iPhone时,我不能使用运动检测的角度预先构建旋转矩阵,并仅使用该矩阵将瓷砖旋转以从上方显示吗?我觉得这将使我节省很多CPU时间,因为我不必为每个瓷砖都使用solvePnP(可能最多可达100个瓷砖)。
寻找单应性矩阵
vector<Point2f> tileDots;
tileDots.push_back(corner1);
tileDots.push_back(edgeMiddle);
tileDots.push_back(corner2);
tileDots.push_back(middle.Dot->ellipse.center);
vector<Point2f> realLivePos;
realLivePos.push_back(Point2f(5.5,19.44));
realLivePos.push_back(Point2f(12.53,19.44));
realLivePos.push_back(Point2f(19.56,19.44));
realLivePos.push_back(Point2f(12.53,12.19));
Mat M = findHomography(tileDots, realLivePos, CV_RANSAC);
cout << "M = "<< endl << " " << M << endl << endl;
vector<Point2f> barPerspective;
barPerspective.push_back(corner1);
barPerspective.push_back(edgeMiddle);
barPerspective.push_back(corner2);
barPerspective.push_back(middle.Dot->ellipse.center);
barPerspective.push_back(possibleBar.center);
vector<Point2f> barTransformed;
if (countNonZero(M) < 1)
{
cout << "No Homography found" << endl;
} else {
perspectiveTransform(barPerspective, barTransformed, M);
}
然而,这给我带来了错误的值,我不知道该去哪里寻找(Sehe den Wald vor lauter Bäumen nicht mehr)。
Image Coordinates https://istack.dev59.com/c67EH.webp
World Coordinates https://istack.dev59.com/Im6M8.webp
Points to Transform https://istack.dev59.com/hHjBM.webp
Transformed Points https://istack.dev59.com/P6lLS.webp
你看,我甚至太蠢了,无法在这里发布4张图片??!
第4个索引项应该在x 2007 y 717处。 我不知道我在这里做错了什么。
更新3: 我找到了以下帖子从图像点计算x、y坐标(3D),它正好做我需要的事情。我不知道也许有更快的方法可以做到这一点,但是如果不这样做,我就无法找到它。目前我可以进行检查,但仍然需要测试算法是否足够稳健。