TakwayBoard/takway/emo_utils.py

176 lines
7.4 KiB
Python
Raw Normal View History

2024-05-23 01:27:51 +08:00
import time
import av
import os
import copy
import random
import numpy as np
try:
from maix import display, image
print("import maix success.")
except:
import cv2
print("import cv2 success.")
class EmoVideoPlayer:
def __init__(self, player='maixsense', emo_dir='ResizedEmoji'):
assert player in ['maixsense', 'opencv'], "player must be'maixsense' or 'opencv'"
self.player = player
self.emo_list = ['兴奋', '愤怒', '静态', '不屑', '惊恐', '难过']
self.emo_init(emo_dir)
def emo_init(self, emo_dir):
# 将此路径替换为Emoji文件夹的实际路径
self.emo_av_dict = self.get_emo_av(emo_dir)
self.emo_time_dict = {
'兴奋': 0.00,
'愤怒': 0.01,
'静态': 0.01,
'不屑': 0.01,
'惊恐': 0.01,
'难过': 0.01,
}
def get_emo_av(self, emo_dir):
emo_av_dict = {emo: dict() for emo in self.emo_list}
for emo in self.emo_list:
emo_path = os.path.join(emo_dir, emo)
for file in os.listdir(emo_path):
if not os.path.isfile(os.path.join(emo_path, file)):
continue
av_container = av.open(os.path.join(emo_path, file))
if emo == '静态':
if "单次眨眼偶发" in file:
emo_av_dict[emo]['seldom_wink'] = av_container
if "快速双眨眼偶发" in file:
emo_av_dict[emo]['quick_wink'] = av_container
else:
if "进入姿势" in file:
emo_av_dict[emo]['start'] = av_container
elif "可循环动作" in file:
emo_av_dict[emo]['loop'] = av_container
elif "回正" in file:
emo_av_dict[emo]['end'] = av_container
self.av_info = emo_av_dict[emo]['loop'].streams.video[0]
return emo_av_dict
def get_emo_frames(self, emo_dir):
emo_av_dict = {emo: dict() for emo in self.emo_list}
for emo in self.emo_list:
emo_path = os.path.join(emo_dir, emo)
for file in os.listdir(emo_path):
if not os.path.isfile(os.path.join(emo_path, file)):
continue
av_container = av.open(os.path.join(emo_path, file))
frame_list = []
av_info = av_container.streams.video[0]
for frame in av_container.decode(video=0):
if self.player =='maixsense':
img = image.load(bytes(frame.to_rgb().planes[0]), (av_info.width, av_info.height))
elif self.player == 'opencv':
img = cv2.cvtColor(numpy.array(frame.to_image()), cv2.COLOR_RGB2BGR)
frame_list.append(img)
# add to dict
if emo == '静态':
if "单次眨眼偶发" in file:
emo_av_dict[emo]['seldom_wink'] = frame_list
if "快速双眨眼偶发" in file:
emo_av_dict[emo]['quick_wink'] = frame_list
else:
if "进入姿势" in file:
emo_av_dict[emo]['start'] = frame_list
elif "可循环动作" in file:
emo_av_dict[emo]['loop'] = frame_list
elif "回正" in file:
emo_av_dict[emo]['end'] = frame_list
return emo_av_dict
def display_emo_frame(self, emo_name, stage='default'):
emo_frame_list = self.emo_av_dict[emo_name][stage]
emo_time = self.emo_time_dict[emo_name]
for img in emo_frame_list:
if self.player =='maixsense':
display.show(img)
elif self.player == 'opencv':
cv2.imshow("video", img)
cv2.waitKey(1) # 你可能需要根据视频的帧率调整这个延时
time.sleep(emo_time)
def display_emo(self, emo_name, stage='default'):
if self.player =='maixsense':
self.display_emo_maixsense(emo_name, stage)
elif self.player == 'opencv':
self.display_emo_opencv(emo_name, stage)
def display_emo_maixsense(self, emo_name, stage):
emo_container = self.emo_av_dict[emo_name][stage]
emo_time = self.emo_time_dict[emo_name]
for frame in emo_container.decode(video=0):
img = image.load(bytes(frame.to_rgb().planes[0]), (self.av_info.width, self.av_info.height))
display.show(img)
time.sleep(emo_time)
emo_container.seek(0) # 重置视频的读取位置
def display_emo_opencv(self, emo_name, stage='default'):
import cv2
import numpy
if stage == 'default':
if emo_name == '静态':
stage = 'quick_wink'
else:
stage = 'loop'
emo_container = self.emo_av_dict[emo_name][stage]
emo_time = self.emo_time_dict[emo_name]
for frame in emo_container.decode(video=0):
img = cv2.cvtColor(numpy.array(frame.to_image()), cv2.COLOR_RGB2BGR)
cv2.imshow("video", img)
time.sleep(emo_time)
cv2.waitKey(1) # 你可能需要根据视频的帧率调整这个延时
cv2.destroyAllWindows()
emo_container.seek(0) # 重置视频的读取位置
def get_emo_status(self, answer):
# `兴奋`, `愤怒`, `静态`, `不屑`, `惊 恐`, `难过`
if any([emo in answer for emo in self.emo_list]):
# 找出是answer中出现了哪个emo
emo_status = [emo for emo in self.emo_list if emo in answer][0]
print(f"emo_status: {emo_status}")
else:
emo_status = '静态'
return emo_status
def random_wink(self):
seed = random.randrange(0, 1000)
if seed < 100:
self.display_emo(emo_name='静态', stage='seldom_wink')
# print("random wink")
if __name__ == '__main__':
emo = EmoVideoPlayer()
# emo.display_emo_opencv(emo_name='兴奋', stage='start')
# emo.display_emo_opencv(emo_name='兴奋', stage='loop')
# emo.display_emo_opencv(emo_name='兴奋', stage='loop')
# emo.display_emo_opencv(emo_name='兴奋', stage='loop')
# emo.display_emo_opencv(emo_name='兴奋', stage='end')
emo.display_emo_opencv(emo_name='静态', stage='seldom_wink')
emo.display_emo_opencv(emo_name='静态', stage='quick_wink')
# emo.display_emo_opencv(emo_name='愤怒', stage='start')
# emo.display_emo_opencv(emo_name='愤怒', stage='loop')
# emo.display_emo_opencv(emo_name='愤怒', stage='end')
# emo.display_emo_opencv(emo_name='静态', stage='seldom_wink')
# emo.display_emo_opencv(emo_name='静态', stage='quick_wink')
# emo.display_emo_opencv(emo_name='不屑', stage='start')
# emo.display_emo_opencv(emo_name='不屑', stage='loop')
# emo.display_emo_opencv(emo_name='不屑', stage='end')
# emo.display_emo_opencv(emo_name='惊恐', stage='start')
# emo.display_emo_opencv(emo_name='惊恐', stage='loop')
# emo.display_emo_opencv(emo_name='惊恐', stage='end')
# emo.display_emo_opencv(emo_name='难过', stage='start')
# emo.display_emo_opencv(emo_name='难过', stage='loop')
# emo.display_emo_opencv(emo_name='难过', stage='end')