| import cv2 | |
| import uuid | |
| import shutil | |
| import numpy as np | |
| from pathlib import Path | |
| from typing import Protocol, Type | |
| from tools.contour_detector import getting_coordinates | |
| from tools.mask_display import mask_map | |
| SAVE_FOLDER = Path.cwd() / 'video-test' | |
| class ExportObject: | |
| def __init__(self, mask, name_class) -> None: | |
| self.mask = mask | |
| self.name_class = name_class | |
| class ExportImage: | |
| def __init__(self, image, objects: list[ExportObject]) -> None: | |
| self.image = image | |
| self.exports_objects = objects | |
| class TypeSave(Protocol): | |
| def start_creation(self) -> None: | |
| pass | |
| def create_archive(self) -> str: | |
| pass | |
| def get_type_save_annotation( | |
| images: list[np.ndarray], | |
| masks: list[np.ndarray], | |
| names_class: list[str], | |
| type_save: str = 'yolo', | |
| ) -> TypeSave: | |
| '''Factory''' | |
| types_saves: dict[str, Type[TypeSave]] = { | |
| 'yolo': YoloSave, | |
| } | |
| return types_saves[type_save](images, masks, names_class) | |
| class YoloSave: | |
| def __init__( | |
| self, images: list[np.ndarray], masks: list[np.ndarray], names_class: list[str] | |
| ) -> None: | |
| self.images = images | |
| self.masks = masks | |
| self.names_class = {} | |
| for i, name in enumerate(names_class): | |
| self.names_class[name] = i | |
| folder_name = ( | |
| ''.join(names_class)[:10] | |
| if len(''.join(names_class)) > 15 | |
| else ''.join(names_class) | |
| ) | |
| folder_name = f'dt-{folder_name}-{uuid.uuid1()}' | |
| p = Path(SAVE_FOLDER / folder_name) | |
| p.mkdir() | |
| self.path_folder = SAVE_FOLDER / folder_name | |
| self.images_folder = self.path_folder / 'images' | |
| p = Path(self.images_folder) | |
| p.mkdir() | |
| self.lables_folder = self.path_folder / 'lables' | |
| p = Path(self.lables_folder) | |
| p.mkdir() | |
| def start_creation(self): | |
| path_image = self.images_folder / 'image_filename' | |
| path_txt = self.lables_folder / 'image_filename' | |
| for i, (image, mask) in enumerate(zip(self.images, self.masks)): | |
| cv2.imwrite(f'{path_image}{i+1}.jpg', image) | |
| txt_frame_save(image, mask, f'{path_txt}{i+1}', 0) | |
| txt_class_save(self.path_folder / 'classes', self.names_class) | |
| def create_archive(self) -> str: | |
| shutil.make_archive(self.path_folder, 'zip', self.path_folder) | |
| shutil.rmtree(self.path_folder) | |
| return f'{self.path_folder}.zip' | |
| def txt_class_save(path: str, names_class: dict): | |
| with open(f'{path}.txt', 'w') as file: | |
| for key, value in names_class.items(): | |
| name_class_str = [f'{value} {key} \n'] | |
| file.writelines(name_class_str) | |
| def txt_frame_save( | |
| images: np.ndarray, mask_unique: np.ndarray, path: str, name_class_idx: int | |
| ): | |
| img_height = images.shape[0] | |
| img_width = images.shape[1] | |
| with open(f'{path}.txt', 'w') as file: | |
| coordinates = [] | |
| for mask in mask_map(mask_unique): | |
| coordinate = getting_coordinates(mask) | |
| coordinates += coordinate | |
| for box in coordinates: | |
| x, y = box[0], box[1] | |
| w, h = box[2], box[3] | |
| x_center = x + int(w / 2) | |
| y_center = y + int(h / 2) | |
| norm_xc = x_center / img_width | |
| norm_yc = y_center / img_height | |
| norm_width = w / img_width | |
| norm_height = h / img_height | |
| yolo_annotation = [ | |
| f'{name_class_idx} {norm_xc} {norm_yc} {norm_width} {norm_height} \n' | |
| ] | |
| file.writelines(yolo_annotation) | |