6
0

MediaFile.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. from typing import List
  2. from typing import Optional
  3. from typing import Union
  4. from pycs.database.File import File
  5. from pycs.database.Result import Result
  6. from pycs.frontend.notifications.NotificationList import NotificationList
  7. from pycs.interfaces.MediaBoundingBox import MediaBoundingBox
  8. from pycs.interfaces.MediaImageLabel import MediaImageLabel
  9. from pycs.interfaces.MediaLabel import MediaLabel
  10. class MediaFile:
  11. """
  12. contains various attributes of a saved media file
  13. """
  14. def __init__(self, file: File, notifications: NotificationList):
  15. self.__file = file
  16. self.__notifications = notifications
  17. self.type = file.type
  18. self.size = file.size
  19. self.frames = file.frames
  20. self.fps = file.fps
  21. self.path = file.absolute_path
  22. def set_collection(self, reference: Optional[str]):
  23. """
  24. set this file's collection
  25. :param reference: use None to remove this file's collection
  26. """
  27. self.__file.set_collection_by_reference(reference)
  28. self.__notifications.add(self.__notifications.notifications.edit_file, self.__file)
  29. def set_image_label(self, label: Union[int, MediaLabel], frame: int = None):
  30. """
  31. create a labeled-image result
  32. :param label: label identifier
  33. :param frame: frame index (only set for videos)
  34. """
  35. if label is not None and isinstance(label, MediaLabel):
  36. label = label.identifier
  37. if frame is not None:
  38. data = {'frame': frame}
  39. else:
  40. data = None
  41. created = self.__file.create_result(origin='pipeline',
  42. result_type='labeled-image', label=label, data=data)
  43. self.__notifications.add(self.__notifications.notifications.create_result, created)
  44. def add_bounding_box(self, x: float, y: float, w: float, h: float,
  45. label: Union[int, MediaLabel] = None, frame: int = None,
  46. origin:str = None, origin_user: str = None) -> Result:
  47. """
  48. create a bounding-box result
  49. :param x: relative x coordinate [0, 1]
  50. :param y: relative y coordinate [0, 1]
  51. :param w: relative width [0, 1]
  52. :param h: relative height [0, 1]
  53. :param label: label
  54. :param frame: frame index (only set for videos)
  55. :param origin: Either pipeline or user
  56. :param origin_user: Username of the user that provided the bounding box
  57. :return: Created Result
  58. """
  59. result = {
  60. 'x': x,
  61. 'y': y,
  62. 'w': w,
  63. 'h': h
  64. }
  65. if frame is not None:
  66. result['frame'] = frame
  67. if label is not None and isinstance(label, MediaLabel):
  68. label = label.identifier
  69. if origin is None:
  70. origin = 'pipeline'
  71. created = self.__file.create_result(origin=origin, origin_user=origin_user,
  72. result_type='bounding-box', label=label, data=result)
  73. self.__notifications.add(self.__notifications.notifications.create_result, created)
  74. return created
  75. def remove_predictions(self):
  76. """
  77. remove and return all predictions added from pipelines
  78. """
  79. removed = self.__file.remove_results(origin='pipeline')
  80. for result in removed:
  81. self.__notifications.add(self.__notifications.notifications.remove_result, result)
  82. def remove_result(self, result_id):
  83. """
  84. Removes the result with the given id.
  85. :param result_id: id of the result to delete
  86. """
  87. removed = self.__file.remove_result(id=result_id)
  88. for result in removed:
  89. self.__notifications.add(self.__notifications.notifications.remove_result, result)
  90. def __get_results(self, origin: str) -> List[Union[MediaImageLabel, MediaBoundingBox]]:
  91. def result_to_media(result: Result) -> Union[MediaImageLabel, MediaBoundingBox]:
  92. cls = MediaImageLabel if result.type == 'labeled-image' else MediaBoundingBox
  93. return cls(result)
  94. return [result_to_media(r) for r in self.__file.results.filter_by(origin=origin).all()]
  95. def results(self) -> List[Union[MediaImageLabel, MediaBoundingBox]]:
  96. """
  97. receive results added by users
  98. :return: list of results
  99. """
  100. return self.__get_results('user')
  101. def predictions(self) -> List[Union[MediaImageLabel, MediaBoundingBox]]:
  102. """
  103. receive results added by pipelines
  104. :return: list of predictions
  105. """
  106. return self.__get_results('pipeline')
  107. def serialize(self) -> dict:
  108. """
  109. serialize all object properties to a dict
  110. :return: dict
  111. """
  112. return {
  113. 'type': self.type,
  114. 'size': self.size,
  115. 'frames': self.frames,
  116. 'fps': self.fps,
  117. 'path': self.path,
  118. 'filename': self.__file.filename,
  119. 'results': list(map(lambda r: r.serialize(), self.results())),
  120. 'predictions': list(map(lambda r: r.serialize(), self.predictions())),
  121. }