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;
- }
检索数据库
![](http://image109.360doc.com/DownloadImg/2018/02/0321/123845928_1_20180203091944487)
检测图片:
![](http://image109.360doc.com/DownloadImg/2018/02/0321/123845928_2_20180203091945550)
我们选取y2作为检测图片:
![](http://image109.360doc.com/DownloadImg/2018/02/0321/123845928_3_20180203091945909)
结果:
![](http://image109.360doc.com/DownloadImg/2018/02/0321/123845928_4_20180203091946268)
|