#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 颜色的平方的平方根。这就是我通常使用的图像的样子:
这就是我的代码的样子。
我想知道这是为什么。
索引变量
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.