torchvision
计算机视觉工具包,包括三部分
torchvision.transforms:常用的图像预处理方法
torchvision.datasets:常用数据集的dataset实现,MNIST,CIFAR-10,ImageNet等
torchvision.model:常用的模型预训练,Alexnet,VGG,ResNet,GoogLenet等
transforms
torchvision.transforms:常用的图像预处理方法
1. transforms.Normalize(mean, std, inplace=False)
功能:逐channel的对图像进行标准化
output = (input - mean) / std
mean:各通道的均值
std:各通道的标准差
inplace:是否原地操作
a = Image.open(data_dir)
t = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])])
inp = t(a).numpy().transpose((1, 2, 0))
plt.imshow(inp)
plt.show()
注意:
1.在Normalize之前必须先ToTensor
2.在显示处理后的图片时,对于三通道图片要改变通道位置
图片裁剪和填充
2. transforms.CenterCrop(size) # 从图像中心裁剪
3. transforms.RandomCrop(size, padding = None, pad_if_needed = False, fill = 0, padding_mode = 'constant') # 随机位置裁剪
4. transforms..RandomResizedCrop(size, scale = (0.08, 1), ratio = (3/4, 4/3)) # 随机大小裁剪后,resize到指定尺寸
5. transforms.FiveCrop(size) # 在图片的上下左右以及中心裁剪出指定大小的图片
6. transforms.TenCrop(size, vertical_flip = False) # 对这五张图片进行水平或垂直翻转获得十张图片
4. transforms.Pad(padding, fill=0, padding_mode='constant')
padding:设置填充大小
当为a时,上下左右填充a个像素
当为(a,b)时,左右填充a个像素,上下填充b个像素
当为(a,b,c,d)时,左上右下分别填充a,b,c,d
padding_mode:设置填充模式(constant:由fill决定;edge:由边缘像素决定;reflect:镜像填充,最后一个像素不镜像;symmetric:镜像填充,最后一个像素镜像)
fill:当为constant模式时,设置填充的像素值
注意:
FiveCrops返回的时一个tuple,需要改为:
transforms.Compose([
transforms.FiveCrop(256),
transforms.Lambda(lambda crops:torch.stack([(transforms.Compose([transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406],[0.229, 0.224, 0.225])])(crop)) for crop in crops])),
])
经过预处理后得到的尺寸为torch.Size([5, 3, 256, 256])
图片翻转、旋转
transforms.RandomHorizontalFlip(p = 0.5) # 水平翻转
transforms.RandomVerticalFlip(p = 0.5) # 上下翻转
transforms.RandomRotation(degrees, resample=False, expand=False, center=None)
degrees: 旋转角度
当为a时,在(-a,a)之间旋转
当为(a,b),在(a,b)之间旋转
resample:重采样方法
expand:是否扩大图片,以保持原图信息
注意:
使用epand时,之后要将图片缩放到统一尺寸
图片画质调整
transforms.ColorJitter(brightness=0, contrast=0, saturation=0)
调整亮度brightness,对比度contrast和饱和度saturation
当为a时,从[max(0,1-a),1+a]中随机选择
当为(a, b)时,从[a, b]中随机选择
transforms.Grayscale(num_output_channels) # 转化为灰度图像
transforms.RandomGrayscale(num_output_channels, p=0.1) # 依概率转化为灰度图像
num_output_channels:输出通道数,只能设为1或3
组合使用方法
from torchvision import transforms
transform = transforms.Compose([
transforms.ToTensor()
])
class Compose(object):
def __call__(self, img):
for t in self.tramsforms:
img = t(img)
return img
注意:
定义类型的时候,实现__call__函数,这个类型就成为可调用的。换句话说,我们可以把这个类型的对象当作函数来使用,相当于 重载了括号运算符。
例如:
t = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
])
inp = t(a)
从t(a),无法确定t是一个函数还是一个类实例。
自定义损失函数
**注意:
- 接受一个参数,返回一个参数
- 注意数据类型**(在ToTensor之前,都是PIL格式)
实现方法:
class YourTransforms(object):
def __init__(self, ...):
def __call__(self, ...):
return img
注:
numpy.random.choice(a, size=None, replace=True, p=None)
从给定的1维数组中产生一个随机样本
numpy.repeat(a,repeats,axis=None)
复制一个数组repeats次
astype:转换数组的数据类型 (numpy的属性)
import numpy
import random
class AddPepperNoise(object):
def __init__(self,snr,p=0.9):
self.snr = snr
self.p = p
def __call__(self, img):
if random.uniform(0,1) < self.p:
img_ = numpy.array(img).copy()
h, w, c = img_.shape
signal_pct = self.snr
noise_pct = (1-self.snr)
mask = numpy.random.choice((0,1,2),size=(h,w,1),p=[signal_pct,noise_pct/2.,noise_pct/2.]) # 0:原始图像,1:盐噪声, 2:椒噪声
mask = numpy.repeat(mask,c,axis=2)
img_[mask == 1] = 255 # 盐噪声
img_[mask == 2] = 0 # 椒噪声
return Image.fromarray(img_.astype('uint8')).convert('RGB')
else:
return img
a = Image.open(data_dir)
t = transforms.Compose([
AddPepperNoise(0.9,p = 1),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
])
inp = t(a).numpy().transpose((1, 2, 0))
plt.imshow(inp)
plt.show()