Shooting-range clip, 200 frames of 240 fps slow-motion under 50 Hz lighting. The shot fires at frame 157. Step through it frame by frame to compare the methods.
A meter that measures flicker the way lighting engineers do, as IEEE 1789 Percent Flicker for every pixel, and a remover that uses those measurements to rebuild each frame from its neighbours.
Slow-motion cameras sample mains-powered lamps faster than the lamps stay steady, so frames alternate between bright and dark. Generic deflickering treats this as noise. We treat it as physics: multiplicative, periodic, aliased by the frame rate, different for every light, and separate from real events like a muzzle flash.
FlickerScope models every pixel as steady scene light multiplied by a flicker gain, Y = S · G, and fits G along optical-flow trajectories so moving people and camera motion are not mistaken for flicker. Flicker Fusion takes that gain field and rebuilds each frame from its neighbours.
The lane behind the shooter swings by up to 88%, so its darkest frames get about 14 times less light than its brightest. The shooter, lit by a different source, barely flickers at all. The meter also flags the muzzle flash as an event and leaves it out of the measurement.
Percent Flicker per pixel, (max − min) / (max + min) of the light reaching it, computed in linear light along motion. Detected frequency: 0.417 cycles per frame, which is 100 Hz at 240 fps.
All methods are scored by the same meter. Calm flicker leaves out the frames around the shot and its smoke, so no method gains from smoothing away a real event. Warp error is the field-standard temporal-consistency measure and does not use our model at all. Structure shows how much of the original image survives.
| Shooting range (200 frames) | Flicker % | Calm flicker % | Warp error | Structure | Grain | Time |
|---|---|---|---|---|---|---|
| Original | 29.73 | 29.19 | 58.69 | 1.000 | 0.90 | – |
| ffmpeg deflicker | 33.89 | 33.27 | 63.01 | 0.999 | 0.94 | 11 s |
| Our previous method | 8.83 | 8.20 | 18.36 | 0.989 | 0.95 | 45 s |
| All-In-One Deflicker (CVPR'23) | 2.28 | 1.59 | 7.53 | 0.754 | 0.75 | 65 min |
| CVPR'23 filter with our guide | 2.48 | 1.66 | 8.82 | 0.734 | 0.87 | ~5 min |
| Flicker Fusion | 1.98 | 1.24 | 5.21 | 0.986 | 0.68 | 3 min |
Lower is better for flicker, warp error and grain; higher is better for structure. Grain compares noise in the flickering zone with that zone in the original's brightest frames. ffmpeg makes this clip worse: one global gain cannot fix flicker that only one region has.
The same method with the same settings, on footage it was never tuned on: real-world slow-motion clips from the public Blind Video Deflickering dataset. Pick a clip, then drag the divider. Clips marked "partial" improve but still show some flicker; the caption says what is left.
Clips: Blind Video Deflickering dataset (Lei, Ren, Zhang and Chen, “Blind Video Deflickering by Neural Filtering with a Flawed Atlas”, CVPR 2023), CC BY 4.0. Shown as original | Flicker Fusion output, downscaled.
Flicker % is FlickerScope's reading before → after. Where the CVPR 2023 method also ran, its result is listed for comparison. Clips with almost no flicker to begin with are left out.
Same run, same settings. These clips are not lamp flicker that repeats over a few frames, so there is little for the method to fuse. None gets meaningfully worse: the flicker reading stays within 0.1 points or drops, and warp error drops on all five. As a safeguard, any result that would shift the whole clip's exposure is discarded and the original returned.
| Clip | Flicker % | Why |
|---|---|---|
| Smoker Low-key portrait, drifting smoke | 63.0 → 59.4 | Drifting smoke changes brightness with no lamp cycle, and flow cannot track it, so there is nothing reliable to fuse from. |
| Sunset Time-lapse exposure flicker | 25.9 → 24.5 | Time-lapse: exposure jumps between shots taken seconds apart. There is no lamp cycle, and too much changes between frames to borrow light. |
| City Time-lapse exposure flicker | 25.1 → 25.2 | Time-lapse: exposure jumps between shots taken seconds apart. There is no lamp cycle, and too much changes between frames to borrow light. |
| Snow day Time-lapse exposure flicker | 28.9 → 25.6 | Time-lapse: exposure jumps between shots taken seconds apart. There is no lamp cycle, and too much changes between frames to borrow light. |
| Snow night Time-lapse exposure flicker | 40.3 → 39.6 | Time-lapse: exposure jumps between shots taken seconds apart. There is no lamp cycle, and too much changes between frames to borrow light. |
Real footage has no "correct answer", so we built clips that do. A physics simulator relights clean video with modelled lamps (filament, fluorescent ballast, LED drivers, LED dimmers from 100 Hz to 2 kHz) on 50 or 60 Hz mains, as seen by a 120 to 480 fps camera with global or rolling shutter, highlight clipping and sensor noise. Because we know the true flicker, we can check both the meter and the remover.
| Meter check | True % | Measured % |
|---|---|---|
| LED + PWM dimmer, 120 fps | 1.2 | 1.4 |
| 2 kHz PWM, 480 fps | 3.8 | 3.7 |
| 3 sources incl. PWM | 11.2 | 11.5 |
| Fluorescent, rolling shutter | 12.5 | 14.6 |
| 2 tubes, 480 fps | 12.8 | 16.5 |
| 3 sources, 240 fps | 19.0 | 20.1 |
| 3 lamps out of phase | 23.3 | 30.6 |
| Raw LED driver | 38.8 | 41.5 |
Correlation with the truth r = 0.988, mean error 2.2 points, frequency correct on all 8. The meter reads a little high, most with several out-of-phase lamps.
| PSNR vs truth (dB) | Original | Best other | Fusion |
|---|---|---|---|
| LED + PWM dimmer | 34.9 | 34.9 | 41.4 |
| 2 kHz PWM | 33.0 | 33.0 | 35.8 |
| 3 sources incl. PWM | 30.1 | 30.6 | 35.7 |
| Fluorescent, rolling | 30.5 | 32.0 | 41.4 |
| 2 tubes, 480 fps | 28.0 | 29.5 | 37.1 |
| 3 sources, 240 fps | 28.2 | 32.5 | 38.3 |
| 3 lamps out of phase | 27.3 | 29.2 | 31.6 |
| Raw LED driver | 23.5 | 29.3 | 35.5 |
Higher is better. Best other: the best of the untouched original, ffmpeg deflicker, our previous method and the FlickerScope-gain-only ablation. Flicker Fusion wins every clip by 2.4 to 9.5 dB, partly because rebuilding dark frames from bright ones also removes noise.
The code is on GitHub. With a CUDA GPU and the RAFT weights (see the README), one command writes the deflickered video (original audio kept), a side-by-side compare video and a flicker report:
git clone https://github.com/devgmstudios/deflicker-fusion cd deflicker-fusion pip install -r requirements.txt python bench/deflicker_file.py my_slowmo_clip.mov
The repository also holds the benchmark (prep.py, run.py, gate.py), the testing-grounds viewer that plays every clip and method side by side, and a small local web app. On iPhone, Deflicker: Slow Mo Flicker Fix runs this method in its Fusion engine.