CS50 边缘过滤程序无法正常运行(Sobel 算子)

CS50 edges filter program does not function properly (Sobel operator)

我必须将 Sobel operator 应用到图像中的每个像素,以便 cs50 突出显示边缘,因此我创建了每个像素的副本,然后找到像素的每种颜色的 Gx 和 Gy 值(6 个总值:gxR、gxB、gxG、gyR、gyB、gyG)。我为图片角落或边缘的像素创建了 8 if 个案例(我意识到这是多余的并且非常重复,但我自己想不出更好的解决方案)。然后,我通过对每种对应颜色的平方和求平方根(例如 int blue = round(sqrt((gxB * gxB) + (gyB * gyB)));)来找到新的蓝色、绿色和红色值。我将颜色值上限设置为 255(请参阅我的 cap 函数),然后将它们应用于图像中的每个对应颜色。但是,当我 运行 时,边缘不显示,而是显示非常明亮的图像,并且程序未通过 check50 中的任何检查。有人知道怎么回事吗?

这是错误信息(完整版here):

:( edges correctly filters middle pixel
    expected "210 150 60\n", not "255 242 207\n"
:( edges correctly filters pixel on edge
    expected "213 228 255\n", not "255 255 255\n"
:( edges correctly filters pixel in corner
    expected "76 117 255\n", not "76 134 255\n"
:( edges correctly filters 3x3 image
    expected "76 117 255\n21...", not "76 134 255\n25..."
:( edges correctly filters 4x4 image
    expected "76 117 255\n21...", not "76 134 255\n25..."

这是我的代码:

void edges(int height, int width, RGBTRIPLE image[height][width])
{
    int gxB;
    int gxG;
    int gxR;
    int gyB;
    int gyG;
    int gyR;

    // create a temporary array to store a duplicate of image.
    RGBTRIPLE temp[height][width];

    // save a new copy of image as temp per color.
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            temp[i][j] = image[i][j];
        }
    }

    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            if (i == 0 && j == 0)
            {
                // top left corner 
                gxB = (temp[i][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*0 + temp[i][j + 1].rgbtBlue*2 + temp[i + 1][j + 1].rgbtBlue*1);
                gxG = (temp[i][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*0 + temp[i][j + 1].rgbtGreen*2 + temp[i + 1][j + 1].rgbtGreen*1);
                gxR = (temp[i][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*0 + temp[i][j + 1].rgbtRed*2 + temp[i + 1][j + 1].rgbtRed*1);
                gyB = (temp[i][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*2 + temp[i][j + 1].rgbtBlue*2 + temp[i + 1][j + 1].rgbtBlue*1);
                gyG = (temp[i][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*2 + temp[i][j + 1].rgbtGreen*2 + temp[i + 1][j + 1].rgbtGreen*1);
                gyR = (temp[i][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*2 + temp[i][j + 1].rgbtRed*2 + temp[i + 1][j + 1].rgbtRed*1);
            }

            else if (i == 0 && j == (width - 1))
            {
                // top right corner 
                gxB = (temp[i][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*0 + temp[i][j - 1].rgbtBlue*-2 + temp[i + 1][j - 1].rgbtBlue*-1);
                gxG = (temp[i][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*0 + temp[i][j - 1].rgbtGreen*-2 + temp[i + 1][j - 1].rgbtGreen*-1);
                gxR = (temp[i][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*0 + temp[i][j - 1].rgbtRed*-2 + temp[i + 1][j - 1].rgbtRed*-1);
                gyB = (temp[i][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*2 + temp[i][j - 1].rgbtBlue*0 + temp[i + 1][j - 1].rgbtBlue*1 );
                gyG = (temp[i][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*2 + temp[i][j - 1].rgbtGreen*0 + temp[i + 1][j - 1].rgbtGreen*1 );
                gyR = (temp[i][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*2 + temp[i][j - 1].rgbtRed*0 + temp[i + 1][j - 1].rgbtRed*1 );
            }

            else if (i == 0 && (j != 0 || j != (width - 1)))
            {
                // top edge 
                gxB = (temp[i][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*0 + temp[i][j - 1].rgbtBlue*-2 + temp[i][j + 1].rgbtBlue*2 + temp[i + 1][j - 1].rgbtBlue*-1 + temp[i + 1][j + 1].rgbtBlue*1);
                gxG = (temp[i][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*0 + temp[i][j - 1].rgbtGreen*-2 + temp[i][j + 1].rgbtGreen*2 + temp[i + 1][j - 1].rgbtGreen*-1 + temp[i + 1][j + 1].rgbtGreen*1);
                gxR = (temp[i][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*0 + temp[i][j - 1].rgbtRed*-2 + temp[i][j + 1].rgbtRed*2 + temp[i + 1][j - 1].rgbtRed*-1 + temp[i + 1][j + 1].rgbtRed*1);
                gyB = (temp[i][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*2 + temp[i][j - 1].rgbtBlue*0 + temp[i][j + 1].rgbtBlue*2 + temp[i + 1][j - 1].rgbtBlue*1 + temp[i + 1][j + 1].rgbtBlue*1);
                gyG = (temp[i][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*2 + temp[i][j - 1].rgbtGreen*0 + temp[i][j + 1].rgbtGreen*2 + temp[i + 1][j - 1].rgbtGreen*1 + temp[i + 1][j + 1].rgbtGreen*1);
                gyR = (temp[i][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*2 + temp[i][j - 1].rgbtRed*0 + temp[i][j + 1].rgbtRed*2 + temp[i + 1][j - 1].rgbtRed*1 + temp[i + 1][j + 1].rgbtRed*1);
            }

            else if (i == (height - 1) && j == 0)
            {
                // bottom left corner 
                gxB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*0 + temp[i][j + 1].rgbtBlue*2 + temp[i - 1][j + 1].rgbtBlue*1);
                gxG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*0 + temp[i][j + 1].rgbtGreen*2 + temp[i - 1][j + 1].rgbtGreen*1);
                gxR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*0 + temp[i][j + 1].rgbtRed*2 + temp[i - 1][j + 1].rgbtRed*1);
                gyB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*-2 + temp[i][j + 1].rgbtBlue*2 + temp[i - 1][j + 1].rgbtBlue*0);
                gyG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*-2 + temp[i][j + 1].rgbtGreen*2 + temp[i - 1][j + 1].rgbtGreen*0);
                gyR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*-2 + temp[i][j + 1].rgbtRed*2 + temp[i - 1][j + 1].rgbtRed*0);
            }

            else if (i == (height - 1) && j == (width - 1))
            {
                // bottom right corner 
                gxB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*0 + temp[i][j - 1].rgbtBlue*-2 + temp[i-1][j - 1].rgbtBlue*-1);
                gxG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*0 + temp[i][j - 1].rgbtGreen*-2 + temp[i-1][j - 1].rgbtGreen*-1);
                gxR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*0 + temp[i][j - 1].rgbtRed*-2 + temp[i-1][j - 1].rgbtRed*-1);
                gyB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*-2 + temp[i][j - 1].rgbtBlue*0 + temp[i-1][j - 1].rgbtBlue*-1);
                gyG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*-2 + temp[i][j - 1].rgbtGreen*0 + temp[i-1][j - 1].rgbtGreen*-1);
                gyR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*-2 + temp[i][j - 1].rgbtRed*0 + temp[i-1][j - 1].rgbtRed*-1);
            }

            else if (i == (height - 1) && (j != 0 || j != (width - 1)))
            {
                // bottom edge 
                gxB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*0 + temp[i][j - 1].rgbtBlue*-2 + temp[i][j + 1].rgbtBlue*2 + temp[i - 1][j + 1].rgbtBlue*1 + temp[i-1][j - 1].rgbtBlue*-1);
                gxG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*0 + temp[i][j - 1].rgbtGreen*-2 + temp[i][j + 1].rgbtGreen*2 + temp[i - 1][j + 1].rgbtGreen*1 + temp[i-1][j - 1].rgbtGreen*-1);
                gxR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*0 + temp[i][j - 1].rgbtRed*-2 + temp[i][j + 1].rgbtRed*2 + temp[i - 1][j + 1].rgbtRed*1 + temp[i-1][j - 1].rgbtRed*-1);
                gyB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*-2 + temp[i][j - 1].rgbtBlue*0 + temp[i][j + 1].rgbtBlue*2 + temp[i - 1][j + 1].rgbtBlue*0 + temp[i-1][j - 1].rgbtBlue*-1);
                gyG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*-2 + temp[i][j - 1].rgbtGreen*0 + temp[i][j + 1].rgbtGreen*2 + temp[i - 1][j + 1].rgbtGreen*0 + temp[i-1][j - 1].rgbtGreen*-1);
                gyR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*-2 + temp[i][j - 1].rgbtRed*0 + temp[i][j + 1].rgbtRed*2 + temp[i - 1][j + 1].rgbtRed*0 + temp[i-1][j - 1].rgbtRed*-1);
            }

            else if (j == 0 && (i != 0 || i != (height - 1)))
            {
                // left edge 
                gxB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*0 + temp[i][j + 1].rgbtBlue*2 + temp[i - 1][j + 1].rgbtBlue*1 + temp[i + 1][j + 1].rgbtBlue*1);
                gxG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*0 + temp[i][j + 1].rgbtGreen*2 + temp[i - 1][j + 1].rgbtGreen*1 + temp[i + 1][j + 1].rgbtGreen*1);
                gxR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*0 + temp[i][j + 1].rgbtRed*2 + temp[i - 1][j + 1].rgbtRed*1 + temp[i + 1][j + 1].rgbtRed*1);
                gyB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*-2 + temp[i + 1][j].rgbtBlue*2 + temp[i][j + 1].rgbtBlue*2 + temp[i - 1][j + 1].rgbtBlue*0 + temp[i + 1][j + 1].rgbtBlue*1);
                gyG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*-2 + temp[i + 1][j].rgbtGreen*2 + temp[i][j + 1].rgbtGreen*2 + temp[i - 1][j + 1].rgbtGreen*0 + temp[i + 1][j + 1].rgbtGreen*1);
                gyR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*-2 + temp[i + 1][j].rgbtRed*2 + temp[i][j + 1].rgbtRed*2 + temp[i - 1][j + 1].rgbtRed*0 + temp[i + 1][j + 1].rgbtRed*1);
            }

            else if (j == (width - 1) && (i != 0 || i != (height - 1)))
            {
                // right edge 
                gxB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*0 + temp[i][j - 1].rgbtBlue*-2 + temp[i-1][j - 1].rgbtBlue*-1 + temp[i + 1][j - 1].rgbtBlue*-1);
                gxG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*0 + temp[i][j - 1].rgbtGreen*-2 + temp[i-1][j - 1].rgbtGreen*-1 + temp[i + 1][j - 1].rgbtGreen*-1);
                gxR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*0 + temp[i][j - 1].rgbtRed*-2 + temp[i-1][j - 1].rgbtRed*-1 + temp[i + 1][j - 1].rgbtRed*-1);
                gyB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*-2 + temp[i + 1][j].rgbtBlue*2 + temp[i-1][j - 1].rgbtBlue*-1 + temp[i + 1][j - 1].rgbtBlue*1);
                gyG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*-2 + temp[i + 1][j].rgbtGreen*2 + temp[i-1][j - 1].rgbtGreen*-1 + temp[i + 1][j - 1].rgbtGreen*1);
                gyR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*-2 + temp[i + 1][j].rgbtRed*2 + temp[i-1][j - 1].rgbtRed*-1 + temp[i + 1][j - 1].rgbtRed*1);
            }

            else
            {
                // any other pixel
                gxB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*0 + temp[i][j - 1].rgbtBlue*-2 + temp[i][j + 1].rgbtBlue*2 + temp[i - 1][j + 1].rgbtBlue*1 + temp[i-1][j - 1].rgbtBlue*-1 + temp[i + 1][j - 1].rgbtBlue*-1 + temp[i + 1][j + 1].rgbtBlue*1);
                gxG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*0 + temp[i][j - 1].rgbtGreen*-2 + temp[i][j + 1].rgbtGreen*2 + temp[i - 1][j + 1].rgbtGreen*1 + temp[i-1][j - 1].rgbtGreen*-1 + temp[i + 1][j - 1].rgbtGreen*-1 + temp[i + 1][j + 1].rgbtGreen*1);
                gxR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*0 + temp[i][j - 1].rgbtRed*-2 + temp[i][j + 1].rgbtRed*2 + temp[i - 1][j + 1].rgbtRed*1 + temp[i-1][j - 1].rgbtRed*-1 + temp[i + 1][j - 1].rgbtRed*-1 + temp[i + 1][j + 1].rgbtRed*1);
                gyB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*-2 + temp[i + 1][j].rgbtBlue*2 + temp[i][j - 1].rgbtBlue*0 + temp[i][j + 1].rgbtBlue*2 + temp[i - 1][j + 1].rgbtBlue*0 + temp[i-1][j - 1].rgbtBlue*-1 + temp[i + 1][j - 1].rgbtBlue*1 + temp[i + 1][j + 1].rgbtBlue*1);
                gyG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*-2 + temp[i + 1][j].rgbtGreen*2 + temp[i][j - 1].rgbtGreen*0 + temp[i][j + 1].rgbtGreen*2 + temp[i - 1][j + 1].rgbtGreen*0 + temp[i-1][j - 1].rgbtGreen*-1 + temp[i + 1][j - 1].rgbtGreen*1 + temp[i + 1][j + 1].rgbtGreen*1);
                gyR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*-2 + temp[i + 1][j].rgbtRed*2 + temp[i][j - 1].rgbtRed*0 + temp[i][j + 1].rgbtRed*2 + temp[i - 1][j + 1].rgbtRed*0 + temp[i-1][j - 1].rgbtRed*-1 + temp[i + 1][j - 1].rgbtRed*1 + temp[i + 1][j + 1].rgbtRed*1);
            }

            int blue = round(sqrt((gxB * gxB) + (gyB * gyB)));
            int green = round(sqrt((gxG * gxG) + (gyG * gyG)));
            int red = round(sqrt((gxR * gxR) + (gyR * gyR)));

            image[i][j].rgbtBlue = cap(blue);
            image[i][j].rgbtGreen = cap(green);
            image[i][j].rgbtRed = cap(red);
        }
    }
    return;
}

最后,这是我的 cap 函数:

// cap function retrieved from this video: https://youtu.be/VbG8tH-Vbko
int cap(int value)
{
    return value < 255 ? value: 255;
}

这是原图:

这是我处理后的图像:

编辑: 在 Solancia 的回答之后,我将 temp[i - 1][j + 1].rgbtRed*0 的所有实例更改为 temp[i - 1][j + 1].rgbtRed*-1 gyRgyB,和 gyG。此外,我意识到 gyRgyBgyG 的所有 temp[i][j + 1].rgbtRed*2 实例都应该是 temp[i][j + 1].rgbtRed*0。更改这些允许我的代码正常运行并通过 check50。我意识到我的代码很糟糕,应该拆分成单独的函数,但是我已经写好了,直到看到它不起作用后才想到拆分成单独的函数。不过下次我会记住这一点,所以谢谢你的帮助。

好的,Mateen Ulhaq 上面所说的需要提高可读性的内容仍然有效。但是,作为快速修复,在您的 else 块中,您输入:

temp[i - 1][j + 1].rgbtRed*0

gyR。这也适用于 rgbtGreen 和 rgbtBlue。

应该是:

temp[i - 1][j + 1].rgbtRed*-1

更重要的是,您应该尝试更改代码或将代码放在其他区域,因为这样人们很难阅读。因此可能会遗漏其他错误。