人脸识别(二):如何使用 dlib 实现简单的人脸识别功能

目录

 

前言

检测人脸

检测视频的人脸

检测人脸的阈值设置

实现人脸识别/人脸对比

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格式

原创文章 5 获赞 8 访问量 420

猜你喜欢

转载自blog.csdn.net/qq_39709813/article/details/105644815