Search code examples
matlabimage-processingedge-detectionsobel

Matlab: First derivative edge detection, about gradients


I'm writing a program that asks the user to choose between Prewitt and Sobel image filters to detect edges of objects of an image. I must use their filter templates, not the edge function. The user also tells if he wants to detect 'horizontal', 'vertical' or 'diagonal' edges. My problem is theoretical rather than about programming.

In my notes i've got that to compute the magnitude of the gradient at each pixel, it is often approximated as sqrt(Gx^2 + Gy^2) where Gx would be the vertical derivative and Gy the horizontal derivative. But what is the value of Gx if I only calculate the horizontal edges? And the value of Gy if I'm only looking for the vertical edges?

I can't guess it by myself.


Solution

  • That's quite simple. What you are concerned about is performing an image filtering with masks, where each mask is a derivative filter. With this approach, knedlsepp is correct in that doing it this way would only find the partial derivatives with respect to a given direction. You would specify one mask to detect the horizontal and another for the vertical edges.

    Gx stands for the vertical edge response by using a vertical derivative filter and Gy stands for the horizontal edge response by using a horizontal derivative filter. To get the responses, you would take your image and filter it by 2D convolution with any of the masks.

    Next, you would combine both of the responses together to get the overall magnitude response. However, edge performs a lot of noise cleanup under the hood and also performs a thresholding to get the final response. Simply computing the magnitude is not the full story of what edge does.

    In any case, for detecting horizontal edges, the Prewitt mask looks like so:

    Gy_prewitt = 
    
    -1    -1   -1
     0     0    0
     1     1    1
    

    Performing a filtering with the above mask finds the horizontal edge response, or Gy.

    For finding the vertical edge response or Gx, you simply transpose the above mask and find the filter response, so:

    Gx_prewitt =
    
         -1     0    1
         -1     0    1
         -1     0    1
    

    The Sobel mask is slightly different than the Prewitt mask. There is more exaggeration on the central row of the mask (for the vertical) or column (for the horizontal) of the mask and is weighted by twice as much. The horizontal mask is:

    Gy_sobel =
    
    -1   -2   -1
     0    0    0
     1    2    1
    

    Similarly, the vertical mask for the Sobel is defined as:

    Gx_sobel =
    
     -1     0    1
     -2     0    2
     -1     0    1
    

    What is important to note is that the total sum of all coefficients in the mask equals to zero, and is actually a property of any edge detection mask seen in practice.

    Now, to determine the overall edge response, you would take the filtering responses for each of the horizontal, Gy, and vertical Gx, and apply the magnitude operation per corresponding pixel:

    out = sqrt(Gx.^2 + Gy.^2);
    

    If you want a more intuitive explanation as to why the Sobel mask is slightly different than the Prewitt, I encourage you to take a look at this post. It provides a very good explanation as well as a good diagram on how to implement the filtering operation yourself if you can't use built-in convolution methods:

    http://blog.saush.com/2011/04/20/edge-detection-with-the-sobel-operator-in-ruby/

    Here's the diagram:

    Basically, for each pixel you want to filter in your image, extract a 3 x 3 neighbourhood and perform a weighted sum between those pixels in the neighbourhood and the filter you want. In this case, this would be the Sobel vertical edge detector.

    Good luck!