实时语义分割网络 BiSeNet , RK1126 Npu 推理

news2024/11/28 12:48:00

在这里插入图片描述

记录下在rk1126上,实现 BiSeNet 网络推理.

https://github.com/CoinCheung/BiSeNet


ONNX

生成 onnx 模型

python tools/export_onnx.py --config configs/bisenetv2_city.py --weight-path ./checkpoints/model_final_v2_city.pth --outpath ./checkpoints/model_final_v2_city.onnx --no-onnxsim

转换 RKNN 模型

  1. 如果是自定义数据集,meanstd 参考自己数据集中的.
  2. datasets.txt 用于量化 ,datasets_ans 用于精度分析
  3. 量化类型使用: asymmetric_affine-u8
    from rknn.api import RKNN
     
    ONNX_MODEL = './model/model_final_v2_city.onnx'
    RKNN_MODEL = './model/model_final_v2_city_u8.rknn'
    
    QUANTIZE_ON = True
    _force_builtin_perm = False
    _acc_analysis_output_dir = './output_dir'
    _acc_analysis_dataset = './images/city/datasets_ans.txt'
    _qua_dataset = './images/city/datasets.txt'
    
    if __name__ == '__main__':
     
        # Create RKNN object
        rknn = RKNN(verbose=True)
     
        # pre-process config
        # asymmetric_affine-u8, dynamic_fixed_point-i8, dynamic_fixed_point-i16
        print('--> config model')
        rknn.config(
                    reorder_channel='0 1 2',
                    mean_values=[[83.0535, 94.095, 82.1865]],
                    std_values=[[53.856, 54.774, 75.786]],  
                    optimization_level=3,
                    target_platform = 'rv1126',
                    quantize_input_node= QUANTIZE_ON,
                    quantized_dtype='asymmetric_affine-u8',
                    batch_size=32,
                    output_optimize=1,
                    force_builtin_perm=_force_builtin_perm)               
        print('done')
     
        print('--> Loading model')
        # ret = rknn.load_onnx(model=ONNX_MODEL, outputs=['output0', 'output1'])
        ret = rknn.load_onnx(model=ONNX_MODEL, outputs=['preds'])
        if ret != 0:
            print('Load model failed!')
            exit(ret)
        print('done')
     
        # Build model
        print('--> Building model')
        ret = rknn.build(do_quantization=QUANTIZE_ON, dataset=_qua_dataset,pre_compile=True) 
        if ret != 0:
            print('Build pp_liteseg_stdc1_camvid_960x720_10k_model failed!')
            exit(ret)
        print('done')
     
        # Export rknn model
        print('--> Export RKNN model')
        ret = rknn.export_rknn(RKNN_MODEL)
        if ret != 0:
            print('Export  failed!')
            exit(ret)
        print('done')
        
        print('--> Accuracy analysis')
        ret = rknn.accuracy_analysis(inputs=_acc_analysis_dataset,output_dir=_acc_analysis_output_dir)
        if ret != 0:
            print('accuracy_analysis failed!')
            exit(ret)
        print('done')
     
        rknn.release()
    

NPU 推理

  1. 主要参考作者给的 ncnntensorrt demo 实现.
    #include <stdio.h>
    #include <stdint.h>
    #include <stdlib.h>
    #include <sys/time.h>
    #include <dirent.h>
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <queue>
    #include "rknn_api.h"
    #include "opencv2/opencv.hpp"
    #include "opencv2/core/core.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/highgui/highgui.hpp"
    #include <chrono>
    #include <iostream>
    #include <random>
    #include <algorithm>
    #include <stdio.h>
    #include <string>
    #include <vector>
    
    using namespace std;
    using namespace cv;
    
    void printRKNNTensor(rknn_tensor_attr *attr)
    {
        printf("index=%d name=%s n_dims=%d dims=[%d %d %d %d] n_elems=%d size=%d "
               "fmt=%d type=%d qnt_type=%d fl=%d zp=%d scale=%f\n",
               attr->index, attr->name, attr->n_dims, attr->dims[3], attr->dims[2],
               attr->dims[1], attr->dims[0], attr->n_elems, attr->size, 0, attr->type,
               attr->qnt_type, attr->fl, attr->zp, attr->scale);
    }
    
    vector<vector<uint8_t>> get_color_map()
    {
        vector<vector<uint8_t>> color_map(256, vector<uint8_t>(3));
        std::minstd_rand rand_eng(123);
        std::uniform_int_distribution<uint8_t> u(0, 255);
        for (int i{0}; i < 256; ++i)
        {
            for (int j{0}; j < 3; ++j)
            {
                color_map[i][j] = u(rand_eng);
            }
        }
        return color_map;
    }
    
    cv::Mat static_resize(cv::Mat &img, int INPUT_W, int INPUT_H)
    {
        float r = std::min(INPUT_W / (img.cols * 1.0), INPUT_H / (img.rows * 1.0));
        // r = std::min(r, 1.0f);
        int unpad_w = r * img.cols;
        int unpad_h = r * img.rows;
        cv::Mat re(unpad_h, unpad_w, CV_8UC3);
        cv::resize(img, re, re.size());
        cv::Mat out(INPUT_H, INPUT_W, CV_8UC3, cv::Scalar(114, 114, 114));
        re.copyTo(out(cv::Rect(0, 0, re.cols, re.rows)));
        return out;
    }
    
    int main(int argc, char *argv[])
    {
    
        std::string model_path = std::string(argv[1]);
        // std::string imagepath = std::string(argv[2]);
        std::string folder_path = std::string(argv[2]);
        int input_width_ = std::atoi(argv[3]);
        int input_height_ = std::atoi(argv[4]);
    
        std::vector<cv::String> file_names;
        cv::glob(folder_path, file_names);
    
        int oH{input_height_}, oW{input_width_}, n_classes{2};
    
        // Load model
        FILE *fp = fopen(model_path.c_str(), "rb");
        if (fp == NULL)
        {
            printf("fopen %s fail!\n", model_path);
            return -1;
        }
        fseek(fp, 0, SEEK_END);
        int model_len = ftell(fp);
        void *model = malloc(model_len);
        fseek(fp, 0, SEEK_SET);
        if (model_len != fread(model, 1, model_len, fp))
        {
            printf("fread %s fail!\n", model_path);
            free(model);
            return -1;
        }
    
        rknn_context ctx = 0;
    
        int ret = rknn_init(&ctx, model, model_len, 0);
        if (ret < 0)
        {
            printf("rknn_init fail! ret=%d\n", ret);
            return -1;
        }
    
        /* Query sdk version */
        rknn_sdk_version version;
        ret = rknn_query(ctx, RKNN_QUERY_SDK_VERSION, &version,
                         sizeof(rknn_sdk_version));
        if (ret < 0)
        {
            printf("rknn_init error ret=%d\n", ret);
            return -1;
        }
        printf("sdk version: %s driver version: %s\n", version.api_version,
               version.drv_version);
    
        /* Get input,output attr */
        rknn_input_output_num io_num;
        ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num));
        if (ret < 0)
        {
            printf("rknn_init error ret=%d\n", ret);
            return -1;
        }
        printf("model input num: %d, output num: %d\n", io_num.n_input,
               io_num.n_output);
    
        rknn_tensor_attr input_attrs[io_num.n_input];
        memset(input_attrs, 0, sizeof(input_attrs));
        for (int i = 0; i < io_num.n_input; i++)
        {
            input_attrs[i].index = i;
            ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]),
                             sizeof(rknn_tensor_attr));
            if (ret < 0)
            {
                printf("rknn_init error ret=%d\n", ret);
                return -1;
            }
            printRKNNTensor(&(input_attrs[i]));
        }
    
        rknn_tensor_attr output_attrs[io_num.n_output];
        memset(output_attrs, 0, sizeof(output_attrs));
        for (int i = 0; i < io_num.n_output; i++)
        {
            output_attrs[i].index = i;
            ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]),
                             sizeof(rknn_tensor_attr));
            printRKNNTensor(&(output_attrs[i]));
        }
    
        int input_channel = 3;
        int input_width = 0;
        int input_height = 0;
        if (input_attrs[0].fmt == RKNN_TENSOR_NCHW)
        {
            printf("model is NCHW input fmt\n");
            input_width = input_attrs[0].dims[0];
            input_height = input_attrs[0].dims[1];
            printf("input_width=%d input_height=%d\n", input_width, input_height);
        }
        else
        {
            printf("model is NHWC input fmt\n");
            input_width = input_attrs[0].dims[1];
            input_height = input_attrs[0].dims[2];
            printf("input_width=%d input_height=%d\n", input_width, input_height);
        }
    
        printf("model input height=%d, width=%d, channel=%d\n", input_height, input_width,
               input_channel);
    
        for (size_t i = 0; i < file_names.size(); i++)
        {
            cv::Mat im = cv::imread(file_names[i]);
            auto t1 = std::chrono::steady_clock::now();
            Mat pr_img;
            cv::resize(im, pr_img, cv::Size(oW, oH));
            cv::cvtColor(pr_img, pr_img, cv::COLOR_BGR2RGB);
            /* Init input tensor */
            rknn_input inputs[1];
            memset(inputs, 0, sizeof(inputs));
            inputs[0].index = 0;
            inputs[0].buf = pr_img.data;
            inputs[0].type = RKNN_TENSOR_UINT8;
            inputs[0].size = input_width * input_height * input_channel;
            inputs[0].fmt = RKNN_TENSOR_NHWC;
            inputs[0].pass_through = 0;
    
            /* Init output tensor */
            rknn_output outputs[io_num.n_output];
            memset(outputs, 0, sizeof(outputs));
            for (int i = 0; i < io_num.n_output; i++)
            {
                outputs[i].want_float = 1;
            }
            rknn_inputs_set(ctx, io_num.n_input, inputs);
            ret = rknn_run(ctx, NULL);
            if (ret < 0)
            {
                printf("ctx error ret=%d\n", ret);
                return -1;
            }
            ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL);
            if (ret < 0)
            {
                printf("outputs error ret=%d\n", ret);
                return -1;
            }
            vector<vector<uint8_t>> color_map = get_color_map();
            cv::Mat pred(cv::Size(oW, oH), CV_8UC3);
            int o_size = input_width * input_height * 4;
            float *prob = new float[o_size];
            memcpy(prob, (float *)outputs[0].buf, o_size);
            int idx{0};
            for (int i{0}; i < oH; ++i)
            {
                uint8_t *ptr = pred.ptr<uint8_t>(i);
                for (int j{0}; j < oW; ++j)
                {
                    ptr[0] = color_map[prob[idx]][0];
                    ptr[1] = color_map[prob[idx]][1];
                    ptr[2] = color_map[prob[idx]][2];
                    ptr += 3;
                    ++idx;
                }
            }
            // resize back and save
            cv::resize(pred, pred, im.size(), cv::INTER_CUBIC);
            cv::imwrite(cv::format("./out/%d.jpg", i), pred);
            ret = rknn_outputs_release(ctx, io_num.n_output, outputs);
            if (ret < 0)
            {
                printf("rknn_query fail! ret=%d\n", ret);
                goto Error;
            }
        }
    
    Error:
        if (ctx > 0)
            rknn_destroy(ctx);
        if (model)
            free(model);
        if (fp)
            fclose(fp);
        return 0;
    }
    
  2. 使用 adb 将程序拷贝到板载上调用
    ./bisenet_seg_npu_sample ./model/model_final_v2_city_u8.rknn ./images 1024 512

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

混合量化

  1. 如果感觉模型识别效果不是那么好,可以尝试这使用混合量化,找到一个速度兼精度的一个平衡点.

  2. hybrid_quantization_step1.py

    from rknn.api import RKNN
    
    ONNX_MODEL = './model/model_final_v2_city.onnx'
    RKNN_MODEL = './model/model_final_v2_city_u8.rknn'
    
    QUANTIZE_ON = True
    
    _qua_dataset = './images/city/datasets.txt'
    
    _force_builtin_perm = False
    
    if __name__ == '__main__':
    
        # Create RKNN object
        rknn = RKNN()
        
        # model config
        print('--> Config model')
        rknn.config(reorder_channel='0 1 2',
                    mean_values=[[83.0535, 94.095, 82.1865]],
                    std_values=[[53.856, 54.774, 75.786]], 
                    optimization_level=3,
                    target_platform='rk1126',
                    output_optimize=1,
                    quantized_dtype='asymmetric_affine-u8',
                    quantize_input_node= QUANTIZE_ON,  
                    batch_size=32,
                    force_builtin_perm=False
                )   
        print('done')
    
        # Load onnx model
        print('--> Loading model')
        ret = rknn.load_onnx(model=ONNX_MODEL)
        if ret != 0:
            print('Load model failed!')
            exit(ret)
        print('done')
    
        # Hybrid quantization step1
        print('--> hybrid_quantization_step1')
        ret = rknn.hybrid_quantization_step1(dataset=_qua_dataset)
        if ret != 0:
            print('hybrid_quantization_step1 failed!')
            exit(ret)
        print('done')
        print('==================================================================================================')
    
        rknn.release()
    
  3. hybrid_quantization_step2.py, 根据精度分析结果,在 torchjitexport.quantization.cfg 中 ,将误差较大的层,换成 floatdynamic_fixed_point-i16 等精度高的量化类型.

    from rknn.api import RKNN
    
    ONNX_MODEL = './model/model_final_v2_city.onnx'
    RKNN_MODEL = './model/model_final_v2_city_u8_hyqua.rknn'
    
    QUANTIZE_ON = True
    _force_builtin_perm = False
    
    _qua_dataset = './images/city/datasets.txt'
    
    if __name__ == '__main__':
    
        # Create RKNN object
        rknn = RKNN()
        
        # Set model config
        print('--> config model')
        rknn.config(reorder_channel='0 1 2',
                    mean_values=[[83.0535, 94.095, 82.1865]],
                    std_values=[[53.856, 54.774, 75.786]], 
                    optimization_level=3,
                    target_platform='rk1126',
                    output_optimize=1,
                    quantized_dtype='asymmetric_affine-u8',
                    quantize_input_node= QUANTIZE_ON,  
                    batch_size=32,
                    force_builtin_perm=False
                )   
        print('done')
    
        # Hybrid quantization step2
        print('--> hybrid_quantization_step2')
        ret = rknn.hybrid_quantization_step2(model_input='./torchjitexport.json',
                                             data_input='./torchjitexport.data',
                                             model_quantization_cfg='./torchjitexport.quantization.cfg',
                                             dataset=_qua_dataset, pre_compile=True)
        if ret != 0:
            print('hybrid_quantization_step2 failed!')
            exit(ret)
        print('done')
    
        # Export RKNN model
        print('--> Export RKNN model')
        ret = rknn.export_rknn(RKNN_MODEL)
        if ret != 0:
            print('Export RKNN model failed!')
            exit(ret)
        print('done')
    
        rknn.release()
    
    

END

  1. 以上差不多就是实现推理全部过程,有不对地方欢迎大佬们指正.

在这里插入图片描述

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

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

相关文章

每日一题(反转链表)

每日一题&#xff08;反转链表&#xff09; 206. 反转链表 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 可以定义一个新的newhead结构体指针。再定义cur指针和next指针互相配合&#xff0c;将原链表中的节点从头到尾依次头插到newhead链表中&#xff0c;同时更…

使用爬虫代码获得深度学习目标检测或者语义分割中的图片。

问题描述&#xff1a;目标检测或者图像分割需要大量的数据&#xff0c;如果手动从网上找的话会比较慢&#xff0c;这时候&#xff0c;我们可以从网上爬虫下来&#xff0c;然后自己筛选即可。 代码如下&#xff08;不要忘记安装代码依赖的库&#xff09;&#xff1a; # -*- co…

记一次特殊的HTTP 500.30

此错误比较常见&#xff0c;网上的解决方式各种各样&#xff0c;今天遇到的情况是&#xff0c;除过配置文件别的程序集都一样&#xff0c;程序部署端口不同&#xff0c;最后检查原因竟然是appsettings配置文件 key值的格式问题&#xff08;中英文字符或者空格导致&#xff0c;粘…

【两周学会FPGA】从0到1学习紫光同创FPGA开发|盘古PGL22G开发板学习之键控流水灯(三)

本原创教程由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处 适用于板卡型号&#xff1a; 紫光同创PGL22G开发平台&#xff08;盘古22K&#xff09; 一&#xff1a;盘古22K开发板&#xff08;紫光同创PGL22G开发…

Java8实战-总结17

Java8实战-总结17 引入流流操作中间操作终端操作使用流 小结 引入流 流操作 java.util.stream.Stream中的Stream接口定义了许多操作。它们可以分为两大类。再来看一下前面的例子&#xff1a; List<String> names menu.stream() //从菜单获得流 .filter(d -> d.get…

基于Java的OA办公管理系统,Spring Boot框架,vue技术,mysql数据库,前台+后台,完美运行,有一万一千字论文。

基于Java的OA办公管理系统&#xff0c;Spring Boot框架&#xff0c;vue技术&#xff0c;mysql数据库&#xff0c;前台后台&#xff0c;完美运行&#xff0c;有一万一千字论文。 系统中的功能模块主要是实现管理员和员工的管理&#xff1b; 管理员&#xff1a;个人中心、普通员工…

etcd读写请求的执行过程

etcd读请求如何执行 首先&#xff0c;etcdctl 会对命令中的参数进行解析。在解析完请求中的参数后&#xff0c;etcdctl 会创建一个 clientv3 库对象通过gRPC API来访问 etcd server。对应流程一。 然后通过负载均衡算法选择一个etcd server节点&#xff0c;然后调用 etcd ser…

Redis之管道解读

目录 基本介绍 使用例子 管道对比 管道与原生批量命令对比 管道与事务对比 使用pipeline注意事项 基准测试 基本介绍 Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务器。 这意味着请求通常按如下步骤处理&#xff1a; 客户端发送一个请求到服务器&am…

飞天使-python的模块与包与装饰器

文章目录 模块与包标准模块第三方模块自定义模块 高级语法切片迭代器/生成器高级模式&#xff08;闭包&#xff09;高级模式&#xff08;装饰器&#xff09; 参考视频 模块与包 标准模块 import os print(os.getcwd())import sys print(sys.argv) print(sys.platform) print(…

Three.js相机参数及Z-Fighting问题的解决方案

本主题讨论透视相机以及如何为远距离环境设置合适的视锥体。 推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 透视相机是一种投影模式&#xff0c;旨在模仿人类在现实世界中看待事物的方式。 这是渲染 3D 场景最常用的投影模式。 - three.js 如果你看一下 Three.js 文档…

十四、组合模式

一、什么是组合模式 组合&#xff08;Composite Pattern&#xff09;模式的定义&#xff1a;有时又叫作整体-部分&#xff08;Part-Whole&#xff09;模式&#xff0c;它是一种将对象组合成树状的层次结构的模式&#xff0c;用来表示“整体-部分”的关系&#xff0c;使用户对单…

极限五分钟,在宝塔中用 Docker 部署升讯威在线客服系统

最近客服系统成功经受住了客户现场组织的压力测试&#xff0c;获得了客户的认可。 客户组织多名客服上线后&#xff0c;所有员工同一时间打开访客页面疯狂不停的给在线客服发消息&#xff0c;系统稳定无异常无掉线&#xff0c;客服回复消息正常。消息实时到达无任何延迟。 本文…

IDEA maven上传速度很慢、解决办法

maven上传的速度很慢&#xff0c;排除网络原因&#xff0c;需要检查配置 一、项目配置 以下针对于maven仓库不在C盘的情况&#xff1a; File | Settings | Build, Execution, Deployment | Build Tools | Maven 以IDEA为例&#xff0c;打开 File&#xff08;文件&#xff09;…

【Vue3+Ts】项目启动准备和配置项目代码规范和css样式的重置

项目启动准备 创建项目&#xff08; 使用Vite 构建工具创建项目模板&#xff09;目录介绍插件安装创建别名编译说明项目配置配置icon和标题配置项目别名配置ts.config.json检测vscode的插件是否配置 配置项目代码规范集成editorconfig配置prettier工具库ESLint检测配置 CSS样式…

软件测试/测试开发丨Selenium 高级定位 Xpath

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/27036 一、xpath 基本概念 XPATH是一门在XML文档中查找信息的语言 XPATH使用路径表达式在XML文档中进行导航 XPATH的应用非常广泛&#xff0c;可以用于UI自…

使用Visual Studio 2022实现透明按钮和标签、POPUP样式窗体的一种工业系统的UI例程

例程实现的功能说明 1、主窗体采用POPUP样式&#xff0c;无标题栏、无菜单栏&#xff0c;适合工业类软件 2、按钮、标签使用自绘&#xff0c;实现透明样式&#xff0c;可以实现灵活的样式设计&#xff0c;更具设计感 按钮重绘函数&#xff1a;OnDrawItem()按钮样式设定&#…

微软 Turing Bletchley v3视觉语言模型更新:必应搜索图片更精准

据微软新闻稿透露&#xff0c;在推出第三代Turing Bletchley视觉语言模型后&#xff0c;微软计划逐步将其整合到Bing等相关产品中&#xff0c;以提供更出色的图像搜索体验。这款模型最初于2021年11月面世&#xff0c;并在2022年秋季开始邀请用户测试。 凭借用户的反馈和建议&am…

Spring Boot 中 Nacos 配置中心使用实战

官方参考文档 https://nacos.io/zh-cn/docs/quick-start-spring-boot.html 本人实践 1、新建一个spring boot项目 我的spirngboot版本为2.5.6 2、添加一下依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-…

FL studio21.1中文最新版FL萝卜音乐制作软件

FL studio21.1版中文名字叫做水果音乐编曲软件&#xff0c;是一款非常专业的电脑音乐制作软件。全新的21版本在功能上进行了升级&#xff0c;帮助用户来进行编曲、剪辑、录音、混音等多种工作&#xff0c;还可以为用户提供很多音乐创作的灵感&#xff0c;让你制作出各种好听的音…

postgresql-通用表表达式

postgresql-通用表表达式 简介简单 CTE递归 CTE案例1案例2 DML 语句与 CTE 简介 通用表表达式&#xff08;Common Table Expression、CTE&#xff09;是一个临时的查询结果或者临时表&#xff0c;可以 在其他 SELECT、INSERT、UPDATE 以及 DELETE 语句中使用。通用表表达式只在…