env_channel.c

Go to the documentation of this file.
00001 /*!@file Envision/env_channel.c Base class for channels that will use integer math */
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_channel.c $
00035 // $Id: env_channel.c 9830 2008-06-18 18:50:22Z lior $
00036 //
00037 
00038 #ifndef ENVISION_ENV_CHANNEL_C_DEFINED
00039 #define ENVISION_ENV_CHANNEL_C_DEFINED
00040 
00041 #include "Envision/env_channel.h"
00042 
00043 #include "Envision/env_c_math_ops.h"
00044 #include "Envision/env_image_ops.h"
00045 #include "Envision/env_log.h"
00046 #include "Envision/env_params.h"
00047 
00048 #ifndef ENV_NO_DEBUG
00049 
00050 //! Check whether the pyramid is dyadic.
00051 /*! A dyadic pyramid is one in which each level is one half
00052   the width and one half the height of the preceding level. */
00053 static int is_dyadic(const struct env_pyr* pyr,
00054                      const env_size_t first, const env_size_t last)
00055 {
00056         if (first == last) return 0;
00057 
00058         for (env_size_t i = first + 1; i < last; ++i)
00059         {
00060                 const struct env_dims prevdims = env_pyr_img(pyr, i-1)->dims;
00061                 const struct env_dims curdims = env_pyr_img(pyr, i)->dims;
00062 
00063                 // make sure we don't go below 1
00064                 const env_size_t pw2 = ENV_MAX(prevdims.w/2,((env_size_t) 1));
00065                 const env_size_t ph2 = ENV_MAX(prevdims.h/2,((env_size_t) 1));
00066 
00067                 if (curdims.w != pw2) return 0;
00068                 if (curdims.h != ph2) return 0;
00069         }
00070 
00071         return 1;
00072 }
00073 
00074 #endif
00075 
00076 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00077 
00078 // ######################################################################
00079 static void abs_diff_thresh(const struct env_image* b,
00080                             const struct env_image* c,
00081                             const intg32 thresh,
00082                             struct env_image* result)
00083 {
00084         ENV_ASSERT(env_dims_equal(b->dims, c->dims));
00085         ENV_ASSERT(env_dims_equal(b->dims, result->dims));
00086 
00087         const intg32* const bptr = env_img_pixels(b);
00088         const intg32* const cptr = env_img_pixels(c);
00089         intg32* const dptr = env_img_pixelsw(result);
00090 
00091         const env_size_t sz = env_img_size(b);
00092 
00093         for (env_size_t i = 0; i < sz; ++i)
00094         {
00095                 dptr[i] =
00096                         (bptr[i] < cptr[i])
00097                         ? cptr[i] - bptr[i]
00098                         : bptr[i] - cptr[i];
00099 
00100                 if (dptr[i] < thresh) dptr[i] = 0;
00101         }
00102 }
00103 
00104 // ######################################################################
00105 static void abs_diff_thresh_pyr(const struct env_pyr* b,
00106                                 const struct env_pyr* c,
00107                                 const intg32 thresh,
00108                                 struct env_pyr* result)
00109 {
00110         ENV_ASSERT(env_pyr_depth(b) == env_pyr_depth(c));
00111         ENV_ASSERT(env_pyr_depth(c) == env_pyr_depth(result));
00112 
00113         const env_size_t n = env_pyr_depth(b);
00114 
00115         if (env_pyr_depth(result) != n)
00116         {
00117                 env_pyr_make_empty(result);
00118                 env_pyr_init(result, n);
00119         }
00120 
00121         for (env_size_t i = 0; i < n; ++i)
00122         {
00123                 const struct env_image* bimg = env_pyr_img(b, i);
00124 
00125                 if (!env_img_initialized(bimg))
00126                         continue;
00127 
00128                 // else...
00129 
00130                 const struct env_image* cimg = env_pyr_img(c, i);
00131                 struct env_image* rimg = env_pyr_imgw(result, i);
00132 
00133                 env_img_resize_dims(rimg, bimg->dims);
00134 
00135                 abs_diff_thresh(bimg, cimg, thresh, rimg);
00136         }
00137 }
00138 
00139 #endif // ENV_WITH_DYNAMIC_CHANNELS
00140 
00141 // ######################################################################
00142 void env_chan_process_pyr(const char* tagName,
00143                           const struct env_dims inputDims,
00144                           const struct env_pyr* pyr,
00145                           const struct env_params* envp,
00146                           const struct env_math* imath,
00147                           const int takeAbs,
00148                           const int normalizeOutput,
00149                           struct env_image* result)
00150 {
00151         const struct env_dims mapDims =
00152                 { ENV_MAX(inputDims.w / (1 << envp->output_map_level), 1),
00153                   ENV_MAX(inputDims.h / (1 << envp->output_map_level), 1) };
00154 
00155         if (env_pyr_depth(pyr) == 0)
00156                 // OK, our pyramid wasn't ready to give us any output
00157                 // yet, so just return an empty output image:
00158         {
00159                 env_img_make_empty(result);
00160                 return;
00161         }
00162 
00163         // We only want dyadic pyramids here:
00164         ENV_ASSERT(is_dyadic(pyr, envp->cs_lev_min, env_max_pyr_depth(envp)));
00165 
00166         env_img_resize_dims(result, mapDims);
00167 
00168         {
00169                 const env_size_t mapSize = mapDims.w * mapDims.h;
00170                 intg32* const rptr = env_img_pixelsw(result);
00171                 for (env_size_t i = 0; i < mapSize; ++i)
00172                         rptr[i] = 0;
00173         }
00174 
00175         // compute max-normalized weighted sum of center-surround at all levels:
00176         for (env_size_t clev = envp->cs_lev_min; clev <= envp->cs_lev_max; ++clev)
00177                 for (env_size_t delta = envp->cs_del_min; delta <= envp->cs_del_max; ++delta)
00178                 {
00179                         const env_size_t slev = clev + delta;
00180 
00181                         // submap is computed from a center-surround difference:
00182                         struct env_image submap;
00183                         env_img_init(&submap, env_pyr_img(pyr, clev)->dims);
00184                         env_center_surround(env_pyr_img(pyr, clev),
00185                                             env_pyr_img(pyr, slev),
00186                                             takeAbs, &submap);
00187 #ifdef ENV_WITH_VISIT_CHANNEL
00188                         if (envp->submapPreProc != 0)
00189                           (*envp->submapPreProc)(tagName, clev, slev, &submap,
00190                              env_pyr_img(pyr, clev), env_pyr_img(pyr, slev) );
00191 #endif
00192 
00193                         // resize submap to fixed scale if necessary:
00194                         if (submap.dims.w > mapDims.w
00195                             || submap.dims.h > mapDims.h)
00196                         {
00197                                 // how many levels to we need to
00198                                 // downscale the current submap to get
00199                                 // to the output map resolution?
00200                                 const env_size_t n =
00201                                         envp->output_map_level - clev;
00202 
00203                                 env_downsize_9_inplace(&submap, n, imath);
00204                         }
00205                         else if (submap.dims.w < mapDims.w
00206                                  || submap.dims.h < mapDims.h)
00207                         {
00208                                 struct env_image tmp;
00209                                 env_img_init(&tmp, mapDims);
00210                                 env_rescale(&submap, &tmp);
00211                                 env_img_swap(&submap, &tmp);
00212                         }
00213 
00214                         // make sure that the resizing came out
00215                         // precisely:
00216                         ENV_ASSERT(env_dims_equal(submap.dims, mapDims));
00217 
00218                         // first normalize the submap to a fixed
00219                         // dynamic range and then apply spatial
00220                         // competition for salience to the submap:
00221                         env_max_normalize_inplace
00222                                 (&submap, INTMAXNORMMIN, INTMAXNORMMAX,
00223                                  envp->maxnorm_type,
00224                                  envp->range_thresh);
00225 
00226 #ifdef ENV_WITH_VISIT_CHANNEL
00227                         if (envp->submapPostNormProc != 0)
00228                           (*envp->submapPostNormProc)(tagName, clev, slev, &submap,
00229                              env_pyr_img(pyr, clev), env_pyr_img(pyr, slev) );
00230 #endif
00231 
00232                         // add submap to our sum
00233                         env_c_image_div_scalar_accum
00234                                 (env_img_pixels(&submap),
00235                                  env_img_size(&submap),
00236                                  (intg32) env_max_cs_index(envp),
00237                                  env_img_pixelsw(result));
00238 
00239                         env_img_make_empty(&submap);
00240                 }
00241 
00242 #ifdef ENV_WITH_VISIT_CHANNEL
00243         if (envp->submapPostProc != 0)
00244           (*envp->submapPostProc)(tagName, result);
00245 #endif
00246 
00247         // apply max-normalization on the result as needed:
00248         if (normalizeOutput)
00249                 env_max_normalize_inplace
00250                         (result, INTMAXNORMMIN, INTMAXNORMMAX,
00251                          envp->maxnorm_type,
00252                          envp->range_thresh);
00253 }
00254 
00255 // ######################################################################
00256 void env_chan_intensity(const char* tagName,
00257                         const struct env_params* envp,
00258                         const struct env_math* imath,
00259                         const struct env_dims inputdims,
00260                         const struct env_pyr* lowpass5,
00261                         const int normalizeOutput,
00262                         env_chan_status_func* status_func,
00263                         void* status_userdata,
00264                         struct env_image* result)
00265 {
00266         env_chan_process_pyr(tagName, inputdims, lowpass5,
00267                              envp,
00268                              imath,
00269                              1, // takeAbs
00270                              normalizeOutput,
00271                              result);
00272 
00273         if (status_func)
00274                 (*status_func)(status_userdata, tagName, result);
00275 }
00276 
00277 // ######################################################################
00278 void env_chan_color(const char* tagName,
00279                     const struct env_params* envp,
00280                     const struct env_math* imath,
00281                     const struct env_rgb_pixel* const colimg,
00282                     const struct env_rgb_pixel* const prev_colimg,
00283                     const struct env_dims dims,
00284                     env_chan_status_func* status_func,
00285                     void* status_userdata,
00286                     struct env_image* result)
00287 {
00288         struct env_image rg; env_img_init(&rg, dims);
00289         struct env_image by; env_img_init(&by, dims);
00290 
00291         const intg32 lumthresh = (3*255) / 10;
00292         env_get_rgby(colimg, prev_colimg, dims.w * dims.h,
00293                      &rg, &by, lumthresh, imath->nbits);
00294 
00295         const env_size_t firstlevel = envp->cs_lev_min;
00296         const env_size_t depth = env_max_pyr_depth(envp);
00297 
00298         {
00299                 struct env_pyr rgpyr;
00300                 env_pyr_init(&rgpyr, depth);
00301                 env_pyr_build_lowpass_5(&rg, firstlevel, imath, &rgpyr);
00302 
00303                 env_chan_intensity("red/green", envp, imath,
00304                                    rg.dims, &rgpyr, 0,
00305                                    status_func, status_userdata, result);
00306 
00307                 env_pyr_make_empty(&rgpyr);
00308         }
00309 
00310         struct env_image byOut = env_img_initializer;
00311 
00312         {
00313                 struct env_pyr bypyr;
00314                 env_pyr_init(&bypyr, depth);
00315                 env_pyr_build_lowpass_5(&by, firstlevel, imath, &bypyr);
00316 
00317                 env_chan_intensity("blue/yellow", envp, imath,
00318                                    by.dims, &bypyr, 0,
00319                                    status_func, status_userdata, &byOut);
00320                 env_pyr_make_empty(&bypyr);
00321         }
00322 
00323         env_img_make_empty(&rg);
00324         env_img_make_empty(&by);
00325 
00326         const intg32* const byptr = env_img_pixels(&byOut);
00327         intg32* const dptr = env_img_pixelsw(result);
00328         const env_size_t sz = env_img_size(result);
00329 
00330         for (env_size_t i = 0; i < sz; ++i)
00331                 dptr[i] = (dptr[i] / 2) + (byptr[i] / 2);
00332 
00333         env_max_normalize_inplace(result, INTMAXNORMMIN, INTMAXNORMMAX,
00334                                   envp->maxnorm_type,
00335                                   envp->range_thresh);
00336         if (status_func)
00337                 (*status_func)(status_userdata, tagName, result);
00338 
00339         env_img_make_empty(&byOut);
00340 }
00341 
00342 // ######################################################################
00343 void env_chan_steerable(const char* tagName,
00344                         const struct env_params* envp,
00345                         const struct env_math* imath,
00346                         const struct env_dims inputdims,
00347                         const struct env_pyr* hipass9,
00348                         const env_size_t thetaidx,
00349                         env_chan_status_func* status_func,
00350                         void* status_userdata,
00351                         struct env_image* result)
00352 {
00353         const env_size_t kdenombits = ENV_TRIG_NBITS;
00354 
00355         // spatial_freq = 2.6 / (2*pi) ~= 0.41380285203892792 ~= 2069/5000
00356 
00357         const intg32 sfnumer = 2069;
00358         const intg32 sfdenom = 5000;
00359 
00360         const intg32 kxnumer = ((intg32) (sfnumer * imath->costab[thetaidx] * ENV_TRIG_TABSIZ)) / sfdenom;
00361         const intg32 kynumer = ((intg32) (sfnumer * imath->sintab[thetaidx] * ENV_TRIG_TABSIZ)) / sfdenom;
00362 
00363         // Compute our pyramid:
00364         struct env_pyr pyr = env_pyr_initializer;
00365         env_pyr_build_steerable_from_hipass_9(hipass9,
00366                                               kxnumer, kynumer, kdenombits,
00367                                               imath,
00368                                               &pyr);
00369 
00370         env_chan_process_pyr(tagName, inputdims, &pyr,
00371                              envp,
00372                              imath,
00373                              0, // takeAbs
00374                              1, // normalizeOutput
00375                              result);
00376 
00377         if (status_func)
00378                 (*status_func)(status_userdata, tagName, result);
00379 
00380         env_pyr_make_empty(&pyr);
00381 }
00382 
00383 // ######################################################################
00384 void env_chan_orientation(const char* tagName,
00385                           const struct env_params* envp,
00386                           const struct env_math* imath,
00387                           const struct env_image* img,
00388                           env_chan_status_func* status_func,
00389                           void* status_userdata,
00390                           struct env_image* result)
00391 {
00392         env_img_make_empty(result);
00393 
00394         if (envp->num_orientations == 0)
00395                 return;
00396 
00397         struct env_pyr hipass9;
00398         env_pyr_init(&hipass9, env_max_pyr_depth(envp));
00399         env_pyr_build_hipass_9(img,
00400                                envp->cs_lev_min,
00401                                imath,
00402                                &hipass9);
00403 
00404         struct env_image chanOut = env_img_initializer;
00405 
00406         char buf[17] =
00407                 {
00408                         's', 't', 'e', 'e', 'r', 'a', 'b', 'l', 'e', // 0--8
00409                         '(', '_', '_', // 9--11
00410                         '/', '_', '_', ')', '\0' // 12--16
00411                 };
00412 
00413         ENV_ASSERT(envp->num_orientations <= 99);
00414 
00415         buf[13] = '0' + (envp->num_orientations / 10);
00416         buf[14] = '0' + (envp->num_orientations % 10);
00417 
00418         for (env_size_t i = 0; i < envp->num_orientations; ++i)
00419         {
00420                 // theta = (180.0 * i) / envp->num_orientations +
00421                 // 90.0, where ENV_TRIG_TABSIZ is equivalent to 360.0
00422                 // or 2*pi
00423                 const env_size_t thetaidx =
00424                         (ENV_TRIG_TABSIZ * i)
00425                         / (2 * envp->num_orientations)
00426                         + (ENV_TRIG_TABSIZ / 4);
00427 
00428                 ENV_ASSERT(thetaidx < ENV_TRIG_TABSIZ);
00429 
00430                 buf[10] = '0' + ((i+1) / 10);
00431                 buf[11] = '0' + ((i+1) % 10);
00432 
00433                 env_chan_steerable
00434                         (buf, envp, imath, img->dims,
00435                          &hipass9, thetaidx,
00436                          status_func, status_userdata, &chanOut);
00437 
00438                 ENV_ASSERT(env_img_initialized(&chanOut));
00439 
00440                 if (!env_img_initialized(result))
00441                 {
00442                         env_img_resize_dims(result, chanOut.dims);
00443                         env_c_image_div_scalar
00444                                 (env_img_pixels(&chanOut),
00445                                  env_img_size(&chanOut),
00446                                  (intg32) envp->num_orientations,
00447                                  env_img_pixelsw(result));
00448                 }
00449                 else
00450                 {
00451                         ENV_ASSERT(env_dims_equal(chanOut.dims,
00452                                                   result->dims));
00453                         env_c_image_div_scalar_accum
00454                                 (env_img_pixels(&chanOut),
00455                                  env_img_size(&chanOut),
00456                                  (intg32) envp->num_orientations,
00457                                  env_img_pixelsw(result));
00458                 }
00459         }
00460 
00461         env_img_make_empty(&chanOut);
00462         env_pyr_make_empty(&hipass9);
00463 
00464         ENV_ASSERT(env_img_initialized(result));
00465 
00466         env_max_normalize_inplace(result, INTMAXNORMMIN, INTMAXNORMMAX,
00467                                   envp->maxnorm_type,
00468                                   envp->range_thresh);
00469 
00470         if (status_func)
00471                 (*status_func)(status_userdata, tagName, result);
00472 }
00473 
00474 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00475 
00476 // ######################################################################
00477 void env_chan_flicker(const char* tagName,
00478                       const struct env_params* envp,
00479                       const struct env_math* imath,
00480                       const struct env_image* prev,
00481                       const struct env_image* cur,
00482                       env_chan_status_func* status_func,
00483                       void* status_userdata,
00484                       struct env_image* result)
00485 {
00486         // If this is the first time the flicker channel has seen input,
00487         // then prev will be uninitialized; obviously we can't compute any
00488         // flicker with only one frame, so we just store the current input
00489         // as the next iteration's previous input
00490         if (!env_img_initialized(prev))
00491         {
00492                 env_img_make_empty(result);
00493         }
00494         else
00495         {
00496                 const intg32 lowthresh =
00497                         (envp->scale_bits > 8)
00498                         ? (envp->flicker_thresh << (envp->scale_bits - 8))
00499                         : (envp->flicker_thresh >> (8 - envp->scale_bits));
00500 
00501                 // take thresholded abs difference between current and
00502                 // previous frame:
00503                 struct env_image fli;
00504                 env_img_init(&fli, prev->dims);
00505                 abs_diff_thresh(cur, prev, lowthresh, &fli);
00506 
00507                 const env_size_t firstlevel = envp->cs_lev_min;
00508                 const env_size_t depth = env_max_pyr_depth(envp);
00509 
00510                 // Compute our pyramid:
00511                 struct env_pyr pyr;
00512                 env_pyr_init(&pyr, depth);
00513                 env_pyr_build_lowpass_5(&fli, firstlevel, imath, &pyr);
00514 
00515                 env_chan_process_pyr(tagName, fli.dims, &pyr,
00516                                      envp,
00517                                      imath,
00518                                      1, // takeAbs
00519                                      1, // normalizeOutput
00520                                      result);
00521 
00522                 if (status_func)
00523                         (*status_func)(status_userdata, tagName, result);
00524 
00525                 env_img_make_empty(&fli);
00526                 env_pyr_make_empty(&pyr);
00527         }
00528 }
00529 
00530 // ######################################################################
00531 void env_chan_msflicker(const char* tagName,
00532                         const struct env_params* envp,
00533                         const struct env_math* imath,
00534                         const struct env_dims inputDims,
00535                         const struct env_pyr* prev_lowpass5,
00536                         const struct env_pyr* cur_lowpass5,
00537                         env_chan_status_func* status_func,
00538                         void* status_userdata,
00539                         struct env_image* result)
00540 {
00541         // If this is the first time the flicker channel has seen
00542         // input, then prev will be uninitialized; obviously we can't
00543         // compute any flicker with only one frame, so we just store
00544         // the current input as the next iteration's previous input
00545         if (env_pyr_depth(prev_lowpass5) == 0)
00546         {
00547                 env_img_make_empty(result);
00548         }
00549         else
00550         {
00551                 const intg32 lowthresh =
00552                         (envp->scale_bits > 8)
00553                         ? (envp->flicker_thresh << (envp->scale_bits - 8))
00554                         : (envp->flicker_thresh >> (8 - envp->scale_bits));
00555 
00556                 // take thresholded abs difference between current and
00557                 // previous frame:
00558                 struct env_pyr fli;
00559                 env_pyr_init(&fli, env_pyr_depth(cur_lowpass5));
00560                 abs_diff_thresh_pyr(cur_lowpass5, prev_lowpass5,
00561                                     lowthresh, &fli);
00562 
00563                 env_chan_process_pyr(tagName, inputDims, &fli,
00564                                      envp,
00565                                      imath,
00566                                      1, // takeAbs
00567                                      1, // normalizeOutput
00568                                      result);
00569 
00570                 if (status_func)
00571                         (*status_func)(status_userdata, tagName, result);
00572 
00573                 env_pyr_make_empty(&fli);
00574         }
00575 }
00576 
00577 // ######################################################################
00578 void env_chan_direction(const char* tagName,
00579                         const struct env_params* envp,
00580                         const struct env_math* imath,
00581                         const struct env_dims inputdims,
00582                         const struct env_pyr* unshiftedPrev,
00583                         const struct env_pyr* unshiftedCur,
00584                         const struct env_pyr* shiftedPrev,
00585                         const struct env_pyr* shiftedCur,
00586                         env_chan_status_func* status_func,
00587                         void* status_userdata,
00588                         struct env_image* result)
00589 {
00590         const env_size_t firstlevel = envp->cs_lev_min;
00591         const env_size_t depth = env_max_pyr_depth(envp);
00592 
00593         const env_size_t nshift = (imath->nbits+1)/2;
00594 
00595         if (env_pyr_depth(unshiftedPrev) == 0)
00596         {
00597                 // it's our first time, so just return an empty image:
00598                 env_img_make_empty(result);
00599         }
00600         else
00601         {
00602                 struct env_pyr pyr;
00603                 env_pyr_init(&pyr, depth);
00604 
00605                 const intg32 lowthresh =
00606                         (envp->scale_bits > 8)
00607                         ? (envp->motion_thresh << (envp->scale_bits - 8))
00608                         : (envp->motion_thresh >> (8 - envp->scale_bits));
00609 
00610                 // compute the Reichardt maps
00611                 for (env_size_t i = firstlevel; i < depth; i++)
00612                 {
00613                         env_img_resize_dims
00614                                 (env_pyr_imgw(&pyr, i),
00615                                  env_pyr_img(unshiftedCur, i)->dims);
00616 
00617                         const intg32* const ucurr = env_img_pixels(env_pyr_img(unshiftedCur, i));
00618                         const intg32* const uprev = env_img_pixels(env_pyr_img(unshiftedPrev, i));
00619                         const intg32* const scurr = env_img_pixels(env_pyr_img(shiftedCur, i));
00620                         const intg32* const sprev = env_img_pixels(env_pyr_img(shiftedPrev, i));
00621                         intg32* const dptr = env_img_pixelsw(env_pyr_imgw(&pyr, i));
00622 
00623                         const env_size_t sz = env_img_size(env_pyr_img(&pyr, i));
00624 
00625                         for (env_size_t c = 0; c < sz; ++c)
00626                         {
00627                                 dptr[c] =
00628                                         ((ucurr[c] >> nshift) * (sprev[c] >> nshift)) -
00629                                         ((uprev[c] >> nshift) * (scurr[c] >> nshift));
00630 
00631                                 if (dptr[c] < lowthresh) dptr[c] = 0;
00632                         }
00633                 }
00634 
00635                 env_chan_process_pyr(tagName, inputdims, &pyr,
00636                                      envp,
00637                                      imath,
00638                                      1, // takeAbs
00639                                      1, // normalizeOutput
00640                                      result);
00641 
00642                 if (status_func)
00643                         (*status_func)(status_userdata, tagName, result);
00644 
00645                 env_pyr_make_empty(&pyr);
00646         }
00647 }
00648 
00649 #endif // ENV_WITH_DYNAMIC_CHANNELS
00650 
00651 // ######################################################################
00652 /* So things look consistent in everyone's emacs... */
00653 /* Local Variables: */
00654 /* indent-tabs-mode: nil */
00655 /* c-file-style: "linux" */
00656 /* End: */
00657 
00658 #endif // ENVISION_ENV_CHANNEL_C_DEFINED
Generated on Sun May 8 08:40:38 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3