图像的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可以作为像素点匹配程度的判断。