Source code for aeon.analysis.movies

import math

import cv2
import numpy as np
import pandas as pd

from aeon.io import video


[docs] def gridframes(frames, width, height, shape: None | int | tuple[int, int] = None): """Arranges a set of frames into a grid layout with the specified pixel dimensions and shape. :param list frames: A list of frames to include in the grid layout. :param int width: The width of the output grid image, in pixels. :param int height: The height of the output grid image, in pixels. :param optional shape: Either the number of frames to include, or the number of rows and columns in the output grid image layout. :return: A new image containing the arrangement of the frames in a grid. """ if shape is None: shape = len(frames) if isinstance(shape, int): shape = math.ceil(math.sqrt(shape)) shape = (shape, shape) dsize = (height, width, 3) cellsize = (height // shape[0], width // shape[1], 3) grid = np.zeros(dsize, dtype=np.uint8) for i in range(shape[0]): for j in range(shape[1]): k = i * shape[1] + j if k >= len(frames): continue frame = frames[k] i0 = i * cellsize[0] j0 = j * cellsize[1] i1 = i0 + cellsize[0] j1 = j0 + cellsize[1] grid[i0:i1, j0:j1] = cv2.resize(frame, (cellsize[1], cellsize[0])) return grid
[docs] def averageframes(frames): """Returns the average of the specified collection of frames.""" return cv2.convertScaleAbs(np.sum(np.multiply(1 / len(frames), frames)))
[docs] def groupframes(frames, n, fun): """Applies the specified function to each group of n-frames. :param iterable frames: A sequence of frames to process. :param int n: The number of frames in each group. :param callable fun: The function used to process each group of frames. :return: An iterable returning the results of applying the function to each group. """ i = 0 group = [] for frame in frames: group.append(frame) if len(group) >= n: yield fun(group) group.clear() i = i + 1
[docs] def triggerclip(data, events, before=None, after=None): """Split video data around the specified sequence of event timestamps. :param DataFrame data: A pandas DataFrame where each row specifies video acquisition path and frame number. :param iterable events: A sequence of timestamps to extract. :param Timedelta before: The left offset from each timestamp used to clip the data. :param Timedelta after: The right offset from each timestamp used to clip the data. :return: A pandas DataFrame containing the frames, clip and sequence numbers for each event timestamp. """ if before is None: before = pd.Timedelta(0) elif before is not pd.Timedelta: before = pd.Timedelta(before) if after is None: after = pd.Timedelta(0) elif after is not pd.Timedelta: after = pd.Timedelta(after) if events is not pd.Index: events = events.index clips = [] for i, index in enumerate(events): clip = data.loc[(index - before) : (index + after)].copy() clip["frame_sequence"] = list(range(len(clip))) clip["clip_sequence"] = i clips.append(clip) return pd.concat(clips)
[docs] def collatemovie(clipdata, fun): """Collates a set of video clips into a single movie using the specified aggregation function. :param DataFrame clipdata: A pandas DataFrame where each row specifies video path, frame number, clip and sequence number. This DataFrame can be obtained from the output of the triggerclip function. :param callable fun: The aggregation function used to process the frames in each clip. :return: The sequence of processed frames representing the collated movie. """ clipcount = len(clipdata.groupby("clip_sequence").frame_sequence.count()) allframes = video.frames(clipdata.sort_values(by=["frame_sequence", "clip_sequence"])) return groupframes(allframes, clipcount, fun)
[docs] def gridmovie(clipdata, width, height, shape=None): """Collates a set of video clips into a grid movie with the specified pixel dimensions and grid layout. :param DataFrame clipdata: A pandas DataFrame where each row specifies video path, frame number, clip and sequence number. This DataFrame can be obtained from the output of the triggerclip function. :param int width: The width of the output grid movie, in pixels. :param int height: The height of the output grid movie, in pixels. :param optional shape: Either the number of frames to include, or the number of rows and columns in the output grid movie layout. :return: The sequence of processed frames representing the collated grid movie. """ return collatemovie(clipdata, lambda g: gridframes(g, width, height, shape))