TVM insightface

2024-05-15 00:38
文章标签 insightface tvm

本文主要是介绍TVM insightface,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

https://github.com/markson14/Face-Recognition-Cpp 结合这个来看,初步看来后续可以做为公司的人脸开发base。

自从AI被炒作以来,各个深度学习框架层出不穷。我们通常来讲,作为AI从业者,我们通常经历着标注-训练-部署的过程。其中部署是较为痛苦的工作,尤其是在跨平台如(移动端需要native对接的时候。)当然用于inference框架同样也是层出不穷。但是大多数框架框架往往性能都一般,或者要手写相关op,或者就是转换模型较为麻烦。TVM的出现很大程度上为模型部署带来了福音。

但是网上将用于TVM部署的教程还比较少,尤其是通过cpp和移动端部署。本文以Insightface Model Zoo中的MobileFaceNet为例,介绍一下如何编译Mxnet模型、在python下inference、在cpp下inference、对比人脸余弦距离、以及在android下的部署。

安装

TVM编译环境的安装需要LLVM编译器,可以简要遵循官方的教程。 official installation tutorial.

LLVM 7.0 可能会导致编译错误,推荐使用LLVM 6.0.1

编译模型

TVM使用了一系列的优化措施来优化计算图,当模型编译完之后会生成若干个编译好的文件。在编译前要指定预编译的平台、架构、指令集等参数。

import numpy as np
import nnvm.compiler
import nnvm.testing
import tvm
from tvm.contrib import graph_runtime
import mxnet as mx
from mxnet import ndarray as ndprefix,epoch = "emore1",0
sym, arg_params, aux_params = mx.model.load_checkpoint(prefix, epoch)
image_size = (112, 112)
opt_level = 3shape_dict = {'data': (1, 3, *image_size)}
target = tvm.target.create("llvm -mcpu=haswell")
# "target" means your target platform you want to compile.#target = tvm.target.create("llvm -mcpu=broadwell")
nnvm_sym, nnvm_params = nnvm.frontend.from_mxnet(sym, arg_params, aux_params)
with nnvm.compiler.build_config(opt_level=opt_level):graph, lib, params = nnvm.compiler.build(nnvm_sym, target, shape_dict, params=nnvm_params)
lib.export_library("./deploy_lib.so")
print('lib export succeefully')
with open("./deploy_graph.json", "w") as fo:fo.write(graph.json())
with open("./deploy_param.params", "wb") as fo:fo.write(nnvm.compiler.save_param_dict(params))

运行该代码后会生成三个文件分别为deploy_lib.so 、deploy_graph.json 、deploy_param.params 。其中deploy_lib.so 为编译好的动态库,deploy_graph.json为部署使用的计算图、deploy_param.params为模型参数。

使用TVM Python Runtime 进行简单的测试

TVM的Runtime(运行时)并不需要任何依赖,直接clone tvm后 make runtime.即可。

import numpy as np
import nnvm.compiler
import nnvm.testing
import tvm
from tvm.contrib import graph_runtime
import mxnet as mx
from mxnet import ndarray as ndctx = tvm.cpu()
# load the module back.
loaded_json = open("./deploy_graph.json").read()
loaded_lib = tvm.module.load("./deploy_lib.so")
loaded_params = bytearray(open("./deploy_param.params", "rb").read())input_data = tvm.nd.array(np.random.uniform(size=data_shape).astype("float32"))module = graph_runtime.create(loaded_json, loaded_lib, ctx)
module.load_params(loaded_params)# Tiny benchmark test.
import time
for i in range(100):t0 = time.time()module.run(data=input_data)print(time.time() - t0)

使用C++来推理MobileFaceNet人脸识别模型

在C++下 TVM Runtime(运行时)仅仅需要编译时输出的so文件,包含 “tvm_runtime_pack.cc” 。runtime的体积也比较小,只有几百K。

下列的CPP代码包含了通过输入一张对齐后的人脸识别照片,输出归一化的之后的人脸向量。

#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <tvm/runtime/module.h>
#include <tvm/runtime/registry.h>
#include <tvm/runtime/packed_func.h>class FR_MFN_Deploy{private:void * handle;public:FR_MFN_Deploy(std::string modelFolder){tvm::runtime::Module mod_syslib = tvm::runtime::Module::LoadFromFile(modelFolder + "/deploy_lib.so");//load graphstd::ifstream json_in(modelFolder + "/deploy_graph.json");std::string json_data((std::istreambuf_iterator<char>(json_in)), std::istreambuf_iterator<char>());json_in.close();int device_type = kDLCPU;int device_id = 0;// get global function module for graph runtimetvm::runtime::Module mod = (*tvm::runtime::Registry::Get("tvm.graph_runtime.create"))(json_data, mod_syslib, device_type, device_id);this->handle = new tvm::runtime::Module(mod);//load paramstd::ifstream params_in(modelFolder + "/deploy_param.params", std::ios::binary);std::string params_data((std::istreambuf_iterator<char>(params_in)), std::istreambuf_iterator<char>());params_in.close();TVMByteArray params_arr;params_arr.data = params_data.c_str();params_arr.size = params_data.length();tvm::runtime::PackedFunc load_params = mod.GetFunction("load_params");load_params(params_arr);}cv::Mat forward(cv::Mat inputImageAligned){//mobilefacnet preprocess has been written in graph.cv::Mat tensor = cv::dnn::blobFromImage(inputImageAligned,1.0,cv::Size(112,112),cv::Scalar(0,0,0),true);//convert uint8 to float32 and convert to RGB via opencv dnn functionDLTensor* input;constexpr int dtype_code = kDLFloat;constexpr int dtype_bits = 32;constexpr int dtype_lanes = 1;constexpr int device_type = kDLCPU;constexpr int device_id = 0;constexpr int in_ndim = 4;const int64_t in_shape[in_ndim] = {1, 3, 112, 112};TVMArrayAlloc(in_shape, in_ndim, dtype_code, dtype_bits, dtype_lanes, device_type, device_id, &input);//TVMArrayCopyFromBytes(input,tensor.data,112*3*112*4);tvm::runtime::Module* mod = (tvm::runtime::Module*)handle;tvm::runtime::PackedFunc set_input = mod->GetFunction("set_input");set_input("data", input);tvm::runtime::PackedFunc run = mod->GetFunction("run");run();tvm::runtime::PackedFunc get_output = mod->GetFunction("get_output");tvm::runtime::NDArray res = get_output(0);cv::Mat vector(128,1,CV_32F);memcpy(vector.data,res->data,128*4);cv::Mat _l2;// normlize cv::multiply(vector,vector,_l2);float l2 =  cv::sqrt(cv::sum(_l2).val[0]);vector = vector / l2;TVMArrayFree(input);return vector;}};

我们可以通过输入两张对齐后的人脸照片来提取人脸向量。

cv::Mat A = cv::imread("/Users/jackyu/Desktop/align_id/aligned/20171231115821836_face.jpg");
cv::Mat B = cv::imread("/Users/jackyu/Desktop/align_id/aligned/20171231115821836_idcard.jpg");
FR_MFN_Deploy deploy("./models");
cv::Mat v2 = deploy.forward(B);
cv::Mat v1 = deploy.forward(A);

测量余弦相似度

inline float CosineDistance(const cv::Mat &v1,const cv::Mat &v2){return static_cast<float>(v1.dot(v2));
}
std::cout<<CosineDistance(v1,v2)<<std::endl;

简单的配置一个cmake文件

cmake_minimum_required(VERSION 3.6)
project(tvm_mobilefacenet)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -ldl -lpthread")
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY  ${CMAKE_CURRENT_SOURCE_DIR})
SET(HOME_TVM /Users/jackyu/downloads/tvm-0.5)
find_package(OPENCV REQUIRED)INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${HOME_TVM}/include)
INCLUDE_DIRECTORIES(${HOME_TVM}/3rdparty/dmlc-core/include)
INCLUDE_DIRECTORIES(${HOME_TVM}/3rdparty/dlpack/include)add_executable(tvm_mobilefacenet  tvm_runtime_pack.cc main.cpp)
target_link_libraries(tvm_mobilefacenet    ${OpenCV_LIBS})

 

这篇关于TVM insightface的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/990317

相关文章

【TVM 教程】在 Relay 中使用外部库

Apache TVM 是一个端到端的深度学习编译框架,适用于 CPU、GPU 和各种机器学习加速芯片。更多 TVM 中文文档可访问 → https://tvm.hyper.ai/ 作者:Masahiro Masuda,Truman Tian 本文介绍如何将 cuDNN 或 cuBLAS 等外部库与 Relay 一起使用。 Relay 内部用 TVM 来生成 target-specific 的

int8量化和tvm实现

量化主要有两种方案 直接训练量化模型如Deepcompression,Binary-Net,Tenary-Net,Dorefa-Net对训练好的float模型(以float32为例)直接进行量化(以int8为例),这边博客主要讲这个 参考NIVIDIA 量化官方文档 int8量化原理 将已有的float32型的数据改成A = scale_A * QA + bias_A,B类似,NVIDI

Insightface 之部署,TVM基础

参考文档 mxnet官方install手册TVM 0.4.0官方安装指导手册LLVM下载地址Debian/Ubuntu Linux下安装LLVM/Clang编译器 开发环境介绍 操作系统版本:Ubuntu16.04 LTS 64-bit,编译TVM的host、target版本;目标器件为Firefly-RK3399,采用双核Cortex-A72和四核Cortex-A53的大小核架构。MXNe

TVM LLVM 加速AI

下面为记录人工智能推理加速过程,基于TVM 总体脉络:     1. TVM 安装     2. TVM 测试及使用     3. Auto TVM 使用     4. 编译导出 so/dll     5.在C++中调用生成的so/dll 零、什么是TVM TVM是apache基金会开放的人工智能模型编译框架,由华人 陈天琦博士 初始开发。陈博士本科毕业于上海交大ACM班,有极深的计算

如果insightface/instantID安装失败怎么办(关于InsightFaceLoader_Zho节点的报错)

可能性有很多,但是今天帮朋友解决问题的时候又收集了一种新的思路。 首先,可以先按照这篇文章里边提到的方法去安装: 【全网最详细】ComfyUI下,Insightface安装指南-聚梦小课堂_insightface如何安装-CSDN博客 其次,如果安装了发现无效,并且报错,比如说这样: Error occurred when executing InsightFaceLoader_Zh

TVM Object类型系统

在TVM Object类型系统中最重要的是三个类:Object、ObjectPtr、ObjectRef 为什么需要这三个类? 设计目的:为了能够在不更改python前端的情况下扩展c++中的语言对象,且能够对任何语言对象序列化。 Object:编译器中所有的语言对象(命名一般以Node结尾)都是Object的子类,Object的子类保存了一般保存了数据成员变量ObjectPtr:Object

TVM踩坑记录

TVM踩坑记录 安装AirFace.onnx试验问题定位: 自动优化 安装 参照官网。 安装完成后安装官网quick-start-py跑一跑简单例子 import numpy as npfrom tvm import relayimport tvmfrom tvm.contrib import graph_runtimebatch_size = 1num_class

[笔记]TVM部署AirFace

使用TVM在Tx2 Arm上部署AirFace c++ 目录前言自动优化终端测试 目录 前言 不要问为什么Tx2要用Arm核,它只是开发方便,习惯把它作工业母机罢了。 自动优化 TVM一个设计亮点在于他可以在PC端通过RPC优化网络,这个大大加快了优化速度。 虽说PC端加速优化过程,但是在实际使用中发现优化速度还是很慢的,也是一个炼丹过程。而且极端依赖CPU性能,在TVM

关于TVM模型的Relay IR的Node遍历

TVM Relay Node类型与遍历方法 目的二、步骤1.遍历方法2.关于节点类型 总结 目的 关于TVM模型的Relay IR的Node遍历 二、步骤 1.遍历方法 代码如下(示例): import tvmfrom tvm import relayfrom tvm.contrib.debugger import debug_executorimport nu

tvm android_rpc_test.py执行报错解决

执行 python3 tests/android_rpc_test.py 报错: Run CPU test ... Traceback (most recent call last):   File "tests/android_rpc_test.py", line 129, in <module>     test_rpc_module()   File "tests/android_r