立體匹配主要是利用多幅影象還原三維世界的空間資訊。通常,立體稠密匹配可以分為4個基本步驟:
matching cost computation,計算左圖乙個畫素和右圖乙個畫素之間的代價。
cost aggregation: connects the matching cost within a certain neighborhood,一般基於點之間的匹配很容易受雜訊的影響,往往真實匹配的畫素的代價並不是最低。所以有必要在點的周圍建立乙個區域,讓畫素周圍之間進行比較,到底乙個綜合的結果。
disparity computation: selects the disparity with the lowest matching cost,這一步可以區分區域性演算法與全域性演算法,區域性演算法直接優化代價聚合模型,輸出乙個粗略的視差圖。全域性演算法,要建立乙個能量函式,能量函式的資料項往往就是代價聚合公式,例如doublebp。
disparity refinement: removing peaks, interpolating gaps or increasing the accuracy by sub-pixel interpolation,對上一步得到的粗估計的視差圖進行精確計算,策略有很多,例如plane fitting,插值,bp,動態規劃等。
上述只是立體匹配的乙個框架,sgm**也同樣按照這樣來組織的,真正的實現還要靠具體實現。下面就按照**的順序來詳細了解下sgm演算法。
opencv sgbm修改自heiko hirschmuller的《stereo processing by semi-global matching and mutual information》,與原方法不同點:
沒有實現原文中基於互資訊的匹配代價計算,而是採用bt演算法(「depth discontinuities by pixel-to-pixel stereo」 by s. birchfield and c. tomasi);
預設執行單通道dp演算法,只用了5個方向,而fulldp使能時則使用8個方向(可能需要占用大量記憶體);
增加了一些bm演算法中的預處理和後處理程式;
sgbm主要配置引數說明:
mindisparity:最小視差,預設為0。此引數決定左圖中的畫素點在右圖匹配搜尋的起點,int 型別;
numdisparities:視差搜尋範圍長度,其值必須為16的整數倍。最大視差 maxdisparity = mindisparity + numdisparities -1;
blocksize:sad代價計算視窗大小,預設為5。視窗大小為奇數,一般在33 到2121之間;
p1、p2:能量函式引數,p1是相鄰畫素點視差增/減 1 時的懲罰係數;p2是相鄰畫素點視差變化值大於1時的懲罰係數。p2必須大於p1。需要指出,在動態規劃時,p1和p2都是常數。
一般建議:p1 = 8cnsgbm.sadwindowsizesgbm.sadwindowsize;
p2 = 32cnsgbm.sadwindowsizesgbm.sadwindowsize;
**片段一
typedef cv::point_point2s;
// sgbm匹配流程
void stereosgbm::operator ()( inputarray _left, inputarray _right,
outputarray _disp )
上述**呼叫了幾個子函式,其中,computedisparitysgbm是基於sgm+bt方法的視差圖計算流程。
**片段二
該函式又呼叫了calcpixelcostbt,也就是birchfeld-tomasi metric 來計算cost,具體函式如下:
/*
for each pixel row1[x], max(maxd, 0) <= minx <= x < maxx <= width - max(0, -mind),
and for each disparity mind<=dwidth1) ? width1 : xrange_max;
maxx1 = minx1 + xrange_max;
minx1 += xrange_min;
width1 = maxx1 - minx1;
int minx2 = std::max(minx1 - maxd, 0), maxx2 = std::min(maxx1 - mind, width);
int width2 = maxx2 - minx2;
// mat最直接的訪問方法是通過.ptr<>函式得到一行的指標,並用操作符訪問某一列的畫素值
const pixtype *row1 = img1.ptr(y), *row2 = img2.ptr(y);
pixtype *prow1 = buffer + width2*2, *prow2 = prow1 + width*cn*2; // buffer後留下兩行後面用
// 查表
tab += tabofs;
// initial
for( c = 0; c < cn*2; c++ )
// 此次 img1.step 就是影象 width
int n1 = y > 0 ? -(int)img1.step : 0, s1 = y < img1.rows-1 ? (int)img1.step : 0; // n1 是左圖的上一行,s1 是左圖的下一行
int n2 = y > 0 ? -(int)img2.step : 0, s2 = y < img2.rows-1 ? (int)img2.step : 0;
int minx_cmn = std::min(minx1,minx2)-1;
int maxx_cmn = std::max(maxx1,maxx2)+1;
minx_cmn = std::max(minx_cmn, 1);
maxx_cmn = std::min(maxx_cmn, width - 1);
// 這裡我們假設輸入的就是單通道
if( cn == 1 )
}memset( cost + xrange_min*d, 0, width1*d*sizeof(cost[0]) );
buffer -= width-1-maxx2; // 回退mind - 1步,不過要乘上視差數
cost -= (minx1-xrange_min)*d + mind; // simplify the cost indices inside the loop
for( c = 0; c < cn*2; c++, prow1 += width, prow2 += width )
for( x = minx1; x < maxx1; x++ ) // 針對左影象素依次計算cost}}
}}
blocksize(sadwindowsize) 越小,也就是匹配代價計算的視窗越小,視差圖雜訊越大;blocksize越大,視差圖越平滑;太大的size容易導致過平滑,並且誤匹配增多,體現在視差圖中空洞增多;
懲罰係數控制視差圖的平滑度,p2>p1,p2越大則視差圖越平滑;
八方向動態規劃較五方向改善效果不明顯,主要在影象邊緣能夠找到正確的匹配;
迷霧forest:
ethan_1990:
sgbm配置引數:
sgbm流程:
立體匹配 立體匹配過程
立體匹配就4個步驟 匹配代價計算,代價聚合,計算視差,視差精化 匹配代價計算 一般是通過計算左右兩圖對應畫素3個通道的灰度值差來決定匹配代價的,常用的就是基於畫素點匹配代價計算,一般有ad,sd,tad什麼的,基於區域的匹配代價計算一般有sad,ssd,stad之類的。匹配代價計算會生成乙個disp...
雙目立體匹配
公式 其中資料項描述了匹配程度,平滑項體現了定義場景的約束,c是匹配代價 或稱penalty p是不同兩畫素p和q視差的函式,一般稱之為平滑項 考慮到能量優化問題在一維空間的複雜度是多項式級的,因此一些研究試圖做一些近似來降低演算法的複雜度。例如,半全域性演算法 sgm 就利用了這一特性將二維問題簡...
立體匹配演算法 RankTransform
1.基本介紹 立體匹配演算法,關鍵是計算左右圖對應點的匹配代價。但是基於畫素的匹配方法有乙個問題就是對於重複紋理區域,支援視窗選取太小則不利於獲取準確的匹配代價,視窗選取過大則計算複雜度過高。對於這種情況,我們應該適當的考慮支援視窗的結構資訊,但是結構資訊如何表示,怎樣定量計算,這裡就要用到標題中提...