otx.api.utils.shape_factory#

This module implements helpers for converting shape entities.

Classes

ShapeFactory()

Helper class converting between shape types.

class otx.api.utils.shape_factory.ShapeFactory[source]#

Bases: object

Helper class converting between shape types.

static shape_as_ellipse(shape: ShapeEntity) Ellipse[source]#

Returns the inner-fitted ellipse for a given shape.

Parameters:

shape (ShapeEntity) – Shape to convert.

Returns:

Ellipse representation of the shape.

Return type:

Ellipse

Raises:

NotImplementedError – If the shape is not a rectangle or polygon.

static shape_as_polygon(shape: ShapeEntity) Polygon[source]#

Return a shape converted as polygon.

For a rectangle, a polygon will be constructed with a point in each corner. For a ellipse, 360 points will be made. Otherwise, the original shape will be returned. The width/height for the parent need to be specified to make sure the aspect ratio is maintained.

Parameters:

shape (ShapeEntity) – the shape to convert to polygon.

Returns:

the polygon representation of the shape.

Return type:

Polygon

Raises:

NotImplementedError – if the shape is not a rectangle or ellipse.

static shape_as_rectangle(shape: ShapeEntity) Rectangle[source]#

Get the outer-fitted rectangle representation of the shape.

media_width and media_height are the width and height of the media in which the shape is expressed.

Example

Let’s assume a DatasetItem dataset_item.

To obtain the shapes inside the full annotation as rectangles, one could call:

>>> from otx.api.entities.dataset_item import DatasetItem
>>> from otx.api.entities.image import NullImage
>>> from otx.api.entities.annotation_scene import NullAnnotationScene
>>> dataset_item = DatasetItem(media=NullImage(),
>>>     annotation=NullAnnotationScene())
>>> rectangles = [ShapeFactory.shape_as_rectangle(shape,
>>>     dataset_item.media.width, dataset_item.media.height) for shape
... in dataset_item.annotation_scene.shapes]

To obtain the shapes inside the dataset item (note that dataset item can have roi), one should call:

>>> rectangles = [ShapeFactory.shape_as_rectangle(shape) for shape in
>>>     dataset_item.get_annotations()]

Since the shapes in the first call come from annotation directly, this means they are expressed in the media coordinate system. Therefore, dataset_item.media.width and dataset_item.media.height are passed. While in the second call, the shapes come from denormalization results wrt. dataset_item.roi and therefore expressed inside the roi. In this case, dataset_item.width and dataset_item.height are passed.

Converting Ellipse to rectangle

>>> height = 240
>>> width = 480
>>> rectangle = Rectangle(x1=0.375, y1=0.25, x2=0.625, y2=0.75,
... labels=[]) # a square of 120 x 120 pixels at the center of the image
>>> ellipse = Ellipse(x1=0.5, y1=0.5, x2=0.625, y2=0.56125,
... labels=[]) # an ellipse of radius 60 pixels (x2 is wrt width) at the
center of the image
>>> ellipse_as_rectangle = ShapeFactory.shape_as_rectangle(ellipse)  # get the
fitted rectangle for the ellipse
>>> str(rectangle) == str(ellipse_as_rectangle)
True

Converting triangle to rectangle

>>> points = [Point(x=0.5, y=0.25), Point(x=0.375, y=0.75),
>>>     Point(x=0.625, y=0.75)]
>>> triangle = Polygon(points=points, labels=[])
>>> triangle_as_rectangle = ShapeFactory.shape_as_rectangle(triangle)
>>> str(triangle_as_rectangle) == str(rectangle)
True
Parameters:

shape (ShapeEntity) – the shape to convert to rectangle

Returns:

bounding box of the shape

Return type:

Rectangle

static shape_produces_valid_crop(shape: ShapeEntity, media_width: int, media_height: int) bool[source]#

Check if crop is valid.

Checks if the shape produces a valid crop based on the image width and height, regardless of the contents of the image.

Parameters:
  • shape (ShapeEntity) – Shape to check

  • media_width (int) – Width of the image

  • media_height (int) – Height of the image

Returns:

True if the shape produces a valid crop, False otherwise

Return type:

bool