1 前言
?? 優(yōu)質(zhì)競(jìng)賽項(xiàng)目系列,今天要分享的是
?? 基于深度學(xué)習(xí)的駕駛行為狀態(tài)檢測(cè)系統(tǒng)
該項(xiàng)目較為新穎,適合作為競(jìng)賽課題方向,學(xué)長(zhǎng)非常推薦!
??學(xué)長(zhǎng)這里給一個(gè)題目綜合評(píng)分(每項(xiàng)滿分5分)
- 難度系數(shù):3分
- 工作量:3分
- 創(chuàng)新點(diǎn):5分
?? 更多資料, 項(xiàng)目分享:文章來源:http://www.zghlxwxcb.cn/news/detail-726242.html
https://gitee.com/dancheng-senior/postgraduate文章來源地址http://www.zghlxwxcb.cn/news/detail-726242.html
1 課題背景
為了有效監(jiān)測(cè)駕駛員是否疲勞駕駛、避免交通事故的發(fā)?,本項(xiàng)目利??臉特征點(diǎn)進(jìn)?實(shí)時(shí)疲勞駕駛檢測(cè)的新?法。對(duì)駕駛員駕駛時(shí)的?部圖像進(jìn)?實(shí)時(shí)監(jiān)控,?先檢測(cè)?臉,并利?ERT算法定位?臉特征點(diǎn);然后根據(jù)?臉眼睛區(qū)域的特征點(diǎn)坐標(biāo)信息計(jì)算眼睛縱橫?EAR來描述眼睛張開程度,根據(jù)合適的EAR閾值可判斷睜眼或閉眼狀態(tài);最后基于EAR實(shí)測(cè)值和EAR閾值對(duì)監(jiān)控視頻計(jì)算閉眼時(shí)間?例(PERCLOS)值度量駕駛員主觀疲勞程度,將其與設(shè)定的疲勞度閾值進(jìn)??較即可判定是否疲勞駕駛。
2 相關(guān)技術(shù)
2.1 Dlib人臉識(shí)別庫
簡(jiǎn)歷
Dlib是一個(gè)基于c++開發(fā)的開源數(shù)據(jù)工具庫,其中包含了不少的機(jī)器學(xué)習(xí)的成熟算法與模型,相對(duì)于tensorflow和PyTorch,它用于圖像處理以及人臉面部特征提取、分類及對(duì)比這幾個(gè)方面比較具有通用性和優(yōu)越性,因此,Dlib正在越來越廣泛地應(yīng)用在人臉識(shí)別技術(shù)領(lǐng)域。
Dlib具有獨(dú)立使用的可移植代碼。Dlib中的代碼使用c++語言進(jìn)行開發(fā)而成,使用獨(dú)立封裝,在不借助第三方數(shù)據(jù)庫的情況下,可以直接移植到自己所需要設(shè)計(jì)的項(xiàng)目中進(jìn)行使用。
Dlib優(yōu)點(diǎn)
-
Dlib擁有全面的文檔說明。作為一個(gè)開源的人臉數(shù)據(jù)庫訓(xùn)練集,Dlib中有很多功能齊全的程序和文件,從人性化的角度而言的,Dlib在這一點(diǎn)上做的是非常不錯(cuò)的,因?yàn)樗鼮槊恳粋€(gè)程序文檔和文件都做了相對(duì)應(yīng)的注釋,這樣開發(fā)者就可以迅速準(zhǔn)確的調(diào)集程序文檔來完成自己所需要的項(xiàng)目功能。
-
Dlib涵蓋了支持功能完備的深度學(xué)習(xí)以及圖像處理的各類算法。Dlib為開發(fā)者提供了機(jī)器深度學(xué)習(xí)的各類成熟的完備算法,并且在圖像處理方面也為開發(fā)者帶來了能夠解決大多數(shù)實(shí)質(zhì)問題的優(yōu)良算法。例如基于SVM的遞歸和分類算法,以及專門用于面對(duì)大規(guī)模分類和遞歸的降維算法。當(dāng)然還有能夠?qū)ξ粗瘮?shù)進(jìn)行預(yù)分類和預(yù)測(cè)的相關(guān)向量機(jī),其分類和預(yù)測(cè)訓(xùn)練是基于貝葉斯框架。
相關(guān)代碼
?
import` `matplotlib.pyplot as plt
import` `dlib
import` `numpy as np
import` `glob
import` `re
#正臉檢測(cè)器
detector``=``dlib.get_frontal_face_detector()
#臉部關(guān)鍵形態(tài)檢測(cè)器
sp``=``dlib.shape_predictor(r``"D:LBJAVAscriptshape_predictor_68_face_landmarks.dat"``)
#人臉識(shí)別模型
facerec ``=` `dlib.face_recognition_model_v1(r``"D:LBJAVAscriptdlib_face_recognition_resnet_model_v1.dat"``)
#候選人臉部描述向量集
descriptors``=``[]
photo_locations``=``[]
for` `photo ``in` `glob.glob(r``'D:LBJAVAscriptfaces*.jpg'``):
``photo_locations.append(photo)
``img``=``plt.imread(photo)
``img``=``np.array(img)
``#開始檢測(cè)人臉
``dets``=``detector(img,``1``)
``for` `k,d ``in` `enumerate``(dets):
``#檢測(cè)每張照片中人臉的特征
``shape``=``sp(img,d)
``face_descriptor``=``facerec.compute_face_descriptor(img,shape)
``v``=``np.array(face_descriptor)
``descriptors.append(v)
#輸入的待識(shí)別的人臉處理方法相同
img``=``plt.imread(r``'D:test_photo10.jpg'``)
img``=``np.array(img)
dets``=``detector(img,``1``)
#計(jì)算輸入人臉和已有人臉之間的差異程度(比如用歐式距離來衡量)
differences``=``[]
for` `k,d ``in` `enumerate``(dets):
``shape``=``sp(img,d)
``face_descriptor``=``facerec.compute_face_descriptor(img,shape)
``d_test``=``np.array(face_descriptor)
``#計(jì)算輸入人臉和所有已有人臉描述向量的歐氏距離
``for` `i ``in` `descriptors:
``distance``=``np.linalg.norm(i``-``d_test)
``differences.append(distance)
#按歐式距離排序 歐式距離最小的就是匹配的人臉
candidate_count``=``len``(photo_locations)
candidates_dict``=``dict``(``zip``(photo_locations,differences))
candidates_dict_sorted``=``sorted``(candidates_dict.items(),key``=``lambda` `x:x[``1``])
#matplotlib要正確顯示中文需要設(shè)置
plt.rcParams[``'font.family'``] ``=` `[``'sans-serif'``]
plt.rcParams[``'font.sans-serif'``] ``=` `[``'SimHei'``]
plt.rcParams[``'figure.figsize'``] ``=` `(``20.0``, ``70.0``)
ax``=``plt.subplot(candidate_count``+``1``,``4``,``1``)
ax.set_title(``"輸入的人臉"``)
ax.imshow(img)
for` `i,(photo,distance) ``in` `enumerate``(candidates_dict_sorted):
``img``=``plt.imread(photo)
``face_name``=``""
``photo_name``=``re.search(r``'([^\]*).jpg$'``,photo)
``if` `photo_name:
``face_name``=``photo_name[``1``]
``ax``=``plt.subplot(candidate_count``+``1``,``4``,i``+``2``)
``ax.set_xticks([])
``ax.set_yticks([])
``ax.spines[``'top'``].set_visible(``False``)
``ax.spines[``'right'``].set_visible(``False``)
``ax.spines[``'bottom'``].set_visible(``False``)
``ax.spines[``'left'``].set_visible(``False``)
``if` `i``=``=``0``:
``ax.set_title(``"最匹配的人臉nn"``+``face_name``+``"nn差異度:"``+``str``(distance))
``else``:
``ax.set_title(face_name``+``"nn差異度:"``+``str``(distance))
``ax.imshow(img)
plt.show()
2.2 疲勞檢測(cè)算法
該系統(tǒng)采用Dlib庫中人臉68個(gè)關(guān)鍵點(diǎn)檢測(cè)shape_predictor_68_face_landmarks.dat的dat模型庫及視頻中的人臉,之后返回人臉特征點(diǎn)坐標(biāo)、人臉框及人臉角度等。本系統(tǒng)利用這68個(gè)關(guān)鍵點(diǎn)對(duì)駕駛員的疲勞狀態(tài)進(jìn)行檢測(cè),算法如下:
- 初始化Dlib的人臉檢測(cè)器(HOG),然后創(chuàng)建面部標(biāo)志物預(yù)測(cè);
- 使用dlib.get_frontal_face_detector() 獲得臉部位置檢測(cè)器;
- 使用dlib.shape_predictor獲得臉部特征位置檢測(cè)器;
- 分別獲取左、右眼面部標(biāo)志的索引;
- 打開cv2本地?cái)z像頭。
Dlib庫68個(gè)特征點(diǎn)模型如圖所示:
眼睛檢測(cè)算法
基于EAR算法的眨眼檢測(cè),當(dāng)人眼睜開時(shí),EAR在某個(gè)值域范圍內(nèi)波動(dòng),當(dāng)人眼閉合時(shí),EAR迅速下降,理論上接近于0。當(dāng)EAR低于某個(gè)閾值時(shí),眼睛處于閉合狀態(tài);當(dāng)EAR由某個(gè)值迅速下降至小于該閾值,再迅速上升至大于該閾值,則判斷為一次眨眼。為檢測(cè)眨眼次數(shù),需要設(shè)置同一次眨眼的連續(xù)幀數(shù)。眨眼速度較快,一般1~3幀即可完成眨眼動(dòng)作。眼部特征點(diǎn)如圖:
EAR計(jì)算公式如下:
當(dāng)后幀眼睛寬高比與前一幀差值的絕對(duì)值(EAR)大于0.2時(shí),認(rèn)為駕駛員在疲勞駕駛。(68點(diǎn)landmark中可以看到37-42為左眼,43-48為右眼)
右眼開合度可以通過以下公式:
眼睛睜開度從大到小為進(jìn)入閉眼期,從小到大為進(jìn)入睜眼期,計(jì)算最長(zhǎng)閉眼時(shí)間(可用幀數(shù)來代替)。閉眼次數(shù)為進(jìn)入閉眼、進(jìn)入睜眼的次數(shù)。通過設(shè)定單位時(shí)間內(nèi)閉眼次數(shù)、閉眼時(shí)間的閾值判斷人是否已經(jīng)疲勞了。
相關(guān)代碼:
?
# 疲勞檢測(cè),檢測(cè)眼睛和嘴巴的開合程度
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 # 數(shù)據(jù)處理的庫 numpy
import argparse
import imutils
import time
import dlib
import cv2
import math
import time
from threading import Thread
def eye_aspect_ratio(eye):
# 垂直眼標(biāo)志(X,Y)坐標(biāo)
A = dist.euclidean(eye[1], eye[5]) # 計(jì)算兩個(gè)集合之間的歐式距離
B = dist.euclidean(eye[2], eye[4])
# 計(jì)算水平之間的歐幾里得距離
# 水平眼標(biāo)志(X,Y)坐標(biāo)
C = dist.euclidean(eye[0], eye[3])
# 眼睛長(zhǎng)寬比的計(jì)算
ear = (A + B) / (2.0 * C)
# 返回眼睛的長(zhǎng)寬比
return ear
打哈欠檢測(cè)算法
基于MAR算法的哈欠檢測(cè),利用Dlib提取嘴部的6個(gè)特征點(diǎn),通過這6個(gè)特征點(diǎn)的坐標(biāo)(51、59、53、57的縱坐標(biāo)和49、55的橫坐標(biāo))來計(jì)算打哈欠時(shí)嘴巴的張開程度。當(dāng)一個(gè)人說話時(shí),點(diǎn)51、59、53、57的縱坐標(biāo)差值增大,從而使MAR值迅速增大,反之,當(dāng)一個(gè)人閉上嘴巴時(shí),MAR值迅速減小。
嘴部主要取六個(gè)參考點(diǎn),如下圖:
計(jì)算公式:
通過公式計(jì)算MAR來判斷是否張嘴及張嘴時(shí)間,從而確定駕駛員是否在打哈欠。閾值應(yīng)經(jīng)過大量實(shí)驗(yàn),能夠與正常說話或哼歌區(qū)分開來。為提高判斷的準(zhǔn)確度,采用雙閾值法進(jìn)行哈欠檢測(cè),即對(duì)內(nèi)輪廓進(jìn)行檢測(cè):結(jié)合張口度與張口時(shí)間進(jìn)行判斷。Yawn為打哈欠的幀數(shù),N為1
min內(nèi)總幀數(shù),設(shè)雙閾值法哈欠檢測(cè)的閾值為10%,當(dāng)打哈欠頻率Freq>10%時(shí),則認(rèn)為駕駛員打了1個(gè)深度哈欠或者至少連續(xù)2個(gè)淺哈欠,此時(shí)系統(tǒng)進(jìn)行疲勞提醒。
相關(guān)代碼:
?
# 疲勞檢測(cè),檢測(cè)眼睛和嘴巴的開合程度
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 # 數(shù)據(jù)處理的庫 numpy
import argparse
import imutils
import time
import dlib
import cv2
import math
import time
from threading import Thread
def mouth_aspect_ratio(mouth): # 嘴部
A = np.linalg.norm(mouth[2] - mouth[10]) # 51, 59
B = np.linalg.norm(mouth[4] - mouth[8]) # 53, 57
C = np.linalg.norm(mouth[0] - mouth[6]) # 49, 55
mar = (A + B) / (2.0 * C)
return mar
?
點(diǎn)頭檢測(cè)算法
基于HPE算法的點(diǎn)頭檢測(cè):算法步驟:2D人臉關(guān)鍵點(diǎn)檢測(cè),3D人臉模型匹配,求解3D點(diǎn)和對(duì)應(yīng)2D點(diǎn)的轉(zhuǎn)換關(guān)系,根據(jù)旋轉(zhuǎn)矩陣求解歐拉角。檢測(cè)過程中需要使用世界坐標(biāo)系(UVW)、相機(jī)坐標(biāo)系(XYZ)、圖像中心坐標(biāo)系(uv)和像素坐標(biāo)系(xy)。一個(gè)物體相對(duì)于相機(jī)的姿態(tài)可以使用旋轉(zhuǎn)矩陣和平移矩陣來表示。
- 平移矩陣:物體相對(duì)于相機(jī)的空間位置關(guān)系矩陣,用T表示。
- 旋轉(zhuǎn)矩陣:物體相對(duì)于相機(jī)的空間姿態(tài)關(guān)系矩陣,用R表示。
因此必然少不了坐標(biāo)系轉(zhuǎn)換。如圖所示:
于是世界坐標(biāo)系(UVW)、相機(jī)坐標(biāo)系(XYZ)、圖像中心坐標(biāo)系(uv)和像素坐標(biāo)系(xy)四兄弟閃亮登場(chǎng)。相對(duì)關(guān)系如:
世界坐標(biāo)系轉(zhuǎn)換到相機(jī)坐標(biāo):
相機(jī)坐標(biāo)系轉(zhuǎn)換到像素坐標(biāo)系:
像素坐標(biāo)系與世界坐標(biāo)系的關(guān)系為:
圖像中心坐標(biāo)系轉(zhuǎn)換到像素坐標(biāo)系:
得到旋轉(zhuǎn)矩陣后,求歐拉角:
設(shè)定參數(shù)閾值為0.3,在一個(gè)時(shí)間段,如10
s內(nèi),當(dāng)?shù)皖^歐拉角|Pitch|≥20°或者頭部?jī)A斜歐拉角|Roll|≥20°的時(shí)間比例超過0.3時(shí),則認(rèn)為駕駛員處于瞌睡狀態(tài),發(fā)出預(yù)警。
2.3 YOLOV5算法
簡(jiǎn)介
我們選擇當(dāng)下YOLO最新的卷積神經(jīng)網(wǎng)絡(luò)YOLOv5來進(jìn)行檢測(cè)是否存在玩手機(jī)、抽煙、喝水這三種行為。6月9日,Ultralytics公司開源了YOLOv5,離上一次YOLOv4發(fā)布不到50天。而且這一次的YOLOv5是完全基于PyTorch實(shí)現(xiàn)的!在我們還對(duì)YOLOv4的各種高端操作、豐富的實(shí)驗(yàn)對(duì)比驚嘆不已時(shí),YOLOv5又帶來了更強(qiáng)實(shí)時(shí)目標(biāo)檢測(cè)技術(shù)。按照官方給出的數(shù)目,現(xiàn)版本的YOLOv5每個(gè)圖像的推理時(shí)間最快0.007秒,即每秒140幀(FPS),但YOLOv5的權(quán)重文件大小只有YOLOv4的1/9。
目標(biāo)檢測(cè)架構(gòu)分為兩種,一種是two-stage,一種是one-stage,區(qū)別就在于 two-stage 有region
proposal過程,類似于一種海選過程,網(wǎng)絡(luò)會(huì)根據(jù)候選區(qū)域生成位置和類別,而one-stage直接從圖片生成位置和類別。今天提到的 YOLO就是一種
one-stage方法。YOLO是You Only Look Once的縮寫,意思是神經(jīng)網(wǎng)絡(luò)只需要看一次圖片,就能輸出結(jié)果。YOLO
一共發(fā)布了五個(gè)版本,其中 YOLOv1 奠定了整個(gè)系列的基礎(chǔ),后面的系列就是在第一版基礎(chǔ)上的改進(jìn),為的是提升性能。
YOLOv5有4個(gè)版本性能如圖所示:
網(wǎng)絡(luò)架構(gòu)圖
3 效果展示
3.1 眨眼
3.2 打哈欠
3.3 使用手機(jī)檢測(cè)
3.4 抽煙檢測(cè)
3.5 喝水檢測(cè)
4 最后
?? 更多資料, 項(xiàng)目分享:
https://gitee.com/dancheng-senior/postgraduate
到了這里,關(guān)于計(jì)算機(jī)競(jìng)賽 深度學(xué)習(xí)駕駛行為狀態(tài)檢測(cè)系統(tǒng)(疲勞 抽煙 喝水 玩手機(jī)) - opencv python的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!