CS50 PSET4 BLUR函数不正确计算边缘和角落

发布于 2025-01-26 17:29:10 字数 2534 浏览 0 评论 0 原文

嘿,所以我被困在CS50 PST4上了一段时间,特别是在Blur上。 目的是创建一个通过将每个像素更改为周围图像的平均值来模糊图像的过滤器。

我首先要做的是创建图像的副本,以便当我不使用更改的像素时计算平均值。

为了计算侧面和角落,我将图片外像素的颜色制成的颜色为0。然后,我可以盲目地添加它并除以除,但是许多像素都在那里。角落周围有4个像素,所以我除以4个,边缘等于6等。

为了使我从[i -1] [j -1]到[i + 1] [i + 1] [j -1] [j -1] [j] [j] [j] [j] [j] [j] [j] + 1] 但是,似乎右侧和右侧的右侧未正确计算。

#include "helpers.h"
#include <stdio.h>
#include <math.h>
#include <stdbool.h>

void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE copy[height][width];
    for(int i = 0; i < height; i++)
    {
        for(int j = 0; j < width; j++)
        {
            for(int n = 0; n < 9; n++)
            {
                copy[i][j].rgbtRed = image[i][j].rgbtRed;
                copy[i][j].rgbtGreen = image[i][j].rgbtGreen;
                copy[i][j].rgbtBlue = image[i][j].rgbtBlue;
            }
        }
    }
    int rgbtRed, rgbtGreen, rgbtBlue;
    for(int i = 0; i < height; i++)
    {
        for(int j = 0; j < width; j++)
        {
            bool corner = false;
            rgbtRed = rgbtGreen = rgbtBlue = 0;
            for(int n = i - 1; n <= i + 1; n++)
            {
                for (int k = j - 1; k <= j + 1; k++)
                {
                    if(n < 0 || n > height || k < 0 || k > width)
                    {
                        copy[n][k].rgbtRed = copy[n][k].rgbtGreen = copy[n][k].rgbtBlue = 0;
                    }
                rgbtRed += copy[n][k].rgbtRed;
                rgbtGreen += copy[n][k].rgbtGreen;
                rgbtBlue += copy[n][k].rgbtBlue;
                }
            }
            if ((i == 0 && (j == 0 || j == width)) || (i == height && (j == 0 || j == width)))
            {
                image[i][j].rgbtRed = (rgbtRed / 4);
                image[i][j].rgbtGreen = (rgbtGreen / 4);
                image[i][j].rgbtBlue = (rgbtBlue / 4);
                corner = true;
            }
            else if (!corner && (i == 0 || i == height || j == 0 || j == width))
            {
                image[i][j].rgbtRed = (rgbtRed / 6);
                image[i][j].rgbtGreen = (rgbtGreen / 6);
                image[i][j].rgbtBlue = (rgbtBlue / 6);
            }
            else
            {
                image[i][j].rgbtRed = (rgbtRed / 9);
                image[i][j].rgbtGreen = (rgbtGreen / 9);
                image[i][j].rgbtBlue = (rgbtBlue / 9);
            }
        }
    }

感谢提供的Anyhelp

Hey, so I been stuck on the cs50 pst4 for a while now, specifically on blur.
The goal is to create a filter which blurs the image by changing each pixel to the average of the ones surrounding it.

What I did first is create a copy of the image so that I wouldn't use the changed pixels when calculating the average.

To calculate the sides and the corners i made the colors of pixels outside of the picture to 0. Then I could blindly add it and divide by however many pixels are there for ex. corners have 4 pixels surrounding it so i divide by 4, edges by 6 etc.

To get the positions I looped around image[i][j] from [i - 1][j - 1] to [i + 1][j + 1]
However it seems that the right and bottom right side aren't being calculated correctly.

#include "helpers.h"
#include <stdio.h>
#include <math.h>
#include <stdbool.h>

void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE copy[height][width];
    for(int i = 0; i < height; i++)
    {
        for(int j = 0; j < width; j++)
        {
            for(int n = 0; n < 9; n++)
            {
                copy[i][j].rgbtRed = image[i][j].rgbtRed;
                copy[i][j].rgbtGreen = image[i][j].rgbtGreen;
                copy[i][j].rgbtBlue = image[i][j].rgbtBlue;
            }
        }
    }
    int rgbtRed, rgbtGreen, rgbtBlue;
    for(int i = 0; i < height; i++)
    {
        for(int j = 0; j < width; j++)
        {
            bool corner = false;
            rgbtRed = rgbtGreen = rgbtBlue = 0;
            for(int n = i - 1; n <= i + 1; n++)
            {
                for (int k = j - 1; k <= j + 1; k++)
                {
                    if(n < 0 || n > height || k < 0 || k > width)
                    {
                        copy[n][k].rgbtRed = copy[n][k].rgbtGreen = copy[n][k].rgbtBlue = 0;
                    }
                rgbtRed += copy[n][k].rgbtRed;
                rgbtGreen += copy[n][k].rgbtGreen;
                rgbtBlue += copy[n][k].rgbtBlue;
                }
            }
            if ((i == 0 && (j == 0 || j == width)) || (i == height && (j == 0 || j == width)))
            {
                image[i][j].rgbtRed = (rgbtRed / 4);
                image[i][j].rgbtGreen = (rgbtGreen / 4);
                image[i][j].rgbtBlue = (rgbtBlue / 4);
                corner = true;
            }
            else if (!corner && (i == 0 || i == height || j == 0 || j == width))
            {
                image[i][j].rgbtRed = (rgbtRed / 6);
                image[i][j].rgbtGreen = (rgbtGreen / 6);
                image[i][j].rgbtBlue = (rgbtBlue / 6);
            }
            else
            {
                image[i][j].rgbtRed = (rgbtRed / 9);
                image[i][j].rgbtGreen = (rgbtGreen / 9);
                image[i][j].rgbtBlue = (rgbtBlue / 9);
            }
        }
    }

Thankful for anyhelp provided

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

草莓酥 2025-02-02 17:29:10

从问题来看,尚不清楚如何无法正确计算右侧和右下方。我运行您的代码,从我的角度来看,输出是不错的。尽管它会出现一些运行时错误。

这是一些建议。

if (n < 0 || n > height || k < 0 || k > width)
{
    copy[n][k].rgbtRed = copy[n][k].rgbtGreen = copy[n][k].rgbtBlue = 0;
}
rgbtRed += copy[n][k].rgbtRed;
rgbtGreen += copy[n][k].rgbtGreen;
rgbtBlue += copy[n][k].rgbtBlue;

我认为您正在尝试为边界案例设置特殊处理。对于上限,是否应该是 n&gt; =高度,因为它是基于零的索引?此外,您不必明确将像素设置为黑色。只需忽略它,不要将它们添加到平均值是可以的。但是您没有停在那儿,然后是 rgbtred += copy [n] [k] .rgbtred n 可以是-1或&gt;高度,它可能会从界限中击中数组索引。

另外,您设置了一个IF语句,具有3个条件,用于边缘,角落和入站情况。您不需要。您只需要知道有多少像素即可。以该数字为平均公式的除数。以下是我的例子。

void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE copy[height][width];
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            for (int n = 0; n < 9; n++)
            {
                copy[i][j].rgbtRed = image[i][j].rgbtRed;
                copy[i][j].rgbtGreen = image[i][j].rgbtGreen;
                copy[i][j].rgbtBlue = image[i][j].rgbtBlue;
            }
        }
    }
    int rgbtRed, rgbtGreen, rgbtBlue;
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            rgbtRed = rgbtGreen = rgbtBlue = 0;
            // number of pixel is within boundary
            int inbound = 0;
            for (int n = i - 1; n <= i + 1; n++)
            {
                for (int k = j - 1; k <= j + 1; k++)
                {
                    if (n >= 0 && n < height && k >= 0 && k < width)
                    {
                        rgbtRed += copy[n][k].rgbtRed;
                        rgbtGreen += copy[n][k].rgbtGreen;
                        rgbtBlue += copy[n][k].rgbtBlue;
                        inbound++;
                    }

                }
            }
            image[i][j].rgbtRed = (rgbtRed / inbound);
            image[i][j].rgbtGreen = (rgbtGreen / inbound);
            image[i][j].rgbtBlue = (rgbtBlue / inbound);
        }
    }
}

$ ./filter -b ./images/courtyard.bmp outfile.bmp

结果

From the question it is not clear how the right and bottom right side aren't being calculated correctly. I run the your code and the output is decent from my point of view. Though it gives some runtime error.

Here are some suggestions.

if (n < 0 || n > height || k < 0 || k > width)
{
    copy[n][k].rgbtRed = copy[n][k].rgbtGreen = copy[n][k].rgbtBlue = 0;
}
rgbtRed += copy[n][k].rgbtRed;
rgbtGreen += copy[n][k].rgbtGreen;
rgbtBlue += copy[n][k].rgbtBlue;

I think you are trying to setup a special handling for the boundary case. For the upper limit, isn't it should be n >= height, since it is zero-based index? Moreover, you don't have to explicitly set the pixel to black. Just ignore it and don't add them to the average value is fine. But you didn't stop there and followed by rgbtRed += copy[n][k].rgbtRed. n could be -1 or > height, it could hit array index out of bound.

Also, you setup a if statement with 3 conditions for edge, corner, and inbound case. You don't need that. You only need to know how many pixel are inbound. Take that number as the divisor for the average formula. Below is my example.

void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE copy[height][width];
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            for (int n = 0; n < 9; n++)
            {
                copy[i][j].rgbtRed = image[i][j].rgbtRed;
                copy[i][j].rgbtGreen = image[i][j].rgbtGreen;
                copy[i][j].rgbtBlue = image[i][j].rgbtBlue;
            }
        }
    }
    int rgbtRed, rgbtGreen, rgbtBlue;
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            rgbtRed = rgbtGreen = rgbtBlue = 0;
            // number of pixel is within boundary
            int inbound = 0;
            for (int n = i - 1; n <= i + 1; n++)
            {
                for (int k = j - 1; k <= j + 1; k++)
                {
                    if (n >= 0 && n < height && k >= 0 && k < width)
                    {
                        rgbtRed += copy[n][k].rgbtRed;
                        rgbtGreen += copy[n][k].rgbtGreen;
                        rgbtBlue += copy[n][k].rgbtBlue;
                        inbound++;
                    }

                }
            }
            image[i][j].rgbtRed = (rgbtRed / inbound);
            image[i][j].rgbtGreen = (rgbtGreen / inbound);
            image[i][j].rgbtBlue = (rgbtBlue / inbound);
        }
    }
}

$ ./filter -b ./images/courtyard.bmp outfile.bmp

Result

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文