https://blog.csdn.net/u014629875/article/details/51227534
由于項(xiàng)目和畢設(shè)的需要,最近在做一些立體視覺的東西,總算是把立體視覺建立起來了,中途查了很多相關(guān)資料,這里做一個(gè)總結(jié)。
1.簡介:
雙目視覺是模擬人類視覺原理,使用計(jì)算機(jī)被動感知距離的方法。從兩個(gè)或者多個(gè)點(diǎn)觀察一個(gè)物體,獲取在不同視角下的圖像,根據(jù)圖像之間像素的匹配關(guān)系,通過三角測量原理計(jì)算出像素之間的偏移來獲取物體的三維信息。得到了物體的景深信息,就可以計(jì)算出物體與相機(jī)之間的實(shí)際距離,物體3維大小,兩點(diǎn)之間實(shí)際距離。
2.建立立體視覺
為了精確地求得某個(gè)點(diǎn)在三維空間里的深度信息,我們需要獲得的參數(shù)有焦距f、視差d、攝像頭中心距Tx;
為了獲得某個(gè)點(diǎn)的X坐標(biāo)和Y坐標(biāo),還需要知道左右像平面的坐標(biāo)系與立體坐標(biāo)系中原點(diǎn)的偏移cx和cy。
因此我們需要進(jìn)行下列三個(gè)步驟:相機(jī)標(biāo)定,圖像校正,立體匹配。
相機(jī)標(biāo)定
標(biāo)定目的:獲取相機(jī)的內(nèi)參(焦距,圖像中心,畸變系數(shù)等)和外參(R(旋轉(zhuǎn))矩陣T(平移)矩陣)
相機(jī)標(biāo)定需要采集標(biāo)定數(shù)據(jù),通常使用打印棋盤格的紙作為特制的標(biāo)定參照物,攝像頭獲取該物體的圖像,并由此計(jì)算攝像頭的內(nèi)外參數(shù)。
相機(jī)標(biāo)定有兩種方法:
方法一:Bouguet的Matlab標(biāo)定工具箱(http://www.vision.caltech.edu/bouguetj/calib_doc/);有比較詳細(xì)的介紹和使用方法,用起來還是比較方便的,只不過做完標(biāo)定要繼續(xù)的話要把標(biāo)定結(jié)果存入xml導(dǎo)入OpenCV再進(jìn)行。
方法二:OpenCV的cvStereoCalibrate;在《學(xué)習(xí)OpenCV》第11,12章有比較詳細(xì)的介紹。12章后有相關(guān)程序代碼。
雙目圖像校正
雙目校正是根據(jù)攝像頭定標(biāo)后獲得的單目內(nèi)參數(shù)據(jù)(焦距、成像原點(diǎn)、畸變系數(shù))和雙目相對位置關(guān)系(旋轉(zhuǎn)矩陣和平移向量),分別對左右視圖進(jìn)行消除畸變和行對準(zhǔn),使得左右視圖的成像原點(diǎn)坐標(biāo)一致、兩攝像頭光軸平行、左右成像平面共面、對極線行對齊。將左右視圖調(diào)整成完全平行對準(zhǔn)的理想形式(如下圖)。
校正反映到圖像上就是要把消除畸變后的兩幅圖像嚴(yán)格地行對應(yīng),使得兩幅圖像的對極線恰好在同一水平線上,這樣一幅圖像上任意一點(diǎn)與其在另一幅圖像上的對應(yīng)點(diǎn)就必然具有相同的行號,只需在該行進(jìn)行一維搜索即可匹配到對應(yīng)點(diǎn)。下圖來自于Stefano Mattoccia
“Stereo vision: algorithms and applications”http://vision.deis.unibo.it/~smatt/Seminars/StereoVision.pdf
(這個(gè)ppt對立體視覺做了一個(gè)很詳盡的講述,讀了可以對立體視覺方面有一個(gè)比較好的了解)
我在這部分用的是OpenCV中的cvStereoRectify,得出校準(zhǔn)參數(shù)之后用cvRemap來校準(zhǔn)輸入的左右圖像。這里要提一下cvRemap這個(gè)函數(shù)src與dst大小格式通道必須一致,所以在使用之前要先對左右圖像做處理。
立體匹配
立體匹配主要是通過找出每對圖像間的對應(yīng)關(guān)系,根據(jù)三角測量原理,得到視差圖;在獲得了視差信息后,根據(jù)投影模型很容易地可以得到原始圖像的深度信息和三維信息。
立體匹配是建立立體視覺中最重要的一環(huán),立體匹配的效果直接影響得到的三維信息。
由于現(xiàn)在只是使用了OpenCV的BM方法和SGBM方法,并沒有做深入的了解,所以關(guān)于這方面后續(xù)會再寫篇博客討論一下這方面的問題。
BM方法:
CvStereoBMState *BMState = cvCreateStereoBMState();
assert(BMState != 0);
BMState->preFilterSize=41;
BMState->preFilterCap=31;
BMState->SADWindowSize=41;
BMState->minDisparity=-64;
BMState->numberOfDisparities=128;
BMState->textureThreshold=10;
BMState->uniquenessRatio=10;
1
2
3
4
5
6
7
8
9
10
SGBM方法:
cv::StereoSGBM sgbm;
sgbm.preFilterCap = 63;
int SADWindowSize=11;
int cn = 1;
sgbm.SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 3;
sgbm.P1 = 4*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
sgbm.P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
sgbm.minDisparity = 0;
sgbm.numberOfDisparities = 32;
sgbm.uniquenessRatio = 10;
sgbm.speckleWindowSize = 100;
sgbm.speckleRange = 32;
sgbm.disp12MaxDiff = 1;
1
2
3
4
5
6
7
8
9
10
11
12
13
立體匹配后得到視差圖后獲取三維信息的方式(世界坐標(biāo)系是以左相機(jī)光心為原點(diǎn),光軸為Z軸,基線為X軸的右手系)
這里有一點(diǎn)要注意,立體匹配得出的視差結(jié)果是以16位符號數(shù)的形式的存儲的,出于精度需要,所有的視差在輸出時(shí)都擴(kuò)大了16倍(2^4),因此,在實(shí)際求距離時(shí),cvReprojectTo3D出來的X/W,Y/W,Z/W都要乘以16 (也就是W除以16),才能得到正確的三維坐標(biāo)信息。
一個(gè)簡單的輸出某個(gè)像素點(diǎn)三維信息的例子:
cvReprojectImageTo3D(disp,depth,&_Qtest);//_Qtest是雙目校正得到的Q矩陣
Point p;
p.x = 400;
p.y = 300;
Mat tempDepth = Mat(depth);
cout << "in world coordinate: " << tempDepth.at<Vec3f>(p)*16 << endl;
---------------------
作者:Array03
來源:CSDN
原文:https://blog.csdn.net/u014629875/article/details/51227534
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請附上博文鏈接!