快捷方式

旋转边界框的变换

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

注意

旋转边界框支持已在 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 0x7F37534A3670>, 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 0x7F37534A3220>, 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 0x7F37534A8AC0>, 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 0x7F37534A8B80>, 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 0x7F37534A8F10>, 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 0x7F37534AA7D0>, 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 0x7F37534AA8C0>, 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 0x7F37534AA020>, 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.780 秒)

由 Sphinx-Gallery 生成的画廊

文档

访问全面的 PyTorch 开发者文档

查看文档

教程

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

查看教程

资源

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

查看资源