我正在尝试测量相机的姿势,我已完成以下操作。
将方块的左上角作为我的原点,并按以下顺序(x,y)或(col,row)给出世界点: (0,0),( - 12.8,0),( - 12.8,12.8),(0,12.8) - in cms
检测图像中的这些点。(以像素为单位) 图像点和世界点的顺序相同。
我已经为内在矩阵和失真系数校准了相机。
我使用 SolvePnP 函数获取rvec和tvec。
我使用 Rodrigues 函数来获取旋转矩阵。
要检查rvec和tvec是否正确,我使用 ProjectPoints 将三维点(z = 0)投影到图像平面中,并在图像上正确获取点X轴上的误差为3像素。
现在我继续使用公式计算我在世界框架中的相机位置:
cam_worl_pos = - inverse(R)* tvec 。 (这个公式我已在许多博客中验证过,这也很有意义)
我怀疑的是,如果我能够使用rvec和tvec将3-D世界点投影回图像平面(X轴上 3像素误差,Y轴几乎没有误差,希望它是不是太糟糕),那么为什么我没有在世界框架中获得相机位置。
另外,我对SolvPnP rvec和tvec解决方案有疑问,它们可能是多种解决方案之一,但不是我想要的解决方案之一。
如何从SolvPnp获得正确的rvec和tvec或任何其他建议来获得rvec和tvec也会有所帮助。
编辑:
图片尺寸 - 720(行)* 1280(col)
相机看到的校准图案
The link has the picture of calibration pattern used.
新编辑
遵循右手规则的世界坐标系和图像中检测到的相应点
左方是我的世界坐标系,是一个边长12.8cm的正方形,左上角是世界原点(0,0)。红点是图像中检测到的三维世界点。
所见图像是在鱼眼镜头相机的径向畸变校正之后。
相机参数
cameraMatrix_Front=[908.65 0 642.88
0 909.28 364.95
0 0 1]
distCoeffs_Front=[-0.4589, 0.09462, -1.46*10^-3, 1.23*10^-3]
OpenCV C ++代码:
vector<Point3f> front_object_pts;
Mat rvec_front;
Mat tvec_front;
Mat rotation_front;
Mat world_position_front_cam;
//Fill front object points(x-y-z order in cms)
//It is square of side 12.8cms on Z=0 plane
front_object_pts.push_back(Point3f(0, 0, 0));
front_object_pts.push_back(Point3f(-12.8, 0, 0));
front_object_pts.push_back(Point3f(-12.8,12.8,0));
front_object_pts.push_back(Point3f(0, 12.8, 0));
//Corresponding Image points detected in the same order as object points
front_image_pts.push_back(points_front[0]);
front_image_pts.push_back(points_front[1]);
front_image_pts.push_back(points_front[2]);
front_image_pts.push_back(points_front[3]);
//Detected points in image matching the 3-D points in the same order
//(467,368)
//(512,369)
//(456,417)
//(391,416)
//Get rvec and tvec using Solve PnP
solvePnP(front_object_pts, front_image_pts, cameraMatrix_Front,
Mat(4,1,CV_64FC1,Scalar(0)), rvec_front, tvec_front, false, CV_ITERATIVE);
//Output of SolvePnP
//tvec=[-26.951,0.6041,134.72] (3 x 1 matrix)
//rvec=[-1.0053,0.6691,0.3752] (3 x 1 matrix)
//Check rvec and tvec is correct or not by projecting the 3-D object points to image
vector<Point2f>check_front_image_pts
projectPoints(front_object_pts, rvec_front, tvec_front,
cameraMatrix_Front, distCoeffs_Front, check_front_image_pts);
//Here to note that I have made **distCoefficents**,
//a 0 vector since my image points are detected after radial distortion is removed
//Get rotation matrix
Rodrigues(rvec_front, rotation_front);
//Get rotation matrix inverse
Mat rotation_inverse;
transpose(rotation_front, rotation_inverse);
//Get camera position in world cordinates
world_position_front_cam = -rotation_inverse * tvec_front;
//相机的实际位置(测量的手动近似值)
X = -47cm
Y =18厘米
Z =25厘米
//获得位置
X = -110cm
Y =71厘米
Z =40厘米
提前致谢。
答案 0 :(得分:0)
您如何知道cam_worl_pos
不正确?
cam_worl_pos
是相机的位置。您可以尝试测量相机与3D点所在平面之间的实际距离,并将其与tvec
(std::sqrt(tx²+ty²+tz²)
)的标准进行比较。如果您不共享代码或不同参数的值,很难说出现了什么问题。
修改强>
如果您计算tvec
的距离,则会137.390683 cm
:std::sqrt(26.951*26.951+0.6041*0.6041+134.72*134.72)
您可以通过测量实际距离来检查这是否正确!
另外,您如何手动测量相机相对于世界框架的位置?
<强> EDIT2 强>
如果没有得到正确的值,那么solvePnP函数的参数就会出错:
cameraMatrix_Front
似乎是正确的。但请确保908.65 * CCD (mm)=focal length (mm)
将校准得到的失真系数的实际值传递给solvePnP
solvePnP
至少需要4个点(越多越好点),为了更准确,不要让你的计划(你的方格在哪里)与图像计划平行如下:
<强> EDIT3 强>
cameraMatrix_Front
,失真系数..等等