CS50 PSET4 Filter-less:运行Blur函数出现黑屏问题求助
CS50 PSET4 Filter-less 方框模糊函数黑屏问题排查
问题说明
在完成CS50第4周作业PSET4的Filter-less任务时,实现方框模糊(box blur)函数后出现图像黑屏的现象,以下是问题代码及错误分析:
问题代码
// Blur image void blur(int height, int width, RGBTRIPLE image[height][width]) { // initialize average variables int averageRed = 0; int averageBlue = 0; int averageGreen = 0; float counter = 0; RGBTRIPLE copy[height][width]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { // create copy of image[i][j] copy[i][j]=image[i][j]; // nest for loops to integrate 9 pixels into algorithm, creates box around pixel for (int y = i - 1; y <= i +1; y++) { for (int x = j - 1; x <= j+1; x++) { // exclude out of bounds pixels if ((y >= 0) &&(y < height) && (x >= 0) && (x < width)) { // find average of middle pixels in contact with each other, round averageRed = copy[y][x].rgbtRed; averageBlue = copy[y][x].rgbtBlue; averageGreen = copy[y][x].rgbtGreen; // ++ sum to average by counter ++; // find average of middle pixels in contact with each other copy[i][j].rgbtRed = (int)round(averageRed/counter); copy[i][j].rgbtBlue = (int)round(averageBlue/counter); copy[i][j].rgbtGreen = (int)round(averageGreen/counter); } // reset average values to 0 averageRed = 0; averageBlue = 0; averageGreen = 0; } } //copy image[i][j] into copy[i][j] (for loops) image[i][j] = copy[i][j]; } } return; }
错误分析
- 累加逻辑错误:当前代码中
averageRed等变量直接被赋值为单个像素的RGB值,而非累加所有有效邻域像素的总和。这样计算出的"平均值"只是单个像素值除以计数器,结果会远低于正常像素值,导致图像偏黑甚至黑屏。 - 变量重置时机错误:
averageRed、averageBlue、averageGreen在内部x循环的每次迭代后都被重置为0,根本无法完成累加操作。counter没有在处理每个目标像素(i,j)前重置,会一直累加所有像素的数量,导致分母越来越大,平均值趋近于0,直接造成黑屏。
- 图像拷贝顺序错误:当前代码是逐个像素将原始图像复制到
copy后立即修改copy[i][j],后续处理其他像素时会用到已经被修改的copy值,而非原始图像的像素值,这会导致模糊效果完全错误,同时加剧黑屏问题。
修正后的代码
// Blur image void blur(int height, int width, RGBTRIPLE image[height][width]) { // 先完整拷贝整个原始图像到copy数组,确保后续计算用的是原始像素值 RGBTRIPLE copy[height][width]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { copy[i][j] = image[i][j]; } } for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int sumRed = 0; int sumBlue = 0; int sumGreen = 0; float counter = 0; // 遍历当前像素的3x3邻域 for (int y = i - 1; y <= i + 1; y++) { for (int x = j - 1; x <= j + 1; x++) { // 跳过超出图像边界的像素 if (y >= 0 && y < height && x >= 0 && x < width) { // 累加邻域像素的RGB值 sumRed += copy[y][x].rgbtRed; sumBlue += copy[y][x].rgbtBlue; sumGreen += copy[y][x].rgbtGreen; counter++; } } } // 计算平均值并赋值回原始图像 image[i][j].rgbtRed = (int)round(sumRed / counter); image[i][j].rgbtBlue = (int)round(sumBlue / counter); image[i][j].rgbtGreen = (int)round(sumGreen / counter); } } return; }
修正说明
- 先完整拷贝原始图像到
copy数组,确保所有模糊计算都基于原始像素值,避免修改过程中污染数据源。 - 对每个目标像素(
i,j),重新初始化sumRed、sumBlue、sumGreen和counter,保证每个像素的邻域计算独立。 - 改为累加邻域内所有有效像素的RGB总和,再除以有效像素数量得到平均值,这才是方框模糊的正确计算逻辑。
- 计算完成后将平均值赋值回原始图像的对应像素,完成模糊效果。
内容的提问来源于stack exchange,提问作者Robbie
相关产品推荐
相关产品推荐

