赞
踩
检测眨眼次数。要求做成一个pyqt5 GUI 界面,点击按键“开始”时,就开始显示视频帧,并检测图像中是否有人的眨眼动作,有眨眼时将眨眼次数加1,并显示在图像的左上角位置。点击按键“停止”时,就停止显示视频帧。
为了构建我们的眨眼检测器,我们将计算一个称为 眼睛纵横比(EAR) 的指标。当确定视频流中是否发生眨眼时,我们需要计算眼睛的长宽比。如果眼睛长宽比低于一定的阈值,然后超过阈值,那么我们将记录一个“眨眼” - EYE_AR_THRESH 是这个阈值,我们默认它的值为 0.3,您也可以为自己的应用程序调整它。另外,我们有一个重要的常量,EYE_AR_CONSEC_FRAME ,这个值被设置为 3,表明眼睛长宽比小于3时,接着三个连续的帧一定发生眨眼动作。同样,取决于视频的帧处理吞吐率,数字大小可以自己调控。
class Wink_Window(QtWidgets.QWidget): def __init__(self, parent=None): super(Wink_Window, self).__init__(parent) self.timer_camera = QtCore.QTimer() self.cap = cv2.VideoCapture() self.cam_num = 0 self.set_ui() self.slot_init() self.__flag_work = 0 self.x = 0 self.count = 0 # 调用人脸特征点检测模型 self.shape_detector_path = '../shape_predictor_68_face_landmarks.dat' # 人脸检测器 self.detector = dlib.get_frontal_face_detector() # 人脸特征点检测器 self.predictor = dlib.shape_predictor(self.shape_detector_path) self.EYE_AR_THRESH = 0.35 # 设置阈值 # 当EAR大小小于阈值时,接连多少帧一定发生眨眼动作 self.EYE_AR_CONSEC_FRAMES = 8 # 对应特征点的序号 self.RIGHT_EYE_START = 37 - 1 self.RIGHT_EYE_END = 42 - 1 self.LEFT_EYE_START = 43 - 1 self.LEFT_EYE_END = 48 - 1 self.face =True def set_ui(self): self.__layout_main = QtWidgets.QHBoxLayout() self.__layout_fun_button = QtWidgets.QVBoxLayout() self.__layout_data_show = QtWidgets.QVBoxLayout() self.button_open_camera = QtWidgets.QPushButton(u'开始检测') self.button_close = QtWidgets.QPushButton(u'停止检测') # Button 的颜色修改 button_color = [self.button_open_camera, self.button_close] for i in range(2): button_color[i].setStyleSheet("QPushButton{color:black}" "QPushButton:hover{color:red}" "QPushButton{background-color:rgb(78,255,255)}" "QPushButton{border:2px}" "QPushButton{border-radius:10px}" "QPushButton{padding:2px 5px}") # move()方法移动窗口在屏幕上的位置到x = 500,y = 300坐标。 self.move(500, 300) # 信息显示 self.button_open_camera.setMinimumHeight(50) self.button_close.setMinimumHeight(50) self.label_show_camera = QtWidgets.QLabel() self.label_move = QtWidgets.QLabel() self.label_move.setFixedSize(100, 50) self.label_show_camera.setFixedSize(641, 481) self.label_show_camera.setAutoFillBackground(False) self.__layout_fun_button.addWidget(self.button_open_camera) self.__layout_fun_button.addWidget(self.button_close) self.__layout_fun_button.addWidget(self.label_move) self.__layout_main.addLayout(self.__layout_fun_button) self.__layout_main.addWidget(self.label_show_camera) self.setLayout(self.__layout_main) self.label_move.raise_() self.setWindowTitle(u'眨眼检测') def slot_init(self): self.button_open_camera.clicked.connect(self.button_open_camera_click) self.timer_camera.timeout.connect(self.show_camera) self.button_close.clicked.connect(self.close) def button_open_camera_click(self): if self.timer_camera.isActive() == False: self.frame_counter = 0 # 连续帧计数 self.blink_counter = 0 # 眨眼计数 flag = self.cap.open(self.cam_num) if flag == False: # 错误警告 msg = QtWidgets.QMessageBox.warning(self, u"⚠警告", u"请检测相机是否连接正确", buttons=QtWidgets.QMessageBox.Ok, defaultButton=QtWidgets.QMessageBox.Ok) else: self.timer_camera.start(30) self.button_open_camera.setText(u'关闭摄像头') else: self.timer_camera.stop() self.cap.release() self.label_show_camera.clear() self.button_open_camera.setText(u'打开摄像头') def show_camera(self): flag, self.image = self.cap.read() if self.face: self.detect_eyes() self.show = cv2.resize(self.image, (640, 480)) self.show = cv2.cvtColor(self.show, cv2.COLOR_BGR2RGB) showImage = QtGui.QImage(self.show.data, self.show.shape[1], self.show.shape[0], QtGui.QImage.Format_RGB888) self.label_show_camera.setPixmap(QtGui.QPixmap.fromImage(showImage)) def detect_eyes(self): #寻找并绘出两眼轮廓 gray = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) rects = self.detector(gray, 0) # 人脸检测 for rect in rects: # 遍历每一个人脸 shape = self.predictor(gray, rect) # 检测特征点 points = face_utils.shape_to_np(shape) leftEye = points[self.LEFT_EYE_START:self.LEFT_EYE_END + 1] # 取出左眼对应的特征点 rightEye = points[self.RIGHT_EYE_START:self.RIGHT_EYE_END + 1] # 取出右眼对应的特征点 leftEAR = self.eye_aspect_ratio(leftEye) # 计算左眼EAR rightEAR = self.eye_aspect_ratio(rightEye) # 计算右眼EAR ear = (leftEAR + rightEAR) / 2.0 # 求左右眼EAR的均值 leftEyeHull = cv2.convexHull(leftEye) # 寻找左眼轮廓 rightEyeHull = cv2.convexHull(rightEye) # 寻找右眼轮廓 cv2.drawContours(self.image, [leftEyeHull], -1, (0, 255, 0), 1) # 绘制左眼轮廓 cv2.drawContours(self.image, [rightEyeHull], -1, (0, 255, 0), 1) # 绘制右眼轮廓 # 只有连续帧计数超过EYE_AR_CONSEC_FRAMES时才会计做一次眨眼 if ear < self.EYE_AR_THRESH: self.frame_counter += 1 else: if self.frame_counter >= self.EYE_AR_CONSEC_FRAMES: self.blink_counter += 1 self.frame_counter = 0 # 在图像上显示出眨眼次数blink_counter cv2.putText(self.image, "blink_counts:{0}".format(self.blink_counter), (250, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) def eye_aspect_ratio(self,eye): A = distance.euclidean(eye[1], eye[5]) B = distance.euclidean(eye[2], eye[4]) C = distance.euclidean(eye[0], eye[3]) ear = (A + B) / (2.0 * C) return ear
开始运行:
当确定视频流中是否发生眨眼时,我们需要计算眼睛的长宽比。所以当检测眨眼的时候会受到很多外界因素的影响,例如光线、眨眼速度、摄像头帧率、清晰度等。
而在实验过程中遇到的第一个问题就是下载安装dlib:
报错:is not a supported wheel on this platform.
原因:安装的不是对应python版本的库
解决办法:在cmd后中输入
①python
②import pip
③print(pip.pep425tags.get_supported())
即可以获取到pip支持的文件名还有版本。在pip 安装中必须要确认自己的版本信息,对应好再安装。
注:检测时眨眼放慢点,那样效果会好一点。眼镜反光也可能会导致检测眼睛轮廓时出错,计算出的结果也会是错的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。