[streamlit]表情判定アプリを作ろう(クラウドサービス使わない)
はじめに
これまで機械学習などをテーマにstreamlitを試してきましたが、もう少し肩の力を抜いたギミック的なこともしたいなと思い今回は表情判定WEBアプリを作ります。
streamlitで表情解析となると王道となるのはクラウドサービスのAPIを用いるパターンだと思いますが、ここではpy-featと言うライブラリを用いてローカルだけで完結させますので気軽に試せるのではないかなと思います。
参考)py-feat
顔画像を入力すると、"anger", "disgust", "fear", "happiness", "sadness", "surprise", "neutral"といった表情の予測スコアを返すライブラリです。
アプリイメージ
画像のアップロード、PCカメラの撮影どちらでも可能です
カメラを選ぶとPCのカメラが起動します
判定画面(ここ、デザイン全く凝っていません・・・表示するだけ)
実装
Dockerで環境を構築します。おおよその流れは以前の記事の通りです。
今回用いるファイル類はこちらに格納しました。
Dockerfile
ここがいきなりのつまずきポイントでした。プログラム中でOpenCVが用いられている関係でlibgl1-mesa-devのインストールが必要とのことです。
# Dockerfile
FROM python:3
COPY requirements.txt .
RUN pip3 install --upgrade pip && \
pip3 install --no-cache-dir -r requirements.txt && \
apt-get update && apt-get upgrade -y && \
apt-get install -y libgl1-mesa-dev
WORKDIR /src
COPY /src /src
docker-compose.yml
特に工夫はありません
version: '3'
services:
streamlit:
restart: always
build:
context: .
dockerfile: Dockerfile
container_name: streamlit
working_dir: '/src'
tty: true
volumes:
- ./src:/src
ports:
- '8501:8501'
command: streamlit run app.py
app.py
今回はシンプルに感情予測を返すだけにしていますが、py-featは色んなことができますので途中の記述は用途に応じて書き換えてください。
#ライブラリのインポート
import streamlit as st
import pandas as pd
import numpy as np
import cv2
import numpy as np
import pandas as pd
import re
import os
import matplotlib.pyplot as plt
from PIL import Image
#py-featでモデルを構築する。色々いじる余地があるので公式ドキュメント参照
from feat import Detector
face_model = "retinaface"
landmark_model = "mobilenet"
au_model = "svm"
emotion_model = "resmasknet"
detector = Detector(
face_model=face_model,
landmark_model=landmark_model,
au_model=au_model,
emotion_model=emotion_model
)
from feat.utils import get_test_data_path
#本編
st.title("Face emotion app")
#画像アップロードかカメラを選択するようにする。
img_source = st.radio("画像のソースを選択してください。",
("画像をアップロード", "カメラで撮影"))
if img_source == "カメラで撮影":
img_file_buffer = st.camera_input("カメラで撮影")
elif img_source == "画像をアップロード":
img_file_buffer = st.file_uploader("ファイルを選択")
else:
pass
#どちらを選択しても後続の処理は同じ
if img_file_buffer :
img_file_buffer_2 = Image.open(img_file_buffer)
img_file = np.array(img_file_buffer_2)
cv2.imwrite('temporary.jpg', img_file)
#py-featの表情解析結果をデータフレーム形式でimage_predictionとする
image_prediction = detector.detect_image("temporary.jpg")
#感情に関するカラムだけを残す
image_prediction = image_prediction[["anger", "disgust", "fear", "happiness", "sadness", "surprise", "neutral"]]
#感情の最大値を示すデータのカラム名(感情名)をemotionとする
emotion = image_prediction.idxmax(axis = 1)[0]
st.markdown("#### あなたの表情は")
st.markdown("### {}です".format(emotion))
Dockerに環境ができたらブラウザでhttp://localhost:8501
にアクセスするとAppが起動します。
おわりに
以上、streamlitを用いた簡単な表情分析アプリでした。とりあえずの実装を趣旨としたものであり推定精度については言及しませんでしたが、「neutral」と「happiness」はある程度正確に判別できているように思うので、笑顔判定器くらいであれば使えるかと思います。
Discussion