当前位置:   article > 正文

双目视觉(六)U-V视差_双目视差

双目视差

系列文章:

  1. 双目视觉(一)双目视觉系统
  2. 双目视觉(二)双目匹配的困难和评判标准
  3. 双目视觉(三)立体匹配算法
  4. 双目视觉(四)匹配代价
  5. 双目视觉(五)立体匹配算法之动态规划全局匹配
  6. 双目视觉(六)U-V视差
  7. 【项目实战】利用U-V视差进行地面检测
  8. 【项目实践】U-V视差路面检测之动态规划

因为在自己的工作中需要剔除行驶的地面,要用到U-V视差,所以写这篇博客主要是记录自己学习到的相关内容。如果写的有问题可以在评论中指出。

实践部分

  1. 【项目实战】利用U-V视差进行地面检测【链接
  2. 【项目实践】U-V视差路面检测之动态规划链接

  3. 【项目实践】开源代码【链接

目录

1.原理:

双目系统

模型推导 

2.U-V视差的构造

3.各种3D平面在U-V视差中的投影 

4.实例 

5.Opencv实现

 参考:


1.原理:

  • 双目系统

双目相机系统如下图所示:f为焦距,b为基线,P(X,Y,Z)为三维点。 我们可以得到视差的公式如下:(双目视觉系统

  • 模型推导 

首先,当我们使用双目相机拍摄真实世界时,如下图所示,(Xw ,Yw , Zw )为世界坐标系,(Xl ,Yl , Zl)为左相机坐标系,(Xr ,Yr , Zr)为右相机坐标系。 

  • 对于世界坐标系和左相机坐标系,存在着b/2的平移,以及一个旋转角θ
  • 对于世界坐标系和右相机坐标系,存在着b/2的平移,以及一个旋转角θ

那么,从世界坐标系到左右相机坐标的变换矩阵为:

 其次,我们预先通过标定知道了左右相机的内参矩阵为:

 当相机的内参和外参都知道了,根据针孔相机模型,就可以计算处相机的投影矩阵P=K[R|t]

使用矩阵的乘法公式对其进行展开得到: 

 由d=ul-ur得到视差:

2.U-V视差的构造

  • U视差的构造

U-disparityMap的列对应于原始视差图的列;

U-disparityMap中(d,u) = 原始视差图中第u列,视差为d的个数。

  • V视差的构造

V-disparityMap的行对应于原始视差图的行;

V-disparityMap中(v,d) = 原始视差图中第v行,视差为d的个数。

3.各种3D平面在U-V视差中的投影 

4.实例 

1.左图像,右图像,视差图像

 2.U-视差,V-视差

3.对U-V视差图使用霍夫变换检测线

 

①,⑤:近似直线,如图中的球体和圆锥;

②   11:地平面在V视差中的投影为直线;

⑥,⑦:侧面的墙在U视差中的投影为直线;

⑨       :垂直障碍物;

③④⑧⑩:垂直墙面的转角处;

4.3D重建的结构

5.Opencv实现

  • 双目匹配(这里我们使用Opencv中自带的SGBM算法)
  1. //SGBM param
  2. int mMaxDisp = 128;
  3. int mP1 = 100;
  4. int mP2 = 2700;
  5. int mWinSize = 4;
  6. int mPreFilterCap = 180;
  7. //create SGBM
  8. cv::Ptr<cv::StereoSGBM> mSGBM=cv::StereoSGBM::create(0,mMaxDisp,mWinSize,mP1,mP2,0,mPreFilterCap,5,0,0,cv::StereoSGBM::MODE_HH);
  9. // read image
  10. cv::Mat left=cv::imread("../image/I1_000000.png");
  11. cv::Mat right=cv::imread("../image/I2_000000.png");
  12. cv::Mat disp16s,disp;
  13. //compute disparity
  14. mSGBM->compute(left,right,disp16s);
  15. disp16s=disp16s/16;
  16. disp16s.convertTo(disp,CV_8UC1);
  •  计算U视差图
  1. cv::Mat UdispMap=cv::Mat(mMaxDisp,disp.cols,CV_16UC1);
  2. void computeUDisparity(cv::Mat &UdispMap,cv::Mat disp)
  3. {
  4. UdispMap.setTo(0);
  5. int width=disp.cols;
  6. int height=disp.rows;
  7. for(int row=0;row<height;row++)
  8. {
  9. auto pRowInDisp=disp.ptr<uchar>(row);
  10. for(int col=0;col<width;col++)
  11. {
  12. uint8_t currDisp=pRowInDisp[col];
  13. if(currDisp>0&&currDisp<128)
  14. {
  15. UdispMap.at<ushort>(currDisp,col)++;
  16. }
  17. }
  18. }
  19. }
  • 计算V视差图
  1. cv::Mat VdispMap=cv::Mat(disp.rows,mMaxDisp,CV_16UC1);
  2. void computeVDisparity(cv::Mat &VdispMap,cv::Mat disp)
  3. {
  4. VdispMap.setTo(0);
  5. int width=disp.cols;
  6. int height=disp.rows;
  7. for(int row=0;row<height;row++)
  8. {
  9. auto pRowInDisp=disp.ptr<uchar>(row);
  10. for(int col=0;col<width;col++)
  11. {
  12. uint8_t currDisp=pRowInDisp[col];
  13. if(currDisp>0&&currDisp<128)
  14. {
  15. VdispMap.at<ushort>(row,currDisp)++;
  16. }
  17. }
  18. }
  19. }
  • 原图像

  • U视差

  • V视差

  • U视差用来剔除障碍物(10为阈值)
  1. cv::Mat removeObstacle(cv::Mat Disparity,cv::Mat Udisparity)
  2. {
  3. cv::Mat mObstacleMap;
  4. mObstacleMap.create(Disparity.rows, Disparity.cols, CV_8UC1);
  5. mObstacleMap.setTo(0);
  6. int height = Disparity.rows;
  7. int width = Disparity.cols;
  8. for (int v = 0; v < height; v++)
  9. {
  10. uint8_t* pRowInDisp = Disparity.ptr<uchar>(v);
  11. uint8_t* pRowInObsMap = mObstacleMap.ptr<uchar>(v);
  12. for (int u = 0; u < width; u++)
  13. {
  14. uint8_t currDisp = pRowInDisp[u];
  15. if (currDisp < 128 && Udisparity.at<ushort>(currDisp, u) > 10)
  16. pRowInObsMap[u] = 255;
  17. }
  18. }
  19. return mObstacleMap;
  20. }

 参考:

基于 U-V 视差算法的障碍物识别技术研究

A Complete U-V-Disparity Study for Stereovision Based 3D Driving Environment analysis

基于U—V 视差算法的障碍物识别技术研究 - 道客巴巴

视差:disparity与UV-视差:UV-disparity_uv视差图_生活没有if-else的博客-CSDN博客

菜鸟看论文——U-V-Disparity与地面检测、相机姿态估计:菜鸟看论文——U-V-Disparity与地面检测、相机姿态估计_yiteeee的博客-CSDN博客

可行使区域检测:https://github.com/OdingdongO/bdd_segmentation

可行驶区域检测

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/298262
推荐阅读
相关标签
  

闽ICP备14008679号