LoginSignup
6
6

More than 5 years have passed since last update.

AI初心者が《顔認識AI LINE Bot「スケベ博士」をPythonとGoogle Apps Scriptで作ろう》をやってみてつまずいた点

Last updated at Posted at 2019-01-14

初めまして、Qiitaで初投稿となります。駆け出しの初心者エンジニアkotaです(@madogiwa_kota
今回は、スケべで有名なDai(@never_be_a_pm)さんのチュートリアルを購入してやってみました。
※あくまで学習のために面白そうなことをやりたかっただけです!笑

基礎的なプログラミングは学んだけど、そこから次はどうすればいいか分からない人にオススメのチュートリアルです!
【LINE Bot x AI】顔認識を利用したAI Bot「スケベ博士」をPythonとGoogle Apps Scriptで作ろう

https://note.mu/daikawai/n/n252b3f8d1138

対象読者(おそらく気合いがあれば誰でも!)

以下引用です。基本的には書かれている通りの事前知識がないと実際に動かせないかもしれないです。
ただ、最後にもある通り、気合いでなんとかなります。(自分に質問して頂いても大丈夫です!)

読者の対象
読者の対象ですが、まったくのプログラミング初心者では難しいかと思います。求める読者のスキルセットとしては

  • 基本的なHTML・CSSの知識(スクレイピングで必要)がある

  • 基本的なPythonの知識(少なくとも自分でPythonの実行環境を構築することができる知識、簡単な文法がわかるレベル)がある

  • 基本的なJavaScriptの知識(Google Apps ScriptがほとんどJavaScriptと同じなので)がある

  • CRUDなどの、基本的なHTTPの通信の理解がある

  • 困難な課題も解決しようと思える、圧倒的な性欲がある。もしくは何かしら独学でプロダクトを作りたいという欲求がある

が必要となってきます。

そもそもの自分のスペックは??(大したことはない)

  • プログラミング学習サイト progate Lv. 237(HTML・CSS、JavaScriptなどの基礎的な文法を学ぶ)
  • python学習サイト PyQ 機械学習コース終了
  • pythonの基礎的な文法は学部の卒研の時に独学で学んだ
  • 業務でpythonは使わない
  • LINE Bot, Azure Face API, GoogleAppsScriptは初めて触る

作成したもの(元祖エロジジイ)

環境:mac10.14.2 Python 3.6.4
アカウント!

友達登録はこちらから!
Screen Shot 2019-01-14 at 12.03.56.png

つまずいた点

スクレイピング時にChromeの言語設定を英語にしていたためか、取得した女優の名前が全てローマ字になっていた(泣)

チュートリアルに付属していたDaiさんがスクレイピングしたデータを使った
(スクレイピングは時間がかかるのでもう一度やりたくなかったです笑)

DMMのアフィリエイトIDとAPI IDがごっちゃになり間違えて指定していた

Azure Face APIの学習の工程をあまり理解していなかったためつまずいた

学習工程は以下のような形です。
この順番で各メソッドを呼び出す必要があります。
結構時間がかかる。
あと、APIコール・登録できる画像の数?に制限がありました。

学習工程

・PersonGroupの作成
・Personの登録
・PersonにFaceを登録
・PersonGroupを学習

判別工程

・特定の画像からFaceをdetect
・detectした人物の画像から、それに該当する人物のidを抽出
・idを基にその人物の名前を抽出

FaceAPI学習プログラム
import requests
import json
import logging
import pandas as pd
import io,sys
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
from time import sleep

BASE_URL = "https://japaneast.api.cognitive.microsoft.com/face/v1.0/"
SUBSCRIPTION_KEY = "your SUBSCRIPTION_KEY"
GROUP_NAME = "your group name"

def makeGroup():
    end_point = BASE_URL + "persongroups/" + GROUP_NAME
    payload = {
        "name": GROUP_NAME
    }
    headers = {
        "Ocp-Apim-Subscription-Key" :SUBSCRIPTION_KEY
    }
    r = requests.put(
        end_point,
        headers = headers,
        json = payload
    )
    print(r.text)

def makePerson(name):
    end_point = BASE_URL + "persongroups/" + GROUP_NAME +"/persons"
    headers = {
        "Ocp-Apim-Subscription-Key" :SUBSCRIPTION_KEY
    }
    payload = {
        "name": name
    }
    r = requests.post(
        end_point,
        headers = headers,
        json = payload
    )
    print(r.text)
    try:
      personId = r.json()["personId"]
    except Exception as e:
      personId = None
      print(r.json()["error"])
    return personId


def addFaceToPerson(personId, imageUrl):
    end_point = BASE_URL + "persongroups/" + GROUP_NAME + "/persons/" + personId + "/persistedFaces"
    print(end_point)
    headers = {
        "Ocp-Apim-Subscription-Key" :SUBSCRIPTION_KEY
    }
    payload = {
        "url": imageUrl
    }
    r = requests.post(
        end_point,
        headers = headers,
        json = payload
    )
    print(r.text)

def trainGroup():
    end_point = BASE_URL + "persongroups/" + GROUP_NAME + "/train"
    headers = {
        "Ocp-Apim-Subscription-Key" :SUBSCRIPTION_KEY
    }
    r = requests.post(
        end_point,
        headers = headers,
    )
    print(r.text)

def detectFace(imageUrl):
    end_point = BASE_URL + "detect"
    headers = {
        "Ocp-Apim-Subscription-Key" :SUBSCRIPTION_KEY
    }
    payload = {
        "url": imageUrl
    }
    r = requests.post(
        end_point,
        json = payload,
        headers = headers
    )
    try:
      faceId = r.json()[0]["faceId"]
      print ("faceId Found:{}".format(faceId))
      return r.json()[0]
    except Exception as e:
      print("faceId not found:{}".format(e))
      return None

def identifyPerson(faceId):
    end_point = BASE_URL + "identify"
    headers = {
        "Ocp-Apim-Subscription-Key" :SUBSCRIPTION_KEY
    }
    faceIds = [faceId]
    payload = {
        "faceIds" :faceIds,
        "personGroupId" :GROUP_NAME,
    }
    r = requests.post(
        end_point,
        json = payload,
        headers = headers
    )
    print(r.text)
    try:
      candidates = r.json()[0]["candidates"]
      print ("candidates Found:{}".format(candidates))
      return r.json()[0]
    except Exception as e:
      print("candidates not found:{}".format(e))
      return None

def getPersonNameByPersonId(personId):
    end_point = BASE_URL + 'persongroups/' + GROUP_NAME + '/persons'
    result = requests.get(
        end_point,
        headers = {
        "Ocp-Apim-Subscription-Key": SUBSCRIPTION_KEY
        },
        json = {
            'personGroupId': GROUP_NAME
        }
    )
    persons = json.loads(result.text)
    for person in persons:
        if person['personId'] == personId:
            return person['name']

if __name__ == '__main__':
    #以下学習用
    """
    trainGroup()
    df = pd.read_csv("CSVファイルのためのパス", index_col=0)
    df2 = pd.read_csv("CSVファイルのためのパス", index_col=0)
    for i, row in df.iterrows(): #,name, kana, image, dmmimage, roman
        name = row["name"]
        kana = row["kana"]
        image = row["image"]
        dmmimage = row["dmmimage"]
        print(name)
        #makeGroup()
        #personを登録し、personIdを返す
        #personId = makePerson(name)
        #personIdをもとに、そのpersonにスクレイピングした画像とDMMの画像を追加する
        print(personId)
        addFaceToPerson(personId, dmmimage)
        addFaceToPerson(personId, image)
        print("begin")
        sleep(11)
        print("end")
        se = pd.Series([name,kana,image,dmmimage,personId],["name","kana","image","dmmimage","personId"])
        df2 = df2.append(se, ignore_index=True)
        print(df2)
    """
    #以下test用
    #image = "https://img.asagei.com/wp-content/uploads/2018/04/20180426j1st.jpg"
    image = "http://images16.wav.tv/688/03299979cff98c68.jpg"

    faceId = detectFace(image)
    person = identifyPerson(faceId["faceId"])
    print(person)
    if person["candidates"]:
        personId = person["candidates"][0]["personId"]
        print(personId)
        personName = getPersonNameByPersonId(personId)
        print(personName)
    else:
        print("No candidates found")

Python記述時にutf-8にエンコーディングしないとエラーが出た

#以下の記述で解決
import io,sys
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

Face APIの指定したURLがチュートリアルのものと違うためエラーが出た

#BASE_URLの指定
BASE_URL = "https://japaneast.api.cognitive.microsoft.com/face/v1.0/"

自分が使用すべきエンドポイントの確認が必要
ポータルで確認できる
https://azure.microsoft.com/ja-jp/

FaceAPIコールの規制(1分間に20回)にかかりエラーが起きた→Sleep(11)で待機し回避

FaceAPI学習プログラム
#以下の記述で解決
from time import sleep
if __name__ == '__main__':
    #trainGroup()
    df = pd.read_csv("CSVファイルへのパス", index_col=0)
    df2 = pd.read_csv("CSVファイルへのパス", index_col=0)
    for i, row in df.iterrows(): #,name, kana, image, dmmimage, roman
        name = row["name"]
        kana = row["kana"]
        image = row["image"]
        dmmimage = row["dmmimage"]
        print(name)
                #Groupを作成するために一度だけ実行
        #makeGroup()
        #personを登録し、personIdを返す
        personId = makePerson(name)
        #personIdをもとに、そのpersonにスクレイピングした画像とDMMの画像を追加する
        print(personId)
        addFaceToPerson(personId, dmmimage)
        addFaceToPerson(personId, image)
        ##ここに11秒間待つ処理を追加した
        sleep(11)
        se = pd.Series([name,kana,image,dmmimage,personId],["name","kana","image","dmmimage","personId"])
        df2 = df2.append(se, ignore_index=True)
        print(df2)

GoogleAppsScriptとLINEが繋がらない

こちらはほぼコピペでいけましたが、1つだけ気をつける点がありました。
コードを修正してファイルを保存した後に、ウェブアプリケーションの更新が必要でした。
さらにプロジェクト バージョンをNewにして更新しないと反映されないっぽいです
これでLINEとつながりました。
Screen Shot 2019-01-14 at 14.04.08.png

感想

  • HTML・CSS、Python、JavaScriptの基礎が分かれば一応動くようになると思います。あとはググれば大丈夫です。
  • API連携の基礎的な部分が分かった
  • LINEのbotの作成方法が分かった
  • URLで判定するのは微妙なので画像でできるようになればいいと思った。(誰かやってた気がする。。)
  • 誰も見つからない時が多く、もどかしい(学習の数か?)
  • これを応用して何か作れたらと思います。

参考にさせて頂いたサイト

6
6
0

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
6
6