C 高斯模糊实现并不完全有效

C 高斯模糊实现并不完全有效,c,gaussian,bmp,C,Gaussian,Bmp,我试图用c语言从头开始实现高斯模糊。我有一个程序,它创建一个结构并加载一个.bmp文件,创建一个高斯模糊过滤器(下面的前两个用于循环),然后将带有高度、宽度和实际像素信息的结构发送给另一个函数,该函数将过滤器应用于图像(下面的4-嵌套用于循环)。应用后,输出修改后的.bmp文件。目前它稍微起作用,但不是一直起作用。我无法调整模糊的强度(所有级别的模糊看起来都一样)。它似乎还遗漏了图像周围像素的最外边缘 创建过滤器时,我使用: double sigma = 10.0; double r, s =

我试图用c语言从头开始实现高斯模糊。我有一个程序,它创建一个结构并加载一个.bmp文件,创建一个高斯模糊过滤器(下面的前两个用于循环),然后将带有高度、宽度和实际像素信息的结构发送给另一个函数,该函数将过滤器应用于图像(下面的4-嵌套用于循环)。应用后,输出修改后的.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 ;
    }
}
//生成5x5内核
对于(int x=-2;x宽度-1;j++)
{
总和=0.0;
对于(p=0;p<5;p++)
{
对于(q=0;q<5;q++)
{
sum+=bmp->pixels[(i+p)*bmp->width+j+q]*gKernel[p][q];
}
}
bmp->像素[(i-1)*(bmp->宽度)+j]=(无符号字符)和;
}
}

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

它错过了边缘周围的点,因为您已告诉它这样做。它还硬编码为宽度为5像素的内核

边总是过滤的问题。通常,最好展开图像,用镜像填充。然后对边缘条件应用无特殊代码的过滤器。
宽度*高度*N*N方法非常慢。对于大型滤波器,需要使用FFT进行滤波。这是一项更先进的技术。

我今天早些时候就发现了这一点——感谢那些回应的人,你们都帮了大忙!基本上,当我添加代码以增加内核的大小,同时增加sigma时,我就能够调整图像的模糊程度。我还添加了处理边缘情况的代码——注意,我目前使用的是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]; 
    }
}
//生成nxn内核
对于(int i=0;i

您可以想象,上面的所有“5”现在都被“kSize”取代。当我应用过滤器时,我将for循环调整为从0到bmp->width/height,然后调整我在循环体中放置像素的位置(这是if-else-if-else语句发挥作用的地方,不过我很快会进行更改)。再次感谢

欢迎来到堆栈溢出。遵循SO惯例会使你更有可能得到帮助。请阅读如何提供MCVE。当你增加sigma时,你是否在增加你的过滤器内核大小?不-你的意思是为y的sigma生成一个x×x内核,然后为y+5的sigma生成一个x+5×x+5内核?我只测试了5乘5的内核大小。当我增加sigma时,我应该增加这个值吗?鉴于计算机总是按照你告诉它们的去做,我认为这是真的,我是在告诉它忽略边缘:)我只需要找出如何修复它。从上面的评论中,我将看到用sigma值增加内核大小是否可以解决这个问题——我没有意识到这是个问题。我会检查填充和FFT。谢谢你的帮助!