图像检索:二维直方图+flann+KNN+欧几里得距离


第一步:批处理提取图像库的二维直方图,并存在到.xml中的featureHists中

第一个参数:图像的路径 目录.txt

第二个参数:图像特征   features.xml

[保存到features.xml中featureHists]

#include<iostream>
#include<fstream>
#include<string>
using namespace std;

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

//计算二维直方图特征
Mat hist2d(const Mat& src);

int main(int argc,char* argv[])
{
  if(argc !=3)
  {
    cerr << "Wrong Argument !" <<endl;
    return -1;
  }
  //定义文件流,只能读取
  ifstream inPutFile(argv[1],ios::in);
  if(! inPutFile)
  {
    cerr << "File Open Erro !" <<endl;
    return -1;
  }
  //读取文件流中的每一行,并赋值给fileName,读取每一幅图像
  string fileName ;
  Mat image;
  Mat featureHist;
  Mat featureHists;
  while (getline(inPutFile,fileName))
  {
    
    image = imread(fileName,1);
    //计算二维直方图特征
    featureHist = hist2d(image);
    //按行存储每一幅图像的二维直方图特征
    featureHists.push_back(featureHist);
  }
  //注意一定要记得关闭文件流
  inPutFile.close();

  /*第五步,把图像特征保存到.xml文件中*/
  FileStorage fs(argv[2],FileStorage::WRITE);
  fs<<"featureHists"<<featureHists;
  fs.release();
  
  return 0;
}

Mat hist2d(const Mat& src)
{
  Mat hsv;

  //颜色空间的转换 BGR2HSV
  cvtColor(src,hsv,CV_BGR2HSV);

  //把H通道分为30个bin,把S通道分为32bin
  int hbins = 30;
  int sbins = 32;
  int histSize[] = { hbins , sbins};

  //H的取值范围 0-179
  float hranges[]= {0,180};
  //S的取值范围 0-255
  float sranges [] ={0,256};
  const float* ranges [] ={hranges,sranges};

  Mat hist2D,histRow,histRowDst;
  //我们根据图像的第一通道和第二通道,计算二维直方图,而且输出的hist2D为32F
  int channels [] ={0,1};
  calcHist(&hsv,1,channels,Mat(),hist2D,2,histSize,ranges,true,false);
  //把直方图特征按一行来存储
  histRow=hist2D.reshape(1,1);

  //把直方图归一化
  normalize(histRow,histRowDst,1,0,NORM_L1);

  return histRowDst;
}
第二步:提取查询图像的二维直方图特征,并保存到.xml中

第一个参数:查询图像的路径

第二个参数:保存查询图像特征的.xml的路径

第三个参数:特征的名字

#include<iostream>
#include<string>
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 src = imread(argv[1],1);
  if(! src.data)
  {
    cout <<"No Image" << endl;
    return -1;
  }
    
  Mat hsv;
  //颜色空间的转换BGR2HSV
  cvtColor(src,hsv,CV_BGR2HSV);

  //把H通道分为60个bin,S通道分为32个bin(可以修改)
  int hbins = 60;
  int sbins = 32;
  int histSize[] = { hbins ,sbins};

  //H的取值范围 0-179
  float hranges[]= {0,180};
  //S的取值范围 0-255
  float sranges[] = {0,256};

  const float* ranges [] ={hranges,sranges};
  Mat hist2D,histRow,histRowDst;
  //我们根据图像的第一和第二个通道,计算二维直方图,而且输出的hist2D为32F
  int channels [] ={0,1};
  calcHist(&hsv,1,channels,Mat(),hist2D,2,histSize,ranges,true,false);
  //把直方图特征按一行来存储
  histRow=hist2D.reshape(1,1);

  //把直方图归一化
  normalize(histRow,histRowDst,1,0,NORM_L1);
  FileStorage fs(argv[2],FileStorage::WRITE);
  //把histRowDst保存到.xml文件中
  fs << argv[3] << histRowDst;
  fs.release(); 
  return 0;
}

第三步:从图像库中用K-最近邻算法中,查找和查询图像相似的图片

#include<iostream>
using namespace std;

#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\flann\flann.hpp>
using namespace cv;
int main(int argc,char* argv[])
{
  FileStorage dataBase(argv[1],FileStorage::READ);
  Mat features;
  dataBase["featureHists"]>>features;
  dataBase.release();
  FileStorage queryImage(argv[2],FileStorage::READ);
  Mat queryFeature;
  queryImage[argv[3]]>>queryFeature;
  queryImage.release();
  flann::Index fl(features,flann::KDTreeIndexParams(4));
  Mat index,distance;
  fl.knnSearch(queryFeature,index,distance,1);
  queryImage.release();
  return 0;
}

因为工作的需要把三部分分开了。

你可能感兴趣的:(图像检索:二维直方图+flann+KNN+欧几里得距离)