00001 /*!@file Envision/env_motion_channel.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_motion_channel.c $ 00035 // $Id: env_motion_channel.c 9830 2008-06-18 18:50:22Z lior $ 00036 // 00037 00038 #ifndef ENVISION_ENV_MOTION_CHANNEL_C_DEFINED 00039 #define ENVISION_ENV_MOTION_CHANNEL_C_DEFINED 00040 00041 #include "Envision/env_motion_channel.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 #ifdef ENV_WITH_DYNAMIC_CHANNELS 00050 00051 // ###################################################################### 00052 // env_motion_channel function definitions: 00053 // ###################################################################### 00054 00055 // ###################################################################### 00056 void env_motion_channel_init(struct env_motion_channel* chan, 00057 const struct env_params* envp) 00058 { 00059 env_pyr_init_empty(&chan->unshifted_prev); 00060 chan->num_directions = envp->num_motion_directions; 00061 chan->shifted_prev = (struct env_pyr*) 00062 env_allocate(envp->num_motion_directions 00063 * sizeof(struct env_pyr)); 00064 for (env_size_t i = 0; i < envp->num_motion_directions; ++i) 00065 env_pyr_init_empty(&chan->shifted_prev[i]); 00066 } 00067 00068 // ###################################################################### 00069 void env_motion_channel_destroy(struct env_motion_channel* chan) 00070 { 00071 env_pyr_make_empty(&chan->unshifted_prev); 00072 for (env_size_t i = 0; i < chan->num_directions; ++i) 00073 env_pyr_make_empty(&chan->shifted_prev[i]); 00074 env_deallocate(chan->shifted_prev); 00075 chan->num_directions = 0; 00076 chan->shifted_prev = 0; 00077 } 00078 00079 // ###################################################################### 00080 void env_motion_channel_input_and_consume_pyr( 00081 struct env_motion_channel* chan, 00082 const char* tagName, 00083 const struct env_params* envp, 00084 const struct env_math* imath, 00085 const struct env_dims inputdims, 00086 struct env_pyr* unshiftedCur, 00087 env_chan_status_func* status_func, 00088 void* status_userdata, 00089 struct env_image* result) 00090 { 00091 env_img_make_empty(result); 00092 00093 if (chan->num_directions != envp->num_motion_directions) 00094 { 00095 env_motion_channel_destroy(chan); 00096 env_motion_channel_init(chan, envp); 00097 } 00098 00099 if (chan->num_directions == 0) 00100 return; 00101 00102 const env_size_t firstlevel = envp->cs_lev_min; 00103 const env_size_t depth = env_max_pyr_depth(envp); 00104 00105 struct env_image chanOut = env_img_initializer; 00106 00107 char buf[17] = 00108 { 00109 'r', 'e', 'i', 'c', 'h', 'a', 'r', 'd', 't', // 0--8 00110 '(', '_', '_', // 9--11 00111 '/', '_', '_', ')', '\0' // 12--16 00112 }; 00113 00114 ENV_ASSERT(chan->num_directions <= 99); 00115 00116 buf[13] = '0' + (chan->num_directions / 10); 00117 buf[14] = '0' + (chan->num_directions % 10); 00118 00119 // compute Reichardt motion detection into several directions 00120 for (env_size_t dir = 0; dir < chan->num_directions; ++dir) 00121 { 00122 // theta = (360.0 * i) / chan->num_directions; 00123 const env_size_t thetaidx = 00124 (dir * ENV_TRIG_TABSIZ) / chan->num_directions; 00125 00126 ENV_ASSERT(thetaidx < ENV_TRIG_TABSIZ); 00127 00128 buf[10] = '0' + ((dir+1) / 10); 00129 buf[11] = '0' + ((dir+1) % 10); 00130 00131 // create an empty pyramid 00132 struct env_pyr shiftedCur; 00133 env_pyr_init(&shiftedCur, depth); 00134 00135 // fill the empty pyramid with the shifted version 00136 for (env_size_t i = firstlevel; i < depth; ++i) 00137 { 00138 env_img_resize_dims(env_pyr_imgw(&shiftedCur, i), 00139 env_pyr_img(unshiftedCur, i)->dims); 00140 env_shift_image(env_pyr_img(unshiftedCur, i), 00141 imath->costab[thetaidx], 00142 -imath->sintab[thetaidx], 00143 ENV_TRIG_NBITS, 00144 env_pyr_imgw(&shiftedCur, i)); 00145 } 00146 00147 env_chan_direction(buf, envp, imath, 00148 inputdims, 00149 &chan->unshifted_prev, unshiftedCur, 00150 &chan->shifted_prev[dir], &shiftedCur, 00151 status_func, status_userdata, &chanOut); 00152 00153 env_pyr_swap(&chan->shifted_prev[dir], &shiftedCur); 00154 env_pyr_make_empty(&shiftedCur); 00155 00156 if (env_img_initialized(&chanOut)) 00157 { 00158 if (!env_img_initialized(result)) 00159 { 00160 env_img_resize_dims(result, chanOut.dims); 00161 env_c_image_div_scalar 00162 (env_img_pixels(&chanOut), 00163 env_img_size(&chanOut), 00164 (intg32) chan->num_directions, 00165 env_img_pixelsw(result)); 00166 } 00167 else 00168 { 00169 ENV_ASSERT 00170 (env_dims_equal(chanOut.dims, 00171 result->dims)); 00172 env_c_image_div_scalar_accum 00173 (env_img_pixels(&chanOut), 00174 env_img_size(&chanOut), 00175 (intg32) chan->num_directions, 00176 env_img_pixelsw(result)); 00177 } 00178 } 00179 } 00180 00181 env_img_make_empty(&chanOut); 00182 00183 if (env_img_initialized(result)) 00184 { 00185 env_max_normalize_inplace(result, 00186 INTMAXNORMMIN, INTMAXNORMMAX, 00187 envp->maxnorm_type, 00188 envp->range_thresh); 00189 if (status_func) 00190 (*status_func)(status_userdata, tagName, result); 00191 } 00192 00193 env_pyr_swap(unshiftedCur, &chan->unshifted_prev); 00194 env_pyr_make_empty(unshiftedCur); 00195 } 00196 00197 #endif // ENV_WITH_DYNAMIC_CHANNELS 00198 00199 // ###################################################################### 00200 /* So things look consistent in everyone's emacs... */ 00201 /* Local Variables: */ 00202 /* indent-tabs-mode: nil */ 00203 /* c-file-style: "linux" */ 00204 /* End: */ 00205 00206 #endif // ENVISION_ENV_MOTION_CHANNEL_C_DEFINED