From 764c5e54f98a3536072f8d4ae863d91049f4df0f Mon Sep 17 00:00:00 2001 From: LEv145 Date: Thu, 6 Apr 2023 22:31:08 +0200 Subject: [PATCH] v 2.1.1 Modular utils Typo `create_image_grid_by_columns` -> `create_images_grid_by_columns` Typo `create_image_grid_by_rows` -> `create_images_grid_by_rows` --- src/nodes/images_grid.py | 8 ++--- src/utils.py | 53 ----------------------------- src/utils/__init__.py | 5 +++ src/utils/grid_annotations.py | 6 ++++ src/utils/images_grid.py | 64 +++++++++++++++++++++++++++++++++++ src/utils/tensor_convert.py | 13 +++++++ 6 files changed, 92 insertions(+), 57 deletions(-) delete mode 100644 src/utils.py create mode 100644 src/utils/__init__.py create mode 100644 src/utils/grid_annotations.py create mode 100644 src/utils/images_grid.py create mode 100644 src/utils/tensor_convert.py diff --git a/src/nodes/images_grid.py b/src/nodes/images_grid.py index aae0184..4bf1cfc 100644 --- a/src/nodes/images_grid.py +++ b/src/nodes/images_grid.py @@ -4,8 +4,8 @@ from ..base import BaseNode, Image from ..utils import ( tensor_to_pillow, pillow_to_tensor, - create_image_grid_by_columns, - create_image_grid_by_rows, + create_images_grid_by_columns, + create_images_grid_by_rows, ) @@ -36,7 +36,7 @@ class ImagesGridByColumnsNode(BaseImagesGridNode): return cls._create_input_types("max_columns") def execute(self, images: Image, **kw) -> tuple[Image]: - return self._create_execute(images, create_image_grid_by_columns, kw) + return self._create_execute(images, create_images_grid_by_columns, kw) class ImagesGridByRowsNode(BaseImagesGridNode): @@ -45,4 +45,4 @@ class ImagesGridByRowsNode(BaseImagesGridNode): return cls._create_input_types("max_rows") def execute(self, images: Image, **kw) -> tuple[Image]: - return self._create_execute(images, create_image_grid_by_rows, kw) + return self._create_execute(images, create_images_grid_by_rows, kw) diff --git a/src/utils.py b/src/utils.py deleted file mode 100644 index 9f8e223..0000000 --- a/src/utils.py +++ /dev/null @@ -1,53 +0,0 @@ -import typing as t - -import torch -import numpy as np -from PIL import Image - - -def tensor_to_pillow(image): - return Image.fromarray(np.clip(255. * image.cpu().numpy().squeeze(), 0, 255).astype(np.uint8)) - - -def pillow_to_tensor(image): - return torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0) - - -def create_image_grid_by_columns( - images: t.List[Image.Image], - gap: int, - max_columns: int, -) -> Image.Image: - max_rows = (len(images) + max_columns - 1) // max_columns - return create_image_grid(images=images, gap=gap, max_columns=max_columns, max_rows=max_rows) - - -def create_image_grid_by_rows( - images: t.List[Image.Image], - gap: int, - max_rows: int, -) -> Image.Image: - max_columns = (len(images) + max_rows - 1) // max_rows - return create_image_grid(images=images, gap=gap, max_columns=max_columns, max_rows=max_rows) - - -def create_image_grid( - images: t.List[Image.Image], - gap: int, - max_columns: int, - max_rows: int, -) -> Image.Image: - size = images[0].size - - width = size[0] * max_columns + (max_columns - 1) * gap - height = size[1] * max_rows + (max_rows - 1) * gap - - grid_image = Image.new("RGB", (width, height), color="white") - - for i, image in enumerate(images): - x = (i % max_columns) * (size[0] + gap) - y = (i // max_columns) * (size[1] + gap) - - grid_image.paste(image, (x, y)) - - return grid_image diff --git a/src/utils/__init__.py b/src/utils/__init__.py new file mode 100644 index 0000000..83ae01c --- /dev/null +++ b/src/utils/__init__.py @@ -0,0 +1,5 @@ +from .images_grid import ( + create_images_grid_by_columns, + create_images_grid_by_rows, +) +from .tensor_convert import tensor_to_pillow, pillow_to_tensor diff --git a/src/utils/grid_annotations.py b/src/utils/grid_annotations.py new file mode 100644 index 0000000..65acf73 --- /dev/null +++ b/src/utils/grid_annotations.py @@ -0,0 +1,6 @@ +from __future__ import annotations + +import typing as t + + +def create_grid_annotations() -> None: ... diff --git a/src/utils/images_grid.py b/src/utils/images_grid.py new file mode 100644 index 0000000..9b2e8e3 --- /dev/null +++ b/src/utils/images_grid.py @@ -0,0 +1,64 @@ +import typing as t + +from PIL import Image, ImageDraw, ImageFont + + +def create_images_grid_by_columns( + images: t.List[Image.Image], + gap: int, + max_columns: int, +) -> Image.Image: + max_rows = (len(images) + max_columns - 1) // max_columns + return _create_images_grid(images=images, gap=gap, max_columns=max_columns, max_rows=max_rows) + + +def create_images_grid_by_rows( + images: t.List[Image.Image], + gap: int, + max_rows: int, +) -> Image.Image: + max_columns = (len(images) + max_rows - 1) // max_rows + return _create_images_grid(images=images, gap=gap, max_columns=max_columns, max_rows=max_rows) + + +def _create_images_grid( + images: t.List[Image.Image], + gap: int, + max_columns: int, + max_rows: int, +) -> Image.Image: + size = images[0].size + + grid_width = size[0] * max_columns + (max_columns - 1) * gap + grid_height = size[1] * max_rows + (max_rows - 1) * gap + + grid_image = Image.new("RGB", (grid_width, grid_height), color="white") + + for i, image in enumerate(images): + image = image.crop((0, 0, size[0], size[1])) + x = (i % max_columns) * (size[0] + gap) + y = (i // max_columns) * (size[1] + gap) + + grid_image.paste(image, (x, y)) + + return grid_image + + +def _draw_center_text( + text: str, + draw: ImageDraw.ImageDraw, + font: ImageFont.ImageFont, + fill: int = 128, +): + image = draw.im # type: ignore + _, _, *text_size = draw.textbbox((0, 0), text, font=font) + draw.text( + ( + (image.size[0]-text_size[0])/2, + (image.size[1]-text_size[1])/2, + ), + text, + font=font, + fill=fill, + ) + return image diff --git a/src/utils/tensor_convert.py b/src/utils/tensor_convert.py new file mode 100644 index 0000000..d929713 --- /dev/null +++ b/src/utils/tensor_convert.py @@ -0,0 +1,13 @@ +import typing as t + +import torch +import numpy as np +from PIL import Image + + +def tensor_to_pillow(image: t.Any) -> Image.Image: + return Image.fromarray(np.clip(255. * image.cpu().numpy().squeeze(), 0, 255).astype(np.uint8)) + + +def pillow_to_tensor(image: Image.Image) -> t.Any: + return torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0)