/**好记性不如烂笔头,将自己之前做的一些工作做一个简单总结**/

在立体视觉中只有当两个相机成像平面完全平行且行对准时,在立体匹配计算立体视差过程中是最简单的,为了使相机两成像平面完全平行且行对准,OpenCV提供了非标定标定的方法来计算左右相机的校正矩阵。

一、非标定方法:

非标定方法也称为(Hartley)方法,有时候我们不知道相机的内参矩阵,而且也不用知道内参数具体是多少,因为我们仅关心如何得到两幅图像的稠密匹配,或者两幅图像之间的视差图或者深度图就足够了。因为不知道相机的内参数,所以只能借助对极约束来解决问题了,通过计算两幅图像的基础矩阵F,然后利用对极约束条件中对极线为平行且行对准,可以很好的实现目标。在opencv中接口函数为:cvStereoRectifyUncalibrated(),具体如下:

(摘自:http://blog.sina.com.cn/s/blog_4298002e01013yb8.html)

//! computes the rectification transformation for an uncalibrated stereo camera (zero distortion is assumed)
bool stereoRectifyUncalibrated( const Mat& points1, const Mat& points2,const Mat& F, Size imgSize,CV_OUT Mat& H1, CV_OUT Mat& H2,double threshold=5 );  

该函数输入参数为:两幅图像的匹配特征点基本矩阵F以及图像的尺寸,返回的参数是两幅图像各自对应的单应变换矩阵H1和H2。只需要对两幅图像按照H1和H2做单应变换,即可得到矫正后图像。假设I为图像,变换如下:
                                                                 
需要说明一点,该函数的前两个参数Mat& points1, Mat& points2与cv::findFundamentalMat的前两个参数并不是相同的数据结构。它们虽然可以是同一个匹配点集,但是他们的数据结构是完全不同的!cv::findFundamentalMat中传入的匹配点集要求是2xN或者Nx2的矩阵,但是cv::stereoRectifyUncalibrated中要求传入的匹配点集必须是1x2N或者2Nx1的矩阵!在很多文档中都说他们的参数是一样的,这其实是一个天大的错误,如果用计算F的匹配点集直接传给图像矫正函数,程序将直接崩溃。正确的做法是利用cv::Mat的构造函数,直接从vector<Point2f>构造一个cv::Mat传入。

cv::stereoRectifyUncalibrated函数默认原始图像是没有径向畸变的,因此在矫正图像之前,最好先对原始图像做径向矫正。另外需要注意的一点,函数返回的单应变换矩阵H1和H2都是double类型,也即CV_64F类型,若不是该类型的矩阵,与之相乘会报错。

// 假设前面我们已经得到两幅图像的匹配特征点,并计算出了基本矩阵F,同时得到了匹配特征点的inlier// Mat m_matLeftImage;
// Mat m_matRightImage;// vector<Point2f> m_LeftInlier;
// vector<Point2f> m_RightInlier;// Mat m_Fundamental;// 计算图像矫正的单应变换矩阵
Mat m_LeftH;
Mat m_RightH;stereoRectifyUncalibrated(Mat(m_LeftInlier), Mat(m_RightInlier), m_Fundamental,Size(m_matLeftImage.cols, m_matLeftImage.rows),m_LeftH, m_RightH);// 任意指定一个内参数矩阵K,不会影响计算结果,此处设为单位阵。
Mat K = Mat::eye(3, 3, CV_64F); // 注意一定是double类型
Mat invK = K.inv(DECOMP_SVD);
Mat LeftR = invK*m_LeftH*K;     // 根据单应变换矩阵计算左图摄像机在空间中的变换矩阵R1
Mat RightR = invK*m_RightH*K;   // 计算右图摄像机在空间中的变换矩阵R2
Mat LeftMap1, LeftMap2;
Mat RightMap1, RightMap2;
Mat Distort;                    // 径向畸变为0,设为空矩阵
Size UndistSize(m_matLeftImage.cols, m_matLeftImage.rows);// 计算左右两幅图像的映射矩阵
initUndistortRectifyMap(K, Distort, LeftR, K, UndistSize, CV_32FC1, LeftMap1, LeftMap2);
initUndistortRectifyMap(K, Distort, RightR, K, UndistSize, CV_32FC1, RightMap1, RightMap2);// 把原始图像投影到新图像上,得到矫正图像
Mat m_LeftRectyImage;
Mat m_RightRectyImage;remap(m_matLeftImage, m_LeftRectyImage, LeftMap1, LeftMap2, INTER_LINEAR);
remap(m_matRightImage, m_RightRectyImage, RightMap1, RightMap2, INTER_LINEAR);// 显示结果
cvNamedWindow( "left image", 1);
cvShowImage("left image", &(IplImage(m_LeftRectyImage)));
cvNamedWindow( "right image", 1);
cvShowImage("right image", &(IplImage(m_RightRectyImage)));
cvWaitKey( 0 );
cvDestroyWindow( "left image" );
cvDestroyWindow( "right image" );

二、标定方法:

标定方法也称为(Bouguet)方法,需要先分别对两个相机进行标定,分别得出两个相机的内参数矩阵,然后再进行立体标定,进行立体图像的矫正。在opencv中用cvStereoRectify()函数来计算相机矫正矩阵。简单实用如下:

/*  计算 3D 坐标点  */vector<vector<Point3f>> objRealPoint;                       //标定板上世界坐标系下3D点的坐标calRealPoint(objRealPoint,boardSize,squareSize,goodFrame);/*  双目标定  */cv::Mat R, T, E, F;   //两个相机平面之间的 旋转矩阵 平移矩阵 本征矩阵 基础矩阵double rms = stereoCalibrate(objRealPoint, imagePointL, imagePointR, cameraMatrixL, distCoeffL, cameraMatrixR, distCoeffR, imageSize, R, T, E, F, CALIB_USE_INTRINSIC_GUESS,
TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, 1e-5));std::cout << "Stereo Calibration RMSE is : " << rms << std::endl;/*立体校正的时候需要两幅图像共面并且行对准,以使得立体匹配更方便使的两幅图像共面的方法就是把两个相机平面投影到一个公共的成像平面上,这样每幅图像投影到公共平面就需要一个旋转矩阵R, stereoRectify()这个函数计算的就是从图像平面投影到公共成像平面的的旋转矩阵Rl,Rr.RlRr就是左右相机平面共面的校正旋转矩阵,左相机经过Rl旋转,右相机经过Rr旋转之后,两幅图像就已经共面了;其中Pl Pr为两个相机的校正内参矩阵(3x4,最后一列为0),也可以称为相机坐标系到像素坐标系的投影矩阵,Q 为像素坐标系与相机坐标系之间的重投影矩阵;*/Rect validROIL, validROIR;cv::Mat Rl, Pl, Rr, Pr, Q;stereoRectify(cameraMatrixL, distCoeffL, cameraMatrixR, distCoeffR, imageSize, R, T, Rl, Rr, Pl, Pr, Q, CALIB_ZERO_DISPARITY, -1, imageSize, &validROIL, &validROIR);/*根据stereoRectify 计算出来的R 和 P 来计算图像的映射表 mapx, mapymapx, mapy这两个映射表接下来可以给remap()函数调用,来校正图像,使得两幅图像共面并且行对准*/ cv::Mat mapLx, mapLy, mapRx, mapRy;initUndistortRectifyMap(cameraMatrixL, distCoeffL, Rl, Pl, imageSize, CV_32FC1, mapLx, mapLy);initUndistortRectifyMap(cameraMatrixR, distCoeffR, Rr, Pr, imageSize, CV_32FC1, mapRx, mapRy);Mat rectifyImageL, rectifyImageR;cvtColor(imgGrayL, rectifyImageL, CV_GRAY2BGR);cvtColor(imgGrayR, rectifyImageR, CV_GRAY2BGR);DisplayScreen(rectifyImageL, rectifyImageR, validROIL, validROIR, false,"rectiftBefor");/*经过remap之后,左右相机的图像已经共面并且行对准了*/remap(rectifyImageL, rectifyImageL, mapLx, mapLy, INTER_LINEAR);remap(rectifyImageR, rectifyImageR, mapRx, mapRy, INTER_LINEAR);DisplayScreen(rectifyImageL,rectifyImageR,validROIL,validROIR,true);PrintParem(R,T,Rl,Rr,Pl,Pr);

参考博客:

https://blog.csdn.net/laobai1015/article/details/54575839

双目立体图像矫正方法简述相关推荐

  1. OpenCV在未知相机内参数情况下的立体图像矫正方法

    很多时候我们不知道摄像机的内参数矩阵,并且我们也不太关注内参数到底是多少,因为我们仅仅关心如何得到两幅图像的稠密匹配,或者两幅图像的差别--例如我们只想计算两幅图像的视差图,或者说得到两幅立体图像对的 ...

  2. 【立体视觉】双目立体标定与立体校正

    from:https://blog.csdn.net/u011574296/article/details/73826420 参考: 机器视觉学习笔记(6)--双目摄像机标定参数说明  机器视觉学习笔 ...

  3. OPENCV3.0 双目立体标定

    OPENCV3.0 双目立体标定 转载于:https://blog.csdn.net/zc850463390zc/article/details/48975263 这里是在上一篇单目标定的基础上拓展来 ...

  4. facebook surround360 环境配置,编译,测试(生成双目立体全景图)

    surround360是facebook开源的一套集采集,渲染与一体的全景内容制作解决方案,其中使用到了诸多开源库,花了几天时间才把它跑通,下面就记录一下其中的一些注意事项. 项目介绍与测试样例 官网 ...

  5. 汉王、海景科技双目立体人脸识别

    一.汉王双目立体人脸识别技术 http://blog.csdn.net/xidianzhimeng/article/details/19073341 人脸识别系统框图 汉王人脸识别系统采用双摄像头,右 ...

  6. 【机器视觉3】双目立体视觉模型

    双目立体视觉模型 简单模型 一般模型 简单模型 假设两个摄像机平行放置于同一高度.光轴平行.成像平面重合.焦距相同.左右图像每一行y坐标方向.大小相同,如下图所示: 由左右成像平面上的点.目标物点.焦 ...

  7. 简述isodata算法的原理_基于UWB技术的室内定位方法简述

    1. UWB室内定位概述: UWB室内定位技术与传统通信技术有极大的差异,它不需要使用传统通信体制中的载波,而是通过发送和接收具有纳秒或纳秒级以下的极窄脉冲来传输数据,从而具有GHz量级的带宽.超宽带 ...

  8. 谷歌浏览器的下载位置如何设置 Chrome浏览器下载路径设置方法简述

    在Chrome地址栏输入"chrome://settings/"后回车; 谷歌浏览器的下载位置如何设置?Chrome浏览器下载路径设置方法简述 谷歌浏览器的下载位置如何设置?Chr ...

  9. 猎豹浏览器小号窗口怎么打开 小号窗口打开方法简述

    针对同一用户在同一浏览器中同时登录多个不同网络账号的需求,猎豹浏览器贴心的推出了一项特别的功能--"小号窗口".那么,猎豹浏览器的小号窗口要怎么打开呢?下面小编就简单介绍一下猎豹浏 ...

最新文章

  1. 面试题--特别是字节对齐
  2. mysql 高并发加锁_Mysql高并发加锁事务处理
  3. 【牛客 - 301哈尔滨理工大学软件与微电子学院第八届程序设计竞赛同步赛(高年级)】小乐乐下象棋(记忆化搜索dp,dfs)
  4. 剑指Offer - 面试题46. 把数字翻译成字符串(DP)
  5. 获利上亿!一程序员主犯非法挖矿被抓
  6. 第45课 蝴蝶效应-动动脑 第2题 《小学生C++趣味编程》
  7. mac下增加eclipse内存
  8. flask response Content-Type
  9. 螺旋数组算法[中篇]--常规数学分析
  10. 蓝桥杯 ALGO-143 算法训练 字符串变换
  11. 一行代码就能写一个日志打印组件,你信吗?为你揭晓RTOS中日志打印组件的核心
  12. 爆肝100天,B站UP主开发会写高考作文的AI,内含17亿参数、2亿数据、1万行代码
  13. 华泰证券:“融券通”是何阳谋?
  14. 网页 flash swf 无法调用 摄像头 问题解决
  15. NDT Matching 算法学习
  16. UVA10142/PC110108Australian Voting
  17. 湖南城市综合竞争力排名
  18. 树莓派安装迅雷xware的失败经验
  19. java接口自动化-post请求获取不到cookie问题解决
  20. 应用在LED植物照明中的LED照明灯

热门文章

  1. table表格学习归纳
  2. 装机必备,四款良心软件释放你的电脑潜力,用了就离不开
  3. 评估方法(交叉验证法、自助法、留出法)
  4. Clickhouse Kafka Engin参数记录
  5. php获取prepay_id时报错,微信支付获取prepay_id返回签名错误,官方demo中的签名方法MD5验证有问题...
  6. HTML第二天学习笔记
  7. gcc: error: : No such file or directory
  8. 用数字万用表测量三极管的方法
  9. 金庸武功之““兰花拂穴手””--elk5.5安装
  10. 机房服务器显示器切换,两台电脑主机,一台显示屏,怎么实现切换!需要什么转换器,大概多少...