001/**
002 * This source code file is part of a direct port of Stan Birchfield's implementation
003 * of a Kanade-Lucas-Tomasi feature tracker. The original implementation can be found
004 * here: http://www.ces.clemson.edu/~stb/klt/
005 *
006 * As per the original code, the source code is in the public domain, available
007 * for both commercial and non-commercial use.
008 */
009package org.openimaj.video.tracking.klt;
010
011import java.io.DataOutputStream;
012import java.io.File;
013import java.io.FileOutputStream;
014import java.io.IOException;
015import java.io.PrintWriter;
016import java.util.ArrayList;
017import java.util.List;
018import java.util.SortedMap;
019import java.util.TreeMap;
020
021/**
022 * A table storing features per frame
023 * 
024 * @author Stan Birchfield
025 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
026 */
027public class FeatureTable {
028        /**
029         * The table of features
030         */
031        public SortedMap<Integer, List<Feature>> features;
032        
033        /**
034         * The number of features 
035         */
036        public int nFeatures;
037
038        /*********************************************************************
039         * KLTCreateFeatureTable
040         * @param nFeatures 
041         *
042         */
043        public FeatureTable(int nFeatures) {
044                features = new TreeMap<Integer, List<Feature>>();
045                this.nFeatures = nFeatures;
046        }
047
048        /**
049         * Store a list of features for the given frame number
050         * @param fl
051         * @param frame
052         */
053        public void storeFeatureList(FeatureList fl, int frame) {
054                ArrayList<Feature> list = new ArrayList<Feature>(fl.features.length);
055                
056                for (Feature f : fl.features)
057                        list.add(f.clone());
058                
059                features.put(frame, list);
060        }
061
062        /**
063         * Convert to a string representation.
064         * @param fmt
065         * @param comments
066         * @return the string representation.
067         */
068        public String toString(String fmt, boolean comments) {
069                String [] setup = IOUtils.setupTxtFormat(fmt);
070                String format = setup[0];
071                String type = setup[1];
072
073                String s = IOUtils.getHeader(format, IOUtils.StructureType.FEATURE_TABLE, features.size(), nFeatures, comments);
074
075                for (int j = 0 ; j < nFeatures; j++) {
076                        s += String.format("%7d | ", j);
077                        for (int i = 0 ; i < features.size(); i++)
078                                s += features.get(i).get(j).toString(format, type);
079                        s += "\n";
080                }
081
082                return s;
083        }
084
085        @Override
086        public String toString() {
087                return toString("%3d", false);
088        }
089
090        /**
091         * Write feature table to a file.
092         * @param fname
093         * @param fmt
094         * @throws IOException
095         */
096        public void writeFeatureTable(File fname, String fmt) throws IOException
097        {
098                if (fmt != null) {  /* text file or stderr */ 
099                        if (fname != null) {
100                                PrintWriter bw = new PrintWriter(new FileOutputStream(fname)); 
101                                bw.write(toString(fmt, true));
102                                bw.close();
103                        } else {
104                                System.out.print(toString(fmt, false));
105                        }
106                } else {  /* binary file */
107                        DataOutputStream dos = new DataOutputStream(new FileOutputStream(fname));
108
109                        dos.write(IOUtils.binheader_ft.getBytes("US-ASCII"));
110                        dos.writeInt(features.size());
111                        dos.writeInt(nFeatures);
112
113                        for (int j = 0 ; j < nFeatures ; j++)  {
114                                for (int i = 0 ; i < features.size() ; i++)  {
115                                        features.get(j).get(i).writeFeatureBin(dos);
116                                }
117                        }
118
119                        dos.close();
120                }
121        }
122}
123