/// <summary>
/// Computes the 2-D Gabor kernel.
/// </summary>
///
public static double[,] Kernel2D(int size, double lambda, double theta,
double psi, double sigma, double gamma, bool normalized, GaborKernelKind function)
{
double sigmaX = sigma;
double sigmaY = sigma / gamma;
double a = Math.Max(
Math.Abs(size * sigmaX * Math.Cos(theta)),
Math.Abs(size * sigmaY * Math.Sin(theta)));
int xMax = (int)Math.Ceiling(Math.Max(1, a));
double b = Math.Max(
Math.Abs(size * sigmaX * Math.Sin(theta)),
Math.Abs(size * sigmaY * Math.Cos(theta)));
int yMax = (int)Math.Ceiling(Math.Max(1, b));
int[] xValues = Matrix.Vector(-xMax, xMax, increment: 1);
int[] yValues = Matrix.Vector(-yMax, yMax, increment: 1);
System.Diagnostics.Debug.Assert(xValues.Length == (2 * xMax + 1));
System.Diagnostics.Debug.Assert(yValues.Length == (2 * yMax + 1));
double[,] kernel = new double[xValues.Length, yValues.Length];
double sum = 0;
switch (function)
{
case GaborKernelKind.Real:
for (int i = 0; i < xValues.Length; i++)
{
for (int j = 0; j < yValues.Length; j++)
{
sum += kernel[i, j] = Gabor.RealFunction2D(
xValues[i], yValues[j], lambda, theta, psi, sigma, gamma);
}
}
break;
case GaborKernelKind.Imaginary:
for (int i = 0; i < xValues.Length; i++)
{
for (int j = 0; j < yValues.Length; j++)
{
sum += kernel[i, j] = Gabor.ImaginaryFunction2D(
xValues[i], yValues[j], lambda, theta, psi, sigma, gamma);
}
}
break;
case GaborKernelKind.Magnitude:
for (int i = 0; i < xValues.Length; i++)
{
for (int j = 0; j < yValues.Length; j++)
{
sum += kernel[i, j] = Gabor.Function2D(
xValues[i], yValues[j], lambda, theta, psi, sigma, gamma).Magnitude;
}
}
break;
case GaborKernelKind.SquaredMagnitude:
for (int i = 0; i < xValues.Length; i++)
{
for (int j = 0; j < yValues.Length; j++)
{
sum += kernel[i, j] = Gabor.Function2D(
xValues[i], yValues[j], lambda, theta, psi, sigma, gamma).SquaredMagnitude;
}
}
break;
}
if (normalized)
{
kernel.Divide(sum, inPlace: true);
}
return(kernel);
}