利用Python實現(xiàn)眨眼計數(shù)器的示例代碼
一、前言
這幾天宅在家里網(wǎng)上沖浪,無意間看到了一個比較有趣的項目,就是使用 Python 語言實現(xiàn)對視頻中的人物的眨眼進行計數(shù)并描繪在圖表中。我嘗試了一下,發(fā)現(xiàn)是可以實現(xiàn)的,所以自己碼了一遍代碼并簡單注釋了一下,有興趣的朋友可以淺試一下。
該項目大致效果如下:
Now, let's start!
二、實現(xiàn)步驟
對于創(chuàng)建項目文件夾配置環(huán)境以及如何安裝第三方庫這里就不再詳細的介紹了,有不會的同學可以去翻我之前的文章或者其他博主的文章去了解學習吧,并不是很難。
1.第三方庫
首先我們需要安裝 cvzone(一個比較專業(yè)的計算機視覺包,在面部識別,手勢、姿勢檢測中為我們提供了很多便利)。還有一個包是 mediapipe,我們將會使用它來實現(xiàn)面部檢測網(wǎng)絡(luò),以便于對視頻中的眼睛部位進行觀察。
2.導入視頻文件并播放
實現(xiàn)代碼及效果如下:
import cv2 import cvzone cap = cv2.VideoCapture('BlinkCounter.mp4')#獲取需要檢測的視頻(添加視頻路徑即可,此處由于視頻和Python文件在同一路徑,直接調(diào)用即可) while True: success, img = cap.read() img = cv2.resize(img, (640, 360)) #對圖像尺寸進行調(diào)節(jié) cv2.imshow("Image", img) #顯示圖像 cv2.waitKey(1)
3.讓視頻循環(huán)播放
我們要對視頻中的眨眼次數(shù)進行計數(shù),但通過上面的代碼可以看出視頻很快就播放結(jié)束了,所以我們采用檢查視頻幀數(shù)的方式,當達到視頻的最后一幀時對其進行重置,達到循環(huán)播放視頻的目的。代碼如下:
#------------------------------------------------------------ #檢查當前幀數(shù)是否等于視頻的總體幀數(shù),如果相等,將播放幀數(shù)重置為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.創(chuàng)建面部檢測器
該步驟需要使用到 cvzone 中的相應(yīng)模塊來實現(xiàn),具體代碼及注釋如下:
import cv2 import cvzone from cvzone.FaceMeshModule import FaceMeshDetector #調(diào)用面部檢測模塊 cap = cv2.VideoCapture('BlinkCounter.mp4')#獲取需要檢測的視頻(添加視頻路徑即可,此處由于視頻和Python文件在同一路徑,直接調(diào)用即可) detector = FaceMeshDetector(maxFaces = 1)#創(chuàng)建人臉網(wǎng)絡(luò)檢測器,檢測面部數(shù)量為1 while True: #------------------------------------------------------------ #檢查當前幀數(shù)是否等于視頻的總體幀數(shù),如果相等,將播放幀數(shù)重置為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)#繪制人臉網(wǎng)絡(luò) img = cv2.resize(img, (640, 360)) #對圖像尺寸進行調(diào)節(jié) cv2.imshow("Image", img) #顯示圖像 cv2.waitKey(1)
得到的結(jié)果如下:
5.對眼睛周圍的點進行標記
由于面部檢測器是對面部用點進行標記的,所以我們需要找到那些眼睛周圍的點并將它們使用特殊的點來進行標記,從而達到檢測眼睛閉合與張開的目的,相應(yīng)的點數(shù)以及代碼如下:
idList = [22, 23, 24, 26, 110, 157, 158, 159, 160, 161, 130, 243]#面部檢測器中眼眶周圍的像素點 color = (0, 0, 255)#將顏色設(shè)置為紅色 #------------------------------------------------------------ #檢測到面部時將面部的關(guān)于眼眶的點用圓圈表示出來,并填補完整 #------------------------------------------------------------ if faces: face = faces[0] for id in idList: cv2.circle(img, face[id], 5, color, cv2.FILLED)
得到的效果如下,可以看出,已經(jīng)對眼眶進行了標記:
我們可以對面部檢測網(wǎng)絡(luò)進行設(shè)置,讓其他的一些點不再顯示出來,只關(guān)注我們的目標點,具體操作方式是只需要在函數(shù)中添加一個參數(shù)即可,效果如下:
img, faces = detector.findFaceMesh(img, draw = False)#繪制人臉檢測網(wǎng)絡(luò),將參數(shù) draw 修改為 False 即可抹去其他的不必要的點
6.觀察眼睛寬度和長度變化并進行計數(shù)
如果單純的靠上下眼皮的變化來檢測是否眨眼會造成判斷錯誤,所以我們需要結(jié)合眼睛長度和寬度之比進行判斷。將這項數(shù)據(jù)的變化趨勢繪制在一個窗口中,就會使得我們的觀察更加明顯,得到的效果也將更加優(yōu)良。具體代碼如下:
#------------------------------------------------------------- #使用眼眶周圍不同的點之間的距離以及眼睛寬度和長度的對比進行眨眼計數(shù) #------------------------------------------------------------- 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)#得到的數(shù)據(jù)并進行標準化,得到比率值 ratioList.append(ratio)#使用比率值填補列表 #------------------------------------------------------------------ #從之前的一共三個比率中得到平均值,如果比率數(shù)目大于3將會刪去前面的比率值 #------------------------------------------------------------------ if len(ratioList) > 3: ratioList.pop(0) ratioAvg = sum(ratioList) / len(ratioList)#得到比率平均值 #------------------------------------ #通過比率平均值的變化對眨眼次數(shù)進行計數(shù) #------------------------------------ if ratioAvg < 35 and counter == 0: blinkCounter += 1#變化一次,計數(shù)器加一 color = (0, 200, 0) counter = 1 if counter != 0: counter += 1 if counter > 10: counter = 0 color = (255, 0, 255) #----------------------------- #編寫文本框來記錄眨眼的總體次數(shù) #------------------------------ cvzone.putTextRect(img, f'Blink Count: {blinkCounter}', (50, 250), 12, colorR = color) imgPlot = plotY.update(ratioAvg, color) img = cv2.resize(img, (400, 640)) # 對圖像尺寸進行調(diào)節(jié) imgStack = cvzone.stackImages([img, imgPlot], 2, 1)#將兩幅圖像放到一起,疊放為2列圖像 else: img = cv2.resize(img, (400, 640)) # 對圖像尺寸進行調(diào)節(jié) imgStack = cvzone.stackImages([img, img], 2, 1)
通過以上步驟大致就能實現(xiàn)眨眼計數(shù)了。
三、整體代碼
整體代碼如下,已經(jīng)添加了注釋,如果有解釋的不清楚的地方可以在評論區(qū)交流。
import cv2 import cvzone from cvzone.FaceMeshModule import FaceMeshDetector from cvzone.PlotModule import LivePlot cap = cv2.VideoCapture('BlinkCounter.mp4')#獲取需要檢測的視頻(添加視頻路徑即可,此處由于視頻和Python文件在同一路徑,直接調(diào)用即可) detector = FaceMeshDetector(maxFaces = 1)#創(chuàng)建人臉網(wǎng)絡(luò)檢測器,檢測面部數(shù)量為1 plotY = LivePlot(640, 640, [20, 50], invert = True)#創(chuàng)建窗口來繪制數(shù)據(jù)的變化 idList = [22, 23, 24, 26, 110, 157, 158, 159, 160, 161, 130, 243]#面部檢測器中眼眶周圍的像素點 ratioList = []#創(chuàng)建一個空的比率列表 blinkCounter = 0 counter = 0#避免每一個幀節(jié)進行一次計數(shù) color = (0, 0, 255)#將顏色設(shè)置為紅色 while True: #------------------------------------------------------------ #檢查當前幀數(shù)是否等于視頻的總體幀數(shù),如果相等,將播放幀數(shù)重置為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)#繪制人臉檢測網(wǎng)絡(luò) #------------------------------------------------------------ #檢測到面部時將面部的關(guān)于眼眶的點用圓圈表示出來,并填補完整 #------------------------------------------------------------ if faces: face = faces[0] for id in idList: cv2.circle(img, face[id], 5, color, cv2.FILLED) #------------------------------------------------------------- #使用眼眶周圍不同的點之間的距離以及眼睛寬度和長度的對比進行眨眼計數(shù) #------------------------------------------------------------- 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)#得到的數(shù)據(jù)并進行標準化,得到比率值 ratioList.append(ratio)#使用比率值填補列表 #------------------------------------------------------------------ #從之前的一共三個比率中得到平均值,如果比率數(shù)目大于3將會刪去前面的比率值 #------------------------------------------------------------------ if len(ratioList) > 3: ratioList.pop(0) ratioAvg = sum(ratioList) / len(ratioList)#得到比率平均值 #------------------------------------ #通過比率平均值的變化對眨眼次數(shù)進行計數(shù) #------------------------------------ if ratioAvg < 35 and counter == 0: blinkCounter += 1#變化一次,計數(shù)器加一 color = (0, 200, 0) counter = 1 if counter != 0: counter += 1 if counter > 10: counter = 0 color = (255, 0, 255) #----------------------------- #編寫文本框來記錄眨眼的總體次數(shù) #------------------------------ cvzone.putTextRect(img, f'Blink Count: {blinkCounter}', (50, 250), 12, colorR = color) imgPlot = plotY.update(ratioAvg, color) img = cv2.resize(img, (400, 640)) # 對圖像尺寸進行調(diào)節(jié) imgStack = cvzone.stackImages([img, imgPlot], 2, 1)#將兩幅圖像放到一起,疊放為2列圖像 else: img = cv2.resize(img, (400, 640)) # 對圖像尺寸進行調(diào)節(jié) imgStack = cvzone.stackImages([img, img], 2, 1) img = cv2.resize(img, (400, 640)) #對圖像尺寸進行調(diào)節(jié) cv2.imshow("Image", imgStack) cv2.waitKey(1)
以上就是利用Python實現(xiàn)眨眼計數(shù)器的示例代碼的詳細內(nèi)容,更多關(guān)于Python眨眼計數(shù)器的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
CNN卷積函數(shù)Conv2D()各參數(shù)的含義及用法解讀
這篇文章主要介紹了CNN卷積函數(shù)Conv2D()各參數(shù)的含義及用法解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02Appium+Python自動化環(huán)境搭建實例教程
這篇文章主要介紹了Appium+Python自動化環(huán)境搭建實例教程,本文通過實例代碼圖文相結(jié)合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-08-08django框架基于模板 生成 excel(xls) 文件操作示例
這篇文章主要介紹了django框架基于模板 生成 excel(xls) 文件操作,結(jié)合具體實例形式分析了Django框架基于模板生成excel的實現(xiàn)步驟與相關(guān)操作技巧,需要的朋友可以參考下2019-06-06python 列表,數(shù)組和矩陣sum的用法及區(qū)別介紹
今天小編就為大家分享一篇python 列表,數(shù)組和矩陣sum的用法及區(qū)別介紹,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-06-06Python中Dataframe數(shù)據(jù)排序方法(含實例講解)
在進行數(shù)據(jù)分析操作時,經(jīng)常需要對數(shù)據(jù)按照某行某列排序,或者按照多行多列排序,以及按照索引值排序等等,下面這篇文章主要給大家介紹了關(guān)于Python中Dataframe數(shù)據(jù)排序方法的相關(guān)資料,需要的朋友可以參考下2023-02-02