Skip to content

Commit a07475e

Browse files
Skeleton for keypoints tutorial
1 parent 3db0b12 commit a07475e

File tree

4 files changed

+121
-1
lines changed

4 files changed

+121
-1
lines changed

docs/source/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ def __init__(self, src_dir):
8888
"plot_transforms_e2e.py",
8989
"plot_cutmix_mixup.py",
9090
"plot_rotated_box_transforms.py",
91+
"plot_keypoints_transforms.py",
9192
"plot_custom_transforms.py",
9293
"plot_tv_tensors.py",
9394
"plot_custom_tv_tensors.py",

gallery/assets/pottery.jpg

89.8 KB
Loading

gallery/transforms/helpers.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import matplotlib.pyplot as plt
22
import torch
3-
from torchvision.utils import draw_bounding_boxes, draw_segmentation_masks
3+
from torchvision.utils import draw_bounding_boxes, draw_keypoints, draw_segmentation_masks
44
from torchvision import tv_tensors
55
from torchvision.transforms import v2
66
from torchvision.transforms.v2 import functional as F
@@ -18,6 +18,7 @@ def plot(imgs, row_title=None, bbox_width=3, **imshow_kwargs):
1818
for col_idx, img in enumerate(row):
1919
boxes = None
2020
masks = None
21+
points = None
2122
if isinstance(img, tuple):
2223
img, target = img
2324
if isinstance(target, dict):
@@ -30,6 +31,8 @@ def plot(imgs, row_title=None, bbox_width=3, **imshow_kwargs):
3031
# work with this specific format.
3132
if tv_tensors.is_rotated_bounding_format(boxes.format):
3233
boxes = v2.ConvertBoundingBoxFormat("xyxyxyxy")(boxes)
34+
elif isinstance(target, tv_tensors.KeyPoints):
35+
points = target
3336
else:
3437
raise ValueError(f"Unexpected target type: {type(target)}")
3538
img = F.to_image(img)
@@ -44,6 +47,8 @@ def plot(imgs, row_title=None, bbox_width=3, **imshow_kwargs):
4447
img = draw_bounding_boxes(img, boxes, colors="yellow", width=bbox_width)
4548
if masks is not None:
4649
img = draw_segmentation_masks(img, masks.to(torch.bool), colors=["green"] * masks.shape[0], alpha=.65)
50+
if points is not None:
51+
img = draw_keypoints(img, points, colors="red", radius=10)
4752

4853
ax = axs[row_idx, col_idx]
4954
ax.imshow(img.permute(1, 2, 0).numpy(), **imshow_kwargs)
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
"""
2+
===============================================================
3+
Transforms on Rotated Bounding Boxes
4+
===============================================================
5+
6+
This example illustrates how to define and use rotated bounding boxes.
7+
8+
.. note::
9+
Support for rotated bounding boxes was released in TorchVision 0.23 and is
10+
currently a BETA feature. We don't expect the API to change, but there may
11+
be some rare edge-cases. If you find any issues, please report them on
12+
our bug tracker: https://github.com/pytorch/vision/issues?q=is:open+is:issue
13+
14+
First, a bit of setup code:
15+
"""
16+
17+
# %%
18+
from PIL import Image
19+
from pathlib import Path
20+
import matplotlib.pyplot as plt
21+
22+
23+
import torch
24+
from torchvision.tv_tensors import KeyPoints
25+
from torchvision.transforms import v2
26+
from helpers import plot
27+
28+
plt.rcParams["figure.figsize"] = [10, 5]
29+
plt.rcParams["savefig.bbox"] = "tight"
30+
31+
# if you change the seed, make sure that the randomly-applied transforms
32+
# properly show that the image can be both transformed and *not* transformed!
33+
torch.manual_seed(0)
34+
35+
# If you're trying to run that on Colab, you can download the assets and the
36+
# helpers from https://github.com/pytorch/vision/tree/main/gallery/
37+
orig_img = Image.open(Path('../assets') / 'pottery.jpg')
38+
39+
# %%
40+
# Creating KeyPoints
41+
# -------------------------------
42+
# Key points are created by instantiating the
43+
# :class:`~torchvision.tv_tensors.KeyPoints` class.
44+
45+
46+
orig_pts = KeyPoints(
47+
[
48+
[
49+
[445, 700], # nose
50+
[320, 660],
51+
[370, 660],
52+
[420, 660], # left eye
53+
[300, 620],
54+
[420, 620], # left eyebrow
55+
[475, 665],
56+
[515, 665],
57+
[555, 655], # right eye
58+
[460, 625],
59+
[560, 600], # right eyebrow
60+
[370, 780],
61+
[450, 760],
62+
[540, 780],
63+
[450, 820], # mouth
64+
],
65+
],
66+
canvas_size=(orig_img.size[1], orig_img.size[0]),
67+
)
68+
69+
plot([(orig_img, orig_pts)])
70+
71+
# %%
72+
# Transforms illustrations
73+
# ------------------------
74+
#
75+
# Using :class:`~torchvision.transforms.RandomRotation`:
76+
rotater = v2.RandomRotation(degrees=(0, 180), expand=True)
77+
rotated_imgs = [rotater((orig_img, orig_pts)) for _ in range(4)]
78+
plot([(orig_img, orig_pts)] + rotated_imgs, bbox_width=10)
79+
80+
# %%
81+
# Using :class:`~torchvision.transforms.Pad`:
82+
padded_imgs_and_points = [
83+
v2.Pad(padding=padding)(orig_img, orig_pts)
84+
for padding in (30, 50, 100, 200)
85+
]
86+
plot([(orig_img, orig_pts)] + padded_imgs_and_points, bbox_width=10)
87+
88+
# %%
89+
# Using :class:`~torchvision.transforms.Resize`:
90+
resized_imgs = [
91+
v2.Resize(size=size)(orig_img, orig_pts)
92+
for size in (300, 500, 1000, orig_img.size)
93+
]
94+
plot([(orig_img, orig_pts)] + resized_imgs, bbox_width=5)
95+
96+
# %%
97+
# Using :class:`~torchvision.transforms.RandomPerspective`:
98+
perspective_transformer = v2.RandomPerspective(distortion_scale=0.6, p=1.0)
99+
perspective_imgs = [perspective_transformer(orig_img, orig_pts) for _ in range(4)]
100+
plot([(orig_img, orig_pts)] + perspective_imgs, bbox_width=10)
101+
102+
# %%
103+
# Using :class:`~torchvision.transforms.CenterCrop`:
104+
center_crops_and_points = [
105+
v2.CenterCrop(size=size)(orig_img, orig_pts)
106+
for size in (300, 500, 1000, orig_img.size)
107+
]
108+
plot([(orig_img, orig_pts)] + center_crops_and_points)
109+
110+
# %%
111+
# Using :class:`~torchvision.transforms.RandomRotation`:
112+
rotater = v2.RandomRotation(degrees=(0, 180))
113+
rotated_imgs = [rotater((orig_img, orig_pts)) for _ in range(4)]
114+
plot([(orig_img, orig_pts)] + rotated_imgs)

0 commit comments

Comments
 (0)