圖像的Census變換
Census變換屬於非參數圖像變換的一種,它能夠較好地檢測出圖像中的局部結構特征,如邊緣、角點特征等。傳統Census變換的基本思想是:在圖像區域定義一個矩形窗口,用這個矩形窗口遍歷整幅圖像。選取中心像素作為參考像素,將矩形窗口中每個像素的灰度值與參考像素的灰度值進行比較,灰度值小於或等於參考值的像素標記為0,大於參考值的像素標記為1,最后再將它們按位連接,得到變換后的結果,變換后的結果是由0和1組成的二進制碼流。Census變換的實質是將圖像像素的灰度值編碼成二進制碼流,以此來獲取鄰域像素灰度值相對於中心像素灰度值的大小關系。變換過程可通過如下公式表達:
其中p是窗口中心像素,q是窗口中心像素以外的其他像素,Np表示中心像素p的鄰域。I(*)表示像素點*處的灰度值。
給出實現Census變換的實現函數如下:

1 void CensusTransform(Mat input_image, Mat &modified_image, int window_sizex, int window_sizey) 2 { 3 int image_height=input_image.rows; 4 int image_width=input_image.cols; 5 6 modified_image=Mat::zeros(image_height, image_width, CV_64F); 7 8 //-----------census變換 --------------------------------- 9 int offsetx=(window_sizex-1)/2; 10 int offsety=(window_sizey-1)/2; 11 for(int j = 0; j < image_width - window_sizex; j++) 12 { 13 for(int i = 0; i < image_height - window_sizey; i++) 14 { 15 unsigned long census = 0; 16 uchar current_pixel=input_image.at<uchar>(i+offsety,j+offsetx); //窗口中心像素 17 Rect roi(j, i, window_sizex, window_sizey); //方形窗口 18 Mat window(input_image, roi); 19 20 for(int a = 0; a <window_sizey; a++) 21 { 22 for(int b = 0; b < window_sizex; b++) 23 { 24 if(!(a==offsety && b==offsetx))//中心像素不做判斷 25 { 26 census = census << 1;//左移1位 27 } 28 uchar temp_value = window.at<uchar>(a, b); 29 if(temp_value <= current_pixel ) //當前像素小於中心像素 01 30 { 31 census += 1; 32 } 33 } 34 } 35 modified_image.at<double>(i+offsety, j+offsetx) = census; 36 } 37 } 38 }
拿兩張圖像做個試驗, 如下:
如上圖所示可以分別得到兩幅Census變換后的圖像,在立體匹配的計算匹配代價部分可以利用這兩幅圖像計算圖像的匹配程度,通常是計算漢明距離hammingDst。函數實現如下:

1 // Fast Hamming distance algorithm 2 unsigned char Hammingdst(long long PL, long long PR) 3 { 4 unsigned char number=0; 5 long long v; 6 v = PL^PR; /* ^ 異或運算 不同為1 相同為0*/ 7 8 while(v) 9 { 10 v &= (v-1); /* & 與運算*/ 11 number++; 12 } 13 return number; 14 }
輸入為兩幅圖像對應像素點處的二進制碼流,輸出為兩個二進制碼流的異或結果中1的個數。用這個number可以作為像素點匹配程度的判斷。