Video
Video
- class byotrack.video.video.VideoTransformConfig(aggregate: bool = False, normalize: bool = False, selected_channel: int | None = None, q_min: float = 0.0, q_max: float = 1.0, smooth_clip: float = 0.0, compute_stats_on: int = 50)
Bases:
objectConfiguration for video transformations.
- selected_channel
Channel to use for aggregation If None, channel average is done. If any, it performs channel selection
- Type:
int | None
- smooth_clip
Smoothness of the clipping process (log clipping) See ScaleAndNormalize: it logs clip the highest values on q_max. If 0.0, hard clipping is done.
- Type:
- class byotrack.video.video.Video(data_source: str | PathLike | VideoReader | ndarray, **kwargs: Any)
Bases:
Sequence[ndarray]Video: Iterable, indexable and sliceable sequence of frames wrapping a VideoReader.
It wraps VideoReader in order to add video preprocessing (Channel Aggregation, Normalization, Projection, …) and to add useful pythonic protocols (Sliceable, Indexable, Iterable).
Frames are 2D or 3D with a channel axis. It behaves similarly as a 5D/4D numpy array of shape (T[, D], H, W, C).
Example
import byotrack # Read a video (Usually 2D RGB) video = byotrack.Video(video_path) # Normalize the video video = video.normalize() # Iterate through the video for frame in video: pass # Temporal slicing sliced = video[10:50:3] # Take one frame every three from frame 10 to frame 50. # Spatial slicing sliced = video[:, 100:200, 150:250] # All frames on the roi (100:200 x 150:250)
- dtype
Data type of the video.
- Type:
np.dtype
- reader
Underlying video reader
- Type:
byotrack.video.VideoReader
- add_preprocessor(preprocessor: VideoPreprocessor) Video
Add a preprocessor to the video.
Added preprocessors are applied sequentially (you may check the order in _preprocessors).
Note: This may change the shape or dtype of the Video.
- Parameters:
preprocessor (byotrack.video.VideoPreprocessor) – The preprocessor to add. Will be initialized with this video.
- Returns:
self
- Return type:
byotrack.Video
- normalize(q_min: float = 0.0, q_max: float = 1.0, smooth_clip: float = 0, compute_stats_on: int = 50) Video
Normalize each channel of the video into [0, 1].
Copy the video and adds the IntensityNormalizer preprocessor with the given arguments.
- Parameters:
q_min (float) – Quantile of the minimum value to consider. Default: 0.0 (min value)
q_max (float) – Quantile of the maximum value to consider. Default: 1.0 (max value)
smooth_clip (float) – Smoothness of the clipping process (a) If 0, values are clipped on the quantiles Else, values above the maximum quantile are log clipped: I = 1 + a log((I - 1)/a + 1) for I > 1, with a the smooth_clip factor Typical values are between 0 and 1. Default: 0 (hard clipping)
compute_stats_on (int) – Max number of frames to compute stats on. It prevents heavy computations that may occur on large videos. Default: 50
- Returns:
the normalized video
- Return type:
byotrack.Video
- set_transform(transform_config: VideoTransformConfig) None
Deprecated. Will be removed in a future version.
- __getitem__(index: int) ndarray
- __getitem__(slice_: slice) Video
- __getitem__(slices: tuple[slice | int | EllipsisType, ...] | EllipsisType) Video
Indexing and slicing operations.
When indexed, it returns the ith frame in the slice. When sliced, it duplicates the video (wrapper) with the right slicing.
Video Reader
- byotrack.video.reader.slice_length(slice_: slice, shape: int) int
Compute the number of element in a slice.
- class byotrack.video.reader.MetaVideoReader(cls_name: str, bases: tuple, attributes: dict)
Bases:
typeMetaClass for Video Readers.
Each VideoReader has to define a list of supported extensions. The last constructed VideoReader to claim an extension will be used to open the video. If no one has claimed an extension the default OpenCVVideoReader is used.
- class byotrack.video.reader.VideoReader(path: str | os.PathLike, **kwargs: Any)
Bases:
objectUnified video reader api.
Close to OpenCV API but few key differences:
There is always a frame loaded
Frame ids goes from 0 to length - 1
Frames are loaded in RGB.
It support any number of channels and 2D/3D
Read method is very different:
It retrieves the current frame then grabs the next (The other way around in opencv)
It returns therefore a ndarray and a bool rather than a bool and a ndarray
The boolean returned indicated if we can continue to read and not if the read operation has failed
Easy to check main attributes like:
frame_id
length
channels
shape
dtype
fps if known (-1 otherwise)
- supported_extensions
Static attribute used by the open factory to automatically select the right VideoReader subclass for a given file extension.
- path
Path of the current video.
- Type:
- dtype
Data type of the frames.
- Type:
np.dtype
- grab() bool
Grab the next frame.
Can be faster than self.seek(self.frame_id + 1)
- Returns:
True if able to grab next frame
- Return type:
- retrieve() ndarray
Retrieve the current frame.
- Returns:
- The current frame
Shape: ([D, ]H, W, C)
- Return type:
np.ndarray
- read() tuple[ndarray, bool]
Consume a frame. Is equivalent to retrieve + grab.
As in this implementation there is always a current frame. It reverses OpenCV implementation It first retrieves then grab next frame
- Returns:
The current frame - Shape: ([D, ]H, W, C) bool: Whether there is a next frame to read
- Return type:
np.ndarray
- seek(frame_id: int) None
Seek to frame_id and update the current frame.
Valid frame ids are in [0, length[.
- static open(path: str | os.PathLike, **kwargs: Any) VideoReader
Open a video file, choosing the right reader from the file extension.
Directories are opened with MultiFrameReader. For files, the extension is looked up in the
extension_to_readerregistry; if no match is found, OpenCVVideoReader is used.- Parameters:
path (str | os.PathLike) – File or directory to open.
**kwargs – Additional kwargs forwarded to the chosen VideoReader constructor.
- Returns:
An open reader positioned at frame 0.
- Return type:
- class byotrack.video.reader.OpenCVVideoReader(path: str | os.PathLike, **kwargs: Any)
Bases:
VideoReaderWrapper around opencv VideoCapture.
Default VideoReader when opening a file.
It only supports 2D images (grayscale or RGB).
- video
VideoCapture from opencv
- Type:
cv2.VideoCapture
- grab() bool
Grab the next frame.
Can be faster than self.seek(self.frame_id + 1)
- Returns:
True if able to grab next frame
- Return type:
- retrieve() ndarray
Retrieve the current frame.
- Returns:
- The current frame
Shape: ([D, ]H, W, C)
- Return type:
np.ndarray
- class byotrack.video.reader.ArrayVideoReader(path: str | os.PathLike, video: np.ndarray, **kwargs: Any)
Bases:
VideoReaderFake VideoReader that directly reads in the given an array-like video.
It’s main goal is to provide a conversion from array-like videos (np.ndarray, zarr, …).
The array-like video is expected to be of shape: T, [D, ]H, W, C.
Note: path is ignored, and the data should be provided via the video argument.
- video
Array-like video. Shape: (T, [D, ]H, W, C)
- Type:
np.ndarray
- grab() bool
Grab the next frame.
Can be faster than self.seek(self.frame_id + 1)
- Returns:
True if able to grab next frame
- Return type:
- seek(frame_id: int) None
Seek to frame_id and update the current frame.
Valid frame ids are in [0, length[.
- retrieve() ndarray
Retrieve the current frame.
- Returns:
- The current frame
Shape: ([D, ]H, W, C)
- Return type:
np.ndarray
- class byotrack.video.reader.PILVideoReader(path: str | os.PathLike, **kwargs: Any)
Bases:
VideoReaderPIL-based video reader for 2D multi-frame TIFF files not supported by OpenCV.
It only supports 2D videos. Prefer TiffVideoReader for broader TIFF support (3D, any channels).
See VideoReader for inherited attributes.
- video
The open PIL image (animated).
- Type:
PIL.Image.Image
- grab() bool
Grab the next frame.
Can be faster than self.seek(self.frame_id + 1)
- Returns:
True if able to grab next frame
- Return type:
- retrieve() ndarray
Retrieve the current frame.
- Returns:
- The current frame
Shape: ([D, ]H, W, C)
- Return type:
np.ndarray
- class byotrack.video.reader.TiffVideoReader(path: str | os.PathLike, level=0, axes: str | None = None, ax_slice: dict[str, slice] | None = None, **kwargs: Any)
Bases:
VideoReaderTiff video reader with tifffile. Handle 2D and 3D videos with any channels.
Axes are inferred from the tifffile metadata and convert into (T, [D, ]H, W, C) (<=> T[Z]YXC). We may not support all formats, or your specific metadata can be wrong/missing. In this case, you can also provide the expected axes of the tifffile using an ordered string.
For example: “TYX” for 2D videos without channel, “TCZYX” for 3D videos with channels (ordered by time, channel then stack), “ZTYX” for 3D videos without channels (ordered by stack then time).
Note
With tifffile syntax, we use X for width, Y for height, Z for depth and C/S for channels (C and S are not supported together) and T for time. Any other letter (I, O, Q, …) is first interpret as T if it is missing, then Z if it is missing, and finally it will yield an error.
It also supports to read the tiff at a specific resolution level
See VideoReader for inherited attributes.
- grab() bool
Grab the next frame.
Can be faster than self.seek(self.frame_id + 1)
- Returns:
True if able to grab next frame
- Return type:
- seek(frame_id: int) None
Seek to frame_id and update the current frame.
Valid frame ids are in [0, length[.
- retrieve() ndarray
Retrieve the current frame.
- Returns:
- The current frame
Shape: ([D, ]H, W, C)
- Return type:
np.ndarray
- class byotrack.video.reader.FrameTiffLoader(level=0, axes: str | None = None, ax_slice: dict[str, slice] | None = None)
Bases:
objectLoad a single frame stored in a TiffFile with tifffile.
It handle 2D and 3D videos with any channels. Axes are inferred from the tifffile metadata and convert into ([D, ]H, W, C) (<=> [Z]YXC).
We may not support all formats, or your specific metadata can be wrong/missing. In this case, you can also provide the expected axes of the tifffile using an ordered string.
For example: “YX” for 2D videos without channel, “CZYX” for 3D videos with channels (ordered by channel then stack).
Note
With tifffile syntax, we use X for width, Y for height, Z for depth and C/S for channels (C and S are not supported together). Any other letter (T, I, O, Q, …) is either interpreted as Z if it is missing, or it will yield an error.
It also supports to read the tiff at a specific resolution level.
- byotrack.video.reader.pil_loader(path: str | os.PathLike) np.ndarray
Load a 2D image with PIL.
- Parameters:
path (str | os.PathLike) – Path to the image file.
- Returns:
- The loaded frame.
Shape: (H, W, C).
- Return type:
np.ndarray
- class byotrack.video.reader.MultiFrameReader(path: str | os.PathLike, paths: Sequence[str | os.PathLike] | None = None, extension: str | None = None, frame_loader: Callable[[str | os.PathLike], np.ndarray] | None = None, **kwargs: Any)
Bases:
VideoReaderRead video from a list of files inside a folder.
By default, it will find the alphanumerically sorted list of paths that shares the most common extension in the folder. The extension may be provided by the user.
You can provide your own list of paths (absolute paths). The folder path is then ignored.
Finally, you may also provide your own loading function to load each frame as a numpy array.
See VideoReader for inherited attributes.
- paths
Sorted list of Paths to each frame of the video.
- Type:
- frame_loader
Loads frame from their associated files.
- Type:
Callable[[str | os.PathLike], np.ndarray]
- grab() bool
Grab the next frame.
Can be faster than self.seek(self.frame_id + 1)
- Returns:
True if able to grab next frame
- Return type:
- seek(frame_id: int) None
Seek to frame_id and update the current frame.
Valid frame ids are in [0, length[.
- retrieve() ndarray
Retrieve the current frame.
- Returns:
- The current frame
Shape: ([D, ]H, W, C)
- Return type:
np.ndarray
Video Preprocessors
- class byotrack.video.preprocessor.preprocessor.VideoPreprocessor
Bases:
ABCVideo preprocessor base class.
A preprocessor can both change the intensity (normalization, denoising, frame filtering, …) as well as the shape (Z-projection, channel aggregation, slicing, …) of each video frame.
It first needs to be initialized on the given video (where it can read the video if needed). Then, it is applied online, i.e., for each frame of the video.
- dtype
Output dtype of each frame. Usually independent of the input video.
- Type:
np.dtype
- initialize(video: Sequence[np.ndarray] | np.ndarray) None
Initialize the preprocessor for the given video.
The default implementation preserve the video shape and dtype. This should be overwritten by VideoProcessor implementations.
- Parameters:
video (Sequence[np.ndarray] | np.ndarray) – The video to preprocess. Sequence of T frames (array). Each array is expected to have a shape ([D, ]H, W, C).
- abstractmethod preprocess_frame(frame: ndarray, frame_id=0) ndarray
Preprocess the given frame.
- Parameters:
frame (np.ndarray) – Frame to be preprocessed. Shape: ([D, ]H, W, C)
frame_id (int) – Optional index of the frame in the video. Default to 0.
- Returns:
- Preprocessed frame.
Shape ([D’, ]H’, W’, C’)
- Return type:
np.ndarray
- preprocess_video(video: Sequence[np.ndarray] | np.ndarray) np.ndarray
Preprocess the given video directly.
It will re-initialize the preprocessor at each call.
- Warning: Consider using the online version, which is integrated into the Video class.
This will requires much more memory than its online counterpart.
- Parameters:
video (Sequence[np.ndarray] | np.ndarray) – The video to preprocess. Sequence of T frames (array). Each array is expected to have a shape ([D, ]H, W, C).
- Returns:
The preprocessed video loaded as a np.ndarray.
- Return type:
np.ndarray
- class byotrack.video.preprocessor.normalizer.IntensityNormalizer(q_min: float, q_max: float, smooth_clip: float = 0, compute_stats_on: int = 50)
Bases:
VideoPreprocessorNormalize each channel intensity into [0, 1].
mini and maxi values are computed using quantile of the video to improve stability. The quantiles are computed using only the first compute_stats_on frames.
Frame shape is preserved, but dtype is changed to float32.
Note: A smooth_clip can be performed by log clipping values above maxi up until the log max.
- mini
Minimum value kept (one for each channel) Shape: (C, ), dtype: float32
- Type:
np.ndarray
- maxi
Maximum value kept (one for each channel) Shape: (C, ), dtype: float32
- Type:
np.ndarray
- smooth_clip
Smoothness of the clipping process (a) If 0, values are clipped on mini/maxi Else, values above maxi are log clipped: I = 1 + a log((I - 1)/a + 1) for I > 1, with a the smooth_clip factor Typical values are between 0 and 1. Default: 0 (hard clipping)
- Type:
- max
True maximum values (one for each channel) when using smooth clipping Shape: (C, ), dtype: float32
- Type:
np.ndarray
- compute_stats_on
Max number of frames to compute stats on. It prevents heavy computations that may occur on large videos. Default: 50
- Type:
- initialize(video: Sequence[np.ndarray] | np.ndarray) None
Initialize the preprocessor for the given video.
It computes mini and maxi values based on the first frames of the video.
- Parameters:
video (Sequence[np.ndarray] | np.ndarray) – The video to preprocess. Sequence of T frames (array). Each array is expected to have a shape ([D, ]H, W, C).
- preprocess_frame(frame: ndarray, frame_id=0) ndarray
Preprocess the given frame.
- Parameters:
frame (np.ndarray) – Frame to be preprocessed. Shape: ([D, ]H, W, C)
frame_id (int) – Optional index of the frame in the video. Default to 0.
- Returns:
- Preprocessed frame.
Shape ([D’, ]H’, W’, C’)
- Return type:
np.ndarray
- class byotrack.video.preprocessor.channel_projection.ChannelProjection(method: Literal['mean', 'min', 'max', 'select'] = 'mean', selected: int = 0)
Bases:
VideoPreprocessorProjection of the video channel.
Allows to reduce multi-channel videos into single channel videos.
- method
Projection method. “mean”, “min” and “max” aggregate the channels with the appropriate function. “select” simply selects one specific channel. Default: “mean”.
- Type:
Literal[“mean”, “min”, “max”, “select”]
- initialize(video: Sequence[np.ndarray] | np.ndarray) None
Initialize the preprocessor for the given video.
This will reduce the channel in the shape attribute.
- Parameters:
video (Sequence[np.ndarray] | np.ndarray) – The video to preprocess. Sequence of T frames (array). Each array is expected to have a shape ([D, ]H, W, C).
- preprocess_frame(frame: ndarray, frame_id=0) ndarray
Preprocess the given frame.
- Parameters:
frame (np.ndarray) – Frame to be preprocessed. Shape: ([D, ]H, W, C)
frame_id (int) – Optional index of the frame in the video. Default to 0.
- Returns:
- Preprocessed frame.
Shape ([D’, ]H’, W’, C’)
- Return type:
np.ndarray
- preprocess_video(video: Sequence[np.ndarray] | np.ndarray) np.ndarray
Preprocess the given video directly.
It will re-initialize the preprocessor at each call.
- Warning: Consider using the online version, which is integrated into the Video class.
This will requires much more memory than its online counterpart.
- Parameters:
video (Sequence[np.ndarray] | np.ndarray) – The video to preprocess. Sequence of T frames (array). Each array is expected to have a shape ([D, ]H, W, C).
- Returns:
The preprocessed video loaded as a np.ndarray.
- Return type:
np.ndarray
- class byotrack.video.preprocessor.spatial_projection.SpatialProjection(axis: str | int = 'Z', method: Literal['mean', 'min', 'max', 'select'] = 'max', selected: int = 0)
Bases:
VideoPreprocessorSpatial projection of the video along an axis.
It allows to project a 3D video onto a 2D one.
- axes_to_int
Mapping from axis name string (
"Z","Y","X","D","H","W") to integer axis index (0, 1, 2).
- method
Projection method.
"mean","min"and"max"aggregate over the axis with the appropriate function."select"selects one slice of the volume. Default:"max".- Type:
Literal[“mean”, “min”, “max”, “select”]
- initialize(video: Sequence[np.ndarray] | np.ndarray) None
Initialize the preprocessor for the given video.
This will set the shape attribute correctly, or raise if not 3D.
- Parameters:
video (Sequence[np.ndarray] | np.ndarray) – The video to preprocess. Sequence of T frames (array). Each array is expected to have a shape ([D, ]H, W, C).
- preprocess_frame(frame: ndarray, frame_id=0) ndarray
Preprocess the given frame.
- Parameters:
frame (np.ndarray) – Frame to be preprocessed. Shape: ([D, ]H, W, C)
frame_id (int) – Optional index of the frame in the video. Default to 0.
- Returns:
- Preprocessed frame.
Shape ([D’, ]H’, W’, C’)
- Return type:
np.ndarray
- preprocess_video(video: Sequence[np.ndarray] | np.ndarray) np.ndarray
Preprocess the given video directly.
It will re-initialize the preprocessor at each call.
- Warning: Consider using the online version, which is integrated into the Video class.
This will requires much more memory than its online counterpart.
- Parameters:
video (Sequence[np.ndarray] | np.ndarray) – The video to preprocess. Sequence of T frames (array). Each array is expected to have a shape ([D, ]H, W, C).
- Returns:
The preprocessed video loaded as a np.ndarray.
- Return type:
np.ndarray
- class byotrack.video.preprocessor.slicer.FrameSlicer(slices: tuple[slice, ...])
Bases:
VideoPreprocessorSlice the frame with given slices.
- initialize(video: Sequence[np.ndarray] | np.ndarray) None
Initialize the preprocessor for the given video.
This will update the shape attribute to reflect the output shape after slicing.
- Parameters:
video (Sequence[np.ndarray] | np.ndarray) – The video to preprocess. Sequence of T frames (array). Each array is expected to have a shape ([D, ]H, W, C).
- preprocess_frame(frame: ndarray, frame_id=0) ndarray
Preprocess the given frame.
- Parameters:
frame (np.ndarray) – Frame to be preprocessed. Shape: ([D, ]H, W, C)
frame_id (int) – Optional index of the frame in the video. Default to 0.
- Returns:
- Preprocessed frame.
Shape ([D’, ]H’, W’, C’)
- Return type:
np.ndarray
- preprocess_video(video: Sequence[np.ndarray] | np.ndarray) np.ndarray
Preprocess the given video directly.
It will re-initialize the preprocessor at each call.
- Warning: Consider using the online version, which is integrated into the Video class.
This will requires much more memory than its online counterpart.
- Parameters:
video (Sequence[np.ndarray] | np.ndarray) – The video to preprocess. Sequence of T frames (array). Each array is expected to have a shape ([D, ]H, W, C).
- Returns:
The preprocessed video loaded as a np.ndarray.
- Return type:
np.ndarray