【人臉識別(二)】:如何使用 dlib 實現簡單的人臉識別功能

人臉識別(一):Ubuntu Python安裝dlib C++ library

人臉識別(三):使用face_recognition庫實現人臉識別,python實現

人臉識別(四):人臉識別理論、原理、分類、概括,請針對性學習所需算法,不要全學。

人臉識別(五):基於Adaboost的人臉檢測算法,及實例教程

目錄

 

前言

檢測人臉

檢測視頻的人臉

檢測人臉的閾值設置

實現人臉識別/人臉對比

ROI追蹤(感興趣區域追蹤)

圖像中多張人臉識別

展望

針對本文的建議


 

前言

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庫實現人臉檢測、比對、識別以及拓展:

人臉識別(三):使用face_recognition庫實現人臉識別,python實現

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章