裁剪加翻转
说明
tensor->show:是将生成的tensor(三维度)生成灰度图
image->show:将tensor变成Img形式再生成
通道1->image->show:取tensor的一个维度,变成Img形式再生成
注意
- 随机裁剪加翻转是在图片格式上进行的,与下面随机擦除不同(在tensor上进行)
- 这里总结了一个如何将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()
碰巧,如果你看到了这篇文章,并且觉得有用的话 那就给个三连吧!