wheatandcatの開発ブログ

React Nativeで開発しているペペロミア & memoirの技術系記事を投稿してます

【flutter】商品画像取得の実装改善:OCRを活用した新たなアプローチ

前回の記事では、バーコードを用いて商品画像を取得する機能を実装したが、以下の課題が浮上した。

  • バーコードから商品情報を取得できないケースがある
  • バーコードが外箱に記載されており、画像から取得が困難な場合がある

これらの課題を解決するため、OCR(Optical Character Recognition)を活用し、画像から商品情報を取得する方法を試した。

PR

github.com

OCRとは

OCRは、画像やスキャンされた文書に含まれる文字を認識し、それをテキストデータとしてデジタル化する技術。今回の実装では、OCRで商品画像から文字情報を取得し、それを基に商品を特定する。

使用するライブラリ & サービス

実装詳細

1. OCRで画像から文字を抽出

dart/app/lib/utils/image_mobile.dart

import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart';
import 'dart:io';

Future<List<String>> imageTextRecognizer(File image) async { 
  final inputImage = InputImage.fromFile(image);
  final textRecognizer = TextRecognizer(script: TextRecognitionScript.japanese);
  final RecognizedText recognizedText =
      await textRecognizer.processImage(inputImage);
  final texts = recognizedText.blocks
      .map((block) => block.text.replaceAll('\n', ' '))
      .where((text) => text.length > 1 && !RegExp(r'^\d+$').hasMatch(text))
      .toList();

  return texts;
}

このコードは画像内の文字列を抽出する。例えば、以下の画像をOCRに通すと次のような文字列が得られる。

実装的には画像の情報をtextRecognizer.processImageに渡してあげればOK。

■抽出結果:

[
  "38%",
  "\\売上/",
  "No.",
  "※インテージSRI+",
  "一般用ウェッ外ティッシ",
  "累計販売金額",
  "207年\\月20B",
  "▲ここまで引っぱってご使用ください。",
  "シルコット",
  "ウェットティッシュ",
  "、純水99%",
  "手·口まわりの汚れに",
  "メイク時の手指の拭き取りに デ",
  "コアウォーター",
  "ノンアルコール"
]

OCRは文字をある程度の精度で認識するが、完全ではない。このため、追加の処理を加える必要がある。

2. 抽出文字列から商品名を特定

Cloud Natural Languageを使用

cloud.google.com

Google Cloud Natural Languageの「エンティティ分析」を使ってテキストを解析し、商品名を自動抽出する。

typescript/backend/src/lib/analyzeText.ts

import { LanguageServiceClient } from '@google-cloud/language'

export const analyzeText = async (text: string) => {
  const client = new LanguageServiceClient()

  const document = {
    content: text,
    type: 'PLAIN_TEXT' as const,
  }

  const [result] = await client.analyzeEntities({ document })
  const { entities } = result

  const entityList = entities.filter(
    (entity) => entity.type === 'CONSUMER_GOOD'
  )

  const topEntities = entityList
    .sort((a, b) => b.salience - a.salience)
    .slice(0, 3)
    .map((entity) => entity.name)

  if (topEntities.length === 0) {
    return {
      productNames: entities.slice(0, 3).map((entity) => entity.name),
      extractedWords: [],
    }
  }

  // 抽出して単語を全て取得
  const extractedWords = entities
    .map((entity) => entity.name)
    .filter((name) => !topEntities.includes(name))

  return {
    productNames: topEntities,
    extractedWords,
  }
}

この実装では、テキストから商品名(CONSUMER_GOOD)を抽出する。ただし、OCRの精度やフォントの影響で期待した商品名が抽出できない場合があるため、ユーザーの手動選択を組み合わせた機能も用意した。

3. 商品検索の自動・手動連携

自動検索の結果

OCRとCloud Natural Languageを組み合わせ、Yahoo!ショッピングAPIで商品情報を取得する。例えば、「ウェットティッシュ」で検索すると以下の結果が得られる。

取得できた値を返してアプリに表示させると以下のように表示される

手動検索機能

  • 手動で商品名を修正できるUIを追加した。以下の流れで操作する。
    • 1.「テキストで検索」ボタンを押下
    • 2.抽出されたテキスト一覧から商品名を選択または修正
    • 3.検索ボタンをタッチ

例えば、OCRが「キャノーノーラ油」と認識した場合、ユーザーが正しい商品名「キャノーラ油」に修正することで適切な結果を取得できる。

実装結果と課題

この新しい仕組みで約8割の商品画像を自動登録可能となった。一方で以下の課題が残っている。

  • フォントやデザインの影響でOCRの精度が低下する場合がある
  • 商品画像が鮮明でない場合に認識精度が低下
  • 自動抽出の精度向上が必要

実際の動作例

実際の動作は以下の動画で確認できる。

www.youtube.com

まとめ

この仕組みにより、在庫管理アプリが大幅に使いやすくなった。今後はOCR精度の向上や、さらに効率的な商品検索アルゴリズムの開発を検討している。