Skip to content

motion

Classes:

  • MotionVectors

    Class for storing and managing motion vectors for a video clip.

MotionVectors

MotionVectors()

Bases: defaultdict[MVDirection, dict[int, VideoNode]], VSObject

Class for storing and managing motion vectors for a video clip.

Contains both backward and forward motion vectors.

Methods:

  • analysis_data
  • clear

    Clear all stored motion vectors.

  • get_vector

    Get a single motion vector.

  • get_vectors

    Get the backward and forward vectors.

  • scale_vectors

    Scales image_size, block_size, overlap, padding, and the individual motion_vectors contained in Analyse output

  • scaled

    Whether motion vectors have been scaled.

  • set_vector

    Store a motion vector.

  • show_vector

    Draws generated vectors onto a clip.

Attributes:

  • tr (int) –

    Temporal radius of the motion vectors.

Source code in vsdenoise/mvtools/motion.py
25
26
def __init__(self) -> None:
    super().__init__(None, {w: {} for w in MVDirection})

tr property

tr: int

Temporal radius of the motion vectors.

analysis_data

analysis_data() -> None
Source code in vsdenoise/mvtools/motion.py
130
131
132
@analysis_data.deleter  # type: ignore[no-redef]
def analysis_data(self) -> None:
    cachedproperty.clear_cache(self, "analysis_data")

clear

clear() -> None

Clear all stored motion vectors.

Source code in vsdenoise/mvtools/motion.py
28
29
30
31
32
33
34
35
36
def clear(self) -> None:
    """
    Clear all stored motion vectors.
    """

    for v in self.values():
        v.clear()

    cachedproperty.clear_cache(self)

get_vector

get_vector(direction: MVDirection, delta: int) -> VideoNode

Get a single motion vector.

Parameters:

  • direction

    (MVDirection) –

    Motion vector direction to get.

  • delta

    (int) –

    Motion vector delta to get.

Returns:

  • VideoNode

    A single motion vector VideoNode

Source code in vsdenoise/mvtools/motion.py
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
def get_vector(self, direction: MVDirection, delta: int) -> vs.VideoNode:
    """
    Get a single motion vector.

    Args:
        direction: Motion vector direction to get.
        delta: Motion vector delta to get.

    Returns:
        A single motion vector VideoNode
    """

    if delta > self.tr:
        raise CustomRuntimeError(
            "Tried to get a motion vector delta larger than what exists!",
            self.get_vector,
            f"{delta} > {self.tr}",
        )

    return self[direction][delta]

get_vectors

get_vectors(
    direction: MVDirection = BOTH, tr: int | None = None
) -> tuple[list[VideoNode], list[VideoNode]]

Get the backward and forward vectors.

Parameters:

  • direction

    (MVDirection, default: BOTH ) –

    Motion vector direction to get.

  • tr

    (int | None, default: None ) –

    The number of frames to get the vectors for.

Returns:

  • list[VideoNode]

    A tuple containing two lists of motion vectors.

  • list[VideoNode]

    The first list contains backward vectors and the second contains forward vectors.

Source code in vsdenoise/mvtools/motion.py
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def get_vectors(
    self,
    direction: MVDirection = MVDirection.BOTH,
    tr: int | None = None,
) -> tuple[list[vs.VideoNode], list[vs.VideoNode]]:
    """
    Get the backward and forward vectors.

    Args:
        direction: Motion vector direction to get.
        tr: The number of frames to get the vectors for.

    Returns:
        A tuple containing two lists of motion vectors.
        The first list contains backward vectors and the second contains forward vectors.
    """

    tr = fallback(tr, self.tr)

    if tr > self.tr:
        raise CustomRuntimeError(
            "Tried to obtain more motion vectors than what exist!", self.get_vectors, f"{tr} > {self.tr}"
        )

    vectors_backward = list[vs.VideoNode]()
    vectors_forward = list[vs.VideoNode]()

    for delta in range(1, tr + 1):
        if direction in [MVDirection.BACKWARD, MVDirection.BOTH]:
            vectors_backward.append(self[MVDirection.BACKWARD][delta])
        if direction in [MVDirection.FORWARD, MVDirection.BOTH]:
            vectors_forward.append(self[MVDirection.FORWARD][delta])

    return (vectors_backward, vectors_forward)

scale_vectors

scale_vectors(scale: int | tuple[int, int], strict: bool = True) -> None

Scales image_size, block_size, overlap, padding, and the individual motion_vectors contained in Analyse output by arbitrary and independent x and y factors.

Parameters:

Source code in vsdenoise/mvtools/motion.py
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
def scale_vectors(self, scale: int | tuple[int, int], strict: bool = True) -> None:
    """
    Scales image_size, block_size, overlap, padding, and the individual motion_vectors contained in Analyse output
    by arbitrary and independent x and y factors.

    Args:
        scale: Factor to scale motion vectors by.
    """

    supported_blksize = (
        (4, 4),
        (8, 4),
        (8, 8),
        (16, 2),
        (16, 8),
        (16, 16),
        (32, 16),
        (32, 32),
        (64, 32),
        (64, 64),
        (128, 64),
        (128, 128),
    )

    scalex, scaley = normalize_seq(scale, 2)

    if scalex > 1 or scaley > 1:
        blksizex, blksizev = self.analysis_data["Analysis_BlockSize"]

        scaled_blksize = (blksizex * scalex, blksizev * scaley)

        if strict and scaled_blksize not in supported_blksize:
            raise CustomRuntimeError("Unsupported block size!", self.scale_vectors, scaled_blksize)

        del self.analysis_data
        cachedproperty.update_cache(self, "scaled", True)

        for delta in range(1, self.tr + 1):
            for direction in MVDirection:
                self[direction][delta] = self[direction][delta].manipmv.ScaleVect(scalex, scaley)

scaled

scaled() -> bool

Whether motion vectors have been scaled.

Source code in vsdenoise/mvtools/motion.py
200
201
202
203
204
@cachedproperty
def scaled(self) -> bool:
    """Whether motion vectors have been scaled."""

    return False

set_vector

set_vector(vector: VideoNode, direction: MVDirection, delta: int) -> None

Store a motion vector.

Parameters:

  • vector

    (VideoNode) –

    Motion vector clip to store.

  • direction

    (MVDirection) –

    Direction of the motion vector (forward or backward).

  • delta

    (int) –

    Frame distance for the motion vector.

Source code in vsdenoise/mvtools/motion.py
38
39
40
41
42
43
44
45
46
47
48
def set_vector(self, vector: vs.VideoNode, direction: MVDirection, delta: int) -> None:
    """
    Store a motion vector.

    Args:
        vector: Motion vector clip to store.
        direction: Direction of the motion vector (forward or backward).
        delta: Frame distance for the motion vector.
    """

    self[direction][delta] = vector

show_vector

show_vector(
    clip: VideoNode,
    direction: Literal[FORWARD, BACKWARD] = FORWARD,
    delta: int = 1,
    scenechange: bool | None = None,
) -> VideoNode

Draws generated vectors onto a clip.

Parameters:

  • clip

    (VideoNode) –

    The clip to overlay the motion vectors on.

  • direction

    (Literal[FORWARD, BACKWARD], default: FORWARD ) –

    Motion vector direction to use.

  • delta

    (int, default: 1 ) –

    Motion vector delta to use.

  • scenechange

    (bool | None, default: None ) –

    Skips drawing vectors if frame props indicate they are from a different scene than the current frame of the clip.

Returns:

  • VideoNode

    Clip with motion vectors overlaid.

Source code in vsdenoise/mvtools/motion.py
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
def show_vector(
    self,
    clip: vs.VideoNode,
    direction: Literal[MVDirection.FORWARD, MVDirection.BACKWARD] = MVDirection.FORWARD,
    delta: int = 1,
    scenechange: bool | None = None,
) -> vs.VideoNode:
    """
    Draws generated vectors onto a clip.

    Args:
        clip: The clip to overlay the motion vectors on.
        direction: Motion vector direction to use.
        delta: Motion vector delta to use.
        scenechange: Skips drawing vectors if frame props indicate they are from a different scene than the current
            frame of the clip.

    Returns:
        Clip with motion vectors overlaid.
    """

    vect = self.get_vector(direction, delta)

    return clip.manipmv.ShowVect(vect, scenechange)