Google Cloud PlatformのOCRサービスを使ってサイマの課題に挑戦する

Ateam cyma Advent Calendar 2019、10日目です！
株式会社エイチーム EC事業本部サイマのエンジニア @shimura_atsushi が務めます。

サイマでは自転車ECとしてプロの整備士が組み立てし整備した自転車をお客様宅まで個配するサービスを運営しております。

サイマでは豊富にある在庫を自社工場にて管理しております、多くの自転車メーカーと取引があり毎日のように自転車の発注と入荷が工場ではされております、在庫の充実化ために毎日のように発注と入荷を繰り返してます。
また自転車本体だけではなくカゴやスタンド、ワイヤー錠といった自転車周辺パーツも取り扱っておりますので商品のSKU[^1]の規模は数千以上です。

[^1]: Stock Keeping Unit 在庫管理の最小単位

# そんなサイマの悩み
サイマは多くの発注と納品をすることでサイト上での商品の充実に努め、お客様の期待に答えようと努力しておりますがそれが故に大きな悩みがあります。

発注した自転車が工場へ納品される際にその商品の納品書が紙で添付されてきます、その納品書は工場から本社へ郵送され本社スタッフによって発注との整合性チェックが手と目で行われております。
発注と納品が日常的にあるためそのチェックに多くの時間を割かざるを得ないのが悩みのタネであります。

# どうするか？
完全ペーパレス状態にするのが理想です。仕入先のメーカからは何らかのデータで納品実績を証明してくれればプログラムでは再利用しやすくサイマにある発注実績とも突合しやすいのですが取引先の都合もありますのでなかなか簡単にそうはできません。

納品書は仕入先から紙のものがサイマの工場へ届きますのでそのタイミングからペーパレスにできないでしょうか？
工場で納品書をスキャンしてその内容をOCRを利用して文字起こしできればチェック作業の自動化に大きなアドバンテージになると思います。

というわけで今回は「紙の納品書のチェックをソフトウェアで自動化できないか？」に対してその一手としてOCRによる文字起こしに挑戦します。

## Google Could Platform（GCP）のOCRを試す
いちからOCRを開発をするのは大変なので既にサービスとしてあるOCRを利用してみます。
その中でGoogleのGCPで提供されているOCRサービスを試します。

GCPの[光学式文字認識（OCR）のチュートリアル](https://cloud.google.com/functions/docs/tutorials/ocr?hl=ja#understanding_the_code)を参考にOCRを試してみます。

### 事前準備
- GCPのプロジェクト作成
- APIを有効(チュートリアルでは４つのGCPサービスを利用するのでその有効化)
    - Cloud Functions
    - Cloud Pub/Sub
    - Cloud Storage
    - Cloud Translation
- Cloud SDKをインストール
 
### プログラムの準備
ローカルのPCに適当にディレクトリを作成してGCPのNode.jsサンプルが用意された[GitHubのリポジトリ](https://github.com/GoogleCloudPlatform/nodejs-docs-samples)から`index.js`と`package.json`をダウンロードしてくる。
今回はお試しなのでチュートリアルにあるソースコードをひたすら`index.js`へコピペしてきます。
`index.js`の編集が完了したら`npm install` もしくは `yarn install`すればOK

**チュートリアルのまま素直に進むとGCPへのデプロイコマンドでエラーが起きるので注意。**

```terminal
ERROR: (gcloud.beta.functions.deploy) Missing required argument [runtime]: Flag `--runtime` is required for new functions.
```
ランタイムの指定が必須のなのでここでコマンドのランタイムを確認して必要なものを指定する
[gcloud functions deploy  |  Cloud SDK |  Google Cloud](https://cloud.google.com/sdk/gcloud/reference/functions/deploy?hl=ja#--runtime)

>--runtime=RUNTIME
Runtime in which to run the function.
Required when deploying a new function; optional when updating an existing function.

> Choices:
> nodejs8: Node.js 8
nodejs10: Node.js 10
python37: Python 3.7
go111: Go 1.11
go113: Go 1.13
nodejs6: Node.js 6 (deprecated)


## 画像をアップロードしてOCRをする
プログラムの準備ができたので実際に画像をUPしてみます。
アップロードするときはブラウザからできますが**Google Clound SDK**がインストールされていれば
以下のコマンドでCouldStorageへアップロードできます。

```
gsutil cp [画像パス] gs://[アップロード先のバケット名]
```

CloudStorageへ画像をアップロードするとCouldFunctionsが発火して文字を読み取りさらに
CloudStorageへ結果を保存するという流れです

以下のような手書きの文字をiPhoneで撮影したサンプル画像を用意して試しました。
**この画像が**
![名称未設定.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311437/7bec2dba-78c0-a239-12ef-151ff4ea53a9.jpeg)

**こうなりました**
<img width="536" alt="スクリーンショット 2019-12-03 21.58.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311437/e78da779-518f-023f-55a9-8a1457183102.png">

字が下手くそだったからでしょうか？うまく読み取れない文字が何文字か見られます。

**意識して少しきれいに書いてみました**
![again.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311437/8f09e90a-1e35-c728-a265-6ec3d14c912f.jpeg)

**なんと！！ちゃんと読み取ることができました**
<img width="574" alt="スクリーンショット 2019-12-03 22.05.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311437/b088ad11-917a-9488-319e-6f7a1a5d28eb.png">

人間が読みやすい文字はソフトウェアも読みやすいということでしょうか？

### 複雑な画像で試す
本来OCRにかけて文字起こしをしたい画像はこちら
<img width="799" alt="nouhin.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311437/9b1c70a5-e611-33d8-0ef3-b4948ec08fd8.png">

※画像は一部修正しております
**この画像をUPすると・・・**
<img width="539" alt="nouhin_ocr.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311437/dd06454b-222f-eec1-ca0a-1aaed4c8e679.png">
※こちらも画像は一部修正しております

かなり読み取れているように思いますが読み取られた文字がテキスト形式で単純に出力されているだけでどれがどの情報なのかわかりづらくこれではOCRの結果を再利用するのが大変です。
読み取った文字に対してタグなどのようなラベリングをしないと再利用性が乏しいですね。
もしくは画像からできるだけ不要な箇所を取り除いてOCRにかけるなどどちらにしても実用するにはさらなる工夫が必要そうです。

# まとめ
今回、GCPのサービスを用いてサイマの課題解決の１手目となる挑戦をしました。
OCRにおいては手書きの文字や色の薄い文字など条件の良くない画像を如何に前処理で好条件にできるかが正確な読み取りへの鍵となりそうです。

OCRのクラウドサービスはGCPだけでなく以下のように各社クラウドベンダーが展開してます。

- Microsoftの[Azure Computer Vision API](https://azure.microsoft.com/ja-jp/services/cognitive-services/computer-vision/)
- AWSの[Amazon Textract](https://aws.amazon.com/jp/textract/)

試してみるのもいいかもしれません。

※**今回のチュートリアルで利用したサービスは有料のものを含むので不要になりましたら、該当のプロジェクトを削除しましょう。**

# おわりに
[Ateam cyma Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ateam-cyma)の10日目、いかがでしたか。
11日目はサイマのプロカメラマンである@senseさんがiPhoneで完結する撮影と編集術について話をしてくれますのでお楽しみに！

株式会社エイチームでは、一緒に働けるチャレンジ精神旺盛な仲間を募集しています。

エンジニアで興味を持った方はcymaの[Qiita Jobs](https://jobs.qiita.com/employers/a-tm/development_teams/149)をご覧ください。

そのほかの職種は、[エイチームグループ採用サイト](https://www.a-tm.co.jp/recruit/)をご覧ください。