由於最初這個方法是用qt界面的形式呈現了,沒有平常見到的main函數執行圖像檢索的那樣,我稍微做了下整理,提供出一個c++接口interface()可供調用。註釋還比較少,後面有時間補上。
#ifndef IMAGERETRIVAL
#define IMAGERETRIVAL
//#include <cxcore.h>
#include <opencv2\features2d\features2d.hpp>
#include <opencv2\calib3d\calib3d.hpp>
#include <opencv2\contrib\contrib.hpp>
#include <opencv2/nonfree/nonfree.hpp>
#include <highgui.h>
#include <iostream>
#include <map>
#include <io.h>
using namespace std ;
using namespace cv;
#define HessianThreshold 400
#define MAX_Image_Num 1000
#define MIN_Image_Similar_Threshold 0.001
struct matDescToImgfile{
int i_begin_index ;
int i_end_index ;
string s_imge_filename ;
};
const string trainFileType = "jpg"; // "*" represent any file type.
//////////////////////////////////////////////////////////////////////////
//從目錄中讀取文件名列表
int readDirFile(const string dirName, const string fileType , vector<string> &allFilename)
{
int fileNum = 0 ;
_finddata_t onefile ;
long lFile ;
string dirName_FileType = dirName + "\\*."+fileType;
lFile = _findfirst(dirName_FileType.c_str() , &onefile) ;
if (lFile == -1l ) //on such file, return -1l (long type)
{
cout << "can`t find the file"<<endl;
return fileNum ;
}
else
{
//cout <<"the files of the folder:"<<endl ;
do
{
//cout<<onefile.name <<endl ;
allFilename.push_back(onefile.name) ;
fileNum ++ ;
} while (_findnext(lFile , &onefile) == 0);
}
_findclose(lFile) ;
return fileNum ;
}
//////////////////////////////////////////////////////////////////////////
void createDetectorDescriptor(const string trainDirName,vector<string> trainAllFileName,
Mat& matTotalDesc, vector<matDescToImgfile>& vec_Desc_Imgfile)
{
//創建特徵點提取器
cv::SurfFeatureDetector* m_pDector = new cv::SurfFeatureDetector(HessianThreshold); //HessianThreshold
SurfDescriptorExtractor* m_pExtractor = new SurfDescriptorExtractor;
//讀取train中圖片
//提取特徵點及描述符
//描述符提取
Mat ImgMat ;
vector<KeyPoint> veckps;
Mat matDesc;
matDescToImgfile one_img_log ;
int img_num = 0 ;
vector<string>::iterator imageName ;
for (imageName = trainAllFileName.begin() ; imageName != trainAllFileName.end() ; imageName++)
{
veckps.clear();
matDesc.release();
ImgMat.release();
//cout<<trainDirName+"\\"+*imageName <<endl ;
ImgMat = imread(trainDirName+"\\"+*imageName,CV_LOAD_IMAGE_ANYCOLOR) ; //CV_LOAD_IMAGE_ANYDEPTH
m_pDector->detect(ImgMat,veckps);
if(veckps.size() == 0)
{
return ;
}
m_pExtractor->compute(ImgMat,veckps,matDesc);
matTotalDesc.push_back(matDesc) ;//集中所有matDesc形成matTotalDesc
if (img_num == 0)
{
one_img_log.i_begin_index = 0 ;
one_img_log.i_end_index = matDesc.rows-1 ;
one_img_log.s_imge_filename = trainDirName+"\\"+*imageName ;
}
else {
one_img_log.i_begin_index = one_img_log.i_end_index + 1;
one_img_log.i_end_index = one_img_log.i_begin_index + matDesc.rows-1 ;
one_img_log.s_imge_filename = trainDirName+"\\"+*imageName ;
}
img_num++;
vec_Desc_Imgfile.push_back(one_img_log) ;
}
delete(m_pDector);
delete(m_pExtractor);
}
vector<string> GetImageFromKNN(vector<matDescToImgfile> Desc_Imgfile ,cv::Mat Indices ,
const int Img_Num ,const double Max_Threshold,int rankNum)
{
int flag_count[200] ={0};
//cout << "Img_Num=" << Img_Num << endl;
vector<matDescToImgfile>::iterator oneDescLog ;
MatIterator_ <int> it_indice ;
int key ;
for (it_indice = Indices.begin<int>() ; it_indice!= Indices.end<int>() ; it_indice++)
{
key = *it_indice ;
int i = 0 ;
for (oneDescLog = Desc_Imgfile.begin() ; oneDescLog!=Desc_Imgfile.end(); oneDescLog++ , i ++)
{
if (key >= oneDescLog->i_begin_index && key <= oneDescLog->i_end_index)
{
flag_count[i] ++ ;//flag ++
break;
}
}
}//找到indices中相似描述符屬於哪個區間
multimap<int,int> result;
for(int j=0;j<Img_Num;j++){
result.insert(make_pair(flag_count[j],j));
//result[flag_count[j]] = j;
}
float max_flag = 0 ;
int count_num =-1;
vector<int> index;
vector<string> resultStr;
for (multimap<int, int>::reverse_iterator iter = result.rbegin();iter != result.rend();++iter){
index.push_back(iter->second);
}
assert(rankNum <= Img_Num);
for (int i=0;i<rankNum;i++){
resultStr.push_back(Desc_Imgfile.at(index[i]).s_imge_filename);
//cout << Desc_Imgfile.at(index[i]).s_imge_filename << endl;
}
return resultStr;
/*for (int j = 0 ; j < Img_Num ; j++ )
{
if (max_flag < flag_count[j]/float (Indices.rows))
{
max_flag = flag_count[j]/float (Indices.rows) ;
count_num = j ;
}
}
//cout<<"max similarity ratio \t"<<max_flag<<endl;
if (max_flag > Max_Threshold)
{
return Desc_Imgfile.at(count_num).s_imge_filename ;
}
else
return "";*/
}
//////////////////////////////////////////////////////////////////////////
vector<string> OneImageRetrival(cv::flann::Index& m_index, const string query_image_name ,
vector<matDescToImgfile>& vec_Desc_Imgfile,int kNum)
{
//創建特徵點提取器
SurfFeatureDetector* m_pDector = new SurfFeatureDetector(HessianThreshold); //HessianThreshold
SurfDescriptorExtractor* m_pExtractor = new SurfDescriptorExtractor;
Mat QueryMat ;
vector<KeyPoint> QueryVecKP ;
Mat QueryMatDesc ;
QueryMat = imread(query_image_name,CV_LOAD_IMAGE_ANYCOLOR);
//QueryMat.resize(256,256);
m_pDector->detect(QueryMat,QueryVecKP);
m_pExtractor->compute(QueryMat,QueryVecKP,QueryMatDesc);
cv::Mat indices(QueryMatDesc.rows, 1, CV_32S);
cv::Mat dists(QueryMatDesc.rows , 1, CV_32F);
m_index.knnSearch(QueryMatDesc, indices, dists, 10, cv::flann::SearchParams(512) );
vector<string> s_the_result_filename = GetImageFromKNN(vec_Desc_Imgfile , indices , vec_Desc_Imgfile.size() ,MIN_Image_Similar_Threshold,kNum) ;
delete(m_pDector);
delete(m_pExtractor);
return s_the_result_filename;
}
//////////////////////////////////////////////////////////////////////////
//filename是想要檢索的那個圖片的包括絕對路徑的名字,trainDirName是檢索圖像庫的絕對路徑,kNum是想要檢索前多少個相似的圖片,這個值一定要小於圖片的數量
vector<string> interface(string filename,string trainDirName,int kNum)
{
//////////////////////////////////////////////////////////////////////////
//cout<<"\n###step 1 --read the train file :"<<endl ;
vector<string> trainAllFileName ;
int readFileStatus = readDirFile(trainDirName , trainFileType,trainAllFileName) ;
//////////////////////////////////////////////////////////////////////////
Mat matTotalDesc ;
vector<matDescToImgfile> vec_Desc_Imgfile ;
createDetectorDescriptor(trainDirName,trainAllFileName , matTotalDesc ,vec_Desc_Imgfile) ;
//建立隨機kd-tree
cv::flann::Index m_index(matTotalDesc, cv::flann::KDTreeIndexParams(4));
vector<string> resultFIlename = OneImageRetrival(m_index, filename , vec_Desc_Imgfile,kNum) ;
return resultFIlename;
}
#endif // IMAGERETRIVAL
效果展示如下圖所示:
轉載請註明地址:http://blog.csdn.net/xbcreal/article/details/70313907