Search code examples
cpixelcs50edgessobel

CS50 edges filter program does not function properly (Sobel operator)


I have to apply the Sobel operator to each pixel in my image for cs50 to highlight the edges, so I created a copy of each pixel, then found the Gx and Gy values for each color of the pixel (6 total values: gxR, gxB, gxG, gyR, gyB, gyG). I created 8 if cases for the pixels that were on a corner or on an edge of the picture (I realize it's redundant and very repetitive, but I couldn't think of a better solution on my own). Then, I found the new blue, green, and red values by square rooting the sum of the squares of each corresponding color (e.g. int blue = round(sqrt((gxB * gxB) + (gyB * gyB)));). I capped the color values at 255 (see my cap function) then applied them to each corresponding color in the image. When I run, however, the edges don't show but rather a very bright image does, and the program doesn't pass any checks in check50. Anyone know what's wrong?

Here's the error message (full version 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..."

And here's my code:

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;
}

Lastly, here's my cap function:

// cap function retrieved from this video: https://youtu.be/VbG8tH-Vbko
int cap(int value)
{
    return value < 255 ? value: 255;
}

This is the original image:

Original Image

And this is my image after processing: enter image description here

EDIT: Following Solancia's answer, I changed all instances of temp[i - 1][j + 1].rgbtRed*0 to temp[i - 1][j + 1].rgbtRed*-1 for gyR, gyB, and gyG. Also, I realized that all instances of temp[i][j + 1].rgbtRed*2 for gyR, gyB, and gyG should be temp[i][j + 1].rgbtRed*0. Changing these allowed my code to function properly and pass check50. I realize that my code is very bad and should be split into separate functions, but I had already written it and did not think to separate into separate functions until seeing solutions after it did not work. I will keep this in mind next time though, so thanks for the help.


Solution

  • Ok, what Mateen Ulhaq saying above where you need to make readability still stands. However, as a quick fix, on your else block, you put:

    temp[i - 1][j + 1].rgbtRed*0
    

    for gyR. This is also for rgbtGreen and rgbtBlue.

    It should be :

    temp[i - 1][j + 1].rgbtRed*-1
    

    More importantly, you should try to change up or put the code in other areas since it's hard for people to read like that There could be other errors that are missed because of this.