参考文章:https://blog.csdn.net/MyStylee/article/details/78491271

Census原理:
在视图中选取任一点,以该点为中心划出一个例如3 × 3的矩形,矩形中除中心点之外的每一点都与中心点进行比较,灰度值小于中心点记为1,灰度大于中心点的则记为0,以所得长度为8的只有0和1的序列作为该中心点的census序列,即中心像素的灰度值被census 序列替换。经过census变换后的图像使用汉明距离计算相似度,所谓图像匹配就是在匹配图像中找出与参考像素点相似度最高的点,而汉明距正是匹配图像像素与参考像素相似度的度量。具体而言,对于欲求取视差的左右视图,要比较两个视图中两点的相似度,可将此两点的census值逐位进行异或运算,计算结果为1的个数,记1的个数作为此两点之间的汉明值。汉明值是两点间相似度的一种体现,汉明值愈小,两点相似度愈大实现算法时先异或再统计1的个数即可,汉明距越小即相似度越高。

代码实现:

#if 1//*************************Census*********************
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>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);int main()
{//LeftImg = imread("./im2.png", 0);     //这个效果不好,视差范围旋转35//RightImg = imread("./im6.png", 0);LeftImg = imread("./pic/2.ppm", 0);RightImg = imread("./pic/3.ppm", 0);#if 0namedWindow("renwu_left", 1);namedWindow("renwu_right", 1);imshow("renwu_left", LeftImg);imshow("renwu_right", RightImg);waitKey(500);
#endif // 1ImgHeight = LeftImg.rows;//288ImgWidth = LeftImg.cols;//384Left_census = ProcessImg(LeftImg);//处理左图,得到左图的CENSUS图像 Left_censusnamedWindow("Left_census", 1);imshow("Left_census", Left_census);waitKey(500);imwrite("./renwu_left.jpg", Left_census);Right_census = ProcessImg(RightImg);namedWindow("Right_census", 1);imshow("Right_census", Right_census);waitKey(500);//  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(500);//视差优化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<uchar>(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 < ImgHeight  && q >= 0 && q < ImgWidth){if (!(p == i + hWind && q == j + hWind)){//--------- 将二进制数存在变量中-----neighbor = Img.at<uchar>(p, q);if (neighbor > center){census = census * 2;//向左移一位,相当于在二进制后面增添0}else{census = census * 2 + 1;//向左移一位并加一,相当于在二进制后面增添1}//cout << "census = " << static_cast<int>(census) << endl;}}}}Img_census.at<uchar>(i + hWind, j + hWind) = census;//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_min = 0;//视差搜索范围上限int DSR_max = 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;int count = 0;//视差图像素L = left.at<uchar>(i, j);Mat Dif(1, DSR_max - DSR_min, CV_8UC1);//          Mat Dif(1, DSR, CV_32F);for (int k = DSR_min; k < DSR_max; k++){//cout << "k = " << k << endl;int y = j - k;if (y < 0){Dif.at<uchar>(k) = 0;}if (y >= 0){R = right.at<uchar>(i, y);#if 0cout << (65 ^ 35) << endl; //98; cout << 65 ^ 34 << endl;//这样会报错cout << (65 | 35) << endl; //99; cout << (65 & 35) << endl; //1
#endif // 0//bitwise_xor(L, R, );diff = L ^ R;diff = GetHammingWeight(diff);Dif.at<uchar>(count++) = diff;//                  Dif.at<float>(k) = diff;//cout << count << endl;}}//---------------寻找最佳匹配点--------------Point minLoc;minMaxLoc(Dif, NULL, NULL, &minLoc, NULL);int loc = minLoc.x;//x相当于矩阵中的列。坐标和矩阵不一样,坐标是P(x, y),对应矩阵是y行x列disparity.at<uchar>(i, j) = loc * 16;//乘以16是因为设置的视差下限是DSR_max,16*16=256,正好可以将视差图(0-15)*16变成灰度图(0-255)}}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<uchar>(i, j);if (pixel < 100)pixel = 0;ProcessDisImg.at<uchar>(i, j) = pixel;}}return ProcessDisImg;
}#endif // 0

左图和右图:

运行结果为:

补充:
(1)事先在工程目录pic文件下存放:立体校正后的左图 “2.ppm"和立体校正后的右图"3.ppm”。图片获取网址:http://vision.middlebury.edu/stereo/data/scenes2001/data/tsukuba/
数据集:http://vision.middlebury.edu/stereo/data/
(2)统计一个整数转换成二进制数后1的个数
https://blog.csdn.net/earther19949/article/details/99840713

#include<stdio.h>
#include<string.h>int NumberOf1_Suluton1(int i) {int count = 0;while (i) {count++;i &= (i - 1);}return count;
}int NumberOf1_Sulution2(int i) {int count = 0;int Flag = 1;while (Flag) {if (Flag & i)count++;Flag <<= 1;}return count;
}
int main(void) {int i = 2;printf("%d\n", NumberOf1_Suluton1(i));printf("%d\n", NumberOf1_Sulution2(i));return 0;
}

(3)Mat:

https://blog.csdn.net/sinat_33718563/article/details/78213233

(a)三通道图像读取方式
Vec3b可以看作是vector<uchar, 3>,简单而言就是一个uchar类型的,长度为3的vector向量。(在程序开头处加上#include以包含所需要的类文件vector,还有一定要加上using namespace std;)
使用由于在OpenCV中,使用imread读取到的Mat图像数据,都是用uchar类型的数据存储,对于RGB三通道的图像,每个点的数据都是一个Vec3b类型的数据。使用at定位方法如下:
img.at(row, col)[0] = 255;  // 这是指修改B通道数据
img.at(row, col)[1] = 255;  // 这是指修改G通道数据
img.at(row, col)[2] = 255;  // 这是指修改R通道数据

(b)单通道图像读取方式

Mat img1 = imread(filename,IMREAD_GRAYSCALE);
for( size_t nrow = 0; nrow < img1.rows; nrow++)
{  for(size_t ncol = 0; ncol < img1.cols; ncol++)  {  uchar val = img1 .at<uchar>(nrow,ncol);      }
}

(4)Opencv minMaxLoc()函数的使用

void cv::minMaxLoc   (   InputArray  src,
double *    minVal,
double *    maxVal = 0,
Point *     minLoc = 0,
Point *     maxLoc = 0,
InputArray  mask = noArray()
)
参量:
src 输入单通道数组。
minVal  指向返回的最小值的指针;如果不需要,则使用NULL。
maxVal 指向返回的最大值的指针;如果不需要,则使用NULL。
minLoc  指向返回的最小位置的指针(在2D情况下);如果不需要,则使用NULL。
maxLoc  指向返回的最大位置的指针(在2D情况下);如果不需要,则使用NULL。
mask 用于选择子阵列的可选遮罩。

函数cv :: minMaxLoc查找最小和最大元素值及其位置;该功能不适用于多通道阵列。如果需要在所有通道中查找最小或最大元素,请先使用Mat :: reshape将数组重新解释为单通道。

立体匹配——census算法相关推荐

  1. 双目视觉07_立体匹配Census算法

    以下实验为左图 以下为实验右图 实验代码 import os import time import cv2 as cv import numpy as np import matplotlib.pyp ...

  2. 双目立体匹配 Census

    上一篇介绍了双目立体匹配SAD算法,这一篇介绍Census算法. Census原理: 在视图中选取任一点,以该点为中心划出一个例如3 × 3 的矩形,矩形中除中心点之外的每一点都与中心点进行比较,灰度 ...

  3. Census算法的C++实现

    census算法的c++实现 这个代码是在(48条消息) 双目立体匹配 Census_MisTimee的博客-CSDN博客 基础上改的,添加了一些代码理解内容,由于本身对c++没有很熟悉(c++小白) ...

  4. 双目立体匹配 等 算法 论文 综述 全局局部算法 CSCA NLCA SegmentTree树 DoubleBP Belief-Propagation AD-Census SGM

    双目立体匹配 等 算法 论文 综述 本文GITHUB 博文末尾支持二维码赞赏哦 _ 双目立体视觉技术实质就是模拟人的双眼视觉处理系统来处理通过摄像机采集所 获取的图像,它利用两台或多台摄像机在一定约束 ...

  5. 基于MVS的三维重建算法学习笔记(五)— 立体匹配经典算法PatchMatch论文翻译及要点解读

    基于MVS的三维重建算法学习笔记(五)- 立体匹配经典算法PatchMatch论文翻译及要点解读 声明 问题提出 问题建模 通过PatchMatch获取平面参数--Inference via Patc ...

  6. 【老生谈算法】matlab实现census算法源码——census算法

    census算法matlab程序 1.文档下载: 本算法已经整理成文档如下,有需要的朋友可以点击进行下载 序号 文档(点击下载) 本项目文档 [老生谈算法]census算法matlab程序.docx ...

  7. 双目立体匹配_SGM算法

    双目立体匹配_SGM算法 视觉感知使人类能非接触地感知三维空间,通过大脑处理快速推断出周围环境的空间特性,从而执行一些生存所需的关键任务,如在环境中移动.识别和抓取物体等等.由于图像是三维世界的二维投 ...

  8. 基于MVS的三维重建算法学习笔记(四)— 立体匹配经典算法Semi-Global Matching(SGM)论文翻译及要点解读

    基于MVS的三维重建算法学习笔记(四)- 立体匹配经典算法Semi-Global Matching(SGM)论文翻译及要点解读 声明 SGM概述 Cost Calculation(像素代价计算)--M ...

  9. 双目立体匹配经典算法之Semi-Global Matching(SGM)概述:匹配代价计算之互信息(Mutual Information,MI)...

      半全局立体匹配算法Semi-Global Matching,SGM由学者Hirschmüller在2005年所提出1,提出的背景是一方面高效率的局部算法由于所基于的局部窗口视差相同的假设在很多情况 ...

最新文章

  1. C语言goto语句的使用
  2. “触达率图”新功能上线,量化网页浏览深度
  3. java循环控制_Java - 循环控制(Loop Control)
  4. 使用C语言将一个数组首尾互换后输出,函数实现体会地址传递
  5. freebsd 手工安装zabbix2.0 php,zabbix 服务端,子客户端安装配置日志
  6. scrollLeft,scrollWidth,clientWidth,offsetWidth之完全详解
  7. 用实例证明dll中new的内存不能在exe中释放
  8. 为什么QueueingConsumer会被Deprecated?
  9. Django ajax 检测用户名是否已被注册
  10. 防火墙问题 Linux系统 /etc/sysconfig/路径下无iptables文件
  11. getmodifiers java_java – getModifiers()方法如何计算多个修饰符的值?
  12. xp系统开机必须启动的服务器,XP系统如何关闭开机启动项呢?
  13. jbpm hibernate.cfg.xml 连接mysql配置_hibernate.cfg.xml文件连接mySql、Oracle、SqlServer配置...
  14. PHP7.1 狐教程
  15. [Django]模型提高部分--聚合(group by)和条件表达式+数据库函数
  16. TX2与PCA9685驱动舵机(RACECAR)
  17. 如何添加二级域名(图文超级详细)
  18. 一、C++面向对象高级编程(上) (侯捷)
  19. 我用 go-zero 一周实现了一个中台系统,已开源!
  20. outlook反复出现验证

热门文章

  1. 虚幻gameframe_UE4虚幻引擎开发手机游戏(一)
  2. ARCGIS之土地耕地占补平衡系统报备坐标txt格式批量导出工具(定制开发版)
  3. 单细胞论文记录(part20)--A Spatiotemporal Organ-Wide Gene Expression and Cell Atlas of the Developing ...
  4. 统计所有n阶方阵(n>0)中既满足自反性规则又满足对称性规则的方阵数量(注:矩阵元素值仅为0或1)
  5. 数据可视化的基本流程总结
  6. 金融电商推广可行性活动概览
  7. Stardock的十条成功法则
  8. [醉了]解决重启mac但是bash_profile不生效的彻底解决方法
  9. 华为新版模拟器-ENSP_PRO发布啦
  10. K-fold划分数据进行训练有k个训练模型,那最终选取哪个模型?