百度飞浆图像分割课程 作业1:basic_dataloader.py、basic_transforms.py、basic_model.py

在这里插入图片描述

1. Paddle数据读取包(basic_dataloader.py)

import os
import random
import numpy as np
import paddle.fluid as fluid
from paddle.reader.decorator import shuffle
import cv2

'''
实现paddle数据读取的包,针对分割来说
  目的: 把图都读到程序当中,让paddle模型能够每次都调用,也就是数据在框架当中都是tensor,并希望更高效
的运行,因此需要找一个dataloader

  paddle虽然提供API,但是我们还得实现自己的 basic_dataLoader(决定我们要怎么样读数据,怎么样处理数据),
因为paddle不知道我们自己的数据要怎么处理,以什么格式输入,paddle只负责当我们输入数据后将数据转换成我们
需要的格式。
'''
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)
        # 用NEAREST,label不会越界
        label = cv2.resize(label, (self.size, self.size), interpolation=cv2.INTER_NEAREST)

        return input, label

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

        self.image_floder = 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:
                # os.path.join 自动填/ 或者是 \
                data_path = os.path.join(self.image_floder,line.split()[0])
                label_path = os.path.join(self.image_floder,line.split()[1])
                # 思考:为什么加tuple而不用list?
                # Python中内置了list集合与tuple集合,在list集合中可以实现元素的添加、修改、插入、以及删除。tuple集合看似与list类似,但两者还是有很大的区别。
                # 在tuple集合中,一旦元素被存储,以后就不能修改,删除了,这比list集合安全许多,所以能用tuple就用tuple
                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)
        # 加了新轴,变成256*256*1
        label = label[:, :, np.newaxis]

        return data, label

    def __len__(self):
        return len(self.data_list)

    def __call__(self):
        # Class A
        # a = A()
        # a()就会调用__call__()方法
        for data_path, label_path in self.data_list:
            # type:numpy.array
            # data:H * W * 3  、 label:H * W
            # 读图、读label
            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 相当于 return
            yield data, label

def main():
    batch_size = 5
    place = fluid.CPUPlace()
    with fluid.dygraph.guard(place):
        transform = Transform(256)
        # create BasicDataloader instance, class:python的generator
        basic_dataloader = BasicDataLoader(
            image_folder = r'./work/dummy_data',
            image_list_file= r'./work/dummy_data/list.txt',
            transform = transform,
            shuffle=True # 打乱数据
        )
        # creat fluid.io.DataLoader instance
        # 在paddle中训练,不断的调取数据
        # 创建instance调用from_generator,basic_dataloader就是generator形式
        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()

在这里插入图片描述
2. basic_transforms.py

import cv2
import numpy as np


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


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

        self.size = size
        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 - h, 0)
        pad_w = max(self.size - 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

# TODO
class CenterCrop(object):
    def __init__(self, crop_size):
        self.crop_h = crop_size
        self.crop_w = crop_size

    def __call__(self, image, label = None):
        h, w, c = image.shape
        top = (h - self.crop_h) // 2
        left = (w - self.crop_w) // 2
        image = image[top:top+self.crop_h, left:left+self.crop_w,:]
        if label is not None:
            label = label[top:top+self.crop_h, left:left+self.crop_w,:]
        return image, label

# TODO
class Resize(object):
    def __init__(self, size):
        self.size = size
    def __call__(self, image, label=None):
        image = cv2.resize(image, (self.size, self.size), interpolation=cv2.INTER_LINEAR)
        if label is not None:
            label = cv2.resize(label, (self.size, self.size), interpolation=cv2.INTER_NEAREST)
        return image,label

# TODO
class RandomFlip(object):
    def __call__(self, image, label = None):
        prob_of_filp = np.random.rand()
        if prob_of_filp > 0.5:
            image = cv2.flip(image, 1)
            if label is not None:
                label = cv2.flip(label,1)
        return image, label


# TODO
class RandomCrop(object):
    def __init__(self, crop_size):
       self.crop_size = crop_size
    def __call__(self, image, label = None):
        h, w, c = image.shape
        top = np.random.uniform(h-self.crop_size)
        left = np.random.uniform(w-self.crop_size)
        assert top >= 0, "Error: crop_size > image height!"
        assert left >= 0, "Error: crop_size > image width!"

        rect = np.array([int(left),
                         int(top),
                         int(left + self.crop_size),
                         int(top + self.crop_size)])
        
        image = image[rect[1]:rect[3], rect[0]:rect[2], :]

        if label is not None:
            label = label[rect[1]:rect[3], rect[0]:rect[2], :]
        return image,label

# # TODO
class Scale(object):
    def __call__(self, image, label=None, scale=1.0):
        if not isinstance(scale,(list,tuple)):
            scale = [scale, scale]
        h, w, c = image.shape
        image = cv2.resize(image,
                            (int(w*scale[0]),int(h*scale[1])),
                            interpolation=cv2.INTER_LINEAR)
        if label is not None:
            label = cv2.resize(label,
                            (int(w*scale[0]),int(h*scale[1])),
                            interpolation=cv2.INTER_NEAREST)
        return image,label

# TODO
class RandomScale(object):
    def __init__(self, min_scale=0.5, max_scale=2.0, step=0.25):
        self.min_scale = min_scale
        self.max_scale = max_scale
        self.step = step
        self.scale = Scale()

    def __call__(self, image, label=None, scale=1.0):
        if self.step == 0:
            self.random_scale = np.random.rand.uniform(self.min_scale,
                                                        self.max_scale,
                                                        1)[0]
        else:
            num_steps = int((self.max_scale - self.min_scale) / self.step + 1)
            scale_factors = np.linspace(self.min_scale,
                                        self.max_scale,
                                        num_steps)
            np.random.shuffle(scale_factors)
            self.random_scale = scale_factors[0]

        image, label = self.scale(image, label, self.random_scale)
        return image,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')

    # TODO: crop_size
    # TODO: Transform: RandomSacle, RandomFlip, Pad, RandomCrop
    crop_size = 200
    augment = Compose([
        RandomScale(),
        RandomFlip(),
        Pad(crop_size, mean_val=[0.485, 0.456, 0.406]),
        RandomCrop(crop_size),
        ConvertDataType(),
        # Normalize(0, 1)
        ])
    # for i in range(10):
        # TODO: call transform
        # TODO: save image
    new_img, new_label = augment(image,label)
    cv2.imwrite('img_new.png', new_img)
    cv2.imwrite('label_new.png', new_label)


if __name__ == "__main__":
    main()

在这里插入图片描述
在这里插入图片描述

3. basic_model.py
在这里插入图片描述

'''
Author: cheng
Date: 2021-10-20 01:12:29
LastEditTime: 2021-10-20 10:58:54
FilePath: /paddlepaddle/code1.py
'''
# paddle动态图
import paddle
import numpy as np
import paddle.fluid as fluid
from paddle.fluid.dygraph.base import to_variable
from paddle.fluid.dygraph import Pool2D
from paddle.fluid.dygraph import Conv2D

# BasicModel继承动态图的层
class BasicModel(fluid.dygraph.Layer):
    # 初始化,简单给一个类别参数,59类
    def __init__(self, num_classes=59):
        # 父类初始化
        super(BasicModel, self).__init__()
        self.pool = Pool2D(pool_size=2, pool_stride=2)
        # num_chanels:input的channel数,
        # num_filters:output维度,或者有多少个卷积核,
        # filter_size卷积尺寸大小
        self.conv = Conv2D(num_channels=3, num_filters=num_classes,filter_size=1)
    def forward(self, inputs):
        x = self.pool(inputs)
        # 上采样,插值,输出和输入尺寸一样
        x = fluid.layers.interpolate(x, out_shape=inputs.shape[2::])
        x = self.conv(x)
        return x

def main():
    # cpu
    place = fluid.CPUPlace()
    # place = fluid.CUDAPlace(0)  #GPU
    with fluid.dygraph.guard(place):
        model = BasicModel(num_classes=59)
        model.eval()    # model.train()
        # random一个数据,类型NCHW,astype转换数据类型
        input_data = np.random.rand(1, 3, 8, 8).astype(np.float32)
        print('Input data shape:', input_data.shape)
        # numpy.array 转换成 tensor
        input_data = to_variable(input_data)
        output_data = model(input_data)
        output_data = output_data.numpy()
        print('Output data shape:',output_data.shape)



if __name__ =='__main__':
    main() 

输出:

Input data shape: (1, 3, 8, 8)
Output data shape: (1, 59, 8, 8)
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值