- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我在代表四边形(不一定是正方形或矩形)的视频(或图像)中有 4 个共面点,我希望能够在它们上面显示一个虚拟立方体,立方体的角恰好站立在视频四边形的角上。
由于点是共面的,我可以计算单位正方形的角(即 [0,0] [0,1] [1,0] [1,1])和四边形的视频坐标之间的单应性.
根据这个单应性,我应该能够计算出正确的相机姿势,即 [R|t],其中 R 是一个 3x3 旋转矩阵,t 是一个 3x1 平移向量,因此虚拟立方体位于视频四边形上。
我已经阅读了很多解决方案(其中一些是关于 SO 的)并尝试实现它们,但它们似乎只在一些“简单”的情况下有效(比如当视频四边形是正方形时)但在大多数情况下不起作用。
以下是我尝试过的方法(大部分都是基于相同的原理,只是翻译的计算略有不同)。设 K 是相机的内在矩阵,H 是单应性矩阵。我们计算:
A = K-1 * H
设a1,a2,a3为A的列向量,r1,r2,r3为旋转矩阵R的列向量。
r1 = a1 / ||a1||
r2 = a2 / ||a2||
r3 = r1 x r2
t = a3 / sqrt(||a1||*||a2||)
问题是这在大多数情况下不起作用。为了检查我的结果,我将 R 和 t 与通过 OpenCV 的 solvePnP 方法获得的结果进行了比较(使用以下 3D 点 [0,0,0] [0,1,0] [1,0,0] [1,1 ,0]).
由于我以相同的方式显示立方体,我注意到在每种情况下 solvePnP 都提供了正确的结果,而从单应性获得的姿势大多是错误的。
理论上,因为我的点是共面的,所以可以从单应性计算姿势,但我找不到从 H 计算姿势的正确方法。
对我做错了什么有任何见解吗?
尝试@Jav_Rock的方法后编辑
您好 Jav_Rock,非常感谢您的回答,我尝试了您的方法(以及许多其他方法),这似乎或多或少是可行的。尽管如此,在基于 4 个共面点计算姿势时,我仍然碰巧遇到一些问题。为了检查结果,我将结果与 solvePnP 的结果进行了比较(由于采用了迭代重投影误差最小化方法,后者会好得多)。
这是一个例子:
如您所见,黑色立方体或多或少还不错,但似乎比例不佳,尽管矢量看起来是正交的。
EDIT2: 我在计算后对 v3 进行了归一化(以强制正交),它似乎也解决了一些问题。
最佳答案
如果你有单应性,你可以用这样的东西计算相机姿势:
void cameraPoseFromHomography(const Mat& H, Mat& pose)
{
pose = Mat::eye(3, 4, CV_32FC1); // 3x4 matrix, the camera pose
float norm1 = (float)norm(H.col(0));
float norm2 = (float)norm(H.col(1));
float tnorm = (norm1 + norm2) / 2.0f; // Normalization value
Mat p1 = H.col(0); // Pointer to first column of H
Mat p2 = pose.col(0); // Pointer to first column of pose (empty)
cv::normalize(p1, p2); // Normalize the rotation, and copies the column to pose
p1 = H.col(1); // Pointer to second column of H
p2 = pose.col(1); // Pointer to second column of pose (empty)
cv::normalize(p1, p2); // Normalize the rotation and copies the column to pose
p1 = pose.col(0);
p2 = pose.col(1);
Mat p3 = p1.cross(p2); // Computes the cross-product of p1 and p2
Mat c2 = pose.col(2); // Pointer to third column of pose
p3.copyTo(c2); // Third column is the crossproduct of columns one and two
pose.col(3) = H.col(2) / tnorm; //vector t [R|t] is the last column of pose
}
这个方法对我很有效。祝你好运。
关于opencv - 基于4个共面点用单应矩阵计算相机位姿,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8927771/
当使用 findHomography 时使用 OpenCV Features2D + Homography Documentation ,它调用 CV_RANSAC 作为它的第三个参数: Mat H
我刚刚安装了 OpenCV 3.2.0,我可以在 this image 中找到很多/大部分角落来自 this question通过使用对比度然后使用 cv2.findChessboardCorners
我是一名优秀的程序员,十分优秀!