Sansan Tech Blog

Sansanのものづくりを支えるメンバーの技術やデザイン、プロダクトマネジメントの情報を発信

AndroidでML Kit Document Scanner APIを触ってみた


こんにちは!Sansan 技術本部 Mobile Applicationグループのふるしんです。

ML KitにてドキュメントスキャナのAPIが公開されました
ML Kit  |  Google for Developers

これはGoogle Driveアプリですでに活用されている機能で、カメラを用いて紙のドキュメントをPDFや画像として取り込めるものです。

このAPIを試しに触ってみたのでまとめました。
↓ 試してみた動画です。この中で汚れの除去を模してネコチャンを消してみました。

www.youtube.com

APIの利用方法

gradleへの定義

dependencies {
   // …
   implementation 'com.google.android.gms:play-services-mlkit-document-scanner:16.0.0-beta1'
}

2024/06/03 本記事執筆時点では16.0.0-beta1が最新バージョンでした。
利用するバージョンはこちらからチェックするようにしましょう。(Android Studioが教えてはくれます)
リリースノート  |  ML Kit  |  Google for Developers

APIをお試し・活用される際は最新のバージョンを確認するようにしましょう。また、最新バージョンを確認する際は、公式ドキュメントは英語表記で確認するようにしましょう。
(日本語で見ると更新されておらず古い場合があります)

ドキュメントスキャナーの準備

次のような条件が利用可能です。

  • ギャラリーからも取り込めるようにするか
    • デフォルトでは可能(true)
    • falseにするとギャラリーから取り込むボタンが非表示になる
  • ページ数の上限
    • 「pageLimit should be be greater than or equal to 1」なので1以上を指定すること。0以下の場合はIllegalArgumentExceptionとなる
    • ページ数の上限がコード上なさそうに見える。Int.MAX_VALUEを引数として渡してもビルドエラーにはならなかった
  • 取り込むフォーマット(PDFかJPEGか両方か)
    • デフォルトではJPEG(RESULT_FORMAT_JPEG)
  • 編集機能(後述します)
    val options = GmsDocumentScannerOptions.Builder()
        .setGalleryImportAllowed(true)
        .setPageLimit(4)
        .setResultFormats(RESULT_FORMAT_JPEG, RESULT_FORMAT_PDF)
        .setScannerMode(SCANNER_MODE_FULL)
        .build()

スキャンする

ドキュメントスキャナーの起動にはGmsDocumentScannerを使い、その結果をActivityResult APIで取得して実行をします

 val scannerLauncher =
    registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { activityResult ->  // ②
        if (activityResult.resultCode == RESULT_OK) {
            val scanResult =
                 GmsDocumentScanningResult.fromActivityResultIntent(activityResult.data)
                    ?: return@registerForActivityResult

            scanResult.pages?.let { pages -> // ③
                   val imageUris = pages.map { it.imageUri }.toList()
                   // do something
             }

              scanResult.pdf?.let { pdf ->  // ④
               val pdfCount = pdf.pageCount
               // do something
             }
         }
     }

val scanner = GmsDocumentScanning.getClient(options)
scanner.getStartScanIntent(this).addOnSuccessListener { intentSender -> // ①
      scannerLauncher.launch(IntentSenderRequest.Builder(intentSender).build())
 }.addOnFailureListener {
        Toast.makeText(this, "failed launch Scanner ${it.message}", Toast.LENGTH_LONG).show()
  }

①スキャンできるかどうかをまずは確認をします。
その結果はonSuccess、onFailureで返されるので、それぞれListenerをセットします。

②スキャンをした結果はGmsDocumentScanningResultとしてActivityResultの中に含まれています。
通常のActivityResultのようにregisterForActivityResultを用意します。

③スキャンした結果の情報を GmsDocumentScanningResult.fromActivityResultIntent で取得することでいろいろと活用できます。
画像データはpagesとして取得でき、画像のUriが含まれています。

    public abstract static class Page implements Parcelable {
        @NonNull
        public abstract Uri getImageUri();

        public Page() {
        }
    }

④PDFデータはPdfとして格納されています。
PDFデータのUriだけでなくページ数も取得できるようになっているのが便利ですね。

    public abstract static class Pdf implements Parcelable {
        public abstract int getPageCount();

        @NonNull
        public abstract Uri getUri();

        public Pdf() {
        }
    }

あとはこれらの画像データやPDFデータを用いて何か実施したい処理を行うだけです。

編集機能

GmsDocumentScannerOptionsに setScannerMode で編集機能の種別を設定できます。

  1. SCANNER_MODE_BASE:最もシンプルなモード。ページの切り抜きや回転、並べ替えなどシンプルな機能を有する
  2. SCANNER_MODE_BASE_WITH_FILTER:SCANNER_MODE_BASEに画像補完やグレースケールなどの画像フィルタ機能が加わったもの
  3. SCANNER_MODE_FULL: SCANNER_MODE_BASE_WITH_FILTERに ML 対応の画像クリーニング機能(汚れや指の消去など)が加わったもの
    1. 今後の Google Play 開発者サービスのアップデートも自動的に追加される

基本的には SCANNER_MODE_FULL を使用するのがよいでしょう。
ドキュメントをスキャンした際に汚れとかが残っているとノイズになりますし、今後追加される新機能も自動で利用できるのは大きなメリットかと思います。

まとめ

まだβ版ではありますが、ML Kit Document Scanner APIを試しに使ってみました。
私はこのAPIを活用して「子供のお絵かきを画像として保存する」アプリを作りました。
(どんどん溜まっていくお絵かきを置いておく場所もないし、けど捨てるのも忍びないし…と思って作った)

このAPIを使えば今流行りのAIを活用した何かを作れそうですし、世界が広がりそうな気がしています。
皆さんもいろんなAPIを試してみてください!

© Sansan, Inc.