一种基于特征点匹配的图像检索方法的opencv实现

来源:互联网 发布:随机森林优化 编辑:程序博客网 时间:2024/05/17 20:15

由于最初这个方法是用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.001struct 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

0 0