我一直在尝试为我的图像编辑程序实现一个简单的高斯模糊算法。但是,我在完成这项工作时遇到了一些麻烦,我认为问题出在下面的代码片段中:
for( int j = 0; j < pow( kernel_size, 2 ); j++ )
{
int idx = ( i + kx + ( ky * img.width ));
//Try and overload this whenever possible
valueR += ( img.p_pixelArray[ idx ].r * kernel[ j ] );
valueG += ( img.p_pixelArray[ idx ].g * kernel[ j ] );
valueB += ( img.p_pixelArray[ idx ].b * kernel[ j ] );
if( kx == kernel_limit )
{
kx = -kernel_limit;
ky++;
}
else
{
kx++;
}
}
kx = -kernel_limit;
ky = -kernel_limit;
上述代码的简要说明:内核大小是由高斯模糊公式生成的内核(或矩阵)的大小。 kx 和 ky 是用于迭代内核的变量。 i 是嵌套此循环的父循环,并遍历图像中的每个像素。每个值变量只保存一个浮点R,G或B值,然后用于获取最终结果。 if-else用于增加 kx 和 ky 。 idx 用于查找正确的像素。 内核限制是设置为
的变量(*kernel size* - 1) / 2
所以我可以让 kx 从-1(使用3x3内核)转换为+1,与 ky 相同。我认为问题在于行
int idx = ( i + kx + ( ky * img.width ));
但我不确定。我得到的图像是:
可以看出,颜色在对角线方向上模糊,看起来更像某种运动模糊而不是高斯模糊。如果有人可以提供帮助,我将非常感激。
编辑: 我填充内核的方式如下:
for( int i = 0; i < pow( kernel_size, 2 ); i++ )
{
// This. Is. Lisp.
kernel[i] = (( 1 / ( 2 * pi * pow( sigma, 2 ))) * pow (e, ( -((( pow( kx, 2 ) + pow( ky, 2 )) / 2 * pow( sigma, 2 ))))));
if(( kx + 1 ) == kernel_size )
{
kx = 0;
ky++;
}
else
{
kx++;
}
}
答案 0 :(得分:2)
几个问题:
你的高斯错过2 * pow( sigma, 2 )
周围的括号(即使你已经有很多......)。现在你乘以方差而不是除以。
但问题是,你的高斯是以kx = ky = 0
为中心,因为你让它从0
到kernel_size
,而不是从-kernel_limit
到{ {1}}。这导致对角线模糊。像下面这样的东西应该更好用
kernel_limit
还要注意我是如何摆脱你的lisp-ness和一些改进的:为了清楚起见使用一些中间变量(如果你要求,编译器会优化它们);简单乘法比kx = -kernel_limit;
ky = -kernel_limit;
int kernel_size_sq = kernel_size * kernel_size;
for( int i = 0; i < kernel_size_sq; i++ )
{
double sigma_sq = sigma * sigma;
double kx_sq = kx * kx;
double ky_sq = ky * ky;
kernel[i] = 1.0 / ( 2 * pi * sigma_sq) * exp(-(kx_sq + ky_sq) / (2 * sigma_sq));
if(kx == kernel_limit )
{
kx = -kernel_limit;
ky++;
}
else
{
kx++;
}
}
快; pow(x, 2)
。