卷积算法逻辑

Convolutional algorithm logic

好的,所以我正在尝试在 EmguCv 中实现我自己的卷积算法(这是一项要求)。过滤似乎无法正常工作。结果并非例外。我的算法错误在哪里?这是我到目前为止所做的:

            int L = 3;

            double kernelTopLeft = kernel[0 + L * 0];
            double kernelTopCenter = kernel[1 + L * 0];
            double kernelTopRight = kernel[2 + L * 0];
            double kernelCenterLeft = kernel[0 + L * 1];
            double kernelCenter = kernel[1 + L * 1];
            double kernelCenterRight = kernel[2 + L * 1];
            double kernelBottomLeft = kernel[0 + L * 2];
            double kernelBottomCenter = kernel[1 + L * 2];
            double kernelBottomRight = kernel[2 + L * 2];

                for (int bNumber = 0; bNumber < 3; bNumber++)
                {
                    for (int j = 1; j < img.Width - 1; j++)
                    {
                        for (int i = 1; i < img.Height - 1; i++)
                        {

                           //Getting pixels in 3x3 Window

                            double topLeft = img.Data[(i - 1), (j - 1), bNumber];
                            double centerLeft = img.Data[(i - 1), (j), bNumber];
                            double bottomLeft = img.Data[(i - 1), (j + 1), bNumber];
                            double topCenter = img.Data[(i), (j - 1), bNumber];
                            double center = img.Data[(i), (j), bNumber];
                            double bottomCenter = img.Data[(i), (j + 1), bNumber];
                            double topRight = img.Data[(i + 1), (j - 1), bNumber];
                            double centerRight = img.Data[(i + 1), (j), bNumber];
                            double bottomRight = img.Data[(i + 1), (j + 1), bNumber];

                            //Kernel operation is kernel window * pixel window (multiplication is mirrored)

                            double newValue = bottomRight * kernelTopLeft + bottomCenter * kernelTopCenter + bottomLeft * kernelTopRight +
                                              centerRight * kernelCenterLeft + center * kernelCenter + centerLeft * kernelCenterRight +
                                              topRight * kernelBottomLeft + topCenter * kernelBottomCenter + topLeft * kernelBottomRight;

                            if (newValue > 255)
                            {
                                newValue = 255;
                            }
                            else if (newValue < 0)
                            {
                                newValue = 0;
                            }

                            img.Data[(i), (j), bNumber] = (byte)newValue;
                        }
                    }
                }

我的算法实际上是在整个图像上移动 3x3 的 window 并将其与内核相乘以得到中间像素的值,然后继续计算直到达到最终值。

正如我在评论中所说,您似乎在计算新的像素值,然后用新值更新原始 img.Data[]。这意味着当您浏览图像时,每个内核都使用右侧和下方行(您尚未处理)像素的原始值,并使用中心左侧像素的新值以及上面的行(您已经处理过)。

对于卷积,每个内核应该只考虑图像的原始值。引用 Wikipedia:

The values of a given pixel in the output image are calculated by multiplying each kernel value by the corresponding input image pixel values.

请注意,在某些形式的图像处理中,您确实会以某种形式将数据从一个内核传输到下一个内核。 Error diffusion such as Floyd–Steinberg dithering 需要将每个像素的误差值拆分并添加到尚未处理的像素中,但这通常是通过更改输入图像中的像素来完成的。

要修复它,请为输出创建一个相同大小的新 "image",然后在循环结束时更新它。

希望对您有所帮助