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

C语言方框模糊(Box Blur)代码的RGB取整问题求助

图像方框模糊RGB值取整偏低的问题

我正在完成C语言课程作业,实现图像的方框模糊(Box Blur)功能,但教授指出多数情况下图像的RGB值取整结果低于实际应有的水平。以下是我的代码:

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
    // Create a copy of image
    RGBTRIPLE copy[height][width];
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            copy[i][j] = image[i][j];
        }
    }

    // for every row
    for (int i=0;i<height;i++)
       { // for every pixel
            for (int j=0;j<width;j++)
            {
                // initalising colours
                int blue=copy[i][j].rgbtBlue;
                int red = copy[i][j].rgbtRed;
                int green =copy[i][j].rgbtGreen;
                // initialising turns
                int tblue=1;
                int tred=1;
                int tgreen =1;

                // if the pixel is between top and 2nd last
                if ((i>=0)&&(i<=height-2))
                {
                        // add the values for the pixel below it
                        blue+=copy[i+1][j].rgbtBlue;
                        red+=copy[i+1][j].rgbtRed;
                        green+=copy[i+1][j].rgbtGreen;
                        // add a turn
                        tblue++;
                        tred++;
                        tgreen++;
                        // if the pixel is between left adn 2nd last
                        if ((j>=0)&&(j<=width-2))
                        {
                            // add the avlue of right side  below it
                            blue+=copy[i+1][j+1].rgbtBlue;
                            red+=copy[i+1][j+1].rgbtRed;
                            green+=copy[i+1][j+1].rgbtGreen;
                            // add a turn
                            tblue++;
                            tred++;
                            tgreen++;
                        }
                        // if the pixel is between right and 2nd
                        if ((j<=height-1)&&(j>=1))
                        {
                            // add the values of left side below it
                            blue+=copy[i+1][j-1].rgbtBlue;
                            red+=copy[i+1][j-1].rgbtRed;
                            green+=copy[i+1][j-1].rgbtGreen;
                            // add a turn
                            tblue++;
                            tred++;
                            tgreen++;
                        }
                    }

                // if the pixel is between bottom and 2nd
                if ((i<=height-1)&&(i>=1))
                {
                    // add the values for the pixel above it
                    blue+=copy[i-1][j].rgbtBlue;
                    red+=copy[i-1][j].rgbtRed;
                    green+=copy[i-1][j].rgbtGreen;
                    // add a turn
                    tblue++;
                    tred++;
                    tgreen++;
                    // if the pixel is between left adn 2nd last
                    if ((j>=0)&&(j<=width-2))
                    {
                        // add the avlue of right side  above it
                        blue+=copy[i-1][j+1].rgbtBlue;
                        red+=copy[i-1][j+1].rgbtRed;
                        green+=copy[i-1][j+1].rgbtGreen;
                        // add a turn
                        tblue++;
                        tred++;
                        tgreen++;
                    }
                    // if the pixel is between right and 2nd
                    if ((j<=height-1)&&(j>=1))
                    {
                        // add the values of left side above it
                        blue+=copy[i-1][j-1].rgbtBlue;
                        red+=copy[i-1][j-1].rgbtRed;
                        green+=copy[i-1][j-1].rgbtGreen;
                        // add a turn
                        tblue++;
                        tred++;
                        tgreen++;
                    }
                }
                // if the pixel is between left and 2nd last
                if ((j>=0)&&(j<=width-2))
                {
                    // add the avlue of the one right of it
                    blue+=copy[i][j+1].rgbtBlue;
                    red+=copy[i][j+1].rgbtRed;
                    green+=copy[i][j+1].rgbtGreen;
                    // add a turn
                    tblue++;
                    tred++;
                    tgreen++;
                }
                // if the pixel is between right and 2nd
                if((j<=height-1)&&(j>=1))
                {
                    // add the avlue of the one left of it
                    blue+=copy[i][j-1].rgbtBlue;
                    red+=copy[i][j-1].rgbtRed;
                    green+=copy[i][j-1].rgbtGreen;
                    // add a turn
                    tblue++;
                    tred++;
                    tgreen++;
                }
                // divide socre by turns and put it in round ()
                image[i][j].rgbtBlue = round(blue/tblue);
                image[i][j].rgbtRed = round(red/tred);
                image[i][j].rgbtGreen = round(green/tgreen);
            }
    }

    return;
}

问题根源分析

  • 整数除法截断问题:代码中blue/tblue是整数除法,在调用round()之前就已经丢失了小数部分。比如5/2会先得到2,再round还是2,但实际5/2=2.5,round后应该是3,这就直接导致结果偏低。
  • 边界判断错误:多处判断中误用了height来判断列(j)的范围,比如if ((j<=height-1)&&(j>=1)),这里应该用width而不是height,会导致边缘像素的邻域计算错误,进而拉低平均值。
  • 冗余计数变量:tblue、tred、tgreen三个变量完全可以合并成一个count变量,因为每个邻域像素对三个通道的计数是一致的,分开统计只会增加代码复杂度。

修复后的代码

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
    // Create a copy of image
    RGBTRIPLE copy[height][width];
    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++)
        {
            int blue = 0, red = 0, green = 0;
            int count = 0;

            // 遍历当前像素周围3x3范围内的所有有效像素
            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)
                    {
                        blue += copy[ni][nj].rgbtBlue;
                        red += copy[ni][nj].rgbtRed;
                        green += copy[ni][nj].rgbtGreen;
                        count++;
                    }
                }
            }

            // 先做浮点除法再取整,避免整数截断
            image[i][j].rgbtBlue = round((double)blue / count);
            image[i][j].rgbtRed = round((double)red / count);
            image[i][j].rgbtGreen = round((double)green / count);
        }
    }

    return;
}

修复说明

  • 解决整数截断问题:将blue等整数强制转换为double类型后再做除法,确保小数部分被保留,之后用round()进行正确的四舍五入,避免结果偏低。
  • 简化邻域遍历逻辑:用两层循环遍历当前像素周围的3x3区域,通过坐标判断筛选有效像素,彻底修复了原代码中用height判断列范围的错误,同时大幅简化了边界条件。
  • 合并计数变量:使用单个count变量统计有效邻域像素的数量,减少代码冗余,逻辑更清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:47:06