From db4531822c730f9dc66cf5b2434ea6e108a0b1db Mon Sep 17 00:00:00 2001 From: Aditya Oke Date: Tue, 26 Jan 2021 15:12:36 +0530 Subject: [PATCH 1/8] adds fill paramter --- torchvision/utils.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/torchvision/utils.py b/torchvision/utils.py index b6880c83f2d..4eaf1c8de83 100644 --- a/torchvision/utils.py +++ b/torchvision/utils.py @@ -143,6 +143,7 @@ def draw_bounding_boxes( boxes: torch.Tensor, labels: Optional[List[str]] = None, colors: Optional[List[Union[str, Tuple[int, int, int]]]] = None, + fill: Optional[List[Union[str, Tuple[int, int, int, int]]]] = None, width: int = 1, font: Optional[str] = None, font_size: int = 10 @@ -151,7 +152,7 @@ def draw_bounding_boxes( """ Draws bounding boxes on given image. The values of the input image should be uint8 between 0 and 255. - + Resulting Tensor should be saved as PNG image. Args: image (Tensor): Tensor of shape (C x H x W) bboxes (Tensor): Tensor of size (N, 4) containing bounding boxes in (xmin, ymin, xmax, ymax) format. Note that @@ -160,6 +161,8 @@ def draw_bounding_boxes( labels (List[str]): List containing the labels of bounding boxes. colors (List[Union[str, Tuple[int, int, int]]]): List containing the colors of bounding boxes. The colors can be represented as `str` or `Tuple[int, int, int]`. + fill (List[Union[str, Tuple[int, int, int, int]]]): List containing the colors of bounding boxes. The colors can + be represented as `str` or `Tuple[int, int, int, int]`. width (int): Width of bounding box. font (str): A filename containing a TrueType font. If the file is not found in this filename, the loader may also search in other directories, such as the `fonts/` directory on Windows or `/Library/Fonts/`, @@ -179,12 +182,13 @@ def draw_bounding_boxes( img_boxes = boxes.to(torch.int64).tolist() - draw = ImageDraw.Draw(img_to_draw) + draw = ImageDraw.Draw(img_to_draw, "RGBA") + txt_font = ImageFont.load_default() if font is None else ImageFont.truetype(font=font, size=font_size) for i, bbox in enumerate(img_boxes): color = None if colors is None else colors[i] - draw.rectangle(bbox, width=width, outline=color) + draw.rectangle(bbox, width=width, outline=color, fill=fill) if labels is not None: draw.text((bbox[0], bbox[1]), labels[i], fill=color, font=txt_font) From 1f1095b851c02fe23bf3dd9f2556eecb8b833465 Mon Sep 17 00:00:00 2001 From: Aditya Oke Date: Tue, 26 Jan 2021 15:18:52 +0530 Subject: [PATCH 2/8] small doc edit --- torchvision/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/torchvision/utils.py b/torchvision/utils.py index 4eaf1c8de83..0907d4e267e 100644 --- a/torchvision/utils.py +++ b/torchvision/utils.py @@ -161,8 +161,8 @@ def draw_bounding_boxes( labels (List[str]): List containing the labels of bounding boxes. colors (List[Union[str, Tuple[int, int, int]]]): List containing the colors of bounding boxes. The colors can be represented as `str` or `Tuple[int, int, int]`. - fill (List[Union[str, Tuple[int, int, int, int]]]): List containing the colors of bounding boxes. The colors can - be represented as `str` or `Tuple[int, int, int, int]`. + fill (List[Union[str, Tuple[int, int, int, int]]]): List containing the colors to fill bounding boxse. + The colors can be represented as `str` or `Tuple[int, int, int, int]`. width (int): Width of bounding box. font (str): A filename containing a TrueType font. If the file is not found in this filename, the loader may also search in other directories, such as the `fonts/` directory on Windows or `/Library/Fonts/`, From fdf6f76139e2bfebf4514654abbaeb4114e2fb69 Mon Sep 17 00:00:00 2001 From: Aditya Oke Date: Wed, 27 Jan 2021 10:03:31 +0530 Subject: [PATCH 3/8] Change fill to bool --- torchvision/utils.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/torchvision/utils.py b/torchvision/utils.py index 0907d4e267e..ae7326e8f2a 100644 --- a/torchvision/utils.py +++ b/torchvision/utils.py @@ -143,7 +143,7 @@ def draw_bounding_boxes( boxes: torch.Tensor, labels: Optional[List[str]] = None, colors: Optional[List[Union[str, Tuple[int, int, int]]]] = None, - fill: Optional[List[Union[str, Tuple[int, int, int, int]]]] = None, + fill: Optional[bool] = False, width: int = 1, font: Optional[str] = None, font_size: int = 10 @@ -153,6 +153,7 @@ def draw_bounding_boxes( Draws bounding boxes on given image. The values of the input image should be uint8 between 0 and 255. Resulting Tensor should be saved as PNG image. + Args: image (Tensor): Tensor of shape (C x H x W) bboxes (Tensor): Tensor of size (N, 4) containing bounding boxes in (xmin, ymin, xmax, ymax) format. Note that @@ -161,7 +162,7 @@ def draw_bounding_boxes( labels (List[str]): List containing the labels of bounding boxes. colors (List[Union[str, Tuple[int, int, int]]]): List containing the colors of bounding boxes. The colors can be represented as `str` or `Tuple[int, int, int]`. - fill (List[Union[str, Tuple[int, int, int, int]]]): List containing the colors to fill bounding boxse. + fill (bool): If true fills the bounding box with specified color The colors can be represented as `str` or `Tuple[int, int, int, int]`. width (int): Width of bounding box. font (str): A filename containing a TrueType font. If the file is not found in this filename, the loader may @@ -182,13 +183,21 @@ def draw_bounding_boxes( img_boxes = boxes.to(torch.int64).tolist() - draw = ImageDraw.Draw(img_to_draw, "RGBA") + if fill: + draw = ImageDraw.Draw(img_to_draw, "RGBA") + fill = colors + [100] + + else: + draw = ImageDraw.Draw(img_to_draw) txt_font = ImageFont.load_default() if font is None else ImageFont.truetype(font=font, size=font_size) for i, bbox in enumerate(img_boxes): color = None if colors is None else colors[i] - draw.rectangle(bbox, width=width, outline=color, fill=fill) + if fill: + draw.rectangle(bbox, width=width, outline=colors, fill=colors) + else: + draw.rectangle(bbox, width=width, outline=colors) if labels is not None: draw.text((bbox[0], bbox[1]), labels[i], fill=color, font=txt_font) From 978ad4a3d4a0804c6185d2bef496e830c7702c27 Mon Sep 17 00:00:00 2001 From: Aditya Oke Date: Wed, 27 Jan 2021 10:05:21 +0530 Subject: [PATCH 4/8] add filled --- torchvision/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/utils.py b/torchvision/utils.py index ae7326e8f2a..368d196b5c4 100644 --- a/torchvision/utils.py +++ b/torchvision/utils.py @@ -152,7 +152,7 @@ def draw_bounding_boxes( """ Draws bounding boxes on given image. The values of the input image should be uint8 between 0 and 255. - Resulting Tensor should be saved as PNG image. + If filled Resulting Tensor should be saved as PNG image. Args: image (Tensor): Tensor of shape (C x H x W) From 9956bd1657afeeaf21028f9e8af2abef955e60ef Mon Sep 17 00:00:00 2001 From: Aditya Oke Date: Wed, 27 Jan 2021 11:28:38 +0530 Subject: [PATCH 5/8] fix the bugs --- torchvision/utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/torchvision/utils.py b/torchvision/utils.py index 368d196b5c4..f984fa7c628 100644 --- a/torchvision/utils.py +++ b/torchvision/utils.py @@ -185,7 +185,6 @@ def draw_bounding_boxes( if fill: draw = ImageDraw.Draw(img_to_draw, "RGBA") - fill = colors + [100] else: draw = ImageDraw.Draw(img_to_draw) @@ -195,9 +194,10 @@ def draw_bounding_boxes( for i, bbox in enumerate(img_boxes): color = None if colors is None else colors[i] if fill: - draw.rectangle(bbox, width=width, outline=colors, fill=colors) + fill_color = color + [100] + draw.rectangle(bbox, width=width, outline=color, fill=fill_color) else: - draw.rectangle(bbox, width=width, outline=colors) + draw.rectangle(bbox, width=width, outline=color) if labels is not None: draw.text((bbox[0], bbox[1]), labels[i], fill=color, font=txt_font) From efe809e8e4324100da7af5a9fe9631a7536dc09b Mon Sep 17 00:00:00 2001 From: Aditya Oke Date: Sat, 30 Jan 2021 21:59:12 +0530 Subject: [PATCH 6/8] Fixes bugs --- test/test_utils.py | 2 +- torchvision/utils.py | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/test/test_utils.py b/test/test_utils.py index 21e2ab461d7..662ad2a0cce 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -86,7 +86,7 @@ def test_draw_boxes(self): [10, 15, 30, 35], [23, 35, 93, 95]], dtype=torch.float) labels = ["a", "b", "c", "d"] colors = ["green", "#FF00FF", (0, 255, 0), "red"] - result = utils.draw_bounding_boxes(img, boxes, labels=labels, colors=colors) + result = utils.draw_bounding_boxes(img, boxes, labels=labels, colors=colors, fill=True) path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "fakedata", "draw_boxes_util.png") if not os.path.exists(path): diff --git a/torchvision/utils.py b/torchvision/utils.py index f984fa7c628..eea55aa38ed 100644 --- a/torchvision/utils.py +++ b/torchvision/utils.py @@ -4,8 +4,7 @@ import math import warnings import numpy as np -from PIL import Image, ImageDraw -from PIL import ImageFont +from PIL import Image, ImageDraw, ImageFont, ImageColor __all__ = ["make_grid", "save_image", "draw_bounding_boxes"] @@ -152,7 +151,7 @@ def draw_bounding_boxes( """ Draws bounding boxes on given image. The values of the input image should be uint8 between 0 and 255. - If filled Resulting Tensor should be saved as PNG image. + If filled, Resulting Tensor should be saved as PNG image. Args: image (Tensor): Tensor of shape (C x H x W) @@ -162,8 +161,7 @@ def draw_bounding_boxes( labels (List[str]): List containing the labels of bounding boxes. colors (List[Union[str, Tuple[int, int, int]]]): List containing the colors of bounding boxes. The colors can be represented as `str` or `Tuple[int, int, int]`. - fill (bool): If true fills the bounding box with specified color - The colors can be represented as `str` or `Tuple[int, int, int, int]`. + fill (bool): If `True` fills the bounding box with specified color. width (int): Width of bounding box. font (str): A filename containing a TrueType font. If the file is not found in this filename, the loader may also search in other directories, such as the `fonts/` directory on Windows or `/Library/Fonts/`, @@ -192,9 +190,19 @@ def draw_bounding_boxes( txt_font = ImageFont.load_default() if font is None else ImageFont.truetype(font=font, size=font_size) for i, bbox in enumerate(img_boxes): - color = None if colors is None else colors[i] + if colors is None: + color = None + else: + color = colors[i] + if fill: - fill_color = color + [100] + if color is None: + fill_color = (255, 255, 255, 100) + elif isinstance(color, str): + # This will automatically raise Error if rgb cannot be parsed. + fill_color = ImageColor.getrgb(color) + (100,) + elif isinstance(color, Tuple): + fill_color = color + (100,) draw.rectangle(bbox, width=width, outline=color, fill=fill_color) else: draw.rectangle(bbox, width=width, outline=color) From 54d44cc3ff036540778c7101f22ba7cacbb99df1 Mon Sep 17 00:00:00 2001 From: Aditya Oke Date: Sat, 30 Jan 2021 22:14:54 +0530 Subject: [PATCH 7/8] adds test with fill param --- test/assets/fakedata/draw_boxes_util.png | Bin 490 -> 547 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/test/assets/fakedata/draw_boxes_util.png b/test/assets/fakedata/draw_boxes_util.png index e6b9286bf922d5dac64e5a083b902efa80bf857b..d64fa2f1f360fc386494b915cef0675fdee705a0 100644 GIT binary patch delta 425 zcmV;a0apI%1EU0xB!B8jL_t(|obBAfZNe}ZK;hpNb94wg2P^ax&r$Y(Q&wP(9=bvo zaSu?cs?^D|q87~iPDludo*c)qP*RDKwkcYbm(u*%o3l#WwA<|3KAaDE*`v8~4`o}1 zr{TX3<2F3}_W|6JQ>@`>aC}WV#oE8_Bf?&Fr&#wkRku0CYJa{U-j%O8D0Am5h0*nP13osTiYu8~?Y5$+) z75hC?!WPT)jdaTobQbQ@qH|WKjn0-ES(nCbXB=68O9#MMz@o9v z(^jYR*K!kl?-N#d8X}Wn0b-Mo0R}B5o<%eJYkGVb4Sg0(^Y?bi(-1HgU@YJRGUZUP T^|=_400000NkvXXu0mjfGtSU2 delta 376 zcmV-;0f+vh1nL8jB!96X`cO(Rz;5r_sNLQZ-vEW{ zbX-X^OO%{4dX-!0e(d2~bIR@)oO6HWBf6BS#JOH_zsp}gfg@RCWjJ3=Ypi8!*{kXv z>ujsK&pp4;T)J7<+}zG^%=0LB801sDr37F%$w-<%OwJ1d^n){s{ga*g_14!4MinAcrC|I*X?pR$zNyewnYH&Yoo z*f4J0SsB?lMx4N=SU;Jsk+c`QjUGHY0F%K16H37QSrz5oUCQ$4<9c~NrV(rNFNXR0 zsgEt+e4E>o)$;`g3%A;JXARouVZX_GH@AavvH*_`fU$sGV?EZ^p!;jT1wZ=23NJ&% zlidLsljQ*sljQ*sljQ*sljQ*sGK>Wn3osU7EWlWR|JMQ7Db@-8Ksvk(5n} Date: Sat, 30 Jan 2021 18:00:36 +0000 Subject: [PATCH 8/8] fix tuple bug --- .gitignore | 1 + torchvision/utils.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3c7e579c23c..e6e4e0f3728 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ gen.yml .idea/ *.orig *-checkpoint.ipynb +*.venv diff --git a/torchvision/utils.py b/torchvision/utils.py index 73c93fe3577..9ee5a0cc65c 100644 --- a/torchvision/utils.py +++ b/torchvision/utils.py @@ -200,7 +200,7 @@ def draw_bounding_boxes( elif isinstance(color, str): # This will automatically raise Error if rgb cannot be parsed. fill_color = ImageColor.getrgb(color) + (100,) - elif isinstance(color, Tuple): + elif isinstance(color, tuple): fill_color = color + (100,) draw.rectangle(bbox, width=width, outline=color, fill=fill_color) else: