Tesseract.jsとReactでOCRコミュニケーションアプリを作る(前編)
読む所要時間: 18 分
背景
「OCR」という技術を耳にしたことがありますか?OCRは、Optical Character Recognition(光学文字認識)の略です。手書きや印刷された文字を光学的な手段でデータとして取り込み、文字認識することによってコンピュータープログラムなどで使用できるように変換する技術です。OCRは様々な分野で利用されています。使用例としては、車のナンバープレートを認識し盗難車を検知したり、書籍をデジタル化したりという例があります。Tesseract.jsは100以上の言語に対応するオープンソースのOCRライブラリです。Tesseract.jsは、C言語で開発されたTesseractOCRエンジンをJavaScriptのWebAssemblyにコンパイルしています。Tesseract.jsを使うと、ブラウザでOCRを簡単に利用できます。
本稿では、Tesseract.jsとReactを使用し、ブラウザ上で画像のOCR処理を行い、読み取ったテキストをSMSとして送信するアプリの作成方法をご紹介します。
目標
このチュートリアルを最後まで進めると、Tesseract.jsの基礎を学べるとともに、以下のようなReactを使ったOCRコミュニケーションアプリを作成できます。
アプリケーションの動作フローは以下を想定しています。
- 画像をアップロードする。
- Tesseract.jsで画像をOCR処理する。
- 必要に応じて読み取ったテキストを編集する。
- テキストを指定した電話番号にSMSとして送信する。
想定される技術知識
本稿では以下の知識を想定しています。
- JavaScriptの基本知識
- Node.jsの基本知識
- Reactの基本知識
必要なツール
- 安定バージョンのNode.jsとnpm
- Twilioアカウント。アカウント作成方法はHelp Centerの「Twilioアカウントの作成方法」を参照してください。
- Twilioの電話番号
アプリケーションの構造
作成するアプリケーションではフロントエンドとバックエンドを準備します。フロントエンド側では画像のアップロードボタン、OCR処理ボタン、テキストのエディタやSMSの送信ボタンなどを表示させます。バックエンド側はNode.jsとExpressを使ってSMSの送信処理を行います。
アプリケーションの具体的な構造は以下のとおりです。
フロントエンド:
-
App
: プロジェクトの実行エントリーポイントとなるルートコンポーネント。 OcrReader
: OCR処理する画像のアップロードとOCR処理ボタンを構成するコンポーネント。SmsSender
: OCR処理し読みとったテキストのエディタと、テキストのSMS送信ボタンを構成するコンポーネント。
バックエンド:
-
server.js
: Node.jsとExpressでSMS送信処理を行うサーバーファイル。
大まかなアプリケーションの構造が理解できたところでプロジェクトの作成に進みましょう。
基本設定とReactの準備
create-react-appでReactアプリケーションを作成する
まずは、Reactアプリケーションを作成します。
ターミナルを開いて、以下のコマンドを実行してください。
このコマンドで、Reactアプリケーションの作成、ディレクトリへの移動、アプリケーションの起動を行います。
ブラウザでlocalhost:3000にアクセスします。問題なくアプリケーションが起動すると、以下のような画面が表示されます。
この時点で、一度ターミナルのプロセスを終了させてください。
依存パッケージをインストールする
次に、アプリケーションに必要な依存パッケージをインストールします。
ターミナルで以下のコマンドを実行してください。
インストールした依存パッケージの詳細は以下のとおりです。
tesseract.js
: ブラウザで機能するJavaScriptOCRライブラリ。twilio
: Twilio Node ヘルパーライブラリ。Twilio APIに対するHTTPリクエストを、Node.jsを使って書けるようにするためのパッケージ。express
: Node.jsで使うウェブサーバーフレームワーク。本稿ではSMSの送信に使います。dotenv
: .envファイルに定義された値を環境変数として取り込むためのパッケージ。intl-tel-input
: International Telephone Input。国際電話の番号を入力して検証するためのJavaScriptプラグイン。
インストールが完了したら、次にフロントエンドを構築します。
フロントエンドを構築する
まずは、フロントエンドで構築するコンポーネントファイルを作成します。ターミナルで、/srcディレクトリの配下に、/componentsフォルダを作成してください。
/componentsフォルダの配下に、OcrReader.jsと、SmsSender.jsファイルを作成してください。
App.jsコンポーネントを構築する
ルートコンポーネントのApp.jsを構築します。create-react-app
を実行した際に自動作成された/src 配下にある App.jsファイルを編集します。テキストエディタでApp.jsファイルを開いてください。
ファイルの内容を、以下のコードに変更してください。
ファイルを保存してください。
このコードでは、画像のOCR処理を担うOcrReader
コンポーネントと、OCR処理で読み取ったテキストの編集とSMS送信を担うSmsSender
コンポーネントをインポートしています。
App.jsでは、子コンポーネントのOcrReader
で読み取ったテキストをocrData
としてpropsオブジェクトで兄弟コンポーネントのSmsSender
に渡します。
onReadOcrData
関数で、ocrData
を受け取ります。<SmsSender>
のJSXの属性で、ocrData
をreadText
としてpropsで渡します。
onRemoveClicked
関数で、OcrReader
コンポーネントで「別の画像を使用する」ボタンがクリックされた際に、<SmsSender>
に渡すテキストのデータも初期化します。
OCR処理コンポーネントを構築する
次に、OCR処理する画像の選択機能、画像の表示、OCR処理ボタンを担う関数コンポーネントのOcrReader
を構築します。OcrReader.js
を開いてください。
ファイルに以下のコードをペーストしてください。
このコードでは、Tesseract.jsのcreateWorker
関数をインポートをしています。
STATUSES
で、Tesseract.jsの画像のOCR処理ステータスをオブジェクトとして定義します。export default OcrReader
で、コンポーネントを親コンポーネントのApp.jsにエキスポートします。
次に、コンポーネントのメインの関数、OcrReader
を定義します。STATUSES
のブロックと、export default OcrReader
の間に、以下のコードをペーストしてください。
上記のコードを詳しく解説します。
OcrReader
関数のパラメーターで、onReadOcrData
とonRemoveClicked
をpropsとして親コンポーネントに渡します。OCR処理する画像が選択されているかに関するステート(selectedImage
)と、OCR処理の実行状況に関するステート(ocrState
)を、useState
フックで定義します。 Tesseract.jsのworker
を変数として定義し、インスタンス化します。
Tesseract.jsでの画像のOCR処理をreadImageText
非同期関数で定義します。
関数が呼び出されてすぐに、OCR処理ステータスをPENDING
に設定します。このステータスはTesseract.jsの処理ステータスが変わるたびに更新します。
worker
インスタンスにはいくつかのメソッドが存在します。まずは、load
メソッドを呼び出します。
OCR処理で読み取りたい言語をloadLanguage
メソッドで指定します。本稿では日本語を表すjpn
を使用します。
OCR処理を初期化するための、initialize
メソッドを呼び出します。パラーメーターで読み取る言語(jpn
)を指定します。
OCR処理の準備ができたので、処理を実際に開始するためのrecognize
メソッドを呼び出します。パラメーターで読み取る画像を指定します。
最後に、OCR処理完了のタイミングでOCR処理の終了、クリーンアップを行うterminate
メソッドを呼び出します。
Tesseract.jsでは、日本語を読み取る言語として指定すると、文字と文字の間に半角スペースが入ってしまうことがあります。これを防ぐために、text.replace(/+/g, ““)
でスペースを取り除きます。
次に、readImageText
関数のブロックの下に、以下のコードをペーストしてください。
このコードでは、「別の画像を使用する」ボタンがクリックされた際に、 setSelectedImage
で選択された画像のステート、selectedImage
をnull
に更新します。onRemoveClicked
で親コンポーネントにステートを渡します。
最後に、コンポーネントのJSXを追加します。handleRemoveClicked
関数のブロックの下に、以下のコードをペーストしてください。
ファイルを保存してください。
これで、OcrReader
コンポーネントが完成しました。OcrReader
コンポーネントの全コードは、Githubリポジトリを参照してください。
SMS送信コンポーネントを構築する
次に、SMSを送信する関数コンポーネントのSmsSender
を構築します。SmsSender.js
を開いてください。
ファイルに以下のコードをペーストしてください。
このコードでは、intl-tel-input
をインポートしています。また、STATUSES
で、SMSの送信ステータスをオブジェクトとして定義します。
次に、コンポーネントのメインの関数、SmsSender
を定義します。STATUSES
のブロックと、export default SmsSender
の間に、以下のコードをペーストしてください。
SmsSender
関数のパラメーターで、OcrReader
コンポーネントから渡されたreadText
をpropsとして親コンポーネントを通して受け取ります。送信するSMSのテキストのステート(smsText
)、SMSを送信する電話番号のステート(iti
)、SMSの送信処理のステート(smsSendingStatus
)をuseState
フックで定義します。
inputRef
を定義し、useRef
でinput要素でユーザーが入力する電話番号にアクセスします。
init
関数で、intl-tel-input
を初期化し、電話番号の入力ができるよう設定します。
useEffect
フックで、レンダーの結果が画面に反映された後にintl-tel-input
を初期化するように設定します。
sendSMS
関数で、後ほど作成するsend-sms
エンドポイントに対してSMS送信リクエストを送信します。
fetch
でHTTP POSTリクエストを送信します。ボディにOCR処理で読み取ったテキストを指定します。エンドポイントからのレスポンスをもとにSTATUS
でSMS送信ステータスを更新します。
次に、ユーザーが「SMSメッセージを送信」ボタンをクリックした際の動作を定義するhandleSubmit
関数を定義します。sendSMS
関数のブロックの下に以下のコードをペーストしてください。
このコードでは、「SMSメッセージを送信」ボタンがクリックされたタイミングでsendSMS
関数を呼び出します。
HTMLページ内でクリックイベントが発生し、処理が終了すると、画面遷移が起こります。これをpreventDefault()
で防ぎます。
また、クリックイベントが発生するとイベントが親要素へと伝播していきます。stopPropagation()
でこれ以上の伝播しないようにイベントの伝播を停止します。
最後に、コンポーネントのJSXを追加します。handleSubmit
関数のブロックの下に、以下のコードをペーストしてください。
ファイルを保存してください。
これで、SmsSender
コンポーネントが完成しました。SmsSender
コンポーネントの全コードは、Githubリポジトリを参照してください。
CSSを追加する
次に、アプリケーションのCSSを定義します。
テキストエディタで/srcの配下にあるindex.css
を開いてください。ファイルの内容を以下のコードに変更してください。
ファイルを保存してください。
これで、フロントエンド側の準備ができました!
次のステップ
前編ではプロジェクトのセットアップからフロントエンド側の構築に関してご紹介しました。後編ではバックエンド側の構築方法と、アプリケーションの実装についてご説明いたします。
後半はこちら:Tesseract.jsとReactでOCRコミュニケーションアプリを作る(後編)
Twilio Blogに投稿してみたい方や、フィードバック、登壇、勉強会のお誘いなどお気軽にsnakajima[at]twilio.comまでご連絡ください。開発中のプロジェクトに関してはGithub(smwilk)を覗いてみて下さい。