1 /**
2 * Copyright (c) 2011, The University of Southampton and the individual contributors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * * Neither the name of the University of Southampton nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 package org.openimaj.image.processing.convolution;
31
32 import org.openimaj.image.FImage;
33 import org.openimaj.image.processor.SinglebandImageProcessor;
34
35 /**
36 * Image processor for FImage capable of performing convolutions with Gaussians.
37 *
38 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
39 */
40 public class FGaussianConvolve implements SinglebandImageProcessor<Float, FImage> {
41 /**
42 * The default number of sigmas at which the Gaussian function is truncated
43 * when building a kernel
44 */
45 public static final float DEFAULT_GAUSS_TRUNCATE = 4.0f;
46
47 protected float[] kernel;
48
49 /**
50 * Construct an {@link FGaussianConvolve} with a Gaussian of standard
51 * deviation sigma.
52 *
53 * @param sigma
54 * Gaussian kernel standard deviation
55 */
56 public FGaussianConvolve(float sigma) {
57 this(sigma, DEFAULT_GAUSS_TRUNCATE);
58 }
59
60 /**
61 * Construct an {@link FGaussianConvolve} with a Gaussian of standard
62 * deviation sigma. The truncate parameter defines how many sigmas wide the
63 * kernel is.
64 *
65 * @param sigma
66 * @param truncate
67 */
68 public FGaussianConvolve(float sigma, float truncate) {
69 kernel = makeKernel(sigma, truncate);
70 }
71
72 /**
73 * Construct a zero-mean Gaussian with the specified standard deviation.
74 *
75 * @param sigma
76 * the standard deviation of the Gaussian
77 * @return an array representing a Gaussian function
78 */
79 public static float[] makeKernel(float sigma) {
80 return makeKernel(sigma, DEFAULT_GAUSS_TRUNCATE);
81 }
82
83 /**
84 * Construct a zero-mean Gaussian with the specified standard deviation.
85 *
86 * @param sigma
87 * the standard deviation of the Gaussian
88 * @param truncate
89 * the number of sigmas from the centre at which to truncate the
90 * Gaussian
91 * @return an array representing a Gaussian function
92 */
93 public static float[] makeKernel(float sigma, float truncate) {
94 if (sigma == 0)
95 return new float[] { 1f };
96 // The kernel is truncated at truncate sigmas from center.
97 int ksize = (int) (2.0f * truncate * sigma + 1.0f);
98 // ksize = Math.max(1, ksize); // size must be at least 3
99 if (ksize % 2 == 0)
100 ksize++; // size must be odd
101
102 final float[] kernel = new float[ksize];
103
104 // build kernel
105 float sum = 0.0f;
106 for (int i = 0; i < ksize; i++) {
107 final float x = i - ksize / 2;
108 kernel[i] = (float) Math.exp(-x * x / (2.0 * sigma * sigma));
109 sum += kernel[i];
110 }
111
112 // normalise area to 1
113 for (int i = 0; i < ksize; i++) {
114 kernel[i] /= sum;
115 }
116
117 return kernel;
118 }
119
120 /*
121 * (non-Javadoc)
122 *
123 * @see
124 * org.openimaj.image.processor.ImageProcessor#processImage(org.openimaj
125 * .image.Image)
126 */
127 @Override
128 public void processImage(FImage image) {
129 FImageConvolveSeparable.convolveHorizontal(image, kernel);
130 FImageConvolveSeparable.convolveVertical(image, kernel);
131 }
132 }