Robbie Hott

Computer Vision
February 14, 2011

Homework 1

Canny Edge Detector

Files

Options

My edge detector has a few user-selectable options:

SIGMA
The value of sigma to use for the calculation of the Gaussian.
GRADIENT_MATRIX_SIZE
The size of the matrix used to discretize the gradient of the Gaussian.
HIST_THRESHOLD_HIGH
The high threshold, T_h, used to perform hysteresis.
HIST_THRESHOLD_LOW
The low threshold, T_l, used to perform hysteresis.
DISPLAY_RESULTS
Set to 1, displays the output of the Canny Edge Detector as figures in Matlab. Set to 0, it does not display output.
SAVE_RESULTS
Set to 1, writes the images (both the output from non-maximum and the hysteresis steps) to disk. Set to 0, it does not write files.
EXTRA_RESULTS
Set to 1, writes and/or displays the images of the x- and y-gradients, the intensity of the gradient, as well as the direction of the gradient.
BRIGHTEN_EDGES
Set to 1, when writing or displaying the resulting non-maximum suppression and final Canny output, overwrites the intensity value with full white pixels (255). Set to 0, allows the intensity to be displayed.
INPUT_FILE
The input filename.

Samples

Firstly, I created a test image, bigtest.jpg, which contains all white along with random black shapes, seen below:


Bigtest image

Then, I looked at the gradient of the Gaussian, with sigma = 2, to ensure that the gradient was produced correctly. Below are first the x-gradient matrix, followed by the y-gradient matrix:


Gradient of the Gaussian (x-direction)


Gradient of the Gaussian (y-direction)

This image produced the following x- and y-gradients, when the gradient of the Gaussian was convolved with the image:


Gradient of the smoothed image in the x direction


Gradient of the smoothed image in the y direction

This led me to know my algorithm was working correctly in finding the gradients and convolving them with the image. Then, I calculated the intensity and directions of each pixel (noting that I binned the directions to 0, 45, 90, -45, and -90).


Intensity of the gradient (before non-maximum suppression)


Direction of the gradient vector at each point

Using the intensity and direction, the algorithm computed the following results, first non-maximum suppression, then the final result after hysteresis. Also to note, I used the BRIGHTEN_EDGES option to set all maximums (and lines at the end) to full white. An interesting side effect is that under non-maximum suppression, the white space between the shapes also counted as maximums because the gradient ended up as .00017 instead of 0, which throws the algorithm off in certain places. This extra "noise" is fixed, however, when thresholds are applied in the hysteresis step.


Intensity of the gradient (after non-maximum suppression)



Non-maximum suppression final image (all edges elevated to 255)


Final image after Canny: sigma = 4, gradient matrix size = 40px, T_h = 9, T_l = 1

I also tested out the edge detector on other images, both from class and from my own Flickr account. The outputs are below (image, non-maximum suppression, and final Canny output). Mouse over to read sigma, gradient matrix size, and threshold values. Each image had to be tweaked to get the best output. I'll discuss choosing good values for these variables later.

Mandrill.jpg




Gradient of the smoothed image in the x direction


Gradient of the smoothed image in the y direction


Intensity of the gradient (before non-maximum suppression)


Direction of the gradient vector at each point


Intensity of the gradient (after non-maximum suppression)



Non-maximum suppression final image (all edges elevated to 255)


Final image after Canny: sigma = 3, gradient matrix size = 40px, T_h = 3, T_l = 2

Building.jpg




Gradient of the smoothed image in the x direction


Gradient of the smoothed image in the y direction


Intensity of the gradient (before non-maximum suppression)


Direction of the gradient vector at each point


Intensity of the gradient (after non-maximum suppression)



Non-maximum suppression final image (all edges elevated to 255)


Final image after Canny: sigma = 1, gradient matrix size = 16px, T_h = 3, T_l = 1

Other results for Building.jpg


Final image after Canny: sigma = 3, gradient matrix size = 32px, T_h = 3, T_l = 1


Final image after Canny: sigma = 1, gradient matrix size = 16px, T_h = 40, T_l = 10

Stonehenge.jpg - from flickr



Intensity of the gradient (after non-maximum suppression)



Non-maximum suppression final image (all edges elevated to 255)


Final image after Canny: sigma = 1, gradient matrix size = 16px, T_h = 17, T_l = 1

Goose.jpg - from flickr




Non-maximum suppression final image (all edges elevated to 255)


Final image after Canny: sigma = 1, gradient matrix size = 16px, T_h = 5, T_l = 1

Discussion

The initial algorithm I employed did not pad the image, so the conv2 function extended the image by padding it with 0s, causing some problems around the edges. That was remedied by padding the image with repetitions of the edge pixels. One of the more interesting phenomenon I have been noticing is that when producing the gradients of a completely white image, the magnitude was greater than 0, approximately .00017, which I would assume to be rounding errors. Needless to say, it does not affect the final output of either the edge nor corner detector. It only became apparent when I set the maximum values of the non-maximum suppression output to be full white, instead of their original intensity values.

With the edge detection algorithm, the time complexity could be as low as O(n^2), where the input image is nxn. To compute the intensity and direction of the gradient, perform non-maximum suppression, and perform hysteresis each requires visiting each pixel once, O(n^2). Non-maximum suppression requires testing two neighboring pixels at each step, but that is a constant overhead. Likewise, hysteresis is also O(n^2) since when a path is traversed from a given pixel, those pixels will not be visited again. The more complicated portion of the algorithm is the convolution step. Each portion of the convolution step (convolving with the x-gradient and y-gradient of the Gaussian) requires O(n^2*m^2), where m is the size of the Gaussian matrix. Since m is chosen by the user, with m set to be relatively small, the entire algorithm acts like O(n^2), however as m approaches n, convolution dominates the entire algorithm, which would result in a time complexity of O(n^4).

Each of the variables that are user-definable are interconnected in the Canny edge detection algorithm. First of all, the gradient matrix size must be set large enough to contain the entire gradient of the the Gaussian created by sigma. More specifically, if simply the Gaussian(x,y) was calculated for each point, the sum over the entire matrix must equal to 1. Secondly, sigma and the thresholds are related. As sigma increases, the thresholds must be lowered, since the gradients are smoothed out, lowering their overall maximum values. The low threshold, T_l, of the hysteresis step (when low) seemed to count much less than the high threshold, T_h, since the high threshold ignored chains without significantly intense points. As T_l increased to T_h, however, the algorithm starts ignoring all but the brightest points. Likewise, with a lower T_h, more and more chains are included.

As an example, let's consider the building.jpg image above. The image shown resulted from sigma set to 1, T_h as 3, and T_l as 1. These values were chosen since the resulting image outlines almost every brick on the building. As sigma increases (see above), the edges around the bricks blurs and those edges are no longer found, but instead, only the more distinct edges are found, such as those around the windows and between the building and the sky. A similar result is found with sigma=1 by increasing T_h (for example, to 40), which excludes the low intensity gradients along the bricks.

Corner Detector

Files

Options

My corner detector has a few user-selectable options:

SIGMA
The value of sigma to use for the calculation of the Gaussian.
GRADIENT_MATRIX_SIZE
The size of the matrix used to discretize the gradient of the Gaussian.
THRESHOLD
The threshold for the minimum eigenvalue. Any window whose covariance matrix has the minimum eigenvalue ≥ THRESHOLD will be considered a possible corner.
WINDOW_SIZE
The size of windows to test for corners. For example, a window size of 6 will result in a 6x6 window around a pixel (x,y) when computing the covariance matrix and drawing the corner box.
DISPLAY_RESULTS
Set to 1, displays the output of the Canny Edge Detector as figures in Matlab. Set to 0, it does not display output.
SAVE_RESULTS
Set to 1, writes the images (both the output from non-maximum and the hysteresis steps) to disk. Set to 0, it does not write files.
EXTRA_RESULTS
Set to 1, writes and/or displays the images of the x- and y-gradients, the intensity of the gradient, as well as the direction of the gradient.
INPUT_FILE
The input filename.

Samples

Checker.jpg


Gradient of the smoothed image in the x direction


Gradient of the smoothed image in the y direction


Intensity of the gradient


Direction of the gradient vector at each point



Output of corner detector, with corners boxed in: sigma = 2, gradient matrix size = 32px, threshold = 1000, window size = 6px

Building.jpg


Output of corner detector, with corners boxed in: sigma = 1, gradient matrix size = 16px, threshold = 500, window size = 6px


Output of corner detector, with corners boxed in: sigma = 2, gradient matrix size = 32px, threshold = 700, window size = 6px

Bigtest.jpg


Output of corner detector, with corners boxed in: sigma = 2, gradient matrix size = 32px, threshold = 700, window size = 6px

Bath.jpg


Output of corner detector, with corners boxed in: sigma = 2, gradient matrix size = 32px, threshold = 700, window size = 12px

Discussion

The corner detection algorithm, while appearing simpler, runs much longer. In this algorithm, the choice of sigma and threshold define greatly the running time of the algorithm and the number of corners found. For example, in the first image of the building above, the corner detector was run with sigma=1 and a threshold of 500. It found many corners, including many of the bricks, but also found "erroneous" corners in the clouds. Simply increasing sigma to 2 and raising the threshold slightly to 700 reduced a great number of the points. With these values, only the most distinct corners on the building are detected, even though some clouds still exhibit the signs of a corner.

To note on running time, as the threshold decreases, more and more windows are added to the list of possible corners and their eigenvalues will have to be sorted and compared later. With a higher threshold, less windows are added and therefore less time will be spent in the sorting and comparing of eigenvalues.

Since I wanted close, small corner selections, I chose small windows to compute the covariance matrix over. For each of the examples above except for Bath, the window size was only 6 pixels. This was key in the bigtest.jpg test image, since a larger value for the window would have led to overlapping corners, therefore leaving some undetected. Bath was chosen to be 12px to give some variance in the results.