Skip to content

Module wtracker.utils.frame_reader

View Source
from __future__ import annotations

import os

import glob

import numpy as np

import cv2 as cv

from wtracker.utils.path_utils import join_paths

class FrameReader:

    """

    An class for reading frames from a directory of frame files.

    Args:

        root_folder (str): The root folder path where the frame files are located.

        frame_files (list[str]): A list of frame file names.

        read_format (int, optional): The format in which the frames should be read.

    Attributes:

        root_folder (str): The root folder path where the frame files are located.

        frame_shape (tuple[int, ...]): The shape of the frame.

        frame_size (tuple[int, int]): The size of the frame.

        files (list[str]): The list of file paths.

        read_format (int): The read format of the frame reader.

    """

    def __init__(

        self,

        root_folder: str,

        frame_files: list[str],

        read_format: int = cv.IMREAD_GRAYSCALE,

    ):

        assert os.path.exists(root_folder)

        assert len(frame_files) > 0

        self._root_folder = root_folder

        self._files = frame_files

        self._read_format = read_format

        self._frame_shape = self._extract_frame_shape()

    def _extract_frame_shape(self) -> tuple[int, ...]:

        path = join_paths(self.root_folder, self.files[0])

        frame = cv.imread(path, self._read_format)

        return frame.shape

    @staticmethod

    def create_from_template(root_folder: str, name_format: str, read_format: int = cv.IMREAD_GRAYSCALE) -> FrameReader:

        """

        Creates a FrameReader object from a file name template.

        Args:

            root_folder (str): The root folder where the frame files are located.

            name_format (str): The format of the frame file names.

            read_format (int, optional): The format in which the frames should be read.

        Returns:

            FrameReader: The created FrameReader object.

        """

        # get all files matching name format

        fmt = name_format.format("[0-9]*")

        frame_paths = glob.glob(fmt, root_dir=root_folder)

        frame_paths = [f for f in frame_paths if os.path.isfile(join_paths(root_folder, f))]

        frame_paths = sorted(frame_paths)

        return FrameReader(root_folder, frame_paths, read_format)

    @staticmethod

    def create_from_directory(root_folder: str, read_format: int = cv.IMREAD_GRAYSCALE) -> FrameReader:

        """

        Creates a FrameReader object from a directory.

        Args:

            root_folder (str): The root folder containing the frame files.

            read_format (int, optional): The format in which the frames should be read.

        Returns:

            FrameReader: The created FrameReader object.

        """

        # get all files in root

        frame_paths = glob.glob("*.*", root_dir=root_folder)

        frame_paths = [f for f in frame_paths if os.path.isfile(join_paths(root_folder, f))]

        frame_paths = sorted(frame_paths)

        return FrameReader(root_folder, frame_paths, read_format)

    @property

    def root_folder(self) -> str:

        """

        Returns the root folder path.

        Returns:

            str: The root folder path.

        """

        return self._root_folder

    @property

    def frame_shape(self) -> tuple[int, ...]:

        """

        Returns the shape of the frame.

        Returns:

            tuple[int, ...]: The shape of the frame, in format (h, w, ...).

        """

        return self._frame_shape

    @property

    def frame_size(self) -> tuple[int, int]:

        """

        Returns the size of the frame.

        Returns:

            tuple[int, int]: The shape of the frame, in format (h, w).

        """

        return self._frame_shape[:2]

    @property

    def files(self) -> list[str]:

        """

        Returns the list of files associated with the FrameReader object.

        Returns:

            list[str]: The list of file paths.

        """

        return self._files

    @property

    def read_format(self) -> int:

        """

        Returns the read format of the frame reader.

        Returns:

            int: The read format.

        """

        return self._read_format

    def __len__(self) -> int:

        return len(self._files)

    def __getitem__(self, idx: int) -> np.ndarray:

        if idx < 0 or idx >= len(self._files):

            raise IndexError("index out of bounds")

        path = join_paths(self.root_folder, self.files[idx])

        frame = cv.imread(path, self._read_format)

        return frame.astype(np.uint8, copy=False)

    def __iter__(self):

        return FrameStream(self)

    def make_stream(self):

        """

        Creates and returns a FrameStream object using the current instance of FrameReader.

        Returns:

            FrameStream: A FrameStream object.

        """

        return FrameStream(self)

class FrameStream:

    """

    A class for streaming frames from a FrameReader object.

    This class serves as an iterator for the FrameReader object.

    Args:

        frame_reader (FrameReader): The frame reader object.

    """

    def __init__(self, frame_reader: FrameReader):

        self._frame_reader = frame_reader

        self._idx = -1

        self.frame = None

    @property

    def index(self) -> int:

        """

        The index of the current frame.

        """

        return self._idx

    def __len__(self):

        return len(self._frame_reader)

    def __iter__(self):

        return self

    def __next__(self) -> np.ndarray:

        self.progress()

        if not self.can_read():

            raise StopIteration()

        frame = self.read()

        return frame

    def can_read(self) -> bool:

        return self._idx >= 0 and self._idx < len(self._frame_reader)

    def seek(self, idx: int) -> bool:

        """

        Move the index to the specified position.

        Args:

            idx (int): The index to seek to.

        Returns:

            bool: True if the index is within the valid range, False otherwise.

        """

        self._idx = idx

        self.frame = None

        return self.can_read()

    def read(self) -> np.ndarray:

        """

        Read and return the frame at the current index.

        Raises:

            IndexError: If the index is out of bounds.

        Returns:

            np.ndarray: The frame at the current index.

        """

        if not self.can_read():

            raise IndexError("index out of bounds")

        if self.frame is None:

            self.frame = self._frame_reader[self._idx]

        return self.frame

    def progress(self, n: int = 1) -> bool:

        """

        Moves the current index forward by the specified number of steps.

        Args:

            n (int): The number of steps to move forward.

        Returns:

            bool: True if the index was successfully moved forward, False otherwise.

        """

        return self.seek(self._idx + n)

    def reset(self):

        """

        Resets the frame reader to the beginning of the steam.

        """

        self.seek(-1)

class DummyReader(FrameReader):

    """

    A dummy frame reader that generates empty frames of a specified resolution.

    Args:

        num_frames (int): The number of frames to generate.

        resolution (tuple[int, int]): The resolution of the frames, in format (h, w).

        colored (bool, optional): Whether the frames are colored or grayscale.

    """

    def __init__(self, num_frames: int, resolution: tuple[int, int], colored: bool = True):

        self.colored = colored

        self._resolution = resolution

        shape = (*resolution, 3) if colored else resolution

        self._frame = np.full(shape, fill_value=255, dtype=np.uint8)

        frames = [str(i) for i in range(num_frames)]

        super().__init__(".", frame_files=frames)

    def __getitem__(self, idx: int) -> np.ndarray:

        return self._frame.copy()

    def _extract_frame_shape(self) -> tuple[int, ...]:

        if self.colored:

            return (*self._resolution, 3)

        return self._resolution

Classes

DummyReader

class DummyReader(
    num_frames: 'int',
    resolution: 'tuple[int, int]',
    colored: 'bool' = True
)

A dummy frame reader that generates empty frames of a specified resolution.

Attributes

Name Type Description Default
num_frames int The number of frames to generate. None
resolution tuple[int, int] The resolution of the frames, in format (h, w). None
colored bool Whether the frames are colored or grayscale. None
View Source
class DummyReader(FrameReader):

    """

    A dummy frame reader that generates empty frames of a specified resolution.

    Args:

        num_frames (int): The number of frames to generate.

        resolution (tuple[int, int]): The resolution of the frames, in format (h, w).

        colored (bool, optional): Whether the frames are colored or grayscale.

    """

    def __init__(self, num_frames: int, resolution: tuple[int, int], colored: bool = True):

        self.colored = colored

        self._resolution = resolution

        shape = (*resolution, 3) if colored else resolution

        self._frame = np.full(shape, fill_value=255, dtype=np.uint8)

        frames = [str(i) for i in range(num_frames)]

        super().__init__(".", frame_files=frames)

    def __getitem__(self, idx: int) -> np.ndarray:

        return self._frame.copy()

    def _extract_frame_shape(self) -> tuple[int, ...]:

        if self.colored:

            return (*self._resolution, 3)

        return self._resolution

Ancestors (in MRO)

  • wtracker.utils.frame_reader.FrameReader

Static methods

create_from_directory

def create_from_directory(
    root_folder: 'str',
    read_format: 'int' = 0
) -> 'FrameReader'

Creates a FrameReader object from a directory.

Parameters:

Name Type Description Default
root_folder str The root folder containing the frame files. None
read_format int The format in which the frames should be read. None

Returns:

Type Description
FrameReader The created FrameReader object.
View Source
    @staticmethod

    def create_from_directory(root_folder: str, read_format: int = cv.IMREAD_GRAYSCALE) -> FrameReader:

        """

        Creates a FrameReader object from a directory.

        Args:

            root_folder (str): The root folder containing the frame files.

            read_format (int, optional): The format in which the frames should be read.

        Returns:

            FrameReader: The created FrameReader object.

        """

        # get all files in root

        frame_paths = glob.glob("*.*", root_dir=root_folder)

        frame_paths = [f for f in frame_paths if os.path.isfile(join_paths(root_folder, f))]

        frame_paths = sorted(frame_paths)

        return FrameReader(root_folder, frame_paths, read_format)

create_from_template

def create_from_template(
    root_folder: 'str',
    name_format: 'str',
    read_format: 'int' = 0
) -> 'FrameReader'

Creates a FrameReader object from a file name template.

Parameters:

Name Type Description Default
root_folder str The root folder where the frame files are located. None
name_format str The format of the frame file names. None
read_format int The format in which the frames should be read. None

Returns:

Type Description
FrameReader The created FrameReader object.
View Source
    @staticmethod

    def create_from_template(root_folder: str, name_format: str, read_format: int = cv.IMREAD_GRAYSCALE) -> FrameReader:

        """

        Creates a FrameReader object from a file name template.

        Args:

            root_folder (str): The root folder where the frame files are located.

            name_format (str): The format of the frame file names.

            read_format (int, optional): The format in which the frames should be read.

        Returns:

            FrameReader: The created FrameReader object.

        """

        # get all files matching name format

        fmt = name_format.format("[0-9]*")

        frame_paths = glob.glob(fmt, root_dir=root_folder)

        frame_paths = [f for f in frame_paths if os.path.isfile(join_paths(root_folder, f))]

        frame_paths = sorted(frame_paths)

        return FrameReader(root_folder, frame_paths, read_format)

Instance variables

files

Returns the list of files associated with the FrameReader object.

frame_shape

Returns the shape of the frame.

frame_size

Returns the size of the frame.

read_format

Returns the read format of the frame reader.

root_folder

Returns the root folder path.

Methods

make_stream

def make_stream(
    self
)

Creates and returns a FrameStream object using the current instance of FrameReader.

Returns:

Type Description
FrameStream A FrameStream object.
View Source
    def make_stream(self):

        """

        Creates and returns a FrameStream object using the current instance of FrameReader.

        Returns:

            FrameStream: A FrameStream object.

        """

        return FrameStream(self)

FrameReader

class FrameReader(
    root_folder: 'str',
    frame_files: 'list[str]',
    read_format: 'int' = 0
)

An class for reading frames from a directory of frame files.

Attributes

Name Type Description Default
root_folder str The root folder path where the frame files are located. None
frame_files list[str] A list of frame file names. None
read_format int The format in which the frames should be read. None
root_folder str The root folder path where the frame files are located. None
frame_shape tuple[int, ...] The shape of the frame. None
frame_size tuple[int, int] The size of the frame. None
files list[str] The list of file paths. None
read_format int The read format of the frame reader. None
View Source
class FrameReader:

    """

    An class for reading frames from a directory of frame files.

    Args:

        root_folder (str): The root folder path where the frame files are located.

        frame_files (list[str]): A list of frame file names.

        read_format (int, optional): The format in which the frames should be read.

    Attributes:

        root_folder (str): The root folder path where the frame files are located.

        frame_shape (tuple[int, ...]): The shape of the frame.

        frame_size (tuple[int, int]): The size of the frame.

        files (list[str]): The list of file paths.

        read_format (int): The read format of the frame reader.

    """

    def __init__(

        self,

        root_folder: str,

        frame_files: list[str],

        read_format: int = cv.IMREAD_GRAYSCALE,

    ):

        assert os.path.exists(root_folder)

        assert len(frame_files) > 0

        self._root_folder = root_folder

        self._files = frame_files

        self._read_format = read_format

        self._frame_shape = self._extract_frame_shape()

    def _extract_frame_shape(self) -> tuple[int, ...]:

        path = join_paths(self.root_folder, self.files[0])

        frame = cv.imread(path, self._read_format)

        return frame.shape

    @staticmethod

    def create_from_template(root_folder: str, name_format: str, read_format: int = cv.IMREAD_GRAYSCALE) -> FrameReader:

        """

        Creates a FrameReader object from a file name template.

        Args:

            root_folder (str): The root folder where the frame files are located.

            name_format (str): The format of the frame file names.

            read_format (int, optional): The format in which the frames should be read.

        Returns:

            FrameReader: The created FrameReader object.

        """

        # get all files matching name format

        fmt = name_format.format("[0-9]*")

        frame_paths = glob.glob(fmt, root_dir=root_folder)

        frame_paths = [f for f in frame_paths if os.path.isfile(join_paths(root_folder, f))]

        frame_paths = sorted(frame_paths)

        return FrameReader(root_folder, frame_paths, read_format)

    @staticmethod

    def create_from_directory(root_folder: str, read_format: int = cv.IMREAD_GRAYSCALE) -> FrameReader:

        """

        Creates a FrameReader object from a directory.

        Args:

            root_folder (str): The root folder containing the frame files.

            read_format (int, optional): The format in which the frames should be read.

        Returns:

            FrameReader: The created FrameReader object.

        """

        # get all files in root

        frame_paths = glob.glob("*.*", root_dir=root_folder)

        frame_paths = [f for f in frame_paths if os.path.isfile(join_paths(root_folder, f))]

        frame_paths = sorted(frame_paths)

        return FrameReader(root_folder, frame_paths, read_format)

    @property

    def root_folder(self) -> str:

        """

        Returns the root folder path.

        Returns:

            str: The root folder path.

        """

        return self._root_folder

    @property

    def frame_shape(self) -> tuple[int, ...]:

        """

        Returns the shape of the frame.

        Returns:

            tuple[int, ...]: The shape of the frame, in format (h, w, ...).

        """

        return self._frame_shape

    @property

    def frame_size(self) -> tuple[int, int]:

        """

        Returns the size of the frame.

        Returns:

            tuple[int, int]: The shape of the frame, in format (h, w).

        """

        return self._frame_shape[:2]

    @property

    def files(self) -> list[str]:

        """

        Returns the list of files associated with the FrameReader object.

        Returns:

            list[str]: The list of file paths.

        """

        return self._files

    @property

    def read_format(self) -> int:

        """

        Returns the read format of the frame reader.

        Returns:

            int: The read format.

        """

        return self._read_format

    def __len__(self) -> int:

        return len(self._files)

    def __getitem__(self, idx: int) -> np.ndarray:

        if idx < 0 or idx >= len(self._files):

            raise IndexError("index out of bounds")

        path = join_paths(self.root_folder, self.files[idx])

        frame = cv.imread(path, self._read_format)

        return frame.astype(np.uint8, copy=False)

    def __iter__(self):

        return FrameStream(self)

    def make_stream(self):

        """

        Creates and returns a FrameStream object using the current instance of FrameReader.

        Returns:

            FrameStream: A FrameStream object.

        """

        return FrameStream(self)

Descendants

  • wtracker.utils.frame_reader.DummyReader

Static methods

create_from_directory

def create_from_directory(
    root_folder: 'str',
    read_format: 'int' = 0
) -> 'FrameReader'

Creates a FrameReader object from a directory.

Parameters:

Name Type Description Default
root_folder str The root folder containing the frame files. None
read_format int The format in which the frames should be read. None

Returns:

Type Description
FrameReader The created FrameReader object.
View Source
    @staticmethod

    def create_from_directory(root_folder: str, read_format: int = cv.IMREAD_GRAYSCALE) -> FrameReader:

        """

        Creates a FrameReader object from a directory.

        Args:

            root_folder (str): The root folder containing the frame files.

            read_format (int, optional): The format in which the frames should be read.

        Returns:

            FrameReader: The created FrameReader object.

        """

        # get all files in root

        frame_paths = glob.glob("*.*", root_dir=root_folder)

        frame_paths = [f for f in frame_paths if os.path.isfile(join_paths(root_folder, f))]

        frame_paths = sorted(frame_paths)

        return FrameReader(root_folder, frame_paths, read_format)

create_from_template

def create_from_template(
    root_folder: 'str',
    name_format: 'str',
    read_format: 'int' = 0
) -> 'FrameReader'

Creates a FrameReader object from a file name template.

Parameters:

Name Type Description Default
root_folder str The root folder where the frame files are located. None
name_format str The format of the frame file names. None
read_format int The format in which the frames should be read. None

Returns:

Type Description
FrameReader The created FrameReader object.
View Source
    @staticmethod

    def create_from_template(root_folder: str, name_format: str, read_format: int = cv.IMREAD_GRAYSCALE) -> FrameReader:

        """

        Creates a FrameReader object from a file name template.

        Args:

            root_folder (str): The root folder where the frame files are located.

            name_format (str): The format of the frame file names.

            read_format (int, optional): The format in which the frames should be read.

        Returns:

            FrameReader: The created FrameReader object.

        """

        # get all files matching name format

        fmt = name_format.format("[0-9]*")

        frame_paths = glob.glob(fmt, root_dir=root_folder)

        frame_paths = [f for f in frame_paths if os.path.isfile(join_paths(root_folder, f))]

        frame_paths = sorted(frame_paths)

        return FrameReader(root_folder, frame_paths, read_format)

Instance variables

files

Returns the list of files associated with the FrameReader object.

frame_shape

Returns the shape of the frame.

frame_size

Returns the size of the frame.

read_format

Returns the read format of the frame reader.

root_folder

Returns the root folder path.

Methods

make_stream

def make_stream(
    self
)

Creates and returns a FrameStream object using the current instance of FrameReader.

Returns:

Type Description
FrameStream A FrameStream object.
View Source
    def make_stream(self):

        """

        Creates and returns a FrameStream object using the current instance of FrameReader.

        Returns:

            FrameStream: A FrameStream object.

        """

        return FrameStream(self)

FrameStream

class FrameStream(
    frame_reader: 'FrameReader'
)

A class for streaming frames from a FrameReader object.

This class serves as an iterator for the FrameReader object.

Attributes

Name Type Description Default
frame_reader FrameReader The frame reader object. None
View Source
class FrameStream:

    """

    A class for streaming frames from a FrameReader object.

    This class serves as an iterator for the FrameReader object.

    Args:

        frame_reader (FrameReader): The frame reader object.

    """

    def __init__(self, frame_reader: FrameReader):

        self._frame_reader = frame_reader

        self._idx = -1

        self.frame = None

    @property

    def index(self) -> int:

        """

        The index of the current frame.

        """

        return self._idx

    def __len__(self):

        return len(self._frame_reader)

    def __iter__(self):

        return self

    def __next__(self) -> np.ndarray:

        self.progress()

        if not self.can_read():

            raise StopIteration()

        frame = self.read()

        return frame

    def can_read(self) -> bool:

        return self._idx >= 0 and self._idx < len(self._frame_reader)

    def seek(self, idx: int) -> bool:

        """

        Move the index to the specified position.

        Args:

            idx (int): The index to seek to.

        Returns:

            bool: True if the index is within the valid range, False otherwise.

        """

        self._idx = idx

        self.frame = None

        return self.can_read()

    def read(self) -> np.ndarray:

        """

        Read and return the frame at the current index.

        Raises:

            IndexError: If the index is out of bounds.

        Returns:

            np.ndarray: The frame at the current index.

        """

        if not self.can_read():

            raise IndexError("index out of bounds")

        if self.frame is None:

            self.frame = self._frame_reader[self._idx]

        return self.frame

    def progress(self, n: int = 1) -> bool:

        """

        Moves the current index forward by the specified number of steps.

        Args:

            n (int): The number of steps to move forward.

        Returns:

            bool: True if the index was successfully moved forward, False otherwise.

        """

        return self.seek(self._idx + n)

    def reset(self):

        """

        Resets the frame reader to the beginning of the steam.

        """

        self.seek(-1)

Descendants

  • wtracker.sim.view_controller.ViewController

Instance variables

index

The index of the current frame.

Methods

can_read

def can_read(
    self
) -> 'bool'
View Source
    def can_read(self) -> bool:

        return self._idx >= 0 and self._idx < len(self._frame_reader)

progress

def progress(
    self,
    n: 'int' = 1
) -> 'bool'

Moves the current index forward by the specified number of steps.

Parameters:

Name Type Description Default
n int The number of steps to move forward. None

Returns:

Type Description
bool True if the index was successfully moved forward, False otherwise.
View Source
    def progress(self, n: int = 1) -> bool:

        """

        Moves the current index forward by the specified number of steps.

        Args:

            n (int): The number of steps to move forward.

        Returns:

            bool: True if the index was successfully moved forward, False otherwise.

        """

        return self.seek(self._idx + n)

read

def read(
    self
) -> 'np.ndarray'

Read and return the frame at the current index.

Returns:

Type Description
np.ndarray The frame at the current index.

Raises:

Type Description
IndexError If the index is out of bounds.
View Source
    def read(self) -> np.ndarray:

        """

        Read and return the frame at the current index.

        Raises:

            IndexError: If the index is out of bounds.

        Returns:

            np.ndarray: The frame at the current index.

        """

        if not self.can_read():

            raise IndexError("index out of bounds")

        if self.frame is None:

            self.frame = self._frame_reader[self._idx]

        return self.frame

reset

def reset(
    self
)

Resets the frame reader to the beginning of the steam.

View Source
    def reset(self):

        """

        Resets the frame reader to the beginning of the steam.

        """

        self.seek(-1)

seek

def seek(
    self,
    idx: 'int'
) -> 'bool'

Move the index to the specified position.

Parameters:

Name Type Description Default
idx int The index to seek to. None

Returns:

Type Description
bool True if the index is within the valid range, False otherwise.
View Source
    def seek(self, idx: int) -> bool:

        """

        Move the index to the specified position.

        Args:

            idx (int): The index to seek to.

        Returns:

            bool: True if the index is within the valid range, False otherwise.

        """

        self._idx = idx

        self.frame = None

        return self.can_read()