TOEICの勉強、AzureのCognitiveServicesでhackしませんか？

#はじめに
理系大学生の皆さんTOEIC勉強しますよね？
特に大学院編入試験には必ずと行っていいほどTOEICスコアの提出があります。

でもTOIECの勉強ってめんどくさいですよね？

TOEICでは幅広い英語力が必要とされるので単語暗記とか、ワークとか、単調でつまらない勉強になりがちなのです。

この記事ではそんなTOEIC学習をAzureのCognitiveServicesでhackして、ちょっと面白さを足しながら楽しく勉強しようというわけです。

「なんでAzureやねん！！」となると思いますがCognitiveServicesとTOEIC学習って実はめちゃくちゃ相性いい事に気づいてしまったんです！（それも学生無料で使える！）

なのでこの記事ではCognitiveServicesをTOEIC学習に使ってみる活用例を紹介していきます。

ネタ的な感じで捉えられるかもしれませんが実際の勉強にも使えるくらい結構実用的ですよ？！まじで！


例だけだと面白くないので実際にFlaskを用いてブラウザ上で動く[デモアプリ](https://tranquil-stream-44921.herokuapp.com "デモアプリ")も作ってみました。

リンクから飛べるので実際使ってみてください！

またコード最後の方に載せていますので自分好みに作り替えてもらえればと思います！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/318bb67e-3479-94f1-b10e-b339bbe8a08b.png)


#活用例１「part1の写真問題」
##概要
part1は写真が与えられて読み上げられた３つの文のうち、写真と合致する選択肢を選ぶ問題です。
下の写真は[TOEIC公式サイト](http://qiita.com "TOEIC公式ホームページ")の例題です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/c3c1dc3c-8663-96b5-5858-7a7099052452.png)

part1は読み上げられた文章中の単語が写真中に存在するかが最も基本的な解き方になっているため写真中の物体の英語名を把握することは勉強中で必須となります。

##作ったデモ
デモでは画像をフォームで投稿するとその中に出現する物体を物体認識して英単語を切り出しそれを翻訳することで単語一覧を表示しています。以下の写真は上の例題の画像を投げたときの分析結果です。
![スクリーンショット 2020-11-16 11.21.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/fa22a867-b3da-96a4-bcf4-03d895f3e54c.png)


正解分に含まれるsittingやtableはもちろんtoeic頻出単語のindoorやfloorといった単語も切り出せています！
今回はweb画像を対象としましたがもちろん手元のワークの写真でも動作します！

#活用例2「問題文の重要単語抜き出し」
##概要
toeicのpart5~7はreadingパートであり、読む力が試されます。
読む力の基本となるのはやはり単語力であり、文章中のわからない単語は１つずつ検索をし意味を照らし合わせます。

part1は読み上げられた文章中の単語が写真中に存在するかが最も基本的な解き方になっているため写真中の物体の英語名を把握することは勉強中で必須となります。

##作ったデモ
デモでは画像を投げるとその中から英文を抽出しそれらを日本語訳したものを表示してくれます。
更に予め登録されている重要単語に該当する単語が登場していればそれを出力もしてくれます。
以下のワークを撮った写真をデモアプリにアップロードすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/a92013b1-8253-083f-b703-87f3afdb0cd8.png)
このような結果が帰ってきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/c0b954ed-3f56-f893-f26e-a822a23c0fb6.png)
光があたっているところは捉えれてないですが、きれいに動いていますね！

#活用例３「単語帳の電子化」
##概要
活用例２でも述べましたがTOEICにおいて単語力は実力の基礎を担う重要な要素であり、多くの人はTOEIC専用の単語帳を買います。
ただ単語帳はあくまで本なので持ち運ぶのに不便だったり、使い勝手が悪かったりするため、スマホ上などで動作するスマホアプリにそれらの本に登場する単語を登録する事が多いです。ただその登録が面倒で、１単語ずつ読み込んでいかないといけません。


##作ったデモ
デモでは単語帳のスクリーンショットを投げるとその中の単語を抽出して、それを事前にセットしてあるCSVファイルに出力してくれます。
多くの単語帳アプリはCSV入力を備えているため、そのまま単語帳に登録する事ができ、大きく手間を省くことができます。
下のTOEIC定番単語帳「金単」の写真をアップロードすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/4686a00f-b110-da13-407d-dec03d5c5bfe.png)
このように結果が返ってきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/01d9ba42-be29-081e-134d-392065d8f42e.png)

うーん、こちらはあまり精度が出ませんでした。多分文字と同系色の背景だったからだとおもいます。

#まとめ
おおまかにはうまくできましたが、ところどころ精度が足りない感じもあります。
ただ、Azureの一番いいところは本来、個人ではできないような機械学習処理を簡単に自分のアプリに組み込めるところだと思います。
CognitiveServicesを学ぶことで趣味のプログラミングやハッカソン等で活かせることは間違いなしです。
この下のおまけではコードの解説も載せているのでぜひ見て参考にしてみてください。

自分でアプリを作る最大の利点は自分にぴったりなアプリが作れることです。
今回のデモアプリはあくまで例ですので、もっと自分好みに機能をカスタマイズして、プログラミングを学びながらTOEICをhackしてみてはいかがでしょうか?
質問等あれば回答するのでコメントしてくださいー


#付録　コード解説
ここからはコード解説に入ります。
ここで解説するのは以下の項目です。

- CognitiveServicesの使い方
- pythonからのCognitiveServices呼び出し方法
- flaskアプリケーションへのCognitiveServicesの組み込み方法

ここでは以下の説明は省略します。

- python Flaskの基本的な使い方
- コードの詳細な解説
- Azureアカウント登録

手順は以下のようになっています。
1. Translatorリソースの作成
2. ComputerVisionリソースの作成
3. Azureクラスのコーディング
4. 全体のコーディング


##1. Translatorリソースの作成

まずは[Azure Portal](https://portal.azure.com/#home "Azure Portal")にアクセスします。
Portalからリソースの生成をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/65d56781-b3c3-de5d-ebab-188755605f7f.png)
検索でTranslatorと検索し
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/bf8d627b-b3fb-3a5d-29b6-a61413ce07b0.png)
リソースを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/d14a9030-77f9-1901-fa5e-c71f2eb10e30.png)
こんな感じで適当に埋めて作成してください。（リソースグループは初めての場合は新規作成してください。価格レベルはF0が無料なのでF0をおすすめします。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/d3ec3940-59d1-5c46-dec0-cee9e507fab9.png)

これでリソースが作成できます。リソース画面からキーとエンドポイントを選択することでキーとエンドポイントを確認できます。この２つはAPIにアクセスするために必要なので後でコピペします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/e9a563a6-f3b3-ab97-2eef-358b1d446278.png)

##2. ComputerVisionリソースの作成
ComputeVisionはTranslatorとほぼ同じなので同じ部分は省略します。
リソースの生成を選択しComputerVisonを検索します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/c9771a47-37d0-9ac4-2e50-ef1c5bca92dc.png)
ComputerVisionを選択するとこの画面に来るので作成を押してあとはTranslatorと同じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/1cfc4116-d400-3837-f5b3-7737ec379fb8.png)
作成完了すると、Translatorと同様にキーとエンドポイントからキーとエンドポイントを取得できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/b177ce3f-2552-457d-2049-6e3f4844df0f.png)


##3. Azureクラスのコーディング
Azureクラス（azure.py)のイメージはこんな感じです。Flaskのapp.pyで直接apiを叩くのではなくてAzureクラスのメソッドを叩きます。それのメソッドに応じて必要なAPIをAzureクラスが叩くことでという感じです。なぜこのAzureクラスを挟むかというとapp.pyがごちゃごちゃするのを防ぐためもあるのですが、一番はこのazure.pyを他のアプリケーションでも使い回せるということです。
よってazure.pyのメソッドはできるだけシンプルな入出力になるよう意識しながら書いていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/eb52dbb8-86aa-0569-b570-60107f8bb527.png)

これがデモアプリのazure.pyです。

```python:azure.py
from azure.cognitiveservices.vision.computervision import ComputerVisionClient
from msrest.authentication import CognitiveServicesCredentials
import requests, uuid


c_key = "ComputerVisionのkey"
c_end = "https://terutocomputervison.cognitiveservices.azure.com/"
#
t_key = "Translatorのkey"
t_end = "https://api.cognitive.microsofttranslator.com/"

class Azure():
    @staticmethod
    #clientをセットする
    def setup():
        Azure.cvc_client = ComputerVisionClient(c_end, CognitiveServicesCredentials(c_key))

    @staticmethod
    #ファイルを受け取って写真の中の物質を検出し名前のリストを返す。
    def detect_objects(f):
        Azure.setup()
        #f = open(image_path, "rb")
        result = Azure.cvc_client.describe_image_in_stream(f)
        #f.close()
        return result

    @staticmethod
    #単語を翻訳し、意味を３つlistで返す
    def trans_word(word,from_lan,to_lan):
        location = "japaneast"
        path = '/dictionary/lookup'
        constructed_url = t_end + path
        params = {'api-version': '3.0','from': from_lan,'to': to_lan}
        headers = {'Ocp-Apim-Subscription-Key': t_key,'Ocp-Apim-Subscription-Region': location,
            'Content-type': 'application/json','X-ClientTraceId': str(uuid.uuid4())
        }
        body = [{
            'text': word
        }]
        request = requests.post(constructed_url, params=params, headers=headers, json=body)
        trans_jsons = request.json()[0]["translations"]
        ans_li = list()
        for trans in trans_jsons[0:3]:
            ans_li.append(trans["displayTarget"])
        return ans_li


    @staticmethod
    #写真内の印刷文字を読取る
    def read(image):
        Azure.setup()
        ocr_result_local = Azure.cvc_client.recognize_printed_text_in_stream(image,language='en')
        sentences = list()
        words = list()
        for region in ocr_result_local.regions:
            for line in region.lines:
                #print("Bounding box: {}".format(line.bounding_box))
                s = ""
                for word in line.words:
                    s += word.text + " "
                    words.append(word.text.lower())
                sentences.append(s)

        return {"sentences":sentences,"words":words}

    @staticmethod
    #文章の翻訳を行う
    def trans_sentence(text_input, to_lan):
        path = '/translate?api-version=3.0'
        params = '&to=' + to_lan
        constructed_url = t_end + path + params

        headers = {
            'Ocp-Apim-Subscription-Key': t_key,
            'Ocp-Apim-Subscription-Region': 'japaneast',
            'Content-type': 'application/json',
            'X-ClientTraceId': str(uuid.uuid4())
        }

        # You can pass more than one object in body.
        body = [{
            'text': text_input
        }]
        response = requests.post(constructed_url, headers=headers, json=body)
        return response.json()[0]["translations"][0]["text"]
```

c_keyとt_keyはAzure上で確認したものをコピペします。
デモアプリのAzureクラスは物体識別メソッドと単語翻訳メソッド、印刷文字読み取りメソッド、文章翻訳メソッドを用意しました。
それぞれのメソッド内でapiを叩いています。ただ、detect_objectsメソッド内ではすでに用意されているComputerVisionのライブラリを使うことで最小限の実装で済んでいます。
これらの実装は[Micosoftのドキュメント](http://qiita.com "Micosoftのドキュメント")で詳しく解説されているためそちらを参照することをおすすめします。


## 4. 全体のコーディング
すべてのコードを乗せると多くなるため[github](https://github.com/teruto725/Azure-for-TOEIC "Micosoftのドキュメント")にあげました。