contrib/mul/mipa/mipa_block_normaliser.cxx
Go to the documentation of this file.
00001 #include "mipa_block_normaliser.h"
00002 //:
00003 // \file
00004 // \brief Class to independently normalise sub-blocks with a region
00005 // \author Martin Roberts
00006 
00007 #include <vcl_iostream.h>
00008 #include <vcl_sstream.h>
00009 #include <vcl_algorithm.h>
00010 #include <vsl/vsl_binary_loader.h>
00011 #include <vsl/vsl_vector_io.h>
00012 #include <vnl/vnl_vector.h>
00013 #include <mbl/mbl_read_props.h>
00014 #include <mbl/mbl_parse_block.h>
00015 #include <mbl/mbl_exception.h>
00016 #include <vcl_cstddef.h>
00017 
00018 //=======================================================================
00019 //: Apply transform to texture vector
00020 void mipa_block_normaliser::normalise(vnl_vector<double>& v) const
00021 {
00022     //Assume layout is cell values (e.g. histogram), the columns most contiguous, then rows.
00023 
00024     //Note any leftover regions not spanned by an integral number of blocks remain unnormalised!!!
00025     //e.g. a 17x17 region with 4x4 blocks has the final row and column not normalised
00026 
00027     unsigned nblockCols=ni_region_/nc_per_block_; //Number of blocks across region
00028     unsigned nblockRows=nj_region_/nc_per_block_; //Number of blocks down region
00029 
00030     unsigned nTargetColEls=nA_*nc_per_block_; //Number of elements in one row of a block
00031     unsigned nblockEls=nTargetColEls*nc_per_block_;  //Total number of elements  a block
00032     //Working vector for a contiguous memory single block
00033 
00034     vnl_vector<double> vblock(nblockEls,0.0);
00035     vcl_ptrdiff_t colStep=nA_; //Columns are contiguous
00036     vcl_ptrdiff_t rowStep=nA_*ni_region_;
00037 
00038     for (unsigned jbRows=0;jbRows<nblockRows;++jbRows) //move down rows of region in block chunks
00039     {
00040         for (unsigned ibCols=0;ibCols<nblockCols;++ibCols) //move down rows of regionc_per_block_n in block chunks
00041         {
00042             {
00043                 unsigned rowNum=jbRows*nc_per_block_;
00044                 unsigned colNum=ibCols*nc_per_block_;
00045                 double* pBlockTopLeft=v.data_block() + rowNum*rowStep + colNum*colStep; //Source
00046                 double* pTarget=vblock.data_block();
00047                 for (unsigned j=0;j<nc_per_block_;++j) //rows of this target block
00048                 {
00049                     //Copy all elements across the columns of the block
00050                     vcl_copy(pBlockTopLeft,pBlockTopLeft+nTargetColEls,pTarget);
00051                     pBlockTopLeft+= rowStep; //Next row of block source
00052                     pTarget+= nTargetColEls; //Next row of block target
00053                 }
00054                 normaliser_->normalise(vblock);
00055             }
00056             //Now copy back into input vector
00057             {
00058                 unsigned rowNum=jbRows*nc_per_block_;
00059                 unsigned colNum=ibCols*nc_per_block_;
00060                 double* pBlockTopLeft=v.data_block() + rowNum*rowStep + colNum*colStep; //Source
00061                 double* pTarget=vblock.data_block();
00062                 for (unsigned j=0;j<nc_per_block_;++j) //rows of this target block
00063                 {
00064                     //Copy all elements across the columns of the block
00065                     vcl_copy(pTarget,pTarget+nTargetColEls,pBlockTopLeft);
00066                     pBlockTopLeft+= rowStep; //Next row of block in overall normalised vector
00067                     pTarget+= nTargetColEls; //Next row of block
00068                 }
00069             }
00070         }
00071     }
00072 }
00073 
00074 //=======================================================================
00075 
00076 vcl_string mipa_block_normaliser::is_a() const
00077 {
00078     return vcl_string("mipa_block_normaliser");
00079 }
00080 
00081 //=======================================================================
00082 
00083 mipa_vector_normaliser* mipa_block_normaliser::clone() const
00084 {
00085     return new mipa_block_normaliser(*this);
00086 }
00087 
00088 //=======================================================================
00089 
00090     // required if data is present in this base class
00091 void mipa_block_normaliser::print_summary(vcl_ostream& os) const
00092 {
00093     os<<"mipa_block_normaliser:\n"
00094       <<"\tni_region_\t"<<ni_region_
00095       <<"\tnj_region_\t"<<nj_region_
00096       <<"\tnA_\t"<<nA_
00097       <<"\tnc_per_block_\t"<<nc_per_block_
00098       <<'\n'
00099       <<"Block normaliser summary is:"<<'\n';
00100     normaliser_->print_summary(os);
00101 }
00102 
00103 //=======================================================================
00104 
00105 // required if data is present in this base class
00106 void mipa_block_normaliser::b_write(vsl_b_ostream& bfs) const
00107 {
00108     const short version_no=1;
00109     vsl_b_write(bfs, version_no);
00110 
00111     vsl_b_write(bfs, ni_region_);
00112     vsl_b_write(bfs, nj_region_);
00113     vsl_b_write(bfs, nA_);
00114     vsl_b_write(bfs, nc_per_block_);
00115 
00116     vsl_b_write(bfs, normaliser_);
00117 }
00118 
00119 //=======================================================================
00120 
00121 // required if data is present in this base class
00122 void mipa_block_normaliser::b_read(vsl_b_istream& bfs)
00123 {
00124     if (!bfs) return;
00125 
00126     short version;
00127     vsl_b_read(bfs,version);
00128     switch (version)
00129     {
00130         case (1):
00131         {
00132             vsl_b_read(bfs, ni_region_);
00133             vsl_b_read(bfs, nj_region_);
00134             vsl_b_read(bfs, nA_);
00135             vsl_b_read(bfs, nc_per_block_);
00136 
00137             vsl_b_read(bfs,normaliser_);
00138             break;
00139         default:
00140             vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, mipa_block_normaliser&)\n"
00141                      << "           Unknown version number "<< version << '\n';
00142             bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00143             return;
00144         }
00145     }
00146 }
00147 
00148 //=======================================================================
00149 //: Initialise from a text stream.
00150 // The next non-ws character in the stream should be a '{'
00151 // syntax
00152 // \verbatim
00153 // {
00154 //   normaliser: mipa_l2norm_vector_normaliser
00155 //   ni: 16
00156 //   nj: 16
00157 //   nc_per_block: 4
00158 // }
00159 // \endverbatim
00160 
00161 void mipa_block_normaliser::config_from_stream(
00162     vcl_istream &is, const mbl_read_props_type &extra_props)
00163 {
00164     vcl_string s = mbl_parse_block(is);
00165 
00166     vcl_istringstream ss(s);
00167     mbl_read_props_type props = mbl_read_props(ss);
00168 
00169     props = mbl_read_props_merge(props, extra_props, true);
00170 
00171     if (props["normaliser"].empty())
00172     {
00173         mbl_exception_parse_error x(vcl_string("mipa_block_normaliser could not find a normaliser property"));
00174         mbl_exception_error(x);
00175     }
00176     vcl_istringstream ss2(props["normaliser"]);
00177     vcl_auto_ptr<mipa_vector_normaliser> norm = new_normaliser_from_stream(ss2, extra_props);
00178     normaliser_=norm.release();
00179     props.erase("normaliser");
00180 
00181     {
00182         if (props["ni"].empty())
00183         {
00184             mbl_exception_parse_error x(vcl_string("mipa_block_normaliser could not find a ni  property"));
00185             mbl_exception_error(x);
00186         }
00187 
00188         //Decode the feature indices using a string stream
00189         vcl_string sfi=props["ni"];
00190 //    vcl_istringstream ssInner(sfi.substr(1,sfi.size()-2));
00191         vcl_istringstream ssInner(sfi);
00192         int n=0;
00193         ssInner>>n;
00194         if (ssInner.bad() || n<=0)
00195         {
00196             mbl_exception_parse_error x(vcl_string("mipa_block_normaliser - string stream read error of ni property"));
00197             mbl_exception_error(x);
00198         }
00199         ni_region_ =n;
00200 
00201         props.erase("ni");
00202     }
00203 
00204     {
00205         if (props["nj"].empty())
00206         {
00207             mbl_exception_parse_error x(vcl_string("mipa_block_normaliser could not find a nj  property"));
00208             mbl_exception_error(x);
00209         }
00210 
00211         //Decode the feature indices using a string stream
00212         vcl_string sfi=props["nj"];
00213 //    vcl_istringstream ssInner(sfi.substr(1,sfi.size()-2));
00214         vcl_istringstream ssInner(sfi);
00215         int n=0;
00216         ssInner>>n;
00217         if (ssInner.bad() || n<=0)
00218         {
00219             mbl_exception_parse_error x(vcl_string("mipa_block_normaliser - string stream read error of nj property"));
00220             mbl_exception_error(x);
00221         }
00222         nj_region_ =n;
00223 
00224         props.erase("nj");
00225     }
00226     {
00227         if (props["nA"].empty())
00228         {
00229             mbl_exception_parse_error x(vcl_string("mipa_block_normaliser could not find a nA  property"));
00230             mbl_exception_error(x);
00231         }
00232 
00233         vcl_string sfi=props["nA"];
00234         vcl_istringstream ssInner(sfi);
00235         int n=0;
00236         ssInner>>n;
00237         if (ssInner.bad() || n<=0)
00238         {
00239             mbl_exception_parse_error x(vcl_string("mipa_block_normaliser - string stream read error of nj property"));
00240             mbl_exception_error(x);
00241         }
00242         nA_ =n;
00243         props.erase("nA");
00244     }
00245     {
00246         if (props["block_size"].empty())
00247         {
00248             mbl_exception_parse_error x(vcl_string("mipa_block_normaliser could not find a block_size  property"));
00249             mbl_exception_error(x);
00250         }
00251 
00252         vcl_string sfi=props["block_size"];
00253         vcl_istringstream ssInner(sfi);
00254         int n=0;
00255         ssInner>>n;
00256         if (ssInner.bad() || n<=0)
00257         {
00258             mbl_exception_parse_error x(vcl_string("mipa_block_normaliser - string stream read error of block_size property"));
00259             mbl_exception_error(x);
00260         }
00261         nc_per_block_ =n;
00262 
00263         props.erase("block_size");
00264     }
00265 
00266     mbl_read_props_look_for_unused_props(
00267             "mipa_block_normaliser::config_from_stream", props, extra_props);
00268 }
00269