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_MT_VISUAL_CORTEX_C_DEFINED
00039 #define ENVISION_ENV_MT_VISUAL_CORTEX_C_DEFINED
00040
00041 #include "Envision/env_mt_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_job_server.h"
00047 #include "Envision/env_log.h"
00048 #include "Envision/env_mt_channel.h"
00049 #include "Envision/env_params.h"
00050
00051 #define WEIGHT_SCALEBITS ((env_size_t) 8)
00052
00053 static void combine_output(struct env_image* chanOut,
00054 const intg32 iweight,
00055 struct env_image* result)
00056 {
00057 if (!env_img_initialized(chanOut))
00058 return;
00059
00060 intg32* const sptr = env_img_pixelsw(chanOut);
00061 const env_size_t sz = env_img_size(chanOut);
00062
00063 if (!env_img_initialized(result))
00064 {
00065 env_img_resize_dims(result, chanOut->dims);
00066 intg32* const dptr = env_img_pixelsw(result);
00067 for (env_size_t i = 0; i < sz; ++i)
00068 {
00069 sptr[i] = (sptr[i] >> WEIGHT_SCALEBITS) * iweight;
00070 dptr[i] = sptr[i];
00071 }
00072 }
00073 else
00074 {
00075 ENV_ASSERT(env_dims_equal(chanOut->dims, result->dims));
00076 intg32* const dptr = env_img_pixelsw(result);
00077 const env_size_t sz = env_img_size(result);
00078 for (env_size_t i = 0; i < sz; ++i)
00079 {
00080 sptr[i] = (sptr[i] >> WEIGHT_SCALEBITS) * iweight;
00081 dptr[i] += sptr[i];
00082 }
00083 }
00084 }
00085
00086 struct env_color_job_data
00087 {
00088 const struct env_params* envp;
00089 const struct env_math* imath;
00090 const struct env_rgb_pixel* const colimg;
00091 const struct env_rgb_pixel* const prev_colimg ;
00092 const struct env_dims dims;
00093 env_chan_status_func* status_func;
00094 void* status_userdata;
00095
00096 struct env_image colorOut;
00097 };
00098
00099 static void env_color_job_run(void* p)
00100 {
00101 struct env_color_job_data* j = (struct env_color_job_data*)(p);
00102 env_chan_color
00103 ("color", j->envp, j->imath, j->colimg, j->prev_colimg,
00104 j->dims, j->status_func, j->status_userdata,
00105 &j->colorOut);
00106 }
00107
00108 struct env_intens_job_data
00109 {
00110 const struct env_params* envp;
00111 const struct env_math* imath;
00112 const struct env_dims dims;
00113 const struct env_pyr* lowpass5;
00114 const int normalizeOutput;
00115 env_chan_status_func* status_func;
00116 void* status_userdata;
00117
00118 struct env_image intensityOut;
00119 };
00120
00121 static void env_intens_job_run(void* p)
00122 {
00123 struct env_intens_job_data* j = (struct env_intens_job_data*)(p);
00124 env_chan_intensity
00125 ("intensity", j->envp, j->imath, j->dims,
00126 j->lowpass5, j->normalizeOutput,
00127 j->status_func, j->status_userdata,
00128 &j->intensityOut);
00129 }
00130
00131 struct env_ori_job_data
00132 {
00133 const struct env_params* envp;
00134 const struct env_math* imath;
00135 const struct env_image* bwimg;
00136 env_chan_status_func* status_func;
00137 void* status_userdata;
00138
00139 struct env_image orientationOut;
00140 };
00141
00142 static void env_ori_job_run(void* p)
00143 {
00144 struct env_ori_job_data* j = (struct env_ori_job_data*)(p);
00145 env_mt_chan_orientation
00146 ("orientation", j->envp, j->imath, j->bwimg,
00147 j->status_func, j->status_userdata,
00148 &j->orientationOut);
00149 }
00150
00151 struct env_flicker_job_data
00152 {
00153 const struct env_params* envp;
00154 const struct env_math* imath;
00155 const struct env_dims dims;
00156 const struct env_pyr* prev_lowpass5;
00157 const struct env_pyr* lowpass5;
00158 const struct env_image* prev_bwimg;
00159 const struct env_image* bwimg;
00160 env_chan_status_func* status_func;
00161 void* status_userdata;
00162
00163 struct env_image flickerOut;
00164 };
00165
00166 static void env_flicker_job_run(void* p)
00167 {
00168 struct env_flicker_job_data* j = (struct env_flicker_job_data*)(p);
00169 if (j->envp->multiscale_flicker)
00170 env_chan_msflicker
00171 ("flicker", j->envp, j->imath, j->dims,
00172 j->prev_lowpass5, j->lowpass5,
00173 j->status_func, j->status_userdata,
00174 &j->flickerOut);
00175 else
00176 env_chan_flicker
00177 ("flicker", j->envp, j->imath,
00178 j->prev_bwimg, j->bwimg,
00179 j->status_func, j->status_userdata,
00180 &j->flickerOut);
00181 }
00182
00183 struct env_motion_job_data
00184 {
00185 struct env_motion_channel* motion_chan;
00186 const struct env_params* envp;
00187 const struct env_math* imath;
00188 const struct env_dims dims;
00189 struct env_pyr lowpass5;
00190 env_chan_status_func* status_func;
00191 void* status_userdata;
00192
00193 struct env_image motionOut;
00194 };
00195
00196 static void env_motion_job_run(void* p)
00197 {
00198 struct env_motion_job_data* j = (struct env_motion_job_data*)(p);
00199 env_mt_motion_channel_input_and_consume_pyr
00200 (j->motion_chan,
00201 "motion", j->envp, j->imath, j->dims, &j->lowpass5,
00202 j->status_func, j->status_userdata,
00203 &j->motionOut);
00204 }
00205
00206
00207 void env_mt_visual_cortex_input(
00208 const int do_multithreaded,
00209 struct env_visual_cortex* vcx,
00210 const struct env_params* envp,
00211 const char* tagName,
00212 const struct env_rgb_pixel* const colimg,
00213 const struct env_rgb_pixel* const prev_colimg,
00214 const struct env_dims dims,
00215 env_chan_status_func* status_func,
00216 void* status_userdata,
00217 struct env_image* result,
00218 struct env_image* intens_result,
00219 struct env_image* color_result,
00220 struct env_image* ori_result
00221 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00222 ,
00223 struct env_image* flicker_result,
00224 struct env_image* motion_result
00225 #endif
00226 )
00227 {
00228 if (!do_multithreaded)
00229 {
00230 env_visual_cortex_input(
00231 vcx, envp, tagName, colimg, prev_colimg, dims,
00232 status_func, status_userdata,
00233 result,
00234 intens_result, color_result, ori_result
00235 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00236 , flicker_result, motion_result
00237 #endif
00238 );
00239 return;
00240 }
00241
00242 env_img_make_empty(result);
00243
00244 const intg32 total_weight = env_total_weight(envp);
00245
00246 ENV_ASSERT(total_weight > 0);
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 struct env_job jobs[5];
00271 env_size_t njobs = 0;
00272
00273 struct env_color_job_data c_data =
00274 {
00275 envp,
00276 &vcx->imath,
00277 colimg,
00278 prev_colimg,
00279 dims,
00280 status_func,
00281 status_userdata,
00282 env_img_initializer
00283 };
00284
00285 if (envp->chan_c_weight > 0)
00286 {
00287 jobs[njobs].callback = &env_color_job_run;
00288 jobs[njobs].userdata = &c_data;
00289 ++njobs;
00290 }
00291
00292 struct env_image bwimg;
00293 env_img_init(&bwimg, dims);
00294 env_c_luminance_from_byte(colimg, dims.w * dims.h,
00295 vcx->imath.nbits, env_img_pixelsw(&bwimg));
00296
00297 struct env_pyr lowpass5;
00298 env_pyr_init(&lowpass5, env_max_pyr_depth(envp));
00299 env_pyr_build_lowpass_5(&bwimg,
00300 envp->cs_lev_min,
00301 &vcx->imath,
00302 &lowpass5);
00303
00304 struct env_intens_job_data i_data =
00305 {
00306 envp,
00307 &vcx->imath,
00308 bwimg.dims,
00309 &lowpass5,
00310 1,
00311 status_func,
00312 status_userdata,
00313 env_img_initializer
00314 };
00315
00316 if (envp->chan_i_weight > 0)
00317 {
00318 jobs[njobs].callback = &env_intens_job_run;
00319 jobs[njobs].userdata = &i_data;
00320 ++njobs;
00321 }
00322
00323 struct env_ori_job_data o_data =
00324 {
00325 envp,
00326 &vcx->imath,
00327 &bwimg,
00328 status_func,
00329 status_userdata,
00330 env_img_initializer
00331 };
00332
00333 if (envp->chan_o_weight > 0)
00334 {
00335 jobs[njobs].callback = &env_ori_job_run;
00336 jobs[njobs].userdata = &o_data;
00337 ++njobs;
00338 }
00339
00340 struct env_flicker_job_data f_data =
00341 {
00342 envp,
00343 &vcx->imath,
00344 bwimg.dims,
00345 &vcx->prev_lowpass5,
00346 &lowpass5,
00347 &vcx->prev_input,
00348 &bwimg,
00349 status_func,
00350 status_userdata,
00351 env_img_initializer
00352 };
00353
00354 if (envp->chan_f_weight > 0)
00355 {
00356 jobs[njobs].callback = &env_flicker_job_run;
00357 jobs[njobs].userdata = &f_data;
00358 ++njobs;
00359 }
00360
00361 struct env_motion_job_data m_data =
00362 {
00363 &vcx->motion_chan,
00364 envp,
00365 &vcx->imath,
00366 bwimg.dims,
00367 env_pyr_initializer,
00368 status_func,
00369 status_userdata,
00370 env_img_initializer
00371 };
00372
00373 if (envp->chan_m_weight > 0)
00374 {
00375 env_pyr_copy_src_dst(&lowpass5, &m_data.lowpass5);
00376 jobs[njobs].callback = &env_motion_job_run;
00377 jobs[njobs].userdata = &m_data;
00378 ++njobs;
00379 }
00380
00381 env_run_jobs(&jobs[0], njobs);
00382
00383 if (env_img_initialized(&c_data.colorOut))
00384 {
00385 const intg32 color_weight =
00386 envp->chan_c_weight*(1<<WEIGHT_SCALEBITS) / total_weight;
00387
00388 combine_output(&c_data.colorOut, color_weight, result);
00389 if (color_result != 0)
00390 env_img_swap(&c_data.colorOut, color_result);
00391 env_img_make_empty(&c_data.colorOut);
00392 }
00393
00394 if (env_img_initialized(&i_data.intensityOut))
00395 {
00396 const intg32 intensity_weight =
00397 envp->chan_i_weight*(1<<WEIGHT_SCALEBITS) / total_weight;
00398
00399 combine_output(&i_data.intensityOut,
00400 intensity_weight, result);
00401 if (intens_result != 0)
00402 env_img_swap(&i_data.intensityOut, intens_result);
00403 env_img_make_empty(&i_data.intensityOut);
00404 }
00405
00406 if (env_img_initialized(&o_data.orientationOut))
00407 {
00408 const intg32 orientation_weight =
00409 envp->chan_o_weight*(1<<WEIGHT_SCALEBITS) / total_weight;
00410
00411 combine_output(&o_data.orientationOut,
00412 orientation_weight, result);
00413 if (ori_result != 0)
00414 env_img_swap(&o_data.orientationOut, ori_result);
00415 env_img_make_empty(&o_data.orientationOut);
00416 }
00417
00418 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00419
00420 if (env_img_initialized(&f_data.flickerOut))
00421 {
00422 const intg32 flicker_weight =
00423 envp->chan_f_weight*(1<<WEIGHT_SCALEBITS) / total_weight;
00424
00425 combine_output(&f_data.flickerOut, flicker_weight, result);
00426 if (flicker_result != 0)
00427 env_img_swap(&f_data.flickerOut, flicker_result);
00428 env_img_make_empty(&f_data.flickerOut);
00429 }
00430
00431 if (envp->chan_f_weight > 0)
00432 {
00433 if (envp->multiscale_flicker)
00434 env_pyr_copy_src_dst
00435 (&lowpass5, &vcx->prev_lowpass5);
00436 else
00437 env_pyr_make_empty(&vcx->prev_lowpass5);
00438 }
00439
00440 if (env_img_initialized(&m_data.motionOut))
00441 {
00442 const intg32 motion_weight =
00443 envp->chan_m_weight*(1<<WEIGHT_SCALEBITS) / total_weight;
00444
00445 combine_output(&m_data.motionOut, motion_weight, result);
00446 if (motion_result != 0)
00447 env_img_swap(&m_data.motionOut, motion_result);
00448 env_img_make_empty(&m_data.motionOut);
00449
00450 env_pyr_make_empty(&m_data.lowpass5);
00451 }
00452
00453 if (!envp->multiscale_flicker)
00454 env_img_swap(&vcx->prev_input, &bwimg);
00455 else
00456 env_img_make_empty(&vcx->prev_input);
00457
00458 #endif
00459
00460 if (status_func)
00461 (*status_func)(status_userdata, tagName, result);
00462
00463 env_pyr_make_empty(&lowpass5);
00464 env_img_make_empty(&bwimg);
00465 }
00466
00467
00468
00469
00470
00471
00472
00473
00474 #endif // ENVISION_ENV_MT_VISUAL_CORTEX_C_DEFINED