Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

brip_para_cvrg.cxx

Go to the documentation of this file.
00001 //:
00002 // \file
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 //: Variable Initialization
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 //:  Image Initialization
00026 void brip_para_cvrg::init(vil1_image const & image)
00027 {
00028   vul_timer t;
00029   //we don't have roi capability so just use the whole image for now
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 //: Constructor s
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 //: Destructor.
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 //: Returns an m*n array of floats.  Private.
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 //: Frees an m*n array of floats.  Private.
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 //: Returns a vector of floats length m.  Private.
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 //: Sets a floating point image to val.  Private.
00145 //
00146 void brip_para_cvrg::set_float_image(float **image, float val)
00147 {
00148   int x, y;
00149   float* ptr = image[0];
00150   // copy first col
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 //: Sets a floating point image to val.  Private.
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 //: Copies float image1 to image2.  Private.
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 //: Convolves the image with the smoothing kernel.  Private.
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 //: Compute the average value in the 7x7 window
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 //: Compute a gradient operator at x,y along the x axis
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 //: Compute a gradient operator at x,y at 45 degrees
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 //: Compute a gradient operator at x,y at 90 degrees
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 //: Compute a gradient operator at x,y at 135 degrees
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 //: Convolves with the kernel in the x direction, to compute the local derivative in that direction.  Private.
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 //: Project the gradient magnitude along a given direction.
00296 //  The result is a 1-d projection plot.
00297 //  \verbatim
00298 //                     .
00299 //                    *  .
00300 //                   ^  *  .
00301 //                 /   ^  *  .
00302 //                  \    ^  *  .
00303 //                         ^  *  \ .
00304 //   2*proj_width_+1   x     ^  x-----2*proj_height_+1
00305 //                        \ / \ .
00306 // \endverbatim
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 //float energy = 0.0;
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 //: Prune any sequences of more than one maximum value.
00344 //That is, it is possible to have a "flat" top peak with an arbitrarily
00345 //long sequence of equal, but maximum values.
00346 //
00347 void brip_para_cvrg::remove_flat_peaks(int n, float* array)
00348 {
00349   int nbm = n-1;
00350 
00351   //Here we define a small state machine - parsing for runs of peaks
00352   //init is the state corresponding to an initial run (starting at i ==0)
00353   bool init= array[0]==0;
00354   int init_end =0;
00355 
00356   //start is the state corresponding to any other run of peaks
00357   bool start=false;
00358   int start_index=0;
00359 
00360   //The scan of the state machine
00361   for (int i = 0; i < n; i++)
00362   {
00363     float v = array[i];
00364 
00365     //State init: a string of non-zeroes at the beginning.
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     //State !init&&!start: a string of "0s"
00377     if (!start&&v==0)
00378       continue;
00379 
00380     //State !init&&start: the first non-zero value
00381     if (!start&&v!=0)
00382     {
00383       start_index = i;
00384       start = true;
00385       continue;
00386     }
00387     //State ending flat peak: encountered a subsequent zero after starting
00388     if (start&&v==0)
00389     {
00390       int peak_location = (start_index+i-1)/2;//The middle of the run
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   //Now handle the boundary conditions
00398   if (init_end!=0)  //Was there an initial run of peaks?
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)       // Did we reach the end of the array in a run of pks?
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 //: Find locally maximum peaks in the input array
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   //Get the counts array of "this"
00427   //Make a new Histogram for the suppressed
00428 
00429   for (int i = sup_radius_; i < (proj_n_-sup_radius_); i++)
00430   {
00431     //find the maximum value in the current kernel
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     //Is position i a local maximum?
00440     if (vcl_fabs(max_val-tmp[i])<1e-03)
00441      sup_array[i] = max_val; //Yes. So set the counts to the max value
00442   }
00443   this->remove_flat_peaks(proj_n_, sup_array);
00444 }
00445 
00446 
00447 //---------------------------------------------------------------
00448 //: Find the amount of overlapping parallel coverage
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 //: Find the direction with maximum parallel coverage.  Return the normalized coverage value.
00470 void brip_para_cvrg::compute_parallel_coverage()
00471 {
00472   vul_timer t;
00473 //float min_sum = .01f;
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 //: Compute a 8-bit image from the projected gradients
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    //find the maximum value
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   //Normalize the data and load the image
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 //: Get the float image of detections. Scale onto [0, max]
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 //: Get the unsigned char image of detections
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 //: Get the direction image (unsigned char)
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 //: Get the combination of coverage and direction as a color image
00610 //
00611 vil1_memory_image_of<vil1_rgb<unsigned char> >
00612 brip_para_cvrg::get_combined_image()
00613 {
00614   //"arbitrary" color assignments to the 4 directions: cyan,yellow,green,red:
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 }

Generated on Thu Jan 10 14:52:30 2008 for contrib/brl/bseg/brip by  doxygen 1.4.4