OpenCV玩耍(一)批量resize一個文件夾里的所有圖像


鑒於用caffe做實驗的時候,里面牽扯到一個問題是必須將訓練集和測試集都轉成256*256的圖像,而官網給出的代碼又不會用,所以我用opencv轉了。其實opencv只轉一幅圖會很簡單,關鍵在於“批量”二字,因此本博客應運而生了。

本博客詳細講解了如何使用opencv批量處理圖像,使某一個文件夾內全部圖像都resize成256*256的。如果理解了本次博客內容,則不光可以對圖像進行resize操作,還可以用來對圖像做其它批處理操作。

1 先用opencv轉一幅圖像試試

 1 #include "cv.h"
 2 #include "highgui.h"
 3 #include "math.h"
 4 #include <iostream>
 5 using namespace std;
 6 
 7 void main()
 8 {
 9     IplImage *src;
10     IplImage *dst;
11     src=cvLoadImage("C:\\Users\\LJJ\\Desktop\\測試圖\\caffe實驗\\resize\\0101.jpg", 0);//載入源圖像
12     dst=cvCreateImage(cvSize(256,256),src->depth,src->nChannels);//分配一個256*256的目標圖像,resize后的結果將放在這里
13     if(src==0)
14     {
15         printf("打開圖片失敗!");
16         exit(0);
17     }
18     cvNamedWindow("src",CV_WINDOW_AUTOSIZE);//分配一個用以承載圖片的窗口
19     cvNamedWindow("dst",CV_WINDOW_AUTOSIZE);//分配一個用以承載圖片的窗口
20     cvShowImage("src",src);//顯示src
21     cvShowImage("dst",dst);//顯示dst
22     cvWaitKey(0);
23 
24     //此處插入resize
25     cvResize(src,dst);
26     //此處插入resize
27     cvSaveImage("C:\\Users\\LJJ\\Desktop\\測試圖\\caffe實驗\\resize\\result\\0101.jpg",dst);//保存dst
28     cvNamedWindow("dst",CV_WINDOW_AUTOSIZE);//分配一個用以承載圖片的窗口
29     cvShowImage("dst",dst);//顯示dst
30     cvWaitKey(0);
31 }

這一部分怎么來的太簡單了就不多說了,直接翻一下opencv中的cvResize函數聲明,需要什么參數就填什么。

【實驗結果】

src:

 

dst:

 

2 FindFirstFile函數與FindNextFile函數

使用這兩個函數可以遍歷整個圖像文件夾。以下例子來自於百度百科,按照自己理解注釋了。

 1 #include <iostream>
 2 #include <windows.h>
 3 using namespace std;
 4 
 5 void main()
 6 {
 7     WIN32_FIND_DATA p; //p是一個用於保存文件信息的結構體
 8     HANDLE h=FindFirstFile("C:\\Users\\LJJ\\Desktop\\測試圖\\caffe實驗\\resize\\*.jpg",&p); 
 9 
10 /*FindFirstFile的返回值是一個句柄,第二個參數p是采用引用的方式,也就是說當這句話執行完畢后p就指向該文件*.jpg*/
11 
12     cout<<p.cFileName<<endl;//打印被找到的第一個*.jpg的文件名
13     while(FindNextFile(h,&p)) //p不斷后移,尋找下一個、下下一個*.jpg
14     {
15         cout<<p.cFileName<<endl;
16     }
17 }

這一部分是用來遍歷整個文件夾里全部jpg類型的圖像的。為了方便觀察,我們的p指針每指向一個新的jpg文件,都將文件名打印出來。

【實驗結果】

 

3 批量resize一個文件夾里的所有圖像

這一部分結合了以上兩部分內容。除此之外還需要一點點C++的string類的知識,知道string類實例化出的對象能夠方便地進行字符串的拼接。

3-1 string類對象的正確用法

需要注意的一點是如果用string類實例化出一個對象,那么這個對象不是字符串,因此像C中用來將字符串轉成整數的函數atoi呀,以及字符串里填上全路徑用作文件地址索引呀,都是不能直接用這個對象的。

以“字符串-整數轉換”為例:

1 string label;
2 
3 label_int=atoi(label); //錯誤用法
4 
5 label_int=atoi(label.c_str());//正確用法

同理在這里把string類實例化出的對象用作路徑索引時,也是不能直接給一個對象,得給出“對象.c_str()”。

3-2 路徑頭+文件名=全路徑

這里要談到將一個文件夾內所有jpg文件批量處理的核心思想。即以下幾步:

(1)在第2節中的結構體p僅能給出它索引到的jpg文件的文件名,而沒有給出它們的路徑。

這些文件名如第2節所述,使用p.cFileName即可獲取。

(2)每一幅圖像的路徑是相同的,只有文件名不同,鑒於這一點,我們應該自行給出這些圖像的路徑頭——即“全路徑-文件名”。

例如對圖像C:\Users\LJJ\Desktop\測試圖\caffe實驗\resize\0000.jpg,其中“0000.jpg”是它的文件名,“C:\Users\LJJ\Desktop\測試圖\caffe實驗\resize\”就是它的路徑頭。在寫成字符串時,應該對反斜杠\進行轉義字符處理(即寫成\\):

 ”C:\\Users\\LJJ\\Desktop\\測試圖\\caffe實驗\\resize\\”

(3)如前述,string類對象可以方便地進行字符串拼接,如:

1 string label1=”one”;
2 
3 string label2=”two”;
4 
5 string label=label1+label2; //如果cout<<label,則輸出字符串”onetwo”

因此我們可以方便地完成對路徑頭和文件名的拼接。其中路徑頭是我們自己給的,文件名則由p.cFileName獲取,隨着指針p后移,將會索引該文件夾內全部的jpg文件。

3-3 批量resize代碼清單

 1 #include "cv.h"
 2 #include "highgui.h"
 3 #include "math.h"
 4 #include <iostream>
 5 #include <string>
 6 #include <windows.h>
 7 using namespace std;
 8 
 9 void main()
10 {
11     IplImage *src;
12     IplImage *dst;
13     WIN32_FIND_DATA p; //指向一個用於保存文件信息的結構體
14     HANDLE h=FindFirstFile("C:\\Users\\LJJ\\Desktop\\測試圖\\caffe實驗\\resize\\*.jpg",&p); //FindFirstFile的返回值是一個句柄,第二個參數p是采用引用的方式,也就是說當這句話執行完畢后p就指向該文件*.jpg
15 
16     //由於p的成員變量只有文件名,而無文件路徑,所以必須加上路徑頭
17     string src_route_head="C:\\Users\\LJJ\\Desktop\\測試圖\\caffe實驗\\resize\\"; //源圖像的路徑頭
18     string dst_route_head="C:\\Users\\LJJ\\Desktop\\測試圖\\caffe實驗\\resize\\result\\";//目標圖像的路徑頭
19     string SourceRoute=src_route_head+p.cFileName; //包含了路徑頭和文件名的全路徑
20     string DestRoute=dst_route_head+p.cFileName;
21 
22     src=cvLoadImage(SourceRoute.c_str(), 0);//載入源圖像
23     dst=cvCreateImage(cvSize(256,256),src->depth,src->nChannels);//分配一個256*256的目標圖像,resize后的結果將放在這里
24 
25     cvResize(src,dst);
26     cvSaveImage(DestRoute.c_str(),dst);//保存dst
27 
28     //到目前為止,我們就已經完成了對目標文件夾中第一幅圖像的resize處理與保存,接下來讓該文件夾中其余圖像也被處理
29 
30     while(FindNextFile(h,&p)) //p指針不斷后移,尋找下一個、下下一個*.jpg
31     {
32         SourceRoute=src_route_head+p.cFileName;
33         src=cvLoadImage(SourceRoute.c_str(), 0);//載入源圖像
34 
35         cvResize(src,dst);
36     
37         DestRoute=dst_route_head+p.cFileName;
38         cvSaveImage(DestRoute.c_str(),dst);//保存dst
39     }
40 }

2016.5.11

by 悠望南山


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM