有什么比较好用的可以实现双目立体视觉标定相机标定的软件

& & &最近在做双目测距,觉得有必要记录点东西,所以我的第一篇博客就这么诞生啦~
& & &双目测距属于立体视觉这一块,我觉得应该有很多人踩过这个坑了,但网上的资料依旧是云里雾里的,要么是理论讲一大堆,最后发现还不知道怎么做,要么就是直接代码一贴,让你懵逼。 所以今天我想做的,是尽量给大家一个明确的阐述,并且能够上手做出来。
& & 首先我们要对摄像头做标定,具体的公式推导在learning opencv中有详细的解释,这里顺带提一句,这本书虽然确实老,但有些理论、算法类的东西里面还是讲的很不错的,必要的时候可以去看看。
& &Q1:为什么要做摄像头标定?
& & & A: &标定的目的是为了消除畸变以及得到内外参数矩阵,内参数矩阵可以理解为焦距相关,它是一个从平面到像素的转换,焦距不变它就不变,所以确定以后就可以重复使用,而外参数矩阵反映的是摄像机坐标系与世界坐标系的转换,至于畸变参数,一般也包含在内参数矩阵中。从作用上来看,内参数矩阵是为了得到镜头的信息,并消除畸变,使得到的图像更为准确,外参数矩阵是为了得到相机相对于世界坐标的联系,是为了最终的测距。
& & &ps1:关于畸变,大家可以看到自己摄像头的拍摄的画面,在看矩形物体的时候,边角处会有明显的畸变现象,而矫正的目的就是修复这个。
& & &ps2:我们知道双目测距的时候两个相机需要平行放置,但事实上这个是很难做到的,所以就需要立体校正得到两个相机之间的旋转平移矩阵,也就是外参数矩阵。 &
& & & & & & & &&
& &Q2:如何做摄像头的标定?
& & & A:这里可以直接用opencv里面的sample,在opencv/sources/sample/cpp里面,有个calibration.cpp的文件,这是单目的标定,是可以直接编译使用的,这里要注意几点:
& & & & & & & &1.棋盘
& & & &棋盘也就是标定板是要预先打印好的,你打印的棋盘的样式决定了后面参数的填写,具体要求也不是很严谨,清晰能用就行。之所用棋盘是因为他检测角点很方便,and..你没得选。。
& & & & & & & &2. 参数
& & & &一般设置为这个样子:-w 6 -h 8 -s 2 -n 10 -o camera.yml -op -oe [&list_of_views.txt&]&&,这是几个重要参数的含义:
-w &board_width&
# 图片某一维方向上的交点个数
-h &board_height&
# 图片另一维上的交点个数
[-n &number_of_frames&]
# 标定用的图片帧数
[-s &square_size&]
# square size in some user-defined units (1 by default)
[-o &out_camera_params&] # the output filename for intrinsic [and extrinsic] parameters
# write detected feature points
# write extrinsic parameters
可以发现 -w -h是棋盘的长和高,也就是有几个黑白交点,-s是每个格子的长度,单位是cm&
长和高一定要数对,不然程序在识别角点的时候会识别不出来的。
& & & & & & & & & & & 最终得到的yml文件,就是单目标定的参数矩阵,之后使用它就可以得到校正后的图像啦。 &&& & & & & & & & & & & & & & & & & & & & & & & & & & & & &
& & & & & &3. 需要对程序做一些修改,这是我遇到的问题,就是他的读取摄像头的代码在我这边没有用,所以我自己重新修改了,不知道大家会 &不会碰到这个问题。
& & & & & & &
& & & & & & & &然后就是双目标定了,同样的地方,找到stereo_calib.cpp,这个参数比较简单,只要确定长、宽和输入的一个xml文件(在之前 & & & & &的文件夹里面),这个文件是为了读取图片用的,你需要自己用固定好的双目摄像头拍14对棋盘图片,命名为&left01,right01......这样 & & & & &一系列的名字,另外,最简单的方法就是把自己拍的照片放到相应的工程下,以及stereo开头的那个xml文件也复制过去这个程序代码 & & & & & &并不复杂,可以稍微研究一下,工程向的代码确实严谨,各种情况都考虑到了,比起自己之前做的那个小项目不知道高到哪里去了
& & & & 这里也有几个注意点(坑):
& & & & & & & 1.老生常谈的问题,长宽一定要写对!!! 这个不多说了,都是泪。
&2.代码的核心函数 static void &StereoCalib(const vector&string&& imagelist, Size boardSize, bool useCalibrated=true, bool &showRectified=true),注意搞清楚参数的意义,因为我是用的单目标定好的摄像头拍摄的图片,不需要再校正了,所以第三个参数要用false,这样最后的结果才能看,不说了,都是泪...
& & & & & & & 3.另外注意到计算rms误差的时候,结束条件的几个参数是可以调整的,
double rms = 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)
下面这段话是某度百科上的:
& & & & 这个函数计算了两个摄像头进行立体像对之间的转换关系。如果你有一个立体相机的相对位置,并且两个摄像头的方向是固定的,以及你计算了物体相对于第一照相机和第二照相机的姿态,(R1,T1)和(R2,T2),各自(这个可以通过solvepnp()做到)通过这些姿态确定。你只需要知道第二相机相对于第一相机的位置和方向。
& & & & 除了立体的相关信息,该函数也可以两个相机的每一个做一个完整的校准。然而,由于在输入数据中的高维的参数空间和噪声的,可能偏离正确值。如果每个单独的相机内参数可以被精确估计(例如,使用calibratecamera()),建议这样做,然后在本征参数计算之中使CV_CALIB_FIX_INTRINSIC的功能。否则,如果一旦计算出所有的参数,它将会合理的限制某些参数,例如,传CV_CALIB_SAME_FOCAL_LENGTH and CV_CALIB_ZERO_TANGENT_DIST,这通常是一个合理的假设。
& & & Q3:标定之后做什么呢?
& & & A: 写到这我发现把单目和双目的一起写确实有点乱...不过,开弓没有回头箭!(不是因为懒!!)
& & & & & 首先还是单目,单目的使用很简单,使用标定得到的参数进行校正就行了,代码如下:
void loadCameraParams(Mat &cameraMatrix, Mat &distCoeffs){ FileStorage fs("camera.yml", FileStorage::READ);//这个名字就是你之前校正得到的yml文件
fs["camera_matrix"] && cameraM fs["distortion_coefficients"] && distC}
Mat calibrator(Mat &view)//需要校正处理的图片{ vector&string& imageL static bool bLoadCameraParams = static Mat cameraMatrix, distCoeffs, map1, map2; M Size imageSize, newImageS
if (!view.data)
return Mat();
imageSize.width = view. imageSize.height = view.
newImageSize.width = imageSize. newImageSize.height = imageSize.
if (bLoadCameraParams == false) {
loadCameraParams(cameraMatrix, distCoeffs);
bLoadCameraParams =
initUndistortRectifyMap(cameraMatrix, distCoeffs, Mat(),
getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, newImageSize, 0), newImageSize, CV_16SC2, map1, map2); }
//undistort( view, rview, cameraMatrix, distCoeffs, cameraMatrix ); remap(view, rview, map1, map2, INTER_LINEAR);
imshow("左图", rview); //int c = 0xff & waitKey();
rview.copyTo(view);
& & & & & & & & & & &这样最后就可以得到校正后消除畸变的图片。
& & & & & & & & & & &OK,接下来显然就是双目啦,双目校正之后的工作就比较多了,我准备另开一节来说...& & & & & & & & & & & & & & & & &&
&二、立体匹配
& & 这是一个很大的题目,网上的资料也很多,所以我想说的是我的一些理解。
& & & &这里最好的方法是从后往前说,我们首先需要理解测距的原理。这个很多人看了一大堆还不明白(其实只有我自己吧..),相似三角形测距,这种东西小学生都能搞清楚,但两摄像头到底怎么做到的,就是我们需要搞清楚的。
& & & 首先需要搞清楚一个非常重要的概念,视差,搞清楚视差,后面的就简单了&,老生常谈的问题我不想多说,网上那些一大堆,我希望给大家的是一些明了的东西
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &&
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &&
& & & &这三幅图看明白了就行,其实视差确实很简单,但很多人都没去理清楚,第一幅图是三维世界的一个点在两个相机的成像,我们可以相信的是,这两个在各自相机的相对位置基本不可能是一样的,而这种位置的差别,也正是我们眼睛区别3D和2D的关键,将右边的摄像机投影到左边,怎么做呢?因为他的坐标和左边相机的左边相距Tx(标定测出来的外参数),所以它相当于在左边的相机对三维世界内的(x-tx,y,z)进行投影,所以这时候,一个完美的形似三角形就出来,这里视差就是d=x-x&,
& & & & & & & & &&
& & & & & & & 得到视差以后,再用相似三角形......也就得到了深度也就是距离啦。
& & & &结束了么??并没有....这样做确实很完美,但是问题来了:1.当我在左边相机确定一个点的时候,我怎么在右边找到这个点? 2.我左边点所在的行一点跟右边点所在的行上的像素一定完全一样么?
& & & & & & &解决第一个问题的方法就是立体匹配了。
& & & & & Q1:立体匹配是什么,怎么进行立体匹配?
& & & & & A:简单的回答就是:立体匹配就是解决上面问题的东西啦....其实我觉得这样就是也够了,有些成熟的算法,未必需要钻研太深,毕竟我这种实在的菜鸡,还是工程导向的..学术的事,日后再说!&
& & & & & & & opencv中提供了很多的立体匹配算法,类似于局部的BM,全局的SGBM等等,这些算法的比较大概是,速度越快的效果越差,如果不是很追究时效性,并且你的校正做的不是很好的话..推荐使用SGBM,算法的具体原理大家可以去百度,不难。这里我想提一下的是为什么做立体匹配有用,原因就是极线约束,这也是个很重要的概念,理解起来并不难,左摄像机上的一个点,对应三维空间上的一个点,当我们要找这个点在右边的投影点时,有必要把这个图像都遍历一边么,当然不用...
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &
& & & & & & &如上图,显然,PL对应的P这个点一定在一条极线上,只要在这条线上找就行了,更明显的是下面这个图:
& & & & & & & & & & & & & & & & & & & & & & & & & & & & &
& & & 最后,怎么在opencv里面实现呢..机智的我又找到了sample..找到stereo_match.cpp这个文件,命令行设置为:left01.jpg right02.jpg --algorithm=hh --blocksize=5 --max-disparity=256 &--scale=1.0 --no-display -i intrinsics.yml -e extrinsics.yml -o disparity.jpg同意给几个建议:
& & & & & & & 1.参数的意义:
-max-disparity 是最大视差,可以理解为对比度,越大整个视差的range也就越大,这个要求是16的倍数
&--blocksize 一般设置为5-29之间的奇数,应该是局部算法的窗口大小。
另,注意带上参数-i intrinsics.yml -e extrinsics.yml,毕竟咱有校正参数...
& & & & & & & 2.后面有两行代码:
& & & & & & & & & & & & & & & & & &reprojectImageTo3D(disp, xyz, Q, true);
& & & & & & & & & & & & & & & & & &saveXYZ(point_cloud_filename, xyz);
& & & & & & & & & & & 这个就是得到图片的三维坐标,Z也就是我们最终要求的深度啦。
& & & & & &
& & & &第二个问题,行和行是对应的么? & 之前我们说过,双目校正的目的就是为了得到两个平行的摄像头,所以当程序运行完毕以后,它会把两幅图像显示出来,并作出一系列的平行线,这样你会看到线上的点大致是呈对应关系,左边的角点对应右边的交点,所以,经过匹配和校正后,是对应的。
& &双目拖了很久,一直没做,最重要的原因就是...我没有两个一样的摄像头,所以最后也没有贴出效果图,因为两个不一样的摄像头,做出来的东西画面太美我不敢看,不过最终搞清楚了整个流程和原理,还是比较开心的。这里面像校正和匹配的算法,我只是有所理解,因为以后不一定走3D这一块,所以也没有过去深入,如果用到在去研究,其实也不晚..总之,第一篇博客,完工啦~
& & & & & & & &&
阅读(...) 评论()后使用快捷导航没有帐号?
相机标定技术及应用分析
共 1696 人围观,
发现评论数0个
简介 :北大——北科联合试验室负责人,北大教授 汪国平  基于图像建模即通过物体照片图像进行分析、比较,以计算机辅助自动合成物体的三维立体图像,在满足最逼真展示物体三维立体图像这一目的的同时,大幅度地降低建模 ...
北大——北科联合试验室负责人,北大教授 汪国平  基于图像建模即通过物体照片图像进行分析、比较,以计算机辅助自动合成物体的三维立体图像,在满足最逼真展示物体三维立体图像这一目的的同时,大幅度地降低建模过程中人工介入程度,从而大幅度降低建模成本,为大范围的推广应用打下基础。  从多幅二维图像中计算三维特征并作场景的三维重构是计算机视觉和图形学领域的一个重要研究内容,目前已经有非常多的相关研究。对于基于图像的三维重构任务而言,准确的相机标定是至关重要的。对于三维场景或模型重构精度要求较高而拍摄环境可以按需定制的应用,离线标定技术一般可以更好地满足用户需求;相反,如果需要从一些无法定制环境或缺失标定信息的图像或视频序列中作场景分析和重构,就只能采用在线标定技术。  鉴于相机标定技术在三维重构中的重要性,我们将相关技术分为基于离线相机标定的三维重构技术和基于在线相机标定的三维重构技术两个大类,并对两类技术及其应用分析。  基于离线相机标定的三维重构技术  基于离线相机标定技术需要准确的相机内参数和外参数作为重构算法的输入和先决条件,目前最为流行的离线相机标定算法是Tsai在1987年提出的 [Tsai1987],Tsai方法使用一个带有非共面专用标定标识的三维标定物来提供图像点和其对应的三维空间点的对应并计算标定参数。Zhang在 1999年提出了另一个实用方法Bouguet2007],该方法需要对一个平面标定图案的至少两幅不同视图来进行标定。加州理工学院的相机标定工具对以上两个方法均作了有效实现,并且已经被集成到Intel的视觉算法库OpenCV中[OpenCV2004]。通过标定算法,可以计算相机的投影矩阵,并提供场景的三维测度信息。在不给定真实场景的绝对平移、旋转和放缩参数的情况下,可以达到相似变换级别的测度重构。  (1)基于图像的重构  在基于图像的重构技术中,既可以考虑稀疏特征匹配,也可以考虑稠密特征匹配,一般需要视应用背景和场景特性作具体选择。特征检测是准确重构框架中的一个关键步骤。传统意义上的特征定义为在至少一个特定方向上存在较大亮度或色度变化的图像区域或位置 [Moravec1977]。Harris等使用一阶导数来估计局部互相关数值[Harris1988],该方法能给出健壮的检测结果但在某些情况下缺乏定位上的准确性。Beaudet等使用梯度和曲率的乘积来刻画角点特征并检测角点[Beaudet1978],Smith等提出的SUSAN检测子结合使用特征区域的尺寸、中心信息来检测角点。Lowe提出的尺度不变的特征检测算子SIFT是目前比较流行的算法 [SIFT2004],SIFT的优势在于能够对有效提取特征在一定程度上的旋转和放缩等不变特征,从而大大减弱了特征检测算法对环境和图像质量的依赖性, Koser等从SIFT的思想进一步引申出透视不变特征的概念[Koser2007]。  特征检测之后一般需要进行多视图之间的特征匹配。特征匹配算法的性能会受到镜头畸变、光线环境、场景遮挡及其他未知图像噪声的影响。解决匹配问题目前主要有两种思路。第一种思路在某个关键帧中检测出一个特征标记并使用跟踪算法在后续帧中跟踪这个特征集,代表算法是基于光流的跟踪算法如Lucas-Kanade算法 [Tomasi1991]。第二种思路则在多个视图中独立进行特征检测并通过数据关联的手段来建立匹配特征对,这可以通过简单的区域相关算法实现[Zhang1995],也可以通过各种手段定义描述相似度的目标函数并作优化来实现[Li1994]。  对于需要稠密场景重构的场合还需要进行稠密多视匹配的工作,稠密多视匹配算法的性能直接影响到最终重构质量,在图像取样点足够密集的情况下,可以用光流技术模拟相邻图像之间的像素或特征位移。三维结构的三角化同样也可以通过具备了点到点对应信息的光流来模拟,在稠密空间采样的假设下光流可以用系数特征位移来有效近似 [Zucchelli2002]。  可以通过图像校正的技术将两个视图中的对应极线调为水平状态且处在同一水平扫描线上,这样就可以使用传统的基于水平视差的双视算法恢复深度信息。在这一框架下,可以用马尔可夫随机场建模并用基于图论的优化算法实现求解[Scharstein2002]。  (2)基于体素的重构  近年来随着计算速度和存储性能的大幅提高,基于体的场景结构表示方法已经成为实用。已有多种方法从图像序列中恢复场景体数据。一种常见方法是从多视图中恢复前景物体的视觉凸包(visualhull)作为物体的重构近似。一般说来,visualhull 的大小随着参与计算的图像数量增多而单调下降。常见的方法是从每一图像中分离出前景区域和背景区域,把前景区域反向投射到三维空间求交来得到visualhull[Szeliski93]。Snow提出了Voxel occupancy算法,通过基于体素标签的图割算法实现三维分割 [Snow2000]。对于有较明显色彩区分特征的图像,也可考虑使用颜色相容性即只保留色彩相容的空间体素来建立约束求解三维信息[Seitz1999]。为了简化基于可见性的空间切割,Seitz等提出了对于相机位置的有序可见性约束 [Seitz1999]。作为对以上框架的进一步改进,Prock提出了多分辨率体素着色方案 [Prock1998],Culbertson等提出了能够精确计算可见性的一般化的色彩相容模型 [Culbertson1999]。  和基于图像的重构技术相比,基于体素的重构技术不需要显示的特征匹配且能更有效地处理遮挡问题,但其潜在的缺点在于庞大的内存消耗会在一定程度上限制重建精度。在某些条件下,有序可见性约束显得过强。  (3)基于对象的重构  与基于体素的重构算法中用体素离散化场景的思想不同,基于对象的重构技术着眼于直接恢复场景中物体的表面模型。Faugeras等提出了level-set重构是第一个面向对象的多视三维复原技术 [Faugeras1998],该技术把用于深度恢复的变分原理推广为一个可以用level-set求解的曲线演化问题 [Robert1996]。该工作的原始框架须作漫反射表面的假设,Lin等所做后续工作减弱了这一要求,使得镜面反射和透明环境下的求解成为可能 [Lin2002]。  基于在线相机标定的三维重构技术  在很多场合下,如缺失标定设备或相机内参数持续改变的情况下,没有足够数据来支持离线相机标定,对这类场景的多视三维重构就要用到在线相机标定的技术。在线标定和离线标定框架的主要区别在于标定相机或估计相机参数的方法上。在大多数文献中离线标定技术被称为自标定。自标定方法可以大致分为两类:基于场景约束的自标定和基于几何约束的自标定。  (1)基于场景约束的自标定  合适的场景约束往往能够在很大程度上简化自标定的难度。比如说,广泛存在于建筑或人造场景中的平行线能够帮助提供三个主正交方向的消视点和消视线信息,并能够据此给出相机内参数的代数解或数值解 [Caprile1990]。消视点的求解可以通过投票并搜索最大值的方法进行。Barnard采用高斯球构造求解空间[Barnard1983]。Quan、Lutton和Rother等给出了进一步的优化策略[Quan1989,Lutton1994, Rother2000]。文献[Quan1989]中给出了搜索解空间的直接算法,Heuvel给出的改进算法加入了强制性的正交条件[Heuvel1998]。Caprile给出了基于3 个主正交方向消视点的几何参数估计法,Hartley 使用标定曲线计算焦距 [Hartley2003]。Liebowitz等进一步从消视点位置构造绝对二次曲线的约束并用考克斯分解求解标定矩阵 [Liebowitz1999]。  (2)基于几何约束的自标定  基于几何约束的自标定不需要外在场景约束。仅仅依靠多视图自身彼此间的内在几何限制来完成标定任务。利用绝对二次曲面作自标定的理论和算法最先由Triggs提出 [Triggs1997]。基于Kruppa方程求解相机参数则始于Faugeras, Maybank等的工作[Faugeras1992, Maybank1992]。Hartley给予基本矩阵推 导出了Kruppa方程的另一个推导[Hartley1997]。  文献[Sturm2000]则给出了Kruppa方程的不确定性的理论探讨,层进式自标定技术被用于从射影重构升级到度量重构[Faugeras1992]。自标定技术的一个主要困难在于它不是无限制地用于任意图像或视频序列,事实上存在着特定运动序列或空间特征分布导致自标定求解框架的退化和奇异解。文献[Sturm1997]给出了关于退化情形的详细讨论和分类。对一些特殊可解情况存在性和求解方法的讨论可以参考文献[Wilesde1996]等。  综合考察以上技术可以看出,对于简单室内环境下小型物体的精度要求较高的模型重构来说,基于离线标定的体素法或对象法在稳定性和实用性等方面有较大的优势。  根据我们在国内外相关技术领域的长期跟踪调研所掌握的情况来看,目前国际上有微软公司斯坦福大学和麻省理工学院等机构在基于图像的三维形体快速重建方面有良好的研究成果。  国内北大、中科院自动化所工信部下属研究所、浙大、清华、北邮、北航、哈工大、香港理工大等科研院所及高校都有相关技术方向的研究。但在技术和市场化方面有所建树的,只有北京大学和北科光大合作研发的3Dcloud平台。该平台在“用于相机标定的方法及所用的彩色参照物”专利技术的基础上,开发了三维建模应用,并通过SAAS的模式向用户提供服务,目前在电子商务、网上博物馆、展览展示方面有着成功的应用。取得了良好的效果。  这种方式的应用成本低廉、服务获取便捷,必将获得广泛应用。
上一篇:下一篇:
  制造商Julien Dorra开发了一种可以在低成本3D打印机上制造的3D打印噪声吸收系统。该系统的开...
  登上几百米高的摩天大楼楼顶已经足够让人头晕目眩,你有没有想过未来可能会在4800米高的大楼...
1.2.3.4.5.6.7.8.
1.2.3.4.5.6.7.8.}

我要回帖

更多关于 立体视觉标定 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信