精华内容
下载资源
问答
  • opencv双目测距

    2017-04-19 20:23:58
    opencv运用matlab标定数据进行双目测距
  • OPENCV 双目测距

    2016-05-16 18:19:10
    从本地获取两张图片进行测距,程序运行时左右视图一直在旋转,最后在视图里面看不到左右视图里面的物体了。视差图也是中间部分也在旋转,最后中间变黑了。这是什么原因? 代码如下:bool left_mouse = false; ...
  • opencv双目测距资料整理

    千次阅读 2017-02-03 00:32:33
    opencv双目测距资料整理

    2010年:

    http://download.csdn.net/detail/s620888/2428778

    使用OpenCV开发的双目标定与景深测距,包括从两个摄像头中直接提取图片,然后直接进行标定。全可以视化操作。相当简单。里面的类封装得也还行。没什么参数,所以想直接使用本类的也想法方便

    评论:是基于mfc界面设计的 主要调用了opencv库函数,工程调试有很多问题,暂时还没有调通,运行一般,并没有实现测距。但可以借鉴代码

    2013年的:

    http://download.csdn.net/detail/o_o8_8/4970091

    基本上还是可以的,就是代码太老了,很多opencv1的东西和c语言的东西还在保留,建议以后用的人改写成opencv2,或者3并且改成c++风格。另外,给的代码是完整的,只是没有给出项目文件。对编程稍微有点知识的人新建一个vc的空项目导入可以运行


    双目测距原理:

    http://blog.csdn.net/sunanger_wang/article/details/7744015

    虽然最近注意力已经不可遏制地被神经科学、大脑记忆机制和各种毕业活动吸引过去了,但是还是觉得有必要把这段时间双目视觉方面的进展总结一下。毕竟从上一篇博文发表之后,很多同仁发E-mail来与我讨论,很多原来的疑团,也在讨论和一步步的试验中逐渐解决了。  

    开篇之前,首先要感谢maxwellsdemon和wobject,没有和你们的讨论,也就没有此篇的成文。


    说到双摄像头测距,首先要复习一下测距原理,把Learning OpenCV翻到416和418页,可以看到下面两幅图


    图1. 双摄像头模型俯视图


    图2, 双摄像头模型立体视图




    图1解释了双摄像头测距的原理,书中Z的公式如下:

     

    在OpenCV中,f的量纲是像素点,Tx的量纲由定标棋盘格的实际尺寸和用户输入值确定,一般总是设成毫米,当然为了精度提高也可以设置为0.1毫米量级,d=xl-xr的量纲也是像素点。因此分子分母约去,z的量纲与Tx相同

     

    图2解释了双摄像头获取空间中某点三维坐标的原理。

     

    可以看到,实际的坐标计算利用的都是相似三角形的原理,其表达式就如同Q矩阵所示。

     

     

    空间中某点的三维坐标就是(X/W, Y/W, Z/W)。

     

    因此,为了精确地求得某个点在三维空间里的距离,我们需要获得的参数有焦距f、视差d、摄像头中心距Tx。

    如果还需要获得X坐标和Y坐标的话,那么还需要额外知道左右像平面的坐标系与立体坐标系中原点的偏移cx和cy。其中f, Tx, cx和cy可以通过立体标定获得初始值,并通过立体校准优化,使得两个摄像头在数学上完全平行放置,并且左右摄像头的cx, cy和f相同(也就是实现图2中左右视图完全平行对准的理想形式)。而立体匹配所做的工作,就是在之前的基础上,求取最后一个变量:视差d(这个d一般需要达到亚像素精度)。从而最终完成求一个点三维坐标所需要的准备工作。

     

    在清楚了上述原理之后,我们也就知道了,所有的这几步:标定、校准和匹配,都是围绕着如何更精确地获得f, d, Tx, cx和cy而设计的。


     

    双目测距的原理就说到这里,为了避免大家看到大段纯叙述性的文字头晕,下面的行文将会以FAQ的形式围绕着实现双摄像头测距过程中碰到的几点疑惑展开。当然,其中的解答也只是我的个人理解,如有不当,敬请指正。

    Q1:标定时棋盘格的大小如何设定,对最后结果有没有影响?

    A:当然有。在标定时,需要指定一个棋盘方格的长度,这个长度(一般以毫米为单位,如果需要更精确可以设为0.1毫米量级)与实际长度相同,标定得出的结果才能用于实际距离测量。一般如果尺寸设定准确的话,通过立体标定得出的Translation的向量的第一个分量Tx的绝对值就是左右摄像头的中心距。一般可以用这个来验证立体标定的准确度。比如我设定的棋盘格大小为270 (27mm),最终得出的Tx大小就是602.8 (60.28mm),相当精确。

     

    Q2:通过立体标定得出的Tx符号为什么是负的?

    A:这个其实我也不是很清楚。个人的解释是,立体标定得出的T向量指向是从右摄像头指向左摄像头(也就是Tx为负),而在OpenCV坐标系中,坐标的原点是在左摄像头的。因此,用作校准的时候,要把这个向量的三个分量符号都要换一下,最后求出的距离才会是正的。

    但是这里还有一个问题,就是Learning OpenCV中Q的表达式,第四行第三列元素是-1/Tx,而在具体实践中,求出来的实际值是1/Tx。这里我和maxwellsdemon讨论下来的结果是,估计书上Q表达式里的这个负号就是为了抵消T向量的反方向所设的,但在实际写OpenCV代码的过程中,那位朋友却没有把这个负号加进去。(一家之言,求更详细的解释)

     

    Q3:cvFindStereoCorrespondenceBM的输出结果好像不是以像素点为单位的视差?

    A:在OpenCV2.0中,BM函数得出的结果是以16位符号数的形式的存储的,出于精度需要,所有的视差在输出时都扩大了16倍(2^4)。其具体代码表示如下:

    dptr[y*dstep] = (short)(((ndisp - mind - 1 + mindisp)*256 + (d != 0 ? (p-n)*128/d : 0) + 15) >> 4);

    可以看到,原始视差在左移8位(256)并且加上一个修正值之后又右移了4位,最终的结果就是左移4位

    因此,在实际求距离时,cvReprojectTo3D出来的X/W,Y/W,Z/W都要乘以16 (也就是W除以16),才能得到正确的三维坐标信息


    Q4:利用双摄像头进行测距的时候世界坐标的原点究竟在哪里? 

    A:世界坐标系的原点是左摄像头凸透镜的光心。

    说起这个,就不得不提到针孔模型。如图3所示,针孔模型是凸透镜成像的一种简化模型。当物距足够远时(远大于两倍焦距),凸透镜成像可以看作是在焦距处的小孔成像。(ref: http://bak1.beareyes.com.cn/2/lib/200110/04/20011004006.htm)


    图3. 针孔模型


    在实际计算过程中,为了计算方便,我们将像平面翻转平移到针孔前,从而得到一种数学上更为简单的等价形式(方便相似三角形的计算),如图4所示。

    图4. 针孔模型的数学等价形式

     

     

    因此,对应图2就可以知道,世界坐标系原点就是左摄像头针孔模型的针孔,也就是左摄像头凸透镜的光心

     

    Q5:f和d的单位是像素,那这个像素到底表示什么,它与毫米之间又是怎样换算的?

    A:这个问题也与针孔模型相关。在针孔模型中,光线穿过针孔(也就是凸透镜中心)在焦距处上成像,因此,图3的像平面就是摄像头的CCD传感器的表面。每个CCD传感器都有一定的尺寸,也有一定的分辨率,这个就确定了毫米与像素点之间的转换关系。举个例子,CCD的尺寸是8mm X 6mm,分辨率是640X480,那么毫米与像素点之间的转换关系就是80pixel/mm。

    在实际运用中,我们在数学上将这个像平面等效到小孔前(图4),这样就相当于将在透镜中心点之前假设了一块虚拟的CCD传感器。

     

    Q6:为什么cvStereoRectify求出的Q矩阵cx, cy, f都与原来的不同?

    A:这个在前文有提到过。在实际测量中,由于摄像头摆放的关系,左右摄像头的f, cx, cy都是不相同的。而为了使左右视图达到完全平行对准的理想形式从而达到数学上运算的方便,立体 校准所做的工作事实上就是在左右像重合区域最大的情况下,让两个摄像头光轴的前向平行,并且让左右摄像头的f, cx, cy相同。因此,Q矩阵中的值与两个instrinsic矩阵的值不一样就可以理解了。

     

    实验结果:

    实验下来,虽然Block Matching算法本身对精度有所限制,但测距基本能达到能让人接受的精度,结果如下图5所示

     

    图5. OpenCV双摄像头测距结果


    上图中,中、左、右三个物体分别被放在离摄像头50cm, 75cm和90cm的位置。可以看出测距的结果相当不错。当然,上面这幅图是比较好的结果。由于BM算法的限制,同一点云中相同距离的点一般会有正负2厘米之内的误差。


    图6是利用双目摄像头测物体长宽的结果,可以看出结果似乎不太准确。。。

    图6. OpenCV双摄像头测边长结果


    其中,物体宽为117-88=29mm,但实际宽度为5.2cm,物体高位71-13=58mm,但实际高度为13cm。这方面的误差还是比较难以理解

    此外,还有一个问题至今尚未完全理解,就是双目摄像头的中心距,为什么采用Tx而不是T向量的长度。因为如果要左右视图重合区域最大化的话两个摄像头的光轴都要与T垂直才是(如图7),这样的话,校正后两个摄像头的中心距应该是T才对。不知道我这样的理解对不对?


    图7. 双摄像头立体校准俯视图


    展开全文
  • 学习OpenCV双目测距原理及常见问题解答 转自博客:https://blog.csdn.net/angle_cal/article/details/50800775 一. 整体思路和问题转化. 图1. 双摄像头模型俯视图图1解释了双摄像头测距的原理,书中Z的公式如下:...

    学习OpenCV双目测距原理及常见问题解答

    转自博客:https://blog.csdn.net/angle_cal/article/details/50800775

    一. 整体思路和问题转化.

    这里写图片描述 
    图1. 双摄像头模型俯视图 
    图1解释了双摄像头测距的原理,书中Z的公式如下: 
    这里写图片描述 
    在OpenCV中,f的量纲是像素点,T的量纲由定标棋盘格的实际尺寸和用户输入值确定,一般总是设成毫米,当然为了精度提高也可以设置为0.1毫米量级,d=xl-xr的量纲也是像素点。因此分子分母约去,z的量纲与T相同 
    这里写图片描述 
    图2, 双摄像头模型立体视图 
    图2解释了双摄像头获取空间中某点三维坐标的原理。 
    注意,左镜头光心是世界坐标系的原点,该坐标系是左手屏幕坐标系,所以在该点上方,前方的物体,他的世界坐标中,Y是负数. 
    这里写图片描述 
    可以看到,实际的坐标计算利用的都是相似三角形的原理,其表达式就如同Q矩阵所示。空间中某点的三维坐标就是(X/W, Y/W, Z/W)。所以,得到了Q矩阵,就是得到了一个点的世界坐标. 
    因此,为了精确地求得某个点在三维空间里的距离,我们需要获得的参数有焦距f、视差d、摄像头中心距Tx。如果还需要获得X坐标和Y坐标的话,那么还需要额外知道左右像平面的坐标系与立体坐标系中原点的偏移cx和cy。 
    要测距,就又有这五个参数. 
    f, Tx, cx和cy可以通过立体标定获得初始值,并通过立体校准优化,使得两个摄像头在数学上完全平行放置,并且左右摄像头的cx, cy和f相同(也就是实现下图中左右视图完全平行对准的理想形式)。 
    这里写图片描述 
    立体匹配所做的工作,就是在之前的基础上,求取最后一个变量:视差d(这个d一般需要达到亚像素精度)。从而最终完成求一个点三维坐标所需要的准备工作。

    总结:使用OpenCV进行的立体视觉测距,其实思路是这样的:根据摄像头的成像原理(表现为小孔成像等效模型)和具体设备的成像特性(表现为光心距离,两个焦距,两个镜头安装的相对位置),设法建立像和真实世界的映射关系(表现为上述五个参数),并以摄像机系统为参考系,为真实世界建立绝对坐标系(该坐标系的具体形式请看下文),通过上述映射关系,该方法能够把像点所在的世界坐标位置求解出来,实现距离测量.

    在清楚了上述原理之后,我们也就知道了,所有的这几步:标定、校准和匹配,都是围绕着如何更精确地获得f, d, Tx, cx和cy而设计的。

    二. OpenCV2.4.11的实现.

    按照上述解释,步骤是这样的: 
    1.准备工作:依次完成:标定->校准->匹配这三个操作,获得所需的参数: 
    T_x,f,d, C_x, C_y.其中,标定和校准的目的是求解Q矩阵,匹配的目的是求解视差值d. 
    这里写图片描述 
    2. 通过某种手段,获得待测点在”像世界”中的坐标(x.y),构造向量: 
    这里写图片描述 
    3. 通过Q•W运算,得到世界坐标向量,进而计算距离. 
    4. 具体实现步骤:

    (1)标定和矫正

    函数 findChessboardCorners()以标定盘图片和标定盘参数为输入,得到立体标定的输入参数; 
    函数:stereoCalibrate()输出变量: 
    R – Output rotation matrix (旋转) 
    T – Output translation vector(平移) 
    E – Output essential matrix.(本征) 
    F – Output fundamental matrix.(基础) 
    函数:stereoRectify()的输入变量已经从上面得到,他的输出变量如下: 
    R1 – Output 3x3 rectification transform (rotation matrix) for the first camera. 
    R2 – Output 3x3 rectification transform (rotation matrix) for the second camera. 
    P1 – Output 3x4 projection matrix in the new (rectified) coordinate systems for the first camera. 
    P2 – Output 3x4 projection matrix in the new (rectified) coordinate systems for the second camera. 
    Q – Output disparity-to-depth mapping matrix

    (2)匹配

    OpenCV2.4.11中提供了若干种匹配方法,这里采用的是BM,SGBM,VAR算法,这三个算法在使用的时候都需要构造相应的对象,对其中的输入属性进行设置,利用其提供的”()”操作符的重载执行相关的算法.他们都要求输入左右视图,输出视差图,具体情况如下: 
    SGBM: left – Left 8-bit single-channel or 3-channel image. 
    right – Right image of the same size and the same type as the left one. 
    disp – Output disparity map. It is a 16-bit signed single-channel image of the same size as the input image. It contains disparity values scaled by 16. So, to get the floating-point disparity map, you need to divide each disp element by 16. 
    BM: left – Left 8-bit single-channel image. 
    right – Right image of the same size and the same type as the left one. 
    disparity – Output disparity map. It has the same size as the input images. When disptype==CV_16S, the map is a 16-bit signed single-channel image, containing disparity values scaled by 16. To get the true disparity values from such fixed-point representation, you will need to divide each disp element by 16. If disptype==CV_32F, the disparity map will already contain the real disparity values on output. 
    disptype – Type of the output disparity map, CV_16S (default) or CV_32F. 
    Var: left – Left 8-bit single-channel or 3-channel image. 
    right – Right image of the same size and the same type as the left one. 
    disp – Output disparity map. It is a 8-bit signed single-channel image of the same size as the input image. 
    输出统一以8位视差图计算,不是8位转换成8位.全部采用CV_16S制式.

    (3)取得待测点的图像空间坐标值

    这一步很简单,只需要设法获取图片上的某个点的坐标就可以,此坐标只是相对于图片本身而言,所以可以使用例如鼠标点击或输入坐标的方法

    (4)已经得到了全部的数据,利用Q矩阵进行计算就可以了。

     

    三.代码中的关键函数:

    cvInitUndistortRectifyMap()函数是开源视觉库OpenCV的库函数。该函数是以C语言为基础编写的,而initUndistortRectifyMap()以C++语言为基础编写的。

    函数体

    编辑
    void cvInitUndistortRectifyMap(const CvMat* camera_matrix, const CvMat* dist_coeffs, const CvMat* R, const CvMat* new_camera_matrix, CvArr* mapx, CvArr* mapy)

    参数说明

    编辑
    camera_matrix——输入的3X3的摄像机内参数矩阵
    dist_coeffs——输入的5X1的摄像机畸变系数矩阵
    R——输入的第一和第二相机坐标系之间3X3的旋转矩阵
    new_camera_matrix——输入的校正后的3X3摄像机矩阵(也可用cvStereoRectify()得出的3X4的左或右投影矩阵,其实系统会自动提取该矩阵前三列的有用部分作为输入参数)
    mapx——输出的X坐标重映射参数
    mapy——输出的Y坐标重映射参数
    上述的输入参数可由cvStereoRectify()直接计算得到

    概述

    编辑
    cvInitUndistortRectifyMap()主要用于摄像机校正映射
     
    initUndistortRectifyMap

    函数体

    编辑
    void initUndistortRectifyMap( InputArray cameraMatrix, InputArray distCoeffs,
    InputArray R, InputArray newCameraMatrix,
    Size size, int m1type, OutputArray map1, OutputArray map2 );

    参数解释

    编辑
    cameraMatrix——输入的摄像机内参数矩阵
    distCoeffs——输入的摄像机畸变系数矩阵
    R——输入的第一和第二相机坐标系之间的旋转矩阵
    newCameraMatrix——输入的校正后的3X3摄像机矩阵(也可用cvStereoRectify()得出的3X4的左或右投影矩阵,其实系统会自动提取该矩阵前三列的有用部分作为输入参数)
    size——摄像机采集的无失真图像尺寸
    m1type——map1的数据类型,可以是CV_32FC1或CV_16SC2
    map1——输出的X坐标重映射参数
    map2——输出的Y坐标重映射参数

    概述

    编辑
    initUndistortRectifyMap()主要用于摄像机校正映射

     

    OpenCV三种立体匹配求视差图算法总结:

    首先我们看一下BM算法:

            Ptr<StereoBM> bm = StereoBM::create(16,9);//局部的BM;
            // bm算法
            bm->setROI1(roi1);//左右视图的有效像素区域 在有效视图之外的视差值被消零
            bm->setROI2(roi2);
            bm->setPreFilterType(CV_STEREO_BM_XSOBEL);
            bm->setPreFilterSize(9);//滤波器尺寸 [5,255]奇数
            bm->setPreFilterCap(31);//预处理滤波器的截断值 [1-31] 
            bm->setBlockSize(SADWindowSize > 0 ? SADWindowSize : 15);//sad窗口大小
            bm->setMinDisparity(0);//最小视差值,代表了匹配搜索从哪里开始
            bm->setNumDisparities(numberOfDisparities);//表示最大搜索视差数
            bm->setTextureThreshold(10);//低纹理区域的判断阈值 x方向导数绝对值之和小于阈值
            bm->setUniquenessRatio(15);//视差唯一性百分比  匹配功能函数
            bm->setSpeckleWindowSize(100);//检查视差连通域 变化度的窗口大小
            bm->setSpeckleRange(32);//视差变化阈值  当窗口内视差变化大于阈值时,该窗口内的视差清零
            bm->setDisp12MaxDiff(-1);// 1
    
        该方法速度最快,一副320*240的灰度图匹配时间为31ms 
    

    第二种方法是SGBM方法这是OpenCV的一种新算法:

        Ptr<StereoSGBM> sgbm = StereoSGBM::create(0,16,3);//全局的SGBM;
         // sgbm算法
            sgbm->setPreFilterCap(63);//预处理滤波器的截断值 [1-63] 
            int sgbmWinSize = SADWindowSize > 0 ? SADWindowSize : 3;
            sgbm->setBlockSize(sgbmWinSize);
            int cn = img0.channels();
            sgbm->setP1(8*cn*sgbmWinSize*sgbmWinSize);// 控制视差变化平滑性的参数。P1、P2的值越大,视差越平滑。
        //P1是相邻像素点视差增/减 1 时的惩罚系数;P2是相邻像素点视差变化值大于1时的惩罚系数。P2必须大于P1
            sgbm->setP2(32*cn*sgbmWinSize*sgbmWinSize);
            sgbm->setMinDisparity(0);//最小视差值,代表了匹配搜索从哪里开始
            sgbm->setNumDisparities(numberOfDisparities);//表示最大搜索视差数
            sgbm->setUniquenessRatio(10);//表示匹配功能函数
            sgbm->setSpeckleWindowSize(100);//检查视差连通域 变化度的窗口大小
            sgbm->setSpeckleRange(32);//视差变化阈值  当窗口内视差变化大于阈值时,该窗口内的视差清零
            sgbm->setDisp12MaxDiff(-1);// 1
        //左视图差(直接计算)和右视图差(cvValidateDisparity计算得出)之间的最大允许差异
            if(alg==STEREO_HH)               sgbm->setMode(StereoSGBM::MODE_HH);
            else if(alg==STEREO_SGBM)  sgbm->setMode(StereoSGBM::MODE_SGBM);
            else if(alg==STEREO_3WAY)   sgbm->setMode(StereoSGBM::MODE_SGBM_3WAY);
        各参数设置如BM方法,速度比较快,320*240的灰度图匹配时间为78ms,
    

    第三种为GC方法:

        该方法速度超慢,但效果超好。

     

    四.FAQ:

    Q1:标定时棋盘格的大小如何设定,对最后结果有没有影响?

    A:当然有。在标定时,需要指定一个棋盘方格的长度,这个长度(一般以毫米为单位,如果需要更精确可以设为0.1毫米量级)与实际长度相同,标定得出的结果才能用于实际距离测量。一般如果尺寸设定准确的话,通过立体标定得出的Translation的向量的第一个分量Tx的绝对值就是左右摄像头的中心距。一般可以用这个来验证立体标定的准确度。比如我设定的棋盘格大小为270 (27mm),最终得出的Tx大小就是602.8 (60.28mm),相当精确。

    Q2:通过立体标定得出的Tx符号为什么是负的?

    A:这个其实我也不是很清楚。个人的解释是,立体标定得出的T向量指向是从右摄像头指向左摄像头(也就是Tx为负),而在OpenCV坐标系中,坐标的原点是在左摄像头的。因此,用作校准的时候,要把这个向量的三个分量符号都要换一下,最后求出的距离才会是正的。 
    但是这里还有一个问题,就是Learning OpenCV中Q的表达式,第四行第三列元素是-1/Tx,而在具体实践中,求出来的实际值是1/Tx。这里我和maxwellsdemon讨论下来的结果是,估计书上Q表达式里的这个负号就是为了抵消T向量的反方向所设的,但在实际写OpenCV代码的过程中,那位朋友却没有把这个负号加进去。(一家之言,求更详细的解释)

    Q3:cvFindStereoCorrespondenceBM的视差输出结果单位是?

    A:在OpenCV中,BM函数得出的结果是以16位符号数的形式的存储的,出于精度需要,所有的视差在输出时都扩大了16倍(2^4)。其具体代码表示如下: 
    dptr[y*dstep] = (short)(((ndisp - mind - 1 + mindisp)*256 + (d != 0 ? (p-n)*128/d : 0) + 15) >> 4); 
    可以看到,原始视差在左移8位(256)并且加上一个修正值之后又右移了4位,最终的结果就是左移4位 
    因此,在实际求距离时,cvReprojectTo3D出来的X/W,Y/W,Z/W都要乘以16 (也就是W除以16),才能得到正确的三维坐标信息

    Q4:利用双摄像头进行测距的时候世界坐标的原点究竟在哪里?

    A:世界坐标系的原点是左摄像头凸透镜的光心。 
    说起这个,就不得不提到针孔模型。如图3所示,针孔模型是凸透镜成像的一种简化模型。当物距足够远时(远大于两倍焦距),凸透镜成像可以看作是在焦距处的小孔成像。 
    这里写图片描述 
    在实际计算过程中,为了计算方便,我们将像平面翻转平移到针孔前,从而得到一种数学上更为简单的等价形式(方便相似三角形的计算),如下图所示。 
    这里写图片描述 
    因此,对应图2就可以知道,世界坐标系原点就是左摄像头针孔模型的针孔,也就是左摄像头凸透镜的光心

    Q5:f和d的单位是像素,那这个像素到底表示什么,它与毫米之间又是怎样换算的?

    A:这个问题也与针孔模型相关。在针孔模型中,光线穿过针孔(也就是凸透镜中心)在焦距处上成像,因此,图3的像平面就是摄像头的CCD传感器的表面。每个CCD传感器都有一定的尺寸,也有一定的分辨率,这个就确定了毫米与像素点之间的转换关系。举个例子,CCD的尺寸是8mm X 6mm,分辨率是640X480,那么毫米与像素点之间的转换关系就是80pixel/mm。 
    在实际运用中,我们在数学上将这个像平面等效到小孔前(图4),这样就相当于将在透镜中心点之前假设了一块虚拟的CCD传感器。

    Q6:为什么cvStereoRectify求出的Q矩阵cx, cy, f都与原来的不同?

    A:这个在前文有提到过。在实际测量中,由于摄像头摆放的关系,左右摄像头的f, cx, cy都是不相同的。而为了使左右视图达到完全平行对准的理想形式从而达到数学上运算的方便,立体 校准所做的工作事实上就是在左右像重合区域最大的情况下,让两个摄像头光轴的前向平行,并且让左右摄像头的f, cx, cy相同。因此,Q矩阵中的值与两个instrinsic矩阵的值不一样就可以理解了。

     

     相关网址:

     opencv双目测距实现:https://cloud.tencent.com/developer/article/1082064

    initUndistortRectifyMap:http://www.voidcn.com/article/p-qyftgzxl-brg.html

    真实场景的双目立体匹配(Stereo Matching)获取深度图详解——最终得到深度图像并且填充:https://www.cnblogs.com/riddick/p/8486223.html 

    OpenCV畸变校正原理以及损失有效像素原理分析:https://www.cnblogs.com/riddick/p/6711263.html

    github双目相关理论与实践:https://github.com/melodybinbin/MVision/tree/master/stereo

     

     

    转载于:https://www.cnblogs.com/yuanlibin/p/9460419.html

    展开全文
  • <?xml version="1.0" ...manifest xmlns:android="http://schemas.android.com/apk/res/android"package="org.opencv" android:versionCode="3410" android:versionName="3.4.1"></manifest>
  • Opencv双目测距 使用cvReprojectImageTo3D函数求目标三维坐标 ``` CvMat* depth_disparity=cvCreateMat(img_left_Change->height,img_left_Change->width, CV_32FC3 ); cvReprojectImageTo3D(norm_...
  • 二、双目测距步骤1.双目标定2.测距测试结果 前言 最近有项目需要用到摄像测距,于是开始接触opencv机器视觉。学了好几天的摄像机测距相关的知识后就开始动手验证,刚开始是单目测距,搞了个树莓派的开发板,然后...
    
    
    


    前言

    最近有项目需要用到摄像测距,于是开始接触opencv机器视觉。学了好几天的摄像机测距相关的知识后就开始动手验证,刚开始是单目测距,搞了个树莓派的开发板,然后下载网上的一些代码验证,发现单目需要预先知道被测物,因为要实现避障功能,所以后面选了双目测距。目前的进度是能在PC上利用双目进行测距,近距离双目测距精度还行,后续需要将代码移植至树莓派B4板子上,由树莓派来进一步论证项目可行性


    提示:以下是本篇文章正文内容,下面案例可供参考

    一、什么是拍照测距?

    个人了解到拍照测距有两种方式,单目测距和双目测距,单目是只用一个摄像头,测距前提是需要知道被测物体是什么。双目测距需要一个双目的摄像头。

    二、双目测距步骤

    1.双目标定

    原来的双目标定是直接使用的opencv自带的标定功能,但是发现对图片的要求比较高,而且标定的结果在后面的测距上并不准(可能是我标定时候不准确导致的),后面就使用的MATLAB进行标定。

    我是在淘宝上买了个双目摄像头,自己A4纸打印的棋盘格。用厂家提供的图像采集方式进行了拍照。取了15张照片(左目和右目各15张),后用matlab标定时候有几张图片的误差有点大就给删了,最后取了12张照片进行标定。标定过程就不说了,可以通过以下链接进行了解
    https://blog.csdn.net/u013451663/article/details/89954646

    重点说一下用matlab得出来的参数的对应关系:
    在这里插入图片描述

    在这里插入图片描述
    先看一下畸变参数,得到的值就是K1,K2,K3,和P1,P2,代码赋值的时候应该是K1,K2,P1,P2,K3

    Mat distCoeffL = (Mat_<double>(5, 1) << 0.310458259610102, -2.26297309194147, -0.00764246381079933, 0.00634878271949189, 6.11556840747635);
    

    具体说一下内参,内参是一个3x3的矩阵,双击matlab里面的值,得到的表格是这样的
    在这里插入图片描述
    这个表格里面和代码需要的数据要置换一下

    fx 0 cx
    0 fy cy
    0  0  1
    

    在这里插入图片描述
    代码赋值如下:

    Mat cameraMatrixL = (Mat_<double>(3, 3) << 337.709436280709, 0.741962718557881, 150.799143051710,
    	0, 337.863855604370, 123.314225146904,
    	0, 0, 1);
    

    旋转矩阵也是3x3,所以也和内参一样,置换一下。
    平移矩阵是可以直接使用的
    在这里插入图片描述
    附上赋值代码如下

    Mat rec = (Mat_<double>(3, 3) << 0.999989526750612, 0.00232022184998904, 0.00394499171785794,
    	-0.00228582974058393, 0.999959540028791, -0.00870018895234802,
    	-0.00396501847211287, 0.00869108025370437, 0.999954370835259); 
    	  
    Mat T = (Mat_<double>(3, 1) << -41.5775139873461, 0.241065317743041, 0.408815384344912);
    

    至此,标定就结束了。

    2.测距

    测距是使用的该大神的代码,我把它拷贝过来了。
    https://guo-pu.blog.csdn.net/article/details/86744936?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.not_use_machine_learn_pai&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.not_use_machine_learn_pai

    #include <opencv2/opencv.hpp>  
    #include <iostream>  
    #include <math.h> 
    
    using namespace std;
    using namespace cv;
    
    const int imageWidth = 320;                             //图片大小  
    const int imageHeight = 240;
    Vec3f  point3;
    float d;
    Size imageSize = Size(imageWidth, imageHeight);
    
    Mat rgbImageL, grayImageL;
    Mat rgbImageR, grayImageR;
    Mat rectifyImageL, rectifyImageR;
    
    Rect validROIL;//图像校正之后,会对图像进行裁剪,这里的validROI就是指裁剪之后的区域  
    Rect validROIR;
    
    Mat mapLx, mapLy, mapRx, mapRy;     //映射表  
    Mat Rl, Rr, Pl, Pr, Q;              //校正旋转矩阵R,投影矩阵P 重投影矩阵Q
    Mat xyz;              //三维坐标
    
    Point origin;         //鼠标按下的起始点
    Rect selection;      //定义矩形选框
    bool selectObject = false;    //是否选择对象
    
    int blockSize = 0, uniquenessRatio = 0, numDisparities = 0;
    Ptr<StereoBM> bm = StereoBM::create(16, 9);
    
    Mat cameraMatrixL = (Mat_<double>(3, 3) << 337.709436280709, 0.741962718557881, 150.799143051710,
    	0, 337.863855604370, 123.314225146904,
    	0, 0, 1);
    
    Mat distCoeffL = (Mat_<double>(5, 1) << 0.310458259610102, -2.26297309194147, -0.00764246381079933, 0.00634878271949189, 6.11556840747635);
    
    Mat cameraMatrixR = (Mat_<double>(3, 3) << 337.093687218177, 0.587984682766586, 152.848985873868,
    	0, 336.971855005274, 117.527331021388,
    	0, 0, 1);
    
    Mat distCoeffR = (Mat_<double>(5, 1) << 0.439757633387106, -5.17644381384173, -0.0103643563681475, 0.00184932125612765, 23.4806041578594);
    
    Mat T = (Mat_<double>(3, 1) << -41.5775139873461, 0.241065317743041, 0.408815384344912);//T平移向量
    
    Mat rec = (Mat_<double>(3, 3) << 0.999989526750612, 0.00232022184998904, 0.00394499171785794,
    	-0.00228582974058393, 0.999959540028791, -0.00870018895234802,
    	-0.00396501847211287, 0.00869108025370437, 0.999954370835259);                //rec旋转向量
    
    Mat R;//R 旋转矩阵
    
    /*****立体匹配*****/
    void stereo_match(int, void*)
    {
    	bm->setBlockSize(2 * blockSize + 5);     //SAD窗口大小,5~21之间为宜
    	bm->setROI1(validROIL);
    	bm->setROI2(validROIR);
    	bm->setPreFilterCap(31);
    	bm->setMinDisparity(0);  //最小视差,默认值为0, 可以是负值,int型
    	bm->setNumDisparities(numDisparities * 16 + 16);//视差窗口,即最大视差值与最小视差值之差,窗口大小必须是16的整数倍,int型
    	bm->setTextureThreshold(10);
    	bm->setUniquenessRatio(uniquenessRatio);//uniquenessRatio主要可以防止误匹配
    	bm->setSpeckleWindowSize(100);
    	bm->setSpeckleRange(32);
    	bm->setDisp12MaxDiff(-1);
    	Mat disp, disp8;
    	bm->compute(rectifyImageL, rectifyImageR, disp);//输入图像必须为灰度图
    	disp.convertTo(disp8, CV_8U, 255 / ((numDisparities * 16 + 16) * 16.));//计算出的视差是CV_16S格式
    	reprojectImageTo3D(disp, xyz, Q, true); //在实际求距离时,ReprojectTo3D出来的X / W, Y / W, Z / W都要乘以16(也就是W除以16),才能得到正确的三维坐标信息。
    	xyz = xyz * 16;
    	imshow("disparity", disp8);
    }
    
    /*****描述:鼠标操作回调*****/
    static void onMouse(int event, int x, int y, int, void*)
    {
    	if (selectObject)
    	{
    		selection.x = MIN(x, origin.x);
    		selection.y = MIN(y, origin.y);
    		selection.width = std::abs(x - origin.x);
    		selection.height = std::abs(y - origin.y);
    	}
    
    	switch (event)
    	{
    	case EVENT_LBUTTONDOWN:   //鼠标左按钮按下的事件
    		origin = Point(x, y);
    		selection = Rect(x, y, 0, 0);
    		selectObject = true;
    		//cout << origin << "in world coordinate is: " << xyz.at<Vec3f>(origin) << endl;
    		point3 = xyz.at<Vec3f>(origin);
    		point3[0];
    		cout << "世界坐标:" << endl;
    		cout << "x: " << point3[0] << "  y: " << point3[1] << "  z: " << point3[2] << endl;
    		d = point3[0] * point3[0] + point3[1] * point3[1] + point3[2] * point3[2];
    		d = sqrt(d);   //mm
    		d = d / 10.0;   //cm
    		cout << "距离是:" << d << "cm" << endl;
    		break;
    	case EVENT_LBUTTONUP:    //鼠标左按钮释放的事件
    		selectObject = false;
    		if (selection.width > 0 && selection.height > 0)
    			break;
    	}
    }
    
    
    /*****主函数*****/
    int main()
    {
    	/*
    	立体校正
    	*/
    	Rodrigues(rec, R); //Rodrigues变换
    	stereoRectify(cameraMatrixL, distCoeffL, cameraMatrixR, distCoeffR, imageSize, R, T, Rl, Rr, Pl, Pr, Q, CALIB_ZERO_DISPARITY,
    		0, imageSize, &validROIL, &validROIR);
    	initUndistortRectifyMap(cameraMatrixL, distCoeffL, Rl, Pr, imageSize, CV_32FC1, mapLx, mapLy);
    	initUndistortRectifyMap(cameraMatrixR, distCoeffR, Rr, Pr, imageSize, CV_32FC1, mapRx, mapRy);
    
    	/*
    	读取图片
    	*/
    	rgbImageL = imread("C:\\Users\\DELL\\picture\\left_33.png", CV_LOAD_IMAGE_COLOR);
    	cvtColor(rgbImageL, grayImageL, CV_BGR2GRAY);
    	rgbImageR = imread("C:\\Users\\DELL\\picture\\right_33.png", CV_LOAD_IMAGE_COLOR);
    	cvtColor(rgbImageR, grayImageR, CV_BGR2GRAY);
    
    	imshow("ImageL Before Rectify", grayImageL);
    	imshow("ImageR Before Rectify", grayImageR);
    
    	/*
    	经过remap之后,左右相机的图像已经共面并且行对准了
    	*/
    	remap(grayImageL, rectifyImageL, mapLx, mapLy, INTER_LINEAR);
    	remap(grayImageR, rectifyImageR, mapRx, mapRy, INTER_LINEAR);
    
    	/*
    	把校正结果显示出来
    	*/
    	Mat rgbRectifyImageL, rgbRectifyImageR;
    	cvtColor(rectifyImageL, rgbRectifyImageL, CV_GRAY2BGR);  //伪彩色图
    	cvtColor(rectifyImageR, rgbRectifyImageR, CV_GRAY2BGR);
    
    	//单独显示
    	imshow("ImageL After Rectify", rgbRectifyImageL);
    	imshow("ImageR After Rectify", rgbRectifyImageR);
    
    	//显示在同一张图上
    	Mat canvas;
    	double sf;
    	int w, h;
    	sf = 600. / MAX(imageSize.width, imageSize.height);
    	w = cvRound(imageSize.width * sf);
    	h = cvRound(imageSize.height * sf);
    	canvas.create(h, w * 2, CV_8UC3);   //注意通道
    
    										//左图像画到画布上
    	Mat canvasPart = canvas(Rect(w * 0, 0, w, h));                                //得到画布的一部分  
    	resize(rgbRectifyImageL, canvasPart, canvasPart.size(), 0, 0, INTER_AREA);     //把图像缩放到跟canvasPart一样大小  
    	Rect vroiL(cvRound(validROIL.x * sf), cvRound(validROIL.y * sf),                //获得被截取的区域    
    		cvRound(validROIL.width * sf), cvRound(validROIL.height * sf));
    	cout << "Painted ImageL" << endl;
    
    	//右图像画到画布上
    	canvasPart = canvas(Rect(w, 0, w, h));                                      //获得画布的另一部分  
    	resize(rgbRectifyImageR, canvasPart, canvasPart.size(), 0, 0, INTER_LINEAR);
    	Rect vroiR(cvRound(validROIR.x * sf), cvRound(validROIR.y * sf),
    		cvRound(validROIR.width * sf), cvRound(validROIR.height * sf));
    	cout << "Painted ImageR" << endl;
    
    	//画上对应的线条
    	for (int i = 0; i < canvas.rows; i += 16)
    		line(canvas, Point(0, i), Point(canvas.cols, i), Scalar(0, 255, 0), 1, 8);
    	imshow("rectified", canvas);
    
    	/*
    	立体匹配
    	*/
    	namedWindow("disparity", CV_WINDOW_AUTOSIZE);
    	// 创建SAD窗口 Trackbar
    	createTrackbar("BlockSize:\n", "disparity", &blockSize, 8, stereo_match);
    	// 创建视差唯一性百分比窗口 Trackbar
    	createTrackbar("UniquenessRatio:\n", "disparity", &uniquenessRatio, 50, stereo_match);
    	// 创建视差窗口 Trackbar
    	createTrackbar("NumDisparities:\n", "disparity", &numDisparities, 16, stereo_match);
    	//鼠标响应函数setMouseCallback(窗口名称, 鼠标回调函数, 传给回调函数的参数,一般取0)
    	setMouseCallback("disparity", onMouse, 0);
    	stereo_match(0, 0);
    
    	waitKey(0);
    	return 0;
    }
    

    测试结果

    测出来的结果还可以,精度挺高,最后附上测试的结果图。先记录这么多,后续还要移植到树莓派。

    在这里插入图片描述

    展开全文
  • opencv双目测距实现

    千次阅读 2017-08-15 15:44:35
    双目测距原理及实现

    虽然最近注意力已经不可遏制地被神经科学、大脑记忆机制和各种毕业活动吸引过去了,但是还是觉得有必要把这段时间双目视觉方面的进展总结一下。毕竟从上一篇博文发表之后,很多同仁发E-mail来与我讨论,很多原来的疑团,也在讨论和一步步的试验中逐渐解决了。  

    开篇之前,首先要感谢maxwellsdemon和wobject,没有和你们的讨论,也就没有此篇的成文。


    说到双摄像头测距,首先要复习一下测距原理,把Learning OpenCV翻到416和418页,可以看到下面两幅图


    图1. 双摄像头模型俯视图


    图2, 双摄像头模型立体视图




    图1解释了双摄像头测距的原理,书中Z的公式如下:

     

    在OpenCV中,f的量纲是像素点,Tx的量纲由定标棋盘格的实际尺寸和用户输入值确定,一般总是设成毫米,当然为了精度提高也可以设置为0.1毫米量级,d=xl-xr的量纲也是像素点。因此分子分母约去,z的量纲与Tx相同

     

    图2解释了双摄像头获取空间中某点三维坐标的原理。

     

    可以看到,实际的坐标计算利用的都是相似三角形的原理,其表达式就如同Q矩阵所示。

     

     

    空间中某点的三维坐标就是(X/W, Y/W, Z/W)。

     

    因此,为了精确地求得某个点在三维空间里的距离,我们需要获得的参数有焦距f、视差d、摄像头中心距Tx。

    如果还需要获得X坐标和Y坐标的话,那么还需要额外知道左右像平面的坐标系与立体坐标系中原点的偏移cx和cy。其中f, Tx, cx和cy可以通过立体标定获得初始值,并通过立体校准优化,使得两个摄像头在数学上完全平行放置,并且左右摄像头的cx, cy和f相同(也就是实现图2中左右视图完全平行对准的理想形式)。而立体匹配所做的工作,就是在之前的基础上,求取最后一个变量:视差d(这个d一般需要达到亚像素精度)。从而最终完成求一个点三维坐标所需要的准备工作。

     

    在清楚了上述原理之后,我们也就知道了,所有的这几步:标定、校准和匹配,都是围绕着如何更精确地获得f, d, Tx, cx和cy而设计的。


     

    双目测距的原理就说到这里,为了避免大家看到大段纯叙述性的文字头晕,下面的行文将会以FAQ的形式围绕着实现双摄像头测距过程中碰到的几点疑惑展开。当然,其中的解答也只是我的个人理解,如有不当,敬请指正。

    Q1:标定时棋盘格的大小如何设定,对最后结果有没有影响?

    A:当然有。在标定时,需要指定一个棋盘方格的长度,这个长度(一般以毫米为单位,如果需要更精确可以设为0.1毫米量级)与实际长度相同,标定得出的结果才能用于实际距离测量。一般如果尺寸设定准确的话,通过立体标定得出的Translation的向量的第一个分量Tx的绝对值就是左右摄像头的中心距。一般可以用这个来验证立体标定的准确度。比如我设定的棋盘格大小为270 (27mm),最终得出的Tx大小就是602.8 (60.28mm),相当精确。

     

    Q2:通过立体标定得出的Tx符号为什么是负的?

    A:这个其实我也不是很清楚。个人的解释是,立体标定得出的T向量指向是从右摄像头指向左摄像头(也就是Tx为负),而在OpenCV坐标系中,坐标的原点是在左摄像头的。因此,用作校准的时候,要把这个向量的三个分量符号都要换一下,最后求出的距离才会是正的。

    但是这里还有一个问题,就是Learning OpenCV中Q的表达式,第四行第三列元素是-1/Tx,而在具体实践中,求出来的实际值是1/Tx。这里我和maxwellsdemon讨论下来的结果是,估计书上Q表达式里的这个负号就是为了抵消T向量的反方向所设的,但在实际写OpenCV代码的过程中,那位朋友却没有把这个负号加进去。(一家之言,求更详细的解释)

     

    Q3:cvFindStereoCorrespondenceBM的输出结果好像不是以像素点为单位的视差?

    A:在OpenCV2.0中,BM函数得出的结果是以16位符号数的形式的存储的,出于精度需要,所有的视差在输出时都扩大了16倍(2^4)。其具体代码表示如下:

    dptr[y*dstep] = (short)(((ndisp - mind - 1 + mindisp)*256 + (d != 0 ? (p-n)*128/d : 0) + 15) >> 4);

    可以看到,原始视差在左移8位(256)并且加上一个修正值之后又右移了4位,最终的结果就是左移4位

    因此,在实际求距离时,cvReprojectTo3D出来的X/W,Y/W,Z/W都要乘以16 (也就是W除以16),才能得到正确的三维坐标信息


    Q4:利用双摄像头进行测距的时候世界坐标的原点究竟在哪里? 

    A:世界坐标系的原点是左摄像头凸透镜的光心。

    说起这个,就不得不提到针孔模型。如图3所示,针孔模型是凸透镜成像的一种简化模型。当物距足够远时(远大于两倍焦距),凸透镜成像可以看作是在焦距处的小孔成像。(ref: http://bak1.beareyes.com.cn/2/lib/200110/04/20011004006.htm)


    图3. 针孔模型


    在实际计算过程中,为了计算方便,我们将像平面翻转平移到针孔前,从而得到一种数学上更为简单的等价形式(方便相似三角形的计算),如图4所示。

    图4. 针孔模型的数学等价形式

     

     

    因此,对应图2就可以知道,世界坐标系原点就是左摄像头针孔模型的针孔,也就是左摄像头凸透镜的光心

     

    Q5:f和d的单位是像素,那这个像素到底表示什么,它与毫米之间又是怎样换算的?

    A:这个问题也与针孔模型相关。在针孔模型中,光线穿过针孔(也就是凸透镜中心)在焦距处上成像,因此,图3的像平面就是摄像头的CCD传感器的表面。每个CCD传感器都有一定的尺寸,也有一定的分辨率,这个就确定了毫米与像素点之间的转换关系。举个例子,CCD的尺寸是8mm X 6mm,分辨率是640X480,那么毫米与像素点之间的转换关系就是80pixel/mm。

    在实际运用中,我们在数学上将这个像平面等效到小孔前(图4),这样就相当于将在透镜中心点之前假设了一块虚拟的CCD传感器。

     

    Q6:为什么cvStereoRectify求出的Q矩阵cx, cy, f都与原来的不同?

    A:这个在前文有提到过。在实际测量中,由于摄像头摆放的关系,左右摄像头的f, cx, cy都是不相同的。而为了使左右视图达到完全平行对准的理想形式从而达到数学上运算的方便,立体 校准所做的工作事实上就是在左右像重合区域最大的情况下,让两个摄像头光轴的前向平行,并且让左右摄像头的f, cx, cy相同。因此,Q矩阵中的值与两个instrinsic矩阵的值不一样就可以理解了。

     

    实验结果:

    实验下来,虽然Block Matching算法本身对精度有所限制,但测距基本能达到能让人接受的精度,结果如下图5所示

     

    图5. OpenCV双摄像头测距结果


    上图中,中、左、右三个物体分别被放在离摄像头50cm, 75cm和90cm的位置。可以看出测距的结果相当不错。当然,上面这幅图是比较好的结果。由于BM算法的限制,同一点云中相同距离的点一般会有正负2厘米之内的误差。


    图6是利用双目摄像头测物体长宽的结果,可以看出结果似乎不太准确。。。

    图6. OpenCV双摄像头测边长结果


    其中,物体宽为117-88=29mm,但实际宽度为5.2cm,物体高位71-13=58mm,但实际高度为13cm。这方面的误差还是比较难以理解

    此外,还有一个问题至今尚未完全理解,就是双目摄像头的中心距,为什么采用Tx而不是T向量的长度。因为如果要左右视图重合区域最大化的话两个摄像头的光轴都要与T垂直才是(如图7),这样的话,校正后两个摄像头的中心距应该是T才对。不知道我这样的理解对不对?


    图7. 双摄像头立体校准俯视图

    展开全文
  • opencv双目测距(BM 与SGBM匹配)

    万次阅读 多人点赞 2019-06-18 14:58:47
    在一年之前小编写了一篇双目测距的博文,引入了大量的童鞋阅读,其博文介绍了详细的相机标定与双目测距过程和代码 https://blog.csdn.net/xiao__run/article/details/78900652 摄像头如前面文章所示,大家可自行...
  • MFC+opencv双目测距

    2017-05-01 14:13:42
    1.请配置好vs环境(此版本是vs2010+opencv2.4.3所写,具体配置自己查吧。http://blog.csdn.net/garfielder007/article/details/50197181) 2.运行界面如下图(很简陋): 3.第一步点击采集棋盘图按钮,可以在...
  • python opencv 双目测距代码

    千次阅读 2019-05-21 19:56:34
    最近高摄像头项目,顺便扩展学习python+opencv的图片处理和视频处理。 拍照效果: 代码: #!/usr/bin/python # -*- coding: utf-8 -*- import cv2 import time AUTO = True # 自动拍照,或手动按s键拍照 ...
  • opencv双目测距的简单代码实现

    千次阅读 2017-12-06 16:13:07
    今年五月份开始研究双目,从刚开始的无从下手到渐渐熟悉,再到中途的想放弃,也算是历经波折,在此我把我自己东拼西凑的东西分享一下,算是我在CSDN成长的一个见证。首先说下遇到的问题: 两个摄像头之间必须固定,...
  • 1、双目相机拍照后使用Matlab进行双目标定 主要参考:https://blog.csdn.net/dulingwen/article/details/98071584 感谢大佬的分享!!!(*≧ω≦)!! Python-openCV 中cv2.StereoSGBM_create()参数的含义 参考:...
  • opencv双目测距原理与应用

    千次阅读 2016-12-28 16:38:50
    虽然最近注意力已经不可遏制地被神经科学、大脑记忆机制和各种毕业活动吸引过去了,但是还是觉得有必要把这段时间双目视觉方面的进展总结一下。毕竟从上一篇博文发表之后,很多同仁发E-mail来与我讨论,很多原来的...
  • 和上一篇一样,首先简单介绍一下使用OpenCV的范例代码来进行双目标定。我所使用的版本是3.x,4.x差别不大。 一、stereo_calib.cpp的使用 需要说明的是各个参数,标定板棋盘格上黑白方块交点的横向个数为w,纵向个...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 790
精华内容 316
关键字:

opencv双目测距