使用 dlib、OpenCV 和 Python 檢測面部标記
今天,我們将使用dlib和OpenCV來檢測圖像中的面部标記。dlib的安裝教程:
https://wanghao.blog.csdn.net/article/details/121470556人臉檢測器模型:
https://download.csdn.net/download/hhhhhhhhhhwwwwwwwwww/50939290人臉标記已成功應用于人臉對齊、頭部姿勢估計、人臉交換、眨眼檢測等領域。
在今天的部落格文章中,我們将重點介紹面部标記的基礎知識,包括:
1、确切的面部标記是什麼以及它們是如何工作的。
2、如何使用dlib、OpenCV和Python從圖像中檢測和提取面部标記。
這篇博文的主要分三個部分:
1、将讨論面部标記以及它們為什麼被用于計算機視覺應用。
2、示範如何使用dlib、OpenCV和Python檢測和提取面部标記。
3、我們将看一些将面部标記檢測應用于圖像的結果。
什麼是面部标記?
人臉标記點檢測是形狀預測問題的一個子集。給定一個輸入圖像(通常是一個指定感興趣對象的ROI),形狀預測器嘗試沿形狀定位感興趣的關鍵點。
在人臉标記的背景下,我們的目标是使用形狀預測方法檢測人臉上的重要人臉結構。
是以,檢測面部标記是一個兩步過程:
步驟1:在圖像中定位人臉。
步驟2:檢測人臉ROI上的關鍵面部結構。
人臉檢測(步驟1)可以通過多種方式實作。
我們可以使用OpenCV内置的Haar級聯。
我們可以将預先訓練好的HOG+線性SVM對象檢測器專門用于人臉檢測任務。
或者我們甚至可以使用基于深度學習的算法進行人臉定位。
無論哪種情況,用于檢測圖像中人臉的實際算法都無關緊要。相反,重要的是,通過某種方法,我們獲得了面邊界框(即,圖像中面的(x,y)-坐标)。
給定面部區域,我們可以應用步驟2:檢測面部區域中的關鍵面部結構。
有多種面部标記檢測器,但所有方法基本上都試圖定位和标記以下面部區域:
- 嘴
- 右眉
- 左眉
- 右眼
- 左眼
- 鼻
- 颌
dlib庫中包含的面部标記檢測器是Kazemi和Sullivan(2014)提出的一系列回歸樹的一毫秒面部校準的實作。
此方法首先使用:
- 圖像上标記的面部标記的訓練集。這些圖像被手動标記,指定每個面部結構周圍區域的特定(x,y)坐标。
- 先驗,更具體地說,是輸入像素對之間距離的機率。
給定該訓練資料,訓練回歸樹集合,以直接從像素強度本身估計面部标記位置(即,不進行“特征提取”)。
最終的結果是一個面部标記檢測器,可用于實時檢測具有高品質預測的面部标記。
dlib的面部标記檢測器
dlib庫中預先訓練的面部标記檢測器用于估計映射到面部結構的68(x,y)坐标的位置。
68個坐标的索引可在下圖中顯示:
這些注釋是68點iBUG 300-W資料集的一部分,dlib面部标記預測器是在該資料集上訓練的。
值得注意的是,還有其他風格的面部标記檢測器,包括可以在HELEN資料集上訓練的194點模型。
無論使用哪一個資料集,都可以利用相同的dlib架構在輸入訓練資料上訓練形狀預測器-如果您想訓練面部标記檢測器或自定義形狀預測器,這非常有用。
在這篇博文的剩餘部分,我将示範如何在圖像中檢測這些面部标記。
使用dlib、OpenCV和Python檢測面部标記
這篇博文使用到了imutils庫face_utils.py中的兩個函數。
第一個實用函數是rect_to_bb,是“矩形到邊框”的縮寫:
def rect_to_bb(rect):
#擷取dlib預測的邊界并将其轉換
#按照我們通常使用的格式(x,y,w,h)
#使用OpenCV
x = rect.left()
y = rect.top()
w = rect.right() - x
h = rect.bottom() - y
# 傳回一個元組 (x, y, w, h)
return (x, y, w, h)
此函數接受一個參數rect,該參數假定為dlib檢測器(即面部檢測器)生成的邊框矩形。
rect對象包括檢測的(x,y)-坐标。
然而,在OpenCV中,我們通常認為邊界框是“(x,y,width,height)”,是以為了友善起見,rect_to_bb函數将這個rect對象轉換為4元組坐标。
第二,shape_to_np函數:
def shape_to_np(shape, dtype="int"):
#初始化(x,y)-坐标清單
coords = np.zeros((68, 2), dtype=dtype)
#在68個面部标記上循環并轉換它們
#到(x,y)-坐标的2元組
for i in range(0, 68):
coords[i] = (shape.part(i).x, shape.part(i).y)
#傳回(x,y)坐标的清單
return coords
dlib面部标記檢測器将傳回一個包含面部标記區域68(x,y)坐标的形狀對象。
使用shape_to_np函數,我們可以将這個對象轉換成一個NumPy數組。
有了這兩個輔助函數,我們現在就可以檢測圖像中的面部标記了。
圖像
打開一個新檔案,将其命名為facial_landmarks.py,然後插入以下代碼:
# import the necessary packages
from imutils import face_utils
import numpy as np
import argparse
import imutils
import dlib
import cv2
#構造參數解析器并解析參數
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--shape-predictor", required=True,
help="path to facial landmark predictor")
ap.add_argument("-i", "--image", required=True,
help="path to input image")
args = vars(ap.parse_args())
導入所需的Python包。
将使用imutils的face_utils子子產品通路上面詳述的助手函數。
然後将導入dlib。
解析我們的指令行參數:
--shape-predictor:這是通往dlib預先訓練的面部标記檢測器的路徑。你可以在這裡下載下傳檢測器模型,也可以使用本文的“下載下傳”部分來擷取代碼+示例圖像+預先訓練過的檢測器。
--image:我們要檢測面部标記的輸入圖像的路徑。
既然我們的導入和指令行參數已經處理完畢,讓我們初始化dlib的面部檢測器和面部标記預測器:
# 初始化dlib的人臉檢測器(基于HOG)然後建立
# 面部标記預測器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(args["shape_predictor"])
初始化dlib的預訓練人臉檢測器,該檢測器基于對用于對象檢測的定向梯度标準直方圖+線性SVM方法的修改。
然後使用提供的shape_predictor的路徑加載面部标記預測器。
但是,在我們能夠實際檢測面部标記點之前,我們首先需要檢測輸入圖像中的面部:
# 加載輸入圖像,調整大小,并将其轉換為灰階
image = cv2.imread(args["image"])
image = imutils.resize(image, width=500)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 在灰階圖像中檢測人臉
rects = detector(gray, 1)
通過OpenCV從磁盤加載我們的輸入圖像,然後通過調整圖像大小使其具有500像素的寬度并将其轉換為灰階來預處理圖像。
處理檢測圖像中面的邊界框。
探測器的第一個參數是我們的灰階圖像(盡管這種方法也可以用于彩色圖像)。
第二個參數是在應用檢測器之前放大圖像時要應用的圖像金字塔層的數量(這相當于在圖像上計算cv2.N次)。
在人臉檢測之前提高輸入圖像分辨率的好處是,它可能允許我們檢測圖像中的更多人臉-缺點是輸入圖像越大,檢測過程的計算成本就越高。
給定圖像中人臉的(x,y)-坐标,我們現在可以對每個人臉區域應用人臉标記檢測:
# 循環面部檢測
for (i, rect) in enumerate(rects):
# 确定面部區域的面部标志,然後
# 将面部标志 (x, y) 坐标轉換為 NumPy數組
shape = predictor(gray, rect)
shape = face_utils.shape_to_np(shape)
# 将 dlib 的矩形轉換為 OpenCV 樣式的邊界框
# [即(x, y, w, h)],然後繪制人臉邊界框
(x, y, w, h) = face_utils.rect_to_bb(rect)
cv2.rectangle(image, (x, y), (x + w, y + h), (255, 255, 0), 2)
# 顯示人臉編号
cv2.putText(image, "Face #{}".format(i + 1), (x - 10, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2)
# 循環面部标志的 (x, y) 坐标
# 并将它們繪制在圖像上
for (x, y) in shape:
cv2.circle(image, (x, y), 1, (0, 255, 0), -1)
# 顯示帶有人臉檢測 + 人臉标記的輸出圖像
cv2.imshow("Output", image)
cv2.waitKey(0)
循環每個人臉檢測。
對于每個人臉檢測,給出68(x,y)-坐标,該坐标映射到圖像中的特定人臉特征。
然後将dlib形狀對象轉換為具有形狀(68,2)的NumPy數組。
繪制圖像上檢測到的人臉周圍的邊界框,繪制人臉的索引。
最後,在檢測到的面部标記上循環并分别繪制它們。
将輸出圖像顯示到螢幕上。
測試結果
打開終端輸入:
python facial_landmarks.py --shape-predictor shape_predictor_68_face_landmarks.dat --image 11.jpg
視訊或攝像頭
讓我們繼續開始這個面部标記的例子。這次調用攝像頭
打開一個新檔案,将其命名為 video_facial_landmarks.py ,并插入以下代碼:
# import the necessary packages
from imutils.video import VideoStream
from imutils import face_utils
import datetime
import argparse
import imutils
import time
import dlib
import cv2
導入需要的包。
然後,讓我們解析指令行參數:
# 構造參數 parse 并解析參數
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--shape-predictor", required=True,
help="path to facial landmark predictor")
ap.add_argument("-r", "--picamera", type=int, default=-1,
help="whether or not the Raspberry Pi camera should be used")
args = vars(ap.parse_args())
腳本需要一個指令行參數,然後是第二個可選參數,每個參數的詳細資訊如下:
--shape-predictor :dlib 的預訓練面部标志檢測器的路徑。
--picamera :可選的指令行參數,此開關訓示是否應使用 Raspberry Pi 攝像頭子產品而不是預設的網絡攝像頭/USB 攝像頭。 提供一個 > 0 的值以使用您的 Raspberry Pi 相機。
現在我們的指令行參數已經解析完畢,我們需要初始化 dlib 的基于 HOG + 線性 SVM 的人臉檢測器,然後加載面部标志預測器:
# 初始化dlib的人臉檢測器(基于HOG)然後建立
# 面部标志預測器
print("[INFO] loading facial landmark predictor...")
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(args["shape_predictor"])
下一個代碼塊簡單地處理初始化我們的 VideoStream 并允許相機傳感器預熱:
# 初始化視訊流并讓相機傳感器預熱
print("[INFO] camera sensor warming up...")
vs = VideoStream(usePiCamera=args["picamera"] > 0).start()
time.sleep(2.0)
我們視訊處理管道的核心可以在下面的 while 循環中找到:
# 循環視訊流中的幀
while True:
# 從線程視訊流中抓取幀,将其調整為
# 最大寬度為 400 像素,并将其轉換為
# 灰階
frame = vs.read()
frame = imutils.resize(frame, width=400)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 在灰階幀中檢測人臉
rects = detector(gray, 0)
# 循環面部檢測
for rect in rects:
# 确定面部區域的面部标志,然後
# 将面部标志 (x, y) 坐标轉換為 NumPy數組
shape = predictor(gray, rect)
shape = face_utils.shape_to_np(shape)
# 循環面部标志的 (x, y) 坐标
# 并将它們繪制在圖像上
for (x, y) in shape:
cv2.circle(frame, (x, y), 1, (0, 0, 255), -1)
# 顯示幀
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
# 如果按下 `q` 鍵,則跳出循環
if key == ord("q"):
break
這裡面的邏輯和圖像的相同,接下來我們測試一下。
python video_facial_landmarks.py --shape-predictor shape_predictor_68_face_landmarks.dat
總結
在今天的部落格文章中,我們了解了什麼是面部标記,以及如何使用dlib、OpenCV和Python檢測它們。
檢測圖像中的面部标記包括兩個步驟:
首先,我們必須在圖像中定位人臉。這可以使用許多不同的技術來實作,但通常涉及Haar級聯或HOG+線性SVM檢測器(但任何在人臉周圍生成邊界框的方法都足夠了)。
應用形狀預測器,特别是面部标記檢測器,以獲得面部ROI中面部區域的(x,y)-坐标。
鑒于這些面部标記,我們可以應用多種計算機視覺技術,包括:
面部部分提取(即鼻子、眼睛、嘴、下颌線等)
面部對齊
頭部姿态估計
面交換
眨眼檢測
…...
希望這篇文章能給你帶來幫助!!!
完整的代碼和檔案詳見:
https://download.csdn.net/download/hhhhhhhhhhwwwwwwwwww/50945619