在 C 中使用“框模糊”技术模糊 image.bmp

问题描述 投票:0回答:2

所以在这个项目中,我需要获取一个 image.bmp 文件并使用“框模糊”对其进行模糊处理。

方框模糊说明如下:

对于这个问题,我们将使用“框模糊”,它的工作原理是获取每个像素,并针对每个颜色值,通过对相邻像素的颜色值进行平均来为其赋予一个新值。

(示例)每个像素的新值将是原始像素 1 行和列内的所有像素值的平均值(形成 3x3 框)。例如,像素 6 的每个颜色值将通过对像素 1、2、3、5、6、7、9、10 和 11 的原始颜色值进行平均来获得(请注意,像素 6 本身包含在平均的)。同样,像素 11 的颜色值可以通过对像素 6、7、8、10、11、12、14、15 和 16 的颜色值进行平均来获得。

对于沿着边缘或角的像素,例如像素 15,我们仍然会查找 1 行和 1 列内的所有像素:在本例中,为像素 10、11、12、14、15 和 16。

现在我知道我的代码有点长而且业余,但这只是因为我是业余爱好者,但我在没有任何帮助的情况下走到了这一步:

void blur(int height, int width, RGBTRIPLE image[height][width])
{
    // iterate through every row
    for (int i = 0; i < height; i++) 
    {
        //for every column
        for (int j = 0; j < width; j++) 
        {
            int avRed = 0;
            int avGreen = 0;
            int avBlue = 0;
            
             // check if the current index is an index of an edge 
            if ((i == 0 && (j >= 0 && j <= width - 1)) 
                || ((i >= 0 && i <= height - 1) && j == 0) 
                || (i == height - 1 && (j >= 0 && j <= width - 1)) 
                || ((i >= 0 && i <= height -1) && j == width - 1))
            {
                // if it is : check if it is a corner
                if ((i == 0 && j == 0) 
                    || (i == 0 && j == width - 1) 
                    || (i == height - 1 && j == 0) 
                    || (i == height - 1 && j == width - 1)) 
                {
                    if (i == 0 && j == 0)
                    {
                        avRed = round((image[i][j].rgbtRed + image[i + 1][j].rgbtRed + image[i + 1][j + 1].rgbtRed + image[i][j + 1].rgbtRed) / 4.0);
                        avGreen = round((image[i][j].rgbtGreen + image[i + 1][j].rgbtGreen + image[i + 1][j + 1].rgbtGreen + image[i][j + 1].rgbtGreen) / 4.0);
                        avBlue = round((image[i][j].rgbtBlue + image[i + 1][j].rgbtBlue + image[i + 1][j + 1].rgbtBlue + image[i][j + 1].rgbtBlue) / 4.0);
                        image[i][j].rgbtRed = avRed;
                        image[i][j].rgbtGreen = avGreen;
                        image[i][j].rgbtBlue = avBlue;
                    }

                    if (i == 0 && j == width - 1)
                    {
                        avRed = round((image[i][j].rgbtRed + image[i +1 ][j].rgbtRed + image[i + 1][j - 1].rgbtRed + image[i][j - 1].rgbtRed) / 4.0);
                        avGreen = round((image[i][j].rgbtGreen + image[i + 1][j].rgbtGreen + image[i + 1][j - 1].rgbtGreen + image[i][j - 1].rgbtGreen) / 4.0);
                        avBlue = round((image[i][j].rgbtBlue + image[i + 1][j].rgbtBlue + image[i + 1][j - 1].rgbtBlue + image[i][j - 1].rgbtBlue) / 4.0);
                        image[i][j].rgbtRed = avRed;
                        image[i][j].rgbtGreen = avGreen;
                        image[i][j].rgbtBlue = avBlue;
                    }

                    if(i == height - 1 && j == 0)
                    {
                        avRed = round((image[i][j].rgbtRed + image[i - 1][j].rgbtRed + image[i - 1][j + 1].rgbtRed + image[i][j + 1].rgbtRed) / 4.0);
                        avGreen= round((image[i][j].rgbtGreen + image[i - 1][j].rgbtGreen + image[i - 1][j + 1].rgbtGreen + image[i][j + 1].rgbtGreen) / 4.0);
                        avRed = round((image[i][j].rgbtBlue + image[i - 1][j].rgbtBlue + image[i - 1][j + 1].rgbtBlue + image[i][j + 1].rgbtBlue) / 4.0);
                        image[i][j].rgbtRed = avRed;
                        image[i][j].rgbtGreen = avGreen;
                        image[i][j].rgbtBlue = avBlue;
                    }

                    if (i == height - 1 && j == width - 1)
                    {
                        avRed = round((image[i][j].rgbtRed + image[i - 1][j].rgbtRed + image[i - 1][j - 1].rgbtRed + image[i][j - 1].rgbtRed) / 4.0);
                        avGreen = round((image[i][j].rgbtGreen + image[i - 1][j].rgbtGreen + image[i - 1][j - 1].rgbtGreen + image[i][j - 1].rgbtGreen) / 4.0);
                        avBlue = round((image[i][j].rgbtBlue + image[i - 1][j].rgbtBlue + image[i - 1][j - 1].rgbtBlue + image[i][j - 1].rgbtBlue) / 4.0);
                        image[i][j].rgbtRed = avRed;
                        image[i][j].rgbtGreen = avGreen;
                        image[i][j].rgbtBlue = avBlue;
                    }
                }
                else // if it is not a corner index
                {
                    if (i == 0 && (j >= 1 && j <= width - 2))
                    {
                        avRed = round((image[i][j].rgbtRed + image[i][j - 1].rgbtRed + image[i][j + 1].rgbtRed + image[i + 1][j].rgbtRed + image[i + 1][j - 1].rgbtRed + image[i + 1][j + 1].rgbtRed) / 6.0);
                        avGreen = round((image[i][j].rgbtGreen + image[i][j - 1].rgbtGreen + image[i][j + 1].rgbtGreen + image[i + 1][j].rgbtGreen + image[i + 1][j - 1].rgbtGreen + image[i + 1][j + 1].rgbtGreen) / 6.0);
                        avBlue = round((image[i][j].rgbtBlue + image[i][j - 1].rgbtBlue + image[i][j + 1].rgbtBlue + image[i + 1][j].rgbtBlue + image[i + 1][j - 1].rgbtBlue + image[i + 1][j + 1].rgbtBlue) / 6.0);
                        image[i][j].rgbtRed = avRed;
                        image[i][j].rgbtGreen = avGreen;
                        image[i][j].rgbtBlue = avBlue;
                    }

                    if ((i >= 1 && i <= height - 2) && j == 0)
                    {
                        avRed = round((image[i][j].rgbtRed + image[i - 1][j].rgbtRed + image[i + 1][j].rgbtRed + image[i][j + 1].rgbtRed + image[i - 1][j + 1].rgbtRed + image[i + 1][j + 1].rgbtRed) / 6.0);
                        avGreen = round((image[i][j].rgbtGreen + image[i - 1][j].rgbtGreen + image[i + 1][j].rgbtGreen + image[i][j + 1].rgbtGreen + image[i - 1][j + 1].rgbtGreen + image[i + 1][j + 1].rgbtGreen) / 6.0);
                        avBlue = round((image[i][j].rgbtBlue + image[i - 1][j].rgbtBlue + image[i + 1][j].rgbtBlue + image[i][j + 1].rgbtBlue + image[i - 1][j + 1].rgbtBlue + image[i + 1][j + 1].rgbtBlue) / 6.0);
                        image[i][j].rgbtRed = avRed;
                        image[i][j].rgbtGreen = avGreen;
                        image[i][j].rgbtBlue = avBlue;
                    }

                    if (i == height - 1 && (j >= 1 && j <= width - 2))
                    {
                        avRed = round((image[i][j].rgbtRed + image[i - 1][j].rgbtRed + image[i][j - 1].rgbtRed + image[i][j + 1].rgbtRed + image[i - 1][j + 1].rgbtRed + image[i - 1][j - 1].rgbtRed) / 6.0);
                        avGreen = round((image[i][j].rgbtGreen + image[i - 1][j].rgbtGreen + image[i][j - 1].rgbtGreen + image[i][j + 1].rgbtGreen + image[i - 1][j + 1].rgbtGreen + image[i - 1][j - 1].rgbtGreen) / 6.0);
                        avBlue = round((image[i][j].rgbtBlue + image[i - 1][j].rgbtBlue + image[i][j - 1].rgbtBlue + image[i][j + 1].rgbtBlue + image[i - 1][j + 1].rgbtBlue + image[i - 1][j - 1].rgbtBlue) / 6.0);
                        image[i][j].rgbtRed = avRed;
                        image[i][j].rgbtGreen = avGreen;
                        image[i][j].rgbtBlue = avBlue;
                    }

                    if ((i >= 1 && i <= height -2) && j == width - 1)
                    {
                        avRed = round((image[i][j].rgbtRed + image[i - 1][j].rgbtRed + image[i + 1][j].rgbtRed + image[i][j - 1].rgbtRed + image[i - 1][j - 1].rgbtRed + image[i + 1][j - 1].rgbtRed) / 6.0);
                        avGreen = round((image[i][j].rgbtGreen + image[i - 1][j].rgbtGreen + image[i + 1][j].rgbtGreen + image[i][j - 1].rgbtGreen + image[i - 1][j - 1].rgbtGreen + image[i + 1][j - 1].rgbtGreen) / 6.0);
                        avBlue = round((image[i][j].rgbtBlue + image[i - 1][j].rgbtBlue + image[i + 1][j].rgbtBlue + image[i][j - 1].rgbtBlue + image[i - 1][j - 1].rgbtBlue + image[i + 1][j - 1].rgbtBlue) / 6.0);
                        image[i][j].rgbtRed = avRed;
                        image[i][j].rgbtGreen = avGreen;
                        image[i][j].rgbtBlue = avBlue;
                    }
                }
            }
            else // if it is not an index of an edge at all
            {
                avRed = round(((image[i - 1][j - 1].rgbtRed) + (image[i - 1][j].rgbtRed) + (image[i - 1][j + 1].rgbtRed) + (image[i][j - 1].rgbtRed) + (image[i][j].rgbtRed) + (image[i][j + 1].rgbtRed) + (image[i + 1][j - 1].rgbtRed) + (image[i + 1][j].rgbtRed) + (image[i + 1][j + 1].rgbtRed)) / 9.0);
                avGreen = round(((image[i - 1][j - 1].rgbtGreen) + (image[i - 1][j].rgbtGreen) + (image[i - 1][j + 1].rgbtGreen) + (image[i][j - 1].rgbtGreen) + (image[i][j].rgbtGreen) + (image[i][j + 1].rgbtGreen) + (image[i + 1][j - 1].rgbtGreen) + (image[i + 1][j].rgbtGreen) + (image[i + 1][j + 1].rgbtGreen)) / 9.0);
                avBlue = round(((image[i - 1][j - 1].rgbtBlue) + (image[i - 1][j].rgbtBlue) + (image[i - 1][j + 1].rgbtBlue) + (image[i][j - 1].rgbtBlue) + (image[i][j].rgbtBlue) + (image[i][j + 1].rgbtBlue) + (image[i + 1][j - 1].rgbtBlue) + (image[i + 1][j].rgbtBlue) + (image[i + 1][j + 1].rgbtBlue)) / 9.0);
                image[i][j].rgbtRed = avRed;
                image[i][j].rgbtGreen = avGreen;
                image[i][j].rgbtBlue = avBlue;
            }    
        }
    } 
    return;
}

此时,程序对图像进行了一定程度的模糊处理,但模糊程度不正确。当我通过 cs50 的预设测试用例对其进行测试时,我的 RGB 比率对于 corner 索引是正确的,但对于所有其他索引则不正确。为什么会发生这种情况?

c cs50
2个回答
1
投票

首先使用 forloop 将原始图像的像素复制到 RGBTRIPLE 类型的另一个变量中,如果不是第一个模糊像素会影响下一个要模糊的像素,那么你做数学运算。

这对我有用!

    // Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE copy[height][width];
    for (int i = 0; i < width; i++)
    {
        for (int j = 0; j < height; j++)
        {
            copy[i][j] = image[i][j];
        }
    }
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            // check for an edge
           if ((i == 0 && (j >= 0 && j <= width - 1))
                || ((i >= 0 && i <= height - 1) && j == 0)
                || (i == height - 1 && (j >= 0 && j <= width - 1))
                || ((i >= 0 && i <= height -1) && j == width - 1))
            {
                //check if it is a corner
                if ((i == 0 && j == 0)
                    || (i == 0 && j == width - 1)
                    || (i == height - 1 && j == 0)
                    || (i == height - 1 && j == width - 1))
                {
                    if (i == 0 && j == 0)
                    {
                        image[i][j].rgbtRed = (int) round((copy[i][j].rgbtRed + copy[i + 1][j].rgbtRed + copy[i + 1][j + 1].rgbtRed + copy[i][j + 1].rgbtRed) / 4.0);
                        image[i][j].rgbtGreen = (int) round((copy[i][j].rgbtGreen + copy[i + 1][j].rgbtGreen + copy[i + 1][j + 1].rgbtGreen + copy[i][j + 1].rgbtGreen) / 4.0);
                        image[i][j].rgbtBlue = (int) round((copy[i][j].rgbtBlue + copy[i + 1][j].rgbtBlue + copy[i + 1][j + 1].rgbtBlue + copy[i][j + 1].rgbtBlue) / 4.0);
                    }

                    if (i == 0 && j == width - 1)
                    {
                        image[i][j].rgbtRed = (int) round((copy[i][j].rgbtRed + copy[i +1 ][j].rgbtRed + copy[i + 1][j - 1].rgbtRed + copy[i][j - 1].rgbtRed) / 4.0);
                        image[i][j].rgbtGreen = (int) round((copy[i][j].rgbtGreen + copy[i + 1][j].rgbtGreen + copy[i + 1][j - 1].rgbtGreen + copy[i][j - 1].rgbtGreen) / 4.0);
                        image[i][j].rgbtBlue = (int) round((copy[i][j].rgbtBlue + copy[i + 1][j].rgbtBlue + copy[i + 1][j - 1].rgbtBlue + copy[i][j - 1].rgbtBlue) / 4.0);
                    }

                    if (i == height - 1 && j == 0)
                    {
                        image[i][j].rgbtRed = (int) round((copy[i][j].rgbtRed + copy[i - 1][j].rgbtRed + copy[i - 1][j + 1].rgbtRed + copy[i][j + 1].rgbtRed) / 4.0);
                        image[i][j].rgbtGreen = (int) round((copy[i][j].rgbtGreen + copy[i - 1][j].rgbtGreen + copy[i - 1][j + 1].rgbtGreen + copy[i][j + 1].rgbtGreen) / 4.0);
                        image[i][j].rgbtBlue = (int) round((copy[i][j].rgbtBlue + copy[i - 1][j].rgbtBlue + copy[i - 1][j + 1].rgbtBlue + copy[i][j + 1].rgbtBlue) / 4.0);
                    }

                    if (i == height - 1 && j == width - 1)
                    {
                        image[i][j].rgbtRed = (int) round((copy[i][j].rgbtRed + copy[i - 1][j].rgbtRed + copy[i - 1][j - 1].rgbtRed + copy[i][j - 1].rgbtRed) / 4.0);
                        image[i][j].rgbtGreen = (int) round((copy[i][j].rgbtGreen + copy[i - 1][j].rgbtGreen + copy[i - 1][j - 1].rgbtGreen + copy[i][j - 1].rgbtGreen) / 4.0);
                        image[i][j].rgbtBlue = (int) round((copy[i][j].rgbtBlue + copy[i - 1][j].rgbtBlue + copy[i - 1][j - 1].rgbtBlue + copy[i][j - 1].rgbtBlue) / 4.0);
                    }
                }
                // if not a corner index
                else
                {
                    if (i == 0 && (j >= 1 && j <= width - 2))
                    {
                        image[i][j].rgbtRed = (int) round((copy[i][j].rgbtRed + copy[i][j - 1].rgbtRed + copy[i][j + 1].rgbtRed + copy[i + 1][j].rgbtRed + copy[i + 1][j - 1].rgbtRed + copy[i + 1][j + 1].rgbtRed) / 6.0);
                        image[i][j].rgbtGreen = (int) round((copy[i][j].rgbtGreen + copy[i][j - 1].rgbtGreen + copy[i][j + 1].rgbtGreen + copy[i + 1][j].rgbtGreen + copy[i + 1][j - 1].rgbtGreen + copy[i + 1][j + 1].rgbtGreen) / 6.0);
                        image[i][j].rgbtBlue = (int) round((copy[i][j].rgbtBlue + copy[i][j - 1].rgbtBlue + copy[i][j + 1].rgbtBlue + copy[i + 1][j].rgbtBlue + copy[i + 1][j - 1].rgbtBlue + copy[i + 1][j + 1].rgbtBlue) / 6.0);
                    }

                    if ((i >= 1 && i <= height - 2) && j == 0)
                    {
                        image[i][j].rgbtRed = (int) round((copy[i][j].rgbtRed + copy[i - 1][j].rgbtRed + copy[i + 1][j].rgbtRed + copy[i][j + 1].rgbtRed + copy[i - 1][j + 1].rgbtRed + copy[i + 1][j + 1].rgbtRed) / 6.0);
                        image[i][j].rgbtGreen = (int) round((copy[i][j].rgbtGreen + copy[i - 1][j].rgbtGreen + copy[i + 1][j].rgbtGreen + copy[i][j + 1].rgbtGreen + copy[i - 1][j + 1].rgbtGreen + copy[i + 1][j + 1].rgbtGreen) / 6.0);
                        image[i][j].rgbtBlue = (int) round((copy[i][j].rgbtBlue + copy[i - 1][j].rgbtBlue + copy[i + 1][j].rgbtBlue + copy[i][j + 1].rgbtBlue + copy[i - 1][j + 1].rgbtBlue + copy[i + 1][j + 1].rgbtBlue) / 6.0);
                    }

                    if (i == height - 1 && (j >= 1 && j <= width - 2))
                    {
                        image[i][j].rgbtRed = (int) round((copy[i][j].rgbtRed + copy[i - 1][j].rgbtRed + copy[i][j - 1].rgbtRed + copy[i][j + 1].rgbtRed + copy[i - 1][j + 1].rgbtRed + copy[i - 1][j - 1].rgbtRed) / 6.0);
                        image[i][j].rgbtGreen = (int) round((copy[i][j].rgbtGreen + copy[i - 1][j].rgbtGreen + copy[i][j - 1].rgbtGreen + copy[i][j + 1].rgbtGreen + copy[i - 1][j + 1].rgbtGreen + copy[i - 1][j - 1].rgbtGreen) / 6.0);
                        image[i][j].rgbtBlue = (int) round((copy[i][j].rgbtBlue + copy[i - 1][j].rgbtBlue + copy[i][j - 1].rgbtBlue + copy[i][j + 1].rgbtBlue + copy[i - 1][j + 1].rgbtBlue + copy[i - 1][j - 1].rgbtBlue) / 6.0);
                    }

                    if ((i >= 1 && i <= height -2) && j == width - 1)
                    {
                        image[i][j].rgbtRed = (int) round((copy[i][j].rgbtRed + copy[i - 1][j].rgbtRed + copy[i + 1][j].rgbtRed + copy[i][j - 1].rgbtRed + copy[i - 1][j - 1].rgbtRed + copy[i + 1][j - 1].rgbtRed) / 6.0);
                        image[i][j].rgbtGreen = (int) round((copy[i][j].rgbtGreen + copy[i - 1][j].rgbtGreen + copy[i + 1][j].rgbtGreen + copy[i][j - 1].rgbtGreen + copy[i - 1][j - 1].rgbtGreen + copy[i + 1][j - 1].rgbtGreen) / 6.0);
                        image[i][j].rgbtBlue = (int) round((copy[i][j].rgbtBlue + copy[i - 1][j].rgbtBlue + copy[i + 1][j].rgbtBlue + copy[i][j - 1].rgbtBlue + copy[i - 1][j - 1].rgbtBlue + copy[i + 1][j - 1].rgbtBlue) / 6.0);
                    }
                }
            }
            // for normal pixel no edge at all
            else
            {
                image[i][j].rgbtRed = (int) round(((copy[i - 1][j - 1].rgbtRed) + (copy[i - 1][j].rgbtRed) + (copy[i - 1][j + 1].rgbtRed) + (copy[i][j - 1].rgbtRed) + (copy[i][j].rgbtRed) + (copy[i][j + 1].rgbtRed) + (copy[i + 1][j - 1].rgbtRed) + (copy[i + 1][j].rgbtRed) + (copy[i + 1][j + 1].rgbtRed)) / 9.0);
                image[i][j].rgbtGreen = (int) round(((copy[i - 1][j - 1].rgbtGreen) + (copy[i - 1][j].rgbtGreen) + (copy[i - 1][j + 1].rgbtGreen) + (copy[i][j - 1].rgbtGreen) + (copy[i][j].rgbtGreen) + (copy[i][j + 1].rgbtGreen) + (copy[i + 1][j - 1].rgbtGreen) + (copy[i + 1][j].rgbtGreen) + (copy[i + 1][j + 1].rgbtGreen)) / 9.0);
                image[i][j].rgbtBlue = (int) round(((copy[i - 1][j - 1].rgbtBlue) + (copy[i - 1][j].rgbtBlue) + (copy[i - 1][j + 1].rgbtBlue) + (copy[i][j - 1].rgbtBlue) + (copy[i][j].rgbtBlue) + (copy[i][j + 1].rgbtBlue) + (copy[i + 1][j - 1].rgbtBlue) + (copy[i + 1][j].rgbtBlue) + (copy[i + 1][j + 1].rgbtBlue)) / 9.0);
            }

        }
    }

    return;
}

0
投票

虽然您可以继续执行上面的代码,但您可以尝试迭代内核本身,如下例所示,这可能更具可读性且更少重复 `

void blur(int height, int width, RGBTRIPLE image[height][width])
{
    // Creating a copy of the image to keep original pixels when doing math
    RGBTRIPLE (*copy)[width] = calloc(height, width * sizeof(RGBTRIPLE));

    // Checking if the pointer isn't null
    if (copy == NULL)
    {
        return;
    }

    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            copy[i][j] = image[i][j];
        }
    }

    // Iterating over the whole image
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            // Declaring and resetting gradients' values
            int sum_red = 0, sum_green = 0, sum_blue = 0;
            int counter = 0;

            // Iterating over a 3x3 kernel
            for (int ki = -1; ki < 2; ki++)
            {
                for (int kj = -1; kj < 2; kj++)
                {
                    // Creating the new indices using the 3x3 kernel
                    int new_i = i + ki;
                    int new_j = j + kj;

                    // Considering the edges
                    if (new_i >= 0 && new_i < height && new_j >= 0 && new_j < width)
                    {
                        // Updating variables to further calculate the average
                        sum_red += copy[new_i][new_j].rgbtRed;
                        sum_green += copy[new_i][new_j].rgbtGreen;
                        sum_blue += copy[new_i][new_j].rgbtBlue;
                        counter++;
                    }

                    // Calculating the average value for each gradient
                    float avg_red = sum_red / (float) counter;
                    float avg_green = sum_green / (float) counter;
                    float avg_blue = sum_blue / (float) counter;

                    // Update the value in the original image
                    image[i][j].rgbtRed = round(avg_red);
                    image[i][j].rgbtGreen = round(avg_green);
                    image[i][j].rgbtBlue = round(avg_blue);
                }
            }
        }
    }

    // Clearing dynamically allocated memory
    free(copy);
    return;
}` 
© www.soinside.com 2019 - 2024. All rights reserved.