def __init__(self): Ui_MainWindow.printf(window, "正在打开摄像头请稍后...") # 设置时钟 self.v_timer = QTimer() # 打开摄像头 self.cap = cv2.VideoCapture(0) if not self.cap: Ui_MainWindow.printf(window, "打开摄像头失败") return # 设置定时器周期,单位毫秒 self.v_timer.start(20) # 连接定时器周期溢出的槽函数,用于显示一帧视频 self.v_timer.timeout.connect(self.show_pic) # 在前端UI输出提示信息 Ui_MainWindow.printf(window, "载入成功,开始运行程序") Ui_MainWindow.printf(window, "") Ui_MainWindow.printf(window, "开始执行疲劳检测...") window.statusbar.showMessage("正在使用摄像头...")
def show_pic(self): # 全局变量 # 在函数中引入定义的全局变量 global EYE_AR_THRESH, EYE_AR_CONSEC_FRAMES, MAR_THRESH, MOUTH_AR_CONSEC_FRAMES, COUNTER, TOTAL, mCOUNTER, mTOTAL, ActionCOUNTER, Roll, Rolleye, Rollmouth # 读取摄像头的一帧画面 success, frame = self.cap.read() if success: # 检测 # 将摄像头读到的frame传入检测函数myframe.frametest() ret, frame = myframe.frametest(frame) lab, eye, mouth = ret # ret和frame,为函数返回 # ret为检测结果,ret的格式为[lab,eye,mouth],lab为yolo的识别结果包含'phone' 'smoke' 'drink',eye为眼睛的开合程度(长宽比),mouth为嘴巴的开合程度 # frame为标注了识别结果的帧画面,画上了标识框 # 分心行为判断 # 分心行为检测以15帧为一个循环 ActionCOUNTER += 1 # 如果检测到分心行为 # 将信息返回到前端ui,使用红色字体来体现 # 并加ActionCOUNTER减1,以延长循环时间 for i in lab: if (i == "phone"): window.label_6.setText("<font color=red>正在用手机</font>") window.label_9.setText("<font color=red>请不要分心</font>") if ActionCOUNTER > 0: ActionCOUNTER -= 1 elif (i == "smoke"): window.label_7.setText("<font color=red>正在抽烟</font>") window.label_9.setText("<font color=red>请不要分心</font>") if ActionCOUNTER > 0: ActionCOUNTER -= 1 elif (i == "drink"): window.label_8.setText("<font color=red>正在用喝水</font>") window.label_9.setText("<font color=red>请不要分心</font>") if ActionCOUNTER > 0: ActionCOUNTER -= 1 # 如果超过15帧未检测到分心行为,将label修改为平时状态 if ActionCOUNTER == 15: window.label_6.setText("手机") window.label_7.setText("抽烟") window.label_8.setText("喝水") window.label_9.setText("") ActionCOUNTER = 0 # 疲劳判断 # 眨眼判断 if eye < EYE_AR_THRESH: # 如果眼睛开合程度小于设定好的阈值 # 则两个和眼睛相关的计数器加1 COUNTER += 1 Rolleye += 1 else: # 如果连续2次都小于阈值,则表示进行了一次眨眼活动 if COUNTER >= EYE_AR_CONSEC_FRAMES: TOTAL += 1 window.label_3.setText("眨眼次数:" + str(TOTAL)) # 重置眼帧计数器 COUNTER = 0 # 哈欠判断,同上 if mouth > MAR_THRESH: mCOUNTER += 1 Rollmouth += 1 else: # 如果连续3次都小于阈值,则表示打了一次哈欠 if mCOUNTER >= MOUTH_AR_CONSEC_FRAMES: mTOTAL += 1 window.label_4.setText("哈欠次数:" + str(mTOTAL)) # 重置嘴帧计数器 mCOUNTER = 0 # 将画面显示在前端UI上 show = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) showImage = QImage(show.data, show.shape[1], show.shape[0], QImage.Format_RGB888) window.label.setPixmap(QPixmap.fromImage(showImage)) # 疲劳模型 # 疲劳模型以150帧为一个循环 # 每一帧Roll加1 Roll += 1 # 当检测满150帧时,计算模型得分 if Roll == 150: # 计算Perclos模型得分 perclos = (Rolleye / Roll) + (Rollmouth / Roll) * 0.2 # 在前端UI输出perclos值 Ui_MainWindow.printf( window, "过去150帧中,Perclos得分为" + str(round(perclos, 3))) # 当过去的150帧中,Perclos模型得分超过0.38时,判断为疲劳状态 if perclos > 0.38: Ui_MainWindow.printf(window, "当前处于疲劳状态") window.label_10.setText("<font color=red>疲劳!!!</font>") Ui_MainWindow.printf(window, "") else: Ui_MainWindow.printf(window, "当前处于清醒状态") window.label_10.setText("清醒") Ui_MainWindow.printf(window, "") # 归零 # 将三个计数器归零 # 重新开始新一轮的检测 Roll = 0 Rolleye = 0 Rollmouth = 0 Ui_MainWindow.printf(window, "重新开始执行疲劳检测...")