cs50 pset4 过滤器 "edges"

cs50 pset4 filter "edges"

当我通过我的 edges 代码 运行 一张照片时,返回的图像全是白色,除了底部的三行像素,看起来类似于静态彩虹电视。我试过调试我的代码,但我还是想不通:

void edges(int height, int width, RGBTRIPLE image[height][width])
{
    int gx[3][3] = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
    int gy[3][3] = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}};
    int redx = 0;
    int greenx = 0;
    int bluex = 0;
    int redy = 0;
    int greeny = 0;
    int bluey = 0;
    int finalred = 0;
    int finalgreen = 0;
    int finalblue = 0;
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            for (int k = i - 1; k <= i + 1 && k < height && k >= 0; k++)
            {
                for (int m = j - 1; m <= j + 1 && m < width && m >= 0; m++)
                {
                    if (k < i)
                    {
                        if (m < j)
                        {
                            redx += image[k][m].rgbtRed * gx[0][0];
                            greenx += image[k][m].rgbtGreen * gx[0][0];
                            bluex += image[k][m].rgbtBlue * gx[0][0];
                            redy += image[k][m].rgbtRed * gy[0][0];
                            greeny += image[k][m].rgbtGreen * gy[0][0];
                            bluey += image[k][m].rgbtBlue * gy[0][0];
                            // gx[?][0]
                        }
                        else if (m > j)
                        {
                            redx += image[k][m].rgbtRed * gx[0][2];
                            greenx += image[k][m].rgbtGreen * gx[0][2];
                            bluex += image[k][m].rgbtBlue * gx[0][2];
                            redy += image[k][m].rgbtRed * gy[0][2];
                            greeny += image[k][m].rgbtGreen * gy[0][2];
                            bluey += image[k][m].rgbtBlue * gy[0][2];
                            // gx[?][2]
                        }
                        else
                        {
                            redx += image[k][m].rgbtRed * gx[0][1];
                            greenx += image[k][m].rgbtGreen * gx[0][1];
                            bluex += image[k][m].rgbtBlue * gx[0][1];
                            redy += image[k][m].rgbtRed * gy[0][1];
                            greeny += image[k][m].rgbtGreen * gy[0][1];
                            bluey += image[k][m].rgbtBlue * gy[0][1];
                            // gx[?][1]
                        }
                        // gx[0][?]
                    }
                    else if (k > i)
                    {
                        if (m < j)
                        {
                            redx += image[k][m].rgbtRed * gx[2][0];
                            greenx += image[k][m].rgbtGreen * gx[2][0];
                            bluex += image[k][m].rgbtBlue * gx[1][0];
                            redy += image[k][m].rgbtRed * gy[2][0];
                            greeny += image[k][m].rgbtGreen * gy[2][0];
                            bluey += image[k][m].rgbtBlue * gy[2][0];
                            // gx[?][0]
                        }
                        else if (m > j)
                        {
                            redx += image[k][m].rgbtRed * gx[2][2];
                            greenx += image[k][m].rgbtGreen * gx[2][2];
                            bluex += image[k][m].rgbtBlue * gx[2][2];
                            redy += image[k][m].rgbtRed * gy[2][2];
                            greeny += image[k][m].rgbtGreen * gy[2][2];
                            bluey += image[k][m].rgbtBlue * gy[2][2];
                            // gx[?][2]
                        }
                        else
                        {
                            redx += image[k][m].rgbtRed * gx[2][1];
                            greenx += image[k][m].rgbtGreen * gx[2][1];
                            bluex += image[k][m].rgbtBlue * gx[2][1];
                            redy += image[k][m].rgbtRed * gy[2][1];
                            greeny += image[k][m].rgbtGreen * gy[2][1];
                            bluey += image[k][m].rgbtBlue * gy[2][1];
                            // gx[?][1]
                        }
                        // gx[2][?]
                    }
                    else
                    {
                        if (m < j)
                        {
                            redx += image[k][m].rgbtRed * gx[1][0];
                            greenx += image[k][m].rgbtGreen * gx[1][0];
                            bluex += image[k][m].rgbtBlue * gx[1][0];
                            redy += image[k][m].rgbtRed * gy[1][0];
                            greeny += image[k][m].rgbtGreen * gy[1][0];
                            bluey += image[k][m].rgbtBlue * gy[1][0];
                            // gx[?][0]
                        }
                        else if (m > j)
                        {
                            redx += image[k][m].rgbtRed * gx[1][2];
                            greenx += image[k][m].rgbtGreen * gx[1][2];
                            bluex += image[k][m].rgbtBlue * gx[1][2];
                            redy += image[k][m].rgbtRed * gy[1][2];
                            greeny += image[k][m].rgbtGreen * gy[1][2];
                            bluey += image[k][m].rgbtBlue * gy[1][2];
                            // gx[?][2]
                        }
                        else
                        {
                            redx += image[k][m].rgbtRed * gx[1][1];
                            greenx += image[k][m].rgbtGreen * gx[1][1];
                            bluex += image[k][m].rgbtBlue * gx[1][1];
                            redy += image[k][m].rgbtRed * gy[1][1];
                            greeny += image[k][m].rgbtGreen * gy[1][1];
                            bluey += image[k][m].rgbtBlue * gy[1][1];
                            // gx[?][1]
                        }
                        // gx[1][?]
                    }
                }
            }
            finalred = (redx)^2 + (redy)^2;
            finalgreen = (greenx)^2 + (greeny)^2;
            finalblue = (bluex)^2 + (bluey)^2;
            if (finalred > 255)
            {
                finalred = 255;
            }
            if (finalgreen > 255)
            {
                finalgreen = 255;
            }
            if (finalblue > 255)
            {
                finalblue = 255;
            }
            image[i][j].rgbtRed = finalred;
            image[i][j].rgbtGreen = finalgreen;
            image[i][j].rgbtBlue = finalblue;
        }
    }
    return;
}

初始化变量

这些初始化:

    int redx = 0;
    int greenx = 0;
    int bluex = 0;
    int redy = 0;
    int greeny = 0;
    int bluey = 0;

出现在ijfor语句之前,但是这些变量为每个像素累加和,所以必须为每个像素初始化它们。那是在 j 上的 for 声明中以及 km.

上的 for 声明之前

(由于在评论中指出了这一点,问题中的代码已被编辑为在更新每个像素后将零分配给这些变量。这可行,但这是一个糟糕的解决方案。只需移动定义和初始化外部两个 for 循环内的变量。)

不正确的循环条件

这条语句会失败:

for (int k = i - 1; k <= i + 1 && k < height && k >= 0; k++)

考虑当 i 为 0 时会发生什么。然后 int k = i - 1k 初始化为 −1。那么 k >= 0 为假,所以测试 k <= i + 1 && k < height && k >= 0 为假,所以循环体永远不会执行,并且 i=0 的行中的像素的 none已更新。

您需要重新考虑代码的设计方式。这显然是一种处理边角的尝试,理论上涉及对阵列外像素的计算,但还有其他解决方案。这是这个问题的重点,所以考虑并实施两个或更多解决方案将是一个很好的练习。

运算符不正确

^ 用于在 (redx)^2 中尝试求幂。在 C 语言中,^ 是异或运算符。在这种情况下,要对一个数求平方,只需将其自身相乘即可,如 redx*redx。 C中有求幂运算符,但它是用于floating-point算术运算的,所以不适合做这道题,你会在另一课学习。

图像过早更新

这些行:

image[i][j].rgbtRed = finalred;
image[i][j].rgbtGreen = finalgreen;
image[i][j].rgbtBlue = finalblue;

ij 的内部循环,因此它们会在处理每个像素时更新图像。这意味着尚未更新的像素将使用为先前更新的像素分配的新值。这是不正确的;计算新像素值时应使用原始 pre-updated 值。对此的解决方案需要使用单独的缓冲区来临时保存新值。 (一个简单的解决方案是使用一个完整的单独数组来保存新值,但还有更多 space-efficient 解决方案。)

计算未四舍五入

此代码取平方根并将其截断为整数:

finalred = sqrt((redx)^2 + (redy)^2);

但是,problem specification 表示“并且由于通道值只能采用 0 到 255 之间的整数值,因此请确保将结果值四舍五入为最接近的整数并且

代码过多

多次出现这样的代码:

if (k < i)
                    {
                        if (m < j)
                        {
                            redx += image[k][m].rgbtRed * gx[0][0];
                            greenx += image[k][m].rgbtGreen * gx[0][0];
                            bluex += image[k][m].rgbtBlue * gx[0][0];
                            redy += image[k][m].rgbtRed * gy[0][0];
                            greeny += image[k][m].rgbtGreen * gy[0][0];
                            bluey += image[k][m].rgbtBlue * gy[0][0];
                            // gx[?][0]
                        }

根据这些循环的结构,k只能等于i-1ii+1。因此,不需要使用if语句来select索引数组的012;我们可以简单地计算一下,m也类似,然后一组代码就可以满足所有情况:

redx   += image[k][m].rgbtRed   * gx[k-(i-1)][m-(j-1)];
greenx += image[k][m].rgbtGreen * gx[k-(i-1)][m-(j-1)];
bluex  += image[k][m].rgbtBlue  * gx[k-(i-1)][m-(j-1)];
redy   += image[k][m].rgbtRed   * gy[k-(i-1)][m-(j-1)];
greeny += image[k][m].rgbtGreen * gy[k-(i-1)][m-(j-1)];
bluey  += image[k][m].rgbtBlue  * gy[k-(i-1)][m-(j-1)];

请注意,处理边角的问题仍然存在,如上所述。

不必要的初始化

这些初始化和重置是不必要的:

    int finalred = 0;
    int finalgreen = 0;
    int finalblue = 0;
            finalred = 0;
            finalgreen = 0;
            finalblue = 0;

相反,只需在需要的地方定义这些变量即可;变化:

            finalred = sqrt((redx)^2 + (redy)^2);
            finalgreen = sqrt((greenx)^2 + (greeny)^2);
            finalblue = sqrt((bluex)^2 + (bluey)^2);

至:

            int finalred = sqrt((redx)^2 + (redy)^2);
            int finalgreen = sqrt((greenx)^2 + (greeny)^2);
            int finalblue = sqrt((bluex)^2 + (bluey)^2);

仅在需要变量的地方定义变量会限制它们的范围,从而限制使用它们出错的机会。这适用于上面的 redx 和相关变量:通过在 per-pixel 代码中定义和初始化它们,它们的使用仅限于计算单个像素,因此让总和累加多个像素是错误的本来不可能做的。