【发布时间】:2020-09-25 08:34:07
【问题描述】:
我必须将Sobel operator 应用于图像中的每个像素,以便 cs50 突出显示边缘,所以我创建了每个像素的副本,然后找到像素的每种颜色的 Gx 和 Gy 值(总共 6 个值:gxR,gxB,gxG,gyR,gyB,gyG)。我为图片角落或边缘上的像素创建了 8 个if 案例(我意识到这是多余的并且非常重复,但我自己想不出更好的解决方案)。然后,我通过对每种相应颜色的平方和求平方根来找到新的蓝色、绿色和红色值(例如int blue = round(sqrt((gxB * gxB) + (gyB * gyB)));)。我将颜色值设置为 255(请参阅我的 cap 函数),然后将它们应用于图像中的每种对应颜色。然而,当我运行时,边缘没有显示,而是一个非常明亮的图像显示,并且程序没有通过 check50 中的任何检查。有谁知道怎么回事?
这是错误信息(完整版here):
:( edges correctly filters middle pixel
expected "210 150 60\n", not "255 242 207\n"
:( edges correctly filters pixel on edge
expected "213 228 255\n", not "255 255 255\n"
:( edges correctly filters pixel in corner
expected "76 117 255\n", not "76 134 255\n"
:( edges correctly filters 3x3 image
expected "76 117 255\n21...", not "76 134 255\n25..."
:( edges correctly filters 4x4 image
expected "76 117 255\n21...", not "76 134 255\n25..."
这是我的代码:
void edges(int height, int width, RGBTRIPLE image[height][width])
{
int gxB;
int gxG;
int gxR;
int gyB;
int gyG;
int gyR;
// create a temporary array to store a duplicate of image.
RGBTRIPLE temp[height][width];
// save a new copy of image as temp per color.
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
temp[i][j] = image[i][j];
}
}
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
if (i == 0 && j == 0)
{
// top left corner
gxB = (temp[i][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*0 + temp[i][j + 1].rgbtBlue*2 + temp[i + 1][j + 1].rgbtBlue*1);
gxG = (temp[i][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*0 + temp[i][j + 1].rgbtGreen*2 + temp[i + 1][j + 1].rgbtGreen*1);
gxR = (temp[i][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*0 + temp[i][j + 1].rgbtRed*2 + temp[i + 1][j + 1].rgbtRed*1);
gyB = (temp[i][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*2 + temp[i][j + 1].rgbtBlue*2 + temp[i + 1][j + 1].rgbtBlue*1);
gyG = (temp[i][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*2 + temp[i][j + 1].rgbtGreen*2 + temp[i + 1][j + 1].rgbtGreen*1);
gyR = (temp[i][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*2 + temp[i][j + 1].rgbtRed*2 + temp[i + 1][j + 1].rgbtRed*1);
}
else if (i == 0 && j == (width - 1))
{
// top right corner
gxB = (temp[i][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*0 + temp[i][j - 1].rgbtBlue*-2 + temp[i + 1][j - 1].rgbtBlue*-1);
gxG = (temp[i][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*0 + temp[i][j - 1].rgbtGreen*-2 + temp[i + 1][j - 1].rgbtGreen*-1);
gxR = (temp[i][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*0 + temp[i][j - 1].rgbtRed*-2 + temp[i + 1][j - 1].rgbtRed*-1);
gyB = (temp[i][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*2 + temp[i][j - 1].rgbtBlue*0 + temp[i + 1][j - 1].rgbtBlue*1 );
gyG = (temp[i][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*2 + temp[i][j - 1].rgbtGreen*0 + temp[i + 1][j - 1].rgbtGreen*1 );
gyR = (temp[i][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*2 + temp[i][j - 1].rgbtRed*0 + temp[i + 1][j - 1].rgbtRed*1 );
}
else if (i == 0 && (j != 0 || j != (width - 1)))
{
// top edge
gxB = (temp[i][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*0 + temp[i][j - 1].rgbtBlue*-2 + temp[i][j + 1].rgbtBlue*2 + temp[i + 1][j - 1].rgbtBlue*-1 + temp[i + 1][j + 1].rgbtBlue*1);
gxG = (temp[i][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*0 + temp[i][j - 1].rgbtGreen*-2 + temp[i][j + 1].rgbtGreen*2 + temp[i + 1][j - 1].rgbtGreen*-1 + temp[i + 1][j + 1].rgbtGreen*1);
gxR = (temp[i][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*0 + temp[i][j - 1].rgbtRed*-2 + temp[i][j + 1].rgbtRed*2 + temp[i + 1][j - 1].rgbtRed*-1 + temp[i + 1][j + 1].rgbtRed*1);
gyB = (temp[i][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*2 + temp[i][j - 1].rgbtBlue*0 + temp[i][j + 1].rgbtBlue*2 + temp[i + 1][j - 1].rgbtBlue*1 + temp[i + 1][j + 1].rgbtBlue*1);
gyG = (temp[i][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*2 + temp[i][j - 1].rgbtGreen*0 + temp[i][j + 1].rgbtGreen*2 + temp[i + 1][j - 1].rgbtGreen*1 + temp[i + 1][j + 1].rgbtGreen*1);
gyR = (temp[i][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*2 + temp[i][j - 1].rgbtRed*0 + temp[i][j + 1].rgbtRed*2 + temp[i + 1][j - 1].rgbtRed*1 + temp[i + 1][j + 1].rgbtRed*1);
}
else if (i == (height - 1) && j == 0)
{
// bottom left corner
gxB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*0 + temp[i][j + 1].rgbtBlue*2 + temp[i - 1][j + 1].rgbtBlue*1);
gxG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*0 + temp[i][j + 1].rgbtGreen*2 + temp[i - 1][j + 1].rgbtGreen*1);
gxR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*0 + temp[i][j + 1].rgbtRed*2 + temp[i - 1][j + 1].rgbtRed*1);
gyB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*-2 + temp[i][j + 1].rgbtBlue*2 + temp[i - 1][j + 1].rgbtBlue*0);
gyG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*-2 + temp[i][j + 1].rgbtGreen*2 + temp[i - 1][j + 1].rgbtGreen*0);
gyR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*-2 + temp[i][j + 1].rgbtRed*2 + temp[i - 1][j + 1].rgbtRed*0);
}
else if (i == (height - 1) && j == (width - 1))
{
// bottom right corner
gxB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*0 + temp[i][j - 1].rgbtBlue*-2 + temp[i-1][j - 1].rgbtBlue*-1);
gxG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*0 + temp[i][j - 1].rgbtGreen*-2 + temp[i-1][j - 1].rgbtGreen*-1);
gxR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*0 + temp[i][j - 1].rgbtRed*-2 + temp[i-1][j - 1].rgbtRed*-1);
gyB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*-2 + temp[i][j - 1].rgbtBlue*0 + temp[i-1][j - 1].rgbtBlue*-1);
gyG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*-2 + temp[i][j - 1].rgbtGreen*0 + temp[i-1][j - 1].rgbtGreen*-1);
gyR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*-2 + temp[i][j - 1].rgbtRed*0 + temp[i-1][j - 1].rgbtRed*-1);
}
else if (i == (height - 1) && (j != 0 || j != (width - 1)))
{
// bottom edge
gxB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*0 + temp[i][j - 1].rgbtBlue*-2 + temp[i][j + 1].rgbtBlue*2 + temp[i - 1][j + 1].rgbtBlue*1 + temp[i-1][j - 1].rgbtBlue*-1);
gxG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*0 + temp[i][j - 1].rgbtGreen*-2 + temp[i][j + 1].rgbtGreen*2 + temp[i - 1][j + 1].rgbtGreen*1 + temp[i-1][j - 1].rgbtGreen*-1);
gxR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*0 + temp[i][j - 1].rgbtRed*-2 + temp[i][j + 1].rgbtRed*2 + temp[i - 1][j + 1].rgbtRed*1 + temp[i-1][j - 1].rgbtRed*-1);
gyB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*-2 + temp[i][j - 1].rgbtBlue*0 + temp[i][j + 1].rgbtBlue*2 + temp[i - 1][j + 1].rgbtBlue*0 + temp[i-1][j - 1].rgbtBlue*-1);
gyG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*-2 + temp[i][j - 1].rgbtGreen*0 + temp[i][j + 1].rgbtGreen*2 + temp[i - 1][j + 1].rgbtGreen*0 + temp[i-1][j - 1].rgbtGreen*-1);
gyR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*-2 + temp[i][j - 1].rgbtRed*0 + temp[i][j + 1].rgbtRed*2 + temp[i - 1][j + 1].rgbtRed*0 + temp[i-1][j - 1].rgbtRed*-1);
}
else if (j == 0 && (i != 0 || i != (height - 1)))
{
// left edge
gxB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*0 + temp[i][j + 1].rgbtBlue*2 + temp[i - 1][j + 1].rgbtBlue*1 + temp[i + 1][j + 1].rgbtBlue*1);
gxG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*0 + temp[i][j + 1].rgbtGreen*2 + temp[i - 1][j + 1].rgbtGreen*1 + temp[i + 1][j + 1].rgbtGreen*1);
gxR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*0 + temp[i][j + 1].rgbtRed*2 + temp[i - 1][j + 1].rgbtRed*1 + temp[i + 1][j + 1].rgbtRed*1);
gyB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*-2 + temp[i + 1][j].rgbtBlue*2 + temp[i][j + 1].rgbtBlue*2 + temp[i - 1][j + 1].rgbtBlue*0 + temp[i + 1][j + 1].rgbtBlue*1);
gyG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*-2 + temp[i + 1][j].rgbtGreen*2 + temp[i][j + 1].rgbtGreen*2 + temp[i - 1][j + 1].rgbtGreen*0 + temp[i + 1][j + 1].rgbtGreen*1);
gyR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*-2 + temp[i + 1][j].rgbtRed*2 + temp[i][j + 1].rgbtRed*2 + temp[i - 1][j + 1].rgbtRed*0 + temp[i + 1][j + 1].rgbtRed*1);
}
else if (j == (width - 1) && (i != 0 || i != (height - 1)))
{
// right edge
gxB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*0 + temp[i][j - 1].rgbtBlue*-2 + temp[i-1][j - 1].rgbtBlue*-1 + temp[i + 1][j - 1].rgbtBlue*-1);
gxG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*0 + temp[i][j - 1].rgbtGreen*-2 + temp[i-1][j - 1].rgbtGreen*-1 + temp[i + 1][j - 1].rgbtGreen*-1);
gxR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*0 + temp[i][j - 1].rgbtRed*-2 + temp[i-1][j - 1].rgbtRed*-1 + temp[i + 1][j - 1].rgbtRed*-1);
gyB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*-2 + temp[i + 1][j].rgbtBlue*2 + temp[i-1][j - 1].rgbtBlue*-1 + temp[i + 1][j - 1].rgbtBlue*1);
gyG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*-2 + temp[i + 1][j].rgbtGreen*2 + temp[i-1][j - 1].rgbtGreen*-1 + temp[i + 1][j - 1].rgbtGreen*1);
gyR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*-2 + temp[i + 1][j].rgbtRed*2 + temp[i-1][j - 1].rgbtRed*-1 + temp[i + 1][j - 1].rgbtRed*1);
}
else
{
// any other pixel
gxB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*0 + temp[i + 1][j].rgbtBlue*0 + temp[i][j - 1].rgbtBlue*-2 + temp[i][j + 1].rgbtBlue*2 + temp[i - 1][j + 1].rgbtBlue*1 + temp[i-1][j - 1].rgbtBlue*-1 + temp[i + 1][j - 1].rgbtBlue*-1 + temp[i + 1][j + 1].rgbtBlue*1);
gxG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*0 + temp[i + 1][j].rgbtGreen*0 + temp[i][j - 1].rgbtGreen*-2 + temp[i][j + 1].rgbtGreen*2 + temp[i - 1][j + 1].rgbtGreen*1 + temp[i-1][j - 1].rgbtGreen*-1 + temp[i + 1][j - 1].rgbtGreen*-1 + temp[i + 1][j + 1].rgbtGreen*1);
gxR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*0 + temp[i + 1][j].rgbtRed*0 + temp[i][j - 1].rgbtRed*-2 + temp[i][j + 1].rgbtRed*2 + temp[i - 1][j + 1].rgbtRed*1 + temp[i-1][j - 1].rgbtRed*-1 + temp[i + 1][j - 1].rgbtRed*-1 + temp[i + 1][j + 1].rgbtRed*1);
gyB = (temp[i][j].rgbtBlue*0 + temp[i - 1][j].rgbtBlue*-2 + temp[i + 1][j].rgbtBlue*2 + temp[i][j - 1].rgbtBlue*0 + temp[i][j + 1].rgbtBlue*2 + temp[i - 1][j + 1].rgbtBlue*0 + temp[i-1][j - 1].rgbtBlue*-1 + temp[i + 1][j - 1].rgbtBlue*1 + temp[i + 1][j + 1].rgbtBlue*1);
gyG = (temp[i][j].rgbtGreen*0 + temp[i - 1][j].rgbtGreen*-2 + temp[i + 1][j].rgbtGreen*2 + temp[i][j - 1].rgbtGreen*0 + temp[i][j + 1].rgbtGreen*2 + temp[i - 1][j + 1].rgbtGreen*0 + temp[i-1][j - 1].rgbtGreen*-1 + temp[i + 1][j - 1].rgbtGreen*1 + temp[i + 1][j + 1].rgbtGreen*1);
gyR = (temp[i][j].rgbtRed*0 + temp[i - 1][j].rgbtRed*-2 + temp[i + 1][j].rgbtRed*2 + temp[i][j - 1].rgbtRed*0 + temp[i][j + 1].rgbtRed*2 + temp[i - 1][j + 1].rgbtRed*0 + temp[i-1][j - 1].rgbtRed*-1 + temp[i + 1][j - 1].rgbtRed*1 + temp[i + 1][j + 1].rgbtRed*1);
}
int blue = round(sqrt((gxB * gxB) + (gyB * gyB)));
int green = round(sqrt((gxG * gxG) + (gyG * gyG)));
int red = round(sqrt((gxR * gxR) + (gyR * gyR)));
image[i][j].rgbtBlue = cap(blue);
image[i][j].rgbtGreen = cap(green);
image[i][j].rgbtRed = cap(red);
}
}
return;
}
最后,这是我的cap 函数:
// cap function retrieved from this video: https://youtu.be/VbG8tH-Vbko
int cap(int value)
{
return value < 255 ? value: 255;
}
这是原图:
编辑: 按照 Solancia 的回答,我将 gyR、gyB 和 gyG 的所有 temp[i - 1][j + 1].rgbtRed*0 实例更改为 temp[i - 1][j + 1].rgbtRed*-1。另外,我意识到gyR、gyB 和gyG 的所有temp[i][j + 1].rgbtRed*2 实例都应该是temp[i][j + 1].rgbtRed*0。更改这些允许我的代码正常运行并通过 check50。我意识到我的代码非常糟糕,应该拆分成单独的函数,但是我已经编写了它并且在看到它不起作用后的解决方案之前没有想到要拆分成单独的函数。不过下次我会记住这一点,所以谢谢你的帮助。
【问题讨论】:
-
您可能需要考虑将此迁移到cs50.stackexchange.com
-
尝试将您的代码分解为可读的函数。我相信一个明显的潜在功能就是
convolution(img, kernel)。尝试编写并测试它。您可能可以在几行代码中使用 4 个嵌套的 for 循环来完成。或者,如果您想将其专门用于 3x3 内核,您可以手动展开循环...