2016-04-23 17 views
2

色合いのような色のある色空間、つまり元々円形の色の画像があるとします。
たとえば、一般的なHSLまたはHSVチャネルでは、色相0または色相256の両方がまったく同じ色、通常は純粋な赤色に対応し、255は少し青みがかったが、依然としてほぼ純粋な赤色です。
ここで、0と255が接触する線に沿ってガウスのぼかしを適用すると、遠くに滑らかになり、2つの赤の間に勾配が形成されます虹。 - この結果はほとんど望ましくないでしょう。画像の色合いを正しく滑らかにするには?

明度/値および/または彩度0の特異点のために2番目の問題が発生します。その場合、色相は技術的に任意の値をとることができます。 - 色空間を変換するとき、ほとんどの色空間変換は単に色相0を選択します。ほとんどの通常のユースケースでは問題にならないためです。しかし、もし私がぼかしていたら、それは絶対にあります。

少なくとも(重要な)最初の問題、理想的には2番目の問題を適切に処理するために、標準的なガウスブラーアルゴリズムを変更する必要がありますか?

私は2番目のものがより厳しいと仮定し、色相チャンネルだけではできませんでしたが、特異性のために他の2つの特殊な場合には情報が必要ですが、うまくいけば、最初。便宜上

特定のアルゴリズムが答えのために必要であれば、たとえば、使用されているように、素敵なシンプルかつ高速な方法は、繰り返しボックスの畳み込みを使用して近似なり、here

は、ここでのコピー+です水平3と3つの垂直ボックスのコンボリューションをやって、そのサイトから貼り付けます。

function gaussBlur_4 (scl, tcl, w, h, r) { 
    var bxs = boxesForGauss(r, 3); 
    boxBlur_4 (scl, tcl, w, h, (bxs[0]-1)/2); 
    boxBlur_4 (tcl, scl, w, h, (bxs[1]-1)/2); 
    boxBlur_4 (scl, tcl, w, h, (bxs[2]-1)/2); 
} 
function boxBlur_4 (scl, tcl, w, h, r) { 
    for(var i=0; i<scl.length; i++) tcl[i] = scl[i]; 
    boxBlurH_4(tcl, scl, w, h, r); 
    boxBlurT_4(scl, tcl, w, h, r); 
} 
function boxBlurH_4 (scl, tcl, w, h, r) { 
    var iarr = 1/(r+r+1); 
    for(var i=0; i<h; i++) { 
     var ti = i*w, li = ti, ri = ti+r; 
     var fv = scl[ti], lv = scl[ti+w-1], val = (r+1)*fv; 
     for(var j=0; j<r; j++) val += scl[ti+j]; 
     for(var j=0 ; j<=r ; j++) { val += scl[ri++] - fv  ; tcl[ti++] = Math.round(val*iarr); } 
     for(var j=r+1; j<w-r; j++) { val += scl[ri++] - scl[li++]; tcl[ti++] = Math.round(val*iarr); } 
     for(var j=w-r; j<w ; j++) { val += lv  - scl[li++]; tcl[ti++] = Math.round(val*iarr); } 
    } 
} 
function boxBlurT_4 (scl, tcl, w, h, r) { 
    var iarr = 1/(r+r+1); 
    for(var i=0; i<w; i++) { 
     var ti = i, li = ti, ri = ti+r*w; 
     var fv = scl[ti], lv = scl[ti+w*(h-1)], val = (r+1)*fv; 
     for(var j=0; j<r; j++) val += scl[ti+j*w]; 
     for(var j=0 ; j<=r ; j++) { val += scl[ri] - fv  ; tcl[ti] = Math.round(val*iarr); ri+=w; ti+=w; } 
     for(var j=r+1; j<h-r; j++) { val += scl[ri] - scl[li]; tcl[ti] = Math.round(val*iarr); li+=w; ri+=w; ti+=w; } 
     for(var j=h-r; j<h ; j++) { val += lv  - scl[li]; tcl[ti] = Math.round(val*iarr); li+=w; ti+=w; } 
    } 
} 

function boxesForGauss(sigma, n) // standard deviation, number of boxes 
{ 
    var wIdeal = Math.sqrt((12*sigma*sigma/n)+1); // Ideal averaging filter width 
    var wl = Math.floor(wIdeal); if(wl%2==0) wl--; 
    var wu = wl+2; 

    var mIdeal = (12*sigma*sigma - n*wl*wl - 4*n*wl - 3*n)/(-4*wl - 4); 
    var m = Math.round(mIdeal); 
    // var sigmaActual = Math.sqrt((m*wl*wl + (n-m)*wu*wu - n)/12); 

    var sizes = []; for(var i=0; i<n; i++) sizes.push(i<m?wl:wu); 
    return sizes; 
} 

しかし、私は必ずしも特定の言語での特定の実装では、必要な実際のアルゴリズムの変更で主に興味があります。

+0

私は誰もあなたの第2段落を理解するとは思わない。 – gpasch

答えて

2

色相の色空間に留まり、循環データ統計を使用してください。hereまたはhereを参照してください。

ガウスフィルタは畳み込みフィルタなので基本的には加重平均です。このような色空間では、単純に加重循環平均を使用します。これは、各値/角度をsin/cosに分解し、sin/cosを平均して角度/値に戻ることによって計算されます。

+1

良い答え - そして良い参考資料。 –

関連する問題