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()