track-anything-annotate / tools /data_exporter.py
lniki's picture
add model
0e83290 verified
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)