Ejemplo n.º 1
0
def filter_objects_by_area(ann: Annotation, classes: List[str], comparator=operator.lt,
                           thresh_percent: float = None) -> Annotation:  # @ TODO: add size mode
    """
    Deletes labels less (or greater) than specified percentage of image area.

    Args
        ann: Input annotation.
        classes: List of classes to filter.
        comparator: Comparison function.
        thresh_percent: Threshold percent value of image area.
    Returns:
        Annotation containing filtered labels.
    """
    imsize = ann.img_size
    img_area = float(imsize[0] * imsize[1])

    def _del_filter_percent(label: Label):
        if label.obj_class.name in classes:
            fig_area = label.area
            area_percent = 100.0 * fig_area / img_area
            if comparator(area_percent, thresh_percent):  # satisfied condition
                return []  # action 'delete'
        return [label]

    return ann.transform_labels(imsize, _del_filter_percent)
Ejemplo n.º 2
0
def drop_object_by_class(ann: Annotation, classes: List[str]) -> Annotation:
    """
    Removes labels of specified classes from annotation.

    Args:
        ann: Input annotation.
        classes: List of classes to remove.
    Returns:
        Annotation with removed labels of specified classes.
    """
    def _filter(label: Label):
        if label.obj_class.name in classes:
            return [label]
        return []
    return ann.transform_labels(_filter)
Ejemplo n.º 3
0
def bitwise_mask(ann: Annotation, class_mask: str, classes_to_correct: List[str],
                 bitwise_op: Callable[[np.ndarray, np.ndarray], np.ndarray] = np.logical_and) -> Annotation:
    """
    Performs bitwise operation between two masks. Uses one target mask to correct all others.

    Args
        ann: Input annotation.
        class_mask: Class name of target mask.
        classes_to_correct: List of classes which will be corrected using target mask.
        bitwise_op: Bitwise numpy function to process masks.For example: "np.logical_or", "np.logical_and",
         "np.logical_xor".
    Returns:
        Annotation containing corrected Bitmaps.
    """
    imsize = ann.img_size

    def find_mask_class(labels, class_mask_name):
        for label in labels:
            if label.obj_class.name == class_mask_name:
                if not isinstance(label.geometry, Bitmap):
                    raise RuntimeError('Class <{}> must be a Bitmap.'.format(class_mask_name))
                return label

    mask_label = find_mask_class(ann.labels, class_mask)
    if mask_label is not None:
        target_original, target_mask = mask_label.geometry.origin, mask_label.geometry.data
        full_target_mask = np.full(imsize, False, bool)

        full_target_mask[target_original.row:target_original.row + target_mask.shape[0],
                         target_original.col:target_original.col + target_mask.shape[1]] = target_mask

        def perform_op(label):
            if label.obj_class.name not in classes_to_correct or label.obj_class.name == class_mask:
                return [label]

            if not isinstance(label.geometry, Bitmap):
                raise RuntimeError('Input class must be a Bitmap.')

            new_geom = label.geometry.bitwise_mask(full_target_mask, bitwise_op)
            return [label.clone(geometry=new_geom)] if new_geom is not None else []

        res_ann = ann.transform_labels(perform_op)
    else:
        res_ann = ann.clone()

    return res_ann
Ejemplo n.º 4
0
def find_contours(ann: Annotation, classes_mapping: dict) -> Annotation:  # @TODO: approximation dropped
    """

    Args:
        ann: Input annotation.
        classes_mapping: Dict matching source class names and new ObjClasses
    Returns:
        Annotation with Bitmaps converted to contours Polygons.
    """
    def to_contours(label: Label):
        new_obj_cls = classes_mapping.get(label.obj_class.name)
        if new_obj_cls is None:
            return [label]
        if not isinstance(label.geometry, Bitmap):
            raise RuntimeError('Input class must be a Bitmap.')

        return [Label(geometry=geom, obj_class=new_obj_cls) for geom in label.geometry.to_contours()]

    return ann.transform_labels(to_contours)
Ejemplo n.º 5
0
def approximate_vector(ann: Annotation, classes: List[str], epsilon: float) -> Annotation:
    """
    Approximates vector figures: lines and polygons.

    Args:
        ann: Input annotations.
        classes: List of classes to apply transformation.
        epsilon: Approximation accuracy (maximum distance between the original curve and its approximation)
    Returns:
        Annotation with approximated vector figures of selected classes.
    """
    def _approx(label: Label):
        if label.obj_class.name not in classes:
            return [label]

        if not isinstance(label.geometry, (Polygon, Polyline)):
            raise RuntimeError('Input class must be a Polygon or a Line.')

        return [label.clone(geometry=label.geometry.approx_dp(epsilon))]

    return ann.transform_labels(_approx)
Ejemplo n.º 6
0
def skeletonize_bitmap(ann: Annotation, classes: List[str], method_id: SkeletonizeMethod) -> Annotation:
    """
    Extracts skeletons from bitmap figures.

    Args:
        ann: Input annotation.
        classes: List of classes to skeletonize.
        method_id: Algorithm of processing. See supervisely.geometry.bitmap.SkeletonizeMethod enum.
    Returns:
        Annotation with skeletonized labels.
    """
    def _skel(label: Label):
        if label.obj_class.name not in classes:
            return [label]

        if not isinstance(label.geometry, Bitmap):
            raise RuntimeError('Input class must be a Bitmap.')

        return [label.clone(geometry=label.geometry.skeletonize(method_id))]

    return ann.transform_labels(_skel)