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

CS50作业:Sobel算子边缘检测函数蓝通道值计算错误排查

CS50 Filter More作业:Sobel算子蓝通道计算错误排查

问题情况

  • 实现了Sobel算子的位图边缘检测函数,红、绿通道输出正确,但蓝通道无法通过CS50测试用例
  • 执行check50 cs50/problems/2024/x/filter/more时,蓝通道测试失败,预期值为255但代码计算结果错误
  • 已添加溢出处理逻辑(超过255时设为255),但未解决问题

实现代码

void edges(int height, int width, RGBTRIPLE image[height][width])
{
    int Gx_Matrix[3][3] = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
    int Gy_Matrix[3][3] = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}};
    RGBTRIPLE copy[height][width];

    // Create a copy of the original image //
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            copy[i][j] = image[i][j];
        }
    }

    // Loop over each pixel //
    // Calculate the weighted sum of each colour channel //
    // Combine the Gx and Gy weight sum to attain a single value for each channel //

    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            float Gx_SumRed = 0;
            float Gy_SumRed = 0;
            float Gx_SumGreen = 0;
            float Gy_SumGreen = 0;
            float Gx_SumBlue = 0;
            float Gy_SumBlue = 0;

            for (int di = -1; di <= 1; di++)
            {
                for (int dj = -1; dj <= 1; dj++)
                {
                    int ni = i + di;
                    int nj = j + dj;

                    if((ni >= 0) && (ni < height) && (nj >= 0) && (nj < width))
                    {
                        Gx_SumRed += Gx_Matrix[di + 1][dj + 1] * (copy[ni][nj].rgbtRed);
                        Gx_SumGreen += Gx_Matrix[di + 1][dj + 1] * (copy[ni][nj].rgbtGreen);
                        Gx_SumBlue += Gx_Matrix[di + 1][dj + 1] * (copy[ni][nj].rgbtBlue);

                        Gy_SumRed += Gy_Matrix[di + 1][dj + 1] * (copy[ni][nj].rgbtRed);
                        Gy_SumGreen += Gy_Matrix[di + 1][dj + 1] * (copy[ni][nj].rgbtGreen);
                        Gy_SumBlue += Gy_Matrix[di + 1][dj + 1] * (copy[ni][nj].rgbtBlue);
                    }
                    else
                    {
                        continue;
                    }
                }
            }
            image[i][j].rgbtRed = round(sqrt((Gx_SumRed * Gx_SumRed) + (Gy_SumRed * Gy_SumRed)));
            image[i][j].rgbtGreen = round(sqrt((Gx_SumGreen * Gx_SumGreen) + (Gy_SumGreen * Gy_SumGreen)));
            image[i][j].rgbtBlue = round(sqrt((Gx_SumBlue * Gx_SumBlue) + (Gy_SumBlue * Gy_SumBlue)));

            if (image[i][j].rgbtRed > 255)
            {
                image[i][j].rgbtRed = 255;
            }

            if (image[i][j].rgbtGreen > 255)
            {
                image[i][j].rgbtGreen = 255;
            }

            if (image[i][j].rgbtBlue > 255)
            {
                image[i][j].rgbtBlue = 255;
            }
        }
    }
    return;
}

错误原因

问题出在溢出处理的顺序上:
RGBTRIPLE中的rgbtRed、rgbtGreen、rgbtBlue都是无符号字符类型(unsigned char),取值范围仅为0-255。当你直接把超过255的计算结果赋值给这些字段时,数值会被自动截断(比如260会变成4),之后再判断>255时,截断后的数值已经小于255,无法触发修正逻辑。

蓝通道的测试用例中,计算结果超过了255,赋值时被截断成了错误的小值,导致测试失败;而红、绿通道的测试用例计算结果可能未超过255,或者截断后刚好符合预期,所以没有暴露问题。

修复方案

先将计算结果存入临时变量,判断并修正溢出后,再赋值给图像通道:

// 替换原有的赋值和溢出判断代码
float red = round(sqrt((Gx_SumRed * Gx_SumRed) + (Gy_SumRed * Gy_SumRed)));
float green = round(sqrt((Gx_SumGreen * Gx_SumGreen) + (Gy_SumGreen * Gy_SumGreen)));
float blue = round(sqrt((Gx_SumBlue * Gx_SumBlue) + (Gy_SumBlue * Gy_SumBlue)));

image[i][j].rgbtRed = (red > 255) ? 255 : red;
image[i][j].rgbtGreen = (green > 255) ? 255 : green;
image[i][j].rgbtBlue = (blue > 255) ? 255 : blue;

或者用if语句的形式:

float red_val = round(sqrt((Gx_SumRed * Gx_SumRed) + (Gy_SumRed * Gy_SumRed)));
if (red_val > 255)
{
    image[i][j].rgbtRed = 255;
}
else
{
    image[i][j].rgbtRed = red_val;
}

// 绿、蓝通道同理处理

这样就能确保超过255的数值在赋值前被修正为255,避免截断错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 11:04:51