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

CS50 Filter-More项目Edges函数未通过check50,求问题排查

CS50 Filter-More项目Edges函数check50测试失败问题排查

我在CS50 Filter-More项目中实现的Edges函数无法通过check50测试,以下是我的代码和测试失败结果:


头文件与宏定义

#include "helpers.h"
#include "math.h"
#include "stdlib.h"

#define RED_COLOR 0
#define GREEN_COLOR 1
#define BLUE_COLOR 2
#define POS_X 0
#define POS_Y 1

getEdge函数

int getEdge(int i, int j, int height, int width, RGBTRIPLE image[height][width], int color_position, int position)
{
     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}
    };

    int row_count = 0;
    int col_count = 0;

    int sum = 0;
    for (int row = i - 1; row <= (i + 1); row++)
    {
        col_count = 0;
        for (int column = j - 1; column <= (j + 1); column++)
        {

            if (row < 0 || row >= height || column < 0 || column >= width)
            {
                sum += 0;
            }
            if (color_position == RED_COLOR)
            {
                if (position == POS_X)
                    sum += image[row][column].rgbtRed * gx[row_count][col_count];
                else
                    sum += image[row][column].rgbtRed * gy[row_count][col_count];
             }
            else if (color_position == GREEN_COLOR)
            {
                if (position == POS_X)
                    sum += image[row][column].rgbtGreen * gx[row_count][col_count];
                else
                    sum += image[row][column].rgbtGreen * gy[row_count][col_count];
            }
            else
            {
                if (position == POS_X)
                    sum += image[row][column].rgbtBlue * gx[row_count][col_count];
                else
                    sum += image[row][column].rgbtBlue * gy[row_count][col_count];
            }
            col_count++;
        }
        row_count++;
    }
    return sum;
}

sobel函数与edges主函数

// Calculate sobel value for each channel (capping at 255)
int sobel (int Gx, int Gy)
{
    int n = sqrt(Gx^2 + Gy^2);
    n = fmin(255, n);
    return n;
}

// Detect edges
void edges(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE copy[height][width];
    // copy image
    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++)
        {
            image[i][j].rgbtRed = sobel(getEdge(i, j, height, width, copy, RED_COLOR, POS_X), getEdge(i, j, height, width, copy, RED_COLOR, POS_Y));
            image[i][j].rgbtGreen = sobel(getEdge(i, j, height, width, copy, GREEN_COLOR, POS_X), getEdge(i, j, height, width, copy, GREEN_COLOR, POS_Y));
            image[i][j].rgbtBlue = sobel(getEdge(i, j, height, width, copy, BLUE_COLOR, POS_X), getEdge(i, j, height, width, copy, BLUE_COLOR, POS_Y));
        }

    return;
}

check50测试失败结果

❌ 正确过滤中间像素
原因
预期输出:"210 150 60\n",实际输出:"4 15 10\n"
日志
测试使用3x3示例图像
第一行:(0, 10, 25), (0, 10, 30), (40, 60, 80)
第二行:(20, 30, 90), (30, 40, 100), (80, 70, 90)
第三行:(20, 20, 40), (30, 10, 30), (50, 40, 10)

❌ 正确过滤边缘像素
原因
预期输出:"213 228 255\n",实际输出:"19 20 15\n"
日志
测试使用3x3示例图像
第一行:(0, 10, 25), (0, 10, 30), (40, 60, 80)
第二行:(20, 30, 90), (30, 40, 100), (80, 70, 90)
第三行:(20, 20, 40), (30, 10, 30), (50, 40, 10)

❌ 正确过滤角落像素
原因
预期输出:"76 117 255\n",实际输出:"0 0 0\n"
日志
测试使用3x3示例图像
第一行:(0, 10, 25), (0, 10, 30), (40, 60, 80)
第二行:(20, 30, 90), (30, 40, 100), (80, 70, 90)
第三行:(20, 20, 40), (30, 10, 30), (50, 40, 10)

❌ 正确过滤3x3图像
原因
预期输出:"76 117 255\n21...",实际输出:"0 17 0\n15 11 ..."
日志
测试使用3x3示例图像
第一行:(0, 10, 25), (0, 10, 30), (40, 60, 80)
第二行:(20, 30, 90), (30, 40, 100), (80, 70, 90)
第三行:(20, 20, 40), (30, 10, 30), (50, 40, 10)


问题定位与修复方案

1. Sobel垂直卷积核定义错误(核心问题)

你定义的gy垂直边缘检测核第一行最后一个元素错误,正确的垂直核应为:

int gy[3][3]={
    {-1, -2, -1},
    {0, 0, 0},
    {1, 2, 1}
};

原代码中该位置写为1,导致垂直边缘计算完全偏离预期。

2. 边界越界访问问题

getEdge函数中,检测到坐标越界后仅执行sum += 0,但后续仍会访问image[row][column],触发非法内存访问,导致结果异常。需调整逻辑跳过越界情况:

for (int column = j - 1; column <= (j + 1); column++)
{
    // 越界则跳过当前循环,不执行后续计算
    if (row < 0 || row >= height || column < 0 || column >= width)
    {
        col_count++;
        continue;
    }
    // 颜色通道计算代码...
    col_count++;
}

或更简洁的写法:

for (int column = j - 1; column <= (j + 1); column++)
{
    if (!(row < 0 || row >= height || column < 0 || column >= width))
    {
        // 颜色通道计算代码...
    }
    col_count++;
}

3. 平方运算使用错误运算符

C语言中^是位异或运算符,不是幂运算。计算平方应使用乘法(效率更高)或pow函数,同时要避免int溢出:

// 修正后的sobel函数
int sobel (int Gx, int Gy)
{
    // 转为long long避免平方后溢出
    long long gx_sq = (long long)Gx * Gx;
    long long gy_sq = (long long)Gy * Gy;
    // 用round取整,避免直接截断小数导致结果偏差
    int n = round(sqrt(gx_sq + gy_sq));
    n = fmin(255, n);
    return n;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 14:15:40