Skip to content

motion

Classes:

  • MotionVectors

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

MotionVectors

MotionVectors(
    blksize: int | tuple[int, int] | None = None,
    overlap_div: int | tuple[int, int] | None = None,
)

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

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

  • set_vector

    Store a motion vector.

  • show_vector

    Draws generated vectors onto a clip.

Attributes:

Source code in vsdenoise/mvtools/motion.py
25
26
27
28
29
30
31
32
33
34
35
def __init__(
    self,
    blksize: int | tuple[int, int] | None = None,
    overlap_div: int | tuple[int, int] | None = None,
) -> None:
    super().__init__(None, {w: {} for w in MVDirection})
    self.scaled = False
    self._blksize: tuple[int, int] | None = None
    self._overlap_div: tuple[int, int] | None = None
    self.blksize = blksize
    self.overlap_div = overlap_div

blksize property writable

blksize: tuple[int, int] | None

deltas property

deltas: list[int]

List of active deltas.

overlap_div property writable

overlap_div: tuple[int, int] | None

scaled instance-attribute

scaled = False

tr property

tr: int

Temporal radius of the motion vectors.

analysis_data

analysis_data() -> None
Source code in vsdenoise/mvtools/motion.py
182
183
184
@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
76
77
78
79
80
81
82
83
84
85
86
def clear(self) -> None:
    """
    Clear all stored motion vectors.
    """

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

    self._blksize = None
    self._overlap_div = None
    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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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 not in self[direction]:
        raise CustomRuntimeError(
            "Tried to get a motion vector delta that does not exist!", self.get_vector, f"{delta}"
        )

    return self[direction][delta]

get_vectors

get_vectors(
    direction: MVDirection = BOTH,
    tr: int | None = None,
    delta: int | Sequence[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.

  • delta

    (int | Sequence[int] | None, default: None ) –

    Specific delta(s) of motion vectors to retrieve.

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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
def get_vectors(
    self,
    direction: MVDirection = MVDirection.BOTH,
    tr: int | None = None,
    delta: int | Sequence[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.
        delta: Specific delta(s) of motion vectors to retrieve.

    Returns:
        A tuple containing two lists of motion vectors.
        The first list contains backward vectors and the second contains forward vectors.
    """
    if delta is not None:
        deltas = to_arr(delta)
    elif tr is not None:
        deltas = range(1, tr + 1)
    else:
        deltas = self.deltas

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

    for d in deltas:
        if direction in [MVDirection.BACKWARD, MVDirection.BOTH] and d in self[MVDirection.BACKWARD]:
            vectors_backward.append(self[MVDirection.BACKWARD][d])
        if direction in [MVDirection.FORWARD, MVDirection.BOTH] and d in self[MVDirection.FORWARD]:
            vectors_forward.append(self[MVDirection.FORWARD][d])

    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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
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
    #     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)
    raise NotImplementedError("scale_vectors is not supported with MVUtensils.")

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
88
89
90
91
92
93
94
95
96
97
98
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
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
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)

    raise NotImplementedError("show_vector is not supported with MVUtensils.")