智能移动设备上人脸定位的实现与优化

时间:2022-05-17 01:28:51

智能移动设备上人脸定位的实现与优化

【摘要】随着模式识别与人工智能学科的发展,现在已经从尖端科技慢慢渗透到我们的日常生活中。但是因为民用设备一般性能有限,想要在有限的资源下做到比较好的识别准确性,就要在实现时对其进行优化。本文以在有android系统的移动设备上,使用NDK和OpenCV的人脸定位为例,讨论了在移动设备上人脸定位的实现以及在有限的资源下对识别率和效率的一种优化。经试验证明有很好的提升效果。

【关键词】OpenCV;模式识别;android;机械学习;NDK;人脸定位

1.前言

因为移动智能设备外形小巧,携带方便等,现在人们使用普通pc机的时间已经慢慢地被移动设备替代。android系统的NDK是使用c\c++的开发环境,c\c++通用型比较好,算法移植方便,但是NDK的相关资料不是很多,这也导致程序编写时出现某些错误很难解决。移动设备与普通pc机相比有一个很大的劣势――普通pc机的单核处理能力很强。但移动设备在核心数量上却没有劣势,所以很多使用串行的方法的文献对人脸定位进行优化并不能很好的体现在移动设备上,会使系统的实时性大打折扣。使用Haar特征的级联分类器是比较流行的人脸检测工具,其不错的识别率很受欢迎,而且可以自己训练。由于同种人的肤色相近,而HSI上的H分量对光照影响极小,只通过H分量即可很好的判断是否为检测到的人脸为真人脸,在加入其他特征的判断,会使得准确性提升明显。

2.整体方案

2.1 使用的工具

OpenCV:

OpenCV的全称是:Open Source Computer Vision Library。它是一个跨平台的计算机视觉库,民用和商用两方面免费。可以对源码进行修改和二次编译,大大加强了其中函数的灵活性。使用非常方便。OpenCV提供了丰富的计算机视觉相关函数,使得开发的效率大幅度提供,而且还支持一些高级的视觉相关方法,比如目标跟踪,机器学习等。本次使用的版本为OpenCV2.4.8。

移动设备:

联想A820t手机。其主要属性为:联发科MT6589cpu,cmos摄像头和安卓系统。MT6589采用28nm工艺,超低功耗四核处理器Cortex-A7,1.2G主频。本次实践的图像分辨率为640*480,所以摄像头像素达到30万就行了,并不关键。关于帧数与实时性,经测试在光线充足的情况下能到达的30帧,即使在很黑暗的环境下也能稳定在24帧,且实时性较好。

安卓 NDK:

NDK全称:Native Development Kit。它提供了一个使用c或c++来编写安卓应用的环境。由于错误资料不是很多,所以在实现时用了大量时间。

2.2 整体流程

2.2.1 实现人脸定位

使用haar特征的级联分类器进行单线程的人脸定位的一帧流程:

①首先采集摄像头一帧数据。

②执行haar特征级联分类器检测人脸。

2.2.2 优化人脸定位

使用haar特征的级联分类器为主要检测手段,并用人脸颜色在hsi颜色空间上的特性以及人脸其他特征检测作为补助判断,增加准确性。其他特征可选人眼鼻子等,也可以是别的几何形状,本文以人眼为例。

①首先采集摄像头一帧数据。

②之后创建三个子线程且主线程继续采集下一帧数据,三个子线程分别对当前的图像数据执行haar特征级联分类器检测人脸、原始图像到hsi颜色空间的转换和人眼检测。

③三个子线程执行完退出后,主线程对这三个结果进行比较分析,分析方法在下面会提到。

④显示结果

3.系统设计

3.1 实现人脸定位

OpenCV上实现基本的人脸定位非常简单.首先初始化,加载已经训练好的XML分类器文件,本次使用的是OpenCV自带的训练好的分类器,识别率很高,但误识率也很高。

if( !face_cascade.load( “haarcas-cade_frontalface_alt2.xml” ) )

{

printf(“haarcascade_frontalface_alt2.xml加载失败\n”);

return;

};

捕获摄像头图像,使用grab()来抓取摄像头,另外还可以用read()来读取。与grab()相同的是,这两个函数都是阻塞的,不用建立一个循环来一直读取它是否返回。它与grab()不同的是read()会直接返回原始图像,而grab()则需要在这之后使用retrieve()来获取图像,retrieve()可以在内部转换图像格式(支持BGR,GREY,RGB,BGRA,RGBA5种格式)。

if(engine.capture->grab()) engine.capture->retrieve(frame,CV_CAP_ANDROID_COLOR_FRAME_RGBA);

图像信息就在frame里,之后进行两次转行,分别为灰度和直方图均衡化。

cvtColor( frame, frame_k, CV_BGR2GRAY );

equalizeHist( frame_k,frame_k );

最后使用detectMultiScale用进行检测,它的第二个参数就是人脸的容器,包含数量和坐标等信息。

3.2 优化人脸定位

捕获摄像头图像,之后取消子线程的结束标记(如果是第一次运行程序这一步遍没有意义,因为在初始化时已经做了),结束标记为三个整型,0为结束,1为在忙,这里之所以不直接读取线程状态,是因为不需要线程完全结束,只要处理结束了,就可以进行进行,所以随手做了优化。创建三个子线程。同时继续捕获图像,图像捕获完成后进入等待状态。

pthread_t haar_tid,hsi_tid,eye_tid;

int haar_ret,hsi_ret,eye_ret;

haar_ret = pthread_create(&haar_tid, NULL,haar,NULL);

hsi_ret = pthread_create(&hsi_tid, NULL,hsi,NULL);

eye_ret= pthread_create(&eye_tid, NULL,eye,NULL);

在等待时每次循环会usleep(100);这样做会让主线程腾出cpu来,在核心数比较少的情况下很重要。第一个子线程用来处理基本的haar特征的分类器检测人脸,首先拷贝图像,对图像进行灰度处理。灰度处理时间很快,每个像素的计算量只是三个8位变量乘以浮点型的常数之后相加。之后直方图均衡化,再送进级联分类器,结果会放在Rect容器中。最后打上线程结束标记。前面两算法相对来说比较简单,可以考虑手写算法,把图像分割给所有线程同时计算,算好后各线程在开始自己的事情,不过省的时间小于1毫秒,不是主要需要优化的地方。第二个子线程,也需要拷贝图像用来处理RGB到HSI转换,经典的RGB到HSI转换速度非常慢,因此特地的对RGB到HSI的转换过程进行优化。因为色彩判断只需要H分量,H分量受到光照的影响最小,是颜色的直接体现,可以去掉其他分量来增加性能。RGB到HSI转换的公式(H分量)如下图。

图1 几何推导法H分量计算公式

这是经典的几何推导法H分量的计算,比较流行,但因为存在平方根和反余弦计算,导致非常消耗时间。经试验证明其时间远大于级联分离器计算的时间。所以考虑用Bajon近似算法:

图2 Bajon近似算法H分量计算公式

使用此计算公式就使得颜色转换的时间小于级联分类器的识别时间。如果想更深度的优化,可以考虑NEON,使用汇编进行优化:建立一个.s文件,汇编函数写在这个文件里,在Android.mk 文件里添加编译这个文件。对于平方根计算,有一个近似的快速算法,利用泰勒级数展开取一次项逼近,虽说有一定的误差,但性能需求较高时可以考虑。当然,可以使用OpenCV自带的cvtColor()转换到hsv来代替hsi,然后取hsv的h分量,但是这样的话就无法优化了。第三个子线程和第一个子线程类似,只不过加载的是查找眼睛的级联分类器:haarcascade_lefteye_2splits.xml,经测试其速度比人脸分类器稍快。等到主线程检测到三个结束标记时,读取容器里的人脸坐标和范围,如果在每个范围内的左上半部分和右上半部分存在1或2个眼睛(有可能只识别到一只眼睛),而且h分量在0.5到0.8的像素数量大于范围面积65%(两个数值是经过分类器提取一些人脸的截图分析,在再适量放宽得出来的,条件太苛刻可能会增加漏识),才会被认为是人脸,并标记显示。然后进行下一帧计算。

图3 整体流程图

准确性:使用这种复合方法定位人脸的抗误识性非常高。笔者找了15个人和6个单独人脸定位会被误识的图案或角落。使用符合识别方法15个人单独识别则100%识别,6个误识样本100%未识别,但在人多环境不稳定的时候相对单haar特征的级联分类器识别会有漏识。

识别人数(共15人) 误识样本(共6个)

单haar特征的级联分类器识别: 15 6

多线程复合识别方法识别:15 0

结果也可能和硬件有关系,不同的平台成像效果不同,结果也就可能不同。

图4 其中一个误识样本

图5 使用复合识别方法的效果

速度:单haar特征的级联分类器识别帧数:6到7帧

单线程复合识别方法识别帧数:2到3帧

没有对HSI转优化的多线程复合识别方法识别帧数:3到4帧

优化后的多线程复合识别方法识别帧数: 6到7帧

可以看到多线程复合识别方法与单haar特征的级联分类器识别速度上没有太大差别,理论上应该稍快,因为提取图像的动作时间省去了,haar线程是最后结束的,所以速度取决于级联分类器的识别速度。多线程加速也起到了作用。有一些地方还可以改进,如下面2个:

(1)grab()和read()抓取摄像头图像时有个很大的缺点,两个函数都是阻塞的,在两帧之间会占用cpu,如果cpu核心数比较低的话,可以考虑对其源码进行二次开发。

(2)在精度要求不是太高的情况下,其他很多算法还可以针对性的加速。例如用整型计算代替浮点型计算或除法计算:浮点型计算可以先用整型计算,最后结果缩小到应有的大小;除数为常数的除法用乘法代替,即a/2.5可以换成a*0.4。

4.结束语

因为此次平台cpu为4核,所以使用了3种方法,加上主线程,一共4个线程,比较充分的使用了硬件资源,如果有更多的核心也可以尝试更多方法复合。如果移动设备可以使用类似CUDA的显卡加速,那么效率能提升不少。本篇只讨论了在移动设备上人脸定位的相关问题。在人脸定位后,还可以扩展许多功能,比如最长见的人脸识别等。笔者水平有限,可能有些地方并不全面,欢迎指出。

参考文献

[1]贾小军,喻擎苍.基于开源计算机视觉库OpenCV的图像处理[J].计算机应用与软件,2008(04).

[2]刘华波.RGB与HSI颜色模型的转换方法对比研究[EB/OL].北京:中国科技论文在线[OL].http:///releasepaper/comment_paper/200804-1063.

[3]高山武,周艳洁.AdaBoost算法在人脸检测中的应用[J].现代计算机(专业版),2011(14).

作者简介:刘欣迪(1992―),男,安徽淮北人,上海交通大学自考本科在读,研究方向:计算机及应用。

上一篇:访问控制列表在高校校园网络安全中的应用 下一篇:探讨地区配电网的稳定性