百度飞桨图像分割7日打卡营class1笔记

本文介绍了如何使用PaddlePaddle的动态图模式构建一个基础模型,包括最大池化层、1x1卷积层和上采样操作,并详细解释了代码实现过程。同时,展示了如何定义一个自定义的数据加载器`BasicDataLoader`,用于读取和预处理图像数据。此外,还演示了如何将自定义数据加载器与PaddlePaddle的`DataLoader`配合使用,进行批量数据处理。
摘要由CSDN通过智能技术生成

由于自己基础很薄弱,跟着老师敲代码的时候把讲解备注了一下。
basic_model

import paddle
import paddle.fluid as fluid
from paddle.fluid.dygraph import to_variable#TODO
from paddle.fluid.dygraph import Pool2D#TODO
from paddle.fluid.dygraph import Conv2D#TODO
import numpy as np
np.set_printoptions(precision=2)

#继承paddle.fluid.dygraph动态图的内容,basicmodel是一个网络要做forward
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):#类别数59
        super(BasicModel, self).__init__() #使用super()将继承的父类初始化
        self.pool = Pool2D(pool_size=2,pool_stride=2)#TODO这个液化将图片面积缩小了4倍既8*8变4*4
        self.conv = Conv2D(num_channels=3,num_filters=num_classes,filter_size=1)#TODD #num_channels为input(图片)的channels
        # num_filters为output数(类数)对应卷积核数量,filter_size既卷积尺寸大小,这里是一个1*1的卷积,输入为3个维度,输出为59个维度。
    def forward(self, inputs):#这是一个成员方法,要加self,它的输入是tensor或图像
        x = self.pool(inputs)#TODO
        x = fluid.layers.interpolate(x, out_shape=(inputs.shape[2], inputs.shape[3]))#液化将feature map(输入)变小,在此将它
        # 放大回去,这个操作叫上采样,通过插值将x的尺寸变为输入,input的尺寸。
        x = self.conv(x)#TODO
        return x

def main():
    place = paddle.fluid.CUDAPlace(0)#程序跑的位置,CPU,或gpu,括号内的0表示单卡。
#   place = paddle.fluid.CPUPlace()
    with fluid.dygraph.guard(place):#这个place用到 paddle的动态图,这是一个固定用法。
        model = BasicModel(num_classes=59)#开始做定义,model等于上面定义的basic model.
        model.eval()#加model.eval表示预测模式,加model.train表示训练模式,
        input_data = np.random.rand(1,3,8,8).astype(np.float32) # TODO #一般图像数据格式都是四维(n,c,h,w)(数量,通道channel,高度,宽度),
        # 输入数据类型记得转换为np.float32浮点数
        print('Input data shape: ', input_data.shape)#打印输入数据的shape,格式,
        input_data = to_variable(input_data)# TODO#将输入数据的类型由np.array转换为paddle的tensor,同时将它放在模型可以找到的地方
        #使模型可以调用
        output_data = model(input_data)# TODO前向,这里output_data数据类型是tensor
        output_data = output_data.numpy()# TODO将output_data转化为np。array格式,方便打印。
        print('Output data shape: ', output_data.shape)

if __name__ == "__main__":
    main()

basic_dataloader

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, input,label):
        input = cv2.resize(input, (self.size, self.size), interpolation=cv2.INTER_LINEAR)#加interpolation在分割领域很重要,因为做图像时通常会用
        # resize,既通过双线性差值,三线性差值来更改尺寸。
        label = cv2.resize(label, (self.size, self.size), interpolation=cv2.INTER_NEAREST)#INTER_NEAREST使用最近的pixel作为插出来的值,
                                                          # 新生成的label的pixel不会有越界,比如原来是0-60,共59类,用INTER_NEAREST能保证还在这个范围。

        return input,label

class BasicDataLoader(object):#object:不继承任何东西。#BasicDataLoader要实现这四个方法。要知道要做几件事
    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,但是找不到参数列表里的东西
        self.transform=transform
        self.shuffle=shuffle

        self.data_list = self.read_list()     #data_list存的是读到的所有list文件里的路径。

    def read_list(self):         #读数据
        data_list = []
        with open(self.image_list_file) as infile:   #list中为JPEGImages/2008_000002.jpg GroundTruth_trainval_png/2008_000002.png,
                                                     #既一对对图片及其label文件名,需要对其添加路径来读取图片和label

            for line in infile:
                data_path = os.path.join(self.image_folder,line.split()[0]) #1、list中是相对路径,因此需要改路径,os.path.join将image_folder路径和第一个文件夹名拼接,该路径既datapath
                lable_path = os.path.join(self.image_folder, line.split()[1])
                data_list.append((data_path,lable_path))                    #这里data_list是一个列表,里边是一对对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):#__len__是一个python类的一个基本方法,这里对其覆写。
        return len(self.data_list)#这个方法就是返回data_list,可以被__call__方法call
    def __call__(self):
        for data_path,label_path in self.data_list:#将data_path,label_path从data_list中一对对读出来,一张图对应一张label
            data = cv2.imread(data_path,cv2.IMREAD_COLOR)#将路径放进来,用OpenCV去读,将图读出来,cv2.IMREAD_COLOR为读取格式
            data = cv2.cvtColor(data,cv2.COLOR_BGR2RGB)  #opencv读进来时bgr,这里转换为rgb
            label = cv2.imread(label_path,cv2.IMREAD_GRAYSCALE)#这是label图,直接读成灰度图(单通道)
            print(data.shape,label.shape)       #这里data、label是np.array类型
            data,label = self.preprocess(data,label)#初始化,预处理
            yield data,label     #相当于return
#Class A   定义一个类
#a = A()   初始化的方法,创建一个对象
#a()       这样call A的时候会调用__call__方法.




def main():
    batch_size = 5
    place = fluid.CUDAPlace(0)
    with fluid.dygraph.guard(place):#打开一个动态图,做一些事。
        transform = Transform(256)
        # TODO: create BasicDataloder instance
        # image_folder="./dummy_data"
        # image_list_file="./dummy_data/list.txt"
        #这basic_dataloader是自己实现的,怎么处理数据,怎么读数据。BasicDataLoader这个类相当于python的generator,生成器。
        basic_dataloader = BasicDataLoader(
                image_folder='C:\\Users\chen\\Desktop\\work\\home\\aistudio\\work\\dummy_data',#数据所在文件夹,
                image_list_file='C:\\Users\chen\\Desktop\\work\\home\\aistudio\\work\\dummy_data\\list.txt',#数据的list位置
                transform=transform,
                shuffle=True
                )
        # TODO: craete fluid.io.DataLoader instance
        dataloader = fluid.io.DataLoader.from_generator(capacity=1,use_multiprocess=False)#这是padele自己定义有一个class叫
        # BasicDataLoader,能够让我们在paddle中去做训练,不断调取数据。要创建一个这样的instance可以调用from_generator。

        # TODO: set sample generator for fluid dataloader
        dataloader.set_sample_generator(basic_dataloader,
                                        batch_size=batch_size,
                                        places=place)  # 通过第一个方式创建的fluid dataloader的instance为了给他初始化,让他按照我们的
        # 方式去读取数据。所以需要使用set_sanple_generator方法,其中第一个输入参数是我们自己写的basic_dataloader,第二个是batch_size,第三个是place。

#在这里测试,打开n个epoch,对每个epoch去做循环。这里是模拟了一个训练过程。训练轮数,每一轮将数据集扫一遍。后边再加上train,loss...
        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()

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值