欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于Python?OpenCV和?dlib實(shí)現(xiàn)眨眼檢測(cè)

 更新時(shí)間:2021年12月09日 14:48:54   作者:AI浩  
這篇文章主要介紹了基于Python?OPenCV及dlib實(shí)現(xiàn)檢測(cè)視頻流中的眨眼次數(shù)。文中的代碼對(duì)我們的學(xué)習(xí)和工作有一定價(jià)值,感興趣的同學(xué)可以參考一下

今天,我們使用面部標(biāo)記和 OpenCV 檢測(cè)視頻流中的眨眼次數(shù)。

為了構(gòu)建我們的眨眼檢測(cè)器,我們將計(jì)算一個(gè)稱為眼睛縱橫比 (EAR) 的指標(biāo),該指標(biāo)由 Soukupová 和 ?ech 在他們 2016 年的論文《使用面部標(biāo)記的實(shí)時(shí)眨眼檢測(cè)》中介紹。

與計(jì)算眨眼的傳統(tǒng)圖像處理方法不同,傳統(tǒng)的圖像處理方法通常涉及以下某些組合:

  • 眼睛定位。
  • 閾值以找到眼白。
  • 確定眼睛的“白色”區(qū)域是否在一段時(shí)間內(nèi)消失(表示眨眼)。
  • 眼睛縱橫比是一個(gè)更優(yōu)雅的解決方案,它涉及基于眼睛面部標(biāo)志之間距離比的非常簡(jiǎn)單的計(jì)算。

這種眨眼檢測(cè)方法要求快速、高效且易于實(shí)現(xiàn)。

今天我們通過(guò)四部分來(lái)實(shí)現(xiàn)眨眼檢測(cè):

第一部分,我們將討論眼睛縱橫比以及如何使用它來(lái)確定一個(gè)人在給定的視頻幀中是否在眨眼。

然后,我們將編寫(xiě) Python、OpenCV 和 dlib 代碼來(lái) (1) 執(zhí)行面部標(biāo)志檢測(cè)和 (2) 檢測(cè)視頻流中的眨眼。

基于此實(shí)現(xiàn),我們將應(yīng)用我們的方法來(lái)檢測(cè)示例網(wǎng)絡(luò)攝像頭流和視頻文件中的眨眼。

最后,我將通過(guò)討論改進(jìn)眨眼檢測(cè)器的方法來(lái)結(jié)束今天的博客文章。

了解“眼睛縱橫比”(EAR)

在眨眼檢測(cè)方面,我們只對(duì)兩組面部結(jié)構(gòu)感興趣——眼睛。每只眼睛由 6 個(gè) (x, y) 坐標(biāo)表示,從眼睛的左角開(kāi)始(就像您在看人一樣),然后圍繞該區(qū)域的其余部分順時(shí)針旋轉(zhuǎn):

基于這張圖片,我們應(yīng)該了解關(guān)鍵點(diǎn):

這些坐標(biāo)的寬度和高度之間存在關(guān)系。根據(jù) Soukupová 和 ?ech 在 2016 年發(fā)表的論文《使用面部標(biāo)志進(jìn)行實(shí)時(shí)眨眼檢測(cè)》中的工作,我們可以推導(dǎo)出反映這種關(guān)系的方程,稱為眼睛縱橫比 (EAR):

其中 p1, …, p6 是 2D 面部標(biāo)志位置。

該方程的分子計(jì)算垂直眼睛界標(biāo)之間的距離,而分母計(jì)算水平眼睛界標(biāo)之間的距離,由于只有一組水平點(diǎn)但有兩組垂直點(diǎn),因此對(duì)分母進(jìn)行適當(dāng)加權(quán)。

為什么這個(gè)方程如此有趣?

好吧,正如我們將發(fā)現(xiàn)的那樣,眼睛睜開(kāi)時(shí)眼睛的縱橫比大致恒定,但在眨眼時(shí)會(huì)迅速降至零。

使用這個(gè)簡(jiǎn)單的方程,我們可以避免使用圖像處理技術(shù),而只需依靠眼睛界標(biāo)距離的比率來(lái)確定一個(gè)人是否在眨眼。

為了更清楚地說(shuō)明這一點(diǎn),請(qǐng)考慮 Soukupová 和 ?ech 的下圖:

在左上角,我們有一個(gè)完全睜開(kāi)的眼睛——這里的眼睛縱橫比會(huì)很大(r)并且隨著時(shí)間的推移相對(duì)恒定。

然而,一旦人眨眼(右上),眼睛的縱橫比就會(huì)急劇下降,接近于零。

下圖繪制了視頻剪輯的眼睛縱橫比隨時(shí)間變化的圖表。 正如我們所看到的,眼睛縱橫比是恒定的,然后迅速下降到接近零,然后再次增加,表明發(fā)生了一次眨眼。

在下一節(jié)中,我們將學(xué)習(xí)如何使用面部標(biāo)志、OpenCV、Python 和 dlib 實(shí)現(xiàn)眨眼檢測(cè)的眼睛縱橫比。

使用面部標(biāo)志和 OpenCV 檢測(cè)眨眼

首先,打開(kāi)一個(gè)新文件并將其命名為 detect_blinks.py 。 從那里,插入以下代碼:

# import the necessary packages
from scipy.spatial import distance as dist
from imutils.video import FileVideoStream
from imutils.video import VideoStream
from imutils import face_utils
import numpy as np
import argparse
import imutils
import time
import dlib
import cv2

導(dǎo)入必要的庫(kù)。

如果您的系統(tǒng)上沒(méi)有安裝 imutils(或者如果您使用的是舊版本),請(qǐng)確保使用以下命令安裝/升級(jí):

pip install --upgrade imutils 

如果沒(méi)有安裝dlib,請(qǐng)參考文章

?接下來(lái),我們將定義我們的 eye_aspect_ratio 函數(shù):

def eye_aspect_ratio(eye):
	# compute the euclidean distances between the two sets of
	# vertical eye landmarks (x, y)-coordinates
	A = dist.euclidean(eye[1], eye[5])
	B = dist.euclidean(eye[2], eye[4])
	# compute the euclidean distance between the horizontal
	# eye landmark (x, y)-coordinates
	C = dist.euclidean(eye[0], eye[3])
	# compute the eye aspect ratio
	ear = (A + B) / (2.0 * C)
	# return the eye aspect ratio
	return ear

此函數(shù)接受單個(gè)必需參數(shù),即給定眼睛的面部標(biāo)志的 (x, y) 坐標(biāo)。

計(jì)算兩組垂直眼睛界標(biāo)之間的距離,然后計(jì)算水平眼睛界標(biāo)之間的距離。

最后,結(jié)合了分子和分母以得出最終的眼睛縱橫比。

然后將眼睛縱橫比返回給調(diào)用函數(shù)。

讓我們繼續(xù)解析我們的命令行參數(shù):

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--shape-predictor", required=True,
	help="path to facial landmark predictor")
ap.add_argument("-v", "--video", type=str, default="",
	help="path to input video file")
args = vars(ap.parse_args())

我們的detect_blinks.py 腳本需要一個(gè)命令行參數(shù),然后是第二個(gè)可選參數(shù):

  1. –shape-predictor :這是 dlib 的預(yù)訓(xùn)練面部標(biāo)志檢測(cè)器的路徑。 您可以使用本博文底部的“下載”部分將檢測(cè)器以及源代碼 + 示例視頻下載到本教程中。
  2. –video :此可選開(kāi)關(guān)控制駐留在磁盤(pán)上的輸入視頻文件的路徑。 如果您想使用實(shí)時(shí)視頻流,只需在執(zhí)行腳本時(shí)省略此開(kāi)關(guān)即可。

我們現(xiàn)在需要設(shè)置兩個(gè)重要的常量,您可能需要為自己的實(shí)現(xiàn)進(jìn)行調(diào)整,同時(shí)初始化另外兩個(gè)重要的變量,所以一定要注意這個(gè)解釋:

# 定義兩個(gè)常量,一個(gè)為眼睛縱橫比來(lái)表示
# 閃爍然后第二個(gè)常量為連續(xù)的次數(shù)
# 幀眼睛必須低于閾值
EYE_AR_THRESH = 0.3
EYE_AR_CONSEC_FRAMES = 3
# 初始化幀計(jì)數(shù)器和閃爍總數(shù)
COUNTER = 0
TOTAL = 0

在確定視頻流中是否發(fā)生眨眼時(shí),我們需要計(jì)算眼睛縱橫比。

如果眼睛縱橫比低于某個(gè)閾值,然后又高于閾值,那么我們將注冊(cè)一個(gè)“眨眼”——EYE_AR_THRESH 就是這個(gè)閾值。我們默認(rèn)它的值為 0.3,因?yàn)檫@對(duì)我的應(yīng)用程序最有效,但您可能需要為自己的應(yīng)用程序調(diào)整它。

然后我們有一個(gè)重要的常量,EYE_AR_CONSEC_FRAME——這個(gè)值被設(shè)置為 3 以指示眼睛縱橫比小于 EYE_AR_THRESH 的三個(gè)連續(xù)幀必須發(fā)生,以便注冊(cè)眨眼。

同樣,根據(jù)管道的幀處理吞吐率,您可能需要為自己的實(shí)現(xiàn)提高或降低此數(shù)字。

第 44 和 45 行初始化兩個(gè)計(jì)數(shù)器。 COUNTER 是眼睛縱橫比小于 EYE_AR_THRESH 的連續(xù)幀的總數(shù),而 TOTAL 是腳本運(yùn)行時(shí)發(fā)生的眨眼總數(shù)。

現(xiàn)在我們的導(dǎo)入、命令行參數(shù)和常量都已經(jīng)處理好了,我們可以初始化 dlib 的人臉檢測(cè)器和面部標(biāo)記檢測(cè)器:

# 初始化dlib的人臉檢測(cè)器(基于HOG)然后創(chuàng)建
# 面部標(biāo)志預(yù)測(cè)器
print("[INFO] loading facial landmark predictor...")
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(args["shape_predictor"])

初始化實(shí)際的面部標(biāo)志預(yù)測(cè)器。

dlib 生成的面部標(biāo)志遵循可索引的列表,如下:

因此,我們可以確定開(kāi)始和結(jié)束數(shù)組切片索引值,以便為下面的左眼和右眼提取 (x, y) 坐標(biāo):

# 獲取左側(cè)和面部標(biāo)志的索引
# 右眼,分別 
(lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
(rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]

使用這些索引,我們將能夠毫不費(fèi)力地提取眼睛區(qū)域。

接下來(lái),我們需要決定是使用基于文件的視頻流還是實(shí)時(shí) USB/網(wǎng)絡(luò)攝像頭/Raspberry Pi 相機(jī)視頻流:

# start the video stream thread
print("[INFO] starting video stream thread...")
vs = FileVideoStream(args["video"]).start()
fileStream = True
# vs = VideoStream(src=0).start()
# vs = VideoStream(usePiCamera=True).start()
# fileStream = False
time.sleep(1.0)
fps = 30    #保存視頻的FPS,可以適當(dāng)調(diào)整
size=(450,800)
videoWriter = cv2.VideoWriter('3.mp4',-1,fps,size)#最后一個(gè)是保存圖片的尺寸

如果您使用的是文件視頻流,則保留代碼原樣。

如果您想使用內(nèi)置網(wǎng)絡(luò)攝像頭或 USB 攝像頭,請(qǐng)取消注釋# vs = VideoStream(src=0).start()。

對(duì)于 Raspberry Pi 攝像頭模塊,取消注釋# vs = VideoStream(usePiCamera=True).start()。

定義幀數(shù)。

定義大小

定義視頻寫(xiě)入對(duì)象

最后,我們到達(dá)了腳本的主循環(huán):

# loop over frames from the video stream
while True:
	# 如果這是一個(gè)文件視頻流,那么我們需要檢查是否
	# 緩沖區(qū)中還有更多幀要處理
	if fileStream and not vs.more():
		break
	frame = vs.read()
	if frame is None:
        break
	frame = imutils.resize(frame, width=450)
	gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
	# 在灰度幀中檢測(cè)人臉
	rects = detector(gray, 0)

遍歷視頻流中的幀。

如果我們正在訪問(wèn)一個(gè)視頻文件流并且視頻中沒(méi)有更多的幀,我們就會(huì)中斷循環(huán)。

從視頻流中讀取下一幀,然后調(diào)整其大小并將其轉(zhuǎn)換為灰度。

然后我們通過(guò) dlib 的內(nèi)置人臉檢測(cè)器檢測(cè)灰度幀中的人臉。

我們現(xiàn)在需要遍歷幀中的每個(gè)人臉,然后對(duì)每個(gè)人應(yīng)用面部標(biāo)志檢測(cè):

	# loop over the face detections
	for rect in rects:
		# 確定面部區(qū)域的面部標(biāo)志,然后
		# 將面部標(biāo)志 (x, y) 坐標(biāo)轉(zhuǎn)換為 NumPy數(shù)組
		shape = predictor(gray, rect)
		shape = face_utils.shape_to_np(shape)
		# 提取左右眼坐標(biāo),然后使用
		# 坐標(biāo)來(lái)計(jì)算雙眼的眼睛縱橫比
		leftEye = shape[lStart:lEnd]
		rightEye = shape[rStart:rEnd]
		leftEAR = eye_aspect_ratio(leftEye)
		rightEAR = eye_aspect_ratio(rightEye)
		# 平均兩只眼睛的眼睛縱橫比
		ear = (leftEAR + rightEAR) / 2.0

確定面部區(qū)域的面部標(biāo)志,將這些 (x, y) 坐標(biāo)轉(zhuǎn)換為 NumPy 數(shù)組。

使用本腳本前面的數(shù)組切片技術(shù),我們可以分別提取左眼和右眼的 (x, y) 坐標(biāo)。

然后,在第 96 和 97 行計(jì)算每只眼睛的眼睛縱橫比。

按照 Soukupová 和 ?ech 的建議,我們將兩只眼睛的縱橫比平均在一起以獲得更好的眨眼估計(jì)(當(dāng)然,假設(shè)一個(gè)人同時(shí)眨眼)。

我們的下一個(gè)代碼塊只是處理眼睛區(qū)域本身的面部標(biāo)志的可視化:

		# 計(jì)算左眼和右眼的凸包,然后
		# 可視化每只眼睛
		leftEyeHull = cv2.convexHull(leftEye)
		rightEyeHull = cv2.convexHull(rightEye)
		cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1)
		cv2.drawContours(frame, [rightEyeHull], -1, (0, 255, 0), 1)

在這一點(diǎn)上,我們已經(jīng)計(jì)算了我們的(平均)眼睛縱橫比,但我們實(shí)際上還沒(méi)有確定是否發(fā)生了眨眼——這將在下一節(jié)中解決:

		# 檢查眼睛的縱橫比是否低于眨眼
		# 閾值,如果是,則增加閃爍幀計(jì)數(shù)器
		if ear < EYE_AR_THRESH:
			COUNTER += 1
		# 否則,眼睛縱橫比不低于眨眼
		# 臨界點(diǎn)
		else:
			# 如果眼睛閉上足夠多的次數(shù)
			# 然后增加閃爍的總數(shù)
			if COUNTER >= EYE_AR_CONSEC_FRAMES:
				TOTAL += 1
			# 重置眼框計(jì)數(shù)器
			COUNTER = 0

檢查眼睛縱橫比是否低于我們的眨眼閾值——如果是增加指示正在發(fā)生眨眼的連續(xù)幀的數(shù)量。

否則,處理眼睛縱橫比不低于眨眼閾值的情況。

在這種情況下,再次檢查以查看是否有足夠數(shù)量的連續(xù)幀包含低于我們預(yù)定義閾值的眨眼率。

如果檢查通過(guò),我們?cè)黾娱W爍的總次數(shù)。

然后我們重置連續(xù)閃爍的次數(shù) COUNTER。

我們的最終代碼塊只是處理在我們的輸出幀上繪制眨眼次數(shù),以及顯示當(dāng)前眼睛縱橫比:

		# 繪制幀上閃爍的總數(shù)以及
		# 計(jì)算出的幀的眼睛縱橫比
		cv2.putText(frame, "Blinks: {}".format(TOTAL), (10, 30),
			cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
		cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30),
			cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
 
	# show the frame
	cv2.imshow("Frame", frame)
	videoWriter.write(frame)
	key = cv2.waitKey(1) & 0xFF
 
	# if the `q` key was pressed, break from the loop
	if key == ord("q"):
		break
videoWriter.release()
# do a bit of cleanup
cv2.destroyAllWindows()
vs.stop()

眨眼檢測(cè)結(jié)果

要將我們的眨眼檢測(cè)器應(yīng)用于示例視頻,只需執(zhí)行以下命令:

python detect_blinks.py --shape-predictor shape_predictor_68_face_landmarks.dat --video 11.mp4

測(cè)試結(jié)果:

測(cè)試視頻鏈接:

眨眼檢測(cè)

如果測(cè)試攝像頭則,如下操作:

#vs = FileVideoStream(args["video"]).start()
#fileStream = True
vs = VideoStream(src=0).start()
# vs = VideoStream(usePiCamera=True).start()
fileStream = False

注釋FileVideoStream,取消注釋VideoStream。

執(zhí)行命令:

python detect_blinks.py --shape-predictor shape_predictor_68_face_landmarks.dat

總結(jié)

在這篇博文中,我演示了如何使用 OpenCV、Python 和 dlib 構(gòu)建眨眼檢測(cè)器。

構(gòu)建眨眼檢測(cè)器的第一步是執(zhí)行面部標(biāo)志檢測(cè),以定位視頻流中給定幀中的眼睛。

一旦我們有了雙眼的面部標(biāo)志,我們就計(jì)算每只眼睛的眼睛縱橫比,這給了我們一個(gè)奇異值,將垂直眼睛標(biāo)志點(diǎn)之間的距離與水平標(biāo)志點(diǎn)之間的距離聯(lián)系起來(lái)。

一旦我們有了眼睛縱橫比,我們就可以確定一個(gè)人是否在眨眼——眼睛縱橫比在睜眼時(shí)將保持大致恒定,然后在眨眼時(shí)迅速接近零,然后隨著眼睛睜開(kāi)再次增加.

為了改進(jìn)我們的眨眼檢測(cè)器,Soukupová 和 ?ech 建議構(gòu)建一個(gè) 13 維的眼睛縱橫比特征向量(第 N 幀、N – 6 幀和 N + 6 幀),然后將該特征向量輸入線性 SVM分類。

通過(guò)這篇博文你還學(xué)會(huì)了如何保存視頻。

眨眼檢測(cè)的一個(gè)應(yīng)用場(chǎng)景是睡意檢測(cè)。

完整的代碼,提取碼:k653

以上就是基于Python OpenCV和 dlib實(shí)現(xiàn)眨眼檢測(cè)的詳細(xì)內(nèi)容,更多關(guān)于Python OpenCV dlib眨眼檢測(cè)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • python實(shí)現(xiàn)簡(jiǎn)單的貪吃蛇游戲

    python實(shí)現(xiàn)簡(jiǎn)單的貪吃蛇游戲

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)簡(jiǎn)單的貪吃蛇游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • Python pandas 列轉(zhuǎn)行操作詳解(類似hive中explode方法)

    Python pandas 列轉(zhuǎn)行操作詳解(類似hive中explode方法)

    這篇文章主要介紹了Python pandas 列轉(zhuǎn)行操作詳解(類似hive中explode方法),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-05-05
  • 利用Python對(duì)中國(guó)500強(qiáng)排行榜數(shù)據(jù)進(jìn)行可視化分析

    利用Python對(duì)中國(guó)500強(qiáng)排行榜數(shù)據(jù)進(jìn)行可視化分析

    這篇文章主要介紹了利用Python對(duì)中國(guó)500強(qiáng)排行榜數(shù)據(jù)進(jìn)行可視化分析,從不同角度去對(duì)數(shù)據(jù)進(jìn)行統(tǒng)計(jì)分析,可視化展示,下文詳細(xì)內(nèi)容介紹需要的小伙伴可以參考一下
    2022-05-05
  • Python實(shí)現(xiàn)隨機(jī)密碼生成器實(shí)例

    Python實(shí)現(xiàn)隨機(jī)密碼生成器實(shí)例

    這篇文章主要介紹了Python實(shí)現(xiàn)隨機(jī)密碼生成器實(shí)例,string.printable是string中的可打印字符,用strip函數(shù)首尾去掉空格,random模塊用來(lái)取字符,random.choice隨機(jī)取字符,將隨機(jī)取出的字符與password空字符串進(jìn)行拼接,最后用print輸出,需要的朋友可以參考下
    2023-09-09
  • python numpy中setdiff1d的用法說(shuō)明

    python numpy中setdiff1d的用法說(shuō)明

    這篇文章主要介紹了python numpy中setdiff1d的用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • Python實(shí)現(xiàn)簡(jiǎn)單的圖書(shū)管理系統(tǒng)

    Python實(shí)現(xiàn)簡(jiǎn)單的圖書(shū)管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Python實(shí)現(xiàn)簡(jiǎn)單的圖書(shū)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 使用python讀取.text文件特定行的數(shù)據(jù)方法

    使用python讀取.text文件特定行的數(shù)據(jù)方法

    今天小編就為大家分享一篇使用python讀取.text文件特定行的數(shù)據(jù)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • 讀取本地json文件,解析json(實(shí)例講解)

    讀取本地json文件,解析json(實(shí)例講解)

    下面小編就為大家分享一篇讀取本地json文件,解析json的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • Python中unittest的斷言方法詳解

    Python中unittest的斷言方法詳解

    大家好,本篇文章主要講的是Python中unittest的斷言方法詳解,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-01-01
  • Pandas.DataFrame重置列的行名實(shí)現(xiàn)(set_index)

    Pandas.DataFrame重置列的行名實(shí)現(xiàn)(set_index)

    本文主要介紹了Pandas.DataFrame重置列的行名實(shí)現(xiàn)(set_index),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02

最新評(píng)論