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

bgui_image_utils.cxx

Go to the documentation of this file.
00001 #include <vcl_cstdlib.h> // for rand()
00002 #include <vcl_cmath.h> // for ceil()
00003 #include <vil/vil_new.h>
00004 #include <vil/vil_property.h>
00005 #include <vil/vil_pixel_traits.h>
00006 #include <vil/vil_blocked_image_resource.h>
00007 #include <vil/vil_pyramid_image_resource.h>
00008 #include <vgui/vgui_range_map_params.h>
00009 #include <bgui/bgui_image_utils.h>
00010 #include <vul/vul_timer.h>
00011 #include <vnl/vnl_numeric_traits.h>
00012 
00013 bgui_image_utils::bgui_image_utils():
00014   hist_valid_(false), percent_limit_(0.005), bin_limit_(1000),
00015   n_skip_upper_bins_(0), n_skip_lower_bins_(1), min_blocks_(20),
00016   scan_fraction_(0.1), image_(0)
00017 {
00018 }
00019 
00020 bgui_image_utils::bgui_image_utils(vil_image_resource_sptr const& image):
00021   hist_valid_(false), percent_limit_(0.005),
00022   bin_limit_(1000), n_skip_upper_bins_(0),
00023   n_skip_lower_bins_(1), min_blocks_(20),
00024   scan_fraction_(0.1), image_(image)
00025 {
00026   if (!image)
00027     return;
00028   unsigned np = image->nplanes();
00029   hist_.resize(np,bsta_histogram<double>(0.0,0.0,1));
00030   data_.resize(np);
00031 }
00032 
00033 void bgui_image_utils::set_image(vil_image_resource_sptr const& image)
00034 {
00035   if (!image)
00036   {
00037     image_ = 0;
00038     return;
00039   }
00040   image_ = image;
00041   unsigned np = image->nplanes();
00042   hist_.resize(np,bsta_histogram<double>(0.0,0.0,1));
00043   data_.resize(np);
00044   hist_valid_ = false;
00045 }
00046 
00047 
00048 void bgui_image_utils::range(double& min_value, double& max_value,
00049                              unsigned plane)
00050 {
00051   if (!hist_valid_)
00052     this->construct_histogram();
00053   min_value = this->compute_lower_bound(plane);
00054   max_value = this->compute_upper_bound(plane);
00055 }
00056 
00057 // fill the histogram by randomly sampling pixels from the image
00058 bool bgui_image_utils::init_histogram_from_data()
00059 {
00060   hist_valid_ = false;
00061   if (!image_)
00062     return false;
00063 
00064   vil_image_resource_sptr image;
00065   bool pyr = image_->get_property(vil_property_pyramid, 0);
00066   if (pyr)
00067   {
00068     //cast to pyramid resource
00069     vil_pyramid_image_resource_sptr pir =
00070       (vil_pyramid_image_resource*)((vil_image_resource*)image_.ptr());
00071     //highest resolution resource
00072     image = pir->get_resource(0);
00073   }
00074   else
00075     image = image_;
00076   // create a blocked image resource from image
00077   vil_blocked_image_resource_sptr bir = blocked_image_resource(image);
00078   if (!bir)
00079     bir = vil_new_blocked_image_facade(image);
00080 
00081   this->set_data_by_random_blocks(min_blocks_, bir, scan_fraction_);
00082 
00083   unsigned np = image_->nplanes();
00084 
00085   vil_pixel_format type = image_->pixel_format();
00086 
00087   if (np!=1&&np!=3&&np!=4)
00088   {
00089     vcl_cout << "Format not supported by bgui_image_utils\n";
00090     return false;
00091   }
00092   double min_val=0, max_val = 255;
00093   switch (type )
00094   {
00095    case  VIL_PIXEL_FORMAT_BYTE:
00096     for (unsigned p = 0; p<np; ++p) {
00097       hist_[p] = bsta_histogram<double>(min_val, max_val, 255);
00098       for (vcl_vector<double>::iterator dit = data_[p].begin();
00099            dit != data_[p].end(); dit++)
00100         hist_[p].upcount(*dit, 1.0);
00101     }
00102     return true;
00103    case  VIL_PIXEL_FORMAT_UINT_16:
00104    {
00105     min_val = static_cast<double>(vil_pixel_traits<unsigned short>::minval());
00106     max_val = static_cast<double>(vil_pixel_traits<unsigned short>::maxval());
00107 
00108     // determine the min and max range of image values
00109     vcl_vector<double> minr(np, max_val), maxr(np,min_val);
00110     for (unsigned p = 0; p<np; ++p) {
00111       for (vcl_vector<double>::iterator dit = data_[p].begin();
00112            dit != data_[p].end(); dit++)
00113       {
00114         if ((*dit)<minr[p]) minr[p] = *dit;
00115         if ((*dit)>maxr[p]) maxr[p] = *dit;
00116       }
00117       // determine if the number of bins exceess the limit
00118       unsigned short smin = static_cast<unsigned short>(minr[p]);
00119       unsigned short smax = static_cast<unsigned short>(maxr[p]);
00120       unsigned short nbins = smax-smin;
00121       if (nbins>bin_limit_) {
00122         nbins = bin_limit_;
00123         //increase max value to make bin delta an integer
00124         double range = smax-smin;
00125         unsigned short del = static_cast<unsigned short>(vcl_ceil(range/nbins));
00126         smax = smin + nbins*del;
00127       }
00128       hist_[p] = bsta_histogram<double>(static_cast<double>(smin),
00129                                         static_cast<double>(smax), nbins);
00130       for (vcl_vector<double>::iterator dit = data_[p].begin();
00131            dit != data_[p].end(); ++dit)
00132         hist_[p].upcount(*dit, 1.0);
00133     }
00134     return true;
00135    }
00136    default:
00137     vcl_cout << "Format not supported by bgui_image_utils\n";
00138     return false;
00139   }
00140   return false;
00141 }
00142 
00143 //Determine the pixel format of the view and cast to appropriate type
00144 //Upcount the histogram with values from the view.
00145 void bgui_image_utils::set_data_from_view(vil_image_view_base_sptr const& view,
00146                                           double fraction)
00147 {
00148   if (!view)
00149   {
00150     vcl_cout << "set histogram failed in bgui_image_utils\n";
00151     return;
00152   }
00153   vil_pixel_format type = view->pixel_format();
00154   unsigned fni = static_cast<unsigned>(view->ni()*fraction);
00155   unsigned fnj = static_cast<unsigned>(view->nj()*fraction);
00156   unsigned np = view->nplanes();
00157   switch (type )
00158   {
00159    case  VIL_PIXEL_FORMAT_BYTE:
00160    {
00161     vil_image_view<unsigned char> v = view;
00162     for (unsigned p = 0; p<np; ++p)
00163       for (unsigned j = 0; j<fnj; ++j)
00164         for (unsigned i = 0; i<fni; ++i)
00165         {
00166           double val = static_cast<double>(v(i,j,p));
00167           data_[p].push_back(val);
00168         }
00169     return;
00170    }
00171    case  VIL_PIXEL_FORMAT_UINT_16:
00172    {
00173     vil_image_view<unsigned short> v = view;
00174     for (unsigned p = 0; p<np; ++p)
00175       for (unsigned j = 0; j<fnj; ++j)
00176         for (unsigned i = 0; i<fni; ++i)
00177         {
00178           double val = static_cast<double>(v(i,j,p));
00179           data_[p].push_back(val);
00180         }
00181     return;
00182    }
00183    default:
00184     vcl_cout << "Format not supported by bgui_image_utils\n";
00185   }
00186 }
00187 
00188 void bgui_image_utils::
00189 set_data_by_random_blocks(const unsigned total_num_blocks,
00190                           vil_blocked_image_resource_sptr const& bir,
00191                           double fraction)
00192 {
00193   unsigned nbi = bir->n_block_i(), nbj = bir->n_block_j();
00194   for (unsigned ib = 0; ib<total_num_blocks; ++ib)
00195   {
00196     unsigned bi = static_cast<unsigned>((nbi-1)*(vcl_rand()/(RAND_MAX+1.0)));
00197     unsigned bj = static_cast<unsigned>((nbj-1)*(vcl_rand()/(RAND_MAX+1.0)));
00198     this->set_data_from_view(bir->get_block(bi, bj), fraction);
00199   }
00200 }
00201 
00202 bool bgui_image_utils::construct_histogram()
00203 {
00204   vul_timer t;
00205   if (!this->init_histogram_from_data())
00206   {
00207     vcl_cout << "Unable to construct histogram in bgui_image_utils\n";
00208     return false;
00209   }
00210   unsigned  np = image_->nplanes();
00211   //zero out the bins of the histogram according to the skip parameters
00212   for (unsigned p = 0; p<np; ++p)
00213     for (unsigned s = 0; s<n_skip_lower_bins_; ++s)
00214       hist_[p].set_count(s, 0.0);
00215 
00216   unsigned last_bin = hist_[0].nbins()-1;
00217   for (unsigned p = 0; p<np; ++p)
00218     for (unsigned s =last_bin; s>last_bin-n_skip_upper_bins_; s--)
00219       hist_[p].set_count(s, 0.0);
00220 
00221   vcl_cout << "computed histogram on " << np*data_[0].size()
00222            << " pixels in " << t.real() << " milliseconds\n";
00223   hist_valid_ = true;
00224   return true;
00225 }
00226 
00227 double bgui_image_utils::compute_lower_bound( unsigned plane )
00228 {
00229   if (plane >= hist_.size())
00230     return 0;
00231   return hist_[plane].value_with_area_below(percent_limit_);
00232 }
00233 
00234 double bgui_image_utils::compute_upper_bound( unsigned plane )
00235 {
00236   if (plane >= hist_.size())
00237     return 0;
00238   return hist_[plane].value_with_area_above(percent_limit_);
00239 }
00240 
00241 //generate a graph tableau from the histogram
00242 bgui_graph_tableau_sptr bgui_image_utils::hist_graph()
00243 {
00244   unsigned n_planes = image_->nplanes();
00245 
00246   if (!image_ || n_planes>4)
00247     return 0;
00248 
00249   if (!hist_valid_)
00250     if (!this->construct_histogram())
00251       return 0;
00252 
00253   bgui_graph_tableau_sptr g = bgui_graph_tableau_new(512, 512);
00254 
00255   if (n_planes ==1)
00256   {
00257     unsigned lowbin =hist_[0].low_bin(), highbin = hist_[0].high_bin();
00258     if (lowbin>highbin) return 0; //shouldn't happen
00259     vcl_vector<double> pos = hist_[0].value_array();
00260     vcl_vector<double> counts = hist_[0].count_array();
00261     vcl_vector<double> trim_pos, trim_counts;
00262     //make sure the lowest sample starts at a multiple of 10
00263     double p0 = pos[lowbin];
00264     double pten = 10.0*static_cast<int>(p0/10);
00265     trim_pos.push_back(pten);
00266     trim_counts.push_back(0.0);
00267     for (unsigned b = lowbin; b<=highbin; ++b)
00268     {
00269       trim_pos.push_back(static_cast<unsigned>(pos[b]));
00270       trim_counts.push_back(counts[b]);
00271     }
00272     g->update(trim_pos, trim_counts);
00273     return g;
00274   }
00275 
00276   //In order to create a multiplot for a color histogram
00277   //all the plots have to have the same integral bin locations
00278   //get the max min range of bin values
00279   double minpos = vnl_numeric_traits<double>::maxval, maxpos = 0;
00280   double min_delta = vnl_numeric_traits<double>::maxval;
00281   for (unsigned p = 0; p<n_planes; ++p)
00282   {
00283     unsigned lbin = hist_[p].low_bin(), hbin = hist_[p].high_bin();
00284     vcl_vector<double> pos = hist_[p].value_array();
00285     if (pos[lbin]<minpos) minpos = pos[lbin];
00286     if (pos[hbin]>maxpos) maxpos = pos[hbin];
00287     double delta = hist_[p].delta();
00288     if (delta<min_delta) min_delta = delta;
00289   }
00290 
00291   // start at a multiple of 10
00292   double min_ten = 10.0*static_cast<int>(minpos/10);
00293   double max_ten = 10.0*(static_cast<int>(maxpos/10)+1);
00294   double range = max_ten-min_ten;
00295 
00296   //Insure at least a bin width of 1.0
00297   double delta_i = static_cast<int>(min_delta);
00298   if (delta_i==0) delta_i += 1.0;
00299   unsigned npos = static_cast<unsigned>(range/delta_i);
00300   // set  up the integral positions
00301   vcl_vector<double> dpos(npos);
00302   for (unsigned i = 0; i<npos; ++i)
00303     dpos[i] = i*delta_i;
00304 
00305   vcl_vector<vcl_vector<double> > mpos(n_planes, dpos);
00306 
00307   vcl_vector<vcl_vector<double> > mcounts(n_planes);
00308   for (unsigned p = 0; p<n_planes; ++p)
00309   {
00310     double area = hist_[p].area();
00311     for (unsigned i = 0; i<npos; ++i){
00312       double v = area*hist_[p].p(dpos[i]);
00313       mcounts[p].push_back(v);
00314     }
00315   }
00316   g->update(mpos, mcounts);
00317 
00318   return g;
00319 }
00320 
00321 bool bgui_image_utils::default_range_map(vgui_range_map_params_sptr& rmp)
00322 {
00323   if (!image_) return false;
00324   //Allow only grey scale for now
00325   unsigned nc = image_->nplanes();
00326   if (!(nc == 1 || nc == 3 || nc == 4))
00327     return false; //all available formats
00328   //default values
00329   double gamma = 1.0;
00330   bool invert = false;
00331   bool gl_map = true;
00332   bool cache = true;
00333   static double minv = 0, maxv = 1500; //typical for uint_16
00334   if (image_->pixel_format()==VIL_PIXEL_FORMAT_BYTE)
00335     maxv = 255;
00336   switch (nc)
00337   {
00338     case 1:
00339       rmp=new vgui_range_map_params(minv, maxv, gamma, invert, gl_map, cache);
00340       break;
00341     case 3:
00342       rmp = new vgui_range_map_params(minv, maxv, minv, maxv, minv, maxv,
00343                                       gamma, gamma, gamma, invert,
00344                                       gl_map, cache);
00345       break;
00346     case 4:
00347     {
00348       int band_map = 1; //map RGB-InfraRed -> RGB
00349       rmp = new vgui_range_map_params(minv, maxv, minv, maxv, minv, maxv,
00350                                       minv, maxv, gamma, gamma, gamma, gamma,
00351                                       band_map, invert, gl_map, cache);
00352       break;
00353     }
00354   }
00355   return true;
00356 }
00357 
00358 bool bgui_image_utils::range_map_from_hist(float gamma, bool invert,
00359                                            bool gl_map, bool cache,
00360                                            vgui_range_map_params_sptr& rmp)
00361 {
00362   rmp = 0;
00363   if (!image_)
00364     return false;
00365 
00366   unsigned np = image_->nplanes();
00367   vcl_vector<double> minr(np, 0.0), maxr(np, 0.0);
00368 
00369   for (unsigned p = 0; p<np; ++p)
00370     this->range(minr[p], maxr[p], p);
00371 
00372   if (np == 1)
00373   {
00374     rmp= new vgui_range_map_params(minr[0], maxr[0], gamma, invert,
00375                                    gl_map, cache);
00376     return true;
00377   }
00378   else if (np == 3)
00379   {
00380     rmp = new vgui_range_map_params(minr[0], maxr[0], minr[1], maxr[1],
00381                                     minr[2], maxr[2],
00382                                     gamma, gamma, gamma, invert,
00383                                     gl_map, cache);
00384     return true;
00385   }
00386   else if (np == 4)
00387   {
00388     int bm = vgui_range_map_params::RGB_m;
00389     rmp = new vgui_range_map_params(minr[0], maxr[0], minr[1], maxr[1],
00390                                     minr[2], maxr[2], minr[3], maxr[3],
00391                                     gamma, gamma, gamma, gamma, bm, invert,
00392                                     gl_map, cache);
00393     return true;
00394   }
00395   else
00396     return false;
00397 }

Generated on Thu Jan 10 14:52:11 2008 for contrib/brl/bbas/bgui by  doxygen 1.4.4