From 41a3161c6eff70482dbf85b13661a7cf47703c32 Mon Sep 17 00:00:00 2001 From: David Rotermund <54365609+davrot@users.noreply.github.com> Date: Wed, 27 Dec 2023 17:45:27 +0100 Subject: [PATCH] Update README.md Signed-off-by: David Rotermund <54365609+davrot@users.noreply.github.com> --- cv2/write_read_play/README.md | 112 ++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/cv2/write_read_play/README.md b/cv2/write_read_play/README.md index c6dd61c..0cef43c 100644 --- a/cv2/write_read_play/README.md +++ b/cv2/write_read_play/README.md @@ -74,4 +74,116 @@ print(test_data.shape) # -> (101, 101, 3, 101) write_video(frames=test_data, filename="test", fps=20.0) ``` +## Read the data from a mp4 file +```python +import numpy as np +import cv2 # type: ignore + + +def read_video(filename: str, display: bool = False) -> np.ndarray: + assert len(filename) > 0, "read_video: Filename is empty." + + frames: np.ndarray = np.array([]) + + cap = cv2.VideoCapture(filename) + + assert cap.isOpened() is True, "read_video: Error opening video stream or file!" + + n: int = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) + x: int = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) + y: int = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) + + print(f"Reading {n} frames with {x} x {y} pixels.") + + frames = np.zeros((y, x, 3, n)).astype(np.uint8) + + i: int = 0 + + while cap.isOpened(): + ret, frame = cap.read() + + if ret is True: + frames[:, :, :, i] = frame + i += 1 + + if display is True: + cv2.imshow("Reading", frame) + cv2.waitKey(25) + else: + break + + cap.release() + + if display is True: + cv2.destroyWindow("Reading") + + return frames + + +movie = read_video("test.mp4", display=True) + +print(movie.shape) # -> (100, 100, 3, 101) +``` + +## Playback a video + +```python +import numpy as np +import cv2 # type: ignore +import time + + +def show_video(frames: np.ndarray, fps: float = 20.0) -> np.ndarray: + assert frames.size > 0, "The frame is empty." + assert frames.ndim == 4, "The frame has wrong dimensions." + + n: int = frames.shape[3] + dt: float = 1 / fps + + t: np.ndarray = np.zeros((n + 1)) + + t[0] = time.perf_counter() + + for i in range(n): + frame = frames[:, :, :, i] + cv2.imshow("Display", frame) + t_wait: float = t[i] + dt - time.perf_counter() + retval = cv2.waitKey(int(max(1, 1000 * t_wait))) + t[i + 1] = time.perf_counter() + if retval != -1: + break + cv2.destroyWindow("Display") + + return t + + +# Create test data +axis_x = np.arange(-50, 51)[:, np.newaxis, np.newaxis] / 50 +axis_y = np.arange(-50, 51)[np.newaxis, :, np.newaxis] / 50 +axis_z = np.arange(-50, 51)[np.newaxis, np.newaxis, :] / 50 + +test_data = np.sqrt(axis_x**2 + axis_y**2 + axis_z**2) < 0.75 + + +# Adding an additional axis for the color channel +test_data = test_data[:, :, :, np.newaxis] +test_data = np.tile(test_data, (1, 1, 1, 3)) +test_data = test_data.astype(dtype=np.float32) + +# Put the time axis as last axis +test_data = np.moveaxis(test_data, 0, -1) + + +# Conversion to uint8 +test_data -= test_data.min() +test_data /= test_data.max() +test_data *= 255 +test_data = test_data.astype(dtype=np.uint8) + + +print(test_data.shape) # -> (101, 101, 3, 101) + +timings = show_video(frames=test_data, fps=20.0) +print(timings.shape) # -> (102,) +```