Source code for isimple.core.features

import numpy as np
import abc
from typing import Tuple, Any, Optional

from isimple.core.backend import BackendInstance
from isimple.core.config import HsvColor


[docs]class Feature(abc.ABC): """A feature implements interactions between BackendElements to produce a certain value """ _color: Optional[np.ndarray] _state: Optional[np.ndarray] _elements: Tuple[BackendInstance, ...] def __init__(self, elements: Tuple[BackendInstance, ...]): self._elements = elements
[docs] def calculate(self, frame: np.ndarray, state: np.ndarray = None) \ -> Tuple[Any, np.ndarray]: """Calculate Feature for given frame and update state image (optional) """ if state is not None: state = self.state(frame, state) return self.value(frame), state
@property def color(self) -> np.ndarray: """Color of the Feature in figures. A Feature's color must be set as not to overlap with other Features in the same FeatureSet. Therefore, <Feature>._color must be determined by FeatureSet! """ return self._color @abc.abstractmethod def _guideline_color(self) -> np.ndarray: """Returns the 'guideline color' of a Feature instance Used by FeatureSet to determine the actual _color """ raise NotImplementedError
[docs] @abc.abstractmethod # todo: we're dealing with frames explicitly, so maybe this should be an isimple.video thing... def state(self, frame: np.ndarray, state: np.ndarray = None) -> np.ndarray: """Return the Feature instance's state image for a given frame """ raise NotImplementedError
[docs] @abc.abstractmethod def value(self, frame: np.ndarray) -> Any: """Compute the value of the Feature instance for a given frame """ raise NotImplementedError
[docs] @abc.abstractmethod def name(self) -> str: """Return the name of the feature """ raise NotImplementedError
[docs]class FeatureSet(object): _features: Tuple[Feature, ...] _colors: Tuple[tuple, ...] def __init__(self, features: Tuple[Feature, ...]): self._features = features
[docs] def get_colors(self) -> Tuple[HsvColor, ...]: if not hasattr(self, '_colors'): guideline_colors = [f._guideline_color() for f in self._features] colors: list = [] # For all features in the FeatureSet for feature, color in zip(self._features, guideline_colors): # Dodge the other colors by hue tolerance = 15 increment = 60 # todo: should be set *after* the number of repititions is determined repetition = 0 for registered_color in colors: if abs(float(color[0]) - float(registered_color[0])) < tolerance: repetition += 1 color = ( float(color[0]), float(220), float(255 - repetition * increment) ) feature._color = color colors.append(color) self._colors = tuple(colors) return self.colors #type: ignore
@property def colors(self) -> Tuple[tuple, ...]: return self._colors @property def features(self) -> Tuple[Feature, ...]: return self._features