本章节在 Lockzhiner Vision Module 上基于paddleseg模型, 实现了一个PP-HumanSeg人像分割案例。
人像分割是一种基于计算机视觉的技术,通过深度学习算法精准识别图像或视频中的人物主体,将其与背景进行像素级分离。该技术可实时运行于移动端及嵌入式设备,广泛应用于虚拟背景、智能抠图、视频会议美颜等场景,支持复杂光照、多样姿态和遮挡情况下的高精度分割,兼顾处理速度与效果。
目前对于实现人像分割任务的方法有很多,下面介绍几种常用的人像分割实现方法。
这些方法各有优势,其中在工业部署方面PP-HumanSeg(精度与速度平衡)和BiSeNet(高性价比)更适合,可配合OpenCV后处理优化边缘。
#include "rknpu2_backend/rknpu2_backend.h"
ockzhiner_vision_module::vision::RKNPU2Backend backend;
bool Initialize(const std::string &model_path, const std::string ¶m_path = "") override;
bool Run();
const std::vector<rknn_tensor_attr>& GetInputAttrs() const;
const std::vector<rknn_tensor_mem*>& GetInputMemories() const;
开始
│
├── 参数检查 (argc == 3)
│ └── 错误 → 输出Usage并退出
│
├── 初始化 RKNN 后端
│ ├── 加载模型
│ └── 初始化失败 → 错误退出
│
├── 加载与预处理输入图像
│ ├── 读取图像文件
│ ├── 获取输入属性
│ ├── 调用 preprocess() 函数
│ ├── 调整尺寸和颜色空间
│ ├── 量化图像数据
│ └── 验证尺寸匹配
│ └── 预处理失败 → 错误退出
│
├── 执行推理
│ ├── 拷贝预处理后的图像数据到输入内存
│ ├── 执行推理
│ └── 推理失败 → 错误退出
│
├── 后处理
│ ├── 获取输出属性及内存
│ ├── 调用 postprocess() 函数
│ ├── 解析输出数据生成概率图
│ ├── 自适应阈值分割
│ ├── 多尺度形态学处理
│ ├── 智能边缘优化
│ └── 多模态结果融合
│
├── 结果展示与保存
│ ├── 计算推理时间
│ ├── 生成并保存结果图像
│ ├── 显示原始图像、掩膜及结果图像
│
└── 程序结束
backend.Initialize(model_path)
const auto& input_attrs = backend.GetInputAttrs();
const auto& output_attrs = backend.GetOutputAttrs();
backend.Run()
自定义函数说明
cv::Mat preprocess(const cv::Mat& image, const std::vector<size_t>& input_dims)
cv::Mat postprocess(const rknn_tensor_mem* output_mem,
const std::vector<size_t>& output_dims,
const cv::Size& target_size)
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 .
)
使用 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目录下生成可执行文件。
chmod 777 Test-pp_humanseg
# 对人像进行分割
./Test-pp_humanseg pp-humanseg.rknn image_path
由于分割的模型很小,并且在模型转换过程中会有精度损失,所以在测试的时候尽量选择背景比较纯净的图像效果比较好。
通过上述内容,我们成功实现了一个简单的人像分割的例子,包括:
加载图像分割的rknn模型和待分割图像。
图像预处理和模型推理。
图像后处理并保存分割结果。
注意在此历程中,分割效果不一定非常理想,如有实际应用场景,需要优化可以在凌智视觉模块官方仓库**凌智视觉模块** 提交Issue
遇到技术问题?请到凌智视觉模块官方仓库**凌智视觉模块** 提交Issue