总所周知,机器学习前要训练很多数据,一直感觉训练数据是个很神圣的东西,到底怎么训练呢?头脑一直有这么个疑问,但一直没时间去体验。因此最近在学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文件夹内):
好吧,很简单的工作已经完成了,没什么含量。以后有时间打算写个界面出来,可以批处理的调整图片到指定的像素大小,为以后搞视觉的图片前期处理带来便利。