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;
}示例:
例子一:
本文介绍如何使用CIELab颜色空间构建三维直方图,并通过卡方距离进行图像相似度比较,实现图像检索应用。具体步骤包括颜色空间转换、直方图计算与归一化、卡方距离计算及建立图像索引数据库。
3698

被折叠的 条评论
为什么被折叠?



