前言

计划是在寒假时用在飞桨平台上做动物,水果的分类。

制作数据集

代码在文章最后

下载数据集

飞桨有内置数据集和自定义数据集,这里主要是写如何制作自定义数据集。我这里用到的数据集就是第十六届智能车视觉AI组组委会提供的数据集:这里放上百度网盘链接:
动物水果数据集l
提取码:lasl
只需要下载动物水果即可。

在这里插入图片描述

飞桨数据集

飞桨有 map-style 的 paddle.io.Dataset 基类 和 iterable-style 的 paddle.io.IterableDataset 基类 ,来完成数据集定义。此外,针对一些特殊的场景,飞桨框架也提供了 paddle.io.TensorDataset 基类,可以直接处理 Tensor 数据为 dataset,一键完成数据集的定义。这里用的是基于paddle.io.Dataset的,也是官方更为推荐使用的API.使用 paddle.io.Dataset,最后会返回一个 map-style 的 Dataset 类。可以用于后续的数据增强、数据加载等。
使用 paddle.io.Dataset 只需要按格式完成以下四步即可。

步骤一:继承paddle.io.IterableDataset类
步骤二:实现构造函数,定义数据读取方式,划分训练和测试数据集
步骤三:实现__getitem__方法,定义指定index时如何获取数据,并返回单条数据(训练数据,对应的标签)
步骤四:实现__len__方法,返回数据集总数目
在下面将会逐步实现这些步骤

制作飞桨数据集

1.继承paddle.io.IterableDataset类

import os
import random

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
import paddle
class myreader(paddle.io.Dataset):


if __name__ == '__main__':
	pass

2.实现构造函数,定义数据读取方式,划分训练和测试数据集
将数据集按照数字索引的方式命名,要处理的文件路径是这样的:

在这里插入图片描述

0~9是分别是5个动物和5个水果大类,里面分别有各类png图片100张左右。
用os.path.join()方法来拼接路径,遍历得到每一张图片的路径。
然后用os.path.splitext()来判段文件是否是.png后缀的,这个方法会将文件名和文件后缀分开,os.path.splitext(文件路径)[-1]所读取到的就是后缀。
然后用cv.imread来读取图片,输入参数有两个,一个是路径,一个是读取的色彩选择,可以选择bgr彩图还是灰度图,默认bgr彩图,注意这个顺序是bgr,而不是常见的rgb,如果读取完后直接用plt来显示的话,图像的色彩就会出错。
所以我们用cv.resize()来对图像的大小以及色彩进行修改,cv.resize(img, (64, 64))[…, (2, 1, 0)],这是指将图像放缩为64×64大小的rgb图片。(这里修改图像大小的步骤不能省去,否则数组形状不一,后面会报错或警告)
我们需要将整组图片分为训练集以及测试集,这两个集合不能有重叠部分。这里用train_ratio作为参数来指定训练集的占比,然后用train_ratio*10与图片索引相比来决定是训练集还是测试集,这样的话对于相同的一组图片以及相同的train_ratio来说其训练集和测试集完全没有重叠
具体代码如下:

	"""
    file_path:大文件夹路径
    train_ratio:训练集的占比 0~1
    index_num:指大文件夹下每个小分类文件的总数
    mode: 训练集还是测试集
    """
    def __init__(self,file_path,train_ratio,index_num,mode):
    	super(myreader, self).__init__()
        # self.all_data=[]
        # self.all_lable=[]
        self.mode = mode
        self.train_data = []
        self.train_lable = []
        self.test_data = []
        self.test_lable = []
        self.file_path = file_path
        self.train_ratio = train_ratio
        dataindex = 0
        for i in range(index_num):
            file_path = os.path.join(self.file_path,'%d' % i)
            for j in os.listdir(file_path):
                dataindex = dataindex % 10

                if(os.path.splitext(j)[-1] == '.png'):
                    img = cv.imread(os.path.join(file_path, j))
                    img = cv.resize(img, (64, 64))[..., (2, 1, 0)]
                    
                    if mode == 'train':
                        if dataindex < train_ratio*10:
                            self.train_data.append(img/255)
                            self.train_lable.append(i)
                    else:
                        if dataindex >= train_ratio*10:
                            self.test_data.append(img)
                            self.test_lable.append(i)
                dataindex += 1

3.实现__getitem__方法,定义指定index时如何获取数据,并返回单条数据

	def __getitem__(self,index):
        if self.mode == 'train':
            npData = np.asarray(self.train_data,dtype='float32')[index]
            npLable = np.asarray(self.train_lable,dtype='int64')[index]
            return npData,npLable
        else:
            npData = np.asarray(self.test_data,dtype='float32')[index]
            npLable = np.asarray(self.test_lable,dtype='int64')[index]
            return npData, npLable

4.实现__len__方法,返回数据集总数目

注意len方法所对应的值要和getitem的值相等,就是说如果要用getitem取训练集的话,相对的len方法也要返回训练集的数目。

    def __len__(self):
        if self.mode == 'train':
            return len(self.train_data)
        else:
            return len(self.test_data)

数据集的加载

当我们定义了数据集后,就需要加载数据集。我们可以通过 paddle.io.DataLoader 完成数据的加载。

train_dataset = myreader(r'picture',0.7,2,'train')
    train_loader = paddle.io.DataLoader(train_dataset, batch_size=64, shuffle=True)

完整代码

import os
import numpy as np
import cv2 as cv
# import matplotlib.pyplot as plt
import paddle

class myreader(paddle.io.Dataset):
    """
    继承paddle.io.Dataset类
    """
    """
    file_path:大文件夹路径
    train_ratio:训练集的占比 0~1
    index_num:指大文件夹下每个小分类文件的总数
    mode: 训练集还是测试集
    """

    def __init__(self,file_path,train_ratio,index_num,mode):
    	super(myreader, self).__init__()
        # self.all_data=[]
        # self.all_lable=[]
        self.mode = mode
        self.train_data = []
        self.train_lable = []
        self.test_data = []
        self.test_lable = []
        self.file_path = file_path
        self.train_ratio = train_ratio
        dataindex = 0
        for i in range(index_num):
            file_path = os.path.join(self.file_path,'%d' % i)
            for j in os.listdir(file_path):
                dataindex = dataindex % 10

                if(os.path.splitext(j)[-1] == '.png'):
                    img = cv.imread(os.path.join(file_path, j))
                    img = cv.resize(img, (64, 64))[..., (2, 1, 0)]
                    
                    if mode == 'train':
                        if dataindex < train_ratio*10:
                            self.train_data.append(img/255)
                            self.train_lable.append(i)
                    else:
                        if dataindex >= train_ratio*10:
                            self.test_data.append(img)
                            self.test_lable.append(i)
                dataindex += 1

    def __getitem__(self,index):
        if self.mode == 'train':
            npData = np.asarray(self.train_data,dtype='float32')[index]
            npLable = np.asarray(self.train_lable,dtype='int64')[index]
            return npData,npLable
        else:
            npData = np.asarray(self.test_data,dtype='float32')[index]
            npLable = np.asarray(self.test_lable,dtype='int64')[index]
            return npData, npLable

    def __len__(self):
        if self.mode == 'train':
            return len(self.train_data)
        else:
            return len(self.test_data)

if __name__ == '__main__':
    import matplotlib.pyplot as plt
    train_dataset = myreader(r'animal_fruit',0.7,1,'train')
    train_loader = paddle.io.DataLoader(train_dataset, batch_size=64, shuffle=True)
    test_dataset = myreader(r'animal_fruit',0.7,1,'test')
    test_loader = paddle.io.DataLoader(test_dataset, batch_size=64, shuffle=True)
    for batch_id, data in enumerate(train_loader()):
        x_data = data[0]
        y_data = data[1]
        print(x_data.numpy().dtype)
        print(y_data.numpy().shape)
    # for batch_id, data in enumerate(test_loader()):
    #     x_data = data[0]
    #     y_data = data[1]
    #     print(x_data.numpy().shape)
    #     print(y_data.numpy().shape)

    print(train_dataset[1][0])
    l = np.array(train_dataset[0][0])
    plt.figure(figsize=(2,2))
    plt.imshow(l, cmap=plt.cm.binary)


在这里插入图片描述

测试:

from work import myImageReader
import paddle
import matplotlib.pyplot as plt
import numpy as np
train_dataset = myImageReader.myreader(r'animal',0.7,1,'train')
# print(train_dataset[1][0])
l = np.array(train_dataset[0][0])
plt.figure(figsize=(2,2))
plt.imshow(l, cmap=plt.cm.binary)

在这里插入图片描述