env_visual_cortex.c

Go to the documentation of this file.
00001 /*!@file Envision/env_visual_cortex.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/Envision/env_visual_cortex.c $
00035 // $Id: env_visual_cortex.c 8054 2007-03-07 00:47:08Z rjpeters $
00036 //
00037 
00038 #ifndef ENVISION_ENV_VISUAL_CORTEX_C_DEFINED
00039 #define ENVISION_ENV_VISUAL_CORTEX_C_DEFINED
00040 
00041 #include "Envision/env_visual_cortex.h"
00042 
00043 #include "Envision/env_c_math_ops.h"
00044 #include "Envision/env_channel.h"
00045 #include "Envision/env_image_ops.h"
00046 #include "Envision/env_log.h"
00047 #include "Envision/env_params.h"
00048 
00049 #define WEIGHT_SCALEBITS ((env_size_t) 8)
00050 
00051 static void combine_output(struct env_image* chanOut,
00052                            const intg32 iweight,
00053                            struct env_image* result)
00054 {
00055         if (!env_img_initialized(chanOut))
00056                 return;
00057 
00058         intg32* const sptr = env_img_pixelsw(chanOut);
00059         const env_size_t sz = env_img_size(chanOut);
00060 
00061         if (!env_img_initialized(result))
00062         {
00063                 env_img_resize_dims(result, chanOut->dims);
00064                 intg32* const dptr = env_img_pixelsw(result);
00065                 for (env_size_t i = 0; i < sz; ++i)
00066                 {
00067                         sptr[i] = (sptr[i] >> WEIGHT_SCALEBITS) * iweight;
00068                         dptr[i] = sptr[i];
00069                 }
00070         }
00071         else
00072         {
00073                 ENV_ASSERT(env_dims_equal(chanOut->dims, result->dims));
00074                 intg32* const dptr = env_img_pixelsw(result);
00075                 const env_size_t sz = env_img_size(result);
00076                 for (env_size_t i = 0; i < sz; ++i)
00077                 {
00078                         sptr[i] = (sptr[i] >> WEIGHT_SCALEBITS) * iweight;
00079                         dptr[i] += sptr[i];
00080                 }
00081         }
00082 }
00083 
00084 // ######################################################################
00085 void env_visual_cortex_init(struct env_visual_cortex* vcx,
00086                             const struct env_params* envp)
00087 {
00088         env_params_validate(envp);
00089 
00090         env_init_integer_math(&vcx->imath, envp);
00091 
00092 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00093         env_img_init_empty(&vcx->prev_input);
00094         env_pyr_init(&vcx->prev_lowpass5, 0);
00095 #endif
00096 
00097 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00098         env_motion_channel_init(&vcx->motion_chan, envp);
00099 #endif
00100 
00101 }
00102 
00103 // ######################################################################
00104 void env_visual_cortex_destroy(struct env_visual_cortex* vcx)
00105 {
00106 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00107         env_img_make_empty(&vcx->prev_input);
00108         env_pyr_make_empty(&vcx->prev_lowpass5);
00109         env_motion_channel_destroy(&vcx->motion_chan);
00110 #endif
00111 }
00112 
00113 // ######################################################################
00114 void env_visual_cortex_input(
00115         struct env_visual_cortex* vcx,
00116         const struct env_params* envp,
00117         const char* tagName,
00118         const struct env_rgb_pixel* const colimg,
00119         const struct env_rgb_pixel* const prev_colimg,
00120         const struct env_dims dims,
00121         env_chan_status_func* status_func,
00122         void* status_userdata,
00123         struct env_image* result,
00124         struct env_image* intens_result,
00125         struct env_image* color_result,
00126         struct env_image* ori_result
00127 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00128         ,
00129         struct env_image* flicker_result,
00130         struct env_image* motion_result
00131 #endif
00132         )
00133 {
00134         env_img_make_empty(result);
00135 
00136         const intg32 total_weight = env_total_weight(envp);
00137 
00138         ENV_ASSERT(total_weight > 0);
00139 
00140         /* We want to compute
00141 
00142          *                 weight
00143          *        img * ------------
00144          *              total_weight
00145          *
00146          *
00147          *        To do that without overflowing, we compute it as
00148          *
00149          *
00150          *                 weight      256
00151          *        img * ------------ * ---
00152          *              total_weight   256
00153          *
00154          *            img       weight * 256
00155          *        = ( --- ) * ( ------------ )
00156          *            256       total_weight
00157          *
00158          * where 256 is an example of (1<<WEIGHT_SCALEBITS) for
00159          * WEIGHT_SCALEBITS=8.
00160          */
00161 
00162         if (envp->chan_c_weight > 0)
00163         {
00164                 const intg32 color_weight =
00165                         envp->chan_c_weight*(1<<WEIGHT_SCALEBITS) / total_weight;
00166 
00167                 struct env_image colorOut = env_img_initializer;
00168                 env_chan_color
00169                         ("color", envp, &vcx->imath, colimg, prev_colimg,
00170                          dims, status_func, status_userdata, &colorOut);
00171                 combine_output(&colorOut, color_weight, result);
00172                 if (color_result != 0)
00173                         env_img_swap(&colorOut, color_result);
00174                 env_img_make_empty(&colorOut);
00175         }
00176 
00177         // don't compute the luminance image and luminance lowpass5
00178         // pyramid until AFTER we've done the color channel, so that
00179         // we minimize the number of simultaneous temporary images at
00180         // the highest resolution
00181 
00182         struct env_image bwimg;
00183         env_img_init(&bwimg, dims);
00184         env_c_luminance_from_byte(colimg, dims.w * dims.h,
00185                                   vcx->imath.nbits, env_img_pixelsw(&bwimg));
00186 
00187         struct env_pyr lowpass5;
00188         env_pyr_init(&lowpass5, env_max_pyr_depth(envp));
00189         env_pyr_build_lowpass_5(&bwimg,
00190                                 envp->cs_lev_min,
00191                                 &vcx->imath,
00192                                 &lowpass5);
00193 
00194         if (envp->chan_i_weight > 0)
00195         {
00196                 const intg32 intensity_weight =
00197                         envp->chan_i_weight*(1<<WEIGHT_SCALEBITS) / total_weight;
00198 
00199                 struct env_image intensityOut = env_img_initializer;
00200                 env_chan_intensity
00201                         ("intensity", envp, &vcx->imath, bwimg.dims,
00202                          &lowpass5, 1, status_func, status_userdata,
00203                          &intensityOut);
00204                 combine_output(&intensityOut, intensity_weight, result);
00205                 if (intens_result != 0)
00206                         env_img_swap(&intensityOut, intens_result);
00207                 env_img_make_empty(&intensityOut);
00208         }
00209 
00210         if (envp->chan_o_weight > 0)
00211         {
00212                 const intg32 orientation_weight =
00213                         envp->chan_o_weight*(1<<WEIGHT_SCALEBITS) / total_weight;
00214 
00215                 struct env_image orientationOut = env_img_initializer;
00216                 env_chan_orientation
00217                         ("orientation", envp, &vcx->imath,
00218                          &bwimg, status_func, status_userdata,
00219                          &orientationOut);
00220                 combine_output(&orientationOut, orientation_weight, result);
00221                 if (ori_result != 0)
00222                         env_img_swap(&orientationOut, ori_result);
00223                 env_img_make_empty(&orientationOut);
00224         }
00225 
00226 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00227 
00228         if (envp->chan_f_weight > 0)
00229         {
00230                 const intg32 flicker_weight =
00231                         envp->chan_f_weight*(1<<WEIGHT_SCALEBITS) / total_weight;
00232 
00233                 struct env_image flickerOut = env_img_initializer;
00234                 if (envp->multiscale_flicker)
00235                         env_chan_msflicker
00236                                 ("flicker", envp, &vcx->imath,
00237                                  bwimg.dims,
00238                                  &vcx->prev_lowpass5, &lowpass5,
00239                                  status_func, status_userdata,
00240                                  &flickerOut);
00241                 else
00242                         env_chan_flicker
00243                                 ("flicker", envp, &vcx->imath,
00244                                  &vcx->prev_input, &bwimg,
00245                                  status_func, status_userdata,
00246                                  &flickerOut);
00247                 combine_output(&flickerOut, flicker_weight, result);
00248                 if (flicker_result != 0)
00249                         env_img_swap(&flickerOut, flicker_result);
00250                 env_img_make_empty(&flickerOut);
00251 
00252                 if (envp->multiscale_flicker)
00253                         env_pyr_copy_src_dst
00254                                 (&lowpass5, &vcx->prev_lowpass5);
00255                 else
00256                         env_pyr_make_empty(&vcx->prev_lowpass5);
00257         }
00258 
00259         if (envp->chan_m_weight > 0)
00260         {
00261                 const intg32 motion_weight =
00262                         envp->chan_m_weight*(1<<WEIGHT_SCALEBITS) / total_weight;
00263 
00264                 struct env_image motionOut = env_img_initializer;
00265                 env_motion_channel_input_and_consume_pyr
00266                         (&vcx->motion_chan,
00267                          "motion", envp, &vcx->imath, bwimg.dims,
00268                          &lowpass5, status_func, status_userdata,
00269                          &motionOut);
00270                 combine_output(&motionOut, motion_weight, result);
00271                 if (motion_result != 0)
00272                         env_img_swap(&motionOut, motion_result);
00273                 env_img_make_empty(&motionOut);
00274         }
00275 
00276         if (!envp->multiscale_flicker)
00277                 env_img_swap(&vcx->prev_input, &bwimg);
00278         else
00279                 env_img_make_empty(&vcx->prev_input);
00280 
00281 #endif
00282 
00283         if (status_func)
00284                 (*status_func)(status_userdata, tagName, result);
00285 
00286         env_pyr_make_empty(&lowpass5);
00287         env_img_make_empty(&bwimg);
00288 }
00289 
00290 // ######################################################################
00291 void env_visual_cortex_merge_ranges(
00292         const struct env_image* intens_result,
00293         const struct env_image* color_result,
00294         const struct env_image* ori_result,
00295 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00296         const struct env_image* flicker_result,
00297         const struct env_image* motion_result,
00298 #endif
00299         intg32* mi,
00300         intg32* ma
00301         )
00302 {
00303         env_merge_range(intens_result, mi, ma);
00304         env_merge_range(color_result, mi, ma);
00305         env_merge_range(ori_result, mi, ma);
00306 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00307         env_merge_range(flicker_result, mi, ma);
00308         env_merge_range(motion_result, mi, ma);
00309 #endif
00310 }
00311 
00312 // ######################################################################
00313 void env_visual_cortex_rescale_ranges(
00314         struct env_image* result,
00315         struct env_image* intens_result,
00316         struct env_image* color_result,
00317         struct env_image* ori_result
00318 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00319         ,
00320         struct env_image* flicker_result,
00321         struct env_image* motion_result
00322 #endif
00323         )
00324 {
00325         intg32 mi = INTG32_MAX;
00326         intg32 ma = INTG32_MIN;
00327 
00328         // first rescale the overall output on its own:
00329         env_merge_range(result, &mi, &ma);
00330         env_rescale_range_inplace(result, mi, ma);
00331 
00332         // now compute a single min/max range covering ALL of the
00333         // individual channel outputs, and rescale the each of the
00334         // outputs using that same range:
00335         mi = INTG32_MAX;
00336         ma = INTG32_MIN;
00337 
00338         env_visual_cortex_merge_ranges(intens_result,
00339                                        color_result,
00340                                        ori_result,
00341 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00342                                        flicker_result,
00343                                        motion_result,
00344 #endif
00345                                        &mi, &ma);
00346 
00347         env_rescale_range_inplace(intens_result, mi, ma);
00348         env_rescale_range_inplace(color_result, mi, ma);
00349         env_rescale_range_inplace(ori_result, mi, ma);
00350 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00351         env_rescale_range_inplace(flicker_result, mi, ma);
00352         env_rescale_range_inplace(motion_result, mi, ma);
00353 #endif
00354 
00355 }
00356 
00357 // ######################################################################
00358 /* So things look consistent in everyone's emacs... */
00359 /* Local Variables: */
00360 /* indent-tabs-mode: nil */
00361 /* c-file-style: "linux" */
00362 /* End: */
00363 
00364 #endif // ENVISION_ENV_VISUAL_CORTEX_C_DEFINED
Generated on Sun May 8 08:40:38 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3