DDRNet-通过PaddleSeg实现全流程跑通


本项目基于DDRNet实现实时语义分割,将其由其他框架转为PaddlePaddle实现并轻量化,用深度可分卷积提升推理速度。使用surpvisely人像数据集,提供带中文注释的网络文件,需创建YML配置文件按PaddleSeg流程训练,还包含数据集处理、训练及测试相关代码与说明。

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

项目背景

      本项目是基于实时准确语义分割的深度双分辨率网络DDRNet创建的,其中DDRNet一个版本Cityscapes test上达到109 FPS / 77.4%mIoU!表现达到SOTA!综合性能优于SFNet、MSFNet和BiSeNetV2等网络。因为项目需求,需要使用到DDRNet,而paddleseg里面尚未内置有DDRNet的网络文件,而源代码作者已经开源,但是是基于其他框架实现的,所以我就将源代码改为使用paddlepaddle实现,并且将其做了一定的改进。
      1.本项目中的DDRNet的网络实现并不是原版,因为项目需要,所以我对其做了一定的轻量化处理,进行了将普通卷积替换成深度可分卷积等操作,让该网络的推理速度得到了进一步的提升。
      2.网络文件在Notebook处,可根据需要修改,并且将其按照PaddleSeg官方文档,进行自定义模型,完成训练。
      3.本项目的数据集是surpvisely人像数据集,可根据需要进行修改。
      4.网络文件已经进行了中文注释,方便阅读。

   

环境配置

首先安装Paddleseg环境

此处使用gitee的下载联机,在国内使用下载更快

In [ ]
!pip install paddleseg
    In [ ]
!git clone https://gitee.com/PaddlePaddle/PaddleSeg
    In [1]
#进入数据集目录%cd data/data61378/
       
/home/aistudio/data/data61378
        In [ ]
#对数据集进行解压,并且返回根目录!unzip humanseg.zip%cd
   

相关配置提示

因为本项目所使用的DDRNet并非paddleseg内置的网络模型

所以需要自己创建YML文件,以及模型文件,在下方的Code Block中已经给出,可根据需要自己更改,如不是很了解YML文件如何使用,可以在paddleseg的仓库中,找到相关的使用教程

此处附上链接: https://gitee.com/paddlepaddle/PaddleSeg#%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B-

YML配置文件,应创建在 work/PaddleSeg/configs/ddrnet/ddrnet.yml 路径下 下方为YML文件内容,复制粘贴进去即可

以下为YML文件配置

batch_size: 48 # 设定迭代一次送入网络的图片数量。一般来说,你所使用机器的显存越大,可以调高batch_size的值。iters: 5000 # 迭代次数model:
  type: DDRNet # 自定义模型类的名称
  num_classes: 2 # 标注图中像素类别个数。你的模型应该是根据具体的分割任务设计的,因此你知道该任务下像素类别个数
  pretrained: output/iter_12000 # 如果你有网络的与预训练参数,请指定其存放路径train_dataset:
  type: Dataset # 自定义数据集类的名称
  dataset_root: data/data61378/humanseg/
  train_path: data/data61378/humanseg/train.txt
  num_classes: 2   #此处为模型输出类别数, 本项目中为人像分割,所以有人像+背景两类,故为2
  transforms:
    - type: Resize
      target_size: [512, 512]    - type: ResizeStepScaling
      min_scale_factor: 0.5
      max_scale_factor: 2.0
      scale_step_size: 0.25
    - type: RandomPaddingCrop
      crop_size: [512, 512]    - type: RandomHorizontalFlip
    - type: RandomDistort
      brightness_range: 0.4
      contrast_range: 0.4
      saturation_range: 0.4
    - type: Normalize
  mode: train # 对训练集设定训练模式val_dataset:
  type: Dataset
  dataset_root: data/data61378/humanseg/
  val_path: data/data61378/humanseg/val.txt
  num_classes: 2   
  transforms:
    - type: Resize
      target_size: [512, 512]    - type: Normalize
  mode: val # 对验证集设定验证模式optimizer: # 优化器设置
  type: sgd 
  momentum: 0.9
  weight_decay: 4.0e-5lr_scheduler: # 学习率的设置
  type: PolynomialDecay
  learning_rate: 0.01
  power: 0.9
  end_lr: 0# lr_scheduler:#   type: ReduceOnPlateau#   learning_rate: 0.04#   mode: 'min'#   factor: 0.6#   patience: 1000#   threshold_mode: 'rel'#   verbose: Trueloss:
  types:
    - type: CrossEntropyLoss
  coef: [1]
   

数据集处理

接下来的两个Code Block为处理数据集的代码,将surpervisely数据集的格式处理为符合paddleseg套件的要求格式进行训练。

数据处理完之后,会生成两个txt文件,train.txt文件和val.txt文件,分别对应训练数据集的路径,和验证数据集路径

In [2]
#将数据集中的标签文件转换为符合paddle框架要求的标签文件#此处处理时间会比较久,需要稍微等待一下import cv2import osimport numpy as npfrom tqdm import tqdmdef three2one(path,path_):
    img=cv2.imread(path) 
    img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    ret,img=cv2.threshold(img,2,255,cv2.THRESH_BINARY)
    img = np.uint8((np.double(img)) / 255)
    cv2.imwrite(path_,img)

root = r'data/data61378/humanseg/person_mask'root_ = r'data/data61378/humanseg/person_mask_data'if not os.path.exists(root_):
    os.mkdir(root_)

names = os.listdir(root)for i,name in enumerate(names):    if name[-2]=='n':        # print(name[-3])
        path = os.path.join(root,name)
        path_ = os.path.join(root_,name)        # print(path)
        three2one(path,path_)# 适配数据集路径-0src_0 = r'data/data61378/humanseg/person_mask'dst_0 = r'data/data61378/humanseg/person_mask_orig'os.rename(src_0, dst_0)# 适配数据集路径-1src_1 = r'data/data61378/humanseg/person_mask_data'dst_1 = r'data/data61378/humanseg/person_mask'os.rename(src_1, dst_1)print('Done!')
       
Done!
        In [4]
###surpervisely数据集的label和train.txt的生成###挂载的数据集的label和train的txt文件里面的内容是重复的###将数据集打乱,按9:1比例划分训练集和验证集#进入目标目录%cd data/data61378/humansegimport osimport numpy as npfrom tqdm import tqdmimport matplotlib.pyplot as pltimport cv2from PIL import Image

data = []
path_img = 'person'path_lab = 'person_mask'train_txt = 'train.txt'label_txt = 'val.txt'def dataset(data, path_img, path_lab):

    for item in os.listdir(path_img):
        img = os.path.join(path_img, item)
        label = os.path.join(path_lab, item.split('.')[0] + '.png')
        data.append([os.path.join(path_img, item),
                     os.path.join(path_lab, item.split('.')[0] + '.png')
                     ])        if os.path.exists(img) and os.path.exists(label):            pass
        else:            raise 'path error!'
    np.random.shuffle(data)    # 划分训练集和验证集
    train_data = data[len(data) // 9:]
    val_data = data[:len(data) // 9]
    write_path(train_data, train_txt)
    write_path(val_data, label_txt)def write_path(data, path):
    with open(path ,'w') as f:        for item in tqdm(data):
            f.write(item[0] + ' ' + item[1] + '\n')        print('Done!')    print('Total: ', len(data))#显示出来看看对不对def draw(img_list, name=None):
    plt.figure(figsize=(20, 20))    for i in range(len(img_list)):
        plt.subplot(1, len(img_list), i+1)
        plt.imshow(img_list[i])        if name:
            plt.title(name[i])    #plt.legend()
    plt.show()#处理数据集图片dataset(data, path_img, path_lab)#展示测试img1 = cv2.cvtColor(cv2.imread('person/active-cold-female-girl-41371.jpeg'), cv2.COLOR_BGR2RGB)  # BGR -> RGBimg2_lab = cv2.imread('person_mask/active-cold-female-girl-41371.png')[..., 0]
draw([img1, img2_lab])#返回根目录%cd
       
100%|██████████| 5077/5077 [00:00<00:00, 936968.43it/s]
100%|██████████| 634/634 [00:00<00:00, 518562.55it/s]
       
/home/aistudio/data/data61378/humanseg
Done!
Total:  5077
Done!
Total:  634
       

       
               
/home/aistudio
       

DDRNet网络文件

下方的code blcok为DDRNet的实现

我对其进行了一定的轻量化处理,在性能降低很小的情况下,加快了在CPU上的推理速度。

自定义网络文件的路径为 work/PaddleSeg/paddleseg/models/ddrnet.py

并且需要在work/PaddleSeg/paddleseg/models/init.py 中进行初始化,具体使用教程在paddleseg仓库中已经有提及,并且非常详细。

下图为DDRNet的结构图

       

In [ ]
'''
    DDRNet网络文件,进行了轻量化,将卷积替换成深度可分卷积,并进行了channel_shuffle
    目前测试,在CPU推理时间为200ms/张
    GPU推理时间为60ms/张
'''from paddleseg.models import layersfrom paddleseg.cvlibs import managerfrom paddleseg.utils import utilsimport paddleimport paddle.nn as nnimport paddle.nn.functional as Fimport numpy as np

bn_mom = 0.1def channel_shuffle(x, groups):
    ### type: (torch.Tensor, int) -> torch.Tensor
    #print(x.shape)
    batchsize, num_channels, height, width = x.shape
    channels_per_group = num_channels // groups    # reshape
    x = paddle.reshape(x, [batchsize, groups, channels_per_group, height, width])

    x = paddle.transpose(x, [0, 2, 1, 3, 4])    # flatten
    x = paddle.reshape(x, [batchsize, -1, height, width])    return xclass DwConv(nn.Layer):
    def __init__(self, inplanes, out_channels,  kernel_size=3, stride=1, padding=1,bias_attr=False):
        super(DwConv, self).__init__()
        self.depth_conv = nn.Conv2D(inplanes, inplanes, kernel_size=kernel_size, stride=stride, padding=padding, groups=inplanes, bias_attr=bias_attr)
        self.point_conv = nn.Conv2D(inplanes, out_channels, kernel_size=1, stride=1, padding=0, groups=8,bias_attr=bias_attr)    def forward(self, x):
        x = self.depth_conv(x)
        x = self.point_conv(x)
        x = channel_shuffle(x, groups=8)        return x#论文作者修改过了的resblockclass basicBlock(nn.Layer):
    expansion = 1
    def __init__(self,inplanes, out_channels, stride=1, downsample=None, no_relu=False):
        super(basicBlock, self).__init__()
        self.conv1 =  DwConv(inplanes, out_channels, kernel_size=3,
                                stride=stride,padding=1)
        self.bn1 = nn.BatchNorm2D(out_channels, momentum=bn_mom)
        self.relu = nn.ReLU()
        self.conv2 = DwConv(out_channels, out_channels,kernel_size=3,
                               stride=1,padding=1)
        self.bn2 = nn.BatchNorm2D(out_channels, momentum=bn_mom)
        self.downsample = downsample
        self.stride = stride
        self.no_relu = no_relu    def forward(self, x):
        res = x
        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)
        out = self.conv2(out)
        out = self.bn2(out)        if self.downsample is not None:
            res = self.downsample(x)

        out += res        if self.no_relu:            return out        else:            return self.relu(out)class Bottleneck(nn.Layer):
    expansion = 2 #通道扩大倍数

    def __init__(self, inplanes, out_channels, stride=1, downsample=None, no_relu=True):
        super(Bottleneck, self).__init__()        super(Bottleneck, self).__init__()
        self.conv1 = nn.Conv2D(inplanes, out_channels, kernel_size=1, bias_attr=False)
        self.bn1 = nn.BatchNorm2D(out_channels, momentum=bn_mom)
        self.conv2 = DwConv(out_channels, out_channels, kernel_size=3, stride=stride,
                               padding=1, bias_attr=False)
        self.bn2 = nn.BatchNorm2D(out_channels, momentum=bn_mom)
        self.conv3 = nn.Conv2D(out_channels, out_channels * self.expansion, kernel_size=1,
                               bias_attr=False)
        self.bn3 = nn.BatchNorm2D(out_channels * self.expansion, momentum=bn_mom)
        self.relu = nn.ReLU()
        self.downsample = downsample
        self.stride = stride
        self.no_relu = no_relu    def forward(self, x):
        res = x

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)
        out = self.relu(out)

        out = self.conv3(out)
        out = self.bn3(out)        if self.downsample is not None:
            res = self.downsample(x)

        out += res        if self.no_relu:            return out        else:            return self.relu(out)#论文中提出的特征提取结构 实验中效果比PPM更好class DAPPM(nn.Layer):
    def __init__(self, inplanes, branch_planes, outplanes):
        super(DAPPM, self).__init__()        #获得不同感受野
        self.scale0 = nn.Sequential(
                                    nn.BatchNorm2D(inplanes, momentum=bn_mom),
                                    nn.ReLU(),
                                    nn.Conv2D(inplanes, branch_planes, kernel_size=1, bias_attr=False),
                                    )
        self.scale1 = nn.Sequential(nn.AvgPool2D(kernel_size=5, stride=2, padding=2),
                                    nn.BatchNorm2D(inplanes, momentum=bn_mom),
                                    nn.ReLU(),
                                    nn.Conv2D(inplanes, branch_planes, kernel_size=1, bias_attr=False),
                                    )
        self.scale2 = nn.Sequential(nn.AvgPool2D(kernel_size=9, stride=4, padding=4),
                                    nn.BatchNorm2D(inplanes, momentum=bn_mom),
                                    nn.ReLU(),
                                    nn.Conv2D(inplanes, branch_planes, kernel_size=1, bias_attr=False),
                                    )
        self.scale3 = nn.Sequential(nn.AvgPool2D(kernel_size=17, stride=8, padding=8),
                                    nn.BatchNorm2D(inplanes, momentum=bn_mom),
                                    nn.ReLU(),
                                    nn.Conv2D(inplanes, branch_planes, kernel_size=1, bias_attr=False),
                                    )
        self.scale4 = nn.Sequential(nn.AdaptiveAvgPool2D((1, 1)),
                                    nn.BatchNorm2D(inplanes, momentum=bn_mom),
                                    nn.ReLU(),
                                    nn.Conv2D(inplanes, branch_planes, kernel_size=1, bias_attr=False),
                                    )        #对不同感受野特征图进行特征提取
        self.process1 = nn.Sequential(
            nn.BatchNorm2D(branch_planes, momentum=bn_mom),
            nn.ReLU(),
            DwConv(branch_planes, branch_planes, kernel_size=3, padding=1, bias_attr=False),
        )
        self.process2 = nn.Sequential(
            nn.BatchNorm2D(branch_planes, momentum=bn_mom),
            nn.ReLU(),
            DwConv(branch_planes, branch_planes, kernel_size=3, padding=1, bias_attr=False),
        )
        self.process3 = nn.Sequential(
            nn.BatchNorm2D(branch_planes, momentum=bn_mom),
            nn.ReLU(),
            DwConv(branch_planes, branch_planes, kernel_size=3, padding=1, bias_attr=False),
        )
        self.process4 = nn.Sequential(
            nn.BatchNorm2D(branch_planes, momentum=bn_mom),
            nn.ReLU(),
            DwConv(branch_planes, branch_planes, kernel_size=3, padding=1, bias_attr=False),
        )        #concat层
        self.compression = nn.Sequential(
            nn.BatchNorm2D(branch_planes * 5, momentum=bn_mom),
            nn.ReLU(),
            nn.Conv2D(branch_planes * 5, outplanes, kernel_size=1, bias_attr=False),
        )

        self.shortcut = nn.Sequential(
            nn.BatchNorm2D(inplanes, momentum=bn_mom),
            nn.ReLU(),
            nn.Conv2D(inplanes, outplanes, kernel_size=1, bias_attr=False),
        )    def forward(self, x):
        # x.shape: NCHW

        width = x.shape[-1]
        height = x.shape[-2]
        x_list = []

        x_list.append(self.scale0(x))
        x_list.append(self.process1((F.interpolate(self.scale1(x),
                                                   size=[height, width],
                                                   mode='bilinear') + x_list[0])))
        x_list.append((self.process2((F.interpolate(self.scale2(x),
                                                    size=[height, width],
                                                    mode='bilinear') + x_list[1]))))
        x_list.append(self.process3((F.interpolate(self.scale3(x),
                                                   size=[height, width],
                                                   mode='bilinear') + x_list[2])))
        x_list.append(self.process4((F.interpolate(self.scale4(x),
                                                   size=[height, width],
                                                   mode='bilinear') + x_list[3])))        # NCHW
        out = self.compression(paddle.concat(x_list, 1)) + self.shortcut(x)        return outclass segmenthead(nn.Layer):
    def __init__(self, inplanes, interplanes, outplanes, scale_factor=None):
        super(segmenthead, self).__init__()
        self.bn1 = nn.BatchNorm2D(inplanes, momentum=bn_mom)
        self.conv1 = DwConv(inplanes, interplanes, kernel_size=3, padding=1, bias_attr=False)
        self.bn2 = nn.BatchNorm2D(interplanes, momentum=bn_mom)
        self.relu = nn.ReLU()
        self.conv2 = nn.Conv2D(interplanes, outplanes, kernel_size=1, padding=0, bias_attr=True)
        self.scale_factor = scale_factor    def forward(self, x):
        x = self.conv1(self.relu(self.bn1(x)))
        out = self.conv2(self.relu(self.bn2(x)))        if self.scale_factor is not None:
            height = x.shape[-2] * self.scale_factor
            width = x.shape[-1] * self.scale_factor
            out = F.interpolate(out,
                                size=[height, width],
                                mode='bilinear')        return outclass DualRseNet(nn.Layer):         #双边残存网络
    def __init__(self, block, layers, num_classes=2, planes=64, spp_planes=128, head_planes=128, augment=False,pretrained=None):
        super(DualRseNet, self).__init__()

        hige_planes = planes * 2
        self.augment = augment
        self.pretrained = pretrained
        self.conv1 = nn.Sequential(
            nn.Conv2D(in_channels=3, out_channels=planes, kernel_size=3, stride=2, padding=1),
            nn.BatchNorm2D(planes, momentum=bn_mom),
            nn.ReLU(),
            DwConv(planes,planes,kernel_size=3, stride=2, padding=1),
            nn.BatchNorm2D(planes, momentum=bn_mom),
            nn.ReLU()
        )
        self.relu = nn.ReLU()
        self.layer1 = self._make_layer(block, planes, planes, layers[0])
        self.layer2 = self._make_layer(block, planes, planes * 2, layers[1], stride=2)
        self.layer3 = self._make_layer(block, planes * 2, planes * 4, layers[2], stride=2)
        self.layer4 = self._make_layer(block, planes * 4, planes * 8, layers[3], stride=2)
        self.compression3 = nn.Sequential(
            nn.Conv2D(planes * 4, hige_planes, kernel_size=1, bias_attr=False),
            nn.BatchNorm2D(hige_planes, momentum=bn_mom),
        )

        self.compression4 = nn.Sequential(
            nn.Conv2D(planes * 8, hige_planes, kernel_size=1, bias_attr=False),
            nn.BatchNorm2D(hige_planes, momentum=bn_mom),
        )

        self.down3 = nn.Sequential(
            DwConv(hige_planes, planes * 4, kernel_size=3, stride=2, padding=1, bias_attr=False),
            nn.BatchNorm2D(planes * 4, momentum=bn_mom),
        )

        self.down4 = nn.Sequential(
            DwConv(hige_planes, planes * 4, kernel_size=3, stride=2, padding=1, bias_attr=False),
            nn.BatchNorm2D(planes * 4, momentum=bn_mom),
            nn.ReLU(),
            DwConv(planes * 4, planes * 8, kernel_size=3, stride=2, padding=1, bias_attr=False),
            nn.BatchNorm2D(planes * 8, momentum=bn_mom),
        )

        self.layer3_ = self._make_layer(block, planes * 2, hige_planes, 2)

        self.layer4_ = self._make_layer(block, hige_planes, hige_planes, 2)

        self.layer5_ = self._make_layer(Bottleneck, hige_planes, hige_planes, 1)

        self.layer5 = self._make_layer(Bottleneck, planes * 8, planes * 8, 1, stride=2)

        self.spp = DAPPM(planes * 16, spp_planes, planes * 4)        # segmenthead 分割头
        if self.augment:
            self.seghead_extra = segmenthead(hige_planes, head_planes, num_classes)

        self.final_layer = segmenthead(planes * 4, head_planes, num_classes)        for m in self.sublayers():            if isinstance(m, nn.Conv2D):
                n = m.weight.shape[0]*m.weight.shape[1]*m.weight.shape[2]
                v = np.random.normal(loc=0.,scale=np.sqrt(2./n),size=m.weight.shape).astype('float32')
                m.weight.set_value(v)            elif isinstance(m, nn.BatchNorm):
                m.weight.set_value(np.ones(m.weight.shape).astype('float32'))
                m.bias.set_value(np.zeros(m.bias.shape).astype('float32'))
        self.init_weight()    #残差结构的生成
    def _make_layer(self, block, inplanes, planes, blocks, stride=1):
        downsample = None
        if stride != 1 or inplanes != planes * block.expansion:   # basic.expansion=1   bottle.expansion=2
            downsample = nn.Sequential(                           # 使用conv进行下采样
                nn.Conv2D(inplanes, planes * block.expansion,
                          kernel_size=1, stride=stride, bias_attr=False),
                nn.BatchNorm2D(planes * block.expansion, momentum=bn_mom),
            )

        layers = []
        layers.append(block(inplanes, planes, stride, downsample))   # 1个block
        inplanes = planes * block.expansion        for i in range(1, blocks):            if i == (blocks - 1):
                layers.append(block(inplanes, planes, stride=1, no_relu=True))  # 最后一个层使用relu输出
            else:
                layers.append(block(inplanes, planes, stride=1, no_relu=False))        return nn.Sequential(*layers)    def forward(self, x):
        # x.shape: NCHW
        input = x
        width_output = x.shape[-1] // 8
        height_output = x.shape[-2] // 8

        layers = []
        x = self.conv1(x)  # conv1

        x = self.layer1(x)
        layers.append(x)        # conv2 layer[0]

        x = self.layer2(self.relu(x))
        layers.append(x)        # conv3 layer[1]

        x = self.layer3(self.relu(x))           # 低分辨率层
        layers.append(x)        # conv4 layer[2]
        x_ = self.layer3_(self.relu(layers[1]))  # 复制一份 高分辨率层

        # Bilateral fusion 论文中的融合方法
        x = x + self.down3(self.relu(x_))       # 高分辨率 通过conv下采样 与低分辨率相加
        x_ = x_ + F.interpolate(                   # 低分辨率上采样后和高分辨率相加
            self.compression3(self.relu(layers[2])), # 1x1conv 将通道下降
            size=[height_output, width_output],
            mode='bilinear')        if self.augment:
            temp = x_        # Conv5_1       使用basicblock
        x = self.layer4(self.relu(x))       # 低分辨率层
        layers.append(x)                    # conv5_1 layer[3]
        x_ = self.layer4_(self.relu(x_))    # 高分辨率

        # Bilateral fusion
        x = x + self.down4(self.relu(x_))   # 高分辨率 通过conv下采样 与低分辨率相加
        x_ = x_ + F.interpolate(            # 低分辨率上采样后和高分辨率相加
            self.compression4(self.relu(layers[3])),    # 1x1conv 将通道下降
            size=[height_output, width_output],
            mode='bilinear')        #print(x_)
        #Conv5_1阶段     使用bottleblock
        x_ = self.layer5_(self.relu(x_))        # 高分通道
        x = F.interpolate(                      # 低分通道
            self.spp(self.layer5(self.relu(x))),    # 使用DAPPM进行多尺度特征融合
            size=[height_output, width_output],
            mode='bilinear')

        x_ = self.final_layer(x + x_)        if self.augment:  #辅助计算损失
            x_extra = self.seghead_extra(temp)            return [x_, x_extra]        else:            return [F.interpolate(x_,
                                 size=[input.shape[-2],input.shape[-1]],
                                 mode='bilinear')]        
    def init_weight(self):
        if self.pretrained is not None:
            utils.load_entire_model(self, self.pretrained)    

def DualResNet_imagenet(num_classes, pretrained=None):
    model = DualRseNet(basicBlock, [2, 2, 2, 2], num_classes=num_classes, planes=32, spp_planes=128, head_planes=64, augment=False, pretrained=pretrained)    #加载预训练模型 填入地址
    
    return model@manager.MODELS.add_componentdef DDRNet(num_classes, pretrained):
    model = DualResNet_imagenet(num_classes=num_classes, pretrained=pretrained)    return model
   

进行训练

In [5]
!python work/PaddleSeg/train.py \
       --config work/PaddleSeg/configs/ddrnet/ddrnet.yml \
       --do_eval \
       --save_interval 500 \
       --save_dir output
       
2025-03-17 16:58:22 [INFO]
------------Environment Information-------------
platform: Linux-4.4.0-150-generic-x86_64-with-debian-stretch-sid
Python: 3.7.4 (default, Aug 13 2019, 20:35:49) [GCC 7.3.0]
Paddle compiled with cuda: True
NVCC: Cuda compilation tools, release 10.1, V10.1.243
cudnn: 7.6
GPUs used: 1
CUDA_VISIBLE_DEVICES: None
GPU: ['GPU 0: Tesla V100-SXM2-32GB']
GCC: gcc (Ubuntu 7.5.0-3ubuntu1~16.04) 7.5.0
PaddleSeg: 2.4.0
PaddlePaddle: 2.2.2
OpenCV: 4.1.1
------------------------------------------------
2025-03-17 16:58:22 [INFO]
---------------Config Information---------------
batch_size: 48
iters: 5000
loss:
  coef:
  - 1
  types:
  - ignore_index: 255
    type: CrossEntropyLoss
lr_scheduler:
  end_lr: 0
  learning_rate: 0.01
  power: 0.9
  type: PolynomialDecay
model:
  num_classes: 2
  pretrained: null
  type: DDRNet
optimizer:
  momentum: 0.9
  type: sgd
  weight_decay: 4.0e-05
train_dataset:
  dataset_root: data/data61378/humanseg/
  mode: train
  num_classes: 2
  train_path: data/data61378/humanseg/train.txt
  transforms:
  - target_size:
    - 640
    - 640
    type: Resize
  - max_scale_factor: 2.0
    min_scale_factor: 0.5
    scale_step_size: 0.25
    type: ResizeStepScaling
  - crop_size:
    - 640
    - 640
    type: RandomPaddingCrop
  - type: RandomHorizontalFlip
  - brightness_range: 0.4
    contrast_range: 0.4
    saturation_range: 0.4
    type: RandomDistort
  - type: Normalize
  type: Dataset
val_dataset:
  dataset_root: data/data61378/humanseg/
  mode: val
  num_classes: 2
  transforms:
  - target_size:
    - 640
    - 640
    type: Resize
  - type: Normalize
  type: Dataset
  val_path: data/data61378/humanseg/val.txt
------------------------------------------------
W0317 16:58:22.691426  3549 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 10.1, Runtime API Version: 10.1
W0317 16:58:22.691483  3549 device_context.cc:465] device: 0, cuDNN Version: 7.6.
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/nn/layer/norm.py:653: UserWarning: When training, we now always track global mean and variance.
  "When training, we now always track global mean and variance.")
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/dygraph/math_op_patch.py:253: UserWarning: The dtype of left and right variables are not the same, left dtype is paddle.float32, but right dtype is paddle.int64, the right dtype will convert to paddle.float32
  format(lhs_dtype, rhs_dtype, lhs_dtype))
2025-03-17 16:59:33 [INFO]	[TRAIN] epoch: 1, iter: 10/5000, loss: 0.6333, lr: 0.009984, batch_cost: 6.6284, reader_cost: 6.25825, ips: 7.2416 samples/sec | ETA 09:11:15
^C
       

测试下模型分割的效果好不好

需要自己上次图片,然后在image_path填好路径噢

输出的路径为save_dir处,根据自己需求更改

In [ ]
!python work/PaddleSeg/predict.py \
       --config work/PaddleSeg/configs/ddrnet/ddrnet.yml \
       --model_path output/best_model/model.pdparams\
       --image_path data/test.png \
       --save_dir output/result
   

效果展示

In [4]
import numpy as npfrom PIL import Image

img= Image.open('output/result/added_prediction/result.png')
img.show()
       


# gitee  # 配置文件  # 可根据  # 时间为  # 对其  # 轻量化  # 辨率  # 将其  # 自定义  # 进行了  # 低分  # linux  # https  # paddlepaddle  # asic  # igs  # red  # cos  # ai  # git  # python 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化91478 】 【 技术知识72672 】 【 云计算0 】 【 GEO优化84317 】 【 优选文章0 】 【 营销推广36048 】 【 网络运营41350 】 【 案例网站102563 】 【 AI智能45237


相关推荐: 批改网AI检测工具怎么生成评分报告_批改网AI检测工具报告生成与维度解读【指南】  Midjourney怎样加元素词丰富画面_Midjourney元素词技巧【方法】  在线歌曲歌词生成器:创意歌词轻松创作指南  利用AI自动化生成电子书:Make.com的终极教程  lovemo网页版直接进入 lovemo官网在线登录  Agentic Testing入门:使用Playwright和Claude Code构建自动化框架  豆包Ai官方网页版入口地址_豆包Ai官网在线使用入口  百度AI助手在线体验入口 最新版免费试用入口  提升效率的AI工具:Jace、Yutori、Dia等效率神器测评  n8n:零代码AI自动化平台的终极指南和免费VPS设置  百度AI助手入口在哪 怎么找到聊天入口  LogMeIn Resolve:IT 运维知识库的 AI 赋能实践  百度搜索ai助手怎么关闭 百度搜索ai对话屏蔽方法  YOU.com AI搜索引擎:Python代码示例及使用指南  AI视频创作终极指南:文本到视频的免费工具与技巧  AI聊天机器人引发伦理思考:泰国老人在Facebook上遭遇情感欺骗悲剧  百度APP的ai助手怎么关闭 百度APP ai功能取消方法  Canva AI工具教程:动漫化图像、生成艺术与定制QR码  文心一言如何做本地生活探店文案 文心一言内容种草指南  批改网AI检测工具怎样开启实时检测_批改网AI检测工具实时检测开启与延迟设置【指南】  AI视频生成器:免费工具,图像转视频和文字转视频  Claude怎么用新功能代码调试_Claude代码调试使用【方法】  如何通过 DeepSeek 优化分布式存储系统架构  探索弦乐器世界:从吉他到卡曼切,乐器全解析  Depseek怎么设置总结汇报重点_Depseek重点突出与关键词标注方法【步骤】  夸克AI怎么用AI写作_夸克AI写作功能与模板选择【指南】  Claude 4.5 深度解析: Coding, VS Code & AI Agent 新纪元  如何让ChatGPT模仿特定文风 创意写作与品牌话术生成教程  GitHub Copilot终极指南:提升代码效率与质量  tofai官方网站入口 tofai在线网页版登录  智行ai抢票怎么设置抢票截止时间_智行ai抢票截止时间设置与确认【步骤】  5分钟教你用AI将你的研究数据生成可视化的图表和摘要  Claude怎么用新功能代码辅助_Claude代码辅助使用攻略【方法】  如何使用 Gemini 进行 Google Cloud 架构成本预估  DiagramMagic:AI驱动的在线图表生成器终极指南  AI学习秘籍:3个高效黑科技,解锁智能学习新时代  AMD Ryzen 2025 CPU深度解析:新品发布与选购指南  解锁 Gemini Gems 高级用法:打造专属 AI 专家助手  2025 YouTube自动化终极指南:利用AI实现高效内容创作和多平台发布  歌曲分析:The Killers乐队的《Mr. Brightside》歌词深度解析  ChatGPT 4o图像生成器:免费AI绘画技巧与应用  AI婴儿播客视频制作终极指南:免费工具与步骤  使用Agent AI Book Cover Creator轻松设计吸睛图书封面  OpenAI Sora 2:AI视频生成新纪元  智行ai抢票如何绑定微信通知_智行ai抢票微信提醒绑定与推送设置【指南】  Avokaado AI:简化合同管理和法律流程的终极指南  百度APP搜索框ai怎么关 百度APP搜索框ai图标去除  豆包AI怎么评价回答的好坏_点赞与反馈功能使用教程  扣子AI怎样设置多轮对话逻辑_扣子AI逻辑树搭建与分支设计【教程】  DeepSeek是免费使用的吗 DeepSeek收费模式与Pro版本功能详解 

 2025-07-28

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

南京市珐之弘网络技术有限公司


南京市珐之弘网络技术有限公司

南京市珐之弘网络技术有限公司专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 87067657

 13565296790

 87067657@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.