python opencv 人臉識別
人臉識別個人理解就是分幾個步驟,1 找素材,讓程序學習得到不同人的不同人臉特點,2,傳入圖片開始識別
這里先展示一下文件目錄
test_data是測試人臉的圖片,images里有兩個文件夾,每一個文件夾對應着一個人,里面都是那個人的人臉圖像
使用opencv開發人臉識別,首先下載對應的包
pip install opencv-python
pip install opencv-contrib-python
然后開始上代碼
# # -*- coding:utf-8 -*-
import cv2
import os
import numpy as np
# 檢測人臉
def detect_face(img):
# 將測試圖像轉換為灰度圖像,因為opencv人臉檢測器需要灰度圖像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 加載OpenCV人臉檢測分類器Haar
face_cascade = cv2.CascadeClassifier('./xml/haarcascade_frontalface_default.xml')
# 檢測多尺度圖像,返回值是一張臉部區域信息的列表(x,y,寬,高)
face = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5)
# 如果未檢測到面部,則返回原始圖像
if len(face) > 0:
# 目前假設只有一張臉,xy為左上角坐標,wh為矩形的寬高
(x, y, w, h) = face[0]
# 返回圖像的正面部分
return gray[y:y + w, x:x + h], face[0]
else:
return None, None
# 該函數將讀取所有的訓練圖像,從每個圖像檢測人臉並將返回兩個相同大小的列表,分別為臉部信息和標簽
def prepare_training_data(data_folder_path):
# 獲取數據文件夾中的目錄(每個主題的一個目錄)
dirs = os.listdir(data_folder_path)
# 兩個列表分別保存所有的臉部和標簽
faces = []
labels = []
# 瀏覽每個目錄並訪問其中的圖像
for dir_name in dirs:
# dir_name(str類型)即標簽
label = int(dir_name)
# 建立包含當前主題主題圖像的目錄路徑
subject_dir_path = data_folder_path + "/" + dir_name
# 獲取給定主題目錄內的圖像名稱
subject_images_names = os.listdir(subject_dir_path)
# 瀏覽每張圖片並檢測臉部,然后將臉部信息添加到臉部列表faces[]
for image_name in subject_images_names:
# 建立圖像路徑
image_path = subject_dir_path + "/" + image_name
# 讀取圖像
image = cv2.imread(image_path)
# 顯示圖像0.1s
cv2.imshow("Training on image...", image)
cv2.waitKey(100)
# 檢測臉部
face, rect = detect_face(image)
# # 我們忽略未檢測到的臉部
if face is not None:
# 將臉添加到臉部列表並添加相應的標簽
faces.append(face)
labels.append(label)
cv2.waitKey(1)
cv2.destroyAllWindows()
# 最終返回值為人臉和標簽列表
return faces, labels
# 調用prepare_training_data()函數
faces, labels = prepare_training_data("images")
# 創建LBPH識別器並開始訓練,當然也可以選擇Eigen或者Fisher識別器
face_recognizer = cv2.face.LBPHFaceRecognizer_create()
face_recognizer.train(faces, np.array(labels))
# 根據指定的坐標和寬高在圖片上繪制矩形
def draw_rectangle(img, rect):
(x, y, w, h) = rect
cv2.rectangle(img, (x, y), (x + w, y + h), (128, 128, 0), 2)
# 根據給定的(x,y)坐標標識出人名
def draw_text(img, text, x, y):
cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_COMPLEX, 1, (128, 128, 0), 2)
# 建立標簽和人名的映射表
subjects = ["yangmi", "liuyifei"]
def predict(test_img):
# 生成圖片的副本,這樣就可以保留原始圖片
img = test_img.copy()
# 檢測人臉
face, rect = detect_face(img)
print(face)
print(rect)
# 預測人臉
label = face_recognizer.predict(face)
print(label)
# 判斷是否識別成功
if label:
# 獲取由人臉識別器返回的相應的標簽名稱
label_text = subjects[label[0]]
# 在檢測到的臉部周圍繪制一個矩形
draw_rectangle(img, rect)
# 標出預測的名字
draw_text(img, label_text, rect[0], rect[1] - 5)
# 返回預測圖像
return img
# else:
# print(img)
# # 在檢測到的臉部周圍繪制一個矩形
# draw_rectangle(img, rect)
# # 標出預測的名字
# draw_text(img, "unkonwn", rect[0], rect[1] - 5)
# # 返回預測圖像
# return img
test_img1 = cv2.imread("test_data/5.jpg")
test_img2 = cv2.imread("test_data/6.jpg")
predicted_img1 = predict(test_img1)
predicted_img2 = predict(test_img2)
cv2.imshow(subjects[0], predicted_img1)
cv2.imshow(subjects[1], predicted_img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
最后結果為
這個是識別率很低很低