美文网首页
三十分钟在安卓上开发一个微笑抓拍神器-用华为机器学习服务HMS

三十分钟在安卓上开发一个微笑抓拍神器-用华为机器学习服务HMS

作者: AI_talking | 来源:发表于2020-03-17 14:34 被阅读0次

    引子

    前段时间Richard Yu在发布会上给大家介绍了华为HMS Core4.0,回顾发布会信息请戳:
    华为面向全球发布HMS Core 4.0意味着什么?

    其中有一个重点被介绍的服务,机器学习服务(Machine Learning Kit 简称 MLKit)。
    那机器学习服务能干什么呢?能帮助开发者解决应用开发过程中的哪些问题?
    今天就抛砖引玉一下,以人脸检测为例,给大家出一个实战小样例,让大家感受下机器学习服务所提供的强大功能以及给开发者提供的便捷性。

    机器学习服务人脸检测所提供的能力

    先给大家看一下华为机器学习服务人脸检测能力的展示:


    20200313-151307(eSpace).gif

    从这个动图里面可以看到,人脸识别可以支持识别人脸的朝向,支持检测人脸的表情(高兴、厌恶、惊讶、伤心、愤怒、生气),支持检测人脸属性(性别、年龄、穿戴),支持检测是否睁眼闭眼,支持人脸以及鼻子、眼睛、嘴唇、眉毛等特征的坐标检测,另外还支持多人脸同时检测,是不是很强大!

    ==核心提示:此功能免费,安卓全机型覆盖!==

    多人脸微笑拍照功能开发实战

    今天就用机器学习服务的多人脸识别+表情检测能力写一个微笑抓拍的小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 创建人脸分析器,检测到微笑后进行拍照

    检测后拍照:
    1)进行分析器参数配置
    2)把分析器参数配置传给分析器
    3)在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 动态权限申请,挂接分析器和视觉引擎创建代码

    @Override
    public 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;
        }
    }
    
    @Override
    public 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分钟就可以开发一个新特性出来!让我们一起体验下这个多人脸微笑抓包的效果。

    单人笑脸抓拍:


    1584090069663.gif

    多人笑脸抓拍:


    1584084416185.gif

    基于人脸检测能力,还可以做哪些功能出来,请开放你的脑洞!这里不妨再给一些提示,比如:
    1、通过识别耳朵、眼睛、鼻子、嘴巴、眉毛等脸部特征的位置,添加一些有趣的装饰特效。
    2、通过识别面部的轮廓,做一些夸张的变形、拉伸,生成一些有趣好玩的人像图片,或者针对轮廓区域开发美颜功能。
    3、通过年龄识别,对儿童沉迷于电子类产品的痛点,开发一些家长管控类功能。
    4、通过检测眼睛盯着屏幕的时长,开发护眼提示的特性。
    5、通过随机指令(摇头、眨眼、张嘴等)实现用户动作配合式活体检测功能。
    6、通过综合运用用户的年龄、性别等的检测结果,给用户做相关商品推荐;

    更详细的开发指南参考华为开发者联盟官网:
    华为开发者联盟机器学习服务开发指南

    下期预告

    基于华为机器学习服务,后面还会有一系列的实战经验分享,大家可以持续关注~

    相关文章

      网友评论

          本文标题:三十分钟在安卓上开发一个微笑抓拍神器-用华为机器学习服务HMS

          本文链接:https://www.haomeiwen.com/subject/ibdtyhtx.html