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.interest;
031
032import java.util.ArrayList;
033import java.util.List;
034
035import org.openimaj.image.FImage;
036import org.openimaj.image.Image;
037import org.openimaj.image.feature.local.keypoints.InterestPointKeypoint;
038import org.openimaj.image.processor.SinglebandImageProcessor;
039import org.openimaj.image.renderer.ImageRenderer;
040import org.openimaj.math.geometry.shape.Ellipse;
041
042/**
043 * Visualise the interest points extracted using an {@link InterestPointDetector}. Allows for points and areas of interest to be drawn
044 * @author Sina Samangooei (ss@ecs.soton.ac.uk)
045 *
046 * @param <T>
047 * @param <Q>
048 */
049public class InterestPointVisualiser <T, Q extends Image<T,Q> & SinglebandImageProcessor.Processable<Float,FImage,Q>> {
050        Q image;
051        List<Ellipse> interestPoints;
052        
053        /**
054         * Image from which interest points were extract and the extracted points.
055         * @param image source image
056         * @param keys extracted interest points
057         */
058        public InterestPointVisualiser(Q image, List<Ellipse> keys) {
059                this.image = image;
060                this.interestPoints = keys;
061        }
062        
063        /**
064         * Extract ellipses from second moment matricies of interest point keypoints
065         * @param <T> Image pixel type
066         * @param <Q> Image type
067         * @param image the image to visualise with
068         * @param keys the list of interest points
069         * @return a prepared visualiser
070         */
071        public static <T, Q extends Image<T,Q> & SinglebandImageProcessor.Processable<Float,FImage,Q>>InterestPointVisualiser<T,Q> visualiseKeypoints(Q image, List<? extends InterestPointKeypoint<? extends InterestPointData>> keys){
072                List<Ellipse> interestPoints = new ArrayList<Ellipse>();
073                for(InterestPointKeypoint<? extends InterestPointData> k : keys){
074                        interestPoints.add(k.location.getEllipse());
075                }
076                return new InterestPointVisualiser<T,Q>(image,interestPoints);
077        }
078        
079        /**
080         * Extract ellipses from second moment matricies of interest point keypoints
081         * @param <T> Image pixel type
082         * @param <Q> Image type
083         * @param image the image to visualise with
084         * @param keys the list of interest points
085         * @return a prepared visualiser
086         */
087        public static <T, Q extends Image<T,Q> & SinglebandImageProcessor.Processable<Float,FImage,Q>>InterestPointVisualiser<T,Q> visualiseInterestPoints(Q image, List<? extends InterestPointData> keys){
088                List<Ellipse> interestPoints = new ArrayList<Ellipse>();
089                for(InterestPointData k : keys){
090                        interestPoints.add(k.getEllipse());
091                }
092                return new InterestPointVisualiser<T,Q>(image,interestPoints);
093        }
094        
095        /**
096         * Extract ellipses from second moment matricies of interest point keypoints
097         * @param <T> Image pixel type
098         * @param <Q> Image type
099         * @param image the image to visualise with
100         * @param keys the list of interest points
101         * @param scale scale axis
102         * @return a prepared visualiser
103         */
104        public static <T, Q extends Image<T,Q> & SinglebandImageProcessor.Processable<Float,FImage,Q>>InterestPointVisualiser<T,Q> visualiseInterestPoints(Q image, List<? extends InterestPointData> keys, double scale){
105                List<Ellipse> interestPoints = new ArrayList<Ellipse>();
106                for(InterestPointData k : keys){
107                        interestPoints.add(k.getEllipse());
108                }
109                return new InterestPointVisualiser<T,Q>(image,interestPoints);
110        }
111        
112        /**
113         * Draw the interest points, a central dot for in the pointCol and a bordered area of interest by borderCol.
114         * If either is null it is not drawn.
115         * 
116         * @param pointCol
117         * @param borderCol
118         * @return image with patches drawn
119         */
120        public Q drawPatches(T pointCol, T borderCol) {
121                Q output = image.clone();
122                ImageRenderer<T, Q> renderer = output.createRenderer();
123                
124                for (Ellipse k : interestPoints) {
125                        if(pointCol!=null){
126                                renderer.drawPoint(k.calculateCentroid(), pointCol, 3);
127                        }
128                        if (borderCol != null) {
129                                renderer.drawShape(k,borderCol);
130                        }
131                }
132                
133                return output;
134        }
135        
136        public Q drawCenter(T col) {
137                Q output = image.clone();
138                ImageRenderer<T, Q> renderer = output.createRenderer();
139                
140                for(Ellipse e : interestPoints){
141                        renderer.drawPoint(e.calculateCentroid(), col,2);
142                }
143                return output;
144        }
145}