/** * Computes the derivative of a Gaussian kernel. * * @param sigma Distributions standard deviation. * @param radius Kernel's radius. * @param normalize * @return The derivative of the gaussian */ protected static Kernel1D_F32 derivative1D_F32( int order, double sigma, int radius, boolean normalize) { Kernel1D_F32 ret = new Kernel1D_F32(radius * 2 + 1); float[] gaussian = ret.data; int index = 0; switch (order) { case 1: for (int i = radius; i >= -radius; i--) { gaussian[index++] = (float) UtilGaussian.derivative1(0, sigma, i); } break; case 2: for (int i = radius; i >= -radius; i--) { gaussian[index++] = (float) UtilGaussian.derivative2(0, sigma, i); } break; case 3: for (int i = radius; i >= -radius; i--) { gaussian[index++] = (float) UtilGaussian.derivative3(0, sigma, i); } break; case 4: for (int i = radius; i >= -radius; i--) { gaussian[index++] = (float) UtilGaussian.derivative4(0, sigma, i); } break; default: throw new IllegalArgumentException("Only derivatives of order 1 to 4 are supported"); } // multiply by the same factor as the gaussian would be normalized by // otherwise it will effective change the intensity of the input image if (normalize) { double sum = 0; for (int i = radius; i >= -radius; i--) { sum += UtilGaussian.computePDF(0, sigma, i); } for (int i = 0; i < gaussian.length; i++) { gaussian[i] /= sum; } } return ret; }
/** * Create a gaussian kernel based on its width. Supports kernels of even or odd widths . * * @param sigma Sigma of the Gaussian distribution. If <= 0 then the width will be used. * @param width How wide the kernel is. Can be even or odd. * @return Gaussian convolution kernel. */ public static Kernel2D_F64 gaussianWidth(double sigma, int width) { if (sigma <= 0) sigma = sigmaForRadius(width / 2, 0); else if (width <= 0) throw new IllegalArgumentException( "Must specify the width since it doesn't know if it should be even or odd"); if (width % 2 == 0) { int r = width / 2 - 1; Kernel2D_F64 ret = new Kernel2D_F64(width); double sum = 0; for (int y = 0; y < width; y++) { double dy = y <= r ? Math.abs(y - r) + 0.5 : Math.abs(y - r - 1) + 0.5; for (int x = 0; x < width; x++) { double dx = x <= r ? Math.abs(x - r) + 0.5 : Math.abs(x - r - 1) + 0.5; double d = Math.sqrt(dx * dx + dy * dy); double val = UtilGaussian.computePDF(0, sigma, d); ret.set(x, y, val); sum += val; } } for (int i = 0; i < ret.data.length; i++) { ret.data[i] /= sum; } return ret; } else { return gaussian2D_F64(sigma, width / 2, true); } }
protected static Kernel1D_F64 gaussian1D_F64(double sigma, int radius, boolean normalize) { Kernel1D_F64 ret = new Kernel1D_F64(radius * 2 + 1); double[] gaussian = ret.data; int index = 0; for (int i = radius; i >= -radius; i--) { gaussian[index++] = UtilGaussian.computePDF(0, sigma, i); } if (normalize) { KernelMath.normalizeSumToOne(ret); } return ret; }