[英]Stereo Calibration in Open CV and 3D Coordinates
我是OpenCV
的初学者,目前正在从事一个项目,该项目需要将像素精确映射到厘米/毫米/任何现实世界单位。
我已经在OpenCV
执行了立体声校准,然后进行了立体声校正。 因此,我同时获得了内在和外在参数。
进行立体声校准时,我没有输入棋盘格的确切正方形尺寸(25mm x 25mm)。 我只输入了水平和垂直内角的数量以及板子的数量。 那么当我重新投影到3D时会产生影响吗? 如果是这样,我如何在StereoCalibrate函数中包括平方大小。
其次,从相机矩阵获得的值fx
和fy
均为513.86,而从EXIF数据得出的值为3.7mm。 那么,两者之间的确切关系是什么?
第三,我使用了reprojectImageTo3D
并获得了3d世界坐标。 现在这些坐标的确切单位是多少(厘米/毫米/英寸/英寸等)?
基本上,我想获得从像素到现实世界单位的精确映射,经过大量的阅读和搜索,我仍然无法做到这一点。 请帮助我解决这个问题。
我同意前两个问题的其他答案。 但是只是为了进一步澄清和详细说明,
1)
在下面的代码块中查看参数“ squareSize”。
这是您提供正方形大小的地方。 它的作用是计算棋盘中每个角的位置,并将其推入点的向量(称为objectPoints)。 这是可能的,因为棋盘具有规则的图案。
然后,向量objectPoints成为StereoCalibrate函数的第一个参数。
另外,请记住,无论您为squareSize指定的单位如何,校准结果(当然fx和fy除外)都将以相同单位显示。
for( j = 0; j < boardSize.height; j++ ){
for( k = 0; k < boardSize.width; k++ ){
objectPoints.push_back(Point3f(j*squareSize, k*squareSize, 0));
}
}
2)
得到的fx和fy将以像素为单位。 为了获得以毫米为单位的焦距,您需要将其乘以比例因子。
fx,fy与实际焦距(以毫米为单位)之间的关系由相机传感器的尺寸确定。 您应该能够在相机规格中找到此参数。
我上面提到的缩放比例将是相机传感器每毫米的像素数。
3)
您获得的3D世界坐标正是您提到的。 座标 。 从系统中的某个点引用。 它们是对象点的x , y和z坐标 。 坐标没有单位!
到目前为止,我可以回答两个第一个问题:
1: cv :: stereoCalibrate中的第一个参数是对象点的向量,可以使用以下函数填充它:
void CalcBoardCornerPositions(cv::Size boardSize, double squareSize, std::vector<cv::Point3f>& corners) {
corners.clear();
for( int i = 0; i < boardSize.height; ++i )
for( int j = 0; j < boardSize.width; ++j )
corners.push_back(cv::Point3f(float( j*squareSize ), float( i*squareSize ), 0));
}
然后使用它:
std::vector<std::vector<cv::Point3f> > objectPoints(1);
CalcBoardCornerPositions(boardSize, squareSize, objectPoints[0]);
cv::stereoCalibrate(objectPoints, imagePointsA, imagePointsB, _cameraMatrixA, /// etc
2:实际上,相机矩阵fx和fy分别是焦距乘以 x和y方向上的像素密度。 那意味着
fx = f * cx
fy = f * cy
其中cx = imageSize.width / sensorSize.width,而cy = imageSize.height / sensorSize.height。 通常在现代相机中cx == cy。 您可以在相机手册中找到相机传感器的尺寸。
StereoCalibrate
的第一个参数是您需要自己创建的校准图案的实际尺寸。 例如,如果您有一个3mm正方形的棋盘格6x5,则需要创建一个矩阵,该矩阵包含棋盘上参考系统ex [(0,0,0)(0,3,0)(0,6,0)...]
等。 fx
和fy
乘以它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.