Code source de Grounded.Tools.DetecteurMire.DetectionCCTag

import os
from exif import Image as exifImage
import numpy as np

import shutil

from Grounded.DataObject import Image
from Grounded.DataObject import Mire2D
from Grounded.DataObject import File
from .DetecteurMire import DetecteurMire

import subprocess

from Grounded.utils import config_builer, check_module_executable_path, path_exist, raise_logged, parse_bool
import Grounded.logger as logger


[docs] def parsing_result(resultat: str) -> list[Image]: """" Parse les sorties standard et d'erreur de l'executable detection afin de renvoyer ces informations sous la forme d'une liste d'image Args: resultat (str): résultat de la sortie standard et d'erreur de l'executable detection Returns: list[Image]: une liste d'image correspondant aux informations données en argument """ tableau_ligne = resultat.split("\n") tableau_ligne_trie = [line for line in tableau_ligne if "frame" in line or line.endswith("1") or "Done" in line or "detected" in line] tableau_image = [Image("", [])] compteur = 0 for ligne in tableau_ligne_trie: if ligne.endswith("1") and not "frame" in ligne: infos_mire = ligne.split(" ") if int(infos_mire[2]) != -1 : tableau_image[compteur].mires_visibles.append( (Mire2D(int(infos_mire[2]), (float(infos_mire[0]), float(infos_mire[1])))) ) if ligne.startswith("Done"): chemin = ligne.split('/') tableau_image[compteur].name = chemin[-1] tableau_image[compteur].extension = chemin[-1].split(".")[-1] if "." in chemin[-1] else '' tableau_image[compteur].path = "/"+"/".join(chemin[1:]) compteur += 1 tableau_image.append(Image("", [])) tableau_image.pop() #detection binary from CCTag automatically rotates images before detecting targets. Image coordinates has then to be corrected for im in tableau_image: im_width = exifImage(im.path).pixel_x_dimension im_height = exifImage(im.path).pixel_y_dimension if exifImage(im.path).orientation.value == 3: # case of a 180° rotation for mire in im.mires_visibles: # simply doing x' = width - x and y' = height - y mire.coordinates = np.subtract((im_width, im_height), mire.coordinates) elif exifImage(im.path).orientation.value == 6: # case of a CW 90° rotation (right_top) for mire in im.mires_visibles: # simply doing x' = y and y' = height - x x = mire.coordinates[0] y = mire.coordinates[1] mire.coordinates = (y, im_height - x) elif exifImage(im.path).orientation.value == 8: # case of a CW 270° rotation (left_bottom) for mire in im.mires_visibles: # simply doing x' = width - y and y' = x x = mire.coordinates[0] y = mire.coordinates[1] mire.coordinates = (im_width - y, x) elif exifImage(im.path).orientation.value != 1: # cases where orientation is neither 180° rotation neither 90° neither 270° neither "normal case" - theses cases (if exist) are currently not managed print(f"""cas d'orientation d'image "{exifImage(im.path).orientation.name}" non traité""") return tableau_image
[docs] def save_liste_image(tableau_image:list[Image], aFile:File): with open(aFile.path, 'w') as f: for im in tableau_image: for mir in im.mires_visibles: f.write(f"{im.name},{mir.identifier},{mir.coordinates[0]:.3f},{mir.coordinates[1]:.3f}") f.write("\n")
[docs] def load_liste_image(aFile: File, path_images: str) -> list[Image]: tableau_image = [] current_image = None with open(aFile.path, 'r') as f: for line in f: name, identifier, x, y = line.strip().split(',') if current_image is None or current_image.name != name: if current_image: tableau_image.append(current_image) current_image = Image(path = os.sep.join([path_images,name]), mires_visibles=[]) mire = Mire2D(identifier = int(identifier), coordinates=(float(x), float(y))) current_image.mires_visibles.append(mire) if current_image: tableau_image.append(current_image) return tableau_image
[docs] class DetectionCCTagException(Exception): pass
[docs] class DetectionCCTag(DetecteurMire): """ Implémente l'interface DetecteurMire et implémente les méthodes nécessaires pour l'exécution de detection, une composante de CCTag Elle est utilisée pour calculer les coordonnées de chacune des mires présentes sur une image """ def __init__(self, path_cctag_directory: str, working_directory: str, output_dir: str, reuse_wd: str = 'False'): """ Initialise une instance de la classe DetectionCCTag Args: path_cctag_directory (str): le chemin vers le dossier contenant l'executable detection et ses librairies. Returns: None """ super().__init__(working_directory, output_dir) check_module_executable_path(path_cctag_directory, "CCTag") self.path_cctag_directory = path_cctag_directory try: self.reuse_wd = parse_bool(reuse_wd) except ValueError: raise ValueError(f"Invalid reuse_wd. {reuse_wd} is not a boolean.") if not self.reuse_wd: self.set_up_working_space()
[docs] def detection_mires(self, chemin_dossier_image) -> list[Image]: """ Détecte chacune des mires présentes sur une image, renvoyant une liste d'objet image contenant les mires (Mire2D) qui apparaissent sur cette image. Args: chemin_dossier_image: un dossier contenant une ou plusieurs images en paramètre. Returns: list[Image]: une liste contenant toutes les images ayant été trouvé par le détecteur de mire """ if not self.reuse_wd: current_dir = os.path.abspath(os.curdir) chemin_absolue_dossier_image = os.path.abspath(chemin_dossier_image) os.chdir(self.path_cctag_directory) arguments = ["./detection", "-n", "3", "-i", chemin_absolue_dossier_image] process, output = self.subprocess(arguments, os.path.join(self.working_directory, "Detection.log")) if process.returncode != 0: raise_logged(logger.get_logger().critical, DetectionCCTagException("Une erreur est survenu lors de la détection des mires dans les " "images. Veuillez revoir les consignes " "d'installation de la dépendance logicielle CCTag") ) liste_image = parsing_result(output) os.chdir(current_dir) os.makedirs(os.path.join(self.working_directory,os.path.split(chemin_dossier_image)[1]), exist_ok=True) cctagResults_filename = os.path.join(self.working_directory,os.path.split(chemin_dossier_image)[1],"cctag3CC_result.txt") save_liste_image(liste_image, File(cctagResults_filename)) out_file = os.path.join(chemin_absolue_dossier_image, "cctag3CC.out") if path_exist(out_file): os.remove(out_file) else: liste_image=load_liste_image(File(os.path.join(self.working_directory, os.path.split(chemin_dossier_image)[1], "cctag3CC_result.txt")),os.path.abspath(chemin_dossier_image)) return liste_image
[docs] def get_config(self) -> str: return config_builer(self, "DetectionCCTag")