杜丹
摘要:人脸检测是指把人脸从一幅静止的图像或者动态视频中检测出来,并且指出人脸在图像或视频中的大小和位置。基于移动端的人脸检测技术操作方便、安全有效,受到了越来越多用户的青睐,人脸检测的方法成为各个计算机视觉技术人员的研究热点。基于此背景,在Android平台下,提出一种基于OpenCV的人脸检测系统,采用训练好的LBP(Local Binary Pattern)与HAAR(特征级联分类)生成人脸分类器,对预处理好的人脸图像,利用OpenCV中的detectMultiScale方法来实现人脸检测,可以对手机端的人脸正面图片进行识别,从测试结果表明,该方法对人脸正面状态下的识别率高,可适用于各个应用场景。
关键词:人脸检测;Android;OpenCV
中图分类号:TP18 文献标识码:A
文章编号:1009-3044(2022)30-0011-03
开放科学(资源服务)标识码(OSID):
随着人工智能技术(AI)和移动互联网技术的不断发展,人脸检测和识别在社交媒体、视频监控、身份验证等领域应用广泛[1]。人脸检测技术是指把人脸从一幅静止的图像或者动态视频中检测出来,并且指出人脸在图像或视频中的大小和位置[2]。基于移动端的人脸检测技术操作方便、安全有效,受到了越来越多用户的青睐,人脸检测的方法成为各个计算机视觉技术人员的研究热点[3]。基于此背景,在Android开发环境Android Studio中配置好OpenCV后,可以方便调用各种API函数对计算机图像进行处理,常用的功能有图像处理、人脸识别、人机互动、图像分割、动作识别、运送跟踪等。本系统调用OpenCV的人脸检测API,采用训练好的LBP(Local Binary Pattern)与HAAR(特征级联分类)生成人脸分类器,最后利用这个分类器来实现人脸正面图片检测。
1 相关技术介绍
OpenCV(Open Source Computer VisionLibray),是一个跨平台的计算机视觉开发软件库,是BSD开源许可的计算机视觉开发框架,其开源协议允许在学术研究和商业应用开发中免费使用[4]。它支持Linux、Windows和Android等各个操作系统,轻量级且高效。Android是谷歌(Google )公司在 2008 年 12 月发布的 移动操作系统。OpenCV Android SDK是OpenCV针对Android平台提供的开发工具包。Android应用开发一般采用Java语言进行,OpenCV主要模块采用C语言、C++语言编制,因此在Android环境下可以通过JNI技术,实现使用Java语言调用OpenCV算法模块的目的[5]。
2 开发环境搭建
基于Android环境下的人脸检测开发要求Android Studio4.0以上环境,同时添加NDK、CMAKE等组件,需要提前下载并配置好OpenCV Android SDK4.5.0或以上版本,OpenCV和Android的集成方式采用全集成的方式,是将OpenCV-SDK全部导入的Android Studio中,具体导入方式如下[6]。
2.1新建一个Android项目
打开Android Studio,按照常规步骤新建一个Empty Activity的Android项目。填写项目的名称,并选择SDK版本,单击确定,完成一个Android项目的创建。
2.2在Android工程中导入OpenCV SDK
Android工程中导入OpenCV SDK的方法有两种,一种是只导入SDK下的API包,还有一种是导入整个SDK包。若采用第一种方式导入,后期修改配置工作量大,本系统设计时采用第二种方式进行SDK的导入,导入具体步骤是点击File-New-import Module,在弹出的对话框中定位到OpenCV-SDK的具体位置,即可将OpenCV SDK包导入到当前APP Project中。
2.3 Android SDK和Gradle的配置
在Android項目列表中,打开App的build.gradle文件,确定gradle版本号和Android SDK版本号与OpenCV中的build.gradle文件中的版本保持一致。
2.4添加module dependency
在Project structure中添加module dependency,使得Android项目可以识别OpenCV,即可完成开发环境的搭建。
3 系统实现
Android平台下基于OpenCV进行人脸检测的过程分为五步。第一步是加载OpenCV库,在Android Studio中添加OpenCV开发包;第二步是Android 平台基于人脸检测的UI界面设计;第三步是图像文件的预处理,处理成OpenCV可以读取的图像格式和色彩模式;第四步是设计合适的人脸检测级联分类器,并利用已经训练好的人脸正面数据进行测验,从而进一步提升分类器测试的准确率;第五步是编写detect方法,实现人脸检测功能。
3.1加载OpenCV库
在Android的用户界面Activity中定义一个方法init(),用于加载OpenCV库。加载的方式是OpenCVLoader.initDebug(),该方法返回一个boolean类型的对象,如果加载成功,返回true,如果加载不成功,可以给一个加载失败的提示,具体的代码如下:
boolean success= OpenCVLoader.initDebug();
if (success){
利用Toast提示加载成功
}
else {
利用Toast提示加载失败
}
3.2 设计Android的用户界面
人脸检测Android 移动端用户界面采用垂直方向的线性布局(LinearLayOut)进行检测界面布局,界面上一共有3个组件,最上面的是一个图像组件(ImageView1),用于加载需要识别的图片,在这个图片正下方,是另一个图像组件(ImageView2),用于显示调用人脸检测方法后,绘制人脸轮廓效果的图片,通过这个图像组件,可以看到人脸检测的效果;第三个组件是在检测界面窗体的最下方,是一个按钮组件(Button)。添加完组件后,对按钮添加单击事件的监听,如果发生单击事情,将调用faceDetect()方法来处理这个事件,即在第二个图像组件ImageView2中显示检测的效果。
3.3图像文件的预处理
3.3.1 Mat和BitMap图像格式转换
Android中的图像是采用Bitmap格式来进行处理的,BitMap是Android系统中用来存储图像信息的内存对象,通过它可以获取图像的常见属性、像素数据,修改图像的像素数据,呈现出不同的图像显示效果,保存图像等。OpenCV中是用Mat格式对图像进行处理的,Mat用于表示一个多维的单通道或多通道的数组,用来保存实数或复数的向量、矩阵、灰度或彩色图像、立体元素、张量以及直方图等。Mat对象中包含了宽、高、维度、通道数、深度、类型、图像像素等基本信息,所以在Android中使用OpenCV,需要将BitMap图像转换成Mat图像才能进行计算,使用OpenCV完成计算时,如果需要在Android UI上进行显示,又要将Mat图像转换成BitMap图像。
(1)BitMap格式转换Mat格式,是通过Utils.bitmatToMat()方法由Bitmap对象转换得到Mat对象实例,首先创建一个Mat对象,命名为matSrc,然后将Bitmap格式的图像对象photo转换成Mat格式存放在matSrc中,核心代码如下:
Mat matSrc=new Mat();
Utils.bitmapToMat(Bitmap photo, Mat matSrc)
(2)Mat格式转换BitMap格式,需先创建和mat对象同等大小的bitmap对象,然后再使用Utils工具类调用matToBitmap方法实现两种图像格式转换,核心代码如下:
Bitmap newBitMap=Bitmap.createBitmap(mat.width(),mat.height(),Bitmap.Config.ARGB_8888);
Utils.matToBitmap(mat,newBitmap);
3.3.2图像灰度化处理
常见图像的色彩模式有位图模式、灰度模式、RGB模式和HSV模式。在人脸识别图像处理过程中,为了加快图像识别速度,需要把彩色图像转换为灰度图像。灰度模式是一种使用单一色调表示图像的模式,一般使用256级灰度来表示图像,一个像素占8个字节,每个像素值使用0~255的亮度值表示,灰度值大的像素点比较亮(像素值最大为255,为白色),反之比较暗(像素最下为0,为黑色)。灰度模式相当于从黑、灰、白的过渡,通常所说的黑白照片就是这种模式,灰度模式与位图模式相比,能表现出一定的细节。
一般有四种方法对彩色图像进行灰度化处理:分量法、最大值法、平均值法、加权平均法。本次实验采用的是平均值法进行灰度化处理,即获取原图像素的RGB值,利用(R值+G值+B值)/3即得到当前图片像素点的灰度值。
3.4设计人脸检测的级联分类器
OpenCV中的人脸检测是基于训练好的LBP与HAAR的特征级分类检测器完成的。LBP(Local Binary Pattern),一般使用统计直方图作为特征向量,用于分类识别,如纹理分类、人脸分析等。HAAR特征是计算机视觉中一种经常使用的特征描述算子,其中Haar-like特征,常用于描述图像的特征,多用于人脸检测、行人检测等目标检测[7]。如果采用單个LBP检测器或单个HAAR检测器都可以对边缘、直线、角点等特殊图像特征进行分类,但容易受到外界噪声、像素混叠等因素的干扰,导致误判率较高。所以,本系统将几个LBP检测器和HAAR特征检测器串联在一起,形成强分类器,如图1所示,再将强分类器组成级联分类器,然后进一步使用更多的强分类器级联对特征区域进行候选检测,直到满足指定的条件,输出检测得到的最终结果。图1是采用决策树构成一个级联分类器的流程图:
3.5 加载OpenCV中的人脸模型训练数据
为了检验笔者设计的级联分类器的分类准确性,在OpenCV SDK中有很多训练好的模型,可以通过测试训练数据了解分类器分类的准确性。在SDK的etc目录下,找到关于人脸正面识别的训练模型数据lbpcascade_frontalface_improved.xml,在Android studio工程的raw目录下,将这个XML文件拷贝进来,具体目标目录见图2,然后初始化级联分类器,就可以使用相关API完成人脸检测功能。
加载完训练集后,需要创建一个文件类对象,指向导入的训练模型文件,根据这个文件,将刚创建的文件类对象的路径作为参数,再创建一个分类器对象,具体代码如下:
File cascadeFile = new File(cascadeDir, "lbpcascade_frontalface_improved.xml");
CascadeClassifier classifier = new CascadeClassifier(cascadeFile.getAbsolutePath());
3.6 OpenCV中使用detectMultiScale方法进行人脸检测
3.5.1 detectMultiScale方法参数介绍
程序初始化后,单击按钮,就可以调用级联分类器的detectMultiScale方法,用来实现人脸检测。
detectMultiScale方法的参数众多,它前面2个参数表示的是输入的图像,也就是待检测的图像,第2个参数表示检测到的对象个数;第3个参数是尺度变换的比率,它的一般值在1.05到1.2之间。第4个参数是领域范围内符合条件的对象个数,它是输出检测最终BOX的重要阈值,如果这个值太大,则条件比较苛刻,不容易检测出对象,如果这个值太小,则容易导致错误检测。第5个flags参数,一般设置为0即可。minSize参数,是对象检测的最小范围,可以设置成new Size(30,30),也就是30×30以下像素的人脸识别不出来。maxSize参数,是对象检测的最大范围。这里可以不限,即设置成new Size(),detectMultiScale具体方法参数和示例见如下代码:
detectMultiScale(Mat matGray, MatOfRect faces, double scaleFactor, minNeighbors, flags, minSize, maxSize);
classifier.detectMultiScale(matGray, faces, 1.05, 3, 0, new Size(30,30), new Size());
3.6.2 遍历检测结果,用矩形绘制检测区域
将检测出的人脸形状数组faces转换成线性链表faceList,利用for-each循环遍历faceList,在每个人脸图像上绘制一个红色的矩形,具体代码如下:
List
for(Rect rect : faceList) {
Imgproc.rectangle(matSrc, rect.tl(), rect.br(), new Scalar(255,0,0,255), 4, 8, 0);
}
3.6.3 將绘制好矩形的图像进行格式转换,并返回给调用的函数
dstBitmap = Bitmap.createBitmap(photo.getWidth(), photo.getHeight(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(matSrc,dstBitmap);
return dstBitmap;
4 Android平台基于OpenCV人脸系统测试
为了提升系统的检测成功率,从网络中搜索图片进行系统功能性测试,测试共进行两轮。第一轮测试选择的是50张正面的人脸图片,当点击人脸检测按钮时,会在下方的图像中用红色矩形绘制一个矩形,矩形内就是人脸的范围;对于单张正面图片的检测识别率很高,共45张照片能够准确识别出人脸的范围,识别率达到90%以上。部分没有识别的图片中,有的是人脸太小,范围小于30×30像素,有的是人脸被手或其他物品遮挡,导致不能正常检测出来。第二轮测试选择的是10张包含多个正面人脸图片,测试发现7张可以正确检测,有3张,由于光照、大小、侧面等因素,人脸检测不完整。不过如果人脸都是正面的,识别率还是相对较高,具体人脸检测系统结果见表1。
以下是两轮测试的结果截图,第一张测试的是单人图片,可以准确地识别出人脸的范围,第二张测试的是4人图片,也可以准确识别出人脸,具体检测结果如图3所示。
5 总结
本文介绍了在Android平台下, 调用 OpenCV 计算机视觉库,搭建开发环境,对输入的人脸正面图片进行预处理,选用多个LBP和HAAR特征构建一个级联分类器,选择OpenCV训练好的人脸正面检测数据库,利用detectMultiScale方法对人脸正面图片进行人脸目标检测,从两轮测试数据来看,对输入单个人脸正面图片的检测精度可达 90%。对输入包含多张人脸图片的检测精度达到70%。该系统进一步升级后,可应用到实际生活中,例如车牌识别,交通信号灯识别等方面;本系统在Android平台上,实现静态的正面人脸图片的检测,今后研究将扩大范围,调用Android移动端的摄像头,可以对动态的人脸图像进行检测;另外也可以增加识别范围,深入研究侧面人脸检测和人脸表情识别工作[8-9]。
参考文献:
[1] 兰胜坤.基于Adaboost算法的人脸检测实现[J].电脑与信息技术,2021,29(2):16-19.
[2] 晏志超.基于Android系统的人脸识别算法研究与实现[D].芜湖:安徽工程大学,2016.
[3] 魏永成.基于Android系统的实时人脸识别及其应用[D].成都:电子科技大学,2014.
[4] 张军平,徐衍胜.Android平台下基于OpenCV的车牌号识别技术[J].兰州交通大学学报,2021,40(3):57-62.
[5] 江鹏,施一萍,袁建平.基于Android系统的人脸识别门禁系统的设计[J].计算机测量与控制,2018,26(11):195-198.
[6] 王甜.基于OpenCV在Android移动终端的图形识别[J].电子制作,2020(23):64-65,63.
[7] 周倩,王军,王亮亮.基于OpenCV轮廓逼近的Android简单图形识别[J].福建电脑,2016,32(2):122-123.
[8] 刘军伟.基于OpenCV的图形识别系统设计[J].电子技术与软件工程,2019(21):60-62.
[9] 季秀怡.浅析人工智能中的图像识别技术[J].电脑知识与技术,2016,12(14):147-148.
【通联编辑:唐一东】