PaddleSeg训练推理及模型转换全流程

文章目录

  • 1、数据准备
    • 1.1 数据标注
    • 1.2 数据导出
    • 1.3 标签较验
    • 1.4 数据集整理
    • 1.5 标签可视化
  • 2、 模型训练
  • 3、模型验证
  • 4、模型推理
  • 5、模型导出
  • 6、导出文件的推理
  • 7、将模型转换成onnx
  • 8、使用onnx进行推理

本文记录一下使用paddleseg进行语议分割模型对人体进行分割的使用流程。事实上,做算法是脱离框架的,用啥实现都何以,但到2024了,一个点是如果有预训练模型,那就用起来;另一个是放下内心对于不同框架的喜好,结束束battle,什么 tensorflow,pytorch,paddlepaddle,keras,jax。。。,重心集中到算法和自己的需求上。需求无非是两个,一个是研究,就是researcher,需要发文章,那就看文章用什么做的,我们就跟着用什么,不会的api现场查,用chatgpt生成都可以;框架同质化的今天,真是一通百通,做到能查能用即可,道理都一样; 另一个点就是落地,engineer,最后肯定是用onnx,tensorrt,openvino…布署到相应的硬件上,更多的是拿来主义,跑通,在自己特定的场景上生效就可以。在跑通过程中,可以适当对原理进行探纠。整个过程可以先看看https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.9/docs/whole_process_cn.md

本文主打一个细致,快速训练模型,时间长了也怕忘记,感觉有帮助的话请点个赞。

1、数据准备

1.1 数据标注

用标注神器x-anylabeling,就是咱国产的,功能强大特别好用。labelimg,labelme都用过,相比差多了。如图:
在这里插入图片描述

那说一下它的好处,就是可以用官方的训练好的模型来直接跑图,不用人标,只要后期调一下错的就行。我用的是 combining GroundingDINO with HQ-SAM to achieve sota zero-shot high-quality predictions,就是dino检测+sam分割,效果比人标的好。也可以用自己训练好的yolov8-seg模型来做为预训练模型去自动标注数据。
对标注的理解,也可以参考contrib/PaddleLabel/doc/CN/project/semantic_segmentation.md:
在这里插入图片描述
https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.9/docs/data/marker/marker_cn.md 这个也要看。
就是说paddleseg是要用灰度标注的,但是支持伪彩色标注的。
在这里插入图片描述

1.2 数据导出

关于数据导出,就参考https://github.com/CVHub520/X-AnyLabeling/blob/main/docs/zh_cn/user_guide.md。这里吧。
paddleseg支持的标签是uint8,8bit 灰度图,0默认是表示 background,255表示无作用(应该是为了方便可视化,图像加pad这类操作,不参加loss计算)。1-254 共254个类是我们可以用的(现在不知道超过这个范围怎么办)。
在这里插入图片描述

导出后的图保存在与图片同路径下的mask文件夹下,肉眼看不了,就是全黑。

1.3 标签较验

导出的标签要通过可视化来看是否标注正确。
tools/data 下边有两个一个是gray2pseudo_color.py,另一个是visualize_annotation.py。前一个是转成伪彩色来看,后一个相对麻烦,后边再说。
在这里插入图片描述
生成图片后,看看效果,我这里遇到的一个问题就是dino+sam标注,因为dino检测框多了,所以会有重复的部分,正常操作应该是要在x-anylbeling中删除,但太没没删尽,或者这个单分类的分割任务是不用删的。
在这里插入图片描述
person标签本来是1的,但重叠部分是会变成2,写代码把所有2的部分变成1就可以。
在这里插入图片描述
背景是红色的,1是绿色,2是黄。
这就是看伪彩色的意义。

1.4 数据集整理

官方的结构是这样:
在这里插入图片描述
这里我的准备是这样的:

datasets||-----images|          ||          |----a|          |----b|          |----c||----labels|			|---a|			|---b|			|---c

a,b,c是三个不同数据的来源,images 下边是原图,labels 同名的png标签。
接着生成各个数据集的训练和验证数据集,用如下代码:

Description: 主要是用来生成各个训练集的训练和测试列表
path_rootimagesablabelsab
将生成a_train.txt  b_train.txt ,这里把所有的数据全做成训练集就ok,不浪费数据;验证集把训练集复制一份就好了,不用担心过拟合,不用担心的
'''
import os
from tqdm import tqdmpath_root="/home/tl/PaddleSeg29/datasets"  #最好上一个绝对路径
img_path = os.path.join(path_root,"images")
lb_path = os.path.join(path_root,"labels")image_names=os.listdir(img_path)
label_names=os.listdir(lb_path)#取个交集,更加安全
dataset_names = list(set(image_names) & set(label_names))
#接着对各个数据集分别生成训练列表
for i,dataset in enumerate(dataset_names):print(f"start to do dataset:{dataset}")dataset_images=[i for i in os.listdir(os.path.join(img_path,dataset)) if os.path.splitext(i.lower())[1] in [".png",".jpg",".jpeg"]] #不做过多的数据集质量较验# dataset_labels=os.listdir(os.path.join(img_path,dataset))lines=[]for imgname in tqdm(dataset_images):labelname = os.path.splitext(imgname)[0]+".png" #注意这个后缀,正常都是小写png,如果自己有特别的line = os.path.join("images",dataset,imgname)+" "+os.path.join("labels",dataset,labelname)+"\n"lines.append(line)save_name=os.path.join(path_root,f"{dataset}_train.txt")with open(save_name,"w") as f:f.writelines(lines)
print("Done")

接着,生成最图训练所用的数据列表:
在这里插入图片描述

cat a_train.txt b_train.txt c_train.txt > train.txt
cat b_train.txt c_train.txt > val.txt

每一行都是:

images/a/1.jpg labels/a/1.png
....
images/b/1.jpg labels/b/1.png
...
images/c/1.jpg labels/c/1.png

1.5 标签可视化

这次用到的是tools/data/visualize_annotation.py

python3 tools/data/visualize_annotation.py --file_path ./dataset/MT_dataset/train.txt --save_dir ./show/

效果是这样的:
在这里插入图片描述
这个脚本还可以同时把predict的图显示出来,但要把预测的mask.png放到与原图同一个文件件下,这里就没做,具体看代码。

2、 模型训练

https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.9/contrib/PP-HumanSeg/README_cn.md
因为是训练人像分割,就用pphuman了,配置文件在contrib/config/PPHUmanSeg中,默认的config下边也有好多的模型。
配置文件保存在./configs目录下,如下。配置文件中,已经通过pretrained设置好预训练权重的路径。

configs
├── human_pp_humansegv1_lite.yml
├── human_pp_humansegv2_lite.yml
├── human_pp_humansegv1_mobile.yml
├── human_pp_humansegv2_mobile.yml
├── human_pp_humansegv1_server.yml
执行如下命令,进行模型微调(大家需要根据实际情况修改配置文件中的超参)。模型训练的详细文档,请参考链接。

export CUDA_VISIBLE_DEVICES=0 # Linux下设置1张可用的卡

# set CUDA_VISIBLE_DEVICES=0  # Windows下设置1张可用的卡
python tools/train.py \--config configs/human_pp_humansegv2_lite.yml \--save_dir output/human_pp_humansegv2_lite \--save_interval 100 --do_eval --use_vdl

v1-lite 大概2M,v2-lite 4M v1 mobile 13M v2 mobile 20M
按需求来取。
配置文件和预训练模型都可以拿来用,如下:

batch_size: 256
iters: 2000train_dataset:type: Datasetdataset_root: /home/tl/PaddleSeg29/datasetstrain_path: /home/tl/PaddleSeg29/datasets/train.txtnum_classes: 2transforms:- type: Resizetarget_size: [192, 192]- type: ResizeStepScalingscale_step_size: 0- type: RandomRotation- type: RandomPaddingCropcrop_size: [192, 192]- type: RandomHorizontalFlip- type: RandomDistort- type: RandomBlurprob: 0.3- type: Normalizemode: trainval_dataset:type: Datasetdataset_root: /home/tl/PaddleSeg29/datasetsval_path:  /home/tl/PaddleSeg29/datasets/val.txtnum_classes: 2transforms:- type: Resizetarget_size: [192, 192]- type: Normalizemode: valexport:transforms:- type: Resizetarget_size: [192, 192]- type: Normalizeoptimizer:type: sgdmomentum: 0.9weight_decay: 0.0005lr_scheduler:type: PolynomialDecaylearning_rate: 0.0005end_lr: 0power: 0.9loss:types:- type: MixedLosslosses:- type: CrossEntropyLoss- type: LovaszSoftmaxLosscoef: [0.8, 0.2]coef: [1]model:type: PPHumanSegLitealign_corners: Falsenum_classes: 2#pretrained: /home/tl/PaddleSeg29/models/segv1-lite/human_pp_humansegv1_lite_192x192_pretrained/model.pdparamspretrained: /home/tl/PaddleSeg29/output/seglitev1/best_model/model.pdparams

batch-size iters 看自己的显卡大小来改;学习率也可以改,各参数的意义可以参看:https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.9/docs/whole_process_cn.md,路径的改动:
在这里插入图片描述
最后读取图片,大致是dataset_root分别加上txt文件里的两部分来读取图和target.
模型保存结果为:
在这里插入图片描述

3、模型验证

这步就不做了,因为在训练过程做过。如查要做,可以参看:
https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.9/docs/evaluation/evaluate_cn.md
命令就是:

python tools/val.py \--config configs/quick_start/pp_liteseg_optic_disc_512x512_1k.yml \--model_path output/iter_1000/model.pdparams

在这里插入图片描述
这里我们只关注我们关注的类别,分别有Iou,精确率和召回率。

4、模型推理

命令行如下:

python tools/predict.py \--config configs/human_pp_humansegv2_lite.yml \--model_path pretrained_models/human_pp_humansegv2_lite_192x192_pretrained/model.pdparams \--image_path data/images/human.jpg \--save_dir ./data/images_result

在这里插入图片描述
added_prediction:
在这里插入图片描述
pseudo_color_prediction:
在这里插入图片描述

5、模型导出

导出方便部署,命令行如下:

python tools/export.py \--config configs/human_pp_humansegv2_lite.yml \--model_path pretrained_models/human_pp_humansegv2_lite_192x192_pretrained/model.pdparams \--save_dir output/human_pp_humansegv2_lite \--without_argmax \--with_softmax

更多的需要参照这个文档:https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.9/docs/model_export_cn.md
在这里插入图片描述
因为后处理,只有一个算子,所以一个都不要,我们在外边处理。
导出文件为:
在这里插入图片描述

6、导出文件的推理

导出文件推理,导出模型时的后处理要加argmax,
推理命令为:

python deploy/python/infer.py --config output/inference_model/mobilev2_192_argx/deploy.yaml --image_path human1.jpg --save_dir ./show/out4

输出结果是伪彩色图,大小是192x192和输入一样大小。并没有转回到原图。
在这里插入图片描述

7、将模型转换成onnx

需要用使用paddle2onnx这个工具,转换命令参照这里:
https://github.com/PaddlePaddle/Paddle2ONNX,命令行如下:

paddle2onnx --model_dir saved_inference_model \--model_filename model.pdmodel \--params_filename model.pdiparams \--save_file model.onnx

接着对onnx 进行简化,要用到onnxsim这个包:

python -m onnxsim litev1_192.onnx litev1_sim_192.onnx

在这里插入图片描述
这里作了四个模型,分别如图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
从精度和性能来看。选合适的来用。
onnx相比是更加重要的,因为我们通常是基于onnx进行各种转换再部署到相应的硬件上的。

8、使用onnx进行推理

这部分代码是从predict.py中按照处理流程,结合deeploy/python中的部分代码及github自己整理的,c++的就不搞了,上个Python的.

'''
Author: tianliang
Date: 2024-05-14 16:33:15
LastEditors: tianliang
LastEditTime: 2024-05-16 16:25:47
FilePath: /deeplabv3/main.py
Description: 
'''
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import copy
import argparse
import cv2
import numpy as np
import onnxruntimeclass mobilev1seg:def __init__(self):# Initialize modelself.onnx_session = onnxruntime.InferenceSession("/home/tl/deeplabv3/mobv1_save_shape_sim.onnx")self.input_name = self.onnx_session.get_inputs()[0].nameself.output_name = self.onnx_session.get_outputs()[0].nameself.input_shape = self.onnx_session.get_inputs()[0].shapeself.input_height = self.input_shape[2]self.input_width = self.input_shape[3]self.mean = np.array([0,0,0], dtype=np.float32).reshape(1,1,3)self.std = np.array([1.,1.,1.], dtype=np.float32).reshape(1,1,3)def prepare_input(self, image):input_image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)input_image = cv2.resize(input_image, dsize=(self.input_width, self.input_height),interpolation=cv2.INTER_LINEAR)input_image = (input_image.astype(np.float32) / 255.0 - self.mean) / self.stdinput_image = input_image.transpose(2, 0, 1)input_image = np.expand_dims(input_image, axis=0)return input_imagedef detect_argmax(self, image):input_image = self.prepare_input(image)# Perform inference on the imageresult = self.onnx_session.run([self.output_name], {self.input_name: input_image})# Post process:squeezesegmentation_map = result[0] # 1x2x384x384segmentation_map = np.squeeze(segmentation_map) #2x384x384segmentation_map = np.transpose(segmentation_map,(1,2,0)) #384x384x2image_width, image_height = image.shape[1], image.shape[0] #原图形状segmentation_map = cv2.resize(segmentation_map,dsize=(image_width, image_height),interpolation=cv2.INTER_LINEAR,)  #双线性插值回到原图pred = np.argmax(segmentation_map,axis=-1) # OrigH x OrigW x 2 -> OrigH x OrigW 值就是0,1pred = pred.astype("uint8")#可视化dst_image = copy.deepcopy(image)contours,hierarchy= cv2.findContours(pred,cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)#for c in contours:if len(contours)>0:cv2.drawContours(dst_image, contours, -1, (0, 255, 0), 1)#contours就是所有的点的坐标return dst_imageif __name__ == '__main__':parser = argparse.ArgumentParser()parser.add_argument('--imgpath', type=str, default='3.jpg', help="image path")parser.add_argument('--use_video', type=int, default=0, help="if use video")args = parser.parse_args()save=Truesegmentor = mobilev1seg()if args.use_video != 1:srcimg = cv2.imread(args.imgpath,cv2.IMREAD_COLOR)# Detect Objectsdstimg = segmentor.detect_argmax(srcimg)if save:cv2.imwrite("dst.jpg",dstimg)else:winName = 'Seg in ONNXRuntime'cv2.namedWindow(winName, 0)cv2.imshow(winName, dstimg)cv2.waitKey(0)cv2.destroyAllWindows()else:cap = cv2.VideoCapture(0)  ###也可以是视频文件while True:ret, frame = cap.read()if not ret:breakdstimg = segmentor.detect(frame)key = cv2.waitKey(1)if key == 27:  # ESCbreakcv2.imshow('Seg Demo', dstimg)cap.release()cv2.destroyAllWindows()

对于多分类的,后处理可以适当自己再处理一下。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基础8 探索JAVA图形编程桌面:邮件操作组件详解

在一个静谧的午后,卧龙和凤雏相邀来到一家古朴典雅的茶馆。茶馆内环境清幽,袅袅的茶香与悠扬的古筝声交织在一起,营造出一种宁静而祥和的氛围。 卧龙和凤雏坐在茶馆的一角,面前的桌子上摆放着一套精致的茶具。茶香四溢&#xff0c…

科技查新是什么?一文了解!

本文主要解答 1、什么是科技查新? 2、科技查新有哪些作用? 3、科技查新一般应用于什么地方? 4、在哪能出具正规查新报告? 5、科技查新流程是怎样的? 带着这些问题阅读这篇文章相信一定会有收获!干活内…

第十三届蓝桥杯国赛大学B组填空题(c++)

A.2022 动态规划 AC; #include<iostream> #define int long long using namespace std; int dp[2050][15]; //dp[i][j]:把数字i分解为j个不同的数的方法数 signed main(){dp[0][0]1;for(int i1;i<2022;i){for(int j1;j<10;j){//一种是已经分成j个数,这时只需每一个…

服务器上创建搭建gitlab

一、下载与安装 在主目录操作~ 1.使用wget下载 wget --no-check-certificate https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-14.0.1-ce.0.el7.x86_64.rpm 可以在开源软件镜像站选择合适的版本&#xff0c;版本不同页面菜单会稍有差异&#xff0c;此次选…

【云原生 | 59】Docker中通过docker-compose部署ELK

目录 1、组件介绍 2 、项目环境 2.1 各个环境版本 2.2 Docker-Compose变量配置 2.3 Docker-Compose服务配置 3、在Services中声明了四个服务 3.1 ElasticSearch服务 3.2 Logstash服务 3.3 Kibana服务 3.4 Filebeat服务 4、使用方法 4.1 方法一 4.2 方法二 5、启动…

想让企业“火力全开”?找六西格玛培训公司就对了!

在如今的市场环境中&#xff0c;企业面临着不断变化的挑战和无限的可能。要在这场竞争中独领风骚&#xff0c;实现稳健的增长&#xff0c;六西格玛作为一种以数据驱动的管理理论&#xff0c;提供了实际可行的解决方案。六西格玛培训公司&#xff0c;作为这一领域的专家&#xf…

element ui 的密码输入框点击显示隐藏密码时,图标随之改变

场景图&#xff1a; 原理&#xff1a; 通过修改el-input框的type属性&#xff0c;来设置显示或者隐藏。从而改变图标地址。 <el-input class"passwordinput" :type"pwdObj.pwdType" ref"pwdInput" placeholder"密码"v-model"…

VirtualBox虚拟机与bhyve虚拟机冲突问题解决@FreeBSD

问题 在安装完bhyve虚拟系统的主机上启动VirtualBox虚拟机的时候&#xff0c;报错&#xff1a;不能为虚拟电脑 debian 打开一个新任务. VirtualBox cant operate in VMX root mode. Please close all other virtualization programs. (VERR_VMX_IN_VMX_ROOT_MODE). 返回 代码…

【源码】【海外客服】简洁版海外客服系统/在线客服系统/即时聊天通讯源码

1&#xff0c;此版本采用前台一人或多人与后台一人&#xff08;管理员&#xff09;进行会话模式 2&#xff0c;此版本前后台只能发送文字和图片&#xff08;图片是选择后自动发送&#xff09; 3&#xff0c;前后台根据IP来识别不同的会话者 4&#xff0c;前台发起会话后&…

CSS(七)

文章目录 CSS&#xff08;七&#xff09;1. 精灵图&#xff08;重点&#xff09;1.1 为什么需要精灵图1.2 精灵图&#xff08;sprites&#xff09;的使用1.3 案例&#xff1a;拼出自己名字1.3.1 案例效果1.3.2 代码参考 2. 字体图标2.1 字体图标的产生2.2 字体图标的优点**2.3*…

57. UE5 RPG 处理AI敌人转向以及拾取物品的问题

在上一篇文章中&#xff0c;我们实现了使用AI行为树控制敌人进行移动&#xff0c;它们可以一直跟随玩家&#xff0c;虽然现在还未实现攻击。但在移动过程中&#xff0c;我发现了有两个问题&#xff0c;第一个是敌人转向的时候很僵硬&#xff0c;可以说是瞬间转向的&#xff0c;…

MM模块六(收货)

接到供应商收到的货以后&#xff0c;进行一个收货的动作 收货&#xff1a;MIGO 1.消耗物料的采购订单 数量是供应商的数量 消耗物料的采购订单&#xff0c;收进来的货物直接进入消耗&#xff0c;不会增加库存&#xff0c;所以这里没有库存地点进行选择 点击过账 收货后在采购…

Epic Pen Pro v3 解锁版安装教程 (屏幕实时标记注释工具)

前言 Epic Pen是一款功能强大的屏幕标记工具&#xff0c;允许您在屏幕上绘图或书写&#xff0c;而无需在后台与软件交互。这意味着您几乎可以注释任何东西&#xff01;使用我们流行的屏幕标记和Windows数字白板工具Epic Pen编写、绘制和突出显示&#xff0c;包括演示文稿软件&…

【Linux】线程安全及锁的使用

文章目录 前言一、锁1.定义一个锁变量2.pthread_mutex_init3.pthread_mutex_destroy4.pthread_mutex_lock/pthread_mutex_unlock5.静态变量锁和全局变量锁的初始化 二、问题描述及锁的运用三、RAII风格的锁 前言 临界资源: 在多个线程或进程间共享的资源. 临界区: 代码中访问临…

目标检测——家庭日常用品数据集

引言 亲爱的读者们&#xff0c;您是否在寻找某个特定的数据集&#xff0c;用于研究或项目实践&#xff1f;欢迎您在评论区留言&#xff0c;或者通过公众号私信告诉我&#xff0c;您想要的数据集的类型主题。小编会竭尽全力为您寻找&#xff0c;并在找到后第一时间与您分享。 …

maven聚合工程整合springboot+mybatisplus遇到的问题

前言&#xff08;可以直接跳过看下面解决方法&#xff09; 项目结构 两个module&#xff1a; yema-terminal-boot 是springboot项目&#xff0c;子包有&#xff1a;controller、service、dao 等等。属于经典三层架构。那么&#xff0c;该module可以理解为是一个单体项目&…

uniapp - 填充页面

在上一篇文章中&#xff0c;创建了一个空白的文章模块页面。在这一篇文章&#xff0c;让我们来向页面中填充内容。 目录 页面效果涉及uniapp组件1.view2.swiper3.scroll-view4.属性解读1) class"style1 style2 .."2) circular单属性无赋值3) :autoplay"autoplay…

SpringSecurity6从入门到实战之SpringSecurity快速入门

SpringSecurity6从入门到实战之SpringSecurity快速入门 环境准备 依赖版本号springsecurity6.0.8springboot3.0.12JDK17 这里尽量与我依赖一致,免得在学习过程中出现位置的bug等 创建工程 这里直接选择springboot初始化快速搭建工程,导入对应的jdk17进行创建 直接勾选一个web…

使用Python发送电子邮件

大家好&#xff0c;当我们需要迅速、方便地与他人沟通时&#xff0c;电子邮件是无疑是一种不可或缺的通信工具。无论是在个人生活中还是工作场合&#xff0c;电子邮件都是我们日常生活中的重要组成部分。它不仅能够传递文字信息&#xff0c;还可以发送附件、链接和嵌入式多媒体…

如何将音频中的人声分离出来?

想要把一段视频中的人声跟背景音乐分离开来&#xff0c;找个好一点的音频处理软件就能把声音分离了&#xff0c;常见的有以下方法&#xff0c;一起来看看吧。 pr 打开软件&#xff0c;然后将电脑上的音频文件&#xff0c;上传到软件中&#xff0c;然后按住[ctrla]选择所有音频…