CS50 第 4 周模糊滤镜,图像模糊但检查 50 个值错误

CS50 Week 4 Blur Filter, have blurred image but check50 values wrong

我的 check50 有问题,我想知道我所做的是否真的得到了正确的盒子。

模糊的目标是获取所有灰色框的颜色并取平均

对于每个像素,如果像素不在第一行,我知道我可以有顶框。如果像素不在底行,我知道我可以有底框。与边缘相同的逻辑。

但也有像素在角落或边缘的情况

void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE arrayCopy[height][width]; 
    memcpy(arrayCopy, image, sizeof arrayCopy);

    for (int i = 0; i < height; i++)
    {
        for (int w = 0; w < width; w++)
        {
            int counter = 0;
            int totalRed = 0;
            int totalBlue = 0;
            int totalGreen = 0; 
            
            if (!(w == 0))
            {
                int leftBoxRed = arrayCopy[i][w-1].rgbtRed;
                int leftBoxBlue = arrayCopy[i][w-1].rgbtBlue;
                int leftBoxGreen = arrayCopy[i][w-1].rgbtGreen;
                
                totalRed = totalRed + leftBoxRed;
                totalBlue = totalBlue + leftBoxBlue;
                totalGreen = totalGreen + leftBoxGreen;
                counter++; 

                //printf("%i\n", leftBoxRed);
            }

            if (!(w == width-1))
            {
                int rightBoxRed = arrayCopy[i][w+1].rgbtRed;
                int rightBoxBlue = arrayCopy[i][w+1].rgbtBlue;
                int rightBoxGreen = arrayCopy[i][w+1].rgbtGreen;
                
                totalRed = totalRed + rightBoxRed; 
                totalBlue = totalBlue + rightBoxBlue;
                totalGreen = totalGreen + rightBoxGreen;
                counter++;
            }

            if (!(i == 0))
            {
                if (!(w == 0))
                {
                    int leftTopBoxRed = arrayCopy[i-1][w-1].rgbtRed;
                    int leftTopBoxBlue = arrayCopy[i-1][w-1].rgbtBlue;
                    int leftTopBoxGreen = arrayCopy[i-1][w-1].rgbtGreen; 
                    
                    totalRed = totalRed + leftTopBoxRed; 
                    totalBlue = totalBlue + leftTopBoxBlue;
                    totalGreen = totalGreen + leftTopBoxGreen;
                    counter++; 
                }
                
                if (!(w == width - 1))
                {
                    int rightTopBoxRed = arrayCopy[i-1][w+1].rgbtRed;
                    int rightTopBoxBlue = arrayCopy[i-1][w+1].rgbtBlue;
                    int rightTopBoxGreen = arrayCopy[i-1][w+1].rgbtGreen; 
                    
                    totalRed = totalRed + rightTopBoxRed; 
                    totalBlue = totalBlue + rightTopBoxBlue;
                    totalGreen = totalGreen + rightTopBoxGreen; 
                    counter++;
                }
                
                int topBoxRed = arrayCopy[i-1][w].rgbtRed;
                int topBoxBlue = arrayCopy[i-1][w].rgbtBlue;
                int topBoxGreen = arrayCopy[i-1][w].rgbtGreen;
                
                totalRed = totalRed + topBoxRed; 
                totalBlue = totalBlue + topBoxBlue; 
                totalGreen = totalGreen + topBoxGreen;
                counter++; 
            }

            if (!(i == height-1))
            {
                
                if (!(w == 0))
                {
                    int leftBottomBoxRed = arrayCopy[i+1][w-1].rgbtRed;
                    int leftBottomBoxBlue = arrayCopy[i+1][w-1].rgbtBlue;
                    int leftBottomBoxGreen = arrayCopy[i+1][w-1].rgbtGreen;
                    
                    totalRed = totalRed + leftBottomBoxRed; 
                    totalBlue = totalBlue + leftBottomBoxBlue;
                    totalGreen = totalGreen + leftBottomBoxGreen; 
                    counter++;
                }
                
                if (!(w == width - 1))
                {
                    int rightBottomBoxRed = arrayCopy[i+1][w+1].rgbtRed;
                    int rightBottomBoxBlue = arrayCopy[i+1][w+1].rgbtBlue;
                    int rightBottomBoxGreen = arrayCopy[i+1][w+1].rgbtGreen;
                    
                    totalRed = totalRed + rightBottomBoxRed; 
                    totalBlue = totalBlue + rightBottomBoxBlue;
                    totalGreen = totalGreen + rightBottomBoxGreen;
                    counter++; 
                }
                
                int bottomBoxRed = arrayCopy[i+1][w].rgbtRed;
                int bottomBoxBlue = arrayCopy[i+1][w].rgbtBlue;
                int bottomBoxGreen = arrayCopy[i+1][w].rgbtGreen;
                counter++;
                
                totalRed = totalRed + bottomBoxRed; 
                totalBlue = totalBlue + bottomBoxBlue;
                totalGreen = totalGreen + bottomBoxGreen;
                
            }
            
            
            float averageRed = totalRed / (float) counter; 
            float averageBlue = totalBlue / (float) counter;
            float averageGreen = totalGreen / (float) counter;
            
        
            
            image[i][w].rgbtRed = (int) roundf(averageRed); 
            image[i][w].rgbtBlue = (int) roundf(averageBlue);
            image[i][w].rgbtGreen = (int) roundf(averageGreen);
                
            //printf("%i\n", (int) roundf(averageRed));
        }
    }

    return;
}


原图 我的图像输出

在第一个失败的休息结果中(顺便说一下,请避免在您的问题中放置文本图像),您应该为中间像素的红色分量计算一个值 127。你计算了 128.

这张图片中九个像素点的红色分量如下:

 10  40  70
110 120 130
200 220 240

如果正如您在问题顶部所说的那样,您应该计算中心像素周围八个像素的平均值,那么您将得到一个值 (10+40+70+ 110+130+200+220+240)/8,等于127.5。 roundf() 函数将远离零的中途情况四舍五入,因此从外观上看,您获得了 128 作为结果的正确答案。

但是,我怀疑您实际上应该计算所有九个像素的平均值,包括中心像素。在这种情况下,结果将是 (10+40+70+110+120+130+200+220+240)/9,roundf() 将从 126.67 向上舍入到 127。

所以我认为您做错的只是忘记在计算中包含 arrayCopy[i][w] 处的像素。

我还应该指出您的代码非常 WET。像这样很容易忘记代码中发生的事情,调试也很困难。也许考虑使用内部循环来扫描每个(最多)九个像素的块。可能是这样的(注意:我根本没有测试过):

    for (int x=0; x<width; x++) {
        for (int y=0; y<height; y++) {
            int counter = 0;
            int totalr=0, totalg=0, totalb=0;
            for (int dx=-1; dx<=1; dx++) {
                if (x+dx < 0 || x+dx >= width) continue;
                for (int dy=-1; dy<=1; dy++) {
                    if (y+dy >=0 && y+dy < height) {
                        totalr += image[y+dy][x+dx].rgbtRed;
                        totalg += image[y+dy][x+dx].rgbtGreen;
                        totalb += image[y+dy][x+dx].rgbtBlue;
                        counter++;
                    }
                }
            }
            result[y][x].rgbtRed = roundf(totalr / (float)counter);
            result[y][x].rgbtGreen = roundf(totalg / (float)counter);
            result[y][x].rgbtBlue = roundf(totalb / (float)counter);
        }
    }