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.analysis.algorithm;
31  
32  import org.openimaj.image.FImage;
33  import org.openimaj.image.analyser.ImageAnalyser;
34  import org.openimaj.math.util.Interpolation;
35  
36  /**
37   * An {@link ImageAnalyser} that can provide interpolate pixel values using a
38   * variety of interpolation approaches.
39   * 
40   * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
41   * 
42   */
43  public class ImageInterpolation implements ImageAnalyser<FImage> {
44  	/**
45  	 * Interface defining an object capable of performing pixel interpolation
46  	 * 
47  	 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
48  	 * 
49  	 */
50  	public static interface Interpolator {
51  		/**
52  		 * Interpolate a pixel value
53  		 * 
54  		 * @param x
55  		 *            the x-ordinate
56  		 * @param y
57  		 *            the y-ordinate
58  		 * @param image
59  		 *            the image
60  		 * @param workingSpace
61  		 *            the working space required
62  		 * @return the interpolated pixel value
63  		 */
64  		public float interpolate(float x, float y, FImage image, Object workingSpace);
65  
66  		/**
67  		 * Create the working space required for interpolation
68  		 * 
69  		 * @return the working space (can be <code>null</code>)
70  		 */
71  		public Object createWorkingSpace();
72  	}
73  
74  	/**
75  	 * Standard interpolation types.
76  	 * 
77  	 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
78  	 * 
79  	 */
80  	public static enum InterpolationType implements Interpolator {
81  		/**
82  		 * Nearest neighbour interpolation
83  		 */
84  		NEAREST_NEIGHBOUR {
85  			@Override
86  			public float interpolate(float x, float y, FImage image, Object workingSpace) {
87  				x = Math.round(x);
88  				y = Math.round(y);
89  
90  				if (x < 0 || x >= image.width || y < 0 || y >= image.height)
91  					return 0;
92  
93  				return image.pixels[(int) y][(int) x];
94  			}
95  
96  			@Override
97  			public Object createWorkingSpace() {
98  				return null;
99  			}
100 		},
101 		/**
102 		 * Bilinear interpolation
103 		 */
104 		BILINEAR {
105 			@Override
106 			public float interpolate(float x, float y, FImage image, Object workingSpace) {
107 				return image.getPixelInterpNative(x, y, 0);
108 			}
109 
110 			@Override
111 			public Object createWorkingSpace() {
112 				return null;
113 			}
114 		},
115 		/**
116 		 * Bicubic interpolation
117 		 */
118 		BICUBIC {
119 			@Override
120 			public float interpolate(float x, float y, FImage image, Object workingSpace) {
121 				final float[][] working = (float[][]) workingSpace;
122 
123 				final int sx = (int) Math.floor(x) - 1;
124 				final int sy = (int) Math.floor(y) - 1;
125 				final int ex = sx + 3;
126 				final int ey = sy + 3;
127 
128 				for (int yy = sy, i = 0; yy <= ey; yy++, i++) {
129 					for (int xx = sx, j = 0; xx <= ex; xx++, j++) {
130 						final int px = xx < 0 ? 0 : xx >= image.width ? image.width - 1 : xx;
131 						final int py = yy < 0 ? 0 : yy >= image.height ? image.height - 1 : yy;
132 
133 						working[i][j] = image.pixels[py][px];
134 					}
135 				}
136 
137 				final float dx = (float) (x - Math.floor(x));
138 				final float dy = (float) (y - Math.floor(y));
139 				return Interpolation.bicubicInterp(dx, dy, working);
140 			}
141 
142 			@Override
143 			public Object createWorkingSpace() {
144 				return new float[4][4];
145 			}
146 		};
147 	}
148 
149 	protected Interpolator interpolator;
150 	protected Object workingSpace;
151 	protected FImage image;
152 
153 	/**
154 	 * Default constructor.
155 	 * 
156 	 * @param interpolator
157 	 *            the interpolator to use
158 	 */
159 	public ImageInterpolation(Interpolator interpolator) {
160 		this.interpolator = interpolator;
161 		this.workingSpace = interpolator.createWorkingSpace();
162 	}
163 
164 	@Override
165 	public void analyseImage(FImage image) {
166 		this.image = image;
167 	}
168 
169 	/**
170 	 * Get the interpolated pixel value of the previously analysed image
171 	 * 
172 	 * @param x
173 	 *            the x-ordinate
174 	 * @param y
175 	 *            the y-ordinate
176 	 * @return the interpolated pixel value
177 	 */
178 	public float getPixelInterpolated(float x, float y) {
179 		return interpolator.interpolate(x, y, image, workingSpace);
180 	}
181 }