精华内容
下载资源
问答
  • 分钟本文讨论一下PaddlePaddle框架中几个重要的概念,在使用Paddle进行开发时,弄清楚这几个概念是使用Paddle进行开发的一个前提。Tensor张量与当前主流框架相同,Paddle同样使用Tensor张量来表示数据,你可以将不同...


    正文共:6452 字 0 图

    预计阅读时间: 17 分钟

    本文讨论一下PaddlePaddle框架中几个重要的概念,在使用Paddle进行开发时,弄清楚这几个概念是使用Paddle进行开发的一个前提。

    Tensor张量

    与当前主流框架相同,Paddle同样使用Tensor张量来表示数据,你可以将不同维度的Tensor理解成对应维度的矩阵,当然,两者是有差异的。

    在Fluid中所有的数据类型都为LoD-Tensor,对于不存在序列信息的数据(如此处的变量X),其lod_level=0。

    在Paddle Fluid版本中,有3个比较重要的Tensor

    可学习参数

    神经网络中的可学习参数(模型权重、偏置等)其生命周期与整个训练周期一样长,在训练过程中,可学习参数会被修改,最常见的就是模型权重这一可学习参数会被梯度下降算法修改,在Fluid中可以使用 fluid.layers.create_parameter来创建可学习参数

      
    1. w = fluid.layers.create_parameter(name='w', shape=[1], dtype='float32')

    在日常编写模型中,该方法并不常用,因为Paddle已经为大部分常见的神经网络基本计算模型进行了封装,如创建全链接层,并不需要自己手动创建链接权重w与偏置b

      
    1. y = fluid.layers.fc(input=x, size=128, bias_attr=True)

    其实进入 fluid.layers.create_parameter()方法的源码和 fluid.layers.fc()方法的源码,可以发现两者最终都是调用 helper.create_parameter()方法来创建可学习参数的,其中helper是LayerHelper的实例。

    输入数据Tensor

    Fluid使用 fluid.layers.data()方法来接受输入数据,与TensorFlow中的placeholder占位符作用是相同的,同样,fluid.layers.data()方法需要定义好输入Tensor的形状,如果遇到无法确定形状的维度,则设置为None

    x = fluid.layers.data(name='x', shape=[3, None], dtype='int64')
    # Batch size 无需显示指定, Paddle会自动填充
    a = fluid.layers.data(name='a', shape=[3,6], dtype='int64')
    # 输入数据为宽、高不是固定的图像, 主要图像数据类型通常为float32
    img = fluid.layers.data(name='img', shape=[3, None, None], dtype='float32')
    

    上述代码中,一个tick就是Batch size,无需自己显示的定义。(通常训练模型时,都以一Batch size大小的数据为一次训练数据的量)

    可以从源码看出(如下),data()方法中使用appendbatchsize变量判断是否要为shape自动加上batch size,但正是的创建输入,使用的是

    helper.create_global_variable()

    方法。而helper依旧是LayerHelper的实例。

    def data(name,shape,append_batch_size=True,dtype='float32',
    		lod_level=0,type=core.VarDesc.VarType.LOD_TENSOR,
    		stop_gradient=True):
    		
    	helper = LayerHelper('data', **locals())
    	shape = list(shape)
    	for i in six.moves.range(len(shape)):
    		if shape[i] is None:
    			shape[i] = -1
    			append_batch_size = False
    		elif shape[i] < 0:
    			append_batch_size = False
    	if append_batch_size:
    		shape = [-1] + shape # append batch size as -1
    		data_var = helper.create_global_variable(
    		name=name,
    		shape=shape,
    		dtype=dtype,
    		type=type,
    		stop_gradient=stop_gradient,
    		lod_level=lod_level,
    		is_data=True)
    return data_var
    

    LayerHelper以出现多次,可以看出LayerHelper在Paddle中起着关键作用,从Paddle的设计文档中可以了解到LayerHelper,它的作用主要是在各个layers函数之间共享代码,设计LayerHelper主要考虑到如果开发全局辅助函数有几个缺点:

    • 1.需要提供这些方法的命名空间,方便开发人员快速定位并使用

    • 2.全局函数迫使图层开发人员需要逐个传递参数

    • 为了避免以上缺点,才定义出了LayerHelper,但它通常在layers开发中使用,对应创建模型结构的搭建不会使用到LayerHelper,关于LayerHelper的更多细节可以参考Design Doc:Python API,当然后面的文章我也打算讲讲Paddle设计层面以及底层点的东西,到时也会有所提及。

      常量Tensor

      Fluid通过 fluid.layers.fill_constant()实现常量Tensor,常量即常量,在模型训练过程中,其值不会改变。

       
      1. data = fluid.layers.fill_constant(shape=[1], value=0, dtype=‘int64’)

      该方法的内部依旧是使用LayerHelper类来实现常量Tensor

       
      1. helper = LayerHelper(“fill_constant”, **locals())

      Paddle数据传入

      Fluid版本的Paddle支持两种传入数据的方式,分别是

    • Python Reader同步读入数据:使用 fluid.layers.data()定义输入层,并在 fluid.Executor或 fluid.ParallelExecutor中使用 executor.run(feed=…)来传入数据,与TensorFlow类似,定义好Placeholder占位符,再在具体训练时,将具体的数据喂养给模型

    • py_reader异步读入数据:异步读入数据,先需要使用 fluid.layers.py_reader()配置异步数据输入层,再使用 py_reader()的 decorate_paddle_reader或 decorate_tensor_provider方法配置数据,配置完数据后,最总通过 fluid.layers.read_file读取数据。

    • 对于常用模型,比较常见的事同步读入数据的方式。Paddle的数据读入会在后一章进行讲解。

      Operator表示对数据的操作

      Fluid版本的Paddle中,所有的数据操作都由Operator表示,在python端,Operator操作被进一步封装在 paddle.fluid.layerspaddle.fluid.nets等模块中,简单而言,所谓构建神经网络其实就是使用框架提供的各种Operator来操作数据,不必想的过于复杂。一个简单的加法运算如下:

      import paddle.fluid as fluid
      
      #输入层
      a = fluid.layers.data(name='a', shape=[2], dtype='float32')
      b = fluid.layers.data(name='b', shape=[2], dtype='float32')
      
      result = fluid.layers.elementwise_add(a,b)
      
      cpu = fluid.CPUPlace() # 定义运算场所
      exe = fluid.Executor(cpu) # 创建执行器
      exe.run(fluid.default_startup_program()) # 网络参数初始化
      # 准备数据
      import numpy
      x = numpy.array([1,2])
      y = numpy.array([2,3])
      
      #执行计算
      outs = exe.run(
      				feed={'a':x,'b':y},
      				fetch_list=[a,b,result.name])
      #查看输出结果
      print(outs)
      

      一开始使用 fluid.layers.data()定义数据输入层,具体的数据通过 numpy.array()生成,因为 fluid.layers.data()定义了shape=[2],那么此时numpy.array()需要定义成[1,2],即第一维的形状为2,如果shape=[1,2],那么第一维的形状为1,第二维的形状为2,即numpy.array()需要定义成[[1,2]]。

      动态图机制

      Fluid使用的是动态图机制,因为静态图机制让使用者在编写过程中丧失了对网络结构修改的灵活性,所以很多优秀的框架都引入了动态图这种设计(TensorFlow 2.0动态图机制也大幅加强了)。

      动态图 vs 静态图

      动态计算意味着程序将按照我们编写命令的顺序进行执行。这种机制将使得调试更加容易,并且也使得我们将大脑中的想法转化为实际代码变得更加容易。而静态计算则意味着程序在编译执行时将先生成神经网络的结构,然后再执行相应操作。从理论上讲,静态计算这样的机制允许编译器进行更大程度的优化,但是这也意味着你所期望的程序与编译器实际执行之间存在着更多的代沟。这也意味着,代码中的错误将更加难以发现(比如,如果计算图的结构出现问题,你可能只有在代码执行到相应操作的时候才能发现它)。尽管理论上而言,静态计算图比动态计算图具有更好的性能,但是在实践中我们经常发现并不是这样的。

      来源:动态图 vs 静态图

      Program描述模型

      Fluid版本的Paddle中使用Program的形式描述计算过程,开发者所有写入在Program中的Operator操作都会自动转为ProgramDesc描述语言。

      Fluid通过提供顺序、分支和循环三种执行结构的支持

      其中顺序执行,写法与静态图的形式没什么差别,如下:

      # 顺序执行的方式搭建网络
      x = fluid.layers.data(name='x', shape=[13], dtype='float32')
      
      y_predict = fluid.layers.fc(input=x, size=1, act=None)
      
      y = fluid.layers.data(name='y', shape=[1], dtype='float32')
      
      cost = fluid.layers.square_error_cost(input=y_predict, label=y)
      

      分支条件switch的使用如下:

      # 条件分支——switch、if else
      lr = fluid.layers.tensor.create_global_var(
      	shape=[1],
      	value=0.0,
      	dtype='float32',
      	persistable=True,
      	name='learning_rate'
      )
      
      one_var = fluid.layers.fill_constant(
      	shape=[1], dtype='float32', value=1.0
      )
      
      two_var = fluid.layers.fill_constant(
      	shape=[1], dtype='float32', value=2.0
      )
      
      
      
      # switch
      with fluid.layers.control_flow.Switch() as switch:
      with switch.case(global_step == one_var):
      fluid.layers.tensor.assign(input=one_var, output=lr)
      with switch.default():
      fluid.layers.tensor.assign(input=two_var, output=lr)
      

      其中流程控制方面的内容都放在了 fluid.layers.control_flow模块下,里面包含了While、Block、Conditional、Switch、if、ifelse等跟中操作,这样可以让在编写模型时,想编写普通的python程序一样。

      Executor执行Program

      Program相当于你模型的整体结构,Fluid中程序执行分为编译与执行两个阶段,当你定义编写完Program后,还需要定义Executor,Executor会接收Program,然后将其转为FluidProgram,这一步称为编译,然后再使用C++编写的后端去执行它,执行的过程也由Executor完成,相关代码片段如下:

      cpu = fluid.core.CPUPlace()
      
      exe = fluid.Executor(cpu) #执行器
      exe.run(fluid.default_startup_program()) #初始化Program
      
      outs = exe.run(
      	feed={'a':x, 'b':y},
      	fetch_list=[result.name]
      )
      

      在Fluid中使用Executor.run来运行一段Program。

      正式进行网络训练前,需先执行参数初始化。其中 defalut_startup_program中定义了创建模型参数,输入输出,以及模型中可学习参数的初始化等各种操作。

      由于传入数据与传出数据存在多列,因此 fluid 通过 feed 映射定义数据的传输数据,通过 fetch_list 取出期望结果

      整体实践

      写过简单结构,预测一组数据,使用单个全连接层来实现预测,核心的逻辑就是喂养为模型一些训练数据,模型输出预测结果,该预测结果与真实结果直接会有个误差,作为损失,通过平方差损失来定义这两个损失,然后再最小化该损失,整体逻辑如下:

      import paddle.fluid as fluid
      
      import numpy as np
      
      
      
      '''
      
      真实数据
      
      '''
      #训练数据
      train_data = np.array([[1.0],[2.0],[3.0],[4.0]]).astype('float32')
      
      #真实标签
      y_true = np.array([[2.0], [4.0], [6.0], [8.0]]).astype('float32')
      
      # 输入层,接受真实数据
      x = fluid.layers.data(name='x', shape=[1], dtype='float32')
      y = fluid.layers.data(name='y', shape=[1], dtype='float32')
      # 模型结构,这里就一个简单的全连接层
      y_predict = fluid.layers.fc(input=x, size=1, act=None)
      # 定义损失,真实标签值与模型预测值之间的损失
      cost = fluid.layers.square_error_cost(input=y_predict, label=y)
      #取平均,因为通常有batch个数据,取平均值作为损失则可
      avg_cost = fluid.layers.mean(cost)
      
      # 定义执行设备,CUP或GPU
      cpu = fluid.CPUPlace()
      # Executor执行,该方法只能实现单设备执行
      exe = fluid.Executor(cpu)
      
      # 初始化整个结构中的节点
      exe.run(fluid.default_startup_program())
      
      for i in range(100):
      	outs = exe.run(
      		feed = {'x': train_data, 'y': y_true}, #将真实数据喂养给模型,注意传入数据与输入层的关系
      		fetch_list=[y_predict.name, avg_cost.name] #获取列表,即执行完后,outs会获得的数据
      	)
      
      print(outs)
      
    展开全文
  • 准备在欧卡2实现无人驾驶,第一步使用paddlepaddle框架的paddleseg模块对车道线语义分割语义分割数据集 本文采用的数据集是tusimple数据集,图森车道线检测数据集。 下载地址:传送门 对数据集做了一些简单的处理...

    前言

    准备在欧卡2实现无人驾驶,第一步使用paddlepaddle框架的paddleseg模块对车道线语义分割。

    语义分割数据集

    本文采用的数据集是tusimple数据集,图森车道线检测数据集。
    下载地址:传送门
    对数据集做了一些简单的处理,记录原始图像和带标签图像的文件路径关系。
    数据集样例:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    paddleseg

    这是百度深度学习框架推出的语义分割模块,集成了很多大佬写好的模型,只需要直接配置就可以使用这些模块了,对于新手上手比较友好。
    paddleseg项目地址:国产深度学习框架,点个star支持一下,github的star在框架的推广上有很直观的反应,所以支持国产从我做起!!!
    我这里选择的模型是deeplabv3p + mobilenetv2,选择mobilenet的主要原因是最后生成的__params__文件较小大概7M左右,适合在移动端上部署。
    mobilenet的模型文件:
    在这里插入图片描述

    配置文件

    EVAL_CROP_SIZE: (512, 256) # (width, height), for unpadding rangescaling and stepscaling
    TRAIN_CROP_SIZE: (512, 256) # (width, height), for unpadding rangescaling and stepscaling
    AUG:
        AUG_METHOD: "stepscaling" # choice unpadding rangescaling and stepscaling
        FIX_RESIZE_SIZE: (512, 256) # (width, height), for unpadding
        INF_RESIZE_VALUE: 500  # for rangescaling
        MAX_RESIZE_VALUE: 600  # for rangescaling
        MIN_RESIZE_VALUE: 400  # for rangescaling
        MAX_SCALE_FACTOR: 2.0  # for stepscaling
        MIN_SCALE_FACTOR: 0.5  # for stepscaling
        SCALE_STEP_SIZE: 0.25  # for stepscaling
        MIRROR: False
            
    BATCH_SIZE: 16
    DATASET:
        DATA_DIR: "./dataset/tusimple_lane_detection/"
        IMAGE_TYPE: "rgb"  # choice rgb or rgba
        NUM_CLASSES: 19
        TEST_FILE_LIST: "dataset/tusimple_lane_detection/training/list.txt"
        TRAIN_FILE_LIST: "dataset/tusimple_lane_detection/training/train1.txt"
        VAL_FILE_LIST: "dataset/tusimple_lane_detection/training/val_part1.txt"
        IGNORE_INDEX: 255
        SEPARATOR: " "
    FREEZE:
        MODEL_FILENAME: "__model__"
        PARAMS_FILENAME: "__params__"
    MODEL:
        DEFAULT_NORM_TYPE: "bn"
        MODEL_NAME: "deeplabv3p"
        DEEPLAB:
            BACKBONE: "mobilenetv2"
            ASPP_WITH_SEP_CONV: True
            DECODER_USE_SEP_CONV: True
            ENCODER_WITH_ASPP: False
            ENABLE_DECODER: False
    TRAIN:
        PRETRAINED_MODEL_DIR: u"pretrained_model/mobilenet_cityscapes"
        MODEL_SAVE_DIR: "saved_model/deeplabv3p_mobilenetv2_cityscapes"
        SNAPSHOT_EPOCH: 10
        SYNC_BATCH_NORM: True
    TEST:
        TEST_MODEL: "saved_model/deeplabv3p_mobilenetv2_cityscapes/final"
    SOLVER:
        LR: 0.005
        LR_POLICY: "poly"
        OPTIMIZER: "sgd"
        NUM_EPOCHS: 100
    
    

    == EVAL_CROP_SIZE: (512, 256)==
    注意这个参数,这个大小对推理过程影响很大,尺寸过大推理速度慢,尺寸过小识别的车道线会变形。数据增强应该加上模糊化,颜色光纤干扰等,但是我加上了之后训练实在太慢了,100轮要训练个两天两夜的样子…所以之后电脑有空再训练一个。

    训练效果

    在这里插入图片描述
    在这里插入图片描述
    因为数据集是图森科技采集的汽车行驶记录仪的图片,并不是端到端的数据集,所以有一些车道线的场景识别的效果确实不太好,这里尝试了使用labelme来标注自己的数据,但是实在是太麻烦了并且要很多数据。。。标注数据又十分的无聊且枯燥的,所以还是先将就着,首先把算法完善再考虑这些问题。
    关于识别速度:
    使用deeplabv3p + mobilenetv2模型,不打开欧卡2游戏,本地部署了paddle1.8.0加gpu,单纯推理图片有0.1s的延迟,evel_size是(512,256),如果尺寸再小点识别速度会相对提高一点,10HZ的频率在低速上也能勉强适用,还是那句话先完善整个框架的算法,后面再做优化。

    车道线分割

    有了上图识别的车道线,还需要计算出当前车行驶的车道以及左右车道线的位置,这样才能推理出应该给的方向盘速度,这里我想到了两种办法:

    • 第一种是将识别得到的车道线黑白图加上打角的角度标签,然后用深度学习的模型来识别图片给出推理的角度,这种方法应该是可行的,但是这个识别的图像有些场景会出现丢线的情况,不太好处理。
    • 第二种是适用opencv来处理车道线,计算黑白图片的直方图,根据直方图来推理左右车道线的位置,这种方法因为视屏帧是连续的,我们出现丢线可以通过上一帧来做一个推理计算下一帧的车道线位置。

    方法一的实现:
    未完待续…

    方法二的实现:
    这里我采用将图像做如下分割:
    在这里插入图片描述
    蓝色的线分割出来的是我想处理的区域,红色的线将预处理区域划分成6块,分别计算六块的直方图,然后推理得到左右车道线的位置,最后做二次多项式拟合计算出左右车道线的公式。
    分块直方图(不同颜色表示不同块的像素直方图):
    在这里插入图片描述
    根据此图可以看到,两个尖峰围起来的区域就是当前车道区域!

    展开全文
  • 语义分割分割算法的核心:像素级分类 语义分割算法基本流程 输入:图像(RGB) 算法:深度学习模型 输出:分类结果(与输入大小一致的单通道图) 训练过程: 输入: image + label 前向: out = model(image) 计算...

    基础概念

    语义分割分割算法的核心:像素级分类

    语义分割算法基本流程

    1. 输入:图像(RGB)
    2. 算法:深度学习模型
    3. 输出:分类结果(与输入大小一致的单通道图)
    4. 训练过程:
      1. 输入:        image + label
      2. 前向:        out = model(image)
      3. 计算损失: loss = loss_func(out,label)
      4. 反向:        loss.backward()
      5. 更新权重:optimizer.minimize(loss) 

    评价指标

    mAcc

    结果样式:

    实际计算流程:

    mIOU

    其中mean表现在多个类别的IOU最后求标签.

    两个评价指标都是越大越好.

    具体实现流程

    图(数据预处理相关)

    import random
    import cv2
    import numpy as np
    import paddle.fluid as fluid
    import os
    
    
    class Transform(object):
        def __init__(self, size=256):
            self.size=size
    
        def __call__(self, input, label):
            input = cv2.resize(input, (self.size, self.size), interpolation=cv2.INTER_LINEAR)
            label = cv2.resize(input, (self.size, self.size), interpolation=cv2.INTER_LINEAR)
    
            return input, label
    
    
    class BasicDataLoader(object):
        
        def __init__(self,
                     image_folder,
                     image_list_file,
                     transform=None,
                     shuffle=True):
            #需要输出的参数
            self.image_folder = image_folder
            self.image_list_file = image_list_file
            self.transform = transform
            self.shuffle = shuffle
            self.data_list = self.read_list()
        
        def read_list(self):
            #获取到文件列表
            data_list = []
            with open(self.image_list_file) as infile:
                for line in infile:
                    data_path = os.path.join(self.image_folder,line.split()[0])
                    label_path = os.path.join(self.image_folder, line.split()[1])
                    data_list.append((data_path, label_path))
            random.shuffle(data_list)
            return data_list
    
        def preprocess(self, data, label):
            #定义预处理流程
            h, w, c = data.shape
            h_gt, w_gt = label.shape
            assert h == h_gt, "Error"
            assert w == w_gt, "Error"
            if self.transform:
                data, label = self.transform(data, label)
            label = label[:, :, np.newaxis]
            return data, label
    
        def __len__(self):
            return len(self.data_list)
    
        def __call__(self):
            #调用时,用迭代器返回数据和对应标签
            for data_path, label_path in self.data_list:
                data = cv2.imread(data_path, cv2.IMREAD_COLOR)
                data = cv2.cvtColor(data, cv2.COLOR_BGR2RGB)
                label = cv2.imread(label_path, cv2.IMREAD_GRAYSCALE)
                data, label = self.preprocess(data, label)
    
                yield data, label
    
    
    def main():
        batch_size = 5
        place = fluid.CPUPlace()
        with fluid.dygraph.guard(place):
            transform = Transform(256)
            # create BasicDataloader instance
            basic_dataloader = BasicDataLoader(
                image_folder = './dummy_data',
                image_list_file = './dummy_data/list.txt',
                transform = transform,
                shuffle = True
                )
            # create fluid.io.Dataloader instance (配合paddel数据集加载器使用,先创建)
            dataloader = fluid.io.DataLoader.from_generator(capacity=1, use_multiprocess=False)
            
            # set sample generator for fluid dataloader (再配置关联上,我们定义的数据集加载器)
            dataloader.set_sample_generator(basic_dataloader,
                                            batch_size=batch_size,
                                            places=place)        
    
            num_epoch = 2
            for epoch in range(1, num_epoch+1):
                print(f'Epoch [{epoch}/{num_epoch}]:')
                for idx, (data, label) in enumerate(dataloader):
                    print(f'iter {idx}, Data shape: {data.shape}, Label shape:{label.shape}')
    
    if __name__ == '__main__':
        main()

    其中数据变换时,我们会额外定义出一个新的类来,执行翻转,裁剪,补边等常见的数据预处理操作.

    import cv2
    import numpy as np
    import random
    
    class Compose(object):
        def __init__(self, transforms):
            self.transforms = transforms
        def __call__(self, image, label=None):
            for t in self.transforms:
                image, label = t(image, label)
            return image, label
    
    
    class Normalize(object):
        def __init__(self, mean_val, std_val, val_scale=1):
            # set val_scale = 1 if mean and std are in range (0,1)
            # set val_scale to other value, if mean and std are in range (0,255)
            self.mean = np.array(mean_val, dtype=np.float32)
            self.std = np.array(std_val, dtype=np.float32)
            self.val_scale = 1/255.0 if val_scale==1 else 1
        def __call__(self, image, label=None):
            image = image.astype(np.float32)
            image = image * self.val_scale
            image = image - self.mean
            image = image * (1 / self.std)
            return image, label
    
    
    class ConvertDataType(object):
        def __call__(self, image, label=None):
            if label is not None:
                label = label.astype(np.int64)
            return image.astype(np.float32), label
    
    
    # 增加边框,size指定为一个int类型,确定增加后图像的尺寸,方形;
    # 若指定为一个tuple或list则宽高分别为list的值
    class Pad(object):
        def __init__(self, size, ignore_label=255, mean_val=0, val_scale=1):
            # set val_scale to 1 if mean_val is in range (0, 1)
            # set val_scale to 255 if mean_val is in range (0, 255) 
            factor = 255 if val_scale == 1 else 1
            
            if isinstance(size, int):
                self.size_height, self.size_width = size, size
            else:
                self.size_height, self.size_width = size[0], size[1]
            self.ignore_label = ignore_label
            self.mean_val=mean_val
            # from 0-1 to 0-255
            if isinstance(self.mean_val, (tuple,list)):
                self.mean_val = [int(x* factor) for x in self.mean_val]
            else:
                self.mean_val = int(self.mean_val * factor)
    
    
        def __call__(self, image, label=None):
            h, w, c = image.shape
            pad_h = max(self.size_height - h, 0)
            pad_w = max(self.size_width - w, 0)
    
            pad_h_half = int(pad_h / 2)
            pad_w_half = int(pad_w / 2)
    
            if pad_h > 0 or pad_w > 0:
    
                image = cv2.copyMakeBorder(image,
                                           top=pad_h_half,
                                           left=pad_w_half,
                                           bottom=pad_h - pad_h_half,
                                           right=pad_w - pad_w_half,
                                           borderType=cv2.BORDER_CONSTANT,
                                           value=self.mean_val)
                if label is not None:
                    label = cv2.copyMakeBorder(label,
                                               top=pad_h_half,
                                               left=pad_w_half,
                                               bottom=pad_h - pad_h_half,
                                               right=pad_w - pad_w_half,
                                               borderType=cv2.BORDER_CONSTANT,
                                               value=self.ignore_label)
            return image, label
    
    
    # 输入为一个int类型的整数,或者元组,列表
    class CenterCrop(object):
        def __init__(self, output_size):
            if isinstance(output_size, int):
                self.output_size = (output_size, output_size)
            else:
                self.output_size = output_size
    
        def _get_params(self, img):
            th, tw = self.output_size
            h, w, _ = img.shape
            assert th <= h and tw <= w, "output size is bigger than image size"
            x = int(round((w - tw) / 2.0))
            y = int(round((h - th) / 2.0))
            return x, y
    
        def __call__(self, img, label=None):
            x, y = self._get_params(img)
            th, tw = self.output_size
            if label is not None:
                return img[y:y + th, x:x + tw], label[y:y + th, x:x + tw]
            else:
                return img[y:y + th, x:x + tw], label
    
    
    # 缩放图像,输入尺寸可以是一个int类型,或一个tuple或list
    class Resize(object):
        def __init__(self, size, interpolation=1):
            if isinstance(size, int):
                self.size = (size, size)
            else:
                self.size = size
            self.interpolation = interpolation
    
        def __call__(self, img, label=None):
            if label is not None:
                return cv2.resize(img, self.size, self.interpolation), cv2.resize(label, self.size, self.interpolation)
            else:
                return cv2.resize(img, self.size, self.interpolation), label
    
    
    # 随机翻转,code=0 垂直翻转,code=1 水平翻转,code=-1 水平垂直翻转
    class RandomFlip(object):
        def __init__(self, code=0):
            self.prob = 0.5
            self.code = code
    
        def __call__(self, img, label=None):
            if np.random.random() < self.prob:
                if label is not None:
                    return cv2.flip(img, self.code), cv2.flip(label, self.code)
                else:
                    return cv2.flip(img, self.code), label
            return img, label
    
    
    # 随机裁剪,输入尺寸,在图片上随机区域裁剪出指定大小图片
    # 输入类型为int,tuple,list
    class RandomCrop(object):
        def __init__(self, img_size):
            if isinstance(img_size, int):
                self.img_width, self.img_height = img_size, img_size
            else:
                self.img_width, self.img_height = img_size[0], img_size[1]
    
        def __call__(self, img, label=None):
            return self.Random_crop(img, label)
    
        def Random_crop(self, img, label):
            height, width, _ = img.shape
            width_range = width - self.img_width
            height_range = height - self.img_height
            random_ws = np.random.randint(width_range)
            random_hs = np.random.randint(height_range)
            random_wd = self.img_width + random_ws 
            random_hd = self.img_height + random_hs
            img = img[random_hs:random_hd, random_ws:random_wd]
            if label is not None:
                label = label[random_hs:random_hd, random_ws:random_wd]
            return img, label
    
    
    # 缩放,输入为一个float类型
    class Scale(object):
        def __init__(self, ratio, interpolation=1):
            self.ratio = ratio
            self.interpolation = interpolation
    
        def __call__(self, img, label=None):
            width, height, _ = img.shape
    
            if label is not None:
                return cv2.resize(img, (int(height * self.ratio), int(width * self.ratio)), self.interpolation), \
                       cv2.resize(label, (int(height * self.ratio), int(width * self.ratio)), self.interpolation)
            else:
                return cv2.resize(img, (int(height * self.ratio), int(width * self.ratio)), self.interpolation), label
    
    
    # 随即缩放,输入为一个float类型,或tuple,list
    class RandomScale(object):
        def __init__(self, range_data, interpolation=1):
            if isinstance(range_data, (int, float)):
                self.ratio = range_data
            else:
                self.ratio = random.uniform(range_data[0], range_data[1])
            self.interpolation = interpolation
    
        def __call__(self, img, label=None):
            width, height, _ = img.shape
            if label is not None:
                return cv2.resize(img, (int(height * self.ratio), int(width * self.ratio)), self.interpolation), \
                       cv2.resize(label, (int(height * self.ratio), int(width * self.ratio)), self.interpolation)
            else:
                return cv2.resize(img, (int(height * self.ratio), int(width * self.ratio)), self.interpolation), label
    
    
    def main():
        image = cv2.imread('./work/dummy_data/JPEGImages/2008_000064.jpg')
        label = cv2.imread('./work/dummy_data/GroundTruth_trainval_png/2008_000064.png')
    
        # crop_size
        img_1 = RandomCrop((300, 200))(image)[0]
        cv2.imwrite('RandomCrop.png', img_1)
    
        # Transform: RandomScale, RandomFlip, Pad, RandomCrop
        img_2 = RandomScale((0.5, 3))(image)[0]
        img_2 = RandomFlip(0)(img_2)[0]
        img_2 = Pad(700)(img_2)[0]
        img_2 = RandomCrop((400, 300))(img_2)[0]
        cv2.imwrite('Transfoimgrm.png', img_2)
    
        for i in range(10):
            # call transform
            img = RandomScale((0.5, 3))(image)[0]
            img = RandomFlip(0)(img)[0]
            img = Pad((700, 700))(img)[0]
            img = RandomCrop((400, 300))(img)[0]
            #  save image
            cv2.imwrite('Transform_{}.png'.format(i+1), img)
            print('Transform_{}.png'.format(i+1) + ' has been saved to disk')
    
    if __name__ == "__main__":
        main()

    网(深度学习网络搭建)

    import paddle
    import paddle.fluid as fluid                    
    from paddle.fluid.dygraph import Conv2D,Pool2D  #TODO 导入需要的层    
    from paddle.fluid.dygraph import base  #TODO   
    import numpy as np
    np.set_printoptions(precision=2)  #打印精度
    
    
    class BasicModel(fluid.dygraph.Layer):
        # BasicModel contains:
        # 1. pool:   4x4 max pool op, with stride 4
        # 2. conv:   3x3 kernel size, takes RGB image as input and output num_classes channels,
        #            note that the feature map size should be the same
        # 3. upsample: upsample to input size
        #
        # TODOs:
        # 1. The model takes an random input tensor with shape (1, 3, 8, 8)
        # 2. The model outputs a tensor with same HxW size of the input, but C = num_classes
        # 3. Print out the model output in numpy format 
    
    #类比pytorch搭建流程 继承fluid.dygraph.Layer
    #先定义层,在forward的里面再将层串起来
    
    
        def __init__(self, num_classes=59):
            super(BasicModel, self).__init__()
    
            self.pool1 = Pool2D(pool_size = 4,pool_stride = 4)# TODO
            self.conv2 = Conv2D(3,num_classes,3,padding=1)# TODO
    
        def forward(self, inputs):
            x = self.pool1(inputs)# TODO
            x = self.conv2(x) # TODO
            x = fluid.layers.interpolate(x, out_shape=(inputs.shape[2], inputs.shape[3]))
            return x
    
    def main():
        place = paddle.fluid.CUDAPlace(0)
        with fluid.dygraph.guard(place):
            model = BasicModel(num_classes=59)
            model.eval()
            input_data = np.random.uniform(-1, 1, [1, 3,8, 8]).astype('float32')# TODO
            print('Input data shape: ', input_data.shape)
            input_data = base.to_variable(input_data)  # TODO
            output_data = model(input_data)            # TODO
            output_data = output_data.numpy()          # TODO
            print('Output data shape: ', output_data.shape)
    
    if __name__ == "__main__":
        main()

    训(网络训练测试)

    计算loss

    def Basic_SegLoss(preds, labels, ignore_index=255):
        n, c, h, w = preds.shape
    
        preds = fluid.layers.transpose(preds, [0, 2, 3, 1])
        
        mask = labels!=ignore_index
        mask = fluid.layers.cast(mask, 'float32')
    
        loss = fluid.layers.softmax_with_cross_entropy(preds, labels)
        loss = loss * mask
        avg_loss = fluid.layers.mean(loss) / (fluid.layers.mean(mask) + eps)
    
        return avg_loss

    定义单次训练流程

    def train(dataloader, model, criterion, optimizer, epoch, total_batch):
        model.train()
        train_loss_meter = AverageMeter()
        for batch_id, data in enumerate(dataloader):
            image = data[0]
            label = data[1]
    
            image = fluid.layers.transpose(image, (0, 3, 1, 2))
            pred = model(image)
            loss = criterion(pred, label)
    
            loss.backward()
            optimizer.minimize(loss)
            model.clear_gradients()
    
            n = image.shape[0]
            train_loss_meter.update(loss.numpy()[0], n)
            print(f"Epoch[{epoch:03d}/{args.num_epochs:03d}], " +
                  f"Step[{batch_id:04d}/{total_batch:04d}], " +
                  f"Average Loss: {train_loss_meter.avg:4f}")
    
        return train_loss_meter.avg

    串成完整的训练脚本

    import os
    import paddle
    import paddle.fluid as fluid
    from paddle.fluid.optimizer import AdamOptimizer
    import numpy as np
    import argparse
    from utils import AverageMeter
    from basic_model import BasicModel
    from basic_dataloader import BasicDataLoader
    from basic_seg_loss import Basic_SegLoss
    from basic_data_preprocessing import TrainAugmentation
    
    
    parser = argparse.ArgumentParser()
    parser.add_argument('--net', type=str, default='basic')
    parser.add_argument('--lr', type=float, default=0.001)
    parser.add_argument('--num_epochs', type=int, default=10)
    parser.add_argument('--batch_size', type=int, default=4)
    parser.add_argument('--image_folder', type=str, default='./work/dummy_data')
    parser.add_argument('--image_list_file', type=str, default='./work/dummy_data/list.txt')
    parser.add_argument('--checkpoint_folder', type=str, default='./output')
    parser.add_argument('--save_freq', type=int, default=2)
    
    
    args = parser.parse_args()
    
    
    def main():
        # Step 0: preparation
        place = paddle.fluid.CUDAPlace(0)
        with fluid.dygraph.guard(place):
            # Step 1: Define training dataloader
            basic_augmentation = TrainAugmentation(image_size=256)
            basic_dataloader = BasicDataLoader(image_folder=args.image_folder,
                                               image_list_file=args.image_list_file,
                                               transform=basic_augmentation,
                                               shuffle=True)
            train_dataloader = fluid.io.DataLoader.from_generator(capacity=10,
                                                              use_multiprocess=True)
            train_dataloader.set_sample_generator(basic_dataloader,
                                                  batch_size=args.batch_size,
                                                  places=place)
            total_batch = int(len(basic_dataloader) / args.batch_size)
            
            # Step 2: Create model
            if args.net == "basic":
                model = BasicModel()
            else:
                raise NotImplementedError(f"args.net: {args.net} is not Supported!")
    
            # Step 3: Define criterion and optimizer
            criterion = Basic_SegLoss
    
            # create optimizer
            optimizer = AdamOptimizer(learning_rate=args.lr,
                                      parameter_list=model.parameters())
            # Step 4: Training
            for epoch in range(1, args.num_epochs+1):
                train_loss = train(train_dataloader,
                                   model,
                                   criterion,
                                   optimizer,
                                   epoch,
                                   total_batch)
                print(f"----- Epoch[{epoch}/{args.num_epochs}] Train Loss: {train_loss:.4f}")
    
                if epoch % args.save_freq == 0 or epoch == args.num_epochs:
                    model_path = os.path.join(args.checkpoint_folder, f"{args.net}-Epoch-{epoch}-Loss-{train_loss}")
    
                    # save model and optmizer states
                    model_dict = model.state_dict()
                    fluid.save_dygraph(model_dict, model_path)
                    optimizer_dict = optimizer.state_dict()
                    fluid.save_dygraph(optimizer_dict, model_path)
                    print(f'----- Save model: {model_path}.pdparams')
                    print(f'----- Save optimizer: {model_path}.pdopt')
    
    
    if __name__ == "__main__":
        main()

     

    展开全文
  • paddle 关于图像分割七日打卡心得 坚持了七天,把百度的打卡内容大概完成了,说...基本可以分为5类:图像分割,语义分割,实例分割,视频分割,应用场景分割 具体得分割概念呢,你们可以去百度,这里就不一一列出来,

    paddle 关于图像分割七日打卡心得

    坚持了七天,把百度的打卡内容大概完成了,说实话,这次的内容并不简单,涉及到的知识对于一个大二的人来说具有挑战性!
    下面我就总结性的写一下培训的大纲

    图像分割的定义:

    图片直观理解
    简单理解就是在一张图片中把不同类别用不同的色块显示出来,并且能通过算法把物体的类别判断出来。这就是我们这七天要学习并且能够实现的东西。
    既然涉及到判别,那么我们就需要分割的概念

    基本可以分为5类:图像分割,语义分割,实例分割,视频分割,应用场景分割

    具体得分割概念呢,你们可以去百度,这里就不一一列出来,因为后面得内容才是本次课程得精华哟!

    FCN网络搭建

    全卷积FCN网络----intro
    这里看一下老师得ppt来帮助我们理解
    在这里插入图片描述
    全卷积vs图像分类
    https://www.cnblogs.com/gujianhan/p/6030639.html
    这个链接有助于大家理解全卷积FCN得概念
    采样过程
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    下面就开始我们的代码部分

    import os
    import random
    import numpy as np
    import cv2
    import paddle.fluid as fluid

    class Transform(object):
    def init(self,size=256):
    self.size = size
    def call(self,inputs,label):
    inputs = cv2.resize(inputs,(self.size,self.size),interpolation=cv2.INTER_LINEAR)
    label = cv2.resize(label,(self.size,self.size),interpolation=cv2.INTER_NEAREST)

        return inputs,label
    

    class BasicDataLoader(object):
    def init(self,
    image_folder,
    image_list_file,
    transform=None,
    shuffle=True):
    self.image_folder=image_folder
    self.image_list_file=image_list_file
    self.transform=transform
    self.shuffle=shuffle

        self.data_list = self.read_list()
    
    def read_list(self):
        data_list = []
        with open(self.image_list_file) as infile:
            for line in infile:
                data_path = os.path.join(self.image_folder,line.split()[0])
                label_path = os.path.join(self.image_folder,line.split()[1])
                data_list.append((data_path,label_path))
        random.shuffle(data_list)
        return data_list
    
    def preprocess(self, data, label):
        h,w,c = data.shape
        h_gt,w_gt = label.shape
        assert h==h_gt , "Error"
        assert w==w_gt , "Error"
    
        if self.transform:
            data,label = self.transform(data,label)
    
        label = label[:, :, np.newaxis]
    
        return data,label
    
    
    def __len__(self):
        return len(self.data_list)
    
    def __call__(self):
        for data_path,label_path in self.data_list:
            data = cv2.imread(data_path,cv2.IMREAD_COLOR,)
            data = cv2.cvtColor(data,cv2.COLOR_BGR2RGB)
            label = cv2.imread(label_path,cv2.IMREAD_GRAYSCALE)
            print(data.shape,label.shape)
            data,label = self.preprocess(data,label)
            yield data,label
    

    def main():
    batch_size = 5
    place = fluid.CPUPlace()
    with fluid.dygraph.guard(place):
    transform = Transform(256)
    # TODO: create BasicDataloder instance
    basic_dataloader = BasicDataLoader(
    image_folder=‘work/dummy_data’,
    image_list_file=‘work/dummy_datast.txt’,
    transform=transform,
    shuffle=True )
    # image_folder="./dummy_data"
    # image_list_file="./dummy_datast.txt"
    # TODO: create fluid.io.DataLoader instance
    dataloader = fluid.io.DataLoader.from_generator(capacity=1,use_multiprocess=False)
    # TODO: set sample generator for fluid dataloader
    dataloader.set_sample_generator(basic_dataloader,
    batch_size=batch_size,
    places=place )

        num_epoch = 2
        for epoch in range(1, num_epoch+1):
            print(f'Epoch [{epoch}/{num_epoch}]:')
            for idx, (data, label) in enumerate(dataloader):
                print(f'Iter {idx}, Data shape: {data.shape}, Label shape: {label.shape}')
    

    if name == “main”:
    main()

    ----------------------------------------------------------------分割线------------------------------------------------------------------------------
    import paddle
    import paddle.fluid as fluid
    from paddle.fluid.dygraph import to_variable # 导入to_variable函数
    from paddle.fluid.dygraph import Pool2D # 导入Pool2D函数
    from paddle.fluid.dygraph import Conv2D # 导入Conv2D函数
    import numpy as np
    np.set_printoptions(precision=2)

    class BasicModel(fluid.dygraph.Layer):
    # BasicModel contains:
    # 1. pool: 4x4 max pool op, with stride 4
    # 2. conv: 3x3 kernel size, takes RGB image as input and output num_classes channels,
    # note that the feature map size should be the same
    # 3. upsample: upsample to input size
    #
    # TODOs:
    # 1. The model takes an random input tensor with shape (1, 3, 8, 8)
    # 2. The model outputs a tensor with same HxW size of the input, but C = num_classes
    # 3. Print out the model output in numpy format

    def __init__(self, num_classes=59):
        super(BasicModel, self).__init__()
        self.pool = Pool2D(pool_size=4,pool_stride=4)  # 继承Pool2D函数
        self.conv = Conv2D(num_channels=3,num_filters=num_classes,filter_size=3,padding=1) # 继承Conv2D函数
    def forward(self, inputs):
        x = self.pool(inputs)# 下采样 
        x = fluid.layers.interpolate(x, out_shape=(inputs.shape[2], inputs.shape[3]))  # 线性插值至图像原大小
        x = self.conv(x)# 卷积
        return x
    

    def main():
    place = paddle.fluid.CUDAPlace(0)
    with fluid.dygraph.guard(place):
    model = BasicModel(num_classes=59) # 网络模型对象创建
    model.eval() # eval-预测模式;train-训练模式
    input_data = np.random.rand(1,3,8,8).astype(np.float32) # 生成一幅大小8*8,3通道的随机数图,格式为numpy array
    print('Input data shape: ', input_data.shape)
    input_data = to_variable(input_data) # 将生成图的numpy array格式改为tensor
    output_data = model.forward(input_data) # 使用fluid中的前向算法处理输入图像
    output_data = output_data.numpy() # 将处理后的图像格式修改为numpy array
    print('Output data shape: ', output_data.shape)

    if name == “main”:
    main()

    以上代码是为了实现:

    1.搭建并熟悉AI Studio环境 2. 熟悉PaddlePaddle环境和动态图模式 3. 实现数据加载模块

    你在运行的时候可能会有很多错误,因为路劲原因,或者是其他的原因

    语义分割-U-Net&PSPNet

    直接上图理解概念
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    话不多说,上代码

    import numpy as np
    import paddle.fluid as fluid
    from paddle.fluid.dygraph import to_variable
    from paddle.fluid.dygraph import Conv2D
    from paddle.fluid.dygraph import Conv2DTranspose
    from paddle.fluid.dygraph import Dropout
    from paddle.fluid.dygraph import BatchNorm
    from paddle.fluid.dygraph import Pool2D
    from paddle.fluid.dygraph import Linear
    from vgg import VGG16

    class FCN8s(fluid.dygraph.Layer):
    #TODO: create fcn8s model
    def init(self,num_classes=59):
    super(FCN8s,self).init()
    backbone = VGG16(pretrained=False)

        self.layer1 = backbone.layer1
        self.layer1[0].con._padding = [100,100]
        self.pool1=Pool2D(pool_size=2, poo_striade=2, ceil_mode=True)
        self.layer2 = backbone.layer2
        self.pool2=Pool2D(pool_size=2, poo_striade=2, ceil_mode=True)
        self.layer3 = backbone.layer3
        self.pool3=Pool2D(pool_size=2, poo_striade=2, ceil_mode=True)
        self.layer4 = backbone.layer4
        self.pool4=Pool2D(pool_size=2, poo_striade=2, ceil_mode=True)
        self.layer5 = backbone.layer5
        self.pool5=Pool2D(pool_size=2, poo_striade=2, ceil_mode=True)
    
        self.fc6 = Conv2D(512,4096,7,act='relu')
        self.fc7 = Conv2D(4096,4096,1,act='relu')
        self.drop6 = Dropout()
        self.drop7 = Dropout()
    
        self.score = Conv2D(4096, num_classes, 1)
        self.score_pool3 = Conv2D(256, num_classes, 1)
        self.score_pool4 = Conv2D(512, num_classes, 1)
    
        self.up_output = Conv2DTranspose(num_channels=num_classes,
                                        num_filters=num_classes,
                                        filter_size=4,
                                        stride=2,bias_attr=False)
    
        self.up_pool4 = Conv2DTranspose(num_channels=num_classes,
                                        num_filters=num_classes,
                                        filter_size=4,
                                        stride=2,bias_attr=False)
    
        self.up_final = Conv2DTranspose(num_channels=num_classes,
                                        num_filters=num_classes,
                                        filter_size=16,
                                        stride=8,bias_attr=False)
    
    
    
    def forward(self,inputs):
        x = self.layer1(inputs)
        x = self.pool1(x)
        x = self.layer2(x)
        x = self.pool2(x)
        x = self.layer3(x)
        x = self.pool3(x)
        pool3 = x
        x = self.layer4(x)
        x = self.pool4(x)
        pool4 = x
        x = self.layer5(x)
        x = self.pool5(x)
    
        x = self.fc6(x)
        x = self.drop6(x)
        x = self.fc7(x)
        x = self.drop(x)
    
        x = self.score(x)
        x = self.up_output(x)
    
        up_output = x
        x = self.score_pool4(pool4)
    
        x = x[:,:,5:5+up_output.shape[2],5:5+up_output.shape[3]]
    
        up_pool4=x
        x = up_pool4 + up_output
        x = self.up_poool4(x)
        up_pool4 = x
    
        x = self.score_pool3(pool3)
        x = x[:, :,9:9+up_pool4.shape[2],9:9+up_pool4.shape[3]]
        up_pool3 = x
    
        x = up_pool3 + up_pool4
    
        x=self.up_final(x)
    
        x = x[:,:,31:31 + inputs.shape[2],31:31+inputs.shape[3]]
    
        return x
    

    def main():
    with fluid.dygraph.guard():
    x_data = np.random.rand(2, 3, 512, 512).astype(np.float32)
    x = to_variable(x_data)
    model = FCN8s(num_classes=59)
    model.eval()
    pred = model(x)
    print(pred.shape)

    if name == ‘main’:
    main()

    这些代码是PaddlePaddle实现FCN网络

    这里面的代码,我有些看不懂,希望各位老师看到了,哪里不对多多指教。

    DeepLab 系列网路

    概念理解图
    在这里插入图片描述
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201026103103759.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ2MDEwMDMw,size_16,color_FFFFFF,t_70#pic_center
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    额,实在不好意思,第三次的代码小白是在是写不出来,见谅见谅,各位大佬们如果感兴趣,可以自己写写!毕竟高手在人间,哈哈哈

    展开全文
  • Paddle图像分割7日打卡心得 非常感谢百度Paddle这次的课程,让我对于图像分割有了初步的了解。刚开始报名的时候,以为是一个实践式的课程,开始上课才发现是一个理论为主加代码实践的课程(朱老师的直播代码水平确实...
  • 以下是本篇文章正文内容 一、图像分割综述 根据 不同的任务和数据类型: -图像分割(image segmentation)(像素级分类) 图像语义分割(image semantic segmentation) 图像实例分割(image instance segmentation...
  • Paddle图像分割7日打卡营学习总结1.FCN1.1 什么是FCN?1.2 FCN网络结构1.3 feature map上采样2. U-Net3. PSPNet4. DeepLab5.总结 1.FCN FCN论文地址:https://arxiv.org/abs/1411.4038 代码地址:...
  • 2.语义分割初探 3.环境搭建与飞桨动态图实战演示 4.语义分割的数据格式和处理 DAY2(10月20日) 1.FCN全卷积网络结构详解 2.飞桨中的上采样操作实践 3.飞桨实现FCN DAY3(10月21日) 1.U-Net模型与PSPNet模型...
  • 如何做语义分割? 语义分割像素级分类 和图像分类有什么关系? 替换FC为Conv 1x1 Conv 在通道维度("C")上进行改变,即在通道上降维或升维. Upsample 目的:将H和W收缩后的特征图恢复为与输入图像尺寸相同的大小...
  • ICNet实时语义分割
  • 4.3 PC端C++推理 4.3.1 动态图转静态图 4.3.2 基于Paddle Inference的C++推理 五、总结 六、参考文献 一、语义分割概述 图像语义分割是一种将图像分割成一系列具有特定语义类别属性区域的方法,目前已成为当前图像...
  • 本文链接:Android基于图像语义分割实现人物背景更换 本教程是通过PaddlePaddle的PaddleSeg实现的,该开源库的地址为:http://github.com/PaddlPaddle/PaddleSeg ,使用开源库提供的预训练模型实现人物的图像语义...
  • PaddlePaddle之语义分割

    2020-10-26 11:18:54
    本次课程学习了经典的语义分割算法,包括FCN ,U_Net,PSPNet, Deeplab系列等算法,并对学员进行了代码解析等干货分享。 学习内容: 首先使用百度飞浆的框架进行深度学习的计算是非常方便的,它是一个与 Tensorflow...
  • 语义分割模型试验记录 2020.10.27 pytorch-encoding 配置pytorch-encoding,编译什么的都正常了,运行测试代码也没有错误,结果没想到测试代码跑的时间有点久(要下载预训练模型,下完一个又有一个,我忘了笔记本没...
  • 语义分割重要指标计算python程序网上有好些,各有特色,但最近在用paddle框架感觉还顺手,其计算分割的指标程序还可以,但原始的有些繁琐,而且没有对分割好的结果图和标记图做评估,在经过一段时间研读源码后,我在...
  • 使用paddlex中的deeplabv3模型进行语义分割
  • 飞桨PaddleSeg--语义分割识别天空制作数据集数据预处理文件夹结构原图以及标注图处理修改像素值配置文件修改训练验证以及推理结束 制作数据集 这一步先略过,一般可以用labelme完成,这个在paddle的readme中有介绍 我...
  • 什么是图像语义分割? 图像语意分割顾名思义是将图像像素按照表达的语义含义的不同进行分组/分割,图像语义是指对图像内容的理解,例如,能够描绘出什么物体在哪里做了什么事情等,分割是指对图片中的每个像素点进行...
  • 在“10分钟快速上手使用PaddleX——DeepLabV3+语义分割”基础上修改的数据,结果出现如下错误,数据总共只有15张,会不会是数据太少?return np.array(f1score_list)UnboundLocalError: local variable 'f...
  • 一、图像语义分割模型DeepLab v3 随着计算机视觉的发展,语义分割成为了很多应用场景必不可少的一环。 比如网络直播有着实时剔除背景的要求,自动驾驶需要通过语义分割识别路面,与日俱增的应用场景对语义分割的...
  • 这里写自定义目录标题【PaddlePaddle】语义分割数据集的加载1.通过路径加载数据列表2.创建数据队列 【PaddlePaddle】语义分割数据集的加载 模型训练首先需要对数据集进行加载,加载数据的同时可以对数据进行数据增强...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 639
精华内容 255
关键字:

paddle语义分割