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

CS50 Week4 Filter(简易版):blur与sepia函数测试未通过求助

CS50 Week4 Filter(Less Comfortable)问题排查

问题描述

完成Filter的四个函数实现后,遇到以下问题:

  • blur函数仅通过边角像素测试,中间像素测试未通过;
  • sepia函数仅通过简单33图像测试,复杂33及4*4图像测试未通过,部分测试值差异仅为1,部分差异高达100。

原实现代码

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

// Convert image to grayscale
void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            image[i][j].rgbtGreen = round((image[i][j].rgbtGreen + image[i][j].rgbtBlue + image[i][j].rgbtRed) / 3.0);
            image[i][j].rgbtBlue = image[i][j].rgbtGreen;
            image[i][j].rgbtRed = image[i][j].rgbtGreen;
        }
    }
    return;
}

// Convert image to sepia
void sepia(int height, int width, RGBTRIPLE image[height][width])
{
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            int sepiaRed = round(.393 * image[i][j].rgbtRed + .769 * image[i][j].rgbtGreen + .189 * image[i][j].rgbtBlue);
            int sepiaGreen = round(.349 * image[i][j].rgbtRed + .686 * image[i][j].rgbtGreen + .168 * image[i][j].rgbtBlue);
            int sepiaBlue = round(.272 * image[i][j].rgbtRed + .534 * image[i][j].rgbtGreen + .131 * image[i][j].rgbtBlue);
            
            image[i][j].rgbtGreen = sepiaGreen;
            if (image[i][j].rgbtGreen > 255)
            {
                image[i][j].rgbtGreen = 255;
            }

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

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

// Reflect image horizontally
void reflect(int height, int width, RGBTRIPLE image[height][width])
{
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < (width / 2); j++)
        {
            RGBTRIPLE temp = image[i][j];
            image[i][j] = image[i][width - j - 1];
            image[i][width - j - 1] = temp;
        }
    }
    return;
}

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE copy[height][width];
    int blue = 0;
    int red = 0;
    int green = 0;
    int counter = 0;
    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++)
        {
            blue = 0;
            red = 0;
            green = 0;
            counter = 0;
            for (int s = i - 1; s < i + 2; s++)
            {
                for (int m = j - 1; m < j + 2; m++)
                {
                    if (s < 0 || m < 0 || s > height - 1 || m > width - 1)
                    {
                        continue;
                    }
                    else
                    {
                        blue += copy[s][m].rgbtBlue;
                        green += copy[s][m].rgbtGreen;
                        red += copy[s][m].rgbtRed;
                        counter++;
                    }
                }
            }
            image [i][j].rgbtBlue = round(blue / counter);
            image [i][j].rgbtGreen = round(green / counter);
            image [i][j].rgbtRed = round(red / counter);
        }
    }
    return;
}

问题分析与修正

1. Sepia函数问题

核心错误:rgbtRed/rgbtGreen/rgbtBlue属于unsigned char类型(取值范围0-255),当计算出的sepia值超过255时,直接赋值会触发溢出截断,此时再判断是否大于255已经无效。比如sepiaGreen=300,赋值给unsigned char后会被截断为300-256=44,后续判断44>255不成立,无法修正为255,这就是部分测试值差异极大的原因。

修正方案:先判断sepia值是否超出范围,再赋值给图像通道:

// Convert image to sepia
void sepia(int height, int width, RGBTRIPLE image[height][width])
{
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            int sepiaRed = round(.393 * image[i][j].rgbtRed + .769 * image[i][j].rgbtGreen + .189 * image[i][j].rgbtBlue);
            int sepiaGreen = round(.349 * image[i][j].rgbtRed + .686 * image[i][j].rgbtGreen + .168 * image[i][j].rgbtBlue);
            int sepiaBlue = round(.272 * image[i][j].rgbtRed + .534 * image[i][j].rgbtGreen + .131 * image[i][j].rgbtBlue);

            // 先截断超出范围的值,再赋值
            image[i][j].rgbtRed = sepiaRed > 255 ? 255 : sepiaRed;
            image[i][j].rgbtGreen = sepiaGreen > 255 ? 255 : sepiaGreen;
            image[i][j].rgbtBlue = sepiaBlue > 255 ? 255 : sepiaBlue;
        }
    }
    return;
}

2. Blur函数问题

核心错误:blue/green/red和counter都是整数类型,blue / counter执行的是整数除法(直接截断小数部分),之后调用round()完全无效。比如blue=5、counter=2,整数除法得到2,round(2)还是2,但正确结果应该是round(5.0/2)=3,这导致中间像素的模糊计算结果错误。

修正方案:将除法运算转换为浮点数除法后再取整:

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE copy[height][width];
    int blue = 0;
    int red = 0;
    int green = 0;
    int counter = 0;
    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++)
        {
            blue = 0;
            red = 0;
            green = 0;
            counter = 0;
            for (int s = i - 1; s < i + 2; s++)
            {
                for (int m = j - 1; m < j + 2; m++)
                {
                    if (s < 0 || m < 0 || s > height - 1 || m > width - 1)
                    {
                        continue;
                    }
                    else
                    {
                        blue += copy[s][m].rgbtBlue;
                        green += copy[s][m].rgbtGreen;
                        red += copy[s][m].rgbtRed;
                        counter++;
                    }
                }
            }
            // 转换为浮点数除法后再取整
            image[i][j].rgbtBlue = round((float)blue / counter);
            image[i][j].rgbtGreen = round((float)green / counter);
            image[i][j].rgbtRed = round((float)red / counter);
        }
    }
    return;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 08:05:55