计算机视觉 基于opencv和dlib库的疲劳检测系统 使用opencv和dlib库实现人脸关键点的标定 对检测到疲劳时,发出预警 疲劳驾驶预警 计算机视觉 基于opencv和dlib库的疲劳检测系统 使用opencv和dlib库实现人脸关键点的标定 对检测到疲劳时发出预警 疲劳驾驶预警文章目录1. 开发软件界面获取人脸视频✅ 一、环境准备✅ 二、完整代码实现✅ 三、各模块详解1️⃣ 人脸检测2️⃣ 关键点定位3️⃣ 特征提取4️⃣ 疲劳判断与预警✅ 四、可选增强功能✅ 五、运行效果基于opencv和dlib库的疲劳预警检测系统构建点实现关键点主要实现策略1、开发软件界面获取人脸视频2、使用opencv和dlib库实现人脸关键点的标定3、定义并提取疲劳人脸特征4、对检测到疲劳时发出预警基于OpenCV和dlib库的疲劳检测系下面是代码示例仅供参考。包括人脸检测、关键点定位、特征提取和疲劳判断等。代码示例展示了如何实现这个系统。主要代码示例1. 开发软件界面获取人脸视频使用Python的tkinter库来创建GUI界面并使用OpenCV捕获视频流。importtkinterastkfromtkinterimportfiledialog,messageboximportcv2importdlibimportnumpyasnpfromPILimportImage,ImageTk# 初始化dlib的人脸检测器和关键点预测器detectordlib.get_frontal_face_detector()predictordlib.shape_predictor(shape_predictor_68_face_landmarks.dat)classFatigueDetectionApp:def__init__(self,root):self.rootroot self.root.title(Fatigue Detection System)# 创建左侧显示区域self.video_frametk.Frame(root)self.video_frame.pack(sidetk.LEFT,padx10,pady10)self.video_labeltk.Label(self.video_frame)self.video_label.pack()# 创建右侧设置区域self.settings_frametk.Frame(root)self.settings_frame.pack(sidetk.RIGHT,padx10,pady10)# 视频源选择self.video_source_vartk.StringVar(value摄像头ID)tk.Label(self.settings_frame,text视频源).pack(anchortk.W)tk.OptionMenu(self.settings_frame,self.video_source_var,摄像头ID,视频文件).pack(anchortk.W)tk.Button(self.settings_frame,text开始检测,commandself.start_detection).pack(anchortk.W)tk.Button(self.settings_frame,text打开视频文件,commandself.open_video_file).pack(anchortk.W)tk.Button(self.settings_frame,text暂停,commandself.pause_detection).pack(anchortk.W)# 疲劳检测设置tk.Label(self.settings_frame,text疲劳检测).pack(anchortk.W)self.blink_detection_vartk.BooleanVar(valueTrue)tk.Checkbutton(self.settings_frame,text眨眼检测,variableself.blink_detection_var).pack(anchortk.W)self.eye_closure_vartk.BooleanVar(valueTrue)tk.Checkbutton(self.settings_frame,text闭眼检测,variableself.eye_closure_var).pack(anchortk.W)self.head_pose_vartk.BooleanVar(valueTrue)tk.Checkbutton(self.settings_frame,text点头检测,variableself.head_pose_var).pack(anchortk.W)# 输出状态tk.Label(self.settings_frame,text状态输出).pack(anchortk.W)self.status_texttk.Text(self.settings_frame,height10,width30)self.status_text.pack(anchortk.W)# 其他变量self.capNoneself.runningFalsedefstart_detection(self):ifnotself.running:ifself.video_source_var.get()摄像头ID:self.capcv2.VideoCapture(0)else:self.capcv2.VideoCapture(self.video_file_path)self.runningTrueself.update_frame()defopen_video_file(self):self.video_file_pathfiledialog.askopenfilename(filetypes[(Video files,*.mp4;*.avi)])ifself.video_file_path:self.video_source_var.set(视频文件)defpause_detection(self):self.runningFalsedefupdate_frame(self):ret,frameself.cap.read()ifret:frameself.detect_fatigue(frame)imagecv2.cvtColor(frame,cv2.COLOR_BGR2RGB)imageImage.fromarray(image)imageImageTk.PhotoImage(image)self.video_label.config(imageimage)self.video_label.imageimageifself.running:self.root.after(10,self.update_frame)else:self.cap.release()self.runningFalsedefdetect_fatigue(self,frame):graycv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)facesdetector(gray)forfaceinfaces:landmarkspredictor(gray,face)points[]foriinrange(68):point(landmarks.part(i).x,landmarks.part(i).y)points.append(point)cv2.circle(frame,point,2,(0,255,0),-1)# 计算EAR眼睛长宽比left_eyepoints[42:48]right_eyepoints[36:42]ear_leftself.calculate_ear(left_eye)ear_rightself.calculate_ear(right_eye)ear(ear_leftear_right)/2.0# 计算MAR嘴部长宽比mouthpoints[48:68]marself.calculate_mar(mouth)# 判断疲劳ifear0.2:self.status_text.insert(tk.END,f{datetime.now()}眨眼\n)ifmar0.5:self.status_text.insert(tk.END,f{datetime.now()}打哈欠\n)# 绘制信息cv2.putText(frame,fEAR:{ear:.2f},(10,30),cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,0,255),2)cv2.putText(frame,fMAR:{mar:.2f},(10,60),cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,0,255),2)returnframedefcalculate_ear(self,eye_points):Anp.linalg.norm(np.array(eye_points[1])-np.array(eye_points[5]))Bnp.linalg.norm(np.array(eye_points[2])-np.array(eye_points[4]))Cnp.linalg.norm(np.array(eye_points[0])-np.array(eye_points[3]))ear(AB)/(2.0*C)returneardefcalculate_mar(self,mouth_points):Anp.linalg.norm(np.array(mouth_points[13])-np.array(mouth_points[19]))Bnp.linalg.norm(np.array(mouth_points[14])-np.array(mouth_points[18]))Cnp.linalg.norm(np.array(mouth_points[15])-np.array(mouth_points[17]))Dnp.linalg.norm(np.array(mouth_points[12])-np.array(mouth_points[16]))mar(ABC)/(2.0*D)returnmarif__name____main__:roottk.Tk()appFatigueDetectionApp(root)root.mainloop()基于OpenCV和dlib库的人脸疲劳检测系统主要包含以下步骤人脸检测使用dlib的HOGSVM分类器或OpenCV中的Haar Cascade进行人脸检测。关键点定位使用dlib提供的68个面部关键点检测模型shape_predictor_68_face_landmarks.dat来获取眼睛、嘴巴等部位的关键点。特征提取计算眼睛长宽比EAR、嘴部长宽比MAR等特征用于判断疲劳状态。疲劳判断根据EAR和MAR阈值判断是否眨眼、打哈欠并触发预警。✅ 一、环境准备安装必要的库pipinstallopencv-python dlib numpy imutils下载 dlib 的 68点人脸关键点模型并解压到项目目录下。✅ 二、完整代码实现importcv2importdlibimportnumpyasnpfromscipy.spatialimportdistanceasdistfromimutilsimportface_utilsimporttimeimportwinsound# Windows 报警音# 初始化dlib人脸检测器和关键点预测器detectordlib.get_frontal_face_detector()predictordlib.shape_predictor(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]# 计算眼睛长宽比 EARdefeye_aspect_ratio(eye):Adist.euclidean(eye[1],eye[5])Bdist.euclidean(eye[2],eye[4])Cdist.euclidean(eye[0],eye[3])ear(AB)/(2.0*C)returnear# 计算嘴部张开度 MARdefmouth_aspect_ratio(mouth):Adist.euclidean(mouth[2],mouth[10])# 上下唇垂直距离Bdist.euclidean(mouth[4],mouth[8])Cdist.euclidean(mouth[0],mouth[6])# 水平距离mar(AB)/(2.0*C)returnmar# 警报函数Windowsdefalert():frequency2500# Set Frequency To 2500 Hertzduration1000# Set Duration To 1000 ms 1 secondwinsound.Beep(frequency,duration)# 主程序逻辑defmain():capcv2.VideoCapture(0)EYE_AR_THRESH0.23# EAR 阈值MOUTH_AR_THRESH0.7# MAR 阈值EYE_AR_CONSEC_FRAMES30# 连续闭眼帧数YAWN_CONSEC_FRAMES20# 打哈欠持续帧数COUNTER_EYE0COUNTER_MOUTH0ALARM_ONFalsewhileTrue:ret,framecap.read()ifnotret:breakgraycv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)rectsdetector(gray,0)forrectinrects:shapepredictor(gray,rect)shapeface_utils.shape_to_np(shape)leftEyeshape[lStart:lEnd]rightEyeshape[rStart:rEnd]mouthshape[mStart:mEnd]leftEAReye_aspect_ratio(leftEye)rightEAReye_aspect_ratio(rightEye)ear(leftEARrightEAR)/2.0marmouth_aspect_ratio(mouth)leftEyeHullcv2.convexHull(leftEye)rightEyeHullcv2.convexHull(rightEye)mouthHullcv2.convexHull(mouth)cv2.drawContours(frame,[leftEyeHull],-1,(0,255,0),1)cv2.drawContours(frame,[rightEyeHull],-1,(0,255,0),1)cv2.drawContours(frame,[mouthHull],-1,(0,255,0),1)# 判断闭眼ifearEYE_AR_THRESH:COUNTER_EYE1ifCOUNTER_EYEEYE_AR_CONSEC_FRAMES:ifnotALARM_ON:ALARM_ONTruealert()cv2.putText(frame,DROWSINESS ALERT!,(10,30),cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,0,255),2)else:COUNTER_EYE0ALARM_ONFalse# 判断打哈欠ifmarMOUTH_AR_THRESH:COUNTER_MOUTH1ifCOUNTER_MOUTHYAWN_CONSEC_FRAMES:cv2.putText(frame,YAWNING,(10,60),cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,0,255),2)else:COUNTER_MOUTH0# 显示指标cv2.putText(frame,fEAR:{ear:.2f},(300,30),cv2.FONT_HERSHEY_SIMPLEX,0.7,(255,255,255),2)cv2.putText(frame,fMAR:{mar:.2f},(300,60),cv2.FONT_HERSHEY_SIMPLEX,0.7,(255,255,255),2)cv2.imshow(Fatigue Detection,frame)keycv2.waitKey(1)0xFFifkeyord(q):breakcap.release()cv2.destroyAllWindows()if__name____main__:main()✅ 三、各模块详解1️⃣ 人脸检测使用dlib.get_frontal_face_detector()检测图像中的人脸区域。rectsdetector(gray,0)2️⃣ 关键点定位使用预训练模型shape_predictor_68_face_landmarks.dat提取68个面部关键点。shapepredictor(gray,rect)shapeface_utils.shape_to_np(shape)3️⃣ 特征提取眼睛长宽比 EAREye Aspect Ratiodefeye_aspect_ratio(eye):Adist.euclidean(eye[1],eye[5])Bdist.euclidean(eye[2],eye[4])Cdist.euclidean(eye[0],eye[3])ear(AB)/(2.0*C)returnear嘴部长宽比 MARMouth Aspect Ratiodefmouth_aspect_ratio(mouth):Adist.euclidean(mouth[2],mouth[10])Bdist.euclidean(mouth[4],mouth[8])Cdist.euclidean(mouth[0],mouth[6])mar(AB)/(2.0*C)returnmar4️⃣ 疲劳判断与预警如果EAR小于设定阈值且持续一定帧数则判定为“闭眼”如果MAR大于设定阈值且持续一定帧数则判定为“打哈欠”触发蜂鸣报警。✅ 四、可选增强功能功能描述头部姿态估计使用solvePnP计算头部角度判断点头实时日志记录将疲劳事件写入日志文件GUI界面使用Tkinter或PyQt构建图形化界面多人检测支持多人同时检测视频保存将检测过程录制为视频✅ 五、运行效果实时显示摄像头画面标注眼睛和嘴巴轮廓显示EAR、MAR数值当检测到闭眼或打哈欠时弹出警告框并发出声音提示亦可加入深度学习模型如CNN提升精度或结合红外摄像头进行夜间检测