The following code i have written has the purpose of detecting the edges in a pixel using the sobel operator. However, it fails all of the tests given by check50 (tool offered by cs50). The output image is also the exact same as the input.
before you continue reading, visit the pset's link
hh
and ww
to do this. // 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;
}
RGBTRIPLE:
typedef struct
{
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;
These are the error messages given by 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 ..."
As you can see, the output values are way off and not even near what they should actually be. the problem is: I don't know if these errors are caused by a) my way of trying to find the GX and GY values from the kernels or b)by the way i'm applying the sobel operator.
I've tried finding GX and GY values in other ways (didn't work) such as:
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;
}
I've been stuck on this pset for almost a week now and so at this point I don't know what else to try.
You have quite some parts that do not really make sense or are missing.
GXblue
and GYblue
, same for GXgreen
and GYgreen
.I have prepared a new version that should do the trick. Now tested and with test data from initially failed test for 4x4 image.
#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;
}