CS50-pset4过滤器“模糊”的问题

时间:2020-04-23 18:02:16

标签: c filter blur cs50

我的模糊功能表现异常。我已经从check50重新创建了3x3位图,以便从测试中获得更多近似结果,但是由于某些原因,每个右边缘或下边缘像素均无法正常工作。

在调试时,由于某种原因,我发现我的for循环运行不正常。我将在下面显示我的代码和示例。

代码:

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE temp[height][width]; // Declares temporary structure to avoid overwriting of original values while running loops

    // For loop to set the value of i, rows or height
    for (int i = 0; i < height; i++)
    {
        // For loop to set the value of j, columns or width
        for (int j = 0; j < width; j++)
        {
            float counter = 0.0;
            int sumRed = 0;
            int sumGreen = 0;
            int sumBlue = 0;

            // For loop to set the value of k, to get surrounding pixels
            for (int k = -1; k < 2; k++)
            {
                for (int m = -1; m < 2; m++)
                {
                    if ((i - k) >= 0 && (i - k) < height && (j - m) >= 0 && (j - m) < width)
                    {
                        sumRed = sumRed + image[i - k][j - m].rgbtRed; // Adds the value of verified pixel to the sum
                        sumGreen = sumGreen + image[i - k][j - m].rgbtGreen;
                        sumBlue = sumBlue + image[i - k][j - m].rgbtBlue;
                        counter++; // To get the average
                    }
                }
            }

            temp[i][j].rgbtRed = round(sumRed / counter); // Sets new color based on average of surrounding pixels
            temp[i][j].rgbtGreen = round(sumGreen / counter);
            temp[i][j].rgbtBlue = round(sumBlue / counter);
        }
    }

    // Start new loops to switch original values with temp values
    for (int i = 0; i < height - 1; i++)
    {
        for (int j = 0; j < width - 1; j++)
        {
            image[i][j].rgbtRed = temp[i][j].rgbtRed;
            image[i][j].rgbtGreen = temp[i][j].rgbtGreen;
            image[i][j].rgbtBlue = temp[i][j].rgbtBlue;
        }
    }

    return;
}

这是 output

作为我在调试过程中发现的示例,我们可以这样说:

i = 0
j = 2
k = 0
m = 0

在这里,不是从sumRed获取image[0 - 0][2 - 0] (RGB 70, 80, 90)的值,而是从image[2][2] (RGB 240, 250, 255)获取值。

我尚未测试其他错误情况,但我想那里正在发生类似的情况。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

这是我的最高评价的开头:

如果counterint,可能会更好。然后,执行:round((double) sumRed / counter),但是,输出单元只有8位。您可能需要:sumRed = round((double) sumRed / counter); temp[i][j].rgbtRed = (sumRed < 255) ? sumRed : 255;这是饱和度数学。否则,当您分配给8位单元时,它是模数学,等效于sumRed % 256。这将产生257 --> 1(接近黑色)而不是257 --> 255(明亮的红色)

您最大的问题是卷积内核索引计算不正确。

代替:

(i - k)
(j - m)

您要

(i + k)
(j + m)

此外,您从temp复制到image的最终循环的限制为1。

此外,我将使用更多描述性变量。而且,您的代码可以简化一些。这是包含错误修复的重构版本:

#include <math.h>

typedef struct {
    unsigned char rgbtRed;
    unsigned char rgbtGreen;
    unsigned char rgbtBlue;
} __attribute__((__packed__)) RGBTRIPLE;

// Blur image
void
blur(int height, int width, RGBTRIPLE image[height][width])
{
    // Declares temporary structure to avoid overwriting of original values
    // while running loops
    RGBTRIPLE temp[height][width];
#if 1
    RGBTRIPLE *tmp;
    RGBTRIPLE *img;
#endif

    // For loop to set the value of yctr, rows or height
    for (int yctr = 0; yctr < height; yctr++) {
        // For loop to set the value of xctr, columns or width
        for (int xctr = 0; xctr < width; xctr++) {
#if 0
            float counter = 0.0;
#else
            int counter = 0;
#endif
            int sumRed = 0;
            int sumGreen = 0;
            int sumBlue = 0;

            // For loop to set the value of yoff, to get surrounding pixels
            for (int yoff = -1; yoff < 2; yoff++) {
// NOTE/BUG: this is the main bug
#if 0
                int ycur = yctr - yoff;
#else
                int ycur = yctr + yoff;
#endif
                if (ycur < 0)
                    continue;
                if (ycur >= height)
                    continue;

                for (int xoff = -1; xoff < 2; xoff++) {
// NOTE/BUG: this is the main bug
#if 0
                    int xcur = xctr - xoff;
#else
                    int xcur = xctr + xoff;
#endif
                    if (xcur < 0)
                        continue;
                    if (xcur >= width)
                        continue;

                    // Adds the value of verified pixel to the sum
                    tmp = &image[ycur][xcur];
                    sumRed += tmp->rgbtRed;
                    sumGreen += tmp->rgbtGreen;
                    sumBlue += tmp->rgbtBlue;
                    counter++;      // To get the average
                }
            }

            // Sets new color based on average of surrounding pixels
            tmp = &temp[yctr][xctr];

#if 0
            tmp->rgbtRed = round(sumRed / counter);
            tmp->rgbtGreen = round(sumGreen / counter);
            tmp->rgbtBlue = round(sumBlue / counter);
#else

            sumRed = round((double) sumRed / counter);
            tmp->rgbtRed = (sumRed < 255) ? sumRed : 255;

            sumGreen = round((double) sumGreen / counter);
            tmp->rgbtGreen = (sumGreen < 255) ? sumGreen : 255;

            sumBlue = round((double) sumBlue / counter);
            tmp->rgbtBlue = (sumBlue < 255) ? sumBlue : 255;
#endif
        }
    }

    // Start new loops to switch original values with temp values
// NOTE/BUG: the for loop ranges are incorrect
#if 0
    for (int yctr = 0; yctr < height - 1; yctr++) {
        for (int xctr = 0; xctr < width - 1; xctr++) {
            image[yctr][xctr].rgbtRed = temp[yctr][xctr].rgbtRed;
            image[yctr][xctr].rgbtGreen = temp[yctr][xctr].rgbtGreen;
            image[yctr][xctr].rgbtBlue = temp[yctr][xctr].rgbtBlue;
        }
    }
#endif

#if 0
    for (int yctr = 0; yctr < height; yctr++) {
        for (int xctr = 0; xctr < width; xctr++) {
            image[yctr][xctr] = temp[yctr][xctr];
        }
    }
#endif

#if 1
    tmp = &temp[0][0];
    img = &image[0][0];

    int idxlim = width * height;
    for (int idxcur = 0; idxcur < idxlim; idxcur++)
        img[idxcur] = tmp[idxcur];
#endif
}