00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
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
00178
00179
00180
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
00329 env_merge_range(result, &mi, &ma);
00330 env_rescale_range_inplace(result, mi, ma);
00331
00332
00333
00334
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
00359
00360
00361
00362
00363
00364 #endif // ENVISION_ENV_VISUAL_CORTEX_C_DEFINED