#include
#include
using namespace std;
using namespace cv;
String Face_fileName = "haarcascade_frontalface_alt.xml";//Face
String LeftEye_fileName = "haarcascade_lefteye_2splits.xml";//LeftEye
String RightEye_fileName = "haarcascade_righteye_2splits.xml";//RightEye
CascadeClassifier Face_cascade;
CascadeClassifier Left_cascade;
CascadeClassifier Right_cascade;
Rect LeftEye_teml, RightEye_teml;
void TrackEye(Mat& in_img, Mat& template_img, Rect& rect);//保存眼睛的位置,用于跟踪
int main(int argc, char** argv)
{
if (!Face_cascade.load(Face_fileName))//人脸
{
cout << "Haar_cascade error" << endl;
return -1;
};
if (!Left_cascade.load(LeftEye_fileName))//左眼
{
cout << "Haar_cascade error" << endl;
return -2;
};
if (!Right_cascade.load(RightEye_fileName))//右眼
{
cout << "Haar_cascade error" << endl;
return -3;
};
VideoCapture capture;
Mat frame, gray;
vector faces;
vector leftEye;
vector rightEye;
Mat leftTemplate, rightTemplate; //眼睛模板
capture.open("../path.mp4");//读入视频流
while (capture.read(frame))
{
cvtColor(frame, gray, COLOR_BGR2GRAY);//转灰度
equalizeHist(gray, gray);//直方图均衡化
Face_cascade.detectMultiScale(gray, faces, 1.2, 3, 0, Size(30, 30));//LBP级联分类器
for (size_t i = 0; i < faces.size(); i++)
{
//画圆形
Point center(faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5);
ellipse(frame, center, Size(faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar(255, 0, 255), 4, 8, 0);
//计算offset
int offset_y = faces[i].height / 4;//人脸检测的区域减去1/4(上方区域)
int offset_x = faces[i].width / 8;//人脸检测的区域减去1/8(左右区域)
int eye_height = faces[i].height / 2 - offset_y;//人眼区域高度
int eye_width = faces[i].width / 2 - offset_x;//人眼区域宽度度
//截取左眼区域
Rect leftRect;
leftRect.x = faces[i].x + offset_x;//左眼起始点x
leftRect.y = faces[i].y + offset_y;//左眼起始点y
leftRect.width = eye_width;//左眼区域宽度
leftRect.height = eye_height;//左眼区域高度
Mat LeftEye_ROI = gray(leftRect);//gray中的左眼区域
//检测左眼
Left_cascade.detectMultiScale(LeftEye_ROI, leftEye, 1.1, 1, 0, Size(20, 20));
if (leftTemplate.empty())//如果模板为空,就执行人眼检测
{
if (leftEye.size())
{
for (size_t j = 0; j 0 && LeftEye_teml.y > 0)
{
LeftEye_teml.width = leftTemplate.cols;
LeftEye_teml.height = leftTemplate.rows;
rectangle(frame, LeftEye_teml, Scalar(0, 0, 255), 2, 8, 0);
}
}
//----------------------------左右眼分割线--------------------------------//
//截取右眼区域
Rect rightRect;
rightRect.x = faces[i].x + faces[i].width / 2;//右眼起始点x
rightRect.y = faces[i].y + offset_y;//右眼起始点y(左上角为起始点)
rightRect.width = eye_width;//右眼区域宽度
rightRect.height = eye_height;//右眼区域高度
Mat RightEye_ROI = gray(rightRect);//gray中的右眼区域
//检测右眼
Right_cascade.detectMultiScale(RightEye_ROI, rightEye, 1.1, 1, 0, Size(20, 20));
if (rightTemplate.empty())//如果模板为空,就执行人眼检测
{
if (rightEye.size())
{
for (size_t k = 0; k 0&& RightEye_teml.y >0)
{
RightEye_teml.width = rightTemplate.cols;
RightEye_teml.height = rightTemplate.rows;
rectangle(frame, RightEye_teml, Scalar(0, 255, 255), 2, 8, 0);
}
}
}
imshow("Face_detection", frame);
char c = waitKey(50);
if (c == 27)
{
break;
}
}
//释放资源
capture.release();
waitKey(0);
return 0;
}
void TrackEye(Mat& in_img, Mat& template_img, Rect& rect)
{
Mat result;//用于存储图片
int result_cols = in_img.cols - template_img.cols + 1;
int result_rows = in_img.rows - template_img.rows + 1;
// 模板匹配
result.create(result_rows, result_cols, CV_32FC1);
//不基于直方图,而是使用一个图像块在输入图像上进行"滑动"
matchTemplate(in_img, //被查找的图像
template_img, //模板//包含给定物体的(和当前图片相似的)另一张图片上取的图像块,计算结果存放在result中
result, //用于存储图片
TM_CCORR_NORMED);//method归一化的互相关匹配方法,如果不匹配返回0,如果完全匹配返回1//定位一个大小相当于图像块的物体:要寻找的物体使用 色调饱和度(HSV)直方图 进行建模,可以和整个图像的HS直方图进行比较
//寻找位置
double minval, maxval;//值
Point minloc, maxloc;//位置
minMaxLoc(result, &minval, &maxval, &minloc, &maxloc);//求矩阵最大(最小)值
if (maxval > 0.75) //TM_CCORR_NORMED匹配极大相关
{
rect.x = rect.x + maxloc.x;//绘制的显示框会自动跟踪
rect.y = rect.y + maxloc.y;
}
else //TM_CCORR_NORMED匹配值相关小
{
rect.x = rect.y = rect.width = rect.height = 0;//绘制的显示框保持不动
}
return;
}
输出结果: