Opencv摄像头实时人脸识别

发布时间:2018-08-05 07:57:59   来源:文档文库   
字号:

Opencv摄像头实时人脸识别

Introduction

网上存在很多人脸识别的文章,这篇文章是我的一个作业,重在通过摄像头实时采集人脸信息,进行人脸检测和人脸识别,并将识别结果显示在左上角。

利用 OpenCV 实现一个实时的人脸识别系统,人脸库采用 ORL FaceDatabase (网上下载) ,另外在数据库中增加了作业中自带的20张照片和自己利用摄像头采集到的10张照片,系统利用摄像头实时的采集到场景图像,从中检测出人脸用方框标出,并利用提供的数据库进行人脸识别,并在图像左上角显示相匹配的数据库图片。

Method

算法流程分两步,分别是人脸检测和人脸识别。人脸检测使用的是 ViolaJones 人脸检测方法,利用样本的 Haar-like 特征进行分类器训练,得到级联boosted 分类器,加载训练好的人脸分类器,利用分类器在视频帧中查找人脸区域;人脸识别利用了局部二进制模式直方图。

Haar-like 特征

Haar-like 特征如下图所示

1 Haar-like 特征

LBPH

人脸识别常用的方法有三种,EigenfacesFisherfaces LBPH;对于高维的图像空间,我们首先应该进行降维操作。LBP 不把图像看做高维的矢量,而是通过物体的局部特征来描述。将每个像素和其相邻像素对比形成局部的结构,把该像素看做中心,并以该值对邻接像素做阈值处理,如果临界像素的亮度大于该像素则为 1 否则为 0,这样每个像素点都可以用一个二进制数来表示,比如一个使用 3*3 临界点的 LBP 操作如下图所示:

2 LBP

Implementation识别训练

利用准备好的数据库进行识别训练:首先我们利用Opencv安装文件中的python脚本create_csv.py建立CSV文件,文件中每条记录如:orl/s13/2.pgm;12,分号之前是图片所存路径,而分号之后是图片的标签号,每一组图片对应着唯一的标签号;之后利用代码中的train_dataread_csv函数对数据集进行训练。使用到的 OpenCV 类和函数有:FaceRecognizercreateLBPHFaceRecognizer

人脸检测

运用Opencv安装文件中的haarcascade_frontalface_alt.xml文件,使用分类器在视频帧中查找人脸区域,并用绿色方框标出。用到的 OpenCV 类和函数有:CascadeClassifier,detectMultiScale

人脸识别

读取训练好的 yaml文件,对每个监测到的区域的图像分类,并在视频帧人脸区域上方显示分类结果(分类结果显示为标签和可信度),在左上角显示缩略图。用到的 OpenCV 函数主要有:predict.

Code

1 /*头文件:*/

2 #include "opencv2/core/core.hpp"

3 #include "opencv2/contrib/contrib.hpp"

4 #include "opencv2/highgui/highgui.hpp"

5 #include "opencv2/imgproc/imgproc.hpp"

6 #include "opencv2/objdetect/objdetect.hpp"

7

8 #include

9 #include

10 #include

11 #include

12

13 char *FACES_TXT_PATH = "face.txt";

14 char *HARR_XML_PATH = "haarcascade_frontalface_alt.xml";

15 char *FACES_MODEL = "face.yaml";

16 char *POTRAITS ="potraits.jpg";

17 int DEVICE_ID = 0;

18

19 /*主文件*/

20 #include "config.h"

21

22 using namespace cv;

23 using namespace std;

24 int FACE_WIDHT=92;

25 int FACE_HEIGHT=112;

26 int POTRITE_WIDTH = 100;

27 int POTRITE_HEIGHT = 100;

28

29 static void read_csv(const string& filename, vector& images, vector& labels, char separator = ';') {

30 std::ifstream file(filename.c_str(), ifstream::in);

31 if (!file) {

32 string error_message = "找不到文件,请核对路径";

33 CV_Error(CV_StsBadArg, error_message);

34 }

35 string line, path, classlabel;

36 while (getline(file, line)) {

37 stringstream liness(line);

38 getline(liness, path, separator);

39 getline(liness, classlabel);

40 if(!path.empty() && !classlabel.empty()) {

41 images.push_back(imread(path, 0));

42 labels.push_back(atoi(classlabel.c_str()));

43 }

44 }

45

46 }

47

48 /*利用csv文件读取数据集并训练对应模型*/

49 void train_data(String fn_csv)

50 {

51 vector images;

52 vector labels;

53 //获取数据集,如果出错抛出异常

54 try {

55 read_csv(fn_csv, images, labels);

56 }

57 catch (cv::Exception& e) {

58 cerr << "打开文件失败 \"" << fn_csv << "\". 原因: " << e.msg << endl;

59 exit(1);

60 }

61

62 // 如果训练集数量不够退出

63 if(images.size() <= 1) {

64 string error_message = "训练集图片少于2";

65 CV_Error(CV_StsError, error_message);

66 }

67

68 //训练模型

69 Ptr model = createLBPHFaceRecognizer();

70 model->train(images, labels);

71 model->save(FACES_MODEL);

72 }

73

74 void show_portrait(Mat &potrait, Mat &frame) {

75 int channels = potrait.channels();

76 int nRows = potrait.rows;

77 int nCols = potrait.cols*channels;

78

79 uchar *p_p, *p_f;

80 for(auto i=0; i

81 p_p = potrait.ptr(i);

82 p_f = frame.ptr(i);

83 for(auto j=0; j

84 p_f[j*3] = p_p[j];

85 p_f[j*3+1] = p_p[j+1];

86 p_f[j*3+2] = p_p[j+2];

87 }

88 }

89

90 }

91

92 void makePotraitImages(vector potraits) {

93 int rows = potraits.size()/6;

94 if(potraits.size()-rows *6>0)rows++;

95 rows *= POTRITE_HEIGHT;

96 int cols = 6*POTRITE_HEIGHT;

97 Mat potrait_s = Mat(rows,cols,CV_8UC3);

98 rows = POTRITE_HEIGHT;

99 cols = POTRITE_WIDTH;

100 uchar *p_ps, *p_p;

101 for(auto i=0; i

102 for(auto j=0; j

103 p_ps = potrait_s.ptr(i/6*POTRITE_HEIGHT+j)+3*(i%6)*POTRITE_WIDTH;

104 p_p = potraits[i].ptr(j);

105 for(auto k=0; k

106 p_ps[k*3] = p_p[k];

107 p_ps[k*3+1] = p_p[k+1];

108 p_ps[k*3+2] = p_p[k+2];

109 }

110 }

111 }

112 imwrite(POTRAITS, potrait_s);

113 }

114

115 void loadPortraits(const string& filename, vector& images, char separator = ';') {

116 string fn_csv = string(FACES_TXT_PATH);

117 std::ifstream file(fn_csv.c_str(), ifstream::in);

118 if (!file) {

119 string error_message = "找不到文件,请核对路径.";

120 CV_Error(CV_StsBadArg, error_message);

121 }

122 string line, path, classlabel;

123 int label(0);

124 while (getline(file, line)) {

125 stringstream liness(line);

126 getline(liness, path, separator);

127 getline(liness, classlabel);

128 if(!path.empty() && !classlabel.empty()) {

129 if(atoi(classlabel.c_str()) != label) {

130 Mat potrait = imread(path, 0);

131 resize(potrait, potrait,Size(POTRITE_WIDTH, POTRITE_HEIGHT));

132 images.push_back(potrait);

133 label = atoi(classlabel.c_str());

134 }

135 }

136 }

137 }

138

139 int main(int argc, const char *argv[]) {

140 // 保存图像和对应标签的向量,要求同一个人的图像必须对应相同的标签

141 string fn_csv = string(FACES_TXT_PATH);

142 string fn_haar = string(HARR_XML_PATH);

143

144 Ptr model = createLBPHFaceRecognizer();

145 FileStorage model_file(FACES_MODEL, FileStorage::READ);

146 if(!model_file.isOpened()){

147 cout<<"无法找到模型,训练中..."<

148 train_data(fn_csv);//训练数据集,1表示EigenFace 2表示FisherFace 3表示LBPHFace

149 }

150 model->load(model_file);

151 model_file.release();

152 vector potraits;

153 loadPortraits(FACES_MODEL,potraits);

154 makePotraitImages(potraits);

155 CascadeClassifier haar_cascade;

156 haar_cascade.load(fn_haar);

157

158 VideoCapture cap(DEVICE_ID);

159 if(!cap.isOpened()) {

160 cerr << "设备 " << DEVICE_ID << "无法打开" << endl;

161 return -1;

162 }

163

164 Mat frame;

165 for(;;) {

166 cap >> frame;

167 if(!frame.data)continue;

168 // 拷贝现有frame

169 Mat original = frame.clone();

170 // 灰度化

171 Mat gray;

172 cvtColor(original, gray, CV_BGR2GRAY);

173 // 识别frame中的人脸

174 vector< Rect_ > faces;

175 haar_cascade.detectMultiScale(gray, faces);

176

177 if(faces.size() != 0)

178 {

179 int max_area_rect=0;

180 for(int i = 0; i < 1; i++) {

181 if(faces[i].area() > faces[max_area_rect].area()){

182 max_area_rect = i;

183 }

184

185 }

186

187 // 顺序处理

188 Rect face_i = faces[max_area_rect];

189

190 Mat face = gray(face_i);

191 rectangle(original, face_i, CV_RGB(0, 255,0), 1);

192 int pridicted_label = -1;

193 double predicted_confidence = 0.0;

194 model->predict(face, pridicted_label, predicted_confidence);

195 string result_text = format("Prediction = %d confidence=%f", pridicted_label, predicted_confidence);

196 int text_x = std::max(face_i.tl().x - 10, 0);

197 int text_y = std::max(face_i.tl().y - 10, 0);

198 putText(original,result_text, Point(text_x, text_y),FONT_HERSHEY_PLAIN, 1.0, CV_RGB(0,255,0), 2.0);

199 if(pridicted_label >0)

200 show_portrait(potraits[pridicted_label], original);

201 }

202 // 显示结果:

203 imshow("face_recognizer", original);

204

205 char key = (char) waitKey(20);

206 if(key == 32)

207 exit(0);;

208 }

209 return 0;

210 }

Experiment

3 结果展示

4 人脸库拼图

本文来源:https://www.2haoxitong.net/k/doc/fde82656fd4ffe4733687e21af45b307e871f99c.html

《Opencv摄像头实时人脸识别.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式