How to Use FFmpeg fftfilt to Remove Film Grid Noise

Scanning physical film often introduces unwanted high-frequency grid noise, scan lines, or Moiré patterns into the digital transfer. This article provides a direct, step-by-step guide on how to construct an FFmpeg command using the Fast Fourier Transform filter (fftfilt) to isolate and eliminate these specific high-frequency periodic patterns, restoring the visual clarity of your digitized film.

The FFmpeg Command

To eliminate high-frequency grid noise, you need to apply a low-pass filter in the frequency domain. This allows low-frequency visual data (the actual film content) to pass through while blocking the high-frequency repetitive grid patterns.

Run the following command in your terminal:

ffmpeg -i input.mp4 -vf "fftfilt=weight_Y='if(lte(sqrt(pow(min(X,W-X),2)+pow(min(Y,H-Y),2)),30),1,0)'" -c:a copy output.mp4

How the Command Works

The fftfilt filter processes the video in the frequency domain rather than the spatial domain. Here is a breakdown of how the mathematical expression target the grid noise:

  • fftfilt: This activates the Fast Fourier Transform filter.
  • weight_Y: This applies the frequency modification to the Y (luminance) channel, where most structural grid noise resides.
  • min(X,W-X) and min(Y,H-Y): In a 2D FFT, the low frequencies (the main image structure) are located at the corners of the frequency domain map, while high frequencies (fine details and sharp noise) are located toward the center. This mathematical expression measures the distance from the nearest low-frequency corner.
  • sqrt(pow(...,2)+pow(...,2)): This calculates the Euclidean distance of each frequency coordinate from the nearest corner.
  • lte(...,30): This acts as a hard cutoff threshold. Any frequency within a radius of 30 pixels from the corners (low frequencies) is kept, while any frequency further away (high frequencies, including the grid noise) is discarded.
  • if(...,1,0): If the frequency is within the threshold, it is multiplied by 1 (kept). If it is outside, it is multiplied by 0 (completely eliminated).

Fine-Tuning the Filter

Because every film scan is different, you may need to adjust the threshold value (set to 30 in the example above) to achieve the best balance between noise reduction and image sharpness:

  • If the grid noise is still visible: Lower the threshold value (e.g., to 20 or 15). This cuts out more high frequencies, which will aggressively remove the noise but may slightly soften the image.
  • If the video looks too blurry: Increase the threshold value (e.g., to 45 or 60). This preserves more high-frequency details, though some grid noise might creep back in.

Applying to Color Channels (Optional)

If the grid noise also appears as color banding or chromatic aberrations, you can apply the same filter to the chroma channels (U and V) by adding weight_U and weight_V parameters to the filter chain:

ffmpeg -i input.mp4 -vf "fftfilt=weight_Y='if(lte(sqrt(pow(min(X,W-X),2)+pow(min(Y,H-Y),2)),30),1,0)':weight_U='if(lte(sqrt(pow(min(X,W-X),2)+pow(min(Y,H-Y),2)),30),1,0)':weight_V='if(lte(sqrt(pow(min(X,W-X),2)+pow(min(Y,H-Y),2)),30),1,0)'" -c:a copy output.mp4