KI-Entrauschung — Sensorrauschen entfernen via DRUNet

Entfernt Sensorrauschen aus Fotos ohne den typischen "weich-bügeligen" KI-Look — feine Texturen (Haare, Stoff, Laub) bleiben erhalten. Basis ist DRUNet, ein Plug-and-play-U-Net; ein Modell für den ganzen σ=0..50 Bereich, sodass STRENGTH von leichtem Korn (10) bis zu starkem ISO-12800-Rauschen (40) regelt. Läuft komplett auf dem Gerät — keine Cloud, kein Upload.

INPUT
INPUT — KI-Entrauschung — Sensorrauschen entfernen via DRUNet
OUTPUT
OUTPUT — KI-Entrauschung — Sensorrauschen entfernen via DRUNet
JavaScript
// Tool plugin demo — AI denoising via DRUNet (DPIR / Zhang et al. 2021)
// tool_denoise.js
//!INPUT: INPUT
//!OUTPUT: OUTPUT
//!PARAM: NOISE_SIGMA:number=0.08,min=0,max=0.3,step=0.005
//!PARAM: STRENGTH:number=20,min=0,max=50,step=1
//!PARAM: DETAIL:integer=620,min=0,max=4096
//!PARAM: SEED:integer=1,min=0,max=1000000
// SEED: gleiche Zahl → gleiches Rauschen (reproduzierbar); 0 → jedes Mal neu.

// Demonstrates a real-world denoising pipeline:
//   1. Synthesize sensor-style noise on the clean input (so the
//      demo is reproducible without needing a separately-noisy
//      reference image).
//   2. Run DRUNet at a configurable STRENGTH (σ in 8-bit pixel
//      scale — same convention DPIR uses).
//   3. Compose a 3-panel comparison: ORIGINAL | NOISY | DENOISED.
//
// DRUNet ships ~65 MB fp16 ncnn weights and runs entirely on-device
// — no cloud, no upload. ~5 s/megapixel on a typical CPU.

// Ausschnitt statt Verkleinerung: Rauschen ist ein Pixel-Phaenomen.
// Wuerde man die fertige Dreier-Tafel herunterskalieren, mittelte
// man das Korn weg, dessen Beseitigung hier vorgefuehrt wird — und
// alle drei Felder saehen gleich sauber aus. DETAIL = 0 nimmt das
// ganze Bild.
const loaded = Engine.loadImage(INPUT);
let orig = loaded;
if (DETAIL > 0 && loaded.width > DETAIL) {
  const cw = Math.min(DETAIL, loaded.width);
  const ch = Math.min(Math.round(DETAIL * loaded.height / loaded.width), loaded.height);
  orig = loaded.clone().crop(
    Math.round((loaded.width - cw) / 2),
    Math.round((loaded.height - ch) / 2),
    cw, ch);
  loaded.free();
}
const W = orig.width, H = orig.height;

// Realistic sensor-noise stack: luminance grain + weaker chroma pass.
const noisy = orig.clone()
    .addNoise({ type: "gaussian", sigma: NOISE_SIGMA, color: false, seed: SEED || undefined })
    .addNoise({ type: "poisson",  sigma: NOISE_SIGMA * 0.6, color: true, seed: SEED ? SEED + 1 : undefined });

// AI denoise — the actual tool plugin call.
const clean = Engine.tool('denoise').apply(noisy, {
    strength: STRENGTH,
});

// 1×3 strip: original | noisy | denoised.
const panels = [
    ["ORIGINAL", orig],
    ["NOISY",    noisy],
    ["DENOISED", clean],
];
const sheet = Engine.createImage(W * panels.length, H);
const ink = new Pixel(1, 1, 1, 0.9);
panels.forEach(([label, img], i) => {
    sheet.blendAt(img, px(i * W, 0), 1.0);
    sheet.drawText(label, i * W + 16, 38,
        { font: "JetBrains Mono", size: 26, color: ink });
});
sheet.save(OUTPUT);

sheet.free();
clean.free();
noisy.free();
orig.free();

`DRUNet σ_in=${NOISE_SIGMA} → σ_clean=${STRENGTH}/255`;

// © 2026 Michael Lechner · mlc OpticScript · https://mlcgo.eu · Elastic License 2.0