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

图像检索:一维直方图+EMD距离

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

EMD距离详细介绍已经在在这里已经给出。

思路:我们把一张图像的归一化的一维直方图作为signature的权值,也就是一般在比较两幅图像颜色直方图的EMD距离时,每一行的坐标一样,只是权重值不一样。

通过以下程序,就可以得到一幅图像的signature:

<pre name="code" class="cpp">#include<iostream>
using namespace std;

#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
using namespace cv;

int main(int argc,char* argv[])
{
	Mat image,imageHsv,hist,normalHist;
	image = imread(argv[1],1);
	if(argc !=2 || !image.data)
	{
		cerr << " No image!" <<endl;
		return -1;
	}
	//颜色空间的转换
	cvtColor(image,imageHsv,CV_BGR2HSV);

	//一维直方图
	int hbins = 90;
	int histSize[] = {hbins};
	float hranges[] = {0.0,180.0};
	const float* ranges[] = {hranges};
	
	int channels[] ={0};
	calcHist(&imageHsv,1,channels,Mat(),hist,1,histSize,ranges,true,false);
	normalize(hist,normalHist,1,0,CV_L1,CV_32F);

	Mat signature(hbins,2,CV_32FC1);
	normalHist.copyTo(signature.col(0));

   //把直方图的bin的索引,作为signature的第二列
	for( int r=0;r < hbins; r++)
		signature.at<float>(r,1) =float(r);
	return 0;
}

第二步:做检索

<pre name="code" class="cpp">#include<iostream>
#include<fstream>
#include<map>
#include<string>
using namespace std;

#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
using namespace cv;

Mat signature(const Mat & src);
int main(int argc,char* argv[])
{
	//定义文件流,只能读取
	ifstream inPutFile(argv[1],ios::in);
	if(! inPutFile)
	{
		cerr <<"File Open Erro !"<<endl;
		return -1;
	}

	//读取文件流中的每一行,并赋值给fileName,形成查询数据库
	string fileName;
	Mat image,imageSignature,sourceSignature;
	vector<Mat> signatures;

	map<int,string> index;//图像的索引
	index.clear();
	int number = 0;
	signatures.clear();
	while(getline(inPutFile,fileName))
	{
		index.insert(pair<int,string>(number,fileName));
		number++;
		image = imread(fileName,1);
        imageSignature =  signature(image);
		signatures.push_back(imageSignature);
	}

	//待搜索的图像
	number = 0;
	Mat imageSource = imread(argv[2],1);
	sourceSignature = signature(imageSource);
	vector<Mat>::iterator iter;
	map<float,int> distance;
	for(iter = signatures.begin();iter != signatures.end();iter ++)
	{
		distance.insert(pair<float,int>(EMD(sourceSignature,*iter,CV_DIST_L2,number),number));
		number ++;
	}
	//显示距离最小的前五名的检索图像
	number = 0;
	map<float,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);
	return 0;
}

Mat signature(const Mat & src)
{
	Mat hsv,hist,normalHist;
	//颜色空间转换
	cvtColor(src,hsv,CV_BGR2HSV);
	//一维直方图
	int hbins = 90;
	int histSize[] = {hbins};
	float hranges[] = {0.0,180.0};
	const float* ranges[] = {hranges};
	
	int channels[] ={0};
	calcHist(&hsv,1,channels,Mat(),hist,1,histSize,ranges,true,false);
	normalize(hist,normalHist,1,0,CV_L1,CV_32F);

	 Mat signature(hbins,2,CV_32FC1);;
	normalHist.copyTo(signature.col(0));
	//把直方图bin的索引,作为signature的第二列
	for( int r=0;r < hbins; r++)
		signature.at<float>(r,1) =float(r);
	return signature;
}

检索数据库

检测图片:

我们选取y2作为检测图片:

结果:


抱歉!评论已关闭.