cs50 pset4过滤器“边缘”

时间:2020-08-04 01:58:06

标签: c filter cs50 edge-detection

当我通过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;
}

1 个答案:

答案 0 :(得分:1)

初始化变量

这些初始化:

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

出现在fori的{​​{1}}语句之前,但是这些变量累积每个像素的总和,因此必须为每个像素初始化它们。在j的{​​{1}}语句之内,在forj的{​​{1}}语句之前。

(由于注释中已指出这一点,因此已对问题中的代码进行了编辑,以在更新每个像素后为这些变量分配零。这是可行的,但这是一个较差的解决方案。只需移动该变量的定义和初始化即可。外部两个for循环中的变量。)

错误的循环条件

此语句将失败:

k

考虑当m为0时会发生什么。然后forfor (int k = i - 1; k <= i + 1 && k < height && k >= 0; k++) 初始化为-1。然后i为假,因此测试int k = i - 1为假,因此永远不会执行循环的主体,并且k = 0的行中的所有像素均不更新。 / p>

您需要重新考虑代码的设计方式。显然,这是对边缘和拐角的尝试,从概念上讲,这涉及使用数组外部像素进行计算,但是还有其他解决方案。这是此问题的重点,因此,考虑并实施两个或更多个解决方案将是一个很好的练习。

运算符不正确

k >= 0用于尝试k <= i + 1 && k < height && k >= 0中的取幂。在C中,i是XOR运算符。在这种情况下,要平方一个数字,只需将自己乘以^。 C中有一个幂运算符,但是它用于浮点运算,因此不适合此问题,您将在另一课中学习它。

过早的图像更新

这些行:

(redx)^2

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

计算未四舍五入

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

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

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

代码过多

这样的代码出现多次:

i

根据这些循环的结构,j只能等于finalred = sqrt((redx)^2 + (redy)^2); 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-1语句来选择数组的索引ii+1if;我们可以简单地对其进行计算,并且对于0类似地进行计算,然后对于所有情况,一组代码就足够了:

1

请注意,上面仍然存在处理边缘和拐角的问题。

不必要的初始化

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

2
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; 和相关变量:通过在每个像素代码中定义和初始化它们,它们的使用仅限于单个像素的计算,因此让总和累加到多个像素上的错误将产生无法制造。