Skip to content

Image

Chitra dataclass

Ultimate image utility class.

  1. Load image from file, web url, numpy or bytes
  2. Plot image
  3. Draw bounding boxes

Parameters:

Name Type Description Default
data Any

numpy, url, filelike

required
bboxes Optional[List] None
labels Optional[List] None
box_format Optional[str] 'XYXY'
cache[bool]

Whether to cache downloaded image

required
Source code in chitra/image/image.py
class Chitra:
    """Ultimate image utility class.

    1. Load image from file, web url, numpy or bytes
    2. Plot image
    3. Draw bounding boxes

    Args:
        data: numpy, url, filelike
        bboxes:
        labels:
        box_format:
        cache[bool]: Whether to cache downloaded image
    """

    data: Any
    bboxes: Optional[BoundingBoxes] = None
    labels: Optional[List] = None

    def __init__(
        self,
        data: Any,
        bboxes: Optional[List] = None,
        labels: Optional[List] = None,
        box_format: Optional[str] = BoundingBoxes.CORNER,
        cache: bool = False,
    ) -> None:
        self.image = self._load_image(data, cache=cache)
        self.bboxes = BoundingBoxes(bboxes, labels, box_format=box_format)

    @staticmethod
    def _load_image(data: DATA_FORMATS, cache: bool):
        if isinstance(data, Image.Image):
            return data

        if isinstance(data, bytes):
            return Image.open(io.BytesIO(data))

        if isinstance(data, str):
            if data.startswith("http"):
                image = _url_to_image(data, cache)

            else:
                image = Image.open(data)

        elif isinstance(data, np.ndarray):
            image = Image.fromarray(data)

        else:
            raise UserWarning("unable to load image!")

        return image

    def numpy(self):
        return np.asarray(self.image)

    @property
    def shape(self):
        return self.numpy().shape

    @property
    def size(self):
        return self.image.size

    def imshow(self, cmap=plt.cm.Blues, **kwargs):
        plt.imshow(self.numpy(), cmap, **kwargs)

    def draw_boxes(
        self,
        marker_size: int = 2,
        color=(0, 255, 0),
    ):
        if self.bboxes is None:
            raise UserWarning("bboxes is None")

        bbox_on_image = self.bboxes.get_bounding_boxes_on_image(self.shape)
        return bbox_on_image.draw_on_image(self.numpy()[..., :3], color=color, size=marker_size)

    def resize(self, *args, **kwargs) -> Image.Image:
        """
        Calls PIL.Image.resize method and passes the arguments
        Args:
            *args:
            **kwargs:

        Returns:
            resized PIL.Image
        """
        self.image = self.image.resize(*args, **kwargs)
        return self.image

    def resize_image_with_bbox(self, size: List[int]):
        """Resize both image and the bounding boxes"""
        old_size = self.shape
        self.image = self.image.resize(size)
        self.bboxes.resize_with_image(old_size, self.numpy())
        return self.image, self.bboxes

resize(self, *args, **kwargs)

Calls PIL.Image.resize method and passes the arguments

Parameters:

Name Type Description Default
*args ()
**kwargs {}

Returns:

Type Description
Image

resized PIL.Image

Source code in chitra/image/image.py
def resize(self, *args, **kwargs) -> Image.Image:
    """
    Calls PIL.Image.resize method and passes the arguments
    Args:
        *args:
        **kwargs:

    Returns:
        resized PIL.Image
    """
    self.image = self.image.resize(*args, **kwargs)
    return self.image

resize_image_with_bbox(self, size)

Resize both image and the bounding boxes

Source code in chitra/image/image.py
def resize_image_with_bbox(self, size: List[int]):
    """Resize both image and the bounding boxes"""
    old_size = self.shape
    self.image = self.image.resize(size)
    self.bboxes.resize_with_image(old_size, self.numpy())
    return self.image, self.bboxes

Last update: December 5, 2021