人脸识别Adaface之libpytorch部署
目录
- 1. libpytorch下载
- 2. Adaface模型下载
- 3. 模型转换
- 4. c++推理
- 4.1 前处理
- 4.2 推理
- 4.3 编译运行
- 4.3.1 写CMakeLists.txt
- 4.3.2 编译
- 4.3.3 运行
1. libpytorch下载
参考:
https://blog.csdn.net/liang_baikai/article/details/127849577
下载完成后,将其解压到/usr/local下
2. Adaface模型下载
https://github.com/mk-minchul/AdaFace?tab=readme-ov-file

WebFace4M模型准确率最高,R50 WebFace4M和R100 WebFace12M的准确率十分接近,但耗时却低了不少,所以建议使用R50 WebFace4M
3. 模型转换
下载Adaface源码,并将下面代码放到其目录下执行即可
model_trans.py
import torch
import torch.nn as nn
from head import AdaFace
import net
import onnxruntime as ort
import numpy as np
import onnx# 加载模型
adaface_models = {
# 'ir_101':"./adaface_ir101_ms1mv2.ckpt",'ir_50':"./adaface_ir50_webface4m.ckpt",
}
architecture = 'ir_50'model = net.build_model(architecture)
#model = AdaFace()
statedict = torch.load(adaface_models[architecture],map_location=torch.device('cpu'),weights_only=True)['state_dict']
model_statedict = {key[6:]:val for key, val in statedict.items() if key.startswith('model.')}model.load_state_dict(model_statedict, strict=True)for p in model.parameters():p.requires_grad = Falsemodel.eval()
device = torch.device("cpu");
model_cpu = model.to(device)# 创建一个示例输入
example_input = torch.rand(1, 3, 112, 112) # 假设输入大小为 (1, 3, 112, 112)# 转换为 TorchScript
traced_model = torch.jit.trace(model_cpu, example_input)# 保存模型
traced_model.save('adaface.pt')# 导出为 ONNX 格式
#onnx_file_path = 'adaface.onnx' # 输出文件名
#torch.onnx.export(model, example_input, onnx_file_path,
# export_params=True)#opset_version=11, # ONNX 版本#do_constant_folding=True, # 是否进行常量折叠#input_names=['input'], # 输入名称#output_names=['output'], # 输出名称#dynamic_axes={'input': {0: 'batch_size'}, # 动态 batch size# 'output': {0: 'batch_size'}})
4. c++推理
4.1 前处理
- resize人脸图片为112x112
- 归一化
- BGR->RGB
- 转换为tensor
- N H W C->N C H W
- reshape 1,3,112,112(模型输入shape)
4.2 推理
- load model
- 读取图片
- 人脸检测对齐
- 前处理
- model.forward推理
#include <torch/script.h>
#include <iostream>
#include <memory>
#include <opencv2/opencv.hpp>torch::Tensor to_input(const cv::Mat& pil_rgb_image) {cv::Mat brg_img;cv::resize(pil_rgb_image, brg_img, cv::Size(112, 112));brg_img.convertTo(brg_img, CV_32FC3, 1.0 / 255.0);brg_img = (brg_img - 0.5) / 0.5;cv::cvtColor(brg_img, brg_img, cv::COLOR_BGR2RGB);torch::Tensor tensor = torch::from_blob(brg_img.data, {1, brg_img.rows, brg_img.cols, 3}, torch::kFloat32);tensor = tensor.permute({0, 3, 1, 2});tensor = tensor.reshape({1, 3, 112, 112});tensor = tensor.to(at::kCPU);return tensor;
}int main() {// 模型加载torch::jit::script::Module model;try {model = torch::jit::load("./adaface.pt");//model.eval();model.to(at::kCPU);} catch (const c10::Error& e) {std::cerr << "Error loading the model\n";return -1;}// 读取图片std::vector<std::string> images;getAllFiles("./images", images, {"jpg", "jpeg", "png"});// 人脸检测器初始化OpenCVFace open_cv_face;open_cv_face.Init("./models/face_detection_yunet_2023mar.onnx","./models/face_recognition_sface_2021dec.onnx", 0.9, 0.5);for (const auto &image_path : images){// Load an image using OpenCVcv::Mat orig_img = cv::imread(image_path);if (orig_img.empty()) {std::cerr << "Could not read the image\n";return -1;}auto detect_start = GetCurTimestamp();std::vector<cv::Mat> aligned_faces;// 人脸检测对齐open_cv_face.detectAndAlign(orig_img, aligned_faces);//std::cout<<"detect use time is "<< (GetCurTimestamp() - detect_start)<<std::endl;for (const auto &face:aligned_faces){cv::Mat img(face);auto img_tensor = to_input(img);// Inference 推理std::vector<torch::jit::IValue> inputs;inputs.push_back(img_tensor);auto output = model.forward(inputs);// Check if the output is a tupleif (output.isTuple()) {auto output_tuple = output.toTuple();if (output_tuple->elements().size() > 0) {at::Tensor output_tensor = output_tuple->elements()[0].toTensor();//std::cout << output_tensor << std::endl;} else {std::cerr << "Output tuple is empty\n";return -1;}} else {at::Tensor output_tensor = output.toTensor();//std::cout << output_tensor << std::endl;}}}return 0;
}
注意:本代码的人脸检测和对齐使用opencv的Yunet和SFace实现, 地址
4.3 编译运行
4.3.1 写CMakeLists.txt
本工程依赖opencv和libtorch,一并下载解压到/usr/local下即可。
cmake_minimum_required(VERSION 3.22.1)
project(adaface-demo)set(QMAKE_CXXFLAGS "-std=c++17")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)include_directories(/usr/local/include)
link_directories(/usr/local/lib)set(OPENCV_VERSION "4.9.0")
set(OPENCV_INSTALLATION_PATH "/usr/local/opencv4" CACHE PATH "Where to look for OpenCV installation")# Find OpenCV
find_package(OpenCV ${OPENCV_VERSION} REQUIRED HINTS ${OPENCV_INSTALLATION_PATH})if (AARCH64)set(Torch_DIR /usr/local/libtorch/lib/python3.10/site-packages/torch/share/cmake/Torch)
else ()set(Torch_DIR /usr/local/libtorch/share/cmake/Torch)
endif ()find_package(Torch REQUIRED)
include_directories(${TORCH_INCLUDE_DIRS})AUX_SOURCE_DIRECTORY(./src DIR_SRCS)
add_executable(adaface-demo ${DIR_SRCS})target_link_libraries(adaface-demo ${OpenCV_LIBS} ${TORCH_LIBRARIES})
4.3.2 编译
mkdir build
cd build
cmake ..
4.3.3 运行
将模型文件adaface.py拷贝到bin目录下
cd ../bin
./main
相关文章:
人脸识别Adaface之libpytorch部署
目录 1. libpytorch下载2. Adaface模型下载3. 模型转换4. c推理4.1 前处理4.2 推理4.3 编译运行4.3.1 写CMakeLists.txt4.3.2 编译4.3.3 运行 1. libpytorch下载 参考: https://blog.csdn.net/liang_baikai/article/details/127849577 下载完成后,将其解…...
vue3+echarts+websocket分时图与K线图实时推送
一、父组件代码: <template> <div class"chart-box" v-loading"loading"> <!-- tab导航栏 --> <div class"tab-box"> <div class"tab-list"> <div v-for"(item, index) in tabList…...
小程序开发实战项目:构建简易待办事项列表
随着移动互联网的飞速发展,小程序以其便捷性、即用即走的特点,成为了连接用户与服务的重要桥梁。无论是电商平台的购物助手,还是餐饮行业的点餐系统,小程序都在各个领域发挥着巨大的作用。 小程序开发基础 1. 小程序简介 小程序是…...
SD Express 卡漏洞导致笔记本电脑和游戏机遭受内存攻击
Positive Technologies 最近发布的一份报告揭示了一个名为 DaMAgeCard 的新漏洞,攻击者可以利用该漏洞利用 SD Express 内存卡直接访问系统内存。 该漏洞利用了 SD Express 中引入的直接内存访问 (DMA) 功能来加速数据传输速度,但也为对支持该标准的设备…...
前端node环境安装:nvm安装详细教程(安装nvm、node、npm、cnpm、yarn及环境变量配置)
需求:在做前端开发的时候,有的时候 这个项目需要 node 14 那个项目需要 node 16,我们也不能卸载 安装 。这岂不是很麻烦。这个时候 就需要 一个工具 来管理我们的 node 版本和 npm 版本。 下面就分享一个 nvm 工具 用来管理 node 版本。 这个…...
java之集合(详细-Map,Set,List)
1集合体系概述 1.1集合的概念 集合是一种容器,用来装数据的,类似于数组,但集合的大小可变,开发中也非常常用。 1.2集合分类 集合分为单列集合和多列集合 Collection代表单列集合,每个元素(数据ÿ…...
常见LeetCode-Saw200
用来记录需要知道见过的题型: LeetCode2-两数相加 说明:以链表的形势给了你每个位的数字,而且是逆序,直接从开头(个位)遍历相加。带上进位即可。有一个为空就直接计算另一个和进位。 LeetCode-3.无重复字符…...
Unity 制作一个视频播放器(打包后,可在外部编辑并放置新的视频)
效果展示: 在这里,我把视频名称(Json)和对应的视频资源都放在了StreamingAssets文件夹下,以便于打包后,客户还可以自己在外部增加、删除、修改对应的视频资料。 如有需要,请联细抠抠。...
MySQL-SQL语句
文章目录 一. SQL语句介绍二. SQL语句分类1. 数据定义语言:简称DDL(Data Definition Language)2. 数据操作语言:简称DML(Data Manipulation Language)3. 数据查询语言:简称DQL(Data Query Language)4. 数据控制语言:简称DCL(Data …...
腾讯微信大数据面试题及参考答案
DNS 协议是否使用 UDP? DNS(Domain Name System)协议主要使用 UDP(User Datagram Protocol),但也会使用 TCP(Transmission Control Protocol)。 UDP 是一种无连接的传输协议,它的特点是简单、高效。DNS 在进行域名解析时,大部分情况下使用 UDP。因为 UDP 的开销小,对…...
Python跳动的爱心
系列文章 序号直达链接表白系列1Python制作一个无法拒绝的表白界面2Python满屏飘字表白代码3Python无限弹窗满屏表白代码4Python李峋同款可写字版跳动的爱心5Python流星雨代码6Python漂浮爱心代码7Python爱心光波代码8Python普通的玫瑰花代码9Python炫酷的玫瑰花代码10Python多…...
计算机启动过程 | Linux 启动流程
注:本文为“计算机启动、 Linux 启动”相关文章合辑。 替换引文部分不清晰的图。 探索计算机的启动过程 Aleksandr Goncharov 2023/04/21 很多人对计算机的启动方式很感兴趣。只要设备开启,这就是魔法开始和持续的地方。在本文中,我们将概…...
反射简单介绍
反射就是从类里拿东西 有的人可能会想为什么不能用io流,从上往下一行一行的读也能获取类中的信息,为什么要用反射呢? 假如我们io流,从左到右一行一行的读取数据,如果碰到局部变量和成员变量同名,怎么区分&a…...
工具篇--GitHub Desktop 使用
文章目录 前言一、GitHub Desktop 的使用:1.1 通过官网下载GitHub Desktop和安装:1.2 安装和使用:1.2.1 填充自己的标识:1.2.3 克隆项目:1.2.4 git 常用忽略项配置: 二、代码的更新和提交:2.1 代…...
单臂路由配置
知识点 单臂路由指在路由器上的一个接口配置子接口(逻辑接口)来实现不同vlan间通信 路由器上的每个物理接口都可以配置多个子接口(逻辑接口) 公司的财务部、技术部和业务部有多台计算机,它们使用一台二层交换机进行互…...
河工oj第七周补题题解2024
A.GO LecturesⅠ—— Victory GO LecturesⅠ—— Victory - 问题 - 软件学院OJ 代码 统计 #include<bits/stdc.h> using namespace std;double b, w;int main() {for(int i 1; i < 19; i ) {for(int j 1; j < 19; j ) {char ch; cin >> ch;if(ch B) b …...
卷积的数学原理与作用
一、一维卷积 (一)定义 数学定义 给定一个输入序列 x [ x 1 , x 2 , ⋯ , x n ] x [x_1,x_2,\cdots,x_n] x[x1,x2,⋯,xn] 和一个卷积核(滤波器) k [ k 1 , k 2 , ⋯ , k m ] k [k_1,k_2,\cdots,k_m] k[k1,k2,⋯,…...
路由介绍.
RIB和FIB Routing Information Base(RIB),即路由信息库,是存储在路由器或联网计算机中的一个电子表格或类数据库,它保存着指向特定网络地址的路径信息,包括路径的路由度量值。RIB的主要目标是实现路由协议…...
CTFshow-命令执行(Web29-40)
CTFshow-命令执行(Web29-40) CTFWeb-命令执行漏洞过滤的绕过姿势_绕过空格过滤-CSDN博客 总结rce(远程代码执行各种sao姿势)绕过bypass_远程命令执行绕过-CSDN博客 对比两者的源代码,我们发现,cat指令把flag.php的内容导出后依…...
MySQL锁的类型有哪些
目录 共享锁(share lock): 排他锁(exclusivelock): 表锁(table lock): 行锁: 记录锁(Record lock): 页锁: 间隙锁: 基于锁的属性分类:共享锁,排他锁。 基于锁的粒…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
