def _add_branches_recursively(
     self,
     layer_config: LayerConfig,
     layer_id: str,
     default_input_layer: ResolvedLayerConfig
 ):
     branches: Optional[List[dict]] = layer_config.get_list('branches')
     assert branches
     branch_layers = []
     for branch_index, branch_config in enumerate(branches):
         branch_layer = self._add_branch_recursively(
             LayerConfig(branch_config),
             default_id=f'{layer_id}b{branch_index}',
             default_input_layer=default_input_layer
         )
         if branch_layer:
             branch_layers.append(branch_layer)
     assert branch_layers
     if len(branch_layers) == 1:
         return branch_layers[0]
     resolved_layer_config = ResolvedLayerConfig({
         **{key: value for key, value in layer_config.props.items() if key != 'branches'},
         'id': layer_id,
         'filter': 'composite'
     })
     resolved_layer_config.input_layers = branch_layers
     return self._add_resolved_layer(resolved_layer_config)
 def test_should_skip_disabled_branch_layers(self):
     resolved_app_config = ResolvedAppConfig(AppConfig([
         LayerConfig({
             'id': 'branches',
             'branches': [{
                 'layers': [{
                     'id': 'in1',
                     'enabled': True,
                     'input_path': 'input_path_1'
                 }]
             }, {
                 'layers': [{
                     'id': 'in2',
                     'enabled': False,
                     'input_path': 'input_path_1'
                 }]
             }]
         }),
         LayerConfig({
             'id': 'out',
             'output_path': 'output_path_1'
         })
     ]))
     assert resolved_app_config.layer_by_id['in1']
     assert not resolved_app_config.layer_by_id.get('in2')
     assert resolved_app_config.layer_by_id['out'].input_layer_ids == ['in1']
def get_resolved_layer_type(layer_config: LayerConfig) -> ResolvedLayerType:
    if layer_config.get('filter'):
        return ResolvedLayerType.FILTER
    if layer_config.get('input_path'):
        return ResolvedLayerType.INPUT_SOURCE
    if layer_config.get('output_path'):
        return ResolvedLayerType.OUTPUT_SINK
    raise ValueError('unable to determine resolved layer type for: %s' % layer_config)
Example #4
0
 def parse_mp_selfie_segmentation_config(self, layer_config: LayerConfig) -> Config:
     config = BodyPixFilter.Config(
         threshold=layer_config.get_float('threshold', 0.1),
         model_selection=layer_config.get_int('model_selection', 1),
         cache_model_result_secs=(
             layer_config.get_float('cache_model_result_secs', 0.0)
         )
     )
     LOGGER.info('mp selfie segmentation filter config: %s', config)
     return config
Example #5
0
 def parse_fill_config(self, layer_config: LayerConfig) -> Config:
     color = layer_config.get('color')
     color_value: Optional[np.ndarray] = get_color_numpy_array(color)
     value = layer_config.get_int('value')
     poly_points_list = layer_config.get_list('poly_points')
     poly_points = (np.asarray(poly_points_list, dtype=np.float32)
                    if poly_points_list else None)
     config = FillFilter.Config(color=color_value,
                                value=value,
                                poly_points=poly_points)
     LOGGER.info('fill config: %s', config)
     assert config.color is not None or config.value is not None
     return config
Example #6
0
 def __init__(self, layer_config: LayerConfig, **kwargs):
     super().__init__(layer_config, **kwargs)
     self.model_path = (layer_config.get('model_path')
                        or BodyPixModelPaths.MOBILENET_FLOAT_50_STRIDE_16)
     self._bodypix_model = None
     self.threshold = float(layer_config.get('threshold') or 0.50)
     self.internal_resolution = float(
         layer_config.get('internal_resolution') or 0.50)
     self.cache_model_result_secs = float(
         layer_config.get('cache_model_result_secs') or 0.0)
     self.parts = list(layer_config.get('parts') or [])
     self._bodypix_result_cache = None
     self._bodypix_result_cache_time = None
Example #7
0
 def parse_warp_perspective_config(self,
                                   layer_config: LayerConfig) -> Config:
     config = WarpPerspectiveFilter.Config(
         target_points=np.asarray(layer_config.get_list(
             'target_points', DEFAULT_POINTS),
                                  dtype=np.float32),
         source_points=np.array(layer_config.get_list(
             'source_points', DEFAULT_POINTS),
                                dtype=np.float32),
         add_alpha_channel=self.layer_config.get_bool(
             'add_alpha_channel', True))
     LOGGER.info('warp perspective config: %s', config)
     assert config.source_points.shape == (4, 2)
     assert config.target_points.shape == (4, 2)
     return config
 def _add_branch_recursively(
     self,
     layer_config: LayerConfig,
     default_id: str,
     default_input_layer: Optional[ResolvedLayerConfig]
 ):
     layers: Optional[List[dict]] = layer_config.get_list('layers')
     assert layers
     resolved_layers = self._add_layers_recursively(
         [LayerConfig(props) for props in layers],
         default_id_prefix=default_id,
         default_input_layer=default_input_layer
     )
     if not resolved_layers:
         return None
     return resolved_layers[-1]
Example #9
0
 def test_should_fill_area_using_poly_points(self,
                                             filter_context: FilterContext):
     layer_config = LayerConfig.from_json({
         'color':
         'red',
         'poly_points': [
             (0.1, 0.1),
             (0.6, 0.1),  # top left, top right
             (0.6, 0.4),
             (0.1, 0.4)  # bottom right, bottom left
         ]
     })
     image_filter = FillFilter(layer_config=layer_config,
                               filter_context=filter_context)
     source_image = np.zeros((10, 10, 3), dtype=np.float32)
     result_image = image_filter.filter(source_image)
     LOGGER.debug('result_image:\n%s', result_image)
     mask = np.zeros(source_image.shape)
     mask[1:5, 1:7] = 1
     masked_result_image: np.ndarray = ma.masked_array(result_image, mask)
     poly_area = result_image[1:5, 1:7]
     LOGGER.debug('poly_area:\n%s', poly_area)
     assert result_image.shape == source_image.shape
     assert np.all(poly_area == (255, 0, 0))
     LOGGER.debug('mask:\n%s', mask)
     LOGGER.debug('masked_result_image:\n%s', masked_result_image)
     assert np.all(masked_result_image == (0, 0, 0))
Example #10
0
 def test_should_not_apply_empty_override_map(self):
     app_config = AppConfig(
         layers=[LayerConfig({
             'id': 'id1',
             'prop': 'value1'
         })])
     apply_config_override_map(app_config, {})
     assert app_config.layers[0].get('prop') == 'value1'
Example #11
0
 def test_should_override_prop_of_root_layer(self):
     app_config = AppConfig(
         layers=[LayerConfig({
             'id': 'id1',
             'prop': 'value1'
         })])
     apply_config_override_map(app_config, {'id1': {'prop': 'new-value'}})
     assert app_config.layers[0].get('prop') == 'new-value'
Example #12
0
 def test_should_fill_whole_image(self, filter_context: FilterContext):
     layer_config = LayerConfig.from_json({'color': 'red'})
     image_filter = FillFilter(layer_config=layer_config,
                               filter_context=filter_context)
     source_image = np.zeros((5, 4, 3), dtype=np.float32)
     result_image = image_filter.filter(source_image)
     LOGGER.debug('result_image:\n%s', result_image)
     assert result_image.shape == source_image.shape
     assert np.all(result_image == (255, 0, 0))
 def test_should_connect_input_to_output_layer(self):
     resolved_app_config = ResolvedAppConfig(AppConfig([
         LayerConfig({
             'id': 'in',
             'input_path': 'input_path_1'
         }),
         LayerConfig({
             'id': 'out',
             'output_path': 'output_path_1'
         })
     ]))
     assert resolved_app_config.layer_by_id['in'].get('input_path') == (
         'input_path_1'
     )
     assert resolved_app_config.layer_by_id['out'].get('output_path') == (
         'output_path_1'
     )
     assert resolved_app_config.layer_by_id['out'].input_layer_ids == ['in']
Example #14
0
 def _add_layer_recursively(
     self,
     layer_config: LayerConfig,
     default_id: str,
     default_input_layer: Optional[ResolvedLayerConfig]
 ) -> ResolvedLayerConfig:
     layer_id = layer_config.get('id') or default_id
     branches = layer_config.get('branches')
     if branches:
         return self._add_branches_recursively(
             layer_config,
             layer_id=layer_id,
             default_input_layer=default_input_layer
         )
     resolved_layer_config = ResolvedLayerConfig({
         **layer_config.props,
         'id': layer_id
     }, default_input_layer=default_input_layer)
     return self._add_resolved_layer(resolved_layer_config)
Example #15
0
 def test_should_raise_exception_if_id_was_not_found(self):
     app_config = AppConfig(
         layers=[LayerConfig({
             'id': 'id1',
             'prop': 'value1'
         })])
     with pytest.raises(ValueError):
         apply_config_override_map(app_config,
                                   {'other-id': {
                                       'prop': 'new-value'
                                   }})
 def test_should_connect_input_to_branch_layers(self):
     resolved_app_config = ResolvedAppConfig(AppConfig([
         LayerConfig({
             'id': 'in',
             'input_path': 'input_path_1'
         }),
         LayerConfig({
             'id': 'branches',
             'branches': [{
                 'layers': [{
                     'id': 'branch_1_layer_1',
                     'filter': 'dummy'
                 }]
             }, {
                 'layers': [{
                     'id': 'branch_2_layer_1',
                     'filter': 'dummy'
                 }]
             }]
         }),
         LayerConfig({
             'id': 'out',
             'output_path': 'output_path_1'
         })
     ]))
     assert resolved_app_config.layer_by_id['in'].get('input_path') == (
         'input_path_1'
     )
     assert resolved_app_config.layer_by_id['out'].get('output_path') == (
         'output_path_1'
     )
     assert resolved_app_config.layer_by_id['branch_1_layer_1'].input_layer_ids == ['in']
     assert resolved_app_config.layer_by_id['branch_2_layer_1'].input_layer_ids == ['in']
     assert resolved_app_config.layer_by_id['branches'].input_layer_ids == [
         'branch_1_layer_1', 'branch_2_layer_1'
     ]
     assert resolved_app_config.layer_by_id['out'].input_layer_ids == ['branches']
Example #17
0
 def test_should_override_prop_of_nested_layer(self):
     app_config = AppConfig(layers=[
         LayerConfig({
             'id':
             'id1',
             'branches': [{
                 'layers': [{
                     'id': 'nested',
                     'prop': 'value1'
                 }]
             }]
         })
     ])
     apply_config_override_map(app_config,
                               {'nested': {
                                   'prop': 'new-value'
                               }})
     assert app_config.layers[0].get(
         'branches')[0]['layers'][0]['prop'] == 'new-value'