2017-06-16 47 views
0

我想在c中从头开始实现高斯模糊。我有一个程序创建一个结构并加载一个.bmp文件,创建一个高斯模糊滤镜(前两个for-loops),然后将高度,宽度和实际像素信息发送给另一个应用滤镜的函数到图像(下面的4个嵌套for循环)。应用后,它会输出修改后的.bmp文件。目前它稍微有效,但它不能一直工作。我无法调整模糊的强度(所有模糊的水平看起来都一样)。它也似乎错过了图像周围像素的外边缘。高斯模糊实现不完全工作

当我创建过滤器,我使用:

double sigma = 10.0; 
double r, s = 2.0 * sigma * sigma; 
double sum = 0.0; 

但它看起来相同的适马是否为1,10,100 - 我的理解是,它应该得到更加模糊与更大的西格玛。

创建过滤器:

// generate 5x5 kernel 
for (int x = -2; x <= 2; x++) 
{ 
    for(int y = -2; y <= 2; y++) 
    { 
     r = sqrt(x*x + y*y); 
     gKernel[x+2][y+2] = (exp(-(r*r)/s))/(M_PI * s); 
     sum += gKernel[x + 2][y + 2]; 
    } 
} 

// normalize the Kernel 
for(int i = 0; i < 5; ++i) 
    for(int j = 0; j < 5; ++j) 
     gKernel[i][j] /= sum; 

,然后应用过滤器:

for (i = 1; i < bmp->height - 1; i++) 
{ 
    for (j = 1; j < bmp->width - 1; j++) 
    { 
     sum = 0.0; 
     for (p = 0; p < 5; p++) 
     { 
      for (q = 0; q < 5; q++) 
      { 
       sum += bmp->pixels[(i + p) * bmp->width + j + q] * gKernel[p][q]; 
      } 
     } 
     bmp->pixels[(i - 1) * (bmp->width) + j] = (unsigned char) sum ; 
    } 
} 

任何帮助,非常感谢!感谢您的时间。

+0

欢迎来到Stack Overflow。遵循SO约定使您更有可能获得帮助。请阅读如何提供一个MCVE。 https://stackoverflow.com/help/mcve – Gene

+0

当您增加西格玛时,是否增加了您的过滤器内核大小? –

+0

否 - 你的意思是为x的西格玛生成一个x x内核,然后x + 5的x + 5内核生成一个y + 5的西格玛?我只测试了5的内核大小5.当我增加西格玛时,我应该增加这个值吗? – kab403

回答

1

它错过了边缘点,因为你已经告诉它这样做。它也被硬编码为宽度为5个像素的内核。

边缘始终是过滤的问题。通常最好是扩大图像,用镜像填充。然后应用没有特殊代码的滤波器来处理边缘条件。 宽*高* N * N方法非常慢。对于大型滤波器,您需要使用FFT进行滤波。这是一种更先进的技术。

+0

鉴于电脑总是按照你告诉他们的方式做,所以我认为这是真的我告诉它错过边缘:)我只需要弄清楚如何解决它。从上面的评论中,我会看看用sigma值增加内核大小是否能解决问题 - 我没有意识到这是一个问题。我会寻找填充和FFT。谢谢你的帮助! – kab403

0

今天早些时候我想到了这一点 - 多亏了那些回应,你们都会有很多帮助!基本上,当我增加代码以增加内核的大小时,我增加了西格玛,我能够调整图像出现的模糊程度。我还添加了代码来处理边缘情况 - 在该笔记中,我正在使用if-else if-else语句,但我试图找出填充。

现在我有:

// generate nxn kernel 
for (int i = 0; i < kSize; i++) 
{ 
    for(int j = 0; j < kSize; j++) 
    { 
     gKernel[i][j] = exp(-(i*i+j*j)/(2*sigma*sigma))/(2*M_PI*sigma*sigma); 
     sum += gKernel[i][j]; 
    } 
} 

你能想象的所有“5的上面现在被替换成 'kSize'。当我应用滤镜时,我调整for循环从0到bmp-> width/height,然后调整我将像素置于循环体内的位置(这是if-else if-else语句进入的位置玩,尽管我会尽快改变)。再次感谢!