You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CS50图像模糊边缘功能异常 求助排查问题

问题

我知道代码看起来不够规范,但打算先实现功能再优化结构。我在CS50中编写的图像blur函数,运行check50时提示无法正确模糊边缘,但在测试固定RGB值的文件中该技术能正常工作。

代码如下:

void blur(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++)
        {
            blurcorner(i,j,height,width,image,copy);
            bluredge(i,j,height,width,image,copy);
            image[i][j] = copy[i][j];
        }
    }
    return;
}


////////
void blurcorner (int i, int j, int height, int width, RGBTRIPLE image[height][width],RGBTRIPLE copy[height][width])
{
    if (i == height - 1  && j == width - 1)
    {
        int redav = (image[i - 1][j].rgbtRed + image[i][j-1].rgbtRed + image[i-1][j-1].rgbtRed + image[i][j].rgbtRed) / 4;
        copy[i][j].rgbtRed = redav;
        int greenav = (image[i - 1][j].rgbtGreen + image[i][j-1].rgbtGreen + image[i-1][j-1].rgbtGreen + image[i][j].rgbtGreen) / 4;
        copy[i][j].rgbtGreen = greenav;
        int blueav = (image[i - 1][j].rgbtBlue + image[i][j-1].rgbtBlue + image[i-1][j-1].rgbtBlue + image[i][j].rgbtBlue) / 4;
        copy[i][j].rgbtBlue = blueav;
    }
    else if (i == height - 1  && j == 0)
    {
        int redav = (image[i - 1][j].rgbtRed + image[i][j+1].rgbtRed + image[i+1][j+1].rgbtRed + image[i][j].rgbtRed) / 4;
        copy[i][j].rgbtRed = redav;
        int greenav = (image[i - 1][j].rgbtGreen + image[i][j+1].rgbtGreen + image[i+1][j+1].rgbtGreen + image[i][j].rgbtGreen) / 4;
        copy[i][j].rgbtGreen = greenav;
        int blueav = (image[i - 1][j].rgbtBlue + image[i][j+1].rgbtBlue + image[i+1][j+1].rgbtBlue + image[i][j].rgbtBlue) / 4;
        copy[i][j].rgbtBlue = blueav;
    }
    else if (i == 0  && j == 0)
    {
        int redav = (image[i + 1][j].rgbtRed + image[i][j+1].rgbtRed + image[i+1][j+1].rgbtRed + image[i][j].rgbtRed) / 4;
        copy[i][j].rgbtRed = redav;
        int greenav = (image[i + 1][j].rgbtGreen + image[i][j+1].rgbtGreen + image[i+1][j+1].rgbtGreen + image[i][j].rgbtGreen) / 4;
        copy[i][j].rgbtGreen = greenav;
        int blueav = (image[i + 1][j].rgbtBlue + image[i][j+1].rgbtBlue + image[i+1][j+1].rgbtBlue + image[i][j].rgbtBlue) / 4;
        copy[i][j].rgbtBlue = blueav;
    }
    else if (i == 0  && j == width - 1)
    {
        int redav = (image[i - 1][j].rgbtRed + image[i][j-1].rgbtRed + image[i-1][j-1].rgbtRed + image[i][j].rgbtRed) / 4;
        copy[i][j].rgbtRed = redav;
        int greenav = (image[i - 1][j].rgbtGreen + image[i][j-1].rgbtGreen + image[i-1][j-1].rgbtGreen + image[i][j].rgbtGreen) / 4;
        copy[i][j].rgbtGreen = greenav;
        int blueav = (image[i - 1][j].rgbtBlue + image[i][j-1].rgbtBlue + image[i-1][j-1].rgbtBlue + image[i][j].rgbtBlue) / 4;
        copy[i][j].rgbtBlue = blueav;
    }
}

void bluredge (int i, int j, int height, int width, RGBTRIPLE image[height][width],RGBTRIPLE copy[height][width])
{
    if (i == 0 && j > 0 && j < width - 1)
    {
        int redav = (image[i][j].rgbtRed + image[i][j-1].rgbtRed + image[i+1][j-1].rgbtRed + image[i+1][j].rgbtRed + image[i+1][j+1].rgbtRed + image[i][j+1].rgbtRed) / 6;
        copy[i][j].rgbtRed = redav;
        int greenav = (image[i][j].rgbtGreen + image[i][j-1].rgbtGreen + image[i+1][j-1].rgbtGreen + image[i+1][j].rgbtGreen + image[i+1][j+1].rgbtGreen + image[i][j+1].rgbtGreen) / 6;
        copy[i][j].rgbtGreen = greenav;
        int blueav = (image[i][j].rgbtBlue + image[i][j-1].rgbtBlue + image[i+1][j+1].rgbtBlue + image[i+1][j].rgbtBlue + image[i+1][j+1].rgbtBlue + image[i][j+1].rgbtBlue) / 6;
        copy[i][j].rgbtBlue = blueav;
    }
    else if (i == height - 1 && j > 0 && j < width - 1)
    {
        int redav = (image[i][j].rgbtRed + image[i][j-1].rgbtRed + image[i-1][j-1].rgbtRed + image[i-1][j].rgbtRed + image[i-1][j+1].rgbtRed + image[i][j+1].rgbtRed) / 6;
        copy[i][j].rgbtRed = redav;
        int greenav = (image[i][j].rgbtGreen + image[i][j-1].rgbtGreen + image[i-1][j-1].rgbtGreen + image[i-1][j].rgbtGreen + image[i-1][j+1].rgbtGreen + image[i][j+1].rgbtGreen) / 6;
        copy[i][j].rgbtGreen = greenav;
        int blueav = (image[i][j].rgbtBlue + image[i][j-1].rgbtBlue + image[i-1][j-1].rgbtBlue + image[i-1][j].rgbtBlue + image[i-1][j+1].rgbtBlue + image[i][j+1].rgbtBlue) / 6;
        copy[i][j].rgbtBlue = blueav;
    }
    else if (i > 0 && i < height - 1 && j == width - 1)
    {
        int redav = (image[i][j].rgbtRed + image[i-1][j].rgbtRed + image[i+1][j].rgbtRed + image[i+1][j-1].rgbtRed + image[i][j - 1].rgbtRed + image[i-1][j-1].rgbtRed) / 6;
        copy[i][j].rgbtRed = redav;
        int greenav = (image[i][j].rgbtGreen + image[i-1][j].rgbtGreen + image[i+1][j].rgbtGreen + image[i+1][j-1].rgbtGreen + image[i][j-1].rgbtGreen + image[i-1][j-1].rgbtGreen) / 6;
        copy[i][j].rgbtGreen = greenav;
        int blueav = (image[i][j].rgbtBlue + image[i-1][j].rgbtBlue + image[i+1][j].rgbtBlue + image[i+1][j-1].rgbtBlue + image[i][j-1].rgbtBlue + image[i-1][j-1].rgbtBlue) / 6;
        copy[i][j].rgbtBlue = blueav;
    }
    else if (i > 0 && i < height - 1 && j == 0)
    {
        int redav = (image[i][j].rgbtRed + image[i-1][j].rgbtRed + image[i+1][j].rgbtRed + image[i+1][j+1].rgbtRed + image[i][j+1].rgbtRed + image[i-1][j+1].rgbtRed) / 6;
        copy[i][j].rgbtRed = redav;
        int greenav = (image[i][j].rgbtGreen + image[i-1][j].rgbtGreen + image[i+1][j].rgbtGreen + image[i+1][j+1].rgbtGreen + image[i][j+1].rgbtGreen + image[i-1][j+1].rgbtGreen) / 6;
        copy[i][j].rgbtGreen = greenav;
        int blueav = (image[i][j].rgbtBlue + image[i-1][j].rgbtBlue + image[i+1][j].rgbtBlue + image[i+1][j+1].rgbtBlue + image[i][j+1].rgbtBlue + image[i-1][j+1].rgbtBlue) / 6;
        copy[i][j].rgbtBlue = blueav;
    }
    else
    {
        return;
    }
}

check50报错:

:( blur correctly filters pixel on edge
expected "80 95 105
", not "80 95 108
"

我怀疑问题出在蓝色通道的计算上,请求帮忙排查。

问题排查与修复

1. 核心逻辑错误:修改原图导致计算污染

你的blur函数中,在循环里直接把copy的值写回image,后续像素计算时会用到已经修改过的原图数据,导致模糊结果错误。正确的做法是先完成所有像素的模糊计算到copy数组,最后一次性把copy复制回image。

修改后的blur函数:

void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE copy[height][width];

    // 先计算所有像素的模糊结果到copy
    for(int i = 0; i < height; i++)
    {
        for(int j = 0; j < width; j++)
        {
            blurcorner(i,j,height,width,image,copy);
            bluredge(i,j,height,width,image,copy);
            // 补充中间区域的像素模糊逻辑
            if (!(i == 0 || i == height-1 || j ==0 || j == width-1)) {
                int red_sum = 0, green_sum = 0, blue_sum = 0;
                for(int di = -1; di <=1; di++){
                    for(int dj = -1; dj <=1; dj++){
                        red_sum += image[i+di][j+dj].rgbtRed;
                        green_sum += image[i+di][j+dj].rgbtGreen;
                        blue_sum += image[i+di][j+dj].rgbtBlue;
                    }
                }
                copy[i][j].rgbtRed = red_sum /9;
                copy[i][j].rgbtGreen = green_sum /9;
                copy[i][j].rgbtBlue = blue_sum /9;
            }
        }
    }
    // 最后一次性复制回原图
    for(int i = 0; i < height; i++)
    {
        for(int j = 0; j < width; j++)
        {
            image[i][j] = copy[i][j];
        }
    }
    return;
}

2. blurcorner函数的越界错误

  • 当i == 0 && j == width -1时,你使用了image[i-1][j](即image[-1][...]),数组下标越界,读取非法内存导致计算错误。正确的应该是取i+1方向的像素:
else if (i == 0  && j == width - 1)
{
    int redav = (image[i + 1][j].rgbtRed + image[i][j-1].rgbtRed + image[i+1][j-1].rgbtRed + image[i][j].rgbtRed) / 4;
    copy[i][j].rgbtRed = redav;
    int greenav = (image[i + 1][j].rgbtGreen + image[i][j-1].rgbtGreen + image[i+1][j-1].rgbtGreen + image[i][j].rgbtGreen) / 4;
    copy[i][j].rgbtGreen = greenav;
    int blueav = (image[i + 1][j].rgbtBlue + image[i][j-1].rgbtBlue + image[i+1][j-1].rgbtBlue + image[i][j].rgbtBlue) / 4;
    copy[i][j].rgbtBlue = blueav;
}
  • 当i == height -1 && j ==0时,你使用了image[i+1][j+1](即image[height][...]),同样越界,应该改为image[i-1][j+1]:
else if (i == height - 1  && j == 0)
{
    int redav = (image[i - 1][j].rgbtRed + image[i][j+1].rgbtRed + image[i-1][j+1].rgbtRed + image[i][j].rgbtRed) / 4;
    copy[i][j].rgbtRed = redav;
    int greenav = (image[i - 1][j].rgbtGreen + image[i][j+1].rgbtGreen + image[i-1][j+1].rgbtGreen + image[i][j].rgbtGreen) / 4;
    copy[i][j].rgbtGreen = greenav;
    int blueav = (image[i - 1][j].rgbtBlue + image[i][j+1].rgbtBlue + image[i-1][j+1].rgbtBlue + image[i][j].rgbtBlue) / 4;
    copy[i][j].rgbtBlue = blueav;
}

3. bluredge函数的蓝色通道重复计算错误

在i ==0 && j>0 && j<width-1的分支中,蓝色通道的计算重复加了image[i+1][j+1].rgbtBlue两次,漏掉了image[i+1][j-1].rgbtBlue:

// 修正后的蓝色计算
int blueav = (image[i][j].rgbtBlue + image[i][j-1].rgbtBlue + image[i+1][j-1].rgbtBlue + image[i+1][j].rgbtBlue + image[i+1][j+1].rgbtBlue + image[i][j+1].rgbtBlue) / 6;

4. 补充中间区域的模糊逻辑

你之前的代码只处理了边角和边缘像素,完全漏掉了中间区域(非边缘非边角)的像素模糊,这也是功能缺失的一部分,已在修改后的blur函数中补充。

其他优化建议

  • 可以把边角、边缘、中间区域的计算逻辑合并,用双重循环遍历当前像素周围的有效像素(判断下标是否在合法范围内),统计总和和计数后求平均,这样代码会更简洁,也不容易出错。
  • 计算平均值时,建议先求和再除以计数,避免整数截断误差(不过CS50的题目要求可能允许直接整除)。

内容的提问来源于stack exchange,提问作者ME Designs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 12:05:45