人脸情绪识别(1)附代码

news/2024/4/29 9:54:23/文章来源:https://blog.csdn.net/PLANTTHESON/article/details/137090514

1.目标

实现人脸情绪实时检测,通过摄像头拍摄人脸并显示出相应情感类别。
代码地址:

2.Emotion-Detection-RealTime

2.1 目录结构

2.2 代码结构

模块导入

参数设置

数据处理

模型构建

训练脚本

展示脚本

2.3 具体代码

import numpy as np
import argparse
import cv2
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.python.layers.core import Dense, Dropout, Flatten
# from tensorflow.python.layers.convolutional import Conv2D
from keras.optimizers import Adam
# from tensorflow.python.layers import Conv2D
from tensorflow.keras.layers import Conv2D, Dense, Flatten,Dropout,MaxPooling2D# from tensorflow.python.layers.pooling import MaxPooling2D
from keras.preprocessing.image import ImageDataGenerator
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import matplotlib as mpl
mpl.use('TkAgg')
import matplotlib.pyplot as plt
import tensorflow as tf# command line argument
ap = argparse.ArgumentParser()
ap.add_argument("--mode",default='train',help="train/display")
a = ap.parse_args()
mode = a.mode def plot_model_history(model_history):"""Plot Accuracy and Loss curves given the model_history"""fig, axs = plt.subplots(1,2,figsize=(15,5))# summarize history for accuracyaxs[0].plot(range(1,len(model_history.history['acc'])+1),model_history.history['acc'])axs[0].plot(range(1,len(model_history.history['val_acc'])+1),model_history.history['val_acc'])axs[0].set_title('Model Accuracy')axs[0].set_ylabel('Accuracy')axs[0].set_xlabel('Epoch')axs[0].set_xticks(np.arange(1,len(model_history.history['acc'])+1),len(model_history.history['acc'])/10)axs[0].legend(['train', 'val'], loc='best')# summarize history for lossaxs[1].plot(range(1,len(model_history.history['loss'])+1),model_history.history['loss'])axs[1].plot(range(1,len(model_history.history['val_loss'])+1),model_history.history['val_loss'])axs[1].set_title('Model Loss')axs[1].set_ylabel('Loss')axs[1].set_xlabel('Epoch')axs[1].set_xticks(np.arange(1,len(model_history.history['loss'])+1),len(model_history.history['loss'])/10)axs[1].legend(['train', 'val'], loc='best')fig.savefig('plot.png')plt.show()# Define data generators
train_dir = 'data/data/train'
val_dir = 'data/data/test'num_train = 28709
num_val = 7178
batch_size = 64
num_epoch = 50train_datagen = ImageDataGenerator(rescale=1./255)
val_datagen = ImageDataGenerator(rescale=1./255)train_generator = train_datagen.flow_from_directory(train_dir,target_size=(48,48),batch_size=batch_size,color_mode="grayscale",class_mode='categorical')validation_generator = val_datagen.flow_from_directory(val_dir,target_size=(48,48),batch_size=batch_size,color_mode="grayscale",class_mode='categorical')# Create the model
model = Sequential()model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(48,48,1)))
model.add(Conv2D(64, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2),strides=(2,2)))
model.add(Dropout(0.25))model.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2),strides=(2,2)))
model.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2),strides=(2,2)))
model.add(Dropout(0.25))model.add(Flatten())
model.add(Dense(1024, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(7, activation='softmax'))# If you want to train the same model or try other models, go for this
if mode == "train":# 使用旧版本的Adam优化器# optimizer = tf.keras.optimizers.legacy.Adam(learning_rate=0.001, decay=1e-6)# model.compile(loss='categorical_crossentropy',optimizer=Adam(learning_rate=0.0001, decay=0.9),metrics=['accuracy'])model.compile(loss='categorical_crossentropy',    optimizer = tf.keras.optimizers.Adam(lr=0.001, decay=1e-6),metrics=['accuracy'])model_info = model.fit_generator(train_generator,steps_per_epoch=num_train // batch_size,epochs=num_epoch,validation_data=validation_generator,validation_steps=num_val // batch_size)plot_model_history(model_info)model.save_weights('model.h5')# emotions will be displayed on your face from the webcam feed
elif mode == "display":model.build((None, 48, 48, 1))model.load_weights(r'E:\pycharm_item\pyqt\EmotionDetection_RealTime-master\model.h5')# prevents openCL usage and unnecessary logging messagescv2.ocl.setUseOpenCL(False)# dictionary which assigns each label an emotion (alphabetical order)emotion_dict = {0: "Angry", 1: "Disgusted", 2: "Fearful", 3: "Happy", 4: "Neutral", 5: "Sad", 6: "Surprised"}# start the webcam feedcap = cv2.VideoCapture(0)while True:# Find haar cascade to draw bounding box around faceret, frame = cap.read()facecasc = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)faces = facecasc.detectMultiScale(gray,scaleFactor=1.3, minNeighbors=5)for (x, y, w, h) in faces:cv2.rectangle(frame, (x, y-50), (x+w, y+h+10), (255, 0, 0), 2)roi_gray = gray[y:y + h, x:x + w]cropped_img = np.expand_dims(np.expand_dims(cv2.resize(roi_gray, (48, 48)), -1), 0)prediction = model.predict(cropped_img)maxindex = int(np.argmax(prediction))cv2.putText(frame, emotion_dict[maxindex], (x+20, y-60), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)# show the output framecv2.imshow("Frame", frame)key = cv2.waitKey(1) & 0xFF# if the `q` key was pressed, break from the loopif key == ord("q"):breakcap.release()cv2.destroyAllWindows()

2.4 代码分析

2.4.1 模块导入
import numpy as np
import argparse
import cv2
from keras.models import Sequential
from tensorflow.python.layers.core import Dense, Dropout, Flatten
from tensorflow.python.layers.convolutional import Conv2D
from keras.optimizers import Adam
from tensorflow.python.layers.pooling import MaxPooling2D
from keras.preprocessing.image import ImageDataGenerator
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import matplotlib as mpl
mpl.use('TkAgg')
import matplotlib.pyplot as plt
import tensorflow as tf

(1)import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

设置TensorFlow的日志级别为仅显示错误信息:os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

  • TensorFlow 默认会输出一些额外的信息,这行代码将日志级别设置为2,表示只显示错误信息,可以减少不必要的输出,使输出更清晰

(2) import matplotlib as mpl
mpl.use('TkAgg')

配置Matplotlib以在TkAgg后端上运行:mpl.use('TkAgg')

  • Matplotlib 是一个用于绘图的 Python 库,在使用 Matplotlib 时,需要指定后端以确定图形如何显示。TkAgg 是一个 Matplotlib 的后端,使用 Tkinter 提供的 GUI 工具包来显示图形。
  • 这行代码将 Matplotlib 的后端设置为 TkAgg,确保图形能够在 Tkinter GUI 上正确显示。
2.4.2 参数设置
ap = argparse.ArgumentParser()
ap.add_argument("--mode",default='display',help="train/display")
a = ap.parse_args()
mode = a.mode 

这段代码使用了 Python 的 argparse 模块来解析命令行参数,并定义了一个名为 "mode" 的参数,其默认值为 "display"。具体解释如下:

1.ap = argparse.ArgumentParser(): 创建了一个参数解析器对象。
2.ap.add_argument("--mode", default='display', help="train/display"): 向参数解析器中添加了一个名为 "--mode" 的参数。其中:


3."--mode" 表示参数的名称;
4.default='display' 表示参数的默认值为 "display";
5.help="train/display" 提供了关于参数的简短描述,提示用户可以设置参数为 "train" 或 "display"。


6.a = ap.parse_args(): 解析了命令行参数,并将结果存储在变量 a 中。
7.mode = a.mode: 从解析结果中获取了参数 "--mode" 的值,并将其存储在变量 mode 中。

这样,通过命令行可以指定 --mode 参数的值为 "train" 或 "display",而在代码中可以通过 mode 变量来获取这个值,从而控制程序的行为。例如,如果用户在命令行中设置了 --mode train,那么在代码中 mode 的值将为 "train",程序将以训练模式运行。

 

2.4.3 数据处理
train_dir = 'data/data/train'
val_dir = 'data/data/test'num_train = 28709
num_val = 7178
batch_size = 64
num_epoch = 50train_datagen = ImageDataGenerator(rescale=1./255)
val_datagen = ImageDataGenerator(rescale=1./255)train_generator = train_datagen.flow_from_directory(train_dir,target_size=(48,48),batch_size=batch_size,color_mode="grayscale",class_mode='categorical')validation_generator = val_datagen.flow_from_directory(val_dir,target_size=(48,48),batch_size=batch_size,color_mode="grayscale",class_mode='categorical')

(1)train_datagen = ImageDataGenerator(rescale=1./255)

这行代码使用 Keras 中的 ImageDataGenerator 类来创建一个图像数据生成器对象 train_datagen,用于对训练图像进行数据增强和预处理。
参数说明:

1.rescale=1./255:将图像的像素值缩放到 [0, 1] 的范围内。这样做是为了将原始图像的像素值(通常为整数值在 [0, 255] 范围内)归一化到 0 到 1 之间,以便更好地进行模型训练。

通过数据生成器对象,可以在训练过程中实时生成经过预处理和数据增强的图像批次,以供模型训练使用。数据增强技术有助于增加训练数据的多样性,提高模型的泛化能力,从而改善模型的性能。

(2) train_generator = train_datagen.flow_from_directory(
        train_dir,
        target_size=(48,48),
        batch_size=batch_size,
        color_mode="grayscale",
        class_mode='categorical')

2.4.4 模型构建
model = Sequential()model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(48,48,1)))
model.add(Conv2D(64, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2),strides=(2,2)))
model.add(Dropout(0.25))model.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2),strides=(2,2)))
model.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2),strides=(2,2)))
model.add(Dropout(0.25))model.add(Flatten())
model.add(Dense(1024, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(7, activation='softmax'))

这段代码定义了一个卷积神经网络模型,使用了 Keras 的 Sequential 模型。以下是模型的层次结构和参数说明:

  1. 输入层:

    • 输入图像的大小为 (48, 48, 1),即图像的高度为 48 像素,宽度为 48 像素,通道数为 1(灰度图像)。
  2. 卷积层1:

    • 32 个大小为 (3, 3) 的卷积核。
    • ReLU 激活函数。
  3. 卷积层2:

    • 64 个大小为 (3, 3) 的卷积核。
    • ReLU 激活函数。
  4. 最大池化层1:

    • 池化窗口大小为 (2, 2)。
    • 步幅为 (2, 2)。
  5. Dropout 层1:

    • 丢弃率为 0.25,用于减少过拟合。
  6. 卷积层3:

    • 128 个大小为 (3, 3) 的卷积核。
    • ReLU 激活函数。
  7. 最大池化层2:

    • 池化窗口大小为 (2, 2)。
    • 步幅为 (2, 2)。
  8. 卷积层4:

    • 128 个大小为 (3, 3) 的卷积核。
    • ReLU 激活函数。
  9. 最大池化层3:

    • 池化窗口大小为 (2, 2)。
    • 步幅为 (2, 2)。
  10. Dropout 层2:

    • 丢弃率为 0.25,用于减少过拟合。
  11. Flatten 层:

    • 将多维输入展平为一维。
  12. 全连接层1:

    • 1024 个神经元。
    • ReLU 激活函数。
  13. Dropout 层3:

    • 丢弃率为 0.5,用于减少过拟合。
  14. 全连接层2(输出层):

    • 7 个神经元,对应于输出类别的数量(假设是 7 类)。
    • 使用 softmax 激活函数,用于多类别分类问题。

这个模型结构是一个经典的卷积神经网络结构,用于图像分类任务。

 

2.4.5 训练脚本
if mode == "train":# 使用旧版本的Adam优化器# optimizer = tf.keras.optimizers.legacy.Adam(learning_rate=0.001, decay=1e-6)# model.compile(loss='categorical_crossentropy',optimizer=Adam(learning_rate=0.0001, decay=0.9),metrics=['accuracy'])model.compile(loss='categorical_crossentropy',    optimizer = tf.keras.optimizers.legacy.Adam(learning_rate=0.001, decay=1e-6),metrics=['accuracy'])model_info = model.fit_generator(train_generator,steps_per_epoch=num_train // batch_size,epochs=num_epoch,validation_data=validation_generator,validation_steps=num_val // batch_size)plot_model_history(model_info)model.save_weights('model.h5')

(1)     model.compile(loss='categorical_crossentropy',    optimizer = tf.keras.optimizers.legacy.Adam(learning_rate=0.001, decay=1e-6),metrics=['accuracy'])

这行代码使用 Keras 中的 ImageDataGenerator 类来创建一个图像数据生成器对象 train_datagen,用于对训练图像进行数据增强和预处理。
参数说明:

1.rescale=1./255:将图像的像素值缩放到 [0, 1] 的范围内。这样做是为了将原始图像的像素值(通常为整数值在 [0, 255] 范围内)归一化到 0 到 1 之间,以便更好地进行模型训练。

通过数据生成器对象,可以在训练过程中实时生成经过预处理和数据增强的图像批次,以供模型训练使用。数据增强技术有助于增加训练数据的多样性,提高模型的泛化能力,从而改善模型的性能。

(2)    model_info = model.fit_generator(
            train_generator,
            steps_per_epoch=num_train // batch_size,
            epochs=num_epoch,
            validation_data=validation_generator,
            validation_steps=num_val // batch_size)

这行代码使用了 train_datagen 这个图像数据生成器来生成训练集的数据。具体参数说明如下:

1.flow_from_directory():从目录中生成批量的数据和标签。
2.train_dir:指定训练数据所在的目录。
3.target_size=(48,48):将输入图像调整为指定的大小,这里调整为 48x48 像素。
4.batch_size:指定每个批次的大小。
5.color_mode="grayscale":将图像转换为灰度模式,即单通道图像,因为训练数据通常不需要使用彩色信息。
6.class_mode='categorical':指定分类方式为 categorical,即多类别分类。

通过这行代码,train_generator 成为一个可以用于迭代访问训练数据的生成器对象,每次迭代会生成一个批次的图像数据和对应的标签,用于模型的训练。

(3)    plot_model_history(model_info)

plot_model_history(model_info) 这个函数的作用是绘制模型的训练过程中的历史数据,通常包括训练集和验证集上的损失值和准确率随着训练轮数的变化趋势。这有助于直观地了解模型的训练情况,以及判断模型是否存在过拟合或欠拟合等问题。
通常情况下,model_info 参数是一个字典,包含了模型训练过程中的历史数据,比如损失值和准确率。这个函数会使用这些数据来生成训练过程的可视化图表,以便分析模型的性能和训练进度。
你可能需要在代码中定义这个函数,或者使用相关的库(如 Matplotlib)来实现这个功能。

(4)    model.save_weights('model.h5')

这行代码用于将模型的权重保存到名为 "model.h5" 的文件中。具体说明如下:

1.model.save_weights('model.h5'):将当前模型的权重保存到名为 "model.h5" 的 HDF5 格式文件中。这个文件可以包含模型的所有权重参数,方便以后加载模型并恢复训练,或者在其他地方使用相同架构的模型。 

这个步骤通常在模型训练完成后用于保存模型的权重,以便在需要时重新加载模型并使用它,或者在其他环境中部署模型。

2.4.6 训练结果展示 
def plot_model_history(model_history):"""Plot Accuracy and Loss curves given the model_history"""fig, axs = plt.subplots(1,2,figsize=(15,5))# summarize history for accuracyaxs[0].plot(range(1,len(model_history.history['acc'])+1),model_history.history['acc'])axs[0].plot(range(1,len(model_history.history['val_acc'])+1),model_history.history['val_acc'])axs[0].set_title('Model Accuracy')axs[0].set_ylabel('Accuracy')axs[0].set_xlabel('Epoch')axs[0].set_xticks(np.arange(1,len(model_history.history['acc'])+1),len(model_history.history['acc'])/10)axs[0].legend(['train', 'val'], loc='best')# summarize history for lossaxs[1].plot(range(1,len(model_history.history['loss'])+1),model_history.history['loss'])axs[1].plot(range(1,len(model_history.history['val_loss'])+1),model_history.history['val_loss'])axs[1].set_title('Model Loss')axs[1].set_ylabel('Loss')axs[1].set_xlabel('Epoch')axs[1].set_xticks(np.arange(1,len(model_history.history['loss'])+1),len(model_history.history['loss'])/10)axs[1].legend(['train', 'val'], loc='best')fig.savefig('plot.png')plt.show()

这是一个用于绘制模型训练过程中准确率和损失值变化曲线的函数。函数的输入是一个包含模型训练历史数据的字典 model_history,其中包括训练集和验证集上的准确率和损失值。
函数的主要步骤如下:

1.创建一个包含两个子图的图形对象,分别用于绘制准确率曲线和损失值曲线。
2.在第一个子图中绘制训练集和验证集的准确率曲线。
3.在第二个子图中绘制训练集和验证集的损失值曲线。
4.设置图表标题、坐标轴标签和图例。
5.将图表保存为文件 "plot.png"。
6.显示图表。

这个函数可以帮助你可视化模型的训练过程,以便更好地理解模型的性能和训练进度。请确保在使用之前导入所需的库,如 Matplotlib 和 NumPy。

 

2.4.7 人脸识别脚本
elif mode == "display":model.build((None, 48, 48, 1))model.load_weights(r'E:\pycharm_item\pyqt\EmotionDetection_RealTime-master\model.h5')# prevents openCL usage and unnecessary logging messagescv2.ocl.setUseOpenCL(False)# dictionary which assigns each label an emotion (alphabetical order)emotion_dict = {0: "Angry", 1: "Disgusted", 2: "Fearful", 3: "Happy", 4: "Neutral", 5: "Sad", 6: "Surprised"}# start the webcam feedcap = cv2.VideoCapture(0)while True:# Find haar cascade to draw bounding box around faceret, frame = cap.read()facecasc = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)faces = facecasc.detectMultiScale(gray,scaleFactor=1.3, minNeighbors=5)for (x, y, w, h) in faces:cv2.rectangle(frame, (x, y-50), (x+w, y+h+10), (255, 0, 0), 2)roi_gray = gray[y:y + h, x:x + w]cropped_img = np.expand_dims(np.expand_dims(cv2.resize(roi_gray, (48, 48)), -1), 0)prediction = model.predict(cropped_img)maxindex = int(np.argmax(prediction))cv2.putText(frame, emotion_dict[maxindex], (x+20, y-60), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)# show the output framecv2.imshow("Frame", frame)key = cv2.waitKey(1) & 0xFF

(1) model.build((None, 48, 48, 1))

model.build((None, 48, 48, 1)) 这行代码用于构建模型的网络结构,指定模型的输入形状。具体来说:

1.(None, 48, 48, 1) 指定了模型的输入形状。在这里,(None, 48, 48, 1) 表示输入数据的形状为 (batch_size, height, width, channels),其中:
2.batch_size 是输入的批量大小,这里使用 None 表示可以接受任意大小的批量输入。
3.height 是输入图像的高度,这里为 48 像素。
4.width 是输入图像的宽度,这里为 48 像素。
5.channels 是输入图像的通道数,这里为 1,表示灰度图像。

通过这行代码,模型被构建并指定了输入的形状,使其准备好接受对应形状的输入数据进行处理。通常,在训练模型之前,需要先调用 build 方法来构建模型,以便指定输入形状并初始化模型的权重。

(2) model.load_weights(r'E:\pycharm_item\pyqt\EmotionDetection_RealTime-master\model.h5')

model.load_weights() 函数用于加载模型的权重参数,通常是在训练好的模型上进行预测或继续训练时使用。在这个例子中,模型的权重参数保存在文件路径 E:\pycharm_item\pyqt\EmotionDetection_RealTime-master\model.h5 中。
通过调用 model.load_weights() 函数,并传入权重文件的路径作为参数,可以将保存在该文件中的模型权重加载到当前模型中,从而恢复模型的训练状态或用于进行预测。
一旦权重加载完成,该模型就可以在预测新数据或继续训练时使用之前训练的参数。

(3) cv2.ocl.setUseOpenCL(False)

cv2.ocl.setUseOpenCL(False) 这行代码是用于禁用 OpenCL 加速的功能,它通常用于 OpenCV 库中。OpenCL 是一种用于并行计算的开放标准,允许利用 GPU 或其他计算设备来加速图像处理和计算任务。
有时在使用 OpenCV 进行图像处理时,可能会出现一些兼容性或性能问题,特别是在某些设备或平台上。因此,通过调用 cv2.ocl.setUseOpenCL(False) 函数,可以显式地禁用 OpenCL 加速,从而确保算法的正确性和稳定性。
在一些情况下,禁用 OpenCL 可能会导致一些性能上的损失,但通常只在特定情况下会对图像处理产生显著影响。

(4) emotion_dict = {0: "Angry", 1: "Disgusted", 2: "Fearful", 3: "Happy", 4: "Neutral", 5: "Sad", 6: "Surprised"}

emotion_dict 是一个字典,用于将模型输出的数字类别标签映射到对应的情绪类别。每个键值对都表示了一个情绪类别的对应关系,其中键是模型输出的类别标签,值是对应的情绪类别名称。
具体来说,这里的映射关系如下:

1.0 对应 "Angry"(愤怒)
2.1 对应 "Disgusted"(厌恶)
3.2 对应 "Fearful"(害怕)
4.3 对应 "Happy"(快乐)
5.4 对应 "Neutral"(中性)
6.5 对应 "Sad"(悲伤)
7.6 对应 "Surprised"(惊讶)

通过这个映射字典,可以将模型输出的数字类别标签转换为对应的情绪类别名称,从而更直观地理解模型的预测结果。

(5) cap = cv2.VideoCapture(0)

这行代码创建了一个名为 cap 的视频捕获对象,用于从摄像头中捕获实时视频流。参数 0 指定了要使用的摄像头设备的索引,其中 0 通常表示默认的摄像头设备。
一旦创建了视频捕获对象,就可以使用它来捕获实时视频帧,进行图像处理、分析或显示等操作。这对于实时的计算机视觉应用非常有用,例如人脸检测、姿态估计、情绪识别等。

(6) while True:
        # Find haar cascade to draw bounding box around face
        ret, frame = cap.read()
        facecasc = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        faces = facecasc.detectMultiScale(gray,scaleFactor=1.3, minNeighbors=5)

这段代码是一个无限循环,用于持续地从摄像头捕获实时视频帧,并在检测到的人脸周围绘制边界框。
在循环的每次迭代中,执行以下步骤:

1.使用 cap.read() 方法读取一帧视频,其中 cap 是之前创建的视频捕获对象。
2.使用 cv2.CascadeClassifier('haarcascade_frontalface_default.xml') 加载人脸检测器的 Haar 级联分类器。
3.将读取的视频帧转换为灰度图像,以便后续的人脸检测。
4.使用 facecasc.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5) 方法检测灰度图像中的人脸,并返回检测到的人脸位置信息(矩形框)。

在这个循环中,不断地获取视频帧,然后在每一帧上执行人脸检测,并得到人脸的位置信息。检测到的人脸位置信息将存储在 faces 变量中,以便后续的处理和绘制边界框。

(7)for (x, y, w, h) in faces:
               cv2.rectangle(frame, (x, y-50), (x+w, y+h+10), (255, 0, 0), 2)
               roi_gray = gray[y:y + h, x:x + w]
               cropped_img = np.expand_dims(np.expand_dims(cv2.resize(roi_gray, (48, 48)), -1), 0)
               prediction = model.predict(cropped_img)
               maxindex = int(np.argmax(prediction))
               cv2.putText(frame, emotion_dict[maxindex], (x+20, y-60), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)

这段代码是在检测到的人脸周围绘制边界框,并使用模型对人脸进行情绪识别,并将识别结果在图像上显示出来。
具体来说,代码执行以下操作:

1.使用 cv2.rectangle 在帧 frame 上绘制一个矩形框,用于框定检测到的人脸区域。矩形框的坐标由 (x, y) 和 (x+w, y+h) 定义,颜色为 (255, 0, 0)(蓝色),线宽为 2。
2.从灰度图像 gray 中提取出人脸区域的灰度图像 roi_gray,该区域由矩形框 (x, y, w, h) 定义。
3.使用 cv2.resize 调整 roi_gray 的大小为 (48, 48),并添加两个维度扩展为 (1, 48, 48, 1) 的数组,以符合模型输入的要求。
4.使用模型 model 对调整大小后的人脸图像进行情绪预测,得到预测结果 prediction。
5.通过 np.argmax(prediction) 找到预测结果中概率最高的类别索引 maxindex。
6.使用 cv2.putText 在帧 frame 上绘制预测的情绪类别文字,坐标为 (x+20, y-60),字体为 cv2.FONT_HERSHEY_SIMPLEX,字体大小为 1,颜色为 (255, 255, 255)(白色),线宽为 2,字体线型为 cv2.LINE_AA。

这段代码实现了在实时视频中检测人脸并进行情绪识别,然后在检测到的人脸周围绘制边界框并显示识别结果。

(8)  cv2.imshow("Frame", frame)
      key = cv2.waitKey(1) & 0xFF

这部分代码使用 OpenCV 的 cv2.imshow() 方法在窗口中显示处理后的帧 frame,窗口标题为 "Frame"。然后使用 cv2.waitKey() 方法等待用户按下键盘上的键,并返回按键的 ASCII 值(只保留最后八位)。通常情况下,等待键盘输入的时间为 1 毫秒。
在这个循环中,窗口会一直显示帧 frame,直到用户按下键盘上的键为止。然后,将按键的 ASCII 值与 0xFF 进行按位与运算,以确保得到的结果在 0 到 255 的范围内。这个过程可以确保在不同的操作系统上都能正确处理键盘输入。

(9)if key == ord("q"):
         break

这个条件语句检查用户是否按下了键盘上的 "q" 键。如果按下了 "q" 键(即按键的 ASCII 值等于 "q" 的 ASCII 值),则会执行 break 语句,退出循环,从而结束程序的执行。
这段代码允许用户在观看视频流的过程中按下 "q" 键来退出程序,以提供用户控制程序执行的能力。

(10)cap.release()
           cv2.destroyAllWindows()

这两行代码用于释放摄像头资源并关闭所有的 OpenCV 窗口。具体来说:

1.cap.release() 释放了之前创建的视频捕获对象 cap,这样就会停止视频流的捕获。
2.cv2.destroyAllWindows() 关闭了所有通过 OpenCV 打开的窗口,包括之前用于显示视频流的窗口。

这两行代码通常在程序的最后用于清理工作,以确保在程序退出时释放资源并关闭窗口,避免资源泄漏和窗口未关闭的情况。

3.运行结果

train模式

 display模式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_1027979.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA的NIO和BIO底层原理分析

文章目录 一、操作系统底层IO原理1. 简介2. 操作系统进行IO的流程 二、BIO底层原理1. 什么是Socket2. JDK原生编程的BIO 三、Java原生编程的NIO1. 简介2. NIO和BIO的主要区别3. Reactor模式4. NIO的三大核心组件5. NIO核心源码分析 一、操作系统底层IO原理 1. 简介 IO&#x…

马斯克旗下xAI发布Grok-1.5,相比较开源的Grok-1,各项性能大幅提升,接近GPT-4!

本文原文来自DataLearnerAI官方网站:马斯克旗下xAI发布Grok-1.5,相比较开源的Grok-1,各项性能大幅提升,接近GPT-4! | 数据学习者官方网站(Datalearner) 继Grok-1开源之后,xAI宣布了Grok-1.5的内测消息&…

qt学习第三天,qt设计师的第一个简单案例

3月25,应用qt设计师,手动设计界面形状 ​ 如何启动qt设计师,找到对应的安装地点,对应你自己安装的pyside6或其他qt的安装路径来找 ​ 应用qt设计师的优点是不用敲代码然后慢慢调节框框大小,位置等、可以直接修改…

武汉星起航:亚马逊物流创新,塑造未来零售的新篇章

亚马逊,作为全球电商的领军者,不仅在商品销售方面取得了举世瞩目的成就,更在物流领域进行了一系列颠覆性的创新。武汉星起航了解到这些创新不仅提升了消费者的购物体验,也为整个物流行业树立了新的标杆。 亚马逊在物流技术方面的…

201基于matlab的成绩管理系统

基于matlab的成绩管理系统。自带的GUI界面设计了一个成绩管理界面,可进行成绩的载入、查询、绘图、求平均分。可更改自己的数据进行录入。包含作业文档。程序已调通,可直接运行。 201 matlab 成绩管理系统 GUI - 小红书 (xiaohongshu.com)

“数据持久化”和“缓存与数据库不一致”到底有什么区别?

之前,我一直把“数据持久化”和“缓存与数据库不一致问题”给搞混了。我当时复习的时候基本上就没有思考,就是纯背诵,数据持久化是什么,数据持久化有两种方式,这两种方式特点是什么,然后巴拉巴拉一堆。缓存…

k8s入门到实战(三)—— 三台服务器从零开始搭建k8s集群

服务器裸机搭建 k8s 集群 环境准备 至少3个服务器(本次使用3台阿里云服务器),4核4G以上(按量付费),内网要能互相通信,也就是必须要在同一个网段下 本次实验的3个服务器私网 ip 如下&#xff…

【数据结构 | 图论】如何用链式前向星存图(保姆级教程,详细图解+完整代码)

一、概述 链式前向星是一种用于存储图的数据结构,特别适合于存储稀疏图,它可以有效地存储图的边和节点信息,以及边的权重。 它的主要思想是将每个节点的所有出边存储在一起,通过数组的方式连接(类似静态数组实现链表…

海外媒体发稿:10种提升出口贸易媒体发稿推广的方法-华媒舍

出口贸易对于一个国家的经济发展至关重要。而有效的媒体发稿推广是扩大出口贸易的关键。本篇科普介绍文章将为大家介绍10种提升出口贸易媒体发稿推广效果的秘笈。 1. 独特而吸引人的标题 一个独特而吸引人的标题是吸引媒体和读者关注的第一步。确保标题简洁、具有吸引力&#…

实战 | 微调训练TrOCR识别弯曲文本

导 读 本文主要介绍如何通过微调训练TrOCR实现弯曲文本识别。 背景介绍 TrOCR(基于 Transformer 的光学字符识别)模型是性能最佳的 OCR 模型之一。在我们之前的文章中,我们分析了它们在单行打印和手写文本上的表现。 TrOCR—基于Transforme…

微信小程序实战:无痛集成腾讯地图服务

在移动互联网时代,地图服务无疑是应用程序中最常见也最实用的功能之一。无论是导航定位、附近搜索还是路线规划,地图服务都能为用户提供极大的便利。在微信小程序开发中,我们可以轻松集成腾讯地图服务,为小程序赋能增值体验。本文将详细介绍如何在微信小程序中集成使用腾讯地图…

Uos中Qt Creator中无法显示qDebug()相关信息

[TOC](Uos中Qt Creator中无法显示qDebug()相关信息) 一、概述 操作系统:统信 UOS 20.1070 在Uos系统中,我在Qt Creator中写了 qDebug()等代码,但是在 应用程序 输出中无法看到对应的调试输出,但是使用的 std::cout 等输出功能无…

查询优化-提升子查询-UNION类型

瀚高数据库 目录 文档用途 详细信息 文档用途 剖析UNION类型子查询提升的条件和过程 详细信息 注:图片较大,可在浏览器新标签页打开。 SQL: SELECT * FROM score sc, LATERAL(SELECT * FROM student WHERE sno 1 UNION ALL SELECT * FROM student…

服务器基础知识(物理服务器云服务器)

今天我们来介绍一下服务器的基础知识 一、服务器硬件基础知识 组件说明中央处理器(CPU)CPU是服务器的大脑,负责执行计算任务和指令。服务器通常配备多个CPU核心,以支持并行处理和提高性能。关键的CPU性能指标包括时钟频率、核心数…

DDos系列攻击原理与防御原理

七层防御体系 静态过滤 命中黑名单 对确定是攻击的流量直接加入黑名单(源地址命中黑名单直接丢弃,缺乏机动性和扩展性) 畸形报文过滤 畸形报文攻击 TCP包含多个标记位,排列组合有规律 • 现象:TCP标记位全为1 …

快速熟悉ElasticSearch的基本概念

1.全文检索 全文检索是通过文本内容进行全面搜索的技术。通过全文检索可以快速地在大量文本数据中查找包含特定关键词或者短语的文档,并且返回相关的搜索结果。 检索和查询的区别 检索没有搜索条件边界,检索的结果取决于相关性,相关性计算…

命令模式(请求与具体实现解耦)

目录 前言 UML plantuml 类图 实战代码 模板 Command Invoker Receiver Client 前言 命令模式解耦了命令请求者(Invoker)和命令执行者(receiver),使得 Invoker 不再直接引用 receiver,而是依赖于…

leetcode 25 K 个一组反转链表

leetcode 25 K 个一组反转链表 原题链接 问题 给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。 k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保…

搜维尔科技:【应急演练】【工业仿真】救援模拟演练可视化仿真项目实施

安全救援综合演练系统是一套面向公共安全事故、预案管理、应急救援模拟演练的虚拟仿真解决方案,它为警察、消防以及专门的应急救援保障部门提供一个综合的应急救援培训和仿真演练平台。平台主要通过设计不同的事故模型和特定的灾难场景,定制不同的应急救…

Java毕业设计-基于springboot开发的游戏分享网站平台-毕业论文+答辩PPT(附源代码+演示视频)

文章目录 前言一、毕设成果演示(源代码在文末)二、毕设摘要展示1、开发说明2、需求分析3、系统功能结构 三、系统实现展示1、系统功能模块2、后台登录2.1管理员功能模块2.2用户功能模块 四、毕设内容和源代码获取总结 Java毕业设计-基于springboot开发的…