
PaddleHub 图像分割实战基于 fcn_hrnetw18_cityscapes 的预测、Fine-tune 与服务部署【免费下载链接】PaddleFormersPaddleFormers is an easy-to-use library of pre-trained large language model zoo based on PaddlePaddle.项目地址: https://gitcode.com/gh_mirrors/pa/PaddleFormers导读本文以 PaddleHub 官方语义分割模块fcn_hrnetw18_cityscapes为线索完整讲解如何在 PaddlePaddle 2.0 与 PaddleHub 2.0 环境下使用该预训练模型进行图像分割预测、基于 OpticDiscSeg 数据集的四步 Fine-tune 流程以及通过 PaddleHub Serving 部署在线分割服务。读完本文你将掌握hub.Module的加载与预测、Trainer训练管线的完整参数语义并能从源码层面理解 FCN HRNet-W18 的模型结构与数据流转。本文对应的模型模块位于仓库 modules/image/semantic_segmentation/fcn_hrnetw18_cityscapes其官方使用说明文档为 modules/image/semantic_segmentation/fcn_hrnetw18_cityscapes/README.md。一、模型与模块概览fcn_hrnetw18_cityscapes是 PaddleHub 中面向语义分割任务的 CV 模块类型为CV/semantic_segmentation其实现由三部分源码构成module.py定义 FCN 分割模型整体主干网络 分割头并通过moduleinfo注册为 PaddleHub 模块hrnet.py实现 HRNet-W18 高分辨率主干网络layers.py提供ConvBN、ConvBNReLU、SELayer等基础组件。从模块注册信息看module.py 中以moduleinfo声明了namefcn_hrnetw18_cityscapes、typeCV/semantic_segmentation、version1.0.0并将meta指定为ImageSegmentationModule。这意味着该模块继承了 paddlehub/module/cv_module.py 中ImageSegmentationModule的predict、serving_method、training_step等标准能力。从架构上看模型主体由两个关键部分组成见 module.py主干网络 HRNet_W18保持高分辨率特征表达的多分支并行网络FCNHead 分割头对主干输出做 1×1 卷积降维再通过 1×1 卷积输出每个像素的类别 logits。forward中最终通过F.interpolate将 logits 上采样回输入尺寸align_corners默认False适用于输出尺寸为偶数的情况如 1024×512若为 769×769 等奇数尺寸应设为True。二、使用预训练模型进行图像分割预测若想直接使用模块提供的预训练权重进行预测可参考以下脚本import paddle import cv2 import paddlehub as hub if __name__ __main__: model hub.Module(namefcn_hrnetw18_cityscapes) img cv2.imread(/PATH/TO/IMAGE) model.predict(images[img], visualizationTrue)hub.Module(namefcn_hrnetw18_cityscapes)会自动从 PaddleHub 拉取该模块及预训练权重。从 module.py 的初始化逻辑可以看到当pretrained为None时会加载模块目录下的model.pdparams默认权重并打印load pretrained parameters success当传入pretrained路径时则加载自定义权重。predict方法由基类ImageSegmentationModule提供见 paddlehub/module/cv_module.py其核心流程为对每张输入图像应用self.transform本模块默认仅为Normalize见 module.py前向得到 logits取argmax得到每个像素的类别索引通过reverse_transform还原到原始图像尺寸若visualizationTrue将分割 mask 叠加到原图并保存。predict 参数说明images原始图像路径或 BGR 格式的 numpy 图像列表batch_size预测时的批大小默认 1visualization是否可视化并保存结果默认Truesave_path结果保存路径默认seg_result。可视化输出会分别写入save_path/image/叠加效果图与save_path/mask/伪彩色 mask 图。注意进行预测时所选择的 module、checkpoint_dir、dataset 必须与 Fine-tune 时保持一致。三、Fine-tune 四步流程在完成 PaddlePaddle 与 PaddleHub 安装后执行python train.py即可使用fcn_hrnetw18_cityscapes在 OpticDiscSeg 等数据集上开始 Fine-tune。仓库 demo/semantic_segmentation/train.py 给出了完整的可运行示例。使用 PaddleHub Fine-tune API 进行迁移学习可分为 4 个步骤。Step 1定义数据预处理方式from paddlehub.vision.segmentation_transforms import Compose, Resize, Normalize transform Compose([Resize(target_size(512, 512)), Normalize()])paddlehub.vision.segmentation_transforms数据增强模块定义了丰富的针对图像分割数据的预处理方式见 paddlehub/vision/segmentation_transforms.py包括Compose将多个预处理算子串行组合输入数据形状约定为[height, width, channels]默认to_rgbTrue会先将 BGR 图像转为 RGBResize将图像缩放到目标尺寸默认(512, 512)。interp插值方式可选NEAREST、LINEAR、CUBIC、AREA、LANCZOS4或RANDOM默认LINEAR值得注意的细节是图像缩放使用指定的插值方式而标签图始终使用cv2.INTER_NEAREST最近邻插值避免类别边界被平滑污染见 segmentation_transforms.pyNormalize按mean/std归一化默认均值和标准差均为[0.5, 0.5, 0.5]Padding向右下角做补边填充图像默认填充值[128, 128, 128]标签默认填充值255与忽略类一致。用户可按需替换、组合这些预处理方式。需要说明的是训练与验证阶段的预处理可以不同例如 demo/semantic_segmentation/train.py 中训练集使用Resize Normalize而验证集只使用Normalize。Step 2下载数据集并使用from paddlehub.datasets import OpticDiscSeg train_reader OpticDiscSeg(transform, modetrain)参数说明transform数据预处理方式mode数据模式可选项为train、test、val默认train。数据集的准备代码可以参考 paddlehub/datasets/opticdiscseg.py。hub.datasets.OpticDiscSeg()会自动从网络下载optic_disc_seg.zip数据集并解压到用户目录下$HOME/.paddlehub/dataset目录。从源码可以看到更细致的实现事实OpticDiscSeg继承自 paddlehub/datasets/base_seg_dataset.py 中的SegDatasetpaddle.io.Dataset子类类别数为 2视盘/背景ignore_index255通过download_data装饰器实现数据集自动下载训练/测试/验证分别读取train_list.txt、test_list.txt、val_list.txt三个文件列表数据列表格式为image_name label_name空格分隔test 模式允许只有图像路径SegDataset.__getitem__根据 mode 返回不同内容train 返回(im, label)val 返回单通道 labeltest 返回(im, image_path)方便预测后按路径保存结果。若需使用自定义数据可直接使用SegDataset基类并传入dataset_root、num_classes、train_path/val_path/test_path等参数构造自己的数据集。Step 3加载预训练模型model hub.Module(namefcn_hrnetw18_cityscapes, num_classes2, pretrainedNone)参数说明name选择预训练模型的名字num_classes分割模型的类别数目pretrained是否加载自己训练的模型若为None则加载模块提供的默认预训练参数。在 module.py 的FCN.__init__中num_classes被传入FCNHead决定最终分类卷积的输出通道数nn.Conv2D(in_channelschannels, out_channelsself.num_classes, kernel_size1)见 module.py。此外模型还暴露了backbone_indices默认(-1, )即使用主干最后一级输出与channels分割头中间通道数默认取主干特征通道数 270两个可选参数进阶用户可以按需调整。Step 4选择优化策略和运行配置scheduler paddle.optimizer.lr.PolynomialDecay(learning_rate0.01, decay_steps1000, power0.9, end_lr0.0001) optimizer paddle.optimizer.Adam(learning_ratescheduler, parametersmodel.parameters()) trainer Trainer(model, optimizer, checkpoint_dirtest_ckpt_img_ocr, use_gpuTrue)优化策略PaddlePaddle 2.0 提供了多种优化器选择如SGD、Adam、Adamax等。其中Adam常用参数learning_rate全局学习率这里传入的是PolynomialDecay学习率调度器实现从 0.01 按 0.9 次幂多项式衰减到 0.0001 的退火策略decay_steps1000控制衰减步数parameters待优化的模型参数即model.parameters()。从 paddlehub/finetune/trainer.py 的实现可以看到Trainer在每个训练 step 中会调用optimizer.step()并自动识别learning_rate是否为paddle.optimizer.lr.LRScheduler实例若是则同步调用learning_rate.step()推进调度器。因此学习率调度器与优化器的配合是开箱即用的。Trainer 运行配置Trainer主要控制 Fine-tune 的训练见 paddlehub/finetune/trainer.py包含以下可控制参数model被优化模型optimizer优化器选择use_gpu是否使用 GPU默认False内部通过paddle.set_device(gpu/cpu)切换设备use_vdl是否使用 VisualDL 可视化训练过程默认True日志写入checkpoint_dir/visualizationcheckpoint_dir保存模型参数的地址未指定时默认生成ckpt_{timestamp}目录Trainer 启动时会自动扫描该目录并恢复最近的epoch_N检查点实现断点续训compare_metrics保存最优模型时的衡量指标比较函数。默认比较验证集返回的第一个指标值越大越好若需自定义例如越小越好可传入形如compare_metrics(old_metric, new_metric)的回调函数。此外当检测到多卡环境paddle.distributed.get_world_size() 1时Trainer 会自动将模型包装为paddle.DataParallel支持分布式训练。trainer.train主要控制具体的训练过程包含以下可控制参数train_dataset训练时所用的数据集epochs训练轮数batch_size训练的批大小如果使用 GPU请根据实际情况调整 batch_sizenum_workers数据加载子进程数量默认 0eval_dataset验证集。一旦传入Trainer 会在每个save_interval轮结束时执行evaluate并将验证指标写入 VisualDL、参与最优模型筛选log_interval打印日志的间隔单位为执行批训练的次数save_interval保存模型的间隔频次单位为执行训练的轮数collate_fn自定义 batch 组装函数默认对样本各字段沿第 0 维 stack。训练日志由 PaddleHub 的 logger 输出格式为Epoch/Step、loss、各项指标、当前学习率 lr、每秒步数 step/sec 与预计剩余时间 ETA并通过log_writer.add_scalar同步记录到 VisualDL见 trainer.py。对分割任务而言ImageSegmentationModule.training_step内部使用nn.loss.CrossEntropyLoss对每个尺度的 logits 计算交叉熵损失并取平均见 paddlehub/module/cv_module.py因此训练阶段无需用户自行定义损失函数。四、Fine-tune 后模型预测当完成 Fine-tune 后在验证集上表现最优的模型会被保存在${CHECKPOINT_DIR}/best_model目录下其中${CHECKPOINT_DIR}为 Fine-tune 时所选择的 checkpoint 目录。从 trainer.py 可以看到每次验证后若compare_metrics判定新指标更优就会将model.state_dict()与optimizer.state_dict()分别保存为best_model/model.pdparams与best_model/model.pdopt同时通过metrics.pkl记录最优指标。使用该最优模型进行预测的predict.py脚本如下import paddle import cv2 import paddlehub as hub if __name__ __main__: model hub.Module(namefcn_hrnetw18_cityscapes, pretrained/PATH/TO/CHECKPOINT) img cv2.imread(/PATH/TO/IMAGE) model.predict(images[img], visualizationTrue)参数配置正确后执行脚本python predict.py即可。此处pretrained传入的是 Fine-tune 产出的 checkpoint 路径如${CHECKPOINT_DIR}/best_model模型会通过paddle.load加载该路径下的model.pdparams见 module.py。五、PaddleHub Serving 在线服务部署PaddleHub Serving 可以部署一个在线图像分割服务将fcn_hrnetw18_cityscapes模型快速封装为 HTTP API。Step 1启动 PaddleHub Serving运行启动命令$ hub serving start -m fcn_hrnetw18_cityscapes这样就完成了一个图像分割服务化 API 的部署默认端口号为 8866。从 paddlehub/commands/serving.py 可以看到该命令的实现细节Serving 进程会将自己的 PID 与模块名写入$CONF_HOME/serving_8866.json配置文件便于后续按端口停止服务hub serving stop -p 8866工作进程数按经验公式cpu_count() * 2 1计算可通过--port参数修改监听端口--gpu参数指定 GPU 设备需先设置CUDA_VISIBLE_DEVICES环境变量。NOTE如使用 GPU 预测需要在启动服务之前设置CUDA_VISIBLE_DEVICES环境变量否则无需设置。Step 2发送预测请求配置好服务端后以下代码即可实现发送预测请求、获取预测结果import requests import json import cv2 import base64 import numpy as np def cv2_to_base64(image): data cv2.imencode(.jpg, image)[1] return base64.b64encode(data.tostring()).decode(utf8) def base64_to_cv2(b64str): data base64.b64decode(b64str.encode(utf8)) data np.fromstring(data, np.uint8) data cv2.imdecode(data, cv2.IMREAD_COLOR) return data # 发送HTTP请求 org_im cv2.imread(/PATH/TO/IMAGE) data {images:[cv2_to_base64(org_im)]} headers {Content-type: application/json} url http://127.0.0.1:8866/predict/fcn_hrnetw18_cityscapes r requests.post(urlurl, headersheaders, datajson.dumps(data)) mask base64_to_cv2(r.json()[results][0])请求将图像以 base64 编码放入 JSON 的images字段POST 到/predict/fcn_hrnetw18_cityscapes端点。服务端由ImageSegmentationModule.serving_method处理见 paddlehub/module/cv_module.py先将 base64 字符串解码为 BGR 图像调用predict得到逐像素类别 mask再将 mask 编码为 base64 放回results列表返回。客户端拿到结果后可用base64_to_cv2还原成分割 mask 图像。六、从源码理解模型结构扩展阅读若想深入理解fcn_hrnetw18_cityscapes的模型结构可研读 hrnet.py多分辨率并行分支HRNet-W18 在 stage2/stage3/stage4 分别维护 2、3、4 条并行分支通道数依次为(18, 36)、(18, 36, 72)、(18, 36, 72, 144)对应代码中的stage2_num_channels、stage3_num_channels、stage4_num_channels过渡层 TransitionLayer在阶段切换时通过 3×3 卷积步长 2为新增的低分辨率分支生成特征特征融合 FuseLayers每个HighResolutionModule内部由Branches各分支独立堆叠BasicBlock与FuseLayers跨分辨率求和融合低分辨率特征经双线性插值上采样后逐元素相加见 hrnet.py组成输出拼接最后一级将四条分支统一上采样到最高分辨率并沿通道维拼接得到183672144 270通道的特征这也是FCNHead默认backbone_channels(270, )的由来再交给 FCN 分割头完成逐像素分类。此外layers.py 中的SyncBatchNorm封装值得注意在 CPU 环境下自动退化为nn.BatchNorm2D因为nn.SyncBatchNorm在 CPU 上无对应 kernelGPU 下使用同步批归一化这与分割任务常用的批量归一化策略一致。七、依赖与运行前提本模块的使用依赖以下运行环境与文档声明一致见 modules/image/semantic_segmentation/fcn_hrnetw18_cityscapes/README.mdpaddlepaddle 2.0.0paddlehub 2.0.0。同时建议安装opencv-pythoncv2用于图像读写与可视化与visualdl用于训练可视化。本文所述命令、代码与参数均以当前仓库中的实现为准实际运行效果取决于所使用硬件CPU/GPU与 PaddlePaddle/PaddleHub 的安装版本。【免费下载链接】PaddleFormersPaddleFormers is an easy-to-use library of pre-trained large language model zoo based on PaddlePaddle.项目地址: https://gitcode.com/gh_mirrors/pa/PaddleFormers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考