利用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眨眼计数器的资料请关注脚本之家其它相关文章!

相关文章

  • Python序列化基础知识(json/pickle)

    Python序列化基础知识(json/pickle)

    这篇文章主要为大家详细介绍了Python序列化json和pickle基础知识,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • Python获取网络时间戳的两种方法详解

    Python获取网络时间戳的两种方法详解

    在我们进行注册码的有效期验证时,通常使用获取网络时间的方式来进行比对。本文将介绍两种利用Python获取网络时间戳的方法,感兴趣的可以了解一下
    2022-01-01
  • Python Django获取URL中的数据详解

    Python Django获取URL中的数据详解

    这篇文章主要介绍了Python Django获取URL中的数据详解,小编觉得挺不错的,这里分享给大家,供需要的朋友参考
    2021-11-11
  • Python实现Wordcloud生成词云图的示例

    Python实现Wordcloud生成词云图的示例

    这篇文章主要介绍了Python实现Wordcloud生成词云图的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • python实现月食效果实例代码

    python实现月食效果实例代码

    在本文里小编给大家整理了关于python实现月食效果的相关实例内容以及对应代码,有兴趣的朋友们学习下。
    2019-06-06
  • python经典100题之皮球掉落的几种解法

    python经典100题之皮球掉落的几种解法

    这篇文章主要给大家介绍了关于python经典100题之皮球掉落的几种解法,这个问题相信不少人都可以从网络上找到相对应的答案本文提供了3种解法,需要的朋友可以参考下
    2023-11-11
  • python中编写config文件并及时更新的方法

    python中编写config文件并及时更新的方法

    在pytorch或者其他深度学习框架中,有许多超参数需要调整,包括learning_rate,training_data_path等,因此编写一个config文件统一存放这些参数,方便调用/查看/修改还是很有必要,这篇文章主要介绍了python中一种编写config文件并及时更新的方法,需要的朋友可以参考下
    2023-02-02
  • python 统计数组中元素出现次数并进行排序的实例

    python 统计数组中元素出现次数并进行排序的实例

    今天小编就为大家分享一篇python 统计数组中元素出现次数并进行排序的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • Python中的with...as用法介绍

    Python中的with...as用法介绍

    这篇文章主要介绍了Python中的with...as用法介绍,本文直接给出用法实例,需要的朋友可以参考下
    2015-05-05
  • pytorch模型的保存加载与续训练详解

    pytorch模型的保存加载与续训练详解

    这篇文章主要为大家介绍了pytorch模型的保存加载与续训练详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11

最新评论