CS50-出现pset4过滤器“模糊"问题 [英] CS50 - Issue with pset4 filter "blur"

查看:66
本文介绍了CS50-出现pset4过滤器“模糊"问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

My blur function is behaving oddly. I've recreated the 3x3 bitmap from check50 to get more approximate results from my tests but, for some reason, every right or lower edge pixels are not working properly.

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

While debugging, I've found that, for some reason, my for loops are not behaving properly. I'll show my code and an example below.

代码:

// 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;
}

这是 输出.

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

As an example of what I've found during the debug, let's say that:

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)获取值.

Here, instead of sumRed getting the value of image[0 - 0][2 - 0] (RGB 70, 80, 90), it's getting the values from image[2][2] (RGB 240, 250, 255).

我还没有测试其他错误情况,但是我想那里正在发生类似的事情.

I've not yet tested the other error cases, but I suppose something similar is happening there.

任何帮助将不胜感激.

推荐答案

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

This is prefaced by my top comment:

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

It might be better if counter were an int. Then, do: round((double) sumRed / counter), But, the output cell is only eight bits. You may need: sumRed = round((double) sumRed / counter); temp[i][j].rgbtRed = (sumRed < 255) ? sumRed : 255; This is saturation math. Otherwise, when you assign to an 8 bit cell, it's modulo math, equivalent to sumRed % 256. That would yield 257 --> 1 (nearly black) instead of 257 --> 255 (bright red)

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

Your biggest problem is that your convolution kernel index calculations are incorrect.

代替:

(i - k)
(j - m)

您想要:

(i + k)
(j + m)

此外,您将要从temp复制回image的最终循环的限制为1.

Also, your the limits on your final loops to copy back from temp to image are off by 1.

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

Plus, I'd use more descriptive variables. And, your code can be simplified a bit. Here's a refactored version that incorporates the bug fixes:

#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
}

这篇关于CS50-出现pset4过滤器“模糊"问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆