Ruhul Mashbu
Ruhul Mashbu

Reputation: 83

Edge detection at a certain degree using canny method

I am using MATLAB. I want to use canny method for edge detection. But I need the edges that are diagonal or the edges that are only on 40 to 50 degree angle. how can i do that?

Upvotes: 2

Views: 2391

Answers (2)

Cecilia
Cecilia

Reputation: 4721

I've answered a similar question about how to use Matlab's edge function to find oriented edges with Canny ( Orientational Canny Edge Detection ), but I also wanted to try out a custom implementation as suggested by Avijit.

Canny Edge Detection steps:

  1. Start with an image, I'll use a built in demo image.

    A = im2double(rgb2gray(imread('peppers.png')));
    
  2. Gaussian Filter

    A_filter = imgaussfilt(A);
    
  3. Sobel Edge Detection -- We can't use the built in implementation (edge(A_filter, 'Sobel')), because we want the edge angles, not just the edge locations, so we implement our own operator.

    a. Convolution to find oriented gradients

    %These filters measure the difference in values between vertically or horizontally adjacent pixels. 
    %Effectively, this finds vertical and horizontal gradients.
    vertical_filter = [-1 0 1; -2 0 2; -1 0 1];
    horizontal_filter = [-1 -2 -1; 0 0 0; 1 2 1];
    A_vertical = conv2(A_filter, vertical_filter, 'same');
    A_horizontal = conv2(A_filter, horizontal_filter, 'same');
    

    b. Calculate the angles

    A_angle = arctan(A_vertical./A_horizontal);
    
  4. At this step, we traditionally bin edges by orientation (0°, 45°, 90°, 135°), but since you only want diagonal edges between 40 and 50 degrees, we will retain those edges and discard the rest.

    % I lowered the thresholds to include more pixels
    % But for your original post, you would use 40 and 50
    lower_angle_threshold = 22.5; 
    upper_angle_threshold = 67.5;
    diagonal_map = zeros(size(A), 'logical');
    diagonal_map (A_angle>(lower_angle_threshold*pi/180) & A_angle<(upper_angle_threshold*pi/180)) = 1;
    
  5. Perform non-max suppression on the remaining edges -- This is the most difficult portion to adapt to different angles. To find the exact edge location, you compare two adjacent pixels: for 0° edges, compare east-west, for 45° south-west pixel to north-east pixel, for 90° compare north-south, and for 135° north-west pixel to south-east pixel.

    Since your desired angle is close to 45°, I just used south-west, but if you wanted 10° to 20°, for example, you'd have to put some more thought into these comparisons.

    non_max = A_sobel;
    [n_rows, n_col] = size(A);
    %For every pixel
    for row = 2:n_rows-1
        for col = 2:n_col-1
            %If we are at a diagonal edge
            if(diagonal_map(row, col))
                %Compare north east and south west pixels
                if(A_sobel(row, col)<A_sobel(row-1, col-1) || ...
                        A_sobel(row, col)<A_sobel(row+1, col+1))
                    non_max(row, col) = 0;
                end
            else
                non_max(row, col) = 0;
            end
        end
    end
    
  6. Edge tracking with hysteresis -- Decide whether weak edge pixels are close enough (I use a 3x3 window) to strong edge pixels. If they are, include them in the edge. If not, they are noise; remove them.

    high_threshold = 0.5; %These thresholds are tunable parameters
    low_threshold = 0.01;
    
    weak_edge_pixels = non_max > low_threshold & non_max < high_threshold;
    strong_edge_pixels = non_max > high_threshold;
    
    final = strong_edge_pixels;
    for row = 2:n_rows-1
        for col = 2:n_col-1
           window = strong_edge_pixels(row-1:row+1, col-1:col+1);
           if(weak_edge_pixels(row, col) && any(window(:)))
               final(row, col) = 1;
           end
        end
    end
    

Here are my results.

Result image

As you can see, discarding the other edge orientations has a very negative effect on the hysteresis step because fewer strong pixels are detected. Adjusting the high_threshold would help somewhat. Another option would be to do Steps 5 and 6 using all edge orientations, and then use the diagonal_map to extract the diagonal edges.

Upvotes: 0

Avijit Dasgupta
Avijit Dasgupta

Reputation: 2065

You need write canny edge detector's code by your own (you would get lots of implementation )in the internet. You would then be calculating the gradient magnitudes and gradient directions in the second step. There you need to filter out the angles and corresponding magnitudes.

Hope this helps you.

Upvotes: 2

Related Questions