def annotations_to_add(self) -> List[Annotation]: labels_to_add = self.labels_to_add() annotation_to_add = Annotation( shape=Rectangle(x1=0.1, y1=0.1, x2=0.7, y2=0.8), labels=[ScoredLabel(label=labels_to_add[0])], id=ID("added_annotation_1"), ) other_annotation_to_add = Annotation( shape=Rectangle(x1=0.2, y1=0.3, x2=0.8, y2=0.9), labels=[ScoredLabel(label=labels_to_add[1])], id=ID("added_annotation_2"), ) return [annotation_to_add, other_annotation_to_add]
def test_rectangle_crop_numpy_array(self): """ <b>Description:</b> Check Rectangle crop_numpy_array method <b>Input data:</b> Rectangle class initiation parameters <b>Expected results:</b> Test passes if crop_numpy_array method return expected cropped array <b>Steps</b> 1. Check crop_numpy_array method for Rectangle with parameters less than 0 2. Check crop_numpy_array method for Rectangle with parameters range from 0 to 1 3. Check crop_numpy_array method for Rectangle with parameters more than 1 """ image_height = image_width = 128 numpy_image_array = np.random.uniform( low=0.0, high=255.0, size=(image_height, image_width, 3) ) scenarios = [ { "input_params": {"x1": -0.2, "x2": -0.1, "y1": -0.3, "y2": -0.2}, "cropped_expected": {"x1": 0, "y1": 0, "x2": 0, "y2": 0}, }, { "input_params": {"x1": 0.2, "x2": 0.3, "y1": 0.4, "y2": 0.8}, "cropped_expected": {"x1": 26, "y1": 51, "x2": 38, "y2": 102}, }, { "input_params": {"x1": 1.1, "x2": 1.3, "y1": 1.1, "y2": 1.5}, "cropped_expected": {"x1": 141, "y1": 141, "x2": 166, "y2": 192}, }, ] for rectangle_parameters in scenarios: with warnings.catch_warnings(): warnings.filterwarnings("ignore", "Rectangle coordinates") rectangle = Rectangle(**rectangle_parameters.get("input_params")) expected_output = rectangle_parameters.get("cropped_expected") actual_cropped_image_array = rectangle.crop_numpy_array(numpy_image_array) expected_image_array = numpy_image_array[ expected_output.get("y1") : expected_output.get("y2"), expected_output.get("x1") : expected_output.get("x2"), ::, ] assert actual_cropped_image_array.shape[2] == 3 try: assert (expected_image_array == actual_cropped_image_array).all() except AttributeError: raise AssertionError("Unequal expected and cropped image arrays")
def annotations(self) -> List[Annotation]: labels = self.labels() rectangle = Rectangle(x1=0.2, y1=0.2, x2=0.6, y2=0.7) other_rectangle = Rectangle(x1=0.3, y1=0.2, x2=0.9, y2=0.9) detection_annotation = Annotation( shape=rectangle, labels=[ScoredLabel(label=labels[0])], id=ID("detection_annotation_1"), ) segmentation_annotation = Annotation( shape=other_rectangle, labels=[ScoredLabel(label=labels[1])], id=ID("segmentation_annotation_1"), ) return [detection_annotation, segmentation_annotation]
def test_rectangle_denormalize_wrt_roi_shape(self): """ <b>Description:</b> Check Rectangle denormalize_wrt_roi_shape method <b>Input data:</b> Instance of Rectangle class <b>Expected results:</b> Test passes if denormalize_wrt_roi_shape method return expected instance of Rectangle class <b>Steps</b> 1. Check values returned by denormalized Rectangle instance 2. Check raise ValueError exception when roi parameter has unexpected type """ # Positive scenario rectangle = self.horizontal_rectangle() roi_shape = Rectangle(x1=0.2, y1=0.2, x2=0.4, y2=0.4) with warnings.catch_warnings(): warnings.filterwarnings("ignore", "Rectangle coordinates") denormalized = rectangle.denormalize_wrt_roi_shape(roi_shape) assert denormalized.x1 == -0.5 assert denormalized.y1 == -1.0 assert denormalized.x2 == 1.0 assert denormalized.y2 == 0.0 assert denormalized.modification_date == rectangle.modification_date # Negative scenario with pytest.raises(ValueError): rectangle.denormalize_wrt_roi_shape(str)
def test_rectangle_generate_full_box(self): """ <b>Description:</b> Check Rectangle generate_full_box method <b>Input data:</b> Labels specified for full_box instance of Rectangle class <b>Expected results:</b> Test passes if generate_full_box method returns instance of Rectangle class with coordinates (x1=0.0, y1=0.0, x2=1.0, y2=1.0) <b>Steps</b> 1. Check generate_full_box method for Rectangle instance with no labels specified 2. Check generate_full_box method for Rectangle instance with labels specified """ detection_label = ScoredLabel( LabelEntity(name="detection", domain=Domain.DETECTION) ) for label_actual, label_expected in [ (None, []), ([detection_label], [detection_label]), ]: full_box = Rectangle.generate_full_box(label_actual) assert full_box.type == ShapeType.RECTANGLE assert full_box.x1 == full_box.y1 == 0.0 assert full_box.x2 == full_box.y2 == 1.0 assert full_box._labels == label_expected
def test_polygon_denormalize_wrt_roi_shape(self): """ <b>Description:</b> Check Polygon denormalize_wrt_roi_shape methods <b>Input data:</b> Initialized instance of Polygon Initialized instance of Rectangle <b>Expected results:</b> Test passes if Polygon denormalize_wrt_roi_shape returns correct values <b>Steps</b> 1. Initialize Polygon instance 2. Check returning value """ polygon = self.polygon() roi = Rectangle(x1=0.5, x2=1.0, y1=0.0, y2=1.0) denormalized = polygon.denormalize_wrt_roi_shape(roi) assert len(denormalized.points) == 3 assert denormalized.min_x == 0.0 assert denormalized.max_x == 0.5 assert denormalized.min_y == 0.0 assert denormalized.max_y == 0.2 with pytest.raises(ValueError): polygon.denormalize_wrt_roi_shape("123")
def optional_result_media_parameters(self) -> dict: optional_result_media_parameters = self.default_result_media_parameters( ) roi_label = LabelEntity( "ROI label", Domain.DETECTION, Color(10, 200, 40), creation_date=datetime.datetime(year=2021, month=12, day=18), id=ID("roi_label_1"), ) roi = Annotation( shape=Rectangle(x1=0.3, y1=0.2, x2=0.7, y2=0.6), labels=[ScoredLabel(roi_label)], id=ID("roi_annotation"), ) result_media_label = LabelEntity( "ResultMedia label", Domain.CLASSIFICATION, Color(200, 60, 100), creation_date=datetime.datetime(year=2021, month=12, day=20), id=ID("result_media_1"), ) optional_result_media_parameters["roi"] = roi optional_result_media_parameters["label"] = result_media_label return optional_result_media_parameters
def normalize_wrt_roi_shape(self, roi_shape: Rectangle) -> "Ellipse": """ Transforms from the `roi` coordinate system to the normalized coordinate system. This function is the inverse of ``denormalize_wrt_roi_shape``. :example: Assume we have Ellipse `c1` which lives in the top-right quarter of a 2D space. The 2D space where `c1` lives in is an `roi` living in the top-left quarter of the normalized coordinate space. This function returns Ellipse `c1` expressed in the normalized coordinate space. >>> from ote_sdk.entities.annotation import Annotation >>> from ote_sdk.entities.shapes.rectangle import Rectangle >>> from ote_sdk.entities.shapes.ellipse import Ellipse >>> c1 = Ellipse(x1=0.5, y1=0.5, x2=0.6, y2=0.6) >>> roi = Rectangle(x1=0.0, x2=0.5, y1=0.0, y2=0.5) >>> normalized = c1.normalize_wrt_roi_shape(roi_shape) >>> normalized Ellipse(, x1=0.25, y1=0.25, x2=0.3, y2=0.3, scored_labels=[]) :param roi_shape: Region of Interest :return: New polygon in the image coordinate system """ if not isinstance(roi_shape, Rectangle): raise ValueError("roi_shape has to be a Rectangle.") roi_shape = roi_shape.clip_to_visible_region() return Ellipse( x1=self.x1 * roi_shape.width + roi_shape.x1, y1=self.y1 * roi_shape.height + roi_shape.y1, x2=self.x2 * roi_shape.width + roi_shape.x1, y2=self.y2 * roi_shape.height + roi_shape.y1, )
def generate(self) -> DatasetEntity: """ Generate OTE Anomaly Dataset Returns: DatasetEntity: Output OTE Anomaly Dataset from an MVTec """ samples = self.get_samples() dataset_items: List[DatasetItemEntity] = [] for _, sample in tqdm(samples.iterrows()): # Create image image = Image(file_path=sample.image_path) # Create annotation shape = Rectangle(x1=0, y1=0, x2=1, y2=1) labels = [ScoredLabel(sample.label)] annotations = [Annotation(shape=shape, labels=labels)] annotation_scene = AnnotationSceneEntity(annotations=annotations, kind=AnnotationSceneKind.ANNOTATION) # Create dataset item dataset_item = DatasetItemEntity(media=image, annotation_scene=annotation_scene, subset=sample.subset) # Add to dataset items dataset_items.append(dataset_item) dataset = DatasetEntity(items=dataset_items) return dataset
def denormalize_wrt_roi_shape(self, roi_shape: Rectangle) -> "Polygon": """ Transforming shape from the normalized coordinate system to the `roi` coordinate system. This function is the inverse of ``normalize_wrt_roi_shape`` :example: Assume we have Polygon `p1` which lives in the top-right quarter of the normalized coordinate space. The `roi` is a rectangle living in the half right of the normalized coordinate space. This function returns Polygon `p1` expressed in the coordinate space of `roi`. (should return top-half) Polygon denormalized to a rectangle as ROI >>> from ote_sdk.entities.shapes.rectangle import Rectangle >>> from ote_sdk.entities.annotation import Annotation >>> p1 = Polygon(points=[Point(x=0.5, y=0.0), Point(x=0.75, y=0.2), Point(x=0.6, y=0.1)]) >>> roi = Rectangle(x1=0.5, x2=1.0, y1=0.0, y2=1.0) # the half-right >>> normalized = p1.denormalize_wrt_roi_shape(roi_shape) >>> normalized Polygon(, len(points)=3, scored_labels=[]) :param roi_shape: Region of Interest :return: New polygon in the ROI coordinate system """ if not isinstance(roi_shape, Rectangle): raise ValueError("roi_shape has to be a Rectangle.") roi_shape = roi_shape.clip_to_visible_region() points = [p.denormalize_wrt_roi_shape(roi_shape) for p in self.points] return Polygon(points=points)
def on_predict_epoch_end(self, _trainer: pl.Trainer, _pl_module: AnomalyModule, outputs: List[Any]): """Called when the predict epoch ends.""" outputs = outputs[0] pred_scores = np.hstack( [output["pred_scores"].cpu() for output in outputs]) pred_labels = np.hstack( [output["pred_labels"].cpu() for output in outputs]) anomaly_maps = np.vstack( [output["anomaly_maps"].cpu() for output in outputs]) # Loop over dataset again to assign predictions for dataset_item, pred_score, pred_label, anomaly_map in zip( self.ote_dataset, pred_scores, pred_labels, anomaly_maps): assigned_label = self.anomalous_label if pred_label else self.normal_label shape = Annotation( Rectangle(x1=0, y1=0, x2=1, y2=1), labels=[ ScoredLabel(assigned_label, probability=float(pred_score)) ], ) dataset_item.append_annotations([shape]) heatmap = anomaly_map_to_color_map(anomaly_map.squeeze()) heatmap_media = ResultMediaEntity( name="Anomaly Map", type="anomaly_map", annotation_scene=dataset_item.annotation_scene, numpy=heatmap, ) dataset_item.append_metadata_item(heatmap_media)
def normalize_wrt_roi_shape(self, roi_shape: Rectangle) -> "Polygon": """ Transforms from the `roi` coordinate system to the normalized coordinate system. This function is the inverse of ``denormalize_wrt_roi_shape``. :example: Assume we have Polygon `p1` which lives in the top-right quarter of a 2D space. The 2D space where `p1` lives in is an `roi` living in the top-left quarter of the normalized coordinate space. This function returns Polygon `p1` expressed in the normalized coordinate space. >>> from ote_sdk.entities.annotation import Annotation >>> from ote_sdk.entities.shapes.rectangle import Rectangle >>> p1 = Polygon(points=[Point(x=0.5, y=0.0), Point(x=0.75, y=0.2), Point(x=0.6, y=0.1)]) >>> roi = Rectangle(x1=0.0, x2=0.5, y1=0.0, y2=0.5) >>> normalized = p1.normalize_wrt_roi_shape(roi_shape) >>> normalized Polygon(, len(points)=3, scored_labels=[]) :param roi_shape: Region of Interest :return: New polygon in the image coordinate system """ if not isinstance(roi_shape, Rectangle): raise ValueError("roi_shape has to be a Rectangle.") roi_shape = roi_shape.clip_to_visible_region() points = [p.normalize_wrt_roi(roi_shape) for p in self.points] return Polygon(points=points)
def test_produces_valid_crop(self): """ <b>Description:</b> Checks that shape_produces_valid_crop returns the correct values and does not raise errors <b>Input data:</b> A valid Rectangle at [0, 0.4, 1, 0.5] A Polygon that has an invalid bounding box <b>Expected results:</b> The test passes if the call with the Rectangle returns True and the one with the polygon returns False <b>Steps</b> 1. Check Valid Rectangle 2. Check invalid Polygon """ rectangle = Rectangle(x1=0, y1=0.4, x2=1, y2=0.5) assert ShapeFactory.shape_produces_valid_crop(rectangle, 100, 100) point1 = Point(x=0.01, y=0.1) point2 = Point(x=0.35, y=0.1) point3 = Point(x=0.35, y=0.1) polygon = Polygon(points=[point1, point2, point3]) assert not ShapeFactory.shape_produces_valid_crop(polygon, 100, 250)
def default_result_media_parameters() -> dict: rectangle_label = LabelEntity( name="Rectangle Annotation Label", domain=Domain.DETECTION, color=Color(100, 200, 60), creation_date=datetime.datetime(year=2021, month=12, day=16), id=ID("rectangle_label_1"), ) rectangle_annotation = Annotation( shape=Rectangle(x1=0.1, y1=0.4, x2=0.4, y2=0.9), labels=[ScoredLabel(rectangle_label)], id=ID("rectangle_annotation"), ) annotation_scene = AnnotationSceneEntity( annotations=[rectangle_annotation], kind=AnnotationSceneKind.ANNOTATION, creation_date=datetime.datetime(year=2021, month=12, day=16), id=ID("annotation_scene"), ) return { "name": "ResultMedia name", "type": "Test ResultMedia", "annotation_scene": annotation_scene, "numpy": RANDOM_IMAGE, }
def __init__( self, media: IMedia2DEntity, annotation_scene: AnnotationSceneEntity, roi: Optional[Annotation] = None, metadata: Optional[Sequence[MetadataItemEntity]] = None, subset: Subset = Subset.NONE, ): self.__media: IMedia2DEntity = media self.__annotation_scene: AnnotationSceneEntity = annotation_scene self.__subset: Subset = subset self.__roi_lock = Lock() # set ROI if roi is None: for annotation in annotation_scene.annotations: # if there is a full box in annotation.shapes, set it as ROI if Rectangle.is_full_box(annotation.shape): roi = annotation break self.__roi = roi self.__metadata: List[MetadataItemEntity] = [] if metadata is not None: self.__metadata = list(metadata)
def denormalize_wrt_roi_shape(self, roi_shape: Rectangle) -> "Ellipse": """ Transforming shape from the normalized coordinate system to the `roi` coordinate system. This function is the inverse of ``normalize_wrt_roi_shape`` :example: Assume we have Ellipse `c1` which lives in the top-right quarter of the normalized coordinate space. The `roi` is a rectangle living in the half right of the normalized coordinate space. This function returns Ellipse `c1` expressed in the coordinate space of `roi`. (should return top-half) Ellipse denormalized to a rectangle as ROI >>> from ote_sdk.entities.annotation import Annotation >>> from ote_sdk.entities.shapes.ellipse import Ellipse >>> c1 = Ellipse(x1=0.5, x2=1.0, y1=0.0, y2=0.5) # An ellipse in the top right >>> roi = Rectangle(x1=0.5, x2=1.0, y1=0.0, y2=1.0) # the half-right >>> normalized = c1.denormalize_wrt_roi_shape(roi_shape) # should return top half >>> normalized Ellipse(, x1=0.0, y1=0.0, x2=1.0, y2=0.5, scored_labels=[]) :param roi_shape: Region of Interest :return: New polygon in the ROI coordinate system """ if not isinstance(roi_shape, Rectangle): raise ValueError("roi_shape has to be a Rectangle.") roi_shape = roi_shape.clip_to_visible_region() x1 = (self.x1 - roi_shape.x1) / roi_shape.width y1 = (self.y1 - roi_shape.y1) / roi_shape.height x2 = (self.x2 - roi_shape.x1) / roi_shape.width y2 = (self.y2 - roi_shape.y1) / roi_shape.height return Ellipse(x1=x1, y1=y1, x2=x2, y2=y2)
def test_ellipse_denormalize_wrt_roi_shape(self): """ <b>Description:</b> Check Ellipse denormalize_wrt_roi_shape methods <b>Input data:</b> Initialized instance of Ellipse Initialized instance of Rectangle <b>Expected results:</b> Test passes if Ellipse denormalize_wrt_roi_shape returns correct values <b>Steps</b> 1. Initialize Ellipse instance 2. Check returning value """ ellipse = self.ellipse() roi = Rectangle(x1=0.5, x2=1.0, y1=0.0, y2=1.0) denormalized = ellipse.denormalize_wrt_roi_shape(roi) assert denormalized.x1 == 0.0 assert denormalized.y1 == 0.0 assert denormalized.x2 == 1.0 assert denormalized.y2 == 0.5 with pytest.raises(ValueError): ellipse.denormalize_wrt_roi_shape("123")
def test_dataset_item_roi(self): """ <b>Description:</b> Check DatasetItemEntity class "roi" property <b>Input data:</b> DatasetItemEntity class object with specified "media", "annotation_scene", "roi", "metadata" and "subset" parameters <b>Expected results:</b> Test passes if value returned by "roi" property is equal to expected <b>Steps</b> 1. Check value returned by "roi" property for DatasetItemEntity with specified "roi" parameter 2. Check value returned by "roi" property for DatasetItemEntity with not specified "roi" parameter 3. Check value returned by "roi" property for DatasetItemEntity with not specified "roi" parameter but one of annotation objects in annotation_scene is equal to full Rectangle """ media = DatasetItemParameters.generate_random_image() annotations = DatasetItemParameters().annotations() annotation_scene = DatasetItemParameters().annotations_entity() roi = DatasetItemParameters().roi() metadata = DatasetItemParameters.metadata() # Checking "roi" property for DatasetItemEntity with specified "roi" parameter specified_roi_dataset_item = DatasetItemParameters().dataset_item() assert specified_roi_dataset_item.roi == roi # Checking that "roi" property is equal to full_box for DatasetItemEntity with not specified "roi" parameter non_specified_roi_dataset_item = DatasetItemEntity(media, annotation_scene, metadata=metadata) default_roi = non_specified_roi_dataset_item.roi.shape assert isinstance(default_roi, Rectangle) assert Rectangle.is_full_box(default_roi) # Checking that "roi" property will be equal to full_box for DatasetItemEntity with not specified "roi" but one # of Annotation objects in annotation_scene is equal to full Rectangle full_box_label = LabelEntity("Full-box label", Domain.DETECTION, id=ID("full_box_label")) full_box_annotation = Annotation(Rectangle.generate_full_box(), [ScoredLabel(full_box_label)]) annotations.append(full_box_annotation) annotation_scene.annotations.append(full_box_annotation) full_box_label_dataset_item = DatasetItemEntity(media, annotation_scene, metadata=metadata) assert full_box_label_dataset_item.roi is full_box_annotation
def roi(self) -> Annotation: """Region Of Interest.""" with self.__roi_lock: if self.__roi is None: requested_roi = Annotation(Rectangle.generate_full_box(), labels=[]) self.__roi = requested_roi else: requested_roi = self.__roi return requested_roi
def get_annotations( self, labels: Optional[List[LabelEntity]] = None, include_empty: bool = False, ios_threshold: float = 0.0, ) -> List[Annotation]: """ Returns a list of annotations that exist in the dataset item (wrt. ROI) :param labels: Subset of input labels to filter with; if ``None``, all the shapes within the ROI are returned :param include_empty: if True, returns both empty and non-empty labels :param ios_threshold: Only return shapes where Area(self.roi ∩ shape)/ Area(shape) > ios_threshold. :return: The intersection of the input label set and those present within the ROI """ is_full_box = Rectangle.is_full_box(self.roi.shape) annotations = [] if is_full_box and labels is None and not include_empty: # Fast path for the case where we do not need to change the shapes annotations = self.annotation_scene.annotations else: # Todo: improve speed. This is O(n) for n shapes. roi_as_box = ShapeFactory.shape_as_rectangle(self.roi.shape) labels_set = {label.name for label in labels} if labels is not None else {} for annotation in self.annotation_scene.annotations: if (not is_full_box and self.roi.shape.intersect_percentage( annotation.shape) <= ios_threshold): continue shape_labels = annotation.get_labels(include_empty) if labels is not None: shape_labels = [ label for label in shape_labels if label.name in labels_set ] if len(shape_labels) == 0: continue if not is_full_box: # Create a denormalized copy of the shape. shape = annotation.shape.denormalize_wrt_roi_shape( roi_as_box) else: # Also create a copy of the shape, so that we can safely modify the labels # without tampering with the original shape. shape = copy.deepcopy(annotation.shape) annotations.append(Annotation(shape=shape, labels=shape_labels)) return annotations
def upper_side_intersect_shapes() -> list: return [ Rectangle(x1=0.2, y1=0.4, x2=0.5, y2=0.7), Polygon([ Point(0.35, 0.7), Point(0.2, 0.6), Point(0.2, 0.4), Point(0.5, 0.4), Point(0.5, 0.6), Point(0.35, 0.7), ]), ]
def lower_side_intersect_shapes() -> list: return [ Rectangle(x1=0.2, y1=0.1, x2=0.5, y2=0.4), Polygon([ Point(0.35, 0.1), Point(0.2, 0.2), Point(0.2, 0.4), Point(0.5, 0.4), Point(0.5, 0.2), Point(0.35, 0.1), ]), ]
def test_result_media_eq(self): """ <b>Description:</b> Check ResultMediaEntity class object __eq__ method <b>Input data:</b> ResultMediaEntity class objects with specified "name", "type", "annotation_scene", "numpy", "roi" and "label" parameters <b>Expected results:</b> Test passes if value returned by __eq__ method is equal to expected <b>Steps</b> 1. Check value returned by __eq__ method for comparing equal ResultMediaEntity objects 2. Check value returned by __eq__ method for comparing ResultMediaEntity objects with unequal "name", "type", "label" and "numpy" parameters - expected equality 3. Check value returned by __eq__ method for comparing ResultMediaEntity objects with unequal "annotation_scene" and "roi" parameters - expected inequality 4. Check value returned by __eq__ method for comparing ResultMediaEntity with different type object """ initialization_params = self.optional_result_media_parameters() result_media = ResultMediaEntity(**initialization_params) # Comparing equal ResultMediaEntity objects equal_result_media = ResultMediaEntity(**initialization_params) assert result_media == equal_result_media # Comparing ResultMediaEntity objects with unequal "name", "type", "label" and "numpy" parameters, # expected equality unequal_values = { "name": "Unequal name", "type": "Unequal type", "label": LabelEntity("Unequal label", Domain.CLASSIFICATION), "numpy": np.random.uniform(low=0.0, high=255.0, size=(1, 2, 3)), } for key in unequal_values: unequal_params = dict(initialization_params) unequal_params[key] = unequal_values.get(key) equal_result_media = ResultMediaEntity(**unequal_params) assert result_media == equal_result_media # Comparing ResultMediaEntity objects with unequal "annotation_scene" and "roi" parameters, expected inequality unequal_values = { "annotation_scene": AnnotationSceneEntity(annotations=[], kind=AnnotationSceneKind.NONE), "roi": Rectangle.generate_full_box(), } for key in unequal_values: unequal_params = dict(initialization_params) unequal_params[key] = unequal_values.get(key) unequal_result_media = ResultMediaEntity(**unequal_params) assert result_media != unequal_result_media # Comparing ResultMediaEntity with different type object assert result_media != str
def test_rectangle_is_full_box(self): """ <b>Description:</b> Check Rectangle is_full_box method <b>Input data:</b> Rectangle class initiation parameters <b>Expected results:</b> Test passes if is_full_box method return expected bool value <b>Steps</b> 1. Check positive scenario for is_full_box method: x1=y1=0, x2=y2=1 2. Check negative scenarios for is_full_box method """ full_box_rectangle_params = {"x1": 0.0, "y1": 0.0, "x2": 1.0, "y2": 1.0} # Positive scenario for Rectangle instance full_box_rectangle = Rectangle(**full_box_rectangle_params) assert Rectangle.is_full_box(full_box_rectangle) # Negative scenarios for Rectangle instance # Generating all scenarios when Rectangle object not a full_box keys_list = ["x1", "y1", "x2", "y2"] parameter_combinations = [] for i in range(1, len(keys_list) + 1): parameter_combinations.append(list(itertools.combinations(keys_list, i))) # In each of scenario creating a copy of full_Box rectangle parameters and replacing to values from prepared # dictionary not_full_box_values_dict = {"x1": 0.01, "y1": 0.01, "x2": 0.9, "y2": 0.9} for combination in parameter_combinations: for scenario in combination: not_full_box_params = dict(full_box_rectangle_params) for key in scenario: not_full_box_params[key] = not_full_box_values_dict.get(key) not_full_box_rectangle = Rectangle(**not_full_box_params) assert not Rectangle.is_full_box(not_full_box_rectangle), ( f"Expected False returned by is_full_box method for rectangle with parameters " f"{not_full_box_params}" ) # Negative scenario for not Rectangle class instance assert not Rectangle.is_full_box(str)
def test_rectangle_coordinates_validation(self): """ <b>Description:</b> Check Rectangle coordinates <b>Input data:</b> Rectangle class initiation parameters <b>Expected results:</b> Test passes if Rectangle correctly checks coordinates during initiation of Rectangle object <b>Steps</b> 1. Check Rectangle coordinates with correct width and height 2. Check Rectangle coordinates with incorrect width: (x2 - x1) <= 0 3. Check Rectangle coordinates with incorrect height: (y2 - y1) <= 0 4. Check Rectangle coordinates with all coordinates equal 0 """ # checks for correct width and height self.horizontal_rectangle() self.vertical_rectangle() self.square() with warnings.catch_warnings(): warnings.filterwarnings("ignore", "Rectangle coordinates") Rectangle(x1=0.2, y1=0.1, x2=1.4, y2=1.5) Rectangle(x1=0.2, y1=0.1, x2=0.4, y2=0.5) # checks for incorrect coordinates width_less_than_zero_params = {"x1": 0.4, "y1": 0.0, "x2": 0.1, "y2": 0.2} width_equal_zero_params = {"x1": 0.1, "y1": 0.0, "x2": 0.1, "y2": 0.2} height_less_than_zero_params = {"x1": 0.1, "y1": 0.4, "x2": 0.3, "y2": 0.1} height_params_equal_zero_params = {"x1": 0.1, "y1": 0.4, "x2": 0.3, "y2": 0.4} zero_rectangle_params = {"x1": 0.0, "x2": 0.0, "y1": 0.0, "y2": 0.0} for incorrect_coordinates in [ width_less_than_zero_params, width_equal_zero_params, height_less_than_zero_params, height_params_equal_zero_params, zero_rectangle_params, ]: with pytest.raises(ValueError): Rectangle(**incorrect_coordinates)
def init_environment(params, model_template, number_of_images=10): resolution = (224, 224) colors = [(0, 255, 0), (0, 0, 255)] cls_names = ['b', 'g'] texts = ['Blue', 'Green'] env_labels = [ LabelEntity(name=name, domain=Domain.CLASSIFICATION, is_empty=False, id=ID(i)) for i, name in enumerate(cls_names) ] items = [] for _ in range(0, number_of_images): for j, lbl in enumerate(env_labels): class_img = np.zeros((*resolution, 3), dtype=np.uint8) class_img[:] = colors[j] class_img = cv.putText(class_img, texts[j], (50, 50), cv.FONT_HERSHEY_SIMPLEX, .8 + j * .2, colors[j - 1], 2, cv.LINE_AA) image = Image(data=class_img) labels = [ScoredLabel(label=lbl, probability=1.0)] shapes = [Annotation(Rectangle.generate_full_box(), labels)] annotation_scene = AnnotationSceneEntity( kind=AnnotationSceneKind.ANNOTATION, annotations=shapes) items.append( DatasetItemEntity(media=image, annotation_scene=annotation_scene)) rng = random.Random() rng.seed(100) rng.shuffle(items) for i, _ in enumerate(items): subset_region = i / number_of_images if subset_region >= 0.9: subset = Subset.TESTING elif subset_region >= 0.6: subset = Subset.VALIDATION else: subset = Subset.TRAINING items[i].subset = subset dataset = DatasetEntity(items) labels_schema = generate_label_schema(dataset.get_labels(), multilabel=False) environment = TaskEnvironment(model=None, hyper_parameters=params, label_schema=labels_schema, model_template=model_template) return environment, dataset
def test_shape_intersect_percentage(self): """ <b>Description:</b> Check Shape intersect_percentage method for Rectangle, Ellipse and Polygon objects <b>Expected results:</b> Test passes if intersect_percentage method returns expected values <b>Steps</b> 1. Check intersect_percentage method when Shapes intersect completely 2. Check intersect_percentage method when Shapes intersect partially 3. Check intersect_percentage method when Shapes intersect by one side 4. Check intersect_percentage method when Shapes not intersect 5. Check GeometryException exception raised with incorrect parameters for intersect_percentage method """ inscribed_shapes_list = [ self.rectangle(), self.ellipse(), self.polygon() ] # Check when Shapes intersect completely for full_element in [ self.fully_covering_rectangle(), self.fully_covering_ellipse(), self.fully_covering_polygon(), ]: for inscribed in inscribed_shapes_list: assert round(full_element.intersect_percentage(inscribed), 2) == 1.0 # Check when Shapes intersect partially second_rectangle = Rectangle(x1=0.3, y1=0.4, x2=0.7, y2=0.6) assert self.rectangle().intersect_percentage(second_rectangle) == 0.75 assert round(self.ellipse().intersect_percentage(self.rectangle()), 2) == 0.44 assert self.polygon().intersect_percentage(self.rectangle()) == 0.45 # Check when Shapes intersect by one side for upper_shape in self.upper_side_intersect_shapes(): for lower_shape in self.lower_side_intersect_shapes(): assert lower_shape.intersect_percentage(upper_shape) == 0.0 # Check shen Shapes not intersect for shape in inscribed_shapes_list: for not_inscribed_shape in ( self.not_inscribed_rectangle(), self.not_inscribed_ellipse(), self.not_inscribed_polygon(), ): assert shape.intersect_percentage(not_inscribed_shape) == 0.0 # Checking GeometryException exception raised with pytest.raises(GeometryException): with warnings.catch_warnings(): warnings.filterwarnings("ignore", "Polygon coordinates") self.base_self_intersect_polygon().intersect_percentage( self.other_self_intersect_polygon())
def check_result_media_attributes(result_media: ResultMediaEntity, expected_values: dict): assert result_media.name == expected_values.get("name") assert result_media.type == expected_values.get("type") assert result_media.annotation_scene == expected_values.get( "annotation_scene") assert np.array_equal(result_media.numpy, expected_values.get("numpy")) if not expected_values.get("roi"): assert isinstance(result_media.roi.shape, Rectangle) assert Rectangle.is_full_box(result_media.roi.shape) else: assert result_media.roi == expected_values.get("roi") assert result_media.label == expected_values.get("label")
def test_dataset_item_setters(self): """ <b>Description:</b> Check DatasetItemEntity class "roi", "subset" and "annotation_scene" setters <b>Input data:</b> DatasetItemEntity class object with specified "media", "annotation_scene", "roi", "metadata" and "subset" parameters <b>Expected results:</b> Test passes if assigned values of "roi", "subset" and "annotation_scene" properties are equal to expected <b>Steps</b> 1. Check value returned by "roi" property after using @roi.setter 2. Check value returned by "subset" property after using @subset.setter 3. Check value returned by "annotation_scene" property after using @subset.annotation_scene """ dataset_item = DatasetItemParameters().dataset_item() # Checking value returned by "roi" property after using @roi.setter new_roi_label = ScoredLabel( LabelEntity("new ROI label", Domain.DETECTION)) new_dataset_roi = Annotation(Rectangle(x1=0.2, y1=0.2, x2=1.0, y2=1.0), [new_roi_label]) dataset_item.roi = new_dataset_roi assert dataset_item.roi == new_dataset_roi # Checking value returned by subset property after using @subset.setter new_subset = Subset.TRAINING dataset_item.subset = new_subset assert dataset_item.subset == new_subset # Checking value returned by annotation_scene property after using @annotation_scene.setter new_annotation_label = ScoredLabel( LabelEntity("new annotation label", Domain.CLASSIFICATION)) new_annotation = Annotation(Rectangle(x1=0.1, y1=0, x2=0.9, y2=1.0), [new_annotation_label]) new_annotation_scene = AnnotationSceneEntity( [new_annotation], AnnotationSceneKind.PREDICTION) dataset_item.annotation_scene = new_annotation_scene assert dataset_item.annotation_scene == new_annotation_scene
def roi(self): roi = Annotation( shape=Rectangle( x1=0.1, y1=0.1, x2=0.9, y2=0.9, modification_date=datetime.datetime(year=2021, month=12, day=9), ), labels=self.roi_scored_labels(), id=ID("roi_annotation"), ) return roi