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.demos.features;
031
032import javax.swing.JFrame;
033
034import org.openimaj.demos.Demo;
035import org.openimaj.image.DisplayUtilities;
036import org.openimaj.image.MBFImage;
037import org.openimaj.image.colour.ColourSpace;
038import org.openimaj.image.colour.RGBColour;
039import org.openimaj.image.colour.Transforms;
040import org.openimaj.image.feature.local.interest.HarrisIPD;
041import org.openimaj.image.processing.convolution.FGaussianConvolve;
042import org.openimaj.math.geometry.point.Point2dImpl;
043import org.openimaj.math.geometry.shape.Ellipse;
044import org.openimaj.math.geometry.shape.EllipseUtilities;
045import org.openimaj.math.geometry.shape.Rectangle;
046import org.openimaj.math.geometry.transforms.TransformUtilities;
047
048import Jama.Matrix;
049
050/**
051 * Demo showing harris points
052 *
053 * @author Sina Samangooei (ss@ecs.soton.ac.uk)
054 *
055 */
056@Demo(
057                author = "Sina Samangooei",
058                description = "Shows Harris interest point detection on an animated shape",
059                keywords = {
060                                "sift", "animation", "feature-selection" },
061                title = "Animated Interest Point Visualiser")
062public class AnimatedInterestPointVisualiser {
063        private Rectangle rectangle;
064        private Point2dImpl point;
065        private Matrix transform;
066        private MBFImage image;
067        private int derivscale;
068        private HarrisIPD ipd;
069        private Ellipse ellipseToDraw;
070        private JFrame jframe;
071        private float rotation;
072
073        /**
074         * Construct the demo
075         */
076        public AnimatedInterestPointVisualiser() {
077                this.rectangle = new Rectangle(100, 100, 200, 200);
078                this.point = new Point2dImpl(110, 110);
079                this.rotation = 0f;
080                this.transform = TransformUtilities.rotationMatrixAboutPoint(this.rotation, 200, 200);
081                derivscale = 1;
082                ipd = new HarrisIPD(derivscale, 3);
083                this.image = new MBFImage(400, 400, ColourSpace.RGB);
084                this.jframe = DisplayUtilities.display(this.image);
085                drawShape();
086                updateEllipse();
087
088                class Updater implements Runnable {
089                        private AnimatedInterestPointVisualiser frame;
090
091                        Updater(AnimatedInterestPointVisualiser frame) {
092                                this.frame = frame;
093                        }
094
095                        @Override
096                        public void run() {
097                                while (true) {
098                                        frame.drawShape();
099                                        frame.updateEllipse();
100                                        frame.drawFrame();
101                                        frame.updateTransform();
102                                        try {
103                                                Thread.sleep(1000 / 30);
104                                        } catch (final InterruptedException e) {
105                                        }
106                                }
107                        }
108                }
109                final Thread t = new Thread(new Updater(this));
110                t.start();
111        }
112
113        /**
114         * Update the transform
115         */
116        public void updateTransform() {
117                this.rotation += Math.PI / 100f;
118                this.transform = TransformUtilities.rotationMatrixAboutPoint(
119                                this.rotation, 200, 200);
120        }
121
122        /**
123         * Draw the frame
124         */
125        public void drawFrame() {
126                this.image.createRenderer()
127                                .drawShape(this.ellipseToDraw, RGBColour.RED);
128                DisplayUtilities.display(this.image, this.jframe);
129        }
130
131        private void updateEllipse() {
132                ipd.findInterestPoints(Transforms.calculateIntensityNTSC(this.image));
133                final Point2dImpl np = this.point.transform(transform);
134                final Matrix sm = ipd.getSecondMomentsAt((int) np.x, (int) np.y);
135                ellipseToDraw = EllipseUtilities.ellipseFromSecondMoments(np.x, np.y,
136                                sm, 5 * 2);
137        }
138
139        /**
140         * Draw the shape
141         */
142        public void drawShape() {
143                this.image.fill(RGBColour.WHITE);
144                this.image.createRenderer().drawShapeFilled(
145                                this.rectangle.transform(transform), RGBColour.BLACK);
146
147                this.image = image.process(new FGaussianConvolve(5));
148                this.image.createRenderer().drawPoint(this.point.transform(transform),
149                                RGBColour.RED, 1);
150        }
151
152        /**
153         * The main method
154         *
155         * @param args
156         *            ignored
157         */
158        public static void main(String args[]) {
159                new AnimatedInterestPointVisualiser();
160        }
161}