Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ def __init__(self, src_dir):
"plot_transforms_illustrations.py",
"plot_transforms_e2e.py",
"plot_cutmix_mixup.py",
"plot_rotated_box_transforms.py",
"plot_custom_transforms.py",
"plot_tv_tensors.py",
"plot_custom_tv_tensors.py",
Expand Down
Binary file added gallery/assets/leaning_tower.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
108 changes: 108 additions & 0 deletions gallery/transforms/plot_rotated_box_transforms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
"""
===============================================================
Transforms on Rotated Bounding Boxes
===============================================================

Introduction.

First, some code to set everything up.
"""

# %%
from PIL import Image
from pathlib import Path
import matplotlib.pyplot as plt


import torch
from torchvision import tv_tensors
from torchvision.transforms import v2
from helpers import plot

plt.rcParams["figure.figsize"] = [10, 5]
plt.rcParams["savefig.bbox"] = "tight"

# 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)

# If you're trying to run that on Colab, you can download the assets and the
# helpers from https://github.com/pytorch/vision/tree/main/gallery/
orig_img = Image.open(Path('../assets') / 'leaning_tower.jpg')

# %%
# Rotated Bounding Boxes
# ----------------------
# Brief intro into what rotated bounding boxes are. Brief description of the
# image.

orig_box = tv_tensors.BoundingBoxes(
[
[860.0, 1100, 570, 1840, -7],
],
format="CXCYWHR",
canvas_size=(orig_img.size[1], orig_img.size[0]),
clamping_mode="hard",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should omit setting clamping_mode here, so that we illustrate the behavior of the boxes with their default clamping_mode: soft.

)
# TODO: why is this necessary?
orig_box = v2.ConvertBoundingBoxFormat("xyxyxyxy")(orig_box)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👀

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured out why, explained in code comments.


plot([(orig_img, orig_box)])

# %%
# Image Rotation
# ---------------
# We can rotate the image itself, and the already rotated bounding boxes are
# rotated appropriately.

out_img, out_box = v2.RandomRotation(degrees=(0, 180), expand=True)(orig_img, orig_box)
plot([(out_img, out_box)])

# %%
# Image Padding
# -------------
# The rotated bounding boxes also respect padding transforms.
padded_imgs_and_boxes = [
v2.Pad(padding=padding)(orig_img, orig_box) for padding in (10, 30, 50, 100)
]
plot([(orig_img, orig_box)] + padded_imgs_and_boxes)

# %%
# Image Resizing
# --------------
# The rotated bounding boxes are resized along with the image.
resized_imgs_and_boxes = [v2.Resize(size=size)(orig_img, orig_box) for size in (30, 50, 100, orig_img.size)]
plot([(orig_img, orig_box)] + resized_imgs_and_boxes)

# %%
# Image Rotation
# --------------
rotater = v2.RandomRotation(degrees=(0, 180))
rotated_imgs = [rotater((orig_img, orig_box)) for _ in range(4)]
plot([(orig_img, orig_box)] + rotated_imgs)

# %%
# Elastic Transform
# -----------------
plot([v2.ElasticTransform(alpha=250.0)(orig_img, orig_box)])

# %%
# Clamping Modes
# --------------
# Explain hard and soft, with appropriate links to documentation. Talk about
# defaults. Link to to-be-written-tutorial on mode-setting in general.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can write the tutorial on mode-setting here in this same tutorial? It might make it easier to for users to find all the relevant info in one single place. Obviously this can be done in a separate PR

soft_box = orig_box.clone()
soft_box.clamping_mode = "soft"

hard_center_crops_and_boxes = [
v2.CenterCrop(size=size)(orig_img, orig_box)
for size in (800, 1200, 2000, orig_img.size)
]

soft_center_crops_and_boxes = [
v2.CenterCrop(size=size)(orig_img, soft_box)
for size in (800, 1200, 2000, orig_img.size)
]

plot([[(orig_img, orig_box)] + hard_center_crops_and_boxes,
[(orig_img, soft_box)] + soft_center_crops_and_boxes])
Loading