我正在尝试使用以下参数调用solvePnP。
apriltag_object_points = np.array([(-1, -1, 0), (-1, 1, 0), (1, 1, 0), (1, -1, 0)], dtype=np.float)
camera_matrix_left = np.eye(3)
dist_left = np.zeros((5, 1))
image_points = np.array(detection.position, dtype=np.float)
cv2.solvePnPRansac(apriltag_object_points, image_points, camera_matrix_left, dist_left)
但是,我收到以下错误:
OpenCV Error: Assertion failed (CV_IS_MAT(_src) && CV_IS_MAT(_dst) && (_src->rows == 1 || _src->cols == 1) && (_dst->rows == 1 || _dst->cols == 1) && _src->cols + _src->rows - 1 == _dst->rows + _dst->cols - 1 && (CV_MAT_TYPE(_src->type) == CV_32FC2 || CV_MAT_TYPE(_src->type) == CV_64FC2) && (CV_MAT_TYPE(_dst->type) == CV_32FC2 || CV_MAT_TYPE(_dst->type) == CV_64FC2)) in cvUndistortPoints, file /Users/travis/miniconda3/conda-bld/opencv_1506476120161/work/opencv-3.3.0/modules/imgproc/src/undistort.cpp, line 312
Traceback (most recent call last):
File "/Users/me/Documents/Code/project/file.py", line 139, in <module>
ret = cv2.solvePnPRansac(apriltag_object_points, image_points, camera_matrix_left, dist_left)
cv2.error: /Users/travis/miniconda3/conda-bld/opencv_1506476120161/work/opencv-3.3.0/modules/imgproc/src/undistort.cpp:312: error: (-215) CV_IS_MAT(_src) && CV_IS_MAT(_dst) && (_src->rows == 1 || _src->cols == 1) && (_dst->rows == 1 || _dst->cols == 1) && _src->cols + _src->rows - 1 == _dst->rows + _dst->cols - 1 && (CV_MAT_TYPE(_src->type) == CV_32FC2 || CV_MAT_TYPE(_src->type) == CV_64FC2) && (CV_MAT_TYPE(_dst->type) == CV_32FC2 || CV_MAT_TYPE(_dst->type) == CV_64FC2) in function cvUndistortPoints
看起来我的论点的形状有问题,但它们看起来很好......
apriltag_object_points.shape == (4, 3)
image_points.shape == (4, 2)
图像点必须是同质的吗?我是否必须hstack
1
的{{1}}的列向量?{/ p>
答案 0 :(得分:2)
这个函数的文档只是错误,因为它是用Python实现的。 solvePnP()
和solvePnPRansac()
的文档均声明:
参数:
objectPoints - 对象坐标空间中的对象点数组,3xN / Nx3 1通道或1xN / Nx1 3通道,其中N是点数。
vector<Point3f>
也可以在这里传递。imagePoints - 相应图像点的阵列,2xN / Nx2 1通道或1xN / Nx1 2通道,其中N是点数。
vector<Point2f>
也可以在这里传递。
所以你认为你很好地使用(N,3)和(N,2)数组作为你的输入。但是,错误代码另有说明。让我们分解一下:
CV_IS_MAT(_src)&amp;&amp; CV_IS_MAT(_dst)&amp;&amp; (_src-&gt; rows == 1 || _src-&gt; cols == 1)&amp;&amp; (_dst-&gt; rows == 1 || _dst-&gt; cols == 1)&amp;&amp; _src-&gt; cols + _src-&gt; rows - 1 == _dst-&gt; rows + _dst-&gt; cols - 1&amp;&amp; (CV_MAT_TYPE(_src-&gt; type)== CV_32FC2 || CV_MAT_TYPE(_src-&gt; type)== CV_64FC2)&amp;&amp; (CV_MAT_TYPE(_dst-&gt; type)== CV_32FC2 || CV_MAT_TYPE(_dst-&gt; type)== CV_64FC2)
好吧,他们的阵列很小,所以我们可能会放弃前两个。但接下来的检查中我们看到了一些有趣的东西:
(_ src-&gt; rows == 1 || _src-&gt; cols == 1)&amp;&amp; (_dst-&gt; rows == 1 || _dst-&gt; cols == 1)
检查src
和dst
中只有一行或一列。换句话说,它严格按照它在文档中声明的第二个版本来期待您的积分;它想要一个多通道点阵。这意味着第一个坐标位于矩阵的一个通道上,第二个坐标位于下一个通道中,等等。
因此,如果我们只是将您的点重塑为多通道数组:
>>> apriltag_object_points = apriltag_object_points.reshape(4,1,3)
>>> image_points = image_points.reshape(4,1,2)
>>> it_works, rvec, tvec, inliers = cv2.solvePnPRansac(apriltag_object_points, image_points, camera_matrix_left, dist_left)
>>> it_works
True
有效!
未来的专业提示:在OpenCV 允许点数为(npoints, ncoords)
格式的每个函数中,它还以(npoints, 1, ncoords)
格式AFAIK接受它们。但是,某些函数仅使用后一种格式。因此,如果您在OpenCV中使用Python中的点坐标,那么最好假设您的点应该在多通道数组中,其中通道数是坐标轴的数量。