最近,我正在努力解决单个相机的姿势估计问题。我在图像上有一些3D点和相应的2D点。然后我使用solvePnP来获取旋转和平移向量。 问题是,如何判断向量是否正确?
现在我用间接的方式来做这件事:
我使用旋转矩阵,平移向量和某个点的世界3D坐标来获得Camera系统中该点的坐标。然后,我所要做的就是确定坐标是否合理。我想我知道Camera系统的x,y和z轴的方向。
下图是世界空间,而描绘的轴是相机系统。
========How Camera and the point be placed in the world space=============
|
|
Camera--------------------------> Z axis
| |} Xw?
| P(Xw, Yw, Zw)
|
v x-axis
我的rvec和tvec结果似乎是对的。对于指定的点,z值似乎是合理的,我的意思是,如果这个点在z方向上离相机大约一米,则z值约为1.但对于x和y,根据位置点我认为x和y应该是正数,但它们是负数。更重要的是,原始图像中检测到的图案是这样的:
但是使用Camera系统中计算的点坐标和相机内部参数,我得到的图像如下:
目标保持其模式。但它从右下角移动到左上角。我不明白为什么。
答案 0 :(得分:1)
是的,相机中心是相机坐标系的原点,它似乎在this post之后。
在相机姿势估计的情况下,值似乎合理可以命名为反投影错误。这是衡量您的结果旋转和平移将3D点映射到2D像素的程度的度量。不幸的是, solvePnP 不会返回残差错误度量。因此,必须计算它:
cv::solvePnP(worldPoints, pixelPoints, camIntrinsics, camDistortion, rVec, tVec);
// Use computed solution to project 3D pattern to image
cv::Mat projectedPattern;
cv::projectPoints(worldPoints, rVec, tVec, camIntrinsics, camDistortion, projectedPattern);
// Compute error of each 2D-3D correspondence.
std::vector<float> errors;
for( int i=0; i < corners.size(); ++i)
{
float dx = pixelPoints.at(i).x - projectedPattern.at<float>(i, 0);
float dy = pixelPoints.at(i).y - projectedPattern.at<float>(i, 1);
// Euclidean distance between projected and real measured pixel
float err = sqrt(dx*dx + dy*dy);
errors.push_back(err);
}
// Here, compute max or average of your "errors"
校准相机的平均反投影误差可能在0-2像素范围内。根据你的两张照片,这会更多。对我来说,它看起来像一个扩展问题。如果我是对的,你自己计算投影。也许你可以尝试一次cv :: projectPoints()并进行比较。
谈到转换,我学会了不要追随我的想象:)我对返回的rVec和tVec做的第一件事通常就是创建一个4x4刚性转换矩阵(我发布了一次代码here )。这使得事情变得更不直观,但它更紧凑,更方便。
答案 1 :(得分:0)
现在我知道了答案。
是的,相机中心是相机坐标系的原点。
考虑相机系统中的坐标计算为(xc,yc,zc)。然后xc应该是相机和之间的距离 现实世界中x方向的观点。
接下来,如何确定输出矩阵是否正确?
1.正如@eidelen指出的那样,反投影错误是一个指示性措施
2.根据世界坐标系和矩阵中的坐标计算点的坐标。
那么为什么我得到了错误的结果(图案仍然存在但移动到图像的不同区域)?
cameraMatrix
中的参数solvePnP()
是一个矩阵,用于提供摄像机外部参数的参数。在相机矩阵中,你应该使用宽度/ 2和高度/ 2来表示cx和cy。虽然我使用图像大小的宽度和高度。我认为这导致了错误。在我纠正并重新校准相机后,一切似乎都很好。