目录
备注
人眼检测有误,需要调整相关参数;
实验代码
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <vector>
using namespace std;
using namespace cv;
void ShowDrawFace(Mat img, double fps1);
int main()
{
// 打开视频文件
VideoCapture cap("1.mp4");
// 检查是否成功打开文件
if (!cap.isOpened())
{
cout << "Error opening video file" << endl;
return -1;
}
// 获取视频的帧率
double fps = cap.get(CAP_PROP_FPS);
cout << "Frames per second using video.get(cv::CAP_PROP_FPS): " << fps << endl;
// 循环读取并显示每一帧
Mat frame;
while (true)
{
// 从视频中读取一帧
cap >> frame;
// 如果没有读取到帧,则退出循环
if (frame.empty())
{
break;
}
ShowDrawFace(frame, fps);
// 显示这一帧
//namedWindow("Video", WINDOW_NORMAL);
//imshow("Video", frame);
//resizeWindow("Video",500,750);
// 按键退出
/*if (waitKey(1000 / fps) >= 0)
{
break;
}*/
}
// 释放资源
cap.release();
// 销毁所有窗口
destroyAllWindows();
return 0;
}
void ShowDrawFace(Mat img, double fps1)
{
// 加载级联分类器文件
CascadeClassifier face_cascade;
//确保您正确加载了级联分类器文件。
if (!face_cascade.load("haarcascade_frontalface_alt.xml"))
{
cout << "--(!)Error loading face cascade\n";
return;
}
//加载眼睛检测模型
cv::CascadeClassifier eye_cascade;
if (!eye_cascade.load("haarcascade_eye.xml"))
{
std::cout << "Error: Could not load eye cascade!" << std::endl;
return;
}
if (img.empty())
{
cout << "--(!) No image detected. Please check file path." << endl;
return;
}
static CvScalar colors[] =
{
{ 0, 0, 255 },//纯蓝色(BGR格式)
{ 0, 128, 255 },//蓝绿色
{ 0, 255, 255 },//青色(Cyan)
{ 0, 255, 0 },//纯绿色
{ 255, 128, 0 },//橙黄色
{ 255, 255, 0 },//黄色
{ 255, 0, 0 },//纯红色
{ 255, 0, 255 }//洋红色(Magenta)
};//这样的数组通常用于需要固定颜色集的情况,比如在图像中标记不同的对象或区域,或者在绘制图形时使用不同的颜色。
// 转换为灰度图
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
// 检测人脸
std::vector<Rect> faces;
face_cascade.detectMultiScale(gray, faces, 1.1, 3, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
//人脸检测:使用detectMultiScale函数检测人脸。
//这里的参数1.1是缩放因子,3是最小邻居数,0 | CASCADE_SCALE_IMAGE是标志位,Size(30, 30)是最小检测窗口尺寸。
//检测每张脸中的眼睛
// 遍历所有检测到的人脸
int i = 0;
for (const auto& face : faces)//用于遍历容器中的元素。
{
//int i = faces.; 能获取本次循环的次数?
//确认人脸位置
{
const Rect& r = face;
// 计算中心点
Point center;
int radius;
center.x = cvRound((r.x + r.width * 0.5));
center.y = cvRound((r.y + r.height * 0.5));
radius = cvRound((r.width + r.height) * 0.25);
//使用 (r.x + r.width * 0.5) 和 (r.y + r.height * 0.5) 来计算中心点。
//请注意,这里的坐标计算没有涉及到任何缩放因子,因为我们直接处理原始图像的尺寸。
// 绘制圆形
//circle(img, center, radius, Scalar(0, 0, 255), 2, LINE_8, 0);
circle(img, center, radius, colors[i % 8], 2, LINE_8, 0);
// 在图像上绘制矩形框
//rectangle(img, r, Scalar(0, 255, 0), 2, 1, 0);
//colors[i%8]
rectangle(img, r, colors[i % 8], 2, 1, 0);
}
Mat faceROI = gray(face); 或者 cv::Mat faceROI = gray(face.x, face.y, face.width, face.height);
提取人脸区域的灰度子图
vector<cv::Rect> eyes;
eye_cascade.detectMultiScale(faceROI, eyes, 1.1, 3, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30));
// 在原图上绘制眼睛的矩形框
for (const auto& eye : eyes)
{
Rect eyeRect(face.x + eye.x, face.y + eye.y, eye.width, eye.height);
//cv::rectangle(img, eyeRect, cv::Scalar(255, 0, 0), 2);
rectangle(img, eyeRect, colors[i % 8], 2);
}
i++;//确认循环的次数
}
// 显示带有标注的图像
namedWindow("Faces found", WINDOW_NORMAL);
resizeWindow("Faces found", 500, 750);
imshow("Faces found", img);
// 等待用户按键
waitKey(1000 / fps1);
}