Temporal filtering smooths motion and reduces noise by analyzing frames over time, leveraging patterns across multiple frames to improve visual consistency and reduce artifacts. It is particularly useful for addressing flickering, noise, and motion artifacts in video sources.
This guide will explore temporal filtering in detail, including common use cases, techniques, and example scripts.
Temporal filtering operates across frames to:
Temporal smoothing reduces noise and flickering by averaging pixel values across frames.
TemporalSoften
import vapoursynth as vs
core = vs.core
clip = core.temporal.TemporalSoften(clip, radius=2, luma_threshold=5, chroma_threshold=10)
radius
: Number of frames to include for analysis.luma_threshold
: Intensity threshold for luma plane adjustments.chroma_threshold
: Intensity threshold for chroma plane adjustments.Motion-compensated filtering identifies and adjusts motion across frames, preserving sharpness and detail in moving objects.
MCTemporalDenoise
clip = core.mctemporal.MCTemporalDenoise(clip, sigma=2)
sigma
: Noise reduction strength.clip = core.mctemporal.MCTemporalDenoise(clip, sigma=3, block_size=16, overlap=8)
block_size
: Size of the motion estimation blocks.overlap
: Overlap percentage between blocks to improve accuracy.Temporal degrain targets grain and noise specifically, useful for film sources or older analog content.
SMDegrain
clip = core.smd.SMD(clip, tr=3, thSAD=300)
tr
: Temporal radius (number of frames to analyze).thSAD
: Threshold for noise detection.Flicker removal stabilizes lighting inconsistencies or color shifts between frames.
Deflicker
clip = core.deflicker.Deflicker(clip, mode="light")
mode
: Choose from “light” (general flicker) or “strong” (severe flicker).Combining temporal and spatial filters ensures balanced results, reducing noise and flickering across frames while maintaining intra-frame details.
# Temporal Filtering
clip = core.mctemporal.MCTemporalDenoise(clip, sigma=2)
# Spatial Filtering
clip = core.knlm.KNLMeansCL(clip, d=1, h=1.2)
Use masks to apply temporal filtering only to specific areas, such as noisy backgrounds.
mask = core.std.Prewitt(clip)
filtered = core.mctemporal.MCTemporalDenoise(clip, sigma=2)
clip = core.std.MaskedMerge(clip, filtered, mask)
Higher temporal radius improves smoothing but increases computational load.
Frame interpolation generates new frames for smoother playback or frame rate conversion.
SVP
clip = core.svp.SmoothMotion(clip, preset="fast")
preset
: Choose from “fast”, “medium”, or “quality”.Here’s a complete example for addressing temporal artifacts:
import vapoursynth as vs
core = vs.core
# Load source
clip = core.ffms2.Source("noisy_source.mkv")
# Step 1: Temporal Filtering (Noise and Grain)
clip = core.smd.SMD(clip, tr=3, thSAD=400)
# Step 2: Flicker Removal
clip = core.deflicker.Deflicker(clip, mode="light")
# Step 3: Motion-Compensated Filtering
clip = core.mctemporal.MCTemporalDenoise(clip, sigma=2)
# Step 4: Spatial Filtering (Refinement)
clip = core.knlm.KNLMeansCL(clip, d=1, h=1.2)
# Output
clip.set_output()
Temporal filtering is a powerful tool for improving video quality, particularly for noisy, grainy, or flickering sources. By understanding the techniques and tools outlined in this guide, you can achieve cleaner, more professional results tailored to your content’s needs. Experiment with different approaches and fine-tune parameters to find the perfect balance between noise reduction and detail preservation.