19
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

今さらline botでdocomoAPIの画像認識を試してみたら意外に高性能だった

Posted at

#概要
lineにてdocomo APIによる画像認識を行い、送った写真から製品を判断し想定される製品のAmazonサイトを紹介するbotです。

#結果
想定していたよりも画像認識技術が高性能でした。

このように商品のパッケージの写真を撮ってbotに送信する。

IMG_3604.PNG

画像から推定される商品を3つ表示するようにしました。
最大で10つの推定される商品の情報を取得可能です。

IMG_3603.PNG

docomoAPIによりその商品のamazon urlを取得できるため「Amazonで見る」をクリックするとそのページに飛べる機能を作成できます。

IMG_3601.PNG

以下の画像のように、写真の一部分に商品が写っている写真(スクショ等)でも商品の判定を行ってくれました。ただし、一番目の候補には別の商品が判定されました、、、

IMG_3602.PNG IMG_3599.PNG

商品が判定されてなかった場合は、「見つかりませんでした。」のメッセージが表示されるようにしました。
また、メッセージを送っても何も返事がないのは寂しいので、recruitAPIのTalkAPI機能を実装し、メッセージに答えてくれるようになっています。

#ソースコード
Github

#参考
linebotを作成する際に、以下のサイトがとても参考になりました。
Django+HerokuでLINE Messaging APIのおそ松botを作るまで
LINE Messaging APIとPythonを使ってChatbotを作ってみた

#環境
アプリケーションフレームワークにはDjangoを使用し、herokuにてサーバーを立てました。
Os:macOS Sierra
Python:Python 3.6.1
Django:1.11.5

#作成方法
すでにline bot、docomoAPIの使い方や、herokuサーバーの構築方法はたくさんの記事があるため、
作成したview.pyのみ説明します。
全コードはgithubを参照ください。

view.py

    # Reply text
def reply_text(reply_token, rep_meg):
    payload = {
        "replyToken": reply_token,
        "messages": [
            {
                "type": "text",
                "text": rep_meg
            }
        ]
    }

reply
    requests.post(REPLY_ENDPOINT, headers=HEADER, data=json.dumps(payload))  # to send data to LINE
    return rep_meg


    # Save image
def save_image(messegeid):
    message_content = lINE_BOT_API.get_message_content(messegeid)

    i = Image.open(BytesIO(message_content.content))
    filename = '/tmp/' + messegeid + '.jpg'
    i.save(filename)

    return filename

    # Get json
def get_json(filename):
    with open(filename, mode='rb') as f:
        result = requests.post(
            url=__build_url('recognize'),
            params={'APIKEY': docomoapikey, 'recog': 'product-all', 'numOfCandidates': 5},
            data=f,
            headers={'Content-Type': 'application/octet-stream'})
        result.raise_for_status()
        result = result.json()
    return result

reply_test・・・ユーザが送信したメッセージを元に、recruitAPIのtalk機能より
得られたメッセージを返します。request post を行う。

save_image・・・ユーザが送信した画像をサーバ側で取得します。

get_jshon・・・docomoAPIの画像認識機能より商品の情報(jshon)を取得します。

view.py

    # Reply carousel
def post_carousel(reply_token,imageUrl,title,brand,releaseDate,maker,url,itmeName):
    payload = {
          "replyToken":reply_token,
          "messages":[
              {
                "type": "template",
                "altText": "商品結果",
                "template": {
                    "type": "carousel",
                    "columns": [

                        {
                          "thumbnailImageUrl": imageUrl[0],
                          "title": itmeName[0],
                          "text": "ブランド名:" + brand[0] + " メーカー名:"+ maker[0] +" 発売日:" +releaseDate[0],
                          "actions": [

                              {
                                  "type": "uri",
                                  "label": "Amazonで見る",
                                  "uri": url[0]
                              }
                          ]
                        },
                        {
                          "thumbnailImageUrl": imageUrl[1],
                          "title": itmeName[1],
                          "text": "ブランド名:" + brand[1] + " メーカー名:"+ maker[1] +" 発売日:" +releaseDate[1],
                          "actions": [

                              {
                                  "type": "uri",
                                  "label": "Amazonで見る",
                                  "uri": url[1]
                              }
                          ]
                        },
                        {
                          "thumbnailImageUrl": imageUrl[2],
                          "title": itmeName[2],
                          "text": "ブランド名:" + brand[2] + " メーカー名:"+ maker[2] +" 発売日:" +releaseDate[2],
                          "actions": [

                              {
                                  "type": "uri",
                                  "label": "Amazonで見る",
                                  "uri": url[2]
                              }
                          ]
                        }
                      ]
                }
              }
            ]
    }
    req = requests.post(REPLY_ENDPOINT, headers=HEADER, data=json.dumps(payload))
    return title[0]

画像判定された商品の結果をTemplate Message機能を使って表示します。
表示する情報は、商品イメージ、商品名、ブランド名、メーカー名、発売日、amazonurlへのアクセスとしました。そのほかにも、重さ、サイズ、等を取得し表示できます。

view.py

def callback(request):
    reply = ""
    request_json = json.loads(request.body.decode('utf-8'))  # to get json

    for e in request_json['events']:
        reply_token = e['replyToken']  # to get reply_token
        message_type = e['message']['type']  # to get type

        # reply for test
        if message_type == 'text':
            text = e['message']['text']  # to get message
            rep_meg = client.talk(text)["results"][0]["reply"]  # to get reply message by recuitTalk
            reply += reply_text(reply_token, rep_meg)

            # reply for image
        if message_type == 'image':
            messegeid = e['message']['id']  # to get messageID
            filename = save_image(messegeid)
            result = get_json(filename)

            if (result.get('candidates') != None):
              imageUrl,title,brand,releaseDate,maker,url,itemName =[],[],[],[],[],[],[]

              for i in range(0,3): # to get item info
                imageUrl.append(result['candidates'][i]['imageUrl'])
                title.append(result['candidates'][i]['sites'][0]['title'])
                brand.append(result['candidates'][i]['detail']['brand'])
                releaseDate.append(result['candidates'][i]['detail']['releaseDate'])
                maker.append(result['candidates'][0]['detail']['maker'])
                url.append(result['candidates'][i]['sites'][0]['url'])
                itemName.append(result['candidates'][i]['detail']['itemName'][0:29]) # to restrict length

              reply += post_carousel(reply_token,imageUrl,title,brand,releaseDate,maker,url,itemName)

            else:
                rep_meg = "お探しのものは見つかりませんでした。"
                reply += reply_text(reply_token, rep_meg)

    return HttpResponse(reply)  # for test

ユーザがテキストを送信したか画像を送信したか判定をし、それぞれにおいてrequest post
する処理です。

#まとめ
すでにたくさんのlinebotについて記事があり、一度自身で作成したいと思い作成に至った。docomoAPIの画像認識を用いて作成したところ、思っていた以上に性能が良かったため、それについて伝えたく記事を書いて見ました。

19
16
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?