RGBHistogram:
分别计算把彩色图像的三个通道R、G、B的一维直方图,然后把这三个通道的颜色直方图结合起来,就是颜色的描述子RGBHistogram。
下面给出计算RGBHistogram的代码:
<span style="font-family:Microsoft YaHei;font-size:18px;">#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> using namespace std; using namespace cv; const int HISTSIZE = 8; int main( int, char** argv ) { Mat src, dst; /// Load image src = imread( argv[1], 1 ); if( !src.data || (src.channels() !=3)) { return -1; } Mat rgbFeature = bgrHistogram(src); return 0; } Mat bgrHistogram(const Mat& src) { //分离B、G、R通道 vector<Mat> bgr_planes; split(src,bgr_planes); float range[] = { 0, 256 } ; const float* histRange = { range }; bool uniform = true; bool accumulate = false; Mat hist1d,normHist1d,hist; for(int i = 0 ;i < 3;i++) { calcHist( &bgr_planes[i], 1, 0, Mat(), hist1d, 1, &HISTSIZE, &histRange, uniform, accumulate ); normalize(hist1d,hist1d,1.0,0.0,CV_L1); hist.push_back(hist1d); } return hist; } </span>
第二步:颜色描述子已经计算出,选取什么样的距离。
对于距离我们先选取两种:
第一种:欧几里得距离
#include<iostream> #include <fstream> #include <stdio.h> using namespace std; #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" using namespace cv; const int HISTSIZE = 16; Mat bgrHistogram(const Mat& src); double euclideanDistance(const Mat & src1,const Mat &src2); int main( int, char** argv ) { //定义文件流,只能读取 ifstream inPutFile(argv[1],ios::in); if(! inPutFile) { cerr << "File Open Erro !"<<endl; return -1; } //读取文件流中的每一行,并赋值给fileName,形成查询数据库 string fileName ; Mat image,histogram,sourceHisrogram; vector<Mat> histograms; map<int,string>index;//图像的索引 index.clear(); int number = 0; histograms.clear(); while(getline(inPutFile,fileName)) { index.insert(pair<int,string>(number,fileName)); number++; image = imread(fileName,1); histogram = bgrHistogram(image); histograms.push_back(histogram); } //待搜索的图像 number = 0; Mat imageSource = imread(argv[2],1); sourceHisrogram = bgrHistogram(imageSource); vector<Mat>::iterator iter; map<double,int>distance; for(iter = histograms.begin();iter != histograms.end();iter++) { distance.insert(pair<double,int>(euclideanDistance(sourceHisrogram,*iter),number)); number++; } //显示距离最小的前五名的检索图像 number = 0; map<double,int>::iterator mapiter; for(mapiter = distance.begin();mapiter != distance.end() && number <2;mapiter++,number++) { string simage = index.find((*mapiter).second) ->second; image = imread(simage,1); namedWindow(simage,1); imshow(simage,image); } waitKey(0); } Mat bgrHistogram(const Mat& src) { //分离B、G、R通道 vector<Mat> bgr_planes; split(src,bgr_planes); float range[] = { 0, 256 } ; const float* histRange = { range }; bool uniform = true; bool accumulate = false; Mat hist1d,normHist1d,hist; for(int i = 0 ;i < 3;i++) { calcHist( &bgr_planes[i], 1, 0, Mat(), hist1d, 1, &HISTSIZE, &histRange, uniform, accumulate ); normalize(hist1d,hist1d,1.0,0.0,CV_L1); hist.push_back(hist1d); } return hist; } double euclideanDistance(const Mat & src1,const Mat &src2) { Mat pow2; pow(src1-src2,2.0,pow2); return sqrt(sum(pow2)[0]); }
搜索数据库
运行结果:
第二种:卡方距离
#include<iostream> #include <fstream> #include <stdio.h> using namespace std; #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" using namespace cv; const int HISTSIZE = 16; Mat bgrHistogram(const Mat& src); int main( int, char** argv ) { //定义文件流,只能读取 ifstream inPutFile(argv[1],ios::in); if(! inPutFile) { cerr << "File Open Erro !"<<endl; return -1; } //读取文件流中的每一行,并赋值给fileName,形成查询数据库 string fileName ; Mat image,histogram,sourceHisrogram; vector<Mat> histograms; map<int,string>index;//图像的索引 index.clear(); int number = 0; histograms.clear(); while(getline(inPutFile,fileName)) { index.insert(pair<int,string>(number,fileName)); number++; image = imread(fileName,1); histogram = bgrHistogram(image); histograms.push_back(histogram); } //待搜索的图像 number = 0; Mat imageSource = imread(argv[2],1); sourceHisrogram = bgrHistogram(imageSource); vector<Mat>::iterator iter; map<double,int>distance; for(iter = histograms.begin();iter != histograms.end();iter++) { distance.insert(pair<double,int>(compareHist(sourceHisrogram,*iter,CV_COMP_CHISQR),number)); number++; } //显示距离最小的前五名的检索图像 number = 0; map<double,int>::iterator mapiter; for(mapiter = distance.begin();mapiter != distance.end() && number <2;mapiter++,number++) { string simage = index.find((*mapiter).second) ->second; image = imread(simage,1); namedWindow(simage,1); imshow(simage,image); } waitKey(0); } Mat bgrHistogram(const Mat& src) { //分离B、G、R通道 vector<Mat> bgr_planes; split(src,bgr_planes); float range[] = { 0, 256 } ; const float* histRange = { range }; bool uniform = true; bool accumulate = false; Mat hist1d,normHist1d,hist; for(int i = 0 ;i < 3;i++) { calcHist( &bgr_planes[i], 1, 0, Mat(), hist1d, 1, &HISTSIZE, &histRange, uniform, accumulate ); normalize(hist1d,hist1d,1.0,0.0,CV_L1); hist.push_back(hist1d); } return hist; }搜索图片数据库
运行结果:(我只提取前两副距离最近的图片)