基于MTCNN+CNN的疲劳(危险)驾驶检测系统设计

一.设计原理

在人脸检测中应用较广的算法就是MTCNN( Multi-task Cascaded Convolutional Networks的缩写)。MTCNN算法是一种基于深度学习的人脸检测和人脸对齐方法,它可以同时完成人脸检测和人脸对齐的任务,相比于传统的算法,它的性能更好,检测速度更快。
本文目的不是为了强调MTCNN模型的训练,而是如何使用MTCNN提取人脸区域和特征点,然后依据“三庭五眼”的理论把人脸分成眼睛、嘴巴、耳朵三个区域后将图像传入训练好的图像分类模型,判断闭眼、睁眼、张嘴、闭嘴、吸烟、电话,在疲劳判断上使用PERCLOS的判断标准,将结果反馈。

二.MTCNN人脸检测

MTCNN 包含三个级联的多任务卷积神经网络,分别是 Proposal Network (P-Net)、Refine Network (R-Net)、Output Network (O-Net),每个多任务卷积神经网络均有三个学习任务,分别是人脸分类、边框回归和关键点定位。MTCNN模块我用的是GitHub的一个项目,通过检测到人脸的五个关键点,定义左、右眼中心点连线与水平方向的夹角为 θ,眼部区域宽度为W, 高度为 H=w/2。从鼻尖点位 C 向左右嘴角连线作垂线, 记垂距为D。嘴部区域上、下沿分别取该垂线及其延长线上D/2 和 3D/2 处。具体可以看代码`

left_eye=keypoints['left_eye']
right_eye=keypoints['right_eye']
nose=keypoints['nose']
mouth_left=keypoints['mouth_left']
mouth_right=keypoints['mouth_right']
arc = atan(abs(right_eye[1] - left_eye[1]) / abs(right_eye[0] - left_eye[0]))
W = abs(right_eye[0] - left_eye[0]) / (2 * cos(arc))
H = W / 2
D=(mouth_left[1]-nose[1])/cos(arc)-(mouth_left[1]-mouth_right[1])/(2*cos(arc))

`

三.CNN卷积神经网络图像识别

将数据分类成open_eye,closed_eye,open_mouth,closed_mouth,smoke,call这些类别,通过训练得到一个图像分类模型即可结合mtcnn裁剪的目标区域,识别得出结果

包含 3 个卷积层,3 个池化 层和 2 个全连接层。3 个卷积层中分别包含 32、32 和 64 个 卷积核,卷积核尺寸大小为 5。
模型代码如下:

from keras.models import Sequential
from keras.layers.normalization import BatchNormalization
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers.convolutional import AveragePooling2D
from keras.initializers import TruncatedNormal
from keras.layers.core import Activation
from keras.layers.core import Flatten
from keras.layers.core import Dropout
from keras.layers.core import Dense
from keras import backend as K

class EAMNET:
    @staticmethod
    def build(width, height, depth, classes):
        model = Sequential()
        inputShape = (height, width, depth)
        chanDim = -1

        if K.image_data_format() == "channels_first":
            inputShape = (depth, height, width)
            chanDim = 1

        # CONV => RELU => POOL
        model.add(Conv2D(32, (5, 5), padding="same",
            input_shape=inputShape,kernel_initializer=TruncatedNormal(mean=0.0, stddev=0.01)))
        model.add(Activation("relu"))
        model.add(BatchNormalization(axis=chanDim))
        model.add(MaxPooling2D(pool_size=(2, 2)))
        model.add(Dropout(0.25))

        # (CONV => RELU) * 2 => POOL
        model.add(Conv2D(32, (5, 5), padding="same",kernel_initializer=TruncatedNormal(mean=0.0, stddev=0.01)))
        model.add(Activation("relu"))
        model.add(BatchNormalization(axis=chanDim))
        model.add(MaxPooling2D(pool_size=(2, 2)))
        model.add(Dropout(0.25))

        # (CONV => RELU) * 3 => POOL
        model.add(Conv2D(64, (3, 3), padding="same",kernel_initializer=TruncatedNormal(mean=0.0, stddev=0.01)))
        model.add(Activation("relu"))
        model.add(BatchNormalization(axis=chanDim))
        model.add(MaxPooling2D(pool_size=(2, 2)))
        model.add(Dropout(0.25))

        # FC层
        model.add(Flatten())
        model.add(Dense(64,kernel_initializer=TruncatedNormal(mean=0.0, stddev=0.01)))
        model.add(Activation("relu"))
        model.add(BatchNormalization())
        model.add(Dropout(0.6))

        # softmax 分类
        model.add(Dense(classes,kernel_initializer=TruncatedNormal(mean=0.0, stddev=0.01)))
        model.add(Activation("softmax"))

        return model
model=EAMNET.build(32,32,1,6)
model.summary()

训练代码如下:

# set the matplotlib backend so figures can be saved in the background
import keras
import matplotlib
from keras.callbacks import ReduceLROnPlateau, EarlyStopping, ModelCheckpoint
from keras.engine.saving import load_model
from keras.utils import to_categorical
from sklearn.metrics import classification_report

from SimpleVGGNet import SimpleVGG
from EAMNet import EAMNET

matplotlib.use("Agg")

# import the necessary packages
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import Adam
from keras.preprocessing.image import img_to_array
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from imutils import paths
import numpy as np
import argparse
import random
import pickle
import cv2
import os

dataset="./dataset/"
EPOCHS =100
INIT_LR = 0.01
BS = 64
IMAGE_DIMS = (64, 64, 1)
classnum=2
# initialize the data and labels
data = []
labels = []

# grab the image paths and randomly shuffle them
print("[INFO] loading images...")
imagePaths = sorted(list(paths.list_images(dataset)))
# print(imagePaths)
random.seed(10010)
random.shuffle(imagePaths)

# loop over the input images
for imagePath in imagePaths:
    # load the image, pre-process it, and store it in the data list
    image = cv2.imread(imagePath,cv2.IMREAD_GRAYSCALE)
    print(imagePath)
    image = cv2.resize(image, (IMAGE_DIMS[1], IMAGE_DIMS[0]))
    image = img_to_array(image)
    data.append(image)

    # extract the class label from the image path and update the
    # labels list
    label = imagePath.split(os.path.sep)[-2]
    labels.append(label)
# scale the raw pixel intensities to the range [0, 1]
print(labels)
data = np.array(data, dtype="float") / 255.0
labels = np.array(labels)
print("[INFO] data matrix: {:.2f}MB".format(
    data.nbytes / (1024 * 1000.0)))

# 数据集切分
(trainX, testX, trainY, testY) = train_test_split(data,labels, test_size=0.25, random_state=42)

# 转换标签为one-hot encoding格式
lb = LabelBinarizer()
print(lb)
trainY = lb.fit_transform(trainY)
testY = lb.fit_transform(testY)

trainY = to_categorical(trainY)
testY = to_categorical(testY)
# construct the image generator for data augmentation
aug = ImageDataGenerator(rotation_range=25, width_shift_range=0.1,
                         height_shift_range=0.1, shear_range=0.2, zoom_range=0.2,
                         horizontal_flip=True, fill_mode="nearest")
# initialize the model
print("[INFO] compiling model...")
model = SimpleVGG.build(width=IMAGE_DIMS[1], height=IMAGE_DIMS[0],
                            depth=IMAGE_DIMS[2], classes=classnum)
# model=load_model('./model/best0428ep150.h5')
opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS)
model.summary()
model.compile(loss="categorical_crossentropy", optimizer=opt,
              metrics=["accuracy"])
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=5, verbose=1)
early_stopping = EarlyStopping(monitor='val_loss', min_delta=0, patience=10, verbose=1)
# train the network
filepath="./model/best0428ep150.h5"
checkpoint = ModelCheckpoint(filepath, monitor='val_acc', verbose=1, save_best_only=True,mode='max')

H = model.fit_generator(
    aug.flow(trainX, trainY, batch_size=BS),
    validation_data=(testX, testY),
    steps_per_epoch=len(trainX) // BS,
   callbacks=[reduce_lr,checkpoint],
    epochs=EPOCHS, verbose=1)
# save the model to disk
model.save('./model/best0428ep150.h5')
# plot the training loss and accuracy
# 测试
print("------测试网络------")
predictions = model.predict(testX, batch_size=32)
print(classification_report(testY.argmax(axis=1),
    predictions.argmax(axis=1), target_names=lb.classes_))

plt.style.use("ggplot")
plt.figure()
N = EPOCHS
plt.plot(np.arange(0, N), H.history["loss"], label="train_loss")
plt.plot(np.arange(0, N), H.history["val_loss"], label="val_loss")
plt.plot(np.arange(0, N), H.history["acc"], label="train_acc")
plt.plot(np.arange(0, N), H.history["val_acc"], label="val_acc")
plt.title("Training Loss and Accuracy")
plt.xlabel("Epoch #")
plt.ylabel("Loss/Accuracy")
plt.legend(loc="upper left")
plt.savefig("./model/best0428ep150.png")
f = open("./model/best0428ep150.pickle", "wb")
f.write(pickle.dumps(lb))
f.close()

四.疲劳判断

PERCLOS的测量的参数是指在单位时间内眼睛闭合程度超过某一闭值(70%、80%)的时间占总时间的百分比。PERCLOS方法的常用标准如下:
P7O:指眼睑遮住瞳孔的面积超过70%就计为眼睛闭合,统计在一定时间内眼睛闭合时所占的时间比例。
P80:指眼睑遮住瞳孔的面积超过80%就计为眼睛闭合,统计在一定时间内眼睛闭合时所占的时间比例。
所以可以通过一定时间内判断眼睛闭合的帧/统计的总帧数判断是否达到了疲劳,结合人打哈欠的正常指标,如果超出阈值就判断为哈欠。

五.效果演示

在这里插入图片描述
在这里插入图片描述

六.项目地址

数据集
复制这段内容后打开百度网盘手机APP,操作更方便哦 链接: https://pan.baidu.com/s/1FLfWZix-vsY5XSaV1oi-pA 提取码:pmh0

项目GitHub地址MTCNN_CNN_DangerDrivingDetection
如果觉得有帮助的话点赞star一波,Thanks♪(・ω・)ノ
另外还有使用SSD目标检测算法做的疲劳驾驶检测系统还没有写文章,如果有需要也可以直接看项目
MTCNN模块使用了开源的项目,也可以自己训练。

  • 41
    点赞
  • 218
    收藏
    觉得还不错? 一键收藏
  • 90
    评论
### 回答1: 基于CNN驾驶疲劳检测系统是一种利用卷积神经网络CNN)算法来检测和预防驾驶疲劳的技术。该系统基于深度学习原理,通过分析驾驶员的眼部特征和行为模式来判断驾驶员是否疲劳,从而提高驾驶的安全性。 该系统的工作原理如下:首先,通过摄像头或红外传感器实时监测驾驶员的眼部动态特征,包括眨眼频率、瞳孔直径、眼睛位置等,以获取驾驶员的眼部状况信息。然后,将这些眼部特征数据输入到预训练好的CNN模型中,进行特征提取和分类。CNN模型是一种深度神经网络,能够自动学习和识别图像特征,从而进行有效的分类和判断。 基于CNN驾驶疲劳检测系统具有以下优点:首先,通过监测眼部特征来判断驾驶员是否疲劳,避免了传统基于生理信号的方法需要使用额外传感器的复杂性。其次,该系统能够实时监测驾驶员的疲劳状态,一旦检测疲劳情况,能够及时发出警报,提醒驾驶员及时休息,减少交通事故的发生。 然而,基于CNN驾驶疲劳检测系统也存在一些挑战和限制。首先,系统对于光线条件的依赖性较强,光线不足或光照不均匀可能影响识别效果。其次,驾驶员个体差异、表情变化等因素也可能引起检测的误判。同时,保护驾驶员隐私也是一个需要考虑的问题。 总的来说,基于CNN驾驶疲劳检测系统具有重要的应用前景和研究价值,对于提高驾驶的安全性和减少交通事故具有积极意义。 ### 回答2: 基于卷积神经网络CNN)的驾驶疲劳检测系统可以通过分析驾驶员的面部表情和眼部活动来判断其疲劳程度。该系统可以帮助提高驾驶安全性,防止由于驾驶疲劳而引发的交通事故。 首先,系统需要收集大量的驾驶员面部数据和相关的疲劳标签数据。这些数据可以包括驾驶员的表情和眼部特征,以及疲劳程度的分类标签(如清醒、稍微疲劳和严重疲劳)。 其次,使用CNN模型进行训练。CNN是一种专门用于图像处理的深度学习模型,能够从大量图像数据中提取高级特征。在训练过程中,将驾驶员的面部图像作为输入,将对应的疲劳标签作为输出,通过多次迭代优化网络参数,使得网络能够准确地预测驾驶员的疲劳程度。 然后,对于实时的驾驶场景,系统可以通过摄像头实时捕捉驾驶员的面部图像。将这些图像输入到已经训练好的CNN模型中,可以得到对应的疲劳预测结果。如果预测结果显示驾驶员正在出现疲劳系统可以及时发出警告,提醒驾驶员休息或切换驾驶人员,以保证道路安全。 最后,系统还可以不断改进和优化。通过不断收集和标注新的驾驶员数据,重新训练模型,可以提高疲劳检测的准确性和稳定性。此外,还可以考虑将其他传感器数据(如心率和车辆运行状态)融合到系统中,以获得更全面的疲劳检测结果。 总之,基于CNN驾驶疲劳检测系统可以通过分析驾驶员的面部表情和眼部活动来实时判断其疲劳程度。这种系统可以提高驾驶安全性,减少因驾驶疲劳引发的交通事故的发生。 ### 回答3: 基于卷积神经网络CNN)的驾驶疲劳检测系统利用深度学习算法来判断驾驶员是否疲劳,从而提高道路安全性。该系统的工作原理如下: 首先,系统通过车载摄像头实时捕捉驾驶员的面部图像。这些图像被输入到CNN中进行处理和分析。 其次,CNN通过多层卷积层、池化层和全连接层,自动学习面部特征的表达。卷积层用于提取图像中的边缘、纹理等低级特征,池化层用于降低数据维度,全连接层用于将提取到的特征进行分类。 然后,CNN根据学习到的特征,通过训练集的样本,学习到疲劳和非疲劳驾驶员的面部特征模式。这些模式可能包括眼睛的状态、脸部表情和头部姿势等。 最后,在实时监测过程中,驾驶员的面部图像被输入到经过训练的CNN中。CNN会对这些图像进行特征提取,并判断驾驶员是否存在疲劳症状。例如,如果驾驶员的眼睛开始闭合、表情变得呆滞或头部开始倾斜等,则可能表明驾驶员处于疲劳状态。 基于CNN驾驶疲劳检测系统具有以下优点:高度自动化、实时性和准确性。它可以通过自动学习驾驶员的面部特征来判断疲劳状态,避免了传统方法中需要手动设计和选择特征的过程。此外,它在实时监测过程中能够快速响应,并能够准确地识别出疲劳驾驶的特征。 该系统可广泛应用于汽车行业,使驾驶员能够及时发现自己的疲劳状态并采取相应措施,从而降低交通事故的风险,保护驾驶员和其他道路用户的生命安全。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 90
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值