總所周知,機器學習前要訓練很多數據,一直感覺訓練數據是個很神聖的東西,到底怎么訓練呢?頭腦一直有這么個疑問,但一直沒時間去體驗。因此最近在學adaboost算法,就要學會怎樣訓練出一個.xml文件了。方法是相同的,用過一次,以后的訓練過程就差不多了。
只是打算進行簡單的人臉數據訓練,而是在網上下載了yale大學的人臉數據庫,由耶魯大學計算視覺與控制中心創建,包含15位志願者的165張圖片,包含光照,表情和姿態。下載網址為:
http://cvc.yale.edu/projects/yalefaces/yalefaces.html。圖片如下所示:
(右下角是我的系統透明主題的青花瓷照片,別驚訝怎么出來的哈…)
Yale大學人臉數據都是bmp格式的,80*80像素大小。由於這次的haartraining只是為了學會其過程,再加上這個算法訓練的時間非常長,圖片不到1000就需要的時間都是以天為單位。所以為了減少訓練時間,我們一方面得減少圖片的數量,這里我打算用133張正樣本圖,另外22個張用來做測試,另一方面打算減小圖片的尺寸,將80*80的圖片統一到尺寸24*24像素大小。
(這里插2個小知識:1. 理解圖片尺寸的概念。比如說圖片的尺寸為80*80代表的是圖片的大小為80*80,並不是指分辨率,而是說的是80*80像素,即寬度為80個像素,長度也為80個像素。因為一個像素寬在一個顯示器件上已經確定了。因此當一副圖片被放大時,它的尺寸像素就可能改變,比如變成了100*100像素,因為放大的時候它的長和寬變了。但是其分辨率在放大時並沒有變化。另外像素和長度cm的對應關系也得看圖形的分辨率,比如通常所說的說1cm=28像素是指在72像素/平方英寸的時候。所以一般所說的數碼相機的像素過高的話其實對顯示器顯示圖片清晰度沒有太大幫助,像素高只是可以打印出來更大更清晰的照片。
2. 在window下如果一副圖片,比如說是bmp格式的。我只需把后綴名改為其他的比如jpg。然后右鍵查看其屬性時竟然是jpg格式,並且也能打開,難道真的就是jpg格式的嗎?肯定不是,比較bmp和改后的jpg就會發現兩者的大小是一樣的。最后用matlab命令的imfinfo來查看圖片的信息,也還是bmp格式的。說明上面單獨改后綴名是一種誤導,以后做圖像處理的時候一定要小心。)
接下來所要進行的操作就是把這165張圖片的尺寸縮小到24*24像素了,當然這里有一個笨方法,就是用圖片查看軟件(比如說ACDsee)一張一張轉換。不過要是圖片成千上萬那就麻煩了。也不懂有什么批處理的工具沒有,有的話大家也可以提出來共享。
所以打算自己寫一個小程序來完成這些批處理工作,圖片的縮放就用opencv中現有的函數了。寫這個小程序的主要目的是練習對文件名的操作,因為以前一直對這些東西沒概念,今天練習了下,收獲還是有的。
剛剛在上圖可以看出,人臉數據庫的命名比如1_s1.bmp表示的是第一個人的第一張人臉圖。最后調整后的名字改為1_s1n.bmp。
首先在工程文件目錄下,建立yale和yale_small_size文件夾,並把165張人臉數據圖片拷貝到yale文件夾中。最后通過程序生成的小尺寸圖全部放在yale_small_size文件夾中。如下所示:
其程序代碼如下:
1 // change_img_size.cpp : 定義控制台應用程序的入口點。
2 //
3 #include "stdafx.h"//這句頭文件一定要放在最上面,否則很容易報錯
4
5 #include "opencv2/imgproc/imgproc.hpp"
6 #include "opencv2/highgui/highgui.hpp"
7
8 #include <iostream>
9 #include <stdio.h>
10
11 using namespace cv;
12 using namespace std;
13
14 #define DST_IMG_WIDTH 24 //需要調整圖片后的尺寸寬度
15 #define SRC_IMG_HEIGH 24 //需要調整圖片后的尺寸高度
16
17 int main(int argc, char* argv[])
18 {
19 Mat src_img;
20 int i,j;
21 string src_img_name="yale/",dst_img_name="yale_small_size/";//源文件和目的文件的文件夾名字
22 char chari[5],charj[5];//因為人臉數據不是很多,所以下標5足夠用
23 for(i=1;i<=15;i++)//15個人的人臉數據
24 {
25 for(j=1;j<=11;j++)//每個人的人臉有11種不同的表情
26 {
27 itoa(i,chari,10);//將變量轉換成字符型,此處的chari是字符數組首地址,但是如果定義為char *chari="";則會出現錯誤,why?
28 itoa(j,charj,10);
29
30 src_img_name+=chari;//原圖命名格式為,比如第5個人的第6張圖,5_s6.bmp
31 src_img_name+="_s";
32 src_img_name+=charj;
33 src_img_name+=".bmp";
34
35 src_img=imread(src_img_name,1);
36 Mat dst_img_rsize(DST_IMG_WIDTH,SRC_IMG_HEIGH,src_img.type());
37 resize(src_img,dst_img_rsize,dst_img_rsize.size(),0,0,INTER_LINEAR);
38
39 dst_img_name+=chari;//轉換后圖的命名格式為:例上,5_s6n.bmp
40 dst_img_name+="_s";
41 dst_img_name+=charj;
42 dst_img_name+="n.bmp";
43
44 imwrite(dst_img_name,dst_img_rsize);
45 src_img_name="yale/",dst_img_name="yale_small_size/";//每次循環后要重新清0字符數組內的內容,目的文件夾一定要事先建立,否則無效果
46
47 }
48 }
49 return 0;
50 }
最后生成的歸一化后的圖片截圖如下所示(yale_small_size文件夾內):
好吧,很簡單的工作已經完成了,沒什么含量。以后有時間打算寫個界面出來,可以批處理的調整圖片到指定的像素大小,為以后搞視覺的圖片前期處理帶來便利。