上一篇介绍了双目立体匹配SAD算法,这一篇介绍Census算法。
Census原理:
在视图中选取任一点,以该点为中心划出一个例如3 × 3 的矩形,矩形中除中心点之外的每一点都与中心点进行比较,灰度值小于中心点记为1,灰度大于中心点的则记为0,以所得长度为 8 的只有 0 和 1 的序列作为该中心点的 census 序列,即中心像素的灰度值被census 序列替换。经过census变换后的图像使用汉明距离计算相似度,所谓图像匹配就是在匹配图像中找出与参考像素点相似度最高的点,而汉明距正是匹配图像像素与参考像素相似度的度量。具体而言,对于欲求取视差的左右视图,要比较两个视图中两点的相似度,可将此两点的census值逐位进行异或运算,然后计算结果为1 的个数,记为此两点之间的汉明值,汉明值是两点间相似度的一种体现,汉明值愈小,两点相似度愈大实现算法时先异或再统计1的个数即可,汉明距越小即相似度越高。
下面的代码是自己根据原理写的,实现的结果并没有很好,以后继续优化代码。
具体代码如下:
//*************************Census********************* #include#include #include #include using namespace std; using namespace cv; //-------------------定义汉明距离---------------------------- int disparity; int GetHammingWeight(uchar value);//求1的个数 //-------------------定义Census处理图像函数--------------------- int hWind = 1;//定义窗口大小为(2*hWind+1) Mat ProcessImg(Mat &Img);//将矩形内的像素与中心像素相比较,将结果存于中心像素中 Mat Img_census, Left_census, Right_census; //--------------------得到Disparity图像------------------------ Mat getDisparity(Mat &left, Mat &right); //--------------------处理Disparity图像----------------------- Mat ProcessDisparity(Mat &disImg); int ImgHeight, ImgWidth; //int num = 0;//异或得到的海明距离 Mat LeftImg, RightImg; Mat DisparityImg(ImgHeight, ImgWidth, CV_8UC1, Scalar::all(0)); Mat DisparityImg_Processed(ImgHeight, ImgWidth, CV_8UC1, Scalar::all(0)); Mat DisparityImg_Processed_2(ImgHeight, ImgWidth, CV_8UC1); //定义读取图片的路径 string file_dir="C:\\Program Files\\FLIR Integrated Imaging Solutions\\Triclops Stereo Vision SDK\\stereomatching\\Grab_Stereo\\pictures\\"; //定义存储图片的路径 string save_dir= "C:\\Program Files\\FLIR Integrated Imaging Solutions\\Triclops Stereo Vision SDK\\stereomatching\\Grab_Stereo\\Census\\"; int main() { LeftImg = imread(file_dir + "renwu_left.png", 0); RightImg = imread(file_dir + "renwu_right.png", 0); namedWindow("renwu_left", 1); namedWindow("renwu_right", 1); imshow("renwu_left", LeftImg); waitKey(5); imshow("renwu_right", RightImg); waitKey(5); ImgHeight = LeftImg.rows; ImgWidth = LeftImg.cols; Left_census= ProcessImg(LeftImg);//处理左图,得到左图的CENSUS图像 Left_census namedWindow("Left_census", 1); imshow("Left_census", Left_census); waitKey(5); // imwrite(save_dir + "renwu_left.jpg", Left_census); Right_census= ProcessImg(RightImg); namedWindow("Right_census", 1); imshow("Right_census", Right_census); waitKey(5); // imwrite(save_dir + "renwu_right.jpg", Right_census); DisparityImg= getDisparity(Left_census, Right_census); namedWindow("Disparity", 1); imshow("Disparity", DisparityImg); // imwrite(save_dir + "disparity.jpg", DisparityImg); waitKey(5); DisparityImg_Processed = ProcessDisparity(DisparityImg); namedWindow("DisparityImg_Processed", 1); imshow("DisparityImg_Processed", DisparityImg_Processed); // imwrite(save_dir + "disparity_processed.jpg", DisparityImg_Processed); waitKey(0); return 0; } //-----------------------对图像进行census编码--------------- Mat ProcessImg(Mat &Img) { int64 start, end; start = getTickCount(); Mat Img_census = Mat(Img.rows, Img.cols, CV_8UC1, Scalar::all(0)); uchar center = 0; for (int i = 0; i < ImgHeight - hWind; i++) { for (int j = 0; j < ImgWidth - hWind; j++) { center = Img.at (i + hWind, j + hWind); uchar census = 0; uchar neighbor = 0; for (int p = i; p <= i + 2 * hWind; p++)//行 { for (int q = j; q <= j + 2 * hWind; q++)//列 { if (p >= 0 && p = 0 && q < ImgWidth) { if (!(p == i + hWind && q == j + hWind)) { //--------- 将二进制数存在变量中----- neighbor = Img.at (p, q); if (neighbor > center) { census = census * 2;//向左移一位,相当于在二进制后面增添0 } else { census = census * 2 + 1;//向左移一位并加一,相当于在二进制后面增添1 } //cout << "census = " << static_cast (census) << endl; } } } } Img_census.at (i + hWind, j + hWind) = census; } } /*end = getTickCount(); cout << "time is = " << end - start << " ms" << endl;*/ return Img_census; } //------------得到汉明距离--------------- int GetHammingWeight( uchar value) { int num = 0; if (value == 0) return 0; while (value) { ++num; value = (value - 1)&value; } return num; } //--------------------得到视差图像-------------- Mat getDisparity(Mat &left, Mat &right) { int DSR =16;//视差搜索范围 Mat disparity(ImgHeight,ImgWidth,CV_8UC1); cout << "ImgHeight = " << ImgHeight << " " << "ImgWidth = " << ImgWidth << endl; for (int i = 0; i < ImgHeight; i++) { for (int j = 0; j < ImgWidth; j++) { uchar L; uchar R; uchar diff; L = left.at (i, j); Mat Dif(1, DSR, CV_8UC1); // Mat Dif(1, DSR, CV_32F); for (int k = 0; k < DSR; k++) { //cout << "k = " << k << endl; int y = j - k; if (y < 0) { Dif.at (k) = 0; } if (y >= 0) { R = right.at (i,y); //bitwise_xor(L, R, ); diff = L^R; diff = GetHammingWeight(diff); Dif.at (k) = diff; // Dif.at (k) = diff; } } //---------------寻找最佳匹配点-------------- Point minLoc; minMaxLoc(Dif, NULL, NULL, &minLoc, NULL); int loc = minLoc.x; //cout << "loc..... = " << loc << endl; disparity.at (i,j)=loc*16; } } return disparity; } //-------------对得到的视差图进行处理------------------- Mat ProcessDisparity(Mat &disImg) { Mat ProcessDisImg(ImgHeight,ImgWidth,CV_8UC1);//存储处理后视差图 for (int i = 0; i < ImgHeight; i++) { for (int j = 0; j < ImgWidth; j++) { uchar pixel = disImg.at (i, j); if (pixel < 100) pixel = 0; ProcessDisImg.at (i, j) = pixel; } } return ProcessDisImg; }
经过处理后的左图census图像
经过处理后的右图census图像
disparity图像
处理后的disparity图像
以上就是C++实现双目立体匹配Census算法的示例代码的详细内容,更多关于C++双目立体匹配Census算法的资料请关注脚本之家其它相关文章!