Python學習:基于Opencv來快速實現(xiàn)人臉識別(完整版)

隨著人工智能的日益火熱,計算機視覺領域發(fā)展迅速悬包,尤其在人臉識別或物體檢測方向更為廣泛,今天就為大家?guī)碜罨A的人臉識別基礎馍乙,從一個個函數(shù)開始走進這個奧妙的世界布近。

首先看一下本實驗需要的數(shù)據(jù)集,為了簡便我們只進行兩個人的識別丝格,選取了beyond樂隊的主唱黃家駒和貝斯手黃家強撑瞧,這哥倆長得有幾分神似,這也是對人臉識別的一個考驗:

在這里插入圖片描述

兩個文件夾显蝌,一個為訓練數(shù)據(jù)集预伺,一個為測試數(shù)據(jù)集,訓練數(shù)據(jù)集中有兩個文件夾0和1曼尊,之前看一些資料有說這里要遵循“slabel”命名規(guī)則酬诀,但后面處理起來比較麻煩,因為目前opencv接受的人臉識別標簽為整數(shù)骆撇,那我們就直接用整數(shù)命名吧:


在這里插入圖片描述

為了方便瞒御,我們每個人用20張照片來訓練,0代表黃家駒神郊,1代表黃家強:


在這里插入圖片描述

開始啦:

  1. 檢測人臉葵腹。這應該是最基本的高每,給我們一張圖片,我們要先檢測出人臉的區(qū)域践宴,然后才能
    進行操作鲸匿,opencv已經(jīng)內(nèi)置了很多分類檢測器,我們這次用haar:

def detect_face(img):

將測試圖像轉(zhuǎn)換為灰度圖像阻肩,因為opencv人臉檢測器需要灰度圖像

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

加載OpenCV人臉檢測分類器Haar

face_cascade = cv2.CascadeClassifier('./haarcascade_frontalface_default.xml')

檢測多尺度圖像带欢,返回值是一張臉部區(qū)域信息的列表(x,y,寬,高)

faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5)

如果未檢測到面部,則返回原始圖像

if (len(faces) == 0):
return None, None

目前假設只有一張臉烤惊,xy為左上角坐標乔煞,wh為矩形的寬高

(x, y, w, h) = faces[0]

返回圖像的正面部分

return gray[y:y + w, x:x + h], faces[0]

2.有了數(shù)據(jù)集和檢測人臉的功能后,我們就可以進行預訓練了柒室,最后返回所有訓練圖片的人臉檢測信息和標簽:

# 該函數(shù)將讀取所有的訓練圖像渡贾,從每個圖像檢測人臉并將返回兩個相同大小的列表,分別為臉部信息和標簽
def prepare_training_data(data_folder_path):
 # 獲取數(shù)據(jù)文件夾中的目錄(每個主題的一個目錄)
 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
 # 獲取給定主題目錄內(nèi)的圖像名稱
 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

3.有了臉部信息和對應標簽后空骚,我們就可以使用opencv自帶的識別器來進行訓練了:

#調(diào)用prepare_training_data()函數(shù)
faces, labels = prepare_training_data("training_data")
#創(chuàng)建LBPH識別器并開始訓練,當然也可以選擇Eigen或者Fisher識別器
face_recognizer = cv2.face.LBPHFaceRecognizer_create()
face_recognizer.train(faces, np.array(labels))

4.訓練完畢后就可以進行預測了擂仍,在這之前我們可以設定一下預測的格式囤屹,包括用矩形框框出人臉并標出其名字,當然最后別忘了建立標簽與真實姓名直接的映射表:

#根據(jù)給定的(x逢渔,y)坐標和寬度高度在圖像上繪制矩形
def draw_rectangle(img, rect):
 (x, y, w, h) = rect
 cv2.rectangle(img, (x, y), (x + w, y + h), (128, 128, 0), 2)
# 根據(jù)給定的(x肋坚,y)坐標標識出人名
def draw_text(img, text, x, y):
 cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_COMPLEX, 1, (128, 128, 0), 2)
#建立標簽與人名的映射列表(標簽只能為整數(shù))
subjects = ["jiaju", "jiaqiang"]

5.現(xiàn)在就可以定義我們的預測函數(shù)了:

# 此函數(shù)識別傳遞的圖像中的人物并在檢測到的臉部周圍繪制一個矩形及其名稱
def predict(test_img):
 #生成圖像的副本,這樣就能保留原始圖像
 img = test_img.copy()
 #檢測人臉
 face, rect = detect_face(img)
 #預測人臉
 label = face_recognizer.predict(face)
 # 獲取由人臉識別器返回的相應標簽的名稱
 label_text = subjects[label[0]]
 # 在檢測到的臉部周圍畫一個矩形
 draw_rectangle(img, rect)
 # 標出預測的名字
 draw_text(img, label_text, rect[0], rect[1] - 5)
 #返回預測的圖像
 return img

6.最后使用我們test_data中的圖片進行預測并顯示最終效果:

#加載測試圖像
test_img1 = cv2.imread("test_data/test1.jpg")
test_img2 = cv2.imread("test_data/test2.jpg")
#執(zhí)行預測
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()

來看看識別的結(jié)果:


在這里插入圖片描述

這就是人臉識別最基本的流程肃廓,后續(xù)還會進一步的研究智厌,下一篇我們將討論本次實驗的一些細節(jié)和注意事項,算是對本篇的一次挖掘和總結(jié)吧盲赊。最后附上完整代碼:

# # -*- coding:utf-8 -*-
import cv2
import os
import numpy as np
# 檢測人臉
def detect_face(img):
 #將測試圖像轉(zhuǎn)換為灰度圖像铣鹏,因為opencv人臉檢測器需要灰度圖像
 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 #加載OpenCV人臉檢測分類器Haar
 face_cascade = cv2.CascadeClassifier('./haarcascade_frontalface_default.xml')
 #檢測多尺度圖像,返回值是一張臉部區(qū)域信息的列表(x,y,寬,高)
 faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5)
 # 如果未檢測到面部角钩,則返回原始圖像
 if (len(faces) == 0):
 return None, None
 #目前假設只有一張臉吝沫,xy為左上角坐標,wh為矩形的寬高
 (x, y, w, h) = faces[0]
 #返回圖像的正面部分
 return gray[y:y + w, x:x + h], faces[0]
# 該函數(shù)將讀取所有的訓練圖像递礼,從每個圖像檢測人臉并將返回兩個相同大小的列表惨险,分別為臉部信息和標簽
def prepare_training_data(data_folder_path):
 # 獲取數(shù)據(jù)文件夾中的目錄(每個主題的一個目錄)
 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
 # 獲取給定主題目錄內(nèi)的圖像名稱
 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
#調(diào)用prepare_training_data()函數(shù)
faces, labels = prepare_training_data("training_data")
#創(chuàng)建LBPH識別器并開始訓練脊髓,當然也可以選擇Eigen或者Fisher識別器
face_recognizer = cv2.face.LBPHFaceRecognizer_create()
face_recognizer.train(faces, np.array(labels))
#根據(jù)給定的(x辫愉,y)坐標和寬度高度在圖像上繪制矩形
def draw_rectangle(img, rect):
 (x, y, w, h) = rect
 cv2.rectangle(img, (x, y), (x + w, y + h), (128, 128, 0), 2)
# 根據(jù)給定的(x,y)坐標標識出人名
def draw_text(img, text, x, y):
 cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_COMPLEX, 1, (128, 128, 0), 2)
#建立標簽與人名的映射列表(標簽只能為整數(shù))
subjects = ["jiaju", "jiaqiang"]
# 此函數(shù)識別傳遞的圖像中的人物并在檢測到的臉部周圍繪制一個矩形及其名稱
def predict(test_img):
 #生成圖像的副本将硝,這樣就能保留原始圖像
 img = test_img.copy()
 #檢測人臉
 face, rect = detect_face(img)
 #預測人臉
 label = face_recognizer.predict(face)
 # 獲取由人臉識別器返回的相應標簽的名稱
 label_text = subjects[label[0]]
 # 在檢測到的臉部周圍畫一個矩形
 draw_rectangle(img, rect)
 # 標出預測的名字
 draw_text(img, label_text, rect[0], rect[1] - 5)
 #返回預測的圖像
 return img
#加載測試圖像
test_img1 = cv2.imread("test_data/test1.jpg")
test_img2 = cv2.imread("test_data/test2.jpg")
#執(zhí)行預測
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()


如果你依然在編程的世界里迷茫恭朗,
不知道自己的未來規(guī)劃屏镊,
對python感興趣,
這里推薦一下我的學習交流圈QQ群:895 797 751痰腮,
里面都是學習python的而芥,

伙伴們有哪些地方不清楚的可以留言

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市膀值,隨后出現(xiàn)的幾起案子棍丐,更是在濱河造成了極大的恐慌,老刑警劉巖沧踏,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件歌逢,死亡現(xiàn)場離奇詭異,居然都是意外死亡翘狱,警方通過查閱死者的電腦和手機秘案,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來潦匈,“玉大人阱高,你說我怎么就攤上這事±龋” “怎么了讨惩?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵辟癌,是天一觀的道長寒屯。 經(jīng)常有香客問我,道長黍少,這世上最難降的妖魔是什么寡夹? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮厂置,結(jié)果婚禮上菩掏,老公的妹妹穿的比我還像新娘。我一直安慰自己昵济,他們只是感情好智绸,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著访忿,像睡著了一般瞧栗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上海铆,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天迹恐,我揣著相機與錄音,去河邊找鬼卧斟。 笑死殴边,一個胖子當著我的面吹牛憎茂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播锤岸,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼竖幔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了是偷?” 一聲冷哼從身側(cè)響起赏枚,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎晓猛,沒想到半個月后饿幅,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡戒职,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年栗恩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片洪燥。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡磕秤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出捧韵,到底是詐尸還是另有隱情市咆,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布再来,位于F島的核電站蒙兰,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏芒篷。R本人自食惡果不足惜搜变,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望针炉。 院中可真熱鬧挠他,春花似錦、人聲如沸篡帕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽镰烧。三九已至拢军,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拌滋,已是汗流浹背朴沿。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人赌渣。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓魏铅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親坚芜。 傳聞我的和親對象是個殘疾皇子览芳,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容