3

New to progamming; trying to implement a sobel edge detection algorithm. I am doing this in a function called edges, as per the code snippet below.

void edges(int height, int width, RGBTRIPLE image[height][width])
{
    // define kernals
    int Gx[3][3];
    Gx[0][0] = -1;
    Gx[0][1] = 0;
    Gx[0][2] = 1;
    Gx[1][0] = -2;
    Gx[1][1] = 0;
    Gx[1][2] = 2;
    Gx[2][0] = -1;
    Gx[2][1] = 0;
    Gx[2][2] = 1;

    int Gy[3][3];
    Gy[0][0] = -1;
    Gy[0][1] = -2;
    Gy[0][2] = -1;
    Gy[1][0] = 0;
    Gy[1][1] = 0;
    Gy[1][2] = 0;
    Gy[2][0] = 1;
    Gy[2][1] = 2;
    Gy[2][2] = 1;

    // define variables
    int Gx_red, Gx_green, Gx_blue;
    int Gy_red, Gy_green, Gy_blue;

    // define temporary array
    RGBTRIPLE edge_image[height][width];

    // loop through columns
    for (int i = 0; i < height; i++)
    {
        // loop through rows
        for (int j = 0; j < width; j++)
        {
            // set/reset sobel values for each colour channel
            Gx_red = Gx_green = Gx_blue = 0;
            Gy_red = Gy_green = Gy_blue = 0;

            // 3x3 kernal around [i][j]
            for (int x = -1; x < 2; x++)
            {
                for (int y = -1; y < 2; y++)
                {
                    // 'pixels' outside of image array treated as black pixels
                    if (i + x > height || i + x < 0 || j + y > width || j + y < 0)
                    {
                        // Gx kernal
                        Gx_red += 0;
                        Gx_green += 0;
                        Gx_blue += 0;

                        // Gy kernal
                        Gy_red += 0;
                        Gy_green += 0;
                        Gy_blue += 0;
                    }

                    // Multiply each channel by corresponding value in convolutional array
                    else if (i + x < height && i + x > 0 && j + y < width && j + y > 0)
                    {
                        // Gx kernal
                        Gx_red += (image[i + x][j + y].rgbtRed * Gx[x][y]);
                        Gx_green += (image[i + x][j + y].rgbtGreen * Gx[x][y]);
                        Gx_blue += (image[i + x][j + y].rgbtBlue * Gx[x][y]);

                        // Gy kernal
                        Gy_red += (image[i + x][j + y].rgbtRed * Gy[x][y]);
                        Gy_green += (image[i + x][j + y].rgbtGreen * Gy[x][y]);
                        Gy_blue += (image[i + x][j + y].rgbtBlue * Gy[x][y]);
                    }
                }
            }
            // Perform sobel operatation and assign each colour channel value to new array
            edge_image[i][j].rgbtRed = sobel(Gx_red, Gy_red);
            edge_image[i][j].rgbtGreen = sobel(Gx_green, Gy_green);
           edge_image[i][j].rgbtBlue = sobel(Gx_blue, Gy_blue);
        }
    }
    // assign temp array to origional array for output
    for (int i = 0; i < height; i++)
        for (int j = 0; j < width; j++)
            image[i][j] = edge_image[i][j];
}

The edges function calls the sobel function, written as below.

// Calculate sobel value for each channel (capping at 255)
int sobel (int Gx, int Gy)
{
    int n = sqrt(Gx^2 + Gy^2);
    if (n > 255)
    {
        n = 255;
    }
    return n;
}

This is the Input image

This is the Output image

As you can see the output is extremely grainy and the edges are undefined. Clearly, I haven't implemented the sobel alorithm properly, but I am unsure what I have done wrong. Please could you give me some advice on how I could fix this?

*Please note I am aware I could convert the image to greyscale before implementing the sobel algorithm but i'm trying to preserve the colour channels as much as possible. Let me know if I can provide any more information.

2
  • 2
    You can clean up your initializations with int Gx[3][3] = { { -1, 0 ,1}, {-2, 0, 2}, {-1, 0 , 2}}; Commented Mar 3, 2021 at 14:52
  • Ah, I knew there was a way to do this - cheers! Commented Mar 3, 2021 at 17:07

1 Answer 1

3

First of all, this all does nothing:

// 'pixels' outside of image array treated as black pixels
if (i + x > height || i + x < 0 || j + y > width || j + y < 0)
{
    // Gx kernal
    Gx_red += 0;
    Gx_green += 0;
    Gx_blue += 0;

    // Gy kernal
    Gy_red += 0;
    Gy_green += 0;
    Gy_blue += 0;
}

Adding zero is a no-op. You can safely delete that.

Your first main issue is here:

// Gx kernal
Gx_red += (image[i + x][j + y].rgbtRed * Gx[x][y]);
Gx_green += (image[i + x][j + y].rgbtGreen * Gx[x][y]);
Gx_blue += (image[i + x][j + y].rgbtBlue * Gx[x][y]);

// Gy kernal
Gy_red += (image[i + x][j + y].rgbtRed * Gy[x][y]);
Gy_green += (image[i + x][j + y].rgbtGreen * Gy[x][y]);
Gy_blue += (image[i + x][j + y].rgbtBlue * Gy[x][y]);

You defined x, y to loop through -1, 0, 1, but defined Gx, Gy as int[3][3] arrays. So when x or y is -1 you are indexing out of bounds.

I would suggest defining

int kx = x + 1; // Kernel x.
int ky = y + 1; // Kernel y.

And then

// Gx kernel
Gx_red += (image[i + x][j + y].rgbtRed * Gx[kx][sy]);
Gx_green += (image[i + x][j + y].rgbtGreen * Gx[kx][sy]);
Gx_blue += (image[i + x][j + y].rgbtBlue * Gx[kx][sy]);

// Gy kernel
Gy_red += (image[i + x][j + y].rgbtRed * Gy[kx][sy]);
Gy_green += (image[i + x][j + y].rgbtGreen * Gy[kx][sy]);
Gy_blue += (image[i + x][j + y].rgbtBlue * Gy[kx][sy]);

Your second main issue is here:

int n = sqrt(Gx^2 + Gy^2);

In C and C++ (and many, but not all other programming languages) ^ means the bit-wise XOR operator, not exponentiation. You want:

int n = sqrt(Gx*Gx + Gy*Gy);
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the response, everything you said makes a lot of sense. I've implemented those changes and everything seems to work. Thanks again and all the best.
@RoryV.S. If my answer helped you please consider upvoting and accepting it :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.