OpenCV projectPoints 的反转

6

我有一个面向类似棋盘的相机。我知道这些点在世界坐标系中的3D位置,以及它们在相机图像上对应的2D位置。所有这些世界坐标系中的点都属于同一平面。我使用solvePnP函数:

Matx33d camMat;
Matx41d distCoeffs;
Matx31d rvec;
Matx31d tvec;
std::vector<Point3f> objPoints;
std::vector<Point2f> imgPoints;
solvePnP(objPoints, imgPoints, camMat, distCoeffs, rvec, tvec);

我可以使用projectPoints将三维世界点转换为二维图像点:

std::vector<Point2f> projPoints;
projectPoints(objPoints, rvec, tvec, camMat, distCoeffs, projPoints);

projPoints非常接近imgPoints。

我如何使用与同一平面上的3D世界点对应的屏幕点进行反向操作。我知道从单个视图中,无法重构3D位置,但是在这里,我在同一平面上,因此这实际上是一个2D问题。我可以计算反向旋转矩阵以及反向平移向量,但是接下来该怎么做呢?

Matx33d rot;
Rodrigues(rvec, rot);
Matx33d camera_rotation_vector;
Rodrigues(rot.t(), camera_rotation_vector);
Matx31d camera_translation_vector = -rot.t() * tvec;

通过像素参数化从相机中心到线路。参数化平面。找出线路与平面相交的参数。 - Micka
2个回答

3

假设您通过objpoints-imgpoints对来校准相机。注意,第一个是校准板上特征点的真实世界3D坐标,第二个是每个图像中特征点的2D像素位置。因此,它们都应该是列表,其中包含校准板图像元素的数量。在以下Python代码行之后,您将拥有校准矩阵mtx,每个校准板的旋转rvecs和其平移tvecs。

ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, np.zeros(5,'float32'),flags=cv2.CALIB_USE_INTRINSIC_GUESS ) 

现在我们可以在某个假设下找到任何像素的3D坐标。这个假设是需要定义一些参考点。让我们假设我们的参考点是第0个(第一个)校准板,其中它的枢轴点在0,0处,校准板的长轴是x轴,短轴是y轴,校准板的表面显示Z=0平面。以下是创建投影矩阵的方法。

# projection matrix
Lcam=mtx.dot(np.hstack((cv2.Rodrigues(rvecs[0])[0],tvecs[0])))

现在我们可以定义任何像素位置和所需的Z值。请注意,由于我想在参考校准板上投射(100,100)像素位置,因此我将Z设置为0。
px=100
py=100
Z=0
X=np.linalg.inv(np.hstack((Lcam[:,0:2],np.array([[-1*px],[-1*py],[-1]])))).dot((-Z*Lcam[:,2]-Lcam[:,3]))

现在我们有像素(px,py)的X和Y坐标,它们是 X[0] 和 X[1]。 X的最后一个元素是λ因子。因此,我们可以说位于(px,py)位置的像素掉落在第0个标定板的表面上的坐标为X[0],X[1]。

1
这个问题似乎是另一个Stackoverflow问题的重复,其中提问者很好地提供了解决方案。这里是链接: 答案在这里: 从图像点计算x、y坐标(3D)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接