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