Android 开发者如何通过运动视觉 API 进行机器学习 - 第一部 - 人脸检测

简介: 本文讲的是Android 开发者如何通过运动视觉 API 进行机器学习 - 第一部 - 人脸检测,在计算机科学中,机器学习是一个非常有意思的领域,它已经在我的最想学习的愿望清单中驻留已久。因为有太多来自于RxJava, Testing, Android N, Android Studio 以及其他 Android 相关的技术更新,所以我都每能花时间来学习这个。
本文讲的是Android 开发者如何通过运动视觉 API 进行机器学习 - 第一部 - 人脸检测,

在计算机科学中,机器学习是一个非常有意思的领域,它已经在我的最想学习的愿望清单中驻留已久。因为有太多来自于RxJavaTestingAndroid NAndroid Studio 以及其他 Android 相关的技术更新,所以我都每能花时间来学习这个。甚至在 Udacity 还专门有一个有关机器学习的课程。 :stuck_out_tongue:  。

让我非常激动的发现是,目前任意一个开发人员都能基于运动视觉(Mobile Vision API) 把机器学习运用在他们自己的应用程序中,这个技术来自于 Google,它让你甚至都不需要有机器学习领域的专业知识。你只需要关心怎么利用这些 APIs

在云服务和移动应用中,有很多运用于机器学习的 APIs,但是在这些 API 中,我将只关注运动视觉 (Mobile Vision)API,因为它是专门为 Android 开发者们创造的。目前运动视觉 (Mobile Vision) API 包含了三种功能: 人脸侦测 API,条形码侦测 API,文本侦测 API。在这篇文章中,我们将涉及人脸侦测的内容,并且会在之后的一系列文章里讨论剩下的两种功能。

人脸侦测 API

这个 API 被用于侦测和追踪在图片或视频中的人脸,但是它还不具备人脸识别的能力。它能在脸上进行侦测标定并提供人脸分类的功能。人脸标定是一系列在脸组成的点,例如眼睛,鼻子和嘴巴。人脸分类被用于检查那些标定的点是否符合某个特征,例如微笑的脸或者闭上了的眼睛,它们是目前仅支持的分类。这个 API 也能在不同的角度进行人脸侦测,并且记录欧式(欧拉)空间中的 Y坐标和 Z 的角度。

入门指南

我们准备创建一个具有两个过滤器的应用程序 printf("%s Story", yourName)。请注意,本文的目的仅为了显示如何使用这个 API,所以这个初始版本的代码将不会进行测试或者遵循任何设计模式。也请注意,最好把所有的处理过程都从 UI 线程中分离。托管在 Github 上的源码 将会更新。

让我们开始吧...

  • 在 Android Studio 中创建一个新的项目
  • 将含有 Mobile Vision API 的 Google Play Services SDK 导入到你项目中 app 层级下的 build.gradle 文件内。在写这篇文章的时候,最新版本是 9.6.1\。请一定要小心这里,如果导入了整个 SDK 而不是仅导入你需要的那个 (play-services-vision),那你一定会达到 65k 方法的限制。
compile 'com.google.android.gms:play-services-vision:9.6.1'
  • 为了启用那些具有人脸侦测功能的依赖库,添加这个 meta-data 到你的 manifest 文件中。
<meta-data
    android:name="com.google.android.gms.vision.DEPENDENCIES"
    android:value="face"/>
  • 下一步,你需要增加一个 ImageView 和 Button 到你的界面布局中。这个按钮通过选择一个图片开始,并处理这个图片,之后把它显示在 ImageView。这个图片能从摄像头或者照片库中获得和加载。为了节约时间,我保存并使用了一个在drawable 文件夹内的图片。
  • 在那个按钮的点击事件内,创建一个新的 BitmapFactory.Options 对象并且把 inmutable 属性设定为 true。这确保了bitmap 是可变的,以便我们对它动态地增加效果。
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inMutable = true;
  • 下一步,从 BitmapFactory 类方法中用 decodeResource 方法创建一个新的 Bitmap。你会使用来自你的 drawable 文件夹内相同的一个图片并且把 BitmapOptions 这个对象通过和之前一样的参数进行创建。
Bitmap defaultBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image, bitmapOptions);
  • 创建一个 Paint 对象并把它的 style 属性设定成 stroke。这确保了图形不会被完全填充,因为我们需要确保头部在长方形内。

注意: 如果你正创建一个名为 !(Recognize Me) 的游戏,你需要在这个游戏内用一个图片挡住你的脸,所以你的对手不得不猜测你是谁,你想要把填充的形式设定成 Paint.Style.FILL

Paint rectPaint = new Paint();
rectPaint.setStrokeWidth(5);
rectPaint.setColor(Color.CYAN);
rectPaint.setStyle(Paint.Style.STROKE);
  • 我们需要一个展现这个 bitmap 的画布。我们先创建一个有临时 bitmap 的画布。这个临时的 bitmap 会和之前的有着一样的尺寸,但是仅仅是这个一样的。我们之后要把原始的 bitmap 画在同一个画布上。
    Bitmap temporaryBitmap = Bitmap.createBitmap(defaultBitmap.getWidth(), defaultBitmap
            .getHeight(), Bitmap.Config.RGB_565);

    Canvas canvas = new Canvas(temporaryBitmap);
    canvas.drawBitmap(defaultBitmap, 0, 0, null);
  • 最后,让我们言归正传,说说看怎么使用 FaceDectector API 。因为我们在使用一个静态的图片,所以追踪功能被禁止了。它应该在视频上被启用。
    FaceDetector faceDetector = new FaceDetector.Builder(this)
            .setTrackingEnabled(false)
            .setLandmarkType(FaceDetector.ALL_LANDMARKS)
            .build();
  • 检查是否人脸侦测正常运作了。有可能第一次它不能正常工作,因为有一个依赖库需要被下载到设备上,而当你需要使用它的时候还没有完全下载完毕。
    if (!faceDetector.isOperational()) {
                new AlertDialog.Builder(this)
                .setMessage("Face Detector could not be set up on your device :(")
                .show();

        return;
    }
  • 下一步,我们用默认的 bitmap 创建一帧,然后调用人脸侦测功能获取人脸对象。
    Frame frame = new Frame.Builder().setBitmap(defaultBitmap).build();
    SparseArray sparseArray = faceDetector.detect(frame);
  • 在这一步中矩形框画在这个人脸上。我们能获取每个人脸左边和上部的位置,但是我们还需要右边和底部的尺寸才能画矩形。为了解决这个问题,我们分别为左边和上部增加宽度和高度。
    for (int i = 0; i < sparseArray.size(); i++) {
        Face face = sparseArray.valueAt(i);

        float left = face.getPosition().x;
        float top = face.getPosition().y;
        float right = left + face.getWidth();
        float bottom = right + face.getHeight();
        float cornerRadius = 2.0f;

        RectF rectF = new RectF(left, top, right, bottom);

        canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, rectPaint);
    }
  • 我们之后创建一个新的 BitmapDrawable,它有一个临时的 bitmap 并且把它设定在界面布局中的 ImageView 中,之后这个人脸侦测的实例就能被释放了。
    imageView.setImageDrawable(new BitmapDrawable(getResources(), temporaryBitmap));

    faceDetector.release();

通过这些步骤,已经可以在每一张人脸上画出一个矩形框了。如果你想在每一张人脸上突出那些标定点,你只需要修改最后两步中的循环内容。你将为没一张脸依次加上标定点,获取标定点的 x 和 y 坐标,并且在每一个标定点处画上一个圆圈。

    for (int i = 0; i < sparseArray.size(); i++) {
        Face face = sparseArray.valueAt(i);

        float left = face.getPosition().x;
        float top = face.getPosition().y;
        float right = left + face.getWidth();
        float bottom = right + face.getHeight();
        float cornerRadius = 2.0f;

        RectF rectF = new RectF(left, top, right, bottom);
        canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, rectPaint);

        for (Landmark landmark : face.getLandmarks()) {
            int x = (int) (landmark.getPosition().x);
            int y = (int) (landmark.getPosition().y);
            float radius = 10.0f;

            canvas.drawCircle(x, y, radius, rectPaint);
        }
    }

有标定点的人脸图片

我很好奇这些标定点是什么展现出来的,所以我使用 landmark.getType() 来查明原由。原来每一个标定点都附带了特别的数字。

    for (Landmark landmark : face.getLandmarks()) {

        int cx = (int) (landmark.getPosition().x);
        int cy = (int) (landmark.getPosition().y);

        // canvas.drawCircle(cx, cy, 10, rectPaint);

        String type = String.valueOf(landmark.getType());
        rectPaint.setTextSize(50);    
        canvas.drawText(type, cx, cy, rectPaint);
    }

当我们想在屏幕上定位跟某个人脸标定点相关的对象的时候,这就非常有用了。如果我们想创建自己的 printf("%s Story", yourName) 应用程序,我们要做的就是把一个图像放置到和其中一个标定点有关的位置上,因为我们现在知道了那些数字代表了什么。让我们开始如下的操作...

假设我们现在是一群海盗,并且我们想通过这个非常棒的 printf("%s Story", yourName) 滤镜来展现左眼上的眼罩。所以eyePatchBitmap 会被画在左眼的位置。

    for (Landmark landmark : face.getLandmarks()) {

        int cx = (int) (landmark.getPosition().x);
        int cy = (int) (landmark.getPosition().y);

        // canvas.drawCircle(cx, cy, 10, rectPaint);

        // String type = String.valueOf(landmark.getType());
        // rectPaint.setTextSize(50);
        // canvas.drawText(type, cx, cy, rectPaint);

        // the left eye is represented by 4 
        if (landmark.getType() == 4) {
            canvas.drawBitmap(eyePatchBitmap, cx - 270, cy - 250, null);
        }
    }

这里有更多 printf("%s Story", yourName) 应用程序的内容...

关于这个 API 还有很多内容。我们能更新这个应用程序,它可以用来在视频内追踪人脸并且允许过滤器跟随头部移动。文中提到的工程源码已经提交到了我们的 GitHub 仓库。





原文发布时间为:2016年11月17日

本文来自云栖社区合作伙伴掘金,了解相关信息可以关注掘金网站。
目录
相关文章
|
24天前
|
Android开发 Swift iOS开发
iOS和安卓作为主流操作系统,开发者需了解两者差异以提高效率并确保优质用户体验。
【10月更文挑战第1天】随着移动互联网的发展,智能手机成为生活必需品,iOS和安卓作为主流操作系统,各有庞大的用户群。开发者需了解两者差异以提高效率并确保优质用户体验。iOS使用Swift或Objective-C开发,强调简洁直观的设计;安卓则采用Java或Kotlin,注重层次与动画。Swift和Kotlin均有现代编程特性。此外,iOS设备更易优化,而安卓需考虑更多兼容性问题。iOS应用仅能通过App Store发布,审核严格;安卓除Google Play外还可通过第三方市场发布,审核较宽松。开发者应根据需求选择合适平台,提供最佳应用体验。
46 3
|
3月前
|
API 开发工具 Android开发
视觉智能开放平台产品使用合集之人脸活体检测能力是否支持Android端或者iOS端直接调用
视觉智能开放平台是指提供一系列基于视觉识别技术的API和服务的平台,这些服务通常包括图像识别、人脸识别、物体检测、文字识别、场景理解等。企业或开发者可以通过调用这些API,快速将视觉智能功能集成到自己的应用或服务中,而无需从零开始研发相关算法和技术。以下是一些常见的视觉智能开放平台产品及其应用场景的概览。
|
3月前
|
Shell Linux 开发工具
"开发者的救星:揭秘如何用adb神器征服Android设备,开启高效调试之旅!"
【8月更文挑战第20天】Android Debug Bridge (adb) 是 Android 开发者必备工具,用于实现计算机与 Android 设备间通讯,执行调试及命令操作。adb 提供了丰富的命令行接口,覆盖从基础设备管理到复杂系统操作的需求。本文详细介绍 adb 的安装配置流程,并列举实用命令示例,包括设备连接管理、应用安装调试、文件系统访问等基础功能,以及端口转发、日志查看等高级技巧。此外,还提供了常见问题的故障排除指南,帮助开发者快速解决问题。掌握 adb 将极大提升 Android 开发效率,助力项目顺利推进。
69 0
|
23天前
|
IDE Android开发 iOS开发
探索安卓与iOS系统的技术差异:开发者的视角
本文深入分析了安卓(Android)与苹果iOS两大移动操作系统在技术架构、开发环境、用户体验和市场策略方面的主要差异。通过对比这两种系统的不同特点,旨在为移动应用开发者提供有价值的见解,帮助他们在不同平台上做出更明智的开发决策。
|
24天前
|
机器学习/深度学习 算法 API
机器学习入门(五):KNN概述 | K 近邻算法 API,K值选择问题
机器学习入门(五):KNN概述 | K 近邻算法 API,K值选择问题
|
2月前
|
前端开发 Java 数据库
💡Android开发者必看!掌握这5大框架,轻松打造爆款应用不是梦!🏆
在Android开发领域,框架犹如指路明灯,助力开发者加速应用开发并提升品质。本文将介绍五大必备框架:Retrofit简化网络请求,Room优化数据库访问,MVVM架构提高代码可维护性,Dagger 2管理依赖注入,Jetpack Compose革新UI开发。掌握这些框架,助你在竞争激烈的市场中脱颖而出,打造爆款应用。
243 3
|
23天前
|
机器学习/深度学习 算法 数据可视化
【机器学习】决策树------迅速了解其基本思想,Sklearn的决策树API及构建决策树的步骤!!!
【机器学习】决策树------迅速了解其基本思想,Sklearn的决策树API及构建决策树的步骤!!!
|
2月前
|
IDE Java Android开发
安卓与iOS开发环境的差异及其对开发者的影响
在数字时代的浪潮中,移动应用成为人们生活的延伸。两大操作系统——安卓与iOS,如同两座技术高峰,各自占据着半壁江山。本文将探索这两个平台的开发环境差异,并讨论这些差异如何塑造开发者的编程习惯与职业选择。我们将从工具和语言、用户界面设计、系统架构、市场定位以及开发社区和资源五个方面进行比较,旨在为开发者提供一份实用的指南,帮助他们在不断变化的技术世界中,找到适合自己的发展路径。
51 3
|
2月前
|
移动开发 开发工具 Android开发
安卓与iOS开发:平台差异及其对开发者的影响
在移动开发的大潮中,安卓和iOS两大阵营各领风骚。本文将探讨这两个平台的关键差异,包括开发环境、编程语言、用户界面设计、应用分发以及商业模式等方面。通过比较分析,我们旨在为开发者提供一个清晰的指导,帮助他们根据项目需求和个人偏好做出明智的平台选择。同时,文章也将分享一些跨平台开发工具的使用经验,以期最大化开发效率和市场覆盖。
60 1
|
3月前
|
开发工具 Android开发 iOS开发
安卓与iOS开发环境的差异及其对开发者的影响
【8月更文挑战第22天】在移动开发的广阔舞台上,安卓与iOS两大操作系统各自占据着半壁江山。它们不仅是用户手中的智能设备,更是开发者展示创意和技术的战场。本文将深入探讨这两个平台的开发环境差异,以及这些差异如何塑造开发者的技术路线和职业生涯。从编程语言到开发工具,从市场定位到用户需求,我们将一探究竟,这两种不同的生态系统是如何影响开发者的决策和成长的。