HRNet语义分割训练及TensorRT部署

这篇具有很好参考价值的文章主要介绍了HRNet语义分割训练及TensorRT部署。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

模型训练

环境构建

1. 创建虚拟环境

conda create -n hrnet python=3.7
conda activate hrnet

2. 安装cuda和cudnn

conda install cudatoolkit=10.2
conda install cudnn

3. 安装pytorch

pip install torch==1.7.0
pip install torchvision==0.8.0

4. 下载项目代码

git clone https://github.com/HRNet/HRNet-Semantic-Segmentation.git
cd HRNet-Semantic-Segmentation-HRNet-OCR
  • 或者直接从 https://github.com/HRNet/HRNet-Semantic-Segmentation/tree/HRNet-OCR 处下载zip包

5. 安装项目依赖的其他包

pip install -r requirements.txt

数据整理

1. 标注

  • 使用labelme或其他标注工具做语义分割标注,网上关于labelme标注的教程很多,且操作并不复杂,这里不进行赘述

2. 数据集格式整理

  • 按照cityscapes数据集格式,整理自己的数据,格式如下:

项目目录/data
├── cityscapes
|   ├── gtFine
|   |   ├── train  # 训练集标签,即label图片,由类别索引构成
|   |   └── val  # 验证集标签,即label图片,由类别索引构成
|   └── leftImg8bit
|       ├── train  # 训练集原始图像
|       └── val  # 验证集原始图像
└── list
    └── cityscapes
        ├── train.lst  # 训练集 原始图像路径\t标签路径
        └── val.lst  # 验证集 原始图像路径 \t标签路径
  • train.lst 或 val.lst 中的内容示例如下:

cityscapes/leftImg8bit/train/005094.jpg	cityscapes/gtFine/train/005094.png
cityscapes/leftImg8bit/train/001748.jpg	cityscapes/gtFine/train/001748.png
cityscapes/leftImg8bit/train/005328.jpg	cityscapes/gtFine/train/005328.png
cityscapes/leftImg8bit/train/000750.jpg	cityscapes/gtFine/train/000750.png
cityscapes/leftImg8bit/train/002818.jpg	cityscapes/gtFine/train/002818.png

代码修改

1. 修改 lib/datasets/cityscapes.py

  • 62行左右,原代码:

self.class_weights = torch.FloatTensor([0.8373, 0.918, 0.866, 1.0345,
                                        1.0166, 0.9969, 0.9754, 1.0489,
                                        0.8786, 1.0023, 0.9539, 0.9843,
                                        1.1116, 0.9037, 1.0865, 1.0955,
                                        1.0865, 1.1529, 1.0507]).cuda()

改为:

self.class_weights = None
或者
self.class_weights = torch.FloatTensor([0.6, 0.9, 0.9]).cuda()  # 数据个位等于类别数,数值为计算loss时权重,自己定
  • 117行左右,原代码:

label = cv2.imread(os.path.join(self.root, item["label"]),
                           cv2.IMREAD_GRAYSCALE)
label = self.convert_label(label)

改为:

label = np.array(
    Image.open(os.path.join(self.root, item['label'])).convert('P')
)

在改完后的代码下方,再添加以下代码:

if 'val' in self.list_path:
    image, label = self.resize_short_length(
        image,
        label=label,
        short_length=self.base_size,
        fit_stride=8
    )
    image, label = self.rand_crop(image, label)
    image = self.input_transform(image)
    image = image.transpose((2, 0, 1))

    return image.copy(), label.copy(), np.array(size), name

image, label = self.resize_short_length(image, label, short_length=self.base_size)

2. 修改 lib/models/bn_helper.py

  • 第10行,原代码:

BatchNorm2d_class = BatchNorm2d = torch.nn.SyncBatchNorm

改为:

BatchNorm2d_class = BatchNorm2d = torch.nn.BatchNorm2d

3. 修改 experiments/cityscapes/seg_hrnet_ocr_w48_train_512x1024_sgd_lr1e-2_wd5e-4_bs_12_epoch484.yaml

  • GPUS: (0,1,2,3) 改为 GPUS: (0,)

  • NUM_CLASSES: 19 处改为自己数据集类别数

  • PRETRAINED: "pretrained_models/hrnetv2_w48_imagenet_pretrained.pth" 改为 PRETRAINED: ""

  • IMAGE_SIZE,BASE_SIZE 和 BATCH_SIZE_PER_GPU 训练时自己根据显存使用情况修改

启动训练

1. 启动

python tools/train.py --cfg experiments/cityscapes/seg_hrnet_ocr_w48_train_512x1024_sgd_lr1e-2_wd5e-4_bs_12_epoch484.yaml

2. 出现如下日志,则训练正常

2023-03-17 22:53:55,854 Epoch: [0/484] Iter:[0/1235], Time: 3.59, lr: [0.01], Loss: 1.664520
2023-03-17 22:54:02,300 Epoch: [0/484] Iter:[10/1235], Time: 0.91, lr: [0.0099998494], Loss: 1.615116
2023-03-17 22:54:08,746 Epoch: [0/484] Iter:[20/1235], Time: 0.78, lr: [0.0099996988], Loss: 1.671794
2023-03-17 22:54:15,251 Epoch: [0/484] Iter:[30/1235], Time: 0.74, lr: [0.0099995482], Loss: 1.695571
2023-03-17 22:54:21,768 Epoch: [0/484] Iter:[40/1235], Time: 0.72, lr: [0.0099993977], Loss: 1.677186
2023-03-17 22:54:28,254 Epoch: [0/484] Iter:[50/1235], Time: 0.71, lr: [0.0099992471], Loss: 1.654732
2023-03-17 22:54:34,774 Epoch: [0/484] Iter:[60/1235], Time: 0.70, lr: [0.0099990965], Loss: 1.631594
2023-03-17 22:54:41,357 Epoch: [0/484] Iter:[70/1235], Time: 0.69, lr: [0.0099989464], Loss: 1.593724
2023-03-17 22:54:47,891 Epoch: [0/484] Iter:[80/1235], Time: 0.69, lr: [0.0099987954], Loss: 1.558106

3. 可以通过 tensorboard 查看 loss 及 mIOU 变化情况

tensorboard --logdir log/

4. 模型保存

  • 训练完成后,到output目录的子目录下寻找 best.pth

TensorRT转换

需要宿主机安装有docker

环境构建

1. 拉取 nvidia 官方 docker 镜像

$ docker pull nvcr.io/nvidia/tensorrt:21.03-py3

2. 在该镜像中安装OpenCV

  • 启动容器,将 /home 目录挂载到容器的 /workspace 目录(目录根据自己喜好选择,非强制):

$ docker run -it -v /home:/workspace nvcr.io/nvidia/tensorrt:21.03-py3 bash
  • 下载OpenCV-4.5.0源码,下载时注意选择 4.5.0 版本(其他有效的亦可):

1)OpenCV 源码链接:https://github.com/opencv/opencv

2)下载后解压,放入宿主机 /home 下,即容器的 /workspace 目录下

  • 开始在容器中操作,安装依赖:

apt install build-essential
apt install libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
apt install libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libdc1394-22-dev
apt install libgl1  # 后续安装opencv-python所需
  • 开始安装 OpenCV,依次执行以下指令:

cd /workspace/opencv-4.5.0
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local ..
make -j$nproc
make install
  1. (可选)安装pytorch和opencv-python

pip install torch==1.7.1 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install torchvision==0.8.2 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install torchaudio==0.7.2 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install opencv-python==4.5.3.56 -i https://pypi.tuna.tsinghua.edu.cn/simple

模型转换

以下步骤主要参考 tensorrtx 项目hrnet目录下的README

1. 下载 tensorrtx 项目

  • 项目链接:https://github.com/wang-xinyu/tensorrtx,下载zip包并解压

  • 进入到项目的hrnet/hrnet-semantic-segmentation目录下

2. 生成 wts 模型文件

  • 将gen_wts.py文件拷贝到模型训练项目的 tools/目录中

  • 在模型训练项目目录下运行:

python tools/gen_wts.py --cfg experiments/cityscapes/seg_hrnet_ocr_w48_train_512x1024_sgd_lr1e-2_wd5e-4_bs_12_epoch484.yaml --ckpt_path output/best.pth --save_path hrnet_ocr_w48.wts

运行之后得到 hrnet_ocr_w48.wts文件

  • 将 hrnet_ocr_w48.wts拷贝到 tensorrtx 项目的hrnet/hrnet-semantic-segmentation目录下

3. 生成 TensorRT 模型文件

  • 修改hrnet/hrnet-semantic-segmentation目录下的 hrnet_ocr.cpp文件

  • 将第 17、18 行的图像输入的 INPUT_H、INPUT_W 改为和训练时一致;

  • 将第 19 行的 NUM_CLASSES 改为自己数据集的类别数

  • 复制 tensorrtx 项目hrnet目录下的 hrnet-semantic-segmentation 目录,拷贝到宿主机/home目录下,也即上述环境构建时的容器的 /workspace 目录下

  • 开始在容器中操作:

  • 编译c++代码

cd /workspace/hrnet-semantic-segmentation
mkdir build
cd build
cmake ..
make
  • 生成 TensorRT 的 engine 模型文件

./hrnet_ocr -s ../hrnet_ocr_w48.wts ./hrnet_ocr_w48.engine 48

运行之后得到 hrnet_ocr_w48.engine 文件

  • 测试 TensorRT 模型

mkdir ../samples  # 向该目录中放入一些测试集图片
./hrnet_ocr -d ./hrnet_ocr_w48.engine ../samples  # 使用 hrnet_ocr_w48.engine 推理

Triton部署

需要宿主机安装有docker

Server端

1. 构建目录

  • 目录结构构建如下:

/home  # 根目录也可以是其他的
└── models
    └── hrnet_ocr  # 模型名称,命名随意
        ├── 1  # 模型版本
        │   └── model.plan  # 即TensorRT编译运行后生成的hrnet_ocr_w48.engine,重命名为model.plan
        └── config.pbtxt  # 自己创建的文件,内容如下
  • config.pbtxt文件内容

platform: "tensorrt_plan"
max_batch_size: 1
input [
  {
    name: "data"
    data_type: TYPE_FP32
    dims: [512, 512, 3]
  }
]
output [
  {
    name: "output"
    data_type: TYPE_INT32
    dims: [1, 512, 512]
  }
]
# default_model_filename: "model.plan"
instance_group [
  {
    count: 1
    kind: KIND_GPU
    gpus: [ 0 ]
  }
]
model_warmup  [
  {
    name: "zero_input"
    batch_size: 1
    inputs: {
      key: "data"
      value: {
        data_type: TYPE_FP32
        dims: [512, 512, 3]
        zero_data: true
      }
    }
  }
]

2. 拉取镜像

docker pull nvcr.io/nvidia/tritonserver:21.03-py3  # 和上面TensorRT编译镜像环境保持一致

3. 启动服务

docker run -d --gpus all --shm-size=16G -p 8000:8000 -p 8001:8001 -p 8002:8002 -v /home/models:/models nvcr.io/nvidia/tritonserver:21.03-py3 tritonserver --model-repository=/models --grpc-infer-allocation-pool-size=16 --log-verbose 1
  • 可通过 docker logs <container id> 查看日志,显示以下内容,启动成功

+--------------------+---------+--------+
| Model              | Version | Status |
+--------------------+---------+--------+
| hrnet_ocr          | 1       | READY  |
+--------------------+---------+--------+                                                   

Client端

1. 构建环境

  • 创建虚拟环境

conda create -n triton-client python=3.7
conda activate triton-client
  • 安装依赖

pip install tritonclient[all]
pip install numpy
pip install opencv-python

2. 客户端代码

  • 使用python编写客户端程序client.py,内容如下:

import argparse
import numpy as np
import cv2

import tritonclient.grpc as grpcclient

input_h, input_w = 512, 512

parser = argparse.ArgumentParser()
parser.add_argument('-m', '--model', type=str, default='hrnet_ocr')
parser.add_argument('-v', '--video', type=str, default=r'./videos/demo.mp4')
FLAGS = parser.parse_args()

# Create server context
ip = '127.0.0.1'
port = 8001
url = "%s:%d" % (ip, port)
triton_client = grpcclient.InferenceServerClient(
    url=url,
    verbose=False,
    ssl=False,
    root_certificates=None,
    private_key=None,
    certificate_chain=None)


def preprocess(image):
    image = cv2.resize(image, (input_h, input_w))
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    image = image.astype(np.float32)
    return image


def postprocess(result, height, width):
    color_dict = {
        0: (255, 0, 0),
        1: (0, 255, 0),
        2: (255, 0, 255)
    }  # 根据自己数据集自行修改
    result = result.reshape((input_h, input_w)).astype(np.uint8)
    result = cv2.resize(result, (width, height), interpolation=cv2.INTER_NEAREST)
    canvas = np.zeros((height, width, 3), dtype=np.uint8)
    for cls in color_dict:
        canvas[result == cls] = color_dict[cls]
    return canvas


def client(image_input):
    height, width = image_input.shape[:2]

    inputs = []
    outputs = []
    inputs.append(grpcclient.InferInput('data', [1, input_h, input_w, 3], "FP32"))
    outputs.append(grpcclient.InferRequestedOutput('output'))

    input_image_buffer = preprocess(image_input).astype(np.float32)
    input_image_buffer = np.expand_dims(input_image_buffer, axis=0)
    inputs[0].set_data_from_numpy(input_image_buffer)

    results = triton_client.infer(model_name=FLAGS.model,
                                  inputs=inputs,
                                  outputs=outputs)
    result = results.as_numpy('output')
    seg_image = postprocess(result, height, width)

    return seg_image


if __name__ == '__main__':
    cap = cv2.VideoCapture(FLAGS.video)
    while True:
        ret, frame = cap.read()
        if ret:
            seg = client(frame)
            cv2.imshow('seg result', seg)
            cv2.waitKey(1)
        else:
            break
    cap.release()

3. 启动客户端

  • 启动命令格式:

python client.py -m <模型名称,与server端一致> -v <要推理的视频路径>
  • 示例:

python client.py -m hrnet_ocr -v videos/demo.mp4

至此,HRNet从训练到加速,再到部署整个流程完成。文章来源地址https://www.toymoban.com/news/detail-723446.html

到了这里,关于HRNet语义分割训练及TensorRT部署的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 计算机视觉框架OpenMMLab(七):语义分割实战

    👨‍💻 作者简介: 大数据专业硕士在读,CSDN人工智能领域博客专家,阿里云专家博主,专注大数据与人工智能知识分享。 公众号: GoAI的学习小屋,免费分享书籍、简历、导图等资料,更有交流群分享AI和大数据,加群方式公众号回复“加群”或➡️点击链接。 🎉 专栏推

    2024年02月02日
    浏览(33)
  • HRNet网络简介

    论文名称: Deep High-Resolution Representation Learning for Human Pose Estimation 论文下载地址:https://arxiv.org/abs/1902.09212 官方源码地址:https://github.com/leoxiaobin/deep-high-resolution-net.pytorch 在bilibili上的视频讲解:https://www.bilibili.com/video/BV1bB4y1y7qP 这篇文章是由中国科学技术大学和亚洲微软研究

    2024年01月23日
    浏览(31)
  • 【深度学习】YOLOv5实例分割 数据集制作、模型训练以及TensorRT部署

    yolov5-seg:官方地址:https://github.com/ultralytics/yolov5/tree/v6.2 TensorRT:8.x.x 语言:C++ 系统:ubuntu18.04 前言:由于yolo仓中提供了标准coco的json文件转txt代码,因此需要将labelme的json文件转为coco json. labelme JSON 转COCO JSON 使用labelme的CreatePolygons按钮开始绘制多边形,然后保存为json格式。

    2024年02月06日
    浏览(40)
  • 计算机视觉与深度学习-图像分割-视觉识别任务01-语义分割-【北邮鲁鹏】

    给每个像素分配类别标签。 不区分实例,只考虑像素类别。 滑动窗口缺点 重叠区域的特征反复被计算,效率很低。 所以针对该问题提出了新的解决方案–全卷积。 让整个网络只包含卷积层,一次性输出所有像素的类别预测。 全卷积优点 不用将图片分为一个个小区域然后再

    2024年02月07日
    浏览(63)
  • 计算机视觉三大基本任务:分类、检测(定位)、分割(语义和实例)

    刚刚接触计算机视觉时可能会对 不同的任务的区分 以及 网络架构的选择 产生迷惑,因此,在此总结了相关的基础知识。在本文中,我们试图回答两个问题: 不同任务要做的事情是什么,研究范畴是什么? 不同的任务需要选择什么类型的网络? 计算机视觉任务可以分为4大

    2024年02月05日
    浏览(49)
  • 【计算机视觉】CVPR 2023 上的分割论文真的是神仙打架(介绍前12篇,图像分割,全景分割,语义分割,实例分割)

    AutoFocusFormer:网格外的图像分割 论文地址: 真实世界的图像通常具有高度不平衡的内容密度。 有些区域非常均匀,例如大片蓝天,而其他区域则散布着许多小物体。 然而,卷积深度网络中常用的连续网格下采样策略平等对待所有区域。 因此,小对象在很少的空间位置表示

    2024年02月12日
    浏览(33)
  • 【U-HRNet2022】U-HRNet: Delving into Improving Semantic Representation of High Resolution Network for

    arXiv:2210.07140v1 [cs.CV] 13 Oct 2022 文章地址:https://arxiv.org/abs/2210.07140 代码地址:https://github.com/PaddlePaddle/PaddleSeg   高分辨率和先进的语义表示对密集预测都是至关重要的。根据经验,低分辨率的特征图往往能实现更强的语义表示,而高分辨率的特征图一般能更好地识别局部特

    2024年02月09日
    浏览(33)
  • 【计算机视觉 | 语义分割】OVSeg:分割一切后,SAM又能分辨类别了,Meta/UTAustin提出全新开放类分割模型

    前几日,Meta 推出了「分割一切」AI 模型 Segment Anything,令网友直呼 CV 不存在了?! 而在另一篇被 CVPR 2023 收录的论文中,Meta、UTAustin 联合提出了新的开放语言风格模型(open-vocabulary segmentation, OVSeg),它能让 Segment Anything 模型知道所要分隔的类别。 论文地址: 从效果上来看

    2024年02月12日
    浏览(44)
  • 深度学习实战23(进阶版)-语义分割实战,实现人物图像抠图的效果(计算机视觉)

    大家好,我是微学AI,今天给大家带来深度学习实战23(进阶版)-语义分割实战,实现人物图像抠图的效果。语义分割是计算机视觉中的一项重要任务,其目标是将图像中的每个像素都分配一个语义类别标签。与传统的目标检测或分类任务不同,语义分割不仅需要识别图像中存在

    2024年02月13日
    浏览(39)
  • 计算机设计大赛 深度学习人体语义分割在弹幕防遮挡上的实现 - python

    🔥 优质竞赛项目系列,今天要分享的是 🚩 深度学习人体语义分割在弹幕防遮挡上的应用 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分 工作量:3分 创新点:3分 🧿 更多资料, 项目分享: https://gi

    2024年02月20日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包