Bild-Degradations-Pipeline — Trainingsdaten für Restaurierungs-Modelle erzeugen

Das „High-Order Degradation Model" von Real-ESRGAN / GFPGAN: ein makelloses Bild nehmen und die Schäden synthetisieren, die echte Low-Quality-Fotos haben — damit ein Restaurierungs-Netz lernt, sie rückgängig zu machen. Eine Ordnung = anisotroper Gauss-Blur → Down-/Up-Resampling (Auflösungsverlust) → Sensor-Rauschen (Gauss / uniform / Poisson-Schrotrauschen über die native addNoise-Op). SECOND_ORDER läuft die Kette zweimal — echte Schäden sind verkettet, das ist Real-ESRGANs Kerntrick. Ausgabe: clean | degraded nebeneinander. Dieselbe Pipeline gibt es als Batch-CLI (samples/binaries/degrade.js → eigenständiges `degrade`-Executable), um einen Ordner sauberer Bilder in clean/degraded-Trainingspaare zu verwandeln.

INPUT
INPUT — Bild-Degradations-Pipeline — Trainingsdaten für Restaurierungs-Modelle erzeugen
Clean | degraded pair
Clean | degraded pair — Bild-Degradations-Pipeline — Trainingsdaten für Restaurierungs-Modelle erzeugen
JavaScript
// Real-ESRGAN / GFPGAN-style image degradation pipeline — generate
// training data for restoration models. Outputs a clean | degraded
// side-by-side so the effect of each parameter is visible live.
// demo_degrade.js
//!INPUT: INPUT
//!OUTPUT: OUTPUT
//!PARAM: BLUR:number=1.4,min=0,max=8,step=0.1
//!PARAM: ANISO:number=0.7,min=0,max=4,step=0.1
//!PARAM: RESAMPLE:number=2.5,min=1,max=8,step=0.5
//!PARAM: NOISE:enum(gaussian|uniform|poisson)=poisson
//!PARAM: NOISE_SIGMA:number=0.06,min=0,max=0.3,step=0.005
//!PARAM: NOISE_COLOR:boolean=true
//!PARAM: SECOND_ORDER:boolean=true
//!SAMPLE light(BLUR=0.6, ANISO=0.2, RESAMPLE=1.5, NOISE=gaussian, NOISE_SIGMA=0.02, SECOND_ORDER=false)
//!SAMPLE heavy(BLUR=2.4, ANISO=1.2, RESAMPLE=4, NOISE=poisson, NOISE_SIGMA=0.12, NOISE_COLOR=true, SECOND_ORDER=true)
//!SAMPLE webcam(BLUR=1.0, ANISO=0.3, RESAMPLE=2, NOISE=poisson, NOISE_SIGMA=0.07, NOISE_COLOR=true, SECOND_ORDER=false)

// Restoration networks (Real-ESRGAN, GFPGAN, CodeFormer) are trained
// on synthetic pairs: take a pristine image, *degrade* it, and let the
// network learn to invert the damage. The quality of that synthetic
// degradation is what makes or breaks the model.
//
// This is the "high-order degradation model" — one order is:
//
//   1. blur     — anisotropic Gaussian (BLUR ± ANISO per axis)
//   2. resample — downscale by RESAMPLE then back up (resolution loss)
//   3. noise    — native addNoise: gaussian / uniform / poisson
//                 (Poisson = signal-dependent shot noise)
//
// SECOND_ORDER runs the chain twice — real-world damage is compounded,
// not single-stage, and that is Real-ESRGAN's central trick.
//
// The same pipeline ships as a batch CLI — `samples/binaries/degrade.js`
// compiles to a standalone `degrade` executable for turning a folder
// of clean images into clean/degraded training pairs.

const orig = Engine.loadImage(INPUT);
const W = orig.width, H = orig.height;

// The image we actually degrade — keep `orig` pristine for the
// side-by-side reference panel.
const dmg = orig.clone();

function degradeOnce() {
    if (BLUR > 0 || ANISO > 0) {
        dmg.anisotropicBlur(BLUR + ANISO, Math.max(0, BLUR - ANISO));
    }
    if (RESAMPLE > 1) {
        const dw = Math.max(1, Math.round(W / RESAMPLE));
        const dh = Math.max(1, Math.round(H / RESAMPLE));
        dmg.resize(dw, dh).resize(W, H);
    }
    if (NOISE_SIGMA > 0) {
        dmg.addNoise({ type: NOISE, sigma: NOISE_SIGMA, color: NOISE_COLOR });
    }
}

degradeOnce();
if (SECOND_ORDER) degradeOnce();

// Compose clean | degraded side-by-side.
const sheet = Engine.createImage(W * 2, H);
sheet.blendAt(orig, px(0, 0), 1.0);
sheet.blendAt(dmg,  px(W, 0), 1.0);
const label = new Pixel(1, 1, 1, 0.8);
sheet.drawText("CLEAN", 16, 32, { font: "JetBrains Mono", size: 22, color: label });
sheet.drawText("DEGRADED", W + 16, 32, { font: "JetBrains Mono", size: 22, color: label });
sheet.save(OUTPUT);

sheet.free();
dmg.free();
orig.free();

`degradation: blur ${BLUR}±${ANISO}, resample ${RESAMPLE}×, ${NOISE} σ=${NOISE_SIGMA}${SECOND_ORDER ? ", 2nd-order" : ""}`;

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