C++开发人脸性别识别教程(4)——OpenCv的人脸检测函数

2024-08-28 18:18

本文主要是介绍C++开发人脸性别识别教程(4)——OpenCv的人脸检测函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  这个项目主要包含三部分:人脸检测、特征提取、性别分类:

  这篇博客中我们重点介绍OpenCv的人脸检测函数。这篇博客我们先不提MFC,而是在win32控制台下编写一段人脸检测的程序。

  一、开启摄像头

  我们先讲解如何通过摄像头来采集图像,这听起来更有实际意义。

  1、新建工程并配置OpenCv(注意工程类型选择win32控制台应用程序):

  2、包含头文件

  OpenCv2.x版本包含头文件非常方便,一句话搞定:

#include <opencv2\opencv.hpp>using namespace cv;
using namespace std;

  谈到包含头文件,这里有一个地方需要详细说一下,就是OpenCv2.x之所以操作简洁,是因为其将各个模块的头文件全部置于“opencv.hpp”这个文件中了,右键打开opencv.hpp文档,你会发现如下内容:

  3、初始化一个摄像头捕捉器

  首先,需要建立一个摄像头捕捉器,并将其与当前设备中的摄像头相关联:

    /***********初始化一个摄像头捕捉器***********/CvCapture* capture = cvCreateCameraCapture(0);cvNamedWindow("Camera");

  注意以"cv"开头的结构体和函数名都是隶属于OpenCv1.x版本中的内容,不过OpenCv2.x是完全兼容1.x版本的,而且貌似在2.x版本并未对摄像头相关函数进行重写,因此这里暂且延用1.x中的代码。

  4、调用摄像头步骤画面并显示

  首先,给出代码,稍后解释:

    IplImage* cameraImage = NULL;while ((cameraImage = cvQueryFrame(capture)) != NULL){cvShowImage("Camera",cameraImage);cvWaitKey(1);}

  显然cvQueryFrame()函数的作用是在当前的时间点从摄像头抓取的视频流中截出一帧,这里将其赋值给变量camearImage(IplImage*类型,因为这是1.0的代码),若其非空,则显示在屏幕上。注意这里必须添加延时函数cvWaitKey(单位是毫秒),哪怕只延时一毫秒否则将无法正常显示摄像头输出。

  按下Ctrl+F5,程序正常运行:

  二、人脸检测

  OpenCv2.x版本中封装的人脸检测函数基于AdaBoost(级联分类器)人脸检测算法,当然这里我们无需深入了解算法相关的知识,因为Intel已经将需要用到的、训练好的人脸检测器(分类器)放在了安装文件里:

  1、准备工作

  调用人脸检测函数前需要做一些准备工作,分别是初始化所需内存、初始化检测器指针、设置检测器路径:

static CvMemStorage* storage            = NULL;
static CvHaarClassifierCascade* cascade = NULL;
const char* cascadePath                 = "D:\\opencv\\sources\\data\
\\haarcascades\\haarcascade_frontalface_alt_tree.xml";

  这里有两个问题需要强调:

  (1)从路径中可以看出,检测器位于安装目录下的source文件夹下的data文件夹下的haarcascades文件夹中。

  (2)在C++表示路径是要用双斜杠,因为第一个斜杠会默认为是转义字符,对第二个斜杠进行转义。

  (3)这三个变量均为全局变量。

  2、图像灰度化

  由于这里用到的人脸检测函数主要针对于灰度图像,因此需要将摄像头采集的彩色图像灰度化:

        /**********灰度化***********/IplImage* grayImage = cvCreateImage(cvSize(cameraImage->width,cameraImage->height),8,1);cvCvtColor(cameraImage,grayImage,CV_BGR2GRAY);

  这里涉及到如何通过cvCreatImage创建一个空的8位无符号整型单通道图,即需要通过一个cvSize结构体来指定图像初始的尺寸,这点在opencv2.x得到了很大改良(Mat类的加入)。

  3、调用人脸检测函数

  首先,创建一块内存区域,并加载相应的检测器(这个在主循环外完成即可):

    storage = cvCreateMemStorage(0);cascade = (CvHaarClassifierCascade*)cvLoad(cascadePath);

  然后,清空指定位置内存块,调用人脸检测函数:

        /**********人脸检测***********/cvClearMemStorage(storage);CvSeq* objects = cvHaarDetectObjects(grayImage,cascade,storage,1.1,2,0,cvSize(30,30));

  cvhaardetectobjects函数的参数较为复杂,具体参数设置参见:cvhaardetectobjects参数设置。我们这里需要了解的就是这个函数的返回参数是一系列检测结果序列,每个检测结果实际上就是一个矩形结构体对象。

  4、绘制人脸区域矩形框

  接下来一一绘制检测到的矩形结果:

        /**********绘制检测结果***********/for (int i = 0; i < (objects ? objects->total : 0); i++){CvRect* rect = (CvRect*)cvGetSeqElem(objects,i);cvRectangle(cameraImage,cvPoint(rect->x,rect->y),cvPoint(rect->x + rect->width,rect->y + rect->height),cvScalar(0.0,255));}cvShowImage("Camera",cameraImage);

  注意这里需要把之前测试摄像头程序中的图片显示语句注释掉,否则前后在显示图像时会发生覆盖,不能正常看到图像的检测结果:

  5、总程序

  这里给出摄像头人脸检测的总程序:

// Camera.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <opencv2\opencv.hpp>using namespace cv;
using namespace std;static CvMemStorage* storage            = NULL;
static CvHaarClassifierCascade* cascade = NULL;
const char* cascadePath                 = "D:\\opencv\\sources\\data\
\\haarcascades\\haarcascade_frontalface_alt_tree.xml";int _tmain(int argc, _TCHAR* argv[])
{/***********初始化一个摄像头捕捉器***********/CvCapture* capture = cvCreateCameraCapture(0);cvNamedWindow("Camera");/***********初始化人脸检测相关变量***********/IplImage* cameraImage = NULL;storage = cvCreateMemStorage(0);cascade = (CvHaarClassifierCascade*)cvLoad(cascadePath);while ((cameraImage = cvQueryFrame(capture)) != NULL){//cvShowImage("Camera",cameraImage);cvWaitKey(1);/**********灰度化***********/IplImage* grayImage = cvCreateImage(cvSize(cameraImage->width,cameraImage->height),8,1);cvCvtColor(cameraImage,grayImage,CV_BGR2GRAY);/**********人脸检测***********/cvClearMemStorage(storage);CvSeq* objects = cvHaarDetectObjects(grayImage,cascade,storage,1.1,2,0,cvSize(30,30));/**********绘制检测结果***********/for (int i = 0; i < (objects ? objects->total : 0); i++){CvRect* rect = (CvRect*)cvGetSeqElem(objects,i);cvRectangle(cameraImage,cvPoint(rect->x,rect->y),cvPoint(rect->x + rect->width,rect->y + rect->height),cvScalar(0.0,255));}cvShowImage("Camera",cameraImage);}return 0;
}

 

这篇关于C++开发人脸性别识别教程(4)——OpenCv的人脸检测函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1115522

相关文章

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

基于 Cursor 开发 Spring Boot 项目详细攻略

《基于Cursor开发SpringBoot项目详细攻略》Cursor是集成GPT4、Claude3.5等LLM的VSCode类AI编程工具,支持SpringBoot项目开发全流程,涵盖环境配... 目录cursor是什么?基于 Cursor 开发 Spring Boot 项目完整指南1. 环境准备2. 创建

C++右移运算符的一个小坑及解决

《C++右移运算符的一个小坑及解决》文章指出右移运算符处理负数时左侧补1导致死循环,与除法行为不同,强调需注意补码机制以正确统计二进制1的个数... 目录我遇到了这么一个www.chinasem.cn函数由此可以看到也很好理解总结我遇到了这么一个函数template<typename T>unsigned

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

基于C#实现PDF转图片的详细教程

《基于C#实现PDF转图片的详细教程》在数字化办公场景中,PDF文件的可视化处理需求日益增长,本文将围绕Spire.PDFfor.NET这一工具,详解如何通过C#将PDF转换为JPG、PNG等主流图片... 目录引言一、组件部署二、快速入门:PDF 转图片的核心 C# 代码三、分辨率设置 - 清晰度的决定因

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象