我最初在 OpenCV 论坛上发布了这个,但不幸的是,我没有得到太多的意见/回复,所以我在这里发帖,希望有人可以提出建议?
我正在使用 Bumblebee XB3 立体相机,它有 3 个镜头。我花了大约三周的时间阅读论坛、教程、Learning OpenCV 书以及有关使用立体校准和立体匹配功能的实际 OpenCV 文档。总之,我的问题是我生成了一个很好的视差图,但点云很差,看起来歪斜/压扁,不代表实际场景。
到目前为止我做了什么:
使用 OpenCV stereo_calibration 和 stereo_matching 示例:
使用棋盘图像校准我的立体相机
1)原始场景图像:http
://answers.opencv.org/upfiles/1380850337241986.jpg
2)使用相机校准后的矩阵校正从相机获得的原始图像:http
: //answers.opencv.org/upfiles/ 13808502665723237.png
3) 使用立体匹配 (SGBM) 从校正图像生成视差图像
:4) 将这些视差投影到 3D 点云
到目前为止,我为消除我的问题所做的工作:
- 我试过第一张和第二张照片,然后是第二张和第三张镜头,最后是第一张和第二张。
- 我通过改变距离(更近/更远)重新校准了我的棋盘捕获
- 我已经使用了 20 多对立体声对进行校准
- 使用不同的棋盘尺寸:我使用 9x6 棋盘图像进行校准,现在改用 8x5 图像
- 我尝试使用块匹配以及 SGBM 变体并获得
相对相似的结果。
到目前为止,使用 SGBM获得了更好的结果。 - 我改变了视差范围,改变了 SAD 窗口大小等,几乎没有改进
我怀疑的问题是:
我的视差图像看起来相对可以接受,但下一步是使用 Q 矩阵进入 3D 点云。我怀疑,我没有正确校准相机以生成正确的 Q 矩阵。不幸的是,在思考我还能做些什么来获得更好的 Q 矩阵方面,我已经碰壁了。有人可以建议前进的道路吗?
我认为可能有问题的另一件事是我在使用 cv::stereoCalibrate 函数时所做的假设。目前,我单独校准每个摄像头以获得摄像头和失真(cameraMatrix[0]、distCoeffs[0] 和 cameraMatrix[1]、distCoeffs[1])矩阵,因此它使 stereoCalibrate 函数的复杂性更容易一些。
stereoCalibrate(objectPoints, imagePoints[0], imagePoints[1],
cameraMatrix[0], distCoeffs[0],
cameraMatrix[1], distCoeffs[1],
imageSize, R, T, E, F,
TermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 100, 1e-5),
//CV_CALIB_FIX_ASPECT_RATIO +
//CV_CALIB_ZERO_TANGENT_DIST +
//CV_CALIB_SAME_FOCAL_LENGTH +
CV_CALIB_RATIONAL_MODEL
//CV_CALIB_FIX_K3 + CV_CALIB_FIX_K4 + CV_CALIB_FIX_K5
);
此外,我认为提及我如何从视差到点云可能会很有用。我正在使用 OpenCV 的 cv::reprojectImageTo3D,然后将数据写入 PCL 点云结构。以下是相关代码:
cv::reprojectImageTo3D( imgDisparity16S, reconstructed3D, Q, false, CV_32F);
for (int i = 0; i < reconstructed3D.rows; i++)
{
for (int j = 0; j < reconstructed3D.cols; j++)
{
cv::Point3f cvPoint = reconstructed3D.at<cv::Point3f>(i, j);
//Filling in a PCL structure
pcl::PointXYZRGB point;
point.x = cvPoint.x;
point.y = cvPoint.y;
point.z = cvPoint.z;
point.rgb = rectified_imgRight.at<cv::Vec3b>(i,j)[0]; //Grey information
point_cloud_ptr->points.push_back (point);
}
}
point_cloud_ptr->width = (int) point_cloud_ptr->points.size();
point_cloud_ptr->height = 1;
pcl::io::savePCDFileASCII("OpenCV-PointCloud.pts", *point_cloud_ptr);
PS:我选择上传这些图片的原因是场景有一些纹理,所以我期待回复说场景太同质化。隔断上的罩子和椅子的质感也相当丰富。
几个问题:
你能帮我删除似乎是点云一部分的图像/视差平面吗?为什么会这样?
有什么明显的我做错了吗?我会发布我的代码,但它与提供的 OpenCV 示例非常相似,我认为我没有做任何更有创意的事情。如果有可能涉及的特定部分,我可以。
在我的幼稚意见中,视差图像似乎还可以。但是点云绝对不是我对一个相对不错的视差图像所期望的,它更糟。
如果有帮助,我已经提到了我在相机校准后获得的 Q 矩阵,以防出现明显的问题。将此与学习 OpenCV 书进行比较,我认为没有任何明显的不正确之处......
Q: rows: 4
cols: 4
data: [ 1., 0., 0., -5.9767076110839844e+002, 0., 1., 0.,
-5.0785438156127930e+002, 0., 0., 0., 6.8683948509213735e+002, 0.,
0., -4.4965180874519222e+000, 0. ]
感谢您的阅读,我真诚地感谢您在这一点上的任何建议......