cs50 pset4 - 边缘检测过滤器不起作用 - sobel 运算符
cs50 pset4 - edge detection filter not working - sobel operator
我编写的以下代码的目的是使用 sobel 运算符检测像素中的边缘。但是,它无法通过 check50(cs50 提供的工具)给出的所有测试。输出图像也与输入完全相同。
在继续阅读之前,请访问 the pset's link
- 注意: 我应该在像素周围形成一个 3x3 的网格 我想过滤以便我可以遍历每个GX 和 GY 值中的值。我使用整数
hh
和 ww
来做到这一点。
// Detect edges
void edges(int height, int width, RGBTRIPLE image[height][width])
{
int sqrtRedd;
int sqrtGreenn;
int sqrtBluee;
//make copy of image
RGBTRIPLE copy[height][width];
for(int h = 0; h < height; h++)
{
for(int w = 0; w < width; w++)
{
copy[h][w] = image[h][w];
}
}
//loop through pixels
for(int h = 0; h < height; h++)
{
for(int w = 0; w < width; w++)
{
int GXred = 0;
int GYred = 0;
int GXgreen = 0;
int GYgreen = 0;
int GXblue = 0;
int GYblue = 0;
for(int hh = -1; hh <= 1; hh++)
{
for(int ww = -1; ww <= 1; ww++)
{
if( h + hh >= 0 && h + hh < height && w + ww >= 0 && w + ww < width)
{
//form 3x3 grid
GXred += ww * copy[2 - hh * hh][2 - ww * ww].rgbtRed;
GYred += hh * copy[2 - hh * hh][2 - ww * ww].rgbtRed;
GXgreen += ww * copy[2 - hh * hh][2 - ww * ww].rgbtGreen;
GYgreen += hh * copy[2 - hh * hh][2 - ww * ww].rgbtGreen;
GXblue += ww * copy[2 - hh * hh][2 - ww * ww].rgbtBlue;
GXblue += hh * copy[2 - hh * hh][2 - ww * ww].rgbtBlue;
}
}
}
int red = round(sqrt(GXred * GXred + GYred * GYred));
int green = round(sqrt(GXgreen * GXgreen + GYgreen * GXgreen));
int blue = round(sqrt(GXblue * GXblue + GYblue * GYblue));
if(red > 225)
{
red = 225;
}
else if(green > 225)
{
green = 225;
}
else if(blue > 225)
{
blue = 225
}
image[h][w].rgbtRed = red;
image[h][w].rgbtGreen = green;
image[h][w].rgbtBlue = blue;
}
}
return;
}
RGB三色:
typedef struct
{
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;
这些是 check50 给出的错误信息:
:( edges correctly filters middle pixel
expected "210 150 60\n", not "143 105 30\n"
:( edges correctly filters pixel on edge
expected "213 228 255\n", not "164 144 79\n"
:( edges correctly filters pixel in corner
expected "76 117 255\n", not "58 77 64\n"
:( edges correctly filters 3x3 image
expected "76 117 255\n21...", not "58 77 64\n164 ..."
:( edges correctly filters 4x4 image
expected "76 117 255\n21...", not "58 77 64\n164 ..."
如您所见,输出值相差甚远,甚至不接近实际值。问题是:我不知道这些错误是否由 a) 我尝试从内核中找到 GX 和 GY 值的方式或 b) 我应用 sobel 运算符的方式引起的。
我试过通过其他方式(没有用)找到 GX 和 GY 值,例如:
if(hh == -1)
{
GYred += copy[h - 1][w + ww].rgbtRed * -1;
GYgreen += copy[h - 1][w + ww].rgbtGreen * -1;
GYblue += copy[h - 1][w + ww].rgbtBlue * -1;
}
else if( hh == 0)
{
GYred += copy[h][w + ww].rgbtRed * 0;
GYgreen += copy[h][w + ww].rgbtGreen * 0;
GYblue += copy[h][w + ww].rgbtBlue * 0;
}
else if(hh == 1)
{
GYred += copy[h + 1][w + ww].rgbtRed * 1;
GYgreen += copy[h + 1][w + ww].rgbtGreen * 1;
GYblue += copy[h + 1][w + ww].rgbtBlue * 2;
}
else if(hh == 2)
{
GYred += copy[h + 2][w + ww].rgbtRed * 2;
GYgreen += copy[h + 2][w + ww].rgbtGreen * 2;
GYblue += copy[h + 2][w + ww].rgbtBlue * 2;
}
//start setting GX values
if(ww == -2)
{
GXred += copy[h + hh][w - 2].rgbtRed * -2;
GXgreen += copy[h + hh][w - 2].rgbtGreen * -2;
GXblue += copy[h + hh][w - 2].rgbtBlue * -2;
}
else if(ww == -1)
{
GXred += copy[h + hh][w - 1].rgbtRed * -1;
GXgreen += copy[h + hh][w - 1].rgbtGreen * -1;
GXblue += copy[h + hh][w - 1].rgbtBlue * -1;
}
else if(ww == 0)
{
GXred += copy[h + hh][w].rgbtRed * 0;
GXgreen += copy[h + hh][w].rgbtGreen * 0;
GXblue += copy[h + hh][w].rgbtBlue * 0;
}
else if(ww == 1)
{
GXred += copy[h + hh][w + 1].rgbtRed * 1;
GXgreen += copy[h + hh][w + 1].rgbtGreen * 1;
GXblue += copy[h + hh][w + 1].rgbtBlue * 1;
}
我已经在这个 pset 上坚持了将近一个星期,所以在这一点上我不知道还能尝试什么。
你有很多部分没有意义或缺失。
- 您没有在任何地方应用 sobel 因子。仅在 3x3 网格内进行偏移不会产生正确的值,
- 你只限制1个颜色通道以防溢出,
- 您限制为 225 而不是 255,
- 您混合了
GXblue
和 GYblue
,GXgreen
和 GYgreen
也是如此。
我已经准备了一个应该可以解决问题的新版本。
现在测试并使用最初失败的 4x4 图像测试的测试数据。
#include <stdio.h>
#include <math.h>
typedef unsigned char BYTE;
typedef struct
{
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;
// Detect edges
void edges(int height, int width, RGBTRIPLE image[height][width])
{
int sqrtRedd;
int sqrtGreenn;
int sqrtBluee;
//make copy of image
RGBTRIPLE copy[height][width];
for(int h = 0; h < height; h++)
{
for(int w = 0; w < width; w++)
{
copy[h][w] = image[h][w];
}
}
//loop through pixels
for(int h = 0; h < height; h++)
{
for(int w = 0; w < width; w++)
{
int GXred = 0;
int GYred = 0;
int GXgreen = 0;
int GYgreen = 0;
int GXblue = 0;
int GYblue = 0;
int index = 0;
int factorsX[] = {-1, 0, 1, -2, 0, 2, -1, 0, 1};
int factorsY[] = {-1, -2, -1, 0, 0, 0, 1, 2, 1};
//form 3x3 grid
for(int hh = -1; hh <= 1; hh++)
{
for(int ww = -1; ww <= 1; ww++)
{
int x = w+ww;
int y = h+hh;
if( y >= 0 && y < height && x >= 0 && x < width)
{
GXred += factorsX[index] * copy[y][x].rgbtRed;
GYred += factorsY[index] * copy[y][x].rgbtRed;
GXgreen += factorsX[index] * copy[y][x].rgbtGreen;
GYgreen += factorsY[index] * copy[y][x].rgbtGreen;
GXblue += factorsX[index] * copy[y][x].rgbtBlue;
GYblue += factorsY[index] * copy[y][x].rgbtBlue;
}
index++;
}
}
int red = round(sqrt(GXred * GXred + GYred * GYred));
int green = round(sqrt(GXgreen * GXgreen + GYgreen * GYgreen));
int blue = round(sqrt(GXblue * GXblue + GYblue * GYblue));
if(red > 255)
{
red = 255;
}
if(green > 255)
{
green = 255;
}
if(blue > 255)
{
blue = 255;
}
image[h][w].rgbtRed = red;
image[h][w].rgbtGreen = green;
image[h][w].rgbtBlue = blue;
}
}
return;
}
int main(void)
{
RGBTRIPLE test_4x4[4][4] = {
{{0, 10, 25}, {0, 10, 30}, {40, 60, 80}, {50, 60, 80}},
{{20, 30, 90}, {30, 40, 100}, {80, 70, 90}, {80, 80, 90}},
{{20, 20, 40}, {30, 10, 30}, {50, 40, 10}, {50, 40, 100}},
{{50, 20, 40}, {50, 20, 40}, {50, 40, 80}, {50, 40, 80}},
};
edges(4, 4, test_4x4);
for(int h = 0; h < 4; h++)
{
for(int w = 0; w < 4; w++)
{
printf("%d %d %d\n", test_4x4[h][w].rgbtBlue, test_4x4[h][w].rgbtGreen, test_4x4[h][w].rgbtRed);
}
}
return 0;
}
我编写的以下代码的目的是使用 sobel 运算符检测像素中的边缘。但是,它无法通过 check50(cs50 提供的工具)给出的所有测试。输出图像也与输入完全相同。
在继续阅读之前,请访问 the pset's link
- 注意: 我应该在像素周围形成一个 3x3 的网格 我想过滤以便我可以遍历每个GX 和 GY 值中的值。我使用整数
hh
和ww
来做到这一点。
// Detect edges
void edges(int height, int width, RGBTRIPLE image[height][width])
{
int sqrtRedd;
int sqrtGreenn;
int sqrtBluee;
//make copy of image
RGBTRIPLE copy[height][width];
for(int h = 0; h < height; h++)
{
for(int w = 0; w < width; w++)
{
copy[h][w] = image[h][w];
}
}
//loop through pixels
for(int h = 0; h < height; h++)
{
for(int w = 0; w < width; w++)
{
int GXred = 0;
int GYred = 0;
int GXgreen = 0;
int GYgreen = 0;
int GXblue = 0;
int GYblue = 0;
for(int hh = -1; hh <= 1; hh++)
{
for(int ww = -1; ww <= 1; ww++)
{
if( h + hh >= 0 && h + hh < height && w + ww >= 0 && w + ww < width)
{
//form 3x3 grid
GXred += ww * copy[2 - hh * hh][2 - ww * ww].rgbtRed;
GYred += hh * copy[2 - hh * hh][2 - ww * ww].rgbtRed;
GXgreen += ww * copy[2 - hh * hh][2 - ww * ww].rgbtGreen;
GYgreen += hh * copy[2 - hh * hh][2 - ww * ww].rgbtGreen;
GXblue += ww * copy[2 - hh * hh][2 - ww * ww].rgbtBlue;
GXblue += hh * copy[2 - hh * hh][2 - ww * ww].rgbtBlue;
}
}
}
int red = round(sqrt(GXred * GXred + GYred * GYred));
int green = round(sqrt(GXgreen * GXgreen + GYgreen * GXgreen));
int blue = round(sqrt(GXblue * GXblue + GYblue * GYblue));
if(red > 225)
{
red = 225;
}
else if(green > 225)
{
green = 225;
}
else if(blue > 225)
{
blue = 225
}
image[h][w].rgbtRed = red;
image[h][w].rgbtGreen = green;
image[h][w].rgbtBlue = blue;
}
}
return;
}
RGB三色:
typedef struct
{
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;
这些是 check50 给出的错误信息:
:( edges correctly filters middle pixel
expected "210 150 60\n", not "143 105 30\n"
:( edges correctly filters pixel on edge
expected "213 228 255\n", not "164 144 79\n"
:( edges correctly filters pixel in corner
expected "76 117 255\n", not "58 77 64\n"
:( edges correctly filters 3x3 image
expected "76 117 255\n21...", not "58 77 64\n164 ..."
:( edges correctly filters 4x4 image
expected "76 117 255\n21...", not "58 77 64\n164 ..."
如您所见,输出值相差甚远,甚至不接近实际值。问题是:我不知道这些错误是否由 a) 我尝试从内核中找到 GX 和 GY 值的方式或 b) 我应用 sobel 运算符的方式引起的。
我试过通过其他方式(没有用)找到 GX 和 GY 值,例如:
if(hh == -1)
{
GYred += copy[h - 1][w + ww].rgbtRed * -1;
GYgreen += copy[h - 1][w + ww].rgbtGreen * -1;
GYblue += copy[h - 1][w + ww].rgbtBlue * -1;
}
else if( hh == 0)
{
GYred += copy[h][w + ww].rgbtRed * 0;
GYgreen += copy[h][w + ww].rgbtGreen * 0;
GYblue += copy[h][w + ww].rgbtBlue * 0;
}
else if(hh == 1)
{
GYred += copy[h + 1][w + ww].rgbtRed * 1;
GYgreen += copy[h + 1][w + ww].rgbtGreen * 1;
GYblue += copy[h + 1][w + ww].rgbtBlue * 2;
}
else if(hh == 2)
{
GYred += copy[h + 2][w + ww].rgbtRed * 2;
GYgreen += copy[h + 2][w + ww].rgbtGreen * 2;
GYblue += copy[h + 2][w + ww].rgbtBlue * 2;
}
//start setting GX values
if(ww == -2)
{
GXred += copy[h + hh][w - 2].rgbtRed * -2;
GXgreen += copy[h + hh][w - 2].rgbtGreen * -2;
GXblue += copy[h + hh][w - 2].rgbtBlue * -2;
}
else if(ww == -1)
{
GXred += copy[h + hh][w - 1].rgbtRed * -1;
GXgreen += copy[h + hh][w - 1].rgbtGreen * -1;
GXblue += copy[h + hh][w - 1].rgbtBlue * -1;
}
else if(ww == 0)
{
GXred += copy[h + hh][w].rgbtRed * 0;
GXgreen += copy[h + hh][w].rgbtGreen * 0;
GXblue += copy[h + hh][w].rgbtBlue * 0;
}
else if(ww == 1)
{
GXred += copy[h + hh][w + 1].rgbtRed * 1;
GXgreen += copy[h + hh][w + 1].rgbtGreen * 1;
GXblue += copy[h + hh][w + 1].rgbtBlue * 1;
}
我已经在这个 pset 上坚持了将近一个星期,所以在这一点上我不知道还能尝试什么。
你有很多部分没有意义或缺失。
- 您没有在任何地方应用 sobel 因子。仅在 3x3 网格内进行偏移不会产生正确的值,
- 你只限制1个颜色通道以防溢出,
- 您限制为 225 而不是 255,
- 您混合了
GXblue
和GYblue
,GXgreen
和GYgreen
也是如此。
我已经准备了一个应该可以解决问题的新版本。 现在测试并使用最初失败的 4x4 图像测试的测试数据。
#include <stdio.h>
#include <math.h>
typedef unsigned char BYTE;
typedef struct
{
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;
// Detect edges
void edges(int height, int width, RGBTRIPLE image[height][width])
{
int sqrtRedd;
int sqrtGreenn;
int sqrtBluee;
//make copy of image
RGBTRIPLE copy[height][width];
for(int h = 0; h < height; h++)
{
for(int w = 0; w < width; w++)
{
copy[h][w] = image[h][w];
}
}
//loop through pixels
for(int h = 0; h < height; h++)
{
for(int w = 0; w < width; w++)
{
int GXred = 0;
int GYred = 0;
int GXgreen = 0;
int GYgreen = 0;
int GXblue = 0;
int GYblue = 0;
int index = 0;
int factorsX[] = {-1, 0, 1, -2, 0, 2, -1, 0, 1};
int factorsY[] = {-1, -2, -1, 0, 0, 0, 1, 2, 1};
//form 3x3 grid
for(int hh = -1; hh <= 1; hh++)
{
for(int ww = -1; ww <= 1; ww++)
{
int x = w+ww;
int y = h+hh;
if( y >= 0 && y < height && x >= 0 && x < width)
{
GXred += factorsX[index] * copy[y][x].rgbtRed;
GYred += factorsY[index] * copy[y][x].rgbtRed;
GXgreen += factorsX[index] * copy[y][x].rgbtGreen;
GYgreen += factorsY[index] * copy[y][x].rgbtGreen;
GXblue += factorsX[index] * copy[y][x].rgbtBlue;
GYblue += factorsY[index] * copy[y][x].rgbtBlue;
}
index++;
}
}
int red = round(sqrt(GXred * GXred + GYred * GYred));
int green = round(sqrt(GXgreen * GXgreen + GYgreen * GYgreen));
int blue = round(sqrt(GXblue * GXblue + GYblue * GYblue));
if(red > 255)
{
red = 255;
}
if(green > 255)
{
green = 255;
}
if(blue > 255)
{
blue = 255;
}
image[h][w].rgbtRed = red;
image[h][w].rgbtGreen = green;
image[h][w].rgbtBlue = blue;
}
}
return;
}
int main(void)
{
RGBTRIPLE test_4x4[4][4] = {
{{0, 10, 25}, {0, 10, 30}, {40, 60, 80}, {50, 60, 80}},
{{20, 30, 90}, {30, 40, 100}, {80, 70, 90}, {80, 80, 90}},
{{20, 20, 40}, {30, 10, 30}, {50, 40, 10}, {50, 40, 100}},
{{50, 20, 40}, {50, 20, 40}, {50, 40, 80}, {50, 40, 80}},
};
edges(4, 4, test_4x4);
for(int h = 0; h < 4; h++)
{
for(int w = 0; w < 4; w++)
{
printf("%d %d %d\n", test_4x4[h][w].rgbtBlue, test_4x4[h][w].rgbtGreen, test_4x4[h][w].rgbtRed);
}
}
return 0;
}