enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 }
http://ggicci.blog.163.com/blog/static/210364096201261052543349/
理解二维直方图的读取:
理解三维直方图:
第一步:先计算Lab空间中的三维直方图,我这里L 、a、b分别为
下面首先给出CIE Lab空间中三维直方图(注:已经归一化,并归一化为double 型,即64F)
<pre name="code" class="cpp">#include<opencv2\highgui\highgui.hpp> #include<opencv2\imgproc\imgproc.hpp> #include<opencv2\core\core.hpp> using namespace cv; #include<iostream> using namespace std; Mat labHist(const Mat& src); int main (int argc, char*argv[]) { Mat image = imread(argv[1],1); Mat hist = labHist(image); cout<<sum(hist)<<endl; system("pause"); return 0; } Mat labHist(const Mat& src) { Mat lab(src); //颜色空间的转换 BGR2Lab //cvtColor(src,lab,CV_BGR2Lab); //L,a,b三个通道分别为 4,14,14bins int lbins = 4; int abins = 14; int bbins = 14; int histSize[] = { lbins , abins , bbins}; //L的取值范围 0-255 float lranges [ ] ={0,256}; //a的取值范围 float aranges [ ] ={0,256}; //b的取值范围 float branges [ ] ={0,256}; const float* ranges [ ]={lranges ,aranges , branges}; Mat hist3D,hist3dNormal; Mat hist =Mat(lbins*abins*bbins,1,CV_64FC1); const int channels [ ]={0,1,2}; calcHist(&lab,1,channels,Mat(),hist3D,3,histSize,ranges,true,false);//hist3D是32F //归一化,64F normalize(hist3D,hist3dNormal,1,0,CV_L1,CV_64F); //第二种方法取得三维直方图中的值 //double* p = (double*)hist3D.data; int row = 0; for(int l = 0; l < lbins; l++) { for(int a = 0;a < abins; a++) { for(int b = 0;b < bbins;b++) { hist.at<double>(row,0)=*((double*)(hist3dNormal.data+l*hist3dNormal.step[0]+a*hist3dNormal.step[1]+b*hist3dNormal.step[2])); //hist.at<double>(row,0) = *(p+row); row++; } } } return hist; }第二步,我们用卡方距离
//这里的hist1和hist2都是N行一列的数据,64F,double double chiSquareDist(const Mat & hist1,const Mat & hist2) { int rows = hist1.rows; double sum = 0.0; double d1,d2; for(int r = 0;r < rows ;r++) { d1 = hist1.at<double>(r,0); d2 = hist2.at<double>(r,0); if( d1 ==0 && d2 == 0) ; else sum += 0.5*pow( d1 - d2,2)/(d1+d2); } return sum; }第三步:建立索引数据库,图像检索
#include<opencv2\highgui\highgui.hpp> #include<opencv2\imgproc\imgproc.hpp> #include<opencv2\core\core.hpp> using namespace cv; #include<fstream> #include<iostream> using namespace std; Mat labHist(const Mat& src); double chiSquareDist(const Mat & hist1,const Mat & hist2); 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 = labHist(image); histograms.push_back(histogram); } //待搜索的图像 number = 0; Mat imageSource = imread(argv[2],1); sourceHisrogram = labHist(imageSource); vector<Mat>::iterator iter; map<double,int>distance; for(iter = histograms.begin();iter != histograms.end();iter++) { distance.insert(pair<double,int>(chiSquareDist(sourceHisrogram,*iter),number)); number++; } //显示距离最小的前五名的检索图像 number = 0; map<double,int>::iterator mapiter; for(mapiter = distance.begin();mapiter != distance.end() && number <5;mapiter++,number++) { string simage = index.find((*mapiter).second) ->second; image = imread(simage,1); namedWindow(simage,1); imshow(simage,image); } waitKey(0); } Mat labHist(const Mat& src) { Mat lab(src); //颜色空间的转换 BGR2Lab //cvtColor(src,lab,CV_BGR2Lab); //L,a,b三个通道分别为 4,14,14bins int lbins = 4; int abins = 14; int bbins = 14; int histSize[] = { lbins , abins , bbins}; //L的取值范围 0-255 float lranges [ ] ={0,256}; //a的取值范围 float aranges [ ] ={0,256}; //b的取值范围 float branges [ ] ={0,256}; const float* ranges [ ]={lranges ,aranges , branges}; Mat hist3D,hist3dNormal; Mat hist =Mat(lbins*abins*bbins,1,CV_64FC1); const int channels [ ]={0,1,2}; calcHist(&lab,1,channels,Mat(),hist3D,3,histSize,ranges,true,false);//hist3D是32F //归一化,64F normalize(hist3D,hist3dNormal,1,0,CV_L1,CV_64F); //第二种方法取得三维直方图中的值 //double* p = (double*)hist3D.data; int row = 0; for(int l = 0; l < lbins; l++) { for(int a = 0;a < abins; a++) { for(int b = 0;b < bbins;b++) { hist.at<double>(row,0)=*((double*)(hist3dNormal.data+l*hist3dNormal.step[0]+a*hist3dNormal.step[1]+b*hist3dNormal.step[2])); //hist.at<double>(row,0) = *(p+row); row++; } } } return hist; } //这里的hist1和hist2都是N行一列的数据,64F,double double chiSquareDist(const Mat & hist1,const Mat & hist2) { int rows = hist1.rows; double sum = 0.0; double d1,d2; for(int r = 0;r < rows ;r++) { d1 = hist1.at<double>(r,0); d2 = hist2.at<double>(r,0); if( d1 ==0 && d2 == 0) ; else sum += 0.5*pow( d1 - d2,2)/(d1+d2); } return sum; }示例:
例子一: