FlowNet stabilizes shaky handheld video by estimating global camera motion with a deep, distilled optical-flow network, converting that flow into an affine camera path, smoothing it with a quadratic-programming path optimizer, and finally refining the result with a multi-scale photometric alignment pass.
Input (shaky) vs. Output (stabilized) β left: original, right: stabilized.
| Handheld phone clip | Synthetic shake |
|---|---|
![]() |
![]() |
Stabilized frames from a longer sequence:
shaky frames βββΊ Global PWC-Net (distilled) βββΊ affine flow coefficients
β
cumulative camera path (affine)
β
QP path smoothing (crop-aware)
β
multi-scale photometric refinement
β
stabilized video
GLNoWarp4YTBB) estimates dense optical flow between consecutive frames. The flow is compressed with a DCT-based parameterization (Utils/DCTUtility.py) so that global camera motion is captured by a handful of coefficients.Utils/AffineUtility.py) are accumulated into a camera path and smoothed by a QP optimizer (PathStabilizers/StdPathStabilizerQP.py) that guarantees a minimum overlap (--maxAffineCrop) between the original and warped frames.grid_sample in chunks, automatically tracking the valid (non-border) region.Stabilizers/MSPhotometric.py) fits low-order polynomial corrections over a sliding window (DCT low-pass, Gaussian weighting) to remove residual jitter that the affine path cannot model.Stabilizers/ComposedStabilizer.py chains both passes: GNetAffine β MSPhotometric.The pretrained flow model ships with the repo (GlobalFlowNets/trainedModels/GFlowNet.pth), so no training is required to stabilize your own videos.
.cuda() mode)torch install line to your CUDA version)git clone https://github.com/Dan178A/FlowNet_Video_Stabilization.git
cd FlowNet_Video_Stabilization
python -m venv venv
venv\Scripts\activate # Windows (use source venv/bin/activate on Linux)
pip install -r requirements.txt
If your CUDA version differs from 12.4, install PyTorch with the matching wheel from pytorch.org first, then
pip install -r requirements.txt.
python stabilizeVideo.py --inpVideoPath inputs/sample.avi --outVideoPath outputs/stabilized.avi
Options:
| Flag | Default | Description |
|---|---|---|
--inpVideoPath |
inputs/VID_...mp4 |
Path to the shaky input video |
--outVideoPath |
outputs/VID_...mp4 |
Where to write the stabilized video |
--maxAffineCrop |
0.8 |
Minimum frame overlap kept after cropping (lower = more aggressive stabilization, larger crop) |
The output is written at the inputβs frame rate.
FlowNet_Video_Stabilization/
βββ stabilizeVideo.py # CLI entry point
βββ GlobalFlowNets/ # Distilled global motion network
β βββ GlobalPWCNets.py # model factory (getGlobalPWCModel)
β βββ PWCBase.py / PWCNet.py # PWC-Net backbone
β βββ FlowLosses.py # training losses
β βββ trainedModels/ # GFlowNet.pth + config.json
βββ Stabilizers/ # Stabilization passes
β βββ ComposedStabilizer.py # GNetAffine + MSPhotometric pipeline
β βββ JoinedAdaptiveGNetStabilizer.py # flow β affine path β warp
β βββ MSPhotometric.py # multi-scale photometric refinement
βββ PathStabilizers/
β βββ StdPathStabilizerQP.py # QP-based camera-path smoothing
βββ Utils/ # DCT, affine, cropping, video I/O helpers
βββ inputs/ outputs/ # demo videos
βββ docs/ # project page (GitHub Pages) + media
Released under the Apache License 2.0.