This program can be used to evaluate the first directional derivative of an image. The orientation of the filter can be specified by the user. In general, these filters could be useful for edge detection and image analysis.
The filters created by this program are derived from the "steerable filters" presented in:
W. T. Freeman and E. H. Adelson, "The Design and Use of Steerable Filters", IEEE PAMI, 1991.
A demonstration program (runDemo.m) is included which will create an animation showing the directional derivatives evenly-spaced from 0 degrees to 360 degrees (in 15 degree increments).
very useful thanks
what does filter supprt exactly mean?
The two-step filtering is because the Gaussian is separable: the code convolves with two 1D filters, once along each of the axes (note the transpose operation!). This is the right way to do it. The function CONV2 actually supports separable filters, you can substitute this code:
Ix = conv2(conv2(I,-gp,'same'),g','same');
Ix = conv2(g,-gp,I,'same');
These produce the same result and I guess there is not much difference in execution time either. It only makes the code simpler to read.
Not only the definition of the derivative of the Gaussian is wrong, the Gaussian itself is also wrong: it needs to be normalized!
g = exp(-(x.^2)/(2*sigma^2)) / (sigma*sqrt(2*pi));
gp = -(x/sigma^2) .* g;
Also, the filter support is a little small, especially for the derivative. I would use ceil(3*sigma).
My last comment:
I think that what Urs meant was that, when you compute the filter under a number of orientations, you perform the same convolutions over and over again. Calculating the kernel is not that much work at all, calculating the two convolutions is quite a bit more work! You can reuse the images Ix and Iy to compute the filter result under any orientation, this is the interesting part of the steerable filter. Your function should store Ix and Iy in the output argument h, not the Gaussian kernels g and gp.
I have also noticed the error in the first derivative of the Gaussian at line 108.
For your second question, I think that a Gaussian smoothing helps as a preprocessing step to remove noise.
line 108: gp = -(x/sigma).*exp(-(x.^2)/(2*sigma^2));
The derivative is not taken correctly, it should be:
gp = -(x/sigma^2).*exp(-(x.^2)/(2*sigma^2));
Another question is why do you convolve the image with gaussian itself? Looks like you doing two step filtering, convolving with gaussian and then with its derivative.
great!helps a lot.
I read the paper you used in implementing this function. they have G_theta = G'_90*cos(theta) + G'_0*sin(theta).
how did you manage to separate the filters into 1D - gaussian(x)*gausian(0)'*cos(theta) ... could you direct to a paper or something or point out what I missed ?
This script is great by the way.
The source code has been updated to address the recommendations made by Urs (us) Schwarz. The demo program now illustrates the reuse of previously-computed filters.
currently more of a demo package than an industrial-strength function
- it calculates the filter each time anew; a second output should return the kernel, which could be re-used if entered as an additional arg, eg,
- im2double is part of the image proc tbx, which is not mentioned as a requirement
- the visualization part, whilst cute, should be left to the user outside the function, or be conditional with an additional option
This version addresses the comments made by Urs (us) Schwarz. The update attempts to extend the general utility of this program beyond the basic demonstration previously provided.