假设您在某种色彩空间中有一个带有色调状通道的图像,即一个固有圆形的通道。
例如,在典型的HSL或HSV通道中,0或25的色调都对应于完全相同的颜色,通常是纯红色,而255则略微偏蓝,但仍然几乎是纯红色。
现在,如果您在这样的通道上应用高斯模糊,沿着0和255触摸的线,您可以将其平滑并且#34;漫长的路程,在穿过整个彩虹的两个红色之间形成一个渐变。 - 几乎肯定不会想到这个结果。
由于亮度/值和/或饱和度为0的奇点而发生第二个问题,在这种情况下,Hue在技术上可以采用任意值。 - 大多数色彩空间转换只是在转换色彩空间时选择0的色调,因为对于几乎所有常见的用例来说,它都不重要。但如果我要模糊,那绝对是。
如何更改典型的高斯模糊算法以至少妥善处理(更重要的)第一个问题,理想情况下也是第二个问题?
我认为第二个更难以完成,仅仅使用Hue通道无法完成,但是宁愿需要来自其他两个的信息来处理奇点的特殊情况,但希望有一些相当简单的调整可以修复第一个
如果答案需要特定的算法,一个简单快捷的方法就是使用重复的盒子卷积进行近似,例如here
为方便起见,这里是来自该网站的复制+粘贴,执行三个水平和三个垂直框卷积:
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;
}
但我主要对实际的算法更改感兴趣,而不一定是特定语言的特定实现。