视频中人脸检测以及人眼跟踪

人脸检测和人眼跟踪:

 

一、普通版人脸及人眼的检测:

      1. 这里我们使用的是opencv库官方提供的训练好的xml文件如下:

       

         

      2.人脸检测原理:

       将摄像头或者视频文件进行抓帧成一帧帧图象,然后将图象灰度化,直方图均衡化,最后通过face的xml文件进行人脸检测。

      3.在每张人脸中进行人脸检测:

      在进行人眼检测时,首先根据人眼的生物学特征在人脸上找到人眼的兴趣位置:

      

        这里简单的将人眼的兴趣区域分在了人脸1/2的上半部,然后与人脸检测一样采用eye的xml文件进行人眼检测。

      最后将检测结果人脸和人眼画出来。

代码如下:

 1 #include<opencv2/opencv.hpp>
 2 #include<iostream>
 3 
 4 using namespace cv;
 5 using namespace std;
 6 
 7 CascadeClassifier face_cascader; //人脸检测类
 8 CascadeClassifier eye_cascader;  //人眼的类
 9 String facefile = "E:/opencv/build/etc/haarcascades/haarcascade_frontalface_alt.xml";
10 String eyefile = "E:/opencv/build/etc/haarcascades/haarcascade_eye.xml";
11 //
12 int main(int argc, char** argv) {  
13     if (!face_cascader.load(facefile)) { //将facefile文件加载到face_cascader(文件起作用关键步骤)
14         printf("could not load face feature data...\n");
15         return -1;  //没有加载到脸部文件()
16     }
17     if (!eye_cascader.load(eyefile)) {  //将eyefile文件加载到eye_cascader(文件起作用关键步骤)
18         printf("could not load eye feature data...\n");
19         return -1;  //没有加载到眼睛文件
20     }
21     namedWindow("camera-demo", CV_WINDOW_AUTOSIZE);//相机窗口
22     //VideoCapture capture;   //可以直接抓取视频文件
23     VideoCapture capture(0);  //抓取默认摄像头内容显示在窗口
24     Mat frame;
25     Mat gray;
26     vector<Rect> faces; //一个faces变量的对象
27     vector<Rect> eyes;  //一个eyes变量的对象
28     while (capture.read(frame)) {  //capture.read读取视频后将每一帧图像放在frame中
29         cvtColor(frame, gray, COLOR_BGR2GRAY); //每帧图象转化为灰度图象
30         equalizeHist(gray, gray);  //直方图均衡化
31         face_cascader.detectMultiScale(gray, faces, 1.2, 3, 0, Size(30, 30));
32     //face_cascader文件下的detectMultiScale方法
33     //detectMultiScale函数:
34     //  1.输入图像  2.检测输出目标 3.每次图像减小比例 4. 每一个目标至少要被检测到3次才算
35     //  5.minSize为目标的最小尺寸    6.maxSize为目标的最大尺寸
36         for (size_t t = 0; t < faces.size(); t++) {    //每张脸人眼检测
37             Rect roi;  //一个对象roi放置人脸face
38             roi.x = faces[static_cast<int>(t)].x; //每个人脸的坐标
39             roi.y = faces[static_cast<int>(t)].y;
40             roi.width = faces[static_cast<int>(t)].width; //每个人脸的高度和宽度/2
41             roi.height = faces[static_cast<int>(t)].height / 2;
42             Mat faceROI = frame(roi); //在没帧图象frame上截取roi(上面设好坐标和宽高)区域,为faceROI
43             eye_cascader.detectMultiScale(faceROI, eyes, 1.2, 3, 0, Size(20, 20)); //在每个faceROI区域做人眼eyes检测
44     //eye_cascader文件下的detectMultiScale方法, detectMultiScale函数与上述一样。
45             for (size_t k = 0; k < eyes.size(); k++) {   //找出每个眼睛的位置
46                 Rect rect; 
47                 rect.x = faces[static_cast<int>(t)].x + eyes[k].x;
48                 rect.y = faces[static_cast<int>(t)].y + eyes[k].y;
49                 rect.width = eyes[k].width;
50                 rect.height = eyes[k].height;
51                 rectangle(frame, rect, Scalar(0, 255, 0), 2, 8, 0); //在frame上画出每个眼睛的位置
52             }
53             rectangle(frame, faces[static_cast<int>(t)], Scalar(0, 0, 255), 2, 8, 0); //在frame上画出每个脸的位置
54         }
55         imshow("camera-demo", frame);
56         char c = waitKey(30);
57         if (c == 27) {
58             break;
59         }
60     }
61     waitKey(0);
62     return 0;
63 }

检测结果如下:

 

二、人脸检测+模板匹配法人眼跟踪

      1.使用opencv库官方提供的训练好的xml文件如下:

      

      

      

     2.人脸检测原理与上面一样

     3.人眼检测:这里将人眼的兴趣区域更加精确化

      

      如图将左眼的兴趣区域画在人脸的左绿色框,右眼的兴趣区域画在人脸的右绿色框。上面大约是人脸高度的1/4

     左右两边大约是人脸宽度的1/8

     模板匹配法:https://www.cnblogs.com/Jack-Elvis/p/11530283.html

     将检测到的第一个人脸的左眼和右眼作为模板,通过模板匹配将其他人脸上的左眼和右眼检测出来。

代码如下:

  1 #include <opencv2/opencv.hpp>
  2 #include <iostream>
  3 
  4 using namespace cv;
  5 using namespace std;
  6 
  7 String facefile = "D:/opencv3.1/opencv/build/etc/haarcascades/haarcascade_frontalface_alt.xml"; //脸文件
  8 String lefteyefile = "D:/opencv3.1/opencv/build/etc/haarcascades/haarcascade_eye.xml";  //左眼文件 
  9 String righteyefile = "D:/opencv3.1/opencv/build/etc/haarcascades/haarcascade_eye.xml"; //右眼文件
 10 CascadeClassifier face_detector;    //face_detector类用于加载文件
 11 CascadeClassifier leftyeye_detector;
 12 CascadeClassifier righteye_detector;
 13 Rect leftEye, rightEye;  //左眼和右眼的数组变量(对象)
 14 
 15 //自定义一个模板匹配模块主函数中调用
 16 void trackEye(Mat&  im, Mat& tpl, Rect& rect) {
 17     //1.  im人眼兴趣图象  2.  tpl人眼模板图象  3.  rect输出目标人眼
 18     Mat result;
 19     int result_cols = im.cols - tpl.cols + 1;
 20     int result_rows = im.rows - tpl.rows + 1;
 21     // 模板匹配
 22     //定义一个result矩阵,必须是单通道32位浮点数,
 23     //假设源图像WxH,模板图像wxh,则结果必须为W - w + 1, H - h + 1的大小。
 24     result.create(result_rows, result_cols, CV_32FC1);
 25     matchTemplate(im, tpl, result, TM_CCORR_NORMED);
 26 
 27     // 寻找位置
 28     double minval, maxval;
 29     Point minloc, maxloc;
 30     minMaxLoc(result, &minval, &maxval, &minloc, &maxloc);
 31     if (maxval > 0.75) { //归一化后的结果最大值若大于0.75
 32      //人眼兴趣图象的始点坐标+匹配最大值所在的坐标(兴趣图象上的)=人眼坐标绝对值
 33         rect.x = rect.x + maxloc.x;
 34         rect.y = rect.y + maxloc.y;
 35     }
 36     else {
 37         rect.x = rect.y = rect.width = rect.height = 0;
 38     }
 39 }
 40 //trackEye(im, tpl, rect)函数输出为rect(对象Rect),即人眼模板匹配后,检测出人眼始点位置
 41 
 42 int main(int argc, char** argv) {
 43     if (!face_detector.load(facefile)) {
 44         printf("could not load data file...\n");
 45         return -1;
 46     }
 47     if (!leftyeye_detector.load(lefteyefile)) {
 48         printf("could not load data file...\n");
 49         return -1;
 50     }
 51     if (!righteye_detector.load(righteyefile)) {
 52         printf("could not load data file...\n");
 53         return -1;
 54     }
 55 
 56     Mat frame;
 57     VideoCapture capture(0);
 58     namedWindow("demo-win", CV_WINDOW_AUTOSIZE);
 59 
 60     Mat gray;
 61     vector<Rect> faces;
 62     vector<Rect> eyes;
 63     Mat lefttpl, righttpl; // 定义左右眼模板为Mat格式
 64     while (capture.read(frame)) {
 65         flip(frame, frame, 1);
 66         cvtColor(frame, gray, COLOR_BGR2GRAY);
 67         equalizeHist(gray, gray);//直方图均衡化
 68         face_detector.detectMultiScale(gray, faces, 1.1, 3, 0, Size(30, 30));
 69         for (size_t t = 0; t < faces.size(); t++) {
 70             rectangle(frame, faces[t], Scalar(255, 0, 0), 2, 8, 0);
 71 
 72             // 计算 offset ROI参数
 73             int offsety = faces[t].height / 4;
 74             int offsetx = faces[t].width / 8;
 75             int eyeheight = faces[t].height / 2 - offsety;
 76             int eyewidth = faces[t].width / 2 - offsetx;
 77 
 78             // 截取左眼兴趣(ROI)区域
 79             Rect leftRect;
 80             leftRect.x = faces[t].x + offsetx;
 81             leftRect.y = faces[t].y + offsety;
 82             leftRect.width = eyewidth;
 83             leftRect.height = eyeheight;
 84             Mat leftRoi = gray(leftRect);
 85 
 86             // 在leftROi区域检测左眼位置
 87             leftyeye_detector.detectMultiScale(leftRoi, eyes, 1.1, 1, 0, Size(20, 20));
 88             if (lefttpl.empty()) { //左眼模板为空
 89                 if (eyes.size()) { //检测到眼睛
 90                     leftRect = eyes[0] + Point(leftRect.x, leftRect.y);
 91             //将检测到的第一个眼睛对象eyes[0]赋给对象leftRect,并加上兴趣区域的始点坐标
 92                     lefttpl = gray(leftRect);//左眼灰度图象模板
 93                     rectangle(frame, leftRect, Scalar(0, 0, 255), 2, 8, 0);//画出左眼
 94                 }
 95             }
 96             else {
 97                 // 跟踪, 基于模板匹配
 98                 leftEye.x = leftRect.x; //左眼兴趣区域(ROI)的始点坐标
 99                 leftEye.y = leftRect.y;
100             //调用trackEye函数得到模板匹配后,左眼始点坐标(leftEye.x,leftEye.y)
101                 trackEye(leftRoi, lefttpl, leftEye);
102             //将人眼模板的宽高参数赋值给leftEye对象(Rect)
103                 if (leftEye.x > 0 && leftEye.y > 0) {
104                     leftEye.width = lefttpl.cols; 
105                     leftEye.height = lefttpl.rows;
106                     rectangle(frame, leftEye, Scalar(0, 0, 255), 2, 8, 0);//画出左眼
107                 }
108             }
109        //右眼检测的方法与左眼一样
110             // 截取右眼区域
111             Rect rightRect;
112             rightRect.x = faces[t].x + faces[t].width / 2;
113             rightRect.y = faces[t].y + offsety;
114             rightRect.width = eyewidth;
115             rightRect.height = eyeheight;
116             Mat rightRoi = gray(rightRect);
117 
118             // 检测右眼
119             righteye_detector.detectMultiScale(rightRoi, eyes, 1.1, 1, 0, Size(20, 20));
120             if (righttpl.empty()) {
121                 if (eyes.size()) {
122                     rightRect = eyes[0] + Point(rightRect.x, rightRect.y);
123                     righttpl = gray(rightRect);
124                     rectangle(frame, rightRect, Scalar(0, 255, 255), 2, 8, 0);
125                 }
126             }
127             else {
128                 // 跟踪, 基于模板匹配
129                 rightEye.x = rightRect.x;
130                 rightEye.y = rightRect.y;
131                 trackEye(rightRoi, righttpl, rightEye);
132                 if (rightEye.x > 0 && rightEye.y > 0) {
133                     rightEye.width = righttpl.cols;
134                     rightEye.height = righttpl.rows;
135                     rectangle(frame, rightEye, Scalar(0, 255, 255), 2, 8, 0);
136                 }
137             }
138         }
139         imshow("demo-win", frame);
140         char c = waitKey(100);
141         if (c == 27) { // ESC
142             break;
143         }
144     }
145 
146     // release resource
147     capture.release();
148     waitKey(0);
149     return 0;
150 }

检测结果如下:

 

猜你喜欢

转载自www.cnblogs.com/Jack-Elvis/p/12303925.html