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

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

ただいまの
回答率

89.10%

表情認識AIで、動画内の表情を0.1秒刻みで解析したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 106

YYJP

score 9

前提・実現したいこと

下記サイトのプログラムにおける、
real_time_video.pyにのみ修正を加え、
動画における表情推移を計測するコードを作成しました。
https://github.com/omar178/Emotion-recognition

再生されている動画に対し、
0.1秒刻みで解析処理を行う(print(preds, file=f)を出力する)には、
コードをどのように改変すれば良いでしょうか?

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

time(0.1)と追記したところ、
動画の再生自体も0.1秒刻みになってしまい、
print(preds, file=f)での出力値は、
time(0.1)追記前と変わりませんでした。

どうしたら、
自然な速度で再生されている動画に対して、
0.1秒刻みでprint(preds, file=f)
を出力することができるようになるでしょうか?

下記見づらいコードですが、
何卒、よろしくお願いいたします。

該当のソースコード

from keras.preprocessing.image import img_to_array
import imutils
import cv2
from keras.models import load_model
import numpy as np
import time
###
import os

filename = "MMM"
filenameMP4 = filename + ".mp4"
filenameTXT = filename + ".txt"
print(filenameTXT)
###

# parameters for loading data and images
detection_model_path = 'haarcascade_files/haarcascade_frontalface_default.xml'
emotion_model_path = 'models/_mini_XCEPTION.102-0.66.hdf5'

# hyper-parameters for bounding boxes shape
# loading models
face_detection = cv2.CascadeClassifier(detection_model_path)
emotion_classifier = load_model(emotion_model_path, compile=False)
EMOTIONS = ["angry" ,"disgust","scared", "happy", "sad", "surprised",
 "neutral"]


#feelings_faces = []
#for index, emotion in enumerate(EMOTIONS):
   # feelings_faces.append(cv2.imread('emojis/' + emotion + '.png', -1))

# starting video streaming
cv2.namedWindow('your_face')
camera = cv2.VideoCapture(r'C:\Users\yukak\OneDrive\experiment_videos\Mari_Elka_Pangestu_M.mp4')

while True:
    frame = camera.read()[1]
    #reading the frame
    frame = imutils.resize(frame,width=300)
    ####
    prev_time = time.time()
    while True:
        curr_time = time.time()
        if curr_time - prev_time >= 0.1:

            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            faces = face_detection.detectMultiScale(gray,scaleFactor=1.1,minNeighbors=5,minSize=(30,30),flags=cv2.CASCADE_SCALE_IMAGE)

            canvas = np.zeros((250, 300, 3), dtype="uint8")
            frameClone = frame.copy()
            if len(faces) > 0:
                faces = sorted(faces, reverse=True,
                key=lambda x: (x[2] - x[0]) * (x[3] - x[1]))[0]
                (fX, fY, fW, fH) = faces
                            # Extract the ROI of the face from the grayscale image, resize it to a fixed 28x28 pixels, and then prepare
                    # the ROI for classification via the CNN
                roi = gray[fY:fY + fH, fX:fX + fW]
                roi = cv2.resize(roi, (64, 64))
                roi = roi.astype("float") / 255.0
                roi = img_to_array(roi)
                roi = np.expand_dims(roi, axis=0)


                preds = emotion_classifier.predict(roi)[0]
                with open(filenameTXT, 'a') as f:
                #print(preds)
                    print(preds, file=f)
                emotion_probability = np.max(preds)
                label = EMOTIONS[preds.argmax()]
                ###
                time.sleep(1)
                ###
            else: continue


            for (i, (emotion, prob)) in enumerate(zip(EMOTIONS, preds)):
                        # construct the label text
                        text = "{}: {:.2f}%".format(emotion, prob * 100)

                        # draw the label + probability bar on the canvas
                       # emoji_face = feelings_faces[np.argmax(preds)]


                        w = int(prob * 300)
                        cv2.rectangle(canvas, (7, (i * 35) + 5),
                        (w, (i * 35) + 35), (0, 0, 255), -1)
                        cv2.putText(canvas, text, (10, (i * 35) + 23),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.45,
                        (255, 255, 255), 2)
                        cv2.putText(frameClone, label, (fX, fY - 10),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
                        cv2.rectangle(frameClone, (fX, fY), (fX + fW, fY + fH),
                                      (0, 0, 255), 2)
        #    for c in range(0, 3):
        #        frame[200:320, 10:130, c] = emoji_face[:, :, c] * \
        #        (emoji_face[:, :, 3] / 255.0) + frame[200:320,
        #        10:130, c] * (1.0 - emoji_face[:, :, 3] / 255.0)

        prev_time = curr_time
    ####
    cv2.imshow('your_face', frameClone)
    cv2.imshow("Probabilities", canvas)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

camera.release()
cv2.destroyAllWindows()
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

ループの中で、gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) の行から cv2.imshow('your_face', frameClone)  より1つ前の行が検出処理に該当する部分ですので、この範囲の処理を「前回実行したときから 0.1 秒以上経過していたら実行する」という if 節の中に入れればいいと思います。

import time

prev_time = time.time()
while True:
    curr_time = time.time()
    if curr_time - prev_time >= 0.1:
        # 0.1 秒ごとに実行したい処理
        print(curr_time - prev_time)

        prev_time = curr_time

追記

「前回表情検出を行った時刻から 0.1 秒以上経過しているかどうか」という判定をする処理だったので、以下のように修正していただく意図でした。
動かしての確認はしていません。

from keras.preprocessing.image import img_to_array
import imutils
import cv2
from keras.models import load_model
import numpy as np
import time
###
import os

filename = "MMM"
filenameMP4 = filename + ".mp4"
filenameTXT = filename + ".txt"
print(filenameTXT)
###

# parameters for loading data and images
detection_model_path = 'haarcascade_files/haarcascade_frontalface_default.xml'
emotion_model_path = 'models/_mini_XCEPTION.102-0.66.hdf5'

# hyper-parameters for bounding boxes shape
# loading models
face_detection = cv2.CascadeClassifier(detection_model_path)
emotion_classifier = load_model(emotion_model_path, compile=False)
EMOTIONS = ["angry" ,"disgust","scared", "happy", "sad", "surprised",
 "neutral"]


#feelings_faces = []
#for index, emotion in enumerate(EMOTIONS):
   # feelings_faces.append(cv2.imread('emojis/' + emotion + '.png', -1))

# starting video streaming
cv2.namedWindow('your_face')
camera = cv2.VideoCapture(r'C:\Users\yukak\OneDrive\experiment_videos\Mari_Elka_Pangestu_M.mp4')

prev_time = time.time()
while True:
    frame = camera.read()[1]
    #reading the frame
    frame = imutils.resize(frame,width=300)
    ################################################################
    curr_time = time.time()
    if curr_time - prev_time >= 0.1:
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        faces = face_detection.detectMultiScale(gray,scaleFactor=1.1,minNeighbors=5,minSize=(30,30),flags=cv2.CASCADE_SCALE_IMAGE)

        canvas = np.zeros((250, 300, 3), dtype="uint8")
        frameClone = frame.copy()
        if len(faces) > 0:
            faces = sorted(faces, reverse=True,
            key=lambda x: (x[2] - x[0]) * (x[3] - x[1]))[0]
            (fX, fY, fW, fH) = faces
                        # Extract the ROI of the face from the grayscale image, resize it to a fixed 28x28 pixels, and then prepare
                # the ROI for classification via the CNN
            roi = gray[fY:fY + fH, fX:fX + fW]
            roi = cv2.resize(roi, (64, 64))
            roi = roi.astype("float") / 255.0
            roi = img_to_array(roi)
            roi = np.expand_dims(roi, axis=0)


            preds = emotion_classifier.predict(roi)[0]
            with open(filenameTXT, 'a') as f:
            #print(preds)
                print(preds, file=f)
            emotion_probability = np.max(preds)
            label = EMOTIONS[preds.argmax()]
        else: continue


        for (i, (emotion, prob)) in enumerate(zip(EMOTIONS, preds)):
                    # construct the label text
                    text = "{}: {:.2f}%".format(emotion, prob * 100)

                    # draw the label + probability bar on the canvas
                    # emoji_face = feelings_faces[np.argmax(preds)]


                    w = int(prob * 300)
                    cv2.rectangle(canvas, (7, (i * 35) + 5),
                    (w, (i * 35) + 35), (0, 0, 255), -1)
                    cv2.putText(canvas, text, (10, (i * 35) + 23),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.45,
                    (255, 255, 255), 2)
                    cv2.putText(frameClone, label, (fX, fY - 10),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
                    cv2.rectangle(frameClone, (fX, fY), (fX + fW, fY + fH),
                                    (0, 0, 255), 2)
        prev_time = curr_time
    ##########################################
    cv2.imshow('your_face', frameClone)
    cv2.imshow("Probabilities", canvas)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

camera.release()
cv2.destroyAllWindows()

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/01 10:56

    現在、プログラムは動いていて、動画のみ読み込めない状態です。
    動画の読み込み箇所は追加したif文の外にあるので、影響はないかと思うのですが、
    動画が読み込めない理由としては、どのようなことが考えられそうでしょうか・・・?

    キャンセル

  • 2020/07/01 10:59 編集

    質問欄に記載されているコードでは明らかに動かないです。(while の中に while があるのでそこでループしてしまっている)
    追記したコードでもうまくいかないということでしょうか?

    キャンセル

  • 2020/07/01 11:05 編集

    すみません、追記して頂いた内容の確認ができていませんでした。
    動きました!
    基礎を理解できていなかったので、きちんと勉強できたらと思います。
    何度もご対応頂き、本当にありがとうございました!

    キャンセル

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

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