Vision APIとNatural Language APIを組み合わせて名刺から情報抽出する

# はじめに
Cloud Vision APIとNatural Language APIを組み合わせて、名刺から情報抽出してみましょう。APIを使うためにPythonを用いて作ることにします。

前回記事はこちら:

* [kintoneで名刺管理アプリを作ってみよう](http://qiita.com/Hironsan/items/be3497972fb3517cb2b2)

# これから作るアプリ
名刺画像を与えると名前、会社名、住所を抽出するアプリを作成します。イメージとしては以下のようになります:
<img width="853" alt="スクリーンショット 2016-11-10 9.52.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/77079/0a65d071-3958-ad20-51e5-acaeb437d4b6.png">



# アプリ作成の流れ
Step 0：アプリ作成の準備をする
↓
Step 1：Vision APIを使ってテキスト検知をする
↓
Step 2：Natural Language APIを使って名前や会社名を抽出する
↓
Step 3：2つのAPIを統合して名刺から情報抽出する

# Step0(3min) アプリ作成の準備をする
アプリを作るために、必要なライブラリのインストール、リポジトリのダウンロード、APIキーの設定を行います。

## 必要なライブラリをインストールする
アプリを作成するために必要なライブラリをインストールします。以下のコマンドを実行してインストールしてください。

```shell-session
$ pip install requests
$ pip install pyyaml
```

## リポジトリをダウンロードする
あらかじめアプリの雛形については作成しておきました。必要なところを埋めれば動くようになっているので、そのためのリポジトリを以下からダウンロードしてください。

* [ダウンロード](https://github.com/Hironsan/kintone-handson/tree/handson)

「Clone or Download」の「Download ZIP」からダウンロードできます。

## API Keyを設定する
Google Cloud Platformで取得したAPIキーを設定ファイル(plugins/config/google.yaml)に記述します。エディタでgoogle.yamlを開いて、tokenの値をあなたのGoogle Cloud PlatformのAPIキーの値で上書きしましょう。**xxx**の部分を書き換えてください。

```yaml:google.yaml
token: xxx
```


# Step1(5min) Vision APIを使ってテキスト検知をする
ここではまずVision APIについて説明します。その後APIを使うためのスクリプトの記述を行います。記述を行ったら、動作確認のためにスクリプトを実行します。ではまずはAPIの説明から行います。

## Vision APIとは？
Google Cloud Vision API は、強力な機械学習モデルの能力を活用することで、画像の内容を認識し理解できるアプリケーションの開発を可能にします。Cloud Vision API は、以下の機能があります:

* 画像の分類（たとえば、「ヨット」「ライオン」「エッフェル塔」など）
* 顔認識
* 文字認識
* ロゴ検知
* ランドマーク検知
* Safe Search検知

言葉だけでは分かりにくいので実際に試してみましょう。以下のWebページにアクセスしてデモを試してみましょう。

* [Google Cloud Vision API](https://cloud.google.com/vision/)

課金体制なのですが、1000リクエストまでは無料で使うことができます。それ以降はリクエスト数に応じて課金が発生します。


## スクリプトの記述
Vision APIを使うために、スクリプトを記述します。スクリプトの場所は、**plugins/apis/vision.py**です。エディタでvision.pyを開いて、内容を以下のように書き換えましょう。書き換え終わったら保存してください。その際の文字コードはUTF8でお願いします。

```py3:vision.py
# -*- coding: utf-8 -*-
import base64
import requests


def detect_text(image_file, access_token=None):

    with open(image_file, 'rb') as image:
        base64_image = base64.b64encode(image.read()).decode()

    url = 'https://vision.googleapis.com/v1/images:annotate?key={}'.format(access_token)
    header = {'Content-Type': 'application/json'}
    body = {
        'requests': [{
            'image': {
                'content': base64_image,
            },
            'features': [{
                'type': 'TEXT_DETECTION',
                'maxResults': 1,
            }]

        }]
    }
    response = requests.post(url, headers=header, json=body).json()
    text = response['responses'][0]['textAnnotations'][0]['description'] if len(response['responses'][0]) > 0 else ''
    return text
```

**detect_text**に画像ファイルのパスとAPIキーを与えることで、画像ファイル内のテキストを検知・抽出して返してくれます。では動作確認のために実行してみましょう。

## スクリプトの実行
先ほど書いたスクリプトを実行してみましょう。
まず**plugins/tests**フォルダに移動してください。その中にtest_vision.pyがあるのを確認できるでしょうか。test_vision.pyでは先ほど書いたスクリプトの**detect_text**を呼び出すように指定しています。つまり、正しく動作すれば画像を与えた時にその画像中のテキストを返してくれるはずです。

では実行します。dataフォルダ内のexample.pngを与えて実行します。
<img width="300" alt="example.png" src="https://qiita-image-store.s3.amazonaws.com/0/77079/c7493d7d-12b1-890e-3ea6-ebcf1d99ecbe.png">


```shell-session
$ python test_vision.py data/example.png > result.txt
```

実行結果として以下の文字列が得られたでしょうか？

```shell-session
キントーン株式会社
東京本社第一営業部
蔡瑁 図太郎
23-4567
東京都日本橋天竺町1-2-3
Tel: 00-1234-5678
E-mail: saibo.zutaro@kintoon.co.jp
义
```


# Step2(5min) Natural Language APIを使って名前や会社名を抽出する
ここではまずNatural Language APIについて説明します。その後、APIを使うためのスクリプトの記述を行います。記述を行ったら、動作確認のためにスクリプトを実行します。ではまずはAPIの説明から行います。

## Natural Language APIとは？
Google Cloud Natural Language API は、使いやすい REST API でパワフルな機械学習モデルを適用し、テキストの構造や意味を認識します。 Natural Language API は以下の機能があります:

* 情報抽出(人名や組織名、イベント情報など)
* 評価分析(商品に対するコメントの感情、消費者の意見など)
* 構文解析

言葉だけでは分かりにくいので実際に試してみましょう。以下のWebページにアクセスしてデモを試してみましょう。

* [Google Cloud Natural Language API](https://cloud.google.com/natural-language/)

課金体制なのですが、5000リクエストまでは無料で使うことができます。それ以降はリクエスト数に応じて課金が発生します。

## スクリプトの記述
Natural Language APIを使うために、スクリプトを記述します。スクリプトの場所は、**plugins/apis/language.py**です。エディタでlanguage.pyを開いて、内容を以下のように書き換えましょう。書き換え終わったら保存してください。その際の文字コードはUTF8でお願いします。

```py3:language.py
# -*- coding: utf-8 -*-
import requests


def extract_entities(text, access_token=None):

    url = 'https://language.googleapis.com/v1beta1/documents:analyzeEntities?key={}'.format(access_token)
    header = {'Content-Type': 'application/json'}
    body = {
        "document": {
            "type": "PLAIN_TEXT",
            "language": "JA",
            "content": text
        },
        "encodingType": "UTF8"
    }
    response = requests.post(url, headers=header, json=body).json()
    return response


def extract_required_entities(text, access_token=None):
    entities = extract_entities(text, access_token)
    required_entities = {'ORGANIZATION': '', 'PERSON': '', 'LOCATION': ''}
    for entity in entities['entities']:
        t = entity['type']
        if t in required_entities:
            required_entities[t] += entity['name']

    return required_entities
```

**extract_entities**にテキストとAPIキーを与えることで、様々な固有表現を抽出することができます。ただし、今回はテキストから抽出するのは**会社名**、**人名**、**所在地**だけです。これらの情報を抽出するために使うのが、**extract_required_entities**です。

では動作確認のために実行してみましょう。


## スクリプトの実行
先ほど書いたスクリプトを実行してみましょう。
まず**plugins/tests**フォルダに移動してください。その中にtest_language.pyがあるのを確認できるでしょうか。test_language.pyでは先ほど書いたスクリプトの**extract_required_entities**を呼び出すように指定しています。つまり、正しく動作すればテキストを与えた時にそのテキスト中の会社名、人名、所在地を返してくれるはずです。

では実行します。dataフォルダ内のexample.txtを与えて実行します。example.txtの中には先ほどの文字認識結果が入っています。

```shell-session
$ python test_language.py data/example.txt > result.txt
```

実行結果として以下の文字列が得られたでしょうか？

```shell-session
{'PERSON': '蔡瑁 図太郎', 'LOCATION': '東京都日本橋天竺町1-2-3', 'ORGANIZATION': 'キントーン株式会社'}
```


# Step3(3min) 2つのAPIを統合して名刺から情報抽出する
では最後に今までに書いたVision APIとNatural Language APIを組み合わせるためのスクリプトの記述を行います。記述を行ったら、動作確認のためにスクリプトを実行します。ではまずはスクリプトの記述から行いましょう。

## スクリプトの記述
Vision APIとNatural Language APIを組み合わせるために、スクリプトを記述します。スクリプトの場所は、**plugins/apis/integration.py**です。エディタでintegration.pyを開いて、内容を以下のように書き換えましょう。書き換え終わったら保存してください。その際の文字コードはUTF8でお願いします。

```py3:integration.py
# -*- coding: utf-8 -*-
from .language import extract_required_entities
from .vision import detect_text


def extract_entities_from_img(img_path, access_token):

    text = detect_text(img_path, access_token)
    entities = extract_required_entities(text, access_token)

    return entities
```

**extract_entities_from_img**に画像ファイルのパスとAPIキーを与えることで、画像ファイル内の会社名や人名を認識して返してくれます。では動作確認のために実行してみましょう。

## スクリプトの実行
ではスクリプトを実行してみましょう。
まず**plugins/tests**フォルダに移動してください。その中にtest_integration.pyがあるのを確認できるでしょうか。test_integration.pyでは先ほど書いたスクリプトの**extract_entities_from_img**を呼び出すように指定しています。つまり、正しく動作すれば画像を与えた時にその画像中の会社名などを返してくれるはずです。

では実行します。dataフォルダ内のexample.pngを与えて実行します。
<img width="300" alt="example.png" src="https://qiita-image-store.s3.amazonaws.com/0/77079/c7493d7d-12b1-890e-3ea6-ebcf1d99ecbe.png">


```shell-session
$ python test_integration.py data/example.png > result.txt
```

実行結果として以下の文字列が得られたでしょうか？

```shell-session
{'PERSON': '蔡瑁 図太郎', 'LOCATION': '東京都日本橋天竺町1-2-3', 'ORGANIZATION': 'キントーン株式会社'}
```

# おわりに
いかがだったでしょうか。Vision APIとNatural Language APIを使った開発を取り扱ってみましたが、2つをつなぐことで様々な可能性を感じて頂けたのではないでしょうか。

次は今までに作ったアプリとSlackを組み合わせて、Slackに名刺画像をアップロードするとkintoneに登録できるようにします。次の記事へ進んでください。

* [名刺から情報を抽出するSlackBotを作る](http://qiita.com/Hironsan/items/9bfba01c37e9fcd7b8af)

# 記事まとめ
今回のハンズオンの内容は３つの記事にまとめています。

* [kintoneで名刺管理アプリを作ってみよう](http://qiita.com/Hironsan/items/be3497972fb3517cb2b2)
* [Vision APIとNatural Language APIを組み合わせて名刺から情報抽出する](http://qiita.com/Hironsan/items/166515acec35658986b2)
* [名刺から情報を抽出するSlackBotを作る](http://qiita.com/Hironsan/items/9bfba01c37e9fcd7b8af)

事前準備は以下の記事からお願いします。

* [kintone x 機械学習で実現する簡単名刺管理@kintone Café](http://qiita.com/Hironsan/items/a81eef912881b1051de5)