RV1106 图像分割 基于paddleseg

RV1106 图像分割 基于paddleseg

  • 图像分割
    • 1. 基本知识简介
      • 1.1 人像分割简介
      • 1.2 人像分割常用方法
    • 2. C++ API 文档
      • 2.1 RKNPU2Backend 类
        • 2.1.1 头文件
        • 2.1.2 构造类函数
        • 2.1.3 Initialize 函数
        • 2.1.4 Run 函数
        • 2.1.5 GetInputAttrs 函数
        • 2.1.6 GetOutputAttrs 函数
    • 3. PP-Humanseg人像分割代码解析
      • 3.1 流程图
      • 3.2 核心代码解析
      • 3.3 完整代码实现
    • [点击获取完整源码](https://gitee.com/LockzhinerAI/LockzhinerVisionModule/blob/master/Cpp_example/D08_pp_humanseg/README.md)
    • 4. 编译调试
      • 4.1 编译环境搭建
      • 4.2 Cmake介绍
      • 4.3 编译项目
    • 5. 执行结果
      • 5.1 运行前准备
      • 5.2 运行过程
      • 5.3 运行效果
        • 5.3.1 人像分割结果
        • 5.3.2 注意事项
    • 6. 总结
    • **开发者生态**:
    • **问题反馈**:

图像分割

本章节在 Lockzhiner Vision Module 上基于paddleseg模型, 实现了一个PP-HumanSeg人像分割案例。

1. 基本知识简介

1.1 人像分割简介

人像分割是一种基于计算机视觉的技术,通过深度学习算法精准识别图像或视频中的人物主体,将其与背景进行像素级分离。该技术可实时运行于移动端及嵌入式设备,广泛应用于虚拟背景、智能抠图、视频会议美颜等场景,支持复杂光照、多样姿态和遮挡情况下的高精度分割,兼顾处理速度与效果。

1.2 人像分割常用方法

目前对于实现人像分割任务的方法有很多,下面介绍几种常用的人像分割实现方法。

  • ​​传统算法(如GrabCut)​:基于颜色直方图与图割优化,适合简单背景,计算量小但精度有限。
  • U-Net系列:编码器-解码器结构,医学图像起家,适合精细边缘,需较高算力。
  • ​DeepLab系列:采用空洞卷积扩大感受野,擅长复杂场景,模型较大。
  • ​​BiSeNet​:双分支结构平衡速度与精度,实时分割首选,移动端友好。
  • ​​PP-HumanSeg​:百度自研轻量模型,专为人像优化,支持半监督训练,RKNN部署效率高。

这些方法各有优势,其中在工业部署方面PP-HumanSeg(精度与速度平衡)和BiSeNet(高性价比)更适合,可配合OpenCV后处理优化边缘。


2. C++ API 文档

2.1 RKNPU2Backend 类

2.1.1 头文件
#include "rknpu2_backend/rknpu2_backend.h"
  • 作用:创建一个RKNPU2Backend类,用于实现对rknn模型的处理。
2.1.2 构造类函数
ockzhiner_vision_module::vision::RKNPU2Backend backend;
  • 作用:创建一个RKNPU2Backen类型的对象实例,用于实现人像分割。
  • 参数说明:
  • 返回值:
2.1.3 Initialize 函数
bool Initialize(const std::string &model_path, const std::string &param_path = "") override;
  • 作用:初始化 RKNN 模型,加载模型文件和可选参数文件,完成推理引擎的准备工作。
  • 参数说明:
    • model_path:必需参数,RKNN 模型文件路径(.rknn 格式)。
    • param_path:可选参数,额外参数文件路径(某些场景下用于补充模型配置,默认空字符串)。
  • 返回值:返回ture/false,表示模型初始化是否成功。
2.1.4 Run 函数
bool Run();
  • 作用:执行模型推理计算,驱动输入数据通过模型计算得到输出结果。
  • 参数说明:
  • 返回值:
    • true:推理执行成功。
    • false:推理失败(可能原因:输入数据未准备、内存不足等)。
2.1.5 GetInputAttrs 函数
const std::vector<rknn_tensor_attr>& GetInputAttrs() const;
  • 作用:获取模型所有输入张量的属性信息(维度/形状、数据类型、量化参数等)。
  • 参数说明:
  • 返回值:常量引用形式的 rknn_tensor_attr 向量,包含输入张量属性。
2.1.6 GetOutputAttrs 函数
const std::vector<rknn_tensor_mem*>& GetInputMemories() const;
  • 作用:获取模型所有输出张量的属性信息。
  • 参数说明:无
  • 返回值:常量引用形式的 rknn_tensor_attr 向量,包含输出张量属性。

3. PP-Humanseg人像分割代码解析

3.1 流程图

开始
│
├── 参数检查 (argc == 3)
│   └── 错误 → 输出Usage并退出
│
├── 初始化 RKNN 后端
│   ├── 加载模型
│   └── 初始化失败 → 错误退出
│
├── 加载与预处理输入图像
│   ├── 读取图像文件
│   ├── 获取输入属性
│   ├── 调用 preprocess() 函数
│       ├── 调整尺寸和颜色空间
│       ├── 量化图像数据
│       └── 验证尺寸匹配
│   └── 预处理失败 → 错误退出
│
├── 执行推理
│   ├── 拷贝预处理后的图像数据到输入内存
│   ├── 执行推理
│       └── 推理失败 → 错误退出
│
├── 后处理
│   ├── 获取输出属性及内存
│   ├── 调用 postprocess() 函数
│       ├── 解析输出数据生成概率图
│       ├── 自适应阈值分割
│       ├── 多尺度形态学处理
│       ├── 智能边缘优化
│       └── 多模态结果融合
│
├── 结果展示与保存
│   ├── 计算推理时间
│   ├── 生成并保存结果图像
│   ├── 显示原始图像、掩膜及结果图像
│
└── 程序结束

3.2 核心代码解析

  • 初始化模型
backend.Initialize(model_path)
  • 获取输入输出属性
const auto& input_attrs = backend.GetInputAttrs();
const auto& output_attrs = backend.GetOutputAttrs();
  • 对输入图像进行推理
backend.Run()

自定义函数说明

  • pp-humanseg输入预处理
cv::Mat preprocess(const cv::Mat& image, const std::vector<size_t>& input_dims) 
  • 作用:对输入图像进行预处理操作,包括 ​​尺寸调整​​、​​颜色空间转换​​ 和 ​​量化处理​​,使其符合 RKNN 模型的输入要求。
  • 参数说明:
    • image:输入图像(BGR 格式的 cv::Mat 对象)。
    • input_dims:模型输入张量的维度定义(需满足 [1, H, W, 3] 的 NHWC 格式)。
  • 返回值:
    • 返回预处理后的量化张量(cv::Mat,数据类型为 CV_8S)。
    • 若输入维度不合法,返回空矩阵(cv::Mat())并报错。
  • pp-humanseg输入后处理
cv::Mat postprocess(const rknn_tensor_mem* output_mem, 
                   const std::vector<size_t>& output_dims,
                   const cv::Size& target_size) 
  • 作用:将模型输出的原始张量转换为高精度分割掩膜,包含 ​​概率解码​​、​​动态阈值分割​​、​​形态学优化​​和​​边缘增强​​等步骤,最终生成与原始图像尺寸匹配的二值化掩膜。
  • 参数说明:
    • output_mem:模型输出的内存指针,包含量化后的原始数据。
    • output_dims:模型输出的维度信息,需满足 [1, 2, H, W] 的 NCHW 格式。
    • target_size:目标输出尺寸。
  • 返回值:返回优化后的二值化掩膜。

3.3 完整代码实现

点击获取完整源码

4. 编译调试

4.1 编译环境搭建

  • 请确保你已经按照 开发环境搭建指南 正确配置了开发环境。
  • 同时已经正确连接开发板。

4.2 Cmake介绍

cmake_minimum_required(VERSION 3.10)

project(pp_humanseg)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 定义项目根目录路径
set(PROJECT_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../..")
message("PROJECT_ROOT_PATH = " ${PROJECT_ROOT_PATH})

include("${PROJECT_ROOT_PATH}/toolchains/arm-rockchip830-linux-uclibcgnueabihf.toolchain.cmake")

# 定义 OpenCV SDK 路径
set(OpenCV_ROOT_PATH "${PROJECT_ROOT_PATH}/third_party/opencv-mobile-4.10.0-lockzhiner-vision-module")
set(OpenCV_DIR "${OpenCV_ROOT_PATH}/lib/cmake/opencv4")
find_package(OpenCV REQUIRED)
set(OPENCV_LIBRARIES "${OpenCV_LIBS}")

# 定义 LockzhinerVisionModule SDK 路径
set(LockzhinerVisionModule_ROOT_PATH "${PROJECT_ROOT_PATH}/third_party/lockzhiner_vision_module_sdk")
set(LockzhinerVisionModule_DIR "${LockzhinerVisionModule_ROOT_PATH}/lib/cmake/lockzhiner_vision_module")
find_package(LockzhinerVisionModule REQUIRED)

# 配置rknpu2
set(RKNPU2_BACKEND_BASE_DIR "${LockzhinerVisionModule_ROOT_PATH}/include/lockzhiner_vision_module/vision/deep_learning/runtime")
if(NOT EXISTS ${RKNPU2_BACKEND_BASE_DIR})
    message(FATAL_ERROR "RKNPU2 backend base dir missing: ${RKNPU2_BACKEND_BASE_DIR}")
endif()


add_executable(Test-pp_humanseg pp_humanseg.cc)
target_include_directories(Test-pp_humanseg PRIVATE ${LOCKZHINER_VISION_MODULE_INCLUDE_DIRS}  ${rknpu2_INCLUDE_DIRS} ${RKNPU2_BACKEND_BASE_DIR})
target_link_libraries(Test-pp_humanseg PRIVATE ${OPENCV_LIBRARIES} ${NCNN_LIBRARIES} ${LOCKZHINER_VISION_MODULE_LIBRARIES})

install(
    TARGETS Test-pp_humanseg
    RUNTIME DESTINATION .  
)

4.3 编译项目

使用 Docker Destop 打开 LockzhinerVisionModule 容器并执行以下命令来编译项目。

# 进入Demo所在目录
cd /LockzhinerVisionModuleWorkSpace/LockzhinerVisionModule/Cpp_example/D08_pp_humanseg
# 创建编译目录
rm -rf build && mkdir build && cd build
# 配置交叉编译工具链
export TOOLCHAIN_ROOT_PATH="/LockzhinerVisionModuleWorkSpace/arm-rockchip830-linux-uclibcgnueabihf"
# 使用cmake配置项目
cmake ..
# 执行编译项目
make -j8 && make install

在执行完上述命令后,会在build目录下生成可执行文件。


5. 执行结果

5.1 运行前准备

  • 请确保你已经下载了 凌智视觉模块人像分割模型

5.2 运行过程

chmod 777 Test-pp_humanseg
# 对人像进行分割
./Test-pp_humanseg pp-humanseg.rknn image_path

5.3 运行效果

5.3.1 人像分割结果
  • 原始图像

  • 分割结果

RV1106 图像分割 基于paddleseg_第1张图片

5.3.2 注意事项

由于分割的模型很小,并且在模型转换过程中会有精度损失,所以在测试的时候尽量选择背景比较纯净的图像效果比较好。


6. 总结

通过上述内容,我们成功实现了一个简单的人像分割的例子,包括:

  • 加载图像分割的rknn模型和待分割图像。

  • 图像预处理和模型推理。

  • 图像后处理并保存分割结果。

  • 注意在此历程中,分割效果不一定非常理想,如有实际应用场景,需要优化可以在凌智视觉模块官方仓库**凌智视觉模块** 提交Issue

开发者生态

  • 订阅 更新日志 获取新模型支持

问题反馈

遇到技术问题?请到凌智视觉模块官方仓库**凌智视觉模块** 提交Issue

你可能感兴趣的:(凌智视觉模块(RV1106),目标检测,计算机视觉,opencv,人工智能)