FFmpeg fftfilt Custom Expression for High-Pass Filter
This article explains how to configure the fftfilt (Fast
Fourier Transform) filter in FFmpeg to function as a custom high-pass
image filter. By utilizing custom math expressions within the frequency
domain, you can isolate high-frequency details, such as edges and fine
textures, while attenuating low-frequency background information in
videos or images.
To create a high-pass filter using the fftfilt filter,
you must define an expression for the luma weight parameter
(weight_Y). In the frequency domain representation used by
FFmpeg, the low-frequency (DC) components are located at the corners of
the transform block, while high-frequency components are located toward
the center.
The Ideal High-Pass Filter Expression
An ideal high-pass filter blocks all frequencies below a certain threshold radius and passes all frequencies above it. The following FFmpeg command applies a sharp high-pass filter with a cutoff radius of 15 pixels:
ffmpeg -i input.png -vf "fftfilt=dc_Y=0:weight_Y='gt(sqrt(pow(min(X,W-X),2)+pow(min(Y,H-Y),2)), 15)'" output.pngHow the Expression Works
dc_Y=0: This setting zeroes out the DC coefficient of the Y (luminance) channel. The DC coefficient represents the average brightness of the block. Setting it to 0 removes the overall brightness, leaving only the directional changes (edges).min(X, W-X)andmin(Y, H-Y): Because the 2D Fourier Transform is periodic, the low frequencies are centered at the four corners of the block. These expressions measure the shortest distance from the current coordinate(X, Y)to the nearest corner of the block of widthWand heightH.sqrt(pow(..., 2) + pow(..., 2)): This calculates the Euclidean distance of the current frequency coefficient from the nearest low-frequency origin.gt(..., 15): The “greater than” function acts as a threshold. If the distance (frequency) is greater than 15, the expression returns1(allowing the frequency to pass). If it is less than or equal to 15, it returns0(blocking the frequency).
Gaussian High-Pass Filter for Smoother Results
Sharp threshold filters can introduce unwanted “ringing” artifacts around edges. To prevent this, you can use a Gaussian high-pass filter, which smoothly transitions from blocking low frequencies to passing high frequencies.
The mathematical expression for a Gaussian high-pass filter is:
\[\text{Weight} = 1 - e^{-\frac{d^2}{2\sigma^2}}\]
Where \(d\) is the frequency distance and \(\sigma\) (sigma) is the cutoff frequency. In FFmpeg, this is written as:
ffmpeg -i input.png -vf "fftfilt=dc_Y=0:weight_Y='1-exp(-(pow(min(X,W-X),2)+pow(min(Y,H-Y),2))/(2*pow(10,2)))'" output.pngIn this command, pow(10,2) represents a \(\sigma\) value of 10. Increasing this value
will block more low-frequency data, resulting in a harsher high-pass
effect that only preserves the sharpest edges. Decreasing it will allow
mid-range frequencies to pass, preserving more of the original image
structure.