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
在这里插入图片描述

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐