ディザ拡散係数チューニング: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
- GA以外は? → Simulated Annealing や CMA-ES も有効。
- 減色パレット側は? → k-means 初期化を複数トライし最良ΔEを採用。
7. まとめ
“目的を指標に落とす” → “係数探索” → “CI 定着” の三段構成で汎用カーネルから脱却できます。まずは ΔE + banding の2軸最小化から着手してください。