Vier-Wege-Entrauschen — verrauscht / Median / Bilateral / NLM
Fügt der Eingabe synthetisches Rauschen hinzu, lässt dann drei verschiedene Entrauscher auf identischen verrauschten Kopien laufen und stapelt sie in einem 2×2-Raster zum direkten Vergleich. - **medianBlur** ist am schnellsten, ideal für Impuls- Rauschen (Staubpunkte, defekte Pixel). Verschmiert feine Texturen bei höheren Radien. - **bilateralBlur** erhält Kanten beim Glätten — guter Allzweck-Entrauscher; Standardwerte liefern ein sanftes Ergebnis. - **nonLocalMeans** ist der Gold-Standard für natürliches Foto-Rauschen: mittelt Pixel im ganzen Bild gewichtet nach Patch-Ähnlichkeit, erhält feine Texturen, die die anderen verschmieren würden. Langsamer als die anderen, aber das sauberste Ergebnis. Alle drei sind reine Pixel-Operationen — keine Erweiterungen nötig. Mit den Reglern siehst du, wie sich die drei Methoden bei gleichem Rauschpegel unterscheiden.
// Four-way denoise comparison: noisy / median / bilateral / NLM
// demo_denoise.js
//!INPUT: INPUT
//!OUTPUT: OUTPUT
//!PARAM: NOISE_AMOUNT:number=0.10,min=0.0,max=0.5
//!PARAM: MEDIAN_RADIUS:number=2,min=1,max=5
//!PARAM: BILATERAL_D:number=7,min=3,max=15
//!PARAM: BILATERAL_SC:number=0.10,min=0.01,max=0.5
//!PARAM: BILATERAL_SS:number=8,min=1,max=30
//!PARAM: NLM_SEARCH:number=7,min=3,max=15
//!PARAM: NLM_PATCH:number=3,min=1,max=5
//!PARAM: NLM_H:number=0.08,min=0.01,max=0.3
//!PARAM: LABEL_SIZE:number=22,min=10,max=64
// Take the input, add `NOISE_AMOUNT` of synthetic film grain so
// there is something to denoise, then run three different
// denoisers on identical noisy copies and stack them in a 2×2
// grid for direct visual comparison:
//
// ┌────────────────┬────────────────┐
// │ noisy (input) │ median │
// │ (control) │ (per-channel │
// │ │ median) │
// ├────────────────┼────────────────┤
// │ bilateral │ Non-Local │
// │ (edge-pres. │ Means │
// │ smoothing) │ (gold std.) │
// └────────────────┴────────────────┘
//
// Median is fastest, ideal for impulse noise (dust spots, dead
// pixels). Bilateral preserves edges while smoothing — good for
// general use, defaults give a soft denoise. NLM is the
// gold-standard for natural-photo Gaussian noise: it averages
// pixels across the whole image weighted by patch similarity,
// preserving fine texture that the other two would smear.
const src = Engine.loadImage(INPUT);
const W = src.width;
const H = src.height;
// Add synthetic noise to the source so all four panels start
// from the same noisy reference.
const noisy = src.clone().filmGrain(NOISE_AMOUNT);
src.free();
const bandH = LABEL_SIZE + 8;
const cellW = W;
const cellH = bandH + H;
const out = Engine.createImage(1, 1);
out.setPixel(px(0, 0), new Pixel(0.05, 0.05, 0.07, 1.0));
out.resize(cellW * 2, cellH * 2);
function panel(label, image, col, row) {
const x0 = col * cellW;
const y0 = row * cellH;
out.drawText(label, x0 + 16, y0 + LABEL_SIZE - 2, {
size: LABEL_SIZE, color: NamedColor.white,
});
out.blendAt(image, px(x0, y0 + bandH), 1.0, BlendMode.Over);
}
// Panel 0,0 — noisy reference
panel('1) noisy input', noisy.clone(), 0, 0);
// Panel 1,0 — median
{
const t = noisy.clone();
t.medianBlur(MEDIAN_RADIUS);
panel(`2) medianBlur(${MEDIAN_RADIUS})`, t, 1, 0);
t.free();
}
// Panel 0,1 — bilateral
{
const t = noisy.clone();
t.bilateralBlur(BILATERAL_D, BILATERAL_SC, BILATERAL_SS);
panel(`3) bilateralBlur(${BILATERAL_D}, ${BILATERAL_SC}, ${BILATERAL_SS})`, t, 0, 1);
t.free();
}
// Panel 1,1 — NLM
{
const t = noisy.clone();
t.nonLocalMeans(NLM_SEARCH, NLM_PATCH, NLM_H);
panel(`4) nonLocalMeans(${NLM_SEARCH}, ${NLM_PATCH}, h=${NLM_H})`, t, 1, 1);
t.free();
}
noisy.free();
out.save(OUTPUT);
out.free();
// © 2026 Michael Lechner · mlc OpticScript · https://mlcgo.eu · Elastic License 2.0