我是编程新手,目前正在学习 CS50x 课程。我最近遇到了 PSET 4 - Filter(更多),其中我必须用 C 语言编写一个程序来对 BMP 图片执行一些操作。 在分享这个问题之前,我想指出我确实遵循学术诚实的准则,并且我自己解决了这个问题。它已提交并计算(我不会分享完整的解决方案,仅分享每个步骤的前几行)。话虽这么说,我只是想要一些帮助来理解为什么我的更改修复了我的代码,因为我花了几天时间却无法给出解释。我相信这对我的学习过程很重要。
挑战是使用 Sorbel 算子来识别和过滤图像内的边缘。复制图像后(这样我就不会在像素上创建多米诺骨牌效应),我创建了一个 2D 数组来存储内核并初始化了一些变量:
double gxRed = 0, gxBlue = 0, gxGreen = 0;
double gyRed = 0, gyBlue = 0, gyGreen = 0;
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}};
然后我通过取消 Gx/y 的值来解决边缘情况:
if (i - 1 < 0)
{
gx[0][0] = 0, gx[0][1] = 0, gx[0][2] = 0;
gy[0][0] = 0, gy[0][1] = 0, gy[0][2] = 0;
}
接下来,我根据内核数组计算每个颜色通道:
gxRed += (imageCopy[i - 1][j - 1].rgbtRed * gx[0][0]) + (imageCopy[i - 1][j].rgbtRed * gx[0][1]) +
(imageCopy[i - 1][j + 1].rgbtRed * gx[0][2]);
gxRed += (imageCopy[i][j - 1].rgbtRed * gx[1][0]) + (imageCopy[i][j].rgbtRed * gx[1][1]) +
(imageCopy[i][j + 1].rgbtRed * gx[1][2]);
gxRed += (imageCopy[i + 1][j - 1].rgbtRed * gx[2][0]) + (imageCopy[i + 1][j].rgbtRed * gx[2][1]) +
(imageCopy[i + 1][j + 1].rgbtRed * gx[2][2]);
计算幅度并应用于原始图片:
image[i][j].rgbtRed = round(sqrt((gxRed * gxRed) + (gyRed * gyRed)));
考虑 255 范围并应用修正(如果有):
if (image[i][j].rgbtRed > 255)
{
image[i][j].rgbtRed = 255;
}
一切顺利,生成的图像看起来不错,正如我所预期的那样。然而,在运行课程检查时,绿色通道出现了一些问题,如下所示:
使用示例 3x3 图像进行测试
第一行:(0, 10, 25), (0, 10, 30), (40, 60, 80)
第二行:(20,30,90),(30,40,100),(80,70,90)
第三行:(20,20,40),(30,10,30),(50,40,10)
预期输出:
76 117 255
213 228 255
192 190 255
114 102 255
210 150 60
103 108 255
114 117 255
200 197 255
210 190 255
实际产量:
76 117 66
213 228 140
192 190 66
114 102 6
210 150 60
103 108 39
114 117 66
200 197 129
210 190 66
int tempGreen = round(sqrt((gxGreen * gxGreen) + (gyGreen * gyGreen)));
int tempRed = round(sqrt((gxRed * gxRed) + (gyRed * gyRed)));
int tempBlue = round(sqrt((gxBlue * gxBlue) + (gyBlue * gyBlue)));
if (tempGreen > 255)
{
tempGreen = 255;
}
if (tempRed > 255)
{
tempRed = 255;
}
if (tempBlue > 255)
{
tempBlue = 255;
}
image[i][j].rgbtGreen = tempGreen;
image[i][j].rgbtRed = tempRed;
image[i][j].rgbtBlue = tempBlue;
这是相同的代码,我只是添加了变量,问题就解决了。我通过了所有检查。为什么?如果这是问题所在,那么蓝色和红色不应该也会发生这种情况吗?这一直困扰着我,所以我决定在这里分享。我对这篇超长的文章表示歉意,这是我的第一篇文章,所以也欢迎任何关于如何更好地在这里写作的建议。
提前非常感谢!
这是相同的代码,我只是添加了变量,问题就解决了。
不。这不是同一个代码。
tempGreen
是 int
,而 .rgbtGreen
是 uint8_t
。
(我知道这一点是因为我读过很多 CS50 问题,但通常您有责任提供所有必需的信息。所有定义等)
因此,
if (image[i][j].rgbtRed > 255)
永远不可能为真,因为任何大于255
的值在将其分配给该变量时都会溢出。
在溢出或回绕已经发生之后,您无法阻止它。
您的固定代码会在将其截断以适合
uint8_t
之前检查较大的值。