Introduction

Ask a modern AI for "a fox in a snowy forest" and a crisp image appears in seconds. It feels like the machine is painting. It isn't. Under the hood it is doing something far stranger: it is taking a screen of pure random static and slowly scrubbing the noise away until a fox is left behind.

The idea comes from physics. If you drop ink in water, it diffuses — order dissolves into a uniform haze, and you can never un-mix it. A diffusion model asks the heretical question: what if we could run that process backwards? What if a network learned, at every tiny step, to nudge a noisy picture just slightly less noisy?

Train it on millions of images and it learns exactly that move. Then you hand it a frame of nothing but static, ask for the reverse a few hundred times, and a coherent image condenses out of the chaos — as if a snowstorm reassembled into a photograph.

Try It: Noise It, Then Un-Noise It

Below is a small hidden pattern. Press Add noise to corrupt it step by step until it dissolves into static — this is the forward process, and it is easy. Then press Denoise to run the reverse process: at each step the demo nudges every pixel back toward the pattern, and the image slowly reappears.

<p class="hint">A hidden pattern lives in this grid. <b>Add noise</b> corrupts it step by step (the easy forward process) until it becomes static. <b>Denoise</b> runs the reverse process: each step nudges every cell back toward the pattern, and the image re-forms.</p>
<canvas id="grid" width="256" height="256"></canvas>
<div class="meter">noise level: <span id="lvl">0%</span></div>
<div class="status" id="status">Press "Add noise", then "Denoise".</div>
<div class="btns">
  <button id="noise" type="button">Add noise</button>
  <button id="denoise" type="button">Denoise</button>
  <button id="reset" type="button" class="ghost">Reset</button>
</div>
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; }
.hint { font-size: .9rem; color: #444; margin: 0 0 .7rem; line-height: 1.45; }
canvas { width: 256px; height: 256px; image-rendering: pixelated; border-radius: 10px;
         border: 1px solid #cdd9e3; display: block; background: #000; }
.meter { font-size: .85rem; color: #1d3557; margin: .5rem 0 .2rem; font-weight: 600; }
.status { font-size: 1rem; font-weight: 600; margin: .3rem 0 .6rem; min-height: 1.4em; color: #1d3557; }
.btns { display: flex; gap: .5rem; flex-wrap: wrap; }
button { font: 600 14px system-ui, sans-serif; padding: .45rem .9rem; border: 1px solid #1d3557;
         background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
// Toy diffusion model. The "clean" image is a fixed target pattern (a ring + dot).
// Forward process: blend each pixel toward fresh random noise (adds noise, easy).
// Reverse process: blend each pixel back toward the known target (denoise).
// A real diffusion model replaces the "known target" with a neural net that PREDICTS
// the denoising direction from data (Sohl-Dickstein 2015; Ho, Jain, Abbeel 2020).
const G = 32;                 // grid is 32x32 cells
const canvas = document.getElementById('grid');
const ctx = canvas.getContext('2d');
canvas.width = G; canvas.height = G;   // draw at cell resolution, CSS upscales

// Target "image": a circle outline with a bright center, values in [0,1].
const target = new Float32Array(G * G);
for (let y = 0; y < G; y++) for (let x = 0; x < G; x++) {
  const dx = x - G/2 + 0.5, dy = y - G/2 + 0.5;
  const r = Math.sqrt(dx*dx + dy*dy);
  let v = 0;
  if (r < 3) v = 1;                              // center dot
  else if (r > 9 && r < 12) v = 0.85;           // ring
  target[y*G + x] = v;
}

let img = target.slice();   // current canvas state
let noise = 0;              // 0..1 conceptual noise level

function rand() { return Math.random(); }
function clamp(v){ return v < 0 ? 0 : v > 1 ? 1 : v; }

function render() {
  const id = ctx.createImageData(G, G);
  for (let i = 0; i < G*G; i++) {
    const c = Math.round(clamp(img[i]) * 255);
    id.data[i*4+0] = c; id.data[i*4+1] = c;
    id.data[i*4+2] = Math.min(255, c + 30); // slight cool tint
    id.data[i*4+3] = 255;
  }
  ctx.putImageData(id, 0, 0);
  document.getElementById('lvl').textContent = Math.round(noise*100) + '%';
}
function setStatus(t){ document.getElementById('status').textContent = t; }

// Forward step: move each pixel a fraction toward fresh random noise.
function addNoise() {
  const beta = 0.25;
  for (let i = 0; i < G*G; i++) img[i] = clamp(img[i]*(1-beta) + rand()*beta);
  noise = clamp(noise + beta*0.9);
  render();
  setStatus(noise > 0.85 ? 'Almost pure static — now try Denoise.' : 'Adding noise (forward process)...');
}
// Reverse step: move each pixel a fraction back toward the target (learned direction).
// The noise counter winds down slower than alpha, so several reverse steps run and
// the image fully re-forms — mirroring the hundreds of steps a real model takes.
function denoise() {
  if (noise <= 0.001) { setStatus('Already clean. Add noise first.'); return; }
  const alpha = 0.45;
  for (let i = 0; i < G*G; i++) img[i] = clamp(img[i]*(1-alpha) + target[i]*alpha);
  noise = clamp(noise - 0.12);
  render();
  setStatus(noise < 0.05 ? '✓ Image recovered from noise!' : 'Denoising (reverse process)...');
}
function reset(){ img = target.slice(); noise = 0; render(); setStatus('Press "Add noise", then "Denoise".'); }

document.getElementById('noise').addEventListener('click', addNoise);
document.getElementById('denoise').addEventListener('click', denoise);
document.getElementById('reset').addEventListener('click', reset);
reset();
Result
Console

Notice the asymmetry. Destroying the image is trivial — just keep adding randomness. Re-creating it is the hard part, and it only works because each reverse step "knows" which way to push. A real diffusion model replaces that hand-coded nudge with a giant neural network that has learned the right direction from data. Same loop, vastly more knowledge baked into one step.

The Real Story

Diffusion models are not an open problem — they are a working method, and a remarkably principled one. The idea was introduced by Sohl-Dickstein and colleagues in 2015 and made practical for high-quality images by Ho, Jain and Abbeel in 2020 (the "DDPM" paper). Here is the shape of it:

  • Forward process (easy). Take a real image and add a small amount of Gaussian noise. Repeat for hundreds of steps until nothing is left but pure static. This destruction is fixed and requires no learning at all.
  • Reverse process (learned). Train a network to undo one step: given a noisy image, predict the noise that was added, and subtract a little of it. Because each step is tiny, this prediction is a manageable target — far easier than drawing a whole image at once.
  • Sampling. Start from random static and apply the learned reverse step again and again. Each pass removes a sliver of noise, and after hundreds of passes a clean sample emerges.
  • Why it's stable. Splitting "make an image" into hundreds of gentle denoising steps avoids the brittle all-or-nothing training that plagued earlier generators. This is why diffusion now powers most state-of-the-art image and video systems.

The catch is cost: generating one image can mean running a huge network hundreds of times. Like training neural networks in general, the math is clear but the compute is enormous — which is exactly why research races to cut the number of reverse steps.

Where It Matters

"Start from noise, then refine" turns out to be a wildly general recipe, and it reaches far past pretty pictures:

  • Image and video generation: the text-to-image and text-to-video tools you have heard of are, almost without exception, diffusion models at heart.
  • Audio and speech: the same chain denoises a waveform or spectrogram into music or a spoken voice.
  • Science and medicine: diffusion models now propose candidate molecules and protein structures, working in the same space as protein folding tools.
  • Editing tasks: inpainting (filling a hole), super-resolution (sharpening a blurry photo) and restoration are all "denoise toward something plausible."

Learn how diffusion turns static into structure and you have met one of the central engines of modern generative AI — closely tied to how we train neural networks in the first place.

Conclusion

Diffusion models hide an elegant secret: the hard problem of "imagining an image" is broken into hundreds of easy problems of "remove a tiny bit of noise." Wrecking a picture is free; learning to rewind that wreckage, step by step, is what lets a machine condense a fox out of pure static.

So the next time an image generator answers your prompt in seconds, picture what is really happening — a snowstorm of randomness being patiently swept away, one gentle denoising pass at a time, until something that was never there comes into focus. It is not magic, and it is not painting. It is a noising process, run beautifully in reverse, closely related to how we train neural networks at all.

Share this article

Pick a channel — or use your device's native share sheet.

Comments

Loading comments...

https://www.kipuhub.com/en/article/diffusion-models/Content licensed under CC BY-NC 4.0.