c++图像检索(coarse to fine)

  //SLAM 相关,需要用到,于是写了一个...这里只实现了course==,不过想达到fine,也是分分钟可以实现的,哈哈
1
#include <opencv2/core/core.hpp> 2 #include <opencv2/imgproc/imgproc.hpp> 3 #include <opencv2/highgui/highgui.hpp> 4 #include <iostream> 5 #include <cassert> 6 #include <stdlib.h> 7 #include <vector> 8 #include <string> 9 #include <iomanip> 10 #include <algorithm> 11 #include <queue> 12 #include <memory> 13 14 using namespace cv; 15 using namespace std; 16 17 class ColorHistogram 18 { 19 private: 20 int histSize[3]; 21 float hranges[2]; 22 const float* ranges[3]; 23 int channels[3]; 24 Mat reduce; 25 public: 26 27 //构造函数 28 ColorHistogram() 29 { 30 histSize[0]= histSize[1]= histSize[2]= 64; 31 hranges[0] = 0.0; 32 hranges[1] = 255.0; 33 ranges[0] = hranges; 34 ranges[1] = hranges; 35 ranges[2] = hranges; 36 channels[0] = 0; 37 channels[1] = 1; 38 channels[2] = 2; 39 } 40 41 //计算彩色图像直方图 42 Mat getHistogram(const Mat& image) 43 { 44 Mat hist; 45 46 //BGR直方图 47 hranges[0]= 0.0; 48 hranges[1]= 255.0; 49 channels[0]= 0; 50 channels[1]= 1; 51 channels[2]= 2; 52 53 //计算 54 calcHist(&image,1,channels,Mat(),hist,3,histSize,ranges); 55 return hist; 56 } 57 58 //计算颜色的直方图 59 Mat getHueHistogram(const Mat &image) 60 { 61 Mat hist; 62 Mat hue; 63 //转换到HSV空间 64 cvtColor(image,hue,CV_BGR2HSV); 65 66 //设置1维直方图使用的参数 67 hranges[0] = 0.0; 68 hranges[1] = 180.0; 69 channels[0] = 0; 70 //计算直方图 71 calcHist(&hue,1,channels,Mat(),hist,1,histSize,ranges); 72 return hist; 73 74 } 75 76 //减少颜色 77 Mat colorReduce(const Mat &image,int div = 64) 78 { 79 int n = static_cast<int>(log(static_cast<double>(div))/log(2.0)); 80 uchar mask = 0xFF<<n; 81 Mat_<Vec3b>::const_iterator it = image.begin<Vec3b>(); 82 Mat_<Vec3b>::const_iterator itend = image.end<Vec3b>(); 83 //设置输出图像 84 Mat result(image.rows,image.cols,image.type()); 85 Mat_<Vec3b>::iterator itr = result.begin<Vec3b>(); 86 for(;it != itend;++it,++itr) 87 { 88 (*itr)[0] = ((*it)[0]&mask) + div/2; 89 (*itr)[1] = ((*it)[1]&mask) + div/2; 90 (*itr)[2] = ((*it)[2]&mask) + div/2; 91 } 92 return result; 93 } 94 Mat getReduceHistogram(const Mat& image){ 95 96 reduce = colorReduce(image,32); 97 return getHistogram(reduce); 98 } 99 100 101 }; 102 103 104 class ImageComparator 105 { 106 private: 107 Mat reference; 108 Mat input; 109 Mat refH; 110 Mat inputH; 111 112 ColorHistogram hist; 113 int div; 114 public: 115 ImageComparator():div(32){} 116 117 void setColorReducation(int factor) 118 { 119 div = factor; 120 } 121 122 int getColorReduction() 123 { 124 return div; 125 } 126 127 void setRefrenceImage(const Mat &image) 128 { 129 reference = hist.colorReduce(image,div); 130 refH = hist.getHistogram(reference); 131 132 } 133 void setRefrenceHist(const Mat &hist1) 134 { 135 136 refH = hist1; 137 138 } 139 double compare(const Mat &image) 140 { 141 input = hist.colorReduce(image,div); 142 inputH = hist.getHistogram(input); 143 return compareHist(refH,inputH,CV_COMP_INTERSECT); 144 } 145 double comparehist(const Mat &inputH){ 146 147 return compareHist(refH,inputH,CV_COMP_INTERSECT); 148 } 149 150 }; 151 struct Node { 152 double value; 153 int idx; 154 Node (double v, int i): value(v), idx(i) {} 155 friend bool operator > (const struct Node &n1, const struct Node &n2) { 156 return n1.value > n2.value; 157 } 158 }; 159 160 161 162 class Getsimilarsulotin{ 163 public: 164 //KF的集合 165 vector<Mat>& _scenebase; 166 //待查询图片 167 Mat _referenceMat; 168 //结果 169 vector<pair<vector<pair<Mat,int>>,double> > res_hist_and_id_of_pic_and_scores; 170 //需要的分数最大的类的个数 171 //int _Nclass; 172 //每个可能图片的分数 173 vector<vector<double> > imgsscores; 174 //图像比较的对像 175 shared_ptr<ImageComparator> imgcompare=make_shared<ImageComparator>(); 176 public: 177 Getsimilarsulotin(vector<Mat>& scenebase,Mat & referenceMat):_scenebase(scenebase){ 178 _referenceMat=referenceMat.clone(); 179 imgcompare->setRefrenceImage(_referenceMat); 180 } 181 182 /* 183 * 输入:scenebase是一个vector,里面放的是KF的hist 184 * Ncalss最终几个输出分数最大的类 185 * referenceMat是带查询的图片 186 * 输出:res_hist_and_id_of_pic_and_scores是输出(分数越小的在越后面) 187 * 其中每个元素是一个pair<类,类的分数> 188 * 类是一个一维的数组,每个元素是一个pair<hist,index> 189 * 这里index的产生是由scenebase的顺序决定的 190 */ 191 void getMostsimilar( ) 192 { 193 194 const int nImages=_scenebase.size(); 195 cout<<"start clustering..."<<endl; 196 //存放类的用二维vector存放聚类结果 197 vector<vector<pair<Mat,int>> > resofclu; 198 199 200 int startid=0; 201 vector<pair<Mat,int>> clutemp; 202 while(startid<nImages){ 203 clutemp.clear(); 204 205 Mat referenceM=_scenebase[startid]; 206 clutemp.push_back(make_pair(referenceM,startid)); 207 208 int iterid=startid+1; 209 if (iterid>=nImages){ 210 break; 211 } 212 ImageComparator* imgcompare=new(ImageComparator); 213 imgcompare->setRefrenceHist(referenceM); 214 for (;iterid<nImages;iterid++){ 215 216 if(imgcompare->comparehist(_scenebase[iterid])>0.7*imgcompare->comparehist(_scenebase[startid])){ 217 clutemp.push_back(make_pair(_scenebase[iterid],iterid)); 218 } 219 else{ 220 break; 221 } 222 } 223 resofclu.push_back(clutemp); 224 cout<<"the class has "<<clutemp.size()<<" elements"<<endl; 225 startid=iterid; 226 delete imgcompare; 227 } 228 cout<<"Done! we get "<<resofclu.size()<<" classes"<<endl; 229 230 cout<<"then we average of classes"<<endl; 231 232 233 //用于存放类的中心 234 vector<Mat> meanRes; 235 const int nclass=resofclu.size(); 236 // meanRes.resize(nclass); 237 //int iii=0; 238 for(auto resclass:resofclu){ 239 Mat Matmean=resofclu[0][0].first.clone(); 240 Matmean=Matmean*0.0; 241 for(auto sMat:resclass){ 242 Matmean=Matmean+sMat.first; 243 } 244 Matmean=Matmean+0.001; 245 Matmean=Matmean*(1.0/double(resclass.size())); 246 meanRes.push_back(Matmean); 247 } 248 249 cout<<"now we test...."<<endl; 250 251 vector<double> meanScores; 252 priority_queue<Node, vector<Node>, greater<Node>> minheap; 253 //做一个大小为_Nclass的最小堆,找出分数最大的类 254 const int _Nclass=1; 255 for (int i=0;i<_Nclass;i++){ 256 double scores=imgcompare->comparehist(meanRes[i]); 257 meanScores.push_back(scores); 258 Node Notemp(scores,i); 259 minheap.push(Notemp); 260 } 261 for(int i=_Nclass;i<nclass;i++){ 262 //当前的node 263 double scores=imgcompare->comparehist(meanRes[i]); 264 meanScores.push_back(scores); 265 Node Noteamp(scores,i); 266 // cout<<Noteamp.value<<endl; 267 if(minheap.top().value<Noteamp.value){ 268 //将这个大的数放进去 269 minheap.push(Noteamp); 270 //将堆顶最小的数弹出 271 minheap.pop(); 272 }else{ 273 continue; 274 } 275 } 276 277 cout<<"we have get the class with the maxinum score is the "<<minheap.top().idx<<"th class..."<<endl; 278 double maxscore=minheap.top().value; 279 int maxscoreindex=minheap.top().idx; 280 for(int i=0;i<nclass;i++){ 281 if(i==maxscoreindex){continue;} 282 if (meanScores[i]>0.9*maxscore){ 283 minheap.push(Node(meanScores[i],i)); 284 } 285 } 286 int _Sclass=minheap.size(); 287 cout<<"we find totally the other classes with scores > 0.9* maxscore,and the number of which is "<<_Sclass<<endl; 288 res_hist_and_id_of_pic_and_scores.resize(_Sclass); 289 for(int i=0;i<_Sclass;i++){ 290 cout<<"the score is "<< minheap.top().value<<" and the idx is "<<minheap.top().idx<<endl; 291 //最小的放最后 292 res_hist_and_id_of_pic_and_scores[_Sclass-1-i]=(make_pair(resofclu[minheap.top().idx],minheap.top().value)); 293 minheap.pop(); 294 } 295 296 297 298 299 } 300 301 //求取每个图片与但前reference的score 302 void solvescores(){ 303 for(auto lei_and_score:res_hist_and_id_of_pic_and_scores){ 304 vector<double> scoretemp; 305 scoretemp.clear(); 306 for(auto leitemp:lei_and_score.first){ 307 scoretemp.push_back(imgcompare->comparehist(leitemp.first)); 308 309 } 310 imgsscores.push_back(scoretemp); 311 } 312 313 } 314 315 vector<vector<double> >& getscores(){ 316 return imgsscores; 317 318 319 } 320 vector<pair<vector<pair<Mat,int>>,double> > getres(){ 321 return res_hist_and_id_of_pic_and_scores; 322 } 323 324 325 }; 326 327 void showtheimage(const string& strPath,const Node& nodett){ 328 string strPrefix=strPath+"image_2/"; 329 stringstream ss; 330 ss<<setfill('0')<<setw(6)<<nodett.idx; 331 imshow("my value is"+to_string(nodett.value)+";my index is"+to_string(nodett.idx),imread(strPrefix+ss.str()+".png")); 332 333 } 334 void LoadImages(const string& strPath,const int n,vector<string>& vstrimage){ 335 string strPrefix=strPath+"image_2/"; 336 vstrimage.resize(n); 337 for(int i=0;i<n;i++){ 338 stringstream ss; 339 ss<<setfill('0')<<setw(6)<<i; 340 vstrimage[i]=strPrefix+ss.str()+".png"; 341 } 342 343 } 344 int main(int argc,char** argv) { 345 if(argc!=3){ 346 cerr<<endl<<"Usage: ./main pathtoimage numberofimages"<<endl; 347 } 348 349 350 //load image 351 352 vector<string> vstrimage; 353 LoadImages(string(argv[1]),stoi(string(argv[2])),vstrimage); 354 const int nImages=vstrimage.size(); 355 356 cout<<"start creating database...."<<endl; 357 //场景库 358 vector<Mat> scenebase; 359 scenebase.resize(nImages); 360 Mat imtemp; 361 ColorHistogram histsolver; 362 int ii=0; 363 for(auto sPath:vstrimage){ 364 imtemp=imread(sPath); 365 Mat histtemp=histsolver.getReduceHistogram(imtemp); 366 scenebase[ii]=histtemp; 367 ii++; 368 } 369 cout<<"the database has been created..."<<"and the size of it is "<<scenebase.size()<<endl; 370 371 //待查询图片 372 Mat imtest=imread("../image_2/000030.png"); 373 imshow("im the reference",imtest); 374 //保存的结果 375 vector<pair<vector<pair<Mat,int>>,double> > res; 376 vector<vector<double> > imagescores; 377 //求解 378 shared_ptr<Getsimilarsulotin> gesolution=make_shared<Getsimilarsulotin>(scenebase,imtest); 379 gesolution->getMostsimilar(); 380 res=gesolution->getres(); 381 gesolution->solvescores(); 382 imagescores=gesolution->getscores(); 383 //res[0].first 可以查询类 384 //res[0].second 可以查询该类的分数 385 //(res[0].first)[0].first 可以查询类的一个元素的hist 386 //(res[0].first)[0].second 可以查询hist的index 387 //demo for 输出结果 388 vector<Node> resofpics; 389 390 int ix=0; 391 for(auto lei_and_score:res){ 392 int iy=0; 393 cout<<"类的分数是 :"<<lei_and_score.second<<endl<<"该类中的index有这些"<<endl; 394 for(auto hist_and_index:lei_and_score.first){ 395 cout<<"index= "<<hist_and_index.second<<" "<<"score= "<<imagescores[ix][iy]<<endl; 396 397 iy++; 398 } 399 ix++; 400 } 401 402 403 404 waitKey(0); 405 return 0; 406 }

 

转载于:https://www.cnblogs.com/geooeg/p/7811887.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值