python 人脸识别项目face_recognition之简单入门

一、项目简介

本项目是世界上最简洁的人脸识别库,你可以使用Python和命令行工具提取、识别、操作人脸。

本项目的人脸识别是基于业内领先的C++开源库 dlib 中的深度学习模型,用Labeled Faces in the Wild人脸数据集进行测试,有高达99.38%的准确率。但对小孩和亚洲人脸的识别准确率尚待提升。

项目地址:https://github.com/ageitgey/face_recognition

截止本博文发布日,项目Star数达50.7k,可见该项目受欢迎程度很高,值得拿来学习下。

PS:该项目及其他人脸识别项目测试运行后续会不定时更新,有兴趣可以点个关注!

二、项目安装

环境:ubuntu18 cuda11.7

1、dlib编译安装

带GPU版:

git clone https://github.com/davisking/dlib.git
cd dlib
mkdir build
cmake .. -DDLIB_USE_CUDA=1 -DUSE_AVX_INSTRUCTIONS=1
cmake --build .

完成后安装到python中,有虚拟环境的先切换到对应的python虚拟环境:

cd ..
python setup.py install --set DLIB_USE_CUDA=1 --no DLIB_GIF_SUPPORT

2、face_recognition 安装

pip install face_recognition

三、示例运行测试

1、在图片中定位人脸的位置

from PIL import Image
import face_recognition
import time

# 加载图片
image = face_recognition.load_image_file("unknown_pic/obama.jpg")

# 人脸定位
beginTime = time.time()
face_locations = face_recognition.face_locations(image)
# face_locations = face_recognition.face_locations(image, model="cnn") # 使用GPU加速
print(f'face_locations Done. ({time.time() - beginTime:.3f}s)') # 打印时间

print("I found {} face(s) in this photograph.".format(len(face_locations)))

for face_location in face_locations:

    # 打印位置
    top, right, bottom, left = face_location
    print("A face is located at pixel location Top: {}, Left: {}, Bottom: {}, Right: {}".format(top, left, bottom, right))

    # 人脸图
    face_image = image[top:bottom, left:right]
    pil_image = Image.fromarray(face_image)
    pil_image.show()

运行结果:

python 人脸识别项目face_recognition之简单入门_第1张图片

2、识别单张图片中人脸的关键点

from PIL import Image, ImageDraw
import face_recognition
import time

# 加载图片
image = face_recognition.load_image_file("unknown_pic/obama.jpg")

beginTime = time.time()
# 找出图像中所有人脸的所有面部特征
face_landmarks_list = face_recognition.face_landmarks(image)
print(f'face_landmarks Done. ({time.time() - beginTime:.3f}s)') # 打印时间

print("I found {} face(s) in this photograph.".format(len(face_landmarks_list)))

# 创建一个PIL imagedraw对象,这样我们就可以在图片上绘图了
pil_image = Image.fromarray(image)
d = ImageDraw.Draw(pil_image)

for face_landmarks in face_landmarks_list:

    # 打印该图像中每个面部特征的位置
    for facial_feature in face_landmarks.keys():
        print("The {} in this face has the following points: {}".format(facial_feature, face_landmarks[facial_feature]))

    # 让我们用一条线描摹出图像中的每个面部特征!
    for facial_feature in face_landmarks.keys():
        d.line(face_landmarks[facial_feature], width=5)


pil_image.show()

运行结果:

python 人脸识别项目face_recognition之简单入门_第2张图片

3、识别图片中的人是谁

import face_recognition

# 加载图片
# 拜登照片
biden_image = face_recognition.load_image_file("known_people/biden.jpg")
# 奥巴马照片
obama_image = face_recognition.load_image_file("known_people/obama.jpg")
# 需要识别的照片(奥巴马)
unknown_image = face_recognition.load_image_file("unknown_pic/unknown1.jpg")

# 获取每个图像文件中每个人脸的人脸编码

# 由于每张图像中可能有不止一张脸,它返回一个编码列表。

# 但是因为我知道每张图片只有一张脸,所以我只关心每张图片的第一个编码,所以我抓取索引0。
try:
    biden_face_encoding = face_recognition.face_encodings(biden_image)[0]
    obama_face_encoding = face_recognition.face_encodings(obama_image)[0]
    unknown_face_encoding = face_recognition.face_encodings(unknown_image)[0]
except IndexError:
    print("无法定位到人脸. Check the image files. Aborting...")
    quit()

# 已知的人脸编码
known_faces = [
    biden_face_encoding,
    obama_face_encoding
]

# results是一个True/False数组,告诉未知面孔是否与known_faces数组中的任何人匹配
results = face_recognition.compare_faces(known_faces, unknown_face_encoding)

print("这是Biden吗? {}".format(results[0]))
print("这是Obama吗? {}".format(results[1]))
print("都不是,没见过? {}".format(not True in results))

运行结果:

这是Biden吗? False
这是Obama吗? True
都不是,没见过? False

4、人脸识别之后在原图上画框框并标注姓名

from PIL import Image, ImageDraw
import time
import numpy as np
import face_recognition


# 加载奥巴马照片并获取其编码.
obama_image = face_recognition.load_image_file("known_people/obama.jpg")
obama_face_encoding = face_recognition.face_encodings(obama_image)[0]

# 加载拜登照片并获取其编码.
biden_image = face_recognition.load_image_file("known_people/biden.jpg")
biden_face_encoding = face_recognition.face_encodings(biden_image)[0]

# 已知的人脸编码数组
known_face_encodings = [
    obama_face_encoding,
    biden_face_encoding
]
# 对应的人的名称
known_face_names = [
    "Barack Obama",
    "Joe Biden"
]

# 加载需要识别的照片(奥巴马)
unknown_image = face_recognition.load_image_file("unknown_pic/unknown1.jpg")

# 找到其所有人脸位置并获取其编码
face_locations = face_recognition.face_locations(unknown_image)
face_encodings = face_recognition.face_encodings(unknown_image, face_locations)

# 将图像转换为pil格式的图像,以便我们可以使用Pillow库在其上绘制
pil_image = Image.fromarray(unknown_image)
# 创建一个Pillow ImageDraw Draw实例来绘制
draw = ImageDraw.Draw(pil_image)

# 循环遍历未知图像中发现的每张脸
for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):
    # 看看这张脸是否与已知的脸匹配。
    matches = face_recognition.compare_faces(known_face_encodings, face_encoding)

    name = "Unknown"

    # 没验证
    # If a match was found in known_face_encodings, just use the first one.
    # if True in matches:
    #     first_match_index = matches.index(True)
    #     name = known_face_names[first_match_index]

    # 给定人脸编码列表,将它们与已知的人脸编码进行比较,并得到每个比较人脸的欧氏距离。距离大小为面孔的相似程度。
    face_distances = face_recognition.face_distance(known_face_encodings, face_encoding)
    best_match_index = np.argmin(face_distances)
    if matches[best_match_index]:
        name = known_face_names[best_match_index]

    # 使用Pillow模块在脸部周围画一个框
    draw.rectangle(((left, top), (right, bottom)), outline=(0, 0, 255))

    # 在脸下面画一个带名字的标签
    text_width, text_height = draw.textsize(name)
    draw.rectangle(((left, bottom - text_height - 10), (right, bottom)), fill=(0, 0, 255), outline=(0, 0, 255))
    draw.text((left + 6, bottom - text_height - 5), name, fill=(255, 255, 255, 255))



del draw
pil_image.show()

运行结果:

python 人脸识别项目face_recognition之简单入门_第3张图片
5、从摄像头获取视频进行人脸识别(官方示例简单修改)

import face_recognition
import cv2
import numpy as np
import uuid
import os

# 获取视频流(这里拿了个海康相机RTSP流)
video_capture = cv2.VideoCapture("rtsp://admin:密码@192.168.*.*/h264/ch1/main/av_stream")

# 创建已知人脸编码及其名称的数组
known_face_encodings =[]
known_face_names=[]

# 已知的人脸库文件夹
known_face_dir = "known_people"

# 加载人脸库
# 遍历文件夹并获取文件夹名(对应人名)
for face_name in os.listdir(known_face_dir):
    fece_name_dir = os.path.join(known_face_dir, face_name)
    if os.path.isdir(fece_name_dir):
        # 再获取该人名文件夹下所有图片名(人脸库图片)
        for face_img in os.listdir(fece_name_dir):
            face_img_filepath = os.path.join(fece_name_dir, face_img)
            if face_img_filepath.endswith(".jpg"):
                print(face_name)
                # 加载人脸图片
                face_img = face_recognition.load_image_file(face_img_filepath)
                # 获取编码
                face_encoding = face_recognition.face_encodings(face_img)[0]
                known_face_encodings.append(face_encoding)
                known_face_names.append(face_name)

# 初始化一些变量
# 人脸位置信息
face_locations = []
# 人脸编码信息
face_encodings = []
# 人脸名称
face_names = []
# 是否处理此帧
process_this_frame = True

while True:
    # 抓取一帧视频
    ret, frame = video_capture.read()

    # 只处理每隔一帧视频以节省时间
    if process_this_frame:
        # 将视频帧调整为1/4大小,以便更快地进行人脸识别处理
        small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)

        # 将图像从BGR颜色(OpenCV使用)转换为RGB颜色(face_recognition使用)
        # rgb_small_frame = small_frame[:, :, ::-1]
        rgb_small_frame = cv2.cvtColor(small_frame, cv2.COLOR_BGR2RGB)
        
        # 找到当前视频帧中的所有人脸和人脸编码
        face_locations = face_recognition.face_locations(rgb_small_frame,model="cnn")

        face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)
        
        face_names = []
        for face_encoding in face_encodings:
            print('detect face !')
            # 看看这张脸是否与已知的脸匹配。
            matches = face_recognition.compare_faces(known_face_encodings, face_encoding)
            name = "Unknown"
            # 使用与新面孔距离最小的已知面孔
            face_distances = face_recognition.face_distance(known_face_encodings, face_encoding)
            best_match_index = np.argmin(face_distances)
            if matches[best_match_index]:
                name = known_face_names[best_match_index]

            face_names.append(name)

        # 显示结果
        for (top, right, bottom, left), name in zip(face_locations, face_names):
            # 缩放面部位置,因为我们检测到的帧被缩放到1/4大小
            top *= 4
            right *= 4
            bottom *= 4
            left *= 4
            pic_name = "face_imgs/"+ name + str(uuid.uuid1()) +".jpg"
            
            # 在脸周围画一个框
            cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)

            # 在脸下面画一个带名字的标签
            cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
            font = cv2.FONT_HERSHEY_DUPLEX
            cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)
            cv2.imwrite(pic_name, frame)  # 并把图片保存到路径的文件夹,注意容量
            print('save face pic :',pic_name)

    process_this_frame = not process_this_frame

    cv2.imshow('Video', cv2.resize(frame,(1280,720)))

    # Hit 'q' on the keyboard to quit!
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# Release handle to the webcam
video_capture.release()
cv2.destroyAllWindows()

其中文件夹结构:

python 人脸识别项目face_recognition之简单入门_第4张图片

发现的小问题:face_locations并不是每次都能准备识别人脸位置,有时候不是人脸也框了。

你可能感兴趣的:(人脸识别,python,深度学习,人工智能)