OpenCV立体匹配/校准

OpenCV立体匹配/校准,opencv,camera-calibration,stereo-3d,Opencv,Camera Calibration,Stereo 3d,我最初在OpenCV论坛上发布了这篇文章,但不幸的是,我没有得到太多的意见/回复,所以我在这里发布,希望有人能提供一些建议 我用的是大黄蜂XB3立体相机,它有3个镜头。我花了大约三周的时间阅读论坛、教程、学习OpenCV的书籍和实际的OpenCV文档,了解如何使用立体声校准和立体声匹配功能。总之,我的问题是,我生成了一个很好的视差贴图,但非常差的点云,看起来倾斜/挤压,不能代表实际场景 到目前为止我所做的: 使用OpenCV立体声校准和立体声匹配示例: 使用棋盘图像校准我的立体相机 1) 原始场

我最初在OpenCV论坛上发布了这篇文章,但不幸的是,我没有得到太多的意见/回复,所以我在这里发布,希望有人能提供一些建议

我用的是大黄蜂XB3立体相机,它有3个镜头。我花了大约三周的时间阅读论坛、教程、学习OpenCV的书籍和实际的OpenCV文档,了解如何使用立体声校准和立体声匹配功能。总之,我的问题是,我生成了一个很好的视差贴图,但非常差的点云,看起来倾斜/挤压,不能代表实际场景

到目前为止我所做的:

使用OpenCV立体声校准和立体声匹配示例:

使用棋盘图像校准我的立体相机

1) 原始场景图像:
2) 使用相机校准后的矩阵校正从相机获得的原始图像:

3) 使用立体匹配(SGBM)从校正后的图像生成视差图像
: 4) 将这些差异投影到三维点云

到目前为止,我为解决我的问题所做的工作:

  • 我试过第一张和第二张照片,然后是第二张和第三张镜头和 最后是1号和2号
  • 我已经通过改变参数重新校准了我的棋盘捕获 距离(近/远)
  • 我使用了20多对立体声进行校准
  • 使用不同的棋盘大小:我使用了一个9x6的棋盘图像 校准,现在改为使用8x5
  • 我尝试使用块匹配以及SGBM变体,并获得
    相对相似的结果。获取
    到目前为止,SGBM的效果更好
  • 我已经改变了视差范围,改变了悲伤的窗口大小等 几乎没有改善
我怀疑问题在于:

我的视差图像看起来相对可以接受,但下一步是使用Q矩阵转到3D点云。我怀疑,我没有正确校准摄像机以生成正确的Q矩阵。不幸的是,我在思考我还能做些什么来获得更好的Q矩阵方面遇到了困难。有人能为我们的未来提出建议吗

另一件我认为可能有问题的事情是我在使用cv::stereoCalibrate函数时所做的假设。目前,我单独校准每个摄像头,以获得摄像头和失真矩阵(cameraMatrix[0]、Distcoefs[0]和cameraMatrix[1]、Distcoefs[1]),从而使立体校准功能的复杂性变得更简单

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);

感谢您的阅读,我真诚地感谢您在这一点上提出的任何建议。

我在使用OpenCV(v.2.4.6)3D重建功能时发现了类似的问题。 有些人,比如Martin Peris,又自己实现了。

遗憾的是,有时我发现两种实现中的数据都存在问题。 所以,我想我在这些情况下的问题是由于一个糟糕的外部摄像机参数描述。也许,这也是你的情况

附言:为了摆脱背景,你需要对它进行分段。或者,至少在重建工作完成后检查大于阈值的深度值。handleMissingValues标志仅消除“无穷大”处的点
PS2。请告诉我们你是否解决了这个问题。我认为这对所有人来说都是有价值的。Thnx

我不允许发布超过2个链接。这是剩下的一个:3)使用立体匹配(SGBM)从校正后的图像生成视差图像:4)将这些视差投影到3D点云:和:问题:您对相机坐标系中的点云满意吗?如果是这样,您可以使用点灰度校准文件获得所需内容(无需使用棋盘校准)。校正后的图像没有镜头失真,因此给定一个视差值,将其转换为深度(z=Bf/d),然后使用已知焦距f将其反向投影到相机坐标。链接已断开,但internet achive拥有它。
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. ]