Rust调用c++动态库实现Yolov8目标检测

1. 前言

上一篇博客留了一个坑,打算尝试用Rust代替Go来调用链接库试试效果。不过由于这次在家只有一个Mac无法使用TensorRT来加速推理,因此这次的推理框架选择的是MNN。本来想用TNN来着,不过居然编译一直有问题,所以果断转MNN。大致内容和流程和上一篇差不多,首先撸一套MNN的推理代码,然后编译成动态库;Rust调用这个动态库并写个简单的api测试一下。

2. 开始

2.1 C++部分

这次就直接跳过模型讲解(Yolov8基本都被讲烂了),直接用官方的export demo导出onnx。然后编译MNN,最好把转换工具和cv也一起编译了,有的时候MNN自带的cv还挺好用的。

将onnx转为mnn文件,MNNConvert -f ONNX --modelFile yolov8n.onnx --MNNModel yolov8n.mnn --fp16 --optimizePrefer 2,这里用fp16存储并且弄个加速优化,具体参数可以看官网介绍,MNN的文档写的还是挺详细的。

然后根据文档教程,用Session模式进行推理。需要注意的是,MNN的模型构建除了加载模型之外,还需要设置线程数,推理后端设置以及精度设置,这些在构造函数的时候设置一下就行,我这里直接利用参数配置初始化构造函数。

ini 复制代码
struct MNNDetConfigs
{
    std::string mnnPath;
    cv::Size inputSize{640,640};
    int classNum = 80 ;
    int threads = 4;
    int forwardType = MNN_FORWARD_CPU;
    float scoreThr = 0.25;
    float nmsThr = 0.5;
    std::array<float, 3> means = {0.0f, 0.0f, 0.0f};
    std::array<float, 3> norms = {1.0f, 1.0f, 1.0f};
};

这里的推理后端有很多种,不过我编译的在Mac上只有CPU、Metal和Auto是可以用的,分别对应0,1,4

前、后处理部分还是letterbox和nms,推理部分其实各个框架差不多,将输入输出设置好之后通过Session得到结果。

scss 复制代码
cv::Mat prImg;
preProcess(img,prImg);
interpreter_->resizeTensor(inputTensor_, {1, 3, inputH, inputW});
interpreter_->resizeSession(session_);
​
pretreat_->convert(prImg.data, inputW, inputH, prImg.step[0], inputTensor_);
interpreter_->runSession(session_);
​
MNN::Tensor* outputTensor = interpreter_->getSessionOutput(session_, NULL);
MNN::Tensor outputTensorHost(outputTensor, outputTensor->getDimensionType());
outputTensor->copyToHostTensor(&outputTensorHost);

大致C++上的推理部分就实现了,来看看效果

推理耗时大概在20ms左右,也没做啥对比实验不知道其他框架的性能如何,以后有空再测测其他的。

2.2 Rust调用

先看一下动态库的头文件定义

arduino 复制代码
//
// Created by shelgi on 2023/12/30.
//
#include <stdio.h>
#include <stdlib.h>
#ifndef YOLO_MNN_RUSTWRAPPER_H
#define YOLO_MNN_RUSTWRAPPER_H
​
#ifdef __cplusplus
extern "C"{
#endif
    extern const char* detect(void* model,char* base64Img);
    extern void* YOLO(const char* mnnPath,int classNums,float scoreThresh,float nmsThresh,int forwardType,int numThreads);
    extern void release(void* model);
​
#ifdef __cplusplus
};
#endif
#endif //YOLO_MNN_RUSTWRAPPER_H

和之前Go的那个基本一致,不过这里我把结果图片也转为base64作为结果传出来了。在C++动态库编译那里也可以隐藏一些不想被看到的函数,只传出这三个函数接口就行。

然后可以通过bindgen去根据头文件生成bindings,也可以自己写。不过第一次不太熟悉Rust对于C的类型定义,还是用工具生成吧。

bindgen rustwrapper.h -o bindings.rs

这样就生成了一个bindings.rs的文件,里面包含很多定义,直接滑到最下面找到这三个函数的定义,其他的可以删掉。

rust 复制代码
extern "C" {
    pub fn detect(
        model: *mut ::std::os::raw::c_void,
        base64Img: *mut ::std::os::raw::c_char,
    ) -> *mut *const ::std::os::raw::c_char;
}
extern "C" {
    pub fn YOLO(
        mnnPath: *const ::std::os::raw::c_char,
        classNums: ::std::os::raw::c_int,
        scoreThresh: f32,
        nmsThresh: f32,
        forwardType: ::std::os::raw::c_int,
        numThreads: ::std::os::raw::c_int,
    ) -> *mut ::std::os::raw::c_void;
}
extern "C" {
    pub fn release(model: *mut ::std::os::raw::c_void);
}

然后根据这个就可以开始写相关的功能函数了,比如图片转base64,json解析等;不过后续发现json解析没啥用,可以把结果字符串在前端直接展示,无非就是丑点😂。

这次Rust的后端部分,一开始想用axum不过一想既然都不了解就随便选吧。恰好看到有个评论推荐了salvo,那就看看文档直接拿来用(其实挺香的,国人开源必须支持 )。根据文件上传的案例直接魔改,用Tera渲染一下检测界面的模板。不得不说,Rust真的挺有意思的,几个陌生的框架上手会在编译期解决大部分问题,运行时确实很少出问题(昨晚一个C++导出char**在Rust调用的时候运行时二次释放除外)。经过一顿瞎操作,得到了一个勉强能用的玩意儿,效果如下

平均检测时间也就20ms左右,后期再去研究一下Rust相关的生态,看看有啥好用的框架。

结尾

这一篇虽说是填坑,不过确实内容很水(工作量不小,Rust里面就c_char转换成String第一次上手的时候都有点懵,但是感觉没啥好讲的)。本来服务方面想试试leptos,不过看了一下文档没看太明白(不过沙盒实时演示很好),加上这几天大部分时间都在医院,也就放弃这个想法,弄了个拿来即用的。等后续空闲一定会整理一下,弄个像样点的分享一下。不知不觉一年又过去马上快元旦了,祝大家元旦快乐!!!

相关推荐
老虎海子几秒前
从零入门 OpenAI Codex|登录、权限、终端、记忆配置全实操
人工智能·vscode·自然语言处理·chatgpt·个人开发·业界资讯
与芯同行几秒前
TP9243S与TP9311双芯片:AI语音产品从采集到回放的完整解决方案
人工智能
迷渡1 分钟前
用 Rust 重写的 Bun 有 13365 个 unsafe!
开发语言·后端·rust
若兰幽竹5 分钟前
【大模型应用】抖音爆款视频深度分析系统:流水线式AI逆向拆解流量密码,精准预测播放量!
人工智能·python·音视频·抖音爆款分析
AI技术控5 分钟前
NeuroH-TGL 论文解读:面向脑疾病诊断的神经异质性引导时序图学习方法
人工智能·语言模型·自然语言处理·langchain·nlp
fuquxiaoguang6 分钟前
微软Maia 200的“算力经济学”:推理时代的专用芯片如何改写游戏规则
人工智能·microsoft
AI_大白6 分钟前
DeepSeek Function Calling 接入实时行情:从工具定义到多轮查询的完整示例
后端·架构
心中有国也有家9 分钟前
pytorch-adapter:让 PyTorch 模型“无缝”跑在昇腾 NPU 上
人工智能·pytorch·笔记·python·学习
Sharewinfo_BJ10 分钟前
从手工报表到实时BI:一个零售数据平台的踩坑与重构实战
大数据·人工智能·科技·数据分析·微软·powerbi
Elastic 中国社区官方博客25 分钟前
在 Elasticsearch 中,存储向量查询速度最高提升 3 倍
大数据·人工智能·elasticsearch·搜索引擎·ai·全文检索