Transformers 文档
ViTPose
并获得增强的文档体验
开始使用
ViTPose
概述
ViTPose 模型由 Yufei Xu、Jing Zhang、Qiming Zhang 和 Dacheng Tao 在论文 《ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation》 中提出。ViTPose 使用标准的非层级式 Vision Transformer 作为关键点估计任务的主干网络。模型顶部添加了一个简单的解码器头,用于从给定图像中预测热图。尽管模型结构简单,但在具有挑战性的 MS COCO 关键点检测基准测试中取得了最先进的结果。该模型在 《ViTPose++: Vision Transformer for Generic Body Pose Estimation》 中得到进一步改进,作者在 ViT 主干网络中采用了混合专家(MoE)模块,并增加了更多数据的预训练,进一步提升了性能。
论文摘要如下:
尽管在设计中没有考虑特定的领域知识,但普通的视觉 Transformer 在视觉识别任务中表现出色。然而,很少有研究揭示这种简单结构在姿态估计任务中的潜力。在本文中,我们通过一个名为 ViTPose 的简单基线模型,从多个方面展示了普通视觉 Transformer 在姿态估计方面的惊人能力,即模型结构的简单性、模型大小的可扩展性、训练范式的灵活性以及模型间知识的可迁移性。具体来说,ViTPose 采用普通且非层级的视觉 Transformer 作为主干网络,为给定的个人实例提取特征,并使用一个轻量级解码器进行姿态估计。利用 Transformer 的可扩展模型容量和高并行性,它可以从 1 亿参数扩展到 10 亿参数,在吞吐量和性能之间建立了一个新的帕累托前沿。此外,ViTPose 在注意力类型、输入分辨率、预训练和微调策略以及处理多种姿态任务方面非常灵活。我们还通过实验证明,大型 ViTPose 模型的知识可以通过一个简单的知识令牌轻松迁移到小型模型中。实验结果表明,我们的基本 ViTPose 模型在具有挑战性的 MS COCO 关键点检测基准测试中优于代表性方法,而最大的模型则创下了新的最先进水平。

此模型由 nielsr 和 sangbumchoi 贡献。原始代码可在此处找到。
使用技巧
ViTPose 是一种所谓的“自顶向下”关键点检测模型。这意味着,首先使用一个目标检测器,如 RT-DETR,来检测图像中的人(或其他实例)。然后,ViTPose 将裁剪后的图像作为输入,并为每个图像预测关键点。
import torch
import requests
import numpy as np
from PIL import Image
from transformers import AutoProcessor, RTDetrForObjectDetection, VitPoseForPoseEstimation
device = "cuda" if torch.cuda.is_available() else "cpu"
url = "http://images.cocodataset.org/val2017/000000000139.jpg"
image = Image.open(requests.get(url, stream=True).raw)
# ------------------------------------------------------------------------
# Stage 1. Detect humans on the image
# ------------------------------------------------------------------------
# You can choose any detector of your choice
person_image_processor = AutoProcessor.from_pretrained("PekingU/rtdetr_r50vd_coco_o365")
person_model = RTDetrForObjectDetection.from_pretrained("PekingU/rtdetr_r50vd_coco_o365", device_map=device)
inputs = person_image_processor(images=image, return_tensors="pt").to(device)
with torch.no_grad():
outputs = person_model(**inputs)
results = person_image_processor.post_process_object_detection(
outputs, target_sizes=torch.tensor([(image.height, image.width)]), threshold=0.3
)
result = results[0] # take first image results
# Human label refers 0 index in COCO dataset
person_boxes = result["boxes"][result["labels"] == 0]
person_boxes = person_boxes.cpu().numpy()
# Convert boxes from VOC (x1, y1, x2, y2) to COCO (x1, y1, w, h) format
person_boxes[:, 2] = person_boxes[:, 2] - person_boxes[:, 0]
person_boxes[:, 3] = person_boxes[:, 3] - person_boxes[:, 1]
# ------------------------------------------------------------------------
# Stage 2. Detect keypoints for each person found
# ------------------------------------------------------------------------
image_processor = AutoProcessor.from_pretrained("usyd-community/vitpose-base-simple")
model = VitPoseForPoseEstimation.from_pretrained("usyd-community/vitpose-base-simple", device_map=device)
inputs = image_processor(image, boxes=[person_boxes], return_tensors="pt").to(device)
with torch.no_grad():
outputs = model(**inputs)
pose_results = image_processor.post_process_pose_estimation(outputs, boxes=[person_boxes])
image_pose_result = pose_results[0] # results for first image
ViTPose++ 模型
最好的检查点是来自 ViTPose++ 论文的。ViTPose++ 模型在 ViT 主干网络中采用了所谓的混合专家(MoE)架构,从而获得了更好的性能。
ViTPose+ 检查点使用了 6 个专家,因此可以传递 6 个不同的数据集索引。下面提供了各个数据集索引的概述:
- 0: COCO 2017 验证集,使用在“person”类别上达到 56 AP 的目标检测器
- 1: AiC 数据集
- 2: MPII 数据集
- 3: AP-10K 数据集
- 4: APT-36K 数据集
- 5: COCO-WholeBody 数据集
在模型的前向传播中传递 dataset_index
参数,以指示批次中每个样本应使用哪些专家。使用示例如下所示:
image_processor = AutoProcessor.from_pretrained("usyd-community/vitpose-plus-base")
model = VitPoseForPoseEstimation.from_pretrained("usyd-community/vitpose-plus-base", device=device)
inputs = image_processor(image, boxes=[person_boxes], return_tensors="pt").to(device)
dataset_index = torch.tensor([0], device=device) # must be a tensor of shape (batch_size,)
with torch.no_grad():
outputs = model(**inputs, dataset_index=dataset_index)
ViTPose+ 检查点使用了 6 个专家,因此可以传递 6 个不同的数据集索引。下面提供了各个数据集索引的概述:
- 0: COCO 2017 验证集,使用在“person”类别上达到 56 AP 的目标检测器
- 1: AiC 数据集
- 2: MPII 数据集
- 3: AP-10K 数据集
- 4: APT-36K 数据集
- 5: COCO-WholeBody 数据集
可视化
要可视化各种关键点,可以使用 supervision
[库](https://github.com/roboflow/supervision)(需要 pip install supervision
)
import supervision as sv
xy = torch.stack([pose_result['keypoints'] for pose_result in image_pose_result]).cpu().numpy()
scores = torch.stack([pose_result['scores'] for pose_result in image_pose_result]).cpu().numpy()
key_points = sv.KeyPoints(
xy=xy, confidence=scores
)
edge_annotator = sv.EdgeAnnotator(
color=sv.Color.GREEN,
thickness=1
)
vertex_annotator = sv.VertexAnnotator(
color=sv.Color.RED,
radius=2
)
annotated_frame = edge_annotator.annotate(
scene=image.copy(),
key_points=key_points
)
annotated_frame = vertex_annotator.annotate(
scene=annotated_frame,
key_points=key_points
)
此外,也可以使用 OpenCV 来可视化关键点(需要 pip install opencv-python
)
import math
import cv2
def draw_points(image, keypoints, scores, pose_keypoint_color, keypoint_score_threshold, radius, show_keypoint_weight):
if pose_keypoint_color is not None:
assert len(pose_keypoint_color) == len(keypoints)
for kid, (kpt, kpt_score) in enumerate(zip(keypoints, scores)):
x_coord, y_coord = int(kpt[0]), int(kpt[1])
if kpt_score > keypoint_score_threshold:
color = tuple(int(c) for c in pose_keypoint_color[kid])
if show_keypoint_weight:
cv2.circle(image, (int(x_coord), int(y_coord)), radius, color, -1)
transparency = max(0, min(1, kpt_score))
cv2.addWeighted(image, transparency, image, 1 - transparency, 0, dst=image)
else:
cv2.circle(image, (int(x_coord), int(y_coord)), radius, color, -1)
def draw_links(image, keypoints, scores, keypoint_edges, link_colors, keypoint_score_threshold, thickness, show_keypoint_weight, stick_width = 2):
height, width, _ = image.shape
if keypoint_edges is not None and link_colors is not None:
assert len(link_colors) == len(keypoint_edges)
for sk_id, sk in enumerate(keypoint_edges):
x1, y1, score1 = (int(keypoints[sk[0], 0]), int(keypoints[sk[0], 1]), scores[sk[0]])
x2, y2, score2 = (int(keypoints[sk[1], 0]), int(keypoints[sk[1], 1]), scores[sk[1]])
if (
x1 > 0
and x1 < width
and y1 > 0
and y1 < height
and x2 > 0
and x2 < width
and y2 > 0
and y2 < height
and score1 > keypoint_score_threshold
and score2 > keypoint_score_threshold
):
color = tuple(int(c) for c in link_colors[sk_id])
if show_keypoint_weight:
X = (x1, x2)
Y = (y1, y2)
mean_x = np.mean(X)
mean_y = np.mean(Y)
length = ((Y[0] - Y[1]) ** 2 + (X[0] - X[1]) ** 2) ** 0.5
angle = math.degrees(math.atan2(Y[0] - Y[1], X[0] - X[1]))
polygon = cv2.ellipse2Poly(
(int(mean_x), int(mean_y)), (int(length / 2), int(stick_width)), int(angle), 0, 360, 1
)
cv2.fillConvexPoly(image, polygon, color)
transparency = max(0, min(1, 0.5 * (keypoints[sk[0], 2] + keypoints[sk[1], 2])))
cv2.addWeighted(image, transparency, image, 1 - transparency, 0, dst=image)
else:
cv2.line(image, (x1, y1), (x2, y2), color, thickness=thickness)
# Note: keypoint_edges and color palette are dataset-specific
keypoint_edges = model.config.edges
palette = np.array(
[
[255, 128, 0],
[255, 153, 51],
[255, 178, 102],
[230, 230, 0],
[255, 153, 255],
[153, 204, 255],
[255, 102, 255],
[255, 51, 255],
[102, 178, 255],
[51, 153, 255],
[255, 153, 153],
[255, 102, 102],
[255, 51, 51],
[153, 255, 153],
[102, 255, 102],
[51, 255, 51],
[0, 255, 0],
[0, 0, 255],
[255, 0, 0],
[255, 255, 255],
]
)
link_colors = palette[[0, 0, 0, 0, 7, 7, 7, 9, 9, 9, 9, 9, 16, 16, 16, 16, 16, 16, 16]]
keypoint_colors = palette[[16, 16, 16, 16, 16, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0]]
numpy_image = np.array(image)
for pose_result in image_pose_result:
scores = np.array(pose_result["scores"])
keypoints = np.array(pose_result["keypoints"])
# draw each point on image
draw_points(numpy_image, keypoints, scores, keypoint_colors, keypoint_score_threshold=0.3, radius=4, show_keypoint_weight=False)
# draw links
draw_links(numpy_image, keypoints, scores, keypoint_edges, link_colors, keypoint_score_threshold=0.3, thickness=1, show_keypoint_weight=False)
pose_image = Image.fromarray(numpy_image)
pose_image

资源
以下是 Hugging Face 官方和社区(以 🌎 标志)提供的资源列表,可帮助您开始使用 ViTPose。如果您有兴趣提交资源以包含在此处,请随时发起 Pull Request,我们将进行审核!资源最好能展示一些新内容,而不是重复现有资源。
VitPoseImageProcessor
class transformers.VitPoseImageProcessor
< 源 >( do_affine_transform: bool = True size: typing.Optional[dict[str, int]] = None do_rescale: bool = True rescale_factor: typing.Union[int, float] = 0.00392156862745098 do_normalize: bool = True image_mean: typing.Union[float, list[float], NoneType] = None image_std: typing.Union[float, list[float], NoneType] = None **kwargs )
参数
- do_affine_transform (
bool
, 可选, 默认为True
) — 是否对输入图像应用仿射变换。 - size (
dict[str, int]
可选, 默认为{"height" -- 256, "width": 192}
): 应用affine_transform
后图像的分辨率。仅当do_affine_transform
设置为True
时有效。可在preprocess
方法中被size
覆盖。 - do_rescale (
bool
, 可选, 默认为True
) — 是否应用缩放因子(将像素值转换为 0.0 到 1.0 之间的浮点数)。 - rescale_factor (
int
orfloat
, 可选, 默认为1/255
) — 如果缩放图像,则使用的缩放因子。可在preprocess
方法中被rescale_factor
覆盖。 - do_normalize (
bool
, 可选, 默认为True
) — 是否使用均值和标准差对输入进行归一化。 - image_mean (
list[int]
, 默认为[0.485, 0.456, 0.406]
, 可选) — 每个通道的均值序列,用于归一化图像。 - image_std (
list[int]
, 默认为[0.229, 0.224, 0.225]
, 可选) — 每个通道的标准差序列,用于归一化图像。
构造一个 VitPose 图像处理器。
preprocess
< 源 >( images: typing.Union[ForwardRef('PIL.Image.Image'), numpy.ndarray, ForwardRef('torch.Tensor'), list['PIL.Image.Image'], list[numpy.ndarray], list['torch.Tensor']] boxes: typing.Union[list[list[float]], numpy.ndarray] do_affine_transform: typing.Optional[bool] = None size: typing.Optional[dict[str, int]] = None do_rescale: typing.Optional[bool] = None rescale_factor: typing.Optional[float] = None do_normalize: typing.Optional[bool] = None image_mean: typing.Union[float, list[float], NoneType] = None image_std: typing.Union[float, list[float], NoneType] = None return_tensors: typing.Union[str, transformers.utils.generic.TensorType, NoneType] = None data_format: typing.Union[str, transformers.image_utils.ChannelDimension] = <ChannelDimension.FIRST: 'channels_first'> input_data_format: typing.Union[str, transformers.image_utils.ChannelDimension, NoneType] = None ) → BatchFeature
参数
- images (
ImageInput
) — 待预处理的图像。期望单个或一批图像,像素值范围为 0 到 255。如果传入的图像像素值在 0 和 1 之间,请设置do_rescale=False
。 - boxes (
list[list[list[float]]]
或np.ndarray
) — 每个图像的边界框列表或数组。每个框应为一个包含 4 个浮点数的列表,代表 COCO 格式的边界框坐标(左上角 x, 左上角 y, 宽度, 高度)。 - do_affine_transform (
bool
, 可选, 默认为self.do_affine_transform
) — 是否对输入图像应用仿射变换。 - size (
dict[str, int]
可选, 默认为self.size
) — 格式为{"height": h, "width": w}
的字典,指定调整大小后输出图像的尺寸。 - do_rescale (
bool
, 可选, 默认为self.do_rescale
) — 是否将图像值重新缩放到 [0 - 1] 之间。 - rescale_factor (
float
, 可选, 默认为self.rescale_factor
) — 如果do_rescale
设置为True
,则用于重新缩放图像的缩放因子。 - do_normalize (
bool
, 可选, 默认为self.do_normalize
) — 是否归一化图像。 - image_mean (
float
orlist[float]
, 可选, 默认为self.image_mean
) — 如果do_normalize
设置为True
,则使用的图像均值。 - image_std (
float
orlist[float]
, 可选, 默认为self.image_std
) — 如果do_normalize
设置为True
,则使用的图像标准差。 - return_tensors (
str
或 TensorType, 可选, 默认为'np'
) — 如果设置,将返回特定框架的张量。可接受的值有:'tf'
: 返回 TensorFlowtf.constant
对象。'pt'
: 返回 PyTorchtorch.Tensor
对象。'np'
: 返回 NumPynp.ndarray
对象。'jax'
: 返回 JAXjnp.ndarray
对象。
返回
一个具有以下字段的 BatchFeature
- pixel_values — 待输入模型的像素值,形状为 (batch_size, num_channels, height, width)。
预处理一张或一批图像。
post_process_pose_estimation
< 源 >( outputs: VitPoseEstimatorOutput boxes: typing.Union[list[list[list[float]]], numpy.ndarray] kernel_size: int = 11 threshold: typing.Optional[float] = None target_sizes: typing.Union[transformers.utils.generic.TensorType, list[tuple]] = None ) → list[list[Dict]]
参数
- outputs (
VitPoseEstimatorOutput
) — VitPoseForPoseEstimation 模型输出。 - boxes (
list[list[list[float]]]
或np.ndarray
) — 每个图像的边界框列表或数组。每个框应为一个包含 4 个浮点数的列表,代表 COCO 格式的边界框坐标(左上角 x, 左上角 y, 宽度, 高度)。 - kernel_size (
int
, 可选, 默认为 11) — 用于调制的 K 个高斯核大小。 - threshold (
float
, 可选, 默认为 None) — 用于保留目标检测预测结果的得分阈值。 - target_sizes (
torch.Tensor
orlist[tuple[int, int]]
, 可选) — 形状为(batch_size, 2)
的张量或包含批次中每个图像目标尺寸(height, width)
的元组列表。如果未设置,预测将使用默认值进行调整。
返回
list[list[Dict]]
一个字典列表,每个字典包含批次中单个图像经模型预测的关键点和边界框。
将热图转换为关键点预测,并将其变换回图像坐标系。
VitPoseConfig
class transformers.VitPoseConfig
< 源 >( backbone_config: typing.Optional[transformers.configuration_utils.PretrainedConfig] = None backbone: typing.Optional[str] = None use_pretrained_backbone: bool = False use_timm_backbone: bool = False backbone_kwargs: typing.Optional[dict] = None initializer_range: float = 0.02 scale_factor: int = 4 use_simple_decoder: bool = True **kwargs )
参数
- backbone_config (
PretrainedConfig
或dict
, 可选, 默认为VitPoseBackboneConfig()
) — 主干模型的配置。目前,仅支持 `model_type` 为 `vitpose_backbone` 的 `backbone_config`。 - backbone (
str
, 可选) — 当 `backbone_config` 为 `None` 时使用的主干名称。如果 `use_pretrained_backbone` 为 `True`,将从 timm 或 transformers 库加载相应的预训练权重。如果 `use_pretrained_backbone` 为 `False`,将加载主干的配置并用它来初始化具有随机权重的主干。 - use_pretrained_backbone (
bool
, 可选, 默认为False
) — 是否为主干使用预训练权重。 - use_timm_backbone (
bool
, 可选, 默认为False
) — 是否从 timm 库加载 `backbone`。如果为 `False`,则从 transformers 库加载主干。 - backbone_kwargs (
dict
, 可选) — 从检查点加载时传递给 AutoBackbone 的关键字参数,例如 `{'out_indices': (0, 1, 2, 3)}`。如果设置了 `backbone_config`,则不能指定此参数。 - initializer_range (
float
, 可选, 默认为 0.02) — 用于初始化所有权重矩阵的 truncated_normal_initializer 的标准差。 - scale_factor (
int
, 可选, 默认为 4) — 用于对来自 ViT 主干的特征图进行上采样的因子。 - use_simple_decoder (
bool
, 可选, 默认为True
) — 是否使用 `VitPoseSimpleDecoder` 将主干的特征图解码为热力图。否则,它使用 `VitPoseClassicDecoder`。
这是用于存储 VitPoseForPoseEstimation 配置的配置类。它用于根据指定的参数实例化一个 VitPose 模型,定义模型架构。使用默认值实例化配置将产生与 VitPose usyd-community/vitpose-base-simple 架构类似的配置。
配置对象继承自 PretrainedConfig,可用于控制模型输出。有关更多信息,请阅读 PretrainedConfig 的文档。
示例
>>> from transformers import VitPoseConfig, VitPoseForPoseEstimation
>>> # Initializing a VitPose configuration
>>> configuration = VitPoseConfig()
>>> # Initializing a model (with random weights) from the configuration
>>> model = VitPoseForPoseEstimation(configuration)
>>> # Accessing the model configuration
>>> configuration = model.config
VitPoseForPoseEstimation
class transformers.VitPoseForPoseEstimation
< 源代码 >( config: VitPoseConfig )
参数
- config (VitPoseConfig) — 包含模型所有参数的模型配置类。使用配置文件进行初始化不会加载与模型相关的权重,只会加载配置。请查阅 from_pretrained() 方法来加载模型权重。
带有姿态估计头的 VitPose 模型。
该模型继承自 PreTrainedModel。请查阅超类文档,了解该库为其所有模型实现的通用方法(例如下载或保存、调整输入嵌入大小、修剪头部等)。
该模型也是一个 PyTorch torch.nn.Module 子类。可以像常规 PyTorch 模块一样使用它,并参考 PyTorch 文档了解所有与常规用法和行为相关的事项。
forward
< 源代码 >( pixel_values: Tensor dataset_index: typing.Optional[torch.Tensor] = None flip_pairs: typing.Optional[torch.Tensor] = None labels: typing.Optional[torch.Tensor] = None output_attentions: typing.Optional[bool] = None output_hidden_states: typing.Optional[bool] = None return_dict: typing.Optional[bool] = None ) → `transformers.models.vitpose.modeling_vitpose.VitPoseEstimatorOutput` 或 `tuple(torch.FloatTensor)`
参数
- pixel_values (形状为 `(batch_size, num_channels, image_size, image_size)` 的 `torch.Tensor`) — 对应于输入图像的张量。像素值可以使用 `{image_processor_class}` 获得。详见 `{image_processor_class}.__call__` (`{processor_class}` 使用 `{image_processor_class}` 处理图像)。
- dataset_index (形状为 `(batch_size,)` 的 `torch.Tensor`) — 在主干的混合专家(MoE)块中使用的索引。
这对应于训练期间使用的数据集索引,例如,对于单个数据集,索引 0 指的是相应的数据集。对于多个数据集,索引 0 指的是数据集 A(例如 MPII),索引 1 指的是数据集 B(例如 CrowdPose)。
- flip_pairs (
torch.tensor
, 可选) — 是否镜像关键点对(例如,左耳 — 右耳)。 - labels (形状为 `(batch_size, sequence_length)` 的 `torch.Tensor`, 可选) — 用于计算掩码语言建模损失的标签。索引应在 `[0, ..., config.vocab_size]` 或 -100 之间(参见 `input_ids` 文档字符串)。索引设置为 `-100` 的标记将被忽略(屏蔽),损失仅对标签在 `[0, ..., config.vocab_size]` 范围内的标记进行计算。
- output_attentions (
bool
, 可选) — 是否返回所有注意力层的注意力张量。有关更多详细信息,请参阅返回张量下的 `attentions`。 - output_hidden_states (
bool
, 可选) — 是否返回所有层的隐藏状态。有关更多详细信息,请参阅返回张量下的 `hidden_states`。 - return_dict (
bool
, 可选) — 是否返回一个 ModelOutput 而不是一个普通的元组。
返回
`transformers.models.vitpose.modeling_vitpose.VitPoseEstimatorOutput` 或 `tuple(torch.FloatTensor)`
一个 `transformers.models.vitpose.modeling_vitpose.VitPoseEstimatorOutput` 或一个 `torch.FloatTensor` 的元组(如果传递 `return_dict=False` 或当 `config.return_dict=False` 时),包含根据配置(VitPoseConfig)和输入而不同的各种元素。
-
loss (形状为 `(1,)` 的 `torch.FloatTensor`, 可选, 当提供 `labels` 时返回) — 目前不支持损失计算。详见 https://github.com/ViTAE-Transformer/ViTPose/tree/main/mmpose/models/losses。
-
heatmaps (形状为 `(batch_size, num_keypoints, height, width)` 的 `torch.FloatTensor`) — 模型预测的热力图。
-
hidden_states (
tuple(torch.FloatTensor)
, 可选, 当传递 `output_hidden_states=True` 或当 `config.output_hidden_states=True` 时返回) — `torch.FloatTensor` 的元组(一个用于嵌入层的输出,如果模型有嵌入层,+ 每个阶段的输出各一个),形状为 `(batch_size, sequence_length, hidden_size)`。模型在每个阶段输出的隐藏状态(也称为特征图)。 -
attentions (`tuple[torch.FloatTensor, ...]`,可选,当传递 `output_attentions=True` 或当 `config.output_attentions=True` 时返回) — `torch.FloatTensor` 的元组(每层一个),形状为 `(batch_size, num_heads, sequence_length, sequence_length)`。
注意力 softmax 后的注意力权重,用于计算自注意力头中的加权平均值。
VitPoseForPoseEstimation 的 forward 方法重写了 `__call__` 特殊方法。
虽然前向传播的流程需要在此函数中定义,但之后应该调用 `Module` 实例而不是此函数,因为前者会处理前处理和后处理步骤,而后者会静默忽略它们。
示例
>>> from transformers import AutoImageProcessor, VitPoseForPoseEstimation
>>> import torch
>>> from PIL import Image
>>> import requests
>>> processor = AutoImageProcessor.from_pretrained("usyd-community/vitpose-base-simple")
>>> model = VitPoseForPoseEstimation.from_pretrained("usyd-community/vitpose-base-simple")
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
>>> image = Image.open(requests.get(url, stream=True).raw)
>>> boxes = [[[412.8, 157.61, 53.05, 138.01], [384.43, 172.21, 15.12, 35.74]]]
>>> inputs = processor(image, boxes=boxes, return_tensors="pt")
>>> with torch.no_grad():
... outputs = model(**inputs)
>>> heatmaps = outputs.heatmaps