CS50 Pset4 Edges代码问题:原黑屏现输出大面积白色图像求排查
CS50 Pset4 边缘检测:大面积白屏问题修复
你的代码现在输出大面积白色,核心问题是卷积计算时误用了实时修改后的图像数据,同时存在临时数组的逻辑混乱,以下是具体问题和修复方案:
核心问题分析
实时修改原图像导致计算错误
在edges函数中,你计算完一个像素后立刻把结果赋值回image[row][column],后续像素的卷积计算会用到已经修改过的像素值,而非原始图像数据。这会导致Gx/Gy的求和结果异常放大,最终大部分像素的RGB值被截断到255(白色)。临时数组逻辑冗余且错误
你创建了temporary数组,但每次循环仅复制当前像素,没有保存完整的原始图像;同时determineEdges中写入temp数组的操作完全多余,反而增加了逻辑混乱。
修复后的代码
// Detect edges void edges(int height, int width, RGBTRIPLE image[height][width]) { // 先保存完整的原始图像到临时数组 RGBTRIPLE original[height][width]; for (int row = 0; row < height; row++) { for (int column = 0; column < width; column++) { original[row][column] = image[row][column]; } } RGBTRIPLE pixel_with_edges[height][width]; // 基于原始图像计算所有边缘像素 for (int row = 0; row < height; row++) { for (int column = 0; column < width; column++) { pixel_with_edges[row][column] = determineEdges(row, column, height, width, original); } } // 一次性将结果写回原图像 for (int row = 0; row < height; row++) { for (int column = 0; column < width; column++) { image[row][column] = pixel_with_edges[row][column]; } } } // i and j are the current pixels RGBTRIPLE determineEdges(int i, int j, int height, int width, RGBTRIPLE original[height][width]) { float sum_surround_redX = 0, sum_surround_greenX = 0, sum_surround_blueX = 0; float sum_surround_redY = 0, sum_surround_greenY = 0, sum_surround_blueY = 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} }; // 遍历3x3邻域 for (int row_idx = i - 1; row_idx <= i + 1; row_idx++) { for (int column_idx = j - 1; column_idx <= j + 1; column_idx++) { int red = 0, green = 0, blue = 0; // 边界处理:越界像素视为0(黑色) if (row_idx >= 0 && row_idx < height && column_idx >= 0 && column_idx < width) { red = original[row_idx][column_idx].rgbtRed; green = original[row_idx][column_idx].rgbtGreen; blue = original[row_idx][column_idx].rgbtBlue; } // 计算Gx和Gy的加权和 int gx_weight = Gx[row_idx - i + 1][column_idx - j + 1]; sum_surround_redX += gx_weight * red; sum_surround_greenX += gx_weight * green; sum_surround_blueX += gx_weight * blue; int gy_weight = Gy[row_idx - i + 1][column_idx - j + 1]; sum_surround_redY += gy_weight * red; sum_surround_greenY += gy_weight * green; sum_surround_blueY += gy_weight * blue; } } // 计算边缘后的RGB值 float newRed = round(sqrt(pow(sum_surround_redX, 2) + pow(sum_surround_redY, 2))); float newGreen = round(sqrt(pow(sum_surround_greenX, 2) + pow(sum_surround_greenY, 2))); float newBlue = round(sqrt(pow(sum_surround_blueX, 2) + pow(sum_surround_blueY, 2))); // 截断到0-255范围 if (newRed > 255) newRed = 255; if (newGreen > 255) newGreen = 255; if (newBlue > 255) newBlue = 255; // 构造返回的像素 RGBTRIPLE result; result.rgbtRed = (BYTE)newRed; result.rgbtGreen = (BYTE)newGreen; result.rgbtBlue = (BYTE)newBlue; return result; }
关键修改点
- 保存完整原始图像:新增
original数组复制整个原始图像,确保所有卷积计算都基于未修改的原始数据。 - 分离计算与写入:先完成所有像素的边缘计算,再一次性将结果写回原图像,避免实时修改导致的连锁错误。
- 简化临时数组逻辑:移除冗余的
temporary和函数中的temp参数,直接在determineEdges中构造返回结果,逻辑更清晰。 - 明确边界处理:将越界像素的RGB值显式设为0,符合边缘检测卷积的标准处理方式,逻辑更直观。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

