Module datatap.droplet.video_annotation
Expand source code
from __future__ import annotations
from typing import Any, Callable, Mapping, Optional, Sequence
from datatap.droplet.video import Video, VideoJson
from typing_extensions import Literal, TypedDict
from ..utils import basic_repr
from .instance import Instance
from .multi_instance import MultiInstance
from .frame_annotation import FrameAnnotation, FrameAnnotationJson
class _VideoAnnotationJsonOptional(TypedDict, total = False):
uid: str
metadata: Mapping[str, Any]
class VideoAnnotationJson(_VideoAnnotationJsonOptional, TypedDict):
"""
The serialized JSON representation of an video annotation.
"""
kind: Literal["VideoAnnotation"]
video: VideoJson
frames: Sequence[FrameAnnotationJson]
class VideoAnnotation:
"""
A collection of class annotations that annotate a given image.
"""
video: Video
"""
The video being annotated.
"""
uid: Optional[str]
"""
A unique identifier for this image annotation.
"""
metadata: Optional[Mapping[str, Any]]
"""
An optional field for storing metadata on the annotation.
"""
@staticmethod
def from_json(json: Mapping[str, Any]) -> VideoAnnotation:
"""
Constructs an `VideoAnnotation` from an `VideoAnnotationJson`.
"""
return VideoAnnotation(
video = Video.from_json(json["video"]),
frames = [FrameAnnotation.from_json(frame) for frame in json["frames"]],
uid = json.get("uid"),
metadata = json.get("metadata")
)
def __init__(
self,
*,
video: Video,
frames: Sequence[FrameAnnotation],
uid: Optional[str] = None,
metadata: Optional[Mapping[str, Any]] = None
):
self.video = video
self.frames = frames
self.uid = uid
self.metadata = metadata
def filter_detections(
self,
*,
instance_filter: Callable[[Instance], bool],
multi_instance_filter: Callable[[MultiInstance], bool]
) -> VideoAnnotation:
"""
Returns a new image annotation consisting only of the instances and
multi-instances that meet the given constraints.
"""
return VideoAnnotation(
video = self.video,
frames = [
frame.filter_detections(
instance_filter = instance_filter,
multi_instance_filter = multi_instance_filter
)
for frame in self.frames
],
uid = self.uid,
metadata = self.metadata
)
def apply_bounding_box_confidence_threshold(self, threshold: float) -> VideoAnnotation:
"""
Returns a new image annotation consisting only of the instances and
multi-instances that have bounding boxes which either do not have a
confidence specified or which have a confience meeting the given
threshold.
"""
return self.filter_detections(
instance_filter = lambda instance: (
instance.bounding_box is not None
and instance.bounding_box.meets_confidence_threshold(threshold)
),
multi_instance_filter = lambda multi_instance: (
multi_instance.bounding_box is not None
and multi_instance.bounding_box.meets_confidence_threshold(threshold)
)
)
def apply_segmentation_confidence_threshold(self, threshold: float) -> VideoAnnotation:
"""
Returns a new image annotation consisting only of the instances and
multi-instances that have segmentations which either do not have a
confidence specified or which have a confience meeting the given
threshold.
"""
return self.filter_detections(
instance_filter = lambda instance: (
instance.segmentation is not None
and instance.segmentation.meets_confidence_threshold(threshold)
),
multi_instance_filter = lambda multi_instance: (
multi_instance.segmentation is not None
and multi_instance.segmentation.meets_confidence_threshold(threshold)
)
)
def apply_metadata(self, metadata: Mapping[str, Any]) -> VideoAnnotation:
"""
Returns a new image annotation with the supplied metadata.
"""
return VideoAnnotation(
video = self.video,
frames = self.frames,
uid = self.uid,
metadata = metadata
)
def __repr__(self) -> str:
return basic_repr(
"VideoAnnotation",
uid = self.uid,
video = self.video,
frames = self.frames,
metadata = self.metadata
)
def __eq__(self, other: object) -> bool:
if not isinstance(other, VideoAnnotation):
return NotImplemented
return (
self.video == other.video
and self.frames == other.frames
and self.uid == other.uid
and self.metadata == other.metadata
)
def __add__(self, other: VideoAnnotation) -> VideoAnnotation:
if not isinstance(other, VideoAnnotation): # type: ignore - pyright complains about the isinstance check being redundant
return NotImplemented
if len(self.frames) != len(other.frames):
raise ValueError("Unable to merge VideoAnnotations with different number of frames")
return VideoAnnotation(
video = self.video,
frames = [
frame1 + frame2
for frame1, frame2 in zip(self.frames, other.frames)
],
uid = self.uid,
metadata = self.metadata
)
def to_json(self) -> VideoAnnotationJson:
"""
Serializes this image annotation into an `VideoAnnotationJson`.
"""
json: VideoAnnotationJson = {
"kind": "VideoAnnotation",
"video": self.video.to_json(),
"frames": [frame.to_json() for frame in self.frames]
}
if self.uid is not None:
json["uid"] = self.uid
if self.metadata is not None:
json["metadata"] = self.metadata
return json
Classes
class VideoAnnotation (*, video: Video, frames: Sequence[FrameAnnotation], uid: Optional[str] = None, metadata: Optional[Mapping[str, Any]] = None)
-
A collection of class annotations that annotate a given image.
Expand source code
class VideoAnnotation: """ A collection of class annotations that annotate a given image. """ video: Video """ The video being annotated. """ uid: Optional[str] """ A unique identifier for this image annotation. """ metadata: Optional[Mapping[str, Any]] """ An optional field for storing metadata on the annotation. """ @staticmethod def from_json(json: Mapping[str, Any]) -> VideoAnnotation: """ Constructs an `VideoAnnotation` from an `VideoAnnotationJson`. """ return VideoAnnotation( video = Video.from_json(json["video"]), frames = [FrameAnnotation.from_json(frame) for frame in json["frames"]], uid = json.get("uid"), metadata = json.get("metadata") ) def __init__( self, *, video: Video, frames: Sequence[FrameAnnotation], uid: Optional[str] = None, metadata: Optional[Mapping[str, Any]] = None ): self.video = video self.frames = frames self.uid = uid self.metadata = metadata def filter_detections( self, *, instance_filter: Callable[[Instance], bool], multi_instance_filter: Callable[[MultiInstance], bool] ) -> VideoAnnotation: """ Returns a new image annotation consisting only of the instances and multi-instances that meet the given constraints. """ return VideoAnnotation( video = self.video, frames = [ frame.filter_detections( instance_filter = instance_filter, multi_instance_filter = multi_instance_filter ) for frame in self.frames ], uid = self.uid, metadata = self.metadata ) def apply_bounding_box_confidence_threshold(self, threshold: float) -> VideoAnnotation: """ Returns a new image annotation consisting only of the instances and multi-instances that have bounding boxes which either do not have a confidence specified or which have a confience meeting the given threshold. """ return self.filter_detections( instance_filter = lambda instance: ( instance.bounding_box is not None and instance.bounding_box.meets_confidence_threshold(threshold) ), multi_instance_filter = lambda multi_instance: ( multi_instance.bounding_box is not None and multi_instance.bounding_box.meets_confidence_threshold(threshold) ) ) def apply_segmentation_confidence_threshold(self, threshold: float) -> VideoAnnotation: """ Returns a new image annotation consisting only of the instances and multi-instances that have segmentations which either do not have a confidence specified or which have a confience meeting the given threshold. """ return self.filter_detections( instance_filter = lambda instance: ( instance.segmentation is not None and instance.segmentation.meets_confidence_threshold(threshold) ), multi_instance_filter = lambda multi_instance: ( multi_instance.segmentation is not None and multi_instance.segmentation.meets_confidence_threshold(threshold) ) ) def apply_metadata(self, metadata: Mapping[str, Any]) -> VideoAnnotation: """ Returns a new image annotation with the supplied metadata. """ return VideoAnnotation( video = self.video, frames = self.frames, uid = self.uid, metadata = metadata ) def __repr__(self) -> str: return basic_repr( "VideoAnnotation", uid = self.uid, video = self.video, frames = self.frames, metadata = self.metadata ) def __eq__(self, other: object) -> bool: if not isinstance(other, VideoAnnotation): return NotImplemented return ( self.video == other.video and self.frames == other.frames and self.uid == other.uid and self.metadata == other.metadata ) def __add__(self, other: VideoAnnotation) -> VideoAnnotation: if not isinstance(other, VideoAnnotation): # type: ignore - pyright complains about the isinstance check being redundant return NotImplemented if len(self.frames) != len(other.frames): raise ValueError("Unable to merge VideoAnnotations with different number of frames") return VideoAnnotation( video = self.video, frames = [ frame1 + frame2 for frame1, frame2 in zip(self.frames, other.frames) ], uid = self.uid, metadata = self.metadata ) def to_json(self) -> VideoAnnotationJson: """ Serializes this image annotation into an `VideoAnnotationJson`. """ json: VideoAnnotationJson = { "kind": "VideoAnnotation", "video": self.video.to_json(), "frames": [frame.to_json() for frame in self.frames] } if self.uid is not None: json["uid"] = self.uid if self.metadata is not None: json["metadata"] = self.metadata return json
Class variables
var metadata : Optional[Mapping[str, Any]]
-
An optional field for storing metadata on the annotation.
var uid : Optional[str]
-
A unique identifier for this image annotation.
var video : Video
-
The video being annotated.
Static methods
def from_json(json: Mapping[str, Any]) ‑> VideoAnnotation
-
Constructs an
VideoAnnotation
from anVideoAnnotationJson
.Expand source code
@staticmethod def from_json(json: Mapping[str, Any]) -> VideoAnnotation: """ Constructs an `VideoAnnotation` from an `VideoAnnotationJson`. """ return VideoAnnotation( video = Video.from_json(json["video"]), frames = [FrameAnnotation.from_json(frame) for frame in json["frames"]], uid = json.get("uid"), metadata = json.get("metadata") )
Methods
def apply_bounding_box_confidence_threshold(self, threshold: float) ‑> VideoAnnotation
-
Returns a new image annotation consisting only of the instances and multi-instances that have bounding boxes which either do not have a confidence specified or which have a confience meeting the given threshold.
Expand source code
def apply_bounding_box_confidence_threshold(self, threshold: float) -> VideoAnnotation: """ Returns a new image annotation consisting only of the instances and multi-instances that have bounding boxes which either do not have a confidence specified or which have a confience meeting the given threshold. """ return self.filter_detections( instance_filter = lambda instance: ( instance.bounding_box is not None and instance.bounding_box.meets_confidence_threshold(threshold) ), multi_instance_filter = lambda multi_instance: ( multi_instance.bounding_box is not None and multi_instance.bounding_box.meets_confidence_threshold(threshold) ) )
def apply_metadata(self, metadata: Mapping[str, Any]) ‑> VideoAnnotation
-
Returns a new image annotation with the supplied metadata.
Expand source code
def apply_metadata(self, metadata: Mapping[str, Any]) -> VideoAnnotation: """ Returns a new image annotation with the supplied metadata. """ return VideoAnnotation( video = self.video, frames = self.frames, uid = self.uid, metadata = metadata )
def apply_segmentation_confidence_threshold(self, threshold: float) ‑> VideoAnnotation
-
Returns a new image annotation consisting only of the instances and multi-instances that have segmentations which either do not have a confidence specified or which have a confience meeting the given threshold.
Expand source code
def apply_segmentation_confidence_threshold(self, threshold: float) -> VideoAnnotation: """ Returns a new image annotation consisting only of the instances and multi-instances that have segmentations which either do not have a confidence specified or which have a confience meeting the given threshold. """ return self.filter_detections( instance_filter = lambda instance: ( instance.segmentation is not None and instance.segmentation.meets_confidence_threshold(threshold) ), multi_instance_filter = lambda multi_instance: ( multi_instance.segmentation is not None and multi_instance.segmentation.meets_confidence_threshold(threshold) ) )
def filter_detections(self, *, instance_filter: Callable[[Instance], bool], multi_instance_filter: Callable[[MultiInstance], bool]) ‑> VideoAnnotation
-
Returns a new image annotation consisting only of the instances and multi-instances that meet the given constraints.
Expand source code
def filter_detections( self, *, instance_filter: Callable[[Instance], bool], multi_instance_filter: Callable[[MultiInstance], bool] ) -> VideoAnnotation: """ Returns a new image annotation consisting only of the instances and multi-instances that meet the given constraints. """ return VideoAnnotation( video = self.video, frames = [ frame.filter_detections( instance_filter = instance_filter, multi_instance_filter = multi_instance_filter ) for frame in self.frames ], uid = self.uid, metadata = self.metadata )
def to_json(self) ‑> VideoAnnotationJson
-
Serializes this image annotation into an
VideoAnnotationJson
.Expand source code
def to_json(self) -> VideoAnnotationJson: """ Serializes this image annotation into an `VideoAnnotationJson`. """ json: VideoAnnotationJson = { "kind": "VideoAnnotation", "video": self.video.to_json(), "frames": [frame.to_json() for frame in self.frames] } if self.uid is not None: json["uid"] = self.uid if self.metadata is not None: json["metadata"] = self.metadata return json
class VideoAnnotationJson (*args, **kwargs)
-
The serialized JSON representation of an video annotation.
Expand source code
class VideoAnnotationJson(_VideoAnnotationJsonOptional, TypedDict): """ The serialized JSON representation of an video annotation. """ kind: Literal["VideoAnnotation"] video: VideoJson frames: Sequence[FrameAnnotationJson]
Ancestors
- builtins.dict
Class variables
var frames : Sequence[FrameAnnotationJson]
var kind : Literal['VideoAnnotation']
var metadata : Mapping[str, Any]
var uid : str
var video : VideoJson