gazou-compressor.jp

ディザ拡散係数チューニング:Floyd vs 自作誤差カーネル最適化の実務

“Floyd-Steinberg だから十分” で止まっている現場は多いですが、用途特化カーネル は可読性や彩度保持で有利です。本稿では誤差拡散係数を多目的最適化し 色差・バンディング・ランダムノイズ のバランスを取る流れを示します。

ゴール
  • 目的指標を数値化(ΔE, banding, noise power)
  • GA で係数探索(制約: 和≒1, 非負)
  • CI で再現性確保 (指標逸脱で失敗)

1. ベースラインと課題

Floyd-Steinberg カーネルは汎用性が高い一方、水平/垂直の筋 が残るケースや 過剰ノイズ化 が発生します。利用シーンを UIアイコン減色 / 写真減色 / 低彩度図表 等に分類し、それぞれ適切な係数バランスを求めます。

// Kernel (Floyd-Steinberg baseline) weights
//    *   7
// 3  5  1
// sum=16
const fs = [
  {dx:1, dy:0, w:7/16},
  {dx:-1,dy:1, w:3/16},
  {dx:0, dy:1, w:5/16},
  {dx:1, dy:1, w:1/16},
];

2. 遺伝的探索 (GA)

小さな自由度(4~7係数)であれば GA は短時間で収束します。Elitism で上位を保持しつつ、突然変異で空間を探索します。

// Genetic Algorithm (simplified pseudo)
initPopulation();
for (let gen=0; gen<80; gen++){
  evalPopulation(); // metrics: deltaE mean, variance, banding score
  const elites = selectTop(pop, 4);
  const next = [...elites];
  while(next.length < POP_SIZE){
    const a = tournament(pop), b = tournament(pop);
    let child = crossover(a,b);
    if(Math.random()<MUT_RATE) child = mutate(child);
    next.push(child);
  }
  pop = next;
}

3. 評価指標の設計

単一ΔEだけでは バンディングノイズ増幅 のトレードオフを監視できません。FFTで周波数集中を測るか、勾配ヒストグラムの谷を banding 指標に採用します。

// Evaluation metrics (illustrative)
const deltaE = meanDeltaE(orig, dithered);
const banding = bandingScore(dithered); // FFT or gradient histogram based
const noisePower = spatialVariance(residual(dithered));
fitness = 0.55*(1-deltaE_norm) + 0.25*(1-banding_norm) + 0.20*(1-noisePower_norm);

4. カーネル適用実装

function diffuse(pixels,w,h,kernel){
  for (let y=0;y<h;y++){
    for (let x=0;x<w;x++){
      const i = (y*w+x)*4;
      const oldR = pixels[i];
      const newR = quantize(oldR); // 例: 4bit
      const err = oldR - newR;
      pixels[i] = newR;
      for (const k of kernel){
        const nx = x + k.dx, ny = y + k.dy;
        if(nx<0||nx>=w||ny<0||ny>=h) continue;
        const ni = (ny*w+nx)*4;
        pixels[ni] = clamp(pixels[ni] + err*k.w);
      }
    }
  }
}

5. CI への組込み

調整後のカーネルを ディザ比較ツール で視覚検証し、差分定量結果を JSON 化し閾値テストします。

# CI regression detection for tuned kernel
node scripts/dither-eval.js --kernel tuned.json --out metrics.json
node scripts/metrics-threshold.js metrics.json   --deltaE-max 3.0   --banding-max 0.08   --noisePower-max 0.12 || exit 1

6. FAQ

7. まとめ

“目的を指標に落とす” → “係数探索” → “CI 定着” の三段構成で汎用カーネルから脱却できます。まずは ΔE + banding の2軸最小化から着手してください。

gazou-compressor.jp 編集部

画像圧縮・変換・背景除去などの実践テクニックと、Webで“速く・軽く・崩さない”ためのノウハウを発信しています。

関連記事

トピック/更新日の近いコンテンツ