神经网络中用于图片裁剪,翻转,随机擦除的transform以及matplotlib可视化(代码逐行解释)

裁剪加翻转


说明
tensor->show:是将生成的tensor(三维度)生成灰度图
image->show:将tensor变成Img形式再生成
通道1->image->show:取tensor的一个维度,变成Img形式再生成
注意

  1. 随机裁剪加翻转是在图片格式上进行的,与下面随机擦除不同(在tensor上进行)
  2. 这里总结了一个如何将tensor数据plt.show()出来的2种方法
1:plt.imshow(img_t[0], cmap='gray')#img_t[0]=tensor 直接将tensor显示2:image_PIL = transforms.ToPILImage()(img_t)  # type(image_PIL)=PIL.Image.Image,将tensor变成Img,再显示

代码

#transform实现数据增广,pytorch中自带的随机翻转,剪切可以解决90%的问题,下面是自己如何做一个transform,实现裁剪、翻转

from __future__ import absolute_import
import torchvision.transforms as transform
from torchvision.transforms import *
from PIL import Image
import random
import matplotlib.pyplot as plt
class Random2DTranslation(object):#随机放大并crop,这里的操作是对图片直接crop  可以img.resize((1000,1000),Image.BILINEAR)show出来
    """
    With a probability, first increase image size to (1 + 1/8), and then perform random crop.
    Args:
        height (int): target height.
        width (int): target width.
        p (float): probability of performing this transformation. Default: 0.5.
    """
    def __init__(self,  height,width, p=0.5, interpolation=Image.BILINEAR):
        self.height = height
        self.width = width
        self.p = p
        self.interpolation = interpolation#放大图片时用的插值来填充

    def __call__(self, img):
        """
        Args:
            img (PIL Image): Image to be cropped.
        Returns:
            PIL Image: Cropped image.
        """
        if random.random() < self.p:#random产生一个0-1分步的随机数,若数字小于P,就不进行数据增广
            return img.resize((self.width, self.height), self.interpolation)
        new_width, new_height = int(round(self.width * 1.125)), int(round(self.height * 1.125))#放大1/8/round取上限,加上int更稳
        resized_img = img.resize((new_width, new_height), self.interpolation)
        x_maxrange = new_width - self.width
        y_maxrange = new_height - self.height#crop的最大范围
        x1 = int(round(random.uniform(0, x_maxrange)))#crop的起始点
        y1 = int(round(random.uniform(0, y_maxrange)))
        croped_img = resized_img.crop((x1, y1, x1 + self.width, y1 + self.height))
        return croped_img

if __name__ == '__main__':
    plt.rcParams['font.sans-serif'] = ['STSong']  # 中文宋体
    img=Image.open('E:\Python_project\scientific research\\test.jpg')

    transform=transform.Compose([
        Random2DTranslation(128, 256, 0.5),
        transforms.RandomHorizontalFlip(p=0.1),#水平翻转
        transform.ToTensor()
        ])

    img_t=transform(img)#torch.Size([3, 128, 256]),这里完全由transform.ToTensor()决定输出是Image形式,还是tensor
                        #img_t[0]表示的是第一个通道的信息size=128x256

    plt.subplot(231)
    plt.imshow(img)  #Image
    plt.title('原图->show')

    plt.subplot(232)
    plt.imshow(img_t[0], cmap='gray')#img_t[0]=tensor
    plt.title('tensor->show')


    plt.subplot(233)
    image_PIL = transforms.ToPILImage()(img_t)  # type(image_PIL)=PIL.Image.Image
    plt.imshow(image_PIL)
    plt.title('image->show')

    plt.subplot(234)
    image_PIL = transforms.ToPILImage()(img_t[0])  # type(image_PIL)=PIL.Image.Image
    plt.imshow(image_PIL)
    plt.title('通道1->image->show')

    plt.subplot(235)
    image_PIL = transforms.ToPILImage()(img_t[1])  # type(image_PIL)=PIL.Image.Image
    plt.imshow(image_PIL)
    plt.title('通道2->image->show')
    plt.subplot(236)
    image_PIL = transforms.ToPILImage()(img_t[2])  # type(image_PIL)=PIL.Image.Image
    plt.imshow(image_PIL)
    plt.title('通道3->image->show')

    plt.show()

随机擦除

在这里插入图片描述
注意:
要先把图片 transform.ToTensor(),再进行RandomErasing(),也就是说随机擦除的过程是在tensor数据上进行的,这与上面的裁剪,翻转不一样。

代码

import math
import random
from PIL import Image
import torchvision.transforms as transform
from torchvision.transforms import *
import matplotlib.pyplot as plt
class RandomErasing(object):
    """ Randomly selects a rectangle region in an image and erases its pixels.
    Args:
         probability: The probability that the Random Erasing operation will be performed.
         sl: Minimum proportion of erased area against input image.擦除面积与输入图像的最小比例
         sh: Maximum proportion of erased area against input image.
         r1: Minimum aspect ratio of erased area.擦除面积的最小纵横比
         mean: Erasing value.
    """

    def __init__(self, probability=0.999, sl=0.02, sh=0.4, r1=0.3, mean=(0.4914, 0.4822, 0.4465)):
        self.probability = probability
        self.mean = mean
        self.sl = sl
        self.sh = sh
        self.r1 = r1

    def __call__(self, img):

        if random.uniform(0, 1) >= self.probability:#随机生成一个数,若>=self.probability,就不在随机擦除
            return img

        for attempt in range(100):#循环100次为了让擦拭能够进行,即 w < img.size()[2] and h < img.size()[1]
            area = img.size()[1] * img.size()[2]#img.size()=tensor.Size([3,300,400])  area=120000,
            target_area = random.uniform(self.sl, self.sh) * area#random.uniform(self.sl, self.sh)=0.087,target_area=43925
            aspect_ratio = random.uniform(self.r1, 1 / self.r1)#=1.851555500982092

            h = int(round(math.sqrt(target_area * aspect_ratio)))#224
            w = int(round(math.sqrt(target_area / aspect_ratio)))#156

            if w < img.size()[2] and h < img.size()[1]:#宽400,高300
                x1 = random.randint(0, img.size()[1] - h)#37
                y1 = random.randint(0, img.size()[2] - w)#90
                if img.size()[0] == 3:#图片为三个通道,则三个通道都赋值
                    img[0, x1:x1 + h, y1:y1 + w] = self.mean[0]#img[0, x1:x1 + h, y1:y1 + w].shape=torch.Size([224, 156]),这么大区域全部附上0.4914这个值
                    img[1, x1:x1 + h, y1:y1 + w] = self.mean[1]
                    img[2, x1:x1 + h, y1:y1 + w] = self.mean[2]
                else:
                    img[0, x1:x1 + h, y1:y1 + w] = self.mean[0]
                return img

        return img

if __name__ == '__main__':
    plt.rcParams['font.sans-serif'] = ['STSong']  # 中文宋体
    img=Image.open('E:\Python_project\scientific research\\test.jpg')
    img=img.resize((400,300),Image.BILINEAR)
    transform=transform.Compose([
        transform.ToTensor(),
        RandomErasing()
        ])
    img_t=transform(img)

    plt.subplot(121)
    plt.imshow(img)
    plt.title('原图->show')

    plt.subplot(122)
    image_PIL = transforms.ToPILImage()(img_t)  # type(image_PIL)=PIL.Image.Image
    plt.imshow(image_PIL)
    plt.title('image->show')
    plt.show()

碰巧,如果你看到了这篇文章,并且觉得有用的话 那就给个三连吧!

如果对matplotlib画图感兴趣:拿走链接

在这里插入图片描述

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值