# coding: utf-8
# docs
from __future__ import annotations
from typing import Any, Dict, List, Optional, Tuple
from supervisely.api.module_api import ApiField
from supervisely.collection.key_indexed_collection import KeyIndexedCollection
from supervisely.video_annotation.frame import Frame
from supervisely.video_annotation.key_id_map import KeyIdMap
from supervisely.video_annotation.video_figure import VideoFigure
from supervisely.video_annotation.video_object_collection import VideoObjectCollection
[docs]class FrameCollection(KeyIndexedCollection):
"""
Collection with :class:`Frame<supervisely.video_annotation.frame.Frame>` instances. :class:`FrameCollection<FrameCollection>` object is immutable.
:Usage example:
.. code-block:: python
import supervisely as sly
# Create two frames for collection
fr_index_1 = 7
frame_1 = sly.Frame(fr_index_1)
fr_index_2 = 10
frame_2 = sly.Frame(fr_index_2)
# Create FrameCollection
fr_collection = sly.FrameCollection([frame_1, frame_2])
print(fr_collection.to_json())
# Output: [
# {
# "index": 7,
# "figures": []
# },
# {
# "index": 10,
# "figures": []
# }
# ]
# Add item to FrameCollection
frame_3 = sly.Frame(12)
# Remember that TagCollection is immutable, and we need to assign new instance of TagCollection to a new variable
new_fr_collection = fr_collection.add(frame_3)
print(new_fr_collection.to_json())
# Output: [
# {
# "index": 7,
# "figures": []
# },
# {
# "index": 10,
# "figures": []
# },
# {
# "index": 12,
# "figures": []
# }
# ]
# You can also add multiple items to collection
frame_3 = sly.Frame(12)
frame_4 = sly.Frame(15)
# Remember that TagCollection is immutable, and we need to assign new instance of TagCollection to a new variable
new_fr_collection = fr_collection.add_items([frame_3, frame_4])
print(new_fr_collection.to_json())
# Output: [
# {
# "index": 7,
# "figures": []
# },
# {
# "index": 10,
# "figures": []
# },
# {
# "index": 12,
# "figures": []
# },
# {
# "index": 15,
# "figures": []
# }
# ]
# Has key, checks if given key exist in collection
fr_collection.has_key(7)
# Output: True
# Intersection, finds intersection of given list of instances with collection items
frame_1 = sly.Frame(7)
frame_2 = sly.Frame(10)
fr_collection = sly.FrameCollection([frame_1, frame_2])
frame_3 = sly.Frame(12)
frames_intersections = fr_collection.intersection([frame_3])
print(frames_intersections.to_json())
# Output: []
frames_intersections = fr_collection.intersection([frame_2])
print(frames_intersections.to_json())
# Output: [
# {
# "index": 10,
# "figures": []
# }
# ]
# Note, two frames with the same index values are not equal
frame_4 = sly.Frame(10)
frames_intersections = fr_collection.intersection([frame_4])
# Output:
# ValueError: Different values for the same key 10
# Difference, finds difference between collection and given list of Frames
frames_difference = fr_collection.difference([frame_2])
print(frames_difference.to_json())
# Output: [
# {
# "index": 7,
# "figures": []
# }
# ]
# Merge, merges collection and given list of FrameCollection
frame_3 = sly.Frame(12)
frame_4 = sly.Frame(15)
over_collection = sly.FrameCollection([frame_3, frame_4])
merged_collection = fr_collection.merge(over_collection)
print(merged_collection.to_json())
# Output: [
# {
# "index": 12,
# "figures": []
# },
# {
# "index": 15,
# "figures": []
# },
# {
# "index": 7,
# "figures": []
# },
# {
# "index": 10,
# "figures": []
# }
# ]
"""
item_type = Frame
[docs] def get(self, key: str, default: Optional[Any] = None) -> Frame:
"""
Get item from collection with given key(name) and set a default if item does not exist.
:param key: Name of Frame in collection.
:type key: str
:param default: The value that is returned if there is no key in the collection.
:type default: Optional[Any]
:return: :class:`Frame<supervisely.video_annotation.frame.Frame>`, :class:`Slice<supervisely.volume_annotation.slice.Slice>` or :class:`PointcloudEpisodeFrame<supervisely.pointcloud_annotation.pointcloud_episode_frame.PointcloudEpisodeFrame>` object
:rtype: :class:`KeyObject<KeyObject>`
:Usage Example:
.. code-block:: python
import supervisely as sly
frame_index = 7
geometry = sly.Rectangle(0, 0, 100, 100)
class_car = sly.ObjClass('car', sly.Rectangle)
object_car = sly.VideoObject(class_car)
figure_car = sly.VideoFigure(object_car, geometry, frame_index)
frame = sly.Frame(frame_index, figures=[figure_car])
frame_collection = sly.FrameCollection([frame])
item = frame_collection.get(frame_index)
pprint(item.to_json())
# Output: {
# "figures": [
# {
# "geometry": {
# "points": {
# "exterior": [
# [0, 0],
# [100, 100]
# ],
# "interior": []
# }
# },
# "geometryType": "rectangle",
# "key": "713968a7d5384709bc5d4e63cd4535f2",
# "objectKey": "3342e68eff3b44dcb75712499265be55"
# }
# ],
# "index": 7
# }
"""
return super().get(key, default)
[docs] def to_json(self, key_id_map: KeyIdMap = None) -> List[Dict]:
"""
Convert the FrameCollection to a list of json dicts. Read more about `Supervisely format <https://docs.supervise.ly/data-organization/00_ann_format_navi>`_.
:param key_id_map: KeyIdMap object.
:type key_id_map: KeyIdMap, optional
:return: List of dicts in json format
:rtype: :class:`List[dict]`
:Usage example:
.. code-block:: python
import supervisely as sly
frame_1 = sly.Frame(7)
frame_2 = sly.Frame(10)
# Create FrameCollection
fr_collection = sly.FrameCollection([frame_1, frame_2])
print(fr_collection.to_json())
# Output: [
# {
# "index": 7,
# "figures": []
# },
# {
# "index": 10,
# "figures": []
# }
# ]
"""
return [frame.to_json(key_id_map) for frame in self]
[docs] @classmethod
def from_json(
cls,
data: List[Dict],
objects: VideoObjectCollection,
frames_count: Optional[int] = None,
key_id_map: Optional[KeyIdMap] = None,
) -> FrameCollection:
"""
Convert a list of json dicts to FrameCollection. Read more about `Supervisely format <https://docs.supervise.ly/data-organization/00_ann_format_navi>`_.
:param data: List with dicts in json format.
:type data: List[dict]
:param objects: VideoObjectCollection object.
:type objects: VideoObjectCollection
:param frames_count: Number of frames in video.
:type frames_count: int, optional
:param key_id_map: KeyIdMap object.
:type key_id_map: KeyIdMap, optional
:return: FrameCollection object
:rtype: :class:`FrameCollection`
:Usage example:
.. code-block:: python
import supervisely as sly
fr_collection_json = [
{
"index": 7,
"figures": []
},
{
"index": 10,
"figures": []
}
]
objects = []
fr_collection = sly.FrameCollection.from_json(fr_collection_json, objects)
"""
frames = [
cls.item_type.from_json(frame_json, objects, frames_count, key_id_map)
for frame_json in data
]
return cls(frames)
def __str__(self):
return "Frames:\n" + super(FrameCollection, self).__str__()
@property
def figures(self) -> List[VideoFigure]:
"""
Get figures from all frames in collection.
:return: List of figures from all frames in collection
:rtype: :class:`List[VideoFigure]<supervisely.video_annotation.video_figure.VideoFigure>`
:Usage example:
.. code-block:: python
import supervisely as sly
fr_index_1 = 7
geometry = sly.Rectangle(0, 0, 100, 100)
obj_class_car = sly.ObjClass('car', sly.Rectangle)
video_object_car = sly.VideoObject(obj_class_car)
video_figure_car = sly.VideoFigure(video_object_car, geometry, fr_index_1)
frame_1 = sly.Frame(fr_index_1, figures=[video_figure_car])
fr_index_2 = 10
geometry = sly.Rectangle(0, 0, 500, 600)
obj_class_bus = sly.ObjClass('bus', sly.Rectangle)
video_object_bus = sly.VideoObject(obj_class_bus)
video_figure_bus = sly.VideoFigure(video_object_bus, geometry, fr_index_2)
frame_2 = sly.Frame(fr_index_2, figures=[video_figure_bus])
fr_collection = sly.FrameCollection([frame_1, frame_2])
figures = fr_collection.figures
"""
figures_array = []
for frame in self:
figures_array.extend(frame.figures)
return figures_array