OpenCV 人臉識別

Ammar Ali 2024年2月15日
  1. 在 OpenCV 中使用 face_recognition 庫識別影象中的人臉
  2. 在 OpenCV 中使用 putText() 函式將文字放的影象頂部
OpenCV 人臉識別

本教程將討論使用 OpenCV 中的 face_recognition 庫識別影象中存在的人臉。

在 OpenCV 中使用 face_recognition 庫識別影象中的人臉

人臉識別用於識別影象或視訊中存在的人臉。例如,Facebook 使用面部識別來標記帖子中的人。

如果我們在圖片中標記我們的朋友,Facebook 演算法將識別該人的姓名,並在我們下次上傳該人的照片時自動標記他。我們還可以使用 face_recognition 庫構建類似的演算法。

人臉識別庫分多個步驟工作以識別人臉。第一步,我們需要傳遞已知人的圖片來訓練模型,庫將使用 HOG 或定向梯度直方圖來查詢給定影象中存在的人臉。

在人臉識別中,我們只需要一張人臉的圖片,不需要任何其他資料,因為資料量大,會使演算法變得更慢、更復雜。

HOG 演算法將每個畫素與其相鄰畫素進行比較,以找到強度方向,並在強度級別增加的方向上用梯度標記它。

該演算法已經有一張平均人臉的梯度影象。該演算法將梯度影象與人臉的已知梯度進行比較,以確定影象的哪個部分包含人臉。

例如,讓我們使用人臉識別庫的 face_locations() 函式查詢影象中存在的人臉。請參閱下面的程式碼。

import cv2
import dlib
import face_recognition

img = cv2.imread("tom1.jpg")
known_img = face_recognition.load_image_file("tom1.jpg")

loc = face_recognition.face_locations(known_img)
cv2.rectangle(img, (loc[0][0], loc[0][3]), (loc[0][1], loc[0][2]), (255, 0, 0), 3)
print(loc)

cv2.imshow("locations", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出:

影象中的人臉檢測

正如我們在上面的輸出中看到的,在上面的影象中使用 HOG 演算法檢測到人臉。我們使用兩個函式匯入了相同的影象,因為 imread() 函式讀取 BGR 色標中的影象,而 load_image_file() 函式讀取 RGB 顏色空間中的影象。

人臉識別庫使用 RGB 影象,而 OpenCV 使用 BGR 影象,我們在上面的程式碼中都需要。我們使用 OpenCV 的 rectangle() 函式在檢測到的面部周圍繪製一個矩形。

face_locations() 函式返回矩形的點或角位置,我們可以在 rectangle() 函式中使用它們來繪製矩形。face_locations() 函式還有兩個可選引數,number_of_times_to_upsamplebatch_size

計算機將影象儲存為數字陣列,因此如果人臉影象被旋轉或影象中的光照發生變化,即使是同一張臉,計算機也會將其視為另一張影象。該庫在第二步中使用人臉界標估計解決了這個問題。

在人臉界標估計中,我們使用機器學習演算法來獲得 68 個對人臉識別很重要的面部界標,例如眼睛和鼻子周圍的界標。

使用這些地標,我們可以旋轉和共享我們的影象,以建立一個完美居中的影象,眼睛和鼻子位於影象的中心。

我們不必擔心面部的方向或角度。第三步,我們必須訓練一個模型來進行預測。

我們不能簡單地將未知影象與所有已知影象進行比較來識別人,因為這需要時間。

我們可以使用每張影象的一些特徵,例如耳朵、眼睛和鼻子大小之間的距離,並將它們與未知的人臉影象進行比較,而不是使用整個人臉影象。

但是,我們不知道哪些特徵最適合識別人臉。因此,我們將使用深度卷積神經網路從每個已知影象中找到 128 個測量值或面部特徵。

為了訓練模型,我們必須提供兩張已知人的影象和一張未知人的影象,神經網路將通過比較給定的影象來找到 128 個測量值。訓練一個模型也需要很多時間,因此人臉庫使用 OpenFace 的預訓練模型來獲取所有已知人臉的 128 個測量值。

在最後一步,我們必須使用分類器來檢查未知人臉是否與任何已知人臉相似。人臉識別庫使用 SVM 或空間向量機分類器進行預測。

例如,讓我們使用 Tom Cruise 的一張影象進行訓練,另一張影象用於測試。請參閱下面的程式碼。

import cv2
import dlib
import face_recognition

known_img = face_recognition.load_image_file("tom1.jpg")
unknown_img = face_recognition.load_image_file("tom2.jpg")

known_en = face_recognition.face_encodings(known_img)[0]
unknown_en = face_recognition.face_encodings(unknown_img)[0]

result = face_recognition.compare_faces([known_en], unknown_en)
print(result)

cv2.imshow("Known Image", known_img)
cv2.imshow("Un_Known Image", unknown_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出:

[True]

輸出結果為,這意味著未知影象是湯姆克魯斯。我們在上面的程式碼中使用了人臉識別庫的 face_encodings() 函式來查詢 128 個測量值。

face_encodings() 函式的第一個引數是輸入影象。第二個引數 known_face_locations 是可選的,它用於設定每個人臉的邊界框,預設情況下,它的值設定為 none

第三個引數 num_jitters 也是可選的,它用於設定用於查詢編碼的重取樣值,預設設定為 1。第四個引數 model 也是可選的,用於設定用於查詢編碼的模型型別,預設設定為 small

小模型速度快但精度較低,大模型速度慢但精度更高。我們使用 compare_faces() 將未知面孔與已知面孔進行比較。

compare_faces() 函式的第一個引數包含已知人臉的編碼,第二個引數包含未知人臉的編碼。第三個引數 tolerance 是可選的,用於設定面之間的距離,預設情況下,其值設定為 0.6

在 OpenCV 中使用 putText() 函式將文字放的影象頂部

我們還可以使用 OpenCV 的 putText() 函式在影象上放置與已知人臉相似的文字。例如,讓我們使用 Tom Cruise 影象來訓練模型,然後使用 Dwayne Johnson 的影象來測試模型。

請參閱下面的程式碼。

import cv2
import dlib
import face_recognition

img = cv2.imread("rock1.jpg")
known_img = face_recognition.load_image_file("tom2.jpg")
unknown_img = face_recognition.load_image_file("rock1.jpg")

known_en = face_recognition.face_encodings(known_img)[0]
unknown_en = face_recognition.face_encodings(unknown_img)[0]

result = face_recognition.compare_faces([known_en], unknown_en)

loc = face_recognition.face_locations(unknown_img)
cv2.rectangle(img, (loc[0][0], loc[0][3]), (loc[0][1], loc[0][2]), (255, 0, 0), 3)

if result[0]:
    text = "Tom Cruise"
else:
    text = "Unknown"
cv2.putText(
    img,
    text,
    (loc[0][0], loc[0][3] - 20),
    cv2.FONT_HERSHEY_SIMPLEX,
    1.2,
    (0, 0, 255),
    2,
    cv2.LINE_AA,
)

cv2.imshow("locations", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出:

人臉檢測和文字

上面這張臉不像湯姆克魯斯的臉。我們還可以使用不同人的多張影象來訓練模型,我們還可以在視訊中找到人臉。

對於視訊,我們必須單獨處理每一幀。檢視此連結瞭解有關人臉識別庫的更多詳細資訊。

作者: Ammar Ali
Ammar Ali avatar Ammar Ali avatar

Hello! I am Ammar Ali, a programmer here to learn from experience, people, and docs, and create interesting and useful programming content. I mostly create content about Python, Matlab, and Microcontrollers like Arduino and PIC.

LinkedIn Facebook

相關文章 - OpenCV Image