人脸识别之第一步,人脸库的建立。
在官方文档中,提供一个人脸库的下载,可以下载回来看看人家的是什么格式的。
我们选择AT&T人脸库下载的下载:http://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html
AT&T Facedatabase又称ORL人脸数据库,40个人,每人10张照片。照片在不同时间、不同光照、不同表情(睁眼闭眼、笑或者不笑)、不同人脸细节(戴眼镜或者不戴眼镜)下采集。所有的图像都在一个黑暗均匀的背景下采集的,正面竖直人脸(有些有有轻微旋转)。
下载回来的是压缩包,先解压得到orl_faces文件夹,文件夹下有40个文件夹,命名从“s1”~"s40",每个文件夹放的是同一人的照片,里面有10张人脸照。
但都是 .pgm 格式的 92 x 112 图片,在windows下打不开,可在linux下打开,如下:
看一遍官方提供的人脸库,大概知道如何存放、处理图片。后面参考官方方法建立自己的图片即可。
废话少说,马上行动。
一、实现步骤与方法
思路很清晰,如下:
1、打开摄像头,采集图像;
2、加载人脸分类器;
3、人脸检测,并框出人脸部分并显示图像;
4、在检测到人脸条件下,一键拍照;
5、对人脸部分,调整大小并写成指定目录下的图像文件;
二、实现代码
你可自己写代码实现这功能,亦可直接COPY代码来用,这只是辅助功能而已。
代码如下:
#include "opencv2/objdetect.hpp" #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" #include <iostream> #include <stdio.h> using namespace cv; using namespace std; int resize_save(Mat& faceIn, char *path, int FaceSeq); int get_face(char *path); int main(int argc, char *argv[]) { if(argc != 2) { printf("usage: %s <path>\n", argv[0]); return -1; } get_face(argv[1]); return 0; } int get_face(char *path) { CascadeClassifier face_cascade; VideoCapture camera; char key = 0; Mat frame; int ret = 0; int faceNum = 1; vector<Rect> faces; Mat img_gray; Mat faceImg; camera.open(0); // 打开摄像头 if(!camera.isOpened()) { cout << "open camera failed. " << endl; return -1; } cout << "open camera succeed. " << endl; // 加载人脸分类器 ret = face_cascade.load("/root/library/opencv/opencv-3.2.0/data/haarcascades/haarcascade_frontalface_alt2.xml"); if( !ret ) { printf("load xml failed.\n"); return -1; } cout << "load xml succeed. " << endl; while (1) { camera >> frame; if(frame.empty()) { continue; } cvtColor(frame, img_gray, COLOR_BGR2GRAY); equalizeHist(img_gray, img_gray); // 检测目标 face_cascade.detectMultiScale(img_gray, faces, 1.1, 3, 0, Size(50, 50)); for(size_t i =0; i<faces.size(); i++) { /* 画矩形框出目标 */ rectangle(frame, Point(faces[0].x, faces[0].y), Point(faces[0].x + faces[0].width, faces[0].y + faces[0].height), Scalar(0, 255, 0), 1, 8); } imshow("camera", frame); // 显示 key = waitKey(1); // 显示后要添加延时 switch (key) { case 'p': // 按 P 一键拍脸 // 只限定检测一个人脸 if(faces.size() == 1) { faceImg = frame(faces[0]); ret = resize_save(faceImg, path, faceNum); // 调整大小及保存 if(ret == 0) { printf("resize_save success.\n"); faceNum ++; } } break; case 27: // 按 Esc 键退出 cout << "Esc..." << endl; return 0; default: break; } } } int resize_save(Mat& faceIn, char *path, int FaceSeq) { string strName; Mat image; Mat faceOut; int ret; if(faceIn.empty()) { printf("faceIn is empty.\n"); return -1; } if (faceIn.cols > 100) { resize(faceIn, faceOut, Size(92, 112)); // 调整大小,这里选择与官方人脸库图片大小兼容 strName = format("%s/%d.jpg", path, FaceSeq); // 先要创建文件夹 ret = imwrite(strName, faceOut); // 文件名后缀要正确 .jpg .bmp ... if(ret == false) // 出现错误,请检测文件名后缀、文件路径是否存在 { printf("imwrite failed!\n"); printf("please check filename[%s] is legal ?!\n", strName.c_str()); return -1; } imshow(strName, faceOut); } waitKey(20); return 0; }
操作说明:
编译成功后,执行可执行文件须提供参数,该参数为存放人脸图像的目录,且须为已有目录。
按“P”键一键拍照取脸保存,按“Esc”键退出。
若执行 imwrite() 函数失败时,请检查参数目录是否存在,要保存的文件名后缀是否合法。
此程序保存为 .jpg 格式,命名采用编号法由1递增。
三、运行示例
$ ./get_face abc
四、构建人脸库
按照以上步骤,可得到单个人的多张人脸照,人脸库由多个人(>=2)的人脸照组成,如下:
人脸库须大于或等于2人,这里暂收集5人照片。
参照官方人脸库,从“s1”~"s4"命名,每个文件夹放着同一个人的多张人脸照。
能力有限,欢迎指出不足,感激不尽!