C++實(shí)現(xiàn)雙目立體匹配Census算法的示例代碼
上一篇介紹了雙目立體匹配SAD算法,這一篇介紹Census算法。
Census原理:
在視圖中選取任一點(diǎn),以該點(diǎn)為中心劃出一個(gè)例如3 × 3 的矩形,矩形中除中心點(diǎn)之外的每一點(diǎn)都與中心點(diǎn)進(jìn)行比較,灰度值小于中心點(diǎn)記為1,灰度大于中心點(diǎn)的則記為0,以所得長(zhǎng)度為 8 的只有 0 和 1 的序列作為該中心點(diǎn)的 census 序列,即中心像素的灰度值被census 序列替換。經(jīng)過census變換后的圖像使用漢明距離計(jì)算相似度,所謂圖像匹配就是在匹配圖像中找出與參考像素點(diǎn)相似度最高的點(diǎn),而漢明距正是匹配圖像像素與參考像素相似度的度量。具體而言,對(duì)于欲求取視差的左右視圖,要比較兩個(gè)視圖中兩點(diǎn)的相似度,可將此兩點(diǎn)的census值逐位進(jìn)行異或運(yùn)算,然后計(jì)算結(jié)果為1 的個(gè)數(shù),記為此兩點(diǎn)之間的漢明值,漢明值是兩點(diǎn)間相似度的一種體現(xiàn),漢明值愈小,兩點(diǎn)相似度愈大實(shí)現(xiàn)算法時(shí)先異或再統(tǒng)計(jì)1的個(gè)數(shù)即可,漢明距越小即相似度越高。

下面的代碼是自己根據(jù)原理寫的,實(shí)現(xiàn)的結(jié)果并沒有很好,以后繼續(xù)優(yōu)化代碼。
具體代碼如下:
//*************************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的個(gè)數(shù)
//-------------------定義Census處理圖像函數(shù)---------------------
int hWind = 1;//定義窗口大小為(2*hWind+1)
Mat ProcessImg(Mat &Img);//將矩形內(nèi)的像素與中心像素相比較,將結(jié)果存于中心像素中
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\\";
//定義存儲(chǔ)圖片的路徑
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;
}
//-----------------------對(duì)圖像進(jìn)行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))
{
//--------- 將二進(jìn)制數(shù)存在變量中-----
neighbor = Img.at<uchar>(p, q);
if (neighbor > center)
{
census = census * 2;//向左移一位,相當(dāng)于在二進(jìn)制后面增添0
}
else
{
census = census * 2 + 1;//向左移一位并加一,相當(dāng)于在二進(jìn)制后面增添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;
}
}
//---------------尋找最佳匹配點(diǎn)--------------
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;
}
//-------------對(duì)得到的視差圖進(jìn)行處理-------------------
Mat ProcessDisparity(Mat &disImg)
{
Mat ProcessDisImg(ImgHeight,ImgWidth,CV_8UC1);//存儲(chǔ)處理后視差圖
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;
}
經(jīng)過處理后的左圖census圖像

經(jīng)過處理后的右圖census圖像

disparity圖像

處理后的disparity圖像
以上就是C++實(shí)現(xiàn)雙目立體匹配Census算法的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于C++雙目立體匹配Census算法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
如何查看進(jìn)程實(shí)際的內(nèi)存占用情況詳解
本篇文章是對(duì)如何查看進(jìn)程實(shí)際的內(nèi)存占用情況進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C++實(shí)現(xiàn)含附件的郵件發(fā)送功能
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)含附件的郵件發(fā)送功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05
C++實(shí)現(xiàn)分?jǐn)?shù)計(jì)算器
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)分?jǐn)?shù)計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06
C語言實(shí)現(xiàn)簡(jiǎn)單三子棋小游戲
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)簡(jiǎn)單三子棋小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06
C語言詳細(xì)講解通過遞歸實(shí)現(xiàn)掃雷的展開
windows自帶的游戲《掃雷》是陪伴了無數(shù)人的經(jīng)典游戲,本文將利用C語言實(shí)現(xiàn)這一經(jīng)典的游戲,文中的示例代碼講解詳細(xì),感興趣的可以學(xué)習(xí)一下2022-05-05
C語言菜鳥基礎(chǔ)教程之?dāng)?shù)據(jù)類型
在 C 語言中,數(shù)據(jù)類型指的是用于聲明不同類型的變量或函數(shù)的一個(gè)廣泛的系統(tǒng)。變量的類型決定了變量存儲(chǔ)占用的空間,以及如何解釋存儲(chǔ)的位模式。2017-10-10
C++ OpenCV學(xué)習(xí)之圖像金字塔與圖像融合詳解
圖像金字塔分為兩種:高斯金字塔和拉普拉斯金字塔。圖像金字塔在保持細(xì)節(jié)的條件下進(jìn)行圖像融合等多尺度編輯操作非常有用。本文將利用圖像金字塔實(shí)現(xiàn)圖像融合,需要的可以參考一下2022-03-03

