Dehalo
37c3317fd058; modified for Encode Wiki · CC BY-SA 4.0A halo is a thin bright or dark outline that runs alongside a strong edge, like a glow or a shadow. It usually comes from sharpening: edge enhancement applied in mastering, an oversharp resize kernel such as Lanczos, or an upscale that overshoots at edges. Ringing is the related effect of waves that fade out away from an edge, and heavy lossy compression produces something similar. Both are most visible on thin, high-contrast lines such as anime linework and text.
First check whether you can avoid the damage. If your own resize caused the halos, use a softer kernel such as Spline36 or Catrom (see resizing) and don’t sharpen. A dehalo filter is for halos that are already baked into the source.
FFmpeg has no purpose-built dehalo filter, so this is VapourSynth territory.
Filters in vs-jetpack
Section titled “Filters in vs-jetpack”The old standalone vs-dehalo package is deprecated; its functions now live in vsdehalo in vs-jetpack. The ones you will use:
| Function | Use it for |
|---|---|
dehalo_alpha | The classic general-purpose dehaloer (a port of AviSynth’s DeHalo_alpha). It processes edges and their surroundings aggressively, so it also softens lines unless limited. |
fine_dehalo | dehalo_alpha plus an edge mask and optional contra-sharpening, so it protects real line detail. The usual first choice. |
fine_dehalo2 | Halo removal for second-order halos. |
edge_cleaner, vine_dehalo | Alternatives: edge-aware cleaning, and dehaloing by non-local errors filtering. |
hq_dering, smooth_dering | Ringing close to edges rather than a halo; they smooth only near edges. |
from vsdehalo import dehalo_alpha, fine_dehalo
dehalo = dehalo_alpha(clip, brightstr=0.8)dehalo = fine_dehalo(clip, brightstr=0.85, darkstr=0.3)The parameters that matter for both:
| Parameter | Effect |
|---|---|
brightstr, darkstr | Strength against bright and dark halos. Defaults are 1.0 and 0.0, so only bright halos are treated unless you raise darkstr. |
blur | Gaussian sigma of the blur used as the reference. Larger values reach wider halos but are more destructive. |
lowsens, highsens | Sensitivity range (default 50 and 50): the halo is fully removed below the lower value and left alone above the upper. Raise highsens to reach halos around stronger edges. |
ss | Supersampling factor (default 1.5) to reduce aliasing from the process. |
rx (fine_dehalo) | Radius of the halo to remove; the default is 2. |
Only luma is processed by default (planes=0). Halos in chroma are rarer; add planes if you can see colour fringes.
To see what fine_dehalo changes, look at the mask it built after the call:
dehalo = fine_dehalo(clip)fine_dehalo.masks.MAIN.set_output(1)Tuning and checking
Section titled “Tuning and checking”Compare a clean, high-contrast edge before and after at 1:1, and look at the difference. The goal is for the halo to disappear without the line getting thinner or fading, and without a new halo of the opposite colour on the other side. Check fine detail that looks like an edge (hair, thin lines, small text), where aggressive settings erode detail. Prefer a mask or per-scene application when only some shots are affected. Don’t sharpen afterwards: it brings back what you just removed.
Dehalo before antialiasing and debanding, and after denoising; noise confuses the edge detection.