競賽選題 題目: 基于深度學習的疲勞駕駛檢測 深度學習

文章目錄

  • 0 前言
  • 1 課題背景
  • 2 實現目標
  • 3 當前市面上疲勞駕駛檢測的方法
  • 4 相關數據集
  • 5 基于頭部姿態的駕駛疲勞檢測
    • 5.1 如何確定疲勞狀態
    • 5.2 算法步驟
    • 5.3 打瞌睡判斷
  • 6 基于CNN與SVM的疲勞檢測方法
    • 6.1 網絡結構
    • 6.2 疲勞圖像分類訓練
    • 6.3 訓練結果
  • 7 最后

0 前言

🔥 優質競賽項目系列,今天要分享的是

基于深度學習的駕駛疲勞檢測

該項目較為新穎,適合作為競賽課題方向,學長非常推薦!

🧿 更多資料, 項目分享:

https://gitee.com/dancheng-senior/postgraduate

在這里插入圖片描述

1 課題背景

關于對疲勞駕駛的研究不在少數, 不少學者從人物面部入手展開。 人類的面部包含著許多不同的特征信息, 例如其中一些比較明顯的特征如打哈欠、 閉眼、
揉眼等表情特征可用來作為判斷駕駛員是否處于疲勞狀態的依據。 隨著計算機技術的不斷發展, 尤其是在人工智能相關技術勃發的今天,
借助計算機可以快速有效的識別出圖片中人臉特征, 對處于當前時刻駕駛員的精神狀態做出判斷, 并將疲勞預警信息傳達給司機, 以保證交通的安全運行,
減少傷亡事故的發生。

2 實現目標

經查閱相關文獻,疲勞在人體面部表情中表現出大致三個類型:打哈欠(嘴巴張大且相對較長時間保持這一狀態)、眨眼(或眼睛微閉,此時眨眼次數增多,且眨眼速度變慢)、點頭(瞌睡點頭)。本實驗從人臉朝向、位置、瞳孔朝向、眼睛開合度、眨眼頻率、瞳孔收縮率等數據入手,并通過這些數據,實時地計算出駕駛員的注意力集中程度,分析駕駛員是否疲勞駕駛和及時作出安全提示。

3 當前市面上疲勞駕駛檢測的方法

學長通過對疲勞駕駛在不同方法下研究進展的分析, 可以更清晰的認識的到當下對該問題較為有效的判定方法。 根據研究對象的不同對檢測方法進行分類,
具體分類方法如圖

在這里插入圖片描述

基于駕駛員面部特征的檢測方法是根據人在疲勞時面部變化來分析此時的精神狀態。 人在瞌睡、 疲勞時面部表情與清醒時有著明顯的區別。
通過裝置在車輛中的攝像頭對駕駛員人臉圖片的采集, 利用計算機圖像處理和模式識別, 可以有效檢測駕駛員的疲
勞特征信息, 比較直觀的特征有: 打哈欠, 眨眼, 低頭等。

4 相關數據集

學長收集的疲勞檢測數據集

駕駛疲勞人臉數據庫圖片來源分為 3 部分, 每部分均包含疲勞、 輕度疲勞和非疲勞

在這里插入圖片描述

5 基于頭部姿態的駕駛疲勞檢測

5.1 如何確定疲勞狀態

  • 思路一:可利用姿態估計結果(如Pitch的讀數)來判斷是否點頭及點頭幅度

  • 思路二:或用鼻尖處30號點的前后移動值(或是方差,方差表示一個單位時間數據的偏離程度,程度越大,則表示發生點頭動作的概率越大、點頭幅度越大)

在這里插入圖片描述

5.2 算法步驟

  • 第一步:2D人臉關鍵點檢測;

  • 第二步:3D人臉模型匹配;

  • 第三步:求解3D點和對應2D點的轉換關系;

  • 第四步:根據旋轉矩陣求解歐拉角。

    import cv2
    import dlib
    import numpy as np
    from imutils import face_utils
    """
    思路:第一步:2D人臉關鍵點檢測;第二步:3D人臉模型匹配;第三步:求解3D點和對應2D點的轉換關系;第四步:根據旋轉矩陣求解歐拉角。
    """# 加載人臉檢測和姿勢估計模型(dlib)face_landmark_path = 'D:/myworkspace/JupyterNotebook/fatigue_detecting/model/shape_predictor_68_face_landmarks.dat'"""
    只要知道世界坐標系內點的位置、像素坐標位置和相機參數就可以搞定旋轉和平移矩陣(OpenCV自帶函數solvePnp())
    """# 世界坐標系(UVW):填寫3D參考點,該模型參考http://aifi.isr.uc.pt/Downloads/OpenGL/glAnthropometric3DModel.cppobject_pts = np.float32([[6.825897, 6.760612, 4.402142],  #33左眉左上角[1.330353, 7.122144, 6.903745],  #29左眉右角[-1.330353, 7.122144, 6.903745], #34右眉左角[-6.825897, 6.760612, 4.402142], #38右眉右上角[5.311432, 5.485328, 3.987654],  #13左眼左上角[1.789930, 5.393625, 4.413414],  #17左眼右上角[-1.789930, 5.393625, 4.413414], #25右眼左上角[-5.311432, 5.485328, 3.987654], #21右眼右上角[2.005628, 1.409845, 6.165652],  #55鼻子左上角[-2.005628, 1.409845, 6.165652], #49鼻子右上角[2.774015, -2.080775, 5.048531], #43嘴左上角[-2.774015, -2.080775, 5.048531],#39嘴右上角[0.000000, -3.116408, 6.097667], #45嘴中央下角[0.000000, -7.415691, 4.070434]])#6下巴角# 相機坐標系(XYZ):添加相機內參K = [6.5308391993466671e+002, 0.0, 3.1950000000000000e+002,0.0, 6.5308391993466671e+002, 2.3950000000000000e+002,0.0, 0.0, 1.0]# 等價于矩陣[fx, 0, cx; 0, fy, cy; 0, 0, 1]# 圖像中心坐標系(uv):相機畸變參數[k1, k2, p1, p2, k3]D = [7.0834633684407095e-002, 6.9140193737175351e-002, 0.0, 0.0, -1.3073460323689292e+000]# 像素坐標系(xy):填寫凸輪的本征和畸變系數cam_matrix = np.array(K).reshape(3, 3).astype(np.float32)
    dist_coeffs = np.array(D).reshape(5, 1).astype(np.float32)# 重新投影3D點的世界坐標軸以驗證結果姿勢reprojectsrc = np.float32([[10.0, 10.0, 10.0],[10.0, 10.0, -10.0],[10.0, -10.0, -10.0],[10.0, -10.0, 10.0],[-10.0, 10.0, 10.0],[-10.0, 10.0, -10.0],[-10.0, -10.0, -10.0],[-10.0, -10.0, 10.0]])# 繪制正方體12軸line_pairs = [[0, 1], [1, 2], [2, 3], [3, 0],[4, 5], [5, 6], [6, 7], [7, 4],[0, 4], [1, 5], [2, 6], [3, 7]]def get_head_pose(shape):# 填寫2D參考點,注釋遵循https://ibug.doc.ic.ac.uk/resources/300-W/"""17左眉左上角/21左眉右角/22右眉左上角/26右眉右上角/36左眼左上角/39左眼右上角/42右眼左上角/45右眼右上角/31鼻子左上角/35鼻子右上角/48左上角/54嘴右上角/57嘴中央下角/8下巴角"""# 像素坐標集合image_pts = np.float32([shape[17], shape[21], shape[22], shape[26], shape[36],shape[39], shape[42], shape[45], shape[31], shape[35],shape[48], shape[54], shape[57], shape[8]])"""用solvepnp或sovlepnpRansac,輸入3d點、2d點、相機內參、相機畸變,輸出r、t之后用projectPoints,輸入3d點、相機內參、相機畸變、r、t,輸出重投影2d點計算原2d點和重投影2d點的距離作為重投影誤差"""# solvePnP計算姿勢——求解旋轉和平移矩陣:# rotation_vec表示旋轉矩陣,translation_vec表示平移矩陣,cam_matrix與K矩陣對應,dist_coeffs與D矩陣對應。_, rotation_vec, translation_vec = cv2.solvePnP(object_pts, image_pts, cam_matrix, dist_coeffs)# projectPoints重新投影誤差reprojectdst, _ = cv2.projectPoints(reprojectsrc, rotation_vec, translation_vec, cam_matrix,dist_coeffs)reprojectdst = tuple(map(tuple, reprojectdst.reshape(8, 2)))# 以8行2列顯示# 計算歐拉角calc euler angle# 參考https://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#decomposeprojectionmatrixrotation_mat, _ = cv2.Rodrigues(rotation_vec)#羅德里格斯公式(將旋轉矩陣轉換為旋轉向量)pose_mat = cv2.hconcat((rotation_mat, translation_vec))# 水平拼接,vconcat垂直拼接# eulerAngles –可選的三元素矢量,包含三個以度為單位的歐拉旋轉角度_, _, _, _, _, _, euler_angle = cv2.decomposeProjectionMatrix(pose_mat)# 將投影矩陣分解為旋轉矩陣和相機矩陣return reprojectdst, euler_angledef main():# returncap = cv2.VideoCapture(0)if not cap.isOpened():print("Unable to connect to camera.")return# 檢測人臉detector = dlib.get_frontal_face_detector()# 檢測第一個人臉的關鍵點predictor = dlib.shape_predictor(face_landmark_path)while cap.isOpened():ret, frame = cap.read()if ret:face_rects = detector(frame, 0)if len(face_rects) > 0:# 循環臉部位置信息,使用predictor(gray, rect)獲得臉部特征位置的信息shape = predictor(frame, face_rects[0])# 將臉部特征信息轉換為數組array的格式shape = face_utils.shape_to_np(shape)# 獲取頭部姿態reprojectdst, euler_angle = get_head_pose(shape)pitch = format(euler_angle[0, 0])yaw = format(euler_angle[1, 0])roll = format(euler_angle[2, 0])print('pitch:{}, yaw:{}, roll:{}'.format(pitch, yaw, roll))# 標出68個特征點for (x, y) in shape:cv2.circle(frame, (x, y), 1, (0, 0, 255), -1)# 繪制正方體12軸for start, end in line_pairs:cv2.line(frame, reprojectdst[start], reprojectdst[end], (0, 0, 255))# 顯示角度結果cv2.putText(frame, "X: " + "{:7.2f}".format(euler_angle[0, 0]), (20, 20), cv2.FONT_HERSHEY_SIMPLEX,0.75, (0, 0, 255), thickness=2)cv2.putText(frame, "Y: " + "{:7.2f}".format(euler_angle[1, 0]), (20, 50), cv2.FONT_HERSHEY_SIMPLEX,0.75, (0, 0, 255), thickness=2)cv2.putText(frame, "Z: " + "{:7.2f}".format(euler_angle[2, 0]), (20, 80), cv2.FONT_HERSHEY_SIMPLEX,0.75, (0, 0, 255), thickness=2)    # 按q退出提示cv2.putText(frame, "Press 'q': Quit", (20, 450),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (84, 255, 159), 2)# 窗口顯示 show with opencvcv2.imshow("Head_Posture", frame)if cv2.waitKey(1) & 0xFF == ord('q'):break# 釋放攝像頭 release cameracap.release()# do a bit of cleanupcv2.destroyAllWindows()if __name__ == '__main__':main()

在這里插入圖片描述

5.3 打瞌睡判斷

頭部姿態判斷打瞌睡得到實時頭部姿態的旋轉角度過后,為頭部旋轉角度的3個參數Yaw,Pitch和Roll的示意圖,駕駛員在打瞌睡時,顯然頭部會做類似于點頭和傾斜的動作.而根據一般人的打瞌睡時表現出來的頭部姿態,顯然很少會在Yaw上有動作,而主要集中在Pitch和Roll的行為.設定參數閾值為0.3,在一個時間段內10
s內,當I PitchI≥20°或者|Rolll≥20°的時間比例超過0.3時,就認為駕駛員處于打瞌睡的狀態,發出預警。

在這里插入圖片描述

?

from scipy.spatial import distance as distfrom imutils.video import FileVideoStreamfrom imutils.video import VideoStreamfrom imutils import face_utilsimport numpy as np # 數據處理的庫 numpyimport argparseimport imutilsimport timeimport dlibimport cv2import mathimport timefrom threading import Thread,# 世界坐標系(UVW):填寫3D參考點,該模型參考http://aifi.isr.uc.pt/Downloads/OpenGL/glAnthropometric3DModel.cppobject_pts = np.float32([[6.825897, 6.760612, 4.402142],  #33左眉左上角[1.330353, 7.122144, 6.903745],  #29左眉右角[-1.330353, 7.122144, 6.903745], #34右眉左角[-6.825897, 6.760612, 4.402142], #38右眉右上角[5.311432, 5.485328, 3.987654],  #13左眼左上角[1.789930, 5.393625, 4.413414],  #17左眼右上角[-1.789930, 5.393625, 4.413414], #25右眼左上角[-5.311432, 5.485328, 3.987654], #21右眼右上角[2.005628, 1.409845, 6.165652],  #55鼻子左上角[-2.005628, 1.409845, 6.165652], #49鼻子右上角[2.774015, -2.080775, 5.048531], #43嘴左上角[-2.774015, -2.080775, 5.048531],#39嘴右上角[0.000000, -3.116408, 6.097667], #45嘴中央下角[0.000000, -7.415691, 4.070434]])#6下巴角# 相機坐標系(XYZ):添加相機內參K = [6.5308391993466671e+002, 0.0, 3.1950000000000000e+002,0.0, 6.5308391993466671e+002, 2.3950000000000000e+002,0.0, 0.0, 1.0]# 等價于矩陣[fx, 0, cx; 0, fy, cy; 0, 0, 1]# 圖像中心坐標系(uv):相機畸變參數[k1, k2, p1, p2, k3]D = [7.0834633684407095e-002, 6.9140193737175351e-002, 0.0, 0.0, -1.3073460323689292e+000]# 像素坐標系(xy):填寫凸輪的本征和畸變系數cam_matrix = np.array(K).reshape(3, 3).astype(np.float32)dist_coeffs = np.array(D).reshape(5, 1).astype(np.float32)# 重新投影3D點的世界坐標軸以驗證結果姿勢reprojectsrc = np.float32([[10.0, 10.0, 10.0],[10.0, 10.0, -10.0],[10.0, -10.0, -10.0],[10.0, -10.0, 10.0],[-10.0, 10.0, 10.0],[-10.0, 10.0, -10.0],[-10.0, -10.0, -10.0],[-10.0, -10.0, 10.0]])# 繪制正方體12軸line_pairs = [[0, 1], [1, 2], [2, 3], [3, 0],[4, 5], [5, 6], [6, 7], [7, 4],[0, 4], [1, 5], [2, 6], [3, 7]]def get_head_pose(shape):# 頭部姿態估計# (像素坐標集合)填寫2D參考點,注釋遵循https://ibug.doc.ic.ac.uk/resources/300-W/# 17左眉左上角/21左眉右角/22右眉左上角/26右眉右上角/36左眼左上角/39左眼右上角/42右眼左上角/# 45右眼右上角/31鼻子左上角/35鼻子右上角/48左上角/54嘴右上角/57嘴中央下角/8下巴角image_pts = np.float32([shape[17], shape[21], shape[22], shape[26], shape[36],shape[39], shape[42], shape[45], shape[31], shape[35],shape[48], shape[54], shape[57], shape[8]])# solvePnP計算姿勢——求解旋轉和平移矩陣:# rotation_vec表示旋轉矩陣,translation_vec表示平移矩陣,cam_matrix與K矩陣對應,dist_coeffs與D矩陣對應。_, rotation_vec, translation_vec = cv2.solvePnP(object_pts, image_pts, cam_matrix, dist_coeffs)# projectPoints重新投影誤差:原2d點和重投影2d點的距離(輸入3d點、相機內參、相機畸變、r、t,輸出重投影2d點)reprojectdst, _ = cv2.projectPoints(reprojectsrc, rotation_vec, translation_vec, cam_matrix,dist_coeffs)reprojectdst = tuple(map(tuple, reprojectdst.reshape(8, 2)))# 以8行2列顯示# 計算歐拉角calc euler angle# 參考https://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#decomposeprojectionmatrixrotation_mat, _ = cv2.Rodrigues(rotation_vec)#羅德里格斯公式(將旋轉矩陣轉換為旋轉向量)pose_mat = cv2.hconcat((rotation_mat, translation_vec))# 水平拼接,vconcat垂直拼接# decomposeProjectionMatrix將投影矩陣分解為旋轉矩陣和相機矩陣_, _, _, _, _, _, euler_angle = cv2.decomposeProjectionMatrix(pose_mat)pitch, yaw, roll = [math.radians(_) for _ in euler_angle]pitch = math.degrees(math.asin(math.sin(pitch)))roll = -math.degrees(math.asin(math.sin(roll)))yaw = math.degrees(math.asin(math.sin(yaw)))print('pitch:{}, yaw:{}, roll:{}'.format(pitch, yaw, roll))return reprojectdst, euler_angle# 投影誤差,歐拉角def eye_aspect_ratio(eye):# 垂直眼標志(X,Y)坐標A = dist.euclidean(eye[1], eye[5])# 計算兩個集合之間的歐式距離B = dist.euclidean(eye[2], eye[4])# 計算水平之間的歐幾里得距離# 水平眼標志(X,Y)坐標C = dist.euclidean(eye[0], eye[3])# 眼睛長寬比的計算ear = (A + B) / (2.0 * C)# 返回眼睛的長寬比return eardef mouth_aspect_ratio(mouth):# 嘴部A = np.linalg.norm(mouth[2] - mouth[9])  # 51, 59B = np.linalg.norm(mouth[4] - mouth[7])  # 53, 57C = np.linalg.norm(mouth[0] - mouth[6])  # 49, 55mar = (A + B) / (2.0 * C)return mar# 定義常數# 眼睛長寬比# 閃爍閾值EYE_AR_THRESH = 0.2EYE_AR_CONSEC_FRAMES = 3# 打哈欠長寬比# 閃爍閾值MAR_THRESH = 0.5MOUTH_AR_CONSEC_FRAMES = 3# 瞌睡點頭HAR_THRESH = 0.3NOD_AR_CONSEC_FRAMES = 3# 初始化幀計數器和眨眼總數COUNTER = 0TOTAL = 0# 初始化幀計數器和打哈欠總數mCOUNTER = 0mTOTAL = 0# 初始化幀計數器和點頭總數hCOUNTER = 0hTOTAL = 0# 初始化DLIB的人臉檢測器(HOG),然后創建面部標志物預測print("[INFO] loading facial landmark predictor...")# 第一步:使用dlib.get_frontal_face_detector() 獲得臉部位置檢測器detector = dlib.get_frontal_face_detector()# 第二步:使用dlib.shape_predictor獲得臉部特征位置檢測器predictor = dlib.shape_predictor('D:/myworkspace/JupyterNotebook/fatigue_detecting/model/shape_predictor_68_face_landmarks.dat')# 第三步:分別獲取左右眼面部標志的索引(lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"](rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"](mStart, mEnd) = face_utils.FACIAL_LANDMARKS_IDXS["mouth"]# 第四步:打開cv2 本地攝像頭cap = cv2.VideoCapture(0)# 從視頻流循環幀while True:# 第五步:進行循環,讀取圖片,并對圖片做維度擴大,并進灰度化ret, frame = cap.read()frame = imutils.resize(frame, width=720)gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 第六步:使用detector(gray, 0) 進行臉部位置檢測rects = detector(gray, 0)# 第七步:循環臉部位置信息,使用predictor(gray, rect)獲得臉部特征位置的信息for rect in rects:shape = predictor(gray, rect)# 第八步:將臉部特征信息轉換為數組array的格式shape = face_utils.shape_to_np(shape)# 第九步:提取左眼和右眼坐標leftEye = shape[lStart:lEnd]rightEye = shape[rStart:rEnd]# 嘴巴坐標mouth = shape[mStart:mEnd]        # 第十步:構造函數計算左右眼的EAR值,使用平均值作為最終的EARleftEAR = eye_aspect_ratio(leftEye)rightEAR = eye_aspect_ratio(rightEye)ear = (leftEAR + rightEAR) / 2.0# 打哈欠mar = mouth_aspect_ratio(mouth)# 第十一步:使用cv2.convexHull獲得凸包位置,使用drawContours畫出輪廓位置進行畫圖操作leftEyeHull = cv2.convexHull(leftEye)rightEyeHull = cv2.convexHull(rightEye)cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1)cv2.drawContours(frame, [rightEyeHull], -1, (0, 255, 0), 1)mouthHull = cv2.convexHull(mouth)cv2.drawContours(frame, [mouthHull], -1, (0, 255, 0), 1)# 第十二步:進行畫圖操作,用矩形框標注人臉left = rect.left()top = rect.top()right = rect.right()bottom = rect.bottom()cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 1)    '''分別計算左眼和右眼的評分求平均作為最終的評分,如果小于閾值,則加1,如果連續3次都小于閾值,則表示進行了一次眨眼活動'''# 第十三步:循環,滿足條件的,眨眼次數+1if ear < EYE_AR_THRESH:# 眼睛長寬比:0.2COUNTER += 1else:# 如果連續3次都小于閾值,則表示進行了一次眨眼活動if COUNTER >= EYE_AR_CONSEC_FRAMES:# 閾值:3TOTAL += 1# 重置眼幀計數器COUNTER = 0# 第十四步:進行畫圖操作,同時使用cv2.putText將眨眼次數進行顯示cv2.putText(frame, "Faces: {}".format(len(rects)), (10, 30),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)     cv2.putText(frame, "COUNTER: {}".format(COUNTER), (150, 30),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)cv2.putText(frame, "Blinks: {}".format(TOTAL), (450, 30),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255,255,0), 2)'''計算張嘴評分,如果小于閾值,則加1,如果連續3次都小于閾值,則表示打了一次哈欠,同一次哈欠大約在3幀'''# 同理,判斷是否打哈欠    if mar > MAR_THRESH:# 張嘴閾值0.5mCOUNTER += 1cv2.putText(frame, "Yawning!", (10, 60),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)else:# 如果連續3次都小于閾值,則表示打了一次哈欠if mCOUNTER >= MOUTH_AR_CONSEC_FRAMES:# 閾值:3mTOTAL += 1# 重置嘴幀計數器mCOUNTER = 0cv2.putText(frame, "COUNTER: {}".format(mCOUNTER), (150, 60),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) cv2.putText(frame, "MAR: {:.2f}".format(mar), (300, 60),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)cv2.putText(frame, "Yawning: {}".format(mTOTAL), (450, 60),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255,255,0), 2)"""瞌睡點頭"""# 第十五步:獲取頭部姿態reprojectdst, euler_angle = get_head_pose(shape)har = euler_angle[0, 0]# 取pitch旋轉角度if har > HAR_THRESH:# 點頭閾值0.3hCOUNTER += 1else:# 如果連續3次都小于閾值,則表示瞌睡點頭一次if hCOUNTER >= NOD_AR_CONSEC_FRAMES:# 閾值:3hTOTAL += 1# 重置點頭幀計數器hCOUNTER = 0# 繪制正方體12軸for start, end in line_pairs:cv2.line(frame, reprojectdst[start], reprojectdst[end], (0, 0, 255))# 顯示角度結果cv2.putText(frame, "X: " + "{:7.2f}".format(euler_angle[0, 0]), (10, 90), cv2.FONT_HERSHEY_SIMPLEX,0.75, (0, 255, 0), thickness=2)# GREENcv2.putText(frame, "Y: " + "{:7.2f}".format(euler_angle[1, 0]), (150, 90), cv2.FONT_HERSHEY_SIMPLEX,0.75, (255, 0, 0), thickness=2)# BLUEcv2.putText(frame, "Z: " + "{:7.2f}".format(euler_angle[2, 0]), (300, 90), cv2.FONT_HERSHEY_SIMPLEX,0.75, (0, 0, 255), thickness=2)# RED    cv2.putText(frame, "Nod: {}".format(hTOTAL), (450, 90),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255,255,0), 2)# 第十六步:進行畫圖操作,68個特征點標識for (x, y) in shape:cv2.circle(frame, (x, y), 1, (0, 0, 255), -1)print('嘴巴實時長寬比:{:.2f} '.format(mar)+"\t是否張嘴:"+str([False,True][mar > MAR_THRESH]))print('眼睛實時長寬比:{:.2f} '.format(ear)+"\t是否眨眼:"+str([False,True][COUNTER>=1]))# 確定疲勞提示:眨眼50次,打哈欠15次,瞌睡點頭15次if TOTAL >= 50 or mTOTAL>=15 or hTOTAL>=15:cv2.putText(frame, "SLEEP!!!", (100, 200),cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 3)# 按q退出cv2.putText(frame, "Press 'q': Quit", (20, 500),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (84, 255, 159), 2)# 窗口顯示 show with opencvcv2.imshow("Frame", frame)# if the `q` key was pressed, break from the loopif cv2.waitKey(1) & 0xFF == ord('q'):break# 釋放攝像頭 release cameracap.release()# do a bit of cleanupcv2.destroyAllWindows()

在這里插入圖片描述
在這里插入圖片描述

6 基于CNN與SVM的疲勞檢測方法

6.1 網絡結構

學長將卷積神經網絡作為特征提取器, 支持向量機作為分類識別器并通過串聯將兩者結合 , 構造理想的深度識別模型, 提高對駕駛員疲勞的識別準確率。
本次課題主要以實現提高識別精度為目的, 設計使用的特征提取網絡結構中卷積層、 池化層以及全連接層個數均為兩層;
在網絡的結尾處添加一層支持向量機作為識別分類器;

在這里插入圖片描述
根據對卷積神經網絡的描述, 這里設計使用的網絡結構為: 輸入層、 二層卷積層、 二層池化層、 二層全連接層以及 SVM
分類器組成的卷積神經網絡對采集數據進行實驗。

可將網絡視為三個部分, 數據輸入部分即網絡輸入層, 為特征提取部分由卷積層和池化層構成, SVM 為分類識別部分; 三部分網絡串聯出整體識別框架,
且相互間約束不大, 為后續優化工作提供了條件。

6.2 疲勞圖像分類訓練

網絡的訓練由于數據量較大進行實驗時將數據分為多個批次, 每個批次中含有 20張圖像, 經過前向、 反向傳播后更新網絡參數, 訓練出誤差合適的網絡。 測試時,
圖像由網絡進行識別, 根據得到的識別正確率來驗證網絡的可行性。

在這里插入圖片描述

疲勞駕駛檢測需對網絡進行訓練, 在保證網絡訓練準確率達到一定精度后即可對圖像進行判別; 疲勞駕駛網絡訓練算法過程如下:

  • Step1: 網絡初始化: 初始化網絡學習率η, 在數值范圍[0, 1]中隨機初始化網絡參數權值及偏置值; 設置網絡結構: 卷積核大小為 5×5, 每批次樣本數量 20;
  • Step2: 隨機選擇數據庫內面部表情圖像并依次輸入網絡, 網絡按照送入每一批次的圖像進行訓練;
  • Step3: 網絡將訓練得到的輸出值同圖像期望值進行比較, 計算出輸出誤差;
  • Step4: 根據反向傳播原理將誤差反向傳播計算, 并調整網絡參數權值和偏置值;
  • Step5: 判斷迭代次數, 達到期望的迭代步數后轉到 Step6, 否則轉到 Step3;
  • Step6: 將 CNN 提取到的圖像特征傳入 SVM 中進行訓練;
  • Step7: 結束。

6.3 訓練結果

學長將對建立起的數據集進行實驗, 實驗中分別在每一批次下對識別正確和錯誤個數進行統計, 然后同批次中圖片數量相比, 得出最終的準確率和損失率(錯誤率) 。

在這里插入圖片描述
在這里插入圖片描述

模型測試結果

在這里插入圖片描述
在這里插入圖片描述

7 最后

🧿 更多資料, 項目分享:

https://gitee.com/dancheng-senior/postgraduate

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/163912.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/163912.shtml
英文地址,請注明出處:http://en.pswp.cn/news/163912.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

河北專升本(微機原理)

目錄 第一章&#xff1a;計算機基礎與數制轉化 1. 進制運算基礎 2. 常用編碼形式 3. 計算機系統的組成及其工作原理 4. 微機系統主要技術指標 第二章&#xff1a;8086微處理器及其系統 1. 8086微處理器&#xff08;CPU&#xff09; 2. 8086的存儲器及I/O組織 3. 8086系…

vue中的列表過濾和列表排序

列表過濾 <body><div id"root"><!--輸入框用于模糊查詢--><input type"text" placeholder"請你輸入名字" v-model"name"><ul><!--in可以換成of--><li v-for"(p,index) in persons" …

航天博物館3D虛擬交互展廳讓大眾對科技發展有更深切的理解和感受

博物館作為人們了解歷史、文化和藝術的重要場所&#xff0c;現在可以通過VR全景技術來進行展覽&#xff0c;讓參觀者身臨其境地感受歷史文化的魅力。本文將介紹博物館VR全景的特點、優勢&#xff0c;以及如何使用VR全景技術來使得博物館的展覽和教育活動更豐富。 VR數字博物館…

WPF圖形變形使用技巧

在 WPF (Windows Presentation Foundation) 中&#xff0c;圖形變形通常是通過使用 Transform 對象來實現的。WPF 提供了幾種不同類型的 Transform&#xff0c;包括&#xff1a; TranslateTransform&#xff1a;用于在 x 軸和 y 軸上移動&#xff08;平移&#xff09;元素。Sc…

SSH 下載及安裝之 Windows Server

文章目錄 1 概述1.1 操作系統截圖1.2 下載 2 安裝2.1 解壓到指定路徑2.2 CMD 到 OpenSSH 目錄下2.3 安裝 sshd 服務2.3 開放端口 222.4 配置開機自啟 sshd 服務2.5 配置環境變量 path2.6 測試 3 連接3.1 使用 Xshell 連接3.2 輸入登錄用戶名3.3 輸入登錄密碼3.4 會話已建立 1 概…

3、如何從0到1去建設數據倉庫

1、數倉實施過程 1.1 數據調研 數據調研包括&#xff1a;業務調研、需求調研 業務調研 需要調研企業內有哪些業務線、業務線的業務是否還有相同點和差異點 各個業務線有哪些業務模塊&#xff0c;每個模型下有哪些業務流程&#xff0c;每個流程下產生的數據 是怎樣存儲的 業務調…

python數據結構與算法-16_優先級隊列

優先級隊列 你可能比較奇怪&#xff0c;隊列不是早就講了嘛。這里之所以放到這里講優先級隊列&#xff0c;是因為雖然名字有隊列&#xff0c; 但其實是使用堆來實現的。上一章講完了堆&#xff0c;這一章我們就趁熱打鐵來實現一個優先級隊列。 實現優先級隊列 優先級隊列(Pr…

UWA報告使用技巧小視頻,你get了么?(第十一彈)

隨著玩家對手游渲染品質的要求日益趨上&#xff0c;60幀、各種花式后處理導致發熱、耗電等問題日趨明顯。本期UWA報告使用技巧將分享關于GPU優化的專題姊妹篇。 《GPU性能優化篇》 UWA專注于手游GPU性能的優化&#xff0c;以確保您的游戲體驗得以最佳展現。基于最新發布的GOT …

141.【Git版本控制】

Git-深入挖掘 (一)、Git分布式版本控制工具1.目標2.概述(1).開發中的實際常見(2).版本控制器的方式(3).SVN (集中版本控制器)(4).Git (分布版本控制器)(5).Git工作流程圖 (二)、Git安裝與常用命令1.Git環境配置(1).安裝Git的操作(2).Git的配置操作(3).為常用的指令配置別名 (可…

輕松解決rpm軟件包的依賴問題 yum download ,rpm和deb不同系列

centos rpm系列的 為它往往有很多依賴項目。比如&#xff0c;我們來查看一下net-tools的依賴項有哪些&#xff1a; yum deplist net-tools 推薦使用以下幾種方法&#xff1a; 1.repotrack 我這里也以上期講到的Mariadb為例演示&#xff0c;以下操作需要在有網絡的環境下進…

國內企業出海首選的免費開源訂單管理系統(OMS)解決方案

用開源智造Odoo訂單管理系統 (OMS) 解決方案實現"訂單到收款"流程自動化 開源智造Odoo 訂單管理軟件功能消除了手動操作瓶頸&#xff0c;可防止出錯&#xff0c;還建立了從銷售報價到訂單履行的順暢工作流來確保及時開票和付款&#xff0c;從而幫助您理順訂單處理過程…

Python將多個視頻幀組合成.mp4視頻

已經有很多文章描述了如何將視頻拆分成視頻幀&#xff0c;例如&#xff1a;https://blog.csdn.net/WYKB_Mr_Q/article/details/124929081 那我們如何將很多視頻幀重新組合成視頻呢&#xff1f; 這里我們主要用到了 OpenCV 庫中的 VideoWriter 類。 OpenCV種的 cv2.VideoWrit…

jdbc批量插入或更新數據

mybatis可以批量插入或更新數據&#xff0c;不過mybatis底層也是基于jdbc來實現的&#xff0c;如何使用jdbc批量操作數據&#xff1f;本文給出demo。 /*** JDBC分批次批量插入* * throws IOException*/public static void testJDBCBatchInsertUser() throws IOException {Conne…

工作流引擎的架構設計主要考慮以下方面

工作流引擎的架構設計主要考慮以下方面&#xff0c;以馳騁工作流引擎為例來說明。 高度抽象和封裝&#xff1a;為了適應各種業務場景&#xff0c;工作流引擎應具備高度抽象和封裝的特性&#xff0c;以便統一處理各流程。靈活配置&#xff1a;工作流引擎應支持靈活的配置&#…

Linux之實現簡易的shell

1.打印提示符并獲取命令行 我們在使用shell的時候&#xff0c;發現我們在輸入命令是&#xff0c;前面會有&#xff1a;有用戶名&#xff0c;版本&#xff0c;當前路徑等信息&#xff0c;這里我們可以用環境變量去獲取: 1 #include <stdio.h>2 #include <stdlib.h>…

python如何快速查找到想要的文檔

字多不看版&#xff0c;直接體驗 待補充 演示代碼 # -*- coding:UTF-8 -*-# region 導入必要的依賴包 import os import subprocess from enum import Enum模塊名 pyperclip try:import pyperclip # 需要安裝 pyperclip 模塊&#xff0c;以支持粘貼板操作 except ImportEr…

PTA-成績轉換

本題要求編寫程序將一個百分制成績轉換為五分制成績。轉換規則&#xff1a; 大于等于90分為A&#xff1b;小于90且大于等于80為B&#xff1b;小于80且大于等于70為C&#xff1b;小于70且大于等于60為D&#xff1b;小于60為E。 輸入格式: 輸入在一行中給出一個整數的百分制成…

羊大師教你如何科學控制體重,輕松瘦下來

羊大師教你如何科學控制體重&#xff0c;輕松瘦下來 我們都知道&#xff0c;控制體重對于保持健康和美麗至關重要。然而&#xff0c;許多人在減肥的道路上走得波折重重&#xff0c;常常陷入挫敗和不知所措的境地。那么&#xff0c;如何科學控制體重&#xff0c;輕松瘦下來呢&a…

項目經理只需要有PMP證書就行?

就目前而言&#xff0c;大部分人對于項目經理的認識還停留在&#xff1a;有項目管理經驗&#xff0c;有對應的工作年限&#xff0c;有PMP證書。所以絕大多數人都認為只要報考了PMP項目管理&#xff0c;取得PMP證書&#xff0c;即可加入項目經理的圈子&#xff0c;薪資翻倍。 但…

協同過濾與矩陣分解講解(PPT)

總覽 協同過濾算法&#xff0c;就是一種完全依賴用戶和物品之間行為關系的推薦算法。 從字面理解&#xff0c;協同大家的反饋、評價和意見一起對海量的信息進行過濾&#xff0c;從中篩選出用戶可能感興趣的信息。 知識概括 從這幾個方面進行分析。 一、基于用戶的協同過濾 顯示…