diff options
Diffstat (limited to 'src/argaze/ArFeatures.py')
-rw-r--r-- | src/argaze/ArFeatures.py | 90 |
1 files changed, 66 insertions, 24 deletions
diff --git a/src/argaze/ArFeatures.py b/src/argaze/ArFeatures.py index 4aedb2b..3101a45 100644 --- a/src/argaze/ArFeatures.py +++ b/src/argaze/ArFeatures.py @@ -24,6 +24,9 @@ ArEnvironmentType = TypeVar('ArEnvironment', bound="ArEnvironment") ArSceneType = TypeVar('ArScene', bound="ArScene") # Type definition for type annotation convenience +ArScreenType = TypeVar('ArScreen', bound="ArScreen") +# Type definition for type annotation convenience + @dataclass class ArEnvironment(): """ @@ -95,6 +98,7 @@ class ArEnvironment(): new_aruco_detector = ArUcoDetector.ArUcoDetector(new_aruco_dictionary, new_marker_size, new_optic_parameters, new_aruco_detector_parameters) + # Build scenes new_scenes = {} for scene_name, scene_data in data.pop('scenes').items(): @@ -129,7 +133,17 @@ class ArEnvironment(): new_aoi_scene = AOI3DScene.AOI3DScene(aoi_scene_value) - new_scenes[scene_name] = ArScene(new_aruco_scene, new_aoi_scene, **scene_data) + # Build screens + new_screens = {} + for screen_name, screen_data in scene_data.pop('screens').items(): + + new_screen_size = screen_data.pop('size') + + # Append new screen + new_screens[screen_name] = ArScreen.from_scene(new_aoi_scene, screen_name, new_screen_size) + + # Append new scene + new_scenes[scene_name] = ArScene(new_aruco_scene, new_aoi_scene, new_screens, **scene_data) return ArEnvironment(new_name, new_aruco_detector, new_scenes) @@ -184,6 +198,8 @@ class ArScene(): aoi_scene: AOI 3D scene description that will be projected onto estimated scene once its pose will be estimated : see [project][argaze.ArFeatures.ArScene.project] function below. + screens: All scene screens + aruco_axis: Optional dictionary to define orthogonal axis where each axis is defined by list of 3 markers identifier (first is origin). \ This pose estimation strategy is used by [estimate_pose][argaze.ArFeatures.ArScene.estimate_pose] function when at least 3 markers are detected. @@ -196,6 +212,7 @@ class ArScene(): aruco_scene: ArUcoScene.ArUcoScene = field(default_factory=ArUcoScene.ArUcoScene) aoi_scene: AOI3DScene.AOI3DScene = field(default_factory=AOI3DScene.AOI3DScene) + screens: dict = field(default_factory=dict) aruco_axis: dict = field(default_factory=dict) aruco_aoi: dict = field(default_factory=dict) angle_tolerance: float = field(default=0.) @@ -207,7 +224,11 @@ class ArScene(): self._environment = None # Preprocess orthogonal projection to speed up further aruco aoi processings - self.__orthogonal_projection_cache = self.orthogonal_projection + self.__orthogonal_projection_cache = self.aoi_scene.orthogonal_projection + + # Setup screens scene after screen creation + for name, screen in self.screens.items(): + screen._scene = self def __str__(self) -> str: """ @@ -221,27 +242,6 @@ class ArScene(): return output - @property - def orthogonal_projection(self) -> AOI2DScene.AOI2DScene: - """ - Orthogonal projection of whole AOI scene. - - Returns: - projected AOI 2D scene - """ - - scene_size = self.aoi_scene.size - scene_center = self.aoi_scene.center - - # Center, step back and rotate pose to get whole scene into field of view - tvec = scene_center*[-1, 1, 0] + [0, 0, scene_size[1]] - rvec = numpy.array([[-numpy.pi, 0.0, 0.0]]) - - # Edit optic intrinsic parameter to capture whole scene - K = numpy.array([[scene_size[1]/scene_size[0], 0.0, 0.5], [0.0, 1., 0.5], [0.0, 0.0, 1.0]]) - - return self.aoi_scene.project(tvec, rvec, K) - def estimate_pose(self, detected_markers) -> Tuple[numpy.array, numpy.array, str, dict]: """Estimate scene pose from detected ArUco markers. @@ -405,4 +405,46 @@ class ArScene(): self.aruco_scene.draw_places(image, self._environment.aruco_detector.optic_parameters.K, self._environment.aruco_detector.optic_parameters.D) - +@dataclass +class ArScreen(): + """ + Define Augmented Reality screen as an AOI2DScene made from a projected then reframed parent AOI3DScene. + + Parameters: + name: name of the screen + size: screen dimension in pixel. + aoi_screen: AOI 2D scene description ... : see [orthogonal_projection][argaze.ArFeatures.ArScene.orthogonal_projection] and [reframe][argaze.AreaOfInterest.AOI2DScene.reframe] functions. + """ + + name: str + size: tuple[int] = field(default=(1, 1)) + aoi_screen: AOI2DScene.AOI2DScene = field(default_factory=AOI2DScene.AOI2DScene) + + def __post_init__(self): + + # Define scene attribute: it will be setup by parent scene later + self._scene = None + + # Init screen + self.init() + + @classmethod + def from_scene(self, aoi_scene, aoi_name, size) -> ArScreenType: + + return ArScreen(aoi_name, size, aoi_scene.orthogonal_projection.reframe(aoi_name, size)) + + @property + def image(self): + """Get screen image.""" + + return self.__image + + def init(self) -> ArScreenType: + """Initialize screen image.""" + + self.__image = numpy.zeros((self.size[1], self.size[0], 3)).astype(numpy.uint8) + + def draw_aoi(self, color=(255, 255, 255)) -> ArScreenType: + """Draw aoi into screen image.""" + + self.aoi_screen.draw(self.__image, color) |