现在的位置: 首页 > 综合 > 正文

图像检索:CIE Lab三维直方图+卡方距离

2018年04月11日 ⁄ 综合 ⁄ 共 4138字 ⁄ 字号 评论关闭

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;
}

示例:


例子一:


抱歉!评论已关闭.