CascadeClassifier(级联分类器)学习与使用

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值