テキストと顔の特徴を認識する ML Kit: iOS

1. はじめに

ML Kit は、Google の機械学習に関する専門知識を Android アプリや iOS アプリに提供するモバイル SDK です。パワフルでありながら使いやすいパッケージで提供されています。ML の初心者でも経験者でも、必要な機能はわずか数行のコードで簡単に実装できます。開始するためにニューラル ネットワークやモデルの最適化に関する深い知識は必要ありません。

仕組み

ML Kit を使用すると、Mobile VisionTensorFlow Lite などの Google の ML テクノロジーを 1 つの SDK にまとめることで、ML 手法を簡単にアプリに適用できます。Mobile Vision のオンデバイス モデルのリアルタイム性能が必要な場合でも、カスタムの TensorFlow Lite 画像分類モデルの柔軟性が必要な場合でも、ML Kit を使用すれば、わずか数行のコードで実現できます。

この Codelab では、画像内のテキストと顔の特徴を自動検出できる独自の iOS アプリを作成する手順について説明します。

作業内容

この Codelab では、ML Kit を使用して iOS アプリを作成します。作成するアプリの機能は次のとおりです。

  • ML Kit の Text Recognition API を使用して画像内のテキストを検出する
  • ML Kit Face Detection API を使用して画像内の顔の特徴を識別する

ML KIt Face Recognition API のデモを行う Grace Hopper の画像テキスト認識 API を示す芝生の上の看板の画像

学習内容

  • ML Kit SDK を使用して、テキスト認識や顔の特徴検出などの高度な ML 機能を iOS アプリに簡単に追加する方法

必要なもの

  • Xcode の最新バージョン(v12.4 以降)
  • iOS シミュレーターまたは iOS 10.0 以降を搭載した実機の iOS デバイス
  • ML Kit は、x86_64arm64 の 2 つの 64 ビット アーキテクチャのみをサポートしています。
  • サンプルコード
  • Swift での iOS 開発に関する基本的な知識
  • ML モデルに関する基礎知識

この Codelab は ML Kit に重点を置いています。関連のない概念やコードブロックについては詳しく触れず、コードはコピーして貼るだけの状態で提供されています。

2. 設定方法

コードをダウンロードする

次のリンクをクリックして、この Codelab のコードをすべてダウンロードします。

ダウンロードした zip ファイルを解凍すると、これにより、必要なリソースがすべて含まれたルートフォルダ(mlkit-ios-codelab)が作成されます。この Codelab で必要になるのは vision サブディレクトリ内のリソースのみです。

mlkit-ios-codelab リポジトリの vision サブディレクトリには、次の 2 つのディレクトリがあります。

  • android_studio_folder.pngstarter - この Codelab で作成する開始コード。
  • android_studio_folder.pngfinal - 完成したサンプルアプリの完全なコード。

CocoaPods を使用して ML Kit の依存関係を追加する

CocoaPods は、ML Kit の依存関係をアプリに追加するために使用します。CocoaPods がマシンにインストールされていない場合は、こちらでインストール手順をご確認ください。インストールが完了したら、任意のエディタで Podfile を開き、ML Kit を依存関係として追加します。

Podfile

platform :ios, '10.0'
use_frameworks!

pod 'GoogleMLKit/FaceDetection'
pod 'GoogleMLKit/TextRecognition'

target 'MLKit-codelab' do
end

ML Kit Cocoa Pod をインストールする

アプリですべての依存関係を使用できるようにするには、コマンドラインを使用して ML Kit Cocoa の Pod をインストールする必要があります。

コマンドライン

# Make sure you are in the root of your app
pod install
xed .

3. スターター アプリを実行する

これで、アプリを初めて実行する準備ができました。Xcode で 98205811bbed9d74.png [Run] をクリックしてアプリをコンパイルし、iOS Simulator で実行します。

シミュレータでアプリが起動するはずです。この時点で、2 つの画像を選択する選択ツールがある基本的なレイアウトが表示されます。次のセクションでは、テキスト認識をアプリに追加して、画像内のテキストを識別します。

4. デバイス上のテキスト認識を追加する

このステップでは、画像内のテキストを認識する機能をアプリに追加します。

MLVision モジュールをインポートする

ViewController クラスへの次のインポートが存在することを確認します。

ViewController.swift

import MLKit

VisionTextRecognizer を作成する

次の遅延プロパティを ViewController クラスに追加します。

ViewController.swift

private lazy var textRecognizer = TextRecognizer.textRecognizer()

デバイス上のテキスト認識を設定して実行する

ViewController クラスの runTextRecognition メソッドに以下を追加します。

ViewController.swift

func runTextRecognition(with image: UIImage) {
  let visionImage = VisionImage(image: image)
  textRecognizer.process(visionImage) { features, error in
    self.processResult(from: features, error: error)
  }
}

上記のコードでは、テキスト認識検出機能を構成し、レスポンスで関数 processResult(from:, error:) を呼び出します。

テキスト認識のレスポンスを処理する

以下のコードを ViewController クラスの processResult に追加して、結果を解析してアプリに表示します。

ViewController.swift

 func processResult(from text: Text?, error: Error?) {
    removeDetectionAnnotations()
    guard error == nil, let text = text else {
      let errorString = error?.localizedDescription ?? Constants.detectionNoResultsMessage
      print("Text recognizer failed with error: \(errorString)")
      return
    }

    let transform = self.transformMatrix()

    // Blocks.
    for block in text.blocks {
      drawFrame(block.frame, in: .purple, transform: transform)

      // Lines.
      for line in block.lines {
        drawFrame(line.frame, in: .orange, transform: transform)

        // Elements.
        for element in line.elements {
          drawFrame(element.frame, in: .green, transform: transform)

          let transformedRect = element.frame.applying(transform)
          let label = UILabel(frame: transformedRect)
          label.text = element.text
          label.adjustsFontSizeToFitWidth = true
          self.annotationOverlayView.addSubview(label)
        }
      }
    }
  }

シミュレータでアプリを実行する

Xcode で 98205811bbed9d74.png [Run] をクリックします。アプリが読み込まれたら、選択ツールで Image 1 が選択されていることを確認し、[Find Text] ボタンをクリックします。

アプリは下の画像のようになります。テキスト認識の結果と境界ボックスが元の画像の上に重ねて表示されます。

7269fd8fcb4dc793.png

写真: Kai Schreiber / Wikimedia Commons / CC BY-SA 2.0

これで、ML Kit を使用して、オンデバイスのテキスト認識をアプリに追加することができました。オンデバイスのテキスト認識は、アプリがインターネットに接続されていなくても動作し、静止画像やライブ動画フレームで使用できるほど高速であるため、多くのユースケースに最適です。

5. デバイス上の顔の輪郭検出を追加する

このステップでは、画像内の顔の輪郭を検出する機能をアプリに追加します。

FaceDetector を作成する

次の遅延プロパティを ViewController クラスに追加します。

ViewController.swift

private lazy var faceDetectorOption: FaceDetectorOptions = {
  let option = FaceDetectorOptions()
  option.contourMode = .all
  option.performanceMode = .fast
  return option
}()
private lazy var faceDetector = FaceDetector.faceDetector(options: faceDetectorOption)

デバイス上の顔の輪郭検出を設定して実行する

ViewController クラスの runFaceContourDetection メソッドに以下を追加します。

ViewController.swift

  func runFaceContourDetection(with image: UIImage) {
    let visionImage = VisionImage(image: image)
    faceDetector.process(visionImage) { features, error in
      self.processResult(from: features, error: error)
    }
  }

上記のコードでは、テキスト認識検出機能を構成し、レスポンスで関数 processResult(from:, error:) を呼び出します。

顔検出器のレスポンスを処理する

以下のコードを ViewController クラスの processResult に追加して、結果を解析してアプリに表示します。

ViewController.swift

  func processResult(from faces: [Face]?, error: Error?) {
    removeDetectionAnnotations()
    guard let faces = faces else {
      return
    }

    for feature in faces {
      let transform = self.transformMatrix()
      let transformedRect = feature.frame.applying(transform)
      UIUtilities.addRectangle(
        transformedRect,
        to: self.annotationOverlayView,
        color: UIColor.green
      )
      self.addContours(forFace: feature, transform: transform)
    }
  }

最後に、ヘルパー メソッド addContoursViewController クラスに追加して、等高線の点を描画します。

ViewController.swift

 private func addContours(forFace face: Face, transform: CGAffineTransform) {
    // Face
    if let faceContour = face.contour(ofType: .face) {
      for point in faceContour.points {
        drawPoint(point, in: .blue, transform: transform)
      }
    }

    // Eyebrows
    if let topLeftEyebrowContour = face.contour(ofType: .leftEyebrowTop) {
      for point in topLeftEyebrowContour.points {
        drawPoint(point, in: .orange, transform: transform)
      }
    }
    if let bottomLeftEyebrowContour = face.contour(ofType: .leftEyebrowBottom) {
      for point in bottomLeftEyebrowContour.points {
        drawPoint(point, in: .orange, transform: transform)
      }
    }
    if let topRightEyebrowContour = face.contour(ofType: .rightEyebrowTop) {
      for point in topRightEyebrowContour.points {
        drawPoint(point, in: .orange, transform: transform)
      }
    }
    if let bottomRightEyebrowContour = face.contour(ofType: .rightEyebrowBottom) {
      for point in bottomRightEyebrowContour.points {
        drawPoint(point, in: .orange, transform: transform)
      }
    }

    // Eyes
    if let leftEyeContour = face.contour(ofType: .leftEye) {
      for point in leftEyeContour.points {
        drawPoint(point, in: .cyan, transform: transform)
      }
    }
    if let rightEyeContour = face.contour(ofType: .rightEye) {
      for point in rightEyeContour.points {
        drawPoint(point, in: .cyan, transform: transform)
      }
    }

    // Lips
    if let topUpperLipContour = face.contour(ofType: .upperLipTop) {
      for point in topUpperLipContour.points {
        drawPoint(point, in: .red, transform: transform)
      }
    }
    if let bottomUpperLipContour = face.contour(ofType: .upperLipBottom) {
      for point in bottomUpperLipContour.points {
        drawPoint(point, in: .red, transform: transform)
      }
    }
    if let topLowerLipContour = face.contour(ofType: .lowerLipTop) {
      for point in topLowerLipContour.points {
        drawPoint(point, in: .red, transform: transform)
      }
    }
    if let bottomLowerLipContour = face.contour(ofType: .lowerLipBottom) {
      for point in bottomLowerLipContour.points {
        drawPoint(point, in: .red, transform: transform)
      }
    }

    // Nose
    if let noseBridgeContour = face.contour(ofType: .noseBridge) {
      for point in noseBridgeContour.points {
        drawPoint(point, in: .yellow, transform: transform)
      }
    }
    if let noseBottomContour = face.contour(ofType: .noseBottom) {
      for point in noseBottomContour.points {
        drawPoint(point, in: .yellow, transform: transform)
      }
    }
  }

シミュレータでアプリを実行する

Xcode で 98205811bbed9d74.png [Run] をクリックします。アプリが読み込まれたら、選択ツールで Image 2 が選択されていることを確認し、[Find Face Contour] ボタンをクリックします。アプリは下の画像のようになります。グレースホッパーの顔の輪郭がポイントとして元の画像の上に重ねて表示されます。

a5169b50dafbcb2f.png

お疲れさまでした。オンデバイス ML Kit を使用して、オンデバイスの顔の輪郭検出をアプリに追加しました。これは、アプリがインターネットに接続されていなくても動作し、静止画像やライブ動画フレームでの使用に十分な速度であるため、多くのユースケースに有効です。

6. 完了

ML Kit を使用して、高度な ML 機能をアプリに簡単に追加できました。

学習した内容

  • ML Kit を iOS アプリに追加する方法
  • ML Kit でオンデバイスのテキスト認識を使用して画像内のテキストを検出する方法
  • ML Kit でオンデバイスの顔認証を使用して、画像内の顔の特徴を特定する方法

次のステップ

  • 独自の iOS アプリで ML Kit を使用します。

詳細

  • https://g.co/mlkit