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

本文介绍了一种使用OpenCV库实现的图像特征提取、匹配及基于距离的图像检索方法。通过读取文件中指定路径的图像,计算其特征向量,并将这些向量作为数据库存储。然后,通过计算待检索图像与数据库中图像之间的距离,找到最相似的图像。此过程展示了如何在计算机视觉应用中高效地进行图像识别。
#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 <1;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,histCol;
	//颜色空间转换
	cvtColor(src,hsv,CV_BGR2HSV);
	//二维直方图
	int hbins = 30;
	int sbins  = 16;
	int histSize[] = {hbins,sbins};
	float hranges[] = {0.0,180.0};
	float sranges[] = {0.0,256.0};
	const float* ranges[] = {hranges,sranges};
	
	int channels[] ={0,1};
	calcHist(&hsv,1,channels,Mat(),hist,2,histSize,ranges,true,false);
	//把直方图特征按一列来存储
	int rows = hbins*sbins;
	histCol = hist.reshape(1,rows);
	//把直方图归一化
	normalize(histCol,normalHist,1000,0,CV_L1,CV_32F);

	Mat signature(hbins*sbins,3,CV_32FC1);
	normalHist.copyTo(signature.col(0));

	//我们把bin的索引放在signature的第二列和第三列
	for(int h =0 ;h<hbins;h++)
	{
		Mat roi(signature,Rect(1,h*sbins,2,sbins));
		for(int s= 0;s<sbins;s++)
		{
			roi.at<float>(s,0) = float(h);
			roi.at<float>(s,1) =float(s);
		}
	}
		return signature;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值