View Javadoc

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.citation.annotation.Reference;
33  import org.openimaj.citation.annotation.ReferenceType;
34  import org.openimaj.image.FImage;
35  import org.openimaj.image.processor.SinglebandImageProcessor;
36  
37  /**
38   * Fast approximate Gaussian smoothing using repeated fast box filtering.
39   * 
40   * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
41   * 
42   */
43  @Reference(
44  		type = ReferenceType.Inproceedings,
45  		author = { "Kovesi, P." },
46  		title = "Fast Almost-Gaussian Filtering",
47  		year = "2010",
48  		booktitle = "Digital Image Computing: Techniques and Applications (DICTA), 2010 International Conference on",
49  		pages = { "121", "125" },
50  		month = "Dec",
51  		customData = {
52  				"keywords", "Gaussian processes;approximation theory;band-pass filters;image processing;Gaussian bandpass filters;fast almost-Gaussian filtering;image averaging;integral images;log-Gabor filters;separable moving average filters;summed area tables;symmetric transfer function;Approximation methods;Bandwidth;Computer vision;Frequency domain analysis;Laplace equations;Pixel;Transfer functions;Difference of Gaussian filtering;Gaussian smoothing",
53  				"doi", "10.1109/DICTA.2010.30"
54  		})
55  public class FFastGaussianConvolve implements SinglebandImageProcessor<Float, FImage> {
56  	private final int n;
57  	private final int m;
58  	private SinglebandImageProcessor<Float, FImage> wlBox;
59  	private SinglebandImageProcessor<Float, FImage> wuBox;
60  
61  	/**
62  	 * Construct an {@link FFastGaussianConvolve} to approximate blurring with a
63  	 * Gaussian of standard deviation sigma.
64  	 * 
65  	 * @param sigma
66  	 *            Standard deviation of the approximated Gaussian
67  	 * @param n
68  	 *            Number of filtering iterations to perform (usually between 3
69  	 *            and 6)
70  	 */
71  	public FFastGaussianConvolve(float sigma, int n) {
72  		if (sigma < 1.8) {
73  			// std.devs of less than 1.8 are not well approximated.
74  			this.m = 1;
75  			this.n = 1;
76  			this.wlBox = new FGaussianConvolve(sigma);
77  		} else {
78  			final float ss = sigma * sigma;
79  			final double wIdeal = Math.sqrt((12.0 * ss / n) + 1.0);
80  			final int wl = (((int) wIdeal) % 2 == 0) ? (int) wIdeal - 1 : (int) wIdeal;
81  			final int wu = wl + 2;
82  
83  			this.n = n;
84  			this.m = Math.round((12 * ss - n * wl * wl - 4 * n * wl - 3 * n) / (-4 * wl - 4));
85  
86  			this.wlBox = new AverageBoxFilter(wl);
87  			this.wuBox = new AverageBoxFilter(wu);
88  		}
89  	}
90  
91  	@Override
92  	public void processImage(FImage image) {
93  		for (int i = 0; i < m; i++)
94  			wlBox.processImage(image);
95  		for (int i = 0; i < n - m; i++)
96  			wuBox.processImage(image);
97  	}
98  }