花40分钟写一个-CBIR引擎-代码公开
生活随笔
收集整理的這篇文章主要介紹了
花40分钟写一个-CBIR引擎-代码公开
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
? ? ? 瀏覽網頁的時候發現一篇不錯的文章"用Python和OpenCV創建一個圖片搜索引擎的完整指南"http://python.jobbole.com/80860/.作者在瀏覽自己旅游的照片的時候,發現照片太多了分類不過來,一時技癢寫了個分類軟件,雖然簡單但是有用。關鍵的是我發現他在原文中使用了半個小時就寫出來了。 ? ? ? ?蠻快的嘛,我想。那么我要用多長時間寫出來了,畢竟對于CBIR也是研究過的。 ? ? ? ?那么立即來做,首先我要找到是圖片。我沒有那么多旅游圖片(汗),但是別人的照片也是可以一樣用的。找到了之前專門用于測試CBIR的圖片集,大概是這個樣子 就是各種奇奇怪怪的照片。然后搭建opencv的基本框架。我們python用的不熟,但是c++下面自己是有類庫的,所以用起來也不是很復雜 ? ? ? ?首先是讀入所有的圖片: //遞歸讀取目錄下全部文件
void?getFiles(string?path,?vector<string>&?files,string?flag){
????//文件句柄
????long???hFile???=???0;
????//文件信息
????struct?_finddata_t?fileinfo;
????string?p;
????if((hFile?=?_findfirst(p.assign(path).append("\\*").c_str(),&fileinfo))?!=??-1){
????????do{
????????????//如果是目錄,迭代之,如果不是,加入列表
????????????if((fileinfo.attrib?&??_A_SUBDIR)){
????????????????if(strcmp(fileinfo.name,".")?!=?0??&&??strcmp(fileinfo.name,"..")?!=?0?&&?flag=="r")
????????????????????getFiles(?p.assign(path).append("\\").append(fileinfo.name),?files,flag?);
????????????}
????????????else{
????????????????files.push_back(p.assign(path).append("\\").append(fileinfo.name)?);
????????????}
????????}while(_findnext(hFile,?&fileinfo)??==?0);
????????_findclose(hFile);
????}
}
//遞歸讀取目錄下全部圖片
void?getFiles(string?path,?vector<Mat>&?files,string?flag){
????vector<string>?fileNames;
????getFiles(path,fileNames,flag);
????for?(int?i=0;i<fileNames.size();i++){
????????Mat?tmp?=?imread(fileNames[i]);
????????if?(tmp.rows>0)//如果是圖片
????????????files.push_back(tmp);
????}
}
//遞歸讀取目錄下全部圖片和名稱
void?getFiles(string?path,?vector<pair<Mat,string>>&?files,string?flag){
????vector<string>?fileNames;
????getFiles(path,fileNames,flag);
????for?(int?i=0;i<fileNames.size();i++){
????????Mat?tmp?=?imread(fileNames[i]);
????????if?(tmp.rows>0){
???????????????pair<Mat,string>?apir;
???????????????apir.first?=?tmp;
???????????????apir.second?=?fileNames[i];
???????????????files.push_back(apir);
????????}
????}
} 然后是編寫hsv距離,這個參考以前的資料 double?GetHsVDistance(Mat?src_base,Mat?src_test1){
????Mat???hsv_base;
????Mat???hsv_test1;
????///??Convert??to??HSV
????cvtColor(??src_base,??hsv_base,??COLOR_BGR2HSV??);
????cvtColor(??src_test1,??hsv_test1,??COLOR_BGR2HSV??);
????///??Using??50??bins??for??hue??and??60??for??saturation
????int??h_bins??=??50;??int??s_bins??=??60;
????int??histSize[]??=??{??h_bins,??s_bins??};
????//??hue??varies??from??0??to??179,??saturation??from??0??to??255
????float??h_ranges[]??=??{??0,??180??};
????float??s_ranges[]??=??{??0,??256??};
????const??float*??ranges[]??=??{??h_ranges,??s_ranges??};
????//??Use??the??o-th??and??1-st??channels
????int??channels[]??=??{??0,??1??};
????///??Histograms
????MatND??hist_base;
????MatND??hist_test1;
????///??Calculate??the??histograms??for??the??HSV??images
????calcHist(??&hsv_base,??1,??channels,??Mat(),??hist_base,??2,??histSize,??ranges,??true,??false??);
????normalize(??hist_base,??hist_base,??0,??1,??NORM_MINMAX,??-1,??Mat()??);
????calcHist(??&hsv_test1,??1,??channels,??Mat(),??hist_test1,??2,??histSize,??ranges,??true,??false??);
????normalize(??hist_test1,??hist_test1,??0,??1,??NORM_MINMAX,??-1,??Mat()??);
????///??Apply??the??histogram??comparison??methods
????double??base_test1??=??compareHist(??hist_base,??hist_test1,??0??);
????return?base_test1;
} 封裝成函數。這個函數比原文中作者提出的方法要簡單,我偷懶了。 然后就是要編寫主函數程序,這個比較麻煩的地方就是要比較出最前面的10 個圖片 。我采用比較笨的方法,趕時間嘛: int?_tmain(int?argc,?_TCHAR*?argv[])
{????
????vector<pair<Mat,string>>?imagepairs;
????vector<double>?dresult;
????double?dmax?=?0;
????int?imax?=?-1;
????
????//讀入圖片
????getFiles("images",imagepairs);
????Mat?src?=?imread("images/0.jpg");
????//距離測算
????for?(int?i=0;i<imagepairs.size();i++){
????????double?tmp?=?GetHsVDistance(src,imagepairs[i].first);
????????if?(tmp?==1)
????????????tmp?=0;//不能搞自己
????????char?cbuf[1024];
????????sprintf_s(cbuf,"dst/%d.jpg",i);
????????dresult.push_back(tmp);//推入vecresult中
????}
????//尋找前10個圖片
????for?(int?index?=?0;index<10;index++){
????????for?(int?i=0;i<imagepairs.size();i++){
????????????if?(dresult[i]>dmax){
????????????????dmax?=?dresult[i];
????????????????imax?=?i;
????????????}
????????}
????????char?cbuf[1024];
????????sprintf_s(cbuf,"dst/%d.jpg",index);
????????imwrite(cbuf,imagepairs[imax].first);
????????dresult[imax]?=?0;//剔出隊列
????????dmax?=?0;
????????imax?=?-1;
????}
????printf("OK");
????waitKey();
????return?0;
} 前后花了40-50分鐘時間,最后的效果不如作者的效果。主要差距在核心算法上面。看來日常的算法總結重構的確很有價值。 這篇文章先寫到這里,最近事多,等到閑下來再進行重構。歡迎大家批評指正。 ?
void?getFiles(string?path,?vector<string>&?files,string?flag){
????//文件句柄
????long???hFile???=???0;
????//文件信息
????struct?_finddata_t?fileinfo;
????string?p;
????if((hFile?=?_findfirst(p.assign(path).append("\\*").c_str(),&fileinfo))?!=??-1){
????????do{
????????????//如果是目錄,迭代之,如果不是,加入列表
????????????if((fileinfo.attrib?&??_A_SUBDIR)){
????????????????if(strcmp(fileinfo.name,".")?!=?0??&&??strcmp(fileinfo.name,"..")?!=?0?&&?flag=="r")
????????????????????getFiles(?p.assign(path).append("\\").append(fileinfo.name),?files,flag?);
????????????}
????????????else{
????????????????files.push_back(p.assign(path).append("\\").append(fileinfo.name)?);
????????????}
????????}while(_findnext(hFile,?&fileinfo)??==?0);
????????_findclose(hFile);
????}
}
//遞歸讀取目錄下全部圖片
void?getFiles(string?path,?vector<Mat>&?files,string?flag){
????vector<string>?fileNames;
????getFiles(path,fileNames,flag);
????for?(int?i=0;i<fileNames.size();i++){
????????Mat?tmp?=?imread(fileNames[i]);
????????if?(tmp.rows>0)//如果是圖片
????????????files.push_back(tmp);
????}
}
//遞歸讀取目錄下全部圖片和名稱
void?getFiles(string?path,?vector<pair<Mat,string>>&?files,string?flag){
????vector<string>?fileNames;
????getFiles(path,fileNames,flag);
????for?(int?i=0;i<fileNames.size();i++){
????????Mat?tmp?=?imread(fileNames[i]);
????????if?(tmp.rows>0){
???????????????pair<Mat,string>?apir;
???????????????apir.first?=?tmp;
???????????????apir.second?=?fileNames[i];
???????????????files.push_back(apir);
????????}
????}
} 然后是編寫hsv距離,這個參考以前的資料 double?GetHsVDistance(Mat?src_base,Mat?src_test1){
????Mat???hsv_base;
????Mat???hsv_test1;
????///??Convert??to??HSV
????cvtColor(??src_base,??hsv_base,??COLOR_BGR2HSV??);
????cvtColor(??src_test1,??hsv_test1,??COLOR_BGR2HSV??);
????///??Using??50??bins??for??hue??and??60??for??saturation
????int??h_bins??=??50;??int??s_bins??=??60;
????int??histSize[]??=??{??h_bins,??s_bins??};
????//??hue??varies??from??0??to??179,??saturation??from??0??to??255
????float??h_ranges[]??=??{??0,??180??};
????float??s_ranges[]??=??{??0,??256??};
????const??float*??ranges[]??=??{??h_ranges,??s_ranges??};
????//??Use??the??o-th??and??1-st??channels
????int??channels[]??=??{??0,??1??};
????///??Histograms
????MatND??hist_base;
????MatND??hist_test1;
????///??Calculate??the??histograms??for??the??HSV??images
????calcHist(??&hsv_base,??1,??channels,??Mat(),??hist_base,??2,??histSize,??ranges,??true,??false??);
????normalize(??hist_base,??hist_base,??0,??1,??NORM_MINMAX,??-1,??Mat()??);
????calcHist(??&hsv_test1,??1,??channels,??Mat(),??hist_test1,??2,??histSize,??ranges,??true,??false??);
????normalize(??hist_test1,??hist_test1,??0,??1,??NORM_MINMAX,??-1,??Mat()??);
????///??Apply??the??histogram??comparison??methods
????double??base_test1??=??compareHist(??hist_base,??hist_test1,??0??);
????return?base_test1;
} 封裝成函數。這個函數比原文中作者提出的方法要簡單,我偷懶了。 然后就是要編寫主函數程序,這個比較麻煩的地方就是要比較出最前面的10 個圖片 。我采用比較笨的方法,趕時間嘛: int?_tmain(int?argc,?_TCHAR*?argv[])
{????
????vector<pair<Mat,string>>?imagepairs;
????vector<double>?dresult;
????double?dmax?=?0;
????int?imax?=?-1;
????
????//讀入圖片
????getFiles("images",imagepairs);
????Mat?src?=?imread("images/0.jpg");
????//距離測算
????for?(int?i=0;i<imagepairs.size();i++){
????????double?tmp?=?GetHsVDistance(src,imagepairs[i].first);
????????if?(tmp?==1)
????????????tmp?=0;//不能搞自己
????????char?cbuf[1024];
????????sprintf_s(cbuf,"dst/%d.jpg",i);
????????dresult.push_back(tmp);//推入vecresult中
????}
????//尋找前10個圖片
????for?(int?index?=?0;index<10;index++){
????????for?(int?i=0;i<imagepairs.size();i++){
????????????if?(dresult[i]>dmax){
????????????????dmax?=?dresult[i];
????????????????imax?=?i;
????????????}
????????}
????????char?cbuf[1024];
????????sprintf_s(cbuf,"dst/%d.jpg",index);
????????imwrite(cbuf,imagepairs[imax].first);
????????dresult[imax]?=?0;//剔出隊列
????????dmax?=?0;
????????imax?=?-1;
????}
????printf("OK");
????waitKey();
????return?0;
} 前后花了40-50分鐘時間,最后的效果不如作者的效果。主要差距在核心算法上面。看來日常的算法總結重構的確很有價值。 這篇文章先寫到這里,最近事多,等到閑下來再進行重構。歡迎大家批評指正。 ?
總結
以上是生活随笔為你收集整理的花40分钟写一个-CBIR引擎-代码公开的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Velocity知识点总结
- 下一篇: Spring MVC配置静态资源的正常访