def __init__(self, config: dict, in_meta: ProjectMeta,
                 model: SingleImageInferenceBase):
        super().__init__(config, in_meta, model)

        # If saving the bounding boxes on which inference was called is requested, create separate classes
        # for those bounding boxes by renaming the source object classes.
        self._renamer_intermediate = None
        if self._config[SAVE]:
            renamer_intermediate = Renamer(
                add_suffix=self._config[Renamer.ADD_SUFFIX],
                enabled_classes=self._config[FROM_CLASSES])
            # First simply rename the matching source classes.
            intermediate_renamed_classes = make_renamed_classes(
                in_meta.obj_classes, renamer_intermediate, skip_missing=True)
            # Next, change the geometry type for the intermediate bounding box classes to Rectangle.
            intermediate_renamed_rectangle_classes = ObjClassCollection(items=[
                renamed_class.clone(geometry_type=Rectangle)
                for renamed_class in intermediate_renamed_classes
            ])
            # Add the renamed Rectangle classes to the output meta and set up a class mapper.
            self._out_meta = self._out_meta.add_obj_classes(
                intermediate_renamed_rectangle_classes)
            self._intermediate_class_mapper = RenamingObjClassMapper(
                dest_obj_classes=intermediate_renamed_rectangle_classes,
                renamer=renamer_intermediate)
Beispiel #2
0
    def to_json(self):
        '''
        The function to_json convert annotation to json format
        :return: annotation in json format
        '''
        res = {
            AnnotationJsonFields.IMG_DESCRIPTION: self.img_description,
            AnnotationJsonFields.IMG_SIZE: {
                AnnotationJsonFields.IMG_SIZE_HEIGHT: int(self.img_size[0]),
                AnnotationJsonFields.IMG_SIZE_WIDTH: int(self.img_size[1])
            },
            AnnotationJsonFields.IMG_TAGS: self.img_tags.to_json(),
            AnnotationJsonFields.LABELS:
            [label.to_json() for label in self.labels],
            AnnotationJsonFields.CUSTOM_DATA: self.custom_data
        }
        if len(self._pixelwise_scores_labels) > 0:
            # construct probability classes from labels
            prob_classes = {}
            for label in self._pixelwise_scores_labels:
                # @TODO: hotfix to save geometry as "multichannelBitmap" instead of "bitmap"; use normal classes
                prob_classes[label.obj_class.name] = label.obj_class.clone(
                    geometry_type=MultichannelBitmap)

            # save probabilities
            probabilities = {
                AnnotationJsonFields.PROBABILITY_LABELS:
                [label.to_json() for label in self._pixelwise_scores_labels],
                AnnotationJsonFields.PROBABILITY_CLASSES:
                ObjClassCollection(list(prob_classes.values())).to_json()
            }
            res[AnnotationJsonFields.CUSTOM_DATA].update(probabilities)

        return res
Beispiel #3
0
 def __init__(self, obj_classes=None, tag_metas=None):
     '''
     :param obj_classes: Collection that stores ObjClass instances with unique names.
     :param tag_metas: Collection that stores TagMeta instances with unique names.
     '''
     self._obj_classes = ObjClassCollection() if obj_classes is None else obj_classes
     self._tag_metas = take_with_default(tag_metas, TagMetaCollection())
Beispiel #4
0
 def delete_obj_classes(self, obj_class_names):
     '''
     The function delete_obj_classes delete objclasses with given list of names from ProjectMeta collection that stores ObjClass instances and return copy of ProjectMeta
     :param obj_class_names: list of names ObjClass objects to delete
     :return: ProjectMeta class object
     '''
     res_items = self._delete_items(self._obj_classes, obj_class_names)
     return self.clone(obj_classes=ObjClassCollection(res_items))
 def __init__(self,
              obj_classes=None,
              img_tag_metas=None,
              obj_tag_metas=None):
     self._obj_classes = take_with_default(obj_classes,
                                           ObjClassCollection())
     # TODO do we actualy need two sets of tags?
     self._img_tag_metas = take_with_default(img_tag_metas,
                                             TagMetaCollection())
     self._obj_tag_metas = take_with_default(obj_tag_metas,
                                             TagMetaCollection())
Beispiel #6
0
    def _load_train_config(self):  # @TODO: partly copypasted from SingleImageInferenceBase
        self._load_raw_model_config_json()

        self.classification_tags = self._model_out_img_tags()
        logger.info('Read model out tags', extra={'tags': self.classification_tags.to_json()})
        self.classification_tags_to_idx = self.train_config[self.classification_tags_to_idx_key]
        logger.info('Read model internal tags mapping', extra={'tags_mapping': self.classification_tags_to_idx})

        self._model_out_meta = ProjectMeta(obj_classes=ObjClassCollection(),
                                           img_tag_metas=self.classification_tags,
                                           obj_tag_metas=self._model_out_obj_tags())

        self.idx_to_classification_tags = {v: k for k, v in self.classification_tags_to_idx.items()}
        self._determine_model_input_size()
Beispiel #7
0
 def to_detection_task(self, convert_classes=False) -> (ProjectMeta, dict):
     mapping = {}
     res_classes = []
     for obj_class in self.obj_classes:
         obj_class: ObjClass
         if obj_class.geometry_type == Rectangle:
             mapping[obj_class] = obj_class
             res_classes.append(obj_class)
         else:
             if convert_classes is True:
                 new_class = obj_class.clone(geometry_type=Rectangle)
                 mapping[obj_class] = new_class
                 res_classes.append(new_class)
             else:
                 # ignore class
                 mapping[obj_class] = None
     res_meta = self.clone(obj_classes=ObjClassCollection(res_classes))
     return res_meta, mapping
Beispiel #8
0
    def setUp(self):
        self._obj_class_gt = ObjClass(name='a', geometry_type=Rectangle)
        self._obj_class_pred = ObjClass(name='b', geometry_type=Rectangle)
        self._confidence_tag_meta = TagMeta(name='confidence', value_type=TagValueType.ANY_NUMBER)
        self._meta = ProjectMeta(
            obj_classes=ObjClassCollection([self._obj_class_gt, self._obj_class_pred]),
            tag_metas=TagMetaCollection([self._confidence_tag_meta]))

        # Will match self._pred_obj_1
        self._gt_obj_1 = Label(obj_class=self._obj_class_gt, geometry=Rectangle(0, 0, 10, 10))

        # Will match self._pred_obj_3
        self._gt_obj_2 = Label(obj_class=self._obj_class_gt, geometry=Rectangle(13, 13, 15, 15))

        # Will be a false negative
        self._gt_obj_3 = Label(obj_class=self._obj_class_gt, geometry=Rectangle(43, 43, 45, 45))

        # Will match self._gt_obj_1
        self._pred_obj_1 = Label(
            obj_class=self._obj_class_pred,
            geometry=Rectangle(0, 0, 9, 9),
            tags=TagCollection([Tag(meta=self._confidence_tag_meta, value=0.7)]))

        # Will be a false positive (self._pred_obj_1 has higher IoU).
        self._pred_obj_2 = Label(
            obj_class=self._obj_class_pred,
            geometry=Rectangle(0, 0, 8, 8),
            tags=TagCollection([Tag(meta=self._confidence_tag_meta, value=0.6)]))

        # Will match self._gt_obj_2
        self._pred_obj_3 = Label(
            obj_class=self._obj_class_pred,
            geometry=Rectangle(13, 13, 15, 15),
            tags=TagCollection([Tag(meta=self._confidence_tag_meta, value=0.1)]))

        # More false positives.
        self._pred_objs_fp = [
            Label(obj_class=self._obj_class_pred,
                  geometry=Rectangle(20, 20, 30, 30),
                  tags=TagCollection([Tag(meta=self._confidence_tag_meta, value=v / 100)]))
            for v in range(15, 85, 10)]

        self._metric_calculator = MAPMetric(class_mapping={'a': 'b'}, iou_threshold=0.5)
Beispiel #9
0
 def to_segmentation_task(self,
                          keep_geometries=[Polygon,
                                           Bitmap]) -> (ProjectMeta, dict):
     mapping = {}
     res_classes = []
     for obj_class in self.obj_classes:
         obj_class: ObjClass
         if obj_class.geometry_type in keep_geometries:
             if obj_class.geometry_type == Bitmap:
                 mapping[obj_class] = obj_class
                 res_classes.append(obj_class)
             else:
                 new_class = obj_class.clone(geometry_type=Bitmap)
                 mapping[obj_class] = new_class
                 res_classes.append(new_class)
         else:
             mapping[obj_class] = None
     res_meta = self.clone(obj_classes=ObjClassCollection(res_classes))
     return res_meta, mapping
 def delete_obj_classes(self, obj_class_names):
     res_items = self._delete_items(self._obj_classes, obj_class_names)
     return self.clone(obj_classes=ObjClassCollection(res_items))