利用OpenCV和Python一百行代码快速实现人脸检测和人脸识别

利用OpenCV和Python一百行代码快速实现人脸检测和人脸识别

本章的博客涉及代码和模型文件。关注以下公众号,回复关键词pycv人脸识别获取下载链接!
利用OpenCV和Python一百行代码快速实现人脸检测和人脸识别

1、前言

在2018年的时候,我写过一篇人脸检测和识别的博客,当时对关于人脸的图像识别还没有什么概念,就纯粹是跟上网上的教程做的一个记录,识别方式是利用的SVM(支持向量机)实现的,用的opencv版本为3.0.0,具体可看这里:Opencv人脸识别学习记录。

现如今图像类的识别都开始转型为使用深度学习方式,本文主要是利用opencv中的DNN模块,在4.5.4版本中并入了这位大神的人脸识别算法,识别精度和速度非常可观,源代码见这里:https://github.com/ShiqiYu/libfacedetection

基于深度学习的人脸识别基本上分为两个步骤。第一步是人脸检测和对齐;第二步是人脸特征提取和比较。

开发环境说明

  • 截止2022年3月14日,python版opencv最新版本为4.5.5.64,本博客使用的就是该版本
  • python3.9
  • PyCharm2018.2

pip安装opencv:

pip install opencv-python==4.5.5.64 -i https://pypi.tuna.tsinghua.edu.cn/simple

2、准备工作

模型下载:

人脸检测模型下载地址:https://github.com/ShiqiYu/libfacedetection.train/tree/master/tasks/task1/onnx

人脸识别模型下载地址:https://drive.google.com/file/d/1ClK9WiB492c5OZFKveF3XiHCejoOxINW/view

利用OpenCV和Python一百行代码快速实现人脸检测和人脸识别

opencv官方例程:

opencv官方人脸检测识别demo(python代码):https://github.com/opencv/opencv/blob/4.x/samples/dnn/face_detect.py

opencv官方人脸检测识别demo(C++代码):https://github.com/opencv/opencv/blob/4.x/samples/dnn/face_detect.cpp

除去参考官方的代码,还参考了这位大神的文章:https://mp.weixin.qq.com/s/VijOXz4NEP3rRCM44Sd2pA

3、OpenCV DNN模块式使用步骤

首先读入图像并加载人脸检测和人脸识别模型:

import numpy as np
import cv2

# 读入人脸图像
image1 = cv2.imread('1.png')
image2 = cv2.imread('2.png')

input_shape = (300, 300)

# 重塑图片为300X300大小
image1 = cv2.resize(image1, input_shape)
image2 = cv2.resize(image2, input_shape)

# 加载人脸检测模型
faceDetector = cv2.FaceDetectorYN_create(model='yunet.onnx', config='', input_size=input_shape)

# 加载人脸识别模型
faceRecognizer = cv2.FaceRecognizerSF_create(model='face_recognizer_fast.onnx', config='')

然后对图像进行人脸检测:

face1_detect = faceDetector.detect(image1)
face2_detect = faceDetector.detect(image2)

face1_detect返回的是一个二维的元组类型,第一纬是识别到的人脸个数,第二纬是一个二维的数组,表示的人脸坐标数据,每一个人脸坐标数据大小为15个数,其中包括:

  • 人脸XY坐标及宽度(4个数)
  • 右眼瞳孔XY坐标(2个数)
  • 左眼瞳孔XY坐标(2个数)
  • 鼻尖XY坐标(2个数)
  • 右嘴角XY坐标(2个数)
  • 左嘴角XY坐标(2个数)
  • 置信度(1个数,越接近1说明与人脸越像)

所以你可以这样做来看看是否找到了一张脸:

if face1_detect[1] is None or face2_detect[1] is None:
    print('------ 未发现人脸!')
    exit(0)

绘制检测到的人脸:

faces_detect = (face1_detect[1], face2_detect[1])
images = (image1, image2)

# 框出人脸并画出人脸的关键点
for i in range(len(images)):
    for face_index, face_coords in enumerate(faces_detect[i]):

        thickness = 2

        # 准确度
        accuracy = face_coords[-1]

        # 坐标转成int类型
        coords = face_coords[:-1].astype(np.int32)

        # 框出人脸
        cv2.rectangle(images[i], (coords[0], coords[1]), (coords[0] + coords[2], coords[1] + coords[3]), (0, 255, 0), thickness)

        # 画出左右瞳孔、左右嘴角、鼻尖的位置
        cv2.circle(images[i], (coords[4], coords[5]), 2, (255, 0, 0), thickness)
        cv2.circle(images[i], (coords[6], coords[7]), 2, (0, 0, 255), thickness)
        cv2.circle(images[i], (coords[8], coords[9]), 2, (0, 255, 0), thickness)
        cv2.circle(images[i], (coords[10], coords[11]), 2, (255, 0, 255), thickness)
        cv2.circle(images[i], (coords[12], coords[13]), 2, (0, 255, 255), thickness)

        # 显示准确度
        cv2.putText(images[i], 'The accuracy of: {:.2f}'.format(accuracy), (1, 16), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)

        # 显示图片
        cv2.imshow('image{:d}'.format(i), images[i])

接下来是人脸对齐:

# 人脸对齐,alignCrop返回的是人脸图像
face1_align = faceRecognizer.alignCrop(image1, face1_detect[1])
face2_align = faceRecognizer.alignCrop(image1, face2_detect[1])

然后提取128纬度的特征向量,用于下一步的人脸对比识别:

face1_feature = faceRecognizer.feature(face1_align)
face2_feature = faceRecognizer.feature(face2_align)

然后进行人脸比对识别,判断是否为同一人:

cosine_similarity_threshold = 0.363
l2_similarity_threshold = 1.128

# 人脸识别(余弦匹配方式)
cosine_score = faceRecognizer.match(face1_feature, face2_feature, cv2.FaceRecognizerSF_FR_COSINE)

# 人脸识别(L2匹配方式)
l2_score = faceRecognizer.match(face1_feature, face2_feature, cv2.FaceRecognizerSF_FR_NORM_L2)

msg = '不是同一个人'
if cosine_score >= cosine_similarity_threshold:
    msg = '是同一个人'
print('------ 两张人脸图像%s!余弦阈值:%0.3f,余弦值:%0.3f。(注:余弦值越高表示相似度越高,最大值为1.0)' % (msg, cosine_similarity_threshold, cosine_score))


msg = '不是同一个人'
if l2_score <= l2_similarity_threshold:
    msg = '是同一个人'
print('------ 两张人脸图像%s!L2距离:%0.3f,阈值:%0.3f。(注:L2距离越低表示相似度越高,最小值为0.0)' % (msg, l2_score, l2_similarity_threshold))

cv2.waitKey()

特地找了两张小李子的照片,一个年轻人,一个老人,用于人脸检测和识别。运行效果如下:
利用OpenCV和Python一百行代码快速实现人脸检测和人脸识别

可以看出人脸检测的结果非常准确,也能正确识别同一个人!

ends…

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2022年3月16日 下午5:49
下一篇 2022年3月16日 下午6:08

相关推荐