关于CS50x问题集4“更多滤镜”(灰度和模糊函数)的代码审查。

huangapple go评论104阅读模式
英文:

Review on code from CS50x Problem Set 4 "Filter More" (Grayscale and Blur functions)

问题

第一个问题 - 我已经创建了一个用于将图像转换为灰度的函数,但由于某种原因,它不会将平均值(3个颜色值除以3)四舍五入。

我在不同的地方(计算平均值和分配'阴影'的值给像素时)使用了round()函数,我也尝试了ceil()函数,但无论如何都不起作用。

第二个问题 - 我已经创建了一个用于模糊图像的函数(在像素周围创建一个3x3的'框',并根据红、绿和蓝的平均值来计算平均值,然后将新的颜色值分配给3x3 '框'中心的像素)。但是,'check50'告诉我我做得完全错误。

我的代码中是否有严重错误,还是它只是不适用于这些特定的测试?

关于灰度处理的代码:

#include <math.h>

// Convert image to grayscale
void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            int shade = 0;
            shade = ceil((image[i][j].rgbtRed + image[i][j].rgbtGreen + image[i][j].rgbtBlue) / 3);
            image[i][j].rgbtRed = shade; //也尝试了round(shade)和ceil(shade)
            image[i][j].rgbtGreen = shade;
            image[i][j].rgbtBlue = shade;
        }
    }
    return;
}

关于模糊处理的代码:

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE temp[height][width]; // 临时数组

    for (int i = 0; i < height; i++) // 复制到临时数组
    {
        for (int j = 0; j < width; j++)
        {
            temp[i][j].rgbtRed = image[i][j].rgbtRed;
            temp[i][j].rgbtGreen = image[i][j].rgbtGreen;
            temp[i][j].rgbtBlue = image[i][j].rgbtBlue;
        }
    }

    for (int i = 0; i <= height; i++)
    {
        for (int j = 0; j <= width; j++) // 遍历像素数组
        {
            unsigned int avgR = 0, avgG = 0, avgB = 0; // 平均颜色值 = 0
            unsigned int count = 0;                    // 用于记录使用了多少像素
            for (int k = (i - 1); k <= i + 1; k++)     // 模糊的边界(3x3)
            {
                for (int l = (j - 1); l < j + 1; l++) // 边界
                {
                    if (k >= 0 && k <= (height - 1) && l >= 0 && l <= (width - 1)) // 检查像素是否存在
                    {
                        avgR += round(temp[k][l].rgbtRed); // 计算平均值
                        avgG += round(temp[k][l].rgbtGreen);
                        avgB += round(temp[k][l].rgbtBlue);
                        count++; // 使用的像素计数
                    }
                }
            }
            image[i][j].rgbtRed = round(avgR / count); // 用平均值重写原始颜色
            image[i][j].rgbtGreen = round(avgG / count);
            image[i][j].rgbtBlue = round(avgB / count);
        }
    }
    return;
}

我已经尝试过:在灰度处理中更改round()ceil()函数的位置,尝试将'shade'变量设置为float类型。至于模糊处理,我没有改动任何东西,因为它完全错误,所以我不知道从哪里开始:(也许问题在于我试图尽可能少地“硬编码”,所以我在尝试通过循环自动化所有过程时犯了一些错误。

英文:

description of tasks: https://cs50.harvard.edu/x/2023/psets/4/filter/more/

There are two problems:

First one - I've made a function to GRAYSCALE a picture, but for some reason it doesn't round the value of average (3 color values divided by 3).
I have used the round() function in diferent places (when counting average and assigning the value of 'shade' to pixel), so I did with the ceil() function, it just doesn't work no matter what.

Second one - I've made a function to BOX-BLUR the image (making a 3x3 'box' around the pixel and counting the average amount of Red Green and Blue accordingly, then assigning the new values of color to the pixel in center of 3x3 'box') But the 'check50' tells me that I'm doing it all wrong.

Is there any critical mistakes in my code or is it just doesn't situated for this specific tests?

screenshots of 'test' included:

Grayscale: first, second, third

Blur: first, second, third

CODE for GRAYSCALE :

#include &lt;math.h&gt;

// Convert image to grayscale
void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
    for (int i = 0; i &lt; height; i++)
    {
        for (int j = 0; j &lt; width; j++)
        {
            int shade = 0;
            shade = ceil((image[i][j].rgbtRed + image[i][j].rgbtGreen + image[i][j].rgbtBlue) / 3);
            image[i][j].rgbtRed = shade; **//also tried round(shade) and ceil(shade)**
            image[i][j].rgbtGreen = shade;
            image[i][j].rgbtBlue = shade;
        }
    }
    return;
}

CODE for BLUR:

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE temp[height][width]; // temp array

    for (int i = 0; i &lt; height; i++) // copy to temporary array
    {
        for (int j = 0; j &lt; width; j++)
        {
            temp[i][j].rgbtRed = image[i][j].rgbtRed;
            temp[i][j].rgbtGreen = image[i][j].rgbtGreen;
            temp[i][j].rgbtBlue = image[i][j].rgbtBlue;
        }
    }

    for (int i = 0; i &lt;= height; i++)
    {
        for (int j = 0; j &lt;= width; j++) // going through array of pixels
        {
            unsigned int avgR = 0, avgG = 0, avgB = 0; // average color value = 0
            unsigned int count = 0;                    // to know how many pixels were used
            for (int k = (i - 1); k &lt;= i + 1; k++)     // boundaries of blur (3x3)
            {
                for (int l = (j - 1); l &lt; j + 1; l++) // boundaries
                {
                    if (k &gt;= 0 &amp;&amp; k &lt;= (height - 1) &amp;&amp; l &gt;= 0 &amp;&amp; l &lt;= (width - 1)) // checking if pixel exists
                    {
                        avgR += round(temp[k][l].rgbtRed); // calculating average
                        avgG += round(temp[k][l].rgbtGreen);
                        avgB += round(temp[k][l].rgbtBlue);
                        count++; // pixels used count
                    }
                }
            }
            image[i][j].rgbtRed = round(avgR / count); // rewriting original color with average
            image[i][j].rgbtGreen = round(avgG / count);
            image[i][j].rgbtBlue = round(avgB / count);
        }
    }
    return;
}

I've tried to: change the position of round()and ceil() functions in **Grayscale **, tried to make 'shade' variable a float-type.

In Blur I didn't touch anything, because it's all wrong, so I dont know where to start 关于CS50x问题集4“更多滤镜”(灰度和模糊函数)的代码审查。

Maybe the problem is that I try to 'hardcode' as less as it is possible, so I make some mistakes while trying to automate all processes via loops

答案1

得分: 0

错误的数学操作

代码执行整数除法 avgR / count,将其截断的整数商传递给 double round(double),但这没有任何有用的效果。

// image[i][j].rgbtRed = round(avgR / count);

而是应该使用整数数学进行四舍五入。可以实现各种四舍五入模式,而不使用浮点数学

unsigned divide_round_half_way_up(unsigned a, unsigned b) {
  return a / b + (a % b * 2 >= b);
}

请注意,a%b 的成本通常很小,考虑到先前的 a/b。好的编译器会将商和余数都渲染为一个时间成本。


3个下标越界错误

// for (int i = 0; i &lt;= height; i++) {
//     for (int j = 0; j &lt;= width; j++)pixels
//     ...
//        for (int l = (j - 1); l &lt; j + 1; l++) // boundaries

for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++)

        for (int l = (j - 1); l <= j + 1; l++)

简化

RGBTRIPLE temp[height][width]; // 临时数组

// for (int i = 0; i &lt; height; i++) // 复制到临时数组 {
//    for (int j = 0; j &lt; width; j++) {
//        temp[i][j].rgbtRed = image[i][j].rgbtRed;
//        temp[i][j].rgbtGreen = image[i][j].rgbtGreen;
//        temp[i][j].rgbtBlue = image[i][j].rgbtBlue;
//    }
// }

memcpy(temp, image, sizeof temp);
英文:

Wrong math

Code performs integer divisions avgR / count with its truncated integer quotient. It then passes the integer quotient to double round(double) for no useful effect.

// image[i][j].rgbtRed = round(avgR / count);

Instead perform rounding with integer math. Various rounding modes are possible to implement without using floating point math.

unsigned divide_round_half_way_up(unsigned a, unsigned b) {
  return = a/b + (a%b*2 &gt;= b);
}

Note that the cost of a%b is often minute given the prior a/b. Good compilers render both the quotient and remainder for the time cost of one.


3 Off by one bugs

// for (int i = 0; i &lt;= height; i++) {
//     for (int j = 0; j &lt;= width; j++)pixels
//     ...
//        for (int l = (j - 1); l &lt; j + 1; l++) // boundaries

for (int i = 0; i &lt; height; i++) {
    for (int j = 0; j &lt; width; j++)

        for (int l = (j - 1); l &lt;= j + 1; l++)

Simplification

RGBTRIPLE temp[height][width]; // temp array

// for (int i = 0; i &lt; height; i++) // copy to temporary array {
//    for (int j = 0; j &lt; width; j++) {
//        temp[i][j].rgbtRed = image[i][j].rgbtRed;
//        temp[i][j].rgbtGreen = image[i][j].rgbtGreen;
//        temp[i][j].rgbtBlue = image[i][j].rgbtBlue;
//    }
// }

memcpy(temp, image, sizeof temp);

答案2

得分: 0

在灰度模式下,你应该尝试:

shade = round((image[i][j].rgbtRed + image[i][j].rgbtGreen + image[i][j].rgbtBlue) / 3.0);

ceil()round() 都接受浮点数。使用 3.0 而不是 3 会强制 C 将其计算为浮点数。

英文:

In the grayscale, you should try:

shade = round((image[i][j].rgbtRed + image[i][j].rgbtGreen + image[i][j].rgbtBlue) / 3.0);

Both ceil() and round() take floating point. Using 3.0 instead of 3 will force C calculate it as float.

答案3

得分: -1

不需要超越第一个示例,其中您得到rgb = (27, 28, 28),应该生成(28,28,28),但得到(27,27,27)。

您正在将除法视为浮点除法,因为您使用了roundceil,但在C中,int/int将执行整数除法,即立即截断所有小数部分。

您可以通过例如除以3.0来修复这个问题,其中值将提升为双精度,保留重要的小数部分,然后按您喜欢的方式四舍五入数字。

int shade = ceil((image[i][j].rgbtRed + image[i][j].rgbtGreen + image[i][j].rgbtBlue) / 3.0);

image[i][j].rgbtRed = round(avgR / (double)count);

分别。

您还混淆了模糊代码的界限。

for (int i = 0; i &lt;= height; i++)

这里您的i太高了。必须小于height
而您的内部循环

for (int k = (i - 1); k &lt;= i + 1; k++)
{
    for (int l = (j - 1); l &lt; j + 1; l++)

很明显,它与kl的上界不一致。两者都应包括上界;l &lt;= j + 1

英文:

No need to go beyond the very first example, where you get rgb = (27, 28, 28), and should produce (28,28,28), but get (27,27,27).

You are treating division as floating point division, given your use of round and ceil, but an int/int in C will perform integer division, i.e. truncating all decimals immediately.

You could fix that by e.g. dividing by 3., where the values will be promoted to a double, preserving the important decimals, then rounding off the numbers by whatever way you prefer.

int shade = ceil((image[i][j].rgbtRed + image[i][j].rgbtGreen + image[i][j].rgbtBlue) / 3.);

and

image[i][j].rgbtRed = round(avgR / (double)count);

respectively.

You have also messed up the bounds of in your blurring code.

for (int i = 0; i &lt;= height; i++)

Your i goes to high here. Must be less than height.
And your inner loops

for (int k = (i - 1); k &lt;= i + 1; k++)
{
    for (int l = (j - 1); l &lt; j + 1; l++)

is clear to see that it's inconsistent with the upper bounds for k and l. Both should include the upper bound; l &lt;= j + 1

huangapple
  • 本文由 发表于 2023年8月4日 04:21:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76831405.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定