人臉識別(一):Ubuntu Python安裝dlib C++ library
人臉識別(三):使用face_recognition庫實現人臉識別,python實現
人臉識別(四):人臉識別理論、原理、分類、概括,請針對性學習所需算法,不要全學。
人臉識別(五):基於Adaboost的人臉檢測算法,及實例教程
目錄
前言
dlib是不錯的人臉檢測、識別的庫,檢測精度爲99.13%。
本文旨在教小白實現人臉檢測、人臉識別、感興趣區域追蹤以及在視頻中的應用。
本文涉及到的代碼、圖片、視頻都已上傳在本文資源中(也可以點擊https://download.csdn.net/download/qq_39709813/12345196),供下載學習。受到時間關係的影響,本文沒有過多的探索dlib庫,希望讀者可以在此基礎上繼續探索、開發。
務必安裝requirem.txt文件中的必要庫。
文檔說明
face_images保存多張人多臉的圖片,供學習使用
model保存已經下載好的模型數據
people_i_know保存已經認識的人的單張圖片
unknow_people保存需要識別的人的圖像
video保存檢測和識別使用的視頻
檢測人臉
檢測人臉,實現的是使用檢測框將圖像中的人臉檢測出,使用的是dlib與PIL實現,保存在test1.py中。代碼和檢測結果如下:
import dlib
from PIL import Image
import numpy as py
import os
file_path = "./people_i_know/huge.jpg"
detector = dlib.get_frontal_face_detector() # 加載檢測器
win = dlib.image_window()
image = py.array(Image.open(file_path)) # 讀取圖片
detector_face = detector(image, 1) # 檢測 1是放大圖片
win.clear_overlay()
win.set_image(image) # 顯示圖pain
win.add_overlay(detector_face) # 添加檢測框
dlib.hit_enter_to_continue()
檢測視頻中的人臉
在檢測人臉的基礎上,融合opencv,實現視頻中的人臉檢測,保存在test2.py中,代碼和結果如下:
import dlib
import cv2
import numpy as np
video_capture = cv2.VideoCapture("./video/hamilton_clip.mp4")
# video_capture = cv2.VideoCapture(0)
detector = dlib.get_frontal_face_detector()
win = dlib.image_window()
while video_capture.isOpened():
# Grab a single frame of video
ret, frame = video_capture.read() # 逐幀讀取圖片
if not ret:
break
# Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses)
frame = frame[:, :, ::-1] # BGR格式轉成RGB格式
image = np.array(frame)
detector_face = detector(image, 1)
win.clear_overlay()
win.set_image(image)
win.add_overlay(detector_face)
video_capture.release()
cv2.destroyAllWindows()
檢測人臉的閾值設置
以上檢測人臉使用的都是默認的閾值,在實際練習的時候,可以按照自己的需求閾值。
可以簡單的認爲檢測人臉時,都會有一個得分,當得分高於閾值時,將其輸出。
dets, sco, idx = detector.run(image,0,1)爲閾值設置部分,dets是檢測框,sco是檢測到的人臉得分,idx是檢測器類型,1即爲人爲設定的閾值。
通過設置不同的閾值,你會發現檢測框會很多,或者沒有,或者吧人臉完美框住。
保存在test3.py中,代碼和結果如下:
import numpy as py
from PIL import Image
path = "./people_i_know/huge.jpg"
detector = dlib.get_frontal_face_detector()
win = dlib.image_window()
image = py.array(Image.open(path))
dets, sco, idx = detector.run(image,0,1) # 設置閾值
for i, d in enumerate(dets):
print('%d:score %f, face_type %f' % (i, sco[i], idx[i]))
win.clear_overlay()
win.set_image(image)
win.add_overlay(dets)
dlib.hit_enter_to_continue()
實現人臉識別/人臉對比
識別人臉需要人臉特徵向量,通過比對兩張臉之間特徵向量的距離來判定,需要檢測的人是否認識,以及這個人叫什麼。
因此,這裏引入了shape_predictor_68_face_landmarks.dat與dlib_face_recognition_resnet_model_v1.dat,前者是人臉68點的檢測模型,後者是人臉特徵向量模型,都是已經訓練好的。
這些模型數據都已經放在資源中,也可以自行去官網下載:http://dlib.net/files/
同時還引入了距離函數,代碼中簡化爲 Eu(a,b)。具體代碼保存在test4.py中,代碼和結果如下:
import dlib
from PIL import Image
import numpy as np
import os
detector = dlib.get_frontal_face_detector()
path_pre = "./model/shape_predictor_68_face_landmarks.dat" # 68點模型
pre = dlib.shape_predictor(path_pre)
path_model = "./model/dlib_face_recognition_resnet_model_v1.dat" # resent模型
model = dlib.face_recognition_model_v1(path_model)
path_know = "./people_i_know" # 已知人臉文件夾
path_unknow = "./unknow_people" # 需要檢測的人來你文件夾
know_list = {}
def Eu(a,b): # 距離函數
return np.linalg.norm(np.array(a) - np.array(b), ord=2)
for path in os.listdir(path_know):# 載入已知人的名字和麪部特徵
img = np.array(Image.open(path_know+"/"+path))
name = path.split('.')[0]
det_img = detector(img, 0)
shape = pre(img, det_img[0])
know_encode = model.compute_face_descriptor(img, shape)
know_list[name] = know_encode
match = {}
for path in os.listdir(path_unknow):#逐個載入待檢測人的面部特徵
img = np.array(Image.open(path_unknow+"/"+path))
name = path.split('.')[0]
det_img = detector(img, 0)
shape = pre(img, det_img[0])
unknow_encode = model.compute_face_descriptor(img, shape)
match[name] = "unknow"
for key, sco in know_list.items():# 與已知的面部特徵匹配
if Eu(unknow_encode, sco) < 0.6:
match[name] = key
break
for key, value in match.items():
print("picture:"+key+' is '+ value)
代碼設計3個文件夾,
model文件夾存放的是上述的兩個模型數據
people_i_know文件夾存放的是你事先知道的人,以及他的樣子。
unknow_people文件夾存放的是你想識別的人,看這個人是否是你認識的(顯示他的名字),或者是你不認識的(顯示unknow)
從下圖中可以看出,unknow2文件是obama,unknown3文件是biden,unknown4文件是不認識的人。
ROI追蹤(感興趣區域追蹤)
感興趣區域,是一副圖像中,我們最關心的地方。感興趣區域追蹤,是指檢測框將隨着這個物體的移動而隨之移動,始終將物體的位置檢測出。
下列代碼實現的是對視頻中感興趣區域的檢測,代碼一運行需要人爲的使用鼠框選選自己感興趣的區域,並按下enter確認,過後,檢測框將自動追蹤物體或者人。
保存在test5.py中,代碼和結果如下:
import dlib
import cv2
video_capture = cv2.VideoCapture("./video/hamilton_clip.mp4")
# video_capture = cv2.VideoCapture(0)
detector = dlib.correlation_tracker()
win = dlib.image_window()
i = 0
while video_capture.isOpened():
# Grab a single frame of video
ret, frame = video_capture.read()
if not ret:
break
# Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses)
frame = frame[:, :, ::-1]
if i == 0:#在第一幀的時候調用鼠標回去檢測框的位置
cv2.namedWindow('image',flags=cv2.WINDOW_NORMAL)
cv2.imshow('image',frame)
rect = cv2.selectROI('image', frame, showCrosshair=False, fromCenter=False)
cv2.destroyAllWindows()
detector.start_track(frame, dlib.rectangle(rect[0],rect[1],rect[0]+rect[2],rect[1]+rect[3]))
i=i+1
else:# 繼續追蹤內容
detector.update(frame)
win.clear_overlay()
win.set_image(frame)
win.add_overlay(detector.get_position())
video_capture.release()
cv2.destroyAllWindows()
下圖藍色框是人爲使用鼠標框選的位置。
下圖紅色框是自動追蹤的位置。由於視頻中的攝像機經常切換位置,因此檢測結果不是很理想。
可以知道:當場景的角度位置變化不大的時候,檢測結果較理想;當場景切換過大,可能會出現誤檢測的現象。
圖像中多張人臉識別
現實生活中,一張圖往往有許多的人臉。下列代碼重點就是將一幅圖中認識的人臉識別出來,對不認識的人不檢測。
檢測使用的是dlib,繪圖部分使用的是opencv。保存在test6.py中,代碼和結果如下:
import dlib
from PIL import Image
import numpy as np
import os
import cv2
from imutils import face_utils
detector = dlib.get_frontal_face_detector()
path_pre = "./model/shape_predictor_68_face_landmarks.dat"
pre = dlib.shape_predictor(path_pre)
path_model = "./model/dlib_face_recognition_resnet_model_v1.dat"
model = dlib.face_recognition_model_v1(path_model)
path_know = "./people_i_know"
path_unknow = "./face_images/bald_guys.jpg"
know_list = {}
def Eu(a,b):
return np.linalg.norm(np.array(a) - np.array(b), ord=2)
for path in os.listdir(path_know):# 建立已知人臉的字典庫
img = np.array(Image.open(path_know+"/"+path))
name = path.split('.')[0]
det_img = detector(img, 0)
shape = pre(img, det_img[0])
know_encode = model.compute_face_descriptor(img, shape)
know_list[name] = know_encode
frame = cv2.imread(path_unknow)
#frame = frame[:, :, ::-1]
img = np.array(frame)
det_img = detector(img, 0)#得到檢測框
for rect in enumerate(det_img):
shape = pre(img, rect[1])
(x,y,w,h) = face_utils.rect_to_bb(rect[1])#rect由tuple轉成bb
unknow_encode = model.compute_face_descriptor(img, shape)
for key, sco in know_list.items():
if Eu(unknow_encode, sco) < 0.6:
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 0, 255), 3)# 繪製檢測框
cv2.putText(img, key, (x, y+h), cv2.FONT_HERSHEY_SIMPLEX, 0.5,(255,0,0), 2)#繪製檢測後的姓名
break
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.imshow('output',img)
cv2.waitKey(0)
檢測的圖像中包含許多張人臉,已經檢測書的人:傑森斯坦森(joson)和強森(johnson)。從結果中,可以看到也有漏檢測和檢測錯誤的情況,原因在於,people_i_know文件夾下的joson和johnson是最新美化過的圖像。
展望
目前,本文就實現這些功能,還有更多的功能可以實現,需要你自己慢慢探索。例如,結合opencv實現視頻中多張人臉的識別和標註、提升機器運行速度等。
針對本文的建議
首先是按照要求安裝必要的包;
其次是people_i_know文件夾裏放置高清端正的圖像;
所有的圖片使用.jpg格式
下一篇將使用face_recognition庫實現人臉檢測、比對、識別以及拓展: