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.transform;
031
032import org.openimaj.image.FImage;
033import org.openimaj.image.analysis.algorithm.ImageInterpolation;
034import org.openimaj.image.analysis.algorithm.ImageInterpolation.InterpolationType;
035import org.openimaj.image.analysis.algorithm.ImageInterpolation.Interpolator;
036import org.openimaj.image.processor.ImageProcessor;
037import org.openimaj.image.processor.SinglebandImageProcessor;
038
039/**
040 * {@link ImageProcessor} and associated static utility methods for transforming
041 * an image based on the pixel positions given by a distortion map:
042 * <code>destination(x,y) = source(mapx(x,y), mapy(x,y))</code>. This allows
043 * efficient implementation of highly non-linear mappings.
044 *
045 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
046 */
047public class RemapProcessor implements SinglebandImageProcessor<Float, FImage> {
048        ImageInterpolation interpolation;
049        FImage xords;
050        FImage yords;
051
052        /**
053         * Construct with the given distortion map, and use
054         * {@link InterpolationType#BILINEAR} interpolation.
055         *
056         * @param xords
057         *            the x-ordinates
058         * @param yords
059         *            the y-ordinates
060         */
061        public RemapProcessor(FImage xords, FImage yords) {
062                this(xords, yords, ImageInterpolation.InterpolationType.BILINEAR);
063        }
064
065        /**
066         * Construct with the given distortion map and interpolator.
067         *
068         * @param xords
069         *            the x-ordinates
070         * @param yords
071         *            the y-ordinates
072         * @param interpolator
073         *            the interpolator
074         */
075        public RemapProcessor(FImage xords, FImage yords, Interpolator interpolator) {
076                this.interpolation = new ImageInterpolation(interpolator);
077                this.xords = xords;
078                this.yords = yords;
079        }
080
081        @Override
082        public void processImage(FImage image) {
083                final FImage out = remap(image, xords, yords, interpolation);
084                image.internalAssign(out);
085        }
086
087        /**
088         * Transform an image using the given parameters
089         *
090         * @param in
091         *            the image to transform
092         * @param xords
093         *            the x-ordinates
094         * @param yords
095         *            the y-ordinates
096         * @param interpolator
097         *            the interpolator
098         * @return the transformed image
099         */
100        public static FImage remap(FImage in, FImage xords, FImage yords, Interpolator interpolator) {
101                return remap(in, xords, yords, new ImageInterpolation(interpolator));
102        }
103
104        /**
105         * Transform an image using the given parameters
106         *
107         * @param in
108         *            the image to transform
109         * @param xords
110         *            the x-ordinates
111         * @param yords
112         *            the y-ordinates
113         * @param interpolation
114         *            the interpolation
115         * @return the transformed image
116         */
117        public static FImage remap(FImage in, FImage xords, FImage yords, ImageInterpolation interpolation) {
118                return remap(in, new FImage(xords.width, xords.height), xords, yords, interpolation);
119        }
120
121        /**
122         * Transform an image using the given parameters, and write te results into
123         * <code>out</code>
124         *
125         * @param in
126         *            the image to transform
127         * @param out
128         *            the output image
129         * @param xords
130         *            the x-ordinates
131         * @param yords
132         *            the y-ordinates
133         * @param interpolation
134         *            the interpolation
135         * @return out
136         */
137        public static FImage remap(FImage in, FImage out, FImage xords, FImage yords, ImageInterpolation interpolation) {
138                final int width = Math.min(xords.width, out.width);
139                final int height = Math.min(xords.height, out.height);
140
141                interpolation.analyseImage(in);
142
143                for (int y = 0; y < height; y++) {
144                        for (int x = 0; x < width; x++) {
145                                out.pixels[y][x] = interpolation.getPixelInterpolated(xords.pixels[y][x], yords.pixels[y][x]);
146                        }
147                }
148                return out;
149        }
150
151        /**
152         * Transform an image using the given parameters. Assume
153         * {@link InterpolationType#BILINEAR} interpolation.
154         *
155         * @param in
156         *            the image to transform
157         * @param xords
158         *            the x-ordinates
159         * @param yords
160         *            the y-ordinates
161         * @return the transformed image
162         */
163        public static FImage remap(FImage in, FImage xords, FImage yords) {
164                return remap(in, xords, yords, new ImageInterpolation(ImageInterpolation.InterpolationType.BILINEAR));
165        }
166
167        /**
168         * Transform an image using the given parameters, and write the results into
169         * <code>out</code>. Assume {@link InterpolationType#BILINEAR}
170         * interpolation.
171         *
172         * @param in
173         *            the image to transform
174         * @param out
175         *            the output image
176         * @param xords
177         *            the x-ordinates
178         * @param yords
179         *            the y-ordinates
180         * @return out
181         */
182        public static FImage remap(FImage in, FImage out, FImage xords, FImage yords) {
183                return remap(in, out, xords, yords, new ImageInterpolation(ImageInterpolation.InterpolationType.BILINEAR));
184        }
185}