-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Refactor primitives Signed-off-by: Ashwin Vaidya <[email protected]> * Add polygon primitive Signed-off-by: Ashwin Vaidya <[email protected]> * Add docstrings Signed-off-by: Ashwin Vaidya <[email protected]> --------- Signed-off-by: Ashwin Vaidya <[email protected]>
- Loading branch information
1 parent
6e7d108
commit ae3241a
Showing
7 changed files
with
184 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
"""Primitive classes.""" | ||
|
||
# Copyright (C) 2025 Intel Corporation | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
from .bounding_box import BoundingBox | ||
from .overlay import Overlay | ||
from .polygon import Polygon | ||
from .primitive import Primitive | ||
|
||
__all__ = ["Primitive", "BoundingBox", "Overlay", "Polygon"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
"""Overlay primitive.""" | ||
|
||
# Copyright (C) 2025 Intel Corporation | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
from __future__ import annotations | ||
|
||
import numpy as np | ||
import PIL | ||
|
||
from .primitive import Primitive | ||
|
||
|
||
class Overlay(Primitive): | ||
"""Overlay primitive. | ||
Useful for XAI and Anomaly Maps. | ||
Args: | ||
image (PIL.Image | np.ndarray): Image to be overlaid. | ||
opacity (float): Opacity of the overlay. | ||
""" | ||
|
||
def __init__(self, image: PIL.Image | np.ndarray, opacity: float = 0.4) -> None: | ||
self.image = self._to_pil(image) | ||
self.opacity = opacity | ||
|
||
def _to_pil(self, image: PIL.Image | np.ndarray) -> PIL.Image: | ||
if isinstance(image, np.ndarray): | ||
return PIL.Image.fromarray(image) | ||
return image | ||
|
||
def compute(self, image: PIL.Image) -> PIL.Image: | ||
image_ = self.image.resize(image.size) | ||
return PIL.Image.blend(image, image_, self.opacity) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
"""Polygon primitive.""" | ||
|
||
# Copyright (C) 2025 Intel Corporation | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
from __future__ import annotations | ||
|
||
from typing import TYPE_CHECKING | ||
|
||
import cv2 | ||
from PIL import Image, ImageDraw | ||
|
||
from .primitive import Primitive | ||
|
||
if TYPE_CHECKING: | ||
import numpy as np | ||
|
||
|
||
class Polygon(Primitive): | ||
"""Polygon primitive. | ||
Args: | ||
points: List of points. | ||
mask: Mask to draw the polygon. | ||
color: Color of the polygon. | ||
Examples: | ||
>>> polygon = Polygon(points=[(10, 10), (100, 10), (100, 100), (10, 100)], color="red") | ||
>>> polygon = Polygon(mask=mask, color="red") | ||
>>> polygon.compute(image).save("polygon.jpg") | ||
>>> polygon = Polygon(mask=mask, color="red") | ||
>>> polygon.compute(image).save("polygon.jpg") | ||
""" | ||
|
||
def __init__( | ||
self, | ||
points: list[tuple[int, int]] | None = None, | ||
mask: np.ndarray | None = None, | ||
color: str | tuple[int, int, int] = "blue", | ||
) -> None: | ||
self.points = self._get_points(points, mask) | ||
self.color = color | ||
|
||
def _get_points(self, points: list[tuple[int, int]] | None, mask: np.ndarray | None) -> list[tuple[int, int]]: | ||
"""Get points from either points or mask. | ||
Note: | ||
Either points or mask should be provided. | ||
Args: | ||
points: List of points. | ||
mask: Mask to draw the polygon. | ||
Returns: | ||
List of points. | ||
""" | ||
if points is not None and mask is not None: | ||
msg = "Either points or mask should be provided, not both." | ||
raise ValueError(msg) | ||
if points is not None: | ||
points_ = points | ||
elif mask is not None: | ||
points_ = self._get_points_from_mask(mask) | ||
else: | ||
msg = "Either points or mask should be provided." | ||
raise ValueError(msg) | ||
return points_ | ||
|
||
def _get_points_from_mask(self, mask: np.ndarray) -> list[tuple[int, int]]: | ||
"""Get points from mask. | ||
Args: | ||
mask: Mask to draw the polygon. | ||
Returns: | ||
List of points. | ||
""" | ||
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) | ||
points_ = contours[0].squeeze().tolist() | ||
return [tuple(point) for point in points_] | ||
|
||
def compute(self, image: Image) -> Image: | ||
"""Compute the polygon. | ||
Args: | ||
image: Image to draw the polygon on. | ||
Returns: | ||
Image with the polygon drawn on it. | ||
""" | ||
draw = ImageDraw.Draw(image) | ||
draw.polygon(self.points, fill=self.color) | ||
return image |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
"""Base class for primitives.""" | ||
|
||
# Copyright (C) 2025 Intel Corporation | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
from __future__ import annotations | ||
|
||
from abc import ABC, abstractmethod | ||
from typing import TYPE_CHECKING | ||
|
||
if TYPE_CHECKING: | ||
import PIL | ||
|
||
|
||
class Primitive(ABC): | ||
"""Base class for primitives.""" | ||
|
||
@abstractmethod | ||
def compute(self, image: PIL.Image) -> PIL.Image: | ||
"""Compute the primitive.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters