Source code for cutcutcodec.core.generation.video.noise

"""Generate a video noise signal."""

import hashlib
import math
import numbers
import struct
import typing
from fractions import Fraction

import numpy as np
import torch

from cutcutcodec.core.classes.colorspace import Colorspace
from cutcutcodec.core.classes.container import ContainerInput
from cutcutcodec.core.classes.stream import Stream
from cutcutcodec.core.classes.stream_video import StreamVideo
from cutcutcodec.core.exceptions import OutOfTimeRange
from cutcutcodec.core.interfaces.seedable import Seedable


[docs] class GeneratorVideoNoise(ContainerInput, Seedable): """Generate a pure noise video signal. Examples -------- >>> from cutcutcodec.core.generation.video.noise import GeneratorVideoNoise >>> stream = GeneratorVideoNoise(0).out_streams[0] >>> stream.snapshot(0, (13, 9))[..., 0] tensor([[0.4976, 0.1507, 0.7209, 0.9210, 0.4234, 0.6914, 0.5738, 0.7943, 0.2666], [0.8495, 0.8949, 0.1428, 0.2344, 0.7305, 0.2934, 0.7902, 0.7953, 0.7240], [0.8922, 0.5601, 0.3209, 0.7038, 0.6147, 0.6749, 0.5931, 0.4498, 0.8169], [0.8651, 0.8585, 0.6637, 0.7421, 0.7787, 0.8397, 0.5273, 0.1200, 0.0898], [0.6951, 0.8386, 0.0467, 0.0464, 0.3364, 0.7802, 0.2447, 0.4340, 0.5589], [0.6606, 0.0946, 0.4455, 0.7455, 0.3952, 0.1906, 0.1819, 0.0491, 0.0420], [0.8508, 0.9034, 0.9956, 0.1559, 0.8482, 0.7545, 0.7674, 0.2627, 0.4990], [0.6151, 0.8380, 0.2572, 0.2566, 0.2822, 0.6001, 0.2548, 0.5048, 0.5755], [0.0945, 0.3594, 0.7347, 0.7935, 0.6703, 0.7138, 0.1562, 0.2473, 0.9415], [0.9597, 0.8605, 0.6243, 0.6964, 0.2863, 0.2299, 0.9015, 0.5524, 0.5453], [0.7710, 0.3945, 0.5054, 0.7245, 0.1786, 0.1364, 0.3120, 0.0159, 0.6122], [0.6102, 0.5685, 0.2871, 0.2369, 0.5085, 0.9186, 0.3615, 0.7656, 0.0692], [0.0971, 0.0807, 0.6121, 0.7933, 0.5584, 0.4088, 0.8809, 0.1755, 0.2246]]) >>> """ def __init__(self, seed: numbers.Real | None = None): """Initialise and create the class. Parameters ---------- seed : numbers.Real, optional Transmitted to :py:class:`cutcutcodec.core.interfaces.seedable.Seedable`. """ Seedable.__init__(self, seed) super().__init__([_StreamVideoNoiseUniform(self)]) def _getstate(self) -> dict: return self._getstate_seed() def _setstate(self, in_streams: typing.Iterable[Stream], state: dict) -> None: assert state.keys() == {"seed"}, set(state) self._setstate_seed(state) ContainerInput.__init__(self, [_StreamVideoNoiseUniform(self)])
class _StreamVideoNoiseUniform(StreamVideo): """Random video stream where each pixel follows a uniform law.""" colorspace = Colorspace.from_default_working() def __init__(self, node: GeneratorVideoNoise): assert isinstance(node, GeneratorVideoNoise), node.__class__.__name__ super().__init__(node) def _snapshot(self, timestamp: Fraction, mask: torch.Tensor) -> torch.Tensor: if timestamp < 0: raise OutOfTimeRange(f"there is no audio frame at timestamp {timestamp} (need >= 0)") seed = int.from_bytes( hashlib.md5( struct.pack( "dLL", self.node.seed, timestamp.numerator % (1 << 64), timestamp.denominator % (1 << 64), ), ).digest(), byteorder="big", ) % (1 << 64) # solve RuntimeError: Overflow when unpacking long return torch.from_numpy( np.random.Generator(np.random.SFC64(seed=seed)) # np.random.default_rng(seed=seed) .random((*mask.shape, 3), dtype=np.float32), ) # numpy 1.24.1 vs torch 2.0.0 is 11 times faster # this version is faster: # return torch.from_numpy( # np.random.Generator(np.random.SFC64(seed=seed)) # np.random.default_rng(seed=seed) # .integers(0, 256, (*mask.shape, 3), dtype=np.uint8) # ) @property def beginning(self) -> Fraction: return Fraction(0) @property def duration(self) -> Fraction | float: return math.inf