public void KernelTest1() { double[,] expected = { { 2.1693514414478006E-34, 2.4546349229561677E-22, -1.5279500064746295E-21 }, { -0.00000069069240704724283, 0.9210609940028851, -0.00000012799017494227224 }, { -7.7578659683414284E-22, -4.1079449607342235E-22, 3.2663608516186217E-34 } }; double[,] actual = Gabor.Kernel2D(sigma: 0.1, theta: 0.2, lambda: 0.3, psi: 0.4, gamma: 0.5); Assert.AreEqual(actual.GetLength(0), expected.GetLength(0)); Assert.AreEqual(actual.GetLength(1), expected.GetLength(1)); for (int i = 0; i < actual.GetLength(0); i++) { for (int j = 0; j < actual.GetLength(1); j++) { double e = expected[i, j]; double a = actual[i, j]; Assert.AreEqual(e, a, System.Math.Abs(e * 1e-10)); } } }
public void KernelTest2() { double[,] expected = { { 1.42405394857622E-52, -1.55301965707389E-39, -5.91718738982049E-28, 6.74066784260594E-19, 9.45212732580885E-13, -1.54728187127383E-07, 1.35216035740648E-05 }, { 2.44396261647309E-27, 6.22350869845861E-18, -2.53179283832159E-10, 4.71970195306204E-06, 0.01750857512698, -0.0562293027375883, -0.000676655483164679 }, { -1.18923149745881E-11, 3.26086352470611E-05, -0.0380349460494781, -0.653643620863612, 0.0705347070196069, 1.49826805190377E-06, -8.02838283000017E-11 }, { -0.00143882468734695, 0.0594224852404454, 0.00675479754684435, -2.97718145336781E-05, 8.09821092370491E-11, 1.01520928946922E-17, -3.06243455885214E-27 }, { -2.89102012691001E-05, 2.93060843736615E-09, 4.32869511491687E-12, -4.97862860483868E-19, -4.04134720949385E-28, 4.26508052356691E-39, -1.65106988580208E-53 } }; double[,] actual = Gabor.Kernel2D(sigma: 1, theta: 2, lambda: 3, psi: 4, gamma: 5); Assert.AreEqual(actual.GetLength(0), expected.GetLength(0)); Assert.AreEqual(actual.GetLength(1), expected.GetLength(1)); for (int i = 0; i < actual.GetLength(0); i++) { for (int j = 0; j < actual.GetLength(1); j++) { double e = expected[i, j]; double a = actual[i, j]; Assert.AreEqual(e, a, System.Math.Abs(e * 1e-10)); } } }
/// <summary> /// Process the filter on the specified image. /// </summary> /// /// <param name="sourceData">Source image data.</param> /// <param name="destinationData">Destination image data.</param> /// protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData) { // check image format if ((sourceData.PixelFormat != PixelFormat.Format8bppIndexed) && (sourceData.PixelFormat != PixelFormat.Format24bppRgb)) { throw new UnsupportedImageFormatException("Unsupported image format."); } if (sourceData.PixelFormat != PixelFormat.Format8bppIndexed) { sourceData = Grayscale.CommonAlgorithms.BT709.Apply(sourceData); } if (recompute) { recompute = false; kernel = Gabor.Kernel2D(size: size, lambda: lambda, theta: theta, psi: psi, sigma: sigma, gamma: gamma, normalized: true, function: GaborKernelKind.Imaginary); } int kernelHeight = kernel.GetLength(0); int kernelWidth = kernel.GetLength(1); int centerX = kernelHeight / 2; int centerY = kernelWidth / 2; int width = sourceData.Width; int height = sourceData.Height; int srcStride = sourceData.Stride; int srcOffset = srcStride - width; byte *src = (byte *)sourceData.ImageData.ToPointer(); int[,] response = new int[height, width]; int max = int.MinValue; int min = int.MaxValue; // for each image row for (int y = 0; y < height; y++) { // for each pixel in the row for (int x = 0; x < width; x++, src++) { double sum = 0; // for each kernel row for (int i = 0; i < kernelHeight; i++) { int ir = i - centerY; int t = y + ir; // skip row if (t < 0) { continue; } // break if (t >= height) { break; } int col = ir * srcStride; // for each kernel value in the row for (int j = 0; j < kernelWidth; j++) { int jr = j - centerX; t = x + jr; // skip column if (t < 0) { continue; } if (t < width) { double k = kernel[i, j]; sum += k * src[col + jr]; } } int v = response[y, x] = (int)sum; if (v > max) { max = v; } if (v < min) { min = v; } } } src += srcOffset; } byte *dst = (byte *)destinationData.ImageData.ToPointer(); int pixelSize = System.Drawing.Image.GetPixelFormatSize(destinationData.PixelFormat) / 8; int dstStride = destinationData.Stride; int dstOffset = dstStride - width * pixelSize; if (destinationData.PixelFormat == PixelFormat.Format8bppIndexed) { // for each image row for (int y = 0; y < height; y++) { // for each pixel in the row for (int x = 0; x < width; x++, dst++) { *dst = (byte)((255 * (response[y, x] - min)) / (max - min)); } dst += dstOffset; } } else { // for each image row for (int y = 0; y < height; y++) { // for each pixel in the row for (int x = 0; x < width; x++, dst += pixelSize) { int v = response[y, x]; if (v > 0) { dst[RGB.R] = (byte)((255 * v) / max); } else // (v <= 0) { dst[RGB.B] = (byte)((255 * v) / min); } } dst += dstOffset; } } }