Skip to main content

A vapoursynth plugin to do potentially useful things with motion vectors that have already been generated.

Project description

Manipulate Motion Vectors

A vapoursynth plugin to do potentially useful things with motion vectors that have already been generated.

Installation

The plugin is available on PyPI and can be installed with:

python -m pip install vapoursynth-manipmv

Overview

Motion vectors are useful for a variety of video processing tasks, and there is a long history of tooling related generating and using them. This historical tooling has generally coupled creating the motion vectors and consuming them into one plugin, MVTools. But it is the author's opinion that decoupled tooling with a standard interface is reasonable and desirable. There is not quite a standard interface among the various versions and ports of MVTools so for now this plugin specifically targets the conventions used by dubhater/vapoursynth-mvtools (see the assumed conventions section for details).

Functions

ExpandAnalysisData

Expands the binary MVTools_MVAnalysisData frame prop into separate frame props for convenience.

int       Analysis_MagicKey
int       Analysis_Version
int[x, y] Analysis_BlockSize
int       Analysis_Pel
int       Analysis_LevelCount
int       Analysis_DeltaFrame
int       Analysis_Backwards
int       Analysis_CpuFlags
int       Analysis_MotionFlags
int[x, y] Analysis_FrameSize
int[x, y] Analysis_Overlap
int[x, y] Analysis_BlockCount
int       Analysis_BitsPerSample
int[x, y] Analysis_ChromaRatio
int[x, y] Analysis_Padding

Usage

mvmanip.ExpandAnalysisData(vnode clip)

Parameters

  • clip:
    A clip generated by mv.Analyse() or which otherwise follows its conventions.

Examples

# Programmatically reference block size used
clip = vs.core.std.BlankClip()
msuper = clip.mv.Super()
forward = msuper.mv.Analyse()

annotated = forward.manipmv.ExpandAnalysisData()
block_size_x, block_size_y = annotated.get_frame(0).props["Analysis_BlockSize"]
print(f"Blocks used for analysis are {block_size_x}x{block_size_y}")

ScaleVect

[!WARNING] Arbitrary scaling of motion vectors is possible and conceptually reasonable and is thus allowed by this plugin. However subsequent operations which use the motion vectors may not support all of the scaled properties. For example scaling 8x8 blocks by 5x results in 40x40 blocks which aren't something Analyse supports generating.

Scales image_size, block_size, overlap, padding, and the individual motion_vectors contained in Analyse output by arbitrary and independent x and y factors. This is mostly useful to use motion vectors generated on a downscaled clip to perform operations on the full size clip (e.g. calculating motion vectors at 1080p and applying them at 4K).

Usage

manipmv.ScaleVect(vnode clip[, int scaleX=1, int scaleY=scaleX])

Parameters

  • clip:
    A clip generated by mv.Analyse() or which otherwise follows its conventions.
  • scaleX:
    The scale factor to use horizontally.
    This is limited to an 8 bit value, but practical scale factors are likely single digit.
    Default value is 1 (no scaling).
  • scaleY:
    The scale factor to use vertically.
    This is limited to an 8 bit value, but practical scale factors are likely single digit.
    Default value is the same as scaleX.

Examples

# Use vectors from 1080p clip to denoise 4K clip
SCALE = 2
HPAD = 16
VPAD = 16
clip = vs.core.std.BlankClip(width=3840, height=2160)
small_clip = clip.resize.Bilinear(clip.width // SCALE, clip.height // SCALE)

small_msuper = small_clip.mv.Super(hpad=HPAD, vpad=VPAD)
small_forward = small_msuper.mv.Analyse()
small_backward = small_msuper.mv.Analyse(isb=True)

big_msuper = clip.mv.Super(hpad=HPAD * SCALE, vpad=VPAD * SCALE)
upscaled_forward = small_forward.manipmv.ScaleVect(SCALE)
upscaled_backward = small_backward.manipmv.ScaleVect(SCALE)

denoised = clip.mv.Degrain1(big_msuper, upscaled_backward, upscaled_forward)
denoised.set_output()

ShowVect

Draws generated vectors onto a clip.

Usage

manipmv.ShowVect(vnode clip, vnode vectors[, bool useSceneChangeProps=True])

Parameters

  • clip:
    A YUV clip with 8/10/12/16 bit integer bitdepth and dimensions which match the vectors.
  • vectors:
    A clip generated by mv.Analyse() or which otherwise follows its conventions. The first frame of this clip will be fetched with the filter is instantiated to determine the pel and block_size used by the vectors.
  • useSceneChangeProps:
    Skips drawing vectors if frame props indicate they are from a different scene than the current frame of the clip. Specifically if the vectors are forwards then _SceneChangePrev and Scenechange are examined, and if the vectors are backwards _SceneChangeNext is examined. There are a few different filters which can stamp these frame props, but mv.SCDetection() should be preferred when visualizing vectors generated with delta greater than 1.

Examples

# This is not a terribly exciting example since the BlankClip doesn't move...
clip = vs.core.std.BlankClip(width=1920, height=1080)

msuper = clip.mv.Super()
forward = msuper.mv.Analyse()

clip = clip.mv.SCDetection(forward)
debug = clip.manipmv.ShowVect(forward)
debug.set_output()

Assumed Conventions

[!NOTE] No MVTools version really documents its conventions explicitly since they are considered to be internal. So the descriptions in this section should not be considered official, but they are hopefully correct, and serve to at least document the assumptions this plugin is making.

The dubhater/vapoursynth-mvtools plugin stores all of its working data for motion vectors as binary data in vapoursynth frame props on the clip which results from calling mv.Analyse(). Specifically there are two props of interest MVTools_MVAnalysisData and MVTools_vectors.

All of this data is serialized rather implictly from C++ structs. Most of these structs contain only signed integers (even for fields which do not have logical negative interpretations) and bytes are written with native endianness. For deserialization I have chosen to interpret fields that should not be negative (e.g. width, height, size) as unsigned and always use little endian byte order. These nuances are hopefully not relevant in practice as the positive integer range of a signed 32 bit integer is still much larger than practical video sizes and almost every host running MVTools is likely to be little endian natively. Still it would be nice conceptually if future motion vector work could make these conventions explicit; for this reason the types below will be listed with the signedness I think they should have.

MVTools_MVAnalysisData

This just contains some metadata about the context in which the vectors were generated. The length of this data is expected to always be 84 bytes (21 32-bit integers) in the following order:

[!IMPORTANT] The magic_key and version appear to be uninitialized by the MVTools plugin and so have no usable data in them.

u32 magic_key
u32 version
u32 block_size_x
u32 block_size_y
u32 pel
u32 level_count
i32 delta_frame
u32 backwards
u32 cpu_flags
u32 motion_flags
u32 width
u32 height
u32 overlap_x
u32 overlap_y
u32 block_count_x
u32 block_count_y
u32 bits_per_sample
u32 chroma_ratio_y
u32 chroma_ratio_x
u32 padding_x
u32 padding_y

MVTools_vectors

This contains the actual motion vector data for all levels of motion vector calculation. The structure of a single motion vector is simply:

i32 x
i32 y
u64 sad

These are serialized without any padding (16 bytes per vector). Each level is structured as:

u32 size
[] vectors

Again without any padding. So for example a level with 10 vectors would have a size value of 164 (16 bytes per vector * 10 vectors + 4 bytes for the size).

This is ultimately structured as:

u32 size
u32 valid
[] levels

Again without any padding. The value stored in size is therefore expected to be equivalent to the size which vapoursynth reports for the frame property. The valid value is expected to be 0 for situations where motion vectors are not present (e.g. the first frame of forwards vectors) and 1 for situations where motion vectors are present.

Maintenance notes

[!NOTE] This section is just so the maintainer doesn't forget how the repo is setup. This isn't really relevant for users.

Tests can be run with

zig build test --summary all

In theory everything is setup such that the following steps are sufficient to build the library, create a github release, and publish all the wheels to PyPI.

zig build version -- inc --patch
git commit -am "Bumping patch version"
git push

The release body can then be edited to whatever seems appropriate.

This depends on a number of third party github actions so any one of those could break. Zig could also make it easier or harder to get the version from build.zig.zon and the approach may need to be tweaked. For now it seems usable.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vapoursynth_manipmv-1.4.0.tar.gz (67.5 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

vapoursynth_manipmv-1.4.0-py3-none-win_amd64.whl (135.1 kB view details)

Uploaded Python 3Windows x86-64

vapoursynth_manipmv-1.4.0-py3-none-musllinux_1_2_x86_64.whl (30.2 kB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

vapoursynth_manipmv-1.4.0-py3-none-musllinux_1_2_aarch64.whl (19.4 kB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

vapoursynth_manipmv-1.4.0-py3-none-manylinux_2_17_x86_64.whl (30.5 kB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

vapoursynth_manipmv-1.4.0-py3-none-manylinux_2_17_aarch64.whl (19.5 kB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

vapoursynth_manipmv-1.4.0-py3-none-macosx_11_0_x86_64.whl (19.4 kB view details)

Uploaded Python 3macOS 11.0+ x86-64

vapoursynth_manipmv-1.4.0-py3-none-macosx_11_0_arm64.whl (19.8 kB view details)

Uploaded Python 3macOS 11.0+ ARM64

File details

Details for the file vapoursynth_manipmv-1.4.0.tar.gz.

File metadata

  • Download URL: vapoursynth_manipmv-1.4.0.tar.gz
  • Upload date:
  • Size: 67.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for vapoursynth_manipmv-1.4.0.tar.gz
Algorithm Hash digest
SHA256 589b6c7c5a134f02e0ea8d880afa42a0fd07e45d4750a3aaeb94776c73fdc5ad
MD5 074cae3c3dae446aaec940e6dae56328
BLAKE2b-256 081dc3f23ccdb2bee49db89af92fa31045f5500bbe3f05ec3308410c71f7153d

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_manipmv-1.4.0.tar.gz:

Publisher: build.yaml on Mikewando/manipulate-motion-vectors

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vapoursynth_manipmv-1.4.0-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for vapoursynth_manipmv-1.4.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 409786ffc9412df976c1973b43d4aa5ae49f176345033f777ba45f2dfb53a846
MD5 0c5b0f617c0e5669aa4fadc583c22d7b
BLAKE2b-256 8adf9777505792d81b5b18d6b3be16ed83738c05f82cf88df7d14c37b70e1244

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_manipmv-1.4.0-py3-none-win_amd64.whl:

Publisher: build.yaml on Mikewando/manipulate-motion-vectors

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vapoursynth_manipmv-1.4.0-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for vapoursynth_manipmv-1.4.0-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 8424f720737711f9a0a2861db56ba6418d858546b819743a6911a36e0fd33a95
MD5 0401b1cb6ba9cf2f636c699418e6e36e
BLAKE2b-256 19c6ed086e26849f5cdab993e7a51161cf50f215c2784f18ff085ebd4419ec89

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_manipmv-1.4.0-py3-none-musllinux_1_2_x86_64.whl:

Publisher: build.yaml on Mikewando/manipulate-motion-vectors

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vapoursynth_manipmv-1.4.0-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for vapoursynth_manipmv-1.4.0-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 b404574b6191d7a579fe107efb3c302087646afc111bbc948b4e2106a721840e
MD5 c6b86875f70d7894f6e4f3782790df55
BLAKE2b-256 18db9f386fd45f09a2980b85ce7bc07a1003018c800ff0e87a4b3fd45abca00b

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_manipmv-1.4.0-py3-none-musllinux_1_2_aarch64.whl:

Publisher: build.yaml on Mikewando/manipulate-motion-vectors

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vapoursynth_manipmv-1.4.0-py3-none-manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for vapoursynth_manipmv-1.4.0-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 43950a418d1c3680b0c252d60cce5d69efd3b239153c463e9c95c84b0ddb3c05
MD5 825e3a1a989ddb33bdad63226c205df7
BLAKE2b-256 fe17c36683b8a386cd5c95f1f710be105f45d37fbbdaf3acf3179ba91d8df131

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_manipmv-1.4.0-py3-none-manylinux_2_17_x86_64.whl:

Publisher: build.yaml on Mikewando/manipulate-motion-vectors

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vapoursynth_manipmv-1.4.0-py3-none-manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for vapoursynth_manipmv-1.4.0-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 c60ce10e8c8e3f3778782a8bfd378dd59230372152c299f9dfb62c5c6e692091
MD5 b592477fdf899cba0d0ef0e3af83ac9a
BLAKE2b-256 071e8689f80b07d1c1f0b5f2fbea4a414ce17306b429ff56cdd3682c97624ef5

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_manipmv-1.4.0-py3-none-manylinux_2_17_aarch64.whl:

Publisher: build.yaml on Mikewando/manipulate-motion-vectors

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vapoursynth_manipmv-1.4.0-py3-none-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for vapoursynth_manipmv-1.4.0-py3-none-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 579ccd88a5da3b144db6a3bb480e6d671e36a6709d62609e6e9bf2ac3c0fa77e
MD5 c77abbd56ff2633f11c6ef352714c915
BLAKE2b-256 8631cb98c02a7af4ecfaaab292779b303c8fef39e35b491a182ec96ad151a561

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_manipmv-1.4.0-py3-none-macosx_11_0_x86_64.whl:

Publisher: build.yaml on Mikewando/manipulate-motion-vectors

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vapoursynth_manipmv-1.4.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for vapoursynth_manipmv-1.4.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ecf02b2b02c7caae8e92c2acb5a17f8fa70508ccafb88e420c18a315753d8804
MD5 4bbe3850d978089fb54f8c30b0a97a06
BLAKE2b-256 0b385e761da56f3e4b0e7610f3c1eee6b4a82b2dac3545bcef5029495fef39a2

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_manipmv-1.4.0-py3-none-macosx_11_0_arm64.whl:

Publisher: build.yaml on Mikewando/manipulate-motion-vectors

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page