CS50 Pset 4 边缘:图像是静态的

问题描述 投票:0回答:1
#include "helpers.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int sq(int x)
{
    return x*x;
}

void edges(int height, int width, RGBTRIPLE image[height][width])
{
    int gx_square[] = {-1,0,1,-2,0,2,-1,0,1};
    int gy_square[] = {-1,-2,-1,0,0,0,1,2,1};
    int gx_red[height][width], gx_blue[height][width], gx_green[height][width];
    int gy_red[height][width], gy_blue[height][width], gy_green[height][width];
    int square = -1;

    for (int i = 0; i < height; i++)
    {
        // Width
        for (int j = 0; j < width; j++)
        {
            gx_red[i][j] = 0;
            gx_blue[i][j] = 0;
            gx_green[i][j] = 0;
            gy_red[i][j] = 0;
            gy_blue[i][j] = 0;
            gy_green[i][j] = 0;
        }
    }
    // Height
    for (int i = 0; i < height; i++)
    {
        // Width
        for (int j = 0; j < width; j++)
        {
            //Fill gx and gy arrays
            for (int column = i - 1; column < i + 2; column++)
            {
                for (int row = j - 1; row < j + 2; row++)
                {
                    //If pixel is outside image
                    square++;
                    if (column < 0 || column >= height || row < 0 || row >= width)
                    {
                            continue;
                    }
                    // Update array
                    gx_red[i][j] += image[column][row].rgbtRed * gx_square[square];
                    gx_blue[i][j] += image[column][row].rgbtBlue * gx_square[square];
                    gx_green[i][j] += image[column][row].rgbtGreen * gx_square[square];
                    gy_red[i][j] += image[column][row].rgbtRed * gy_square[square];
                    gy_blue[i][j] += image[column][row].rgbtBlue * gy_square[square];
                    gy_green[i][j] += image[column][row].rgbtGreen * gy_square[square];
                }
            }
            square = 0;
        }
    }

    // Height
    for (int i = 0; i < height; i++)
    {
        //Width
        for (int j = 0; j < width; j++)
        {
            // Return color
            image[i][j].rgbtRed = sqrt(sq(gx_red[i][j]) + sq(gy_red[i][j]));
            if (image[i][j].rgbtRed > 255)
            {
                image[i][j].rgbtRed = 255;
            }
            image[i][j].rgbtBlue = sqrt(sq(gx_blue[i][j]) + sq(gy_blue[i][j]));
            if (image[i][j].rgbtBlue > 255)
            {
                image[i][j].rgbtBlue = 255;
            }
            image[i][j].rgbtGreen = sqrt(sq(gx_green[i][j]) + sq(gy_green[i][j]));
            if (image[i][j].rgbtGreen > 255)
            {
                image[i][j].rgbtGreen= 255;
            }
        }
    }
    return;
}

    //./filter -e images/stadium.bmp OUTFILE.bmp
    // debug50 filter -e images/stadium.bmp OUTFILE.bmp

我的边缘任务是勾勒出图像中的任何对象,如下所示:

您可以通过获取图像周围的所有像素颜色,并通过它运行 2 个算法(称为 gx 和 gy)来实现此目的。该算法的工作原理是将一个像素周围的所有像素乘以几个数字。这是乘法顺序的直观表示。 (中间的像素是当前像素)

因此对于 gx,第一个像素乘以 -1,下一个像素乘以 0,然后乘以 1,依此类推。然后我们保留总和。但倍增的不是像素,而是颜色值。让我们以红色为例。假设某个像素周围的所有像素(包括该像素本身)都有 255 红色。

由于像素之间几乎没有变化,所以一切都抵消了,所有数字的总和为 0。

如果发生重大变化,我们就会留下很大的数字。 (我很快就会介绍我们如何处理这个数字)我们用绿色和蓝色来做这个。 gx和gy的目的是检测x坐标和y坐标的变化。 您可能还会想,如果程序查看的不是图像内部的像素怎么办?如果是这样的话,我们就将它们视为 0。(这与忽略它们是一样的)

最后,我们取 (gx.red squared + gy.red squared) 的平方根以获得该像素的新红色值。 (你仍然用绿色和蓝色来做这个。)

我发布这个问题是因为我不太确定我的代码出了什么问题。我有 gx 和 gy 数组来存储所有颜色值,以及用于实际乘法算法的数组。如果像素位于边界,则跳过它(与 0 相同)。然后我使所有像素等于 gx 颜色的平方 + gy 颜色的平方的平方根。这就是我通常使用的图像的样子:

这就是我的代码的样子。

我想知道这是为什么。

c pixel rgb cs50
1个回答
0
投票

索引变量

square
在声明时被初始化为
-1
。这是一个危险信号。以负值开始索引表明正在发生一些不好的事情。正确声明后,任何索引都应为
size_t
类型,即无符号数据类型。

该错误因该变量的范围而变得更加复杂。它的范围应该仅限于使用它的代码。

这是未经测试的修订版:

void edges(int height, int width, RGBTRIPLE image[height][width])
{
    int gx_square[] = {-1,0,1,-2,0,2,-1,0,1};
    int gy_square[] = {-1,-2,-1,0,0,0,1,2,1};
    int gx_red[height][width], gx_blue[height][width], gx_green[height][width];
    int gy_red[height][width], gy_blue[height][width], gy_green[height][width];


    memset( gx_red, 0, sizeof gx_red ); // use library functions when possible.
    memset( gx_blue, 0, sizeof gx_blue );
    memset( gx_green, 0, sizeof gx_green );
    memset( gy_red, 0, sizeof gy_red );
    memset( gy_blue, 0, sizeof gy_blue );
    memset( gy_green, 0, sizeof gy_green );

    // Height
    for (size_t row = 0; row < height; row++)
    {
        // Width
        for (size_t col = 0; col < width; col++)
        {
            size_t square = 0; // local to this single pixel

            // DO NOT switch from row/col to col/row... Just confusing!!!

            //Fill gx and gy arrays
            for (int r = row - 1; r < row + 2; r++)
            {
                // square increments AFTER each iteration.
                // No mysterious -1 values...
                for (int c = col - 1; c < col + 2; c++, square++)
                {
                    // avoid "continue;" whenever possible.
                    // use "positive" logic instead.
                    if ( ( 0 <= r && r < width) && ( 0 <= c && c < height ) )
                    {
                        // Update array
                        gx_red[row][col] += image[r][c].rgbtRed * gx_square[square];
                        gx_blue[row][col] += image[r][c].rgbtBlue * gx_square[square];
                        gx_green[row][col] += image[r][c].rgbtGreen * gx_square[square];
                        gy_red[row][col] += image[r][c].rgbtRed * gy_square[square];
                        gy_blue[row][col] += image[r][c].rgbtBlue * gy_square[square];
                        gy_green[row][col] += image[r][c].rgbtGreen * gy_square[square];
                    }
                }
            }
        }
    }
    // unaltered function code continues below.
© www.soinside.com 2019 - 2024. All rights reserved.