手把手教你OpenCV实现实时人脸检测(C++)

news2024/12/26 14:27:37

目录

1,原理介绍

2,代码讲解

3,全部代码

4,结果展示


1,原理介绍

haarcascade_frontalface_default.xml 是一个 XML 文件,它包含了使用 Haar 特征分类器训练得到的人脸检测模型。这个模型是 OpenCV 库自带的,常用于实时人脸检测任务。下面详细介绍这个模型的几个方面:

  1. Haar 特征: Haar 特征是基于图像的小波特征,它们能够捕捉图像中的局部变化,如边缘、纹理等。这些特征对于物体检测尤其有用,因为它们能够描述物体的某些属性。

  2. 级联分类器: haarcascade_frontalface_default.xml 中的模型是一个级联分类器,这意味着它由多个阶段的分类器组成。每个阶段都会对输入图像进行分类,如果图像通过了所有阶段的检测,它就被认为是正面人脸。

  3. 训练过程: 这个模型是通过在正面人脸和非人脸图像数据集上训练得到的。训练过程中,算法学习区分人脸和非人脸的特征。

  4. 实时性能: Haar 级联分类器因其计算效率较高,通常用于实时人脸检测。尽管它可能不如深度学习模型那样精确,但在许多实时应用中已经足够使用。

  5. 使用方式: 在 OpenCV 中,可以使用 CascadeClassifier 类加载这个 XML 文件,并调用 detectMultiScale 方法来检测图像或视频流中的人脸。

  6. 参数调整: detectMultiScale 方法允许调整多个参数,如缩放因子、邻居窗口的数量、检测的最小和最大邻居尺寸等,以适应不同的检测需求。

  7. 局限性: Haar 级联分类器可能在复杂场景中表现不佳,例如,当人脸被遮挡或光照条件不佳时。此外,它可能无法很好地处理不同姿态的人脸(如侧面人脸)。

  8. 可扩展性: 除了正面人脸检测,OpenCV 还提供了其他类型的 Haar 级联分类器,如 haarcascade_profileface.xml 用于检测侧脸,haarcascade_eye.xml 用于检测眼睛等。

2,代码讲解

#include <iostream> #include <opencv2/opencv.hpp>

这两行代码包含了必要的头文件。iostream 是标准输入输出流库,opencv2/opencv.hpp 是 OpenCV 的主头文件。

using namespace std; using namespace cv;

这两行代码使用 stdcv 命名空间中的所有名称,这样在调用函数和类型时就不需要前缀。

void face_detect_demo() { // ... }

定义了一个名为 face_detect_demo 的函数,用于执行人脸检测演示。

cv::CascadeClassifier face_cascade;

创建了一个 CascadeClassifier 对象,用于加载和使用级联分类器进行人脸检测。

 

if (!face_cascade.load("...")) { std::cerr << "Error loading face cascade model!" << std::endl; return; }

尝试加载人脸检测模型(XML 文件)。如果加载失败,输出错误信息并返回。

cv::VideoCapture capture(0);

创建了一个 VideoCapture 对象,尝试打开默认摄像头。

 

if (!capture.isOpened()) { std::cerr << "Error opening camera!" << std::endl; return; }

检查摄像头是否成功打开,如果失败,输出错误信息并返回。

cv::Mat frame; while (capture.read(frame)) { // ... }

循环读取摄像头的每一帧图像。如果无法读取帧,循环将终止。

cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);

将当前帧从 BGR 颜色空间转换为灰度图像。

cv::equalizeHist(gray, gray);

对灰度图像进行直方图均衡化,以提高图像的对比度。

cv::bilateralFilter(gray, dst, 20, 150, 150);

对灰度图像应用双边滤波,以减少噪声并保留边缘。

std::vector<cv::Rect> faces; face_cascade.detectMultiScale(dst, faces, 1.1, 3, 0, cv::Size(30, 30));

使用 CascadeClassifier 对象在图像 dst 中检测人脸,并返回检测到的人脸区域列表。

for (const auto& face : faces) { cv::rectangle(frame, face, cv::Scalar(255, 0, 0), 2); }

遍历检测到的每个人脸区域,并在原始帧图像上绘制蓝色矩形框。

cv::imshow("Face Detection Demo", frame);

在窗口 "Face Detection Demo" 中显示带有人脸标记的帧图像。

if (cv::waitKey(30) == 27) { break; }

等待 30 毫秒的按键事件,如果检测到按键值为 27(ESC 键),则退出循环。

capture.release(); cv::destroyAllWindows();

释放摄像头资源并销毁所有创建的窗口。

int main() { // ... }

程序的入口点。

Mat img = imread("2.png"); if (img.empty()) { cout << "Could not open or find the image" << endl; return -1; }

尝试读取名为 "2.png" 的图像文件。如果文件无法打开或找不到,输出错误信息并返回 -1

face_detect_demo();

调用 face_detect_demo 函数执行人脸检测演示。

return 0;

正常退出程序,返回 0 表示成功状态。


3,全部代码

#include <iostream>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;


void face_detect_demo()
{
	// 加载人脸检测器模型
	cv::CascadeClassifier face_cascade;
	if (!face_cascade.load("E:/Opencv/opencv/build/etc/haarcascades/haarcascade_frontalface_default.xml"))
	{
		std::cerr << "Error loading face cascade model!" << std::endl;
		return;
	}

	// 在这里添加进行人脸检测的代码

	// 例如,可以在摄像头捕获的每一帧上运行人脸检测
	cv::VideoCapture capture(0);  // 打开默认摄像头
	if (!capture.isOpened())
	{
		std::cerr << "Error opening camera!" << std::endl;
		return;
	}

	cv::Mat frame;
	while (capture.read(frame))
	{
		// 转换图像为灰度图
		cv::Mat gray;
		cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
		cv::equalizeHist(gray, gray);  // 直方图均衡化提高对比度

		//进行双边滤波
		cv::Mat dst;
		cv::bilateralFilter(gray, dst, 20, 150, 150);

		// 进行人脸检测
		std::vector<cv::Rect> faces;
		face_cascade.detectMultiScale(dst, faces, 1.1, 3, 0, cv::Size(30, 30));

		// 在图像上标记检测到的人脸
		for (const auto& face : faces)
		{
			cv::rectangle(frame, face, cv::Scalar(255, 0, 0), 2);  // 用蓝色矩形标记人脸
		}

		// 显示结果
		cv::imshow("Face Detection Demo", frame);

		// 检测按键,按下ESC键退出循环
		if (cv::waitKey(30) == 27)
		{
			break;
		}
	}
	capture.release();	// 释放摄像头
	cv::destroyAllWindows();	// 销毁所有窗口
}

int main()
{
	Mat img = imread("2.png");
	if (img.empty())
	{
		cout << "Could not open or find the image" << endl;
		return -1;  //return -1; 通常用作从 main 函数返回一个错误状态码
	}

	face_detect_demo();

	return 0;
}

4,结果展示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1972178.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【小知识】站在前人的肩膀上写程序——STL库初阶算法函数的使用

【小知识】站在前人的肩膀上写程序——STL库初阶算法函数的使用 1.墨水瓶算法和swap函数2.打擂台算法和max&#xff0c;min函数3.排序——sort函数 1.墨水瓶算法和swap函数 如果想交换两个墨水瓶的墨水该怎么办呢&#xff1f;我们可以准备第三个墨水瓶。将第一个墨水瓶的墨水倒…

linux安装配置jdk

①下载jdk安装包&#xff0c;放在/opt/app/software/java下 cd /opt/app/software/java②进行解压操作 tar -zxvf jdk-8u251-linux-x64.tar.gz③解压完成之后&#xff0c;进行环境变量的配置&#xff0c;shell下执行 vi ~/.bash_profile根据jdk的安装目录&#xff0c;加入 …

LeeCode Practice Journal | Day31_GA05

56. 合并区间 题目&#xff1a;56. 合并区间 - 力扣&#xff08;LeetCode&#xff09; 题解&#xff1a;代码随想录 (programmercarl.com) 思路很清晰&#xff0c;对数组的操作稀烂&#xff0c;细节上也出现很多问题 solution public class Solution {public int[][] Merge(in…

2024全新Thinkphp聊天室H5实时聊天室群聊聊天室自动分配账户完群组/私聊/禁言等功能/全开源运营版本

全开源运营版本聊天室H5实时聊天室群聊聊天室自动分配账户完群组/私聊/禁言等功能 运营版本的聊天室&#xff0c;可以添加好友&#xff0c;建立群组&#xff0c;私聊&#xff0c;禁言功能 H5TP5.0mysqlPHP 源码开源不加密

【python】Python二手房住房数据抓取可视化(源码+数据集+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

python爬取豆瓣电影top250-python实战项目,手把手教学,附源码

目录 1、分析网页2、请求服务器 2.1导入包2.2设置浏览器代理2.3请求服务器格式2.4请求服务器代码汇总 3.xpath提取信息 3.1获取xpath节点的方法3.2xpath提取内容3.2.1提取文本3.2.2提取链接3.2.3提取标签元素 4.正则表达式 4.1提取固定位置的信息4.2匹配出数字 5、提取一页中的…

Java 并发编程:Java 线程池的介绍与使用

大家好&#xff0c;我是栗筝i&#xff0c;这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 024 篇文章&#xff0c;在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验&#xff0c;并希望进…

细分 Insight 合作伙伴 2024 年企业技术状况报告

Insight Partners 的团队刚刚发布了 2024 年企业技术状况报告。在 60 幻灯片中有很多东西可以消耗&#xff0c;但我们挑选了应该让我们的观众感兴趣的东西 - 坦率地说&#xff0c;有很多有趣的东西。我将把调查方法的东西留给你使用&#xff0c;但足以说样本量很大&#xff0c;…

dami支付漏洞

使用burpsuite等抓包工具&#xff0c;抓取数据包后&#xff0c;修改数据包中的参数从而达到支付篡改的目的&#xff1b;篡 改的参数&#xff1a;商品ID&#xff0c;购买价格&#xff0c;购买数量&#xff0c;手机号码&#xff0c;订单D&#xff0c;支付状态 常见漏洞利用手段…

国家网络身份个人认证方法

申领网络身份认证后&#xff0c;用户会得到一张虚拟的“网络身份证”&#xff0c;它可以向需要实名认证的互联网平台进行认证&#xff0c;不再需要输入姓名和身份证号等信息。 申请方式&#xff1a;各手机应用平台搜索国家网络身份认证即可&#xff08;必须支持NFC才能申请&am…

AI产品经理必备:什么是LLM,有什么优劣势

LLM&#xff08;Large Language Model大型语言模型&#xff09;是一种人工智能技术&#xff0c;能够理解和生成自然语言文本。LLM可以应用于多种场景&#xff0c;包括自然语言理解、文本生成、机器翻译、对话系统、问答系统、文本摘要、情感分析等。可以帮助人们快速生成文章、…

c# 构造器的声明与调用

在C#中&#xff0c;构造器&#xff08;Constructor&#xff09;是一种特殊类型的函数&#xff0c;用于初始化类的新实例。构造器的名字必须与类名完全相同&#xff0c;并且没有返回类型&#xff0c;甚至连void也不行。 当创建类的一个新实例时&#xff0c;构造器会自动被调用。…

全球轻型电动轮椅市场规划预测:未来六年CAGR为7.3%

随着全球人口老龄化的加剧和消费者对便捷、高效出行工具的需求增加&#xff0c;轻型电动轮椅作为提升行动不便人士生活质量的重要工具&#xff0c;正逐渐受到市场的广泛关注。本文旨在通过深度分析轻型电动轮椅行业的各个维度&#xff0c;揭示行业发展趋势和潜在机会。 【市场…

StudyStudyStudy第十六天(2024.8.2)

1.代理模式 代理模式分为静态代理和动态代理 代理模式&#xff0c;就是在想要执行的代码之前或之后添加代码块&#xff0c;并不会破坏原有的代码结构。可以理解成加上了一个访问层 1.静态代理 创建一个接口Shopping public interface Shopping {void shopping(); }创建一个…

笔记:唐老师讲电赛之唐老师讲电子器件(1)电阻 参数与选型

电阻 a . 精度 电阻----运放中的电阻要选精度高的&#xff0c;一般0.1% 若在设计电路中电路参数由某个电阻决定&#xff0c;则需要选取高精度电阻。例如&#xff0c;反向放大器等对于反馈系数、增益等参数完全由电阻决定的&#xff0c;则需要选取精度较高的电阻&#xff0c;…

PDF文件点击打印无反应?是何原因造成能解决吗?

PDF无法打印怎么处理&#xff1f;在我们工作中&#xff0c;经常会遇见各种各样的文件问题&#xff0c;当我们想要将PDF文件打印出来纸质版使用&#xff0c;却不知什么原因&#xff0c;显示PDF无法打印&#xff0c;这时应该怎么处理呢&#xff1f; 一般情况下&#xff0c;PDF文件…

园区运营管理系统是如何提升园区管理水平和运营效率的?

随着大数据、人工智能等新一代信息技术的迅猛发展&#xff0c;园区运营管理系统逐渐成为提升园区运营效率的重要工具。园区运营管理系统涵盖了运营监测、企业管理、企业服务、项目管理、资产管理、智能办公、物业管理、集成监控等核心功能&#xff0c;利用这些功能可以大幅提升…

Ecovadis认证标准|Ecovadis认证是什么

三分钟内&#xff0c;让我们深入探索Ecovadis认证的广阔世界&#xff0c;这是一场绿色革命中的璀璨明珠&#xff0c;引领着全球企业迈向可持续发展的新纪元。 Ecovadis认证&#xff0c;犹如绿色经济浪潮中的一盏明灯&#xff0c;它不仅照亮了企业责任与环保实践的融合之路&…

动态申请的二维数组不是连续的

在初学阶段&#xff0c;曾学过二维数组的内存空间是连续分布的&#xff0c;参考下图&#xff1a; 后来由于动态申请二维数组的方法不常用&#xff08;一般都是用vector或者直接定义一个二维数组&#xff09;&#xff0c;所以就一直以为二维数组的内存空间是连续的。但实际上&a…

OpenCV仿射变换实现图像扭曲与旋转

目录 1. 仿射变换 2. 仿射变换的求解 3. 代码实现 3.1 图像扭曲 3.2 图像旋转 参考内容 1. 仿射变换 仿射变换是一种可以表达为乘以一个矩阵&#xff08;线性变换&#xff09;再加上一个向量&#xff08;平移&#xff09;的变换。在几何中&#xff0c;就是将一个向量空间…