首页 > 其他分享 >表情识别+情感分析+人脸识别(代码+教程)

表情识别+情感分析+人脸识别(代码+教程)

时间:2024-11-09 09:48:15浏览次数:3  
标签:教程 人脸识别 情绪 frame cv2 boxes 识别 size

表情识别

面部情绪识别(FER)是指根据面部表情识别和分类人类情绪的过程。通过分析面部特征和模式,机器可以对一个人的情绪状态作出有根据的推断。这个面部识别的子领域高度跨学科,涉及计算机视觉、机器学习和心理学等领域的知识。

img

添加图片注释,不超过 140 字(可选)

应用领域

以下是一些关键领域,其中这项技术可能有所帮助:

社交和内容创作平台:

根据情感反馈个性化用户体验。 自适应学习系统根据学习者的情绪状态调整内容,提供更具针对性的建议。

医疗研究:

监测患者是否存在抑郁、焦虑或其他情绪障碍的迹象。 协助治疗师在治疗过程中跟踪患者的进展或反应。 实时监测应激水平。

驾驶员安全机制:

监测驾驶员是否出现疲劳、注意力分散、压力或昏昏欲睡的迹象。

营销和市场研究:

实时分析观众对广告的反应。 根据观众的情绪状态定制广告内容。 产品测试和反馈。

安全和监控:

在拥挤区域检测可疑或异常行为。 分析公共事件中人群的反应,以确保安全。

构建面部情绪识别系统

本节深入探讨构建面部情绪识别系统的复杂性。我们首先探讨一个专门为面部情绪识别设计的数据集,确保我们的模型有稳健的基础。接下来,我们将介绍一种自定义的VGG13模型架构,该架构以其在分类任务中的效率和准确性而闻名,并阐明其与我们情绪识别目标的相关性。

最后,我们花费一些时间在实验结果部分,提供全面的评估,阐明系统的性能指标及其潜在应用。

面部情绪识别数据集(FER +)

FER + 数据集是原始面部表情识别(FER)数据集的一个重要扩展。为了改进原始数据集的局限性,FER + 提供了更精细和细致的面部表情标签。虽然原始FER数据集将面部表情分类为六种基本情绪——快乐、悲伤、愤怒、惊讶、恐惧和厌恶——但FER + 根据这一基础更进一步引入了两个额外的类别:中性和蔑视。

img

添加图片注释,不超过 140 字(可选)

用于人脸检测的RFB-320

Single Shot Multibox Detector (SSD)模型 在识别情绪之前,需要在输入帧中检测人脸。为此,使用了超轻量级人脸检测模型RFB-320。它是一种针对边缘计算设备进行优化的创新人脸检测模型。该模型采用了改进的感受野块(RFB)模块,在不增加计算负担的情况下有效地捕捉多尺度的上下文信息。它在多样化的WIDER FACE数据集上进行训练,并针对320×240的输入分辨率进行优化,具有出色的效率平衡,计算速度为0.2106 GFLOPs,参数量仅为0.3004百万个。该模型基于PyTorch框架开发,取得了令人称赞的平均精度(mAP)为84.78%,在资源受限环境中成为高效人脸检测的强大解决方案。在此实现中,RFB-320 SSD模型以Caffe格式使用。

img

添加图片注释,不超过 140 字(可选)

自定义的VGG13模型架构

情绪识别分类模型采用了定制的VGG13架构,专为64×64灰度图像设计。它使用具有最大池化和dropout的卷积层将图像分类为八个情绪类别,以防止过拟合。该架构开始于两个具有64个卷积核的卷积层,然后是最大池化和25%的dropout。额外的卷积层捕捉复杂的特征,两个具有1024个节点的密集层聚合信息,然后是50%的dropout。一个softmax输出层预测情绪类别。

让我们编写一些代码来实现这个系统。

首先,需要初始化一些重要的参数。


image_mean = np.array([127, 127, 127])
image_std = 128.0
iou_threshold = 0.3
center_variance = 0.1
size_variance = 0.2
min_boxes = [
    [10.0, 16.0, 24.0], 
    [32.0, 48.0], 
    [64.0, 96.0], 
    [128.0, 192.0, 256.0]
]
strides = [8.0, 16.0, 32.0, 64.0]
threshold = 0.5

image_mean: 在RGB通道上进行图像归一化的均值。 image_std: 图像归一化的标准差。 iou_threshold: 确定边界框匹配的交并比(IoU)度量的阈值。 center_variance: 预测的边界框中心坐标的缩放因子。 size_variance: 预测的边界框尺寸的缩放因子。 min_boxes: 不同尺寸对象的最小边界框尺寸。 strides: 根据图像大小控制特征图的尺度。 threshold: 目标检测的置信度阈值。


def define_img_size(image_size):
    shrinkage_list = []
    feature_map_w_h_list = []
    for size in image_size:
        feature_map = [int(ceil(size / stride)) for stride in strides]
        feature_map_w_h_list.append(feature_map)
 
    for i in range(0, len(image_size)):
        shrinkage_list.append(strides)
    priors = generate_priors(
        feature_map_w_h_list, shrinkage_list, image_size, min_boxes
    )
    return priors

上述的 define_img_size 函数旨在为目标检测任务生成先验边界框(priors)。该函数以 image_size 参数作为输入,根据提供的图像尺寸和一组预定义的步长值计算特征图的尺寸。这些特征图的尺寸反映了卷积神经网络(CNN)层对不同输入图像尺度的期望输出尺寸。实质上,SSD中的先验边界框提供了一种高效的方法,可以在网络的单次前向传递中同时预测多个边界框及其关联的类别得分,从而实现实时目标检测。

def FER_live_cam():
    emotion_dict = {
        0: 'neutral', 
        1: 'happiness', 
        2: 'surprise', 
        3: 'sadness',
        4: 'anger', 
        5: 'disgust', 
        6: 'fear'
    }
 
    # cap = cv2.VideoCapture('video1.mp4')
    cap = cv2.VideoCapture(0)
 
    frame_width = int(cap.get(3))
    frame_height = int(cap.get(4))
    size = (frame_width, frame_height)
    result = cv2.VideoWriter('result.avi', 
                         cv2.VideoWriter_fourcc(*'MJPG'),
                         10, size)
 
    # Read ONNX model
    model = 'onnx_model.onnx'
    model = cv2.dnn.readNetFromONNX('emotion-ferplus-8.onnx')
     
    # Read the Caffe face detector.
    model_path = 'RFB-320/RFB-320.caffemodel'
    proto_path = 'RFB-320/RFB-320.prototxt'
    net = dnn.readNetFromCaffe(proto_path, model_path)
    input_size = [320, 240]
    width = input_size[0]
    height = input_size[1]
    priors = define_img_size(input_size)
 
    while cap.isOpened():
        ret, frame = cap.read()
        if ret:
            img_ori = frame
            #print("frame size: ", frame.shape)
            rect = cv2.resize(img_ori, (width, height))
            rect = cv2.cvtColor(rect, cv2.COLOR_BGR2RGB)
            net.setInput(dnn.blobFromImage(
                rect, 1 / image_std, (width, height), 127)
            )
            start_time = time.time()
            boxes, scores = net.forward(["boxes", "scores"])
            boxes = np.expand_dims(np.reshape(boxes, (-1, 4)), axis=0)
            scores = np.expand_dims(np.reshape(scores, (-1, 2)), axis=0)
            boxes = convert_locations_to_boxes(
                boxes, priors, center_variance, size_variance
            )
            boxes = center_form_to_corner_form(boxes)
            boxes, labels, probs = predict(
                img_ori.shape[1], 
                img_ori.shape[0], 
                scores, 
                boxes, 
                threshold
            )
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            for (x1, y1, x2, y2) in boxes:
                w = x2 - x1
                h = y2 - y1
                cv2.rectangle(frame, (x1,y1), (x2, y2), (255,0,0), 2)
                resize_frame = cv2.resize(
                    gray[y1:y1 + h, x1:x1 + w], (64, 64)
                )
                resize_frame = resize_frame.reshape(1, 1, 64, 64)
                model.setInput(resize_frame)
                output = model.forward()
                end_time = time.time()
                fps = 1 / (end_time - start_time)
                print(f"FPS: {fps:.1f}")
                pred = emotion_dict[list(output[0]).index(max(output[0]))]
                cv2.rectangle(
                    img_ori, 
                    (x1, y1), 
                    (x2, y2), 
                    (0, 255, 0), 
                    2,
                    lineType=cv2.LINE_AA
                )
                cv2.putText(
                    frame, 
                    pred, 
                    (x1, y1), 
                    cv2.FONT_HERSHEY_SIMPLEX, 
                    0.8, 
                    (0, 255, 0), 
                    2,
                    lineType=cv2.LINE_AA
                )
 
            result.write(frame)
         
            cv2.imshow('frame', frame)
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
        else:
            break
 
    cap.release()
    result.release()
    cv2.destroyAllWindows()

FER_live_cam() 函数对视频帧进行实时的面部情绪识别。首先,它设置了一个字典 emotion_dict,将数字情绪类别索引映射到可读的情绪标签。视频源被初始化,尽管也可以使用网络摄像头输入。该函数还初始化了一个输出视频写入器,用于保存带有情绪注释的处理过的帧。主要的情绪预测模型以ONNX格式保存,在使用OpenCV DNN的 readNetFromONNX 方法读取并与以Caffe格式保存的RFB-30 SSD人脸检测模型一起加载。在逐帧处理视频时,人脸检测模型通过边界框识别出人脸。

检测到的人脸在输入情绪识别模型之前经过预处理,包括调整大小和转换为灰度图像。通过从模型的输出分数中选择最大值确定识别出的情绪,并使用 emotion_dict 将其映射到标签。然后,在检测到的人脸周围添加矩形框和情绪标签,将帧保存到输出视频文件中,并实时显示。用户可以通过按下 ‘q’ 键停止视频显示。一旦视频处理完成或中断,资源如视频捕获和写入器将被释放,并关闭任何打开的窗口。值得注意的是,该函数引用了一些在其作用域内未定义的变量和辅助函数,这表明它们是整个代码库的一部分。

推理结果

表情识别

面部情绪识别(FER)是指根据面部表情识别和分类人类情绪的过程。通过分析面部特征和模式,机器可以对一个人的情绪状态作出有根据的推断。这个面部识别的子领域高度跨学科,涉及计算机视觉、机器学习和心理学等领域的知识。

应用领域

以下是一些关键领域,其中这项技术可能有所帮助:

社交和内容创作平台:

根据情感反馈个性化用户体验。 自适应学习系统根据学习者的情绪状态调整内容,提供更具针对性的建议。

医疗研究:

监测患者是否存在抑郁、焦虑或其他情绪障碍的迹象。 协助治疗师在治疗过程中跟踪患者的进展或反应。 实时监测应激水平。

驾驶员安全机制:

监测驾驶员是否出现疲劳、注意力分散、压力或昏昏欲睡的迹象。

营销和市场研究:

实时分析观众对广告的反应。 根据观众的情绪状态定制广告内容。 产品测试和反馈。

安全和监控:

在拥挤区域检测可疑或异常行为。 分析公共事件中人群的反应,以确保安全。

构建面部情绪识别系统

本节深入探讨构建面部情绪识别系统的复杂性。我们首先探讨一个专门为面部情绪识别设计的数据集,确保我们的模型有稳健的基础。接下来,我们将介绍一种自定义的VGG13模型架构,该架构以其在分类任务中的效率和准确性而闻名,并阐明其与我们情绪识别目标的相关性。

最后,我们花费一些时间在实验结果部分,提供全面的评估,阐明系统的性能指标及其潜在应用。

面部情绪识别数据集(FER +)

FER + 数据集是原始面部表情识别(FER)数据集的一个重要扩展。为了改进原始数据集的局限性,FER + 提供了更精细和细致的面部表情标签。虽然原始FER数据集将面部表情分类为六种基本情绪——快乐、悲伤、愤怒、惊讶、恐惧和厌恶——但FER + 根据这一基础更进一步引入了两个额外的类别:中性和蔑视。

img

添加图片注释,不超过 140 字(可选)

用于人脸检测的RFB-320

Single Shot Multibox Detector (SSD)模型 在识别情绪之前,需要在输入帧中检测人脸。为此,使用了超轻量级人脸检测模型RFB-320。它是一种针对边缘计算设备进行优化的创新人脸检测模型。该模型采用了改进的感受野块(RFB)模块,在不增加计算负担的情况下有效地捕捉多尺度的上下文信息。它在多样化的WIDER FACE数据集上进行训练,并针对320×240的输入分辨率进行优化,具有出色的效率平衡,计算速度为0.2106 GFLOPs,参数量仅为0.3004百万个。该模型基于PyTorch框架开发,取得了令人称赞的平均精度(mAP)为84.78%,在资源受限环境中成为高效人脸检测的强大解决方案。在此实现中,RFB-320 SSD模型以Caffe格式使用。

img

添加图片注释,不超过 140 字(可选)

自定义的VGG13模型架构

情绪识别分类模型采用了定制的VGG13架构,专为64×64灰度图像设计。它使用具有最大池化和dropout的卷积层将图像分类为八个情绪类别,以防止过拟合。该架构开始于两个具有64个卷积核的卷积层,然后是最大池化和25%的dropout。额外的卷积层捕捉复杂的特征,两个具有1024个节点的密集层聚合信息,然后是50%的dropout。一个softmax输出层预测情绪类别。

img

添加图片注释,不超过 140 字(可选)

让我们编写一些代码来实现这个系统。

首先,需要初始化一些重要的参数。

image_mean = np.array([127, 127, 127])
image_std = 128.0
iou_threshold = 0.3
center_variance = 0.1
size_variance = 0.2
min_boxes = [
    [10.0, 16.0, 24.0], 
    [32.0, 48.0], 
    [64.0, 96.0], 
    [128.0, 192.0, 256.0]
]
strides = [8.0, 16.0, 32.0, 64.0]
threshold = 0.5

image_mean: 在RGB通道上进行图像归一化的均值。 image_std: 图像归一化的标准差。 iou_threshold: 确定边界框匹配的交并比(IoU)度量的阈值。 center_variance: 预测的边界框中心坐标的缩放因子。 size_variance: 预测的边界框尺寸的缩放因子。 min_boxes: 不同尺寸对象的最小边界框尺寸。 strides: 根据图像大小控制特征图的尺度。 threshold: 目标检测的置信度阈值。

def define_img_size(image_size):
    shrinkage_list = []
    feature_map_w_h_list = []
    for size in image_size:
        feature_map = [int(ceil(size / stride)) for stride in strides]
        feature_map_w_h_list.append(feature_map)

    for i in range(0, len(image_size)):
        shrinkage_list.append(strides)
    priors = generate_priors(
        feature_map_w_h_list, shrinkage_list, image_size, min_boxes
    )
    return priors

上述的 define_img_size 函数旨在为目标检测任务生成先验边界框(priors)。该函数以 image_size 参数作为输入,根据提供的图像尺寸和一组预定义的步长值计算特征图的尺寸。这些特征图的尺寸反映了卷积神经网络(CNN)层对不同输入图像尺度的期望输出尺寸。实质上,SSD中的先验边界框提供了一种高效的方法,可以在网络的单次前向传递中同时预测多个边界框及其关联的类别得分,从而实现实时目标检测。

def FER_live_cam():
    emotion_dict = {
        0: 'neutral', 
        1: 'happiness', 
        2: 'surprise', 
        3: 'sadness',
        4: 'anger', 
        5: 'disgust', 
        6: 'fear'
    }

    # cap = cv2.VideoCapture('video1.mp4')
    cap = cv2.VideoCapture(0)

    frame_width = int(cap.get(3))
    frame_height = int(cap.get(4))
    size = (frame_width, frame_height)
    result = cv2.VideoWriter('result.avi', 
                         cv2.VideoWriter_fourcc(*'MJPG'),
                         10, size)

    # Read ONNX model
    model = 'onnx_model.onnx'
    model = cv2.dnn.readNetFromONNX('emotion-ferplus-8.onnx')

    # Read the Caffe face detector.
    model_path = 'RFB-320/RFB-320.caffemodel'
    proto_path = 'RFB-320/RFB-320.prototxt'
    net = dnn.readNetFromCaffe(proto_path, model_path)
    input_size = [320, 240]
    width = input_size[0]
    height = input_size[1]
    priors = define_img_size(input_size)

    while cap.isOpened():
        ret, frame = cap.read()
        if ret:
            img_ori = frame
            #print("frame size: ", frame.shape)
            rect = cv2.resize(img_ori, (width, height))
            rect = cv2.cvtColor(rect, cv2.COLOR_BGR2RGB)
            net.setInput(dnn.blobFromImage(
                rect, 1 / image_std, (width, height), 127)
            )
            start_time = time.time()
            boxes, scores = net.forward(["boxes", "scores"])
            boxes = np.expand_dims(np.reshape(boxes, (-1, 4)), axis=0)
            scores = np.expand_dims(np.reshape(scores, (-1, 2)), axis=0)
            boxes = convert_locations_to_boxes(
                boxes, priors, center_variance, size_variance
            )
            boxes = center_form_to_corner_form(boxes)
            boxes, labels, probs = predict(
                img_ori.shape[1], 
                img_ori.shape[0], 
                scores, 
                boxes, 
                threshold
            )
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            for (x1, y1, x2, y2) in boxes:
                w = x2 - x1
                h = y2 - y1
                cv2.rectangle(frame, (x1,y1), (x2, y2), (255,0,0), 2)
                resize_frame = cv2.resize(
                    gray[y1:y1 + h, x1:x1 + w], (64, 64)
                )
                resize_frame = resize_frame.reshape(1, 1, 64, 64)
                model.setInput(resize_frame)
                output = model.forward()
                end_time = time.time()
                fps = 1 / (end_time - start_time)
                print(f"FPS: {fps:.1f}")
                pred = emotion_dict[list(output[0]).index(max(output[0]))]
                cv2.rectangle(
                    img_ori, 
                    (x1, y1), 
                    (x2, y2), 
                    (0, 255, 0), 
                    2,
                    lineType=cv2.LINE_AA
                )
                cv2.putText(
                    frame, 
                    pred, 
                    (x1, y1), 
                    cv2.FONT_HERSHEY_SIMPLEX, 
                    0.8, 
                    (0, 255, 0), 
                    2,
                    lineType=cv2.LINE_AA
                )

            result.write(frame)

            cv2.imshow('frame', frame)
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
        else:
            break

    cap.release()
    result.release()
    cv2.destroyAllWindows()

FER_live_cam() 函数对视频帧进行实时的面部情绪识别。首先,它设置了一个字典 emotion_dict,将数字情绪类别索引映射到可读的情绪标签。视频源被初始化,尽管也可以使用网络摄像头输入。该函数还初始化了一个输出视频写入器,用于保存带有情绪注释的处理过的帧。主要的情绪预测模型以ONNX格式保存,在使用OpenCV DNN的 readNetFromONNX 方法读取并与以Caffe格式保存的RFB-30 SSD人脸检测模型一起加载。在逐帧处理视频时,人脸检测模型通过边界框识别出人脸。

检测到的人脸在输入情绪识别模型之前经过预处理,包括调整大小和转换为灰度图像。通过从模型的输出分数中选择最大值确定识别出的情绪,并使用 emotion_dict 将其映射到标签。然后,在检测到的人脸周围添加矩形框和情绪标签,将帧保存到输出视频文件中,并实时显示。用户可以通过按下 ‘q’ 键停止视频显示。一旦视频处理完成或中断,资源如视频捕获和写入器将被释放,并关闭任何打开的窗口。值得注意的是,该函数引用了一些在其作用域内未定义的变量和辅助函数,这表明它们是整个代码库的一部分。

推理结果

img

添加图片注释,不超过 140 字(可选)

img

添加图片注释,不超过 140 字(可选)

论文辅导,代码获取,作业辅助

起加载。在逐帧处理视频时,人脸检测模型通过边界框识别出人脸。

检测到的人脸在输入情绪识别模型之前经过预处理,包括调整大小和转换为灰度图像。通过从模型的输出分数中选择最大值确定识别出的情绪,并使用 emotion_dict 将其映射到标签。然后,在检测到的人脸周围添加矩形框和情绪标签,将帧保存到输出视频文件中,并实时显示。用户可以通过按下 ‘q’ 键停止视频显示。一旦视频处理完成或中断,资源如视频捕获和写入器将被释放,并关闭任何打开的窗口。值得注意的是,该函数引用了一些在其作用域内未定义的变量和辅助函数,这表明它们是整个代码库的一部分。

推理结果

[外链图片转存中…(img-JuBrmpoL-1730637000769)]

添加图片注释,不超过 140 字(可选)

[外链图片转存中…(img-0jtMGVYE-1730637000770)]

添加图片注释,不超过 140 字(可选)

论文辅导,代码获取,作业辅助

更多项目见主页:目标检测、跟踪、姿态识别、计算机视觉入门、红绿灯、交通标识等项目等你来练手!

标签:教程,人脸识别,情绪,frame,cv2,boxes,识别,size
From: https://blog.csdn.net/qq1309399183/article/details/143470363

相关文章

  • ffmpeg安装教程
    1下载所需要的软件mkdir/usr/local/softcd/usr/local/softwgethttps://www.ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2wgethttp://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gzfreetype下载地址http://www.linuxfromscratch.org/blfs/view/svn/gen......
  • Springboot 整合 Java DL4J 打造自然语言处理之语音识别系统
    ......
  • PyQt5 详细安装与配置教程及使用
    文章目录Part1:安装PyQt5Part2:配置PyQt5的依赖工具QtDesigner和PyUICPart3:使用QtDesigner设计界面Part4:使用PyUIC将设计好的界面转换为.py文件Part5:通过代码显示ui界面Part1:安装PyQt5需要安装两个库,可直接通过一下命令安装pipinstallPyQt5pipinstallpyq......
  • [游戏音效配音套件含教程]Shadow Samples Razor Production Suite
    RAZOR探索超过90GB的改变游戏规则的声音和奖励内容我们最疯狂的项目……5个全新捆绑包我们全力投入Razor。超过2000个自定义样本,涵盖低音音乐的所有流派– Dubstep、UKG、UKBass、Hard Techno、Trap 等。我们为您提供一切–低音循环+镜头、完整鼓循环+......
  • tensorflow案例5--基于改进VGG16模型的马铃薯识别,准确率提升0.6%,计算量降低78.07%
    ......
  • Gpt4.0最新保姆级教程开通升级
     如何使用WildCard服务注册Claude3随着Claude3的震撼发布,最强AI模型的桂冠已不再由GPT-4独揽。Claude3推出了三个备受瞩目的模型:Claude3Haiku、Claude3Sonnet以及Claude3Opus,每个模型都展现了卓越的性能与特色。其中,Claude3Opus更是实现了对GPT-4的全......
  • 使用 Vala 编写一个简单的文字识别程序
    文字识别(OpticalCharacterRecognition,OCR)是一项非常有用的技术,能够将图像中的文本转换为可编辑和搜索的格式。Vala语言,作为一种现代的编程语言,具有与C类似的效率,并且与GNOME框架高度兼容。在本文中,我们将使用Vala编写一个简单的OCR程序。环境设置首先,您需要确保已......
  • 使用 ATS 实现基本文字识别程序
    本文介绍如何使用ATS语言来实现一个基本的文字识别程序。ATS是一种支持类型和逻辑的编程语言,特别适合处理复杂的算法逻辑。以下示例展示如何在ATS中实现简单的字符匹配,以模拟图像中的字符识别。步骤概览加载图像数据:将输入的图像转化为二进制格式,以便于处理。字符模板定义......
  • 医疗行业语音识别的变革力量:思通数科AI多模态能力平台的技术说明与应用场景
    一、系统概述随着医疗行业对诊疗效率和准确性的要求不断提升,传统的医生与患者沟通方式正面临挑战。过多的书面记录使得医生的注意力从患者转移到了记录工作上,增加了患者等待时间,并可能影响诊断质量。语音识别(ASR)技术的引入为这一现状带来了革新,通过将患者的口头描述实时转化为文......
  • 关于LIME和SHAP的具体代码示例或实现教程
    关注我,持续分享逻辑思维&管理思维&面试题;可提供大厂面试辅导、及定制化求职/在职/管理/架构辅导;推荐专栏《10天学会使用asp.net编程AI大模型》,目前已完成所有内容。一顿烧烤不到的费用,让人能紧跟时代的浪潮。从普通网站,到公众号、小程序,再到AI大模型网站。干货满满。学成后可......