用opencv 轮廓匹配做立体匹配时,用自己拍的照片视差图为什么效果这么差

基于MATLAB与OpenCV相结合的双目立体视觉测距系统--《天津理工大学学报》2013年01期
基于MATLAB与OpenCV相结合的双目立体视觉测距系统
【摘要】:双目立体视觉测距技术是当前机器视觉领域中的一个主要研究内容.本文设计了基于MATLABatlab与OpenCV相结合的双目立体视觉测距系统,利用MATLAB进行摄像机标定后将结果导入到OpenCV进行后续的图像处理与立体匹配.摄像机标定通过MATLAB标定工具箱来完成,较于人工标定和OpenCV标定具有更好的鲁棒性和较高的精确性.立体匹配采用区域匹配中相对快速实时的SAD匹配,能够更好的被应用于工程实际.
【作者单位】:
【关键词】:
【分类号】:TP391.41【正文快照】:
本文在VC++的环境下,采用OpenCV与MATLAB相结合的方法开发了一种新的双目测距系统,先通过MATLAB对标定图像进行标定(该方法较于人工标定和OpenCV标定具有更高的精确性和鲁棒性),再将标定的结果导入到OpenCV进行后续的图像校正和立体匹配,快速而实时的计算出周围目标景物的三
欢迎:、、)
支持CAJ、PDF文件格式,仅支持PDF格式
【参考文献】
中国期刊全文数据库
徐奕,周军,周源华;[J];计算机工程与应用;2003年15期
【共引文献】
中国期刊全文数据库
王力超;熊超;王晨毅;陆起涌;;[J];传感技术学报;2007年01期
李毅,杨文玉;[J];华中科技大学学报(自然科学版);2004年08期
高媛媛,关胜晓,许栋;[J];计算机工程与应用;2005年22期
赵杰,彭京,蔡鹤皋;[J];机械与电子;2004年06期
高欣;安平;刘佳;张兆扬;;[J];上海大学学报(自然科学版);2006年02期
中国重要会议论文全文数据库
樊彬;罗飞;李招;;[A];2006北京地区高校研究生学术交流会——通信与信息技术会议论文集(下)[C];2006年
吉大纯;李学军;谢剑薇;刘涛;;[A];第一届中国高校通信类院系学术研讨会论文集[C];2007年
赵杰;彭京;李戈;王晨;;[A];全国第13届计算机辅助设计与图形学(CAD/CG)学术会议论文集[C];2004年
中国博士学位论文全文数据库
张可;[D];华中科技大学;2005年
张方明;[D];浙江大学;2006年
翟乃斌;[D];吉林大学;2007年
张小虎;[D];国防科学技术大学;2006年
周秀芝;[D];国防科学技术大学;2006年
于海滨;[D];浙江大学;2007年
张维忠;[D];南京航空航天大学;2007年
唐新星;[D];吉林大学;2007年
中国硕士学位论文全文数据库
蔡钦涛;[D];浙江大学;2004年
宋长波;[D];武汉大学;2004年
王晓华;[D];山东科技大学;2004年
张艳峰;[D];大连理工大学;2005年
杜娜;[D];青岛大学;2005年
石波;[D];山东科技大学;2005年
吴剑锋;[D];浙江大学;2005年
胡凌山;[D];哈尔滨工程大学;2005年
宋近才;[D];大连理工大学;2006年
谢涛;[D];大连理工大学;2006年
【二级参考文献】
中国期刊全文数据库
赵勋杰,高稚允;[J];光学技术;2003年06期
【相似文献】
中国期刊全文数据库
方玫;;[J];北京教育学院学报(自然科学版);2011年01期
林俊义;黄常标;刘斌;江开勇;;[J];机械设计与制造;2011年08期
秦小文;温志芳;乔维维;;[J];电子测试;2011年07期
许雁飞;陈春玲;陈夏梅;;[J];信息与电脑(理论版);2011年08期
刘李娟;卢选民;陶旺林;单长;;[J];现代电子技术;2011年16期
陶旺林;卢选民;刘李娟;单长;;[J];现代电子技术;2011年12期
刘维杰;梁志剑;马铁华;;[J];电子测试;2011年07期
赵波;郑力新;;[J];微型机与应用;2011年13期
姜宇;张子潮;周富强;;[J];辽宁师范大学学报(自然科学版);2011年02期
胡萍萍;;[J];电脑编程技巧与维护;2011年16期
中国重要会议论文全文数据库
唐文冰;张彦娥;张东兴;李民赞;;[A];中国农业工程学会2011年学术年会论文集[C];2011年
王强;刘建丽;;[A];逻辑学及其应用研究——第四届全国逻辑系统、智能科学与信息科学学术会议论文集[C];2008年
周平;刘越;王涌天;;[A];第十四届全国图象图形学学术会议论文集[C];2008年
谭彩凤;邢座程;田海军;;[A];中国电子学会第十六届信息论学术年会论文集[C];2009年
张静;李琳;刘晓平;;[A];计算机技术与应用进展——全国第17届计算机科学与技术应用(CACIS)学术会议论文集(上册)[C];2006年
曹志刚;李宇成;;[A];全国冶金自动化信息网2010年年会论文集[C];2010年
蒋路帆;刘博;白相志;周付根;;[A];第十一届中国体视学与图像分析学术会议论文集[C];2006年
柳迪;董绪荣;;[A];2011年全国通信安全学术会议论文集[C];2011年
常俊林;魏巍;梁君燕;;[A];中国自动化学会控制理论专业委员会C卷[C];2011年
史玉升;李中伟;钟凯;王从军;;[A];2009年促进中部崛起专家论坛暨第五届湖北科技论坛——装备制造产业发展论坛论文集(下)[C];2009年
中国博士学位论文全文数据库
罗桂娥;[D];中南大学;2012年
潘锋;[D];浙江大学;2005年
田原嫄;[D];吉林大学;2008年
叶南;[D];南京航空航天大学;2010年
周佳立;[D];浙江大学;2009年
阚江明;[D];北京林业大学;2008年
张文明;[D];燕山大学;2010年
翟乃斌;[D];吉林大学;2007年
李明喜;[D];江苏大学;2008年
王静红;[D];河北工业大学;2008年
中国硕士学位论文全文数据库
韩坤芳;[D];浙江大学;2011年
张元元;[D];南京航空航天大学;2010年
朱军军;[D];扬州大学;2010年
曹莉;[D];济南大学;2011年
张杨;[D];长春理工大学;2010年
施万利;[D];河南工业大学;2010年
陈莹莹;[D];南京理工大学;2010年
魏春苗;[D];兰州理工大学;2011年
陈吉庐;[D];南京理工大学;2010年
沈璐;[D];东北师范大学;2010年
&快捷付款方式
&订购知网充值卡
400-819-9993
《中国学术期刊(光盘版)》电子杂志社有限公司
同方知网数字出版技术股份有限公司
地址:北京清华大学 84-48信箱 大众知识服务
出版物经营许可证 新出发京批字第直0595号
订购热线:400-819-82499
服务热线:010--
在线咨询:
传真:010-
京公网安备75号您的位置: &
基于OpenCV的立体匹配算法的研究与实现
优质期刊推荐/*--------------------CSS部分-------------------*/
/*--------------------JS部分-------------------*/
三种匹配算法比较 BM算法: 该算法代码:
CvStereoBMState *BMState = cvCreateStereoBMState();&& int SADWindowSize=15;&&&
BMState-&SADWindowSize = SADWindowSize & 0 ? SADWindowSize : 9;&&
BMState-&minDisparity = 0;&&
BMState-&numberOfDisparities = 32;&&
BMState-&textureThreshold = 10;&&
BMState-&uniquenessRatio = 15;&&
BMState-&speckleWindowSize = 100;&&
BMState-&speckleRange = 32;&&
BMState-&disp12MaxDiff = 1;&&
cvFindStereoCorrespondenceBM( left, right, left_disp_,BMState);&& && cvNormalize( left_disp_, left_vdisp, 0, 256, CV_MINMAX );&
其中minDisparity是控制匹配搜索的第一个参数,代表了匹配搜苏从哪里开始,numberOfDisparities表示最大搜索视差数uniquenessRatio表示匹配功能函数,这三个参数比较重要,可以根据实验给予参数值。 该方法速度最快,一副320*240的灰度图匹配时间为31ms,视差图如下。
这图是解释BM(bidirectional matching)算法的很好的例子。进行双向匹配,首先通过匹配代价在右图中计算得出匹配点。然后相同的原理及计算在左图中的匹配点。比较找到的左匹配点和源匹配点是否一致,如果你是,则匹配成功。
第二种方法是SGBM方法这是OpenCV的一种新算法:
cv::StereoSGBM&& &&&&&&& sgbm.preFilterCap = 63;&& &&&&&&& int SADWindowSize=11;&&& &&&&&&& int cn = 1;&& &&&&&&& sgbm.SADWindowSize = SADWindowSize & 0 ? SADWindowSize : 3;&& &&&&&&& sgbm.P1 = 4*cn*sgbm.SADWindowSize*sgbm.SADWindowS&& &&&&&&& sgbm.P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowS&& &&&&&&& sgbm.minDisparity = 0;&& &&&&&&& sgbm.numberOfDisparities = 32;&& &&&&&&& sgbm.uniquenessRatio = 10;&& &&&&&&& sgbm.speckleWindowSize = 100;&& &&&&&&& sgbm.speckleRange = 32;&& &&&&&&& sgbm.disp12MaxDiff = 1;&&
&&&&&&& sgbm(left , right , left_disp_);&& &&&&&&& sgbm(right, left& , right_disp_);&
各参数设置如BM方法,速度比较快,320*240的灰度图匹配时间为78ms,视差效果如下图。
第三种为GC方法:
CvStereoGCState* state = cvCreateStereoGCState( 16, 2 );&&
left_disp_& =cvCreateMat( left-&height,left-&width, CV_32F );&&
right_disp_ =cvCreateMat( right-&height,right-&width,CV_32F );&&
cvFindStereoCorrespondenceGC( left, right, left_disp_, right_disp_, state, 0 );&&
cvReleaseStereoGCState( &state );&
该方法速度超慢,但效果超好。
各方法理论可以参考文献。
函数解释 参数注释 (1)StereoBMState
// 预处理滤波参数
preFilterType:预处理滤波器的类型,主要是用于降低亮度失真(photometric distortions)、消除噪声和增强纹理等, 有两种可选类型:CV_STEREO_BM_NORMALIZED_RESPONSE(归一化响应) 或者 CV_STEREO_BM_XSOBEL(水平方向Sobel算子,默认类型), 该参数为 int 型;
preFilterSize:预处理滤波器窗口大小,容许范围是[5,255],一般应该在 5x5..21x21 之间,参数必须为奇数值, int 型
preFilterCap:预处理滤波器的截断值,预处理的输出值仅保留[-preFilterCap, preFilterCap]范围内的值,参数范围:1 - 31(文档中是31,但代码中是 63), int // SAD 参数
SADWindowSize:SAD窗口大小,容许范围是[5,255],一般应该在 5x5 至 21x21 之间,参数必须是奇数,int 型
minDisparity:最小视差,默认值为 0, 可以是负值,int 型
numberOfDisparities:视差窗口,即最大视差值与最小视差值之差, 窗口大小必须是 16 的整数倍,int 型 // 后处理参数
textureThreshold:低纹理区域的判断阈值。如果当前SAD窗口内所有邻居像素点的x导数绝对值之和小于指定阈值,则该窗口对应的像素点的视差值为 0(That is, if the sum of absolute values of x-derivatives computed over SADWindowSize by SADWindowSize pixel neighborhood is smaller than the parameter, no disparity is computed at the pixel),该参数不能为负值,int 型
uniquenessRatio:视差唯一性百分比, 视差窗口范围内最低代价是次低代价的(1 + uniquenessRatio/100)倍时,最低代价对应的视差值才是该像素点的视差,否则该像素点的视差为 0 (the minimum margin in percents between the best (minimum) cost function value and the second best value to accept the computed disparity, that is, accept the computed disparity d^ only if SAD(d) &= SAD(d^) x (1 + uniquenessRatio/100.) for any d != d*+/-1 within the search range ),该参数不能为负值,一般5-15左右的值比较合适,int 型
speckleWindowSize:检查视差连通区域变化度的窗口大小, 值为 0 时取消 speckle 检查,int 型
speckleRange:视差变化阈值,当窗口内视差变化大于阈值时,该窗口内的视差清零,int 型 // OpenCV2.1 新增的状态参数
roi1, roi2:左右视图的有效像素区域,一般由双目校正阶段的 cvStereoRectify 函数传递,也可以自行设定。一旦在状态参数中设定了 roi1 和 roi2,OpenCV 会通过cvGetValidDisparityROI 函数计算出视差图的有效区域,在有效区域外的视差值将被清零。
disp12MaxDiff:左视差图(直接计算得出)和右视差图(通过cvValidateDisparity计算得出)之间的最大容许差异。超过该阈值的视差值将被清零。该参数默认为 -1,即不执行左右视差检查。int 型。注意在程序调试阶段最好保持该值为 -1,以便查看不同视差窗口生成的视差效果。具体请参见《》一文中的讨论。 在上述参数中,对视差生成效果影响较大的主要参数是 SADWindowSize、numberOfDisparities 和 uniquenessRatio 三个,一般只需对这三个参数进行调整,其余参数按默认设置即可。
在OpenCV2.1中,BM算法有C和C++ 两种实现模块。
(2)StereoSGBMState
SGBM算法的状态参数大部分与BM算法的一致,下面只解释不同的部分:
SADWindowSize:SAD窗口大小,容许范围是[1,11],一般应该在 3x3 至 11x11 之间,参数必须是奇数,int 型
P1, P2:控制视差变化平滑性的参数。P1、P2的值越大,视差越平滑。P1是相邻像素点视差增/减 1 时的惩罚系数;P2是相邻像素点视差变化值大于1时的惩罚系数。P2必须大于P1。OpenCV2.1提供的例程 stereo_match.cpp 给出了 P1 和 P2 比较合适的数值。
fullDP:布尔值,当设置为 TRUE 时,运行双通道动态编程算法(full-scale 2-pass dynamic programming algorithm),会占用O(W*H*numDisparities)个字节,对于高分辨率图像将占用较大的内存空间。一般设置为 FALSE。 注意OpenCV2.1的SGBM算法是用C++ 语言编写的,没有C实现模块。与H. Hirschmuller提出的原算法相比,主要有如下变化:
算法默认运行单通道DP算法,只用了5个方向,而fullDP使能时则使用8个方向(可能需要占用大量内存)。
算法在计算匹配代价函数时,采用块匹配方法而非像素匹配(不过SADWindowSize=1时就等于像素匹配了)。
匹配代价的计算采用BT算法("" by S. Birchfield and C. Tomasi),并没有实现基于互熵信息的匹配代价计算。
增加了一些BM算法中的预处理和后处理程序。
(3)StereoGCState
GC算法的状态参数只有两个:numberOfDisparities 和 maxIters ,并且只能通过 cvCreateStereoGCState 在创建算法状态结构体时一次性确定,不能在循环中更新状态信息。GC算法并不是一种实时算法,但可以得到物体轮廓清晰准确的视差图,适用于静态环境物体的深度重构。
注意GC算法只能在C语言模式下运行,并且不能对视差图进行预先的边界延拓,左右视图和左右视差矩阵的大小必须一致。 原理解释 目前立体匹配算法是计算机视觉中的一个难点和热点,算法很多,但是一般的步骤是:
A、匹配代价计算 匹配代价计算是整个立体匹配算法的基础,实际是对不同视差下进行灰度相似性测量。常见的方法有灰度差的平方SD(squared intensity differences),灰度差的绝对值AD(absolute intensity differences)等。另外,在求原始匹配代价时可以设定一个上限值,来减弱叠加过程中的误匹配的影响。以AD法求匹配代价为例,可用下式进行计算,其中T为设定的阈值。
这就是在参数设置中阈值的作用,在视差图中经常有黑色区域,就是和阈值的设置关。
B、 匹配代价叠加 一般来说,全局算法基于原始匹配代价进行后续算法计算。而区域算法则需要通过窗口叠加来增强匹配代价的可靠性,根据原始匹配代价不同,可分为:
此图是核心算法的解释,就是计算区域内像素差值,可以为单个像素也可以为一定区域内,主要看SAD的窗口大小的设置,同时SAD设置决定误匹配的多少和运算效率问题,所以大小设置一定要很慎重。
C、 视差获取 对于区域算法来说,在完成匹配代价的叠加以后,视差的获取就很容易了,只需在一定范围内选取叠加匹配代价最优的点(SAD和SSD取最小值,NCC取最大值)作为对应匹配点,如胜者为王算法WTA(Winner-take-all)。而全局算法则直接对原始匹配代价进行处理,一般会先给出一个能量评价函数,然后通过不同的优化算法来求得能量的最小值,同时每个点的视差值也就计算出来了。
D、视差细化(亚像素级) 大多数立体匹配算法计算出来的视差都是一些离散的特定整数值,可满足一般应用的精度要求。但在一些精度要求比较高的场合,如精确的三维重构中,就需要在初始视差获取后采用一些措施对视差进行细化,如匹配代价的曲线拟合、图像滤波、图像分割等。 亚像素级的处理就是涉及到BMState参数设置后后续参数的设置了。 有关立体匹配的介绍和常见匹配算法的比较,推荐大家看看 的讲义 ,190页的ppt,讲解得非常形象详尽。
1. opencv2.1和opencv2.0在做stereo vision方面有什么区别了? 2.1版增强了Stereo Vision方面的功能: (1) 新增了 SGBM 立体匹配算法(源自Heiko Hirschmuller的《》),可以获得比 BM 算法物体轮廓更清晰的视差图(但低纹理区域容易出现横/斜纹路,在 GCstate-&fullDP 选项使能时可消减这种异常纹路,但对应区域视差变为0,且运行速度会有所下降),速度比 BM 稍慢, 352*288的帧处理速度大约是 5 帧/秒; (2) 视差效果:BM & SGBM & GC;处理速度:BM & SGBM & GC ; (3) BM 算法比2.0版性能有所提升,其状态参数新增了对左右视图感兴趣区域 ROI 的支持(roi1 和 roi2,由stereoRectify函数产生); (4) BM 算法和 GC 算法的核心代码改动不大,主要是面向多线程运算方面的(由 OpenMP 转向 Intel TBB); (5) cvFindStereoCorrespondenceBM 函数的disparity参数的数据格式新增了 CV_32F 的支持,这种格式的数据给出实际视差,而 2.0 版只支持 CV_16S,需要除以 16.0 才能得到实际的视差数值。 2. 用于立体匹配的图像可以是彩色的吗? 在OpenCV2.1中,BM和GC算法只能对8位灰度图像计算视差,SGBM算法则可以处理24位(8bits*3)彩色图像。所以在读入图像时,应该根据采用的算法来处理图像: int color_mode = alg == STEREO_SGBM ? 1 : 0;//////////////////////////////////////////////////////////////////////////// 载入图像cvGrabFrame( lfCam );cvGrabFrame( riCam );frame1 = cvRetrieveFrame( lfCam );frame2 = cvRetrieveFrame( riCam );if(frame1.empty())resize(frame1, img1, img_size, 0, 0);resize(frame2, img2, img_size, 0, 0);// 选择彩色或灰度格式作为双目匹配的处理图像if (!color_mode && cn&1){cvtColor(img1, img1gray, CV_BGR2GRAY);cvtColor(img2, img2gray, CV_BGR2GRAY);img1p = img1img2p = img2}else{img1p = img1;img2p = img2;} 3. 怎样获取与原图像有效像素区域相同的视差图? 在OpenCV2.0及以前的版本中,所获取的视差图总是在左侧和右侧有明显的黑色区域,这些区域没有有效的视差数据。视差图有效像素区域与视差窗口(ndisp,一般取正值且能被16整除)和最小视差值(mindisp,一般取0或负值)相关,视差窗口越大,视差图左侧的黑色区域越大,最小视差值越小,视差图右侧的黑色区域越大。其原因是为了保证参考图像(一般是左视图)的像素点能在目标图像(右视图)中按照设定的视差匹配窗口匹配对应点,OpenCV 只从参考图像的第 (ndisp - 1 + mindisp) 列开始向右计算视差,第 0 列到第 (ndisp - 1 + mindisp) 列的区域视差统一设置为 (mindisp - 1) *16;视差计算到第 width + mindisp 列时停止,余下的右侧区域视差值也统一设置为 (mindisp - 1) *16。&
static const int DISPARITY_SHIFT = 4;
int ndisp = state-&numberOfD
int mindisp = state-&minD
int lofs = MAX(ndisp - 1 + mindisp, 0);
int rofs = -MIN(ndisp - 1 + mindisp, 0);
int width = left-&cols, height = left-&
int width1 = width - rofs - ndisp + 1;
short FILTERED = (short)((mindisp - 1) && DISPARITY_SHIFT);
initialize the left and right borders of the disparity map
for( y = 0; y & y++ )
for( x = 0; x & x++ )
dptr[y*dstep + x] = FILTERED;
for( x = lofs + width1; x & x++ )
dptr[y*dstep + x] = FILTERED;
for( x = 0; x & width1; x++, dptr++ )
这样的设置很明显是不符合实际应用的需求的,它相当于把摄像头的视场范围缩窄了。因此,OpenCV2.1 做了明显的改进,不再要求左右视图和视差图的大小(size)一致,允许对视差图进行左右边界延拓,这样,虽然计算视差时还是按上面的代码思路来处理左右边界,但是视差图的边界得到延拓后,有效视差的范围就能够与对应视图完全对应。具体的实现代码范例如下://////////////////////////////////////////////////////////////////////////
// 对左右视图的左边进行边界延拓,以获取与原始视图相同大小的有效视差区域
copyMakeBorder(img1r, img1b, 0, 0, m_nMaxDisp, 0, IPL_BORDER_REPLICATE);
copyMakeBorder(img2r, img2b, 0, 0, m_nMaxDisp, 0, IPL_BORDER_REPLICATE);
//////////////////////////////////////////////////////////////////////////
// 计算视差
if( alg == STEREO_BM )
bm(img1b, img2b, dispb);
// 截取与原始画面对应的视差区域(舍去加宽的部分)
displf = dispb.colRange(m_nMaxDisp, img1b.cols);
else if(alg == STEREO_SGBM)
sgbm(img1b, img2b, dispb);
displf = dispb.colRange(m_nMaxDisp, img1b.cols);
4. cvFindStereoCorrespondenceBM的输出结果好像不是以像素点为单位的视差?
“:在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),才能得到正确的三维坐标信息。”
在OpenCV2.1中,BM算法可以用 CV_16S 或者 CV_32F 的方式输出视差数据,使用32位float格式可以得到真实的视差值,而CV_16S 格式得到的视差矩阵则需要 除以16 才能得到正确的视差。另外,OpenCV2.1另外两种立体匹配算法 SGBM 和 GC 只支持 CV_16S 格式的 disparity 矩阵。
5. 如何设置BM、SGBM和GC算法的状态参数?
& 6. 如何实现视差图的伪彩色显示?
首先要将16位符号整形的视差矩阵转换为8位无符号整形矩阵,然后按照一定的变换关系进行伪彩色处理。我的实现代码如下: // 转换为 CV_8U 格式,彩色显示
dispLfcv = displf, dispRicv = dispri, disp8cv = disp8;
if (alg == STEREO_GC)
cvNormalize( &dispLfcv, &disp8cv, 0, 256, CV_MINMAX );
displf.convertTo(disp8, CV_8U, 255/(m_nMaxDisp*16.));
F_Gray2Color(&disp8cv, vdispRGB);
灰度图转伪彩色图的代码,主要功能是使灰度图中 亮度越高的像素点,在伪彩色图中对应的点越趋向于 红色;亮度越低,则对应的伪彩色越趋向于 蓝色;总体上按照灰度值高低,由红渐变至蓝,中间色为绿色。其对应关系如下图所示:
图20void F_Gray2Color(CvMat* gray_mat, CvMat* color_mat)
if(color_mat)
cvZero(color_mat);
int stype = CV_MAT_TYPE(gray_mat-&type), dtype = CV_MAT_TYPE(color_mat-&type);
int rows = gray_mat-&rows, cols = gray_mat-&
// 判断输入的灰度图和输出的伪彩色图是否大小相同、格式是否符合要求
if (CV_ARE_SIZES_EQ(gray_mat, color_mat) && stype == CV_8UC1 && dtype == CV_8UC3)
CvMat* red = cvCreateMat(gray_mat-&rows, gray_mat-&cols, CV_8U);
CvMat* green = cvCreateMat(gray_mat-&rows, gray_mat-&cols, CV_8U);
CvMat* blue = cvCreateMat(gray_mat-&rows, gray_mat-&cols, CV_8U);
CvMat* mask = cvCreateMat(gray_mat-&rows, gray_mat-&cols, CV_8U);
// 计算各彩色通道的像素值
cvSubRS(gray_mat, cvScalar(255), blue); // blue(I) = 255 - gray(I)
cvCopy(gray_mat, red);
// red(I) = gray(I)
cvCopy(gray_mat, green);
// green(I) = gray(I),if gray(I) & 128
cvCmpS(green, 128, mask, CV_CMP_GE ); // green(I) = 255 - gray(I), if gray(I) &= 128
cvSubRS(green, cvScalar(255), green, mask);
cvConvertScale(green, green, 2.0, 0.0);
// 合成伪彩色图
cvMerge(blue, green, red, NULL, color_mat);
cvReleaseMat( &red );
cvReleaseMat( &green );
cvReleaseMat( &blue );
cvReleaseMat( &mask );
7. 如何将视差数据保存为 txt 数据文件以便在 Matlab 中读取分析?
由于OpenCV本身只支持 xml、yml 的数据文件读写功能,并且其xml文件与构建网页数据所用的xml文件格式不一致,在Matlab中无法读取。我们可以通过以下方式将视差数据保存为txt文件,再导入到Matlab中。 void saveDisp(const char* filename, const Mat& mat)
FILE* fp = fopen(filename, "wt");
fprintf(fp, "%02d/n", mat.rows);
fprintf(fp, "%02d/n", mat.cols);
for(int y = 0; y & mat. y++)
for(int x = 0; x & mat. x++)
short disp = mat.at&short&(y, x); // 这里视差矩阵是CV_16S 格式的,故用 short 类型读取
fprintf(fp, "%d/n", disp); // 若视差矩阵是 CV_32F 格式,则用 float 类型读取
fclose(fp);
相应的Matlab代码为:function img = txt2img(filename)
data = importdata(filename);
r = data(1);
c = data(2);
disp = data(3:end); % 视差
vmin = min(disp);
vmax = max(disp);
disp = reshape(disp, [c,r])'; % 将列向量形式的 disp 重构为 矩阵形式
OpenCV 是行扫描存储图像,Matlab 是列扫描存储图像
故对 disp 的重新排列是首先变成 c 行 r 列的矩阵,然后再转置回 r 行 c 列
img = uint8( 255 * ( disp - vmin ) / ( vmax - vmin ) );
mesh(disp);
set(gca,'YDir','reverse');
% 通过 mesh 方式绘图时,需倒置 Y 轴方向
% 使坐标轴显示范围与数据范围相贴合,去除空白显示区
显示效果如下:
SGBM算法原理
emi-global matching(缩写SGM)是一种用于计算双目视觉中disparity的半全局匹配算法。在OpenCV中的实现为semi-global block matching(SGBM)。
SGBM的思路是:
通过选取每个像素点的disparity,组成一个disparity map,设置一个和disparity map相关的全局能量函数,使这个能量函数最小化,以达到求解每个像素最优disparity的目的。
能量函数形式如下:
D指disparity map。E(D)是该disparity map对应的能量函数。
p, q代表图像中的某个像素
Np 指像素p的相邻像素点(一般认为8连通)
C(p, Dp)指当前像素点disparity为Dp时,该像素点的cost
P1 是一个惩罚系数,它适用于像素p相邻像素中dsparity值与p的dsparity值相差1的那些像素。
P2 是一个惩罚系数,它适用于像素p相邻像素中dsparity值与p的dsparity值相差大于1的那些像素。
I[.]函数返回1如果函数中的参数为真,否则返回0
利用上述函数在一个二维图像中寻找最优解是一个NP-complete问题,耗时过于巨大,因此该问题被近似分解为多个一维问题,即线性问题。而且每个一维问题都可以用动态规划来解决。因为1个像素有8个相邻像素,因此一般分解为8个一维问题。
考虑从左到右这一方向,如下图所示:
则每个像素的disparity只和其左边的像素相关,有如下公式:
r指某个指向当前像素p的方向,在此可以理解为像素p左边的相邻像素。Lr(p, d) 表示沿着当前方向(即从左向右),当目前像素p的disparity取值为d时,其最小cost值。
这个最小值是从4种可能的候选值中选取的最小值:
1.前一个像素(左相邻像素)disparity取值为d时,其最小的cost值。
2.前一个像素(左相邻像素)disparity取值为d-1时,其最小的cost值+惩罚系数P1。
3.前一个像素(左相邻像素)disparity取值为d+1时,其最小的cost值+惩罚系数P1。
4.前一个像素(左相邻像素)disparity取值为其他时,其最小的cost值+惩罚系数P2。
另外,当前像素p的cost值还需要减去前一个像素取不同disparity值时最小的cost。这是因为Lr(p, d)是会随着当前像素的右移不停增长的,为了防止数值溢出,所以要让它维持在一个较小的数值。
C(p, d)的计算很简单,由如下两个公式计算:
即,当前像素p和移动d之后的像素q之间,经过半个像素插值后,寻找两个像素点灰度或者RGB差值的最小值,作为C(p, d)的值。
具体来说:设像素p的灰度/RGB值为I(p),先从I(p),(I(p)+I(p-1))/2,(I(p)+I(p+1))/2三个值中选择出和I(q)差值最小的,即
d(p,p-d)。然后再从I(q),(I(q)+I(q-1))/2,(I(q)+I(q+1))/2三个值中选择出和I(p)差值最小的,即d(p-d,p)。最后从两个值中选取最小值,就是C(p, d)
上面是从一个方向(从左至右)计算出的像素在取值为某一disparity值时的最小cost值。但是一个像素有8个邻域,所以一共要从8个方向计算(左右,右左,上下,下上,左上右下,右下左上,右上左下,左下右上)这个cost值。
然后把八个方向上的cost值累加,选取累加cost值最小的disparity值作为该像素的最终disparity值。对于每个像素进行该操作后,就形成了整个图像的disparity map。公式表达如下:
SGBM算法遍历每个像素,针对每个像素的操作和disparity的范围有关,故时间复杂度为:
经典算法例子解释
阅读(...) 评论()

我要回帖

更多关于 opencv 轮廓匹配 的文章

 

随机推荐