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.feature.local.affine;
031
032import java.io.DataInput;
033import java.io.DataOutput;
034import java.io.IOException;
035import java.io.PrintWriter;
036import java.util.Scanner;
037
038import org.openimaj.image.feature.local.keypoints.Keypoint;
039import org.openimaj.image.feature.local.keypoints.KeypointLocation;
040import org.openimaj.image.processing.transform.AffineParams;
041
042/**
043 * An extension of a {@link Keypoint} that holds the {@link AffineParams} and
044 * simulation index of the affine simulation from which it was detected.
045 * 
046 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
047 * 
048 */
049public class AffineSimulationKeypoint extends Keypoint {
050        private static final long serialVersionUID = 1L;
051
052        /**
053         * The affine simulation parameters of the keypoint
054         */
055        public AffineParams affineParams;
056
057        /**
058         * The simulation index of the keypoint; this corresponds to the simulation
059         * in which the keypoint was detected.
060         */
061        public int index;
062
063        /**
064         * Construct with the given feature vector length. The parameters are set to
065         * zero tilt and rotation.
066         * 
067         * @param length
068         *            the length of the feature vector
069         */
070        public AffineSimulationKeypoint(int length) {
071                super(length);
072
073                this.affineParams = new AffineParams();
074        }
075
076        /**
077         * Construct from the given parameters
078         * 
079         * @param k
080         *            a keypoint
081         * @param afParams
082         *            the affine simulation parameters
083         * @param index
084         *            the affine simulation index
085         */
086        public AffineSimulationKeypoint(Keypoint k, AffineParams afParams, int index) {
087                super(k);
088                this.affineParams = new AffineParams();
089                this.affineParams.theta = afParams.theta;
090                this.affineParams.tilt = afParams.tilt;
091                this.index = index;
092        }
093
094        /**
095         * A {@link KeypointLocation} extended to hold a rotation, tilt and index
096         * corresponding to an affine simulation.
097         * 
098         * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
099         * 
100         */
101        public static class AffineSimulationKeypointLocation extends KeypointLocation {
102                private static final long serialVersionUID = 1L;
103
104                /**
105                 * The rotation angle
106                 */
107                public float theta;
108
109                /**
110                 * The amount of tilt
111                 */
112                public float tilt;
113
114                /**
115                 * The simulation index
116                 */
117                public int index;
118
119                /**
120                 * Construct with zero tilt and rotation.
121                 */
122                public AffineSimulationKeypointLocation() {
123                        super();
124                }
125
126                /**
127                 * Construct with the given parameters
128                 * 
129                 * @param x
130                 *            x-ordinate of feature
131                 * @param y
132                 *            y-ordinate of feature
133                 * @param scale
134                 *            scale of feature
135                 * @param ori
136                 *            orientation of feature
137                 * @param theta
138                 *            rotation of the simulation from which the feature was
139                 *            extracted
140                 * @param tilt
141                 *            tilt of the simulation from which the feature was
142                 *            extracted
143                 * @param index
144                 *            index of the simulation from which the feature was
145                 *            extracted
146                 */
147                public AffineSimulationKeypointLocation(float x, float y, float scale, float ori, float theta, float tilt,
148                                int index)
149                {
150                        super(x, y, ori, scale);
151
152                        this.theta = theta;
153                        this.tilt = tilt;
154                        this.index = index;
155                }
156
157                @Override
158                public void writeBinary(DataOutput out) throws IOException {
159                        out.writeFloat(this.x);
160                        out.writeFloat(this.y);
161                        out.writeFloat(this.scale);
162                        out.writeFloat(this.orientation);
163                        out.writeFloat(theta);
164                        out.writeFloat(tilt);
165                        out.writeInt(index);
166                }
167
168                @Override
169                public void writeASCII(PrintWriter out) throws IOException {
170                        /* Output data for the keypoint. */
171                        out.format("%4.2f %4.2f %4.2f %4.3f %4.3f %4.3f %d", y, x, scale, orientation, theta, tilt, index);
172                        out.println();
173                }
174
175                @Override
176                public void readBinary(DataInput in) throws IOException {
177                        super.readBinary(in);
178                        theta = in.readFloat();
179                        tilt = in.readFloat();
180                        index = in.readInt();
181                }
182
183                @Override
184                public void readASCII(Scanner in) throws IOException {
185                        super.readASCII(in);
186                        theta = in.nextFloat();
187                        tilt = in.nextFloat();
188                        String indexString = in.next();
189                        final int dotIndex = indexString.indexOf(".");
190                        if (dotIndex != -1)
191                                indexString = indexString.substring(0, dotIndex);
192                        index = Integer.parseInt(indexString);
193                }
194
195                @Override
196                public Float getOrdinate(int dimension) {
197                        final float[] pos = { x, y, scale, orientation, theta, tilt, index };
198                        return pos[dimension];
199                }
200        }
201
202        @Override
203        public AffineSimulationKeypointLocation getLocation() {
204                return new AffineSimulationKeypointLocation(x, y, scale, ori, this.affineParams.theta, this.affineParams.tilt,
205                                this.index);
206        }
207
208        @Override
209        public void setLocation(KeypointLocation location) {
210                super.setLocation(location);
211                this.affineParams = new AffineParams();
212                this.affineParams.theta = ((AffineSimulationKeypointLocation) location).theta;
213                this.affineParams.tilt = ((AffineSimulationKeypointLocation) location).tilt;
214                this.index = ((AffineSimulationKeypointLocation) location).index;
215        }
216
217        @Override
218        public Float getOrdinate(int dimension) {
219                final float[] pos = { x, y, scale, ori, this.affineParams.theta, this.affineParams.tilt, index };
220                return pos[dimension];
221        }
222
223        @Override
224        public String toString() {
225                return "AffineKeypoint(" + this.affineParams.theta + "," + this.affineParams.tilt + "," + super.toString() + ")";
226        }
227}