contrib/mul/mipa/mipa_ms_block_normaliser.cxx
Go to the documentation of this file.
00001 #include "mipa_ms_block_normaliser.h"
00002 //:
00003 // \file
00004 // \brief Class to independently normalise sub-blocks with a region at several (SIFT-like) scales
00005 // \author Martin Roberts
00006 
00007 #include <vcl_iostream.h>
00008 #include <vcl_sstream.h>
00009 #include <vsl/vsl_binary_loader.h>
00010 #include <vsl/vsl_vector_io.h>
00011 #include <vnl/vnl_vector_ref.h>
00012 #include <mbl/mbl_read_props.h>
00013 #include <mbl/mbl_parse_block.h>
00014 #include <mbl/mbl_exception.h>
00015 
00016 //=======================================================================
00017 //: Apply transform to texture vector
00018 void mipa_ms_block_normaliser::normalise(vnl_vector<double>& v) const
00019 {
00020     //Apply the base class normalisation to each scale in turn.
00021     //It is assumed that the vector (v's) memory layout is lowest scale, then ordered by scale
00022     // There may be an overall histogram left over at the end
00023 
00024     double* pDataForScale=v.data_block();
00025 
00026     unsigned nTotal=0;
00027     unsigned ni_region_low=ni_region_;
00028     unsigned nj_region_low=nj_region_;
00029     unsigned nc_per_block_low=nc_per_block_;
00030     unsigned& ni_region=const_cast<unsigned&>(this->ni_region_);
00031     unsigned& nj_region=const_cast<unsigned&>(this->nj_region_);
00032     unsigned& nc_per_block=const_cast<unsigned&>(this->nc_per_block_);
00033     for (unsigned iscale=0;iscale<nscales_;++iscale)
00034     {
00035         //Do each scale
00036         unsigned nForScale=ni_region_ * nj_region_ * nA_;
00037         vnl_vector_ref<double> vscale(nForScale,pDataForScale);
00038         //Normalise this scale's sub-vector
00039         mipa_block_normaliser::normalise(vscale);
00040 
00041         //Increment sub-vector pointer and reduce number of elements for next scale
00042         pDataForScale += nForScale;
00043         ni_region/=2;
00044         nj_region/=2;
00045         nc_per_block/=2;
00046         nTotal += nForScale;
00047     }
00048     if (include_overall_histogram_ && (nTotal+nA_) <= v.size())
00049     {
00050         vnl_vector_ref<double> vOverall(nA_,pDataForScale);
00051         //Normalise the overall histogram
00052         this->normaliser().normalise(vOverall);
00053     }
00054     //Restore region cell count to that of lowest scale
00055     ni_region = ni_region_low;
00056     nj_region = nj_region_low;
00057     nc_per_block = nc_per_block_low;
00058 }
00059 
00060 //=======================================================================
00061 
00062 vcl_string mipa_ms_block_normaliser::is_a() const
00063 {
00064     return vcl_string("mipa_ms_block_normaliser");
00065 }
00066 
00067 //=======================================================================
00068 
00069 mipa_vector_normaliser* mipa_ms_block_normaliser::clone() const
00070 {
00071     return new mipa_ms_block_normaliser(*this);
00072 }
00073 
00074 //=======================================================================
00075 
00076 // required if data is present in this base class
00077 void mipa_ms_block_normaliser::print_summary(vcl_ostream& os) const
00078 {
00079     os<<"mipa_ms_block_normaliser:\n"
00080       <<"\tnscales:\t"<<nscales_
00081       <<"\tinclude_overall_histogram:\t"<<include_overall_histogram_
00082       <<'\n';
00083     mipa_block_normaliser::print_summary(os);
00084 }
00085 
00086 //=======================================================================
00087 
00088 // required if data is present in this base class
00089 void mipa_ms_block_normaliser::b_write(vsl_b_ostream& bfs) const
00090 {
00091     const short version_no=1;
00092     vsl_b_write(bfs, version_no);
00093 
00094     vsl_b_write(bfs, nscales_);
00095     vsl_b_write(bfs, include_overall_histogram_);
00096     mipa_block_normaliser::b_write(bfs);
00097 }
00098 
00099 //=======================================================================
00100 
00101 // required if data is present in this base class
00102 void mipa_ms_block_normaliser::b_read(vsl_b_istream& bfs)
00103 {
00104     if (!bfs) return;
00105 
00106     short version;
00107     vsl_b_read(bfs,version);
00108     switch (version)
00109     {
00110         case (1):
00111         {
00112             vsl_b_read(bfs, nscales_);
00113             vsl_b_read(bfs, include_overall_histogram_);
00114             mipa_block_normaliser::b_read(bfs);
00115         break;
00116         default:
00117             vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, mipa_ms_block_normaliser&)\n"
00118                      << "           Unknown version number "<< version << '\n';
00119             bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00120             return;
00121         }
00122     }
00123 }
00124 
00125 //=======================================================================
00126 //: Initialise from a text stream.
00127 // The next non-ws character in the stream should be a '{'
00128 // syntax
00129 // \verbatim
00130 // {
00131 //   nscales: 2
00132 //   include_overall_histogram: true
00133 //   normaliser: mipa_l2norm_vector_normaliser
00134 //   ni: 16
00135 //   nj: 16
00136 //   nc_per_block: 4
00137 // }
00138 // \endverbatim
00139 
00140 void mipa_ms_block_normaliser::config_from_stream(
00141     vcl_istream &is, const mbl_read_props_type &extra_props)
00142 {
00143     vcl_string s = mbl_parse_block(is);
00144 
00145 
00146     vcl_istringstream ss(s);
00147     mbl_read_props_type props = mbl_read_props(ss);
00148 
00149     props = mbl_read_props_merge(props, extra_props, true);
00150 
00151     if (!(props["nscales"].empty()))
00152     {
00153         vcl_string sfi=props["nscales"];
00154         vcl_istringstream ssInner(sfi);
00155         int n=0;
00156         ssInner>>n;
00157         if (ssInner.bad() || n<=0)
00158         {
00159             mbl_exception_parse_error x(vcl_string("mipa_ms_block_normaliser - string stream read error of nscales property"));
00160             mbl_exception_error(x);
00161         }
00162 
00163         nscales_ =n;
00164     }
00165     props.erase("nscales");
00166 
00167     if (!(props["include_overall_histogram"].empty()))
00168     {
00169         vcl_string strBool=props["include_overall_histogram"];
00170         if (strBool=="true" || strBool=="TRUE" || strBool=="t" || strBool=="T" )
00171         {
00172             include_overall_histogram_ = true;
00173         }
00174         else
00175         {
00176             include_overall_histogram_ = false;
00177         }
00178     }
00179     props.erase("include_overall_histogram");
00180 
00181     vcl_string dummy;
00182     vcl_istringstream ssDummy(dummy);
00183     mipa_block_normaliser::config_from_stream(ssDummy,props);
00184 }
00185