人脸识别速度超高识别度超高项目,可实时进行检测,一看就会!

news2024/11/17 8:17:35

1.本项目属于pytorch-facenet项目,核心代码是facenet算法,经过1周的代码修改,可以进行入库和识别的连续操作,经过测试,识别效果很好,在GPU环境中可以进行实时摄像头的识别,同时项目将放在百度网盘中供大家免费下载,技术无价,大家一起学习改进!
在这里插入图片描述
2.软件环境大家需要anaconda+pycharm+cuda10.0,这是我的GPU环境。python库包环境如下,大家根据下面的库包下载相对应的库,主要的两个库包是torch=1.2.0和torchvision==0.4.0。

numpy==1.16.2
opencv_python==3.4.8.29
Pillow==8.4.0
requests==2.27.1
setuptools==58.0.4
tensorflow==1.13.1
torch=1.2.0
torchvision==0.4.0
tqdm==4.62.3

3.主要项目结构如下,里面包含算法和模型放置在文件夹内,主要是以下目录结构中三个py文件讲解,分别是facenet_pytorch_ruku.py、facenet_pytorch_shibie_image.py、facenet_pytorch_shibie_video.py,第一个py文件是来进行人脸入库操作,会生成库模型以供接下来的操作,第二个py文件是来进行人脸图片识别操作,第三个py文件是来进行人脸视频识别操作。
在这里插入图片描述
4.facenet_pytorch_ruku.py文件中开始是需要输入你要入库的姓名,同时准备好一张人脸照片,然后输入人脸图片照片的地址,输入完成之后会自动将照片中的人脸截图入库保存,同时生成一个人脸模型。
在这里插入图片描述
5.facenet_pytorch_ruku.py完整代码如下

from PIL import ImageFont, ImageDraw
from facenet_pytorch import MTCNN, InceptionResnetV1
import torch
from torch.utils.data import DataLoader
from torchvision import datasets
import os


import cv2
a=input("请输入姓名:")
if not os.path.exists("database/orgin"+a):
    os.mkdir("database/orgin/"+a)
b=input("请输入你要入库的图片路径:")
res=cv2.imread(b)
cv2.imencode(".jpg",res)[1].tofile("database/orgin/"+a+"/"+"1.jpg")


workers = 0 if os.name == 'nt' else 4
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
print('Running on device: {}'.format(device))
mtcnn = MTCNN(
    image_size=160, margin=0, min_face_size=20,
    thresholds=[0.8, 0.8, 0.9], factor=0.709, post_process=True,
    device=device
)
# InceptionResnetV1提供了两个预训练模型,分别在vggface数据集和casia数据集上训练的。
# 预训练模型如果不手动下载,可能速度会很慢,可以从作者给的谷歌云链接下载,然后放到C:\Users\你的用户名\.cache\torch\checkpoints这个文件夹下面
# 如果是linux系统,那么存放在/home/你的用户名/.cache/torch/checkpoints下面
resnet = InceptionResnetV1(pretrained='vggface2').eval().to(device)


def collate_fn(x):
    return x[0]


# 将所有的单人照图片放在各自的文件夹中,文件夹名字就是人的名字,存放格式如下
'''
--orgin
  |--zhangsan
     |--1.jpg
     |--2.jpg
  |--lisi
     |--1.jpg
     |--2.jpg
'''
dataset = datasets.ImageFolder('./database/orgin')  # 加载数据库
dataset.idx_to_class = {i: c for c, i in dataset.class_to_idx.items()}
loader = DataLoader(dataset, collate_fn=collate_fn, num_workers=workers)
aligned = []  # aligned就是从图像上抠出的人脸,大小是之前定义的image_size=160
names = []
i = 1
for x, y in loader:
    path = './database/aligned/{}/'.format(dataset.idx_to_class[y])  # 这个是要保存的人脸路径
    print("1-1",path)
    if not os.path.exists(path):
        i = 1
        os.mkdir(path)
    # 如果要保存识别到的人脸,在save_path参数指明保存路径即可,不保存可以用None
    x_aligned, prob = mtcnn(x, return_prob=True, save_path=path + '/{}.jpg'.format(i))
    print("1-2", x_aligned,i)
    i = i + 1
    if x_aligned is not None:
        print('Face detected with probability: {:8f}'.format(prob))
        aligned.append(x_aligned)
        names.append(dataset.idx_to_class[y])

aligned = torch.stack(aligned).to(device)
embeddings = resnet(aligned).detach().cpu()  # 提取所有人脸的特征向量,每个向量的长度是512
# 两两之间计算混淆矩阵
dists = [[(e1 - e2).norm().item() for e2 in embeddings] for e1 in embeddings]
torch.save(embeddings, './database/database.pt')  # 当然也可以保存在一个文件
torch.save(names, './database/names.pt')

# mtcnn网络负责检测人脸
mtcnn = MTCNN(keep_all=True, device=device)
resnet = InceptionResnetV1(pretrained='vggface2').eval().to('cuda')

names = torch.load("./database/names.pt")
embeddings = torch.load("./database/database.pt").to('cuda')

6.facenet_pytorch_ruku.py文件代码运行展示效果
在这里插入图片描述
在这里插入图片描述

7.facenet_pytorch_shibie_image.py文件主要目的是将一张图片经过人脸模型的检测和识别,最后判断出姓名并且输出。
在这里插入图片描述
8.facenet_pytorch_shibie_image.py完整代码如下

import time
import cv2
from PIL import ImageFont, ImageDraw, Image
from facenet_pytorch import MTCNN, InceptionResnetV1
import torch
import os
import numpy
import time
t1=time.time()

workers = 0 if os.name == 'nt' else 4
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
print('Running on device: {}'.format(device))

# mtcnn网络负责检测人脸
mtcnn = MTCNN(keep_all=True, device=device)
resnet = InceptionResnetV1(pretrained='vggface2').eval().to('cuda')

names = torch.load("./database/names.pt")
embeddings = torch.load("./database/database.pt").to('cuda')


def cv2ImgAddText(img, text, a, b, textColor=(0, 255, 0), textSize=20):
    if (isinstance(img, numpy.ndarray)):
        img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    draw = ImageDraw.Draw(img)
    fontStyle = ImageFont.truetype("./font/msyhbd.ttc", textSize, encoding="utf-8")
    draw.text((a, b), text, textColor, font=fontStyle)
    return cv2.cvtColor(numpy.asarray(img), cv2.COLOR_RGB2BGR)


def detect_frame(img):
    faces = mtcnn(img)
    boxes, _ = mtcnn.detect(img)  # 检测出人脸框 返回的是位置
    if boxes is not None:
        for i, box in enumerate(boxes):
            face_embedding = resnet(faces[i].unsqueeze(0).to('cuda'))
            # 计算距离
            probs = [(face_embedding - embeddings[i]).norm().item() for i in range(embeddings.size()[0])]
            # 我们可以认为距离最近的那个就是最有可能的人,但也有可能出问题,数据库中可以存放一个人的多视角多姿态数据,对比的时候可以采用其他方法,如投票机制决定最后的识别人脸
            index = probs.index(min(probs))  # 对应的索引就是判断的人脸
            if probs[index] < 1:
                name = names[index]  # 对应的人脸
                # print(name)
            else:
                name = "未知人员"
            cv2.rectangle(img, (box[0], box[1]), (box[2], box[3]), (0, 0, 255), 2)
            img = cv2ImgAddText(img, name, box[0], box[1] - 100, (255, 0, 0), 80)
    return name


if __name__ == '__main__':
    frame1=cv2.imread("1.jpg")
    draw =detect_frame(frame1)
    print(draw)
    print(time.time()-t1)

9.facenet_pytorch_shibie_image.py运行效果展示
在这里插入图片描述
10.facenet_pytorch_shibie_video.py文件主要目的是将视频内的人脸经过人脸模型的检测和识别,最后判断出姓名并且输出在视频显示窗口中。
在这里插入图片描述
11.facenet_pytorch_shibie_video.py文件完整代码

#视频识别
import cv2
from PIL import ImageFont, ImageDraw, Image
from facenet_pytorch import MTCNN, InceptionResnetV1
import torch
import os
import numpy
import time
t1=time.time()

workers = 0 if os.name == 'nt' else 4
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
print('Running on device: {}'.format(device))

# mtcnn网络负责检测人脸
mtcnn = MTCNN(keep_all=True, device=device)
resnet = InceptionResnetV1(pretrained='vggface2').eval().to('cuda')

names = torch.load("./database/names.pt")
embeddings = torch.load("./database/database.pt").to('cuda')


def cv2ImgAddText(img, text, a, b, textColor=(0, 255, 0), textSize=20):
    if (isinstance(img, numpy.ndarray)):
        img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    draw = ImageDraw.Draw(img)
    fontStyle = ImageFont.truetype("./font/msyhbd.ttc", textSize, encoding="utf-8")
    draw.text((a, b), text, textColor, font=fontStyle)
    return cv2.cvtColor(numpy.asarray(img), cv2.COLOR_RGB2BGR)
def write_chinese(img,  content,position,font_type, font_size,color):
    # 图像从OpenCV格式转换成PIL格式
    img_PIL = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    # 字体  字体*.ttc的存放路径一般是: /usr/share/fonts/opentype/noto/ 查找指令locate *.ttc
    font = ImageFont.truetype(font_type, font_size)
    # 字体颜色
    # 文字输出位置
    # 输出内容
    draw = ImageDraw.Draw(img_PIL)
    draw.text(position, content, font=font, fill=color)
    # 转换回OpenCV格式
    img_OpenCV = cv2.cvtColor(numpy.asarray(img_PIL), cv2.COLOR_RGB2BGR)
    return img_OpenCV



def detect_frame(img):
    faces = mtcnn(img)
    boxes, _ = mtcnn.detect(img)  # 检测出人脸框 返回的是位置
    if boxes is not None:
        for i, box in enumerate(boxes):
            face_embedding = resnet(faces[i].unsqueeze(0).to('cuda'))
            # 计算距离
            probs = [(face_embedding - embeddings[i]).norm().item() for i in range(embeddings.size()[0])]
            # 我们可以认为距离最近的那个就是最有可能的人,但也有可能出问题,数据库中可以存放一个人的多视角多姿态数据,对比的时候可以采用其他方法,如投票机制决定最后的识别人脸
            index = probs.index(min(probs))  # 对应的索引就是判断的人脸
            if probs[index] < 1:
                name = names[index]  # 对应的人脸
                # print(name)
            else:
                name = "未知人员"
            cv2.rectangle(img, (box[0], box[1]), (box[2], box[3]), (0, 0, 255), 2)
            img = cv2ImgAddText(img, name, box[0], box[1] - 100, (255, 0, 0), 80)
            ket=(box[0], box[1])
            print((box[0], box[1]))
    return name,ket


if __name__ == '__main__':
    cap=cv2.VideoCapture("3.mp4")
    while (cap.isOpened()):
        ret, frame = cap.read()
        if ret==True:
            draw,ket = detect_frame(frame)
            # frame = cv2.putText(frame, (draw), (0, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
            frame = write_chinese(frame, (draw),ket,'font/simhei.ttf', 20, (255, 0, 255), )
            cv2.imshow('Video', frame)
            cv2.waitKey(1)
            if draw!="未知人员":
                print(draw)
        else:
            break

12.facenet_pytorch_shibie_video.py文件运行效果展示
在这里插入图片描述
在这里插入图片描述
13.完整项目如下,保存在百度网盘中,点击即可下载。
链接:https://pan.baidu.com/s/1pUkLD-PK_pBLBbP9kY0-3g
提取码:b075

14.运行成功的小伙伴麻烦一键三连,感谢感谢!!!

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

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

相关文章

知行之桥传输带附件的文件示例

在大多数的项目中&#xff0c;交易伙伴往往只要求传输报文消息&#xff0c;业务数据经由报文内容来进行传输。但有些交易伙伴也会要求传输带附件的文件&#xff0c;比如在与大众和延锋汽车YFAI对接的项目当中&#xff0c;交易伙伴要求传输VDA4951 ENGDAT报文&#xff0c;该业务…

vue3 销毁组件方法

问题描述&#xff1a;使用elementplus的dialog,当关闭弹窗后不刷新页面&#xff0c;直接再次打开发现弹窗中还存留上一次的数据。尝试定义关闭事件&#xff0c;或者使用api中提供的属性destroy-on-close 都不行。后来发现这是一个误区。弹窗关闭时并不代表这个组件已经被销毁了…

Linux测试主机之间连通性和端口是否开放的方法

文章目录测试主机之间的连通性测试端口是否开放(curl)测试端口是否开放(wget)测试端口是否开放(ssh)下面每一种测试方式都给出了成功通信的截图&#xff0c;如果与截图不相符可以根据你控制台的报错调试。测试主机之间的连通性 测试两个主机之间是否可以通信&#xff0c;通常使…

Odoo 16 企业版手册 - 库存管理之规则与路线

规则和路线 产品上定义的路线将帮助您理解和跟踪产品的每一次调拨。它是用于库存调拨的操作规则或路线。没有适当的策略&#xff0c;就很难监控和管理公司的库存变动。根据您的公司政策&#xff0c;您可以设置某些操作规则来定义库存中的产品调拨。使用这些规则&#xff0c;Odo…

何为 Vue3 组件标注 TS 类型,看这篇文章就够了!

文章目录前言一、为 props 标注类型使用 < script setup >非 < script setup >二、为 emits 标注类型使用 < script setup >非 < script setup >三、为 ref() 标注类型默认推导类型通过接口指定类型通过泛型指定类型四、为 reactive() 标注类型默认推导…

什么真无线蓝牙耳机值得入手?蓝牙耳机全方位挑选攻略

从我们的日常生活中可以看到&#xff0c;蓝牙耳机的使用频率真的是越来越高了&#xff0c;这主要得益于蓝牙耳机的使用便捷性以及近几年的快速发展。很多人在选择时不禁有些疑问&#xff0c;不知道哪款真无线蓝牙耳机值得入手&#xff1f; 都说买新不买旧&#xff0c;所以&…

黑马2022新版SSM框架教程(SpringMVC_day01)

SpringMVC_day01 文章目录SpringMVC_day011&#xff0c;SpringMVC简介1.1 SpringMVC概述2&#xff0c;SpringMVC入门案例2.1 需求分析2.2 案例制作步骤1:创建Maven项目&#xff0c;并导入对应的jar包步骤2:创建控制器类步骤3:创建配置类步骤4:创建Tomcat的Servlet容器配置类步骤…

网上流行短视频运营方法验证和试错,这些坑你踩过吗?

网上流行短视频运营方法验证和试错,这些坑你踩过吗&#xff1f; 人到中年&#xff0c;35岁以后找份工作不容易&#xff0c;这不刚刚有了一份短视频运营的工作。 在网上找了一些短视频运营技巧&#xff0c;看网上的评论有说有用的有说没用的。 只好自己去试一下错了&#xff…

升级win11后,此电脑中原来7个文件夹的恢复

目录前言问题描述解决方法新建一个.reg文件在.reg文件中添加代码执行.reg文件效果展示P.S. 添加部分文件夹参考文献链接前言 这个方法需要向注册表添加一些项。只需要新建一个.reg文件然后执行即可。 问题描述 更新win11后&#xff0c;以前的文件夹都消失不见了 解决方法 …

一文读懂JVM类加载机制过程及原理万字详解

JVM加载机制详解 文章目录JVM加载机制详解类装载子系统类加载子系统介绍类加载器ClassLoader角色类加载的执行过程加载链接初始化< cinit > 方法和 < init > 方法有什么区别&#xff1f;类加载器类加载器的作用类加载器分类启动类加载器扩展类加载器系统类加载器用…

STM32 TIM PWM高阶操作:刹车及状态约束

STM32 TIM PWM高阶操作&#xff1a;刹车及状态约束 刹车及状态约束是STM32 TIM PWM控制里面比较复杂的一部分&#xff0c;涉及到PWM波形产生前&#xff0c;中&#xff0c;后的管脚状态输出。 这里先引入两个描述&#xff0c;一个是“半高阻”&#xff0c;意思是STM32管脚输出…

我的基于 JamStack 的新博客

概述 今天心血来潮&#xff0c;介绍一下我的新博客站点 —— https://EWhisper.cn。 我是做基础平台 PaaS 运维和架构的&#xff0c;挺喜欢把工作中学到的新知识写下来、记笔记&#xff0c;突然有一天就抱着「资源共享、天下为公」的理念&#xff0c;分享我的学习心得&#x…

KDevelop详细Debug教程

KDevelop官方连接&#xff1a;https://www.kdevelop.org/ 感觉网上对KDevelop的使用介绍比较少&#xff0c;也没有一个完整的Debug教程&#xff0c;这里记录一下我的踩坑过程。当然首先你需要有一个Ubuntu系统&#xff0c;然后需要apt-get安装一下KDevelop。 首先CMakeLists.t…

基于springboot+mybatis+mysql+html实现宠物医院管理系统2(包含实训报告)

基于springbootmybatismysqlhtml实现宠物医院管理系统2&#xff08;包含实训报告&#xff09;一、需求背景二、系统简介二、系统主要功能界面1、用户登陆2、系统主页3、医生信息4、客户信息5、宠物信息6、浏览管理7、诊断管理8、医生管理9、用户管理三、其它系统四、获取源码一…

Dubbo相关概念

分布式系统中的相关概念 dubbo 概述 dubbo快速入门 dubbo的高级特性 2-相关概念 2.1-互联网项目架构-特点 互联网项目架构-特点 用户多 流量大&#xff0c;并发高 海量数据 易受攻击 功能繁琐 变更快 传统项目和互联网项目的不同 用户体验&#xff1a; 美观、功能…

【 Vue3 + Vite + setup语法糖 + Pinia + VueRouter + Element Plus 第四篇】(持续更新中)

在第三篇中&#xff0c;我们主要学习了组件的封装与使用以及 组件间传值和 Element Plus 表格、表单的用法 本期需要掌握的知识如下: mixin 公共方法封装和使用项目中导入 VueRouter使用 VueRouter 完成 路由跳转、获取路由信息VueRouter 模块化、路由拦截器权限路由配置 下期…

https 加密原理握手过程详解

HTTPS握手过程 HTTPS的握手过程比较繁琐&#xff0c;我们来回顾下。 先是建立TCP连接&#xff0c;毕竟HTTP是基于TCP的应用层协议。 在TCP成功建立完协议后&#xff0c;就可以开始进入HTTPS阶段。 HTTPS可以用TLS或者SSL啥的进行加密&#xff0c;下面我们以TLS1.2为例。 总…

自定义antd或element table 列设置组件(拖拽排序及控制是否展示)

需求 展示出所有的字段显示当前展示的是哪些字段可以全选、取消全选可以拖拽排序&#xff0c;更改字段的展示顺序&#xff0c;在前面还是在后面可以保存配置&#xff0c;刷新不失效 难点 如何进行拖拽排序&#xff0c;自己手写一个吗&#xff1f;如何得到拖拽后的顺序&#…

verilog学习笔记- 8)状态机

目录 概念&#xff1a; 状态机的模型&#xff1a; 状态机的设计&#xff1a; 根据状态机的实际写法&#xff0c;状态机可以分为一段式、二段式和三段式状态机。 三段式状态机的基本格式&#xff1a; 概念&#xff1a; 状态机&#xff0c;全称是有限状态机&#xff08;Fin…

再学C语言29:函数——概述

C的设计原则是把函数作为程序的构成模块 函数&#xff08;function&#xff09;&#xff1a;用于完成特定任务的程序代码的自包含单元 使用函数的好处&#xff1a; 1&#xff09;函数的使用可以省去重复代码的编写&#xff0c;尤其是程序中需要多次使用某种特定的功能时&…