反向OpenCV projectPoints

时间:2015-12-07 18:00:29

标签: opencv pose-estimation

我有一台相当于棋盘的相机。我知道点的世界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从<3d世界点转到2d图像点:

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

projPoints非常接近imgPoints。

如何使用与属于同一平面的3d世界点对应的屏幕点进行反向操作。我知道从单一视图来看,重建三维位置是不可能的,但是我在同一个平面上,所以它确实是一个二维问题。我可以计算反向旋转矩阵以及反向平移向量,但是我该如何进行?

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

2 个答案:

答案 0 :(得分:1)

这个问题似乎与另一个Stackoverflow问题重复,其中提问者提供了很好的解决方案。这是链接:答案在这里:Computing x,y coordinate (3D) from image point

答案 1 :(得分:0)

假设您通过objpoints-imgpoints对来校准相机。注意,第一个是校准板上特征点的真实世界3维坐标,第二个是每个图像中特征点的2维像素位置。因此,它们两个都应该是包含校准板图像元素数量的列表。在执行以下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]坐标上。