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.tools.vis;
031
032import java.io.File;
033import java.io.IOException;
034import java.util.ArrayList;
035import java.util.List;
036
037import org.kohsuke.args4j.Argument;
038import org.kohsuke.args4j.CmdLineException;
039import org.kohsuke.args4j.CmdLineParser;
040import org.kohsuke.args4j.Option;
041import org.openimaj.feature.local.list.LocalFeatureList;
042import org.openimaj.feature.local.list.MemoryLocalFeatureList;
043import org.openimaj.image.ImageUtilities;
044import org.openimaj.image.MBFImage;
045import org.openimaj.image.colour.RGBColour;
046import org.openimaj.image.feature.local.keypoints.Keypoint;
047import org.openimaj.image.feature.local.keypoints.KeypointVisualizer;
048import org.openimaj.image.feature.local.keypoints.quantised.QuantisedKeypoint;
049
050/**
051 * A tool for visualising quantised sift features by drawing their sampling
052 * boxes on the image they were extracted from
053 * 
054 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
055 */
056public class QuantisedSIFTVisualiser {
057        @Option(name="--input-image", aliases="-ii", required=true, usage="input image file")
058        File imageFile;
059        
060        @Option(name="--input-features", aliases="-if", required=true, usage="input quantised features file")
061        File quantisedFeatureFile;
062
063        @Option(name="--output", aliases="-o", required=true, usage="output image file")
064        File outputImageFile;
065        
066        @Option(name="--colour", aliases="-c", required=false, usage="colour to draw boxes in")
067        String colour = "BLUE";
068        Float[] colourValue = null; 
069        
070        @Argument(required=false, usage="required term identifiers")
071        List<Integer> requiredIds;
072
073        void process() throws IOException {
074                LocalFeatureList<QuantisedKeypoint> qkeys = MemoryLocalFeatureList.read(quantisedFeatureFile, QuantisedKeypoint.class);
075                List<Keypoint> keys = new ArrayList<Keypoint>();
076                
077                MBFImage image = ImageUtilities.readMBF(imageFile);
078                
079                
080                if (requiredIds == null || requiredIds.size() == 0) {
081                        for (QuantisedKeypoint kpt : qkeys) {
082                                keys.add(makeKeypoint(kpt));
083                        }
084                } else {
085                        for (QuantisedKeypoint kpt : qkeys) {
086                                if (requiredIds.contains(kpt.id)) {
087                                        keys.add(makeKeypoint(kpt));
088                                }
089                        }
090                }
091                
092                KeypointVisualizer<Float[], MBFImage> viz = new KeypointVisualizer<Float[], MBFImage>(image, keys);
093                MBFImage outimg = viz.drawPatches(colourValue, null);
094                
095                ImageUtilities.write(outimg, outputImageFile);
096        }
097        
098        protected Keypoint makeKeypoint(QuantisedKeypoint kpt) {
099                Keypoint key = new Keypoint();
100                
101                key.y = kpt.location.y;
102                key.x = kpt.location.x;
103                key.scale = kpt.location.scale;
104                key.ori = kpt.location.orientation;
105                
106                return key; 
107        }
108        
109        static QuantisedSIFTVisualiser load(String [] args) {
110                QuantisedSIFTVisualiser options = new QuantisedSIFTVisualiser();
111        CmdLineParser parser = new CmdLineParser( options );
112
113        try {
114                parser.parseArgument( args );
115                
116                options.colourValue = RGBColour.fromString(options.colour);
117        } catch( CmdLineException e ) {
118                System.err.println( e.getMessage() );
119                System.err.println( "java " + QuantisedSIFTVisualiser.class.getName() + " options...");
120                parser.printUsage( System.err );
121                System.exit(1);
122        }
123
124        return options;
125        }
126        
127        /**
128         * The main method of the tool.
129         * @param args
130         * @throws IOException
131         */
132        public static void main(String [] args) throws IOException {
133                QuantisedSIFTVisualiser extr = QuantisedSIFTVisualiser.load(args);
134                extr.process();
135        }
136}