Source code for swc.aeon.io.video
"""Module for reading and writing video files using OpenCV."""
from collections.abc import Iterable
import cv2
import pandas as pd
from cv2.typing import MatLike
[docs]
def frames(data: pd.DataFrame) -> Iterable[MatLike]:
"""Extracts the raw frames corresponding to the provided video metadata.
Args:
data: A DataFrame where each row specifies video acquisition path and frame number.
Returns:
An object to iterate over numpy arrays for each row in the DataFrame,
containing the raw video frame data.
"""
capture = None
filename = None
index = 0
try:
for frameidx, path in zip(data._frame, data._path, strict=False):
if filename != path or capture is None:
if capture is not None:
capture.release()
capture = cv2.VideoCapture(path)
filename = path
index = 0
if frameidx != index:
capture.set(cv2.CAP_PROP_POS_FRAMES, frameidx)
index = frameidx
success, frame = capture.read()
if not success:
raise ValueError(f'Unable to read frame {frameidx} from video path "{path}".')
yield frame
index = index + 1
finally:
if capture is not None:
capture.release()
[docs]
def export(frames: Iterable[MatLike], filename: str, fps: float, fourcc: int | None = None) -> None:
"""Exports the specified frame sequence to a new video file.
Args:
frames: An object to iterate over the raw video frame data.
filename: The path to the exported video file.
fps: The frame rate of the exported video.
fourcc: Specifies the four character code of the codec used to compress the frames.
"""
writer = None
try:
for frame in frames:
if writer is None:
if fourcc is None:
fourcc = cv2.VideoWriter.fourcc(*"mp4v")
writer = cv2.VideoWriter(filename, fourcc, fps, (frame.shape[1], frame.shape[0]))
writer.write(frame)
finally:
if writer is not None:
writer.release()