OpenCV实现Census变换

census        在立体视觉中,常常用到Census变换,Census变换是一种非参数局部变换,其将周围像素的强度映射到一个比特穿,从而捕获图像的结构。同时使用Census变换可以减少由相机增益和偏置引起变化的影响。在立体匹配过程中,将图像做Census变换后,计算像素点之间的明式距离进行匹配,可以得到较好的效果。

        这篇博客主要介绍介绍实现Census变换,由于使用OpenCV的容器和接口,所以直接使用OpenCV调用比较方便。

一、Census变换原理

        先给个链接,这个可以看这个链接中的内容。。

二、Census变换OpenCV实现

        先贴上代码

// _Tp为数据类型,根据自己比特串的长度选取
	template<typename _Tp>
	void ImageCensus(Mat& gray, Mat& census, int cw, int ch){
		for (int y = ch; y < rows - 1 - ch; y++){
			const uchar *pcur = gray.ptr<uchar>(y);
			for (int x = cw; x < cols - 1 - cw; x++){
				const uchar cur = pcur[x];
				_Tp mask = 1;
				_Tp val = 0;
				for (int i = -ch; i <= ch; ++i){
					const uchar *psur = gray.ptr<uchar>(y + i);
					for (int j = -cw; j <= cw; ++j){
						if (i == 0 && j == 0){
							continue;
						}
						const uchar sur = psur[x + j];
						if (cur < sur){
							val |= mask;
						}
						mask <<= 1;
					}
				}
				census.ptr<_Tp>(y)[x] = val;
			}
		}
	}

        解释一下函数的参数

        Mat& gray:CV_8UC1的灰度图像,如果你的图像不是灰度图像,那么只需要在gray.ptr<uchar>,改掉uchar就可以了,由于大家大多使用灰度图像做输入,这部分就没有用泛型写。

        Mat& census:输出的Census图像,类型需要和泛型参数<_Tp>对应,表示了census图像每个点的长度。    如果你使用的是3*3窗格,那么使用uchar类型就可以了,除去中心像素只有8个位,如果是5*5窗格,就是24位,必须用int32,如果使用更大的窗口,那么久需要长的结构__int64或者__m128   __m256等,要是更长就要自己定义联合体或者新类型了。

        cw:窗口的宽度,ch:窗口的高度

        下面,选取1*1窗口,用uchar8位来看看效果

im2

        Census变换之后的结构,是不是和LBP有相似之处呢?

census

        OK,See You Next Chapter!

 

发表评论