Spaces:
Sleeping
Sleeping
File size: 4,566 Bytes
26f7fa0 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
"""
MLSTRUCT-FP - DB - IMAGE - BASE
Image of the surroundings of a rect.
"""
__all__ = ['BaseImage', 'TYPE_IMAGE']
from MLStructFP._types import TYPE_CHECKING, List, NumberType, Tuple
from MLStructFP.utils import make_dirs
import math
import numpy as np
import os
from abc import ABC, abstractmethod
if TYPE_CHECKING:
from MLStructFP.db._c_rect import Rect
from MLStructFP.db._floor import Floor
TYPE_IMAGE: str = 'uint8'
class BaseImage(ABC):
"""
Base dataset image object.
"""
_image_size: int
_images: List['np.ndarray'] # List of stored images during make_region
_last_make_region_time: float # Total time for last make region
_names: List[str]
_path: str
_save_images: bool
patches: List['np.ndarray'] # Additional stored images
save: bool
def __init__(self, path: str, save_images: bool, image_size_px: int) -> None:
"""
Constructor.
:param path: Image path
:param save_images: Save images on path
:param image_size_px: Image size (width/height), bigger images are expensive, double the width, quad the size
"""
assert image_size_px > 0 and isinstance(image_size_px, int)
assert math.log(image_size_px, 2).is_integer(), 'Image size must be a power of 2'
if path != '':
make_dirs(path)
assert os.path.isdir(path), f'Path <{path}> does not exist'
super().__init__()
self._image_size = image_size_px
self._images = []
self._names = [] # List of image names
self._path = path
self._save_images = save_images # Caution, this can be file expensive
self.patches = []
self.save = True
@property
def image_shape(self) -> Tuple[int, int]:
return self._image_size, self._image_size
@abstractmethod
def close(self, *args, **kwargs) -> None:
"""
Close and delete all generated figures.
"""
raise NotImplementedError()
@abstractmethod
def make_rect(self, rect: 'Rect', crop_length: NumberType) -> Tuple[int, 'np.ndarray']:
"""
Generate image for the perimeter of a given rectangle.
:param rect: Rectangle
:param crop_length: Size of crop from center of the rect to any edge in meters
:return: Returns the image index and matrix
"""
raise NotImplementedError()
@abstractmethod
def make_region(self, xmin: NumberType, xmax: NumberType, ymin: NumberType, ymax: NumberType,
floor: 'Floor') -> Tuple[int, 'np.ndarray']:
"""
Generate image for a given region.
:param xmin: Minimum x-axis (m)
:param xmax: Maximum x-axis (m)
:param ymin: Minimum y-axis (m)
:param ymax: Maximum y-axis (m)
:param floor: Floor object
:return: Returns the image index and matrix
"""
raise NotImplementedError()
@property
def make_region_last_time(self) -> float:
return self._last_make_region_time
def export(self, filename: str, close: bool = True, compressed: bool = True) -> None:
"""
Export saved images to numpy format and then removes all data.
:param filename: File to export
:param close: Close after export
:param compressed: Save compressed file
"""
assert len(self._images) > 0, 'Exporter cannot be empty'
filename += f'_{self._image_size}'
make_dirs(filename)
if compressed:
np.savez_compressed(filename, data=self.get_images()) # .npz
else:
np.save(filename, self.get_images()) # .npy
imnames = open(filename + '_files.csv', 'w', encoding='utf-8')
imnames.write('ID,File\n')
for i in range(len(self._names)):
imnames.write(f'{i},{self._names[i]}\n')
imnames.close()
if close:
self.close()
def get_images(self) -> 'np.ndarray':
"""
:return: Images as numpy ndarray
"""
return np.array(self._images, dtype=TYPE_IMAGE)
def get_file_id(self, filename) -> int:
"""
Returns the index of a given filename.
:param filename: Name of the file
:return: Index on saved list
"""
if filename not in self._names:
raise ValueError(f'File <{filename}> have not been processed yet')
return self._names.index(filename)
def init(self) -> 'BaseImage':
"""
Init the object.
"""
return self
|