首页IT科技pytorch tensor类型转换([九]深度学习Pytorch-transforms图像增强(剪裁、翻转、旋转))

pytorch tensor类型转换([九]深度学习Pytorch-transforms图像增强(剪裁、翻转、旋转))

时间2025-05-05 11:55:33分类IT科技浏览3904
导读:0. 往期内容 [一]深度学习Pytorch-张量定义与张量创建...

0. 往期内容

[一]深度学习Pytorch-张量定义与张量创建

[二]深度学习Pytorch-张量的操作:拼接            、切分               、索引和变换

[三]深度学习Pytorch-张量数学运算

[四]深度学习Pytorch-线性回归

[五]深度学习Pytorch-计算图与动态图机制

[六]深度学习Pytorch-autograd与逻辑回归

[七]深度学习Pytorch-DataLoader与Dataset(含人民币二分类实战)

[八]深度学习Pytorch-图像预处理transforms

[九]深度学习Pytorch-transforms图像增强(剪裁     、翻转         、旋转)

[十]深度学习Pytorch-transforms图像操作及自定义方法

1. 数据增强

2. 剪裁

2.1 transforms.CenterCrop(size)

transforms.CenterCrop(size)

(1)功能

:从图像中心裁剪尺寸为size的图片;

(2)参数

size: 若为int         ,则尺寸为size*size; 若为(h,w)                 ,则尺寸为h*w.

(3)代码示例train_transform = transforms.Compose([ transforms.Resize((224, 224)), #图片统一缩放到244*244 # 1 CenterCrop transforms.CenterCrop(196), # 裁剪为196*196      ,如果是512的话       ,超出244的区域填充为黑色 transforms.ToTensor(), transforms.Normalize(norm_mean, norm_std), ])

2.2 transforms.RandomCrop(size, fill=0, padding_mode=‘constant’)

transforms.RandomCrop(size, padding=None, pad_if_needed=False, fill=0, padding_mode=constant)

(1)功能

:对图像随机裁剪出尺寸为size的图片;

(2)参数

size: 若为int                ,则尺寸为size*size; 若为(h,w)         ,则尺寸为h*w;

padding: 设置填充大小:

I. 当padding为a时     ,左右上下均填充a个像素;

II. 当padding为(a,b)时               ,左右填充a个像素            ,上下填充b个像素;

III. 当padding为(a,b,c,d)时   ,左                、上       、右      、下分别填充a                 、b         、c   、d;

pad_if_need:若设定的size大于原图像尺寸               ,则填充;

padding_mode:填充模式               ,有4种模式:

I. constant:像素值由fill设定;

II. edge:像素值由图像边缘的像素值决定;

III. reflect:镜像填充,最后一个像素不镜像            ,eg. [1,2,3,4] --> [3,2,1,2,3,4,3,2];

向左:由于1不会镜像                  ,所以左边镜像2                  、3;

向右:由于4不会镜像   ,所以右边镜像3            、2;

IV. symmetric:镜像填充         ,最后一个像素镜像                 ,eg. [1,2,3,4] --> [2,1,1,2,3,4,4,3];

向左:1、2镜像;

向右:4               、3镜像;

fill:当padding_mode=constant时      ,用于设置填充的像素值;

(3)代码示例

train_transform = transforms.Compose([ transforms.Resize((224, 224)), #图片统一缩放到244*244 # 2 RandomCrop transforms.RandomCrop(224, padding=16), transforms.RandomCrop(224, padding=(16, 64)), transforms.RandomCrop(224, padding=16, fill=(255, 0, 0)), #fill=(255, 0, 0)RGB颜色 #当size大于图片尺寸       ,即512大于244                ,pad_if_needed必须设置为True         ,否则会报错     ,其他区域会填充黑色(0               ,0            ,0) transforms.RandomCrop(512, pad_if_needed=True), # pad_if_needed=True transforms.RandomCrop(224, padding=64, padding_mode=edge), #边缘 transforms.RandomCrop(224, padding=64, padding_mode=reflect), #镜像 transforms.RandomCrop(1024, padding=1024, padding_mode=symmetric), #镜像 transforms.ToTensor(), transforms.Normalize(norm_mean, norm_std), ])

2.3 transforms.RandomResizedCrop(size, scale=(0.08, 1.0), ratio=(3/4, 4/3), interpolation)

transforms.RandomResizedCrop(size, scale=(0.08, 1.0), ratio=(3/4, 4/3), interpolation=<InterpolationMode.BILINEAR: bilinear>)

(1)功能

:随机大小               、随机长宽比裁剪图片;

(2)参数

size: 裁剪图片尺寸   ,若为int               ,则尺寸为size*size; 若为(h,w)               ,则尺寸为h*w,size是最后图片的尺寸;

scale: 随机裁剪面积比例,默认区间(0.08,1),scale默认是随机选取0.08-1之间的一个数

ratio: 随机长宽比            ,默认区间(3/4,4/3),ratio默认是随机选取3/4-4/3之间的一个数

interpolation: 插值方法                  ,eg. PIL. Image. NEAREST, PIL. Image. BILINEAR, PIL. Image. BICUBIC;

(3)步骤

随机确定scale和ratio   ,然后对原始图片进行选取         ,再将选取的片段缩放到size大小;

(4)代码示例train_transform = transforms.Compose([ transforms.Resize((224, 224)), #图片统一缩放到244*244 # 3 RandomResizedCrop transforms.RandomResizedCrop(size=224, scale=(0.5, 0.5)), transforms.ToTensor(), transforms.Normalize(norm_mean, norm_std), ])

2.4 transforms.FiveCrop(size)

transforms.FiveCrop(size)

(1)功能

:在图像的左上   、右上            、左下               、右下     、中心随机剪裁出尺寸为size的5张图片;

(2)参数

size: 裁剪图片尺寸                 ,若为int      ,则尺寸为size*size; 若为(h,w)       ,则尺寸为h*w;

(3)代码示例train_transform = transforms.Compose([ transforms.Resize((224, 224)), #图片统一缩放到244*244 # 4 FiveCrop transforms.FiveCrop(112), #单独使用错误                ,直接使用transforms.FiveCrop(112)会报错         ,需要跟下一行一起使用 #lamda的冒号之前是函数的输入(crops)     ,冒号之后是函数的返回值 transforms.Lambda(lambda crops: torch.stack([(transforms.ToTensor()(crop)) for crop in crops])), #这里进行了ToTensor()               ,后面不需要执行Totensor()和Normalize            ,第114-115行 ])

使用FiveCrop时需要使用五维可视化   ,这是因为inputs为五维(batch_size*ncrops*chanel*图像宽*图像高)               ,代码如下:

for epoch in range(MAX_EPOCH): for i, data in enumerate(train_loader): inputs, labels = data #五维可视化 #使用FiveCrop时inputs为五维:batch_size*ncrops*chanel*图像宽*图像高,此时ncrops=5 bs, ncrops, c, h, w = inputs.shape for n in range(ncrops): img_tensor = inputs[0, n, ...] # C H W img = transform_invert(img_tensor, train_transform) plt.imshow(img) plt.show() plt.pause(1)

2.5 transforms.TenCrop(size, vertical_flip=False)

transforms.TenCrop(size, vertical_flip=False)

(1)功能

:在图像的左上         、右上                、左下       、右下      、中心随机剪裁出尺寸为size的5张图片               ,然后再对这5张照片进行水平或者垂直镜像来获得总共10张图片;

(2)参数

size: 裁剪图片尺寸,若为int            ,则尺寸为size*size; 若为(h,w)                  ,则尺寸为h*w;

vertical_flip: 是否垂直翻转   ,默认为False代表进行水平翻转;

(3)代码示例train_transform = transforms.Compose([ transforms.Resize((224, 224)), #图片统一缩放到244*244 # 5 TenCrop transforms.TenCrop(112, vertical_flip=False), #lamda的冒号之前是函数的输入(crops)         ,冒号之后是函数的返回值 transforms.Lambda(lambda crops: torch.stack([(transforms.ToTensor()(crop)) for crop in crops])), ])

使用TenCrop时需要使用五维可视化                 ,这是因为inputs为五维(batch_size*ncrops*chanel*图像宽*图像高)      ,代码如下:

for epoch in range(MAX_EPOCH): for i, data in enumerate(train_loader): inputs, labels = data #五维可视化 #使用FiveCrop时inputs为五维:batch_size*ncrops*chanel*图像宽*图像高,此时ncrops=5 bs, ncrops, c, h, w = inputs.shape for n in range(ncrops): img_tensor = inputs[0, n, ...] # C H W img = transform_invert(img_tensor, train_transform) plt.imshow(img) plt.show() plt.pause(1)

3. 旋转

3.1 transforms.RandomHorizontalFlip(p=0.5)

transforms.RandomHorizontalFlip(p=0.5)

(1)功能

:根据概率对图片进行水平(左右)翻转       ,每次根据概率来决定是否执行翻转;

(2)参数

p: 反转概率;

(3)代码示例train_transform = transforms.Compose([ transforms.Resize((224, 224)), #图片统一缩放到244*244 # 1 Horizontal Flip transforms.RandomHorizontalFlip(p=1), #执行水平翻转的概率为1 transforms.ToTensor(), transforms.Normalize(norm_mean, norm_std), ])

3.2 transforms.RandomVerticalFlip(p=0.5)

transforms.RandomVerticalFlip(p=0.5)

(1)功能

:根据概率对图片进行垂直(上下)翻转                ,每次根据概率来决定是否执行翻转;

(2)参数

p: 反转概率;

(3)代码示例train_transform = transforms.Compose([ transforms.Resize((224, 224)), #图片统一缩放到244*244 # 2 Vertical Flip transforms.RandomVerticalFlip(p=0.5), #执行垂直翻转的概率为0.5 transforms.ToTensor(), transforms.Normalize(norm_mean, norm_std), ])

3.3 transforms.RandomRotation(degrees, expand=False, center=None, fill=0, resample=None)

transforms.RandomRotation(degrees, expand=False, center=None, fill=0, resample=None)

(1)功能

:对图片旋转随机的角度;

(2)参数

degrees: 旋转角度;

I. 当degrees为a时         ,在区间(-a,a)之间随机选择旋转角度;

II. 当degrees为(a,b)时     ,在区间(a,b)之间随机选择旋转角度;

resample: 重采样方法;

expand: 是否扩大图片以保持原图信息               ,因为旋转后可能有些信息被遮挡了而丢失            ,如果扩大尺寸则可以显示完整图片信息;

center: 旋转点设置   ,默认沿着中心旋转;

(3)代码示例train_transform = transforms.Compose([ transforms.Resize((224, 224)), #图片统一缩放到244*244 # 3 RandomRotation transforms.RandomRotation(90), transforms.RandomRotation((90), expand=True), #当batch_size不为1时               ,expand使用时               ,张量在第0个维度尺寸需要匹配,需要对图片缩放到统一的size transforms.RandomRotation(30, center=(0, 0)), #左上角旋转 transforms.RandomRotation(30, center=(0, 0), expand=True), #expand只可以针对中心旋转来扩展            ,无法用于左上角旋转来找回丢失的信息 transforms.ToTensor(), transforms.Normalize(norm_mean, norm_std), ])

4. 完整代码示例

# -*- coding: utf-8 -*- """ # @file name : transforms_methods_1.py # @author : tingsongyu # @date : 2019-09-11 10:08:00 # @brief : transforms方法(一) """ import os import numpy as np import torch import random from torch.utils.data import DataLoader import torchvision.transforms as transforms from tools.my_dataset import RMBDataset from PIL import Image from matplotlib import pyplot as plt def set_seed(seed=1): random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) torch.cuda.manual_seed(seed) set_seed(1) # 设置随机种子 # 参数设置 MAX_EPOCH = 10 BATCH_SIZE = 1 LR = 0.01 log_interval = 10 val_interval = 1 rmb_label = {"1": 0, "100": 1} def transform_invert(img_, transform_train): """ 将data 进行反transfrom操作 :param img_: tensor :param transform_train: torchvision.transforms :return: PIL image """ if Normalize in str(transform_train): norm_transform = list(filter(lambda x: isinstance(x, transforms.Normalize), transform_train.transforms)) mean = torch.tensor(norm_transform[0].mean, dtype=img_.dtype, device=img_.device) std = torch.tensor(norm_transform[0].std, dtype=img_.dtype, device=img_.device) img_.mul_(std[:, None, None]).add_(mean[:, None, None]) #normalize是减去均值除以标准差                  ,反操作就是乘以标准差加上均值 img_ = img_.transpose(0, 2).transpose(0, 1) # C*H*W --> H*W*C 通道变换 img_ = np.array(img_) * 255 #将0-1转换为0-255 #针对chanel是三通道还是一通道分别转换 if img_.shape[2] == 3: #RGB图像 img_ = Image.fromarray(img_.astype(uint8)).convert(RGB) #将ndarray数据转换为image elif img_.shape[2] == 1: #灰度图像 img_ = Image.fromarray(img_.astype(uint8).squeeze()) else: raise Exception("Invalid img shape, expected 1 or 3 in axis 2, but got {}!".format(img_.shape[2]) ) return img_ # ============================ step 1/5 数据 ============================ split_dir = os.path.join("..", "..", "data", "rmb_split") train_dir = os.path.join(split_dir, "train") valid_dir = os.path.join(split_dir, "valid") norm_mean = [0.485, 0.456, 0.406] norm_std = [0.229, 0.224, 0.225] train_transform = transforms.Compose([ transforms.Resize((224, 224)), #图片统一缩放到244*244 # 1 CenterCrop # transforms.CenterCrop(196), # 裁剪为196*196   ,如果是512的话         ,超出244的区域填充为黑色 # 2 RandomCrop # transforms.RandomCrop(224, padding=16), # transforms.RandomCrop(224, padding=(16, 64)), # transforms.RandomCrop(224, padding=16, fill=(255, 0, 0)), #fill=(255, 0, 0)RGB颜色 #当size大于图片尺寸                 ,即512大于244      ,pad_if_needed必须设置为True       ,否则会报错                ,其他区域会填充黑色(0         ,0     ,0) # transforms.RandomCrop(512, pad_if_needed=True), # pad_if_needed=True # transforms.RandomCrop(224, padding=64, padding_mode=edge), #边缘 # transforms.RandomCrop(224, padding=64, padding_mode=reflect), #镜像 # transforms.RandomCrop(1024, padding=1024, padding_mode=symmetric), #镜像 # 3 RandomResizedCrop # transforms.RandomResizedCrop(size=224, scale=(0.5, 0.5)), # 4 FiveCrop # transforms.FiveCrop(112), #单独使用错误               ,直接使用transforms.FiveCrop(112)会报错            ,需要跟下一行一起使用 #lamda的冒号之前是函数的输入(crops)   ,冒号之后是函数的返回值 # transforms.Lambda(lambda crops: torch.stack([(transforms.ToTensor()(crop)) for crop in crops])), #这里进行了ToTensor()               ,后面不需要执行Totensor()和Normalize               ,第114-115行 # 5 TenCrop # transforms.TenCrop(112, vertical_flip=False), # transforms.Lambda(lambda crops: torch.stack([(transforms.ToTensor()(crop)) for crop in crops])), # 1 Horizontal Flip # transforms.RandomHorizontalFlip(p=1), #执行水平翻转的概率为1 # 2 Vertical Flip # transforms.RandomVerticalFlip(p=0.5), #执行垂直翻转的概率为0.5 # 3 RandomRotation # transforms.RandomRotation(90), # transforms.RandomRotation((90), expand=True), #当batch_size不为1时,expand使用时            ,张量在第0个维度尺寸需要匹配                  ,需要对图片缩放到统一的size # transforms.RandomRotation(30, center=(0, 0)), #左上角旋转 # transforms.RandomRotation(30, center=(0, 0), expand=True), #expand只可以针对中心旋转来扩展   ,无法用于左上角旋转来找回丢失的信息 #若使用FiveCrop或TenCrop         ,以下两行需要注释掉 transforms.ToTensor(), transforms.Normalize(norm_mean, norm_std), ]) valid_transform = transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(norm_mean, norm_std) ]) # 构建MyDataset实例 train_data = RMBDataset(data_dir=train_dir, transform=train_transform) valid_data = RMBDataset(data_dir=valid_dir, transform=valid_transform) # 构建DataLoder train_loader = DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True) valid_loader = DataLoader(dataset=valid_data, batch_size=BATCH_SIZE) # ============================ step 5/5 训练 ============================ for epoch in range(MAX_EPOCH): for i, data in enumerate(train_loader): inputs, labels = data #四维可视化 #input的大小为四维:batch_size*chanel*图像宽*图像高 # B C H W img_tensor = inputs[0, ...] # C H W img = transform_invert(img_tensor, train_transform) #对transform进行逆变换                 ,可视化图片 plt.imshow(img) plt.show() plt.pause(0.5) plt.close() #五维可视化 #使用FiveCrop时inputs为五维:batch_size*ncrops*chanel*图像宽*图像高,此时ncrops=5 bs, ncrops, c, h, w = inputs.shape # for n in range(ncrops): # img_tensor = inputs[0, n, ...] # C H W # img = transform_invert(img_tensor, train_transform) # plt.imshow(img) # plt.show() # plt.pause(1)
声明:本站所有文章      ,如无特殊说明或标注       ,均为本站原创发布            。任何个人或组织                ,在未征得本站同意时         ,禁止复制                 、盗用         、采集   、发布本站内容到任何网站                  、书籍等各类媒体平台               。如若本站内容侵犯了原著者的合法权益     ,可联系我们进行处理     。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
wordpress插件赚钱(培养网站流量的利器——WordPress插件) spring依赖注入作用(如何理解spring框架中的依赖注入和控制反转?)