Skip to content

Add decoder motion vector export and experimental VideoRegistration module - #463

Merged
IanButterworth merged 4 commits into
masterfrom
motion-vector-registration
Aug 7, 2026
Merged

Add decoder motion vector export and experimental VideoRegistration module#463
IanButterworth merged 4 commits into
masterfrom
motion-vector-registration

Conversation

@IanButterworth

@IanButterworth IanButterworth commented Aug 6, 2026

Copy link
Copy Markdown
Member

Adds a way to extract any already available motion information from the video file during read.

Also adds an experimental VideoRegistration module, which may be moved to a separate package.

Demoing it with util/motion_vector_demo.jl
The one on the right is an opinionated rough registration based on the info. There are many ways to use the data

mv_demo_synthetic.mp4
mv_demo_annie_oakley.mp4

IanButterworth and others added 2 commits August 6, 2026 11:21
Motion vector extraction (src/avio.jl):
- `openvideo(file; export_mvs=true)` sets AV_CODEC_FLAG2_EXPORT_MVS so the
  decoder exports block motion vectors as frame side data (software decoding
  only; errors if combined with `hwaccel`)
- `motion_vectors(reader)` returns the `MotionVector`s of the most recently
  read frame, mirroring `frame_metadata`; side data is captured at decode
  time into a FIFO kept in lockstep with the frame queue across
  read/skip/seek
- sub-pixel helpers `displacement`, `src_position`, `dst_position`, and
  `correspondences(mvs)` converting vectors to filtered (dst, src)
  point-pair matrices

VideoIO.VideoRegistration (src/registration.jl):
- self-contained, purely point-based robust 2D registration module
  (stdlib deps only) designed to be movable to a standalone package
  unchanged; all codec-specific knowledge stays in VideoIO, with the
  motion-vector convenience method as glue in src/registration_glue.jl
- closed-form translation / similarity (Umeyama) / affine fits wrapped in
  RANSAC with adaptive early termination and inlier refinement
- `estimate_global_motion` -> `GlobalMotion` with quality metrics (inlier
  fraction, median residual, spatial coverage), `local_residuals` for
  residual local motion, and `classify_confidence` implementing a
  use-directly / initialize-refinement / full-registration-fallback
  decision rule

Also: util/motion_vector_demo.jl renders a side-by-side annotated video
(inlier/outlier dots, global-translation arrow); docs pages, tests
(round-trip against synthetic H.264 with known ground-truth motion), and
CHANGELOG entry; version bumped to 1.9.0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Aug 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.74468% with 8 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (master@072509e). Learn more about missing BASE report.

Files with missing lines Patch % Lines
src/registration.jl 95.48% 6 Missing ⚠️
src/avio.jl 96.15% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##             master     #463   +/-   ##
=========================================
  Coverage          ?   81.63%           
=========================================
  Files             ?       12           
  Lines             ?     1721           
  Branches          ?        0           
=========================================
  Hits              ?     1405           
  Misses            ?      316           
  Partials          ?        0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…ion experimental

Demo (util/motion_vector_demo.jl):
- third pane showing the frame corrected for global movement, warped by the
  chained per-frame estimates with bilinear sampling
- --smooth=N: correct only the deviation from an exponentially smoothed
  trajectory instead of a fixed anchor (follows slow/intentional motion,
  immune to long-sequence drift)
- --refine: hybrid image-domain SAD refinement seeded by the codec estimate,
  with parabolic sub-pixel interpolation. Recovers global motion that
  encoders code as residuals instead of motion vectors on low-contrast or
  grainy content (where near-all blocks are zero-motion skips and form a
  false consensus), and bridges I-frames, which carry no vectors
- --coast / --model=<m> chain-policy flags
- grain-robust temporal-stability metric (downsampled central crop) and
  chain-drift indicator printed per run

On the Annie Oakley test video the hybrid refine+smooth settings reach the
measured geometric ceiling (pairwise-optimal alignment); the residual frame
difference is dominated by luminance flicker and film grain, which
geometric registration cannot remove.

VideoRegistration:
- add compose_transform for chaining per-frame estimates into a cumulative
  anchor-relative transform (exported, documented, tested)
- mark the module experimental in the module docstring, docs page, and
  CHANGELOG: API may change between minor releases and the module may move
  to a separate package (it is self-contained to permit that); the
  extraction API in VideoIO proper is unaffected

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@IanButterworth
IanButterworth force-pushed the motion-vector-registration branch from b5e1f25 to 7509b1c Compare August 7, 2026 01:42
@IanButterworth
IanButterworth merged commit f69e70d into master Aug 7, 2026
18 checks passed
@IanButterworth
IanButterworth deleted the motion-vector-registration branch August 7, 2026 02:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant