Ask Your Question
1

Canny Edge Detection- Non Maximum Surpression Implementation

asked 2016-11-01 04:31:21 -0500

kevgeo gravatar image

I am trying to implement the Canny edge detection algorithm from scratch with the help of OpenCV. I am facing a problem implementing the Non-Maximum Suppression step which helps to thin the edges.

My logic is to first compute the intensity gradient vector, then group it in either 0,45,90,135 degrees direction and then try to find local maxima. The method to find this local maxima is by making sure that current pixel is greater than succeeding and preceeding pixel in same direction. If not, I assign value of zero to this pixel. Using this logic, I'm still not able to thin the edges. I feel the error is when I'm computing the intensity gradient vector for each pixel.

Here is my code-

#include <iostream>
#include <bits/stdc++.h>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <opencv2/objdetect/objdetect.hpp>
#include <math.h>
using namespace cv;  
using namespace std; 

int main()
{
// Reading image
Mat img = imread("1.jpg");

// Displaying image
//imshow("Original Image",img);
//waitKey(0);

// Converting to grayscale
Mat img_gray,image_gray;
cvtColor(img,image_gray,CV_RGB2GRAY);
GaussianBlur( image_gray, img_gray, Size(15,15), 3, 3);


// Displaying grayscale image
imshow("Original Image",img_gray);
waitKey(0);


int cols = img_gray.cols;
int rows = img_gray.rows;

// Creating sobel operator in x direction
int sobel_x[3][3] = {-1,0,1,-2,0,2,-1,0,1};
// Creating sobel operator in y direction
int sobel_y[3][3] = {1,2,1,0,0,0,-1,-2,-1};


int radius = 1;

// Handle border issues
Mat _src;
copyMakeBorder(img_gray, _src, radius, radius, radius, radius, BORDER_REFLECT101);

// Create output matrix
Mat gradient_x = img_gray.clone();
Mat gradient_y = img_gray.clone();
Mat gradient_f = img_gray.clone();
Mat gradient_mag = img_gray.clone();

// Conrrelation loop in x direction 

// Iterate on image 
for (int r = radius; r < _src.rows - radius; ++r)
{
    for (int c = radius; c < _src.cols - radius; ++c)
    {
        int s = 0;

        // Iterate on kernel
        for (int i = -radius; i <= radius; ++i)
        {
            for (int j = -radius; j <= radius; ++j)
            {
                s += _src.at<uchar>(r + i, c + j) * sobel_x[i + radius][j + radius];
            }
        }
        gradient_x.at<uchar>(r - radius, c - radius) = s/8;

        /*if(s>200)
            gradient.at<uchar>(r - radius, c - radius) = 255;
        else
            gradient.at<uchar>(r - radius, c - radius) = 0;
        */    
    }
}

// Conrrelation loop in y direction 

// Iterate on image 
for (int r = radius; r < _src.rows - radius; ++r)
{
    for (int c = radius; c < _src.cols - radius; ++c)
    {
        int s = 0;

        // Iterate on kernel
        for (int i = -radius; i <= radius; ++i)
        {
            for (int j = -radius; j <= radius; ++j)
            {
                s += _src.at<uchar>(r + i, c + j) * sobel_y[i + radius][j + radius];
            }
        }
        gradient_y.at<uchar>(r - radius, c - radius) = s/8;

        /*if(s>200)
            gradient.at<uchar>(r - radius, c - radius) = 255;
        else
            gradient.at<uchar>(r - radius, c - radius) = 0;
        */    
    }
}

///cout<<endl<<"max:"<<max;
//cout<<img_gray.rows;
//cout<<endl<<_src.rows;
cout<<endl<<gradient_x.rows;
cout<<endl<<gradient_y.rows;
cout<<endl<<gradient_f.rows<<gradient_f.cols;   


//Calculating gradient magnitude
for(int i=0; i ...
(more)
edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
0

answered 2016-11-02 03:16:56 -0500

Roy2511 gravatar image

Maybe the issue is with how you're calculating the Sobel gradients. Try this .

cv::Mat Gx, Gy;
cv::Sobel(img, Gx, CV_64F, 1, 0, ksize);
cv::Sobel(img, Gy, CV_64F, 0, 1, ksize);

where ksize is the size of the Sobel kernel. (in your case, ksize = 3)

edit flag offensive delete link more

Comments

Yes, it actually gave me much thinner edges. Do you have any idea why my sobel gradients isn't coming out properly? I changed the value of my sobel operator in y direction to int sobel_y[3][3] = {-1,-2,-1,0,0,0,1,2,1}; . I thought that was the mistake but barely any change is there.

kevgeo gravatar imagekevgeo ( 2016-11-03 19:49:17 -0500 )edit
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2016-11-01 04:31:21 -0500

Seen: 157 times

Last updated: Nov 02 '16