def writer( in_q: Queue, progress_queue: Queue, filename: str, fps: float, ): """Write annotated images to video. Image size is determined by the first image received in queue. Args: in_q: Queue with annotated images as (images, h, w, channels) ndarray progress_queue: Queue to send progress as (total frames written: int, elapsed time: float). Send (-1, elapsed time) when done. filename: full path to output video fps: frames per second for output video Returns: None. """ cv2.setNumThreads(usable_cpu_count()) writer_object = None total_elapsed = 0 total_frames_written = 0 start_time = clock() i = 0 while True: data = in_q.get() if data is _sentinel: # no more data to be received so stop in_q.put(_sentinel) break if writer_object is None and data: h, w = data[0].shape[:2] writer_object = VideoWriter.safe_builder(filename, height=h, width=w, fps=fps) t0 = clock() for img in data: writer_object.add_frame(img, bgr=True) elapsed = clock() - t0 fps = len(data) / elapsed logger.debug(f"writing chunk {i} in {elapsed} s = {fps} fps") i += 1 total_frames_written += len(data) total_elapsed = clock() - start_time progress_queue.put((total_frames_written, total_elapsed)) writer_object.close() # send (-1, time) to signal done progress_queue.put((-1, total_elapsed))
def marker(self): cv2.setNumThreads(usable_cpu_count()) chunk_i = 0 while True: data = self.in_q.get() if data is _sentinel: # no more data to be received so stop self.in_q.put(_sentinel) break frames_idx_chunk, video_frame_images = data t0 = clock() imgs = self._mark_images( frame_indices=frames_idx_chunk, frame_images=video_frame_images, ) elapsed = clock() - t0 fps = len(imgs) / elapsed logger.debug(f"drawing chunk {chunk_i} in {elapsed} s = {fps} fps") chunk_i += 1 self.out_q.put(imgs) # send _sentinal object into queue to signal that we're done self.out_q.put(_sentinel)
def reader(out_q: Queue, video: Video, frames: List[int], scale: float = 1.0): """Read frame images from video and send them into queue. Args: out_q: Queue to send (list of frame indexes, ndarray of frame images) for chunks of video. video: The `Video` object to read. frames: Full list frame indexes we want to read. scale: Output scale for frame images. Returns: None. """ cv2.setNumThreads(usable_cpu_count()) total_count = len(frames) chunk_size = 64 chunk_count = math.ceil(total_count / chunk_size) logger.info(f"Chunks: {chunk_count}, chunk size: {chunk_size}") i = 0 for chunk_i in range(chunk_count): # Read the next chunk of frames frame_start = chunk_size * chunk_i frame_end = min(frame_start + chunk_size, total_count) frames_idx_chunk = frames[frame_start:frame_end] t0 = clock() # Safely load frames from video, skipping frames we can't load loaded_chunk_idxs, video_frame_images = video.get_frames_safely( frames_idx_chunk) if not loaded_chunk_idxs: print(f"No frames could be loaded from chunk {chunk_i}") i += 1 continue if scale != 1.0: video_frame_images = resize_images(video_frame_images, scale) elapsed = clock() - t0 fps = len(loaded_chunk_idxs) / elapsed logger.debug(f"reading chunk {i} in {elapsed} s = {fps} fps") i += 1 out_q.put((loaded_chunk_idxs, video_frame_images)) # send _sentinal object into queue to signal that we're done out_q.put(_sentinel)
def marker(in_q: Queue, out_q: Queue, labels: Labels, video_idx: int, scale: float): """Annotate frame images (draw instances). Args: in_q: Queue with (list of frame indexes, ndarray of frame images). out_q: Queue to send annotated images as (images, h, w, channels) ndarray. labels: the `Labels` object from which to get data for annotating. video_idx: index of `Video` in `labels.videos` list. Returns: None. """ cv2.setNumThreads(usable_cpu_count()) chunk_i = 0 while True: data = in_q.get() if data is _sentinel: # no more data to be received so stop in_q.put(_sentinel) break frames_idx_chunk, video_frame_images = data t0 = clock() imgs = mark_images( frame_indices=frames_idx_chunk, frame_images=video_frame_images, video_idx=video_idx, labels=labels, scale=scale, ) elapsed = clock() - t0 fps = len(imgs) / elapsed logger.debug(f"drawing chunk {chunk_i} in {elapsed} s = {fps} fps") chunk_i += 1 out_q.put(imgs) # send _sentinal object into queue to signal that we're done out_q.put(_sentinel)