利用Python实现眨眼计数器的示例代码

 更新时间:2022年02月07日 08:44:56   作者:一马归一码  
这篇文章主要介绍了如何使用Python语言实现对视频中的人物的眨眼进行计数并描绘在图表中,文中的实现步骤讲解详细,感兴趣的可以动手试一试

一、前言

这几天宅在家里网上冲浪,无意间看到了一个比较有趣的项目,就是使用 Python 语言实现对视频中的人物的眨眼进行计数并描绘在图表中。我尝试了一下,发现是可以实现的,所以自己码了一遍代码并简单注释了一下,有兴趣的朋友可以浅试一下。

该项目大致效果如下:

Now, let's start! 

二、实现步骤

对于创建项目文件夹配置环境以及如何安装第三方库这里就不再详细的介绍了,有不会的同学可以去翻我之前的文章或者其他博主的文章去了解学习吧,并不是很难。

1.第三方库

首先我们需要安装 cvzone(一个比较专业的计算机视觉包,在面部识别,手势、姿势检测中为我们提供了很多便利)。还有一个包是 mediapipe,我们将会使用它来实现面部检测网络,以便于对视频中的眼睛部位进行观察。

2.导入视频文件并播放

实现代码及效果如下:

import cv2
import cvzone
 
cap = cv2.VideoCapture('BlinkCounter.mp4')#获取需要检测的视频(添加视频路径即可,此处由于视频和Python文件在同一路径,直接调用即可)
 
while True:
    success, img = cap.read()
    img = cv2.resize(img, (640, 360)) #对图像尺寸进行调节
    cv2.imshow("Image", img)          #显示图像
    cv2.waitKey(1)

3.让视频循环播放

我们要对视频中的眨眼次数进行计数,但通过上面的代码可以看出视频很快就播放结束了,所以我们采用检查视频帧数的方式,当达到视频的最后一帧时对其进行重置,达到循环播放视频的目的。代码如下:

#------------------------------------------------------------
#检查当前帧数是否等于视频的总体帧数,如果相等,将播放帧数重置为0
#------------------------------------------------------------
    if cap.get(cv2.CAP_PROP_POS_FRAMES) == cap.get(cv2.CAP_PROP_FRAME_COUNT):  
        cap.set(cv2.CAP_PROP_POS_FRAMES, 0)

4.创建面部检测器

该步骤需要使用到 cvzone 中的相应模块来实现,具体代码及注释如下:

import cv2
import cvzone
from cvzone.FaceMeshModule import FaceMeshDetector  #调用面部检测模块
 
cap = cv2.VideoCapture('BlinkCounter.mp4')#获取需要检测的视频(添加视频路径即可,此处由于视频和Python文件在同一路径,直接调用即可)
detector = FaceMeshDetector(maxFaces = 1)#创建人脸网络检测器,检测面部数量为1
 
while True:
#------------------------------------------------------------
#检查当前帧数是否等于视频的总体帧数,如果相等,将播放帧数重置为0
#------------------------------------------------------------
    if cap.get(cv2.CAP_PROP_POS_FRAMES) == cap.get(cv2.CAP_PROP_FRAME_COUNT):
        cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
#------------------------------------------------------------
    success, img = cap.read()
    img, faces = detector.findFaceMesh(img)#绘制人脸网络
 
    img = cv2.resize(img, (640, 360)) #对图像尺寸进行调节
    cv2.imshow("Image", img)          #显示图像
    cv2.waitKey(1) 

得到的结果如下:

5.对眼睛周围的点进行标记

由于面部检测器是对面部用点进行标记的,所以我们需要找到那些眼睛周围的点并将它们使用特殊的点来进行标记,从而达到检测眼睛闭合与张开的目的,相应的点数以及代码如下:

idList = [22, 23, 24, 26, 110, 157, 158, 159, 160, 161, 130, 243]#面部检测器中眼眶周围的像素点
 
color = (0, 0, 255)#将颜色设置为红色
 
#------------------------------------------------------------
#检测到面部时将面部的关于眼眶的点用圆圈表示出来,并填补完整
#------------------------------------------------------------
    if faces:
        face = faces[0]
        for id in idList:
            cv2.circle(img, face[id], 5, color, cv2.FILLED)

得到的效果如下,可以看出,已经对眼眶进行了标记:

我们可以对面部检测网络进行设置,让其他的一些点不再显示出来,只关注我们的目标点,具体操作方式是只需要在函数中添加一个参数即可,效果如下:

img, faces = detector.findFaceMesh(img, draw = False)#绘制人脸检测网络,将参数 draw 修改为    False 即可抹去其他的不必要的点

6.观察眼睛宽度和长度变化并进行计数

如果单纯的靠上下眼皮的变化来检测是否眨眼会造成判断错误,所以我们需要结合眼睛长度和宽度之比进行判断。将这项数据的变化趋势绘制在一个窗口中,就会使得我们的观察更加明显,得到的效果也将更加优良。具体代码如下:

#-------------------------------------------------------------
#使用眼眶周围不同的点之间的距离以及眼睛宽度和长度的对比进行眨眼计数
#-------------------------------------------------------------
        leftUp = face[159]#定义不同部位的像素点
        leftDown = face[23]
        leftLeft = face[130]
        leftRight = face[243]
        lenghtVer, _ = detector.findDistance(leftUp, leftDown)#得到眼睛宽度
        lenghtHor, _ = detector.findDistance(leftLeft, leftRight)#得到眼睛长度
 
        cv2.line(img, leftUp, leftDown, (0, 200, 0), 3)#绘制与眼睛等宽的线段
        cv2.line(img, leftLeft, leftRight, (0, 200, 0), 3)#绘制与眼睛等长的线段
 
        ratio = int((lenghtVer / lenghtHor) * 100)#得到的数据并进行标准化,得到比率值
 
        ratioList.append(ratio)#使用比率值填补列表
        #------------------------------------------------------------------
        #从之前的一共三个比率中得到平均值,如果比率数目大于3将会删去前面的比率值
        #------------------------------------------------------------------
        if len(ratioList) > 3:
            ratioList.pop(0)
        ratioAvg = sum(ratioList) / len(ratioList)#得到比率平均值
        #------------------------------------
        #通过比率平均值的变化对眨眼次数进行计数
        #------------------------------------
        if ratioAvg < 35 and counter == 0:
            blinkCounter += 1#变化一次,计数器加一
            color = (0, 200, 0)
            counter = 1
        if counter != 0:
            counter += 1
            if counter > 10:
                counter = 0
                color = (255, 0, 255)
        #-----------------------------
        #编写文本框来记录眨眼的总体次数
        #------------------------------
        cvzone.putTextRect(img, f'Blink Count: {blinkCounter}', (50, 250),
                           12, colorR = color)
 
        imgPlot = plotY.update(ratioAvg, color)
        img = cv2.resize(img, (400, 640))  # 对图像尺寸进行调节
        imgStack = cvzone.stackImages([img, imgPlot], 2, 1)#将两幅图像放到一起,叠放为2列图像
    else:
        img = cv2.resize(img, (400, 640))  # 对图像尺寸进行调节
        imgStack = cvzone.stackImages([img, img], 2, 1)

通过以上步骤大致就能实现眨眼计数了。 

三、整体代码

整体代码如下,已经添加了注释,如果有解释的不清楚的地方可以在评论区交流。

import cv2
import cvzone
from cvzone.FaceMeshModule import FaceMeshDetector
from cvzone.PlotModule import LivePlot
 
cap = cv2.VideoCapture('BlinkCounter.mp4')#获取需要检测的视频(添加视频路径即可,此处由于视频和Python文件在同一路径,直接调用即可)
detector = FaceMeshDetector(maxFaces = 1)#创建人脸网络检测器,检测面部数量为1
plotY = LivePlot(640, 640, [20, 50], invert = True)#创建窗口来绘制数据的变化
 
idList = [22, 23, 24, 26, 110, 157, 158, 159, 160, 161, 130, 243]#面部检测器中眼眶周围的像素点
ratioList = []#创建一个空的比率列表
blinkCounter = 0
counter = 0#避免每一个帧节进行一次计数
 
color = (0, 0, 255)#将颜色设置为红色
 
while True:
#------------------------------------------------------------
#检查当前帧数是否等于视频的总体帧数,如果相等,将播放帧数重置为0
#------------------------------------------------------------
    if cap.get(cv2.CAP_PROP_POS_FRAMES) == cap.get(cv2.CAP_PROP_FRAME_COUNT):
        cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
 
    success, img = cap.read()#读取到的视频
    img, faces = detector.findFaceMesh(img, draw = False)#绘制人脸检测网络
#------------------------------------------------------------
#检测到面部时将面部的关于眼眶的点用圆圈表示出来,并填补完整
#------------------------------------------------------------
    if faces:
        face = faces[0]
        for id in idList:
            cv2.circle(img, face[id], 5, color, cv2.FILLED)
#-------------------------------------------------------------
#使用眼眶周围不同的点之间的距离以及眼睛宽度和长度的对比进行眨眼计数
#-------------------------------------------------------------
        leftUp = face[159]#定义不同部位的像素点
        leftDown = face[23]
        leftLeft = face[130]
        leftRight = face[243]
        lenghtVer, _ = detector.findDistance(leftUp, leftDown)#得到眼睛宽度
        lenghtHor, _ = detector.findDistance(leftLeft, leftRight)#得到眼睛长度
 
        cv2.line(img, leftUp, leftDown, (0, 200, 0), 3)#绘制与眼睛等宽的线段
        cv2.line(img, leftLeft, leftRight, (0, 200, 0), 3)#绘制与眼睛等长的线段
 
        ratio = int((lenghtVer / lenghtHor) * 100)#得到的数据并进行标准化,得到比率值
 
        ratioList.append(ratio)#使用比率值填补列表
        #------------------------------------------------------------------
        #从之前的一共三个比率中得到平均值,如果比率数目大于3将会删去前面的比率值
        #------------------------------------------------------------------
        if len(ratioList) > 3:
            ratioList.pop(0)
        ratioAvg = sum(ratioList) / len(ratioList)#得到比率平均值
        #------------------------------------
        #通过比率平均值的变化对眨眼次数进行计数
        #------------------------------------
        if ratioAvg < 35 and counter == 0:
            blinkCounter += 1#变化一次,计数器加一
            color = (0, 200, 0)
            counter = 1
        if counter != 0:
            counter += 1
            if counter > 10:
                counter = 0
                color = (255, 0, 255)
        #-----------------------------
        #编写文本框来记录眨眼的总体次数
        #------------------------------
        cvzone.putTextRect(img, f'Blink Count: {blinkCounter}', (50, 250),
                           12, colorR = color)
 
        imgPlot = plotY.update(ratioAvg, color)
        img = cv2.resize(img, (400, 640))  # 对图像尺寸进行调节
        imgStack = cvzone.stackImages([img, imgPlot], 2, 1)#将两幅图像放到一起,叠放为2列图像
    else:
        img = cv2.resize(img, (400, 640))  # 对图像尺寸进行调节
        imgStack = cvzone.stackImages([img, img], 2, 1)
 
    img = cv2.resize(img, (400, 640)) #对图像尺寸进行调节
    cv2.imshow("Image", imgStack)
    cv2.waitKey(1)

以上就是利用Python实现眨眼计数器的示例代码的详细内容,更多关于Python眨眼计数器的资料请关注脚本之家其它相关文章!

相关文章

  • wxPython的安装与使用教程

    wxPython的安装与使用教程

    wxPython是Python语言的一套优秀的GUI图形库。wxPython可以很方便的创建完整的、功能键全的GUI用户界面。这篇文章给大家介绍了wxPython的安装与使用,感兴趣的朋友一起看看吧
    2018-08-08
  • CNN卷积函数Conv2D()各参数的含义及用法解读

    CNN卷积函数Conv2D()各参数的含义及用法解读

    这篇文章主要介绍了CNN卷积函数Conv2D()各参数的含义及用法解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • Appium+Python自动化环境搭建实例教程

    Appium+Python自动化环境搭建实例教程

    这篇文章主要介绍了Appium+Python自动化环境搭建实例教程,本文通过实例代码图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-08-08
  • Python制作简易版2048小游戏

    Python制作简易版2048小游戏

    2048作为经典的手机端游戏一直深受大家的喜爱,本文将利用Python中的Pygame模块制作简单版的2048游戏,感兴趣的小伙伴可以了解一下
    2022-07-07
  • python 简单的多线程链接实现代码

    python 简单的多线程链接实现代码

    这篇文章主要介绍了python 简单的多线程链接实现代码,需要的朋友可以参考下
    2016-08-08
  • django框架基于模板 生成 excel(xls) 文件操作示例

    django框架基于模板 生成 excel(xls) 文件操作示例

    这篇文章主要介绍了django框架基于模板 生成 excel(xls) 文件操作,结合具体实例形式分析了Django框架基于模板生成excel的实现步骤与相关操作技巧,需要的朋友可以参考下
    2019-06-06
  • python 列表,数组和矩阵sum的用法及区别介绍

    python 列表,数组和矩阵sum的用法及区别介绍

    今天小编就为大家分享一篇python 列表,数组和矩阵sum的用法及区别介绍,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-06-06
  • 如何使用Python抓取网页tag操作

    如何使用Python抓取网页tag操作

    这篇文章主要介绍了如何使用Python抓取网页tag操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • Python中Dataframe数据排序方法(含实例讲解)

    Python中Dataframe数据排序方法(含实例讲解)

    在进行数据分析操作时,经常需要对数据按照某行某列排序,或者按照多行多列排序,以及按照索引值排序等等,下面这篇文章主要给大家介绍了关于Python中Dataframe数据排序方法的相关资料,需要的朋友可以参考下
    2023-02-02
  • python3实现tailf命令的示例代码

    python3实现tailf命令的示例代码

    本文主要介绍了python3实现tailf命令的示例代码,tail -f 是一个linux的操作命令.其主要的是会把文件里的最尾部的内容显显示在屏幕上,并且不断刷新,只要文件有变动就可以看到最新的文件内容,感兴趣的可以了解一下
    2023-11-11

最新评论