readers.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. # copyright (c) 2024 PaddlePaddle Authors. All Rights Reserve.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import enum
  15. import itertools
  16. import cv2
  17. __all__ = ['ImageReader', 'VideoReader', 'ReaderType']
  18. class ReaderType(enum.Enum):
  19. """ ReaderType """
  20. IMAGE = 1
  21. GENERATIVE = 2
  22. POINT_CLOUD = 3
  23. class _BaseReader(object):
  24. """ _BaseReader """
  25. def __init__(self, backend, **bk_args):
  26. super().__init__()
  27. if len(bk_args) == 0:
  28. bk_args = self.get_default_backend_args()
  29. self.bk_type = backend
  30. self.bk_args = bk_args
  31. self._backend = self.get_backend()
  32. def read(self, in_path):
  33. """ read file from path """
  34. raise NotImplementedError
  35. def get_backend(self, bk_args=None):
  36. """ get the backend """
  37. if bk_args is None:
  38. bk_args = self.bk_args
  39. return self._init_backend(self.bk_type, bk_args)
  40. def _init_backend(self, bk_type, bk_args):
  41. """ init backend """
  42. raise NotImplementedError
  43. def get_type(self):
  44. """ get type """
  45. raise NotImplementedError
  46. def get_default_backend_args(self):
  47. """ get default backend arguments """
  48. return {}
  49. class ImageReader(_BaseReader):
  50. """ ImageReader """
  51. def __init__(self, backend='opencv', **bk_args):
  52. super().__init__(backend=backend, **bk_args)
  53. def read(self, in_path):
  54. """ read the image file from path """
  55. arr = self._backend.read_file(in_path)
  56. return arr
  57. def _init_backend(self, bk_type, bk_args):
  58. """ init backend """
  59. if bk_type == 'opencv':
  60. return OpenCVImageReaderBackend(**bk_args)
  61. else:
  62. raise ValueError("Unsupported backend type")
  63. def get_type(self):
  64. """ get type """
  65. return ReaderType.IMAGE
  66. class _GenerativeReader(_BaseReader):
  67. """ _GenerativeReader """
  68. def get_type(self):
  69. """ get type """
  70. return ReaderType.GENERATIVE
  71. def is_generative_reader(reader):
  72. """ is_generative_reader """
  73. return isinstance(reader, _GenerativeReader)
  74. class VideoReader(_GenerativeReader):
  75. """ VideoReader """
  76. def __init__(self,
  77. backend='opencv',
  78. st_frame_id=0,
  79. max_num_frames=None,
  80. auto_close=True,
  81. **bk_args):
  82. super().__init__(backend=backend, **bk_args)
  83. self.st_frame_id = st_frame_id
  84. self.max_num_frames = max_num_frames
  85. self.auto_close = auto_close
  86. def read(self, in_path):
  87. """ read vide file from path """
  88. self._backend.set_pos(self.st_frame_id)
  89. gen = self._backend.read_file(in_path)
  90. if self.num_frames is not None:
  91. gen = itertools.islice(gen, self.num_frames)
  92. yield from gen
  93. if self.auto_close:
  94. self._backend.close()
  95. def _init_backend(self, bk_type, bk_args):
  96. """ init backend """
  97. if bk_type == 'opencv':
  98. return OpenCVVideoReaderBackend(**bk_args)
  99. else:
  100. raise ValueError("Unsupported backend type")
  101. class _BaseReaderBackend(object):
  102. """ _BaseReaderBackend """
  103. def read_file(self, in_path):
  104. """ read file from path """
  105. raise NotImplementedError
  106. class _ImageReaderBackend(_BaseReaderBackend):
  107. """ _ImageReaderBackend """
  108. pass
  109. class OpenCVImageReaderBackend(_ImageReaderBackend):
  110. """ OpenCVImageReaderBackend """
  111. def __init__(self, flags=cv2.IMREAD_COLOR):
  112. super().__init__()
  113. self.flags = flags
  114. def read_file(self, in_path):
  115. """ read image file from path by OpenCV """
  116. return cv2.imread(in_path, flags=self.flags)
  117. class _VideoReaderBackend(_BaseReaderBackend):
  118. """ _VideoReaderBackend """
  119. def set_pos(self, pos):
  120. """ set pos """
  121. raise NotImplementedError
  122. def close(self):
  123. """ close io """
  124. raise NotImplementedError
  125. class OpenCVVideoReaderBackend(_VideoReaderBackend):
  126. """ OpenCVVideoReaderBackend """
  127. def __init__(self, **bk_args):
  128. super().__init__()
  129. self.cap_init_args = bk_args
  130. self._cap = None
  131. self._pos = 0
  132. self._max_num_frames = None
  133. def read_file(self, in_path):
  134. """ read vidio file from path """
  135. if self._cap is not None:
  136. self._cap_release()
  137. self._cap = self._cap_open(in_path)
  138. if self._pos is not None:
  139. self._cap_set_pos()
  140. return self._read_frames(self._cap)
  141. def _read_frames(self, cap):
  142. """ read frames """
  143. while True:
  144. ret, frame = cap.read()
  145. if not ret:
  146. break
  147. yield frame
  148. self._cap_release()
  149. def _cap_open(self, video_path):
  150. self._cap = cv2.VideoCapture(video_path, **self.cap_init_args)
  151. if not self._cap.isOpened():
  152. raise RuntimeError(f"Failed to open {video_path}")
  153. return self._cap
  154. def _cap_release(self):
  155. self._cap.release()
  156. def _cap_set_pos(self):
  157. self._cap.set(cv2.CAP_PROP_POS_FRAMES, self._pos)
  158. def set_pos(self, pos):
  159. self._pos = pos
  160. def close(self):
  161. if self._cap is not None:
  162. self._cap_release()
  163. self._cap = None