快捷方式

旋转边界框上的变换

本示例说明如何定义和使用旋转边界框。

注意

TorchVision 0.23 中发布了对旋转边界框的支持,目前仍处于 BETA 阶段。我们预计 API 不会更改,但可能存在一些罕见的边缘情况。如果您发现任何问题,请在我们的 bug 跟踪器上报告:https://github.com/pytorch/vision/issues?q=is:open+is:issue

首先,一些设置代码

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


import torch
from torchvision.tv_tensors import BoundingBoxes
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')

创建旋转边界框

通过实例化 BoundingBoxes 类来创建旋转边界框。构造函数的 format 参数决定边界框是否为旋转的。在此实例中,我们使用 CXCYWHR BoundingBoxFormat。前两个值是边界框中心的 X 和 Y 坐标。接下来的两个值是边界框的宽度和高度,最后一个值是边界框的旋转角度(以度为单位)。

orig_box = BoundingBoxes(
    [
        [860.0, 1100, 570, 1840, -7],
    ],
    format="CXCYWHR",
    canvas_size=(orig_img.size[1], orig_img.size[0]),
)

plot([(orig_img, orig_box)], bbox_width=10)
plot rotated box transforms

变换说明

使用 RandomRotation

rotater = v2.RandomRotation(degrees=(0, 180), expand=True)
rotated_imgs = [rotater((orig_img, orig_box)) for _ in range(4)]
plot([(orig_img, orig_box)] + rotated_imgs, bbox_width=10)
plot rotated box transforms

使用 Pad

padded_imgs_and_boxes = [
    v2.Pad(padding=padding)(orig_img, orig_box)
    for padding in (30, 50, 100, 200)
]
plot([(orig_img, orig_box)] + padded_imgs_and_boxes, bbox_width=10)
plot rotated box transforms

使用 Resize

resized_imgs = [
    v2.Resize(size=size)(orig_img, orig_box)
    for size in (30, 50, 100, orig_img.size)
]
plot([(orig_img, orig_box)] + resized_imgs, bbox_width=5)
plot rotated box transforms

请注意,在像素较少的图像中看起来更大的边界框是一种伪影,而非真实情况。那仅仅是边界框边界的栅格化表示,由于我们指定了该栅格线的固定宽度,因此显得更大。例如,当图像只有 30 像素宽时,3 像素宽的线相对较大。

裁剪模式及其对变换的影响

某些变换,例如 CenterCrop,可能导致变换后的边界框部分超出变换后的(裁剪的)图像。通常,这可能发生在大多数 几何变换 上。

在这种情况下,边界框会根据其 clamping_mode 属性裁剪到变换后的图像大小。 clamping_mode 有三种值,决定了变换后边界框的裁剪方式。

  • None:不应用裁剪,边界框可能部分超出图像。

  • “hard”:边界框被裁剪到图像大小,使其所有角点都位于图像画布内。这可能会导致信息丢失,并可能导致不直观的结果。但对于某些应用程序可能是必需的,例如,如果模型不支持图像外部的边界框。

  • “soft”:这是 None 和“hard”之间的一种中间模式:边界框被裁剪,但不如“hard”模式严格。某些边界框尺寸可能仍超出图像。这是构造 BoundingBoxes 时的默认值。

注意

对于轴对齐边界框,“soft”“hard” 模式的行为相同,因为边界框始终被裁剪到图像大小。

让我们用 CenterCrop 变换来说明裁剪模式。

assert orig_box.clamping_mode == "soft"

box_hard_clamping = BoundingBoxes(orig_box, format=orig_box.format, canvas_size=orig_box.canvas_size, clamping_mode="hard")

box_no_clamping = BoundingBoxes(orig_box, format=orig_box.format, canvas_size=orig_box.canvas_size, clamping_mode=None)

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

hard_center_crops_and_boxes = [
    v2.CenterCrop(size=size)(orig_img, box_hard_clamping)
    for size in crop_sizes
]

no_clamping_center_crops_and_boxes = [
    v2.CenterCrop(size=size)(orig_img, box_no_clamping)
    for size in crop_sizes
]

plot([[(orig_img, box_hard_clamping)] + hard_center_crops_and_boxes,
      [(orig_img, orig_box)] + soft_center_crops_and_boxes,
      [(orig_img, box_no_clamping)] + no_clamping_center_crops_and_boxes],
     bbox_width=10)
plot rotated box transforms

上面的图显示了“hard”裁剪模式、“soft”模式和 None 模式,顺序依次是。虽然“soft”和 None 模式的结果图相似,但它们不会产生完全相同的裁剪边界框。未裁剪的边界框将显示尺寸偏离图像的情况。

print("boxes with soft clamping:")
print(soft_center_crops_and_boxes)
print()
print("boxes with no clamping:")
print(no_clamping_center_crops_and_boxes)
boxes with soft clamping:
[(<PIL.Image.Image image mode=RGB size=800x800 at 0x7F7F333DA6B0>, BoundingBoxes([[478.8188, 400.9185, 570.0000, 874.1443,  -7.0000]], format=BoundingBoxFormat.CXCYWHR, canvas_size=(800, 800), clamping_mode=soft)), (<PIL.Image.Image image mode=RGB size=1200x1200 at 0x7F7F333DA770>, BoundingBoxes([[ 678.9319,  600.0001,  569.9992, 1278.9989,   -7.0000]], format=BoundingBoxFormat.CXCYWHR, canvas_size=(1200, 1200), clamping_mode=soft)), (<PIL.Image.Image image mode=RGB size=2000x2000 at 0x7F7F333DA860>, BoundingBoxes([[1089.0000,  918.0000,  570.0001, 1840.0000,   -7.0000]], format=BoundingBoxFormat.CXCYWHR, canvas_size=(2000, 2000), clamping_mode=soft)), (<PIL.Image.Image image mode=RGB size=2364x1542 at 0x7F7F333DA920>, BoundingBoxes([[1260.9314,  771.0001,  570.0002, 1623.5675,   -7.0000]], format=BoundingBoxFormat.CXCYWHR, canvas_size=(1542, 2364), clamping_mode=soft))]

boxes with no clamping:
[(<PIL.Image.Image image mode=RGB size=800x800 at 0x7F7F333DA350>, BoundingBoxes([[ 489.,  318.,  570., 1840.,   -7.]], format=BoundingBoxFormat.CXCYWHR, canvas_size=(800, 800), clamping_mode=None)), (<PIL.Image.Image image mode=RGB size=1200x1200 at 0x7F7F333DA290>, BoundingBoxes([[ 689.,  518.,  570., 1840.,   -7.]], format=BoundingBoxFormat.CXCYWHR, canvas_size=(1200, 1200), clamping_mode=None)), (<PIL.Image.Image image mode=RGB size=2000x2000 at 0x7F7F333DA1A0>, BoundingBoxes([[1089.,  918.,  570., 1840.,   -7.]], format=BoundingBoxFormat.CXCYWHR, canvas_size=(2000, 2000), clamping_mode=None)), (<PIL.Image.Image image mode=RGB size=2364x1542 at 0x7F7F333DA0E0>, BoundingBoxes([[1271.,  689.,  570., 1840.,   -7.]], format=BoundingBoxFormat.CXCYWHR, canvas_size=(1542, 2364), clamping_mode=None))]

设置裁剪模式

决定应用于边界框的裁剪策略的 clamping_mode 属性可以通过多种方式设置:

  • 在使用其 BoundingBoxes 构造函数创建边界框时,如上面的示例所示。

  • 通过直接在现有实例上设置该属性,例如 boxes.clamping_mode = "hard"

  • 通过调用 SetClampingMode 变换。

另外,请记住,您始终可以通过调用 ClampBoundingBoxes() 变换来手动裁剪边界框!这是一个说明所有这些选项的示例。

t = v2.Compose([
    v2.CenterCrop(size=(800,)),  # clamps according to the current clamping_mode
                                 # attribute, in this case set by the constructor
    v2.SetClampingMode(None),  # sets the clamping_mode attribute for future transforms
    v2.Pad(padding=3),  # clamps according to the current clamping_mode
                        # i.e. ``None``
    v2.ClampBoundingBoxes(clamping_mode="soft"),  # clamps with "soft" mode.
])

out_img, out_box = t(orig_img, orig_box)
plot([(orig_img, orig_box), (out_img, out_box)], bbox_width=10)
plot rotated box transforms

脚本总运行时间: (0 分钟 6.887 秒)

由 Sphinx-Gallery 生成的画廊

文档

访问全面的 PyTorch 开发者文档

查看文档

教程

为初学者和高级开发者提供深入的教程

查看教程

资源

查找开发资源并让您的问题得到解答

查看资源