質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.58%

Raspberry piでのemoji-unicornhathdでDrawEmotion関連のエラーが出てしまう(FACE API)

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 336

maru19

score 5

前提・実現したいこと

Raspberry piをFACE APIを使用してemoji-unicornhathdの動作を試みています。

emoji-unicornhathd
github

上記を参考にしながら動作を試みたのですが、
数年前とFACE APIの内容が変わっておりうまく動作しません。

発生している問題・エラーメッセージ

pi@raspberrypi:~ $ python /home/pi/emoji-unicornhathd/emoji-unicornhathd-stream.py
unicorn hat hd detected
Unicorn HAT HD: Emoji

Press Ctrl+C to exit!


captured!
face rectangle
[]
.
.
.
.
.
captured!
face rectangle
[[224 130 172 172]]
[{"faceId":"c5ed71c5-706a-4f25-b408-75189dd0f58a","faceRectangle":{"top":144,"left":223,"width":172,"height":172}}]
Traceback (most recent call last):
  File "/home/pi/emoji-unicornhathd/emoji-unicornhathd-stream.py", line 123, in <module>
    drawEmotion(data)
  File "/home/pi/emoji-unicornhathd/emoji-unicornhathd-stream.py", line 64, in drawEmotion
    f_rec  =  face['scores']
KeyError: 'scores'


「/face/v1.0/detect?」を「/face/v1.0/detect?returnFaceAttributes=emotions」に変更した場合

pi@raspberrypi:~ $ python /home/pi/emoji-unicornhathd/emoji-unicornhathd-stream.py
unicorn hat hd detected
Unicorn HAT HD: Emoji

Press Ctrl+C to exit!
.
.
.
.
captured!
face rectangle
[[250 106 225 225]]
{"error":{"code":"BadArgument","message":"Invalid argument returnFaceAttributes."}}
Traceback (most recent call last):
  File "/home/pi/emoji-unicornhathd/emoji-unicornhathd-stream.py", line 126, in <module>
    drawEmotion(data)
  File "/home/pi/emoji-unicornhathd/emoji-unicornhathd-stream.py", line 77, in drawEmotion
    f_rec  =  face['scores']
TypeError: string indices must be integers


リクエストURLを私のエンドポイントにした場合
conn = httplib.HTTPSConnection('私の名前.cognitiveservices.azure.com')

captured!
face rectangle
[[442 327  76  76]]
[Errno -3] Temporary failure in name resolution

None
Traceback (most recent call last):
  File "/home/pi/emoji-unicornhathd/emoji-unicornhathd-stream.py", line 127, in <module>
    drawEmotion(data)
  File "/home/pi/emoji-unicornhathd/emoji-unicornhathd-stream.py", line 76, in drawEmotion
    data = json.loads(data)
  File "/usr/lib/python2.7/json/__init__.py", line 339, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python2.7/json/decoder.py", line 364, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
TypeError: expected string or buffer

リクエストURLをconn = httplib.HTTPSConnection('japaneast.api.cognitive.microsoft.com')にした場合

captured!
face rectangle
[[212 106 220 220]
 [544 392  46  46]]
{"error":{"code":"BadArgument","message":"Invalid argument returnFaceAttributes."}}
Traceback (most recent call last):
  File "/home/pi/emoji-unicornhathd/emoji-unicornhathd-stream.py", line 127, in <module>
    drawEmotion(data)
  File "/home/pi/emoji-unicornhathd/emoji-unicornhathd-stream.py", line 78, in drawEmotion
    f_rec  =  face['scores']
TypeError: string indices must be integers


conn.request("POST", "/face/v1.0/detect?returnFaceAttributes=emotions", image, headers)のemotionに書き直した場合

captured!
face rectangle
[[174 170 240 240]]
[{"faceId":"222cb191-eac7-4f4d-bd12-85804a4f06ae","faceRectangle":{"top":186,"left":182,"width":237,"height":237},"faceAttributes":{"emotion":{"anger":0.0,"contempt":0.0,"disgust":0.0,"fear":0.0,"happiness":0.0,"neutral":0.956,"sadness":0.043,"surprise":0.0}}}]
Traceback (most recent call last):
  File "/home/pi/emoji-unicornhathd/emoji-unicornhathd-stream.py", line 127, in <module>
    drawEmotion(data)
  File "/home/pi/emoji-unicornhathd/emoji-unicornhathd-stream.py", line 78, in drawEmotion
    f_rec  =  face['scores']
KeyError: 'scores'


キャプチャした表情の感情はフィードバックされるものの、
最終的に達成したいRaspberry PiのHATに感情に適した絵文字を表示させることができない。

使用しているコード

emoji-unicornhathd/emoji-unicornhathd-stream.py
を使用しています。

# -*- encoding:utf-8 -*-

import io
import time
import picamera
import cv2
import numpy as np
import httplib
import json
import ssl
ssl._create_default_https_context = ssl._create_unverified_context


try:
    import unicornhathd
    print("unicorn hat hd detected")
except ImportError:
    from unicorn_hat_sim import unicornhathd

print("""Unicorn HAT HD: Emoji

Press Ctrl+C to exit!

""")

unicornhathd.rotation(0)

# Azure API Key
# ここを変更してください!
api_key = 'ここは個人のKey入力しています。'

# CV2
cascade_path = "/usr/share/opencv/haarcascades/haarcascade_frontalface_alt.xml"

# Image Size
camera_width = 640
camera_height = 480

#####
def emoji_show(emoji):
    R = np.load('/home/pi/emoji-unicornhathd/rgb/' + emoji + '_R.npy')
    G = np.load('/home/pi/emoji-unicornhathd/rgb/' + emoji + '_G.npy')
    B = np.load('/home/pi/emoji-unicornhathd/rgb/' + emoji + '_B.npy')
    for x in range(0, 16):
        for y in range(0, 16):
            unicornhathd.set_pixel(x, y, R[x][y], G[x][y], B[x][y])
    unicornhathd.show()

def getEmotion(image, headers):
    try:
        conn = httplib.HTTPSConnection('japaneast.api.cognitive.microsoft.com')
        conn.request("POST", "/face/v1.0/detect?", image, headers)
        response = conn.getresponse()
        data = response.read()
        conn.close()
        return data
    except Exception as e:
        print("[Errno {0}] {1}".format(e.errno, e.strerror))
        print(e.message)

def drawEmotion(data):
    data = json.loads(data)
    for face in data:
        f_rec  =  face['scores']
        f_rec = sorted(f_rec.items(), key=lambda x:x[1],reverse = True)
        emo = f_rec[0][0]

        emoji_show(emo)


#####


try:
    while True:
        # Create the in-memory stream
        stream = io.BytesIO()
        emoji_show('camera')
        with picamera.PiCamera() as camera:
            camera.resolution = (camera_width, camera_height)
            camera.capture(stream, format='jpeg')
        print "captured!"
        emoji_show('camera-with-flash')
        time.sleep(0.5)
        emoji_show('camera')

        # Construct a numpy array from the stream
        data = np.fromstring(stream.getvalue(), dtype=np.uint8)
        # "Decode" the image from the array, preserving colour
        image = cv2.imdecode(data, 1)

        # Detect face
        image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        cascade = cv2.CascadeClassifier(cascade_path)
        facerect = cascade.detectMultiScale(image_gray, scaleFactor=1.1, minNeighbors=1, minSize=(1, 1))

        emoji_show('hourglass')

        print "face rectangle"
        print facerect

        if len(facerect) > 0:
            save_file_name = "face_detect.jpg"

            cv2.imwrite(save_file_name, image)

            headers = {
                'Content-Type': 'application/octet-stream',
                'Ocp-Apim-Subscription-Key': api_key,
            }
            image_load = open(save_file_name, 'rb')
            data = getEmotion(image_load, headers)
            print data

            drawEmotion(data)

        else:
            emoji_show('no-face')

        time.sleep(1)
        print "."
        time.sleep(1)
        print "."
        time.sleep(1)
        print "."
        time.sleep(1)
        print "."
        time.sleep(1)
        print "."

except KeyboardInterrupt:
    unicornhathd.off()

試したこと

数年前とFACE API関連が変わっておりそこを修正しました。
また自分の環境に応じてパスを加えております。
しかし、カメラやUnicorn HAT HDは動作するものの表情を認識し、
HATにフィードバックする際にエラーが起きます。
いろいろ試しては見ましたがどうも、
「def drawEmotion(data)」「f_rec  =  face['scores']」辺りでエラーが発生します。
解決法方法などあればご教授お願いします。

補足情報(FW/ツールのバージョンなど)

・Raspberry Pi 3B+
Description:    Raspbian GNU/Linux 10 (buster)
Release:    10
Codename:    buster

・Raspberry Pi カメラモジュール V2
・Unicorn HAT HD

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • vanderlvov

    2019/12/11 19:36

    Urlをマークダウン形式に修正してください: [title](url)

    キャンセル

  • maru19

    2019/12/11 19:42

    申し訳ございません。
    修正致しました。

    キャンセル

回答 2

checkベストアンサー

0

さらに調べてみて、
https://www.indetail.co.jp/blog/12502/
にはソースがありました。
まず、apiは違うでしょう:

        conn = httplib.HTTPSConnection('api.projectoxford.ai')
        conn.request("POST", "/emotion/v1.0/recognize?", image, headers)


しかし、APIは違うけど、レスポンスは似ているでしょう。
http://martink.me/articles/using-the-project-oxford-emotion-api
scoresの代わりに

 f_rec  =  face['scores']


ではなくて

 f_rec  =  face['faceAttributes']['emotions']


で同じのデータを取得できるはずです!

APIを正しく使ってみてください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/12/13 23:33

    ありがとうございます!
    遂に動作が可能となりました!
    Pythonを使い始めて1ヵ月ほどでずっと悩み続けていましたが、
    あなたのおかげで動作することが可能となりうれしい限りです。
    ここでは感謝しきれないほどです。
    ご多忙にもかかわらず、何度も対応していただきありがとうございます。

    キャンセル

  • 2019/12/13 23:47

    おめでとうございます!嬉しいです。

    キャンセル

0

Face API公式ドキュメント によると、レスポンスオブジェクトは結構変わったようです。

解決方法:

  1. まず、エラーメッセージを見るとemotionsのデーターを取得してないと分かりました。
  2. 取得できるはずけど、取得してない原因は、APIの使い方が適切ではないでしょうね :)。このドキュメント「FACE API Detectについて」を見ると、リクエストはreturnFaceAttributesのパラメタが必要だと分かります。
    /face/v1.0/detect?/face/v1.0/detect?returnFaceAttributes=emotionsにしてみてください。
    レスポンスが変わるはずですよね。同じのドキュメントの中で、レスポンスオブジェクトの事例があります。
    こうなるはずだと思います:
[
    {
        "faceId": "c5c24a82-6845-4031-9d5d-978df9175426",
        "recognitionModel": "recognition_02",
        "faceAttributes": {
            "emotion": {
                "anger": 0.575,
                "contempt": 0,
                "disgust": 0.006,
                "fear": 0.008,
                "happiness": 0.394,
                "neutral": 0.013,
                "sadness": 0,
                "surprise": 0.004
            }
        }
    }
]

このレスポンス

[{"faceId":"222cb191-eac7-4f4d-bd12-85804a4f06ae","faceRectangle":{"top":186,"left":182,"width":237,"height":237},"faceAttributes":{"emotion":{"anger":0.0,"contempt":0.0,"disgust":0.0,"fear":0.0,"happiness":0.0,"neutral":0.956,"sadness":0.043,"surprise":0.0}}}]


には

{"emotion":{"anger":0.0,"contempt":0.0,"disgust":0.0,"fear":0.0,"happiness":0.0,"neutral":0.956,"sadness":0.043,"surprise":0.0}


それを使ってみてください。scoresはレスポンスにないので!

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/12/13 00:44

    リクエストのURLはどうなっていますか?

    キャンセル

  • 2019/12/13 14:38

    ご返信ありがとうございます。

    リクエストURLを私のエンドポイントにした場合と、
    東日本の場合のリクエストURLをエラーコードに追加しました。
    お忙しいところ恐縮ですが、ご教授いただければ幸いです。

    キャンセル

  • 2019/12/13 14:54

    何度も申し訳ございません。
    conn.request("POST", "/face/v1.0/detect?returnFaceAttributes=emotions", image, headers)
    をemotionと書き直したところ、感情は帰ってきたのですがやはり
    Raspberry PiのHATに感情に適した絵文字を表示させることはできませんでした。砂時計の絵文字で止まってしまいます。
    その時のエラーコードも追加しておきます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.58%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る