在 C 中模糊图像:代码只有一半有效

Blurring an Image in C: Code only half works

我的目标是通过取所有周围像素的平均值来模糊 C(不是 C++)中的图像。 我将我的计算分开:

我的代码有很多问题,我通过创建图像的副本修复了这个问题。但是,当我的代码到达 3x3 和 4x4 图像的底部几行时,它开始不起作用。

我需要帮助来检查我的代码有什么问题。另外,我知道我的代码非常冗长,这是我写出所有内容并加深理解的一种方式,但我也希望有人能以另一种方式提供输入来编写代码。我对此很陌生,所以我肯定需要很多解释。我已经搜索并查看了其他缩短的、写得很好的代码,但我很难理解它。

非常感谢所有帮助!

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width]){

//top left corner variables
float ravg_lcorner = 0;
float gavg_lcorner = 0;
float bavg_lcorner = 0;

//top right corner variables
float ravg_rcorner = 0;
float gavg_rcorner = 0;
float bavg_rcorner = 0;

//bottom left corner variables
float ravg_blcorner = 0;
float gavg_blcorner = 0;
float bavg_blcorner = 0;

//bottom right corner variables
float ravg_brcorner = 0;
float gavg_brcorner = 0;
float bavg_brcorner = 0;

//top row center variables
float ravg_topcenter = 0;
float gavg_topcenter = 0;
float bavg_topcenter = 0;

//top row center variables
float ravg_btmcenter = 0;
float gavg_btmcenter = 0;
float bavg_btmcenter = 0;

//left side center variables
float ravg_lscenter = 0;
float gavg_lscenter = 0;
float bavg_lscenter = 0;

//right side center variables
float ravg_rscenter = 0;
float gavg_rscenter = 0;
float bavg_rscenter = 0;

//center variaables
float ravg_center = 0;
float gavg_center = 0;
float bavg_center = 0;

RGBTRIPLE temp;
RGBTRIPLE copy_image[height][width];

//create copy of image canvas
for (int i = 0; i < height; i++) 
{
    for (int j = 0; j < width; j++)
    {
        temp = image[i][j];
        image[i][j] = copy_image[i][j];
        copy_image[i][j] = temp;
    }
}


for (int i = 0; i < height; i++)
{
    for (int j = 0; j < width; j++)
    {
        
        //if pixel is at top row left corner 
        if (i == 0 && j == 0)
        {
            //calculate all red average
            ravg_lcorner = (int) round((copy_image[i][j].rgbtRed + copy_image[i][j+1].rgbtRed + copy_image[i+1][j].rgbtRed + copy_image[i+1][j+1].rgbtRed) / 4.00);
            //calculate all green average
            gavg_lcorner = (int) round((copy_image[i][j].rgbtGreen + copy_image[i][j+1].rgbtGreen + copy_image[i+1][j].rgbtGreen + copy_image[i+1][j+1].rgbtGreen) / 4.00);
            //calculate all blue average
            bavg_lcorner = (int) round((copy_image[i][j].rgbtBlue + copy_image[i][j+1].rgbtBlue + copy_image[i+1][j].rgbtBlue + copy_image[i+1][j+1].rgbtBlue) / 4.00);
            
            //new pixel color

            image[i][j].rgbtRed = ravg_lcorner;
            image[i][j].rgbtGreen = gavg_lcorner;
            image[i][j].rgbtBlue = bavg_lcorner;
            
        }
        
        //if pixel is top row right corner
        if (i == 0 && j == width - 1)
        {
            //calculate all red average
            ravg_rcorner = (int) round((copy_image[i][j].rgbtRed + copy_image[i][j-1].rgbtRed + copy_image[i+1][j].rgbtRed + copy_image[i+1][j-1].rgbtRed) / 4.00);
            //calculate all green average
            gavg_rcorner = (int) round((copy_image[i][j].rgbtGreen + copy_image[i][j-1].rgbtGreen + copy_image[i+1][j].rgbtGreen + copy_image[i+1][j-1].rgbtGreen) / 4.00);
            //calculate all blue average
            bavg_rcorner = (int) round((copy_image[i][j].rgbtBlue + copy_image[i][j-1].rgbtBlue + copy_image[i+1][j].rgbtBlue + copy_image[i+1][j-1].rgbtBlue) / 4.00);
            
            //new pixel color
            image[i][j].rgbtRed = ravg_rcorner;
            image[i][j].rgbtGreen = gavg_rcorner;
            image[i][j].rgbtBlue = bavg_rcorner;
        }
        
        //if pixel is at bottom row left corner 
        if(i == height - 1 && j == 0)
        {
            //calculate all red average
            ravg_blcorner = (int) round((copy_image[i][j].rgbtRed + copy_image[i][j+1].rgbtRed + copy_image[i-1][j].rgbtRed + copy_image[i-1][j+1].rgbtRed) / 4.00);
            //calculate all green average
            gavg_blcorner = (int) round((copy_image[i][j].rgbtGreen + copy_image[i][j+1].rgbtGreen + copy_image[i-1][j].rgbtGreen + copy_image[i-1][j+1].rgbtGreen) / 4.00);
            //calculate all blue average
            bavg_blcorner = (int) round((copy_image[i][j].rgbtBlue + copy_image[i][j+1].rgbtBlue + copy_image[i-1][j].rgbtBlue + copy_image[i-1][j+1].rgbtBlue) / 4.00);
            
            //new pixel color
            copy_image[i][j].rgbtRed = ravg_blcorner;
            copy_image[i][j].rgbtGreen = gavg_blcorner;
            copy_image[i][j].rgbtBlue = bavg_blcorner;
        }
        
        //if pixel is at bottom row right corner 
        if(i == height -1 && j == width - 1)
        {
            //calculate all red average
            ravg_brcorner = (int) round((copy_image[i][j].rgbtRed + copy_image[i][j-1].rgbtRed + copy_image[i-1][j].rgbtRed + copy_image[i-1][j-1].rgbtRed) / 4.00);
            //calculate all green average
            gavg_brcorner = (int) round((copy_image[i][j].rgbtGreen + copy_image[i][j-1].rgbtGreen + copy_image[i-1][j].rgbtGreen + copy_image[i-1][j-1].rgbtGreen) / 4.00);
            //calculate all blue average
            bavg_brcorner = (int) round((copy_image[i][j].rgbtBlue + copy_image[i][j-1].rgbtBlue + copy_image[i-1][j].rgbtBlue + copy_image[i-1][j-1].rgbtBlue) / 4.00);
            
            //new pixel color
            image[i][j].rgbtRed = ravg_rcorner;
            image[i][j].rgbtGreen = gavg_rcorner;
            image[i][j].rgbtBlue = bavg_rcorner;
        }
        
        //if pixel is top row center
        if(i == 0 && j < width - 1 && j > 0)
        {
            //calculate all red average
            ravg_topcenter = (int) round((copy_image[i][j].rgbtRed + copy_image[i][j-1].rgbtRed + copy_image[i][j+1].rgbtRed + copy_image[i+1][j-1].rgbtRed + copy_image[i+1][j].rgbtRed + copy_image[i+1][j+1].rgbtRed) / 6.00);
            //calculate all green average
            gavg_topcenter = (int) round((copy_image[i][j].rgbtGreen + copy_image[i][j-1].rgbtGreen + copy_image[i][j+1].rgbtGreen + copy_image[i+1][j-1].rgbtGreen + copy_image[i+1][j].rgbtGreen + copy_image[i+1][j+1].rgbtGreen) / 6.00);
            //calculate all blue average
            bavg_topcenter = (int) round((copy_image[i][j].rgbtBlue + copy_image[i][j-1].rgbtBlue + copy_image[i][j+1].rgbtBlue + copy_image[i+1][j-1].rgbtBlue + copy_image[i+1][j].rgbtBlue + copy_image[i+1][j+1].rgbtBlue) / 6.00);
            
            //new pixel color
            image[i][j].rgbtRed = ravg_topcenter;
            image[i][j].rgbtGreen = gavg_topcenter;
            image[i][j].rgbtBlue = bavg_topcenter;
        }
        
        //if pixel is bottom row center
        if(i == height - 1 && j < width - 1 && j > 0)
        {
            //calculate all red average
            ravg_topcenter = (int) round((copy_image[i][j].rgbtRed + copy_image[i][j-1].rgbtRed + copy_image[i][j+1].rgbtRed + copy_image[i-1][j-1].rgbtRed + copy_image[i-1][j].rgbtRed + copy_image[i-1][j+1].rgbtRed) / 6.00);
            //calculate all green average
            gavg_topcenter = (int) round((copy_image[i][j].rgbtGreen + copy_image[i][j-1].rgbtGreen + copy_image[i][j+1].rgbtGreen + copy_image[i-1][j-1].rgbtGreen + copy_image[i-1][j].rgbtGreen + copy_image[i-1][j+1].rgbtGreen) / 6.00);
            //calculate all blue average
            bavg_topcenter = (int) round((copy_image[i][j].rgbtBlue + copy_image[i][j-1].rgbtBlue + copy_image[i][j+1].rgbtBlue + copy_image[i-1][j-1].rgbtBlue + copy_image[i-1][j].rgbtBlue + copy_image[i-1][j+1].rgbtBlue) / 6.00);
            
            //new pixel color
            image[i][j].rgbtRed = ravg_btmcenter;
            image[i][j].rgbtGreen = gavg_btmcenter;
            image[i][j].rgbtBlue = bavg_btmcenter;
        }
        
        //if pixel is at left side center
        if (i < height - 1 && i > 0 && j == 0)
        {
            //calculate all red average
            ravg_lscenter = (int) round((copy_image[i][j].rgbtRed + copy_image[i][j+1].rgbtRed + copy_image[i-1][j].rgbtRed + copy_image[i-1][j+1].rgbtRed + copy_image[i+1][j].rgbtRed + copy_image[i+1][j+1].rgbtRed) / 6.00);
            //calculate all green average
            gavg_lscenter = (int) round((copy_image[i][j].rgbtGreen + copy_image[i][j+1].rgbtGreen + copy_image[i-1][j].rgbtGreen + copy_image[i-1][j+1].rgbtGreen + copy_image[i+1][j].rgbtGreen + copy_image[i+1][j+1].rgbtGreen) / 6.00);
            //calculate all blue average
            bavg_lscenter = (int) round((copy_image[i][j].rgbtBlue + copy_image[i][j+1].rgbtBlue + copy_image[i-1][j].rgbtBlue + copy_image[i-1][j+1].rgbtBlue + copy_image[i+1][j].rgbtBlue + copy_image[i+1][j+1].rgbtBlue) / 6.00);
            
            //new pixel color
            image[i][j].rgbtRed = ravg_lscenter;
            image[i][j].rgbtGreen = gavg_lscenter;
            image[i][j].rgbtBlue = bavg_lscenter;
        }
        
        //if pixel is at right side center
        if (i < height - 1 && i > 0 && j == width - 1)
        {
            //calculate all red average
            ravg_rscenter = (int) round((copy_image[i][j].rgbtRed + copy_image[i][j-1].rgbtRed + copy_image[i-1][j].rgbtRed + copy_image[i-1][j-1].rgbtRed + copy_image[i+1][j].rgbtRed + copy_image[i+1][j-1].rgbtRed) / 6.00);
            //calculate all green average
            gavg_rscenter = (int) round((copy_image[i][j].rgbtGreen + copy_image[i][j-1].rgbtGreen + copy_image[i-1][j].rgbtGreen + copy_image[i-1][j-1].rgbtGreen + copy_image[i+1][j].rgbtGreen + copy_image[i+1][j-1].rgbtGreen) / 6.00);
            //calculate all blue average
            bavg_rscenter = (int) round((copy_image[i][j].rgbtBlue + copy_image[i][j-1].rgbtBlue + copy_image[i-1][j].rgbtBlue + copy_image[i-1][j-1].rgbtBlue + copy_image[i+1][j].rgbtBlue + copy_image[i+1][j-1].rgbtBlue) / 6.00);
            
            //new pixel color
            image[i][j].rgbtRed = ravg_rscenter;
            image[i][j].rgbtGreen = gavg_rscenter;
            image[i][j].rgbtBlue = bavg_rscenter;
        }
        
        //if pixel is at center
        if (i < height - 1 && i > 0 && j < width - 1 && j > 0)
        {
            //calculate all red average
            ravg_center = (int) round((copy_image[i][j].rgbtRed + copy_image[i][j-1].rgbtRed + copy_image[i][j+1].rgbtRed + copy_image[i+1][j+1].rgbtRed + copy_image[i+1][j].rgbtRed + copy_image[i+1][j-1].rgbtRed + copy_image[i-1][j-1].rgbtRed + copy_image[i-1][j].rgbtRed + copy_image[i-1][j+1].rgbtRed) / 9.00);
            //calculate all green average
            gavg_center = (int) round((copy_image[i][j].rgbtGreen + copy_image[i][j-1].rgbtGreen + copy_image[i][j+1].rgbtGreen + copy_image[i+1][j+1].rgbtGreen + copy_image[i+1][j].rgbtGreen + copy_image[i+1][j-1].rgbtGreen + copy_image[i-1][j-1].rgbtGreen + copy_image[i-1][j].rgbtGreen + copy_image[i-1][j+1].rgbtGreen) / 9.00);
            //calculate all blue average
            bavg_center = (int) round((copy_image[i][j].rgbtBlue + copy_image[i][j-1].rgbtBlue + copy_image[i][j+1].rgbtBlue + copy_image[i+1][j+1].rgbtBlue + copy_image[i+1][j].rgbtBlue + copy_image[i+1][j-1].rgbtBlue + copy_image[i-1][j-1].rgbtBlue + copy_image[i-1][j].rgbtBlue + copy_image[i-1][j+1].rgbtBlue) / 9.00);
            
            //new pixel color
            image[i][j].rgbtRed = ravg_center;
            image[i][j].rgbtGreen = gavg_center;
            image[i][j].rgbtBlue = bavg_center;
        }
        
    }
}

return;}

好的,下次把你的类型定义包含在问题中,这样人们就可以避免猜测。

我建议通过避免复制和粘贴来简化它。这应该是一个规则:“如果你复制粘贴,你就做错了”。

所以我们可以遍历图像,遍历 3x3 邻域,对值求和并计算我们有多少有效像素。然后我们除以该计数。我避免了四舍五入并坚持使用更简单的截断,但如果你真的想四舍五入,用整数来做,不要仅仅为此使用浮点数。

这三个函数是为了让代码更简洁,可以用重复的代码代替。

我的意见:不要使用带名称的 RGB 三元组,而更喜欢具有 3 个元素的数组,这样您可以更轻松地循环通道。我强烈建议避免使用 VLA。 Visual Studio 不支持它们,使用起来很痛苦。

最后,您的“复制图像”将未定义的数据无用地交换到图像中。

最后,我没有测试这段代码!

#include <stdint.h>
#include <string.h>

typedef struct tagRGBTRIPLE {
    uint8_t rgbtRed, rgbtGreen, rgbtBlue;
} RGBTRIPLE;

RGBTRIPLE rgbtMake(int r, int g, int b) 
{
    RGBTRIPLE out = { r, g, b };
    return out;
}
void rgbtIntAdd(int *r, int *g, int *b, RGBTRIPLE *t)
{
    *r += t->rgbtRed;
    *g += t->rgbtGreen;
    *b += t->rgbtBlue;
}
void rgbtIntDiv(int *r, int *g, int *b, int div)
{
    *r /= div;
    *g /= div;
    *b /= div;
}

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE copy_image[height][width];

    //create copy of image canvas
    memcpy(copy_image, image, height * width * sizeof(RGBTRIPLE));

    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            int r = 0, g = 0, b = 0, count = 0;
            for (int m = -1; m <= 1; ++m) {
                if (i + m < 0 || i + m >= height) {
                    continue;
                }
                for (int n = -1; n <= 1; ++n) {
                    if (j + n < 0 || j + n >= width) {
                        continue;
                    }
                    rgbtIntAdd(&r, &g, &b, &copy_image[i + m][j + n]);
                    ++count;
                }
            }
            rgbtIntDiv(&r, &g, &b, count);

            image[i][j] = rgbtMake(r, g, b);
        }
    }
}