分享

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

 mscdj 2018-02-03

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

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

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

  1. <pre name="code" class="cpp">#include<iostream>  
  2. using namespace std;  
  3.   
  4. #include<opencv2\core\core.hpp>  
  5. #include<opencv2\highgui\highgui.hpp>  
  6. #include<opencv2\imgproc\imgproc.hpp>  
  7. using namespace cv;  
  8.   
  9. int main(int argc,char* argv[])  
  10. {  
  11.     Mat image,imageHsv,hist,normalHist;  
  12.     image = imread(argv[1],1);  
  13.     if(argc !=2 || !image.data)  
  14.     {  
  15.         cerr << " No image!" <<endl;  
  16.         return -1;  
  17.     }  
  18.     //颜色空间的转换  
  19.     cvtColor(image,imageHsv,CV_BGR2HSV);  
  20.   
  21.     //一维直方图  
  22.     int hbins = 90;  
  23.     int histSize[] = {hbins};  
  24.     float hranges[] = {0.0,180.0};  
  25.     const float* ranges[] = {hranges};  
  26.       
  27.     int channels[] ={0};  
  28.     calcHist(&imageHsv,1,channels,Mat(),hist,1,histSize,ranges,true,false);  
  29.     normalize(hist,normalHist,1,0,CV_L1,CV_32F);  
  30.   
  31.     Mat signature(hbins,2,CV_32FC1);  
  32.     normalHist.copyTo(signature.col(0));  
  33.   
  34.    //把直方图的bin的索引,作为signature的第二列  
  35.     for( int r=0;r < hbins; r++)  
  36.         signature.at<float>(r,1) =float(r);  
  37.     return 0;  
  38. }  



第二步:做检索

  1. <pre name="code" class="cpp">#include<iostream>  
  2. #include<fstream>  
  3. #include<map>  
  4. #include<string>  
  5. using namespace std;  
  6.   
  7. #include<opencv2\core\core.hpp>  
  8. #include<opencv2\highgui\highgui.hpp>  
  9. #include<opencv2\imgproc\imgproc.hpp>  
  10. using namespace cv;  
  11.   
  12. Mat signature(const Mat & src);  
  13. int main(int argc,char* argv[])  
  14. {  
  15.     //定义文件流,只能读取  
  16.     ifstream inPutFile(argv[1],ios::in);  
  17.     if(! inPutFile)  
  18.     {  
  19.         cerr <<"File Open Erro !"<<endl;  
  20.         return -1;  
  21.     }  
  22.   
  23.     //读取文件流中的每一行,并赋值给fileName,形成查询数据库  
  24.     string fileName;  
  25.     Mat image,imageSignature,sourceSignature;  
  26.     vector<Mat> signatures;  
  27.   
  28.     map<int,string> index;//图像的索引  
  29.     index.clear();  
  30.     int number = 0;  
  31.     signatures.clear();  
  32.     while(getline(inPutFile,fileName))  
  33.     {  
  34.         index.insert(pair<int,string>(number,fileName));  
  35.         number++;  
  36.         image = imread(fileName,1);  
  37.         imageSignature =  signature(image);  
  38.         signatures.push_back(imageSignature);  
  39.     }  
  40.   
  41.     //待搜索的图像  
  42.     number = 0;  
  43.     Mat imageSource = imread(argv[2],1);  
  44.     sourceSignature = signature(imageSource);  
  45.     vector<Mat>::iterator iter;  
  46.     map<float,int> distance;  
  47.     for(iter = signatures.begin();iter != signatures.end();iter ++)  
  48.     {  
  49.         distance.insert(pair<float,int>(EMD(sourceSignature,*iter,CV_DIST_L2,number),number));  
  50.         number ++;  
  51.     }  
  52.     //显示距离最小的前五名的检索图像  
  53.     number = 0;  
  54.     map<float,int>::iterator mapiter;  
  55.     for(mapiter = distance.begin();mapiter != distance.end() && number <5;mapiter++,number++)  
  56.     {  
  57.         string simage = index.find((*mapiter).second)->second;  
  58.         image = imread(simage,1);  
  59.         namedWindow(simage,1);  
  60.         imshow(simage,image);  
  61.     }  
  62.     waitKey(0);  
  63.     return 0;  
  64. }  
  65.   
  66. Mat signature(const Mat & src)  
  67. {  
  68.     Mat hsv,hist,normalHist;  
  69.     //颜色空间转换  
  70.     cvtColor(src,hsv,CV_BGR2HSV);  
  71.     //一维直方图  
  72.     int hbins = 90;  
  73.     int histSize[] = {hbins};  
  74.     float hranges[] = {0.0,180.0};  
  75.     const float* ranges[] = {hranges};  
  76.       
  77.     int channels[] ={0};  
  78.     calcHist(&hsv,1,channels,Mat(),hist,1,histSize,ranges,true,false);  
  79.     normalize(hist,normalHist,1,0,CV_L1,CV_32F);  
  80.   
  81.      Mat signature(hbins,2,CV_32FC1);;  
  82.     normalHist.copyTo(signature.col(0));  
  83.     //把直方图bin的索引,作为signature的第二列  
  84.     for( int r=0;r < hbins; r++)  
  85.         signature.at<float>(r,1) =float(r);  
  86.     return signature;  
  87. }  



检索数据库

检测图片:

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

结果:


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多