尝试在 CS50 中为 PSET4 的图像实施框模糊时,为什么我的 RGB 值略有偏差?

Why are my RGB values slightly off when trying to implement a box blur on a image for PSET4 in CS50?

我已经为此工作了几个星期但无济于事。我认为逻辑和实现是合理的,但它没有通过所有测试,除了模糊角像素。

我的逻辑:将原始文件图像中的每个像素复制到相同的图像,计算每个相邻像素(如果存在)的 RGB 值的平均值,然后应用回原始图像。我的实现通过嵌套循环扫描每个像素的上行、下行和下行。我知道这不是最简洁的实施方式——我是新手。

下面是一个此类错误的示例:

:( blur incorrectly filters 3x3 image

Expected Output

70 85 95

80 95 105

90 105 115

117 130 140

127 140 149

137 150 159

163 178 188

170 185 194

178 193 201

我的结果:

Actual Output

70 85 95

90 106 116

103 119 129

135 150 160

145 160 169

155 169 178

175 188 197

178 191 200

180 193 201

这是我的代码(用 C 语言编写):

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE imageCopy[height][width];
                                            //assign new image
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            imageCopy[i][j] = image[i][j];
        }
    }

    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            int red = 0;
            int green = 0;
            int blue = 0;
            float pixelCount = 0.00;
                                                        //scan top row
            for (int k = -1; k < 2; k++)
            {
                if ((i - 1) >= 0 && (j + k) >= 0 && (j + k) < width)
                {
                    red += imageCopy[i - 1][j + k].rgbtRed;
                    green += imageCopy[i - 1][j + k].rgbtGreen;
                    blue += imageCopy[i - 1][j + k].rgbtBlue;
                    pixelCount++;
                }
            }
                                                        //scan same row
            for (int m = -1; m < 2; m++)
            {
                if ((j + m) >= 0 && (j + m) < width)
                {
                    red += imageCopy[i][j + m].rgbtRed;
                    green += imageCopy[i][j + m].rgbtGreen;
                    blue += imageCopy[i][j + m].rgbtBlue;
                    pixelCount++;
                }
            }
                                                        //scan below row
            for (int n = -1; n < 2; n++)
            {
                if ((i + 1) < height && (j + n) >= 0 && (j + n) < width)
                {
                    red += imageCopy[i + 1][j + n].rgbtRed;
                    green += imageCopy[i + 1][j + n].rgbtGreen;
                    blue += imageCopy[i + 1][j + n].rgbtBlue;
                    pixelCount++;
                }
            }
                                                        // find averages
            imageCopy[i][j].rgbtRed = round(red / pixelCount);
            imageCopy[i][j].rgbtGreen = round(green / pixelCount);
            imageCopy[i][j].rgbtBlue = round(blue / pixelCount);
        }
    }
                                                        // assign back to original image
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            image[i][j] = imageCopy[i][j];
        }
    }
    return;
}

提前致谢。

好的,我找到了问题

你为每个像素计算一个新的 "blurred" 值,逻辑似乎没问题。最后,您要做的是使用这段代码将像素分配给它们的 "new blurred value"。

imageCopy[i][j].rgbtRed = round(red / pixelCount);
imageCopy[i][j].rgbtGreen = round(green / pixelCount);
imageCopy[i][j].rgbtBlue = round(blue / pixelCount);

这不行,因为您对已更改的图像应用 "blur" 过滤。所以你所做的实际上是你用一个模糊的像素改变一个像素,然后对于邻域像素你使用它旁边的"blurred"像素来计算这是错误的。

解决办法;

imageCopy在计算的时候不要改变,因为所有的模糊计算都应该在"original image"上完成。在每个像素的末尾,您应该将值直接传递给 image。将 imageCopy 替换为 image,如下所示。

image[i][j].rgbtRed = round(red / pixelCount);
image[i][j].rgbtGreen = round(green / pixelCount);
image[i][j].rgbtBlue = round(blue / pixelCount);

并从代码中删除这个 for 循环。

for (int i = 0; i < height; i++)
{
    for (int j = 0; j < width; j++)
        {
            image[i][j] = imageCopy[i][j];
        }
}