faster_bytecode.h

00001 /*
00002 
00003     This file is part of the FAST-ER machine learning system.
00004     Copyright (C) 2008  Edward Rosten and Los Alamos National Laboratory
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License along
00017     with this program; if not, write to the Free Software Foundation, Inc.,
00018     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00019 */
00020 #ifndef FASTER_BYTECODE_H
00021 #define FASTER_BYTECODE_H
00022 
00023 #include <vector>
00024 #include <climits>
00025 #include <cstdlib>
00026 #include <iostream>
00027 #include <cvd/byte.h>
00028 #include <cvd/image.h>
00029 #include <tag/stdpp.h>
00030 
00031 /// This struct contains a byte code compiled version of the detector.
00032 /// 
00033 ///
00034 /// @ingroup gFastTree
00035 struct block_bytecode
00036 {
00037 
00038     /// This is a bytecode element for the bytecode-compiled
00039     /// detector. The bytecode consists of a number of fixed length 
00040     /// blocks representing a 3 way branch. Special values of
00041     /// of a block indicate the result that a pixel is a corner or
00042     /// non-corner.
00043     ///
00044     /// Specifically, if <code>lt == 0</code>, then this is a leaf and \c gt holds the class.
00045     /// The root node is always stored as the first bytecode instruction.
00046 
00047     /// @ingroup gFastTree
00048     struct fast_detector_bit
00049     {
00050         int offset; ///< Memory offset from centre pixel to examine. This means that the fast 
00051                     ///detector must be created for an image of a known width.
00052 
00053         //Root node is 0. If lt == 0, then this is a leaf.
00054         //gt holds the class.
00055 
00056         int lt; ///<Position in bytecode to branch to if offset pixel is much darker than the centre pixel. If this 
00057                 ///is zero, then gt stores the result.
00058         int gt; ///<Position in bytecode to branch to if offset pixel is much brighter than the centre pixel. If lt==0
00059                 ///is a result block, then this stores the result, 0 for a non corner, 1 for a corner.
00060         int eq; ///<Position in bytecode to branch to otherwise.
00061     };
00062 
00063     
00064     std::vector<fast_detector_bit> d; ///<This contains the compiled bytecode.
00065 
00066     ///Detects a corner at a given pointer, without the book keeping required to compute the score.
00067     ///This is quite a lot faster than @ref detect.
00068     ///
00069     ///@param imp  Pointer at which to detect corner
00070     ///@param b    FAST barrier
00071     ///@return     is a corner or not
00072     inline bool detect_no_score(const CVD::byte* imp, int b) const 
00073     {
00074         int n=0;    
00075         int cb = *imp + b;
00076         int c_b = *imp - b;
00077         int p;
00078 
00079         while(d[n].lt)
00080         {
00081             p = imp[d[n].offset];
00082 
00083             if(p > cb)
00084                 n = d[n].gt;
00085             else if(p < c_b)
00086                 n = d[n].lt;
00087             else
00088                 n = d[n].eq;
00089         }
00090         
00091         return d[n].gt;
00092     }
00093 
00094     ///Detects a corner at a given pointer, with book-keeping required for score computation
00095     ///
00096     ///@param imp  Pointer at which to detect corner
00097     ///@param b    FAST barrier
00098     ///@return     0 for non-corner, minimum increment required to make detector go down different branch, if it is a corner.
00099     inline int detect(const CVD::byte* imp, int b) const
00100     {
00101         int n=0;    
00102         int m = INT_MAX;
00103         int cb = *imp + b;
00104         int c_b = *imp - b;
00105         int p;
00106 
00107         while(d[n].lt)
00108         {
00109             p = imp[d[n].offset];
00110 
00111             if(p > cb)
00112             {
00113                 if(p-cb < m)
00114                     m = p-cb;
00115 
00116                 n = d[n].gt;
00117             }
00118             else if(p < c_b)
00119             {
00120                 if(c_b - p < m)
00121                     m = c_b - p;
00122             
00123                 n = d[n].lt;
00124             }
00125             else
00126                 n = d[n].eq;
00127         }
00128         
00129         if(d[n].gt)
00130             return m;
00131         else
00132             return 0;
00133     }
00134     
00135     ///Serialize the detector to an ostream. The serialized detector a number of lines
00136     ///of the form:
00137     ///@code
00138     ///Block N [X Y] G E L
00139     ///@endcode
00140     ///or:
00141     ///@code
00142     ///Block N corner
00143     ///@endcode
00144     ///or:
00145     ///@code
00146     ///Block N non_corner
00147     ///@endcode
00148     ///The first block type represents the code:
00149     ///@code
00150     ///if Image[current_pixel + (x, y)] > Image[current_pixel] + threshold
00151     ///   goto block G
00152     ///elseif Image[current_pixel + (x, y)] < Image[current_pixel] -threshold
00153     ///   goto block L
00154     ///else
00155     ///   goto block E
00156     ///endif
00157     ///@endcode
00158     ///@param o         ostream for output
00159     ///@param width     width the detector was created at, required to back out the offsets correctly.
00160     void print(std::ostream& o, int width) const
00161     {
00162         using tag::operator<<;
00163         for(unsigned int i=0; i < d.size(); i++)
00164         {
00165             if(d[i].lt == 0)
00166                 o << tag::print << "Block" << i <<  (d[i].gt?"corner":"non_corner");
00167             else
00168             {
00169                 int a = abs(d[i].offset) + width / 2;
00170                 if(d[i].offset < 0)
00171                     a = -a;
00172                 int y = a / width;
00173 
00174                 int x = d[i].offset - y * width;
00175                 o << tag::print << "Block" << i << CVD::ImageRef(x , y) << d[i].gt << d[i].eq << d[i].lt;
00176             }
00177         }
00178     }
00179 
00180     void detect(const CVD::Image<CVD::byte>& im, std::vector<int>& corners, int threshold, int xmin, int xmax, int ymin, int ymax);
00181 };
00182 
00183 #endif

Generated on Mon Mar 2 12:47:12 2009 for FAST-ER by  doxygen 1.5.3