人工智能实验:人脸检测

一、实现目的:

  1. 了解人脸检测的主要方法;
  2. 了解 detectMultiScale 函数的功能及用法;
  3. 掌握使用 OpenCV 提供的分类器和检测器进行人脸检测的方法。

二、实验设备:

  1. 计算机一台;
  2. 视觉实验软件环境及资源一套(visual studio 2022,opencv-4.8)。

环境配置请参考以下文章:

  1. http://t.csdnimg.cn/ku3rS
  2. http://t.csdnimg.cn/owEsG
  3. http://t.csdnimg.cn/vEe72

三、实验原理:

人脸检测(Face Detection),就是给一幅图像,找出图像中的所有人脸位置, 通常用一个矩形框框起来,如下图所示。其输入是一幅图像 image,输出是若 干个包含人脸的矩形框位置(x,y,w,h)。人脸检测属于计算机视觉的范畴,早期人 们的主要研究方向是人脸识别,即根据人脸来识别人物的身份,后来在复杂背景 下的人脸检测需求越来越大,人脸检测也逐渐作为一个单独的研究方向发展起来。 目前人脸检测的方法主要有以下两大类。

287b39fd3705482f9a25f6881eb784d5.png

基于知识的方法:主要利用先验知识将人脸看作器官特征的组合,根据眼睛、 眉毛、嘴巴、鼻子等器官的特征以及相互之间的几何位置关系来检测人脸。主要 包括模板匹配、人脸特征、形状与边缘、纹理特性、颜色特征等方法。

基于统计的方法:将人脸看作一个整体的模式——二维像素矩阵,从统计的 观点通过大量人脸图像样本构造人脸模式空间,根据相似度来判断人脸是否存在。 主要包括主成分分析与特征脸、神经网络方法、支持向量机、隐马尔可夫模型、 Adaboost 算法等。

本次实验将使用Haar+AdaBoost 的算法,实现任意图像中人脸的检测。OpenCV 自带了训练器和检测器,还包含了人脸检测的 XML 文件, 如下图所示。这些文件位于:

D:\software\other\opencv\build\etc\haarcascades
# 其中:D:\software\other是我自己的安装目录

文件夹, 主要保存相关的特征矩阵,以及各个弱分类器相关的信息,可用于检测静止图像、 视频和摄像头所得到图像中的人脸。除此之外还有一个同级文件夹是 lbpcascades, 它不是通过 Haar 特征进行人脸检测,而是采用的 LBP 特征,这里仅作了解,不再细究。

d97716a0f9b14081b62c8220cbed1d37.png

四、算法接口:

CascadeClassifier 是 OpenCV 中用来做目标检测的级联分类器的一个类。早期 OpenCV 版本仅支持 Haar 特征的目标检测,新版本开始支持 LBP 和 HOG 特 征的目标检测。CascadeClassifier 类有一个 detectMultiScale 的成员函数用于调整检测参数,检测目标图像并得到检测结果。

void detectMultiScale( InputArray image,
 std::vector<Rect>& objects,
 double scaleFactor = 1.1, 
 int minNeighbors = 3,
 int flags = 0,
 Size minSize = Size(), Size maxSize = Size());

【image】:输入图像。

【objects】:检测到的目标的矩形框向量组。

【scaleFactor】:在前后两次相继的扫描中搜索窗口的比例系数。默认为 1.1,即每次搜索    窗口依次扩大 10%。

【minNeighbors】:每个目标至少要被检测到不低于该值的次数才算是真的目标。

【flags】:旧版本的 OpenCV 1.x 使用的参数,当前版本已被忽略。

【minSize 和 maxSize】:限制检测到的目标尺寸。

五、实验任务:

1 基础任务:

  1. 搭建实验环境;
  2. 根据指导书示例完成人脸检测实验;
  3. 完成实验报告。

2 拓展任务:

  1. 调整 minNeighbors 参数的值,观察对人脸检测结果的影响。
  2. 调整 minSize 和 maxSize 参数的值,观察对人脸检测结果的影响。
  3. 修改程序,实现在视频流中进行动态的人脸检测。

六、实验内容:

1 搭建实验环境:

见上述推荐的参考文章。

2 人脸检测示例运行:

2.1 人脸识别:

2.1.1 测试代码:

//人脸检测
#include <vector>
#include <opencv2/opencv.hpp>
int main()
{
	// 创建级联分类器对象,并加载 OpenCV 自带的人脸分类器
	cv::CascadeClassifier faceDetector("D:/software/other/opencv/build/etc/haarcascades/haarcascade_frontalface_alt2.xml");
		cv::Mat image = cv::imread("D:/Projects/visio projects/opencv_test1/test_picture/test1.jpg");
	// 用于储存检测结果的矩形框向量组
	std::vector<cv::Rect> objects;
	// 使用分类器进行目标检测,并设置相关参数
	faceDetector.detectMultiScale(image, objects, 1.1, 3);
	// 在原图上绘制检测得到的矩形框,并显示出来
	for (int i = 0; i < objects.size(); ++i) {
		cv::rectangle(image, objects[i], cv::Scalar(0, 0, 255));
	}
	cv::imshow("face_detection", image);
	cv::waitKey(0);
	return 0;
}

2.1.2 运行结果:

ea8944a32a7f4ffe8053e54daa06fe93.png

注意这里左下角有个柱子被错误的检测为人脸,后面有用。

2.2 猫脸识别:

2.2.1 测试代码:

//猫脸识别
#include <vector>
#include <opencv2/opencv.hpp>
int main()
{
	// 创建级联分类器对象,并加载 OpenCV 自带的猫脸分类器
	cv::CascadeClassifier faceDetector("D:/software/other/opencv/build/etc/haarcascades/haarcascade_frontalcatface.xml");
	cv::Mat image = cv::imread("D:/Projects/visio projects/opencv_test1/test_picture/test3.jpg");
// 用于储存检测结果的矩形框向量组
std::vector<cv::Rect> objects;
// 使用分类器进行目标检测,并设置相关参数
faceDetector.detectMultiScale(image, objects, 1.1, 3);
// 在原图上绘制检测得到的矩形框,并显示出来
for (int i = 0; i < objects.size(); ++i) {
cv::rectangle(image, objects[i], cv::Scalar(0, 255, 0));
}
cv::imshow("cat_face_detection", image);
cv::waitKey(0);
return 0;
		}

2.2.2 运行结果:

c817f56c13c748f2ad9ec806df2378e4.png

3 拓展任务:

(1)调整人脸识别代码中的 minNeighbors 参数的值从3调整为30:

	faceDetector.detectMultiScale(image, objects, 1.1, 30);
974bb592516e44c59e106381f86ff8a4.png

可以观察到,原来被误识别为人脸的柱子的检测框不见了。

 

(2)调整猫脸识别代码中的 minSize 和 maxSize 参数的值:

因为测试代码中没有定义minSize 和 maxSize 参数的值,所以我们加入以下代码:

// 调整 minSize 和 maxSize 参数的值
cv::Size minSize(10, 10); // 设置最小尺寸
cv::Size maxSize(50, 50); // 设置最大尺寸

// 使用分类器进行目标检测,并设置相关参数
faceDetector.detectMultiScale(image, objects, 1.1, 3, 0, minSize, maxSize);

新的完整代码如下:

//猫脸识别
#include <vector>
#include <opencv2/opencv.hpp>
int main()
{
	// 创建级联分类器对象,并加载 OpenCV 自带的猫脸分类器
	cv::CascadeClassifier faceDetector("D:/software/other/opencv/build/etc/haarcascades/haarcascade_frontalcatface.xml");
	cv::Mat image = cv::imread("D:/Projects/visio projects/opencv_test1/test_picture/test3.jpg");
// 用于储存检测结果的矩形框向量组
std::vector<cv::Rect> objects;
// 调整 minSize 和 maxSize 参数的值
cv::Size minSize(10, 10); // 设置最小尺寸
cv::Size maxSize(50, 50); // 设置最大尺寸

// 使用分类器进行目标检测,并设置相关参数
faceDetector.detectMultiScale(image, objects, 1.1, 3, 0, minSize, maxSize);
// 在原图上绘制检测得到的矩形框,并显示出来
for (int i = 0; i < objects.size(); ++i) {
cv::rectangle(image, objects[i], cv::Scalar(0, 255, 0));
}
cv::imshow("cat_face_detection", image);
cv::waitKey(0);
return 0;
		}
3a431888a5294e6f821aa1bdec70dc97.png

可以看到脸大的猫猫都检测不到了

(3)修改程序,实现在视频流中进行动态的人脸检测:

要在视频流中进行动态人脸检测,需要使用 OpenCV 读取实时视频流(例如,从网络摄像头获取的视频)并对每一帧进行人脸检测,代码如下:

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

int main()
{
    // 创建级联分类器对象,并加载 OpenCV 自带的人脸分类器
    cv::CascadeClassifier faceDetector("D:/software/other/opencv/build/etc/haarcascades/haarcascade_frontalface_alt2.xml");

    // 创建视频捕获对象,从默认摄像头读取视频
    cv::VideoCapture cap(0); // 0 表示默认摄像头

    if (!cap.isOpened()) {
        std::cerr << "Error: Unable to open camera" << std::endl;
        return -1;
    }

    // 循环读取视频流的每一帧
    while (true) {
        cv::Mat frame;
        cap >> frame; // 获取当前帧

        if (frame.empty()) {
            std::cerr << "Error: Empty frame" << std::endl;
            break;
        }

        // 用于储存检测结果的矩形框向量组
        std::vector<cv::Rect> faces;

        // 使用分类器进行人脸检测,调整缩放因子和最小邻近数等参数
        faceDetector.detectMultiScale(frame, faces, 1.1, 3, 0, cv::Size(30, 30));

        // 在帧上绘制检测得到的矩形框
        for (const auto& face : faces) {
            cv::rectangle(frame, face, cv::Scalar(0, 0, 255), 2); // 红色矩形框,线宽为 2
        }

        // 显示带有人脸检测框的当前帧
        cv::imshow("Face Detection", frame);

        // 检查是否按下 'q' 键退出
        if (cv::waitKey(1) == 'q') {
            break;
        }
    }

    cap.release(); // 释放摄像头
    cv::destroyAllWindows(); // 关闭所有 OpenCV 窗口

    return 0;
}

8a39b85f1244425694f65ce4e45d8f7c.jpeg

调用的摄像头检测我自己的大脸

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL-----多表查询(二)

目录 一.子查询概述&#xff1a; 二&#xff1a;标量子查询&#xff1a; 三&#xff1a;列子查询&#xff1a; 四&#xff1a;行子查询&#xff1a; 五&#xff1a;表子查询&#xff1a; 六&#xff1a;练习部分&#xff1a; 写在之前&#xff1a;本文承接上文MySQL-----多…

万用板是什么?和印刷电路板一样吗?

同学们大家好&#xff0c;今天我们继续学习杨欣的《电子设计从零开始》&#xff0c;这本书从基本原理出发&#xff0c;知识点遍及无线电通讯、仪器设计、三极管电路、集成电路、传感器、数字电路基础、单片机及应用实例&#xff0c;可以说是全面系统地介绍了电子设计所需的知识…

Hikyuu-PF-银行股轮动交易策略实现

今天&#xff0c;带来的是“如何使用 Hikyuu 中的投资组合来实现银行股轮动交易策略”。 这个策略的逻辑很简单&#xff1a;持续持有两支市净率最低银行股&#xff0c;然后每月换仓 定义回测周期与回测标的 同样&#xff0c;首先定义回测周期&#xff1a; # 定义回测日期 …

基于Nios-II的流水灯

基于Nios-II的流水灯 一、Qsys设计&#xff08;一&#xff09;新建项目&#xff08;二&#xff09;Platfrom Designer&#xff08;三&#xff09;设置时钟主频&#xff08;四&#xff09;添加Nios-II Processor并设置&#xff08;五&#xff09;添加JTAG并配置&#xff08;六&a…

android_systemServer进程启动流程

一&#xff0c;systemServer进程是被Zygote进程fork出来的&#xff0c;具体代码&#xff0c; 在startBootstrapServices、startCoreServices、startOtherServices、startApexServices中&#xff0c;对各类服务进行了启动&#xff0c;比如我们常见的ActivityManagerService、Pa…

AI视频教程下载:用ChatGP在24小时内制作发布畅销电子书

这门变革性的课程使您能够利用内容生成和自行出版的新兴AI世界。利用ChatGPT 4等尖端人工智能工具&#xff0c;也称为ChatGPT Plus&#xff0c;您将获得所需的技能集&#xff0c;以创建引人入胜的内容&#xff0c;掌握设计&#xff0c;并成为亚马逊KDP上成功的自行出版作者 。 …

Parallels Desktop 19 for Mac v19.3.0.54924中文破解版

Parallels Desktop 19 for Mac v19.3.0.54924中文破解版是一款强大的虚拟机软件&#xff0c;支持多操作系统&#xff0c;提供卓越的虚拟化技术&#xff0c;确保流畅稳定的运行。新增特色功能如共享打印、TouchID集成等&#xff0c;提供便捷高效的虚拟机体验。界面美观现代&…

理解DPI:从数码到打印的深入分析

目录标题 1. DPI的定义2. DPI与图像质量2.1. 对于打印来说&#xff1a;2.2. 对于屏幕显示来说&#xff1a; 3. 如何计算DPI4. 调整DPI4.1. 提高DPI&#xff1a;4.2. 降低DPI&#xff1a; 5. DPI与图像文件大小的关系6. 实际应用中的DPI6.1. 专业打印&#xff1a;6.2. 屏幕设计&…

含义:理财风险等级R1、R2、R3、R4、R5

理财风险等级R1、R2、R3代表什么&#xff0c;为什么R1不保本&#xff0c;R2可能亏损 不尔聊投资https://author.baidu.com/home?frombjh_article&app_id1704141696580953 我们购买理财产品的时候&#xff0c;首先都会看到相关产品的风险等级。风险等级约定俗成有5级&…

谷歌十诫 Ten things we know to be true, Google‘s Core values

雷军曾经要求金山人人都必须能背谷歌十诫 我们所知的十件事 当谷歌刚成立几年时&#xff0c;我们首次写下了这“十件事”。我们时不时回顾这个列表&#xff0c;看看它是否仍然适用。我们希望它仍然适用——你也可以要求我们做到这点。 1. Focus on the user and all else wi…

三、Redis五种常用数据结构-Hash

Hash是redis中常用的一种无序数据结构。结构类似HashMap。 具体结构如下&#xff1a;key field value 1、优缺点 1.1、优点 同类数据归类整合储存&#xff0c;方便数据管理。相比于string操作消耗内存和CPU更小。分字段存储&#xff0c;节省网络流量。 1.2、缺点 过期时间…

Java数组的使用

前言 这里我使用的是IDEA编译器进行演示 数组的创建与初始化 创建格式&#xff1a; T[] 数组名 new T[N] T表示数组存放的数据类型&#xff0c;N表示数组的大小。 T[] 表示数组的类型。 这里要注意和C语言不同的是C语言使用类似int arr[10]这样的结构进行创建数组&#xff0c…

24V转3.8V用什么芯片方案-AH8310

在将24V降压至3.8V的电源转换中&#xff0c;AH8310是一个理想的选择。这款芯片是一款降压转换器&#xff0c;输入电压范围为4.5V至36V&#xff0c;输出电压可调&#xff0c;峰值电流可达1.5A。AH8310采用SOT23-6封装&#xff0c;内置MOS&#xff0c;适用于各种应用场合&#xf…

modprobe: can‘t open ‘modules.dep‘: No such file or directory

使用modprobe会提示modprobe: cant open modules.dep: No such file or directory 直接输入depmod即可。 如果depmod没有效果&#xff0c;则需要重新配置编译你的根文件。 在busybox配置界面进入linux Module Utilities, 上下键选择depmod&#xff0c;并按 y 选中&#xff0c…

【vue+vue-treeselect】根据指定字段,如isLeaf(是否末级节点),设置只允许末级节点可以选

1、当项目有特殊要求&#xff0c;必须根据某个字段的值去判断&#xff0c;是否节点可以选&#xff0c;即使已经是末级节点了&#xff0c;还是需要根据字段判断是否禁用 &#xff08;1&#xff09; :flat"true"一定要设置 (2)获取数据源的时候&#xff0c;设置下禁用…

leetcode91.解码方法(动态规划)

问题描述&#xff1a; 一条包含字母 A-Z 的消息通过以下映射进行了 编码 &#xff1a; A -> "1" B -> "2" ... Z -> "26" 要 解码 已编码的消息&#xff0c;所有数字必须基于上述映射的方法&#xff0c;反向映射回字母&#xff08;可…

NineData亮相2024中国移动算力网络大会

4月28日至29日&#xff0c;2024中国移动算力网络大会在苏州召开。大会以“算力网络点亮AI新时代”为主题&#xff0c;全面展示了中国移动最新算力网络成果与能力。江苏省委常委、苏州市委书记刘小涛&#xff0c;副省长赵岩出席开幕式并致辞。内蒙古自治区副主席白清元出席。中国…

【JAVA语言-第20话】多线程详细解析(二)——线程安全,非线程安全的集合转换成线程安全

目录 线程安全 1.1 概述 1.2 案例分析 1.3 解决线程安全 1.3.1 synchronized关键字 1.3.1.1 同步代码块 1.3.1.2 同步方法 1.3.2 使用Lock锁 1.3.2.1 概述 代码示例 1.4 线程安全的类 1.4.1 非线程安全集合转换成线程安全集合 线程安全 1.1 概述 指如果有多…

JavaEE企业级开发中常用的JDK7和JDK8的时间类

JDK7时间类 全世界的时间有一个统一的计算标准 在同一条经线上的时间是一样的 格林威治时间 简称GMT 计算核心 地球自转一天是24小时 太阳直射正好是12小时 但是误差太大 现在用原子钟来代替 用铯原子震动的频率来计算时间&#xff0c;作为世界的标准时间UTC 中国标准时间…

Dockerfile实践java项目

目的&#xff1a;用java项目测试dockerfil部署&#xff08;前提是安装好了docker&#xff09; 部署准备文件如下 1. java项目 java项目demo地址 https://gitee.com/xiaoqu_12/dockerfileDemo.git 或者百度网盘直接下载打包好的jar包 链接&#xff1a;https://pan.baidu.com/s/…
最新文章