123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- import numpy as np
- import PIL
- from PIL import Image
- from PIL import ImageDraw
- from PIL import ImageFont
- from PIL import ImageColor
- def _is_legal_color(color):
- if color is None:
- return True
- if isinstance(color, str):
- return True
- return isinstance(color, (tuple, list)) and len(color) == 3
-
- def _normalize_color(color, pil_mode, swap_rgb=False):
- if color is None:
- return color
- if isinstance(color, str):
- color = ImageColor.getrgb(color)
- gray = color[0]
- if swap_rgb:
- color = (color[2], color[1], color[0])
- if pil_mode == 'L':
- color = gray
- return color
-
-
- def draw_text(image, text, position, color=(255,0,0), font=None, font_size=15):
- """Draws text on given image.
-
- Args:
- image (ndarray).
- text (str): text to be drawn.
- position (Tuple[int, int]): position where to be drawn.
- color (List[Union[str, Tuple[int, int, int]]]): text color.
- font (str): A filename or file-like object 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/`, `/System/Library/Fonts/` and `~/Library/Fonts/` on macOS.
- font_size (int): The requested font size in points.
- References:
- torchvision.utils.draw_bounding_boxes
- """
- if isinstance(image, np.ndarray):
- pil_image = Image.fromarray(image)
- elif isinstance(image, PIL.Image.Image):
- pil_image = image
- else:
- raise ValueError('Unsupported image type!')
- assert pil_image.mode in ['L', 'RGB', 'RGBA']
-
- assert _is_legal_color(color)
- color = _normalize_color(color, pil_image.mode, isinstance(image, np.ndarray))
-
- if font is None:
- font_object = ImageFont.load_default()
- else:
- font_object = ImageFont.truetype(font, size=font_size)
-
- draw = ImageDraw.Draw(pil_image)
- draw.text((position[0], position[1]), text,
- fill=color, font=font_object)
- if isinstance(image, np.ndarray):
- return np.asarray(pil_image)
- return pil_image
- def draw_bounding_boxes(image, boxes, labels=None, colors=None,
- fill=False, width=1, font=None, font_size=15):
- """Draws bounding boxes on given image.
- Args:
- image (ndarray).
- boxes (ndarray): ndarray of size (N, 4) containing bounding boxes in (xmin, ymin, xmax, ymax) format.
- 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 or labels.
- fill (bool): If `True` fills the bounding box with specified color.
- width (int): Width of bounding box.
- font (str): A filename or file-like object 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/`, `/System/Library/Fonts/` and `~/Library/Fonts/` on macOS.
- font_size (int): The requested font size in points.
- References:
- torchvision.utils.draw_bounding_boxes
- """
- if isinstance(image, np.ndarray):
- pil_image = Image.fromarray(image)
- elif isinstance(image, PIL.Image.Image):
- pil_image = image
- else:
- raise ValueError('Unsupported image type!')
- pil_image = pil_image.convert('RGB')
-
- if font is None:
- font_object = ImageFont.load_default()
- else:
- font_object = ImageFont.truetype(font, size=font_size)
- if fill:
- draw = ImageDraw.Draw(pil_image, "RGBA")
- else:
- draw = ImageDraw.Draw(pil_image)
- for i, bbox in enumerate(boxes):
- if colors is None:
- color = None
- else:
- color = colors[i]
-
- assert _is_legal_color(color)
- color = _normalize_color(color, pil_image.mode, isinstance(image, np.ndarray))
-
- if fill:
- 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)
- if labels is not None:
- margin = width + 1
- draw.text((bbox[0] + margin, bbox[1] + margin), labels[i], fill=color, font=font_object)
- if isinstance(image, np.ndarray):
- return np.asarray(pil_image)
- return pil_image
-
-
|