Source code for crappy.tool.camera_config.config_tools.spots_boxes

# coding: utf-8

from __future__ import annotations
from dataclasses import dataclass
from typing import Optional, List, Tuple

from .box import Box


[docs] @dataclass class SpotsBoxes: """This class stores up to four instances of :class:`~crappy.tool.camera_config.config_tools.Box`, defining the bounding boxes of the spots for :class:`~crappy.blocks.VideoExtenso` or the patches for :class:`~crappy.blocks.DICVE`. It can also instantiate the Box objects by parsing a list of tuples containing enough information. .. versionadded:: 2.0.0 """ spot_1: Optional[Box] = None spot_2: Optional[Box] = None spot_3: Optional[Box] = None spot_4: Optional[Box] = None x_l0: Optional[float] = None y_l0: Optional[float] = None _index = -1 def __getitem__(self, i: int) -> Optional[Box]: if i == 0: return self.spot_1 elif i == 1: return self.spot_2 elif i == 2: return self.spot_3 elif i == 3: return self.spot_4 else: raise IndexError def __setitem__(self, i: int, value: Optional[Box]) -> None: if i == 0: self.spot_1 = value elif i == 1: self.spot_2 = value elif i == 2: self.spot_3 = value elif i == 3: self.spot_4 = value else: raise IndexError def __iter__(self) -> SpotsBoxes: self._index = -1 return self def __next__(self) -> Box: self._index += 1 try: return self[self._index] except IndexError: raise StopIteration def __len__(self) -> int: return len([spot for spot in self if spot is not None])
[docs] def set_spots(self, spots: List[Tuple[int, int, int, int]]) -> None: """Parses a list of tuples and instantiates the corresponding :class:`~crappy.tool.camera_config.config_tools.Box` objects.""" for i, spot in enumerate(spots): self[i] = Box(x_start=spot[1], x_end=spot[1] + spot[3], y_start=spot[0], y_end=spot[0] + spot[2])
def save_length(self) -> None: """Setting the :attr:`x_l0` and :attr:`y_l0` attributes based on the positions of the centroids. If only one spot is detected, setting the initial lengths to 0. """ # Calculating the centroids of the spots if not already known for spot in self: if spot is not None and spot.x_centroid is None: min_x, max_x, min_y, max_y = spot.sorted() spot.x_centroid = min_x + (max_x - min_x) / 2 spot.y_centroid = min_y + (max_y - min_y) / 2 # Simply taking the distance between the extrema as the initial length if len(self) > 1: x_centers = [spot.x_centroid for spot in self if spot is not None] y_centers = [spot.y_centroid for spot in self if spot is not None] self.x_l0 = max(x_centers) - min(x_centers) self.y_l0 = max(y_centers) - min(y_centers) # If only one spot detected, setting the initial lengths to 0 else: self.x_l0 = 0 self.y_l0 = 0
[docs] def empty(self) -> bool: """Returns :obj:`True` if all spots are :obj:`None`, else :obj:`False`.""" return all(spot is None for spot in self)
[docs] def reset(self) -> None: """Resets the boxes to :obj:`None`.""" for i in range(4): self[i] = None