一、簡介
ELAS是由Andreas Geiger於2010年提出的一種比較新穎的立體匹配算法,全稱爲《Efficient Large Scale Stereo Matching》。這種算法的優點是對於高分辨率的圖像,能夠兼顧較高的匹配速度和匹配精度,在許多公開的數據集中ELAS的平均匹配精度十分接近SGM,但是速度卻比SGM更快。ELAS算法並沒有遵循典型的代價計算、代價聚合、視差優化、視差細化的過程,而是將立體匹配過程建模成爲貝葉斯最優估計理論,通過最大後驗概率估計方法推理視差。該算法利用圖像中一些稀疏的能夠魯棒匹配的支持點作爲先驗,並將這些支持點進行Delaunay三角化,從而可以降低剩餘像素點的匹配歧義,不需要進行全局優化。該算法可以自動決定每一個像素點的視差搜索範圍,並且很容易實現並行操作。僅使用單核CPU的話,ELAS算法對於一百萬像素分辨率的圖像進行匹配需要僅僅大概1s左右的時間。
ELAS算法的基本流程是:
(1) 對左右圖像進行sobel濾波,生成sobel特徵圖;
(2) 基於sobel特徵進行匹配,篩選出其中具有較高置信度的匹配點,作爲"support points",即支持點;
(3) 對支持點構建Delaunay三角網格;
(4) 構建立體匹配的概率生成模型;
(5) 基於最大後驗概率密度估計(MAP)進行稠密立體匹配,獲取初始視差圖;
(6) 視差後處理:無效孔洞插值、(自適應)中值濾波、連通域噪聲剔除、左右一致性檢驗。
二、計算支持點
在計算支持點之前,需要設置一個全局可靠的視差搜索範圍:, 一般最小視差設置爲0,最大視差需要根據所使用的場景來調整。首先對左圖像採用的sobel算子進行濾波,獲取每一個像素點的水平和垂直響應值和。然後對每一個像素,從其周圍鄰域中的水平方向響應值選取12個,垂直方向響應值選取4個,構成一個16維的特徵向量:
特徵匹配時,對左圖中的每一個像素,使用右圖中對應的每一個像素鄰域中的四個角的特徵向量、、、, ,進行匹配,匹配對的相似性度量值的計算方式如下:
從中選取相似度最高的像素作爲匹配對(同樣的方法可以獲取右圖所有像素的匹配),然後採用ratio test對匹配進行篩選,即最低匹配值和次低匹配值的比值小於設定閾值時才認爲是正確的匹配。爲了進一步保證匹配的置信度,採用左右一致性檢驗和支持點周圍一定鄰域內其它支持點數量的判斷(數量太少,認爲該支持點不可靠),繼續篩選剩餘匹配。經過以上幾個步驟就可以得到所有的支持點了。
作者還指出sobel濾波對於特徵匹配是十分高效的,雖然有很多可以進行魯棒匹配的描述子,比如SIFT、SURF等,但是他們對於整個立體匹配的精度並沒有帶來提升,而且還會拖累運行速度。
三、立體匹配的概率生成模型
所謂概率生成模型就是將視差和左右圖的像素看作隨機變量,根據貝葉斯理論對視差的概率分佈進行建模,根據概率生成模型,給定參考圖像和支持點,可以從另外一副圖像中進行採樣。令表示支持點的集合,每一個支持點,令表示觀測點的集合,每一個觀測點,其中爲特徵向量。令
和表示左右圖像中對應像素點。不失一般性,將左圖作爲參考圖。在給定視差的條件下,觀測對和支持點集S是條件獨立的,他們的聯合分佈可以被分解爲:
其中稱爲先驗概率,稱爲似然概率。
(1)先驗概率建模
作者認爲先驗概率與均勻分佈和高斯分佈的組合成比例:
其中爲觀測點基於周圍支持點的平均值,爲觀測點周圍鄰域內所有支持點的視差值所構成的取值範圍。爲了進一步縮小取值範圍,所有與均值之差大於的視差都被排除了。表示爲一個分段線性函數,可以通過基於支持點構建的delaunay三角形來進行視差插值得到。對每一個三角形,其所在的視差平面定義如下:
其中i是所屬三角形的索引,對每一個三角形,平面參數可以由三角形的三個頂點通過求解線性方程求得。
(2)似然概率建模
作者認爲圖像似然概率可以表示成一個拉普拉斯分佈:
其中 和 爲特徵向量,是一個常數。if條件保證似然概率約束在左右圖像的同一行上。特徵向量由觀測點周圍鄰域內像素的sobel響應值拼接而成,故其維數爲(實際使用的特徵向量依然按照上一節所引入的16維特徵向量)。作者在文中特別指出基於sobel濾波的特徵性能明顯好於基於LoG濾波的特徵。
(3)基於概率生成模型的採樣
概率生成模型的優點是給定支持點集合和左圖參考點,可以從右圖採樣對應的像素點,方法如下:
1)給定S和,可以根據先驗概率分佈隨機採樣視差;
2)給定和,可以根據似然概率分佈得到右圖對應點。
如下圖所示是採樣過程示意圖:
爲了更好的理解這個過程,下圖展示了使用灰度值作爲特徵,對左圖每一個像素重複上述過程採樣一百次,取平均之後得到一個新圖,從圖中可以看到,正如所預料的那樣,新圖相當於一個模糊版本的右圖。
四、視差計算
第三節講述了概率生成模型:
(1)提出一個先驗概率分佈和圖像似然概率分佈,並基於此進行立體匹配,先驗分佈決定視差採樣的範圍,似然概率提供了視差採樣可靠性的判斷;
(2)根據概率生成模型,給定左圖和支持點,可以從右圖中進行採樣。
然而更爲重要的是如何根據概率生成模型來計算視差圖。作者提出可以使用最大後驗概率估計(MAP)的方法估計視差:
其中,,......,表示右圖中位於對極線上的觀測點。後驗概率表示給定左圖觀測點、支持點集和右圖觀測點,左圖觀測點取視差的概率。後驗概率可以被分解爲:
將先驗概率和似然概率帶入上式,並取負對數可以得到一個能量函數:
能量函數的第一部分表示似然項,第二部分爲先驗項或平滑項。通過最小化能量函數,可以得到觀測點的視差。出於編程的考慮,實際當中應用的能量函數爲:
這樣可以預計算先驗項。最小化能量函數時,將視差分成了兩個部分:(1)基於先驗分佈,僅考慮觀測點經插值後的平均視差的局部範圍,即, sradius一般取2或3;(2)基於像素周圍鄰域內的所有支撐點的視差構成的視差搜索範圍(如下圖所示),這部分視差在最小化能量函數時不考慮先驗項。(Note:最小化搜索過程中考慮了紋理,對於太弱的紋理直接跳過計算視差)
同樣的方法可以計算右圖的視差圖。
五、後處理
後處理部分採用無效區域孔洞插值、左右一致性檢驗、連通域噪聲剔除、中值濾波、自適應中值濾波。
1.左右一致性檢測
設左圖像素點的視差爲,則右圖的對應點的視差爲,若,則認爲視差是可靠的,否則將其置爲-1或其他無效值。其中一般取1或2,可適當調整。
2.孔洞插值
在立體匹配的過程中,有多種情況導致視差圖中某點的像素被置爲無效值,如紋理不足、左右一致性檢驗、圖像邊緣處的像素。對於這些點處的視差往往需要通過插值給予其一個合理的視差值。首先考慮水平方向,若某個無效區域的最左側和最右側的視差值爲和,考慮深度突變,則其中所有點的視差的插值公式如下:
其中表示深度不連續的閾值。垂直方向也以同樣的方法進行一次插值。
3.中值濾波與自適應中值濾波
中值濾波可以消除視差圖中的孤立噪點,而自適應中值濾波類似於雙邊濾波,在平滑去噪的同時,還能較好的保留視差圖的邊緣。原理:略
4.連通域噪聲剔除
視差圖中總是包含着錯誤的視差,由於弱紋理、反射、噪聲等諸多因素,這些錯誤的視差往往成聚集成小的塊狀區域,使用該方法可以有效去除視差圖中塊狀噪聲區域。給定連通域的灰度閾值和尺寸閾值,通過檢測連通域的尺寸是否滿足尺寸閾值條件,來判斷該連通域是否爲噪聲。若爲噪聲,將該連通域中的所有視差置爲無效值。
六、代碼實現
作者已經開源了C++源代碼,並提供了Matla接口,下載地址爲http://www.cvlibs.n。源碼如下:
下載源碼後,導入visual studio工程,編寫main函數:
#include <iostream>
#include <time.h>
#include "elas.h"
#include "image.h"
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
string path1 = "C:/Users/thinkpad/Desktop/left/000003.png";
string path2 = "C:/Users/thinkpad/Desktop/right/000003.png";
//讀取左右視圖
Mat iml = imread( path1, -1);
Mat imr = imread( path2, -1);
if (iml.rows != imr.rows || iml.cols != imr.cols)
cerr << "左右視圖必須擁有相同的尺寸" << endl;
Mat left, right;
if (iml.channels() == 3)
cvtColor(iml, left, COLOR_RGB2GRAY);
else
iml.copyTo(left);
if (imr.channels() == 3)
cvtColor(imr, right, COLOR_RGB2GRAY);
else
imr.copyTo(right);
int width = left.cols;
int height = left.rows;
int dim[3] = { width, height, width };
Mat disp_left = Mat::zeros(Size(width, height), CV_32FC1);
Mat disp_right = Mat::zeros(Size(width, height), CV_32FC1);
// 參數設置
Elas::parameters param;
param.disp_min = 0; // 最小視差
param.disp_max = 256; // 最大視差
param.support_threshold = 0.85; // 比率測試:最低match VS 次低match
param.support_texture = 10; // 支持點的最小紋理
param.candidate_stepsize = 5; // 用於支持點的sobel特徵匹配的鄰域半徑
param.incon_window_size = 5; // 不連續性窗口的尺寸
param.incon_threshold = 5; // 不連續性窗口內的視差範圍閾值
param.incon_min_support = 5; // 不連續性窗口內的最低支持點數量
param.add_corners = true; // 是否添加角點
param.grid_size = 20; // 網格尺寸
param.beta = 0.02; // 圖像相似性度量的參數
param.gamma = 3; // 先驗概率常數
param.sigma = 1; // 先驗概率的標準差
param.sradius = 3; // 標準差半徑
param.match_texture = 1; // 最低紋理
param.lr_threshold = 1; // 左右一致性檢驗閾值
param.speckle_sim_threshold = 1; // 連通域判斷閾值
param.speckle_size = 200; // 連通域噪聲尺寸判斷閾值
param.ipol_gap_width = 3; // 空洞寬
param.filter_median = false; // 是否中值濾波
param.filter_adaptive_mean = true; // 是否自適應中值濾波
param.postprocess_only_left = true; // 是否只對左視差圖後處理,設置爲True可以節省時間
param.subsampling = false; // 每個兩個像素進行視差計算,設置爲True可以節省時間,但是傳入的D1和D2的分辨率必須爲(w/2) x (h/2)
clock_t start = clock();
Elas elas(param);
elas.process(left.data, right.data, disp_left.ptr<float>(0), disp_right.ptr<float>(0), dim);
clock_t end = clock();
cout << "running time:" << (double)(1000*(end - start) / CLOCKS_PER_SEC) << endl;
disp_left = disp_left * 3;
imwrite("C:/Users/thinkpad/Desktop/disparity.jpg", disp_left);
}
七、實驗效果
這裏隨機選擇了KITTI雙目數據集中的幾張圖片,下面是左視圖及使用ELAS算法生成的對應的視差圖:
八、總結
- ELAS算法的最大優點就是匹配速度快的同時又有較高的匹配精度,這是因爲它通過魯棒匹配的支持點作爲先驗,降低了剩餘像素點視差的搜索範圍。所有視差平面實際上代表了場景的幾何結構,因此位於某視差平面內的點的視差必定與附近的支持點具有相近的視差。
- 獲取支撐點的過程實際上就是傳統的不包含代價聚合的局部立體匹配算法,這一步驟耗時較短,所以ELAS算法的運行時間下限不會比最快的匹配算法更少。
- 先驗概率和似然概率的建模似乎還有可以改造的空間。
- 雖然在公開數據集中ELAS匹配都能夠取得很好的效果。但是對於實際場景的圖像特別是室外圖像,當傳感器噪聲較高、存在大面積無紋理區域時,ELAS算法依然不能處理的很好,原因在於在這種情況下sobel算子從圖像中不能獲得足夠多的精確支持點,後續的匹配性能就會大打折扣。
- 到目前爲止,關於ELAS算法的變種不是太多,其中較好的改進有LS-ELAS。
各位覺得不錯的一定要點個贊哦!!!!!!