官网介绍:Orange Pi 5 Pro Orange Pi官网-香橙派(Orange Pi)开发板,开源硬件,开源软件,开源芯片,电脑键盘

官方资料:Orange Pi - Orangepi
在这里插入图片描述

  • Orange Pi 5 Pro采用了瑞芯微RK3588S新一代八核64位处理器,具体为四核A76+四核A55,采用了8nm工艺设计,主频高达2.4GHz,集成ARM Mali-G610,内置3D GPU,兼容OpenGL ES1.1/2.0/3.2、OpenCL 2.2和Vulkan 1.2;内嵌的NPU支持INT4/INT8/INT16混合运算,算力高达6TOPS,可以满足绝大多数终端设备的边缘计算需求;拥有4GB/8GB/16GB LPDDR5,具有高达8K显示处理能力,支持eMMC模块或SPI Flash(二选一),具有Wi-Fi5、BT5.0,支持BLE。
  • Orange Pi 5 Pro引用了相当丰富的接口,包括HDMI输出、GPIO接口、USB2.0、USB3.1、3.5mm耳机插座、千兆网口,支持 PoE+(需要 PoE+ HAT),配备一个M.2 M-Key插槽,支持安装NVMe 固态硬盘或SATA 固态硬盘。
  • Orange Pi 5 Pro精致小巧,尺寸仅为89mmX56mmX1.6mm,功能强大,可广泛适用于高端平板、边缘计算、人工智能、云计算、AR/VR、智能安防、智能家居等领域,覆盖 AIoT各个行业。Orange Pi 5 Pro支持Orange Pi 官方研发的操作系统Orange Pi OS,同时,支持Ubuntu、Android12、Debian等操作系统。

产品详细图

正面视图

在这里插入图片描述

背面视图

在这里插入图片描述

烧录Linux系统

详细参考OrangePi_5_Pro_RK3588S_用户手册_v1.3-1.pdf

我买的开发版有eMMC,所以直接烧录Linux镜像到eMMC中

我的是Orangepi5pro_1.0.6_ubuntu_jammy_desktop_xfce_linux6.1.43.img

初始设置

烧录完成后会自动开机,连接上wifi无线网

ssh

找到ip后远程登录ssh

更新软件

sudo apt update

sudo apt upgrade

ADB的使用

参考使用USB2.0公对公数据线连接adb章节

每次都要做在开发板上先打开adb调试

sudo set_device.sh

然后在Ubuntu PC端检测是否检测到设备
adb devices

安装开发环境

在Ubuntu的PC上位机(注意不是开发版)安装对应的环境

使用了conda安装3.10 python版的

然后安装依赖

sudo apt-get install libxslt1-dev zlib1g-dev libglib2.0 libsm6 libgl1-mesa-glx libprotobuf-dev gcc

下载源代码

git clone https://github.com/airockchip/rknn-toolkit2

安装rknn-toolkit2所需的依赖

pip3 install -r /rknn-toolkit2/rknn-toolkit2/packages/x86_64/requirements_cp310-2.3.0.txt

安装rknn-toolkit2

pip3 install /rknn-toolkit2/rknn-toolkit2/packages/x86_64/rknn_toolkit2-2.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

仿真测试

yolov5

cd rknn-toolkit2/examples/onnx/yolov5
python test.py

该脚本首先将yolov5s_relu.onnx模型转换为可以在模拟器 上运行的RKNN模型,然后使用模拟器仿真运行该模型对当前目录下的bus.jpg图 片进行推理

在这里插入图片描述

使用开发板的NPU运行模型

准备工作

RKNN-Toolkit2 为用户提供了通过adb使用开发板的NPU进行推理的Python 接口,可以让用户在Ubuntu PC端使用开发板的NPU来运行模型进行推理。 这样Ubuntu PC端可以根据模型在开发板的NPU上运行时的实际效果,使用 Python 提供的机器学习库,对模型进行优化和调整。

  • 首先确定adb能使用
  • 然后上传shell命令和库到开发板上

    adb push /rknn-toolkit2/rknpu2/runtime/Linux/rknn_server/aarch64/usr/bin/*  /usr/bin
     adb push /rknn-toolkit2/rknpu2/runtime/Linux/librknn_api/aarch64/librknnrt.so /usr/lib
  • 进入到开发板系统,启动rknn_server

    rknn_server 是一个运行在开发板上的后台代理服务,用于接收PC通过USB 传输过来的协议,然后执行板端runtime库中对应的接口,并返回结果给PC。

    adb shell
     sudo restart_rknn.sh
  • 检查rknn_server 是否已经打开

     pgrep rknn_server

代码调试

在Ubuntu PC 端通过下面的命令可以查看到连接到UbuntuPC的开发板的设备 ID,这个ID在下面会用到

adb devices

切换到/rknn-toolkit2/rknn-toolkit2/examples/onnx/yolov5目录

在test.py 文件中,需要对以下内容进行修改:

a. 在预处理配置中,将目标平台target_platform修改为rk3588,这样模型转换后得到的是适 用于RK3588开发板的NPU的RKNN模型

rknn.config(mean_values=[[0, 0, 0]], std_values=[[255, 255, 255]], target_platform='rk3588')

b. 在初始化运行环境中,增加对目标平台和设备ID的说明,目标平台是 rk3588,设备ID 是前面通过adb得到的开发板的设备ID,运行模型进行推 理的操作将会在RK3588开发板的NPU上进行

ret = rknn.init_runtime()改为

ret = rknn.init_runtime(target='rk3588',device_id='0b5040a7dcd9a0fb')

最后在Ubuntu PC上运行python test.py

在这里插入图片描述

调用C接口部署RKNN模型到开发板上运行

RKNPU2为带有Rockchip NPU的芯片平台提供C编程接口,能够帮助用户部署使用RKNN-Toolkit2导出的RKNN模型,加速AI应用的落地。

在RKNPU2的example文件夹中,提供了将不同功能的RKNN模型部署到开 发板的示例。

安装交叉编译工具

sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu

gcc和g++都安装到了/usr/bin/下面

编译

cd /rknn-toolkit2/rknpu2/examples/rknn_yolov5_demo/
./build-linux.sh -t rk3588 -a aarch64 -b Release

编译后在./build/build_RK3588_linux_aarch64_Release/下生成一个rknn_yolov5_demo文件

部署rknn_yolov5_demo到开发板运行

adb push rknn_yolov5_demo /data/rknn_yolov5_demo
adb push /rknn-toolkit2/rknpu2/examples/rknn_yolov5_demo/model/RK3588/yolov5s-640-640.rknn   /data/yolov5s-640-640.rknn
adb push /rknn-toolkit2/rknpu2/examples/rknn_yolov5_demo/model/bus.jpg  /data/bus.jpg
adb push /rknn-toolkit2/rknpu2/examples/rknn_yolov5_demo/model/coco_80_labels_list.txt  /data/coco_80_labels_list.txt

然后进入到开发板运行代码

 adb shell
 cd /data/
 sudo ./rknn_yolov5_demo ./yolov5s-640-640.rknn ./bus.jpg

得到推理后的图片out.jpg

yolo

快速测试

$ ls /dev/video*
/dev/video0   /dev/video12  /dev/video16  /dev/video2  /dev/video6  /dev/video-camera0
/dev/video1   /dev/video13  /dev/video17  /dev/video3  /dev/video7  /dev/video-dec0
/dev/video10  /dev/video14  /dev/video18  /dev/video4  /dev/video8  /dev/video-enc0
/dev/video11  /dev/video15  /dev/video19  /dev/video5  /dev/video9

查看所有的摄像头设备

其中的/dev/video-camera0是OV13855摄像头

查看它的索引

$ ls -l /dev/video-camera0
lrwxrwxrwx 1 root root 7 Mar 13 10:39 /dev/video-camera0 -> video11

它的索引是11

快速开始

pip install ultralytics
import cv2
from ultralytics import YOLO
# 设置摄像头设备索引
source = 11  # 对应于 /dev/video0

# 加载预训练的 YOLO 模型
model = YOLO("yolo11n.pt")
results = model(source,show=True)

<img src="Orange-Pi-5-Pro.assets/image-20250313170132830.png" alt="image-20250313170132830" style="zoom:50%;" />

<img src="Orange-Pi-5-Pro.assets/image-20250313170213038.png" alt="image-20250313170213038" style="zoom:50%;" />

rknn

Rockchip RKNN - Ultralytics YOLO Docs

转换模型

基于 X86 的 Linux PC 将模型导出到 RKNN

在 Linux PC上不仅需要ultralytics,还需要rknn-toolkit2

pip install rknn-toolkit2

然后

from ultralytics import YOLO

# Load the YOLO11 model
model = YOLO("yolo11n.pt")

# Export the model to RKNN format
# 'name' can be one of rk3588, rk3576, rk3566, rk3568, rk3562, rv1103, rv1106, rv1103b, rv1106b, rk2118
model.export(format="rknn", name="rk3588")  # creates '/yolo11n_rknn_model'

得到yolo11n_rknn_model文件夹以及metadata.yaml配置文件和yolo11n-rk3588.rknn模型

使用

在rk3588开发板上先安装好rknn_toolkit_lite2

pip install rknn_toolkit_lite2
import cv2
from ultralytics import YOLO
# 设置摄像头设备索引
source = 11  # 对应于 /dev/video0

# 加载预训练的 YOLO 模型
model = YOLO("./yolo11n_rknn_model")
results = model(source,show=True)

在这里插入图片描述

在这里插入图片描述

可以明显看到性能有成倍的提升,加速了6倍

优化

上面是有yolo官方的代码可以运行,但内存会积累导致溢出,优化如下

import cv2
from ultralytics import YOLO
import time
import threading

# model = YOLO("yolo11n.pt")
model = YOLO("./yolo11n_rknn_model")

# 连接 RTSP 流
source = 11 # 对应于 /dev/video0
# source = "rtsp://xxxx"  # RTSP 流地址


# 获取屏幕分辨率
screen_width = 1280  # 适配你屏幕的宽度
screen_height = 720   # 适配你屏幕的高度

# 创建可调整大小的窗口
cv2.namedWindow("RTSP Stream", cv2.WINDOW_NORMAL)
cv2.resizeWindow("RTSP Stream", screen_width, screen_height)

# 线程类:异步读取视频流
class VideoCaptureThread:
    def __init__(self, source):
        self.cap = cv2.VideoCapture(source)
        self.frame = None
        self.running = True
        self.lock = threading.Lock()  # 线程锁,保证线程安全
        self.thread = threading.Thread(target=self.update, args=())
        self.thread.daemon = True
        self.thread.start()

    def update(self):
        while self.running:
            ret, frame = self.cap.read()
            if ret:
                with self.lock:  # 加锁,防止数据竞争
                    self.frame = frame
            time.sleep(0.01)  # 限制 CPU 占用,避免高负载

    def get_frame(self):
        """获取最新帧"""
        with self.lock:
            return self.frame

    def stop(self):
        """停止线程"""
        self.running = False
        self.cap.release()

video_thread = VideoCaptureThread(source)

while True:
    frame = video_thread.get_frame()
    if frame is None:
        continue

    results = model.predict(frame, conf=0.5)
    annotated_frame = results[0].plot() if results else frame

    frame_resized = cv2.resize(annotated_frame, (screen_width, screen_height))
    cv2.imshow("RTSP Stream", frame_resized)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

video_thread.stop()
cv2.destroyAllWindows()

多线程读取RTSP流并让视频解码和YOLO推理并行的核心思想是 将视频解码(读取RTSP流)与YOLO推理分离,使它们能够并行执行,从而提高整体帧率


1. 传统单线程的瓶颈

主线程按顺序执行:

  1. 从 RTSP 流读取一帧 cap.read()
  2. 进行 YOLO 目标检测 model(frame)
  3. 显示检测后的画面 cv2.imshow()

问题

  • cap.read() 可能会阻塞,特别是网络抖动或 RTSP 服务器响应慢时,导致帧率降低。
  • YOLO 处理时间过长时,会卡住整个流程,导致视频播放不流畅(灰屏或卡顿)。
  • 由于单线程按顺序执行,每一步都需要等待前一步完成,无法充分利用 CPU 和 GPU 资源。

2. 采用多线程的优化思路

可以创建 两个独立的线程

  1. 读取 RTSP 流线程VideoCaptureThread):

    • 持续从 RTSP 服务器获取最新的视频帧,并缓存在一个变量中。
    • 主线程可以随时获取最新帧,而不会被 cap.read() 阻塞。
  2. YOLO 目标检测线程(主线程):

    • 在需要时获取最新的帧,而不是等待 cap.read() 返回新帧。
    • 如果 YOLO 处理太慢,可以丢弃一些帧,确保视频流畅度。

这样,我们可以并行进行 RTSP 读取和 YOLO 计算,从而提高 FPS。

拓展

如果要对人进行跟踪

while True:
    frame = video_thread.get_frame()
    if frame is None:
        continue
    results = model.track(frame,classes=[0],persist=True,conf=0.5,stream=True)
    for result in results:
        annotated_frame = result.plot() if results else frame

    frame_resized = cv2.resize(annotated_frame, (screen_width, screen_height))
    cv2.imshow("RTSP Stream", frame_resized)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

七仔啊
1 声望0 粉丝