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

CS50 Pset4 Filter blur函数实现不符合check50校验预期

CS50 Pset4 Filter (less comfortable) blur函数错误排查

问题描述

  • 实现blur函数时,无论怎么调整方案都无法输出正确结果
  • 已尝试多层for循环嵌套、创建二维图像副本避免已模糊像素干扰的方案,代码编译、运行全程无报错,但check50中所有blur相关用例均未通过
  • 不希望直接照搬现成答案,仅需要逻辑错误点的排查指引

现有实现代码

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

//temp equals image
for (int i = 0; i < height; i++)
{
    for (int j = 0; j < width; j++)
    {
        temp[i][j] = image[i][j];
    }
}


for (int i = 0; i < height; i++)
{
    for (int j = 0; j < width; j++)
    {
        // copy equals image on every iteration so the blurred parts become non-blurred
        for (int k = 0; k < height; k++)
        {
            for (int l = 0; l < width; l++)
            {
                copy[k][l] = image[k][l];
            }
        }
        
        // just some variables for easy use
        int n = i + 1;
        int m = i - 1;
        int o = j + 1;
        int p = j - 1;

        if (n == height)
        {n -= 1;}
        else if (m < 0)
        {m = 0;}

        if (o == width)
        {o -= 1;}
        else if (p < 0)
        {p = 0;}

        // using the array copy and not image
        RGBTRIPLE center = copy[i][j];
        RGBTRIPLE top = copy[n][j];
        RGBTRIPLE bottom = copy[m][j];
        RGBTRIPLE left = copy[i][p];
        RGBTRIPLE right = copy[i][o];
        RGBTRIPLE top_left = copy[n][p];
        RGBTRIPLE bottom_left = copy[m][p];
        RGBTRIPLE top_right = copy[n][o];
        RGBTRIPLE bottom_right = copy[m][o];

        int avgred = (center.rgbtRed + top.rgbtRed + bottom.rgbtRed + left.rgbtRed + right.rgbtRed + top_left.rgbtRed + bottom_left.rgbtRed + top_right.rgbtRed + bottom_right.rgbtRed) / 9.0;
        int avggreen = (center.rgbtGreen + top.rgbtGreen + bottom.rgbtGreen + left.rgbtGreen + right.rgbtGreen + top_left.rgbtGreen + bottom_left.rgbtGreen + top_right.rgbtGreen + bottom_right.rgbtGreen) / 9.0;
        int avgblue = (center.rgbtBlue + top.rgbtBlue + bottom.rgbtBlue + left.rgbtBlue + right.rgbtBlue + top_left.rgbtBlue + bottom_left.rgbtBlue + top_right.rgbtBlue + bottom_right.rgbtBlue) / 9.0;
        
        // saving the blurred in temp on every iteration
        temp[i][j].rgbtRed = round(avgred);
        temp[i][j].rgbtGreen = round(avggreen);
        temp[i][j].rgbtBlue = round(avgblue);
    }
}

// image equals the blurred temp
for (int i = 0; i < height; i++)
{
    for (int j = 0; j < width; j++)
    {
        image[i][j] = temp[i][j];
    }
}
return;
}

依赖的RGBTRIPLE结构体定义

typedef struct
{
BYTE  rgbtBlue;
BYTE  rgbtGreen;
BYTE  rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;

check50校验失败返回

:( blur correctly filters middle pixel
    expected "127 140 149\n", not "126 140 149\n"
:( blur correctly filters pixel on edge
    expected "80 95 105\n", not "66 80 90\n"
:( blur correctly filters pixel in corner
    expected "70 85 95\n", not "51 64 74\n"
:( blur correctly filters 3x3 image
    expected "70 85 95\n80 9...", not "51 64 74\n66 8..."
:( blur correctly filters 4x4 image
    expected "70 85 95\n80 9...", not "51 64 74\n66 8..."

核心逻辑错误点

代码有3个关键问题,完全对应check50返回的错误现象:

  1. 边界处理逻辑完全错误
    用if...else if结构处理越界坐标会导致两个问题:一是角落像素同时存在行、列两个方向的越界,else if只会处理其中一个方向;二是把越界坐标直接改成当前边界值,相当于角落、边缘像素计算时重复累加了自身/同边界像素的值,同时没有统计实际有效的邻域像素数量,永远固定除以9计算平均值——角落像素实际只有3个有效邻域,边缘非角落像素只有6个有效邻域,固定除以9会让计算出的平均值比正确值小1/3到1/4,和返回的角落、边缘像素值远低于预期的现象完全吻合。
  2. 四舍五入逻辑无效
    把RGB总和除以9.0得到的浮点数直接赋值给int类型的avgred/avggreen/avgblue,赋值时浮点数会被直接截断取整,后续调用round()没有任何作用,这就是中间像素计算结果差1的原因:本该四舍五入到127的值被截断成126。
  3. 无意义的性能损耗
    每次内层像素循环时都全量拷贝整个图像到copy数组完全没必要,只需要在进入像素遍历循环前拷贝一次原始图像到副本,所有计算都从这个原始副本读值,就不会出现已模糊像素污染后续计算的问题,不需要每次循环重拷全图。

修正方向提示

  • 不要硬改越界坐标为边界值:遍历当前像素周围3*3范围的所有坐标时,先判断坐标是否落在0<=行号<height、0<=列号<width的合法范围内,仅累加合法像素的RGB值,同时统计合法像素的总个数,最后用RGB总和除以合法像素总个数得到平均值,不要固定除以9
  • 计算平均值时,先对浮点型的总和做round()四舍五入,再把结果赋值给像素的BYTE类型通道值,不要提前转int导致截断
  • 原始图像副本只需要在遍历所有像素前拷贝一次即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 17:21:22