OpenCV 学习笔记 —— CascadeClassifier 级联分类器(人脸检测)
CascadeClassifier 是 OpenCV 提供的级联分类器实现,
可以加载训练好的分类器(如 Haar / LBP 特征模型),完成快速检测。
它主要用于:
- 人脸检测
- 眼睛检测
- 行人检测
- 车牌检测
以人脸检测为例,如果检测到人脸则绘制正方形方框
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
//加载人脸检测模型
CascadeClassifier face_detected;
String model_path = "haarcascade_frontalface_default.xml";
cout << "<<加载人脸检测模型>>" << endl;
if (!face_detected.load(model_path))
{
cout << "无法加载人脸识别模型" << endl;
return -1;
}
cout << "<<人脸检测模型加载成功>>" << endl;
//摄像头设置
VideoCapture cap(0);
if (!cap.isOpened())
{
cout << "摄像头打开失败" << endl;
return -1;
}
//设置摄像头分辨率
cap.set(CAP_PROP_FRAME_WIDTH, 1280);
cap.set(CAP_PROP_FRAME_HEIGHT, 720);
cout << "摄像头已打开,分辨率:"
<< cap.get(CAP_PROP_FRAME_WIDTH) << "x"
<< cap.get(CAP_PROP_FRAME_HEIGHT) << endl;
cout << "\n【操作提示】" << endl;
cout << "# 按 'q' 键退出" << endl;
cout << "# 按 's' 键保存当前帧" << endl;
cout << "# 按 空格 暂停/继续" << endl;
cout << "\n开始检测..." << endl;
//主循环
Mat frame, gray;
int frame_count = 0; //帧计数器
int saved_count = 0; // 保存计数器
int total_faces_detected = 0; // 累计检测到的人脸总数
int max_faces_once = 0; // 单帧最大人脸数
int frames_with_face = 0; // 有人脸的帧数
while (true)
{
cap >> frame;
if (frame.empty())
{
cout << "无法读取摄像头帧" << endl;
break;
}
frame_count++;
//转灰度图
cvtColor(frame, gray, COLOR_BGR2GRAY);//转换成灰度图
//检测人脸
vector<Rect> faces;
face_detected.detectMultiScale(
gray,
faces,
1.1, // 1.2→1.1 更精细的多尺度检测
4, // 7→4 降低过滤强度,提高检测率
0,
Size(30, 30) // 50→30 检测更小的人脸(远距离)
);
for (size_t i = 0; i < faces.size(); i++)
{
rectangle(frame, faces[i], Scalar(0, 255, 0), 3);
string label = "Face " + to_string(i + 1);
putText(frame, label,
Point(faces[i].x, faces[i].y),
FONT_HERSHEY_SIMPLEX,
0.9,
Scalar(0, 255, 0),
2
);
}
//更新数据
int current_faces = faces.size();
if (current_faces)
{
frames_with_face++;
total_faces_detected += current_faces;
if (current_faces > max_faces_once)
{
max_faces_once = current_faces;
}
}
//绘制统计面板
// 创建半透明黑色背景
Mat overlay = frame.clone();
rectangle(overlay, Point(0, 0), Point(500, 250),
Scalar(0, 0, 0), -1);
addWeighted(overlay, 0.7, frame, 0.3, 0, frame);
// 标题
putText(frame, "=== Face Counter ===",
Point(100, 40),
FONT_HERSHEY_SIMPLEX,
1.0,
Scalar(0, 255, 255),
2);
// 当前检测数
String info_current = "Current: " + to_string(current_faces) + " faces";
putText(frame, info_current,
Point(20, 80),
FONT_HERSHEY_SIMPLEX,
0.8,
Scalar(0, 255, 0),
2);
// 最大检测数
String info_max = "Max (once): " + to_string(max_faces_once);
putText(frame, info_max,
Point(20, 115),
FONT_HERSHEY_SIMPLEX,
0.7,
Scalar(255, 200, 0),
2);
// 总检测数
String info_total = "Total detected: " + to_string(total_faces_detected);
putText(frame, info_total,
Point(20, 150),
FONT_HERSHEY_SIMPLEX,
0.7,
Scalar(255, 150, 0),
2);
// 检测率
float detection_rate = frame_count > 0 ?
(float)frames_with_face / frame_count * 100 : 0;
String info_rate = "Detection rate: " +
to_string((int)detection_rate) + "%";
putText(frame, info_rate,
Point(20, 185),
FONT_HERSHEY_SIMPLEX,
0.7,
Scalar(100, 200, 255),
2);
// 帧数
String info_frames = "Frames: " + to_string(frame_count);
putText(frame, info_frames,
Point(20, 220),
FONT_HERSHEY_SIMPLEX,
0.6,
Scalar(200, 200, 200),
1);
// 底部操作提示
putText(frame, "Q:Quit | S:Save | R:Reset",
Point(10, frame.rows - 20),
FONT_HERSHEY_SIMPLEX,
0.6,
Scalar(255, 255, 255),
1);
imshow("Face Counter", frame);
//按键控制
char key = waitKey(1); // 改为 1 毫秒,实现实时视频
if (key == 'q' || key == 'Q' || key == 27) {
cout << "\n退出程序..." << endl;
break;
}
else if (key == 's' || key == 'S') {
String filename = "face_counter_" + to_string(++saved_count) + ".jpg";
imwrite(filename, frame);
cout << "✅ 已保存:" << filename << endl;
}
else if (key == 'r' || key == 'R') {
// 重置统计
total_faces_detected = 0;
max_faces_once = 0;
frames_with_face = 0;
frame_count = 0;
cout << " 已重置计数" << endl;
}
}
cap.release();
destroyAllWindows();
return 0;
}
1万+

被折叠的 条评论
为什么被折叠?



