訂閱
糾錯(cuò)
加入自媒體

駕駛員嗜睡分類 - 深度學(xué)習(xí)

瞌睡檢測(cè)是一種汽車安全技術(shù),有助于防止駕駛員在駕駛時(shí)睡著了造成的事故。根據(jù) NHTSA(美國國家公路交通安全管理局)的數(shù)據(jù),警方報(bào)告的 91,000 起車禍涉及疲勞駕駛。這些車禍導(dǎo)致 2017 年估計(jì)有 50,000 人受傷和近 800 人死亡。目前,方法主要集中在使用深度學(xué)習(xí)或機(jī)器學(xué)習(xí)技術(shù)進(jìn)行眨眼檢測(cè),但是,如果司機(jī)戴墨鏡怎么辦?

如果我們同時(shí)考慮駕駛員的頭部?jī)A斜、打哈欠和其他因素會(huì)怎樣?是的,這正是本文所做的。

在進(jìn)入特征提取部分之前,從“ULg 多模態(tài)嗜睡數(shù)據(jù)庫”(也稱為DROZY )中獲取數(shù)據(jù),該數(shù)據(jù)庫包含各種類型的嗜睡相關(guān)數(shù)據(jù)(信號(hào)、圖像等)。

該數(shù)據(jù)集包含大約 45 個(gè)視頻剪輯,這些剪輯按照卡羅林斯卡嗜睡量表 (KSS) 進(jìn)行標(biāo)記。KSS 量表范圍從 1 到 9,其中 1 表示非常警覺,9 表示非常困。

由于該數(shù)據(jù)集中缺少數(shù)據(jù)和標(biāo)簽,因此將標(biāo)簽從 1-9 轉(zhuǎn)換為 1-3,分別表示無嗜睡、中度嗜睡和高度嗜睡。本來會(huì)使用視頻分類過程,但由于數(shù)據(jù)不夠,先提取特征并將它們用作我的模型輸入。這樣,模型將使用更少的數(shù)據(jù)達(dá)到更準(zhǔn)確的效果。

特征提取

對(duì)于這個(gè)特定任務(wù),我將使用 TensorFlow-GPU 2.6 和 python 3.6 以及使用 pip 預(yù)安裝的庫 open-cv、dlib、scipy。

特征提取所需的所有庫:

from scipy.spatial import distance as dist

from imutils.video import FileVideoStream

from imutils.video import VideoStream

from imutils import face_utils

import numpy as np

import argparse

import imutils

import time

import dlib

import cv2

import datetime

import csv

import os

import math

平均眨眼持續(xù)時(shí)間:眼睛縱橫比低于 0.3 然后高于 0.3 的持續(xù)時(shí)間被檢測(cè)為眨眼。眨眼發(fā)生的時(shí)間稱為眨眼持續(xù)時(shí)間。平均每分鐘眨眼持續(xù)時(shí)間以計(jì)算平均眨眼持續(xù)時(shí)間。

# grab the indexes of the facial landmarks for the left and

# right eye, respectively

(lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]

(rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]

def eye_aspect_ratio(eye):

 A = dist.euclidean(eye[1], eye[5])

 B = dist.euclidean(eye[2], eye[4])

 C = dist.euclidean(eye[0], eye[3])

 ear = (A + B) / (2.0 * C)

 return ear

眨眼頻率:每分鐘眨眼的次數(shù)稱為眨眼頻率。

def time_difference(start_time, end_time):

  start_time = start_time.split()

  for i in range(0,8):

    hours = int(start_time[3])

    mins = int(start_time[4])

    secs = int(start_time[5])

    milisecs = int(start_time[6])

    microsecs = int(start_time[7])

 #converting it to microsecs

 t1, m1, s1, ms1, mis1  = hours, mins, secs, milisecs, microsecs

 start_time_microsecs = mis1 + 1000*(ms1 + 1000*(s1 + 60*(m1 + 60*t1)))

 end_time = end_time.split()

 for x in range(0,8,1):

    hours = int(end_time[3])

    mins = int(end_time[4])

    secs = int(end_time[5])

    milisecs = int(end_time[6])

    microsecs = int(end_time[7])

t2, m2, s2, ms2, mis2  = hours, mins, secs, milisecs, microsecs
end_time_microsecs = mis2 + 1000*(ms2 + 1000*(s2 + 60*(m2 + 60*t2)))

#finding the duration of blink

time_differ = end_time_microsecs - start_time_microsecs

#print 'time_difference in microsecs = ', time_differ

return time_differ

嘴部縱橫比:計(jì)算 MAR 以檢測(cè)一個(gè)人是否在打哈欠。

(omouth, emouth) = face_utils.FACIAL_LANDMARKS_IDXS["mouth"]

def mouth_aspect_ratio(mouth):

   # compute the euclidean distances between the two sets of

   # vertical mouth landmarks (x, y)-coordinates

   A = dist.euclidean(mouth[2], mouth[10])  # 51, 59

   B = dist.euclidean(mouth[4], mouth[8])  # 53, 57

   # compute the euclidean distance between the horizontal

   # mouth landmark (x, y)-coordinates

   C = dist.euclidean(mouth[0], mouth[6])  # 49, 55

   # compute the mouth aspect ratio

   mar = (A + B) / (2.0 * C)

   # return the mouth aspect ratio

   return mar

頭部姿態(tài):每幀計(jì)算不同的角度,得到頭部的姿態(tài)。

def getHeadTiltAndCoords(size, image_points, frame_h(yuǎn)eight):

   focal_length = size[1]

   center = (size[1]/2, size[0]/2)

   camera_matrix = np.a(chǎn)rray([[focal_length, 0, center[0]], [

       0, focal_length, center[1]], [0, 0, 1]], dtype="double")

   dist_coeffs = np.zeros((4, 1))  # Assuming no lens distortion

   (_, rotation_vector, translation_vector) = cv2.solvePnP(model_points, image_points,
                         camera_matrix, dist_coeffs,
                         flags = cv2.SOLVEPNP_ITERATIVE)  # flags=cv2.CV_ITERATIVE)

   (nose_end_point2D, _) = cv2.projectPoints(np.a(chǎn)rray(

       [(0.0, 0.0, 1000.0)]), rotation_vector, translation_vector, camera_matrix, dist_coeffs)

   #get rotation matrix from the rotation vector

   rotation_matrix, _ = cv2.Rodrigues(rotation_vector)

   #calculate head tilt angle in degrees

   head_tilt_degree = abs(

       [-180] - np.rad2deg([rotationMatrixToEulerAngles(rotation_matrix)[0]]))

   #calculate starting and ending points for the two lines for illustration

   starting_point = (int(image_points[0][0]), int(image_points[0][1]))

   ending_point = (int(nose_end_point2D[0][0][0]), int(nose_end_point2D[0][0][1]))

   ending_point_alternate = (ending_point[0], frame_h(yuǎn)eight // 2)

   return head_tilt_degree, starting_point, ending_point, ending_point_alternate

這就是我的特征提取過程中的樣子。

是時(shí)候制作模型了!

由于我們已經(jīng)完成了特征選擇部分,我們不必構(gòu)建復(fù)雜的模型。我將使用人工神經(jīng)網(wǎng)絡(luò)

import numpy as np

import sklearn

from sklearn import preprocessing

#from sklearn.datasets.samples_generator import make_blobs

#from sklearn.preprocessing import LabelEncoder, StandardScaler

import csv

import os

from tensorflow import keras

import random

from keras.models import Sequential

from keras.layers import Dense , Dropout, Activation, BatchNormalization

from keras import regularizers

importmatplotlib.pyplot as plt

#from keras.utils import plot_model

import sklearn

from sklearn.metrics import chaos_matrix

from sklearn.metrics import accuracy_score

from sklearn.metrics import classification_report

import pickle

from keras.utils import np_utils

from keras import optimizers

from keras.models import load_model

這是深度學(xué)習(xí)中最簡(jiǎn)單的模型的設(shè)計(jì),但由于特征提取而有效。因?yàn)槲覀冇?jì)算的是每分鐘的瞌睡程度,所以要確保你將你的輸入連接起來,然后傳遞給模型。

#designing the model

model=Sequential()

model.a(chǎn)dd(Dense(64, input_dim=6, activation='relu'))

model.a(chǎn)dd(Dropout(0.001))

model.a(chǎn)dd(Dense(64, input_dim=6, activation='relu'))

model.a(chǎn)dd(Dropout(0.001))

model.a(chǎn)dd(Dense(32, input_dim=6, activation='relu'))

model.a(chǎn)dd(Dense(16, input_dim=6, activation='relu'))

model.a(chǎn)dd(Dense(4, activation='softmax', use_bias=False))


#compile the model

#adam = keras.optimizers.Adam(lr=0.01)

adam = keras.optimizers.Adam(lr=0.001)

model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy'])


#fit the model

checkpoint = keras.callbacks.ModelCheckpoint(filepath="trained_models/DrowDet_model(output4).hdf5", period=1)

tbCallBack = keras.callbacks.TensorBoard(log_dir='./scalar',

histogram_freq=0, write_graph=True, write_images=True)
history=model.fit(Xtrain, Ytrain, epochs=50, batch_size=256, callbacks=[checkpoint, tbCallBack], validation_data=(Xval,Yval))

使用準(zhǔn)確性與驗(yàn)證準(zhǔn)確性和訓(xùn)練損失與驗(yàn)證損失的模型性能。

超參數(shù)調(diào)優(yōu)模型!我改變了學(xué)習(xí)率(0.01 -> 0.001),不同的優(yōu)化器(RMSprop),時(shí)期數(shù)(20 -> 50)。

使用 Sklearn 的混淆矩陣,我在測(cè)試集上評(píng)估了模型,得到了 73% 的準(zhǔn)確率和 89% 的訓(xùn)練準(zhǔn)確率。再使用大約 4 個(gè)隱藏層,我在測(cè)試集上得到了大約 74% 的準(zhǔn)確率,在訓(xùn)練數(shù)據(jù)集上得到了 93% 的準(zhǔn)確率。

       原文標(biāo)題 : 駕駛員嗜睡分類 - 深度學(xué)習(xí)

聲明: 本文由入駐維科號(hào)的作者撰寫,觀點(diǎn)僅代表作者本人,不代表OFweek立場(chǎng)。如有侵權(quán)或其他問題,請(qǐng)聯(lián)系舉報(bào)。

發(fā)表評(píng)論

0條評(píng)論,0人參與

請(qǐng)輸入評(píng)論內(nèi)容...

請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字

您提交的評(píng)論過于頻繁,請(qǐng)輸入驗(yàn)證碼繼續(xù)

  • 看不清,點(diǎn)擊換一張  刷新

暫無評(píng)論

暫無評(píng)論

人工智能 獵頭職位 更多
掃碼關(guān)注公眾號(hào)
OFweek人工智能網(wǎng)
獲取更多精彩內(nèi)容
文章糾錯(cuò)
x
*文字標(biāo)題:
*糾錯(cuò)內(nèi)容:
聯(lián)系郵箱:
*驗(yàn) 證 碼:

粵公網(wǎng)安備 44030502002758號(hào)