[图像处理]-使用python及PIL库对图像分类数据图片进行数据增强扩充

1.简介

在一些时候,我们进行分类任务的时候,样本数据太少,这就需要我们对数据集进行数据增强来扩充数据集。
常用的方法包含以下几种

空间几何变换类

  • 翻转
  • 裁剪
  • 旋转
  • 缩放变形
  • 平移变换

颜色变换类
噪声变换类

2.脚本

以下包含一个python脚本,主要调用了PIL库,来完成对数据集的批量扩充。
主要包含三个部分:

  • 函数def1-def8:分别对于1中的不同图像增强手段
  • 概率执行函数:以某种概率来执行数据增强方法,即设置不同的概率来执行函数def1-函数def8
  • 主函数:可以对应更改,读取要增强的数据集文件夹及保存文件及
# 本代码主要提供一些针对图像分类的数据增强方法

# 1、平移。在图像平面上对图像以一定方式进行平移。
# 2、翻转图像。沿着水平或者垂直方向翻转图像。
# 3、旋转角度。随机旋转图像一定角度; 改变图像内容的朝向。
# 4、随机颜色。包括调整图像饱和度、亮度、对比度、锐度
# 5、缩放变形图片。
# 6、二值化图像。
# 7、随机黑色块遮挡
# 8、添加噪声

# @ author : cheng
# @ time : 2021.03.25


from PIL import Image
from PIL import ImageEnhance
from PIL import ImageChops
import os
import numpy as np


# 1、图像平移
def move(img): #平移,平移尺度为off
    offset = ImageChops.offset(img, np.random.randint(1, 20), np.random.randint(1, 40))
    return offset

# 2、翻转图像
def flip(img):   
    factor = np.random.randint(1, 3) #随机因子,随机上下或者左右翻转
    if factor == 1:
        filp_img = img.transpose(Image.FLIP_TOP_BOTTOM)
    else:
        filp_img = img.transpose(Image.FLIP_LEFT_RIGHT)
    return filp_img

#  3、旋转角度
def rotation(img):
    factor = np.random.randint(1, 21) #随机旋转角度
    rotation_img = img.rotate(factor) 
    return rotation_img

# 4、随机颜色 
def color(img): 
    """
    对图像进行颜色抖动
    :param image: PIL的图像image
    :return: 有颜色色差的图像image
    """
    random_factor = np.random.randint(5, 15) / 10.  # 随机因子
    color_image = ImageEnhance.Color(img).enhance(random_factor)                     # 调整图像的饱和度
    random_factor = np.random.randint(8, 15) / 10.  # 随机因子
    brightness_image = ImageEnhance.Brightness(color_image).enhance(random_factor)   # 调整图像的亮度
    random_factor = np.random.randint(10, 13) / 10. # 随机因子
    contrast_image = ImageEnhance.Contrast(brightness_image).enhance(random_factor)  # 调整图像对比度
    random_factor = np.random.randint(5, 31) / 10.  # 随机因子
    random_color = ImageEnhance.Sharpness(contrast_image).enhance(random_factor)     # 调整图像锐度
    return random_color 

# 5、缩放变形图片
def crop(img):
    factor_1 = np.random.randint(10, 50)
    factor_2 = np.random.randint(20, 50)
    crop_img = img.crop((img.size[0]/factor_1, img.size[1]/factor_2, img.size[0]*(factor_1-1)/factor_1, img.size[1]*(factor_2-1)/factor_2))
    cropResize_img = crop_img.resize((img.size[0], img.size[1]))
    return cropResize_img

# 6、二值化图像
def convert(img):
    convert_img = img.convert('L')
    return convert_img


# 7、黑色块遮挡
def paste(img):
    # 左上右下
    factor_1 = np.random.randint(20, 70)
    factor_2 = np.random.randint(30, 60)
    # 随机进行左边遮罩
    a = np.random.randint(1,3)
    if a == 2:
        img.paste((0,0,0),(int(img.size[0]*(factor_1-np.random.randint(2,4))/factor_1), 
                        int(img.size[1]*(np.random.randint(1,25))/factor_2), 
                        int(img.size[0]*(factor_1-np.random.randint(0,2))/factor_1),
                        int(img.size[1]*(np.random.randint(26,50))/factor_2)
                        ))
    else:
        # 随机进行底部遮罩
        img.paste((0,0,0),(int(img.size[0]*(np.random.randint(1,19))/factor_1), 
                        # int(img.size[1]*(factor_2-2)/factor_2), 
                        int(img.size[1]*(factor_2-np.random.randint(3,6))/factor_2),
                        int(img.size[0]*(np.random.randint(21,41))/factor_1),
                        # int(img.size[1]*(factor_2-1)/factor_2)
                        int(img.size[1]*(factor_2-np.random.randint(0,3))/factor_2)
                        ))
    return img


# 8、随机添加黑白噪声
def salt_and_pepper_noise(img, proportion = 0.00025):
    noise_img = img
    height,width =noise_img.size[0],noise_img.size[1]
    proportion = proportion * np.random.randint(1, 50)
    num = int(height * width * proportion) #多少个像素点添加椒盐噪声
    pixels = noise_img.load()
    for i in range(num):
        w = np.random.randint(0,width-1)
        h = np.random.randint(0,height-1)
        if np.random.randint(0,2) == 1:
            pixels[h,w] = 0
        else:
            pixels[h,w] = 255
    return noise_img



# 概率执行函数
def random_run(probability, func, useimage):
    """以probability%的概率执行func(*args)"""
    list = []
    for i in range(probability):
        list.append(1)                      #list中放入probability个1
    for x in range(100 - probability):
        list.append(0)                      #剩下的位置放入0
    a = np.random.choice(list)              #随机抽取一个
    if a == 0:
        return useimage
    if a == 1:
        image = func(useimage)
        return image




def main():
    imageDir = "./pricture/"            #要改变的图片的路径文件夹
    saveDir = "./save/"                 #要保存的图片的路径文件夹
    seed = 10                           #每张初始图片要数据增强为多少张图片
    for name in os.listdir(imageDir):
        i=0
        for i in range(seed):
            i = i+1
            saveName = str(name[:-4]) + str(i) +".jpg"
            img = Image.open(os.path.join(imageDir, name))
            saveImage = random_run(60, flip, img)                               # 翻转
            saveImage = random_run(70, color, saveImage)                        # 色彩变化
            saveImage = random_run(30, crop, saveImage)                         # 裁减缩放
            saveImage = random_run(30, paste, saveImage)                        # 添加遮罩
            saveImage = random_run(20, move, saveImage)                         # 平移
            saveImage = random_run(50, rotation, saveImage)                     # 旋转
            saveImage = random_run(10, convert, saveImage)                      # 二值化  
            saveImage = random_run(20, salt_and_pepper_noise, saveImage)        # 添加噪声点
            # saveImage = random_run(90, gauss_noise, saveImage)
            print(type(saveImage))
            if saveImage != None:
                saveImage.save(os.path.join(saveDir, saveName))
            else:
                pass
            print(i)


if __name__ == "__main__":
    main()

3.示意图

初始数据图片如下
在这里插入图片描述
执行后生成数据如下所示

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

4.补充

更多功能待完善

  • 6
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值