首页
商城
  • English
  • 简体中文
首页
商城
  • English
  • 简体中文
  • 产品系列

    • FPGA+ARM

      • GM-3568JHF

        • 一、简介

          • GM-3568JHF 简介
        • 二、快速开始

          • 00 前言
          • 01 环境搭建
          • 02 编译说明
          • 03 烧录指南
          • 04 调试工具
          • 05 软件更新
          • 06 查看信息
          • 07 测试命令
          • 08 应用编译
          • 09 源码获取
        • 三、外设与接口

          • 01 USB
          • 02 显示与触摸
          • 03 以太网
          • 04 WIFI
          • 05 蓝牙
          • 06 TF-Card
          • 07 音频
          • 08 串口
          • 09 CAN
          • 10 RTC
        • 四、应用开发

          • 01 UART读写案例
          • 02 按键检测案例
          • 03 LED灯闪烁案例
          • 04 MIPI屏幕检测案例
          • 05 读取 USB 设备信息案例
          • 06 FAN 检测案例
          • 07 FPGA FSPI 通信案例
          • 08 FPGA DMA 读写案例
          • 09 GPS调试案例
          • 10 以太网测试案例
          • 11 RS485读写案例
          • 12 FPGA IIC 读写案例
          • 13 PN532 NFC读卡案例
          • 14 TF卡读写案例
        • 五、QT开发

          • 01 ARM64交叉编译器环境搭建
          • 02 QT 程序加入开机自启服务
        • 六、RKNN_NPU开发

          • 01 RK3568 NPU 概述
          • 02 开发环境搭建
          • 运行官方 YOLOv5 示例
        • 七、FPGA开发

          • ARM与FPGA通讯
          • FPGA开发手册
        • 八、其他

          • 01 根目录文件系统的修改
          • 02 系统自启服务
        • 九、资料下载

          • 资料下载
    • ShimetaPi

      • M4-R1

        • 一、简介

          • M4-R1简介
        • 二、快速上手

          • 01 OpenHarmony概述
          • 02 镜像烧录
          • 03 应用开发快速上手
          • 04 设备开发快速上手
        • 三、应用开发

          • 3.1 ArkUI

            • 1 ArkTS语言简介
            • 2 UI 组件-Row 容器介绍
            • 3 UI 组件-Column 容器介绍
            • 4 UI 组件-Text 组件
            • 5 UI 组件-Toggle 组件
            • 6 UI 组件-Slider 组件
            • 7 UI 组件-Animation 组件&Transition 组件
          • 3.2 资料获取

            • 1 OpenHarmony 官方资料
          • 3.3 开发须知

            • 1 Full-SDK替换教程
            • 2 引入和使用三方库
            • 3 HDC调试
            • 4 命令行恢复出厂模式
            • 5 升级App为system权限
          • 3.4 构建第一个应用

            • 1 构建第一个ArkTs应用-HelloWorld
          • 3.5 案例

            • 01 串口调试助手应用案例
            • 02 手写板应用案例
            • 03 数字时钟应用案例
            • 04 WIFI 信息获取应用案例
        • 四、设备开发

          • 4.1 Ubuntu环境开发

            • 01 环境搭建
            • 02 下载源码
            • 03 编译源码
          • 4.2 使用DevEco Device Tool 工具

            • 01 工具简介
            • 02 开发环境的搭建
            • 03 导入SDK
            • 04 HUAWEI DevEco Tool 功能介绍
        • 五、内核外设与接口

          • 5.1 指南
          • 5.2 设备树介绍
          • 5.3 NAPI 入门
          • 5.4 ArkTS入门
          • 5.5 NAPI开发实战演示
          • 5.6 GPIO介绍
          • 5.7 I2C通讯
          • 5.8 SPI通信
          • 5.9 PWM 控制
          • 5.10 串口通讯
          • 5.11 TF卡
          • 5.12 屏幕
          • 5.13 触摸
          • 5.14 Ethernet(以太网)
          • 5.15 M.2 硬盘
          • 5.16 音频
          • 5.17 WIFI & BT
          • 5.18 摄像头
        • 六、资料下载

          • 资料下载
      • M5-R1

        • 一、简介

          • M5-R1 开发文档
        • 二、快速上手

          • 镜像烧录
          • 环境搭建
          • 下载源码
        • 三、外设与接口

          • 3.1 树莓派接口
          • 3.2 GPIO接口
          • 3.3 I2C接口
          • 3.4 SPI通信
          • 3.5 PWM控制
          • 3.6 串口通信
          • 3.7 TF卡插槽
          • 3.8 显示屏
          • 3.9 触摸屏
          • 3.10 音频
          • 3.11 RTC
          • 3.12 以太网
          • 3.13 M.2接口
          • 3.14 MINI PCIE接口
          • 3.15 摄像头
          • 3.16 WIFI蓝牙
        • 四、资料下载

          • 资料下载
    • 开源鸿蒙

      • SC-3568HA

        • 一、简介

          • SC-3568HA简介
        • 二、快速上手

          • OpenHarmony概述
          • 镜像烧录
          • 开发环境准备
          • Hello World应用以及部署
        • 三、应用开发

          • 3.1 ArkUI

            • 第一章 ArkTS语言简介
            • 第二章 UI组件介绍和实际应用(上)
            • 第三章 UI组件介绍和实际应用(中)
            • 第四章 UI组件介绍和实际应用(下)
          • 3.2 拓展

            • 第一章 入门指引
            • 第二章 三方库的引用和使用
            • 第三章 应用编译以及部署
            • 第四章 命令行恢复出厂设置
            • 第五章 系统调试--HDC调试
            • 第六章 APP 稳定性测试
            • 第七章 应用测试
        • 四、设备开发

          • 4.1 环境搭建
          • 4.2 源码下载
          • 4.3 源码编译
        • 五、内核的外设与接口

          • 5.1 树莓派接口
          • 5.2 GPIO 接口
          • 5.3 I2C 接口
          • 5.4 SPI 通信
          • 5.5 PWM 控制
          • 5.6 串口通信
          • 5.7 TF卡插槽
          • 5.8 显示屏
          • 5.9 触摸屏
          • 5.10 音频
          • 5.11 RTC
          • 5.12 以太网
          • 5.13 M.2接口
          • 5.14 MINI PCIE接口
          • 5.15 摄像头
          • 5.16 WIFI蓝牙
          • 5.17 树莓派拓展板
        • 六、资料下载

          • 资料下载
      • M-K1HSE

        • 一、简介

          • 1.1 产品简介
        • 二、快速开始

          • 2.1 调试工具安装
          • 2.2 开发环境搭建
          • 2.3 源码下载
          • 2.4 编译说明
          • 2.5 烧录指南
          • 2.6 APT 更新源
          • 2.7 查看板卡信息
          • 2.8 命令行 LED 和按键测试
          • 2.9 GCC 编译程序
        • 三、应用开发

          • 3.1 基础应用开发

            • 3.1.1 开发环境准备
            • 3.1.2 第一个应用 HelloWorld
            • 3.1.3 开发 HAR 包
          • 3.2 外设应用案例

            • 3.2.1 UART 读写
            • 3.2.2 按键实验
            • 3.2.3 LED 闪烁
        • 四、外设与接口

          • 4.1 标准外设

            • 4.1.1 USB
            • 4.1.2 显示与触摸
            • 4.1.3 以太网
            • 4.1.4 WIFI
            • 4.1.5 蓝牙
            • 4.1.6 TF卡
            • 4.1.7 音频
            • 4.1.8 串口
            • 4.1.9 CAN
            • 4.1.10 RTC
          • 4.2 接口

            • 4.2.1 音频
            • 4.2.2 RS485
            • 4.2.3 显示
            • 4.2.4 触摸
        • 五、系统定制开发

          • 5.1 系统移植
          • 5.2 系统定制
          • 5.3 驱动开发
          • 5.4 系统调试
          • 5.5 OTA 升级
        • 六、资料下载

          • 6.1 资料下载
    • EVS相机

      • CF-NRS1

        • 一、简介

          • 1.1 关于 CF-NRS1
          • 1.2 基于事件的概念
          • 1.3 快速开始
          • 1.4 资源
        • 二、开发

          • 2.1 开发概览

            • 2.1.1 Shimetapi 混合相机 SDK 简介
          • 2.2 环境与API

            • 2.2.1 环境说明
            • 2.2.2 开发 API 说明
          • 2.3 Linux开发

            • 2.3.1 Linux SDK 简介
            • 2.3.2 Linux SDK API
            • 2.3.3 Linux 算法
            • 2.3.4 Linux 算法 API
          • 2.4 服务与Web

            • 2.4.1 EVS 服务器
            • 2.4.2 时间服务器
            • 2.4.3 EVS Web
        • 三、资料下载

          • 3.1 资料下载
        • 四、常见问题

          • 4.1 常见问题
      • CF-CRA2

        • 一、简介

          • 1.1 关于 CF-CRA2
        • 二、资料下载

          • 2.1 资料下载
      • EVS模块

        • 一、相关概念
        • 二、硬件准备与环境配置
        • 三、示例程序使用指南
        • 资料下载
    • AI硬件

      • 1684XB-32T

        • 一、简介

          • AIBOX-1684XB-32简介
        • 二、快速上手

          • 初次使用
          • 网络配置
          • 磁盘使用
          • 内存分配
          • 风扇策略
          • 固件升级
          • 交叉编译
          • 模型量化
        • 三、应用开发

          • 3.1 开发简介

            • Sophgo SDK开发
            • SOPHON-DEMO简介
          • 3.2 大语言模型

            • 部署Llama3示例
            • Sophon LLM_api_server开发
            • 部署MiniCPM-V-2_6
            • Qwen-2-5-VL图片视频识别DEMO
            • Qwen3-chat-DEMO
            • Qwen3-Qwen Agent-MCP开发
            • Qwen3-langchain-AI Agent
          • 3.3 深度学习

            • ResNet(图像分类)
            • LPRNet(车牌识别)
            • SAM(通用图像分割基础模型)
            • YOLOv5(目标检测)
            • OpenPose(人体关键点检测)
            • PP-OCR(光学字符识别)
        • 四、资料下载

          • 资料下载
      • 1684X-416T

        • 一、简介

          • 1.1 产品简介
        • 二、Demo简单操作指引

          • 2.1 智慧监控Demo使用说明
      • RDK-X5

        • 一、简介

          • RDK-X5 硬件简介
        • 二、快速开始

          • RDK-X5 快速开始
        • 三、应用开发

          • 3.1 AI在线模型开发

            • 实验01-接入火山引擎豆包 AI
            • 实验02-图片分析
            • 实验03-多模态视觉分析定位
            • 实验04-多模态图文比较分析
            • 实验05-多模态文档表格分析
            • 实验06-摄像头运用-AI视觉分析
          • 3.2 大语言模型

            • 实验01-语音识别
            • 实验02-语音对话
            • 实验03-多模态图片分析-语音对话
            • 实验04-多模态图片比较-语音对话
            • 实验05-多模态文档分析-语音对话
            • 实验06-多模态视觉运用-语音对话
          • 3.3 40pin-IO开发

            • 实验01-GPIO 输出(LED闪烁)
            • 实验02-GPIO 输入
            • 实验03-按键控制 LED
            • 实验04-PWM 输出
            • 实验05-串口输出
            • 实验06-IIC 实验
            • 实验07-SPI 实验
          • 3.4 USB模块开发使用

            • 实验01-USB 语音模块使用
            • 实验02-声源定位模块使用
          • 3.5 机器视觉技术实战

            • 实验01-打开 USB 摄像头
            • 实验02-颜色识别检测
            • 实验03-手势识别体验
            • 实验04-YOLOv5物体检测
          • 3.6 ROS2基础开发

            • 实验01-搭建环境
            • 实验02-工作包的创建及编译
            • 实验03-运行 ROS2 话题通信节点
            • 实验04-ROS2 相机应用
      • RDK-S100

        • 一、简介

          • 1.1 关于 RDK-S100
        • 二、快速开始

          • 2.1 首次使用
        • 三、应用开发

          • 3.1 AI在线模型开发

            • 3.1.1 接入火山引擎豆包 AI
            • 3.1.2 图片分析
            • 3.1.3 多模态视觉分析定位
            • 3.1.4 多模态图文比较分析
            • 3.1.5 多模态文档表格分析
            • 3.1.6 摄像头运用-AI视觉分析
          • 3.2 大语言模型

            • 3.2.1 语音识别
            • 3.2.2 语音对话
            • 3.2.3 多模态图片分析-语音对话
            • 3.2.4 多模态图片比较-语音对话
            • 3.2.5 多模态文档分析-语音对话
            • 3.2.6 多模态视觉运用-语音对话
          • 3.3 40pin-IO开发

            • 3.3.1 GPIO 输出(LED闪烁)
            • 3.3.2 GPIO 输入
            • 3.3.3 按键控制 LED
            • 3.3.4 PWM 输出
            • 3.3.5 串口输出
            • 3.3.6 IIC 实验
            • 3.3.7 SPI 实验
          • 3.4 USB模块开发使用

            • 3.4.1 USB 语音模块使用
            • 3.4.2 声源定位模块使用
          • 3.5 机器视觉技术实战

            • 3.5.1 打开 USB 摄像头
            • 3.5.2 图像处理基础
            • 3.5.3 目标检测
            • 3.5.4 图像分割
          • 3.6 ROS2基础开发

            • 3.6.1 搭建环境
            • 3.6.2 工作包的创建及编译
            • 3.6.3 运行 ROS2 话题通信节点
            • 3.6.4 ROS2 相机应用
    • 核心板

      • C-3568BQ

        • 一、简介

          • C-3568BQ 简介
      • C-3588LQ

        • 一、简介

          • C-3588LQ 简介
      • GC-3568JBAF

        • 一、简介

          • GC-3568JBAF 简介
      • C-K1BA

        • 一、简介

          • C-K1BA 简介

运行官方 YOLOv5 示例

3.1 获取官方预编译 Demo

下载官方示例代码

从GitHub获取

# 克隆官方RKNN示例仓库
git clone https://github.com/rockchip-linux/rknn_model_zoo.git
cd rknn_model_zoo

# 查看目录结构
ls -la

目录结构说明

rknn_model_zoo/
├── models/                    # 预训练模型
│   └── CV/                   # 计算机视觉模型
│       └── object_detection/ # 目标检测模型
│           └── yolo/         # YOLO系列模型
│               └── yolov5/   # YOLOv5模型
├── examples/                 # 示例代码
│   └── yolov5/              # YOLOv5示例
│       ├── python/          # Python版本
│       └── cpp/             # C++版本
└── docs/                    # 文档

下载预编译模型

# 进入YOLOv5模型目录
cd models/CV/object_detection/yolo/yolov5

# 下载预编译的RKNN模型
wget https://ftrg.zbox.filez.com/v2/delivery/data/95f00b0fc900458ba134f8b180b3f7a1/examples/yolov5/yolov5s.rknn

# 或者从百度网盘下载 (如果GitHub下载慢)
# 链接: https://pan.baidu.com/s/1XXX
# 提取码: XXXX

获取测试数据

下载测试图片

# 创建测试数据目录
mkdir -p test_data/images

# 下载COCO测试图片
cd test_data/images
wget https://github.com/ultralytics/yolov5/raw/master/data/images/bus.jpg
wget https://github.com/ultralytics/yolov5/raw/master/data/images/zidane.jpg

# 或使用自己的测试图片
# cp /path/to/your/image.jpg ./

准备视频测试文件 (可选)

# 下载测试视频
wget https://sample-videos.com/zip/10/mp4/SampleVideo_1280x720_1mb.mp4

# 或使用摄像头 (后续会用到)
# 确保摄像头设备可用
ls /dev/video*

验证下载文件

检查模型文件

# 检查RKNN模型文件
ls -lh yolov5s.rknn
file yolov5s.rknn

# 查看模型信息 (需要RKNN工具)
python3 -c "
from rknnlite.api import RKNNLite
rknn = RKNNLite()
ret = rknn.load_rknn('yolov5s.rknn')
if ret == 0:
    print('模型加载成功')
    rknn.init_runtime()
    print('运行时初始化成功')
else:
    print('模型加载失败')
"

3.2 板端运行 YOLOv5 Demo

准备板端环境

传输文件到开发板

# 使用scp传输文件
scp -r rknn_model_zoo/ root@192.168.1.100:/home/root/

# 或使用rsync (更高效)
rsync -av --progress rknn_model_zoo/ root@192.168.1.100:/home/root/rknn_model_zoo/

# SSH登录到开发板
ssh root@192.168.1.100

安装依赖 (板端)

# 更新包管理器
sudo apt update

# 安装Python依赖
pip3 install opencv-python numpy pillow

# 安装系统依赖
sudo apt install python3-opencv

# 验证摄像头 (如果使用)
ls /dev/video*
v4l2-ctl --list-devices

Python版本示例运行

基本图片检测

#!/usr/bin/env python3
# yolov5_image_demo.py

import cv2
import numpy as np
import time
from rknnlite.api import RKNNLite

# COCO数据集类别名称
CLASSES = [
    'person', 'bicycle', 'car', 'motorcycle', 'airplane', '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', 'couch',
    'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone',
    'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear',
    'hair drier', 'toothbrush'
]

def preprocess_image(image, input_size=(640, 640)):
    """图像预处理"""
    # 保持宽高比的resize
    h, w = image.shape[:2]
    scale = min(input_size[0] / w, input_size[1] / h)
    new_w, new_h = int(w * scale), int(h * scale)
    
    # Resize图像
    resized = cv2.resize(image, (new_w, new_h))
    
    # 创建新的图像并居中放置
    new_image = np.full((input_size[1], input_size[0], 3), 114, dtype=np.uint8)
    top = (input_size[1] - new_h) // 2
    left = (input_size[0] - new_w) // 2
    new_image[top:top+new_h, left:left+new_w] = resized
    
    # 转换为RGB并归一化
    new_image = cv2.cvtColor(new_image, cv2.COLOR_BGR2RGB)
    new_image = new_image.astype(np.float32) / 255.0
    
    # 转换为NCHW格式
    new_image = np.transpose(new_image, (2, 0, 1))
    new_image = np.expand_dims(new_image, axis=0)
    
    return new_image, scale, (left, top)

def postprocess_output(outputs, scale, offset, conf_threshold=0.5, nms_threshold=0.45):
    """后处理输出结果"""
    predictions = outputs[0][0]  # 获取预测结果
    
    # 解析预测结果
    boxes = []
    scores = []
    class_ids = []
    
    for detection in predictions:
        confidence = detection[4]
        if confidence > conf_threshold:
            # 获取类别分数
            class_scores = detection[5:]
            class_id = np.argmax(class_scores)
            class_score = class_scores[class_id]
            
            if class_score > conf_threshold:
                # 解析边界框
                x_center, y_center, width, height = detection[:4]
                
                # 转换为实际坐标
                x_center = (x_center - offset[0]) / scale
                y_center = (y_center - offset[1]) / scale
                width = width / scale
                height = height / scale
                
                # 转换为左上角坐标
                x1 = int(x_center - width / 2)
                y1 = int(y_center - height / 2)
                x2 = int(x_center + width / 2)
                y2 = int(y_center + height / 2)
                
                boxes.append([x1, y1, x2, y2])
                scores.append(float(confidence * class_score))
                class_ids.append(class_id)
    
    # 非极大值抑制
    if len(boxes) > 0:
        indices = cv2.dnn.NMSBoxes(boxes, scores, conf_threshold, nms_threshold)
        if len(indices) > 0:
            indices = indices.flatten()
            return [boxes[i] for i in indices], [scores[i] for i in indices], [class_ids[i] for i in indices]
    
    return [], [], []

def draw_detections(image, boxes, scores, class_ids):
    """绘制检测结果"""
    for box, score, class_id in zip(boxes, scores, class_ids):
        x1, y1, x2, y2 = box
        
        # 绘制边界框
        cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
        
        # 绘制标签
        label = f"{CLASSES[class_id]}: {score:.2f}"
        label_size = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 2)[0]
        cv2.rectangle(image, (x1, y1 - label_size[1] - 10), (x1 + label_size[0], y1), (0, 255, 0), -1)
        cv2.putText(image, label, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 2)
    
    return image

def main():
    # 初始化RKNN
    rknn = RKNNLite()
    
    # 加载模型
    print("加载RKNN模型...")
    ret = rknn.load_rknn('yolov5s.rknn')
    if ret != 0:
        print("模型加载失败!")
        return
    
    # 初始化运行时
    print("初始化运行时...")
    ret = rknn.init_runtime()
    if ret != 0:
        print("运行时初始化失败!")
        return
    
    # 加载测试图片
    image_path = 'test_data/images/bus.jpg'
    image = cv2.imread(image_path)
    if image is None:
        print(f"无法加载图片: {image_path}")
        return
    
    print(f"处理图片: {image_path}")
    
    # 预处理
    input_data, scale, offset = preprocess_image(image)
    
    # 推理
    print("开始推理...")
    start_time = time.time()
    outputs = rknn.inference(inputs=[input_data])
    inference_time = time.time() - start_time
    print(f"推理时间: {inference_time:.3f}s")
    
    # 后处理
    boxes, scores, class_ids = postprocess_output(outputs, scale, offset)
    
    # 绘制结果
    result_image = draw_detections(image.copy(), boxes, scores, class_ids)
    
    # 保存结果
    output_path = 'yolov5_result.jpg'
    cv2.imwrite(output_path, result_image)
    print(f"结果保存到: {output_path}")
    
    # 打印检测结果
    print(f"检测到 {len(boxes)} 个目标:")
    for i, (box, score, class_id) in enumerate(zip(boxes, scores, class_ids)):
        print(f"  {i+1}. {CLASSES[class_id]}: {score:.3f} at {box}")
    
    # 释放资源
    rknn.release()

if __name__ == "__main__":
    main()

运行图片检测

# 进入示例目录
cd /home/root/rknn_model_zoo/examples/yolov5/python

# 运行图片检测
python3 yolov5_image_demo.py

# 查看结果
ls -la yolov5_result.jpg

实时摄像头检测

摄像头检测脚本

#!/usr/bin/env python3
# yolov5_camera_demo.py

import cv2
import numpy as np
import time
from rknnlite.api import RKNNLite
import threading
import queue

class YOLOv5Camera:
    def __init__(self, model_path, camera_id=0):
        self.model_path = model_path
        self.camera_id = camera_id
        self.rknn = None
        self.cap = None
        self.frame_queue = queue.Queue(maxsize=2)
        self.result_queue = queue.Queue(maxsize=2)
        self.running = False
        
    def init_model(self):
        """初始化RKNN模型"""
        self.rknn = RKNNLite()
        ret = self.rknn.load_rknn(self.model_path)
        if ret != 0:
            print("模型加载失败!")
            return False
        
        ret = self.rknn.init_runtime()
        if ret != 0:
            print("运行时初始化失败!")
            return False
        
        print("RKNN模型初始化成功")
        return True
    
    def init_camera(self):
        """初始化摄像头"""
        self.cap = cv2.VideoCapture(self.camera_id)
        if not self.cap.isOpened():
            print(f"无法打开摄像头 {self.camera_id}")
            return False
        
        # 设置摄像头参数
        self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
        self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
        self.cap.set(cv2.CAP_PROP_FPS, 30)
        
        print("摄像头初始化成功")
        return True
    
    def capture_thread(self):
        """摄像头捕获线程"""
        while self.running:
            ret, frame = self.cap.read()
            if ret:
                if not self.frame_queue.full():
                    self.frame_queue.put(frame)
                else:
                    # 丢弃旧帧
                    try:
                        self.frame_queue.get_nowait()
                        self.frame_queue.put(frame)
                    except queue.Empty:
                        pass
            time.sleep(0.01)
    
    def inference_thread(self):
        """推理线程"""
        while self.running:
            try:
                frame = self.frame_queue.get(timeout=1.0)
                
                # 预处理
                input_data, scale, offset = preprocess_image(frame)
                
                # 推理
                start_time = time.time()
                outputs = self.rknn.inference(inputs=[input_data])
                inference_time = time.time() - start_time
                
                # 后处理
                boxes, scores, class_ids = postprocess_output(outputs, scale, offset)
                
                # 绘制结果
                result_frame = draw_detections(frame.copy(), boxes, scores, class_ids)
                
                # 添加FPS信息
                fps = 1.0 / inference_time if inference_time > 0 else 0
                cv2.putText(result_frame, f"FPS: {fps:.1f}", (10, 30), 
                           cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
                
                if not self.result_queue.full():
                    self.result_queue.put(result_frame)
                else:
                    try:
                        self.result_queue.get_nowait()
                        self.result_queue.put(result_frame)
                    except queue.Empty:
                        pass
                        
            except queue.Empty:
                continue
    
    def run(self):
        """运行检测"""
        if not self.init_model():
            return
        
        if not self.init_camera():
            return
        
        self.running = True
        
        # 启动线程
        capture_thread = threading.Thread(target=self.capture_thread)
        inference_thread = threading.Thread(target=self.inference_thread)
        
        capture_thread.start()
        inference_thread.start()
        
        print("开始实时检测,按 'q' 退出...")
        
        try:
            while True:
                try:
                    result_frame = self.result_queue.get(timeout=1.0)
                    cv2.imshow('YOLOv5 Real-time Detection', result_frame)
                    
                    if cv2.waitKey(1) & 0xFF == ord('q'):
                        break
                except queue.Empty:
                    continue
                    
        except KeyboardInterrupt:
            print("用户中断")
        
        # 清理资源
        self.running = False
        capture_thread.join()
        inference_thread.join()
        
        if self.cap:
            self.cap.release()
        if self.rknn:
            self.rknn.release()
        cv2.destroyAllWindows()
        
        print("检测结束")

# 使用之前定义的预处理和后处理函数
# (这里省略,使用上面图片检测中的函数)

if __name__ == "__main__":
    detector = YOLOv5Camera('yolov5s.rknn', camera_id=0)
    detector.run()

运行摄像头检测

# 检查摄像头设备
ls /dev/video*

# 运行摄像头检测
python3 yolov5_camera_demo.py

# 如果没有显示器,可以保存视频
# 修改代码保存为视频文件而不是显示

性能测试和优化

性能基准测试

#!/usr/bin/env python3
# yolov5_benchmark.py

import cv2
import numpy as np
import time
from rknnlite.api import RKNNLite

def benchmark_model(model_path, test_image_path, num_runs=100):
    """模型性能基准测试"""
    # 初始化模型
    rknn = RKNNLite()
    ret = rknn.load_rknn(model_path)
    if ret != 0:
        print("模型加载失败!")
        return
    
    ret = rknn.init_runtime()
    if ret != 0:
        print("运行时初始化失败!")
        return
    
    # 加载测试图片
    image = cv2.imread(test_image_path)
    input_data, _, _ = preprocess_image(image)
    
    print(f"开始性能测试,运行 {num_runs} 次推理...")
    
    # 预热
    for _ in range(10):
        rknn.inference(inputs=[input_data])
    
    # 正式测试
    times = []
    for i in range(num_runs):
        start_time = time.time()
        outputs = rknn.inference(inputs=[input_data])
        end_time = time.time()
        times.append(end_time - start_time)
        
        if (i + 1) % 20 == 0:
            print(f"完成 {i + 1}/{num_runs} 次推理")
    
    # 统计结果
    times = np.array(times)
    avg_time = np.mean(times)
    min_time = np.min(times)
    max_time = np.max(times)
    std_time = np.std(times)
    
    print(f"\n性能测试结果:")
    print(f"平均推理时间: {avg_time*1000:.2f} ms")
    print(f"最小推理时间: {min_time*1000:.2f} ms")
    print(f"最大推理时间: {max_time*1000:.2f} ms")
    print(f"标准差: {std_time*1000:.2f} ms")
    print(f"平均FPS: {1/avg_time:.2f}")
    
    rknn.release()

if __name__ == "__main__":
    benchmark_model('yolov5s.rknn', 'test_data/images/bus.jpg')

3.3 PC 端运行仿真 Demo

PC端仿真环境准备

安装RKNN-Toolkit2

# 激活虚拟环境
source rknn_env/bin/activate

# 确认RKNN-Toolkit2已安装
pip list | grep rknn

# 如果未安装
pip install rknn-toolkit2

PC端仿真代码

仿真推理脚本

#!/usr/bin/env python3
# yolov5_pc_simulation.py

import cv2
import numpy as np
import time
from rknn.api import RKNN

def pc_simulation_demo():
    """PC端仿真演示"""
    # 创建RKNN对象
    rknn = RKNN(verbose=True)
    
    # 加载RKNN模型
    print("加载RKNN模型...")
    ret = rknn.load_rknn('yolov5s.rknn')
    if ret != 0:
        print("模型加载失败!")
        return
    
    # 初始化运行时 (仿真模式)
    print("初始化仿真运行时...")
    ret = rknn.init_runtime(target='rk3568', device_id=None)
    if ret != 0:
        print("仿真运行时初始化失败!")
        return
    
    # 加载测试图片
    image_path = 'test_data/images/bus.jpg'
    image = cv2.imread(image_path)
    if image is None:
        print(f"无法加载图片: {image_path}")
        return
    
    print(f"处理图片: {image_path}")
    
    # 预处理 (使用相同的预处理函数)
    input_data, scale, offset = preprocess_image(image)
    
    # 仿真推理
    print("开始仿真推理...")
    start_time = time.time()
    outputs = rknn.inference(inputs=[input_data])
    inference_time = time.time() - start_time
    print(f"仿真推理时间: {inference_time:.3f}s")
    
    # 后处理
    boxes, scores, class_ids = postprocess_output(outputs, scale, offset)
    
    # 绘制结果
    result_image = draw_detections(image.copy(), boxes, scores, class_ids)
    
    # 保存结果
    output_path = 'yolov5_pc_simulation_result.jpg'
    cv2.imwrite(output_path, result_image)
    print(f"仿真结果保存到: {output_path}")
    
    # 打印检测结果
    print(f"仿真检测到 {len(boxes)} 个目标:")
    for i, (box, score, class_id) in enumerate(zip(boxes, scores, class_ids)):
        print(f"  {i+1}. {CLASSES[class_id]}: {score:.3f} at {box}")
    
    # 释放资源
    rknn.release()

if __name__ == "__main__":
    pc_simulation_demo()

模型转换和仿真一体化

完整的转换+仿真流程

#!/usr/bin/env python3
# yolov5_convert_and_simulate.py

import cv2
import numpy as np
import time
from rknn.api import RKNN

def convert_and_simulate():
    """模型转换和仿真一体化流程"""
    # 创建RKNN对象
    rknn = RKNN(verbose=True)
    
    # 配置模型转换参数
    print("配置模型转换参数...")
    rknn.config(
        target_platform='rk3568',
        quantized_dtype='asymmetric_quantized-u8',
        optimization_level=3,
        output_optimize=1
    )
    
    # 加载ONNX模型 (如果有原始ONNX模型)
    onnx_model_path = 'yolov5s.onnx'
    try:
        print(f"加载ONNX模型: {onnx_model_path}")
        ret = rknn.load_onnx(model=onnx_model_path)
        if ret != 0:
            print("ONNX模型加载失败!")
            return
    except:
        print("未找到ONNX模型,直接加载RKNN模型...")
        ret = rknn.load_rknn('yolov5s.rknn')
        if ret != 0:
            print("RKNN模型加载失败!")
            return
    
    # 构建模型 (如果是从ONNX转换)
    if onnx_model_path:
        print("构建RKNN模型...")
        ret = rknn.build(do_quantization=True)
        if ret != 0:
            print("模型构建失败!")
            return
        
        # 导出RKNN模型
        print("导出RKNN模型...")
        ret = rknn.export_rknn('./yolov5s_converted.rknn')
        if ret != 0:
            print("模型导出失败!")
            return
    
    # 初始化仿真运行时
    print("初始化仿真运行时...")
    ret = rknn.init_runtime()
    if ret != 0:
        print("仿真运行时初始化失败!")
        return
    
    # 准备测试数据
    test_images = [
        'test_data/images/bus.jpg',
        'test_data/images/zidane.jpg'
    ]
    
    for image_path in test_images:
        if not os.path.exists(image_path):
            print(f"跳过不存在的图片: {image_path}")
            continue
            
        print(f"\n处理图片: {image_path}")
        
        # 加载图片
        image = cv2.imread(image_path)
        if image is None:
            print(f"无法加载图片: {image_path}")
            continue
        
        # 预处理
        input_data, scale, offset = preprocess_image(image)
        
        # 仿真推理
        start_time = time.time()
        outputs = rknn.inference(inputs=[input_data])
        inference_time = time.time() - start_time
        print(f"推理时间: {inference_time:.3f}s")
        
        # 后处理
        boxes, scores, class_ids = postprocess_output(outputs, scale, offset)
        
        # 绘制和保存结果
        result_image = draw_detections(image.copy(), boxes, scores, class_ids)
        output_path = f'result_{os.path.basename(image_path)}'
        cv2.imwrite(output_path, result_image)
        print(f"结果保存到: {output_path}")
        
        # 打印检测结果
        print(f"检测到 {len(boxes)} 个目标:")
        for i, (box, score, class_id) in enumerate(zip(boxes, scores, class_ids)):
            print(f"  {i+1}. {CLASSES[class_id]}: {score:.3f}")
    
    # 释放资源
    rknn.release()
    print("\n仿真完成!")

if __name__ == "__main__":
    import os
    convert_and_simulate()

精度对比测试

原始模型vs RKNN模型精度对比

#!/usr/bin/env python3
# accuracy_comparison.py

import torch
import torchvision.transforms as transforms
from rknn.api import RKNN
import cv2
import numpy as np

def compare_accuracy():
    """比较原始模型和RKNN模型的精度"""
    
    # 加载原始PyTorch模型 (如果有)
    try:
        import torch
        original_model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)
        original_model.eval()
        print("原始PyTorch模型加载成功")
    except:
        print("无法加载原始PyTorch模型,跳过精度对比")
        return
    
    # 加载RKNN模型
    rknn = RKNN(verbose=False)
    ret = rknn.load_rknn('yolov5s.rknn')
    if ret != 0:
        print("RKNN模型加载失败!")
        return
    
    ret = rknn.init_runtime()
    if ret != 0:
        print("RKNN运行时初始化失败!")
        return
    
    # 测试图片
    test_image = 'test_data/images/bus.jpg'
    image = cv2.imread(test_image)
    
    # 原始模型推理
    print("原始模型推理...")
    original_results = original_model(image)
    
    # RKNN模型推理
    print("RKNN模型推理...")
    input_data, scale, offset = preprocess_image(image)
    rknn_outputs = rknn.inference(inputs=[input_data])
    rknn_boxes, rknn_scores, rknn_class_ids = postprocess_output(rknn_outputs, scale, offset)
    
    # 比较结果
    print(f"\n精度对比结果:")
    print(f"原始模型检测目标数: {len(original_results.pandas().xyxy[0])}")
    print(f"RKNN模型检测目标数: {len(rknn_boxes)}")
    
    # 详细对比 (需要进一步实现)
    # ...
    
    rknn.release()

if __name__ == "__main__":
    compare_accuracy()

常见问题和解决方案

运行问题排查

# 1. 检查NPU驱动
lsmod | grep rknpu
dmesg | grep -i npu

# 2. 检查Python环境
python3 -c "from rknnlite.api import RKNNLite; print('OK')"

# 3. 检查模型文件
file yolov5s.rknn
ls -lh yolov5s.rknn

# 4. 检查摄像头
v4l2-ctl --list-devices
ls /dev/video*

# 5. 内存使用监控
free -h
top -p $(pgrep python3)

性能优化建议

# 1. 多线程优化
import threading
import queue

# 2. 内存复用
# 预分配输入输出缓冲区

# 3. 批处理
# 如果支持,使用batch推理

# 4. 预处理优化
# 使用OpenCV的DNN模块进行预处理

# 5. 后处理优化
# 使用向量化操作替代循环

总结

通过本章的学习,您已经成功运行了官方的YOLOv5示例,包括:

  1. 获取官方Demo: 下载预编译模型和示例代码
  2. 板端运行: 在GM-3568JHF开发板上运行图片检测和实时摄像头检测
  3. PC端仿真: 在PC上进行模型仿真验证

这为后续的模型转换和自定义应用开发奠定了基础。下一章将详细介绍如何进行模型转换,将您自己的模型部署到RK3568 NPU上。

在 GitHub 上编辑此页
上次更新:
贡献者: jxc
Prev
02 开发环境搭建