00001
00002
00003 #include <vul/vul_timer.h>
00004 #include <vcl_cstdlib.h>
00005 #include <vcl_cmath.h>
00006 #include <brip/brip_vil1_float_ops.h>
00007 #include <brip/brip_para_cvrg.h>
00008 #include <vcl_cassert.h>
00009
00010
00011
00012 void brip_para_cvrg::init_variables()
00013 {
00014 width_ = int(3*sigma_);
00015 proj_n_ = 2*proj_width_ + 1;
00016 sup_proj_ = new float[proj_n_];
00017 proj_0_ = new float[proj_n_];
00018 proj_45_ = new float[proj_n_];
00019 proj_90_ = new float[proj_n_];
00020 proj_135_ = new float[proj_n_];
00021 }
00022
00023
00024
00025
00026 void brip_para_cvrg::init(vil1_image const & image)
00027 {
00028 vul_timer t;
00029
00030 int w = image.width(), h = image.height();
00031 xstart_ = 0;
00032 ystart_ = 0;
00033 xsize_ = w;
00034 ysize_ = h;
00035
00036 vcl_cout << "xstart = " << xstart_ << " ystart_ = " << ystart_ << '\n'
00037 << "xsize = " << xsize_ << " ysize_ = " << ysize_ << '\n';
00038
00039 image_ = brip_vil1_float_ops::convert_to_float(image);
00040 avg_ = make_float_image(w, h);
00041 grad0_ = make_float_image(w, h);
00042 grad45_ = make_float_image(w, h);
00043 grad90_ = make_float_image(w, h);
00044 grad135_ = make_float_image(w, h);
00045 det_ = make_float_image(w, h);
00046 dir_ = make_float_image(w, h);
00047 this->init_variables();
00048 vcl_cout << "Do Initialization in " << t.real() << " msecs\n";
00049 }
00050
00051
00052
00053
00054
00055 brip_para_cvrg::brip_para_cvrg(float sigma, float thresh,
00056 float gauss_tail, int proj_width,
00057 int proj_height, int sup_radius,
00058 bool v) :
00059 brip_para_cvrg_params(sigma, thresh, gauss_tail, proj_width, proj_height,
00060 sup_radius, v)
00061 {
00062 this->init_variables();
00063 }
00064
00065 brip_para_cvrg::brip_para_cvrg(brip_para_cvrg_params& pdp) :
00066 brip_para_cvrg_params(pdp)
00067 {
00068 this->init_variables();
00069 }
00070
00071
00072
00073
00074
00075 brip_para_cvrg::~brip_para_cvrg()
00076 {
00077 vul_timer t;
00078 free_float_image(avg_);
00079 free_float_image(grad0_);
00080 free_float_image(grad45_);
00081 free_float_image(grad90_);
00082 free_float_image(grad135_);
00083 free_float_image(dir_);
00084 free_float_image(det_);
00085 delete [] proj_0_;
00086 delete [] proj_45_;
00087 delete [] proj_90_;
00088 delete [] proj_135_;
00089 delete [] sup_proj_;
00090
00091 vcl_cout << "Destruct in " << t.real() << " msecs\n";
00092 }
00093
00094
00095
00096
00097
00098
00099 float **brip_para_cvrg::make_float_image(int m, int n)
00100 {
00101 float *array = new float[m*n];
00102 float **data = new float* [m];
00103 for (int i =0; i < m; i++)
00104 {
00105 data[i] = &array[i*n];
00106 }
00107 return data;
00108 }
00109
00110
00111
00112
00113
00114
00115 void brip_para_cvrg::free_float_image(float **image)
00116 {
00117 float* array = image[0];
00118 delete [] array;
00119 delete [] image;
00120 }
00121
00122
00123
00124
00125
00126
00127 float *brip_para_cvrg::make_float_vector(int m)
00128 {
00129 float *tmp;
00130
00131 tmp = new float[m];
00132 if (tmp == NULL)
00133 {
00134 vcl_cout << "Can't allocate a " << m << " vector\n";
00135 vcl_exit(1);
00136 }
00137
00138 return tmp;
00139 }
00140
00141
00142
00143
00144
00145
00146 void brip_para_cvrg::set_float_image(float **image, float val)
00147 {
00148 int x, y;
00149 float* ptr = image[0];
00150
00151 for (y=0;y<image_.height();y++)
00152 ptr[y] = val;
00153
00154 for (x=1; x < image_.width();x++)
00155 {
00156 ptr = image[x];
00157 vcl_memcpy((char*)ptr, (char*)image[x-1], image_.height()*sizeof(float));
00158 }
00159 }
00160
00161
00162
00163
00164
00165
00166 void brip_para_cvrg::set_float_vector(float *vector, int n, float val)
00167 {
00168 int x;
00169 for (x = 0; x<n; x++)
00170 vector[x]=val;
00171 }
00172
00173
00174
00175
00176
00177
00178 void brip_para_cvrg::copy_image(float **image1, float **image2)
00179 {
00180 vcl_memcpy((char*)image2[0], (char*)image1[0],
00181 image_.width()* image_.height() * sizeof(float));
00182 #if 0 // was:
00183 for (int x=0;x<image_.width();++x)
00184 for (int y=0;y<image_.height();++y)
00185 image2[x][y] = image1[x][y];
00186 #endif // 0
00187 }
00188
00189
00190
00191
00192
00193
00194 void brip_para_cvrg::smooth_image()
00195 {
00196 vul_timer t;
00197 smooth_ = brip_vil1_float_ops::gaussian(image_, sigma_);
00198 vcl_cout << "Smooth image in " << t.real() << " msecs\n";
00199 }
00200
00201
00202
00203
00204 void brip_para_cvrg::avg(int x, int y, vil1_memory_image_of<float> const& smooth, float** avg)
00205 {
00206 float sum =0;
00207 for (int i = -3; i<=3; i++)
00208 for (int j = -3; j<=3; j++)
00209 {
00210 sum += smooth(x+i, y+j);
00211 }
00212
00213 avg[x][y] = sum/49.0f;
00214 }
00215
00216
00217
00218
00219 void brip_para_cvrg::grad0(int x, int y, vil1_memory_image_of<float> const& smooth, float** grad0)
00220 {
00221 float plus = 0.5f*smooth(x+1,y+3) + smooth(x+1,y+2) + smooth(x+1,y+1) +
00222 smooth(x+1,y) + smooth(x+1,y-1) + smooth(x+1,y-2)
00223 + 0.5f*smooth(x+1,y-3);
00224 float minus = 0.5f*smooth(x-1,y+3) + smooth(x-1,y+2) + smooth(x-1,y+1) +
00225 smooth(x-1,y) + smooth(x-1,y-1) + smooth(x-1,y-2) + 0.5f*smooth(x-1,y-3);
00226 grad0[x][y] = (plus-minus);
00227 }
00228
00229
00230
00231
00232 void brip_para_cvrg::grad45(int x, int y, vil1_memory_image_of<float> const& smooth, float** grad45)
00233 {
00234 float plus = smooth(x-2,y+3) + smooth(x-1,y+2) + smooth(x,y+1)
00235 + smooth(x+1,y) + smooth(x+2,y-1) + smooth(x+3,y-2);
00236 float minus = smooth(x-3,y+2) + smooth(x-2,y+1) + smooth(x-1,y)
00237 + smooth(x,y-1) + smooth(x+1,y-2) + smooth(x+2,y-3);
00238
00239 grad45[x][y] = 1.30f*(plus-minus);
00240 }
00241
00242
00243
00244
00245 void brip_para_cvrg::grad90(int x, int y, vil1_memory_image_of<float> const& smooth, float** grad90)
00246 {
00247 float plus = 0.5f*smooth(x+3,y+1) + smooth(x+2,y+1) + + smooth(x+1,y+1) +
00248 smooth(x,y+1) + smooth(x-1,y+1) + smooth(x-2,y+1) + 0.5f*smooth(x-3,y+1);
00249 float minus =0.5f*smooth(x+3,y-1) + smooth(x+2,y-1)+ smooth(x+1,y-1) +
00250 smooth(x,y-1) + smooth(x-1,y-1) + smooth(x-2,y-1) + 0.5f*smooth(x-3,y-1);
00251 grad90[x][y] = (plus-minus);
00252 }
00253
00254
00255
00256
00257 void brip_para_cvrg::grad135(int x, int y, vil1_memory_image_of<float> const& smooth, float** grad135)
00258 {
00259 float plus = smooth(x+3,y+2) + smooth(x+2,y+1) + smooth(x+1,y)
00260 + smooth(x,y-1) + smooth(x-1,y-2) + smooth(x-2,y-3);
00261 float minus = smooth(x+2,y+3) + smooth(x+1,y+2) + smooth(x,y+1)
00262 + smooth(x-1,y) + smooth(x-2,y-1) + smooth(x-3,y-2);
00263
00264 grad135[x][y] = 1.3f*(plus-minus);
00265 }
00266
00267
00268
00269
00270
00271
00272 void brip_para_cvrg::compute_gradients()
00273 {
00274 vul_timer t;
00275 int x,y;
00276 int radius = width_+3;
00277 set_float_image(grad0_,0.0);
00278 set_float_image(grad45_,0.0);
00279 set_float_image(grad90_,0.0);
00280 set_float_image(grad135_,0.0);
00281 for (y=radius;y<image_.height()-radius;y++)
00282 for (x=radius;x<image_.width()-radius;x++)
00283 {
00284 this->avg(x, y, smooth_, avg_);
00285 this->grad0(x, y, smooth_, grad0_);
00286 this->grad45(x, y, smooth_, grad45_);
00287 this->grad90(x, y, smooth_, grad90_);
00288 this->grad135(x, y, smooth_, grad135_);
00289 }
00290 vcl_cout << "Compute gradients in " << t.real() << " msecs\n";
00291 }
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 float brip_para_cvrg::project(int x, int y, int dir, float* projection)
00308 {
00309 int w,h;
00310 int w0 = proj_width_;
00311
00312 for (h=-proj_height_; h<=proj_height_; h++)
00313 for (w=-w0; w<=w0; w++)
00314 switch (dir)
00315 {
00316 case 0:
00317 projection[w+w0] += grad0_[x+w][y+h];
00318 break;
00319 case 45:
00320 projection[w+w0] += grad45_[x+h+w][y+w-h];
00321 break;
00322 case 90:
00323 projection[w+w0] += grad90_[x+h][y+w];
00324 break;
00325 case 135:
00326 projection[w+w0] += grad135_[x+h-w][y+w+h];
00327 break;
00328 default:
00329 projection[w+w0] += 0;
00330 break;
00331 }
00332 float max_energy = 0;
00333 for (int i =0; i<proj_n_; i++)
00334 {
00335 float val = vcl_fabs(projection[i]);
00336 if (val>max_energy)
00337 max_energy = val;
00338 }
00339 return max_energy;
00340 }
00341
00342
00343
00344
00345
00346
00347 void brip_para_cvrg::remove_flat_peaks(int n, float* array)
00348 {
00349 int nbm = n-1;
00350
00351
00352
00353 bool init= array[0]==0;
00354 int init_end =0;
00355
00356
00357 bool start=false;
00358 int start_index=0;
00359
00360
00361 for (int i = 0; i < n; i++)
00362 {
00363 float v = array[i];
00364
00365
00366 if (init&&v!=0)
00367 continue;
00368
00369 if (init&&v==0)
00370 {
00371 init_end = i;
00372 init = false;
00373 continue;
00374 }
00375
00376
00377 if (!start&&v==0)
00378 continue;
00379
00380
00381 if (!start&&v!=0)
00382 {
00383 start_index = i;
00384 start = true;
00385 continue;
00386 }
00387
00388 if (start&&v==0)
00389 {
00390 int peak_location = (start_index+i-1)/2;
00391 for (int k = start_index; k<=(i-1); k++)
00392 if (k!=peak_location)
00393 array[k] = 0;
00394 start = false;
00395 }
00396 }
00397
00398 if (init_end!=0)
00399 {
00400 int init_location = (init_end-1)/2;
00401 for (int k = 0; k<init_end; k++)
00402 if (k!=init_location)
00403 array[k] = 0;
00404 }
00405 if (start)
00406 {
00407 int end_location = (start_index + nbm)/2;
00408 for (int k = start_index; k<n; k++)
00409 if (k!=end_location)
00410 array[k] = 0;
00411 }
00412 }
00413
00414
00415
00416
00417 void brip_para_cvrg::non_maximum_supress(float* input_array, float* sup_array)
00418 {
00419 if ((2*sup_radius_ +1)> proj_width_)
00420 {
00421 vcl_cout << "In brip_para_cvrg::NonMaximumSupress(..) the kernel is too large\n";
00422 }
00423 float* tmp = this->make_float_vector(proj_n_);
00424 for (int i=0; i<proj_n_; i++)
00425 tmp[i]=vcl_fabs(input_array[i]);
00426
00427
00428
00429 for (int i = sup_radius_; i < (proj_n_-sup_radius_); i++)
00430 {
00431
00432 float max_val = 0;
00433 for (int k = -sup_radius_; k <= sup_radius_ ;k++)
00434 {
00435 int index = i+k;
00436 if (tmp[index] > max_val)
00437 max_val = tmp[index];
00438 }
00439
00440 if (vcl_fabs(max_val-tmp[i])<1e-03)
00441 sup_array[i] = max_val;
00442 }
00443 this->remove_flat_peaks(proj_n_, sup_array);
00444 }
00445
00446
00447
00448
00449
00450 float brip_para_cvrg::parallel_coverage(float* input_array)
00451 {
00452 this->set_float_vector(sup_proj_, proj_n_, 0.0);
00453 this->non_maximum_supress(input_array, sup_proj_);
00454 int n_peaks = 0;
00455 float proj_sum = 0;
00456 for (int i = 0; i<proj_n_; i++)
00457 if (sup_proj_[i]>0)
00458 {
00459 n_peaks++;
00460 proj_sum += sup_proj_[i];
00461 }
00462 if (n_peaks<2)
00463 return 0;
00464 return proj_sum/(n_peaks);
00465 }
00466
00467
00468
00469
00470 void brip_para_cvrg::compute_parallel_coverage()
00471 {
00472 vul_timer t;
00473
00474 this->set_float_image(det_,0.0);
00475 this->set_float_image(dir_,0.0);
00476 float direct;
00477 int radius = proj_width_+proj_height_ + 3;
00478 for (int y=radius; y<(image_.height()-radius);y++)
00479 for (int x=radius ;x<(image_.width()-radius);x++)
00480 {
00481 this->set_float_vector(proj_0_, proj_n_, 0.0);
00482 this->set_float_vector(proj_45_, proj_n_, 0.0);
00483 this->set_float_vector(proj_90_, proj_n_, 0.0);
00484 this->set_float_vector(proj_135_, proj_n_, 0.0);
00485
00486 float coverage[4];
00487 this->project(x, y, 0, proj_0_);
00488 coverage[0] = this->parallel_coverage(proj_0_);
00489 float max_coverage = coverage[0];
00490 direct = 0.f;
00491 this->project(x, y, 45, proj_45_);
00492 coverage[1] = this->parallel_coverage(proj_45_);
00493 if (coverage[1]>max_coverage)
00494 {
00495 max_coverage = coverage[1];
00496 direct = 45.f;
00497 }
00498 this->project(x, y, 90, proj_90_);
00499 coverage[2] = this->parallel_coverage(proj_90_);
00500 if (coverage[2]>max_coverage)
00501 {
00502 max_coverage = coverage[2];
00503 direct = 90.f;
00504 }
00505 this->project(x, y, 135, proj_135_);
00506 coverage[3] = this->parallel_coverage(proj_135_);
00507 if (coverage[3]>max_coverage)
00508 {
00509 max_coverage = coverage[3];
00510 direct = 135.f;
00511 }
00512 #ifdef DEBUG
00513 vcl_cout << '(' << x << ',' << y << ") coverage:\n"
00514 << " O degrees = " << coverage[0] << '\n'
00515 << " 45 degrees = " << coverage[1] << '\n'
00516 << " 90 degrees = " << coverage[2] << '\n'
00517 << " 135 degrees = " << coverage[3] << '\n'
00518 << "max_coverage = " << max_coverage << '\n';
00519 #endif
00520
00521 det_[x][y] = max_coverage;
00522 dir_[x][y] = direct;
00523 }
00524 vcl_cout << "Do parallel coverage in " << t.real() << " msecs\n";
00525 }
00526
00527
00528
00529
00530
00531 void brip_para_cvrg::compute_image(float** data, vil1_memory_image_of<unsigned char>& image)
00532 {
00533 image = vil1_memory_image_of<unsigned char>(xsize_, ysize_);
00534
00535 float max_val = 0;
00536 for (int y = 0; y<ysize_; y++)
00537 for (int x = 0; x<xsize_; x++)
00538 if (data[x][y]>max_val)
00539 max_val = data[x][y];
00540 if (max_val<1e-06)
00541 max_val = 1e-06f;
00542
00543 for (int y = 0; y<ysize_; y++)
00544 for (int x = 0; x<xsize_; x++)
00545 {
00546 float temp = 255*data[x][y]/max_val;
00547 unsigned char val;
00548 val = (unsigned char)temp;
00549 image(x, y)=val;
00550 }
00551 }
00552
00553
00554 void brip_para_cvrg::do_coverage(vil1_image const& image)
00555 {
00556 this->init(image);
00557 this->smooth_image();
00558 this->compute_gradients();
00559 this->compute_parallel_coverage();
00560 }
00561
00562
00563
00564
00565
00566 vil1_memory_image_of<float>
00567 brip_para_cvrg::get_float_detection_image(const float max)
00568 {
00569 vil1_memory_image_of<float> out(xsize_, ysize_);
00570 out.fill(0);
00571 float max_val = 0;
00572 for (int y = 0; y<ysize_; y++)
00573 for (int x = 0; x<xsize_; x++)
00574 if (det_[x][y]>max_val)
00575 max_val = det_[x][y];
00576
00577 if (max_val==0)
00578 return out;
00579 float s = max/max_val;
00580 for (int y = 0; y<ysize_; y++)
00581 for (int x = 0; x<xsize_; x++)
00582 out(x,y) = s*det_[x][y];
00583 return out;
00584 }
00585
00586
00587
00588
00589
00590 vil1_memory_image_of<unsigned char> brip_para_cvrg::get_detection_image()
00591 {
00592 if (!det_image_)
00593 this->compute_image(det_, det_image_);
00594 return det_image_;
00595 }
00596
00597
00598
00599
00600
00601 vil1_memory_image_of<unsigned char> brip_para_cvrg::get_dir_image()
00602 {
00603 if (!dir_image_)
00604 this->compute_image(dir_, dir_image_);
00605 return dir_image_;
00606 }
00607
00608
00609
00610
00611 vil1_memory_image_of<vil1_rgb<unsigned char> >
00612 brip_para_cvrg::get_combined_image()
00613 {
00614
00615 unsigned char r[4] ={0, 1, 0, 1};
00616 unsigned char g[4] ={1, 0, 1, 0};
00617 unsigned char b[4] ={1, 1, 0, 0};
00618 vil1_memory_image_of<unsigned char> cvrg_image = this->get_detection_image();
00619 vil1_memory_image_of<unsigned char> dir_image = this->get_dir_image();
00620 vil1_memory_image_of<vil1_rgb<unsigned char> > out(xsize_, ysize_);
00621 for (int y = 0; y<ysize_; y++)
00622 for (int x = 0; x<xsize_; x++)
00623 {
00624 unsigned int direct = ((unsigned int)dir_image(x,y))/45;
00625 assert (direct<=3);
00626 unsigned char c = cvrg_image(x,y),
00627 red = r[direct]*c,
00628 green= g[direct]*c,
00629 blue = b[direct]*c;
00630 out(x, y) = vil1_rgb<unsigned char>(red, green, blue);
00631 }
00632 return out;
00633 }