EnvVisualCortex.C

Go to the documentation of this file.
00001 /*!@file Neuro/EnvVisualCortex.C */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Neuro/EnvVisualCortex.C $
00035 // $Id: EnvVisualCortex.C 12651 2010-01-25 21:54:07Z itti $
00036 //
00037 
00038 #ifndef NEURO_ENVVISUALCORTEX_C_DEFINED
00039 #define NEURO_ENVVISUALCORTEX_C_DEFINED
00040 
00041 #include "Neuro/EnvVisualCortex.H"
00042 
00043 #include "Component/ModelOptionDef.H"
00044 #include "Envision/env_c_math_ops.h"
00045 #include "Envision/env_image_ops.h"
00046 #include "Envision/env_job_server.h"
00047 #include "Envision/env_log.h"
00048 #include "Envision/env_mt_visual_cortex.h"
00049 #include "Envision/env_pthread_interface.h"
00050 #include "Envision/env_stdio_interface.h"
00051 #include "Neuro/EnvOpts.H"
00052 #include "Util/AllocAux.H"
00053 #include "Util/JobWithSemaphore.H"
00054 #include "Util/StringConversions.H"
00055 #include "Util/WorkThreadServer.H"
00056 
00057 #include <cstdio>
00058 #include <sstream>
00059 #include <vector>
00060 
00061 // Used by: EnvVisualCortex
00062 const ModelOptionDef OPT_EvcMaxnormType =
00063   { MODOPT_ARG(std::string), "EvcMaxnormType", &MOC_ENVISION, OPTEXP_CORE,
00064     "Type of normalization to use",
00065     "evc-maxnorm-type", '\0', "<None|Maxnorm>", "Maxnorm" };
00066 
00067 // Used by: EnvVisualCortex
00068 const ModelOptionDef OPT_EvcScaleBits =
00069   { MODOPT_ARG(byte), "EvcScaleBits", &MOC_ENVISION, OPTEXP_CORE,
00070     "Number of bits of dynamic range to use",
00071     "evc-scale-bits", '\0', "<byte>", "16" };
00072 
00073 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00074 
00075 // Used by: EnvVisualCortex
00076 const ModelOptionDef OPT_EvcNumDirections =
00077   { MODOPT_ARG(byte), "EvcNumDirections", &MOC_ENVISION, OPTEXP_CORE,
00078     "Number of motion directions to use",
00079     "evc-num-directions", '\0', "<byte>", "4" };
00080 
00081 // Used by: EnvVisualCortex
00082 const ModelOptionDef OPT_EvcMotionThresh =
00083   { MODOPT_ARG(byte), "EvcMotionThresh", &MOC_ENVISION, OPTEXP_CORE,
00084     "Low threshold cutoff for motion channel",
00085     "evc-motion-thresh", '\0', "<byte>", "12" };
00086 
00087 // Used by: EnvVisualCortex
00088 const ModelOptionDef OPT_EvcFlickerThresh =
00089   { MODOPT_ARG(byte), "EvcFlickerThresh", &MOC_ENVISION, OPTEXP_CORE,
00090     "Low threshold cutoff for flicker channel",
00091     "evc-flicker-thresh", '\0', "<byte>", "20" };
00092 
00093 // Used by: EnvVisualCortex
00094 const ModelOptionDef OPT_EvcRangeThresh =
00095   { MODOPT_ARG(int), "EvcRangeThresh", &MOC_ENVISION, OPTEXP_CORE,
00096     "Low threshold cutoff for normalizing maps. "
00097     "If the range of the map is bellow this threshold "
00098     "then the value would be set to 0.",
00099     "evc-range-thresh", '\0', "<int>", "0" };
00100 
00101 // Used by: EnvVisualCortex
00102 const ModelOptionDef OPT_EvcMultiScaleFlicker =
00103   { MODOPT_FLAG, "EvcMultiScaleFlicker", &MOC_ENVISION, OPTEXP_CORE,
00104     "Whether to use a true multi-scale flicker channel",
00105     "evc-multiscale-flicker", '\0', "", "true" };
00106 
00107 // Used by: EnvVisualCortex
00108 const ModelOptionDef OPT_EvcShowMemStats =
00109   { MODOPT_FLAG, "EvcShowMemStats", &MOC_ENVISION, OPTEXP_CORE,
00110     "Whether to show memory usage",
00111     "evc-show-memstats", '\0', "", "false" };
00112 
00113 #endif
00114 
00115 // Used by: EnvVisualCortex
00116 const ModelOptionDef OPT_EvcNumOrientations =
00117   { MODOPT_ARG(byte), "EvcNumOrientations", &MOC_ENVISION, OPTEXP_CORE,
00118     "Number of orientation channels to use",
00119     "evc-num-orientations", '\0', "<byte>", "4" };
00120 
00121 // Used by: EnvVisualCortex
00122 const ModelOptionDef OPT_EvcType =
00123   { MODOPT_ARG(std::string), "EvcType", &MOC_ENVISION, OPTEXP_CORE,
00124     "A string containing one or more of the characters "
00125 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00126     "'I', 'C', 'O', 'F', and 'M', "
00127 #else
00128     "'I', 'C', and 'O', "
00129 #endif
00130     "indicating which of the intensity, color, orientation, flicker, "
00131     "and motion channels should be included, respectively. Additionally, "
00132     "each character can optionally be followed by a ':' and a "
00133     "floating-point number between 0.0 and 1.0 indicating the weight for "
00134     "that channel. By default, each channel receives a weight of 1.0.",
00135     "evc-type", '\0',
00136 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00137     "<I:wC:wO:wF:wM:w>", "ICOFM"
00138 #else
00139     "<I:wC:wO:w>", "ICO"
00140 #endif
00141   };
00142 
00143 // Used by: EnvVisualCortex
00144 const ModelOptionDef OPT_EvcColorSmoothing =
00145   { MODOPT_FLAG, "EvcColorSmoothing", &MOC_ENVISION, OPTEXP_CORE,
00146     "Whether to do two-frame smoothing of the color channel",
00147     "evc-color-smoothing", '\0', "", "false" };
00148 
00149 const ModelOptionDef OPT_EvcOutputFactor =
00150   { MODOPT_ARG(float), "EvcOutputFactor", &MOC_ENVISION, OPTEXP_CORE,
00151     "Factor applied to outputs of EnvVisualCortexFloat to scale them to Amps of "
00152     "synaptic input currents to saliency map",
00153     "evc-outfac", '\0', "<float>", "5.0e-18" };
00154 
00155 // ######################################################################
00156 // Thunk to convert from env_size_t to size_t
00157 static void* malloc_thunk(env_size_t n)
00158 {
00159   return malloc(n);
00160 }
00161 
00162 // ######################################################################
00163 static Image<byte> convert_gray(const struct env_image* iimage, const struct env_dims dims)
00164 {
00165   if (!env_img_initialized(iimage)) return Image<byte>(dims.w, dims.h, ZEROS);
00166 
00167   Image<byte> result(iimage->dims.w, iimage->dims.h, NO_INIT);
00168 
00169   const intg32* const src = env_img_pixels(iimage);
00170   const env_size_t sz = env_img_size(iimage);
00171   byte* bimage = result.getArrayPtr();
00172 
00173   for (env_size_t i = 0; i < sz; ++i)
00174     {
00175       // the caller is supposed to have already ensured that the intg32 image has been downsampled to a [0,255] range,
00176       // so let's verify that:
00177       ENV_ASSERT(src[i] >= 0 && src[i] <= 255);
00178       bimage[i] = byte(src[i]);
00179     }
00180 
00181   return result;
00182 }
00183 
00184 // ######################################################################
00185 static Image<float> convert_gray_float(const struct env_image* iimage,
00186                                        const struct env_dims dims, const float factor)
00187 {
00188   if (!env_img_initialized(iimage)) return Image<float>(dims.w, dims.h, ZEROS);
00189 
00190   Image<float> result(iimage->dims.w, iimage->dims.h, NO_INIT);
00191 
00192   const intg32* src = env_img_pixels(iimage);
00193   const env_size_t sz = env_img_size(iimage);
00194   float* fimage = result.getArrayPtr();
00195   if (factor == 1.0F) for (env_size_t i = 0; i < sz; ++i) { *fimage = *src; ++fimage; ++src; }
00196   else for (env_size_t i = 0; i < sz; ++i) { *fimage = (*src) * factor; ++fimage; ++src; }
00197 
00198   return result;
00199 }
00200 
00201 // ######################################################################
00202 namespace
00203 {
00204   class EnvisionJob : public JobWithSemaphore
00205   {
00206   public:
00207     EnvisionJob(const struct env_job* j) : envJob(*j) {}
00208 
00209     virtual ~EnvisionJob() {}
00210 
00211     virtual void run()
00212     {
00213       (*envJob.callback)(envJob.userdata);
00214       this->markFinished();
00215     }
00216 
00217     virtual const char* jobType() const { return "EnvisionJob"; }
00218 
00219     const struct env_job envJob;
00220   };
00221 }
00222 
00223 // ######################################################################
00224 static void workthread_job_server(void* job_server_data,
00225                                   const struct env_job* jobs,
00226                                   const env_size_t njobs)
00227 {
00228   if (njobs == 0) return;
00229 
00230   WorkThreadServer* srv = static_cast<WorkThreadServer*>(job_server_data);
00231 
00232   std::vector<rutz::shared_ptr<EnvisionJob> > ejobs;
00233   for (env_size_t i = 0; i < njobs; ++i)
00234     {
00235       ejobs.push_back(rutz::make_shared(new EnvisionJob(jobs + i)));
00236       srv->enqueueJob(ejobs.back());
00237     }
00238 
00239   for (size_t i = 0; i < ejobs.size(); ++i) ejobs[i]->wait();
00240 }
00241 
00242 // ######################################################################
00243 EnvVisualCortexBase::EnvVisualCortexBase(OptionManager& mgr, const std::string& descrName,
00244                                          const std::string& tagName) :
00245   ModelComponent(mgr, descrName, tagName),
00246   itsIweight("EvcIntensityWeight", this, 255, ALLOW_ONLINE_CHANGES),
00247   itsCweight("EvcColorWeight", this, 255, ALLOW_ONLINE_CHANGES),
00248   itsOweight("EvcOrientationWeight", this, 255, ALLOW_ONLINE_CHANGES),
00249 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00250   itsFweight("EvcFlickerWeight", this, 255, ALLOW_ONLINE_CHANGES),
00251   itsMweight("EvcMotionWeight", this, 255, ALLOW_ONLINE_CHANGES),
00252 #endif
00253   itsMultithreaded(&OPT_EvcMultithreaded, this, ALLOW_ONLINE_CHANGES),
00254   itsMaxnormType(&OPT_EvcMaxnormType, this),
00255   itsScaleBits(&OPT_EvcScaleBits, this),
00256   itsNumOrientations(&OPT_EvcNumOrientations, this, ALLOW_ONLINE_CHANGES),
00257   itsColorSmoothing(&OPT_EvcColorSmoothing, this, ALLOW_ONLINE_CHANGES),
00258 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00259   itsNumDirections(&OPT_EvcNumDirections, this, ALLOW_ONLINE_CHANGES),
00260   itsMotionThresh(&OPT_EvcMotionThresh, this, ALLOW_ONLINE_CHANGES),
00261   itsFlickerThresh(&OPT_EvcFlickerThresh, this, ALLOW_ONLINE_CHANGES),
00262   itsRangeThresh(&OPT_EvcRangeThresh, this, ALLOW_ONLINE_CHANGES),
00263   itsMultiScaleFlicker(&OPT_EvcMultiScaleFlicker, this, ALLOW_ONLINE_CHANGES),
00264   itsShowMemStats(&OPT_EvcShowMemStats, this, ALLOW_ONLINE_CHANGES),
00265 #endif
00266   itsLevelSpec(&OPT_EnvLevelSpec, this),
00267   itsType(&OPT_EvcType, this)
00268 {
00269   env_params_set_defaults(&this->envp);
00270 }
00271 
00272 // ######################################################################
00273 EnvVisualCortexBase::~EnvVisualCortexBase()
00274 {
00275   itsThreadServer.reset(0);
00276   env_set_job_server(0, 0);
00277   env_allocation_cleanup();
00278 }
00279 
00280 // ######################################################################
00281 void EnvVisualCortexBase::start1()
00282 {
00283   env_assert_set_handler(&env_stdio_assert_handler);
00284   env_allocation_init(&malloc_thunk, &free);
00285 
00286   LINFO(".scale_bits = %u", (unsigned int) itsScaleBits.getVal());
00287 
00288   this->envp.scale_bits = itsScaleBits.getVal();
00289 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00290   this->envp.num_motion_directions = itsNumDirections.getVal();
00291   this->envp.motion_thresh = itsMotionThresh.getVal();
00292   this->envp.flicker_thresh = itsFlickerThresh.getVal();
00293   this->envp.range_thresh = itsRangeThresh.getVal();
00294   this->envp.multiscale_flicker = itsMultiScaleFlicker.getVal() ? 1 : 0;
00295 #endif
00296   this->envp.num_orientations = itsNumOrientations.getVal();
00297   this->envp.cs_lev_min = itsLevelSpec.getVal().levMin();
00298   this->envp.cs_lev_max = itsLevelSpec.getVal().levMax();
00299   this->envp.cs_del_min = itsLevelSpec.getVal().delMin();
00300   this->envp.cs_del_max = itsLevelSpec.getVal().delMax();;
00301   this->envp.output_map_level = itsLevelSpec.getVal().mapLevel();
00302 
00303   env_visual_cortex_init(&this->ivc, &this->envp);
00304 
00305   this->npixels = 0;
00306 
00307   this->framenum = 0;
00308 
00309   itsIweight.setVal(this->envp.chan_i_weight);
00310   itsCweight.setVal(this->envp.chan_c_weight);
00311   itsOweight.setVal(this->envp.chan_o_weight);
00312 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00313   itsFweight.setVal(this->envp.chan_f_weight);
00314   itsMweight.setVal(this->envp.chan_m_weight);
00315 #endif
00316 }
00317 
00318 // ######################################################################
00319 void EnvVisualCortexBase::stop2()
00320 {
00321   if (itsShowMemStats.getVal())
00322     {
00323       struct env_alloc_stats stats;
00324       env_allocation_get_stats(&stats);
00325       env_stdio_print_alloc_stats(&stats, this->npixels ? this->npixels : 1);
00326       invt_allocation_show_stats(1, "final", this->npixels);
00327     }
00328 
00329   env_visual_cortex_destroy(&this->ivc);
00330 }
00331 
00332 // ######################################################################
00333 void EnvVisualCortexBase::paramChanged(ModelParamBase* const param,
00334                                    const bool valueChanged,
00335                                    ParamClient::ChangeStatus* status)
00336 {
00337   ModelComponent::paramChanged(param, valueChanged, status);
00338 
00339   if (this->started() && valueChanged)
00340     LDEBUG("online change of %s", param->getName().c_str());
00341 
00342   if      (param == &itsIweight) { this->envp.chan_i_weight = itsIweight.getVal(); }
00343   else if (param == &itsCweight) { this->envp.chan_c_weight = itsCweight.getVal(); }
00344   else if (param == &itsOweight) { this->envp.chan_o_weight = itsOweight.getVal(); }
00345 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00346   else if (param == &itsFweight) { this->envp.chan_f_weight = itsFweight.getVal(); }
00347   else if (param == &itsMweight) { this->envp.chan_m_weight = itsMweight.getVal(); }
00348 #endif
00349   else if (param == &itsMultithreaded)
00350     {
00351       env_set_job_server(0, 0);
00352 
00353       if (itsMultithreaded.getVal())
00354         {
00355           // once this is turned on, don't ever turn it off again
00356           env_init_pthread_alloc();
00357 
00358           itsThreadServer.reset(new WorkThreadServer("EnvVisualCortex", 12));
00359           env_set_job_server(&workthread_job_server, static_cast<void*>(itsThreadServer.get()));
00360         }
00361       else itsThreadServer.reset(0);
00362     }
00363   else if (param == &itsMaxnormType)
00364     {
00365       if (itsMaxnormType.getVal().compare("None") == 0) this->envp.maxnorm_type = ENV_VCXNORM_NONE;
00366       else if (itsMaxnormType.getVal().compare("Maxnorm") == 0) this->envp.maxnorm_type = ENV_VCXNORM_MAXNORM;
00367       else LFATAL("Invalid maxnorm type '%s' -- must be either 'Maxnorm' or 'None'", itsMaxnormType.getVal().c_str());
00368     }
00369   else if (param == &itsType)
00370     {
00371       // first, set all weights to zero:
00372       this->envp.chan_i_weight = 0;
00373       this->envp.chan_c_weight = 0;
00374       this->envp.chan_o_weight = 0;
00375 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00376       this->envp.chan_f_weight = 0;
00377       this->envp.chan_m_weight = 0;
00378 #endif
00379 
00380       const std::string type = itsType.getVal();
00381       const size_t len = itsType.getVal().length();
00382 
00383       for (size_t i = 0; i < len; /* incr in loop */)
00384         {
00385           const char chantype = type[i];
00386           byte* bweightptr = 0;
00387 
00388           switch (chantype)
00389             {
00390             case 'I': bweightptr = &this->envp.chan_i_weight; break;
00391             case 'C': bweightptr = &this->envp.chan_c_weight; break;
00392             case 'O': bweightptr = &this->envp.chan_o_weight; break;
00393 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00394             case 'F': bweightptr = &this->envp.chan_f_weight; break;
00395             case 'M': bweightptr = &this->envp.chan_m_weight; break;
00396 #endif
00397             default:  LFATAL("Invalid channel specifier '%c'", chantype);
00398             }
00399 
00400           ++i;
00401 
00402           if (type[i] != ':') *bweightptr = 255;
00403           else {
00404             ++i;
00405             const size_t end = type.find_first_not_of(".0123456789", i);
00406             const std::string weightstr = type.substr(i, end - i);
00407             double weight = 1.0;
00408 
00409             std::stringstream s; s << weightstr; s >> weight;
00410             if (s.fail()) LFATAL("couldn't parse '%c' channel weight from '%s'", chantype, weightstr.c_str());
00411             i = end;
00412 
00413             if (weight < 0.0 || weight > 1.0)
00414               LFATAL("invalid weight for channel '%c': got %s but expected a value between 0.0 and 1.0",
00415                      chantype, weightstr.c_str());
00416 
00417             *bweightptr = byte(weight * 255.0 + 0.5);
00418           }
00419         }
00420     }
00421   else if (param == &itsNumOrientations)
00422     {
00423       if (itsNumOrientations.getVal() > 99) *status = ParamClient::CHANGE_REJECTED;
00424       else this->envp.num_orientations = itsNumOrientations.getVal();
00425     }
00426 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00427   else if (param == &itsNumDirections)
00428     {
00429       if (itsNumDirections.getVal() > 99) *status = ParamClient::CHANGE_REJECTED;
00430       else this->envp.num_motion_directions = itsNumDirections.getVal();
00431     }
00432   else if (param == &itsMotionThresh)
00433     {
00434       this->envp.motion_thresh = itsMotionThresh.getVal();
00435     }
00436   else if (param == &itsFlickerThresh)
00437     {
00438       this->envp.flicker_thresh = itsFlickerThresh.getVal();
00439     }
00440   else if (param == &itsMultiScaleFlicker)
00441     {
00442       this->envp.multiscale_flicker = itsMultiScaleFlicker.getVal() ? 1 : 0;
00443     }
00444 #endif
00445 }
00446 
00447 // ######################################################################
00448 // ######################################################################
00449 // ######################################################################
00450 EnvVisualCortex::EnvVisualCortex(OptionManager& mgr, const std::string& descrName,
00451                                  const std::string& tagName) :
00452   EnvVisualCortexBase(mgr, descrName, tagName)
00453 {
00454   this->chanmi = INTG32_MAX; this->chanma = INTG32_MIN;
00455   this->vcxmi = INTG32_MAX; this->vcxma = INTG32_MIN;
00456 }
00457 
00458 // ######################################################################
00459 EnvVisualCortex::~EnvVisualCortex()
00460 { }
00461 
00462 // ######################################################################
00463 void EnvVisualCortex::input(const Image<PixRGB<byte> >& rgbin)
00464 {
00465   struct env_image ivcout = env_img_initializer;
00466   struct env_image intens = env_img_initializer;
00467   struct env_image color = env_img_initializer;
00468   struct env_image ori = env_img_initializer;
00469 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00470   struct env_image flicker = env_img_initializer;
00471   struct env_image motion = env_img_initializer;
00472 #endif
00473 
00474   ++this->framenum;
00475 
00476   struct env_dims indims = { rgbin.getWidth(), rgbin.getHeight() };
00477 
00478   npixels = indims.w * indims.h;
00479 
00480   const struct env_rgb_pixel* src = (const struct env_rgb_pixel*) rgbin.getArrayPtr();
00481 
00482   const struct env_rgb_pixel* src2 = (const struct env_rgb_pixel*)
00483     (itsColorSmoothing.getVal() == true && itsPrevRgb.initialized() ? itsPrevRgb.getArrayPtr() : 0);
00484 
00485   env_mt_visual_cortex_input(itsMultithreaded.getVal() ? 1 : 0,
00486                           &this->ivc, &this->envp,
00487                           "visualcortex",
00488                           src, src2,
00489                           indims,
00490                           0, //&print_chan_status,
00491                           0, //&userdata,
00492                           &ivcout,
00493                           &intens, &color, &ori
00494 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00495                           , &flicker, &motion
00496 #endif
00497                           );
00498 
00499   env_merge_range(&ivcout, &vcxmi, &vcxma);
00500   env_rescale_range_inplace(&ivcout, vcxmi, vcxma);
00501 
00502   env_visual_cortex_merge_ranges(&intens, &color, &ori,
00503 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00504                                  &flicker, &motion,
00505 #endif
00506                                  &chanmi, &chanma);
00507 
00508   env_rescale_range_inplace(&intens, chanmi, chanma);
00509   env_rescale_range_inplace(&color, chanmi, chanma);
00510   env_rescale_range_inplace(&ori, chanmi, chanma);
00511 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00512   env_rescale_range_inplace(&flicker, chanmi, chanma);
00513   env_rescale_range_inplace(&motion, chanmi, chanma);
00514 #endif
00515 
00516   this->itsVCXmap = convert_gray(&ivcout, ivcout.dims);
00517 
00518   this->itsImap = convert_gray(&intens, ivcout.dims);
00519   this->itsCmap = convert_gray(&color, ivcout.dims);
00520   this->itsOmap = convert_gray(&ori, ivcout.dims);
00521 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00522   this->itsFmap = convert_gray(&flicker, ivcout.dims);
00523   this->itsMmap = convert_gray(&motion, ivcout.dims);
00524 #endif
00525 
00526   env_img_make_empty(&ivcout);
00527   env_img_make_empty(&intens);
00528   env_img_make_empty(&color);
00529   env_img_make_empty(&ori);
00530 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00531   env_img_make_empty(&flicker);
00532   env_img_make_empty(&motion);
00533 #endif
00534 
00535   itsPrevRgb = rgbin;
00536 }
00537 
00538 // ######################################################################
00539 // ######################################################################
00540 // ######################################################################
00541 EnvVisualCortexFloat::EnvVisualCortexFloat(OptionManager& mgr, const std::string& descrName,
00542                                            const std::string& tagName) :
00543   EnvVisualCortexBase(mgr, descrName, tagName),
00544   itsOutputFactor(&OPT_EvcOutputFactor, this)
00545 { }
00546 
00547 // ######################################################################
00548 EnvVisualCortexFloat::~EnvVisualCortexFloat()
00549 { }
00550 
00551 // ######################################################################
00552 // ######################################################################
00553 void EnvVisualCortexFloat::input(const Image<PixRGB<byte> >& rgbin)
00554 {
00555   struct env_image ivcout = env_img_initializer;
00556   struct env_image intens = env_img_initializer;
00557   struct env_image color = env_img_initializer;
00558   struct env_image ori = env_img_initializer;
00559 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00560   struct env_image flicker = env_img_initializer;
00561   struct env_image motion = env_img_initializer;
00562 #endif
00563 
00564   ++this->framenum;
00565 
00566   struct env_dims indims = { rgbin.getWidth(), rgbin.getHeight() };
00567 
00568   npixels = indims.w * indims.h;
00569 
00570   const struct env_rgb_pixel* src = (const struct env_rgb_pixel*) rgbin.getArrayPtr();
00571 
00572   const struct env_rgb_pixel* src2 = (const struct env_rgb_pixel*)
00573     (itsColorSmoothing.getVal() == true && itsPrevRgb.initialized() ? itsPrevRgb.getArrayPtr() : 0);
00574 
00575   env_mt_visual_cortex_input(itsMultithreaded.getVal() ? 1 : 0,
00576                              &this->ivc, &this->envp,
00577                              "visualcortex",
00578                              src, src2,
00579                              indims,
00580                              0, //&print_chan_status,
00581                              0, //&userdata,
00582                              &ivcout,
00583                              &intens, &color, &ori
00584 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00585                              , &flicker, &motion
00586 #endif
00587                              );
00588 
00589   this->itsVCXmap = convert_gray_float(&ivcout, ivcout.dims, itsOutputFactor.getVal());
00590 
00591   this->itsImap = convert_gray_float(&intens, ivcout.dims, 1.0F);
00592   this->itsCmap = convert_gray_float(&color, ivcout.dims, 1.0F);
00593   this->itsOmap = convert_gray_float(&ori, ivcout.dims, 1.0F);
00594 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00595   this->itsFmap = convert_gray_float(&flicker, ivcout.dims, 1.0F);
00596   this->itsMmap = convert_gray_float(&motion, ivcout.dims, 1.0F);
00597 #endif
00598 
00599   env_img_make_empty(&ivcout);
00600   env_img_make_empty(&intens);
00601   env_img_make_empty(&color);
00602   env_img_make_empty(&ori);
00603 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00604   env_img_make_empty(&flicker);
00605   env_img_make_empty(&motion);
00606 #endif
00607 
00608   itsPrevRgb = rgbin;
00609 }
00610 
00611 
00612 
00613 // ######################################################################
00614 /* So things look consistent in everyone's emacs... */
00615 /* Local Variables: */
00616 /* mode: c++ */
00617 /* indent-tabs-mode: nil */
00618 /* End: */
00619 
00620 #endif // NEURO_ENVVISUALCORTEX_C_DEFINED
Generated on Sun May 8 08:05:24 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3