DeepFace深度学习库+OpenCV实现——情绪分析器

DeepFace深度学习库+OpenCV实现——情绪分析器

目录

应用场景

实现组件

1. 硬件组件

2. 软件库与依赖

3. 功能模块

代码详解(实现思路)

导入必要的库

打开摄像头并初始化变量

主循环

FPS计算

情绪分析及结果展示

显示FPS和图像

退出条件

​编辑

完整代码

效果展示

自然的

开心的

伤心的

恐惧的

惊讶的



 效果展示

自然的

开心的

伤心的

恐惧的

惊讶的


 



应用场景

        应用场景比较广泛,尤其是在需要了解和分析人类情感反应的场合。:

  1. 心理健康评估:在心理健康领域,可以通过长期监控和分析一个人的情绪变化来辅助医生进行诊断或治疗效果评估。
  2. 用户体验研究:在产品设计、广告制作或网站开发过程中,通过观察用户在使用过程中的情绪反应,来优化产品的用户体验。
  3. 互动娱乐:在游戏或虚拟现实应用中,根据玩家的情绪状态动态调整游戏难度或故事情节,以增加沉浸感和互动性。
  4. 安全监控:在公共安全领域,通过情绪识别技术可以早期发现异常行为或潜在威胁,例如在机场安检区域或者大型公共活动场所。
  5. 教育与培训:帮助教师了解学生在学习过程中的情绪状态,以便及时调整教学方法;也可用于职业培训中,通过模拟不同情境下的情绪反应来进行针对性训练。
  6. 智能助手:集成到智能家居系统或个人助理设备中,让设备能够感知用户的情绪状态,并据此提供更加个性化的服务或响应。
  7. 疲劳驾驶预测:对于司机情绪的分析,可以监控和作为一种影响因子判断出出司机的驾驶状态,以至于安全的驾驶。

        总之,随着人工智能技术的发展,情绪识别作为一种重要的交互方式,在许多领域都有着巨大的潜力和广阔的应用前景。


实现组件

1. 硬件组件

  • 摄像头:用于捕捉实时视频流,通常为电脑内置的摄像头或外接USB摄像头。

2. 软件库与依赖

  • OpenCV (cv2):一个开源的计算机视觉和机器学习软件库。它提供了大量的图像处理和计算机视觉算法,这里主要用于捕获摄像头视频流、处理图像以及在图像上绘制矩形框和文字。
  • time:Python标准库的一部分,用于计算时间间隔,进而计算FPS(每秒帧数)。
  • numpy (np):虽然在这段代码中没有直接使用,但它是进行科学计算的基础库,通常与OpenCV一起用于更复杂的图像处理任务。
  • DeepFace:这是一个深度学习库,专门用于面部识别及其相关任务(如年龄、性别、情绪等属性的预测)。在这个应用中,DeepFace被用来对每一帧视频中的人脸进行情绪分析。

3. 功能模块

  • 视频捕捉与处理模块
    • 使用cv2.VideoCapture(0)打开摄像头,并通过循环不断读取视频帧。
    • 对每一帧图像进行处理,包括计算FPS、进行情绪分析以及在图像上标注结果。
  • FPS计算模块
    • 利用time.time()获取当前时间戳,通过计算连续两帧之间的时间差来计算瞬时FPS,并采用滑动平均方法平滑FPS值。
  • 情绪分析模块
    • 调用DeepFace.analyze()函数对每一帧中的所有人脸进行情绪分析。分析结果包含每个人脸的位置、主导情绪及置信度。
  • 结果显示模块
    • 使用OpenCV提供的绘图函数(如cv2.rectangle()cv2.putText())在视频帧上标记出人脸位置、显示情绪信息及置信度,并展示当前的FPS值。
  • 用户交互模块
    • 通过监听键盘输入(cv2.waitKey(1)),允许用户按下q键退出程序。

代码详解(实现思路)

        主要是通过摄像头捕捉实时视频流,然后使用深度学习模型对捕捉到的每一帧进行情绪分析,然后在视频上标记出检测到的情绪和置信度,并显示当前的FPS(每秒帧数)。下面是对代码各个部分的详细解释:

导入必要的库

import cv2 import time import numpy as np from deepface import DeepFace
  • cv2:OpenCV库,用于处理图像和视频流。
  • time:用于计算时间间隔,进而计算FPS。
  • numpy:虽然在这段代码中没有直接使用,但通常与OpenCV一起用于图像处理。
  • DeepFace:一个基于深度学习的面部识别和分析库。

打开摄像头并初始化变量

cap = cv2.VideoCapture(0) prev_time = time.time() fps = 0 alpha = 0.9
  • cv2.VideoCapture(0):打开默认摄像头(0代表第一个摄像头设备)。
  • prev_time 和 fps:用于计算FPS的变量。prev_time保存上一帧的时间戳,而fps保存当前帧率。
  • alpha:用于滑动平均计算FPS的权重值。

主循环

while True: ret, frame = cap.read() if not ret: break ... cap.release() cv2.destroyAllWindows()
  • 这个无限循环不断从摄像头读取帧(cap.read())。如果读取失败(ret为False),则退出循环。
  • 循环体内部实现了帧的获取、FPS计算、情绪分析、结果绘制以及画面显示。
FPS计算
current_time = time.time() delta_time = current_time - prev_time prev_time = current_time if delta_time > 0: instant_fps = 1.0 / delta_time fps = alpha * fps + (1 - alpha) * instant_fps
  • 计算自上次迭代以来经过的时间(delta_time),然后根据这个时间差计算瞬时FPS(instant_fps)。
  • 使用滑动平均更新总体FPS(fps)。
情绪分析及结果展示
result = DeepFace.analyze(frame, actions=['emotion'], enforce_detection=False) ...
  • 对每一帧调用DeepFace.analyze()方法进行情绪分析。actions=['emotion']指定只执行情绪分析。
  • 遍历返回的结果,在画面上标出人脸的位置(cv2.rectangle)和识别出的情绪信息(cv2.putText)。
显示FPS和图像
cv2.putText(frame, f'FPS: {fps:.2f}', (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 255), 2) cv2.imshow("Emotion Detection", frame)
  • 在图像上显示当前的FPS。
  • 使用cv2.imshow()显示带有标注的图像。
退出条件
if cv2.waitKey(1) & 0xFF == ord('q'): break
  • 如果按下键盘上的q键,则退出循环结束程序。

最后,释放摄像头资源(cap.release())并关闭所有窗口(cv2.destroyAllWindows())。


完整代码

import cv2 import time import numpy as np from deepface import DeepFace # 打开摄像头 cap = cv2.VideoCapture(0) # FPS 计算参数 prev_time = time.time() fps = 0 alpha = 0.9 # 滑动平均权重,数值越大,FPS 越平稳 while True: ret, frame = cap.read() if not ret: break # 计算 FPS current_time = time.time() delta_time = current_time - prev_time prev_time = current_time if delta_time > 0: instant_fps = 1.0 / delta_time fps = alpha * fps + (1 - alpha) * instant_fps # 计算滑动平均 FPS try: # 进行表情识别 result = DeepFace.analyze(frame, actions=['emotion'], enforce_detection=False) for face in result: x, y, w, h = face['region']['x'], face['region']['y'], face['region']['w'], face['region']['h'] emotion = face['dominant_emotion'] confidence = face['emotion'][emotion] # 获取表情的置信度 # 绘制人脸矩形框 cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) # 在人脸上方显示情绪信息 text = f'{emotion} ({confidence:.2f}%)' cv2.putText(frame, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) except Exception as e: print("无法检测到人脸:", e) # 显示 FPS(平滑更新) cv2.putText(frame, f'FPS: {fps:.2f}', (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 255), 2) # 显示图像 cv2.imshow("Emotion Detection", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() 

总结

        核心在于结合了OpenCV进行视频处理和DeepFace进行面部情绪分析的能力。通过这些组件,实现从摄像头实时捕捉视频、分析视频中人物的情绪状态并在视频画面上直观地展示分析结果的功能。

        这不仅展示了如何利用现有的AI库快速构建实用的应用程序,也为进一步开发基于情感识别的复杂系统提供了基础框架或者是组件。

Read more

Flutter 三方库 dartcv4 的鸿蒙化适配指南 - 在鸿蒙应用中运行 OpenCV4 高性能视觉算法,支持图像处理、矩阵计算及 C++ 级 NATIVE 资产加载

Flutter 三方库 dartcv4 的鸿蒙化适配指南 - 在鸿蒙应用中运行 OpenCV4 高性能视觉算法,支持图像处理、矩阵计算及 C++ 级 NATIVE 资产加载

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 dartcv4 的鸿蒙化适配指南 - 在鸿蒙应用中运行 OpenCV4 高性能视觉算法,支持图像处理、矩阵计算及 C++ 级 NATIVE 资产加载 前言 在 OpenHarmony 应用中处理复杂的图像处理任务(如人脸识别、边缘检测或图像变换)时,纯 Dart 逻辑往往难以在性能上达到平衡。dartcv4 是一款专为 Dart/Flutter 设计的 OpenCV 4 绑定库,它通过 dart:ffi(外部函数接口)技术直接调用底层的 C++ 动态链接库。本文将深入讲解如何在鸿蒙端利用 dartcv4 实现极速的图像处理逻辑,打通鸿蒙原生 C++ 与

By Ne0inhk
【C++指南】STL list容器完全解读(一):从入门到掌握基础操作

【C++指南】STL list容器完全解读(一):从入门到掌握基础操作

.💓 博客主页:倔强的石头的ZEEKLOG主页 📝Gitee主页:倔强的石头的gitee主页 ⏩ 文章专栏:《C++指南》 期待您的关注 文章目录 * 一、初识list容器 * 1.1 什么是list? * 1.2 核心特性 * 1.3 典型应用场景 * 二、核心成员函数 * 2.1 默认成员函数 * 三、迭代器操作 * 3.1 基础迭代器 * 3.2 常量迭代器(C++11) * 四、容量与访问操作 * 4.1 容量查询 * 4.2 元素访问 * 五、修改操作详解 * 5.1 基础修改函数 * 5.2

By Ne0inhk
《 C++ 点滴漫谈: 二十七 》告别低效!C++ 输入输出操作你真的会用吗?

《 C++ 点滴漫谈: 二十七 》告别低效!C++ 输入输出操作你真的会用吗?

摘要 C++ 的输入输出系统是程序开发中的重要组成部分,涵盖数据交互、文件操作、格式化输出等多方面内容。本篇博客全面解析了 C++ 输入输出的基础知识,包括标准输入输出流的操作方法、文件输入输出的灵活应用、格式化工具的精确控制,以及异常处理与错误管理的关键技术。此外,我们深入探讨了高级输入输出技巧,如多线程日志记录、自定义流缓冲区等,并通过实际案例总结了最佳实践和常见问题的解决方法。这篇博客不仅适合初学者理解 C++ 输入输出的核心概念,也为经验开发者提供了优化性能和提升代码质量的实用指南。通过本博客,读者将全面掌握 C++ 输入输出的各个方面,构建稳健、高效的程序。 1、引言 在计算机编程中,输入与输出(Input/Output, I/O) 是程序与外界交互的桥梁,是几乎所有程序中不可或缺的一部分。从用户输入数据到程序处理,再到将结果输出给用户,这一过程在任何应用场景中都起着关键作用。在 C++ 中,输入输出不仅仅是数据的传递,更是体现语言强大功能和灵活性的关键领域之一。 与 C 语言中传统的 printf

By Ne0inhk

C++ 继承、多态与类型转换 | 函数重载 / 隐藏 / 覆盖实现与基派生类指针转换

注:本文为 “C++ 继承、多态与类型转换 ” 相关合辑。 略作重排,未整理去重。 如有内容异常,请看原文。 C++ 基类指针和派生类指针之间的转换 -牧野- 原创于 2018-10-28 11:01:19 发布 本文系统解析函数重载、函数隐藏与函数覆盖的概念,重点阐述上述概念在基类与派生类间的应用机制,以及依托虚函数实现多态性的方法。同时,明确基类指针与派生类指针间的转换规则。 函数重载、函数隐藏、函数覆盖 函数重载仅发生于同一作用域内(或同一类中),要求函数名称相同,但参数类型或参数个数存在差异。函数重载无法通过返回类型进行区分,原因在于函数返回前,其返回类型无法被程序识别。 函数隐藏与函数覆盖仅发生于基类与派生类之间。 函数隐藏指派生类中存在与基类同名的函数,且该函数未在基类中被声明为虚函数的情形。 隐藏的具体表现为:采用常规调用方式时,派生类对象访问该函数会优先调用派生类中的同名函数,基类中的对应函数对派生类对象而言处于隐藏状态。但隐藏并不代表该函数不存在或完全不可访问,可通过 b->Base::func() 的形式访问基类中被隐藏的函数。 函数覆盖特指由基类

By Ne0inhk