offsets.cc

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 #include <vector>
00021 #include <algorithm>
00022 #include <cmath>
00023 
00024 #include <cvd/vector_image_ref.h>
00025 #include <cvd/image.h>
00026 
00027 #include <TooN/TooN.h>
00028 
00029 #include <tag/stdpp.h>
00030 #include <tag/fn.h>
00031 
00032 #include <gvars3/instances.h>
00033 
00034 #include "offsets.h"
00035 
00036 ///\cond never
00037 using namespace std;
00038 using namespace CVD;
00039 using namespace TooN;
00040 using namespace tag;
00041 using namespace GVars3;
00042 ///\endcond
00043 
00044 
00045 
00046 
00047 ///Actual x,y offset of the offset numbers in the different available orientations.
00048 ///@ingroup gTree
00049 vector<vector<ImageRef> > offsets;
00050 ///The number of possible offsets. Equivalent to <code>offsets[x].size()</code>
00051 ///@ingroup gTree
00052 int num_offsets;
00053 ///Bounding box for offsets in all orientations. This is therefore a bounding box for the detector.
00054 ///@ingroup gTree
00055 pair<ImageRef, ImageRef> offsets_bbox;
00056 
00057 
00058 
00059 
00060 ///Rotate a vector<ImageRef> by a given angle, with an optional reflection.
00061 ///@param offsets Offsets to rotate.
00062 ///@param angle Angle to rotate by.
00063 ///@param r Whether to reflect.
00064 ///@return The rotated offsets.
00065 ///@ingroup gTree
00066 vector<ImageRef> transform_offsets(const vector<ImageRef>& offsets, int angle, bool r)
00067 {
00068     double a = angle * M_PI / 2;    
00069 
00070     double R_[] = { cos(a), sin(a), -sin(a) , cos(a) };
00071     double F_[] = { 1, 0, 0, r?-1:1};
00072 
00073     Matrix<2> R(R_), F(F_);
00074     Matrix<2> T = R*F;
00075 
00076     vector<ImageRef> ret;
00077 
00078     for(unsigned int i=0; i < offsets.size(); i++)
00079     {
00080         Vector<2> v = vec(offsets[i]);
00081         ret.push_back(ir_rounded(T * v));
00082     }
00083     
00084     return ret;
00085 }
00086 
00087 
00088 ///Pretty print some offsets to stdout.
00089 ///@param offsets List of offsets to pretty-print.
00090 ///@ingroup gUtility
00091 void draw_offset_list(const vector<ImageRef>& offsets)
00092 {
00093 
00094     cout << "Allowed offsets: " << offsets.size() << endl;
00095 
00096     ImageRef min, max;
00097     min.x = *min_element(member_iterator(offsets.begin(), &ImageRef::x), member_iterator(offsets.end(), &ImageRef::x));
00098     max.x = *max_element(member_iterator(offsets.begin(), &ImageRef::x), member_iterator(offsets.end(), &ImageRef::x));
00099     min.y = *min_element(member_iterator(offsets.begin(), &ImageRef::y), member_iterator(offsets.end(), &ImageRef::y));
00100     max.y = *max_element(member_iterator(offsets.begin(), &ImageRef::y), member_iterator(offsets.end(), &ImageRef::y));
00101 
00102     cout << print << min <<max << endl;
00103 
00104     Image<int> o(max-min+ImageRef(1,1), -1);
00105     for(unsigned int i=0; i <offsets.size(); i++)
00106         o[offsets[i] -min] = i;
00107 
00108     for(int y=0; y < o.size().y; y++)
00109     {
00110         for(int x=0; x < o.size().x; x++)
00111             cout << "+------";
00112         cout << "+"<< endl;
00113 
00114         for(int x=0; x < o.size().x; x++)
00115             cout << "|      ";
00116         cout << "|"<< endl;
00117 
00118 
00119         for(int x=0; x < o.size().x; x++)
00120         {
00121             if(o[y][x] >= 0)
00122                 cout << "|  " << setw(2) << o[y][x] << "  ";
00123             else if(ImageRef(x, y) == o.size() / 2)
00124                 cout << "|   " << "#" << "  ";
00125             else 
00126                 cout << "|      ";
00127         }
00128         cout <<  "|" << endl;
00129 
00130         for(int x=0; x < o.size().x; x++)
00131             cout << "|      ";
00132         cout << "|"<< endl;
00133     }
00134 
00135     for(int x=0; x < o.size().x; x++)
00136         cout << "+------";
00137     cout << "+"<< endl;
00138 
00139     cout << endl;
00140 
00141 }
00142 
00143 ///Create a list of offsets with various transformation to map the offset number
00144 /// (see Figure 7 in the accompanying paper) to a pixel coordinate, inclusing all 
00145 /// combinations of rotation and reflection.
00146 /// 
00147 /// The function populates ::offsets, and must be called before anything uses
00148 /// this variable.
00149 ///
00150 /// All possible offsets are selected in an annulus, which uses the following gvars:
00151 /// - \c offsets.min_radius Minimum distance from (0,0) for offset
00152 /// - \c offsets.max_radius Maximum distance from (0,0) for offset
00153 ///
00154 ///
00155 ///@ingroup gTree
00156 void create_offsets()
00157 {
00158     //Pixel offsets are represented as integer indices in to an array of
00159     //ImageRefs. That means that by choosing the array, the tree can be
00160     //rotated and/or reflected. Here, an annulus of possible offsets is 
00161     //created and rotated by all multiples of 90 degrees, and then reflected.
00162     //This gives a total of 8.
00163     offsets.resize(8);
00164     {   
00165         double min_r = GV3::get<double>("offsets.min_radius");
00166         double max_r = GV3::get<double>("offsets.max_radius");
00167 
00168         ImageRef max((int)ceil(max_r+1), (int)ceil(max_r+1));
00169         ImageRef min = -max, p = min;
00170 
00171         //cout << "Offsets: ";
00172 
00173         do
00174         {
00175             double d = vec(p) * vec(p);
00176 
00177             if(d >= min_r*min_r && d <= max_r * max_r)
00178             {
00179                 offsets[0].push_back(p);
00180                 //cout << offsets[0].back() << " ";
00181             }
00182         }
00183         while(p.next(min, max));
00184 
00185     //  cout << endl;
00186 
00187         offsets_bbox = make_pair(min, max);
00188     }
00189     offsets[1] = transform_offsets(offsets[0], 1, 0);
00190     offsets[2] = transform_offsets(offsets[0], 2, 0);
00191     offsets[3] = transform_offsets(offsets[0], 3, 0);
00192     offsets[4] = transform_offsets(offsets[0], 0, 1);
00193     offsets[5] = transform_offsets(offsets[0], 1, 1);
00194     offsets[6] = transform_offsets(offsets[0], 2, 1);
00195     offsets[7] = transform_offsets(offsets[0], 3, 1);
00196     num_offsets=offsets[0].size();
00197 }
00198 
00199 ///Prettyprints the contents of ::offsets
00200 ///@ingroup gUtility
00201 void draw_offsets()
00202 {
00203     //Print the offsets out.    
00204     for(unsigned int i=0; i < 8; i++)
00205     {
00206         cout << "Offsets " << i << endl;
00207         draw_offset_list(offsets[i]);   
00208         cout << endl;
00209     }
00210 }

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