00001 #include <vcl_cstdlib.h>
00002 #include <vcl_cmath.h>
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
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
00069 vil_pyramid_image_resource_sptr pir =
00070 (vil_pyramid_image_resource*)((vil_image_resource*)image_.ptr());
00071
00072 image = pir->get_resource(0);
00073 }
00074 else
00075 image = image_;
00076
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
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
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
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
00144
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
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
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;
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
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
00277
00278
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
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
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
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
00325 unsigned nc = image_->nplanes();
00326 if (!(nc == 1 || nc == 3 || nc == 4))
00327 return false;
00328
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;
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;
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 }