如何将内核应用于光栅图像

How to apply a kernel to a raster image

我正在尝试将锐化内核应用于光栅图片,这是我的内核:

  { 0.0f,-1.0f,0.0f,
    -1.0f,5.0f,-1.0f,
    0.0f,-1.0f,0.0f }

这是我的代码:

struct Pixel{
    GLubyte R, G, B;
    float x, y;
};
. . . 

for (unsigned i = 1; i < iWidth - 1; i++){
            for (unsigned j = 1; j < iHeight - 1; j++){
                float r = 0, g = 0, b = 0;
                r += -(float)pixels[i + 1][j].R;
                g += -(float)pixels[i + 1][j].G;
                b += -(float)pixels[i + 1][j].B;

                r += -(float)pixels[i - 1][j].R;
                g += -(float)pixels[i - 1][j].G;
                b += -(float)pixels[i - 1][j].B;

                r += -(float)pixels[i][j + 1].R;
                g += -(float)pixels[i][j + 1].G;
                b += -(float)pixels[i][j + 1].B;

                r += -(float)pixels[i][j - 1].R;
                g += -(float)pixels[i][j - 1].G;
                b += -(float)pixels[i][j - 1].B;

                pixels[i][j].R = (GLubyte)((pixels[i][j].R * 5) + r);
                pixels[i][j].G = (GLubyte)((pixels[i][j].G * 5) + g);
                pixels[i][j].B = (GLubyte)((pixels[i][j].B * 5) + b);

            }
        }

但是当我应用这个内核时颜色会混淆,这是一个例子:

我做错了什么?

注意:我知道 OpenGL 可以快速轻松地做到这一点,但我只是想试验一下这种遮罩。

编辑:第一个代码有一个错误:

            pixels[i][j].R = (GLubyte)((pixels[i][j].R * 5) + r);
            pixels[i][j].G = (GLubyte)((pixels[i][j].R/*G*/ * 5) + g);
            pixels[i][j].B = (GLubyte)((pixels[i][j].R/*B*/ * 5) + b);

我修复了它,但我仍然遇到这个问题。

我将最后三行更改为:

                 r = (float)((pixels[i][j].R * 5) + r);
                 g = (float)((pixels[i][j].G * 5) + g);
                 b = (float)((pixels[i][j].B * 5) + b);
                 if (r < 0) r = 0;
                 if (g < 0) g = 0;
                 if (b < 0) b = 0;
                 if (r > 255) r = 255;
                 if (g > 255) g = 255;
                 if (b > 255) b = 255;

                pixels[i][j].R = r;
                pixels[i][j].G = g;
                pixels[i][j].B = b;

现在输出如下所示:

您在此处存在复制粘贴错误:

            pixels[i][j].R = (GLubyte)((pixels[i][j].R * 5) + r);
            pixels[i][j].G = (GLubyte)((pixels[i][j].R * 5) + g);
            pixels[i][j].B = (GLubyte)((pixels[i][j].R * 5) + b);
                                                     ^

这应该是:

            pixels[i][j].R = (GLubyte)((pixels[i][j].R * 5) + r);
            pixels[i][j].G = (GLubyte)((pixels[i][j].G * 5) + g);
            pixels[i][j].B = (GLubyte)((pixels[i][j].B * 5) + b);

另外看起来你可能有 iWidth/iHeight 转置,但如果没有看到其余代码就很难说。通常虽然外层循环遍历行,但上限将是行数,即图像高度。

最重要的是,尽管您有一个基本问题,因为您正试图就地执行邻域操作。每个输出像素都取决于它的邻居,但是您在遍历图像时正在修改这些邻居。你需要在异地做这种操作,即有一个单独的输出图像:

            out_pixels[i][j].R = r;
            out_pixels[i][j].G = g;
            out_pixels[i][j].B = b;

这样输入图像就不会被修改。 (另请注意,您需要将边缘像素从输入图像复制到输出图像。)