OpenCV入门指南----人脸检测

本篇介绍图像处理与模式识别中最热门的一个领域——人脸检测(人脸识别)。人脸检测可以说是学术界的宠儿,在不少EI,SCI高级别论文都能看到它的身影。甚至很多高校学生的毕业设计都会涉及到人脸检测。当然人脸检测的巨大实用价值也让很多公司纷纷关注,很多公司都拥有这方面的专利或是开发商业产品出售。

    在OpenCV中,人脸检测也是其热门应用之一。在OpenCV的特征检测专题就详细介绍了人脸检测的原理——通过Haar特征来识别是否为人脸。Haar特征检测原理与Haar特征分类器的训练放到下一篇《【OpenCV入门指南】第十四篇  Haartraining》来讲,本篇主要介绍如何在OpenCV中使用Haar特征分类器来对图像中的人脸进行检测和识别。下面将分成五步来详细示范如何在OpenCV中进行人脸识别:

    一.人脸的Haar特征分类器是什么

    二.在哪找人脸的Haar特征分类器

    三.怎么用人脸的Haar特征分类器

    四.人脸识别示例代码

    五.人脸识别程序运行结果

一.人脸的Haar特征分类器是什么

人脸的Haar特征分类器就是一个XML文件,该文件中会描述人脸的Haar特征值。当然Haar特征的用途可不止可以用来描述人脸这一种,用来描述眼睛,嘴唇或是其它物体也是可以的。

二.在哪找人脸的Haar特征分类器

OpenCV有已经自带了人脸的Haar特征分类器。OpenCV安装目录中的\data\ haarcascades目录下的haarcascade_frontalface_alt.xml与haarcascade_frontalface_alt2.xml都是用来检测人脸的Haar分类器。这个haarcascades目录下还有人的全身,眼睛,嘴唇的Haar分类器。读者可以仿照本方的例子来试验下效果看看。

三.怎么用人脸的Haar特征分类器

使用人脸的Haar特征分类器非常之简单,直接使用cvHaarDetectObjects。下面来看看这个函数的介绍:

函数功能:检测图像中的目录

函数原型:

CVAPI(CvSeq*) cvHaarDetectObjects(

  const CvArr* image,

  CvHaarClassifierCascade* cascade,

  CvMemStorage* storage,

  double scale_factor CV_DEFAULT(1.1),

  int min_neighbors CV_DEFAULT(3),

  int flags CV_DEFAULT(0),

  CvSize min_size CV_DEFAULT(cvSize(0,0)),

  CvSize max_size CV_DEFAULT(cvSize(0,0))

);

函数说明:

第一个参数表示输入图像,尽量使用灰度图以加快检测速度。

第二个参数表示Haar特征分类器,可以用cvLoad()函数来从磁盘中加载xml文件作为Haar特征分类器。

第三个参数为CvMemStorage类型,大家应该很熟悉这个CvMemStorage类型了,《OpenCV入门指南》中很多文章都介绍过了。

第四个参数表示在前后两次相继的扫描中,搜索窗口的比例系数。默认为1.1即每次搜索窗口依次扩大10%

第五个参数表示构成检测目标的相邻矩形的最小个数(默认为3个)。如果组成检测目标的小矩形的个数和小于 min_neighbors - 1 都会被排除。如果min_neighbors 为 0, 则函数不做任何操作就返回所有的被检候选矩形框,这种设定值一般用在用户自定义对检测结果的组合程序上。

第六个参数要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,如果设置为CV_HAAR_DO_CANNY_PRUNING,那么函数将会使用Canny边缘检测来排除边缘过多或过少的区域,因此这些区域通常不会是人脸所在区域。

第七个,第八个参数表示检测窗口的最小值和最大值,一般设置为默认即可。

函数返回值:

函数将返回CvSeq对象,该对象包含一系列CvRect表示检测到的人脸矩形。

四.人脸识别示例代码

下面给出一个完整的示例代码,代码中的GetTickCount可以参阅《Windows 各种计时函数总结》,cvEqualizeHist可以参阅《【OpenCV入门指南】第八篇灰度直方图》。

// FaceDetect.cpp : 定义控制台应用程序的入口点。
// 本文配套博客文章地址: http://blog.csdn.net/morewindows/article/details/8426318  

#include "stdafx.h"#include <iostream>
#include <opencv2/core/core.hpp>   //cvGetSize  cvCreateImage
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>  //cvResize cvInitMatHeader cvGetMinMaxHistValue cvCvtColor
#include <opencv2/imgproc/imgproc.hpp>#include <Windows.h>   //DWORD  GetTickCount()

#ifdef _DEBUG
#pragma comment(lib, "opencv_core244d")
#pragma comment(lib, "opencv_highgui244d")
#pragma comment(lib, "opencv_imgproc244d")  //cvResize 
#pragma comment(lib, "opencv_objdetect244d")  //cvHaarDetectObjects
#else
#pragma comment(lib, "opencv_core244")
#pragma comment(lib, "opencv_highgui244")
#pragma comment(lib, "opencv_imgproc244")  //cvResize
#pragma comment(lib, "opencv_objdetect244") //cvHaarDetectObjects
#endifusing namespace std;  
int main()  
{  // 加载Haar特征检测分类器  // haarcascade_frontalface_alt.xml系OpenCV自带的分类器 下面是我机器上的文件路径  const char *pstrCascadeFileName = "G:\\Software\\openCV\\opencv\\data\\haarcascades\\haarcascade_frontalface_alt.xml";  CvHaarClassifierCascade *pHaarCascade = NULL;  pHaarCascade = (CvHaarClassifierCascade*)cvLoad(pstrCascadeFileName);  // 载入图像  const char *pstrImageName = "./images/linzhiling.jpg";  //const char *pstrImageName = "./images/liuyifei.jpg";  //const char *pstrImageName = "./images/unknown.jpg";  IplImage *pSrcImage = cvLoadImage(pstrImageName, CV_LOAD_IMAGE_UNCHANGED);  IplImage *pGrayImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);  cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY);  // 人脸识别与标记  if (pHaarCascade != NULL)  {         CvScalar FaceCirclecolors[] =   {  {{0, 0, 255}},  {{0, 128, 255}},  {{0, 255, 255}},  {{0, 255, 0}},  {{255, 128, 0}},  {{255, 255, 0}},  {{255, 0, 0}},  {{255, 0, 255}}  };  CvMemStorage *pcvMStorage = cvCreateMemStorage(0);  cvClearMemStorage(pcvMStorage);  // 识别  
        DWORD dwTimeBegin, dwTimeEnd;  dwTimeBegin = GetTickCount();  //函数将返回CvSeq对象,该对象包含一系列CvRect表示检测到的人脸矩形//第一个参数表示输入图像,尽量使用灰度图以加快检测速度//第二个参数表示Haar特征分类器,可以用cvLoad()函数来从磁盘中加载xml文件作为Haar特征分类器//第三个参数为CvMemStorage类型//第四个参数表示在前后两次相继的扫描中,搜索窗口的比例系数。默认为1.1即每次搜索窗口依次扩大10%//第五个参数表示构成检测目标的相邻矩形的最小个数(默认为3个)。如果组成检测目标的小矩形的个数和小于 min_neighbors - 1 都会被排除。//如果min_neighbors 为 0, 则函数不做任何操作就返回所有的被检候选矩形框,这种设定值一般用在用户自定义对检测结果的组合程序上//第六个参数要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,如果设置为CV_HAAR_DO_CANNY_PRUNING,那么函数将会使用Canny边缘检测//来排除边缘过多或过少的区域,因此这些区域通常不会是人脸所在区域//第七个,第八个参数表示检测窗口的最小值和最大值,一般设置为默认即可CvSeq *pcvSeqFaces = cvHaarDetectObjects(pGrayImage, pHaarCascade, pcvMStorage);  dwTimeEnd = GetTickCount();  printf("人脸个数: %d   识别用时: %d ms\n", pcvSeqFaces->total, dwTimeEnd - dwTimeBegin);  // 标记  for(int i = 0; i <pcvSeqFaces->total; i++)  {  CvRect* r = (CvRect*)cvGetSeqElem(pcvSeqFaces, i);  //用圆形画出脸部部分
            CvPoint center;  int radius;  center.x = cvRound((r->x + r->width * 0.5));  center.y = cvRound((r->y + r->height * 0.5));  radius = cvRound((r->width + r->height) * 0.25);  cvCircle(pSrcImage, center, radius, FaceCirclecolors[i % 8], 2); //用矩形画出脸部部分/*CvPoint startPoint,endPoint;startPoint.x = cvRound(r->x);startPoint.y = cvRound(r->y);endPoint.x = cvRound(r->x + r->width);endPoint.y = cvRound(r->x + r->height);cvRectangle(pSrcImage,startPoint,endPoint,FaceCirclecolors[i % 8]);*/}  cvReleaseMemStorage(&pcvMStorage);  }  const char *pstrWindowsTitle = "人脸识别";  cvNamedWindow(pstrWindowsTitle, CV_WINDOW_AUTOSIZE);  cvShowImage(pstrWindowsTitle, pSrcImage);  cvWaitKey(0);  cvDestroyWindow(pstrWindowsTitle);  cvReleaseImage(&pSrcImage);   cvReleaseImage(&pGrayImage);  return 0;  
}
View Code

五.人脸识别程序运行结果

运行结果一(单人正面):

这张图的干扰太少,换张干扰大点的图来试试。

 

运行结果二:

 

运行结果三(多人):

 

本文转自:http://blog.csdn.net/morewindows/article/details/8426318

转载于:https://www.cnblogs.com/tianyalu/p/5689285.html

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

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

相关文章

matlab提取艾里斑,艾里斑:我不是雀斑

正是艾里斑&#xff0c;限制了光学仪器的精度我们知道凸透镜能把入射光会聚到它的焦点上&#xff0c;由于透镜的口径有一定大小&#xff0c;限制了光线的传播&#xff0c;所以凸透镜也会发生衍射。这导致透镜无法把光线会聚成无限小的点&#xff0c;而只会在焦点上形成具有一定…

mysql启动错误排查-无法申请足够内存

一般情况下mysql的启动错误还是很容易排查的&#xff0c;但是今天我们就来说一下不一般的情况。拿到一台服务器&#xff0c;安装完mysql后进行启动&#xff0c;启动错误如下&#xff1a; 有同学会说&#xff0c;哥们儿你是不是buffer pool设置太大了&#xff0c;设置了96G内存。…

loadrunner 关联

1、记住关联的位置&#xff08;之前&#xff09;&#xff0c;因为登录之前需要token&#xff0c;才能验证登录是否成功&#xff0c;所以&#xff0c;放在登录之前 转载于:https://www.cnblogs.com/zyp1/p/5692343.html

Akka STM –与STM Ref和Agent进行乒乓球比赛

乒乓是一个经典示例&#xff0c;其中2个玩家&#xff08;或线程&#xff09;访问共享资源–乒乓球桌并在彼此之间传递Ball&#xff08;状态变量&#xff09;。 使用任何共享资源&#xff0c;除非我们同步访问&#xff0c;否则线程可能会遇到潜在的死锁情况。 PingPong算法非常简…

JSP九大内置对象,七大动作,三大指令

JSP之九大内置对象 隐藏对象入门探索 Servlet 和JSP中输出数据都需要使用out对象。Servlet 中的out对象是通过getWriter()方法获取的。而JSP中没有定义out对象却可以直接使用。这是因为out是JSO的内置隐藏对象。JSP中的常见的9个内置隐藏对象如下 out输出流对象 隐藏对象out是…

可以添加自定义的Select控件

1.控件dom <select name"WebSiteTarget" id"WebSiteTarget" class"w1" onchange"editable2(this);"><option value"-1">请选择城市</option><option>福州</option><option>厦门</op…

innodb_io_capacity =innodb_lru_scan_depth*inoodb_buffer_pool_instances。与 checkpoint

innodb_lru_scan_depth:每个缓冲池刷脏页的能力 innodb_io_capacity: iops inoodb_buffer_pool_instances8 :缓冲池的个数 .关系&#xff1a; innodb_io_capacity > innodb_lru_scan_depth * inoodb_buffer_pool_instances 转载于:https://www.cnblogs.com/zengkefu/…

Java中的责任链模式

当应有几个处理器来执行某项操作并为这些处理器定义特定顺序时&#xff0c;就需要采用责任链设计模式。 在运行时处理器顺序的可变性也很重要。模式的UML表示如下&#xff1a; 处理程序定义处理器对象的一般结构。 这里的“ HandleRequest”是抽象处理器方法。 处理程序还具有自…

使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(六)-- 依赖注入

本篇将介绍Asp.Net Core中一个非常重要的特性&#xff1a;依赖注入&#xff0c;并展示其简单用法。 第一部分、概念介绍 Dependency Injection&#xff1a;又称依赖注入&#xff0c;简称DI。在以前的开发方式中&#xff0c;层与层之间、类与类之间都是通过new一个对方的实例进行…

基于JAX-WS的webService开发实例

最近因为工作原因接触到webService&#xff0c;所以记录下开发中碰到的问题&#xff0c;方便自己以后复习&#xff0c;顺便发扬一下开源精神。刚刚接触webServie如果有什么错误欢迎大家指正。 本地环境&#xff1a;myEclipse10.6 tomcat7 JDK7 jaxws-ri-2.2.10 第一步&#xff…

完整的WebApplication JSF EJB JPA JAAS –第2部分

视图–创建和JSF设置 本教程是第1部分的继续。 让我们创建一个新的Dynamic Web Project 。 如下图所示创建它&#xff1a; 注意&#xff1a;在某些时候&#xff0c;Eclipse会询问您是否要添加JSF功能&#xff08;自动完成&#xff09;&#xff0c;然后启用它。 就像下面的屏幕…

Android使用绘图Path总结

Path作为Android中一种相对复杂的绘图方式&#xff0c;官方文档中的有些解释并不是很好理解&#xff0c;这里作一个相对全面一些的总结&#xff0c;供日后查看&#xff0c;也分享给大家&#xff0c;共同进步。 1.基本绘图方法 addArc(RectF oval, float startAngle, float swee…

2017.3.23下午

下午通过对OSPF基本原理进一步的学习&#xff0c;对上午学习的内容进行了复习。 转载于:https://www.cnblogs.com/bgd140206206/p/6606192.html

编写Eclipse插件教程–第1部分

Eclipse是三个最受欢迎的Java开发IDE之一。 其成功的原因之一是其可扩展性。 对于任何知道该怎么做并且已经做到的人来说&#xff0c;编写eclipse插件都可以非常轻松快捷。 不幸的是&#xff0c;第一次在Eclipse中进行操作可能会非常耗时且令人沮丧。 Eclipse框架非常庞大&…

简单Window下 Android Studio的安装

&#xff08;1&#xff09;首先安装JDK 下载JDK 本人觉得官方网站下JDK比较慢&#xff0c;可以直接百度JDK&#xff0c;&#xff08;如果是64位 百度搜索记得64位&#xff09; 类似于这样的下载 安装可以看下教程&#xff0c;包括环境变量的配置 如何安装JDK &#xff08;2&…

日期处理一之NSLalendar的使用

一、日期和时间模式 日期和时间格式由日期和时间模式字符串组成&#xff0c;在日期和时间模式字符串中未加引号的A到‘Z’和a到‘z’被解释为模式字母&#xff0c;用来表示日期或时间。字符串元素&#xff0c;文本可以使用单引号&#xff08;‘’&#xff09;引起来使用。定义以…

十大最受欢迎的新Eclipse插件

Eclipse Marketplace仍然是发现有趣且相关的Eclipse插件的地方。 通过Eclipse Marketplace客户端&#xff0c;每月成功安装100,000多个基于Eclipse的产品。 我们提供了过去30天 以来所有时间最受欢迎的插件列表。 我认为看看过去12个月中最受欢迎的新插件会很有趣。 以下列出了…

《Java技术》第二次作业计科1501赵健宇

&#xff08;一&#xff09;学习总结 1.使用Eclipse关联jdk源代码,查看String类的equals&#xff08;&#xff09;方法 equals&#xff08;&#xff09;方法截图 “”比较的是地址。equals方法他同样使用号进行内存地址的比较。但是equals方法重写如果号比较不相等&#xff0c;…

JUnit的内置Hamcrest Core Matcher支持

在用JUnit和Hamcrest改进assertEquals的文章中&#xff0c;我简要讨论了Hamcrest “ 核心 ”匹配器与JUnit的现代版本“结合”在一起的情况。 在那篇文章中&#xff0c;我特别关注了JUnit的assertThat&#xff08;T&#xff0c;Matcher&#xff09;静态方法与Hamcrest核心is()匹…

Java开发高性能网站需要关注的事

转自&#xff1a;http://www.javabloger.com/java-development-concern-those-things/ 近期各家IT媒体举办的业内技术大会让很多网站都在披露自己的技术内幕与同行们分享&#xff0c;大到facebook&#xff0c;百度&#xff0c;小到刚起步的网站。facebook&#xff0c;百度之类的…