plot_transforms_illustrations.py 11.7 KB
Newer Older
1
2
3
4
5
"""
==========================
Illustration of transforms
==========================

Nicolas Hug's avatar
Nicolas Hug committed
6
.. note::
7
8
    Try on `collab <https://colab.research.google.com/github/pytorch/vision/blob/gh-pages/main/_generated_ipynb_notebooks/plot_transforms_illustrations.ipynb>`_
    or :ref:`go to the end <sphx_glr_download_auto_examples_transforms_plot_transforms_illustrations.py>` to download the full example code.
Nicolas Hug's avatar
Nicolas Hug committed
9

10
11
This example illustrates some of the various transforms available in :ref:`the
torchvision.transforms.v2 module <transforms>`.
12
"""
13
# %%
14

15
16
# sphinx_gallery_thumbnail_path = "../../gallery/assets/transforms_thumbnail.png"

17
18
19
20
from PIL import Image
from pathlib import Path
import matplotlib.pyplot as plt

21
import torch
22
from torchvision.transforms import v2
23

24
plt.rcParams["savefig.bbox"] = 'tight'
25

26
27
28
29
# if you change the seed, make sure that the randomly-applied transforms
# properly show that the image can be both transformed and *not* transformed!
torch.manual_seed(0)

30
31
32
33
# If you're trying to run that on collab, you can download the assets and the
# helpers from https://github.com/pytorch/vision/tree/main/gallery/
from helpers import plot
orig_img = Image.open(Path('../assets') / 'astronaut.jpg')
Philip Meier's avatar
Philip Meier committed
34

35
# %%
36
37
38
39
40
41
# Geometric Transforms
# --------------------
# Geometric image transformation refers to the process of altering the geometric properties of an image,
# such as its shape, size, orientation, or position.
# It involves applying mathematical operations to the image pixels or coordinates to achieve the desired transformation.
#
42
# Pad
43
# ~~~
44
45
# The :class:`~torchvision.transforms.Pad` transform
# (see also :func:`~torchvision.transforms.functional.pad`)
46
# pads all image borders with some pixel values.
47
48
padded_imgs = [v2.Pad(padding=padding)(orig_img) for padding in (3, 10, 30, 50)]
plot([orig_img] + padded_imgs)
49

50
# %%
51
# Resize
52
# ~~~~~~
53
54
55
# The :class:`~torchvision.transforms.Resize` transform
# (see also :func:`~torchvision.transforms.functional.resize`)
# resizes an image.
56
57
resized_imgs = [v2.Resize(size=size)(orig_img) for size in (30, 50, 100, orig_img.size)]
plot([orig_img] + resized_imgs)
58

59
# %%
60
# CenterCrop
61
# ~~~~~~~~~~
62
63
64
# The :class:`~torchvision.transforms.CenterCrop` transform
# (see also :func:`~torchvision.transforms.functional.center_crop`)
# crops the given image at the center.
65
66
center_crops = [v2.CenterCrop(size=size)(orig_img) for size in (30, 50, 100, orig_img.size)]
plot([orig_img] + center_crops)
67

68
# %%
69
# FiveCrop
70
# ~~~~~~~~
71
72
73
# The :class:`~torchvision.transforms.FiveCrop` transform
# (see also :func:`~torchvision.transforms.functional.five_crop`)
# crops the given image into four corners and the central crop.
74
75
(top_left, top_right, bottom_left, bottom_right, center) = v2.FiveCrop(size=(100, 100))(orig_img)
plot([orig_img] + [top_left, top_right, bottom_left, bottom_right, center])
76

77
# %%
78
79
# RandomPerspective
# ~~~~~~~~~~~~~~~~~
80
81
82
# The :class:`~torchvision.transforms.RandomPerspective` transform
# (see also :func:`~torchvision.transforms.functional.perspective`)
# performs random perspective transform on an image.
83
perspective_transformer = v2.RandomPerspective(distortion_scale=0.6, p=1.0)
84
perspective_imgs = [perspective_transformer(orig_img) for _ in range(4)]
85
plot([orig_img] + perspective_imgs)
86

87
# %%
88
# RandomRotation
89
# ~~~~~~~~~~~~~~
90
91
92
# The :class:`~torchvision.transforms.RandomRotation` transform
# (see also :func:`~torchvision.transforms.functional.rotate`)
# rotates an image with random angle.
93
rotater = v2.RandomRotation(degrees=(0, 180))
94
rotated_imgs = [rotater(orig_img) for _ in range(4)]
95
plot([orig_img] + rotated_imgs)
96

97
# %%
98
# RandomAffine
99
# ~~~~~~~~~~~~
100
101
102
# The :class:`~torchvision.transforms.RandomAffine` transform
# (see also :func:`~torchvision.transforms.functional.affine`)
# performs random affine transform on an image.
103
affine_transfomer = v2.RandomAffine(degrees=(30, 70), translate=(0.1, 0.3), scale=(0.5, 0.75))
104
affine_imgs = [affine_transfomer(orig_img) for _ in range(4)]
105
plot([orig_img] + affine_imgs)
106

107
# %%
108
109
110
111
112
113
# ElasticTransform
# ~~~~~~~~~~~~~~~~
# The :class:`~torchvision.transforms.ElasticTransform` transform
# (see also :func:`~torchvision.transforms.functional.elastic_transform`)
# Randomly transforms the morphology of objects in images and produces a
# see-through-water-like effect.
114
elastic_transformer = v2.ElasticTransform(alpha=250.0)
115
transformed_imgs = [elastic_transformer(orig_img) for _ in range(2)]
116
plot([orig_img] + transformed_imgs)
117

118
# %%
119
# RandomCrop
120
# ~~~~~~~~~~
121
122
123
# The :class:`~torchvision.transforms.RandomCrop` transform
# (see also :func:`~torchvision.transforms.functional.crop`)
# crops an image at a random location.
124
cropper = v2.RandomCrop(size=(128, 128))
125
crops = [cropper(orig_img) for _ in range(4)]
126
plot([orig_img] + crops)
127

128
# %%
129
# RandomResizedCrop
130
# ~~~~~~~~~~~~~~~~~
131
132
133
134
# The :class:`~torchvision.transforms.RandomResizedCrop` transform
# (see also :func:`~torchvision.transforms.functional.resized_crop`)
# crops an image at a random location, and then resizes the crop to a given
# size.
135
resize_cropper = v2.RandomResizedCrop(size=(32, 32))
136
resized_crops = [resize_cropper(orig_img) for _ in range(4)]
137
plot([orig_img] + resized_crops)
138

139
# %%
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# Photometric Transforms
# ----------------------
# Photometric image transformation refers to the process of modifying the photometric properties of an image,
# such as its brightness, contrast, color, or tone.
# These transformations are applied to change the visual appearance of an image
# while preserving its geometric structure.
#
# Except :class:`~torchvision.transforms.Grayscale`, the following transforms are random,
# which means that the same transform
# instance will produce different result each time it transforms a given image.
#
# Grayscale
# ~~~~~~~~~
# The :class:`~torchvision.transforms.Grayscale` transform
# (see also :func:`~torchvision.transforms.functional.to_grayscale`)
# converts an image to grayscale
156
157
gray_img = v2.Grayscale()(orig_img)
plot([orig_img, gray_img], cmap='gray')
158

159
# %%
160
161
162
163
# ColorJitter
# ~~~~~~~~~~~
# The :class:`~torchvision.transforms.ColorJitter` transform
# randomly changes the brightness, contrast, saturation, hue, and other properties of an image.
164
165
166
jitter = v2.ColorJitter(brightness=.5, hue=.3)
jittered_imgs = [jitter(orig_img) for _ in range(4)]
plot([orig_img] + jittered_imgs)
167

168
# %%
169
170
171
172
173
# GaussianBlur
# ~~~~~~~~~~~~
# The :class:`~torchvision.transforms.GaussianBlur` transform
# (see also :func:`~torchvision.transforms.functional.gaussian_blur`)
# performs gaussian blur transform on an image.
174
blurrer = v2.GaussianBlur(kernel_size=(5, 9), sigma=(0.1, 5.))
175
blurred_imgs = [blurrer(orig_img) for _ in range(4)]
176
plot([orig_img] + blurred_imgs)
177

178
# %%
179
180
181
182
183
# RandomInvert
# ~~~~~~~~~~~~
# The :class:`~torchvision.transforms.RandomInvert` transform
# (see also :func:`~torchvision.transforms.functional.invert`)
# randomly inverts the colors of the given image.
184
inverter = v2.RandomInvert()
185
invertered_imgs = [inverter(orig_img) for _ in range(4)]
186
plot([orig_img] + invertered_imgs)
187

188
# %%
189
190
191
192
193
194
# RandomPosterize
# ~~~~~~~~~~~~~~~
# The :class:`~torchvision.transforms.RandomPosterize` transform
# (see also :func:`~torchvision.transforms.functional.posterize`)
# randomly posterizes the image by reducing the number of bits
# of each color channel.
195
posterizer = v2.RandomPosterize(bits=2)
196
posterized_imgs = [posterizer(orig_img) for _ in range(4)]
197
plot([orig_img] + posterized_imgs)
198

199
# %%
200
201
202
203
204
205
# RandomSolarize
# ~~~~~~~~~~~~~~
# The :class:`~torchvision.transforms.RandomSolarize` transform
# (see also :func:`~torchvision.transforms.functional.solarize`)
# randomly solarizes the image by inverting all pixel values above
# the threshold.
206
solarizer = v2.RandomSolarize(threshold=192.0)
207
solarized_imgs = [solarizer(orig_img) for _ in range(4)]
208
plot([orig_img] + solarized_imgs)
209

210
# %%
211
212
213
214
215
# RandomAdjustSharpness
# ~~~~~~~~~~~~~~~~~~~~~
# The :class:`~torchvision.transforms.RandomAdjustSharpness` transform
# (see also :func:`~torchvision.transforms.functional.adjust_sharpness`)
# randomly adjusts the sharpness of the given image.
216
sharpness_adjuster = v2.RandomAdjustSharpness(sharpness_factor=2)
217
sharpened_imgs = [sharpness_adjuster(orig_img) for _ in range(4)]
218
plot([orig_img] + sharpened_imgs)
219

220
# %%
221
222
223
224
225
# RandomAutocontrast
# ~~~~~~~~~~~~~~~~~~
# The :class:`~torchvision.transforms.RandomAutocontrast` transform
# (see also :func:`~torchvision.transforms.functional.autocontrast`)
# randomly applies autocontrast to the given image.
226
autocontraster = v2.RandomAutocontrast()
227
autocontrasted_imgs = [autocontraster(orig_img) for _ in range(4)]
228
plot([orig_img] + autocontrasted_imgs)
229

230
# %%
231
232
233
234
235
# RandomEqualize
# ~~~~~~~~~~~~~~
# The :class:`~torchvision.transforms.RandomEqualize` transform
# (see also :func:`~torchvision.transforms.functional.equalize`)
# randomly equalizes the histogram of the given image.
236
equalizer = v2.RandomEqualize()
237
equalized_imgs = [equalizer(orig_img) for _ in range(4)]
238
plot([orig_img] + equalized_imgs)
239

240
# %%
241
242
243
244
245
# Augmentation Transforms
# -----------------------
# The following transforms are combinations of multiple transforms,
# either geometric or photometric, or both.
#
246
247
248
249
250
# AutoAugment
# ~~~~~~~~~~~
# The :class:`~torchvision.transforms.AutoAugment` transform
# automatically augments data based on a given auto-augmentation policy.
# See :class:`~torchvision.transforms.AutoAugmentPolicy` for the available policies.
251
252
policies = [v2.AutoAugmentPolicy.CIFAR10, v2.AutoAugmentPolicy.IMAGENET, v2.AutoAugmentPolicy.SVHN]
augmenters = [v2.AutoAugment(policy) for policy in policies]
253
254
255
256
257
imgs = [
    [augmenter(orig_img) for _ in range(4)]
    for augmenter in augmenters
]
row_title = [str(policy).split('.')[-1] for policy in policies]
258
plot([[orig_img] + row for row in imgs], row_title=row_title)
259

260
# %%
261
262
# RandAugment
# ~~~~~~~~~~~
263
# The :class:`~torchvision.transforms.RandAugment` is an alternate version of AutoAugment.
264
augmenter = v2.RandAugment()
265
imgs = [augmenter(orig_img) for _ in range(4)]
266
plot([orig_img] + imgs)
267

268
# %%
269
270
# TrivialAugmentWide
# ~~~~~~~~~~~~~~~~~~
271
272
273
# The :class:`~torchvision.transforms.TrivialAugmentWide` is an alternate implementation of AutoAugment.
# However, instead of transforming an image multiple times, it transforms an image only once
# using a random transform from a given list with a random strength number.
274
augmenter = v2.TrivialAugmentWide()
275
imgs = [augmenter(orig_img) for _ in range(4)]
276
plot([orig_img] + imgs)
277

278
# %%
279
280
# AugMix
# ~~~~~~
281
# The :class:`~torchvision.transforms.AugMix` transform interpolates between augmented versions of an image.
282
augmenter = v2.AugMix()
283
imgs = [augmenter(orig_img) for _ in range(4)]
284
plot([orig_img] + imgs)
285

286
# %%
287
# Randomly-applied Transforms
288
289
# ---------------------------
#
290
291
292
# The following transforms are randomly-applied given a probability ``p``.  That is, given ``p = 0.5``,
# there is a 50% chance to return the original image, and a 50% chance to return the transformed image,
# even when called with the same transform instance!
293
#
294
# RandomHorizontalFlip
295
# ~~~~~~~~~~~~~~~~~~~~
296
297
298
# The :class:`~torchvision.transforms.RandomHorizontalFlip` transform
# (see also :func:`~torchvision.transforms.functional.hflip`)
# performs horizontal flip of an image, with a given probability.
299
hflipper = v2.RandomHorizontalFlip(p=0.5)
300
transformed_imgs = [hflipper(orig_img) for _ in range(4)]
301
plot([orig_img] + transformed_imgs)
302

303
# %%
304
# RandomVerticalFlip
305
# ~~~~~~~~~~~~~~~~~~
306
307
308
# The :class:`~torchvision.transforms.RandomVerticalFlip` transform
# (see also :func:`~torchvision.transforms.functional.vflip`)
# performs vertical flip of an image, with a given probability.
309
vflipper = v2.RandomVerticalFlip(p=0.5)
310
transformed_imgs = [vflipper(orig_img) for _ in range(4)]
311
plot([orig_img] + transformed_imgs)
312

313
# %%
314
# RandomApply
315
# ~~~~~~~~~~~
316
# The :class:`~torchvision.transforms.RandomApply` transform
317
# randomly applies a list of transforms, with a given probability.
318
applier = v2.RandomApply(transforms=[v2.RandomCrop(size=(64, 64))], p=0.5)
319
transformed_imgs = [applier(orig_img) for _ in range(4)]
320
plot([orig_img] + transformed_imgs)