-
Notifications
You must be signed in to change notification settings - Fork 7.1k
Description
🚀 The feature
I propose an optional key-point visibility flag for ~torchvision.utils.draw_keypoints()
, to be able to draw human skeletons with key-points that are not set / visible.
If a key point is marked as invisible, the "dot" and the corresponding connection(s) in the connectivity
/ skeleton will not be printed for this person on this image. Other people on the same image (num_instances
>1) can still have the full skeleton or another set of visible joints.
The visibility
input can either be a torch.BoolTensor
(or any other Callable[bool]
) with the same number of entries K
as the keypoints
tensor, describing the visibility of each respective key point. If num_instances
is bigger than one, there should either be a tensor of shape [num_instances, K]
describing every person individually, or one of shape [K]
describing all instances within this image at once.
The visibility
should be optional and therefore be True
/ torch.ones((num_instances, K))
by default.
Motivation, pitch
The current issue arises when key point coordinates are set to the origin, e.g., if they are not visible, not found, or otherwise not available.
Lets have a look at the example showing the possibilities of draw_keypoints()
over at the docs.
Given the image of the skateboarder, let some (other) model predict the key-point- or joint-coordinates as (x, y, visibility)
, obtaining the following result:
>>> print(new_keypoints)
tensor([[[208.0176, 214.2409, 1.0000],
[ 0.0000, 0.0000, 0.0000],
[197.8246, 210.6392, 1.0000],
[ 0.0000, 0.0000, 0.0000],
[178.6378, 217.8425, 1.0000],
[221.2086, 253.8591, 1.0000],
[160.6502, 269.4662, 1.0000],
[243.9929, 304.2822, 1.0000],
[138.4654, 328.8935, 1.0000],
[277.5698, 340.8990, 1.0000],
[153.4551, 374.5145, 1.0000],
[ 0.0000, 0.0000, 0.0000],
[226.0053, 370.3125, 1.0000],
[221.8081, 455.5516, 1.0000],
[273.9723, 448.9486, 1.0000],
[193.6275, 546.1933, 1.0000],
[273.3727, 545.5930, 1.0000]]])
This is the result of the example, just that the left_eye
, left_ear
, and left_hip
are annotated as "not visible" with key point coordinates as (0, 0)
.
Plotting this result shows three lines connecting the skateboarder with the origin, which doesn't look good. On the left is the original image, on the right the one using new_keypoints
which has invisible key points.
Now imagine how that looks for other skeleton structures, like Halpe-FullBody (136 key points) or COCO-WholeBody (133 key points)...
Alternatives
It is possible to remove the "invisible" key points from the the skeleton, by updating the skeleton for every image and using something like:
invisible_indices = torch.argwhere(new_keypoints[0,:,2] == 0)
custom_connect_skeleton = [
link for link in custom_connect_skeleton if not any(idx in link for idx in invisible_indices)
]
draw_keypoints(person_int, new_keypoints, connectivity=custom_connect_skeleton, ...)
But the "dots" are still printed in the upper left corner (see below), and the whole process is fairly cumbersome. That's because now the skeleton of every human has to be analysed and drawn seperately, due to the fact that the skeletons of different persons might have different exclusions and draw_keypoints()
only accepts one connectivity for all instances.
Therefore, a second alternative would be to allow passing multiple connectivities, one for each instance. But that still doesn't solve the drawn "dot"s problem and feels less intuitive than the proposed approach.
Additional context
This image is taken from the PoseTrack21 dataset, and shows how a full body skeleton fails when only the upper body gets detected by the bounding box. These are the original annotated key points within the annotated bounding box of the dataset. (Image Source, not publically available: PoseTrack21/images/val/010516_mpii_test/000048.jpg)