尧图精选

使用 OpenCV DNN 运行 PaddlePaddle 模型:从 ResNet50 图像分类到 PaddleSeg 人像分割的完整落地指南

🕒 发布时间:2026/9/8 23:57:04 📁 来源:尧图网络
使用 OpenCV DNN 运行 PaddlePaddle 模型从 ResNet50 图像分类到 PaddleSeg 人像分割的完整落地指南【免费下载链接】opencvOpen Source Computer Vision Library项目地址: https://gitcode.com/GitHub_Trending/opencv31/opencv本文基于 OpenCV 官方示例目录 samples/dnn/dnn_model_runner/dnn_conversion/paddlepaddle/README.md 及其配套脚本系统讲解如何把 PaddlePaddle 生态PaddleHub / PaddleSeg训练好的模型转成 ONNX再通过 OpenCV 的 DNN 模块cv2.dnn.readNetFromONNX在纯 OpenCV 环境中完成推理。读完本文你将能复现「PaddlePaddle 图像分类」与「PaddleSeg 人像分割」两条从模型获取、格式转换到 OpenCV 推理可视化的完整链路并掌握预处理、输出节点名解析与分割后处理伪彩色映射 叠加可视化等关键工程细节。背景与适用场景PaddlePaddle 生态提供了丰富的预训练模型PaddleHub 可以一键加载 ResNet50 等图像分类模型PaddleSeg 提供了 HumanSeg 系列人像分割模型。当这些模型需要在 OpenCV 既有推理流水线中被复用例如与 OpenCV 的通用 DNN API、图像处理模块打通时最便捷的路径就是将 PaddlePaddle 模型导出为 ONNXOpen Neural Network Exchange中间格式用 OpenCV DNN 模块加载 ONNX 文件并执行推理。这样后续的预处理、推理和后处理全部可以基于cv2/numpy完成不再依赖 Paddle 运行时。本仓库在 dnn_conversion 目录下同时维护了 PaddlePaddle、PyTorch、TensorFlow 三个框架的同类示例本文聚焦其中的 paddlepaddle 子目录包含两份完整脚本paddle_resnet50.pyPaddleHub ResNet50 分类模型端到端示例paddle_humanseg.pyPaddleSeg HumanSeg 人像分割端到端示例。环境准备官方文档要求的最小依赖如下pip install paddlepaddle-gpu pip install paddlehub pip install paddle2onnx结合仓库中 dnn_conversion/requirements.txt 提供的版本参考标注了 Python 3.7.5 环境推荐关注以下版本约束依赖包版本要求仓库建议用途paddlepaddle/paddlepaddle-gpu 2.0.0PaddlePaddle 深度学习框架paddlehub 2.1.0加载预训练模型ResNet50 示例使用paddle2onnx 0.5.1Paddle 模型转 ONNX 的转换器onnx 1.7.0ONNX 运行时/模型校验paddleseg 2.0.0PaddleSeg 分割工具包获取 HumanSeg 模型时参考numpy 1.19.1张量与数组处理opencv-python需自行安装提供cv2.dnn模块无 GPU 时可把第一条命令替换为pip install paddlepaddleCPU 版。转换与推理示例本身只需要 CPU 即可运行GPU 包主要用于导出/验证阶段的便利性。示例一用 OpenCV 运行 PaddlePaddle ResNet50 图像分类进入示例目录后直接运行python paddle_resnet50.py整个流程分为三部分将 PaddlePaddle ResNet50 模型导出为 ONNX 格式使用cv2.dnn.readNetFromONNX加载模型文件预处理图像文件并完成推理。1.1 模型获取与 ONNX 导出脚本自动完成export_onnx_resnet50 函数通过 PaddleHub 自动下载并导出模型def export_onnx_resnet50(save_path): model hub.Module(nameresnet50_vd_imagenet_ssld) input_spec paddle.static.InputSpec( [1, 3, 224, 224], float32, image) paddle.onnx.export(model, save_path, input_spec[input_spec], opset_version10)关键参数说明hub.Module(nameresnet50_vd_imagenet_ssld)从 PaddleHub 加载基于 ImageNet 训练的 ResNet50-vd SSLD 蒸馏模型模型权重在首次运行时自动下载到本地 hub 缓存paddle.static.InputSpec([1, 3, 224, 224], float32, image)声明输入形状NCHW 1×3×224×224、类型float32、变量名image。这里显式给出固定 batch 与固定分辨率是 ONNX 导出能成功的必要条件paddle.onnx.export(..., opset_version10)使用 ONNX opset 10 导出。导出结果会写入当前目录模型文件名为save_path .onnx默认./resnet50.onnx同时会伴随生成可被readNetFromONNX忽略的辅助元数据文件。1.2 预处理、加载与推理主流程位于 paddle_resnet50.pynet cv.dnn.readNetFromONNX(save_path .onnx) im preprocess(image_file) # shape: (1, 3, 224, 224) net.setInput(im) result net.forward([save_infer_model/scale_0.tmp_0])其中preprocess()复用了 PaddleHub vision 的 transforms 管线并使用np.expand_dims把单张图扩展出 batch 维transforms T.Compose([ T.Resize((256, 256)), T.CenterCrop(224), T.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225])], to_rgbTrue) return np.expand_dims(transforms(image_path), axis0)这里的预处理与 ImageNet 训练约定完全一致先缩放到 256×256再做 224×224 中心裁剪最后使用 ImageNet 的均值/标准差做标准化并统一转换为 RGB 通道顺序。需要特别留意输出节点名save_infer_model/scale_0.tmp_0这是 Paddle 静态图保存推理模型时自动生成的 scale 输出名。net.forward(...)传入该名字即可精确取出分类 logits。1.3 结果解析class_id np.argmax(result[0]) label labels[class_id] print(Predict Category: {}.format(label))labels来自仓库自带的 ImageNet 1000 类标签文件 labels.txt测试图片为本目录下的 data/cat.jpg。对网络输出做argmax后按下标查表即可得到类似tiger cat的预测类别。示例二用 OpenCV 运行 PaddleSeg HumanSeg 人像分割人像分割与分类的最大区别在于输出是逐像素的类别图每个像素一个类别 id需要额外的后处理来生成伪彩色分割掩膜并与原图叠加。PaddleSeg 提供了 HumanSeg 系列人像分割模型运行示例前需要先拿到 Paddle 推理模型并转换为 ONNX。2.1 获取 Paddle 推理模型HumanSeg HRNet18-small 推理模型以 zip 压缩包形式提供原文档给出的是下载解压命令# 模型压缩包来自 PaddleSeg HumanSeg 官方发布资源 wget humanseg_hrnet18_small_v1.zip 官方下载地址 unzip humanseg_hrnet18_small_v1.zip解压后的目录中包含 Paddle 推理模型的标准产物转换时会用到其中两个关键文件model.pdmodel网络结构文件对应--model_filenamemodel.pdiparams网络权重文件对应--params_filename。注意文档原文提示导出的模型必须具有固定的输入形状fixed input shape当前转换工具链不支持动态形状。因此请确保下载/导出的 HumanSeg 模型输入是固定分辨率本示例预处理按 192×192 进行否则paddle2onnx会报错或产出不可用模型。2.2 使用 paddle2onnx 转换为 ONNXpaddle2onnx --model_dir humanseg_hrnet18_small_v1 \ --model_filename model.pdmodel \ --params_filename model.pdiparams \ --opset_version 11 \ --save_file humanseg_hrnet18_tiny.onnx各参数含义如下参数值含义--model_dirhumanseg_hrnet18_small_v1Paddle 推理模型所在目录--model_filenamemodel.pdmodel网络结构文件名--params_filenamemodel.pdiparams权重参数文件名--opset_version11目标 ONNX opset 版本--save_filehumanseg_hrnet18_tiny.onnx输出 ONNX 文件路径转换成功后当前目录下会生成humanseg_hrnet18_tiny.onnx供下一步 OpenCV 加载使用。注意该转换使用 opset 11而第一个示例中 PaddleHub 内部导出用的是 opset 10两者各自可用互不冲突。2.3 运行人像分割 demopython paddle_humanseg.py处理流程同样分为三步使用cv2.dnn.readNetFromONNX加载 ONNX 模型预处理输入图片并执行推理后处理推理结果并可视化输出。2.4 预处理与推理细节paddle_humanseg.py 默认从脚本所在目录出发读取测试图../../../../data/messi5.jpg对应仓库根目录下的 samples/data/messi5.jpg并加载humanseg_hrnet18_tiny.onnxtransforms T.Compose([ T.Resize((192, 192)), T.Normalize(mean[0.5, 0.5, 0.5], std[0.5, 0.5, 0.5]) ], to_rgbTrue) return np.expand_dims(transforms(image_path), axis0)人像分割使用与分类不同的归一化均值和标准差均取0.5即把像素映射到[-1, 1]输入尺寸为 192×192。推理部分net cv.dnn.readNetFromONNX(humanseg_hrnet18_tiny.onnx) net.setInput(im) result net.forward([save_infer_model/scale_0.tmp_1])与分类示例相比分割模型的输出节点名是save_infer_model/scale_0.tmp_1同样来自 Paddle 推理模型自动生成的 scale 命名务必与模型实际输出名保持一致否则forward取不到结果。2.5 分割后处理与可视化推理输出result的形状为(1, num_classes, 192, 192)。后处理代码对每个像素取类别 argmax 得到 192×192 的分割索引图再放大回原图尺寸image cv.imread(img_path) r, c, _ image.shape result np.argmax(result[0], axis1).astype(np.uint8) result cv.resize(result[0, :, :], dsize(c, r), interpolationcv.INTER_NEAREST)注意这里必须使用cv.INTER_NEAREST最近邻插值做上采样——分割图是离散的类别标签若用双线性插值会在类别边界产生伪标签。随后进入可视化阶段visualize()先生成一张可支持任意类别数的调色板再把分割索引图转换为伪彩色图最后与原图按权重叠加get_color_map_list(num_classes)按位算法为每个类别 id 生成 RGB 三元组构成颜色查找表cv.LUT(result, color_map[:, i])用 OpenCV 查表LUT分别映射 R/G/B 三个通道cv.addWeighted(im, weight, pseudo_img, 1 - weight, 0)将原图与伪彩色分割图按weight0.6混合得到半透明的分割叠加效果。最终结果写入data/result_test_human.jpg可从 paddlepaddle/data/result_test_human.jpg 查看实际分割可视化效果。人像分割可视化效果对比左侧为原始输入图右侧为 OpenCV 推理并叠加伪彩色掩膜后的分割结果OpenCV DNN 加载 ONNX 的底层依据两个示例最终都收敛到同一个 APIcv2.dnn.readNetFromONNX。其 C 声明定义在 modules/dnn/include/opencv2/dnn/dnn.hpp提供三个重载版本分别支持从本地文件路径、内存字节缓冲区和std::vectoruchar加载readNetFromONNX(const String onnxFile, int engine ENGINE_AUTO)readNetFromONNX(const char* buffer, size_t sizeBuffer, int engine ENGINE_AUTO)readNetFromONNX(const std::vectoruchar buffer, int engine ENGINE_AUTO)。从源码结构看返回类型是通用的cv::dnn::Net这意味着 ONNX 只是 OpenCV DNN 支持的众多网络载体之一——DNN 模块会根据模型来源自动分派到 TensorFlow、Caffe 等对应读取函数参见 dnn.hpp 中关于readNet的描述。一旦进入Net后续setInput、forward、getPerfProfile等推理与性能分析接口对所有来源的模型完全一致。这正是「Paddle 模型转 ONNX 后无缝接入 OpenCV」的底层原因。运行目录与文件依赖一览复现本文示例需要关心以下相对路径关系从仓库根目录出发用途路径分类示例脚本samples/dnn/dnn_model_runner/dnn_conversion/paddlepaddle/paddle_resnet50.py分割示例脚本samples/dnn/dnn_model_runner/dnn_conversion/paddlepaddle/paddle_humanseg.py分类输入图片paddlepaddle/data/cat.jpgImageNet 标签表paddlepaddle/data/labels.txt分割输入图片原图samples/data/messi5.jpg分割可视化输出paddlepaddle/data/result_test_human.jpg框架转换相关示例总入口samples/dnn/dnn_model_runner/dnn_conversion统一依赖版本参考samples/dnn/dnn_model_runner/dnn_conversion/requirements.txt由于paddle_resnet50.py与paddle_humanseg.py使用了相对当前脚本目录的路径如./data/cat.jpg、../../../../data/messi5.jpg请在 paddlepaddle 示例目录内直接运行脚本否则需同步调整这些路径。同理paddle_humanseg.py期望humanseg_hrnet18_tiny.onnx位于其运行目录下即转换命令的--save_file输出位置。常见问题与排错要点转换报动态形状相关错误paddle2onnx 目前不支持动态输入。请确保原始 Paddle 模型输入为固定 shape如1×3×192×192并在导出/下载模型时即采用固定分辨率版本。net.forward(...)取不到输出分类示例用save_infer_model/scale_0.tmp_0分割示例用save_infer_model/scale_0.tmp_1。这两个名称来源于 Paddle 静态图推理模型的自动命名。若换用其他模型应先打印 ONNX 输出节点名如用net.getUnconnectedOutLayersNames()确认实际名称再传入forward。分割结果边缘出现杂色点大概率是放大分割索引图时未使用最近邻插值导致类别标签被插值成中间值。务必显式指定interpolationcv.INTER_NEAREST。预处理不一致导致精度异常分类需 ImageNet 均值/标准差0.485/0.456/0.406 与 0.229/0.224/0.225HumanSeg 需 0.5/0.5/0.5 归一化二者不可混用同时都要保证to_rgbTrue与模型训练时的通道顺序一致。opset 版本选择两个示例分别使用 opset 10PaddleHub 导出与 opset 11paddle2onnx 命令行只要目标 OpenCV 支持的 opset 能覆盖模型算子即可遇到算子不支持报错时优先尝试调整 opset 版本。通过本文的两条链路可以看到PaddlePaddle 生态模型接入 OpenCV 的核心工程范式是一致的固定输入形状 → 导出/转换 ONNX →readNetFromONNX加载 → 按需匹配预处理与输出节点名 → 用 OpenCV 原生 API 完成后处理与可视化。掌握这一范式后你可以将 PaddleHub、PaddleSeg 乃至 PaddleDetection 等生态中任意可转 ONNX 的模型平滑接入 OpenCV DNN复用 OpenCV 统一的推理与图像处理基础设施。【免费下载链接】opencvOpen Source Computer Vision Library项目地址: https://gitcode.com/GitHub_Trending/opencv31/opencv创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →