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

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



本章博客涉及代码和模型文件,关注以下公众号,回复关键字pycv人脸识别获取下载链接!

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官方例程:

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()

我特意找了小李子一个年轻时候和一个上了年纪的两张照片进行人脸检测和识别,运行效果如下:

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


ends…

  • 5
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

觉皇嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值