#!/usr/bin/env python """ """ __author__ = "Théo de la Hogue" __credits__ = [] __copyright__ = "Copyright 2023, Ecole Nationale de l'Aviation Civile (ENAC)" __license__ = "BSD" from typing import TypeVar from dataclasses import dataclass, field import cv2 as cv import cv2.aruco as aruco import numpy all_aruco_markers_dictionaries = { 'DICT_4X4_50': aruco.DICT_4X4_50, 'DICT_4X4_100': aruco.DICT_4X4_100, 'DICT_4X4_250': aruco.DICT_4X4_250, 'DICT_4X4_1000': aruco.DICT_4X4_1000, 'DICT_5X5_50': aruco.DICT_5X5_50, 'DICT_5X5_100': aruco.DICT_5X5_100, 'DICT_5X5_250': aruco.DICT_5X5_250, 'DICT_5X5_1000': aruco.DICT_5X5_1000, 'DICT_6X6_50': aruco.DICT_6X6_50, 'DICT_6X6_100': aruco.DICT_6X6_100, 'DICT_6X6_250': aruco.DICT_6X6_250, 'DICT_6X6_1000': aruco.DICT_6X6_1000, 'DICT_7X7_50': aruco.DICT_7X7_50, 'DICT_7X7_100': aruco.DICT_7X7_100, 'DICT_7X7_250': aruco.DICT_7X7_250, 'DICT_7X7_1000': aruco.DICT_7X7_1000, 'DICT_ARUCO_ORIGINAL': aruco.DICT_ARUCO_ORIGINAL, 'DICT_APRILTAG_16h5': aruco.DICT_APRILTAG_16h5, 'DICT_APRILTAG_25h9': aruco.DICT_APRILTAG_25h9, 'DICT_APRILTAG_36h10': aruco.DICT_APRILTAG_36h10, 'DICT_APRILTAG_36h11': aruco.DICT_APRILTAG_36h11 } """Dictionnary to list all built-in ArUco markers dictionaries from OpenCV ArUco package.""" ArUcoMarkerType = TypeVar('ArUcoMarker', bound="ArUcoMarker") # Type definition for type annotation convenience @dataclass(frozen=True) class ArUcoMarkersDictionary(): """Handle an ArUco markers dictionary.""" name: str = field(default='DICT_ARUCO_ORIGINAL') """Dictionary name""" def __post_init__(self): if all_aruco_markers_dictionaries.get(self.name, None) is None: raise NameError(f'Bad ArUco markers dictionary name: {self.name}') def __str__(self) -> str: """String display""" output = f'{self.name}\n' return output @property def markers(self) -> aruco.Dictionary: """Get all markers from dictionary.""" return aruco.getPredefinedDictionary(all_aruco_markers_dictionaries[self.name]) @property def format(self) -> str: """Get markers format.""" dict_name_split = self.name.split('_') dict_type = dict_name_split[1] # DICT_ARUCO_ORIGINAL case if dict_type == 'ARUCO': return '5X5' # DICT_APRILTAG case elif dict_type == 'APRILTAG': april_tag_format = dict_name_split[2] if april_tag_format == '16h5': return '4X4' elif april_tag_format == '25h9': return '5X5' elif april_tag_format == '36h10': return '6X6' elif april_tag_format == '36h11': return '6X6' # other cases else: return dict_type @property def number(self) -> int: """Get number of markers inside dictionary.""" dict_name_split = self.name.split('_') dict_type = dict_name_split[1] # DICT_ARUCO_ORIGINAL case if dict_type == 'ARUCO': return 1024 # DICT_APRILTAG case elif dict_type == 'APRILTAG': april_tag_format = dict_name_split[2] if april_tag_format == '16h5': return 30 elif april_tag_format == '25h9': return 30 elif april_tag_format == '36h10': return 2320 elif april_tag_format == '36h11': return 587 # other cases else: return int(dict_name_split[2]) def create_marker(self, i, size) -> ArUcoMarkerType: """Create a marker.""" if i >= 0 and i < self.number: from argaze.ArUcoMarkers import ArUcoMarker return ArUcoMarker.ArUcoMarker(self, i, size) else: raise ValueError(f'Bad index: {i}') def save(self, destination_folder, size, dpi): """Save all markers dictionary into separated .png files.""" for i in range(self.number): self.create_marker(i, size).save(destination_folder, dpi)