基于双目摄像头的障碍物检测

基于双目摄像头的障碍物检测前言:关于双目摄像头的障碍物检测以及基于OpenCV的障碍物检测在CSDN以及博客园上都有几篇相关的文章。然而,相当一部分的关于障碍物检测的文章多偏向于理论,而有实践的文章却少之又少。在这里,我将按照我从网上学习到的例子进行整合并加入了我自己的理解。希望能为大家在障碍物检测方面起到一定的参考作用。特别鸣谢:亦轩Dhc的博客琪其齐奇旗棋的CSDN_寒潭雁影的CSD...
摘要由CSDN通过智能技术生成

基于双目摄像头的障碍物检测

前言:关于双目摄像头的障碍物检测以及基于OpenCV的障碍物检测在CSDN以及博客园上都有几篇相关的文章。然而,相当一部分的关于障碍物检测的文章多偏向于理论,而有实践的文章却少之又少。在这里,我将按照我从网上学习到的例子进行整合并加入了我自己的理解。希望能为大家在障碍物检测方面起到一定的参考作用。

特别鸣谢:
亦轩Dhc的博客
琪其齐奇旗棋的CSDN
_寒潭雁影的CSDN

下面开始进入正题啦!

前期准备:

  • 这里我使用的是一个双目摄像头进行的障碍物检测。该双目摄像头如图所示:
    camera.png

前期知识点:

  • 双目摄像头的标定
  • 使用OpenCV获取图片
  • 双目校正
  • 立体匹配
双目摄像头的标定的前期知识点:

在这里,我使用的标定方法是张正友标定法

  • 首先你需要明确,对于一个摄像头来说,分为内参外参
    • 内参分别有五个:
    • 摄像头拍摄到的物体和实际物体在x,y轴上的映射关系(两个参数)。
    • 摄像头中心和图像中心的偏移关系(两个参数)。
    • 摄像头和镜头安装非完全垂直,存在一个角度的偏差。(一个参数)。
    • 外参有六个:
    • 分别是x,y,z方向上的平移和旋转。

      只要有了上面的两种参数,我们基本上就知道了摄像头拍摄到的图像和现实事物的对应关系了。然而, 摄像头拍摄图像与现实事物中还是会有“畸变”上的误差。这是由于镜头质量等原因导致的2D点的偏移。

因此,我们使用张正友标定法对摄像头进行内外参数以及畸变参数的标定。

张正友标定法

前言:张正友标定又称“张氏标定”。是张正友教授在1998年提出的单平面棋盘格的摄像机标定法。

  • 前期准备:
    • 标定板
    • 需要自定准备一个标定板,这标定板的长相大致如下:

Calibration_board.jpg

    • 实景拍摄的图像如下:

True_Calibration_board.jpg

  • 这种标定板有两种方式可以得到:
    • 第二种:使用Python+OpenCV生成棋盘格图片:

      import cv2 
      import numpy as np
      
      width = 350
      height = 500
      length = 50
      
      image = np.zeros((width,height),dtype = np.uint8)
      print(image.shape[0],image.shape[1])
      
      for j in range(height):
         for i in range(width):
             if((int)(i/length) + (int)(j/length))%2:
                 image[i,j] = 255;
      cv2.imwrite("pic/chess.jpg",image)
      cv2.imshow("chess",image)
      cv2.waitKey(0)

      所生成的图片和在OpenCV官网下载得到的图片是一样的规格的。

OpenCV下的张正友标定法

  • 角点提取

使用的函数1: bool findChessboardCorners(InputArray image,Size atternSIze,OutputArray corners,int flags=CALIB_CB_ADAPTIVE_THRESH+CALIB_CB_NORMALIZE_IMAGE);

作用:用于提取标定板的内角点,也就是提取示例图中中每四个黑白格中间的那些角点。

  • 参数解析:
    • image:拍摄到的棋盘图像;
    • patternSize:每个棋盘图上的内角点数。(如果是上图的话,内角点数Size(9,6),即:每行9个角点,每列9个角点);
    • corners:用于存储检测到的内角点的图像坐标位置。(一般用Point2f的向量来表示);
    • flags:用于定义棋盘图上的内角点查找的不同处理方式。
    • 返回值类型为bool,用以返回是否从图中找到角点。

使用函数2: bool find4QuadCornerSubpix(InputArray img,InputOutputArray corners,Size region_size);

作用:用于在初步提取的角点信息上进一步提取亚像素信息,降低相机标定偏差,该方法专门用来获取棋盘图上内角点的精确位置。(有时候也会使用cornerSubPix函数

  • 参数解析:
    • img:输入的Mat矩阵,最好是8位灰度图像;
    • corners:初始的角点坐标向量,同时作为亚像素坐标位置的输出,所以需要的是浮点型数据,一般用Pointf2f/Point2d的向量来表示。即输入上面findChessboardCorners函数的第三个参数;
    • region_size:角点搜索窗口的尺寸;
  • 在一般情况下,其实我们用得较多的是cornerSubPix,但是我们这里用的是棋盘格,而
    find4QuadCornerSubpix是专门用来获取棋盘图上内角点的精确位置的。

使用函数3: drawChessboardCorners( InputOutputArray image, Size patternSize, InputArray corners, bool patternWasFound);

作用:在棋盘上绘制找到的内角点。

  • 参数解析:
    • image:8位灰度或者彩色图像。
    • patternSize:每张标定棋盘上内角点的行列数,即findChessboardCorners的第二个参数;
    • corners:角点坐标向量,可用find4QuadCornerSubpix函数的第二个参数输出做输入;
    • patternWasFound:标志位,用来指示定义的棋盘内角点是否被完整的探测到,true表示被完整的探测到,函数会用直线依次连接所有的内角点,作为一个整体,false表示有未被探测到的内角点,这时候函数会以(红色)圆圈标记处检测到的内角点;
    • 总查找角点的实力代码大致如下:
Mat imageInput = imread("chess.jpg");
Size board_size = Size(9, 6);//标定板上每行、列的角点数
vector<Point2f> image_points_buf;//缓存每幅图像上检测到的角点
/*提取角点*/
if (!findChessboardCorners(imageInput, board_size, image_points_buf))
{
    cout << "can not find chessboard corners!\n"; //找不到角点  
    return;
}
else
{
    Mat view_gray;
    cvtColor(imageInput, view_gray, CV_RGB2GRAY);
    /*亚像素精确化*/
    find4QuadCornerSubpix(view_gray, image_points_buf, Size(5, 5)); //对粗提取的角点进行精确化  
    drawChessboardCorners(view_gray, board_size, image_points_buf, true); //用于在图片中标记角点  
    imshow("Camera Calibration", view_gray);//显示图片  
    waitKey(0);     
}
  • 相机标定

    利用上面获取到的图像角点(理论上需要三张图像,即三组数据,事实上以10~20张为宜,因为这样误差会比较小),便可以用calibrateCamera函数做摄像头标定,计算出摄像头的内参、外参和畸变参数了。

使用函数1: double calibrateCamera(InputArrays objectPoints,InputAttaysOfArrays imagePoints,Size imageSize,CV_OUT InputOutputArray cameraMatrix,CV_OUT InputOutputArray distCoeffs,OutputArrayOfArrays rvecs,OutputArrayOfArrays tvecs,int flags=0,TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS,30,DBL_EPSILON));

  • 参数解析:
    • objectPoints:为世界坐标系中的三维点。在使用时,应该输入一个三维坐标点的向量集合。一般我们假定标定板放在z=0的平面上,然后依据棋盘上单个黑白方块的大小(也可以直接都取10,如果不需要很准确的映射到现实事物的话)可以计算出每个内角点的世界坐标。
    • imagePoints:为每一个内角点对应的图像坐标点。也即是上面求得的各张图像的角点集合。
    • imageSize:为图像的像素尺寸大小,在计算相机的内参和畸变矩阵的时候需要用到的该参数。
    • cameraMatrix:为相机的内参矩阵。输入一个Mat cameraMatrix即可,如Mat cameraMatrix=Mat(3,3,CV_32FC1,Scalar::all(0))。
    • distCoeffs:为畸变矩阵。输入一个Mat distCoffs=Mat(1,5,CV_32FC1,Scalar::all(0));即可。
    • rvecs:旋转向量。应该输入一个Mat类型的vector,即vectorrvecs;
    • tvecs:位移向量。和rvecs一样,应该为vector tvecs;
    • flags:标定时所采用的算法。flags有如下几个参数(直接不写则依据下面参数描述中没设参数的情况进行):
      • CV_CALIB_USE_INTRINSIC_GUESS:使用该参数时,在cameraMatrix矩阵中应该有fx,fy,u0,v0的估计值。否则的话,将初始化(u0,v0)图像的中心点,使用最小二乘估算出fx,fy。
      • CV_CALIB_FIX_PRINCIPAL_POINT:在进行优化时会固定光轴点。当CV_CALIB_USE_INTRINSIC_GUESS参数被设置,光轴点将保持在中心或者某个输入的值。
      • CV_CALIB_FIX_ASPECT_RATIO:固定fx/fy的比值,只将fy作为可变量,进行优化计算。当CV_CALIB_USE_INTRINSIC_GUESS没有被设置,fx和fy将会被忽略。只有fx/fy的比值在计算中会被用到。
      • CV_CALIB_ZERO_TANGENT_DIST:设定切向畸变参数(p1,p2)为零。
      • CV_CALIB_FIX_K1,…,CV_CALIB_FIX_K6:对应的径向畸变在优化中保持不变。
      • CV_CALIB_RATIONAL_MODEL:计算k4,k5,k6三个畸变参数。如果没有设置,则只计算其它5个畸变参数。
    • criteria:最优迭代终止条件设定。

在使用该函数进行

  • 9
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值