使用机器学习套件检测图片中的对象:Android

1. 准备工作

机器学习套件是一个移动 SDK,可为 Android 和 iOS 应用引入 Google 的设备端机器学习专业技术。您可以使用功能强大且简单易用的 Vision API 和 Natural Language API 来解决应用中的常见问题,或打造全新的用户体验。所有这些功能均由 Google 一流的机器学习模型提供支持,并且免费提供给您。

机器学习套件的 API 全部在设备端运行,因此可支持需要处理实时相机数据流的实时用例,这也意味着该功能可在离线状态下使用。

此 Codelab 将引导您逐步完成一些简单步骤,以向现有 Android 应用添加针对给定图片的对象检测和跟踪 (ODT) 功能。请注意,此 Codelab 采用了一些捷径来重点介绍机器学习套件 ODT 的使用。

构建内容

在此 Codelab 中,您将使用机器学习套件构建一个 Android 应用。您的应用将使用机器学习套件的对象检测和跟踪 API 检测给定图片中的对象。最后,您应该会看到与右侧图片类似的内容。

学习内容

  • 如何将机器学习套件 SDK 集成到 Android 应用中
  • 机器学习套件对象检测和跟踪 API

所需条件

  • 最新版 Android Studio (v4.1.2+)
  • Android Studio 模拟器或一台实体 Android 设备
  • 示例代码
  • 使用 Kotlin 进行 Android 开发的基础知识

此 Codelab 重点介绍机器学习套件。对于不相关的概念,我们仅会略作介绍,但是会提供相应代码块供您复制和粘贴。

2. 进行设置

下载代码

点击下面的链接可下载本 Codelab 的所有代码:

解压下载的 ZIP 文件。此操作会解压缩一个根文件夹 (mlkit-android-main),其中包含您需要的所有资源。在此 Codelab 中,您只需要 object-detection 子目录中的源代码。

mlkit-android 代码库中的 object-detection 子目录包含两个目录:

  • android_studio_folder.pngstarter - 在此 Codelab 中帮助您开始构建的起始代码。
  • android_studio_folder.pngfinal - 完成后的示例应用的完整代码。

3. 将机器学习套件的对象检测和跟踪 API 添加到项目中

将应用导入 Android Studio

首先,将 starter 应用导入 Android Studio。

打开 Android Studio,选择 Import Project (Gradle, Eclipse ADT, etc.),然后从之前下载的源代码中选择 starter 文件夹。

7c0f27882a2698ac.png

为机器学习套件的对象检测和跟踪功能添加依赖项

借助 ML Kit 依赖项,您可以在应用中集成 ML Kit ODT SDK。请将以下代码行添加到项目的 app/build.gradle 文件的末尾:

build.gradle

dependencies {
  // ...
  implementation 'com.google.mlkit:object-detection:16.2.4'
}

将您的项目与 Gradle 文件同步

为确保您的应用拥有所有依赖项,此时您应该将项目与 Gradle 文件同步。

在 Android Studio 工具栏中选择 Sync Project with Gradle Files 图标 ( b451ab2d04d835f9.png)。

(如果此按钮已停用,请确保仅导入 starter/app/build.gradle ,而不是整个代码库。)

4. 运行起始应用

现在,您已将项目导入 Android Studio 并添加了机器学习套件对象检测和跟踪的依赖项,可以首次运行应用了。

通过 USB 将 Android 设备连接到主机,或启动 Android Studio 模拟器,然后点击 Android Studio 工具栏中的 Run 图标 ( execute.png)。

运行和探索应用

应用应在 Android 设备上启动。其中包含一些样板代码,可让您拍摄照片或选择预设图片,并将其馈送到您将在此 Codelab 中构建的对象检测和跟踪流水线。在编写代码之前,我们先来探索一下该应用。

首先,底部有一个按钮 ( c6d965d639c3646.png),用于执行以下操作:

  • 调出设备/模拟器中集成的相机应用
  • 相机应用中拍照
  • 起始应用接收拍摄的图片
  • 显示图片

试用拍照按钮,按照提示拍照,接受照片,然后观察照片在启动应用中显示。

重复几次以上操作,了解其运作方式:

9ec541980dbe2d31.png 8312dde41425ba4b.png fa8492bfc1914ff0.png

其次,您可以从 3 张预设图片中进行选择。如果您是在 Android 模拟器上运行,则稍后可以使用这些图片来测试对象检测代码。

从 3 张预设图片中选择一张图片。您会看到图片显示在放大的视图中:

1dd41b3ec978f1d9.png

5. 添加设备端对象检测功能

在此步骤中,您将向起始应用添加功能,以检测图片中的对象。如您在上一步中所看到的,起始应用包含用于使用设备上的相机应用拍照的样板代码。如果您是在 Android 模拟器上运行此 Codelab,则还可以使用应用中的 3 张预设图片来试用对象检测功能。

当您从预设图片中选择一张图片或使用相机应用拍摄一张照片后,样板代码会将该图片解码为 Bitmap 实例,并将其显示在屏幕上,然后使用该图片调用 runObjectDetection 方法。

在此步骤中,您将向 runObjectDetection 方法添加代码以执行对象检测!

做好设置,并对图片进行设备端对象检测

只需 3 个简单步骤,即可完成 3 个 API 的设置 ML Kit ODT:

  • 准备图片:InputImage
  • 创建检测器对象:ObjectDetection.getClient(options)
  • 连接上面的 2 个对象:process(image)

您可以在 MainActivity.kt 文件中通过 runObjectDetection(bitmap: Bitmap) 函数实现这些操作。

/**
 * ML Kit Object Detection Function
 */
private fun runObjectDetection(bitmap: Bitmap) {
}

目前该函数为空。请按照以下步骤实现 ML Kit ODT!在此过程中,Android Studio 会提示您添加必要的导入:

  • com.google.mlkit.vision.common.InputImage
  • com.google.mlkit.vision.objects.ObjectDetection
  • com.google.mlkit.vision.objects.defaults.ObjectDetectorOptions

第 1 步:创建 InputImage

ML Kit 提供了一个简单的 API,用于从 Bitmap 创建 InputImage。然后,您可以将 InputImage 馈送到 ML Kit API。

// Step 1: create ML Kit's InputImage object
val image = InputImage.fromBitmap(bitmap, 0)

将上述代码添加到 runObjectDetection(bitmap:Bitmap) 的顶部。

第 2 步:创建检测器实例

机器学习套件遵循构建器设计模式。您将配置传递给构建器,然后从中获取检测器。您可以配置 3 个选项(此 Codelab 中使用了粗体选项):

  • 检测器模式(单张图片 或数据流
  • 检测模式(单个对象检测多个对象检测
  • 分类模式(开启 或关闭

此 Codelab 适用于单张图片 - 多对象检测和分类。现在添加该代码:

// Step 2: acquire detector object
val options = ObjectDetectorOptions.Builder()
   .setDetectorMode(ObjectDetectorOptions.SINGLE_IMAGE_MODE)
   .enableMultipleObjects()
   .enableClassification()
   .build()
val objectDetector = ObjectDetection.getClient(options)

第 3 步:将图片传递给检测器

对象检测和分类是异步处理的:

  • 您将图片发送给检测器(通过 process())。
  • 检测器会非常努力地处理此问题。
  • 检测器会通过回调将结果报告给您。

以下代码会执行此操作(将其复制并附加fun runObjectDetection(bitmap:Bitmap)): 中的现有代码

// Step 3: feed given image to detector and setup callback
objectDetector.process(image)
   .addOnSuccessListener {
       // Task completed successfully
        debugPrint(it)
   }
   .addOnFailureListener {
       // Task failed with an exception
       Log.e(TAG, it.message.toString())
   }

完成后,检测器会通过以下方式通知您:

  • 检测到的对象总数。每个检测到的对象都通过以下内容描述:
  • trackingId:一个整数,用于跨帧跟踪它(在此 Codelab 中未使用)。
  • boundingBox:对象的边界框。
  • labels: 检测到的对象的标签列表(仅当启用分类时有效):
  • index(获取此标签的索引)
  • text(获取此标签的文本,包括“时尚商品”“食品”“家居用品”“地点”“植物”)
  • confidence(介于 0.0 和 1.0 之间的浮点数,1.0 表示 100%)

您可能已经注意到,该代码会使用 debugPrint() 对检测到的结果执行 printf 类型的处理。

将其添加到 MainActivity 类中:

private fun debugPrint(detectedObjects: List<DetectedObject>) {
   detectedObjects.forEachIndexed { index, detectedObject ->
       val box = detectedObject.boundingBox

       Log.d(TAG, "Detected object: $index")
       Log.d(TAG, " trackingId: ${detectedObject.trackingId}")
       Log.d(TAG, " boundingBox: (${box.left}, ${box.top}) - (${box.right},${box.bottom})")
       detectedObject.labels.forEach {
           Log.d(TAG, " categories: ${it.text}")
           Log.d(TAG, " confidence: ${it.confidence}")
       }
   }
}

现在,您可以接受要检测的图片了!

点击 Android Studio 工具栏中的 Run 图标 ( execute.png) 运行此 Codelab。尝试选择预设图片或拍摄照片,然后查看 IDE 中的 logcat 窗口( 16bd6ea224cf8cf1.png)

您应该会看到如下所示的内容:

D/MLKit Object Detection: Detected object: 0
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (481, 2021) - (2426,3376)
D/MLKit Object Detection:  categories: Food
D/MLKit Object Detection:  confidence: 0.90234375
D/MLKit Object Detection: Detected object: 1
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (2639, 2633) - (3058,3577)
D/MLKit Object Detection: Detected object: 2
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (3, 1816) - (615,2597)
D/MLKit Object Detection:  categories: Home good
D/MLKit Object Detection:  confidence: 0.75390625

...这意味着检测器检测到了 3 个对象:

  • 类别包括食品家居用品
  • 系统不会为第二个返回类别,因为它是未知类。
  • trackingId(因为这是单图片检测模式)。
  • boundingBox 矩形内的位置(例如 (481, 2021) - (2426, 3376))
  • 检测器非常确信第 1 个是食物(置信度为 90% - 是沙拉)。

从技术上来说,这就是 ML Kit 对象检测正常运行所需执行的一切工作:目前您已完成所有操作!恭喜!

在界面方面,您仍处于开始阶段,但您可以在界面上利用检测到的结果(例如绘制边界框),以打造更好的体验:接下来,我们将进行下一步操作 - 对检测到的结果进行后处理!

6. 对检测结果进行后处理

在前面的步骤中,您将检测结果输出到 logcat 中:简单快速。

在本部分中,您将将结果用于图片:

  • 在图片上绘制边界框
  • 在边界框内绘制类别名称和置信度

了解可视化实用程序

此 Codelab 中包含一些样板代码,可帮助您直观呈现检测结果。利用这些实用程序简化可视化代码:

  • data class BoxWithText(val box: Rect, val text: String):这是一个用于存储可视化对象检测结果的数据类。box 是对象所在的边界框,text 是与对象的边界框一起显示的检测结果字符串。
  • fun drawDetectionResult(bitmap: Bitmap, detectionResults: List<BoxWithText>): Bitmap:此方法会在输入 bitmap 上的 detectionResults 中绘制对象检测结果,并返回修改后的副本。

以下是 drawDetectionResult 实用程序方法的输出示例:

58c6f1d4ddb00dfa.png

直观呈现机器学习套件检测结果

使用可视化实用程序在输入图片上绘制机器学习套件对象检测结果。

前往调用 debugPrint() 的位置,并在其下方添加以下代码段:

// Parse ML Kit's DetectedObject and create corresponding visualization data
val detectedObjects = it.map { obj ->
    var text = "Unknown"

    // We will show the top confident detection result if it exist
    if (obj.labels.isNotEmpty()) {
        val firstLabel = obj.labels.first()
        text = "${firstLabel.text}, ${firstLabel.confidence.times(100).toInt()}%"
    }
    BoxWithText(obj.boundingBox, text)
}

// Draw the detection result on the input bitmap
val visualizedResult = drawDetectionResult(bitmap, detectedObjects)

// Show the detection result on the app screen
runOnUiThread {
    inputImageView.setImageBitmap(visualizedResult)
}
  • 首先,解析机器学习套件的 DetectedObject 并创建 BoxWithText 对象列表,以显示可视化结果。
  • 然后,您可以使用 drawDetectionResult 实用程序方法在输入图片上绘制检测结果,并将其显示在屏幕上。

开始运行

现在,点击 Android Studio 工具栏中的 Run 图标 ( execute.png)。

应用加载后,按带摄像头图标的按钮,将摄像头对准物体,拍摄照片,接受照片(在相机应用中),或轻松点按任何预设图片。您应该会看到检测结果;再次按下按钮或选择其他图片,重复几次即可体验最新的 ML Kit ODT!

a03109cb30d5014d.png

7. 恭喜!

您已使用机器学习套件为应用添加了对象检测功能:

  • 3 步 3 个 API
  • 创建输入图片
  • 创建检测器
  • 将图片发送给检测器

它现在可以立即运行并使用了!

在继续操作时,您可能需要增强模型:如您所见,默认模型只能识别 5 个类别,甚至不知道刀、叉和瓶子。请查看设备端机器学习 - 对象检测学习衔接课程中的其他 Codelab,了解如何训练自定义模型。

所学内容

  • 如何将机器学习套件的对象检测和跟踪功能添加到 Android 应用中
  • 如何使用机器学习套件的设备端对象检测和跟踪功能来检测图片中的对象

后续步骤

  • 使用 ML Kit ODT 探索更多图片和实时视频,体验检测和分类准确性和性能
  • 查看设备端机器学习 - 对象检测学习衔接课程,了解如何训练自定义模型
  • 在您自己的 Android 应用中应用机器学习套件 ODT

了解详情