001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.image.processing.convolution; 031 032import org.openimaj.citation.annotation.Reference; 033import org.openimaj.citation.annotation.ReferenceType; 034import org.openimaj.image.FImage; 035import org.openimaj.image.processor.SinglebandImageProcessor; 036 037/** 038 * Fast approximate Gaussian smoothing using repeated fast box filtering. 039 * 040 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 041 * 042 */ 043@Reference( 044 type = ReferenceType.Inproceedings, 045 author = { "Kovesi, P." }, 046 title = "Fast Almost-Gaussian Filtering", 047 year = "2010", 048 booktitle = "Digital Image Computing: Techniques and Applications (DICTA), 2010 International Conference on", 049 pages = { "121", "125" }, 050 month = "Dec", 051 customData = { 052 "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", 053 "doi", "10.1109/DICTA.2010.30" 054 }) 055public class FFastGaussianConvolve implements SinglebandImageProcessor<Float, FImage> { 056 private final int n; 057 private final int m; 058 private SinglebandImageProcessor<Float, FImage> wlBox; 059 private SinglebandImageProcessor<Float, FImage> wuBox; 060 061 /** 062 * Construct an {@link FFastGaussianConvolve} to approximate blurring with a 063 * Gaussian of standard deviation sigma. 064 * 065 * @param sigma 066 * Standard deviation of the approximated Gaussian 067 * @param n 068 * Number of filtering iterations to perform (usually between 3 069 * and 6) 070 */ 071 public FFastGaussianConvolve(float sigma, int n) { 072 if (sigma < 1.8) { 073 // std.devs of less than 1.8 are not well approximated. 074 this.m = 1; 075 this.n = 1; 076 this.wlBox = new FGaussianConvolve(sigma); 077 } else { 078 final float ss = sigma * sigma; 079 final double wIdeal = Math.sqrt((12.0 * ss / n) + 1.0); 080 final int wl = (((int) wIdeal) % 2 == 0) ? (int) wIdeal - 1 : (int) wIdeal; 081 final int wu = wl + 2; 082 083 this.n = n; 084 this.m = Math.round((12 * ss - n * wl * wl - 4 * n * wl - 3 * n) / (-4 * wl - 4)); 085 086 this.wlBox = new AverageBoxFilter(wl); 087 this.wuBox = new AverageBoxFilter(wu); 088 } 089 } 090 091 @Override 092 public void processImage(FImage image) { 093 for (int i = 0; i < m; i++) 094 wlBox.processImage(image); 095 for (int i = 0; i < n - m; i++) 096 wuBox.processImage(image); 097 } 098}