Python+OpenCV实现实时眼动追踪的示例代码

使用Python+OpenCV实现实时眼动追踪,不需要高端硬件简单摄像头即可实现,效果图如下所示。

项目演示参见:https://www.bilibili.com/video/av75181965/

项目主程序如下:

import sys
import cv2
import numpy as np
import process
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.uic import loadUi
from PyQt5.QtGui import QPixmap, QImage

class Window(QMainWindow):
  def __init__(self):
    super(Window, self).__init__()
    loadUi('GUImain.ui', self)
    with open("style.css", "r") as css:
      self.setStyleSheet(css.read())
    self.face_decector, self.eye_detector, self.detector = process.init_cv()
    self.startButton.clicked.connect(self.start_webcam)
    self.stopButton.clicked.connect(self.stop_webcam)
    self.camera_is_running = False
    self.previous_right_keypoints = None
    self.previous_left_keypoints = None
    self.previous_right_blob_area = None
    self.previous_left_blob_area = None

  def start_webcam(self):
    if not self.camera_is_running:
      self.capture = cv2.VideoCapture(cv2.CAP_DSHOW) # VideoCapture(0) sometimes drops error #-1072875772
      if self.capture is None:
        self.capture = cv2.VideoCapture(0)
      self.camera_is_running = True
      self.timer = QTimer(self)
      self.timer.timeout.connect(self.update_frame)
      self.timer.start(2)

  def stop_webcam(self):
    if self.camera_is_running:
      self.capture.release()
      self.timer.stop()
      self.camera_is_running = not self.camera_is_running

  def update_frame(self): # logic of the main loop

    _, base_image = self.capture.read()
    self.display_image(base_image)

    processed_image = cv2.cvtColor(base_image, cv2.COLOR_RGB2GRAY)

    face_frame, face_frame_gray, left_eye_estimated_position, right_eye_estimated_position, _, _ = process.detect_face(
      base_image, processed_image, self.face_decector)

    if face_frame is not None:
      left_eye_frame, right_eye_frame, left_eye_frame_gray, right_eye_frame_gray = process.detect_eyes(face_frame,
                                                       face_frame_gray,
                                                       left_eye_estimated_position,
                                                       right_eye_estimated_position,
                                                       self.eye_detector)

      if right_eye_frame is not None:
        if self.rightEyeCheckbox.isChecked():
          right_eye_threshold = self.rightEyeThreshold.value()
          right_keypoints, self.previous_right_keypoints, self.previous_right_blob_area = self.get_keypoints(
            right_eye_frame, right_eye_frame_gray, right_eye_threshold,
            previous_area=self.previous_right_blob_area,
            previous_keypoint=self.previous_right_keypoints)
          process.draw_blobs(right_eye_frame, right_keypoints)

        right_eye_frame = np.require(right_eye_frame, np.uint8, 'C')
        self.display_image(right_eye_frame, window='right')

      if left_eye_frame is not None:
        if self.leftEyeCheckbox.isChecked():
          left_eye_threshold = self.leftEyeThreshold.value()
          left_keypoints, self.previous_left_keypoints, self.previous_left_blob_area = self.get_keypoints(
            left_eye_frame, left_eye_frame_gray, left_eye_threshold,
            previous_area=self.previous_left_blob_area,
            previous_keypoint=self.previous_left_keypoints)
          process.draw_blobs(left_eye_frame, left_keypoints)

        left_eye_frame = np.require(left_eye_frame, np.uint8, 'C')
        self.display_image(left_eye_frame, window='left')

    if self.pupilsCheckbox.isChecked(): # draws keypoints on pupils on main window
      self.display_image(base_image)

  def get_keypoints(self, frame, frame_gray, threshold, previous_keypoint, previous_area):

    keypoints = process.process_eye(frame_gray, threshold, self.detector,
                    prevArea=previous_area)
    if keypoints:
      previous_keypoint = keypoints
      previous_area = keypoints[0].size
    else:
      keypoints = previous_keypoint
    return keypoints, previous_keypoint, previous_area

  def display_image(self, img, window='main'):
    # Makes OpenCV images displayable on PyQT, displays them
    qformat = QImage.Format_Indexed8
    if len(img.shape) == 3:
      if img.shape[2] == 4: # RGBA
        qformat = QImage.Format_RGBA8888
      else: # RGB
        qformat = QImage.Format_RGB888

    out_image = QImage(img, img.shape[1], img.shape[0], img.strides[0], qformat) # BGR to RGB
    out_image = out_image.rgbSwapped()
    if window == 'main': # main window
      self.baseImage.setPixmap(QPixmap.fromImage(out_image))
      self.baseImage.setScaledContents(True)
    if window == 'left': # left eye window
      self.leftEyeBox.setPixmap(QPixmap.fromImage(out_image))
      self.leftEyeBox.setScaledContents(True)
    if window == 'right': # right eye window
      self.rightEyeBox.setPixmap(QPixmap.fromImage(out_image))
      self.rightEyeBox.setScaledContents(True)

if __name__ == "__main__":
  app = QApplication(sys.argv)
  window = Window()
  window.setWindowTitle("GUI")
  window.show()
  sys.exit(app.exec_())

人眼检测程序如下:

import os
import cv2
import numpy as np

def init_cv():
  """loads all of cv2 tools"""
  face_detector = cv2.CascadeClassifier(
    os.path.join("Classifiers", "haar", "haarcascade_frontalface_default.xml"))
  eye_detector = cv2.CascadeClassifier(os.path.join("Classifiers", "haar", 'haarcascade_eye.xml'))
  detector_params = cv2.SimpleBlobDetector_Params()
  detector_params.filterByArea = True
  detector_params.maxArea = 1500
  detector = cv2.SimpleBlobDetector_create(detector_params)

  return face_detector, eye_detector, detector

def detect_face(img, img_gray, cascade):
  """
  Detects all faces, if multiple found, works with the biggest. Returns the following parameters:
  1. The face frame
  2. A gray version of the face frame
  2. Estimated left eye coordinates range
  3. Estimated right eye coordinates range
  5. X of the face frame
  6. Y of the face frame
  """
  coords = cascade.detectMultiScale(img, 1.3, 5)

  if len(coords) > 1:
    biggest = (0, 0, 0, 0)
    for i in coords:
      if i[3] > biggest[3]:
        biggest = i
    biggest = np.array([i], np.int32)
  elif len(coords) == 1:
    biggest = coords
  else:
    return None, None, None, None, None, None
  for (x, y, w, h) in biggest:
    frame = img[y:y + h, x:x + w]
    frame_gray = img_gray[y:y + h, x:x + w]
    lest = (int(w * 0.1), int(w * 0.45))
    rest = (int(w * 0.55), int(w * 0.9))
    X = x
    Y = y

  return frame, frame_gray, lest, rest, X, Y

def detect_eyes(img, img_gray, lest, rest, cascade):
  """
  :param img: image frame
  :param img_gray: gray image frame
  :param lest: left eye estimated position, needed to filter out nostril, know what eye is found
  :param rest: right eye estimated position
  :param cascade: Hhaar cascade
  :return: colored and grayscale versions of eye frames
  """
  leftEye = None
  rightEye = None
  leftEyeG = None
  rightEyeG = None
  coords = cascade.detectMultiScale(img_gray, 1.3, 5)

  if coords is None or len(coords) == 0:
    pass
  else:
    for (x, y, w, h) in coords:
      eyecenter = int(float(x) + (float(w) / float(2)))
      if lest[0] < eyecenter and eyecenter < lest[1]:
        leftEye = img[y:y + h, x:x + w]
        leftEyeG = img_gray[y:y + h, x:x + w]
        leftEye, leftEyeG = cut_eyebrows(leftEye, leftEyeG)
      elif rest[0] < eyecenter and eyecenter < rest[1]:
        rightEye = img[y:y + h, x:x + w]
        rightEyeG = img_gray[y:y + h, x:x + w]
        rightEye, rightEye = cut_eyebrows(rightEye, rightEyeG)
      else:
        pass # nostril
  return leftEye, rightEye, leftEyeG, rightEyeG

def process_eye(img, threshold, detector, prevArea=None):
  """
  :param img: eye frame
  :param threshold: threshold value for threshold function
  :param detector: blob detector
  :param prevArea: area of the previous keypoint(used for filtering)
  :return: keypoints
  """
  _, img = cv2.threshold(img, threshold, 255, cv2.THRESH_BINARY)
  img = cv2.erode(img, None, iterations=2)
  img = cv2.dilate(img, None, iterations=4)
  img = cv2.medianBlur(img, 5)
  keypoints = detector.detect(img)
  if keypoints and prevArea and len(keypoints) > 1:
    tmp = 1000
    for keypoint in keypoints: # filter out odd blobs
      if abs(keypoint.size - prevArea) < tmp:
        ans = keypoint
        tmp = abs(keypoint.size - prevArea)
    keypoints = np.array(ans)

  return keypoints

def cut_eyebrows(img, imgG):
  height, width = img.shape[:2]
  img = img[15:height, 0:width] # cut eyebrows out (15 px)
  imgG = imgG[15:height, 0:width]

  return img, imgG

def draw_blobs(img, keypoints):
  """Draws blobs"""
  cv2.drawKeypoints(img, keypoints, img, (0, 0, 255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2019-11-10

python+opencv实现动态物体追踪

简单几行就可以实现对动态物体的追踪,足见opencv在图像处理上的强大. python代码: import cv2 import numpy as np camera=cv2.VideoCapture(0) firstframe=None while True: ret,frame = camera.read() if not ret: break gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) gray=cv2.GaussianBlur(gray,(21

opencv+arduino实现物体点追踪效果

本文所要实现的结果是:通过在摄像头中选择一个追踪点,通过pc控制摄像头的舵机,使这一点始终在图像的中心. 要点:使用光流法在舵机旋转的同时进行追踪,若该点运动,则摄像头跟踪联动. #include<opencv2\opencv.hpp> #include<opencv\cv.h> #include<opencv\highgui.h> #include<math.h> #include<Windows.h> #include<string.h

使用OpenCV实现检测和追踪车辆

本文实例为大家分享了OpenCV实现检测和追踪车辆的具体代码,供大家参考,具体内容如下 完整源码GitHub 使用高斯混合模型(BackgroundSubtractorMOG2)对背景建模,提取出前景 使用中值滤波去掉椒盐噪声,再闭运算和开运算填充空洞 使用cvBlob库追踪车辆,我稍微修改了cvBlob源码来通过编译 由于要对背景建模,这个方法要求背景是静止的 另外不同车辆白色区域不能连通,否则会认为是同一物体 void processVideo(char* videoFilename) {

Opencv光流运动物体追踪详解

光流的概念是由一个叫Gibson的哥们在1950年提出来的.它描述是空间运动物体在观察成像平面上的像素运动的瞬时速度,利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系,从而计算出相邻帧之间物体的运动信息的一种方法.那么所说的光流到底是什么? 简单来说,上图表现的就是光流,光流描述的是图像上每个像素点的灰度的位置(速度)变化情况,光流的研究是利用图像序列中的像素强度数据的时域变化和相关性来确定各自像素位置的"运动".研究光流场的目的就是为了从

OpenCV3.0+Python3.6实现特定颜色的物体追踪

一.环境 win10.Python3.6.OpenCV3.x:编译器:pycharm5.0.3 二.实现目标 根据需要追踪的物体颜色,设定阈值,在视频中框选出需要追踪的物体. 三.实现步骤 1)根据需要追踪的物体颜色,设定颜色阈值,获取追踪物体的掩膜 代码:generate_threshold.py # -*- coding : utf-8 -*- # Author: Tom Yu import cv2 import numpy as np cap = cv2.VideoCapture(0)#获

浅析Python+OpenCV使用摄像头追踪人脸面部血液变化实现脉搏评估

使用摄像头追踪人脸由于血液流动引起的面部色素的微小变化实现实时脉搏评估. 效果如下(演示视频): 由于这是通过比较面部色素的变化评估脉搏所以光线.人体移动.不同角度.不同电脑摄像头等因素均会影响评估效果,实验原理是面部色素对比,识别效果存在一定误差,各位小伙伴且当娱乐,代码如下: import cv2 import numpy as np import dlib import time from scipy import signal # Constants WINDOW_TITLE = 'Pu

Python OpenCV调用摄像头检测人脸并截图

本文实例为大家分享了Python OpenCV调用摄像头检测人脸并截图的具体代码,供大家参考,具体内容如下 注意:需要在python中安装OpenCV库,同时需要下载OpenCV人脸识别模型haarcascade_frontalface_alt.xml,模型可在OpenCV-PCA-KNN-SVM_face_recognition中下载. 使用OpenCV调用摄像头检测人脸并连续截图100张 #-*- coding: utf-8 -*- # import 进openCV的库 import cv2

python openCV实现摄像头获取人脸图片

本文实例为大家分享了python openCV实现摄像头获取人脸图片的具体代码,供大家参考,具体内容如下 在机器学习中,训练模型需要大量图片,通过openCV中的库可以快捷的调用摄像头,截取图片,可以快速的获取大量人脸图片 需要注意将CascadeClassifier方法中的地址改为自己包cv2包下面的文件 import cv2 def load_img(path,name,mun = 100,add_with = 0): # 获取人脸识别模型 # # #以下路径需要更改为自己环境下xml文件

python opencv设置摄像头分辨率以及各个参数的方法

1,为了获取视频,你应该创建一个 VideoCapture 对象.他的参数可以是设备的索引号,或者是一个视频文件.设备索引号就是在指定要使用的摄像头.一般的笔记本电脑都有内置摄像头.所以参数就是 0.你可以通过设置成 1 或者其他的来选择别的摄像头.之后,你就可以一帧一帧的捕获视频了.但是最后,别忘了停止捕获视频.使用 ls /dev/video*命令可以查看摄像头设备 2,cap.read() 返回一个布尔值(True/False).如果帧读取的是正确的,就是 True.所以最后你可以通过检查

python+opencv实现的简单人脸识别代码示例

# 源码如下: #!/usr/bin/env python #coding=utf-8 import os from PIL import Image, ImageDraw import cv def detect_object(image): '''检测图片,获取人脸在图片中的坐标''' grayscale = cv.CreateImage((image.width, image.height), 8, 1) cv.CvtColor(image, grayscale, cv.CV_BGR2GR

python+openCV利用摄像头实现人员活动检测

本文实例为大家分享了python+openCV利用摄像头实现人员活动检测的具体代码,供大家参考,具体内容如下 1.前言 最近在做个机器人比赛,其中一项要求是让机器人实现对是否有人员活动的检测,所以就先拿PC端写一下,准备移植到机器人的树莓派. 2.工具 工具还是简单的python+视觉模块openCV,代码量也比较少.很简单就可以实现 3.人员检测的原理   从图书馆借了一本<特征提取与图像处理(第二版)>,是Mark S.Nixon和Alberto S.Aguado写的,其中讲了跟多关于检测

Python OpenCV 调用摄像头并截图保存功能的实现代码

0x01 OpenCV安装 通过命令pip install opencv-python 安装 pip install opencv-python 0x02  示例 import cv2 cap = cv2.VideoCapture(0) #打开摄像头 while(1): # get a frame ret, frame = cap.read() # show a frame cv2.imshow("capture", frame) #生成摄像头窗口 if cv2.waitKey(1)

python+openCV调用摄像头拍摄和处理图片的实现

在深度学习过程中想做手势识别相关应用,需要大量采集手势图片进行训练,作为一个懒人当然希望飞快的连续采集图片并且采集到的图片就已经被处理成统一格式的啦..于是使用python+openCV调用摄像头,在采集图片的同时顺便处理成想要的格式. 详细代码如下: import cv2 import os print("=============================================") print("= 热键(请在摄像头的窗口使用): =") pri

python+opencv打开摄像头,保存视频、拍照功能的实现方法

以下代码是保存视频 # coding:utf-8 import cv2 import sys reload(sys) sys.setdefaultencoding('utf8') cap = cv2.VideoCapture(0) cap.set(3,640) cap.set(4,480) cap.set(1, 10.0) #此处fourcc的在MAC上有效,如果视频保存为空,那么可以改一下这个参数试试, 也可以是-1 fourcc = cv2.cv.CV_FOURCC('m', 'p', '4

python+opencv+caffe+摄像头做目标检测的实例代码

首先之前已经成功的使用Python做图像的目标检测,这回因为项目最终是需要用摄像头的, 所以实现摄像头获取图像,并且用Python调用CAFFE接口来实现目标识别 首先是摄像头请选择支持Linux万能驱动兼容V4L2的摄像头, 因为之前用学ARM的时候使用的Smart210,我已经确认我的摄像头是支持的, 我把摄像头插上之後自然就在 /dev 目录下看到多了一个video0的文件, 这个就是摄像头的设备文件了,所以我就没有额外处理驱动的部分 一.检测环境 再来在开始前因为之前按着国嵌的指导手册安