라즈파이와 Azure의 FaceAPI로 아기의 표정을 읽어 보았습니다.

소개



요 전날, 우리 집에 아이가 태어났기 때문에, 지켜보기 위한 베이비 카메라를 라즈파이로 만들어 보려고 했습니다.
단지 지켜볼 뿐만 아니라, Azure의 FaceAPI를 사용하여 아기의 표정을 읽을 수 있다면 말할 수 없는 아기의 기분을 읽을 수 있을까 생각하고, FaceAPI의 결과로부터 아기의 기분을 LINE 통지하는 장치를 만들어 보았습니다.

최종적으로는, 쓰러져 아기에 부딪치면 위험하고 베이비 카메라를 둘 정도로 집은 넓지 않았기 때문에 정리했습니다만, 모처럼이므로 소개만 하고 싶습니다.

장비 개요



전체 구성



집에서 사용하는 장치이므로 통신은 wifi를 사용하고 있습니다.
정기적으로 사진을 촬영하여 FaceAPI의 결과와 온습도에 따른 LINE 통지를 해줍니다.
또, 좋은 표정이 잡히면 Googledrive에 이미지를 축적하도록 하고 있습니다.


처리 개요



처리의 흐름은 이하와 같이 되어 있어 이것을 5분 주기로 실시하고 있습니다.
  • 사진 촬영
  • 촬영한 사진을 FaceAPI로 해석
  • "HAPPINESS (행복)"사진을 찍을 때 Google 드라이브에 사진을 전송
  • 분석 결과의 변화가있을 때 LINE 통지

  • 모든 것을 소개하는 것은 힘들기 때문에, FaceAPI로 해석하는 처리와, 해석 결과에 응한 LINE 통지하는 처리에 대해 소개합니다.

    FaceAPI로 분석하는 처리



    FaceAPI를 사용하려면 Azure 계정을 만들고 미리 KEY와 ENDPOINT를 얻고 라즈파이에 패키지를 설치해야합니다.
    detect_with_stream()을 실행하면 이미지 분석 결과(emotion_dict)가 {'anger': 0.0, 'contempt': 0.0, 'disgust': 0.0, 'fear': 0.0, 'happiness': 1.0, 'neutral': 0.0, 'sadness': 0.0, 'surprise': 0.0} 의 형태로 취득할 수 있으므로, 그 정보를 소트 해, 값이 가장 큰 감정을 반환값으로 돌려줍니다.
    def emotion_check(filename):
    
        from azure.cognitiveservices.vision.face import FaceClient
        from msrest.authentication import CognitiveServicesCredentials
    
        emotion = EMOTION_NONE
        KEY = "XXXXXXXXXXXXXXXXXXXXX"
        ENDPOINT = "https://XXXXXXXXXXXXXXXXXXX.azure.com/"
    
        #Azureのアカウントに応じたKEYとENDPOINTを設定する
        face_client = FaceClient(ENDPOINT, CognitiveServicesCredentials(KEY))
    
        #感情(emotion)を返すようにAPIを実行
        filepath = '/var/local/photo/' + filename
        img = open(filepath, 'rb')
        params = ['age','emotion']
        detected_faces = face_client.face.detect_with_stream(img, return_face_attributes = params)
    
        if not detected_faces:
            print("face not detect")
        else:
            emotion_dict = detected_faces[0].as_dict()['face_attributes']['emotion']
            emotion_sort = sorted(emotion_dict.items(), key=lambda x:x[1], reverse=True)
    
            if emotion_sort[0][0] == "anger":
                emotion = EMOTION_ANGER
            elif emotion_sort[0][0] == "contempt":
                emotion = EMOTION_CONTEMPT
            elif emotion_sort[0][0] == "disgust":
                emotion = EMOTION_DISGUST
            elif emotion_sort[0][0] == "fear":
                emotion = EMOTION_FEAR
            elif emotion_sort[0][0] == "happiness":
                emotion = EMOTION_HAPPINESS
            elif emotion_sort[0][0] == "neutral":
                emotion = EMOTION_NEUTRUL
            elif emotion_sort[0][0] == "sadness":
                emotion = EMOTION_SADNESS
            elif emotion_sort[0][0] == "surrise":
                emotion = EMOTION_SURPRISE
    
        return emotion
    

    해석 결과에 따른 LINE 통지 처리



    인수로 받은 감정과 온습도 정보에 따라 메시지를 보냅니다.
    온도는 27도 이하로 하는 것이 좋다고, 병아리 클럽에 써 있었으므로, 27도를 임계치로 하고 있습니다.
    FaceAPI로 인식할 수 있는 감정이 「anger(분노),contempt(경멸),disgust(혐오),fear(공포),happiness(행복),neutral(평상),sadness(슬픔),surprise(놀람)」이므로, 각각 에 대해 같은 문자열을 할당하고, LINE 메시지입니다.
    소스에 작성된 file_id_get()은 GoogleDrive에서 파일 ID를 얻기 위해 만든 고유한 함수입니다.
    또한 now_env_get()은 온습도를 얻기 위해 만든 독특한 함수입니다. 참고로 하는 경우는 주의해 주세요.
    def line_send(emotion):
        from linebot import LineBotApi
        from linebot.models import TextSendMessage
    
        #赤ちゃんラインのアクセストークン
        LINE_CHANNEL_ACCESS_TOKEN = "XXXXXXXXXXXXXXXXX"
        line_bot_api = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
    
        if emotion == EMOTION_NONE:
            message = "顔を見つけてないよ。ちゃんと映るように角度を変えてね。"
        elif emotion == EMOTION_HAPPINESS:
            #対象のファイルのパスを取得
            file_id = file_id_get("beby_camera")
            message = "楽しい写真が取れたよ。見てみてね。 https://drive.google.com/file/d/" + file_id
        elif emotion == EMOTION_ANGER:
            message = "機嫌が悪いよ。なんでだかわかる?"
        elif emotion == EMOTION_CONTEMPT:
            message = "もっと遊んでほしいよ。"
        elif emotion == EMOTION_DISGUST:
            message = "嫌な気持ちだよ。なんでだかわかる?"
        elif emotion == EMOTION_FEAR:
            message = "怖い気持ちだよ。なんでだかわかる?"
        elif emotion == EMOTION_NEUTRUL:
            message = "ぼーっとしてるんだ。"
        elif emotion == EMOTION_SADNESS:
            message = "悲しい気持ちだよ。なんでだかわかる?"
        elif emotion == EMOTION_SURPRISE:
            message = "びっくりしてるよ。もっと色んな事を教えてね。"
    
        #温湿度もチェック
        temp,humi = now_env_get()
        if int(temp) > 27:
            message = message + "暑いから何とかしてよ~(温度" + temp + "C,湿度" + humi + "%)"
        else:
            message = message + "(温度" + temp + "C,湿度" + humi + "%)"
    
        #コマンドの実行結果を送信
        messages = TextSendMessage(text=message)
        line_bot_api.broadcast(messages)
    

    ※ 방금 태어난 아기는 평상이 많기 때문에, 스스로 여러가지 시험했습니다.


    결론



    클라우드 서비스가 유행하고 있기 때문에 사용하고 싶다고 생각했습니다만, 솔직히, 개인으로 사용하는 용도가 별로 없도록 느꼈습니다.
    Azure의 FaceAPI와 같은 서비스라면, 그다지 사용하지 않는 한 무료로 사용할 수 있을 것 같기 때문에, 개인이라도 조금 놀 수 있을까라고 생각했습니다.
    고정이 확실히 할 수 있으면 편리할지도 모릅니다만, 싹돗거나 기저귀 교환하거나 하고 있으면 조금 방해인 때도 있기 때문에, 잠시는 자력으로 표정을 읽어내기로 하고 있습니다.

    좋은 웹페이지 즐겨찾기