Noise and grain

Video Noise Reduction: hqdn3d vs nlmeans, Measured

By the FixPixelatedVideos team · Invalid Date · 11 min read

Noisy video frame beside a denoised version with a bar chart of file sizes before and after

Noise is the quiet enemy of video quality. It does not look like a blocky mess at first. It looks like a faint shimmer, a dirty texture in the shadows, a fizz on a flat wall. But it does something worse behind the scenes: the encoder treats it as detail and spends your bitrate on it. The picture that you care about gets less.

So removing noise is not only a cosmetic fix. It makes the file smaller and the compression cleaner. The question is how to do it without turning faces into wax. I ran a small experiment to find out how much the common filters help, how they differ, and what they cost in time.

Two kinds of noise reduction

Spatial denoising looks at a pixel and its neighbors in the same frame. If a pixel is very different from the pixels around it, it is probably noise, so the filter pulls it toward the average. It works on a single frame, so it does not need motion, and it never creates ghosts. The weakness is that it cannot tell fine texture from noise, so heavy settings smear detail.

Temporal denoising compares the same position across several frames. Real detail in a static scene stays the same from frame to frame, while noise changes randomly. Averaging over time keeps the first and removes the second. It is very effective on static shots. The weakness is movement: if something moves, the filter can blend it with its own earlier position, leaving a faint trail.

The most popular filters combine both. In FFmpeg, hqdn3d is a high quality 3D denoiser that applies a spatial and a temporal component and is cheap to run. nlmeans is non-local means, which compares patches rather than single pixels and searches a wide area for similar-looking patches to average. It is slower but smarter about preserving structure.

The experiment

I used a clean 5 second, 1080p clip from an open-source animated film as the reference. Then I added synthetic noise to it with FFmpeg’s noise filter at strength 18, with temporal and uniform components, to produce a noisy version. The advantage of this method is that I know the truth: I can compare each denoised result against the clean reference and measure how close it comes.

The disadvantage is that artificial noise is not the same as real sensor noise. Real noise varies by brightness and color and is partly correlated. So the numbers show how filters compare with each other, and not how well they would do on your camera.

I tried three filters:

  • hqdn3d=4:3:6:4.5, a light setting.
  • hqdn3d=8:6:10:8, a strong setting.
  • nlmeans=s=3:p=5:r=11, a moderate setting with a research window of 11.

For each, I measured PSNR and SSIM against the clean reference, then encoded the result at CRF 23 for delivery and recorded the file size. I also timed each filter.

Results

Version PSNR vs clean SSIM vs clean Size at CRF 23
Noisy, no filter 34.1 dB not measured 9.4 MB
hqdn3d light (4:3:6:4.5) 35.8 dB 0.879 7.4 MB
hqdn3d strong (8:6:10:8) 38.7 dB 0.945 5.4 MB
nlmeans (s=3, p=5, r=11) 38.8 dB 0.956 5.2 MB

And time, running each filter followed by a fast encode on a 5 second clip:

Filter Time
hqdn3d light about 5 s
hqdn3d strong about 4 s
nlmeans about 146 s

The first thing I notice is how much the filtering helps. A 4.5 dB improvement from the strong hqdn3d is large. The picture is much closer to the clean original.

The second thing is that the nlmeans filter gets only a hair better than the strong hqdn3d, 38.8 dB against 38.7, with SSIM of 0.956 against 0.945. The SSIM gap is more interesting. SSIM measures structure, and nlmeans keeps edges and textures better. But it costs about thirty times as much to run: about two and a half minutes for five seconds of video. For a ten minute video that would be five hours.

The third thing is file size. The noisy clip at CRF 23 was 9.4 MB. The light denoise cut that by 21 percent and the strong one by 43 percent. That happens because the encoder is no longer spending bits on random grain. If you are producing a video for streaming or sharing, a cleaner source is the cheapest way to get a smaller file at the same visible quality.

What the numbers do not tell you

PSNR rewards smoothness. A filter that blurs everything can score well against a clean reference because the reference has less texture than the noisy version. This is why I would not choose the strongest setting just because it scored best.

On real footage there is a cost to strong denoising: faces lose texture, hair looks painted, brick walls become flat. My test clip is animated, which is forgiving. With a person on screen, stop earlier. I look at a close crop of skin at 100 percent and check that pores and fine lines are still faintly there. If they are gone, I lower the setting.

Another thing the test does not show is ghosting. A strong temporal filter will smear a moving object, and my clip has mostly camera motion, which the filter handles reasonably well. For footage with a static camera and moving subjects, such as a security camera, lower the temporal strength (the third number in hqdn3d) or use a motion-compensated filter.

What the hqdn3d numbers mean

The filter takes four values: luma_spatial:chroma_spatial:luma_tmp:chroma_tmp. Defaults are 4, 3, 6 and 4.5. The first two control how strongly each frame is smoothed. The last two control how strongly the filter averages over time. Higher means more noise reduction and more risk of smearing.

My practical settings:

  • Light cleanup of slightly grainy footage: hqdn3d=2:1.5:3:2.25
  • Typical phone video in low light: hqdn3d=4:3:6:4.5 (the default)
  • Very noisy footage, mostly static: hqdn3d=8:6:10:8
  • Noisy footage with fast motion: keep spatial high and temporal low, such as hqdn3d=6:4:3:2

Chroma noise, the colored speckles in dark areas, is much less important to the eye than luma noise, so you can push the chroma values higher with little visible cost.

When nlmeans is worth the wait

At 30 times slower, nlmeans is for special cases. I would use it when:

  • The clip is short, under a minute.
  • The footage is high value, such as a single important shot.
  • Hqdn3d leaves a texture of residual noise that you cannot get rid of without smearing.
  • The scene has large smooth areas such as sky or walls where noise is most visible.

For a long video, use hqdn3d, or consider a faster alternative such as atadenoise or vaguedenoiser, depending on your build. Sometimes a good compromise is to run nlmeans on only the segments that need it.

The order of operations

Denoise before anything else that depends on image detail. A sensible order is:

  1. Repair or deinterlace if needed.
  2. Denoise at the original resolution.
  3. Adjust exposure and color, if the footage is dark. Brightening raises noise, so denoise before or lightly after a lift.
  4. Scale up, if you are scaling.
  5. Sharpen lightly.
  6. Encode.

If you brighten first and denoise later, the filter has to work harder because the noise is amplified. If you denoise first and then brighten a lot, you may bring out noise that the filter left behind. For a very dark clip, I do a small lift, then denoise, then a final small adjustment.

Sharpening should always come after the denoise. Sharpening noise makes it worse.

Denoising in editors

Not everyone wants a command line. The common editors include denoisers:

DaVinci Resolve has temporal and spatial noise reduction on the Color page, with the temporal option available in the paid Studio version. Start with a temporal setting of two frames and a modest threshold, and add spatial NR only if needed.

Premiere Pro has no great built-in denoiser, though the Median effect and the Remove Noise options in some plugins can help. Many editors use third-party plugins for this job.

CapCut offers a “Denoise” effect that you can apply to a clip, with a strength slider. It is easy to overdo.

HandBrake includes hqdn3d and nlmeans among its denoise filters. The presets “Ultralight”, “Light”, “Medium”, “Strong” and so on map to specific settings. It is a handy way to try them without a command line.

If you want a reference for a command line chain, my FFmpeg guide puts a denoise in front of the scale and sharpen steps.

Where noise comes from, and what you can do before you shoot

Understanding the source helps you decide how hard to fight it.

Sensor noise in low light. A camera sensor is a grid of tiny light detectors. When there is little light, each one receives only a handful of photons, and the random variation in that small number shows up as grain. The camera then amplifies the weak signal (that is what a high ISO is), and the amplification raises the noise with it. Phones have small sensors, so they hit this limit sooner. The cure is more light, a wider aperture, a longer shutter, or a bigger sensor. The shutter is the free one: at 30 fps you can use 1/60 of a second rather than 1/120, which doubles the light, at the cost of a bit more motion blur.

The phone’s own processing. Phones apply aggressive noise reduction and sharpening before the video is even saved. That is why phone video at night often looks smeared and crawly: the camera has already done a rough denoise, and then the encoder compresses what is left. If you run another heavy denoise on top of that, you are working on already smoothed footage, and a light touch is enough.

Compression noise. Not true noise, but it behaves similarly. Mosquito noise around edges and shimmering in textured areas come from the codec. A spatial denoise helps a little, and a deblock filter helps more.

Film grain and overlays. If someone added grain on purpose, it is part of the look. Removing it changes the style. If you want grain in the final video, apply it after you scale and just before the encode, and give it a bit of extra bitrate. Otherwise the encoder will eat it.

Old tape and analog sources. VHS and other analog formats have a mix of noise types, including horizontal tearing and color bleeding. These need specific filters beyond the ones in this article.

Once you know which kind you have, the plan follows. For sensor noise, a temporal denoise and a mild spatial one. For compression noise, a deblock. For analog sources, a specialized chain. For intentional grain, leave it.

How to check a denoise without fooling yourself

Denoising is easy to misjudge, because the eye adapts. After a few minutes of staring at a smooth, clean picture, the original looks worse than it did. A few habits keep me honest.

Compare on the same frame, split screen if the editor allows it. In FFmpeg you can build a side by side with hstack to see the original and the result in one picture.

Look at the darkest and the most detailed areas, not the middle. That is where the filter does the most harm and the most good.

Pause on a face and zoom to 100 percent. If it looks like a mannequin, back off.

Watch a moving shot, not only still frames. Ghosting is invisible in a still.

Look away for a minute and come back. Your first reaction after a break is more reliable than your tenth minute of tweaking.

And measure when you can. The same SSIM and PSNR commands I used here work on your own clips, if you have a clean reference. For real footage you rarely do, so the file size and your eyes are the judges.

A starter chain you can copy

Here is a chain that I would use as a first attempt on a grainy phone clip, from dim indoor shooting:

ffmpeg -i grainy.mp4 \
  -vf "hqdn3d=4:3:6:4.5,unsharp=5:5:0.4:5:5:0.0" \
  -c:v libx264 -crf 20 -preset slow -c:a copy cleaned.mp4

For a very noisy night clip with a static camera:

ffmpeg -i night.mp4 \
  -vf "hqdn3d=7:5:9:7,eq=gamma=1.2" \
  -c:v libx264 -crf 20 -preset slow -c:a copy night_clean.mp4

And for a short, important clip where you can wait, a slower and smarter version:

ffmpeg -i important.mp4 \
  -vf "nlmeans=s=3:p=5:r=11" \
  -c:v libx264 -crf 18 -preset slow -c:a copy important_clean.mp4

Run the last one on a short segment first, since it is slow. The -t 10 option limits the output to ten seconds, which is a good test length.

Common mistakes

Over-denoising. The most common mistake. Faces look like plastic.

Denoising already compressed footage heavily. If the source has compression blocks, a strong temporal denoise can smear them into a blotchy texture. Use a deblock and a light denoise instead.

Forgetting chroma. Colored noise is easy to remove. Leaving it in makes footage look dirty in the shadows.

Applying the filter to the whole video when only some shots need it. Apply it to the shots that need it. The bright, well-lit scenes do not.

Expecting it to fix blocks. Noise reduction removes random noise. It does not repair compression artifacts, although deblocking filters can soften them.

How this site uses it

The pipeline on this site measures how heavily compressed a video is, using the bitrate per pixel. For a heavily compressed or severely blocky clip, it applies a stronger deblock and hqdn3d denoise. For a clean clip it applies little. That is a judgment call made by numbers, so it is not always perfect, which is why there is a free preview. You can upload a short clip and compare the before and after yourself.

A quick way to choose a starting point

If you are unsure where to begin, start with the light hqdn3d setting from my table, look at the result at full size, and only then go stronger. It takes a few seconds to run on a short clip, so you can try three strengths and keep the one where the grain is calmer but faces still have texture. Save the nlmeans run for the clips that deserve the wait.

Summary

Noise costs you in two ways: it looks bad, and it wastes bits. In my test, a strong hqdn3d improved a noisy clip by 4.5 dB and cut the encoded size by 43 percent, while nlmeans matched that quality on the numbers, preserved structure slightly better by SSIM, and took about thirty times longer. For most videos, a moderate hqdn3d at the start of the chain is the best trade. Keep the settings gentle on faces, denoise before you sharpen or scale, and check a frame at 100 percent before you commit.

If you want one habit to take away, make it this: run the denoise on a short, hard section first, look at faces at 100 percent, and only then process the whole video. It takes two minutes and it prevents most of the regrets.

Got a pixelated video right now?

Upload it and see a free before and after preview in about a minute.

Fix my video

Frequently asked questions

What is the best way to remove noise from video?

For most footage, a temporal-spatial filter like hqdn3d is the best balance of speed and results. For stubborn noise and short clips, nlmeans can be a little better but runs about thirty times slower.

Does denoising reduce file size?

Yes. In my test, a noisy 1080p clip encoded at CRF 23 was 9.4 MB. After a light denoise it was 7.4 MB, and after a stronger one 5.4 MB.

Why does denoised video look waxy?

Strong denoising removes fine texture along with the noise. Faces lose pores and hair loses strands. Use the lightest setting that cleans the picture and check a frame at 100 percent.

What is the difference between spatial and temporal denoising?

Spatial filters look at neighboring pixels in the same frame. Temporal filters compare the same pixel across several frames. Temporal filtering removes more noise from static scenes but can ghost moving objects.

Should I denoise before or after upscaling?

Before. At the original size there are fewer pixels to process, and noise is easier to separate from detail.

Keep reading

Step-by-step guides · All articles · Pixelated video fixer