CS50 filter-more edges函数check50检测不通过,求错误排查
CS50 Problem Set 4 Filter-More:Edges函数无法通过check50检测的问题
我正在完成CS50的Problem Set 4中filter-more项目,除edges函数外其余功能均正常,但该函数无法通过check50检测。ChatGPT判定我的代码正确,想请教代码中存在什么问题?
我的Edges函数代码
// Detect edges void edges(int height, int width, RGBTRIPLE image[height][width]) { // Copying RGBTRIPLE copy[height][width]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { copy[i][j] = image[i][j]; } } 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}}; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int GxsumRed = 0; int GxsumGreen = 0; int GxsumBlue = 0; int GysumRed = 0; int GysumGreen = 0; int GysumBlue = 0; // Forming 3x3 grid int m = 0; // For Gx and Gy for (int k = i - 1; k < i + 2; k++) { if (k < 0) { continue; } // if k > height then break if (k >= height) { break; } int n = 0; // For Gx and Gy for (int l = j - 1; l < j + 2; l++) { if (l < 0) { continue; } if (l >= width) { break; } GxsumRed += Gx[m][n] * copy[k][l].rgbtRed; GxsumGreen += Gx[m][n] * copy[k][l].rgbtGreen; GxsumBlue += Gx[m][n] * copy[k][l].rgbtBlue; GysumRed += Gy[m][n] * copy[k][l].rgbtRed; GysumGreen += Gy[m][n] * copy[k][l].rgbtGreen; GysumBlue += Gy[m][n] * copy[k][l].rgbtBlue; n++; } m++; } int newRed = round(sqrt((GxsumRed * GxsumRed) + (GysumRed * GysumRed))); int newGreen = round(sqrt((GxsumGreen * GxsumGreen) + (GysumGreen * GysumGreen))); int newBlue = round(sqrt((GxsumBlue * GxsumBlue) + (GysumBlue * GysumBlue))); // Caping to 255 if (newRed > 255) { newRed = 255; } if (newGreen > 255) { newGreen = 255; } if (newBlue > 255) { newBlue = 255; } image[i][j].rgbtRed = newRed; image[i][j].rgbtGreen = newGreen; image[i][j].rgbtBlue = newBlue; } } return; }
check50检测结果

问题分析
你的代码核心错误在于边界处理时的权重矩阵索引错位:
- 当遍历到超出图像范围的
k(行)或l(列)时,你用continue跳过了该位置的计算,但没有同步递增m或n(Gx/Gy矩阵的索引)。 - 例如,处理图像第一行(
i=0)时,k=-1触发continue,此时m不会递增,导致后续k=0(原图像第一行)对应的Gx/Gy索引是m=0,而正确索引应为m=1(对应3x3窗口的中间行)。 - 同理,列方向的
l<0会导致n不递增,后续列的权重对应全部错位,最终计算出的Gx、Gy求和值完全错误。
正确逻辑:遍历3x3窗口的所有9个相对位置(行偏移和列偏移从-1到1),不管位置是否在图像范围内,都对应Gx/Gy矩阵的正确索引。若位置超出范围,用0作为该位置的像素值参与计算,而非跳过整个权重位置。
修正后的代码示例
// Detect edges void edges(int height, int width, RGBTRIPLE image[height][width]) { RGBTRIPLE copy[height][width]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { copy[i][j] = image[i][j]; } } 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}}; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int GxsumRed = 0, GxsumGreen = 0, GxsumBlue = 0; int GysumRed = 0, GysumGreen = 0, GysumBlue = 0; // 遍历3x3窗口的相对偏移量 for (int dx = -1; dx <= 1; dx++) { for (int dy = -1; dy <= 1; dy++) { int k = i + dx; int l = j + dy; // 计算Gx/Gy的索引 int m = dx + 1; int n = dy + 1; int red = 0, green = 0, blue = 0; if (k >= 0 && k < height && l >= 0 && l < width) { red = copy[k][l].rgbtRed; green = copy[k][l].rgbtGreen; blue = copy[k][l].rgbtBlue; } GxsumRed += Gx[m][n] * red; GxsumGreen += Gx[m][n] * green; GxsumBlue += Gx[m][n] * blue; GysumRed += Gy[m][n] * red; GysumGreen += Gy[m][n] * green; GysumBlue += Gy[m][n] * blue; } } // 转换为double避免整数溢出 int newRed = round(sqrt((double)GxsumRed * GxsumRed + (double)GysumRed * GysumRed)); int newGreen = round(sqrt((double)GxsumGreen * GxsumGreen + (double)GysumGreen * GysumGreen)); int newBlue = round(sqrt((double)GxsumBlue * GxsumBlue + (double)GysumBlue * GysumBlue)); // 限制值在0-255之间 image[i][j].rgbtRed = (newRed > 255) ? 255 : newRed; image[i][j].rgbtGreen = (newGreen > 255) ? 255 : newGreen; image[i][j].rgbtBlue = (newBlue > 255) ? 255 : newBlue; } } return; }
额外注意:计算平方根时将整数转换为double类型,可避免整数溢出导致的计算错误,这也是check50可能检测到的问题点之一。
内容的提问来源于stack exchange,提问作者GreenIsLearningProgramming
相关产品推荐
相关产品推荐

