【从零学习openCV】IOS7根据人脸检测

前言:

人脸检測与识别一直是计算机视觉领域一大热门研究方向,并且也从安全监控等工业级的应用扩展到了手机移动端的app。总之随着人脸识别技术获得突破,其应用前景和市场价值都是不可估量的,眼下在学习openCV,自然不能放过这个领域。于是略微了解了下openCV下人脸检測的一些原理。为之后的人脸识别等研究做个小小的铺垫。

原理:

人脸检測属于目标检測(object detection) 的一部分,主要涉及两个方面

  1. 先对要检測的目标对象进行概率统计,从而知道待检測对象的一些特征,建立起目标检測模型。

  2. 用得到的模型来匹配输入的图像,假设有匹配则输出匹配的区域

好吧,这样说有点抽象,接下来我们来看看openCV经常使用的haar人脸检測是怎么回事吧

Haar特征

首先,什么是Haar呢?说白了,haar就是一种基于“块”的特征,它最早是由Papageorigiou等人用于人脸描写叙述。眼下经常使用的Haar-like特征能够分为三类:线性特征、边缘特征、点特征(中心特征)、对角线特征。例如以下图所看到的:

显然。边缘特征有4种:x方向。y方向,x倾斜方向,y倾斜方向;线特征有8种,点特征有2种,对角线特征有1种。

每一种特征的计算都是由黑色填充区域的像素值之和与白色填充区域的像素值之和的差值。而计算出来的这个差值就是所谓的Haar-like特征的特征值。

Haar特征是基于"块"的特征,可以减少计算成本。

可是对于一张24*24的图片可以提取的haar特征量很巨大,大概有16万之多。怎样从这么多的特征中提取出对人脸识别真正实用的特征是一个很重要的问题,于是就要使用到Adaboosting算法。

Adaboosting算法

AdaBoost算法是一种迭代的算法。对于一组训练集,通过改变当中每个样本的分布概率,而得到不同的训练集Si,对于每个Si进行训练从而得到一个弱分类器Hi,再将这些若分类器依据不同的权值组合起来,就得到了强分类器。

第一次的时候。每一个样本都是均匀分布,通过训练得到分类器H0,在该训练集中。分类正确的。就减少其分布概率。分类错误的,就提高其分布概率,这样得到的新的训练集S1就主要是针对不太好分类的样本了。再使用S1进行训练,得到分类器H1,依次迭代下去……。设迭代此外为T,则得到T个分类器。

对于每一个分类器的权值,其分类准确性越高,权值越高。

前面说到,一张24*24的图片,能提取到16W多的haar特征。一个弱分类器,实际上就是在这16W多的特征中选取一个特征。用这个特征可以区分出人脸or非人脸,且错误率最低。

比方如今有人脸样本2000张,非人脸样本4000张,这些样本都经过了归一化,大小都是24X24的图像。那么,对于16W中的任一特征fi。我们计算该特征在这2000人脸样本、4000非人脸样本上的值,这样就得到6000个特征值。

将这些特征值排序,然后选取一个最佳的特征值,在该特征值下,对于特征fi来说。样本的加权错误率最低。选择全部特征中,错误率最低的特征,用来推断人脸,这就是一个弱分类器,同一时候用此分类器对样本进行分类。并更新样本的权重。

详细实施步骤例如以下。内容均摘自DylanTsou的博客

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2hhd25faHQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" width="514" height="462" >

窗体扫描检測

得到了分类器后就行对图像进行人脸检測了。因为输入的图像往往与分类器训练的图像大小不一致(一般更大)。于是我们须要一个可以滑动的窗体在输入图像上不断移动进行扫描。假设我们训练的图像就是24*24的,滑动窗体就是一个24*24
window,使用这个window扫描一张大图上全部位置。在每一个位置上都使用训练好的分类器回答是不是人脸的问题。

扫描结束之后须要一些重叠的窗体合并(在同一张人脸附近可能有非常多个临近窗体都被推断为包括人脸)。

为了可以提高扫描速度可以使用了逐级删选的方案,就是先開始使用计算成本低的分类器海选(这种分类器包括较少的特征),海选过程中标准较低,尽可能将全部的人脸都删选进来,低标准导致非常多非人脸也被选进来。然后逐渐提高分类器的标准(也就是说使用包括很多其它特征的分类器,同一时候添加了计算成本)这种逐级删选可以减少计算成本。

最后另一个问题: 在一张照片中人脸的大小各有区别不一定就和训练图片大小同样。解决问题的方法是使用不同大小的窗体来检測人脸。 这时候若分类器中的阈值须要随着窗体面积做等比例的变化。

使用openCV进行人脸检測

好了。经过前面的介绍。对人脸检測的原理应该有了大体的了解。其有用openCV实现人脸检測十分简单。

首先OpenCV自带了人脸的Haar特征分类器。

OpenCV安装文件夹中的\data haarcascades文件夹下的haarcascade_frontalface_alt.xml与haarcascade_frontalface_alt2.xml都是用来检測人脸的Haar分类器。这个haarcascades文件夹下还有人的全身,眼睛。嘴唇的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))

);

參数说明:

const CvArr* image:表示输入图像,使用灰度图能够去除一些噪声,而且加快检測速度。

CvHaarClassifierCascade* cascade:表示Haar特征分类器。能够用cvLoad()函数来从磁盘中载入xml文件作为Haar特征分类器。

CvMemStorage* storage:表示内存存储器,用来统一管理各种动态对象的内存。

double scale_factor:表示在前后两次相继的扫描中。搜索窗体的比例系数。默觉得1.1即每次搜索窗体依次扩大10%

int min_neighbors:表示构成检測目标的相邻矩形的最小个数(默觉得3个)。

假设组成检測目标的小矩形的个数和小于 min_neighbors
- 1 都会被排除。

假设min_neighbors 为 0, 则函数不做不论什么操作就返回全部的被检候选矩形框,这样的设定值一般用在用户自己定义对检測结果的组合程序上。

int flags:要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,假设设置为CV_HAAR_DO_CANNY_PRUNING,那么函数将会使用Canny边缘检測来排除边缘过多或过少的区域,因此这些区域通常不会是人脸所在区域。

CvSize min_size、max_size:表示检測窗体的最小值和最大值,一般设置为默认就可以。

函数返回值:

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

案例实战——IOS7人脸检測应用

最终进入正题了,这次的案例是在上篇的基础上稍加改动的。关于怎样在Xcode下配置openCV以及UIImage与cv:Mat和IplImage之间的转化我就不赘述了,详细请參看【从零学习openCV】IOS7下的openCV开发起步(Xcode5.1.1&openCV2.49)

首先我们先将haarcascade_frontalface_alt2.xml导入project文件夹

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2hhd25faHQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" width="245" height="40" style="color:rgb(51,51,51); font-family:KaiTi_GB2312; font-size:14px; line-height:26px; white-space:pre-wrap">

将main.storyboard下的布局改成例如以下形式:

好了,废话不多说,直接上代码:

- (void) opencvFaceDetect  {
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
        UIImage* img = [image copy];
	if(img) {
        [self.view bringSubviewToFront:self.indicator];
        [self.indicator startAnimating];  //因为人脸检測比較耗时,于是使用载入指示器

        cvSetErrMode(CV_ErrModeParent);
		IplImage *image = [self CreateIplImageFromUIImage:img];

		IplImage *grayImg = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1); //先转为灰度图
        cvCvtColor(image, grayImg, CV_BGR2GRAY);

        //将输入图像缩小4倍以加快处理速度
        int scale = 4;
		IplImage *small_image = cvCreateImage(cvSize(image->width/scale,image->height/scale), IPL_DEPTH_8U, 1);
		cvResize(grayImg, small_image);

		//载入分类器
		NSString *path = [[NSBundle mainBundle] pathForResource:@"haarcascade_frontalface_alt2" ofType:@"xml"];
		CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad([path cStringUsingEncoding:NSASCIIStringEncoding], NULL, NULL, NULL);
		CvMemStorage* storage = cvCreateMemStorage(0);
		cvClearMemStorage(storage);

		//关键部分,使用cvHaarDetectObjects进行检測,得到一系列方框
		CvSeq* faces = cvHaarDetectObjects(small_image, cascade, storage ,1.1, currentvalue, CV_HAAR_DO_CANNY_PRUNING, cvSize(0,0), cvSize(0, 0));

        NSLog(@"faces:%d",faces->total);
		cvReleaseImage(&small_image);
		cvReleaseImage(&image);
        cvReleaseImage(&grayImg);

		//创建画布将人脸部分标记出
		CGImageRef imageRef = img.CGImage;
		CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
		CGContextRef contextRef = CGBitmapContextCreate(NULL, img.size.width, img.size.height,8, img.size.width * 4,colorSpace, kCGImageAlphaPremultipliedLast|kCGBitmapByteOrderDefault);

		CGContextDrawImage(contextRef, CGRectMake(0, 0, img.size.width, img.size.height), imageRef);

		CGContextSetLineWidth(contextRef, 4);
		CGContextSetRGBStrokeColor(contextRef, 1.0, 0.0, 0.0, 1);

		//对人脸进行标记。假设isDoge为Yes则在人脸上贴图
		for(int i = 0; i < faces->total; i++) {
			NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

			// Calc the rect of faces
			CvRect cvrect = *(CvRect*)cvGetSeqElem(faces, i);
			CGRect face_rect = CGContextConvertRectToDeviceSpace(contextRef, CGRectMake(cvrect.x*scale, cvrect.y*scale , cvrect.width*scale, cvrect.height*scale));

			if(isDoge) {
				CGContextDrawImage(contextRef, face_rect, [UIImage imageNamed:@"doge.png"].CGImage);
			} else {
				CGContextStrokeRect(contextRef, face_rect);
			}

			[pool release];
		}

		self.imageView.image = [UIImage imageWithCGImage:CGBitmapContextCreateImage(contextRef)];
		CGContextRelease(contextRef);
		CGColorSpaceRelease(colorSpace);

		cvReleaseMemStorage(&storage);
		cvReleaseHaarClassifierCascade(&cascade);
	}

	[pool release];
    [self.indicator stopAnimating];
}

上面这个函数就是整个人脸检測的核心了,思路非常easy。先将原图像转为灰度图。而且缩小4倍,这样处理的速度可以大大加快。然后就是载入haar分类器,调用cvHaarDetectObjects函数进行检測得到一系列的人脸框(cvRect),最后就是在原图像上把cvRect的地方画出来。

因为整个检測过程相对照较耗时,尤其是图像像素特别大的时候。甚至须要好几秒的时间,所以应该单开线程来调用opencvFaceDetect方法。而且最后用指示器来表示图像正在处理中。

- (IBAction)FaceDetectClicked:(id)sender {
    [self.view bringSubviewToFront:self.indicator];
    [self.indicator startAnimating];
    [NSThread detachNewThreadSelector:@selector(opencvFaceDetect) toTarget:self withObject:nil];
}

终于效果例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2hhd25faHQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" width="320" height="568" >

近期迷上了doge啊。女神不要怪我。

老规矩,整个案例的project代码附上:IOS7下openCV人脸检測demo

(转载请注明作者和出处:Shawn-HT  http://blog.csdn.net/shawn_ht 未经同意请勿用于商业用途)

參考文章:

http://www.iteye.com/topic/463668

http://www.douban.com/note/61620214/

http://www.cnblogs.com/dylantsou/archive/2012/08/11/2633483.html

http://blog.csdn.net/morewindows/article/details/8239678

版权声明:本文博客原创文章。博客,未经同意,不得转载。

时间: 2024-08-05 07:45:37

【从零学习openCV】IOS7根据人脸检测的相关文章

【从零学习openCV】IOS7人脸识别实战

前言 接着上篇<IOS7下的人脸检測>,我们顺藤摸瓜的学习怎样在IOS7下用openCV的进行人脸识别,实际上非常easy,因为人脸检測部分已经完毕,剩下的无非调用openCV的方法对採集到的人脸样本进行训练,终于得到一个能够预測人脸的模型.可是当中的原理可谓是博大精深,因为快临最近末考试了,没时间去琢磨当中详细的细节,这次就先写个大概的demo,下次更新文章就得到6月20号之后了. 原理: 从OpenCV2.4之后,openCV增加了新的类FaceRecognizer,我们能够使用它便捷地进

OpenCV例程实现人脸检测

前段时间看的OpenCV,其实有很多的例子程序,参考代码值得我们学习,对图像特征提取三大法宝:HOG特征,LBP特征,Haar特征有一定了解后. 对本文中的例子程序刚开始没有调通,今晚上调通了,试了试效果还可以,还需要深入理解.值得大家动手试试,还是很有成就感的,虽然是现成的例子....... 环境:OpenCV3.1+VS2013+WIN10 复制代码/*! * \file Capture.cpp * * \author ranjiewen * \date 十一月 2016 * * http:

Python学习经典案例:人脸检测

前言 随着科技的发展,人脸识别技术在许多领域得到的非常广泛的应用,手机支付.银行身份验证.手机人脸解锁等等. 识别 废话少说,这里我们使用 opencv 中自带了 haar人脸特征分类器,利用训练好的 haar 特征的 xml 文件,在图片上检测出人脸的坐标,利用这个坐标,我们可以将人脸区域剪切保存,也可以在原图上将人脸框出. 代码实现: # -*-coding:utf8-*-# import os import cv2 from PIL import Image, ImageDraw from

Python学习案例之视频人脸检测识别

前言 上一篇博文与大家分享了简单的图片人脸识别技术,其实在实际应用中,很多是通过视频流的方式进行识别,比如人脸识别通道门禁考勤系统.人脸动态跟踪识别系统等等. 案例 这里我们还是使用 opencv 中自带了 haar人脸特征分类器,通过读取一段视频来识别其中的人脸. 代码实现: # -*- coding: utf-8 -*- __author__ = "小柒" __blog__ = "https://blog.52itstyle.vip/" import cv2 i

Opencv:视频中人脸检测并保存人脸图片

# OpenCV版本的视频检测 import cv2 # 图片识别方法封装 def discern(img): gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) cap = cv2.CascadeClassifier( "C:\Python36\Lib\site-packages\opencv-master\data\haarcascades\haarcascade_frontalface_default.xml" ) faceRects = c

【从零学习openCV】IOS7下的openCV开发起步(Xcode5.1.1&amp;amp;openCV2.49)

前言: 开发IOS7已经有一月的时间了,近期在准备推研的事,有点想往CV方向发展,于是開始自学openCV. 关注CSDN已经非常久了,也从非常多博主那学到了非常多知识,于是我也从这周开启自己的blog之旅,从零開始学openCV,从零開始做笔记写blog,哈哈~ 好了,废话不多说,进入正题.. IOS7下使用openCV Mac OS下要使用openCV当然要编译,可是假设仅仅是在ios下使用openCV的话,仅仅须要将bulid好的opencv2.framework导入到project中就可

【OpenCV入门指南】第十三篇 人脸检测

[OpenCV入门指南]第十三篇 人脸检测 本篇介绍图像处理与模式识别中最热门的一个领域--人脸检测(人脸识别).人脸检测可以说是学术界的宠儿,在不少EI,SCI高级别论文都能看到它的身影.甚至很多高校学生的毕业设计都会涉及到人脸检测.当然人脸检测的巨大实用价值也让很多公司纷纷关注,很多公司都拥有这方面的专利或是开发商业产品出售. 在OpenCV中,人脸检测也是其热门应用之一.在OpenCV的特征检测专题就详细介绍了人脸检测的原理--通过Haar特征来识别是否为人脸.Haar特征检测原理与Haa

OpenCV+OpenVINO实现人脸Landmarks实时检测

缘由 自从OpenCV3.3版本引入深度神经网络(DNN)模块之后,OpenCV对DNN模块支持最好的表现之一就是开始支持基于深度学习人脸检测,OpenCV本身提供了两个模型分别是基于Caffe与Tensorflow的,Caffe版本的模型是半精度16位的,tensorflow版本的模型是8位量化的.同时OpenCV通过与OpenVINO IE模型集成实现了底层硬件对对象检测.图像分割.图像分类等常见模型加速推理支持.OpenVINO框架本身提供直接快速开发应用原型的模型库,对很多常见视觉任务都

opencv-python学习一--人脸检测

简略的介绍一下 :  opencv是什么? , 人脸检测是什么? 最近对机器学习有点感兴趣,想直接从图像识别入手,这里选择了鼎鼎有名的 opencv ,一开始想直接调用opencv的api进行人脸的检测,功能也特简单,一:检测出人脸,用方框标记一下,二:输出图片中存在几个人. 在opencv的 example 中找到了已经写好的示例,示例是对一个video中的图像识别,这里做一个简化,只是检测单独的一张图片. import cv2 import sys # Get user supplied v