2.2.2 上一節中的**的具體實現
目前常用的立體匹配演算法有bm(blocking match塊匹配),sgbm(semi-global bm),gc(graph cut圖割);傳統的立體匹配演算法中,全域性匹配演算法都無法滿足實時性的要求,因此此處只對bm和sgbm這種區域性匹配法進行分析和優化,gc是全域性匹配不做介紹。
bm演算法是一種基於sad窗的區域性匹配演算法,思想是以左目影象的源匹配點為中心,定義乙個視窗d,其大小為(2m+1x2n+1),統計其視窗的灰度值的和,然後在右目影象中逐步計算其左右視窗的灰度和的差值,最後搜尋到的差值最小的區域的中心畫素即為匹配點。基於sad視窗的bm演算法的處理速度很快,理論上一副320x240的灰度圖匹配時間為30ms。實驗使用640x480的鏡頭,測算出平均耗時約為90ms。但是這種演算法只能用於處理簡單場景,對於稍微複雜的場景會存在邊緣匹配關鍵點缺失的資訊丟失問題,嚴重影響測距效能。
#include
#include
#include
using namespace std;
using namespace cv;
mat imagel, imager;
ptr bm = stereobm:
:create(32
,15);
intmain()
下面依次給出視差圖和ll.jpg以及rr,jpg;可以看出效果一般,基本不實用。同時可以看到除了輪廓資訊丟失之外,左側有一條明顯的黑色部分:資訊完全丟失。這是乙個明顯的錯誤,接下來我們分析一下產生這個黑條的原因。
這裡給出opencv中stereobm演算法的原始碼的位置:d:\opencv\sources\modules\calib3d\src(依據個人安裝路徑查詢,**太多不便貼上展示)
bm演算法一共1278行,看起來蠻嚇人的,但是仔細一分析其實沒有多麼恐怖,演算法主要由以下部分組成:
定義結構體stereobmparams;
使用opencl和不適用opencl情況下prefilternorm函式的實現,這個函式的功能是對預處理;
使用opencl和不適用opencl情況下prefilterxsobel函式的實現,這個函式的功能是對預處理;
在cpu支援cv_sse2指令集優化的情況下,findstereocorrespondencebm_sse2的函式實現;
在cpu不支援cv_sse2指令集優化的情況下,findstereocorrespondencebm的函式實現;
構造迴圈體進行平行計算prefilterinvoker;
定義stereobm的子類stereobmimpl;
在子類stereobmimpl類裡實現所有需要呼叫的函式,如compute,setmindisparity,setprefiltercap等等。
首先建立乙個智慧型指標指向stereobm的bm物件,這裡呼叫了create函式,這個函式會呼叫下面的**:
ptr stereobm:
:create
(int _numdisparities,
int _sadwindowsize)
關於makeptr函式的定義(建立智慧型指標的基本原理和智慧型指標的優點不再贅述)
template
ptrmakeptr
(const a1& a1,
const a2& a2)
因此creat函式最後返回的結果為
ptrbm指向stereobmimpl的指標
;stereobmimpl是stereobm的子類,因此bm是父類指標指向了子類物件。
2. 讀取設定引數;
3. 呼叫compute函式:bm->compute(imagel, imager, disp);
函式定義為:void compute( inputarray leftarr, inputarray rightarr, outputarray disparr )
,輸入的形參為左圖,右圖和用來儲存輸出的視差圖。
void
compute
(inputarray leftarr, inputarray rightarr, outputarray disparr)
mat disp = disp0;
//定義disp
if(dtype == cv_32f)
//此處型別為cv_16s,如果是32f則在此處更改為16s
int wsz = params.sadwindowsize;
//sad視窗大小
int bufsize0 =
(int)(
(ndisp +2)
*sizeof
(int))
; bufsize0 +=(
int)
((height + wsz +2)
*ndisp *
sizeof
(int))
; bufsize0 +=(
int)
((height + wsz +2)
*sizeof
(int))
; bufsize0 +=(
int)
((height + wsz +2)
*ndisp*
(wsz +2)
*sizeof
(uchar)
+256);
int bufsize1 =
(int)(
(width + params.prefiltersize +2)
*sizeof
(int)+
256)
;int bufsize2 =0;
if(params.specklerange >=
0&& params.specklewindowsize >0)
bufsize2 = width*height*
(sizeof
(point_<
short
>)+
sizeof
(int)+
sizeof
(uchar));
//to be continued
這部分首先用getmat()函式將左右兩幅inputarray型別的影象轉化成mat型別;同時disp0也是cv_16s型別的mat圖,然後prefilteredimg0建立乙個和left0一樣大的cv_8u型別的影象矩陣的矩陣體,prefilteredimg1與之相同;cost則是和left0一樣大的cv_16s型別的影象矩陣的矩陣體。定義left和right影象,分別為
prefilteredimg0和prefilteredimg1;
width1用來表示最終生成的視差圖的有效寬度,因為左圖最左側的點在右圖中沒有對應點;故視差圖中沒有這一部分,這也解釋了之前我們的疑問,為什麼最終的視差圖左側有一條明顯的額黑色的資訊缺失;這是必然出現的,而且這一部分的寬度隨著視差視窗的大小變化,視差視窗越大,則黑帶越寬。
定義wsz為sad視窗大小;
雙目立體匹配演算法漫談
雙目立體匹配演算法是計算機視覺中比較經典的問題。有大量經典的雙目立體匹配演算法。本文簡要介紹一下雙目立體匹配的常用基本流程,也可以說是套路。第一次寫這麼長的博文,我想到 寫 更詳細內容的可見文章a taxonomy and evaluation of dense two frame stereo c...
halcon的雙目立體匹配及應用概述
對要求大測量範圍和較高測量精度的場合,採用基於雙攝像機的雙目立體視覺系統比較合適 對測量範圍要求比較小,對視覺系統體積和質量要求嚴格,需要高速度實時測量物件,基於光學成像的單攝像機雙目立體視覺系統便成為最佳選擇。基於雙攝像機的雙目立體視覺系統必須安裝在乙個穩定的平台上,在進行雙目視覺系統標定以及應用...
基於深度學習演算法和傳統立體匹配演算法的雙目立體視覺
人類通過眼睛感知世界 獲取資訊。人類獲取資訊的方式有很多種,可通過眼睛 耳朵 觸覺 嗅覺 味覺等,但我們接受到的絕大部分資訊都是通過視覺的方式獲取到的。由此可見,視覺系統在人類的生存 生產 發展中起到了極其重要的作用。隨著計算機技術 智慧型機械人等的廣泛研究與應用,不少科學家嘗試將人類視覺系統功能賦...