Orangepi 5 Pro(香橙派5pro)部署yolov5

news2024/12/25 13:07:06

前言

        香橙派内置了6T算力的NPU,想着可以跑一下yolov5,看看香橙派的速度如何。

        在开始部署之前,需要具备一定的linux技能——vim、linux常见指令、conda等等。如果没有这些技能的话,做下去会有一定的难度,可以先看几遍了解一下流程;也可以边学边部署。

香橙派环境

Orangepi5pro 1.0.4 ubuntu jammy desktop xfce linux6.1.43.7z

python=3.10.0

conda:Miniconda3-py310_23.11.0-2-Linux-x86_64.sh

参考文章香橙派5 RK3588 yolov5模型转换rknn及部署踩坑全记录 orangepi 5-CSDN博客


第一步——在PC端生成文件

 这一步是在PC端(笔记本或台式电脑)上实现的。

(1)、在电脑上使用WSL安装Ubuntu22.04系统并配置conda环境

可以在应用商城搜索WSL,点击安装

具体可以看这个视频:【WSL2】在你的win10/11电脑上安装Linux子系统+Ubuntu+图形化界面_哔哩哔哩_bilibili

conda环境可以看我的上一篇博客香橙派5pro(orangepi5pro)安装miniconda3_orange pi 5 pro install conda-CSDN博客

虽然是在PC端,但都是linux环境,上传.sh文件安装就行(上传过程自行百度)

(2)下载rknn-toolkit2源码

rockchip-linux/rknn-toolkit2 at v1.5.2 (github.com)icon-default.png?t=N7T8https://github.com/rockchip-linux/rknn-toolkit2/tree/v1.5.2

(3)一、在windows上

①下载yolov5源码以及yolov5s.pt

Release v6.0 - YOLOv5n 'Nano' models, Roboflow integration, TensorFlow export, OpenCV DNN support · ultralytics/yolov5 (github.com)icon-default.png?t=N7T8https://github.com/ultralytics/yolov5/releases/tag/v6.0

②将yolov5.pt转换成yolov5.onnx

按照官方文档操作,将class Detect(nn.Moudle)类的子函数forword更改

文件名字

 改为:

def forward(self, x):
        z = []  # inference output
        for i in range(self.nl):
            x[i] = self.m[i](x[i])  # conv

        return x

③然后,在yolov5目录下,打开终端输入命令

python export.py --weights yolov5n.pt --data data/coco128.yaml --include onnx --opset 12 --batch-size 1

注意注意!opset一定要为12,不然后面onnx转rknn会报错。weights自己选你训练完成的best.pt,data选你自己设置的,这里会生成一个.onnx文件

  二、在windows中的linux上

④onnx转化为rknn格式

进入用conda创建的虚拟环境中,假设叫yolo_py310,python=3.10.0

conda activate yolo_py310

假设你刚刚将rknn-toolkit2源码和yolov5源码上传到/root/Download/下面

这个rknn是rknn-toolkit2-1.5.2文件的重命名

在rknn/doc/,运行这个指令

pip install -r requirements_cp310-1.5.2.txt -i https://mirror.baidu.com/pypi/simple

进入/rknn/packages/中

pip install rknn_toolkit2-1.5.2+b642f30c-cp310-cp310-linux_x86_64.whl

中间会出现这个错误

具体看这个博客:Ubuntu 20.04安装RKNN-Toolkit2出现tf-estimator-nightly==2.8.0.dev2021122109找不到的问题_no matching distribution found for tf-estimator-ni-CSDN博客

这个上面这个博客的命令时需要科学上网!!!

        完成后,输入命令 python,输入以下代码如果不报错说明安装成功,使用键盘Ctrl+Z退出此模式。

from rknn.api import RKNN

        将(2)③中获得的.onnx文件放到rknn/examples/onnx/yolov5文件夹下,终端里进入该文件夹。用你喜欢的编辑器修改 test.py里面的一些内容

根据你的板子情况添加芯片型号

情况像下面的差不多就时成功了

此时会出现一个yolo5s.rknn的文件

⑤准备文件

1.创建一个名为deploy.py的文件

#deploy.py
import numpy as np
import cv2
from rknnlite.api import RKNNLite

RKNN_MODEL = 'yolov5n.rknn'

QUANTIZE_ON = True

OBJ_THRESH = 0.25
NMS_THRESH = 0.45
IMG_SIZE = 640

CLASSES = ("person", "bicycle", "car", "motorbike ", "aeroplane ", "bus ", "train", "truck ", "boat", "traffic light",
           "fire hydrant", "stop sign ", "parking meter", "bench", "bird", "cat", "dog ", "horse ", "sheep", "cow", "elephant",
           "bear", "zebra ", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball", "kite",
           "baseball bat", "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle", "wine glass", "cup", "fork", "knife ",
           "spoon", "bowl", "banana", "apple", "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza ", "donut", "cake", "chair", "sofa",
           "pottedplant", "bed", "diningtable", "toilet ", "tvmonitor", "laptop	", "mouse	", "remote ", "keyboard ", "cell phone", "microwave ",
           "oven ", "toaster", "sink", "refrigerator ", "book", "clock", "vase", "scissors ", "teddy bear ", "hair drier", "toothbrush ")


def sigmoid(x):
    return 1 / (1 + np.exp(-x))


def xywh2xyxy(x):
    # Convert [x, y, w, h] to [x1, y1, x2, y2]
    y = np.copy(x)
    y[:, 0] = x[:, 0] - x[:, 2] / 2  # top left x
    y[:, 1] = x[:, 1] - x[:, 3] / 2  # top left y
    y[:, 2] = x[:, 0] + x[:, 2] / 2  # bottom right x
    y[:, 3] = x[:, 1] + x[:, 3] / 2  # bottom right y
    return y


def process(input, mask, anchors):

    anchors = [anchors[i] for i in mask]
    grid_h, grid_w = map(int, input.shape[0:2])

    box_confidence = sigmoid(input[..., 4])
    box_confidence = np.expand_dims(box_confidence, axis=-1)

    box_class_probs = sigmoid(input[..., 5:])

    box_xy = sigmoid(input[..., :2])*2 - 0.5

    col = np.tile(np.arange(0, grid_w), grid_w).reshape(-1, grid_w)
    row = np.tile(np.arange(0, grid_h).reshape(-1, 1), grid_h)
    col = col.reshape(grid_h, grid_w, 1, 1).repeat(3, axis=-2)
    row = row.reshape(grid_h, grid_w, 1, 1).repeat(3, axis=-2)
    grid = np.concatenate((col, row), axis=-1)
    box_xy += grid
    box_xy *= int(IMG_SIZE/grid_h)

    box_wh = pow(sigmoid(input[..., 2:4])*2, 2)
    box_wh = box_wh * anchors

    box = np.concatenate((box_xy, box_wh), axis=-1)

    return box, box_confidence, box_class_probs


def filter_boxes(boxes, box_confidences, box_class_probs):
    """Filter boxes with box threshold. It's a bit different with origin yolov5 post process!

    # Arguments
        boxes: ndarray, boxes of objects.
        box_confidences: ndarray, confidences of objects.
        box_class_probs: ndarray, class_probs of objects.

    # Returns
        boxes: ndarray, filtered boxes.
        classes: ndarray, classes for boxes.
        scores: ndarray, scores for boxes.
    """
    boxes = boxes.reshape(-1, 4)
    box_confidences = box_confidences.reshape(-1)
    box_class_probs = box_class_probs.reshape(-1, box_class_probs.shape[-1])

    _box_pos = np.where(box_confidences >= OBJ_THRESH)
    boxes = boxes[_box_pos]
    box_confidences = box_confidences[_box_pos]
    box_class_probs = box_class_probs[_box_pos]

    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 >= OBJ_THRESH)

    boxes = boxes[_class_pos]
    classes = classes[_class_pos]
    scores = (class_max_score* box_confidences)[_class_pos]

    return boxes, classes, scores


def nms_boxes(boxes, scores):
    """Suppress non-maximal boxes.

    # Arguments
        boxes: ndarray, boxes of objects.
        scores: ndarray, scores of objects.

    # Returns
        keep: ndarray, index of effective boxes.
    """
    x = boxes[:, 0]
    y = boxes[:, 1]
    w = boxes[:, 2] - boxes[:, 0]
    h = boxes[:, 3] - boxes[:, 1]

    areas = w * h
    order = 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 * h1

        ovr = inter / (areas[i] + areas[order[1:]] - inter)
        inds = np.where(ovr <= NMS_THRESH)[0]
        order = order[inds + 1]
    keep = np.array(keep)
    return keep


def yolov5_post_process(input_data):
    masks = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
    anchors = [[10, 13], [16, 30], [33, 23], [30, 61], [62, 45],
               [59, 119], [116, 90], [156, 198], [373, 326]]

    boxes, classes, scores = [], [], []
    for input, mask in zip(input_data, masks):
        b, c, s = process(input, mask, anchors)
        b, c, s = filter_boxes(b, c, s)
        boxes.append(b)
        classes.append(c)
        scores.append(s)

    boxes = np.concatenate(boxes)
    boxes = xywh2xyxy(boxes)
    classes = np.concatenate(classes)
    scores = np.concatenate(scores)

    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)

        nboxes.append(b[keep])
        nclasses.append(c[keep])
        nscores.append(s[keep])

    if not nclasses and not nscores:
        return None, None, None

    boxes = np.concatenate(nboxes)
    classes = np.concatenate(nclasses)
    scores = np.concatenate(nscores)

    return boxes, classes, scores


def draw(image, boxes, scores, classes):
    """Draw the boxes on the image.

    # Argument:
        image: original image.
        boxes: ndarray, boxes of objects.
        classes: ndarray, classes of objects.
        scores: ndarray, scores of objects.
        all_classes: all classes name.
    """
    for box, score, cl in zip(boxes, scores, classes):
        top, left, right, bottom = box
        print('class: {}, score: {}'.format(CLASSES[cl], score))
        print('box coordinate left,top,right,down: [{}, {}, {}, {}]'.format(top, left, right, bottom))
        top = int(top)
        left = int(left)
        right = int(right)
        bottom = int(bottom)

        cv2.rectangle(image, (top, left), (right, bottom), (255, 0, 0), 2)
        cv2.putText(image, '{0} {1:.2f}'.format(CLASSES[cl], score),
                    (top, left - 6),
                    cv2.FONT_HERSHEY_SIMPLEX,
                    0.6, (0, 0, 255), 2)


def letterbox(im, new_shape=(640, 640), color=(0, 0, 0)):
    # Resize and pad image while meeting stride-multiple constraints
    shape = im.shape[:2]  # current shape [height, width]
    if isinstance(new_shape, int):
        new_shape = (new_shape, new_shape)

    # Scale ratio (new / old)
    r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])

    # Compute padding
    ratio = r, r  # width, height ratios
    new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
    dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]  # wh padding

    dw /= 2  # divide padding into 2 sides
    dh /= 2

    if shape[::-1] != new_unpad:  # resize
        im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
    top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
    left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
    im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)  # add border
    return im, ratio, (dw, dh)


if __name__ == '__main__':

    # Create RKNN object
    rknn = RKNNLite()

    # load RKNN model
    print('--> Load RKNN model')
    ret = rknn.load_rknn(RKNN_MODEL)


    # Init runtime environment
    print('--> Init runtime environment')
    ret = rknn.init_runtime(core_mask=RKNNLite.NPU_CORE_0_1_2)  #使用0 1 2三个NPU核心
    # ret = rknn.init_runtime('rk3566')
    if ret != 0:
        print('Init runtime environment failed!')
        exit(ret)
    print('done')

    # Set inputs
    img = cv2.imread(IMG_PATH)
    # img, ratio, (dw, dh) = letterbox(img, new_shape=(IMG_SIZE, IMG_SIZE))
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img = cv2.resize(img, (IMG_SIZE, IMG_SIZE))

    # Inference
    outputs = rknn.inference(inputs=[img])


    # post process
    input0_data = outputs[0]
    input1_data = outputs[1]
    input2_data = outputs[2]

    input0_data = input0_data.reshape([3, -1]+list(input0_data.shape[-2:]))
    input1_data = input1_data.reshape([3, -1]+list(input1_data.shape[-2:]))
    input2_data = input2_data.reshape([3, -1]+list(input2_data.shape[-2:]))

    input_data = list()
    input_data.append(np.transpose(input0_data, (2, 3, 0, 1)))
    input_data.append(np.transpose(input1_data, (2, 3, 0, 1)))
    input_data.append(np.transpose(input2_data, (2, 3, 0, 1)))

    boxes, classes, scores = yolov5_post_process(input_data)

    img_1 = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
    if boxes is not None:
        draw(img_1, boxes, scores, classes)
    # show output
    cv2.imshow("post process result", img_1)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    rknn.release()

这是基于原来test.py做的一些修改,删除了导出模型的部分,只保留了加载模型和推理部分。接下来把这几个文件放在同一个文件夹,传到香橙派的 /home/orangepi/Desktop/yolov5 目录下

第二步——在香橙派上部署

(1)将rknn-toolkit2-1.5.2.zip上传到香橙派上并解压,上传到Download目录下面

在香橙派上创建python=3.10.0的虚拟环境(yolo_py310),进入虚拟环境

将①版本升级为1.5.2,结合下面这个两个网站进行升级

rknn3588如何升级驱动_rk2588 rknpu驱动-CSDN博客

RK3588S rknnlite版本1.4升级到1.5.2,yolov5推理速度变慢 · Issue #242 · rockchip-linux/rknn-toolkit2 (github.com) 

将②版本升级到0.9.6,这个博客的做法可以升级,升级后要重启

香橙派5B-RK3588-NPU内核更新至0.9.6_rk3588更新npu驱动-CSDN博客

(2)下载rknn-toolkit2-1.5.2依赖

将下载源设置为清华源

pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
pip install rknn/rknn-toolkit2-lite/packages/rknn_toolkit_lite2-1.5.2-cp310-cp310-linux_aarch64.whl

安装剩下的依赖包

pip install opencv-python=4.5.5.64

运行deploy.py

python deploy.py

运行之后看到这个图像就是部署成功了

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

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

相关文章

19.实现一个算法实现删除链表中倒数第 n 个结点

19. Remove Nth Node From End of List 题目 Given the head of a linked list, remove the nth node from the end of the list and return its head. Follow up: Could you do this in one pass? Example 1: Input: head = [1,2,3,4,5], n = 2 Output: [1,2,3,5]Example…

蚂蚁AL1 15.6T 创新科技的新典范

● 哈希率&#xff1a;算力达到15.6T&#xff08;相当于15600G&#xff09;&#xff0c;即每秒能够进行15.6万亿次哈希计算&#xff0c;在同类产品中算力较为出色&#xff0c;能提高WA掘效率。 ● 功耗&#xff1a;功耗为3510W&#xff0c;虽然数值看似不低&#xff0c;但结合其…

PythonStudio 控件使用常用方式(二十七)TActionList

PythonStudio是一个极强的开发Python的IDE工具&#xff0c;官网地址是&#xff1a;https://glsite.com/ &#xff0c;在官网可以下载最新版的PythonStudio&#xff0c;同时&#xff0c;在使用PythonStudio时&#xff0c;它也能及时为用户升到最新版本。它使用的是Delphi的控件&…

Python爬虫技术与K-means算法的计算机类招聘信息获取与数据分析

有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主 目录 摘要.... 1 Abstract 2 1 引言.... 3 1.1 研究背景... 3 1.2 国内外研究现状... 4 1.3 研究目的... 5 1.4 研究意义... 7 2 关键技术理论介绍... 7 2.1 Python爬虫... 7 2.1 K-means…

消灭星星游戏程序设计【连载十一】——在线程中解决音效卡顿问题

消灭星星游戏程序设计【连载十一】——在线程中解决音效卡顿问题 大家每次都可以在页面中下载本节内容的实现代码&#xff0c;一步一步从简单开始&#xff0c;逐步完成游戏的各种功能&#xff0c;如果大家有任何问题也欢迎留言交流。 游戏整体效果展示&#xff1a; 1、本节要达…

宠物空气净化器哪款好?希喂、有哈宠物空气净化器测评

回想起几年前那个午后&#xff0c;我意外的在路边捡到了两只小猫咪&#xff0c;心中莫名有一份责任感出现&#xff0c;所以没有丝毫犹豫我就决定将它们带回家。捡回家以后&#xff0c;家里确实多了几分温馨&#xff0c;逐渐成为我的精神支柱。小猫的到来&#xff0c;让家的每一…

Mybatis工具类的封装

为什么要进行Mybatis工具类的封装&#xff1f; 每次我们执行数据库操作都需要做以下操作&#xff1a; //读取配置文件InputStream inputStream Resources.getResourceAsStream("mybatis-config.xml");//通过配置文件创建SqlSessionFactorySqlSessionFactory sqlSess…

模板[C++]

目录 1.&#x1f680;泛型编程&#x1f680; 2.&#x1f680;函数模板&#x1f680; 2.1 ✈️函数模板概念✈️ 2.2 ✈️函数模板格式✈️ 2.3✈️函数模板的原理✈️ 2.4 ✈️函数模板的实例化✈️ 2.5 ✈️模板参数的匹配原则✈️ 3.&#x1f680;类模板&#x1f680…

Ubuntu20.4 系统安装后无wifi图标

0. 问题排查 1.检查 BIOS 设置: 有时候&#xff0c;无线网卡可能在 BIOS 中被禁用。重启电脑&#xff0c;进入 BIOS 设置&#xff0c;确保无线网卡选项是启用的。 2.检查硬件开关: 检查您的笔记本电脑是否有物理开关或键盘快捷键来启用或禁用无线网卡。 3.在软件更新中切换…

Codeforces Round 495 (Div. 2) F. Sonya and Bitwise OR(线段树)

原题链接&#xff1a;F. Sonya and Bitwise OR 题目大意&#xff1a; 给出一个长度为 n n n 的数组 a a a&#xff0c;并给出 m m m 次询问以及一个数字 x x x。 每个询问形式如下给出&#xff1a; 1 1 1 i i i y y y &#xff1a;将 a i a_{i} ai​ 位置的值更改为 y…

将2,3,4,5,6,8分别填入算式“口口口X口口口“的“囗“中,怎么填使得算式结果最大。

一、解题思路 将数组元素进行全排列&#xff1a;对整个数组进行全排列&#xff0c;这样我们可以避免手动选择组合、排列剩余元素等步骤。 直接分割排列后的数组&#xff1a;在每一个全排列中&#xff0c;前3个元素和后3个元素自然形成了一个组合和一个剩余元素组合。 计算并…

Linux安装redis和使用redisDesktop连接

目录 Linux安装redis及启动 第一步&#xff1a;下载redis压缩包 第二步&#xff1a;下载gcc-c 第三步&#xff1a;解压redis文件 第四步&#xff1a;进入redis-4.0.0.0目录执行make命令 第五步&#xff1a;安装redis到redis目录 第五步&#xff1a;复制redis.conf配置文件…

电脑开机LOGO修改教程_BIOS启动图片替换方法

准备工具&#xff1a;刷BIOS神器和change logo&#xff0c;打包下载地址&#xff1a;https://download.csdn.net/download/baiseled/89374686 一.打开刷BIOS神器&#xff0c;点击备份BIOS&#xff0c;保存到桌面 二.打开change logo&#xff0c;1.点击load image&#xff0c;选…

11-sentinel利用nacos作持久化

本文介绍sentinel配置数据的持久化方法。由于sentinel官方并没有提供持久化功能&#xff0c;大家在测试过程中也能发现sentinel服务重启后&#xff0c;原来配置的数据就丢了&#xff0c;本文就是来处理这一问题的。 做好心理准备&#xff0c;我们要修改sentinel的源代码&#…

Python 批量修改 Word 文档中图片的大小并居中对齐

Python 批量修改 Word 文档中图片的大小并居中对齐 错过&#xff0c;再遇见可能就难了&#xff01;此时&#xff0c;你是你&#xff0c;我是我&#xff0c;再遇见&#xff0c;可就真的你是你&#xff0c;我是我&#xff0c;没有一丝的牵连纠缠—— !!! 对于已经编辑好的文档一定…

图表:调用FluentUI中的折线图散点图和饼状图

文章目录 0.文章介绍1.源码位置2.效果图3.代码3.1 代码结构3.2 main.qml3.3 MyLineChart.qml 0.文章介绍 调用项目FluentUI中的散点图、折线图和饼状图组件&#xff0c;做定制化改进。 项目FluentUI源码位置&#xff1a;https://github.com/zhuzichu520/FluentUI 项目FluentUI…

物联网产业链图谱_产业链全景图_物联网行业市场分析

物联网(IoT, Internet of Things)是通信网和互联网的拓展应用与网络延伸&#xff0c;它利用感知技术与智能装置对物理世界进行感知识别&#xff0c;通过网络传输互联&#xff0c;进行计算、处理和知识挖掘&#xff0c;实现人与物、物与物信息交互和无缝链接&#xff0c;达到对物…

springboot生成、响应图片验证码

我们平时经常会碰见图片验证码&#xff0c;那么在springboot中我们该怎么实现呢 我们可以使用一款开源的验证码生成工具EasyCaptcha&#xff0c;其支持多种类型的验证码&#xff0c;例如gif、中文、算术等&#xff0c;并且简单易用&#xff0c;具体内容可参考其官方文档。 效果…

网站SSL证书该如何更新?

网站SSL证书的更新是一个确保网站安全性的重要步骤。以下是一个详细的更新流程&#xff1a; 一、检查证书有效期 首先&#xff0c;需要定期检查SSL证书的有效期。通常情况下&#xff0c;SSL证书的有效期为一年&#xff0c;到期前需要进行更新。可以通过以下方式检查证书有效期…

证书|“机器学习工程师”来了,由工业和信息化部教育与考试中心颁发,含金量高

“机器学习工程师”职业技术考试是由工业和信息化部教育与考试中心推出人才考核标准&#xff0c;在互联网、零售、金融、电信、医学、旅游等行业均有涉及&#xff0c;是专门从事数据采集、数据分析、机器学习、人工智能并能制作业务报告、提供决策的新型数据分析人才所需要的技…