I have been stuck on CS50 Filter - Edges for a few days now, having a hard time determining what's wrong with my code. This code returns an almost all white images (which indicates to me final values are too large for each of the pixels). Any help would be greatly appreciated!
I've checked with my friend's code as well and I don't see any obvious logic flaws with the code, the image is mostly white and there's definitely no edges detected in the image.
void edges(int height, int width, RGBTRIPLE image[height][width])
{
//Create Gx and Gy Matrixes
int Gx[3][3]={{-1,0,1},{-2,0,2},{-1,0,1}};
int Gy[3][3]={{-1,-2,-1},{0,0,0},{1,2,1}};
//create copy of image
RGBTRIPLE copy[height][width];
for(int row=0; row<height;row )
{
for(int col=0; col<width; col )
{
copy[row][col].rgbtBlue=image[row][col].rgbtBlue;
copy[row][col].rgbtRed=image[row][col].rgbtRed;
copy[row][col].rgbtGreen=image[row][col].rgbtGreen;
}
}
//create loop for edge detection
int red; int blue; int green;
double Gxsum[3]; double Gysum[3]; double finalval[3];
int icount; int jcount;
for(int row=0; row<height; row )//inside image loop
{
for(int col=0; col<width; col )
{
Gxsum[0]=0.0; Gxsum[1]=0.0; Gxsum[2]=0.0;
Gysum[0]=0.0; Gysum[1]=0.0; Gysum[2]=0.0;
icount=0; jcount=0;
for(int i=row-1; i<=row 1; i )//inside 3x3 loop
{
for(int j=col-1; j<=col 1; j )
{
if(i<0||j<0||i>=height||j>=width)
{
red=0.0;blue=0.0;green=0.0;
}
else
{
red=copy[i][j].rgbtRed;
blue=copy[i][j].rgbtBlue;
green=copy[i][j].rgbtGreen;
Gxsum[0] =Gx[icount][jcount]*red;
Gxsum[1] =Gx[icount][jcount]*blue;
Gxsum[2] =Gx[icount][jcount]*green;
Gysum[0] =Gy[icount][jcount]*red;
Gysum[1] =Gy[icount][jcount]*blue;
Gysum[2] =Gy[icount][jcount]*green;
}
jcount ;
}
icount ;
}
finalval[0]=round(sqrt(Gxsum[0]*Gxsum[0] Gysum[0]*Gysum[0]));//red
finalval[1]=round(sqrt(Gxsum[1]*Gxsum[1] Gysum[1]*Gysum[1]));//blue
finalval[2]=round(sqrt(Gxsum[2]*Gxsum[2] Gysum[2]*Gysum[2]));//green
for(int k=0; k<3; k )
{
if (finalval[k]>255)
{
finalval[k]=255;
}
}
//now assign image pixel to newvals;
image[row][col].rgbtRed=(int)finalval[0];
image[row][col].rgbtBlue=(int)finalval[1];
image[row][col].rgbtGreen=(int)finalval[2];
}
}
return;
}
CodePudding user response:
I think your code contains compilation error and runtime error. When you execute, you are just running the version comes form the course material. Hence the result is a white image.
First, you need to #include <math.h>
to use sqrt()
, round()
. Second, there is a logical error where you forgot to reset jcount
to 0 after each row completes. When jcount
becomes 3, it hit array index out of bound.
Below is my corrected, simplified version
// Detect edges
void edges(int height, int width, RGBTRIPLE image[height][width])
{
//Create Gx and Gy Matrixes
int gx[3][3] = { {-1,0,1},{-2,0,2},{-1,0,1} };
int gy[3][3] = { {-1,-2,-1},{0,0,0},{1,2,1} };
// max of each channel
const int channelCap = 255;
//create copy of image
RGBTRIPLE copy[height][width];
for (int row = 0; row < height; row )
{
for (int col = 0; col < width; col )
{
copy[row][col].rgbtBlue = image[row][col].rgbtBlue;
copy[row][col].rgbtRed = image[row][col].rgbtRed;
copy[row][col].rgbtGreen = image[row][col].rgbtGreen;
}
}
//create loop for edge detection
int red; int blue; int green;
double finalRed, finalGreen, finalBlue;
double gxRed, gxGreen, gxBlue;
double gyRed, gyGreen, gyBlue;
for (int row = 0; row < height; row )//inside image loop
{
for (int col = 0; col < width; col )
{
gxRed = 0.0; gxGreen = 0.0; gxBlue = 0.0;
gyRed = 0.0; gyGreen = 0.0; gyBlue = 0.0;
int icount = 0, jcount = 0;
for (int i = row - 1; i <= row 1; i )//inside 3x3 loop
{
for (int j = col - 1; j <= col 1; j )
{
if (i >= 0 && j >= 0 && i < height && j < width)
{
// within boundary
red = copy[i][j].rgbtRed;
blue = copy[i][j].rgbtBlue;
green = copy[i][j].rgbtGreen;
gxRed = gx[icount][jcount] * red;
gxBlue = gx[icount][jcount] * blue;
gxGreen = gx[icount][jcount] * green;
gyRed = gy[icount][jcount] * red;
gyBlue = gy[icount][jcount] * blue;
gyGreen = gy[icount][jcount] * green;
}
jcount ;
}
icount ;
jcount = 0;
}
finalRed = fmin(round(sqrt(gxRed * gxRed gyRed * gyRed)), channelCap);//red
finalBlue = fmin(round(sqrt(gxBlue * gxBlue gyBlue * gyBlue)), channelCap);//blue
finalGreen = fmin(round(sqrt(gxGreen * gxGreen gyGreen * gyGreen)), channelCap);//green
//now assign image pixel to newvals;
image[row][col].rgbtRed = (int)finalRed;
image[row][col].rgbtBlue = (int)finalBlue;
image[row][col].rgbtGreen = (int)finalGreen;
}
}
return;
}
$ ./filter -e ./images/yard.bmp outfile.bmp
Result: