MMsegmentation与MMdeploy简单使用

news2024/11/15 7:00:11

最近涉及到了图像分割的任务,于是拿来写下博客加深下使用。
MMsegmentation与MMdeploy的环境配置暂不做讲解,在官网和其他博客中有很多说明。
MMdeploy主要是把pt转为 onnx_int8的情况。
MMsegmentation环境配置可以参考 : 安装与配置MMSegmentation

目录

    • MMsegmentation简易使用
      • 数据集的准备
      • 数据集的config设置
        • 新建一个自己的dataset类
        • 修改__init__.py
        • 新建自己config文件
      • model文件设置
        • 训练
        • 测试
    • MMdeploy简易使用
      • deploy_cfg
      • deploy.py
      • 问题及改进
    • 参考博客
  • 欢迎指正

MMsegmentation简易使用

数据集的准备

采用MICCAI2023牙齿分割挑战的数据集----CHASE_DB1
以下的例子都是针对这个数据集,算是一个二分类的图像分割任务(背景,牙齿)
CHASE_DB1_牙齿分割数据集
我将其放到了如下位置:
work_dir/tt/mmsegmentation-main/datasets/CHASE_DB1/

数据集的config设置

新建一个自己的dataset类

路径如下 : work_dir/mmsegmentation-main/mmseg/datasets
新建一个tooth_test_dataset.py
可以复制同目录下的 cityscapes.py,然后在它上面进行如下3处修改
在这里插入图片描述

修改__init__.py

work_dir/mmsegmentation-main/mmseg/datasets/init.py
在如下两个位置加上刚才的类名,来供后续的代码调用。
在这里插入图片描述

新建自己config文件

work_dir/mmsegmentation-main/configs/base/datasets/
下新建自己的config文件 tooth_test_640x320.py (结尾可以是W x H的形式,方便后续更改)
可以复制同目录下的cityscapes.py进行更改

更改:dataset_type; data_root ; crop_size
train_dataloader中 Img_path 和 seg_map_path路径的设置
其中batch_size 和num_workers可以自行设置
在这里插入图片描述
在这里插入图片描述

model文件设置

上面这样就算是把数据集相关的文件设置好了,现在来配置Model文件的设置

work_dir/mmsegmentation-main/configs
下面有很多种模型,读者可以自行选择一个,笔者选择的是hrnet模型
新建如下py:work_dir/mmsegmentation-main/configs/hrnet/fcn_hr18_4xb2-40k_tooth_test-640x320.py
可以复制同目录下的fcn_hr18_4xb2-40k_cityscapes-512x1024.py 然后进行修改

同样的还有crop_size也需要修改,要和数据集中的大小设置为一致。
在这里插入图片描述

然后来看__base__第一个文件,fcn_hr18_cls2.py
新建/home/siyingzhen/tt/mmsegmentation-main/configs/base/models/fcn_hr18_cls2.py
读者可以通过复制同目录下fcn_hr18.py进行修改
在这里插入图片描述
修改对应类别即可

然后来看__base__第二个文件,这是第一步 数据集的config设置的文件,没什么好讲的
然后来看__base__第四个文件,这是训练时的一些超参数:
在这里插入图片描述

训练

使用.tools/train.py或者.tools/dist_train.sh进行训练
接下来就可以进行训练了
单gpu训练:

mmsegmentation-main]$ python tools/train.py work_dir/mmsegmentation-main/configs/hrnet/fcn_hr18_4xb2-20k_tooth_test-640x320.py --work-dir work_dir

B U G ,笔者不会解决 \textcolor{red}{BUG,笔者不会解决} BUG,笔者不会解决 :
如果使用–resume会使得刚开始加载数据的时候卡住
官方ISSUE

多GPU训练:
CUDA_VISIBLE_DEVICES=3,4,5,6 ./tools/dist_train.sh work_dir/mmsegmentation-main/configs/hrnet/fcn_hr18_4xb2-20k_tooth_test-640x320.py 4

测试

使用.tools/test.py进行测试

python tools/test.py work_dir/mmsegmentation-main/configs/hrnet/fcn_hr18_4xb2-40k_tooth_test-640x320.py  work_dir/mmsegmentation-main/work_dirs/fcn_hr18_4xb2-40k_tooth_test-640x320/iter_20000.pth --show-dir work_dir/mmsegmentation-main/work_dirs/eval_show

然后就可以看到测试结果可视化情况
在这里插入图片描述

MMdeploy简易使用

环境配置相关还是不说了
参考:mmdeploy环境配置
(笔者是参考的官方github)

目标,mmsegmentation的pt模型转为onnx_int8

主要代码:
work_dir/deploy-main/tools/deploy.py
在这里插入图片描述
需要的是4个参数

deploy_cfg

/home/siyingzhen/tt/mmdeploy-main/configs/mmseg/segmentation_onnxruntime-int8_dynamic.py

在这里插入图片描述

需要修改__base__的第二个文件路径
需要修改input_shape中,一般是训练时的图片大小(640x320)
.
./segmentation_static.py如下:
在这里插入图片描述
再往下看…/base/onx_config.py

在这里插入图片描述
会发现这里和
torch.onnx.export的API参数设置基本一致,实际上deploy.py中如果选择转ONNX,最终执行的就是这个接口

现在回过头来看…/base/backends/onnxruntime_int8.py
work_dir/mmdeploy-main/configs/base/backends/onnxruntime-int8.py
笔者是复制了同目录下的onnxruntime-fp16.py然后进行修改的
在这里插入图片描述

deploy.py

于此,就得到了deploy_cfg。
model_cfg在mmsegmentation中我们已经设置了,在work_dir/mmsegmentation-main/configs/hrnet/fcn_hr18_4xb2-40k_tooth_test-640x320.py
checkpoint就是训练的模型权重结果
img 可以是训练中的任意一张图片
使用代码:

python tools/deploy.py 
work_dir/mmdeploy-main/configs/mmseg/segmentation_onnxruntime_static-640x320.py 
work_dir/mmsegmentation-main/configs/hrnet/fcn_hr18_4xb2-40k_tooth_test-640x320.py 
work_dir/mmsegmentation-main/work_dirs/fcn_hr18_4xb2-40k_tooth_test-640x320/iter_20000.pth 
work_dir/mmsegmentation-main/datasets/CHASE_DB1/images/training/A-1.png 
--work-dir work_dir/mmdeploy-main/work_dir/HRnet_640x320 

最终可能会报错(主要是可视化方面的报错),但是也会生成量化后的onnx

Error: 
RuntimeError: Exporting the operator einsum to ONNX opset version 11 is not supported. Support for this operator was added in version 12, try exporting with this version.

问题及改进

最后发现,这个onnx里面的数据还是fp32的。

如果进行如下修改:
在这里插入图片描述

会发现onnx中的数据是fp16的,这个是成功的。

后来问了下别人,如果要从pt量化为onnx int8的话最好使用 onnxruntime.quantization 下 quantize_static或quantize_dynamic的函数

以下是另一个大佬写的mmdeploy环境下,将pt转为onnx_int8的代码,读者可以参考
(涉及了Onnxsim简化 以及 核心的quantize_static)

# Copyright (c) OpenMMLab. All rights reserved.
import argparse
import logging
import os
import os.path as osp
import numpy as np
import random
import subprocess
import sys
from mmdeploy.apis import (extract_model, get_predefined_partition_cfg,visualize_model,
                           torch2onnx)
from mmdeploy.utils import get_input_shape
from mmdeploy.utils import (get_ir_config, get_backend_config,get_common_config,Backend,
                            get_root_logger, load_config)

from mmengine.runner import Runner
from mmengine.registry import DATASETS
from onnxruntime.quantization import CalibrationDataReader, QuantFormat, quantize_static, QuantType, CalibrationMethod
from mmdeploy.apis.utils import build_task_processor


def batch_reader(datas,task_processor,data_preprocessor,input_shape,batch_size):
    _datas = []
    length = len(datas)
    # print("len: ",length)
    # exit()
    max_num = 20 #建议设置到300-500之间,此处设置为20是为了加速。
    print("max_num: ",max_num)
    for i, data in enumerate(datas):
        if i>max_num:
            return None
        
        img_path = data['data_samples'].img_path
        
        data, model_inputs = task_processor.create_input(
                            img_path,
                            input_shape,
                            data_preprocessor=data_preprocessor)
        
        if isinstance(model_inputs, list) and len(model_inputs) == 1:
            model_inputs = model_inputs[0]
                
        if batch_size==1:
            yield {'input': model_inputs.numpy()}
        elif (i+1) % batch_size==0:
            _datas.append(data)
            yield {'input': np.concatenate(_datas, 0)}
            _datas = []
        elif i<length-1:
            _datas.append(model_inputs.numpy())
        else:
            _datas.append(model_inputs.numpy())
            yield {'input': np.concatenate(_datas, 0)}
        


class DataReader(CalibrationDataReader):
    def __init__(self, dataset,task_processor,data_preprocessor,input_shape,batch_size=1):
         self.datas = batch_reader(dataset,task_processor,data_preprocessor,input_shape, batch_size)
         
    def get_next(self):
        return next(self.datas, None)


def parse_args():
    parser = argparse.ArgumentParser(description='Export model to ONNX.')
    # parser.add_argument('--deploy_cfg',default='/root/mmdeploy/configs/mmseg/segmentation_onnxruntime_int8_static-512x512.py', help='deploy config path')
    # parser.add_argument('--model_cfg',default='model_weights/fcn/fcn_r50-d8_4xb4-20k_voc12aug-512x512.py',help='model config path')
    # parser.add_argument('--checkpoint',default='model_weights/fcn/fcn_r50-d8_512x512_20k_voc12aug_20200617_010715-52dc5306.pth',help='model checkpoint path')
    # parser.add_argument('--test_img',default='/root/mmdeploy/data/VOCdevkit/VOC2012/JPEGImages/2007_000027.jpg',help='image used to convert model model')
    parser.add_argument('--deploy_cfg',default='', help='deploy config path')
    parser.add_argument('--model_cfg',default='',help='model config path')
    parser.add_argument('--checkpoint',default='',help='model checkpoint path')
    parser.add_argument('--test_img',default='',help='image used to convert model model')
    parser.add_argument(
        '--work-dir',
        default='',
        help='Directory to save output files.')
    parser.add_argument(
        '--device', help='device used for conversion', default='cpu')
    parser.add_argument(
        '--log-level',
        help='set log level',
        default='INFO',
        choices=list(logging._nameToLevel.keys()))
    args = parser.parse_args()

    return args


def main():
    args = parse_args()
    logger = get_root_logger(log_level=args.log_level)

    logger.info(f'torch2onnx: \n\tmodel_cfg: {args.model_cfg} '
                f'\n\tdeploy_cfg: {args.deploy_cfg}')

    os.makedirs(args.work_dir, exist_ok=True)
    # load deploy_cfg
    deploy_cfg, model_cfg = load_config(args.deploy_cfg, args.model_cfg)
    
    save_file = get_ir_config(deploy_cfg)['save_file']

    torch2onnx(
        args.test_img,
        args.work_dir,
        save_file,
        deploy_cfg=args.deploy_cfg,
        model_cfg=args.model_cfg,
        model_checkpoint=args.checkpoint,
        device=args.device)
    
    backend_cfg = get_backend_config(deploy_cfg)

    precision = backend_cfg.get('precision', 'fp32')
    if precision == 'fp16':
        import onnx
        from onnxconverter_common import float16

        common_cfg = get_common_config(deploy_cfg)
        model = onnx.load(os.path.join(args.work_dir,save_file))
        model_fp16 = float16.convert_float_to_float16(model, **common_cfg)
        onnx.save(model_fp16, os.path.join(args.work_dir,save_file.replace('.onnx','_fp16.onnx')))
        
    if precision == 'int8':
        dataset = DATASETS.build(model_cfg['train_dataloader']['dataset'])
        
        task_processor = build_task_processor(model_cfg, deploy_cfg, 'cpu')

        torch_model = task_processor.build_pytorch_model(args.checkpoint)
        data_preprocessor=getattr(torch_model, 'data_preprocessor', None)
        
        input_shape = get_input_shape(deploy_cfg)
        print("input_shape: ",input_shape)
        data_reader = DataReader(dataset,task_processor,data_preprocessor,input_shape,1)
        
        sim_onnx_path =  os.path.join(args.work_dir,save_file.replace('.onnx','_sim.onnx'))

        if os.path.exists(os.path.join(args.work_dir,save_file)):
            command = r"/root/miniconda3/envs/mmdeploy/bin/python -m onnxsim {} {}".format(os.path.join(args.work_dir,save_file),sim_onnx_path)

            process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
            
            for line in process.stdout:
                print(line.rstrip())

            for line in process.stderr:
                print(line.rstrip(), file=sys.stderr)

            process.wait()
            quant_onnx_path = sim_onnx_path.replace("_sim.onnx","_sim_int8.onnx")
            if os.path.join(sim_onnx_path):
                quantize_static(
                    model_input=sim_onnx_path, # 输入模型
                    model_output=quant_onnx_path, # 输出模型
                    calibration_data_reader=data_reader, # 校准数据读取器
                    quant_format= QuantFormat.QDQ, # 量化格式 QDQ / QOperator
                    activation_type=QuantType.QInt8, # 激活类型 Int8 / UInt8
                    weight_type=QuantType.QInt8, # 参数类型 Int8 / UInt8
                    calibrate_method=CalibrationMethod.MinMax, # 数据校准方法 MinMax / Entropy / Percentile
                    per_channel=True, # 量化通道
                )
                
                # 可视化ONNX模型输出
                onnx_out_put_file = os.path.join(args.work_dir, 'output_onnxruntime_int8.png')
                visualize_model(model_cfg,deploy_cfg,[quant_onnx_path],args.test_img,device='cpu',backend=Backend.ONNXRUNTIME,output_file=onnx_out_put_file)
                
                #可视化torch模型输出
                torch_out_put_file = os.path.join(args.work_dir, 'output_torch.png')
                visualize_model(model_cfg,deploy_cfg,[args.checkpoint],args.test_img,device='cpu',backend=Backend.PYTORCH,output_file=torch_out_put_file)
                
                logger.info(f'torch2onnx finished. Results saved to {args.work_dir}')


if __name__ == '__main__':
    main()

笔者任务下部分结果展示
fp32.pt模型预测结果:
在这里插入图片描述

onnx_int8模型的预测结果:
在这里插入图片描述

参考博客

MMSegmentation的用法(手把手入门教程)搭配Colab,对自己的数据进行训练
【Python】mmSegmentation语义分割框架教程(1.x版本)

欢迎指正

因为本文主要是本人用来做的笔记,顺便进行知识巩固。如果本文对你有所帮助,那么本博客的目的就已经超额完成了。

欢迎交流
邮箱:refreshmentccoffee@gmail.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2082096.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【管理型文档】软件需求管理过程(原件)

软件需求管理规程应明确需求收集、分析、确认、变更控制及验证等流程&#xff0c;确保需求准确反映用户期望&#xff0c;支撑软件开发。该规程要求系统记录需求来源&#xff0c;通过评审确保需求完整、清晰、无歧义&#xff0c;实施变更控制以维护需求基线稳定&#xff0c;并持…

后端面试真题整理

面试问题整理 本人主要记录2024年秋招、春招过程中的疑难八股真题&#xff0c;参考来源&#xff1a;牛客网、知乎等。 八股 深拷贝与浅拷贝 浅拷贝&#xff1a; 浅拷贝会在堆上创建一个新的对象&#xff08;区别于引用拷贝的一点&#xff09;&#xff0c;不过&#xff0c;如果…

井盖丢失隐患大?智慧井盖监管系统帮你解决

在现代都市中&#xff0c;我们每天行走在钢筋水泥之间&#xff0c;却很少有人注意到脚下的小小井盖。这些不起眼的圆形铁盘不仅是城市地下管网的入口&#xff0c;更是维系城市生命线的重要组成部分。然而&#xff0c;当暴雨来袭&#xff0c;或是深夜无人之时&#xff0c;井盖的…

无线麦克风什么牌子的音质效果好?一文读懂麦克风哪个牌子的好

无线领夹麦克风哪款音质最好&#xff1f;在这个追求高质量音效的年代&#xff0c;选择一款合适的无线领夹麦克风&#xff08;简称领夹麦&#xff09;对于提升录音或直播的音质至关重要。随着市场的不断扩大&#xff0c;市面上充斥着大量信号不稳定、音质差的无线领夹麦克风&…

2024年汽车零部件企业CRM研究:服务商排名、案例分析、需求分析

最近媒体上频现各车企大佬发声&#xff0c;抗议某汽车企业“不要卷价格&#xff0c;要卷长期价值”&#xff0c;还有的直接批判其打破行业规则。图穷匕现&#xff0c;汽车行业的竞争愈发激烈了。 汽车产业作为我国国民经济的重要支柱产业、经济增长和转型的重要抓手&#xff0…

微软将持续多年的 Mono 项目移交给 Wine

今天&#xff0c;微软突然决定将 Mono 项目交由 Wine 开发社区管理。自Mono项目上一次作为开源.NET框架发布以来&#xff0c;已经过去了五年时间&#xff0c;此前Wine已经使用了Mono的代码&#xff0c;而在微软专注于开源.NET和其他工作的情况下&#xff0c;此举是合理的&#…

Python编程的终极十大工具(非常详细)零基础入门到精通,收藏这一篇就够了

&#x1f91f; 基于入门网络安全打造的&#xff1a;&#x1f449;黑客&网络安全入门&进阶学习资源包 Python一直以来都是程序员们的首选编程语言之一&#xff0c;其灵活性和功能强大的库使其成为解决各种问题的理想选择。在本文中&#xff0c;我们将介绍Python编程的终…

fdMemTable内存表进行SQL查询

fdLocalSql可以对fdMemTable内存表进行SQL查询&#xff08;可以对多个fdMemTable内存表进行联表查询哦&#xff09;&#xff0c;fdLocalSql使用SQLITE引擎&#xff0c;而FIREDAC驱动SQLITE&#xff0c;连SQLITE驱动DLL都不需要附带的。 所有设置用FormCreate里用代码 procedure…

【C#】Visual Studio2017 MSDN离线安装

1. 运行Visual Studio Installer 在Windows的开始菜单中直接搜索 2. 单击“修改”按钮 3. 依次点击&#xff0c;单个组件 - 代码工具 - Help Viewer - 修改&#xff0c;开始安装 4. 下载速度慢解决方法 修改IPv4 DNS 参考&#xff1a;visual studio下载慢解决方法&#xf…

unity脚本

Transform.Rotate 描述 使用 Transform.Rotate 以各种方式旋转 GameObjects。通常以欧拉角而不是四元数提供旋转。 可以在世界轴或本地轴中指定旋转。 世界轴旋转使用 Scene 的坐标系&#xff0c;因此在开始旋转 GameObject 时&#xff0c;它的 x、y 和 z 轴与 x、y 和 z 世…

Leetcode 131.分割回文串 回溯 C++实现

Leetcode 131. 分割回文串 问题&#xff1a;给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 算法&#xff1a; 创建二维返回数组 ans &#xff0c;和临时数组 path 。 进入 dfs 函数&#xff0c;当 …

初识linux(1)

linux背景 1991年10月5日&#xff0c;赫尔辛基大学的一名研究生Linus Benedict Torvalds在一个Usenet新闻组 &#xff08;comp.os.minix&#xff09;中宣布他编制出了一种类似UNIX的小操作系统&#xff0c;叫Linux。新的操作系统是受到另 一个UNIX的小操作系统——Minix的启发…

今日arXiv最热大模型论文:港大微软发布AgentGen提高大模型规划能力,8B模型接近GPT-4水平

夕小瑶科技说 原创 作者 | Richard 在大语言模型&#xff08;LLM&#xff09;问世之后&#xff0c;基于 LLM 的 Agent 引起了广泛的关注并且变得越来越流行。规划能力无论对人类还是 Agent 都是一个重要的决策步骤&#xff0c;规划的本质是通过预先设定的行动过程&#xff0c…

软件设计师全套备考系列文章20 -- UML建模(重点,15分)

软考-- 软件设计师&#xff08;20&#xff09;-- UML建模(重点&#xff0c;15分) 文章目录 软考-- 软件设计师&#xff08;20&#xff09;-- UML建模(重点&#xff0c;15分)前言一、章节考点二、概述三、类图四、用例图五、顺序图六、活动图七、状态图八、通信图九、构建图 前言…

扫码点餐系统的前景如何?

扫码点餐系统作为一种餐饮业数字化转型的关键工具&#xff0c;其发展前景广阔。随着移动支付和智能手机的普及&#xff0c;该系统在餐厅、咖啡馆、快餐店等场所得到广泛应用&#xff0c;不仅简化了顾客点餐流程&#xff0c;减轻了服务员的工作负担&#xff0c;还提高了翻台率。…

沃尔玛停止在 3 个城市使用无人机送货,将重点转移到达拉斯

沃尔玛&#xff0c;作为全球领先的零售商&#xff0c;一直在探索创新的物流解决方案以提升顾客体验。近年来&#xff0c;该公司与无人机送货服务提供商DroneUp合作&#xff0c;尝试通过无人机技术实现快速配送服务。然而&#xff0c;经过一段时间的试点运营后&#xff0c;沃尔玛…

输电线路分布式故障诊断系统:分布式智慧网络的构建

输电线路分布式故障诊断系统&#xff1a;分布式智慧网络的构建 今天&#xff0c;就让深圳鼎信智慧科技陪大家一起走进输电线路分布式故障定位系统的世界&#xff1a; 1、系统架构&#xff1a;分布式智慧网络的构建 输电线路分布式故障定位系统主要由三大核心部分组成&#x…

微服务|一文带你了解无感知部署方案实战

目录 一、现有部署方案介绍 二、Nacos 介绍 三、影响时间的因素 四、方案目录结构 五、方案脚本实现 六、遇到的问题及优化 七、其他替代方案 一、现有部署方案介绍 在程序开发和运维过程中&#xff0c;会频繁地部署服务&#xff0c;并且每个服务的正常运行都依赖于其他服…

Springboot @RestControllerAdvice全局异常捕获处理

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、RestControllerAdvice二、案例1.自定义异常2.自定义相应常量3.自定义响应类4.核心逻辑5.测试 一、RestControllerAdvice RestControllerAdvice是Spring框架提供…

Linux网络:网络基础

Linux网络&#xff1a;网络基础 一、网络诞生背景及产生的诸多问题1. 1 网络诞生背景1.2 网络诞生面临的困境 二、网络协议栈&#xff08;OSI七层模型、CP/IP五层模型&#xff09;2.1 TCP/IP五层(或四层)模型 三、网络和系统关系四、网络传输流程4.1 同一个局域网中的两台主机进…