1. 程式人生 > >影象檢索:二維直方圖+flann+KNN+歐幾里得距離

影象檢索:二維直方圖+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;
}

因為工作的需要把三部分分開了。