Click here to Skip to main content
15,891,316 members
Please Sign up or sign in to vote.
5.00/5 (2 votes)
See more:
I am having difficulty implementing a Laplacian of Gaussian kernel. I have the following code and I am trying to implement a 9x9 kernel with sigma = 1.4. The kernel is shown on this link

http://homepages.inf.ed.ac.uk/rbf/HIPR2/log.htm[^]

However, my values are nothing like those in that kernel, I think my function is off. Help would be greatly appreciated. Thank you.

const Int32 N = 9; //, Nh = N / 2;
float[,] MASK = new float[N, N];
int min = (int)Math.Ceiling((double)-N / (double)2);
int max = (int)Math.Floor((double)N/ (double)2);
float sigma = 1.4f;
float s2 = sigma * sigma;
float s4 = sigma * sigma * sigma * sigma;

int xCount = 0;

for(int x = min; x <= max; ++x)
{
   int yCount = 0;
   for(int y = min; y <= max; ++y)
   {
      float val = (float)(-1.0f / (Math.PI * (s4))) * (1.0f - ((x * x + y * y) / (2.0f * (s2)))) * (float)Math.Exp((-(x * x + y * y) / (2.0f * (s2))));
      MASK[xCount, yCount] = val;
      ++yCount;
   }
   ++xCount;
}
Posted
Updated 31-Mar-10 21:12pm
v3

I'm sorry I can't help you directly with your problem, but when I have a issue complex mathmatical transformation like this I test my code on a very small sample set of simple test data.

Sometimes I reproduce the equations in Excel (or on paper) and feed the same test data into my code and into the test spreadsheet. If it still doesn't correlate I break the equations down so that the code is over a few lines then single step through checking the results on each line of code until I find the difference between my spreadsheet data and my program results.

Sometime the error is a simple typo, they can be hard to spot!

Good Luck, :)
 
Share this answer
 
I think you're pretty close. When performing the actual convolution you're going to expect that a constant input (say always 1) results in the same constant value at the output. The formula (and your code) don't account for that, you need a correction factor of around 480.

And then of course, they have shown an all-integer approximation. What normally happens is this I guess:
- choose a correction factor;
- round all numbers to integers;
- check the sum equals N*N;
- iterate the above (and fiddle a bit when rounding) until it all matches well.

A simpler approach would be to come up with a one-dimensional integer approximation, then multiple that to itself using integers only. It would still need some fixing up to get the sum exact though.

:)
 
Share this answer
 
v2
Yes. I had to add a scaling factor to the code and then round this value to an int. Thank you all for your suggestions. Greatly appreciated.
 
Share this answer
 
Although the question is like 5 years old and it marks solved here, but since i stumbled upon the same issue while trying some opencv stuff, I would like to comment on it. There is one more complication to this apart from scaling.

It is the formula for an LoG operator which is a double derivative over an image (gaussian smoothed to remove noise which gets immensely enhanced by double derivative). Hence, when you do convolution with a constant input, you should expect 0 at output and not the same constant value (double derivative of constant is 0).

When you compute a kernel using this formula, at the first look, you will notice some big negative values at the centre of the kernel and smaller positive values as you go away from the centre. Probably, you would expect it to work as described in above paragraph. But why you won't get this is because this formula is derived by double differentiating gaussian function and hence, describes an infinite impulse response. In other words, you need to convolve with the infinite signal to get 0 for a constant input. You can easily verify this by summing up all values in the kernel which will come out to be a non-zero negative number (ideally, you'd want it to be 0). As you increase the size of filter, this value will decrease but that will also have an impact on your filter performance & timing. Hence, you can't just put an arbitrarily large number.

One way to do this is by finding sum of all the values and increase net positive values in kernel by exactly that amount so that the sum of all values is 0. To preserve the shape of filter to maximum extent possible, you should do a weighted increment of the positive values for eg. let sum of all values be S; sum of all positive values be PS. Then for every positive value N, increase it by N*S/PS and let the negative values be as it is.

After this, you can do scaling and round off the values to nearest integer. Or you can work on floating point numbers and normalize the final output later.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900