Google Cloud Vision APIのOCR（画像認識）を検証する

みなさん機械学習プログラミングというとどんなイメージですか？
これからは機械学習の時代だよねー。と思いながらも、「なんか難しそう・・・」「その筋の専門家じゃ無いと出来ないのでは？」と考えている方もいるのではないでしょうか。

いえいえそんなことはありません。
Googleが提供するGoogle Cloud Platform（GCP）の機械学習APIを使うと、驚くほど簡単に機械学習プログラムを書けるのです。

今回はGCPの中でも画像に関する機械学習であるGoogle Cloud Vision APIのOCR機能を使って文字認識プログラムを書き、どのくらいの精度で文字認識が出来るか検証してみました。

ちなみにコーディングに費やした時間はおよそ３０分です。
本当に簡単に出来るので、皆さん是非お試し下さい。

# Google Cloud Vision APIとは
Google Cloud Platformが提供する機械学習サービスのうち、画像解析に関する処理をしてくれるAPIで、以下の機能を備えています。

| サービス名| 説明|
|:-----------------|:------------------|
| 物体検知|画像に写っている物体が何なのか（犬？猫？ etc）を検知|
| 文章検知（OCR）|画像内の文字や文章を検知|
| 表情・感情検知|画像内に写っている人物の表情や感情を検知|
| 場所検知|画像内の構造物から場所（名所）を検知|
| ロゴ検知|画像内のロゴを検知|
| 有害検知|画像内にアダルトコンテンツやバイオレンスな表現がないかを検知|

今回はこの中の「文章検知（OCR）」を使っています。

# 検証に使った画像
今回、色々なパターンの画像を使い、どのくらいの精度で検知が出来るのか試してみました。検証に使った画像は以下の通りです。

1. キャプチャ画像（文字のみ）
2. キャプチャ画像（イラスト＆文字）
3. 印刷物を撮影したデータ（Word文章）
4. 印刷物を撮影（Excel表）
5. 手書き文字を撮影
6. （おまけ）アラビア文字

# 検証環境
以下の環境で検証しています。
- AWS EC2 Amazon Linux
- PHP 5.3.29
- Google Cloud Vision V1

# 検証方法
## APIキーの取得
まずはGoogle Cloud Visionを使用するにあたって必要なAPIキーをGoogle Developers Consoleから取得します。

> [Google Developers Console](https://console.developers.google.com/)

## サンプルプログラム
サンプルプログラムはこちら。

```php:ocr.php
<?php
        // APIキー
        $apiKey = "ご自身のAPIキーを入力してください";

        // 画像ファイル名
        $imageNm = $argv[1] ;

        // リクエスト用json作成
        $json = json_encode(array(
                "requests" => array(
                        array(
                                "image" => array(
                                        "content" => base64_encode(file_get_contents($imageNm)),
                                ),
                                "features" => array(
                                        array(
                                                "type" => "TEXT_DETECTION",
                                                "maxResults" => 10,
                                        ),
                                ),
                        ),
                ),
        ));

        // 各種オプションを設定
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, "https://vision.googleapis.com/v1/images:annotate?key=" . $apiKey); // Google Cloud Vision APIのURLを設定
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // curl_execの結果を文字列で取得
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // サーバ証明書の検証を行わない
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST"); // POSTでリクエストする
        curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: application/json")); // 送信するHTTPヘッダーの設定
        curl_setopt($curl, CURLOPT_TIMEOUT, 15); // タイムアウト時間の設定（秒）
        curl_setopt($curl, CURLOPT_POSTFIELDS, $json); // 送信するjsonデータを設定

        // curl実行
        $res = curl_exec($curl);
        $data = json_decode($res, true);
        curl_close($curl);


        // 結果を表示
        print $data["responses"][0]["fullTextAnnotation"]["text"];
```
上記ファイルをPHPが動く環境に保存し、以下のコマンドで実行できます。
第１引数に文字解析したい画像のパスを指定します。

> \# php /file/to/path/ocr.php image_file_path

# 実際に試してみた

実際に試してみた結果がこちらです。

## キャプチャ画像（文字のみ）
- 日本語文字

使った画像がこちら

>![japanese.png](https://qiita-image-store.s3.amazonaws.com/0/117041/6cdb1442-c06e-4ae8-e40a-e6521b7bca42.png)

引越し侍のTOPページにある文字の一部をキャプチャしたものです。
その結果は・・・

> \# php ocr.php japanese.png
ネット予約とは、あなたの引越し情報を入力すると、ネット上で費用相
場と引越し業者ごとの見積もりの料金が比較できるサービスです。今す
07
ぐ最安値の引越し業者を探したい人や、引越しの依頼をしたい人におす
すめです。

おお！結構正しく変換されてますね。
07というよくわからない数字が入っていますが・・・それ以外は問題なさそうです。

- 英語文字

続いて英語文字です。ちょうど良いデータがなかったので、手打ち文字をキャプチャしたものを使いました。

> ![english.png](https://qiita-image-store.s3.amazonaws.com/0/117041/1928deee-7e68-0df4-0bae-001e3bb86a8d.png)

どこかで聞いたことある例のやつですね。
結果がこちら。

> \# php ocr.php english.png
I have a pen. I have a apple. ahh apple pen.
I have a pen. I have a pineapple. ahh pinapple pen.
apple pen. pinapple pen. ahh pen pinapple apple pen.

すごい完璧。1文字の狂いもありません。
実はキャプチャした際、文字の一番最後にカーソルがあたっていて、それも一緒にキャプチャしてしまったのですが・・・ちゃんと省かれています。
これはかなり期待できるのではないでしょうか。

## キャプチャ画像（イラスト＆文字）

次はイラストと文字が両方含まれる画像です。

> ![withImage.png](https://qiita-image-store.s3.amazonaws.com/0/117041/78b81c96-3fec-39aa-4644-796b5221526f.png)

こちらも引越し侍のTOPページからキャプチャしてきました。
その結果がこちら。

> \# php ocr.php withImage.png
サカイ、日通、アリさんなど大手から中小業者まで徹底比較
見積もり費用と相場を F 60較ー
見積もり比較で
安くなる!
比較して安く引越し!
4-,44ーー前 ︿ 44-4--,44ーー-id", 44-4 ah44-
44. l li 물 t1-144-

むむむ・・・どうやらイラスト有りのデータだとかなりノイズが入りますね。
侍くんの頭が邪魔しておかしな変換をしてしまっているのと、
下の町並みイラストまで無理矢理変換しようとしてノイズになってますね。
あと、上から下、左から右に解析する仕組みのようです。そこまでの融通は利かないみたいです。
ただ、日本語部分はそれなりに正しく変換されていますので、飾り文字等であれば問題なさそうです。

## 印刷物を撮影（word文章）

続いて印刷物の撮影データです。
ちょうど良いものがなかったので、子供の保育園のお便りを撮影してみました（個人情報は削除しております）

> ![wordData2.png](https://qiita-image-store.s3.amazonaws.com/0/117041/39ca5d8b-253c-4c0a-141e-5ca80c9f6973.png)

結果がこちら

> \# php ocr.php wordData.jpeg
平成2 9年3月吉日
保護者各位
園長
平成29年度 第1 3回入園·進級式のご案内
早春の候、ひと雨ごとに暖かさの増す、今日この頃でございます。皆様方には、ご健勝の
こととお喜び申し上げます。
さて、下記の通り平成2 9年度 第13回 入園·進級式を行いますので、ご出席いただき
ますようご案内申し上げます。
記
1.日時
平成29年4月1日 (土) 10時より
(9時15分より受付を行います。4 5分までには登園してください)
2.場所
遊戯室
3,その他
·保護者の方は当日スリッパをご用意ください。
·駐車場が少ないので、できるだけ徒歩または自転車でお越しください。
·車の方は、発表会と同じく、近隣の方々にご迷惑をおかけしないように駐車券を配布い
たします。一家庭に一枚、配布いたしますのでの乗り合わせてお越しください。ただし、
駐車場の数が足りていませんので、駐車券があっても止められない場合もあります。ご
協力お願いいたします。
·入園式終了後は保護者会総会を行いますので、ご参加ください。
·幼児は名札の中身を交換いたしますので、必ず、名札を持ってきてください。
·当日は土曜日です。式終了後(12時~)に保育をご希望の方は事前にお知らせくださ
い。3月18日 (金)までに必ずお申し込みください。
(給食がありませんので弁当·おやつ。水筒を持参してください)

こちらもほぼ完璧。微妙に全角数字周りの解析が怪しく、空白文字が入ってしまいますが読む分には問題ないレベルですね。

## 印刷物を撮影（Excel表）

次はこちら。同じく保育園のお便りですが、今度はExcelデータを印刷したものを撮影しました。

> ![excelData2.jpeg](https://qiita-image-store.s3.amazonaws.com/0/117041/aff0137f-2d54-2857-bae3-6b21404fe9d9.jpeg)

結果がこちら。

> \# php ocr.php excelData2.jpeg
平成28年度年間行臺予罡ㄧㄧㄧㄧㄧㄧㄧㄧㄧㄧㄧㄧㄧㄧ一一一一一﹁
園の行事
4月 2日 (土) 1入園、進級式
18日(水) 親子遠足 4, 5才児親子で出かけます(変更あり)
5月1日程未定 徒歩遠足 0~3才児 気候に合わせて出かけます(園児のみ)
9日~20日 個人懇談 (新入園児のみ)
6月111日(土) |堡克参観
日程未定-/ r科検診
内科検診
7日休) |七夕会
7月
12日 (火) プール開き
6日 (H) |夏祭り
8月 2 4日 (水) 人形劇(むすび座)
20日 (土) |夏祭り (6日が雨天の場合)
9月113日(火) 祖父母の会
10月18日(土) |運動会( 1 5日 予備日)
日程未定 1秋の遠足·芋掘り
11811 8日 (金),作品展
11月
19日 (土)作品展
日程未定 1内科検診
5日~16日 個人懇談(全園児)
12月119日 (月)レ
クリスマス会
日程未定 歯科検診
1月11 6日 (金) |新年お楽しみ会(餅つき)
17日(火) 移動動物園
2月11 3日 (金) |豆まき
18日 (土) 生活発表会
3 3日 (金) ひな祭り会
3月
25日 (土) 卒園式
*行事は予定です。変更、中止になる場合がありますのでご了承ください。
1育
1保歯
月1

う、うーん。微妙。。表の部分を無理矢理認識してパイプラインが混じったり、数字の1が入ってしまっていますね。。読めなくはないですが、実用には厳しいレベルかも知れません。

## 手書き文字を撮影

続いてはこちら。引越し侍のTOPページにある文章を手書きで起こしてみました。
汚い字で申し訳ありませんが・・・OCRの機能を試す為にあえて汚く書いたことにします。

> ![write.jpeg](https://qiita-image-store.s3.amazonaws.com/0/117041/a5ec2497-f149-2f00-14aa-6a48a92a074d.jpeg)

結果がこちら

> \# php ocr.php write.jpeg
サ ()
引越し見通ty-f n 751る/
250社の人気乳石とでメんたhtc較
需抖篷03 220 1-e"Z
矛斗釒, . D);で、
Fri選した衣社た-J th?
貝翁钊依强!
人: AL Za 1%で
電話, y-IL-2 、科还相談
33
ーーー見租もリサーじーの予し
(D a、は引越Lrt)窘を入力
(Z) /取逞した数社にひとbrRB+I)
(3 )花) 1昂요見通t')でtt
ヌ、卜쿵約T-t'Z の荒
引玅 内宏飞NDL王者と琁家
G)料钅ヤ口コシをネー7-rcd
9人気茉声たta h7:んネ、ト予抈

悲しい。悲しすぎる。なんだよヤロコシって。
私の字が汚すぎたのもありますが、、手書きだときれいに書かないと正しく読み取ってくれないのですね。

# （おまけ）アラビア文字
最後にちょっと気になったのでおまけです。
先ほどの検証結果で、基本左から右に解析する結果が出ていましたので、
右から左に記述するアラビア文字で試したらどうなるか、やってみました。

検証に使った画像がこちら。

> ![arabia.png](https://qiita-image-store.s3.amazonaws.com/0/117041/233054a4-11ed-3ee9-b917-5898d0ea5e62.png)

私には何が書いてあるのか全く読めませんが、
内容は先ほど英語文字で使った「どこかで聞いたことのある例のやつ」です。
Google翻訳さんの力を借りました。

結果がこちら。

> \# php ocr.php arabia.png
AaliてLiali .alis gal .,a Gsie UI.
-sanてuisi Jiu pail al .. Miu all yWs poi!,

おっと。英語で認識されてしまいました。

先ほどのソースを少し作り替えて、以下を追加してみました。
languageHintsオプションに"ar"（アラビア語）を追加しています。

```php:ocr.php
                                "features" => array(
                                        array(
                                                "type" => "TEXT_DETECTION",
                                                "maxResults" => 10,
                                        ),
                                ),
                                // -- ここから追加 --
                                "imageContext" => array(
                                        "languageHints" => array("ar"),
                                ),
                                // -- ここまで --
                        ),
```

再チャレンジした結果がこちら。

> \# php ocr.php arabia.png
.انا عندي قلم. لدي تفاحة . أه التفاح القلم
انا عندي قلم. لدي الأناناس. أه القلم بينابل
.القلم اتفاح. القلم بينابل. أ القلم بينابل التفاح القلم

え、えっと、いかんせんアラビア語が読めないので、
うまくいってるのかよくわかりませんが・・・
ざっと見る限り、ちゃんと出来ているように思えます。
（どなたかアラビア語が読める方、ご判断頂きたいです。。）

# 結論
1. キャプチャ文字の認識はかなり高精度。
2. 印刷文字も大丈夫。ただし、Excelの表形式になっているとノイズが入りやすい。
3. 言語は特に問わない。アラビア語も出来ていると思われる。
4. 手書き文字はよほどきれいに書かないと認識してくれない。
5. イラストが入ると誤認識・ノイズの原因になる。
6. 基本は左から右に解析される。

いかがでしたでしょうか？
手書き文字の認識は散々な結果になってしまいましたが、
条件さえ整えば、かなり高精度で文字認識をしてくれるという結果になりました。

検証しているうちに楽しくなってしまい時間を費やしてしまいましたが、
コーディングに費やした時間は本当に30分程度です。
Google Cloud Vision APIを使えば簡単に機械学習を試すことが出来ますので、是非皆さん使ってみてください。

# 追伸
株式会社エイチーム引越し侍では、一緒にサイト改善をしてくれるWebエンジニアを募集しています。エイチームグループのエンジニアとして働きたい！という方は是非、以下のリンクから応募してください。
皆様からのご応募、お待ちしております！！

> [エイチームグループ採用サイト（Web開発エンジニア職）](http://hikkoshi.a-tm.co.jp/recruit/request.php?ea=kekiqiita_gcv)