opencv 人脸识别_Python学习:基于Opencv来快速实现人脸识别(完整版)
隨著人工智能的日益火熱,計(jì)算機(jī)視覺領(lǐng)域發(fā)展迅速,尤其在人臉識(shí)別或物體檢測(cè)方向更為廣泛,今天就為大家?guī)碜罨A(chǔ)的人臉識(shí)別基礎(chǔ),從一個(gè)個(gè)函數(shù)開始走進(jìn)這個(gè)奧妙的世界。
首先看一下本實(shí)驗(yàn)需要的數(shù)據(jù)集,為了簡(jiǎn)便我們只進(jìn)行兩個(gè)人的識(shí)別,選取了beyond樂隊(duì)的主唱黃家駒和貝斯手黃家強(qiáng),這哥倆長得有幾分神似,這也是對(duì)人臉識(shí)別的一個(gè)考驗(yàn):
兩個(gè)文件夾,一個(gè)為訓(xùn)練數(shù)據(jù)集,一個(gè)為測(cè)試數(shù)據(jù)集,訓(xùn)練數(shù)據(jù)集中有兩個(gè)文件夾0和1,之前看一些資料有說這里要遵循“slabel”命名規(guī)則,但后面處理起來比較麻煩,因?yàn)槟壳皁pencv接受的人臉識(shí)別標(biāo)簽為整數(shù),那我們就直接用整數(shù)命名吧:
為了方便,我們每個(gè)人用20張照片來訓(xùn)練,0代表黃家駒,1代表黃家強(qiáng):
開始啦:
進(jìn)行操作,opencv已經(jīng)內(nèi)置了很多分類檢測(cè)器,我們這次用haar:
def detect_face(img):#將測(cè)試圖像轉(zhuǎn)換為灰度圖像,因?yàn)閛pencv人臉檢測(cè)器需要灰度圖像gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#加載OpenCV人臉檢測(cè)分類器Haarface_cascade = cv2.CascadeClassifier('./haarcascade_frontalface_default.xml')#檢測(cè)多尺度圖像,返回值是一張臉部區(qū)域信息的列表(x,y,寬,高)faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5)# 如果未檢測(cè)到面部,則返回原始圖像if (len(faces) == 0):return None, None#目前假設(shè)只有一張臉,xy為左上角坐標(biāo),wh為矩形的寬高(x, y, w, h) = faces[0]#返回圖像的正面部分return gray[y:y + w, x:x + h], faces[0]2.有了數(shù)據(jù)集和檢測(cè)人臉的功能后,我們就可以進(jìn)行預(yù)訓(xùn)練了,最后返回所有訓(xùn)練圖片的人臉檢測(cè)信息和標(biāo)簽:
# 該函數(shù)將讀取所有的訓(xùn)練圖像,從每個(gè)圖像檢測(cè)人臉并將返回兩個(gè)相同大小的列表,分別為臉部信息和標(biāo)簽 def prepare_training_data(data_folder_path):# 獲取數(shù)據(jù)文件夾中的目錄(每個(gè)主題的一個(gè)目錄)dirs = os.listdir(data_folder_path)# 兩個(gè)列表分別保存所有的臉部和標(biāo)簽faces = []labels = []# 瀏覽每個(gè)目錄并訪問其中的圖像for dir_name in dirs:# dir_name(str類型)即標(biāo)簽label = int(dir_name)# 建立包含當(dāng)前主題主題圖像的目錄路徑subject_dir_path = data_folder_path + "/" + dir_name# 獲取給定主題目錄內(nèi)的圖像名稱subject_images_names = os.listdir(subject_dir_path)# 瀏覽每張圖片并檢測(cè)臉部,然后將臉部信息添加到臉部列表faces[]for image_name in subject_images_names:# 建立圖像路徑image_path = subject_dir_path + "/" + image_name# 讀取圖像image = cv2.imread(image_path)# 顯示圖像0.1scv2.imshow("Training on image...", image)cv2.waitKey(100)# 檢測(cè)臉部face, rect = detect_face(image)# 我們忽略未檢測(cè)到的臉部if face is not None:#將臉添加到臉部列表并添加相應(yīng)的標(biāo)簽faces.append(face)labels.append(label)cv2.waitKey(1)cv2.destroyAllWindows()#最終返回值為人臉和標(biāo)簽列表return faces, labels3.有了臉部信息和對(duì)應(yīng)標(biāo)簽后,我們就可以使用opencv自帶的識(shí)別器來進(jìn)行訓(xùn)練了:
#調(diào)用prepare_training_data()函數(shù) faces, labels = prepare_training_data("training_data") #創(chuàng)建LBPH識(shí)別器并開始訓(xùn)練,當(dāng)然也可以選擇Eigen或者Fisher識(shí)別器 face_recognizer = cv2.face.LBPHFaceRecognizer_create() face_recognizer.train(faces, np.array(labels))4.訓(xùn)練完畢后就可以進(jìn)行預(yù)測(cè)了,在這之前我們可以設(shè)定一下預(yù)測(cè)的格式,包括用矩形框框出人臉并標(biāo)出其名字,當(dāng)然最后別忘了建立標(biāo)簽與真實(shí)姓名直接的映射表:
#根據(jù)給定的(x,y)坐標(biāo)和寬度高度在圖像上繪制矩形 def draw_rectangle(img, rect):(x, y, w, h) = rectcv2.rectangle(img, (x, y), (x + w, y + h), (128, 128, 0), 2) # 根據(jù)給定的(x,y)坐標(biāo)標(biāo)識(shí)出人名 def draw_text(img, text, x, y):cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_COMPLEX, 1, (128, 128, 0), 2) #建立標(biāo)簽與人名的映射列表(標(biāo)簽只能為整數(shù)) subjects = ["jiaju", "jiaqiang"]5.現(xiàn)在就可以定義我們的預(yù)測(cè)函數(shù)了:
# 此函數(shù)識(shí)別傳遞的圖像中的人物并在檢測(cè)到的臉部周圍繪制一個(gè)矩形及其名稱 def predict(test_img):#生成圖像的副本,這樣就能保留原始圖像img = test_img.copy()#檢測(cè)人臉face, rect = detect_face(img)#預(yù)測(cè)人臉label = face_recognizer.predict(face)# 獲取由人臉識(shí)別器返回的相應(yīng)標(biāo)簽的名稱label_text = subjects[label[0]]# 在檢測(cè)到的臉部周圍畫一個(gè)矩形draw_rectangle(img, rect)# 標(biāo)出預(yù)測(cè)的名字draw_text(img, label_text, rect[0], rect[1] - 5)#返回預(yù)測(cè)的圖像return img6.最后使用我們test_data中的圖片進(jìn)行預(yù)測(cè)并顯示最終效果:
#加載測(cè)試圖像 test_img1 = cv2.imread("test_data/test1.jpg") test_img2 = cv2.imread("test_data/test2.jpg") #執(zhí)行預(yù)測(cè) predicted_img1 = predict(test_img1) predicted_img2 = predict(test_img2) #顯示兩個(gè)圖像 cv2.imshow(subjects[0], predicted_img1) cv2.imshow(subjects[1], predicted_img2) cv2.waitKey(0) cv2.destroyAllWindows()來看看識(shí)別的結(jié)果:
這就是人臉識(shí)別最基本的流程,后續(xù)還會(huì)進(jìn)一步的研究,下一篇我們將討論本次實(shí)驗(yàn)的一些細(xì)節(jié)和注意事項(xiàng),算是對(duì)本篇的一次挖掘和總結(jié)吧。最后附上完整代碼:
# # -*- coding:utf-8 -*- import cv2 import os import numpy as np # 檢測(cè)人臉 def detect_face(img):#將測(cè)試圖像轉(zhuǎn)換為灰度圖像,因?yàn)閛pencv人臉檢測(cè)器需要灰度圖像gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#加載OpenCV人臉檢測(cè)分類器Haarface_cascade = cv2.CascadeClassifier('./haarcascade_frontalface_default.xml')#檢測(cè)多尺度圖像,返回值是一張臉部區(qū)域信息的列表(x,y,寬,高)faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5)# 如果未檢測(cè)到面部,則返回原始圖像if (len(faces) == 0):return None, None#目前假設(shè)只有一張臉,xy為左上角坐標(biāo),wh為矩形的寬高(x, y, w, h) = faces[0]#返回圖像的正面部分return gray[y:y + w, x:x + h], faces[0] # 該函數(shù)將讀取所有的訓(xùn)練圖像,從每個(gè)圖像檢測(cè)人臉并將返回兩個(gè)相同大小的列表,分別為臉部信息和標(biāo)簽 def prepare_training_data(data_folder_path):# 獲取數(shù)據(jù)文件夾中的目錄(每個(gè)主題的一個(gè)目錄)dirs = os.listdir(data_folder_path)# 兩個(gè)列表分別保存所有的臉部和標(biāo)簽faces = []labels = []# 瀏覽每個(gè)目錄并訪問其中的圖像for dir_name in dirs:# dir_name(str類型)即標(biāo)簽label = int(dir_name)# 建立包含當(dāng)前主題主題圖像的目錄路徑subject_dir_path = data_folder_path + "/" + dir_name# 獲取給定主題目錄內(nèi)的圖像名稱subject_images_names = os.listdir(subject_dir_path)# 瀏覽每張圖片并檢測(cè)臉部,然后將臉部信息添加到臉部列表faces[]for image_name in subject_images_names:# 建立圖像路徑image_path = subject_dir_path + "/" + image_name# 讀取圖像image = cv2.imread(image_path)# 顯示圖像0.1scv2.imshow("Training on image...", image)cv2.waitKey(100)# 檢測(cè)臉部face, rect = detect_face(image)# 我們忽略未檢測(cè)到的臉部if face is not None:#將臉添加到臉部列表并添加相應(yīng)的標(biāo)簽faces.append(face)labels.append(label)cv2.waitKey(1)cv2.destroyAllWindows()#最終返回值為人臉和標(biāo)簽列表return faces, labels #調(diào)用prepare_training_data()函數(shù) faces, labels = prepare_training_data("training_data") #創(chuàng)建LBPH識(shí)別器并開始訓(xùn)練,當(dāng)然也可以選擇Eigen或者Fisher識(shí)別器 face_recognizer = cv2.face.LBPHFaceRecognizer_create() face_recognizer.train(faces, np.array(labels)) #根據(jù)給定的(x,y)坐標(biāo)和寬度高度在圖像上繪制矩形 def draw_rectangle(img, rect):(x, y, w, h) = rectcv2.rectangle(img, (x, y), (x + w, y + h), (128, 128, 0), 2) # 根據(jù)給定的(x,y)坐標(biāo)標(biāo)識(shí)出人名 def draw_text(img, text, x, y):cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_COMPLEX, 1, (128, 128, 0), 2) #建立標(biāo)簽與人名的映射列表(標(biāo)簽只能為整數(shù)) subjects = ["jiaju", "jiaqiang"] # 此函數(shù)識(shí)別傳遞的圖像中的人物并在檢測(cè)到的臉部周圍繪制一個(gè)矩形及其名稱 def predict(test_img):#生成圖像的副本,這樣就能保留原始圖像img = test_img.copy()#檢測(cè)人臉face, rect = detect_face(img)#預(yù)測(cè)人臉label = face_recognizer.predict(face)# 獲取由人臉識(shí)別器返回的相應(yīng)標(biāo)簽的名稱label_text = subjects[label[0]]# 在檢測(cè)到的臉部周圍畫一個(gè)矩形draw_rectangle(img, rect)# 標(biāo)出預(yù)測(cè)的名字draw_text(img, label_text, rect[0], rect[1] - 5)#返回預(yù)測(cè)的圖像return img #加載測(cè)試圖像 test_img1 = cv2.imread("test_data/test1.jpg") test_img2 = cv2.imread("test_data/test2.jpg") #執(zhí)行預(yù)測(cè) predicted_img1 = predict(test_img1) predicted_img2 = predict(test_img2) #顯示兩個(gè)圖像 cv2.imshow(subjects[0], predicted_img1) cv2.imshow(subjects[1], predicted_img2) cv2.waitKey(0) cv2.destroyAllWindows()伙伴們有哪些地方不清楚的可以留言哦!
總結(jié)
以上是生活随笔為你收集整理的opencv 人脸识别_Python学习:基于Opencv来快速实现人脸识别(完整版)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python课程主要介绍哪些内容_Pyt
- 下一篇: python正态检验_Python检验数