C++实现双目立体匹配Census算法的示例代码

上一篇介绍了双目立体匹配SAD算法,这一篇介绍Census算法。

Census原理:

在视图中选取任一点,以该点为中心划出一个例如3 × 3 的矩形,矩形中除中心点之外的每一点都与中心点进行比较,灰度值小于中心点记为1,灰度大于中心点的则记为0,以所得长度为 8 的只有 0 和 1 的序列作为该中心点的 census 序列,即中心像素的灰度值被census 序列替换。经过census变换后的图像使用汉明距离计算相似度,所谓图像匹配就是在匹配图像中找出与参考像素点相似度最高的点,而汉明距正是匹配图像像素与参考像素相似度的度量。具体而言,对于欲求取视差的左右视图,要比较两个视图中两点的相似度,可将此两点的census值逐位进行异或运算,然后计算结果为1 的个数,记为此两点之间的汉明值,汉明值是两点间相似度的一种体现,汉明值愈小,两点相似度愈大实现算法时先异或再统计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);
//定义读取图片的路径
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<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;
        }
    }
    /*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<uchar>(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<uchar>(k) = 0;
                }
                if (y >= 0)
                {
                    R = right.at<uchar>(i,y);
                    //bitwise_xor(L, R, );
                    diff = L^R;
                    diff = GetHammingWeight(diff);
                    Dif.at<uchar>(k) = diff;
//                  Dif.at<float>(k) = diff;
                }
            }
            //---------------寻找最佳匹配点--------------
            Point minLoc;
            minMaxLoc(Dif, NULL, NULL, &minLoc, NULL);
            int loc = minLoc.x;
            //cout << "loc..... = " << loc << endl;
            disparity.at<uchar>(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<uchar>(i, j);
            if (pixel < 100)
                pixel = 0;
            ProcessDisImg.at<uchar>(i, j) = pixel;
        }
    }
    return ProcessDisImg;
}

经过处理后的左图census图像

经过处理后的右图census图像

disparity图像

处理后的disparity图像

以上就是C++实现双目立体匹配Census算法的示例代码的详细内容,更多关于C++双目立体匹配Census算法的资料请关注我们其它相关文章!

(0)

相关推荐

  • c++ 实现文件逐行读取与字符匹配

    C++读取文件 首先我们构造一个txt文件用于测试,比如以下这个名为mindspore.txt的文件(之所以取这个名字,是因为最近在研究mindspore,因此最方便拿到的数据就是mindspore的借口api文档): MindSpore Python API MindSpore Python API mindspore mindspore.common.initializer mindspore.communication mindspore.compression mindspore.con

  • opencv3/C++ FLANN特征匹配方式

    使用函数detectAndCompute()检测关键点并计算描述符 函数detectAndCompute()参数说明: void detectAndCompute( InputArray image, //图像 InputArray mask, //掩模 CV_OUT std::vector<KeyPoint>& keypoints,//输出关键点的集合 OutputArray descriptors,//计算描述符(descriptors[i]是为keypoints[i]的计算描述符

  • opencv C++模板匹配的简单实现

    目录 一简单实现 二函数及原理讲解 1matchTemplate()参数详解 2minMaxLoc()函数 一 简单实现 #include <opencv2/opencv.hpp> #include<iostream> using namespace cv; using namespace std; int main() { Mat img = imread("52.jpg"); Mat templ = imread("templ.jpg")

  • Java实现8种排序算法的示例代码

    冒泡排序 O(n2) 两个数比较大小,较大的数下沉,较小的数冒起来. public static void bubbleSort(int[] a) { //临时变量 int temp; //i是循环次数,也是冒泡的结果位置下标,5个数组循环5次 for (int i = 0; i < a.length; i++) { //从最后向前面两两对比,j是比较中下标大的值 for (int j = a.length - 1; j > i; j--) { //让小的数字排在前面 if (a[j] <

  • JAVA用递归实现全排列算法的示例代码

    求一个n阶行列式,一个比较简单的方法就是使用全排列的方法,那么简述以下全排列算法的递归实现. 首先举一个简单的例子说明算法的原理,既然是递归,首先说明一下出口条件.以[1, 2]为例 首先展示一下主要代码(完整代码在后面),然后简述 //对数组array从索引为start到最后的元素进行全排列 public void perm(int[]array,int start) { if(start==array.length) { //出口条件 for(int i=0;i<array.length;i

  • C++实现顺序排序算法简单示例代码

    本文实例讲述了最直接的顺序排序法VC++示例代码,还记得以前上学时候这是计算机的必考题,而且在排序算法中,顺序排序似乎是最简单的了,也是最容易掌握的.现在列出来让大家重新回顾一下! 具体代码如下: //顺序排序 void InsertSort(int r[], int n){ for (int i=2; i<n; i++){ r[0]=r[i]; //设置哨兵 for (int j=i-1; r[0]<r[j]; j--) //寻找插入位置 r[j+1]=r[j]; //记录后移 r[j+1]

  • Android多边形区域递归种子填充算法的示例代码

    平面区域填充算法是计算机图形学领域的一个很重要的算法,区域填充即给出一个区域的边界(也可以是没有边界,只是给出指定颜色),要求将边界范围内的所有象素单元都修改成指定的颜色(也可能是图案填充).区域填充中最常用的是多边形填色,本文中我们就讨论几种多边形区域填充算法. 一.种子填充算法(Seed Filling) 如果要填充的区域是以图像元数据方式给出的,通常使用种子填充算法(Seed Filling)进行区域填充.种子填充算法需要给出图像数据的区域,以及区域内的一个点,这种算法比较适合人机交互方式

  • Angularjs实现分页和分页算法的示例代码

    对于大多数web应用来说显示项目列表是一种很常见的任务.通常情况下,我们的数据会比较多,无法很好地显示在单个页面中.在这种情况下,我们需要把数据以页的方式来展示. 页面展示效果: 页面HTML代码: <table class="table table-striped" style="margin: 0px;"> <thead> <tr> <td>选择</td> <td>企业名称</td&g

  • python实现决策树ID3算法的示例代码

    在周志华的西瓜书和李航的统计机器学习中对决策树ID3算法都有很详细的解释,如何实现呢?核心点有如下几个步骤 step1:计算香农熵 from math import log import operator # 计算香农熵 def calculate_entropy(data): label_counts = {} for feature_data in data: laber = feature_data[-1] # 最后一行是laber if laber not in label_counts

  • 用python实现k近邻算法的示例代码

    K近邻算法(或简称kNN)是易于理解和实现的算法,而且是你解决问题的强大工具. 什么是kNN kNN算法的模型就是整个训练数据集.当需要对一个未知数据实例进行预测时,kNN算法会在训练数据集中搜寻k个最相似实例.对k个最相似实例的属性进行归纳,将其作为对未知实例的预测. 相似性度量依赖于数据类型.对于实数,可以使用欧式距离来计算.其他类型的数据,如分类数据或二进制数据,可以用汉明距离. 对于回归问题,会返回k个最相似实例属性的平均值.对于分类问题,会返回k个最相似实例属性出现最多的属性. kNN

  • Java实现高效随机数算法的示例代码

    前言 事情起源于一位网友分享了一个有趣的面试题: 生成由六位数字组成的ID,要求随机数字,不排重,不可自增,且数字不重复.ID总数为几十万. 初次解答 我一开始想到的办法是 生成一个足够大的ID池(其实就是需要多少就生成多少) 对ID池中的数字进行随机排序 依次消费ID池中的数字 可惜这个方法十分浪费空间,且性能很差. 初遇梅森旋转算法 后面咨询了网友后得知了一个高效的随机数算法:梅森旋转(Mersenne Twister/MT).通过搜索资料得知: 梅森旋转算法(Mersenne twiste

  • Python 实现大整数乘法算法的示例代码

    我们平时接触的长乘法,按位相乘,是一种时间复杂度为 O(n ^ 2) 的算法.今天,我们来介绍一种时间复杂度为 O (n ^ log 3) 的大整数乘法(log 表示以 2 为底的对数). 介绍原理 karatsuba 算法要求乘数与被乘数要满足以下几个条件,第一,乘数与被乘数的位数相同:第二,乘数与被乘数的位数应为  2 次幂,即为 2 ^ 2,  2 ^ 3, 2 ^ 4, 2 ^ n 等数值. 下面我们先来看几个简单的例子,并以此来了解 karatsuba 算法的使用方法. 两位数相乘 我

  • golang实现LRU缓存淘汰算法的示例代码

    LRU缓存淘汰算法 LRU是最近最少使用策略的缩写,是根据数据的历史访问记录来进行淘汰数据,其核心思想是"如果数据最近被访问过,那么将来被访问的几率也更高". 双向链表实现LRU 将Cache的所有位置都用双链表连接起来,当一个位置被访问(get/put)之后,通过调整链表的指向,将该位置调整到链表头的位置,新加入的Cache直接加到链表头中. 这样,在多次操作后,最近被访问(get/put)的,就会被向链表头方向移动,而没有访问的,向链表后方移动,链表尾则表示最近最少使用的Cache

随机推荐

其他