香橙派5(RK3588)使用npu加速yolov5推理的部署过程

香橙派5使用npu加速yolov5推理的部署过程

硬件环境

image-20241025093331088

部署过程

模型训练(x86主机)

在带nvidia显卡(最好)的主机上进行yolo的配置与训练, 获取最终的best.pt模型文件, 详见另一篇文档

模型转换(x86主机)

下载airockchip提供的yolov5(从pt到onnx)

一定要下这个版本的yolov5, 用于将pt模型转换成onnx模型, 这里的模型转换做了优化, 砍掉了最后一层, 只有这个onnx转换成rknn后, 可以正常推理

https://github.com/airockchip/yolov5.git
# 以下操作需要在虚拟环境中进行, 如果不是在虚拟环境 请先激活
cd yolov5
python3 export.py --rknpu --weight yolov5s.pt #请把这里的pt文件换成自己的文件
# 执行结束后, 应该会在当前目录下, 看到一个同名的 .onnx文件, 例如yolov5s.onnx

将该模型放到在线模型可视化网站, 检查模型的末端是否为下图类似的结构, 在sigmoid函数后直接就是输出, 而不是另一个检测层

image-20241025102804763

如果是下面这种, 说明转换的onnx模型有问题, 用的export.py应该不是瑞芯微的, yolo官方支持的转换模型, 在最后多了一层检测, 正常是没有下面红框里的内容的

image-20241025103004096

下载rknn-toolkit2(从onnx到rknn)
git clone https://github.com/airockchip/rknn-toolkit2.git
cd rknn-toolkit2/rknn-toolkit2/packages
# 需要确定是在虚拟环境下执行下面的指令, 如果不是在虚拟环境下, 请先使用下面的命令激活虚拟环境
# conda activate yolo
pip install -r requirements_cp38-2.2.0.txt #这里要对应python版本, 以及可能需要走清华镜像源, 否则很卡, 如果需要走镜像源, 请执行下面这段进行替代
# pip install -r requirements_cp38-2.2.0.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install rknn_toolkit2-2.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

如果有其他依赖不满足, 需要手动下载, 最后应该是这样的结果, 说明安装成功了

image-20241025101042639

下载rknn_model_zoo
git clone https://github.com/airockchip/rknn_model_zoo.git
cd rknn_model_zoo/examples/yolov5/python
# 需要确定是在虚拟环境下执行下面的指令, 如果不是在虚拟环境下, 请先使用下面的命令激活虚拟环境
# conda activate yolo
python convert.py ../model/yolov5s_relu.onnx rk3588 i8 ../model/yolov5s_relu.rknn # 注意将前面的onnx模型路径修改成上面best.pt转换成的best.onnx路径, 后面那个是输出的路径, 可以随便改

香橙派部署(arm64)

下载虚拟环境管理工具 miniforge3

安装过程与在amd64上安装anaconda类似, 可以一路敲回车, 输yes

wget https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-aarch64.sh
# 如果上一步卡很久, 可以考虑在自己电脑上挂梯子下好传过去, 或者走中转, 使用
# wget https://mirror.ghproxy.com/https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-aarch64.sh 进行偷渡
chmod +x Miniforge3-Linux-aarch64.sh
./Miniforge3-Linux-aarch64.sh
# 一路回车就好, 默认安装路径为 ~/miniforge3
使用miniforge3创建虚拟环境
source ~/miniforge3/bin/activate #有可能在安装过程中, 就已经把这一步写进了环境变量, 看是否有(base)前缀, 有的话就不需要执行这一步

image-20241025095818043

# 创建虚拟环境
conda create -n yolo python=3.8 #这里python版本可以指定不同的, 以3.8为例, -n 后面跟的是环境名
# 激活环境, 如果环境名不是yolo, 就把yolo这个名字换掉
conda activate yolo
安装rknn-toolkit-lite
git clone https://github.com/airockchip/rknn-toolkit2.git
# 以下命令需要在虚拟环境中进行
cd rknn-toolkit2/rknn-toolkit-lite2/packages
pip install rknn_toolkit_lite2-2.2.0-cp38-cp38-linux_aarch64.whl # 这一步可能会缺少相关依赖? 也许需要
# cd ../../rknn-toolkit2/packages
# pip install -r requirements_cp38-2.2.0.txt

测试推理(香橙派)

# 下载rknn_model_zoo
git clone https://github.com/airockchip/rknn_model_zoo.git
cd rknn_model_zoo/examples/yolov5/python
# 需要确定是在虚拟环境下执行下面的指令, 如果不是在虚拟环境下, 请先使用下面的命令激活虚拟环境
# conda activate yolo
修改香橙派自带的yolo代码

rknn-toolkit只支持amd64, 在香橙派上部署运行时需要arm架构的库, 即rknn-toolkit-lite, 因此相应的要修改该包的代码, 使用rknnlite进行推理

import os
import cv2
import sys
import argparse
import numpy as np
import platform
from rknnlite.api import RKNNLite# 添加路径
realpath = os.path.abspath(__file__)
_sep = os.path.sep
realpath = realpath.split(_sep)
sys.path.append(os.path.join(realpath[0]+_sep, *realpath[1:realpath.index('rknn_model_zoo')+1]))from py_utils.coco_utils import COCO_test_helperOBJ_THRESH = 0.25
NMS_THRESH = 0.45
IMG_SIZE = (640, 640)  # (width, height), 例如 (1280, 736), 需要和训练时的size匹配CLASSES = ("pallet",)  # 这里的类型需要匹配模型中检测的类型个数, 名称以及顺序, 否则会出现检测的是对的, 但是标签打错了的情况DEVICE_COMPATIBLE_NODE = '/proc/device-tree/compatible'def get_host():# 获取平台和设备类型system = platform.system()machine = platform.machine()os_machine = system + '-' + machineif os_machine == 'Linux-aarch64':try:with open(DEVICE_COMPATIBLE_NODE) as f:device_compatible_str = f.read()if 'rk3588' in device_compatible_str:host = 'RK3588'else:host = 'RK356x'except IOError:print('Read device node {} failed.'.format(DEVICE_COMPATIBLE_NODE))exit(-1)else:host = os_machinereturn hostdef filter_boxes(boxes, box_confidences, box_class_probs):box_confidences = box_confidences.reshape(-1)class_max_score = np.max(box_class_probs, axis=-1)classes = np.argmax(box_class_probs, axis=-1)_class_pos = np.where(class_max_score * box_confidences >= OBJ_THRESH)scores = (class_max_score * box_confidences)[_class_pos]boxes = boxes[_class_pos]classes = classes[_class_pos]return boxes, classes, scoresdef nms_boxes(boxes, scores):x = boxes[:, 0]y = boxes[:, 1]w = boxes[:, 2] - boxes[:, 0]h = boxes[:, 3] - boxes[:, 1]areas = w * horder = scores.argsort()[::-1]keep = []while order.size > 0:i = order[0]keep.append(i)xx1 = np.maximum(x[i], x[order[1:]])yy1 = np.maximum(y[i], y[order[1:]])xx2 = np.minimum(x[i] + w[i], x[order[1:]] + w[order[1:]])yy2 = np.minimum(y[i] + h[i], y[order[1:]] + h[order[1:]])w1 = np.maximum(0.0, xx2 - xx1 + 0.00001)h1 = np.maximum(0.0, yy2 - yy1 + 0.00001)inter = w1 * h1ovr = inter / (areas[i] + areas[order[1:]] - inter)inds = np.where(ovr <= NMS_THRESH)[0]order = order[inds + 1]keep = np.array(keep)return keepdef post_process(input_data, anchors):boxes, scores, classes_conf = [], [], []# 调试输出 - 查看 input_data 和 anchors 的形状for i in range(len(input_data)):print(f"Debug: input_data[{i}].shape = {input_data[i].shape}")print(f"Debug: anchors[{i}] = {anchors[i]}")# 调整 reshape 逻辑以匹配实际输入尺寸for i in range(len(input_data)):# 根据输出形状和锚点数调整 reshape 逻辑num_anchors = len(anchors[i])grid_h, grid_w = input_data[i].shape[-2], input_data[i].shape[-1]expected_channels = num_anchors * (5 + len(CLASSES))if input_data[i].shape[1] != expected_channels:print(f"Error: input_data[{i}] channels {input_data[i].shape[1]} does not match expected channels {expected_channels}")continue# Reshape to (num_anchors, 5 + num_classes, grid_h, grid_w)input_data[i] = input_data[i].reshape((num_anchors, 5 + len(CLASSES), grid_h, grid_w))boxes.append(box_process(input_data[i][:, :4, :, :], anchors[i]))scores.append(input_data[i][:, 4:5, :, :])classes_conf.append(input_data[i][:, 5:, :, :])def sp_flatten(_in):ch = _in.shape[1]_in = _in.transpose(0, 2, 3, 1)return _in.reshape(-1, ch)boxes = [sp_flatten(_v) for _v in boxes]classes_conf = [sp_flatten(_v) for _v in classes_conf]scores = [sp_flatten(_v) for _v in scores]boxes = np.concatenate(boxes) if boxes else np.array([])classes_conf = np.concatenate(classes_conf) if classes_conf else np.array([])scores = np.concatenate(scores) if scores else np.array([])if len(boxes) == 0 or len(classes_conf) == 0 or len(scores) == 0:return None, None, Noneboxes, classes, scores = filter_boxes(boxes, scores, classes_conf)nboxes, nclasses, nscores = [], [], []for c in set(classes):inds = np.where(classes == c)b = boxes[inds]c = classes[inds]s = scores[inds]keep = nms_boxes(b, s)if len(keep) != 0:nboxes.append(b[keep])nclasses.append(c[keep])nscores.append(s[keep])if not nclasses and not nscores:return None, None, Noneboxes = np.concatenate(nboxes)classes = np.concatenate(nclasses)scores = np.concatenate(nscores)return boxes, classes, scoresdef box_process(position, anchors):grid_h, grid_w = position.shape[2:4]anchors = np.array(anchors)num_anchors = len(anchors)anchors = anchors.reshape(num_anchors, 2, 1, 1)# 生成网格col, row = np.meshgrid(np.arange(0, grid_w), np.arange(0, grid_h))grid = np.stack((col, row), axis=0).astype(np.float32)grid = grid[np.newaxis, :, :, :]  # shape: (1, 2, grid_h, grid_w)# 位置解码box_xy = (position[:, :2, :, :] * 2.0 - 0.5 + grid) * (IMG_SIZE[0] / grid_w)box_wh = (position[:, 2:4, :, :] * 2.0) ** 2 * anchors# 将 [c_x, c_y, w, h] 转换为 [x1, y1, x2, y2]box = np.concatenate((box_xy - box_wh / 2.0, box_xy + box_wh / 2.0), axis=1)return boxdef draw(image, boxes, scores, classes):for box, score, cl in zip(boxes, scores, classes):left, top, right, bottom = [int(_b) for _b in box]print("%s @ (%d %d %d %d) %.3f" % (CLASSES[cl], left, top, right, bottom, score))cv2.rectangle(image, (left, top), (right, bottom), (255, 0, 0), 2)cv2.putText(image, '{0} {1:.2f}'.format(CLASSES[cl], score),(left, top - 6), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)def setup_model(args):# 根据设备类型选择模型if args.model_path:rknn_model = args.model_pathelse:rknn_model = 'pallet_detection.rknn'  # Replace with your model pathrknn_lite = RKNNLite()ret = rknn_lite.load_rknn(rknn_model)if ret != 0:print('Load RKNN model failed')exit(ret)print('done')return rknn_liteif __name__ == '__main__':parser = argparse.ArgumentParser(description='RKNNLite inference example')parser.add_argument('--model_path', type=str, required=False, help='model path, could be .rknn file')parser.add_argument('--target', type=str, required=False, default='rk3566', help='target RKNPU platform')parser.add_argument('--img_folder', type=str, default='../model', help='img folder path')parser.add_argument('--img_show', action='store_true', default=False, help='draw the result and show')parser.add_argument('--img_save', action='store_true', default=False, help='save the result')parser.add_argument('--coco_map_test', action='store_true', help='enable coco map test')args = parser.parse_args()# 初始化模型rknn_lite = setup_model(args)print('--> Init runtime environment')ret = rknn_lite.init_runtime()if ret != 0:print('Init runtime environment failed')exit(ret)print('done')# 加载图片file_list = sorted(os.listdir(args.img_folder))img_list = [f for f in file_list if f.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp'))]co_helper = COCO_test_helper(enable_letter_box=True)# 定义锚点(这里用的是yolo默认的锚点, 可以使用自定义训练后生成的)anchors = [[[10, 13], [16, 30], [33, 23]],     # 第一个尺度的锚点[[30, 61], [62, 45], [59, 119]],    # 第二个尺度的锚点[[116, 90], [156, 198], [373, 326]] # 第三个尺度的锚点]# 运行推理for i, img_name in enumerate(img_list):print('infer {}/{}'.format(i + 1, len(img_list)), end='\r')img_path = os.path.join(args.img_folder, img_name)img_src = cv2.imread(img_path)if img_src is None:continueimg = co_helper.letter_box(im=img_src.copy(), new_shape=(IMG_SIZE[1], IMG_SIZE[0]), pad_color=(0, 0, 0))img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)img = img[np.newaxis, ...]  # 增加批次维度以匹配4D输入要求# 推理outputs = rknn_lite.inference(inputs=[img])# 输出调试信息for idx, output in enumerate(outputs):print(f"Output[{idx}] shape: {output.shape}")boxes, classes, scores = post_process(outputs, anchors=anchors)if args.img_show or args.img_save:print('\n\nIMG: {}'.format(img_name))img_p = img_src.copy()if boxes is not None:draw(img_p, co_helper.get_real_box(boxes), scores, classes)if args.img_save:result_path = os.path.expanduser(f'~/result_{i+1}.jpg')cv2.imwrite(result_path, img_p)print('Detection result save to {}'.format(result_path))if args.img_show:cv2.imshow("full post process result", img_p)cv2.waitKeyEx(0)rknn_lite.release()
运行推理
# 以下命令需要在虚拟环境中进行, 当前应该在以下目录 rknn_model_zoo/examples/yolov5/python
python3 pallet_detect.py --model_path ~/new.rknn --img_folder images/ --img_save
# 修改model_path为新模型的实际目录
# 修改img_folder为实际要测试的图像集
# 如果需要保存图像, 则加上--img_save, 会将图片保存到当前路径下, 以result_*jpg为名

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sass软件登录设定——未来之窗行业应用跨平台架构

一、saas软件开发中登录设计 以为大公司为参考思迅在登录时候需要录入商户号 二、独立商户商户好处 1.每个店铺的账户是独立的&#xff0c;保护商户职员账户信息的相对安全。 2.不同店铺可以试用相同用户名

LDR6020:为VR串流线方案注入高效能与稳定性

随着虚拟现实&#xff08;VR&#xff09;技术的不断发展&#xff0c;VR设备已经成为连接用户与沉浸式体验的重要桥梁。而VR串流线&#xff0c;作为这一技术的重要组成部分&#xff0c;更是承担着传输高质量图像、音频及数据的重任。在这个过程中&#xff0c;一款功能强大、性能…

【计网】从零开始认识IP协议 --- 认识网络层,认识IP报头结构

从零开始认识IP协议 1 网络层协议1.1 初步认识IP协议1.2 初步理解IP地址 2 IP协议报头3 初步理解网段划分 1 网络层协议 1.1 初步认识IP协议 我们已经熟悉了传输层中的UDP和TCP协议&#xff0c;接下来我们来接触网络层的协议&#xff1a; 网络层在计算机网络中的意义主要体现…

寻找大自然的颜色

走在停停&#xff0c;停停走走&#xff0c;恍惚间一天过去了&#xff0c;转瞬间一年过去了&#xff0c;身边的一切在变化又不在变化&#xff0c;生活是自己的又不是自己的。 今天是个特殊的日子&#xff0c;其实前几天对我而言就算特殊的日子了&#xff0c;一个心里暗暗等待着却…

Maven项目管理工具-初始+环境配置

1. Maven的概念 1.1. 什么是Maven Maven是跨平台的项目管理工具。主要服务于基于Java平台的项目构建&#xff0c;依赖管理和项目信息管理。 理想的项目构建&#xff1a;高度自动化&#xff0c;跨平台&#xff0c;可重用的组件&#xff0c;标准化的流程 maven能够自动下载依…

python项目实战——多线程爬虫

多线程爬虫 文章目录 多线程爬虫概念并行并发Python多线程用途threading模块小知识----函数体内pass的用处1. **占位符**2. **控制结构**3. **定义接口**总结 代码解读单线程--串行多线程--并行查看当前程序的线程让主函数等待子线程结束&#xff0c;再运行---.join()join()方法…

C# 串口通信教程

串口通信&#xff08;Serial Communication&#xff09;是一种用于设备之间数据传输的常见方法&#xff0c;通常用于与外部硬件设备&#xff08;如传感器、机器人、微控制器&#xff09;进行通信。在 C# 中&#xff0c;System.IO.Ports 命名空间提供了与串口设备交互的功能&…

【Linux | 网络I/O模型】五种网络I/O模型详解

1、数据传输过程 在 Linux 系统中&#xff0c;数据传输是通过 I/O 操作来实现的。I/O 操作是指数据从应用程序到内核&#xff0c;再到硬件设备&#xff08;如磁盘、网络接口&#xff09;的过程。 操作系统为了保护自己&#xff0c;设计了用户态、内核态两个状态。应用程序一般工…

数据库的诗篇:深入探索 MySQL 表操作的艺术与哲学

文章目录 前言&#x1f338;一、创建表——搭建数据存储的基础框架1.1 基本语法1.2 创建表的实际案例解释&#xff1a; 1.3 表设计的最佳实践 &#x1f338;二、查看表结构——快速了解数据库设计2.1 使用 DESC 命令解释&#xff1a; 2.2 使用 SHOW COLUMNS 命令2.3 使用 SHOW …

Java线程安全

目录 一.引入 二.介绍 1.概念 2.产生的原因 三.修改操作不是原子性 1.分析问题 2.解决问题&#xff08;锁&#xff09; 四.可重入与不可重入 五.死锁 1.引入 2.死锁的三种情况 3.构成死锁的必要条件 六.内存可见性 1.引入 2.产生原因 3.解决问题 七.指令重排序…

让你的 IDEA 使用更流畅 | IDEA内存修改

随着idea使用越来越频繁&#xff0c;笔者最近发现使用过程中有时候会出现卡顿现象&#xff0c;例如&#xff0c;启动软件变慢&#xff0c;打开项目的速度变慢等&#xff1a; 因此如果各位朋友觉得最近也遇到了同样的困惑&#xff0c;不妨跟着笔者一起来设置IDEA的内存大小吧~ …

虚拟现实在制造业中的应用

当你想到制造业中的虚拟现实技术时&#xff0c;你脑海中闪过的第一个念头是什么&#xff1f;从目前来看&#xff0c;只需几年时间&#xff0c;制造业就将离不开虚拟现实技术的帮助。实施虚拟现实应用对制造业来说都有诸多好处。通常情况下&#xff0c;制造设施都是由各种机器组…

基于neo4j的学术论文关系管理系统

正在为毕业设计头疼&#xff1f;又或者在学术研究中总是找不到像样的工具来管理浩瀚的文献资料&#xff1f;今天给大家介绍一款超实用的工具——基于Neo4j的学术论文关系管理系统&#xff0c;让你轻松搞定学术文献的管理与展示&#xff01;&#x1f389; 系统的核心是什么呢&a…

一个基于.NET8+WPF开源的简单的工作流系统

项目介绍 AIStudio.Wpf.AClient 是一个基于 WPF (Windows Presentation Foundation) 构建的客户端框架&#xff0c;专为开发企业级应用而设计。该项目目前版本为 6.0&#xff0c;进行了全面优化和升级&#xff0c;提供了丰富的功能和模块&#xff0c;以满足不同场景下的开发需…

清华大学《2022年+2021年822自动控制原理真题》 (完整版)

本文内容&#xff0c;全部选自自动化考研联盟的&#xff1a;《清华大学822自控考研资料》的真题篇。后续会持续更新更多学校&#xff0c;更多年份的真题&#xff0c;记得关注哦~ 目录 2022年真题 2021年真题 Part1&#xff1a;2022年2021年完整版真题 2022年真题 2021年真题…

图层之间的加减法

如右图所示&#xff0c;正方形ABCD的边长为1cm&#xff0c;AC、BD分别是以点D和点C为圆心、1cm为半径作的圆弧。问阴影部分a的面积比阴影部分b小____? 这道题首先是固定的图形&#xff0c;形状已经确定了&#xff0c;按理说a和b的面积都可以求出来&#xff0c;但是题目问的是b…

ALIGN_ Tuning Multi-mode Token-level Prompt Alignment across Modalities

文章汇总 当前的问题 目前的工作集中于单模提示发现&#xff0c;即一种模态只有一个提示&#xff0c;这可能不足以代表一个类[17]。这个问题在多模态提示学习中更为严重&#xff0c;因为视觉和文本概念及其对齐都需要推断。此外&#xff0c;仅用全局特征来表示图像和标记是不…

颐驰06持续交付,明日科技赋能出行生活

在全球智能出行领域&#xff0c;自动驾驶技术的发展一直是行业关注的焦点。不久前&#xff0c;特斯拉发布的自动驾驶出租车引发了全球关注&#xff0c;但由于缺乏具体的技术细节&#xff0c;导致投资者信心受挫&#xff0c;特斯拉股票一度下跌近10%。与此同时&#xff0c;中国车…

springboot079信息化在线教学平台的设计与实现(论文+源码)_kaic

信息化在线教学平台的设计与实现 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了信息化在线教学平台的开发全过程。通过分析信息化在线教学平台管理的不足&#xff0c;创建了一个计算机管理信息化在线教学平台…

家政服务管理系统小程序ssm+论文源码调试讲解

第2章 开发环境与技术 基于微信小程序的家政服务管理系统的编码实现需要搭建一定的环境和使用相应的技术&#xff0c;接下来的内容就是对基于微信小程序的家政服务管理系统用到的技术和工具进行介绍。 2.1 MYSQL数据库 本课题所开发的应用程序在数据操作方面是不可预知的&…