diff --git a/common/polystar/common/models/image.py b/common/polystar/common/models/image.py index 61af256e9c096f11347a3d419421ea7f20626b5e..fcc4faafdfded5bf1558b237dab685132bff813f 100644 --- a/common/polystar/common/models/image.py +++ b/common/polystar/common/models/image.py @@ -4,19 +4,20 @@ from typing import Iterable import cv2 from nptyping import Array +Image = Array[int, ..., ..., 3] -class Image(Array[int, ..., ..., 3]): - @staticmethod - def from_path(image_path: Path, conversion: int = cv2.COLOR_BGR2RGB) -> "Image": - return cv2.cvtColor(cv2.imread(str(image_path), cv2.IMREAD_UNCHANGED), conversion) - def save(self, image_path: Path, conversion: int = cv2.COLOR_RGB2BGR): - image_path.parent.mkdir(exist_ok=True, parents=True) - cv2.imwrite(str(image_path), cv2.cvtColor(self, conversion)) +def load_image(image_path: Path, conversion: int = cv2.COLOR_BGR2RGB) -> Image: + return cv2.cvtColor(cv2.imread(str(image_path), cv2.IMREAD_UNCHANGED), conversion) + + +def save_image(image: Image, image_path: Path, conversion: int = cv2.COLOR_RGB2BGR): + image_path.parent.mkdir(exist_ok=True, parents=True) + cv2.imwrite(str(image_path), cv2.cvtColor(image, conversion)) def load_images_in_directory( directory: Path, pattern: str = "*", conversion: int = cv2.COLOR_BGR2RGB ) -> Iterable[Image]: for image_path in directory.glob(pattern): - yield Image.from_path(image_path, conversion) + yield load_image(image_path, conversion) diff --git a/common/polystar/common/models/image_annotation.py b/common/polystar/common/models/image_annotation.py index b34e4116626ba1be75bb26c7e3ac62045b50d087..36707b94e2e83f7eb923044cab184229072cabdb 100644 --- a/common/polystar/common/models/image_annotation.py +++ b/common/polystar/common/models/image_annotation.py @@ -6,7 +6,7 @@ from xml.dom.minidom import parseString import xmltodict from dicttoxml import dicttoxml -from polystar.common.models.image import Image +from polystar.common.models.image import Image, load_image, save_image from polystar.common.models.object import Object, ObjectFactory @@ -28,7 +28,7 @@ class ImageAnnotation: @property def image(self) -> Image: if self._image is None: - self._image = Image.from_path(self.image_path) + self._image = load_image(self.image_path) return self._image @staticmethod @@ -78,5 +78,5 @@ class ImageAnnotation: self.image_path.parent.mkdir(exist_ok=True, parents=True) self.xml_path.parent.mkdir(exist_ok=True, parents=True) - Image.save(self.image, self.image_path) + save_image(self.image, self.image_path) self.xml_path.write_text(self.to_xml()) diff --git a/common/research/common/dataset/perturbations/perturbator.py b/common/research/common/dataset/perturbations/perturbator.py index 986aa8a91fa6b80575f7ca3b9d48159b544e9cbe..4391fe969ce49d6deff254f7c6f7e7b8060d2170 100644 --- a/common/research/common/dataset/perturbations/perturbator.py +++ b/common/research/common/dataset/perturbations/perturbator.py @@ -6,15 +6,21 @@ from typing import List import cv2 import matplotlib.pyplot as plt import numpy as np - -from polystar.common.models.image import Image -from research.common.dataset.perturbations.image_modifiers.brightness import BrightnessModifier -from research.common.dataset.perturbations.image_modifiers.contrast import ContrastModifier -from research.common.dataset.perturbations.image_modifiers.gaussian_blur import GaussianBlurrer -from research.common.dataset.perturbations.image_modifiers.gaussian_noise import GaussianNoiser -from research.common.dataset.perturbations.image_modifiers.horizontal_blur import HorizontalBlurrer -from research.common.dataset.perturbations.image_modifiers.image_modifier_abc import ImageModifierABC -from research.common.dataset.perturbations.image_modifiers.saturation import SaturationModifier +from polystar.common.models.image import Image, load_image +from research.common.dataset.perturbations.image_modifiers.brightness import \ + BrightnessModifier +from research.common.dataset.perturbations.image_modifiers.contrast import \ + ContrastModifier +from research.common.dataset.perturbations.image_modifiers.gaussian_blur import \ + GaussianBlurrer +from research.common.dataset.perturbations.image_modifiers.gaussian_noise import \ + GaussianNoiser +from research.common.dataset.perturbations.image_modifiers.horizontal_blur import \ + HorizontalBlurrer +from research.common.dataset.perturbations.image_modifiers.image_modifier_abc import \ + ImageModifierABC +from research.common.dataset.perturbations.image_modifiers.saturation import \ + SaturationModifier @dataclass @@ -37,7 +43,7 @@ class ImagePerturbator: if __name__ == "__main__": EXAMPLE_DIR = Path(__file__).parent / "examples" - rune_img = Image.from_path(EXAMPLE_DIR / "test.png") + rune_img = load_image(EXAMPLE_DIR / "test.png") perturbator = ImagePerturbator( [ ContrastModifier(), diff --git a/common/research/common/dataset/perturbations/utils.py b/common/research/common/dataset/perturbations/utils.py index 551bc65023efc8983c09ec78dbdbbeb598a7dce7..fb90ebea203cece50b3439264561e125587e2b87 100644 --- a/common/research/common/dataset/perturbations/utils.py +++ b/common/research/common/dataset/perturbations/utils.py @@ -3,15 +3,15 @@ from pathlib import Path import cv2 import matplotlib.pyplot as plt import numpy as np - -from polystar.common.models.image import Image -from research.common.dataset.perturbations.image_modifiers.image_modifier_abc import ImageModifierABC +from polystar.common.models.image import load_image +from research.common.dataset.perturbations.image_modifiers.image_modifier_abc import \ + ImageModifierABC EXAMPLE_DIR = Path(__file__).parent / "examples" def simple_modifier_demo(modifier: ImageModifierABC): - rune_img = Image.from_path(EXAMPLE_DIR / "test.png") + rune_img = load_image(EXAMPLE_DIR / "test.png") rune_perturbed = modifier.modify(rune_img, 1) cv2.imwrite(str(EXAMPLE_DIR / f"res_{modifier}.png"), cv2.cvtColor(rune_perturbed, cv2.COLOR_RGB2BGR)) side_by_side_display = np.hstack((rune_img, rune_perturbed)) diff --git a/common/research/common/dataset/roco_dataset.py b/common/research/common/dataset/roco_dataset.py index b90eefc0d2e772937dd576381a828725d22500d6..7c8b9e650862b2e311092129456b91da51a407ca 100644 --- a/common/research/common/dataset/roco_dataset.py +++ b/common/research/common/dataset/roco_dataset.py @@ -3,8 +3,7 @@ from pathlib import Path from typing import Iterable from more_itertools import ilen - -from polystar.common.models.image import Image +from polystar.common.models.image import Image, load_image from polystar.common.models.image_annotation import ImageAnnotation @@ -17,7 +16,7 @@ class ROCODataset: @property def images(self) -> Iterable[Image]: for image_path in self.image_paths: - yield Image.from_path(image_path) + yield load_image(image_path) @property def image_annotations(self) -> Iterable[ImageAnnotation]: diff --git a/common/research/common/datasets/image_dataset.py b/common/research/common/datasets/image_dataset.py index 9ede6326accbf19365c098f7f1f59b6fb6ed2a8f..047633689a5bcbccf2b6052a4fff0a3918f4a4f2 100644 --- a/common/research/common/datasets/image_dataset.py +++ b/common/research/common/datasets/image_dataset.py @@ -25,7 +25,7 @@ class ImageFileDataset(LazyDataset[Path, TargetT], ABC): pass def open(self) -> ImageDataset: - return self.transform_examples(Image.from_path) + return self.transform_examples(load_image) def __len__(self): return ilen(self.image_files) diff --git a/common/research/common/datasets/roco/directory_roco_dataset.py b/common/research/common/datasets/roco/directory_roco_dataset.py index 9857bea0b90228184f7517226ee6c6e199fc066a..5df40213d341fff85c3eadd42ac5fb0c688360d2 100644 --- a/common/research/common/datasets/roco/directory_roco_dataset.py +++ b/common/research/common/datasets/roco/directory_roco_dataset.py @@ -1,6 +1,6 @@ from pathlib import Path -from polystar.common.models.image import Image +from polystar.common.models.image import Image, save_image from research.common.datasets.image_dataset import ImageDirectoryDataset from research.common.datasets.roco.roco_annotation import ROCOAnnotation @@ -21,5 +21,5 @@ class DirectoryROCODataset(ImageDirectoryDataset[ROCOAnnotation]): self.annotations_dir.mkdir() def add(self, image: Image, annotation: ROCOAnnotation): - Image.save(image, self.images_dir / f"{annotation.name}.jpg") + save_image(image, self.images_dir / f"{annotation.name}.jpg") (self.annotations_dir / f"{annotation.name}.xml").write_text(annotation.to_xml()) diff --git a/common/research/common/image_pipeline_evaluation/image_dataset_generator.py b/common/research/common/image_pipeline_evaluation/image_dataset_generator.py index 862b0492325578aa2391ed6afc85d098066d5aee..f9b321bbbd1ac05ebc001137efd6410382e32a44 100644 --- a/common/research/common/image_pipeline_evaluation/image_dataset_generator.py +++ b/common/research/common/image_pipeline_evaluation/image_dataset_generator.py @@ -2,7 +2,7 @@ from abc import abstractmethod from pathlib import Path from typing import Generic, Iterable, List, Tuple, TypeVar -from polystar.common.models.image import Image +from polystar.common.models.image import Image, load_image from research.common.dataset.directory_roco_dataset import DirectoryROCODataset T = TypeVar("T") @@ -17,7 +17,7 @@ class ImageDatasetGenerator(Generic[T]): prev_total_size = len(images) for img_path, label in self.from_roco_dataset(dataset): images_path.append(img_path) - images.append(Image.from_path(img_path)) + images.append(load_image(img_path)) labels.append(label) dataset_sizes.append(len(images) - prev_total_size) return images_path, images, labels, dataset_sizes diff --git a/common/tests/common/unittests/datasets/roco/test_directory_dataset_zoo.py b/common/tests/common/unittests/datasets/roco/test_directory_dataset_zoo.py index 69ad22403d4d6acb5445a98506b42f829269da83..fbb37073dd6f19c8b17ecacd2e0ac7360ccf03c4 100644 --- a/common/tests/common/unittests/datasets/roco/test_directory_dataset_zoo.py +++ b/common/tests/common/unittests/datasets/roco/test_directory_dataset_zoo.py @@ -4,7 +4,7 @@ from unittest import TestCase from numpy import asarray, float32 from numpy.testing import assert_array_almost_equal -from polystar.common.models.image import Image +from polystar.common.models.image import save_image from research.common.datasets.roco.directory_roco_dataset import \ DirectoryROCODataset from research.common.datasets.roco.roco_annotation import ROCOAnnotation @@ -35,7 +35,7 @@ class TestDirectoryROCODataset(TestCase): dataset.annotations_dir.mkdir() dataset.images_dir.mkdir() (dataset.annotations_dir / "frame_1.xml").write_text(annotation.to_xml()) - Image.save(image, dataset.images_dir / "frame_1.jpg") + save_image(image, dataset.images_dir / "frame_1.jpg") image_dataset = dataset.open() diff --git a/robots-at-runes/research/robots_at_runes/dataset/labeled_image.py b/robots-at-runes/research/robots_at_runes/dataset/labeled_image.py index bc49b1cb35158127d3aeff40c0c2b8131db528dc..e6894d1cf51b4e3d64034e7db8a7684b05deac76 100644 --- a/robots-at-runes/research/robots_at_runes/dataset/labeled_image.py +++ b/robots-at-runes/research/robots_at_runes/dataset/labeled_image.py @@ -4,10 +4,9 @@ from typing import Any, Dict, Iterable, List from xml.dom.minidom import parseString import cv2 - import xmltodict from dicttoxml import dicttoxml -from polystar.common.models.image import Image +from polystar.common.models.image import Image, load_image, save_image @dataclass @@ -35,7 +34,7 @@ class LabeledImage: point_of_interests: List[PointOfInterest] = field(default_factory=list) def save(self, directory_path: Path, name: str): - Image.save(self.image, directory_path / "image" / f"{name}.jpg") + save_image(self.image, directory_path / "image" / f"{name}.jpg") self._save_annotation(directory_path / "image_annotation" / f"{name}.xml") def _save_annotation(self, annotation_path: Path): @@ -57,7 +56,7 @@ class LabeledImage: directory: Path, name: str, conversion: int = cv2.COLOR_BGR2RGB, ext: str = "jpg" ) -> "LabeledImage": return LabeledImage( - image=Image.from_path(directory / "image" / f"{name}.{ext}", conversion), + image=load_image(directory / "image" / f"{name}.{ext}", conversion), point_of_interests=PointOfInterest.from_annotation_file(directory / "image_annotation" / f"{name}.xml"), )