RK3588部署yolov11记录
RK3588部署yolov11记录
整体环境:
python = 3.9
ubuntu
一、模型训练
1.环境配置
按照标准的U版本Yolo环境进行配置即可
2.模型训练
train.py代码如下:
from ultralytics import YOLO
import argparse
import yaml
import os
import shutil
from pathlib import Path
from datetime import datetime
def get_next_run_number(base_dir):
base_path = Path(base_dir)
if not base_path.exists():
return 1
run_numbers = []
for item in base_path.iterdir():
if item.is_dir() and item.name.startswith('run'):
try:
num = int(item.name[3:])
run_numbers.append(num)
except ValueError:
continue
if not run_numbers:
return 1
return max(run_numbers) + 1
def create_run_directory(base_dir, run_number):
run_dir = Path(base_dir) / f"run{run_number}"
run_dir.mkdir(parents=True, exist_ok=True)
subdirs = ['weights', 'logs', 'configs', 'results']
for subdir in subdirs:
(run_dir / subdir).mkdir(exist_ok=True)
return run_dir
def save_training_config(run_dir, args_dict):
config_file = run_dir / 'configs' / 'training_config.yaml'
with open(config_file, 'w', encoding='utf-8') as f:
yaml.dump(args_dict, f, default_flow_style=False, allow_unicode=True)
print(f"训练配置已保存到: {config_file}")
return config_file
def save_training_summary(run_dir, summary_dict):
summary_file = run_dir / 'training_summary.txt'
with open(summary_file, 'w', encoding='utf-8') as f:
f.write("=" * 60 + "\n")
f.write("YOLOv11 烟火检测训练摘要\n")
f.write("=" * 60 + "\n\n")
f.write(f"训练时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
for key, value in summary_dict.items():
f.write(f"{key}: {value}\n")
f.write("\n" + "=" * 60 + "\n")
print(f"训练摘要已保存到: {summary_file}")
return summary_file
def train_yolo(data_yaml, model_size='n', epochs=100, batch_size=16, img_size=640, device='0', hyp_yaml=None, base_runs_dir='runs'):
model_name = f'yolo11{model_size}.pt'
print(f"加载预训练模型: {model_name}")
model = YOLO(model_name)
run_number = get_next_run_number(base_runs_dir)
run_dir = create_run_directory(base_runs_dir, run_number)
print(f"创建训练目录: {run_dir}")
args_dict = {
'model': model_name,
'data': data_yaml,
'epochs': epochs,
'batch': batch_size,
'imgsz': img_size,
'device': device,
'run_number': run_number,
'run_directory': str(run_dir),
'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
}
if hyp_yaml and hyp_yaml.lower() != 'none':
print(f"使用数据增强配置: {hyp_yaml}")
with open(hyp_yaml, 'r', encoding='utf-8') as f:
hyp_params = yaml.safe_load(f)
args_dict['hyp_config'] = hyp_yaml
args_dict.update(hyp_params)
hyp_dest = run_dir / 'configs' / 'hyp.yaml'
shutil.copy2(hyp_yaml, hyp_dest)
print(f"数据增强配置已复制到: {hyp_dest}")
save_training_config(run_dir, args_dict)
print(f"\n开始训练...")
print(f"数据集配置: {data_yaml}")
print(f"训练轮数: {epochs}")
print(f"批次大小: {batch_size}")
print(f"图像大小: {img_size}")
print(f"设备: {device}")
print(f"运行目录: {run_dir}")
train_args = {
'data': data_yaml,
'epochs': epochs,
'batch': batch_size,
'imgsz': img_size,
'device': device,
'project': str(run_dir),
'name': 'train',
'exist_ok': True,
'patience': 50,
'save': True,
'plots': True,
'verbose': True
}
if hyp_yaml and hyp_yaml.lower() != 'none':
train_args.update(hyp_params)
results = model.train(**train_args)
print("\n训练完成!")
summary_dict = {
'模型': model_name,
'数据集': data_yaml,
'训练轮数': epochs,
'批次大小': batch_size,
'图像大小': img_size,
'设备': device,
'运行编号': run_number,
'最佳模型': f"{run_dir}/train/weights/best.pt",
'最后模型': f"{run_dir}/train/weights/last.pt",
'训练结果目录': f"{run_dir}/train"
}
save_training_summary(run_dir, summary_dict)
print(f"\n训练文件保存在:")
print(f" - 权重文件: {run_dir}/train/weights/")
print(f" - 训练日志: {run_dir}/train/")
print(f" - 配置文件: {run_dir}/configs/")
print(f" - 训练摘要: {run_dir}/training_summary.txt")
return results, run_dir
def main():
parser = argparse.ArgumentParser(description='YOLOv11训练脚本')
parser.add_argument('--data', type=str, default='/home/chenjun0310/SmokeAndFire_Yolov11/yolov11/data.yaml',
help='数据集YAML配置文件路径')
parser.add_argument('--model', type=str, default='s',
choices=['n', 's', 'm', 'l', 'x'],
help='模型大小: n(nano), s(small), m(medium), l(large), x(xlarge)')
parser.add_argument('--epochs', type=int, default=150,
help='训练轮数')
parser.add_argument('--batch', type=int, default=128,
help='批次大小')
parser.add_argument('--imgsz', type=int, default=640,
help='图像大小')
parser.add_argument('--device', type=str, default='0',
help='训练设备: 0,1,2,3 (GPU) 或 cpu')
parser.add_argument('--hyp', type=str, default='/home/chenjun0310/SmokeAndFire_Yolov11/yolov11/hyp.yaml',
help='数据增强配置文件路径')
parser.add_argument('--runs_dir', type=str, default='/home/chenjun0310/SmokeAndFire_Yolov11/yolov11/runs',
help='训练运行目录')
args = parser.parse_args()
print("=" * 60)
print("YOLOv11 烟火检测训练")
print("=" * 60)
results, run_dir = train_yolo(
data_yaml=args.data,
model_size=args.model,
epochs=args.epochs,
batch_size=args.batch,
img_size=args.imgsz,
device=args.device,
hyp_yaml=args.hyp,
base_runs_dir=args.runs_dir
)
print("=" * 60)
print(f"训练完成!所有文件已保存到: {run_dir}")
print("=" * 60)
if __name__ == "__main__":
main()
其中,data.yaml文件如下:
path: /home/chenjun0310/fireSmoke
train: images/train
val: images/val
test: images/test
names:
0: fire
1: Smoke
hyp.yaml文件如下
# YOLOv11 数据增强配置文件
# 数据增强参数说明
# HSV颜色空间增强
hsv_h: 0.015 # 色调增强范围 (0-1),默认0.015
hsv_s: 0.7 # 饱和度增强范围 (0-1),默认0.7
hsv_v: 0.4 # 明度增强范围 (0-1),默认0.4
# 几何变换增强
degrees: 0.0 # 旋转角度范围 (度),默认0.0
translate: 0.1 # 平移范围 (0-1),默认0.1
scale: 0.5 # 缩放范围 (0-1),默认0.5
shear: 0.0 # 剪切角度范围 (度),默认0.0
perspective: 0.0 # 透视变换范围 (0-1),默认0.0
# 翻转增强
flipud: 0.0 # 上下翻转概率 (0-1),默认0.0
fliplr: 0.5 # 左右翻转概率 (0-1),默认0.5
# 高级增强技术
mosaic: 0.5 # 马赛克增强概率 (0-1),默认1.0
mixup: 0.3 # 混合增强概率 (0-1),默认0.0
cutmix: 0.3 # 剪切混合增强概率 (0-1),默认0.0
copy_paste: 0.3 # 复制粘贴增强概率 (0-1),默认0.0
# 自动增强
auto_augment: randaugment # 自动增强方法: randaugment, autoaugment, None
erasing: 0.4 # 随机擦除概率 (0-1),默认0.4
# 其他增强参数
bgr: 0.0 # BGR通道翻转概率 (0-1),默认0.0
close_mosaic: 10 # 最后N个epoch关闭马赛克增强,默认10
# 训练超参数 (非数据增强)
lr0: 0.01 # 初始学习率
lrf: 0.01 # 最终学习率因子
momentum: 0.937 # SGD动量
weight_decay: 0.0005 # 权重衰减
warmup_epochs: 3.0 # 预热轮数
warmup_momentum: 0.8 # 预热动量
warmup_bias_lr: 0.1 # 预热偏置学习率
# 损失函数权重
box: 7.5 # 边界框损失权重
cls: 0.5 # 分类损失权重
dfl: 1.5 # 分布焦点损失权重
YOLO11.yaml文件如下
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
# Ultralytics YOLO11 object detection model with P3/8 - P5/32 outputs
# Model docs: https://docs.ultralytics.com/models/yolo11
# Task docs: https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 2 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolo11n.yaml' will call yolo11.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.50, 0.25, 1024] # summary: 181 layers, 2624080 parameters, 2624064 gradients, 6.6 GFLOPs
s: [0.50, 0.50, 1024] # summary: 181 layers, 9458752 parameters, 9458736 gradients, 21.7 GFLOPs
m: [0.50, 1.00, 512] # summary: 231 layers, 20114688 parameters, 20114672 gradients, 68.5 GFLOPs
l: [1.00, 1.00, 512] # summary: 357 layers, 25372160 parameters, 25372144 gradients, 87.6 GFLOPs
x: [1.00, 1.50, 512] # summary: 357 layers, 56966176 parameters, 56966160 gradients, 196.0 GFLOPs
# YOLO11n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 2, C3k2, [256, False, 0.25]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 2, C3k2, [512, False, 0.25]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 2, C3k2, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 2, C3k2, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 2, C2PSA, [1024]] # 10
# YOLO11n head
head:
- [-1, 1, nn.Upsample, [None, 2, "nearest"]]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 2, C3k2, [512, False]] # 13
- [-1, 1, nn.Upsample, [None, 2, "nearest"]]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 2, C3k2, [256, False]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 2, C3k2, [512, False]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 2, C3k2, [1024, True]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)
二、模型转换
转换主要包括两个部分。pt–>onnx和onnx—>rknn
1.pt转onnx部分
环境主要是使用该git库:https://github.com/airockchip/ultralytics_yolo11
修改./ultralytics/cfg/default.yaml中的模型路径
回到该项目目录下依次输入:
export PYTHONPATH=./
python ./ultralytics/engine/exporter.py
在这里插入图片描述
2.onnx转rknn部分
这一部分要配置rknn-toolkit2环境,下载rknn-toolkit2:rknn-toolkit2
版本需要留意一下,需要与后面的rknn_model_zoo版本一致,这里我使用的是2.3.2的版本
先创建一个python3.9的环境,单独给rknn-toolkit2使用。
conda create -n rknn-toolkit2 python=3.9 #创建虚拟环境
conda activate rknn-toolkit2 #激活该环境
cd rknn-toolkit2/rknn-toolkit2/packages/x86_64/ #进入该目录下
pip install -r requirements_cp39-2.3.2.txt -i https://pypi.tuna.tsinghua.edu.cn/simple #安装依赖
pip install rknn_toolkit2-2.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
安装结束后,在该虚拟环境下,终端输入:
from rknn.api import RKNN
3.下载rknn_model_zoo
该文件下载到PC端,rknn_model_zoo库中有相关的案例可以进行测试部署。
github链接:
https://github.com/airockchip/rknn_model_zoo.git
#git clone https://github.com/airockchip/rknn_model_zoo.git
但是下载会很慢。
更换:
git clone https://gitee.com/airockchip/rknn_model_zoo.git
不报错就是安装成功。
量化:需要选取一些图像,放置于dataset文件夹,然后新建dataset.txt文件,改txt文件中包含dataset文件夹下图像的绝对路径。
接下来利用rknn_model_zoo/examples/yolo11/python中的代码进行转换
在convert.py中修改dataset_path(量化图像路径)
在yolo11.py中修改
输入指令进行转换
python convert.py XXXX/FireAndSmoke1.onnx rk3588
XXXX/FireAndSmoke1.onnx修改模型路径
三、部署
部署整体流程:rknn_model_zoo的pc端,确认Pc端和开发板端的gcc版本是否匹配,pc端编译,编译后拷贝到开发板进行测试。
1.确认pc端和开发板端的gcc版本
我遇到的情况是PC 使用的是 Ubuntu 22.04 自带的 GCC 11.4.0。
这个版本的编译器默认生成的二进制文件需要 GLIBC 2.34+,而你的 RK3588 开发板(通常是 Ubuntu 18.04 或 20.04 基础)只有 GLIBC 2.27 或 2.31。
# 1. 创建一个目录存放工具链
mkdir -p ~/toolchains
cd ~/toolchains
# 2. 下载 Linaro GCC 7.5 (2019.12 版本),这个版本非常稳定且兼容老系统
# 如果 wget 速度慢,可以尝试用 curl 或者找国内镜像
wget https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/aarch64-linux-gnu/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz
# 3. 解压
tar -xf gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz
# 4. 确认解压后的文件夹名称 (通常是 gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu)
ls
后续自行安装,使用对应版本进行编译即可。
2.rknn_model_zoo/examples/yolo11/cpp代码修改
cpp文件夹中大概包含如下文件
CmakeList.txt修改
其中CmakeList.txt文件做了一点修改,修改为静态编译
文件路径:rknn_model_zoo/examples/yolo11/cpp/CMakeLists.txt
修改内容:
# 在set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")之后添加:
# 静态链接选项,避免GLIBC版本不兼容问题
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
完整修改:
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
# 静态链接选项,避免GLIBC版本不兼容问题
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
file(GLOB SRCS ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
完整文件如下:
cmake_minimum_required(VERSION 3.10)
project(rknn_yolo11_demo)
if (ENABLE_ASAN)
message(STATUS "BUILD WITH ADDRESS SANITIZER")
set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
set (CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
endif ()
set(rknpu_yolo11_file rknpu2/yolo11.cc)
if (TARGET_SOC STREQUAL "rv1106" OR TARGET_SOC STREQUAL "rv1103")
add_definitions(-DRV1106_1103)
set(rknpu_yolo11_file rknpu2/yolo11_rv1106_1103.cc)
#dma
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../3rdparty/allocator/dma)
endif()
if(TARGET_SOC STREQUAL "rk1808" OR TARGET_SOC STREQUAL "rv1109" OR TARGET_SOC STREQUAL "rv1126")
add_definitions(-DRKNPU1)
set(rknpu_yolo11_file rknpu1/yolo11.cc)
endif()
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../../3rdparty/ 3rdparty.out)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../../utils/ utils.out)
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
# 静态链接选项,避免GLIBC版本不兼容问题
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
file(GLOB SRCS ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
add_executable(${PROJECT_NAME}
main.cc
postprocess.cc
${rknpu_yolo11_file}
)
target_link_libraries(${PROJECT_NAME}
imageutils
fileutils
imagedrawing
${LIBRKNNRT}
dl
)
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
target_link_libraries(${PROJECT_NAME}
log
)
endif()
message(STATUS "!!!!!!!!!!!CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}")
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(${PROJECT_NAME} Threads::Threads)
endif()
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${LIBRKNNRT_INCLUDES}
)
# Currently zero copy only supports rknpu2, v1103/rv1103b/rv1106 supports zero copy by default
if (NOT (TARGET_SOC STREQUAL "rv1106" OR TARGET_SOC STREQUAL "rv1103" OR TARGET_SOC STREQUAL "rk1808"
OR TARGET_SOC STREQUAL "rv1109" OR TARGET_SOC STREQUAL "rv1126" OR TARGET_SOC STREQUAL "rv1103b"))
add_executable(${PROJECT_NAME}_zero_copy
main.cc
postprocess.cc
rknpu2/yolo11_zero_copy.cc
)
target_compile_definitions(${PROJECT_NAME}_zero_copy PRIVATE ZERO_COPY)
target_link_libraries(${PROJECT_NAME}_zero_copy
imageutils
fileutils
imagedrawing
${LIBRKNNRT}
dl
)
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
target_link_libraries(${PROJECT_NAME}_zero_copy
log
)
endif()
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(${PROJECT_NAME}_zero_copy Threads::Threads)
endif()
target_include_directories(${PROJECT_NAME}_zero_copy PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${LIBRKNNRT_INCLUDES}
)
install(TARGETS ${PROJECT_NAME}_zero_copy DESTINATION .)
endif()
install(TARGETS ${PROJECT_NAME} DESTINATION .)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../model/bus.jpg DESTINATION model)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../model/coco_80_labels_list.txt DESTINATION model)
file(GLOB RKNN_FILES "${CMAKE_CURRENT_SOURCE_DIR}/../model/*.rknn")
install(FILES ${RKNN_FILES} DESTINATION model)
postprocess.h修改
文件路径:rknn_model_zoo/examples/yolo11/cpp/postprocess.h
修改内容:
// 将OBJ_CLASS_NUM从80改为2
#define OBJ_CLASS_NUM 2
完整修改:
#define OBJ_NAME_MAX_SIZE 64
#define OBJ_NUMB_MAX_SIZE 128
#define OBJ_CLASS_NUM 2 // 修改这里:80 -> 2
#define NMS_THRESH 0.45
#define BOX_THRESH 0.25 // 置信度阈值,可根据需要调整
postprocess.cc修改
文件路径:rknn_model_zoo/examples/yolo11/cpp/postprocess.cc
修改内容:
// 将LABEL_NALE_TXT_PATH改为LABEL_NAME_TXT_PATH
// 原代码(错误):
ret = loadLabelName(LABEL_NALE_TXT_PATH, labels);
printf("Load %s failed!\n", LABEL_NALE_TXT_PATH);
// 修改后(正确):
ret = loadLabelName(LABEL_NAME_TXT_PATH, labels);
printf("Load %s failed!\n", LABEL_NAME_TXT_PATH);
这里labels_list.txt中的内容修改为你自己的模型的类别
#define LABEL_NAME_TXT_PATH "./model/labels_list.txt"
创建labels_list.txt
文件路径:rknn_model_zoo/examples/yolo11/model/labels_list.txt
写入类别即可。
3.编译项目
进入zoo目录
cd ../rknn_model_zoo
指定编译器
export GCC_COMPILER=/home/chenjun0310/toolchains/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu
进行编译
rm -rf build/build_rknn_yolo11_demo_rk3588_linux_aarch64_Release #首次编译需要在rknn_model_zoo目录下新建build
./build-linux.sh -t rk3588 -a aarch64 -d yolo11
编译结束后,会生成rknn_model_zoo/install文件夹
需要留意一下是否在lib文件夹下存在libstdc++.so.6和libstdc++.so.6.0.24这两个文件,如果没有的话,直接从gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/aarch64-linux-gnu/lib64中直接拷贝进去即可。
完整文件应该如install_1
4.RK3588开发板端
拷贝编译好的install文件夹到开发板上
在项目目录下依次输入
chmod +x rknn_yolo11_demo
chmod +x rknn_yolo11_demo_zero_copy
export LD_LIBRARY_PATH=./lib
./rknn_yolo11_demo model/yolov11s.rknn model/000155.jpg
输出图像为out.png
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)