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)

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

(0)

相关推荐

  • 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)#获

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

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

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

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

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

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

  • Opencv光流运动物体追踪详解

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

  • 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

  • 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

  • Python进度条实时显示处理进度的示例代码

    前言 在大多数时候,我们的程序会一直进行循环处理.这时候,我们非常希望能够知道程序的处理进度,由此来决定接下来该做些什么.接下来告诉大家如何简单又漂亮的实现这一功能. 如何使用这个类 使用这个类很简单,只需要三步即可完成,如下: process_bar = ShowProcess(max_steps) # 1.在循环前定义类的实体, max_steps是总的步数 for i in range(max_steps + 1): process_bar.show_process() # 2.显示当前进

  • Python+OpenCV六种实时图像处理详细讲解

    目录 1.导入库文件 2.设计GUI 3.调用摄像头 4.实时图像处理 4.1.阈值二值化 4.2.边缘检测 4.3.轮廓检测 4.4.高斯滤波 4.5.色彩转换 4.6.调节对比度 5.退出系统 初学OpenCV图像处理的小伙伴肯定对什么高斯函数.滤波处理.阈值二值化等特性非常头疼,这里给各位分享一个小项目,可通过摄像头实时动态查看各类图像处理的特点,也可对各位调参.测试有一定帮助. 1.导入库文件 这里主要使用PySimpleGUI.cv2和numpy库文件,PySimpleGUI库文件实现

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

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

  • Python 使用Opencv实现目标检测与识别的示例代码

    在上章节讲述到图像特征检测与匹配 ,本章节是讲述目标检测与识别.后者是在前者的基础上进一步完善. 在本章中,我们使用HOG算法,HOG和SIFT.SURF同属一种类型的描述符.功能代码如下: import cv2 def is_inside(o, i): ox, oy, ow, oh = o ix, iy, iw, ih = i # 如果符合条件,返回True,否则返回False return ox > ix and oy > iy and ox + ow < ix + iw and o

  • Opencv对象追踪的示例代码

    1 HSV上下限 颜色的HSV上下限如下表: 2 追踪单个颜色 import cv2 as cv import numpy as np cap = cv.VideoCapture(0) lower_color = np.array([0, 43, 46]) upper_color = np.array([10, 255, 255]) while cap.isOpened(): # 读取帧 _, frame = cap.read() # 转换颜色空间 BGR 到 HSV hsv = cv.cvtC

  • python编程冒泡排序法实现动图排序示例解析

    目录 先上个冒泡排序的效果图: 动态排序的原理 Python tkinter库Canvas操作 动态排序的完整代码 部分代码注释 先上个冒泡排序的效果图: 是不是,有那么一点点像了? 其实要做这个动图真不是很难,来看冒泡的代码: >>> def Bubble(List): L = len(List)-1 for i in range(L): for j in range(L-i): if List[j]>List[j+1]: List[j],List[j+1]=List[j+1],

  • Python绘制惊艳的可视化动图的示例代码

    今天小编给大家介绍一款可视化模块,使用它可以绘制出十分惊艳的动图效果,那么当然第一步我们首先是要安装一下该模块,通过pip命令行来安装: pip install ipyvizzu 牛刀小试 我们首先来简单地使用该模块来绘制一张动图,用Pandas导入数据集,代码如下: import pandas as pd from ipyvizzu import Chart, Data, Config data_frame = pd.read_csv("titanic.csv") 在导入数据集完毕之

  • 使用OpenCV实现人脸图像卡通化的示例代码

    引言 通过前面的文章我们已经了解到OpenCV 是一个用于计算机视觉和机器学习的开源 python 库.它主要针对实时计算机视觉和图像处理.它用于对图像执行不同的操作,这些操作使用不同的技术对图像进行转换.在本文中,我们将实现使用OpenCV将人脸图像卡通化. 让我们从导入必需的库开始! import cv2 import numpy as np 第一次变换(卡通化) 在这个转换中,我们将找到图像的边缘,并使用双边滤波器和位操作符制作一个卡通化的图像. # Reading the Image i

  • Python编程pygame模块实现移动的小车示例代码

    Pygame是跨平台Python模块,专为电子游戏设计,包含图像.声音.建立在SDL基础上,允许实时电子游戏研发而无需被低级语言(如机器语言和汇编语言)束缚. 最近一个星期学习了一下python的pygame模块,顺便做个小程序巩固所学的,运行效果如下: 其中,背景图"highway.jpg"是使用PhotoShop将其分辨率改变为640 × 480,而小车"car.png"则是将其转变为png格式的图片,并且填充其背景色,让其拥有透明性. 代码测试可用: # -*

随机推荐