-
导入必要的库和模型文件:
- 导入了OpenCV、Keras模型加载相关库,以及自定义的工具函数和预处理函数。
- 指定了情绪识别模型路径、情绪标签列表、是否使用灰度图像、人脸检测模型路径等。
-
定义函数 detect_emotion(image):
- 从输入的图像中检测人脸。
- 针对每张检测到的人脸:
- 根据人脸位置应用偏移量,提取人脸图像并进行预处理(缩放、拓展维度等)。
- 使用情绪识别模型对人脸图像进行情绪预测。
- 根据预测结果确定情绪标签,并根据不同情绪选择不同的颜色。
- 在原始图像上绘制人脸边界框和情绪标签。
-
定义函数 show_image(window_name, image):
- 调用 detect_emotion(image) 处理传入的图像,并在图像上显示实时的情绪分析结果。
- 计算并显示处理速度(FPS)。
-
定义函数 catch_camera(window_name, camera_idx):
- 创建窗口并打开指定摄像头。
- 在循环中读取摄像头帧画面,调用 show_image(window_name, frame) 处理每一帧图像,并显示实时结果。
- 当按下 'q' 键或关闭窗口时退出循环,释放摄像头资源并关闭窗口。
-
主程序入口:
- 如果直接运行该代码文件,则会调用 catch_camera("表情识别", 0),打开摄像头并展示实时的情绪识别结果。
总体思路是通过人脸检测模型检测人脸位置,然后利用情绪识别模型对人脸进行情绪识别,并将识别结果实时绘制在图像上展示给用户。整个流程涵盖了图像处理、模型推断和实时展示等方面,为用户提供了一个简单但有趣的表情识别应用。
主程序代码:
import cv2
from keras.models import load_model
import numpy as np
from utils.inference import detect_faces
from utils.inference import draw_text, draw_text_lines
from utils.inference import draw_bounding_box
from utils.inference import apply_offsets
from utils.preprocessor import process_img
import time
emotion_model_path = '../trained_models/emotion_models/VGG16_Dense_RAF_20190714.h5' # 选择模型
emotion_labels = ['Surprise', 'Fear', 'Disgust', 'Happy', 'Sad', 'Angry', 'Neutral']
isgray = False
detection_model_path = '../trained_models/detection_models/haarcascade_frontalface_default.xml'
face_detection = cv2.CascadeClassifier(detection_model_path)
emotion_classifier = load_model(emotion_model_path, compile=True)
emotion_target_size = emotion_classifier.input_shape[1:3]
def detect_emotion(image):
bgr_image = image
if isgray:
gray_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2GRAY)
gray_image = np.squeeze(gray_image)
gray_image = gray_image.astype('uint8')
image_origin = gray_image
else:
rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB)
rgb_image = np.squeeze(rgb_image).astype('uint8')
image_origin = rgb_image
emotion_offsets = (0, 0)
faces = detect_faces(face_detection, image_origin)
if len(faces) > 0:
for face in faces:
x1, x2, y1, y2 = apply_offsets(face, emotion_offsets)
face_image = image_origin[y1:y2, x1:x2]
face_image = cv2.resize(face_image, emotion_target_size)
face_image = process_img(face_image)
face_image = np.expand_dims(face_image, 0)
if isgray:
face_image = np.expand_dims(face_image, -1)
emotion_texts = []
emotion_prediction = emotion_classifier.predict(face_image)[0]
max_emotion_probability = np.max(emotion_prediction)
emotion_labels_arg = np.argsort(-emotion_prediction)
max_emotion_text = emotion_labels[int(emotion_labels_arg[0])]
for emotion_label_arg in emotion_labels_arg:
emotion_texts.append(emotion_labels[int(emotion_label_arg)] + ' '
+ str('%.2f' % emotion_prediction[int(emotion_label_arg)]))
if max_emotion_text == 'Angry':
color = max_emotion_probability * np.asarray((255, 0, 0))
elif max_emotion_text == 'Sad':
color = max_emotion_probability * np.asarray((0, 0, 255))
elif max_emotion_text == 'Happy':
color = max_emotion_probability * np.asarray((255, 255, 0))
elif max_emotion_text == 'Surprise':
color = max_emotion_probability * np.asarray((0, 255, 255))
else:
color = max_emotion_probability * np.asarray((0, 255, 0))
color = color.astype(int)
color = color.tolist()
draw_bounding_box(face, bgr_image, color)
# draw_text(face, rgb_image, max_emotion_text, color, 0, -50, 1, 2)
draw_text_lines(face, bgr_image, emotion_texts, (255, 255, 255), 0, -50, 0.5, 1)
return bgr_image
def show_image(window_name, image):
start = time.time()
image = detect_emotion(image)
fps = 1. / (time.time() - start)
draw_text((10, 30), image, "FPS:" + str(int(fps)), (0, 0, 255))
cv2.imshow(window_name, image)
def catch_camera(window_name, camera_idx):
cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
cap = cv2.VideoCapture(camera_idx)
while cap.isOpened():
ok, frame = cap.read() # 读取一帧数据
if not ok:
break
show_image(window_name, frame)
c = cv2.waitKey(10)
if c & 0xFF == ord('q') or c & 0xFF == ord('Q'):
break
if cv2.getWindowProperty(window_name, cv2.WND_PROP_VISIBLE) < 1:
break
# 释放摄像头并销毁所有窗口
cap.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
catch_camera("表情识别", 0)
需要工具函数和模型权重私信我。