Android | 教你如何用三十分钟在安卓上开发一个微笑抓拍神器
前言
前段时间Richard Yu在发布会上给大家介绍了华为HMS Core4.0,回顾发布会信息请戳:
华为面向全球发布HMS Core 4.0意味着什么?
其中有一个重点被介绍的服务,机器学习服务(Machine Learning Kit 简称 MLKit)。
那机器学习服务能干什么呢?能帮助开发者解决应用开发过程中的哪些问题?
今天就抛砖引玉一下,以人脸检测为例,给大家出一个实战小样例,让大家感受下机器学习服务所提供的强大功能以及给开发者提供的便捷性。
机器学习服务人脸检测所提供的能力
先给大家看一下华为机器学习服务人脸检测能力的展示:
从这个动图里面可以看到,人脸识别可以支持识别人脸的朝向,支持检测人脸的表情(高兴、厌恶、惊讶、伤心、愤怒、生气),支持检测人脸属性(性别、年龄、穿戴),支持检测是否睁眼闭眼,支持人脸以及鼻子、眼睛、嘴唇、眉毛等特征的坐标检测,另外还支持多人脸同时检测,是不是很强大!
核心提示:此功能免费,安卓全机型覆盖!
多人脸微笑拍照功能开发实战
今天就用机器学习服务的多人脸识别+表情检测能力写一个微笑抓拍的小demo,做一次实战演练。demo源码github下载请戳这里
1、开发准备
华为HMS的kit开发前准备工作都差不多,无非就是添加maven依赖,引入SDK。
1.1 在项目级gradle里添加华为maven仓
增量添加如下maven地址:
buildscript { repositories { maven {url 'http://developer.huawei.com/repo/'} } }allprojects { repositories { maven { url 'http://developer.huawei.com/repo/'} }}
1.2 在应用级的build.gradle里面加上SDK依赖
把人脸识别的SDK和基础SDK引入:
dependencies{ // 引入基础SDK implementation 'com.huawei.hms:ml-computer-vision:1.0.2.300' // 引入人脸检测能力包 implementation 'com.huawei.hms:ml-computer-vision-face-recognition-model:1.0.2.300' }
1.3 在AndroidManifest.xml文件里面增量添加模型自动下载
这个主要是用来模型更新的,后面算法有了优化,可以自动下载到手机里面更新
<manifest <application <meta-data android:name="com.huawei.hms.ml.DEPENDENCY" android:value= "face"/> </application></manifest>
1.4 在AndroidManifest.xml文件里面申请相机和存储权限
<!--相机权限--><uses-permission android:name="android.permission.CAMERA" /><!--使用存储权限--><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2、代码开发
2.1 创建人脸分析器,检测到微笑后进行拍照
检测后拍照:
- 进行分析器参数配置
- 把分析器参数配置传给分析器
- 在analyzer.setTransacto内通过重写transactResult处理人脸识别后的内容,人脸识别后会返回一个微笑的置信度(简单可以理解为是微笑的概率),只要设置大于一定置信度进行拍照就可以了。
private MLFaceAnalyzer analyzer;private void createFaceAnalyzer() { MLFaceAnalyzerSetting setting = new MLFaceAnalyzerSetting.Factory() .setFeatureType(MLFaceAnalyzerSetting.TYPE_FEATURES) .setKeyPointType(MLFaceAnalyzerSetting.TYPE_UNSUPPORT_KEYPOINTS) .setMinFaceProportion(0.1f) .setTracingAllowed(true) .create(); this.analyzer = MLAnalyzerFactory.getInstance().getFaceAnalyzer(setting); this.analyzer.setTransactor(new MLAnalyzer.MLTransactor<MLFace>() { @Override public void destroy() { } @Override public void transactResult(MLAnalyzer.Result<MLFace> result) { SparseArray<MLFace> faceSparseArray = result.getAnalyseList(); int flag = 0; for (int i = 0; i < faceSparseArray.size(); i++) { MLFaceEmotion emotion = faceSparseArray.valueAt(i).getEmotions(); if (emotion.getSmilingProbability() > smilingPossibility) { flag++; } } if (flag > faceSparseArray.size() * smilingRate && safeToTakePicture) { safeToTakePicture = false; mHandler.sendEmptyMessage(TAKE_PHOTO); } } });}
拍照存储部分:
private void takePhoto() { this.mLensEngine.photograph(null, new LensEngine.PhotographListener() { @Override public void takenPhotograph(byte[] bytes) { mHandler.sendEmptyMessage(STOP_PREVIEW); Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); saveBitmapToDisk(bitmap); } });}
2.2 创建视觉引擎,捕捉相机动态视频流后传给分析器
private void createLensEngine() { Context context = this.getApplicationContext(); // Create LensEngine this.mLensEngine = new LensEngine.Creator(context, this.analyzer).setLensType(this.lensType) .applyDisplayDimension(640, 480) .applyFps(25.0f) .enableAutomaticFocus(true) .create();}
2.3 动态权限申请,挂接分析器和视觉引擎创建代码
@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.activity_live_face_analyse); if (savedInstanceState != null) { this.lensType = savedInstanceState.getInt("lensType"); } this.mPreview = this.findViewById(R.id.preview); this.createFaceAnalyzer(); this.findViewById(R.id.facingSwitch).setOnClickListener(this); // Checking Camera Permissions if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { this.createLensEngine(); } else { this.requestCameraPermission(); }} private void requestCameraPermission() { final String[] permissions = new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}; if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) { ActivityCompat.requestPermissions(this, permissions, LiveFaceAnalyseActivity.CAMERA_PERMISSION_CODE); return; }}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode != LiveFaceAnalyseActivity.CAMERA_PERMISSION_CODE) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); return; } if (grantResults.length != 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { this.createLensEngine(); return; }}
结束语
怎么样,开发过程是不是特别简单,30分钟就可以开发一个新特性出来!让我们一起体验下这个多人脸微笑抓包的效果。
单人笑脸抓拍:
多人笑脸抓拍:
基于人脸检测能力,还可以做哪些功能出来,请开放你的脑洞!这里不妨再给一些提示,比如:
- 通过识别耳朵、眼睛、鼻子、嘴巴、眉毛等脸部特征的位置,添加一些有趣的装饰特效。
- 通过识别面部的轮廓,做一些夸张的变形、拉伸,生成一些有趣好玩的人像图片,或者针对轮廓区域开发美颜功能。
- 通过年龄识别,对儿童沉迷于电子类产品的痛点,开发一些家长管控类功能。
- 通过检测眼睛盯着屏幕的时长,开发护眼提示的特性。
- 通过随机指令(摇头、眨眼、张嘴等)实现用户动作配合式活体检测功能。
- 通过综合运用用户的年龄、性别等的检测结果,给用户做相关商品推荐;
更详细的开发指南参考华为开发者联盟官网
华为开发者联盟机器学习服务开发指南
内容来源:https://developer.huawei.com/consumer/cn/forum/topicview?tid=0201198419687680377&fid=18
原作者:AI_talking
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
华为发布全新一代OceanStor存储Pacific系列,打造海量数据存储新标杆
[中国,深圳,2020年5月28日] 今天,华为面向全球发布全新一代海量数据存储OceanStor存储Pacific系列,通过打破架构、服务和性能的边界,以多协议无损互通、下一代弹性EC算法和系列化硬件,灵活应对AI、HPC、视频等海量数据场景的多样化需求及效率、成本和可靠性挑战,成为海量数据存储新标杆,帮助企业释放海量数据价值。 随着第四次工业革命的来临,数字化生产已经成为普遍的商业模式。数字化生产以数据为处理对象,实现“数据变机会,机会变服务,服务变收入”。数据成为新生产资料,企业需要采集和存储更丰富的数据,包括核心业务的结构化数据和5G、IoT、超高清等带来的海量非结构化数据,并结合人工智能对数据进行分析和处理,将数据转换为知识和服务,提升生产效率。 华为数据存储与机器视觉产品线总裁周跃峰表示:“海量数据在企业数字化转型中扮演着越来越重要的角色,然而当前只有2%的数据被保存、保存下来的数据只有10%得到分析利用,企业面临海量数据存不下、流不动、管不好的问题。华为OceanStor存储Pacific系列致力于打造海量数据存储新标杆,成为海量数据安心之选。” 华为数据存储与机器视觉产...
- 下一篇
无声的性能杀手——伪共享(False Sharing)
性能杀手 缓存系统中是以缓存行(cache line)为单位存储的。缓存行是2的整数幂个连续字节,一般为32-256个字节。最常见的缓存行大小是64个字节。当多线程修改互相独立的变量时,如果这些变量共享同一个缓存行,就会无意中影响彼此的性能,这就是伪共享。缓存行上的写竞争是运行在SMP系统中并行线程实现可伸缩性最重要的限制因素。有人将伪共享描述成无声的性能杀手,因为从代码中很难看清楚是否会出现伪共享。 为了让可伸缩性与线程数呈线性关系,就必须确保不会有两个线程往同一个变量或缓存行中写。两个线程写同一个变量可以在代码中发现。为了确定互相独立的变量是否共享了同一个缓存行,就需要了解内存布局,或找个工具告诉我们。Intel VTune就是这样一个分析工具。本文中我将解释Java对象的内存布局以及我们该如何填充缓存行以避免伪共享。 上图说明了伪共享的问题。在Core1上运行的线程想更新变量X,同时Core2上的线程想要更新变量Y。不幸的是,这两个变量在同一个缓存行中。每个线程都要去竞争缓存行的所有权来更新变量。如果Core1获得了所有权,缓存子系统将会使Core2中对应的缓存行失效。当Core...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Hadoop3单机部署,实现最简伪集群
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2全家桶,快速入门学习开发网站教程
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库