基于Android及OpenCV平台的形状及颜色识别系统设计
2019-09-07任志敏
任志敏
(常州纺织服装职业技术学院机电学院,江苏 常州 213164)
0 引言
随着无人驾驶、人工智能及5G技术的飞速发展,越来越多的智能新技术应用产品深入寻常百姓家。不管是哪一种产品,少不了Android系统的身影。作为智能化产品的标志之一,类人的视觉系统是必不可少的,其中对颜色和形状的识别又是最基本的。因此,本文将着重解决android平台下颜色和形状识别的问题。
1 方案设计
关于颜色及形状的识别在PC机平台下已经比较成熟,但是在Android平台下受制于软硬件系统的局限性,该技术有待进一步研究。
Android系统的内核是由C/C++设计的Linux系统,其上层支持Java和Kotlin编程语言,目前国内主流使用的仍旧是Java。第一种方案是直接在Android平台上使用Java语言实现颜色和形状识别算法,但是比起C/C++语言,使用Java语言进行图像处理的效率没那么高,因此,直接使用Java语言进行图像处理不是最佳的选择。第二种方案是采用已有的成熟的图像处理库,在Android平台下调用库实现颜色和形状识别。现有的主流图像处理库有OpenCv,CxImage,FreeImage,AForge等。
OpenCV的全称是Open Source Computer Vision Library,是一个基于BSD许可(开源)发行的跨平台计算机视觉库,又名“开源计算机视觉库”。OpenCV可运行在Windows、Android、Maemo、FreeBSD、OpenBSD、iOS、Linux和Mac OS等平台。OpenCV提供了各种图像处理算法,用户通过组合算法实现需要的功能。
CxImage类库是一个优秀的图像操作类库。它可以快捷地存取、显示、转换各种图像。对Windows、MFC支持极好,支持图像的多种操作(线性滤波、中值滤波、直方图操作、旋转缩放、区域选取、阈值处理、膨胀腐蚀、alpha混合等)。
FreeImage也是一个开放源码库项目,为开发人员提供支持当今多媒体应用程序所需的流行图形图像格式,如PNG、BMP、JPEG、TIFF等。FreeImage易于使用,速度快,多线程安全,兼容所有32位或64位版本的Windows,也支持Linux和Mac OS X。
AForge.NET是一个专门为开发者和研究者基于C#框架设计的,该框架提供了不同的类库和关于类库的资源,还有很多应用程序例子,包括计算机视觉与人工智能,图像处理,神经网络,遗传算法,机器学习,机器人等领域。
综合比较,OpenCV因其优秀的跨平台性,已经是目前PC平台下最主流的图像处理库,并已经通过了大量工程应用的考验,因此,本文选择OpenCV为颜色形状识别的支持库。OpenCV提供了基于Android平台的SDK,支持3种方式接入Android。
第一种方式适用于对OpenCVc++不熟悉的用户,不需要直接调用C++方案,因为官方提供的SDK已经用JNI全部封装好了。用户只需要安装好JDK、AndroidStudio与NDK环境。
第二种方式是使用OpenCVSDK提供的C++头文件、.so动态库和.a静态库,用户自己封装JNI,该方式使用的效率会比第一种方法高一些,且可以100%使用OpenCV的接口[1]。
第三种方式通过OpenCV的源码,重新编译成Android SDK库,这样的好处是能获取到OpenCV最新的功能,缺点是编译较为复杂,且新的代码或许会存在不兼容与错误。
综合比较以上三种方式的优缺点,本文使用第二种方式,通过JNI调用OpenCV提供的API,使用C++语言操作OpenCV的接口。
2 设计过程
为了验证颜色形状识别的可行性与可靠性,本文设定的识别目标为4种颜色(红色、绿色、黄色和蓝色),5种形状(长方形、正方形、三角形、多边形和圆)。如图1所示。
图1 颜色形状识别样图
第一步建立Androidstudio平台下OpenCv的JNI开发环境[2]。本文使用的版本是Android Studio3.2和OpenCv3.4.2-android-sdk。如图2所示。
第二步:设计APP(Java语言)。如图3所示。
一共设计了4个控件,包括2个Button,1个ImageView,1个TextView。“选择…”按钮用于打开Android系统的图片目录,选择需要识别的图片。ImageView用于显示选择的待识别图片。“形状颜色识别”按钮用于执行具体的识别程序。APP底部的TextView控件用于显示识别的结果。
图2 android studio及opencv开发环境
图3 颜色形状识别APP布局文件
因为要读取Android的系统图片目录,需要首先在AndroidManifest.xml文件中设置允许读外部存储器权限。即:
若使用的androidSDK是23及以上版本,还需要在程序中设置运行时允许读权限。
因为打开Android系统图片目录是一个新的Activity,该Activity需要向MainActivity回传图片路径信息,因此使用startActivityForResult(Intent intent, int requestCode)方法打开新的Activity,并把图片文件回传给MainActivity中的变量fileUri。设计颜色形状识别函数
private void colorShapeDector() {
Mat image = Imgcodecs.imread(fileUri.getPath());
if(image.empty()) {
return;
}
strResult = DetectShapeColor(image.getNativeObjAddr());
tvResult.setText(strResult);
调用imread获取待识别图片的数据元素。通过image.getNativeObjAddr()方法把Java端获得的路径转换为OpenCV端可识别的路径。
第三步:设计颜色形状识别程序(C++语言)
在native-lib.cpp声明识别函数名称、参数和返回值。
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_sidneyren_firstdemo_MainActivity_DetectShapeColor(
JNIEnv *env,
jobject /* this */,
jlong addrInputRgbaImage
)
S1:为了增强识别的鲁棒性,转换图片的颜色空间,由RGB转换为HSV。cvtColor(img,imgHSV,COLOR_BGR2HSV);其中img为原始图像,imgHSV为转换后的图像。
S2:设置待识别颜色的HSV三个分量的上下限阈值,以绿色为例,greenLowH=35,greenHighH=77,greenLowS=43,greenHighS=255,greenLowV=46,greenHighV=255。调用inRange(imgHSV,Scalar(greenLowH,greenLowS,greenLowV),Scalar(greenHighH,greenHighS,greenHighV),imgThresholded)函数对imgHSV图像进行分割,位于绿色HSV上下限区间内的像素点设置为255,不在该范围内的像素点设置为0,即生成一个二值化图像[3],分割后生成的图像imgThresholded如图4所示。
图4 分割后的图像
S3:调用形态学操作函数:element=getStructuringElement(MORPH_RECT, Size(5,5));对图像进行腐蚀和膨胀。调用函数morphologyEx对图像进行开闭操作,并提取轮廓,处理后的图像如图5所示。
图5 腐蚀、膨胀后的图像
S4:设计形状识别的类ShapeDetector。
调用arcLength函数计算封闭轮廓的周长。调用approxPolyDP函数对图像轮廓点进行多边形拟合,从而获得输出的多边形点集,通过判断多边形点集的数量判断具体是哪种形状。
S5:遍历图像中所有轮廓,调用形状识别类,即可识别具体某一种颜色块的所有形状。
S6:设置红色、黄色和蓝色的HSV上下限阈值,重复步骤S3~S5即可识别4种颜色块的形状。
3 结论
本文一共使用100张各种形状的图片来验证APP的识别准确率,图片分成形状和颜色不连接的部分和连接的部分,结果形状和颜色均不连接的图片识别准确率为100%,形状和颜色连接的图片有一张未能准确识别,总体识别准确率为99%。