Python实现人脸识别功能

news2024/11/17 6:27:04

Python实现人脸识别功能

闲来没事,记录一下前几天学习的人脸识别小项目。

要想实现人脸识别,我们首先要搞明白,人脸识别主要分为哪些步骤?为了提高人脸识别的准确性,我们首先要把图像或视频中的人脸检测出来,然后使用分类网络,对检测到的人脸进行分类。

概括起来,主要包括:人脸检测人脸分类两个部分。

人脸检测

人脸检测部分我们直接使用现成的 MTCNN,它的模型结构如下图所示,主要由三个级联的简单网络组成。

首先将图像重新缩放为不同尺度的图像,然后第一个网络负责提出候选框,第二个网络对候选框进行过滤,留下更加精准的候选框,第三个网络进一步回归和过滤,输出预测的面部边界框和特征点位置。

在这里插入图片描述

下图是该网络的模型结构参数,可以发现该网络结构由简单的若干个卷积层组成,结构简单,运行十分快速,因此适用于在线的人脸识别。

在这里插入图片描述
这里代码也很简单,有现成的:

import cv2
from mtcnn_cv2 import MTCNN

# 加载模型(MTCNN)
mtcnn = MTCNN()

# 打开摄像头
cap = cv2.VideoCapture(0)

while True:
    # 读取一帧图像
    ret, img = cap.read()

    # 如果读取成功
    if ret:
        # 将图像转为RGB格式
        img_rgb = cv2.cvtColor(src=img, code=cv2.COLOR_BGR2RGB)

        # 人脸检测(检测图像中是否存在人脸)
        faces = mtcnn.detect_faces(img=img_rgb)

人脸识别

在人脸识别部分,我们首先将想要识别的人脸图片存入文件夹,然后计算视频中检测到的人脸与文件夹内人脸的差异,根据阈值判断检测到的人脸是已知的,还是陌生人。

import cv2
from mtcnn_cv2 import MTCNN
from img_mark import mark_face
from img_mark import rec_face

# 加载模型(MTCNN)
mtcnn = MTCNN()

# 打开摄像头
cap = cv2.VideoCapture(0)

while True:
    # 读取一帧图像
    ret, img = cap.read()

    # 如果读取成功
    if ret:
        # 将图像转为RGB格式
        img_rgb = cv2.cvtColor(src=img, code=cv2.COLOR_BGR2RGB)

        # 人脸检测(检测图像中是否存在人脸)
        faces = mtcnn.detect_faces(img=img_rgb)

        if faces:
            # 人脸标注(box, landmark)
            mark_face(img=img, faces=faces)

            # 人脸识别(识别身份)
            rec_face(img=img, faces=faces)

        # 显示图像
        cv2.imshow(winname="love", mat=img)
        cv2.waitKey(delay=1)

    else:
        # 读取失败,退出循环
        break

# 释放资源
cap.release()
cv2.destroyAllWindows()

还有一个 img_mark.py 文件定义了人脸识别的功能部分。

from torchvision import transforms
from PIL import Image
import numpy as np
import os
import cv2
from res_facenet.models import model_921

# 加载模型(FaceNet)
model921 = model_921()


def reg_faces(root="../faces"):
    """
    使用 FaceNet 录入人脸
    :param root: 存储的人脸仓库
    :return:
    """
    # 定义空字典,存放录入的人脸
    faces = {}
    # 预处理
    preprocess = [transforms.Resize(224),
                  transforms.CenterCrop(224),
                  transforms.ToTensor(),
                  transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                       std=[0.229, 0.224, 0.225])]
    trans = transforms.Compose(preprocess)

    # 读取带录入的人脸
    for file in os.listdir(root):
        if file.endswith(".jpg"):
            # 拼接完整路径
            file_path = os.path.join(root, file)
            # 读取图像内容并预处理
            img = trans(Image.open(file_path)).unsqueeze(0)
            # 使用FaceNet模型,将人脸变成128维向量
            embed = model921(img)
            # 将录入的脸存储在字典中
            faces[file.split(".")[0]] = embed.detach().numpy()[0]

    return faces


def embed_faces(img=None):
    """
    将人脸图像变成一个向量
    """

    preprocess = [transforms.Resize(224),
                  transforms.CenterCrop(224),
                  transforms.ToTensor(),
                  transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                       std=[0.229, 0.224, 0.225])]
    trans = transforms.Compose(preprocess)
    img = trans(Image.fromarray(obj=img)).unsqueeze(0)
    embed = model921(img).detach().numpy()[0]

    return embed


def get_dist(face, faces):
    """
       求解欧氏距离
    :param face: 预测的结果
    :param faces: 库中的结果
    :return:
    """
    result = []
    for n, f in faces.items():
        result.append((n, np.sqrt(((f - face) ** 2).sum())))
    result.sort(key=lambda ele: ele[1])

    return result

# 获取人脸库
face_db = reg_faces()


def mark_face(img=None, faces=None):
    for face in faces:
        x, y, w, h = face["box"]
        confidence = face["confidence"]
        keypoints = face["keypoints"]

        if confidence > 0.9:
            cv2.rectangle(img=img, pt1=(x, y), pt2=((x+w), (y+h)), color=(0, 0, 200))
            # 左眼
            cv2.circle(img=img, center=keypoints["left_eye"], radius=2, color=(200, 0, 0))
            # 右眼
            cv2.circle(img=img, center=keypoints["right_eye"], radius=2, color=(200, 0, 0))
            # 鼻子
            cv2.circle(img=img, center=keypoints["nose"], radius=2, color=(200, 0, 0))
            # 左嘴角
            cv2.circle(img=img, center=keypoints["mouth_left"], radius=2, color=(200, 0, 0))
            # 右嘴角
            cv2.circle(img=img, center=keypoints["mouth_right"], radius=2, color=(200, 0, 0))


def rec_face(img, faces):
    """
       人脸识别
    :param img:
    :param faces:
    :return:
    """
    # 将图像转为RGB格式
    img_rgb = cv2.cvtColor(src=img, code=cv2.COLOR_BGR2RGB)

    for face in faces:
        x, y, w, h = face["box"]
        confidence = face["confidence"]
        # 通过置信度,过滤部分人脸
        if confidence > 0.9:
            # 截取人脸
            data = img_rgb[y:y+h, x:x+w, :]
            # 嵌入向量
            vec = embed_faces(img=data)
            # 计算距离
            result = get_dist(vec, face_db)
            # 求最短距离
            name, distance = result[0]
            print(distance)
            # 超过距离的阈值,则认为是陌生人
            if distance > 1.5:
                name = "Stranger"
            # 将名字打印到图像中
            cv2.putText(img=img, text=name, org=(x, y+h+30), color=(0, 200, 0),
                        fontFace=cv2.FONT_HERSHEY_SIMPLEX,
                        fontScale=1)

放张简单的效果图。

在这里插入图片描述

完整的代码文件见百度网盘:链接:https://pan.baidu.com/s/15q69SjVFEhfJ9WpgWSyhbg
提取码:pymx

日常学习记录,一起交流讨论吧!侵权联系~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/789469.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux入门 系统编程三 嵌入式开发 使用gcc制作静态库动态库,及调用库头文件应用

一、静态库的制作与使用 生成静态的主要是有5个步骤 1、编写源代码 2、将要编译成库的源文件编译成.o文件 3、使用ar命令创建静态库 4、调用库 5、测试 静态库的命名规则:lib开头。.a结尾。lib和.a中间的称作库名。lib库名称作库文件名 1.1 先写两个测试程序&…

《论文阅读》具有特殊Token和轮级注意力的层级对话理解 ICLR 2023

《论文阅读》具有特殊Token和轮级注意力的层级对话理解 前言简介问题定义模型构建知识点Intra-turn ModelingInter-turn Modeling分类前言 你是否也对于理解论文存在困惑? 你是否也像我之前搜索论文解读,得到只是中文翻译的解读后感到失望? 小白如何从零读懂论文?和我一…

用OpenCV图像处理技巧之巧用直方图

1. 引言 欢迎回到我的Python图像处理系列!在这一节中,我们将更深入地研究图像分析领域中图像直方图的应用,事实上通过对直方图进行相应操作,我们可以来调整图像的对比度和亮度,这可以极大地改善图像的视觉效果。 闲话…

vue脚手架文件说明

vue脚手架文件说明 1、文件介绍2、脚手架里面主要文件和作用 1、文件介绍 2、脚手架里面主要文件和作用 node_modules 都是下载的第三方包public/index.html 浏览器运行的网页src/main.js webpack打包的入口src/APP.vue Vue页面入口package.json 依赖包列表文件

Tangible Software Solutions Crack

Tangible Software Solutions Crack 有形软件解决方案-最准确可靠的源代码转换器,在VB.NET、C#、Java、C和Python之间进行转换,同时节省了无数小时的艰苦工作和宝贵的时间。 主要优点: 节省宝贵时间 准确全面 安全-您的代码永远不会离开您的机…

阿里云容器镜像仓库(ACR)的创建和使用

天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…

(一)RabbitMQ概念-优势、劣势、应用场景 、AMQP、工作原理

Lison <dreamlison163.com>, v1.0.0, 2023.06.22 RabbitMQ概念-优势、劣势、应用场景 、AMQP、工作原理 文章目录 RabbitMQ概念-优势、劣势、应用场景 、AMQP、工作原理RabbitMQ概念RabbitMQ的优势RabbitMQ劣势RabbitMQ应用的场景RabbitMQ_AMQPRabbitMQ工作原理 RabbitM…

如何在3ds max中创建可用于真人场景的巨型机器人:第 1部分

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. 创建主体 步骤 1 打开 3ds Max。 打开 3ds Max 步骤 2 在左侧视口中&#xff0c;按键盘上的 Alt-B 键。它 打开视口配置窗口。 打开“锁定缩放/平移”和“匹配位图”选项。单击“文件”并转到参考 …

从Vue2到Vue3【五】——新的组件(Fragment、Teleport、Suspense)

系列文章目录 内容链接从Vue2到Vue3【零】Vue3简介从Vue2到Vue3【一】Composition API&#xff08;第一章&#xff09;从Vue2到Vue3【二】Composition API&#xff08;第二章&#xff09;从Vue2到Vue3【三】Composition API&#xff08;第三章&#xff09;从Vue2到Vue3【四】C…

STM32CUBUMX配置FLASH(W25Q128)--保姆级教程

———————————————————————————————————— ⏩ 大家好哇&#xff01;我是小光&#xff0c;嵌入式爱好者&#xff0c;一个想要成为系统架构师的大三学生。 ⏩最近在开发一个STM32H723ZGT6的板子&#xff0c;使用STM32CUBEMX做了很多驱动&#x…

服务网格技术对比:深入比较Istio、Linkerd和Envoy等服务网格解决方案的优缺点

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

Github上方导航栏介绍

Code Watch&#xff1a;相当于关注&#xff0c;到时候这个项目又有什么操作&#xff0c;就会以通知的形式提醒你。 Fork&#xff1a;也就是把这个项目拉到你的仓库里&#xff0c;之后你可以对该代码进行修改&#xff0c;之后你可以发起Pull Request&#xff0c;简称PR&#xf…

SpringBoot集成kafka全面实战

本文是SpringBootKafka的实战讲解&#xff0c;如果对kafka的架构原理还不了解的读者&#xff0c;建议先看一下《大白话kafka架构原理》、《秒懂kafka HA&#xff08;高可用&#xff09;》两篇文章。 一、生产者实践 普通生产者 带回调的生产者 自定义分区器 kafka事务提交…

Windows下基于VSCode搭建C++开发环境(包含整合MinGW64、CMake的详细流程)

最近想写写C&#xff0c;装了VisualStudio 2022&#xff0c;折腾半天。对于一个用惯VSCode的人来说&#xff0c;总感觉IDE太笨重。于是自己网上各种查资料&#xff0c;自己琢磨&#xff0c;搭建了一套Windows下基于VSCode和CMake的C轻量级开发环境。 具体搭建步骤 1. 下载并安…

golang 冒号等于号 := 的注意事项和全局和局部变量的使用

全局变量错误用法&#xff1a; 全局变量正确用法&#xff1a;

ChatGPT应用探索:自动文本生成的无限可能

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

基于一致性引导的元学习bootstraping半监督医学图像分割

文章目录 Consistency-guided Meta-Learning for Bootstrapping Semi-Supervised Medical Image Segmentation摘要本文方法实验结果 Consistency-guided Meta-Learning for Bootstrapping Semi-Supervised Medical Image Segmentation 摘要 医学成像取得了显著的进步&#xf…

3.Java面试题—JVM基础、内存管理、垃圾回收

七、JVM 一、JVM 基础 一篇文章掌握整个JVM&#xff0c;JVM超详细解析&#xff01;&#xff01;&#xff01; 什么是Java虚拟机? Java虚拟机(JVM) 是用来 解析和运行Java程序 的一种 虚拟机。编译器 将 Java ⽂件 编译成 平台无关 的 Java 字节码文件 (.class)&#xff0c;…

嵌入式:QT Day1

一、手动实现登录框 源码&#xff1a; widge.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QDebug> //用于打印输出 #include <QIcon> //图标头文件 #include <QPushButton> //按钮类头文件 #includ…

Hadoop 之 Spark 配置与使用(五)

Hadoop 之 Spark 配置与使用 一.Spark 配置1.Spark 下载2.单机测试环境配置3.集群配置 二.Java 访问 Spark1.Pom 依赖2.测试代码1.计算 π 三.Spark 配置 Hadoop1.配置 Hadoop2.测试代码1.统计字符数 一.Spark 配置 环境说明环境版本AnolisAnolis OS release 8.6Jdkjava versi…