00001
00002 #ifndef bmdl_classify_txx_
00003 #define bmdl_classify_txx_
00004
00005
00006
00007
00008
00009
00010
00011 #include "bmdl_classify.h"
00012 #include <vcl_limits.h>
00013 #include <vnl/vnl_math.h>
00014 #include <vcl_algorithm.h>
00015 #include <vcl_utility.h>
00016 #include <vcl_set.h>
00017 #include <vcl_map.h>
00018 #include <vcl_cassert.h>
00019
00020 #include <vil/algo/vil_binary_dilate.h>
00021 #include <vil/algo/vil_binary_erode.h>
00022 #include <vgl/vgl_box_2d.h>
00023 #include <vgl/vgl_point_2d.h>
00024
00025
00026
00027
00028
00029
00030
00031
00032 template <class T>
00033 bmdl_classify<T>::bmdl_classify(unsigned int area_threshold,
00034 T height_resolution,
00035 T gnd_threshold,
00036 T veg_threshold)
00037 : hgt_stdev_(T(0.01)),
00038 area_threshold_(area_threshold),
00039 height_resolution_(height_resolution),
00040 gnd_threshold_(gnd_threshold),
00041 veg_threshold_(veg_threshold),
00042 first_min_( vcl_numeric_limits<T>::infinity()),
00043 first_max_(-vcl_numeric_limits<T>::infinity()),
00044 last_min_ ( vcl_numeric_limits<T>::infinity()),
00045 last_max_ (-vcl_numeric_limits<T>::infinity())
00046 {
00047 }
00048
00049
00050
00051 template <class T>
00052 void bmdl_classify<T>::set_lidar_data(const vil_image_view<T>& first_return,
00053 const vil_image_view<T>& last_return)
00054 {
00055 assert(first_return.ni() == last_return.ni());
00056 assert(first_return.nj() == last_return.nj());
00057 first_return_ = first_return;
00058 last_return_ = last_return;
00059
00060
00061 bmdl_classify::range(first_return_,first_min_,first_max_);
00062 bmdl_classify::range(last_return_,last_min_,last_max_);
00063 }
00064
00065
00066
00067 template <class T>
00068 void bmdl_classify<T>::set_bare_earth(const vil_image_view<T>& bare_earth)
00069 {
00070 assert(first_return_.ni() == bare_earth.ni());
00071 assert(first_return_.nj() == bare_earth.nj());
00072 bare_earth_ = bare_earth;
00073 }
00074
00075
00076
00077
00078
00079 template <class T>
00080 T bmdl_classify<T>::estimate_bare_earth()
00081 {
00082 vcl_vector<T> data;
00083 unsigned int ni = last_return_.ni();
00084 unsigned int nj = last_return_.nj();
00085
00086 for (unsigned int j=0; j<nj; ++j) {
00087 for (unsigned int i=0; i<ni; ++i) {
00088 if (vnl_math_isfinite(last_return_(i,j))) {
00089 data.push_back(last_return_(i,j));
00090 }
00091 }
00092 }
00093
00094 T mean = 0.0;
00095 T gnd_stdev = 0.0;
00096 fit_gaussian_to_peak(data,last_min_,last_max_,mean,gnd_stdev);
00097
00098 bare_earth_.set_size(ni,nj);
00099 bare_earth_.fill(mean);
00100
00101 return mean;
00102 }
00103
00104
00105
00106
00107 template <class T>
00108 T bmdl_classify<T>::estimate_height_noise_stdev()
00109 {
00110
00111
00112
00113 unsigned int ni = first_return_.ni();
00114 unsigned int nj = first_return_.nj();
00115
00116 assert(ni>0 && nj>0);
00117 assert(last_return_.ni() == ni);
00118 assert(last_return_.nj() == nj);
00119
00120 vcl_vector<T> diff;
00121 for (unsigned int j=0; j<nj; ++j) {
00122 for (unsigned int i=0; i<ni; ++i) {
00123 if (!vnl_math_isfinite(last_return_(i,j)) || !vnl_math_isfinite(first_return_(i,j)))
00124 continue;
00125 diff.push_back(first_return_(i,j) - last_return_(i,j));
00126 }
00127 }
00128 vcl_sort(diff.begin(),diff.end());
00129
00130 T max_diff = diff[int(diff.size()*.95)];
00131
00132 if (max_diff == 0.0)
00133 vcl_cout << "Warning: first and last return images are identical" << vcl_endl;
00134
00135 T mean = 0.0;
00136 fit_gaussian_to_peak(diff,0,max_diff,mean,hgt_stdev_);
00137
00138 vcl_cout << "diff mean = "<< mean << " stdev = "<< hgt_stdev_ << vcl_endl;
00139 return hgt_stdev_;
00140 }
00141
00142
00143
00144
00145
00146 template <class T>
00147 void bmdl_classify<T>::label_lidar()
00148 {
00149 unsigned int ni = first_return_.ni();
00150 unsigned int nj = first_return_.nj();
00151
00152 assert(ni>0 && nj>0);
00153 assert(last_return_.ni() == ni);
00154 assert(last_return_.nj() == nj);
00155 assert(bare_earth_.ni() == ni);
00156 assert(bare_earth_.nj() == nj);
00157 assert(hgt_stdev_ > 0.0);
00158
00159
00160 segment();
00161
00162
00163 cluster_buildings();
00164
00165
00166 while (greedy_merge())
00167 ;
00168
00169
00170 fill_ground_holes(5);
00171
00172
00173 while (dilate_buildings(5))
00174 ;
00175
00176
00177 threshold_building_area();
00178
00179
00180 while (dilate_buildings(5))
00181 ;
00182
00183
00184 while (greedy_merge())
00185 ;
00186
00187
00188 refine_buildings();
00189
00190
00191 heights_.set_size(ni,nj);
00192 for (unsigned int j=0; j<nj; ++j) {
00193 for (unsigned int i=0; i<ni; ++i) {
00194 if (labels_(i,j) > 1)
00195 heights_(i,j) = building_mean_hgt_[labels_(i,j)-2];
00196 else if (labels_(i,j) == 1)
00197 heights_(i,j) = first_return_(i,j);
00198 else
00199 heights_(i,j) = bare_earth_(i,j);
00200 }
00201 }
00202 }
00203
00204
00205
00206
00207
00208 template <class T>
00209 void bmdl_classify<T>::segment()
00210 {
00211 unsigned int ni = first_return_.ni();
00212 unsigned int nj = first_return_.nj();
00213
00214 assert(ni>0 && nj>0);
00215 assert(last_return_.ni() == ni);
00216 assert(last_return_.nj() == nj);
00217 assert(bare_earth_.ni() == ni);
00218 assert(bare_earth_.nj() == nj);
00219 assert(hgt_stdev_ > 0.0);
00220
00221
00222 labels_.set_size(ni,nj);
00223
00224 for (unsigned int j=0; j<nj; ++j) {
00225 for (unsigned int i=0; i<ni; ++i) {
00226
00227 if (!vnl_math_isfinite(first_return_(i,j)) ||
00228 first_return_(i,j) - bare_earth_(i,j) < gnd_threshold_)
00229 labels_(i,j) = 0;
00230
00231 else if ((first_return_(i,j) - last_return_(i,j)) > veg_threshold_)
00232 labels_(i,j) = 1;
00233
00234 else
00235 labels_(i,j) = 2;
00236 }
00237 }
00238 }
00239
00240
00241
00242
00243
00244 template <class T>
00245 void bmdl_classify<T>::cluster_buildings()
00246 {
00247 unsigned int ni=first_return_.ni();
00248 unsigned int nj=first_return_.nj();
00249
00250 assert(ni>0 && nj>0);
00251 assert(last_return_.ni() == ni);
00252 assert(last_return_.nj() == nj);
00253 assert(labels_.ni() == ni);
00254 assert(labels_.nj() == nj);
00255 assert(hgt_stdev_ > 0.0);
00256
00257 building_mean_hgt_.clear();
00258 building_area_.clear();
00259
00260
00261 vil_image_view<unsigned int> bin_img = bin_heights(height_resolution_);
00262
00263 vcl_vector<unsigned int> merge_map;
00264 vcl_vector<unsigned int> count;
00265 vcl_vector<T> mean;
00266
00267
00268 if (labels_(0,0) >= 2)
00269 {
00270 count.push_back(1);
00271 merge_map.push_back(merge_map.size());
00272 mean.push_back(last_return_(0,0));
00273 labels_(0,0) = count.size()+1;
00274 }
00275
00276 for (unsigned int i=1; i<ni; ++i) {
00277 if (labels_(i,0)!=2)
00278 continue;
00279
00280 int idx = labels_(i-1,0)-2;
00281 while (idx>=0 && merge_map[idx] != (unsigned int)idx )
00282 idx = merge_map[idx];
00283 T val = last_return_(i,0);
00284 if (idx>=0 && bin_img(i-1,0) == bin_img(i,0)) {
00285 labels_(i,0) = idx+2;
00286 mean[idx] = (mean[idx]*count[idx] + val)/(count[idx]+1);
00287 ++count[idx];
00288 }
00289 else{
00290 count.push_back(1);
00291 merge_map.push_back(merge_map.size());
00292 mean.push_back(val);
00293 labels_(i,0) = count.size()+1;
00294 }
00295 }
00296
00297 for (unsigned int j=1; j<nj; ++j) {
00298 if (labels_(0,j)!=2)
00299 continue;
00300
00301 int idx = labels_(0,j-1)-2;
00302 while (idx>=0 && merge_map[idx] != (unsigned int)idx )
00303 idx = merge_map[idx];
00304 T val = last_return_(0,j);
00305 if (idx>=0 && bin_img(0,j-1) == bin_img(0,j)) {
00306 labels_(0,j) = idx+2;
00307 mean[idx] = (mean[idx]*count[idx] + val)/(count[idx]+1);
00308 ++count[idx];
00309 }
00310 else {
00311 count.push_back(1);
00312 merge_map.push_back(merge_map.size());
00313 mean.push_back(val);
00314 labels_(0,j) = count.size()+1;
00315 }
00316 }
00317
00318
00319 for (unsigned int j=1; j<nj; ++j)
00320 {
00321 for (unsigned int i=1; i<ni; ++i)
00322 {
00323 if (labels_(i,j)!=2)
00324 continue;
00325
00326 T val = last_return_(i,j);
00327 int idx1 = labels_(i-1,j)-2, idx2 = labels_(i,j-1)-2;
00328 while (idx1>=0 && merge_map[idx1] != (unsigned int)idx1 )
00329 idx1 = merge_map[idx1];
00330 while (idx2>=0 && merge_map[idx2] != (unsigned int)idx2 )
00331 idx2 = merge_map[idx2];
00332 int idx = -1;
00333 if (idx1>=0 && (bin_img(i-1,j) == bin_img(i,j)) )
00334 idx = idx1;
00335 if (idx2>=0 && (bin_img(i,j-1) == bin_img(i,j)) )
00336 {
00337 if (idx == -1 || idx1 == idx2)
00338 idx = idx2;
00339 else {
00340 labels_(i,j) = idx1+2;
00341 mean[idx1] = (mean[idx1]*count[idx1] + mean[idx2]*count[idx2] + val)
00342 /(count[idx1]+count[idx2]+1);
00343 count[idx1] += count[idx2]+1;
00344 count[idx2] = 0;
00345 merge_map[idx2] = idx1;
00346 continue;
00347 }
00348 }
00349
00350 if (idx >= 0 ) {
00351 labels_(i,j) = idx+2;
00352 mean[idx] = (mean[idx]*count[idx] + val)/(count[idx]+1);
00353 ++count[idx];
00354 }
00355 else {
00356 count.push_back(1);
00357 merge_map.push_back(merge_map.size());
00358 mean.push_back(val);
00359 labels_(i,j) = count.size()+1;
00360 }
00361 }
00362 }
00363 vcl_cout << "num labels = "<<count.size() << vcl_endl;
00364
00365
00366 vcl_vector<vcl_pair<T,int> > unique;
00367 for (unsigned int i=0; i<merge_map.size(); ++i)
00368 {
00369 if (merge_map[i] == i) {
00370 unique.push_back(vcl_pair<T,int>(mean[i],i));
00371 continue;
00372 }
00373 unsigned int i2 = i;
00374 while (merge_map[i2] != i2 )
00375 merge_map[i] = i2 = merge_map[i2];
00376 }
00377 vcl_sort(unique.begin(), unique.end());
00378
00379 building_mean_hgt_.resize(unique.size(),0.0);
00380 building_area_.resize(unique.size(),0);
00381
00382 vcl_vector<unsigned int> unique_map(merge_map.size(),0);
00383 for (unsigned int i=0; i<unique.size(); ++i) {
00384 unique_map[unique[i].second] = i;
00385 building_mean_hgt_[i] = unique[i].first;
00386 building_area_[i] = count[unique[i].second];
00387 }
00388 for (unsigned int i=0; i<unique_map.size(); ++i)
00389 if (merge_map[i] != i)
00390 unique_map[i] = unique_map[merge_map[i]];
00391
00392 for (unsigned int j=0; j<nj; ++j) {
00393 for (unsigned int i=0; i<ni; ++i) {
00394 if (labels_(i,j)>=2)
00395 labels_(i,j) = unique_map[labels_(i,j)-2]+2;
00396 }
00397 }
00398
00399 vcl_cout << "After clustering there are "
00400 <<building_area_.size()<<" buildings" << vcl_endl;
00401 }
00402
00403
00404
00405
00406 template <class T>
00407 void bmdl_classify<T>::fill_ground_holes(unsigned int min_size)
00408 {
00409 unsigned int ni = labels_.ni();
00410 unsigned int nj = labels_.nj();
00411
00412 vil_image_view<unsigned int> labels(ni,nj);
00413 for (unsigned int j=0; j<nj; ++j) {
00414 for (unsigned int i=0; i<ni; ++i) {
00415 if (labels_(i,j)>0)
00416 labels(i,j) = 0;
00417 else
00418 labels(i,j) = 1;
00419 }
00420 }
00421
00422 vcl_vector<unsigned int> merge_map;
00423 vcl_vector<unsigned int> count;
00424
00425
00426 if (labels(0,0) > 0)
00427 {
00428 count.push_back(1);
00429 merge_map.push_back(merge_map.size());
00430 labels(0,0) = count.size();
00431 }
00432
00433 for (unsigned int i=1; i<ni; ++i) {
00434 if (labels(i,0)!=1)
00435 continue;
00436
00437 int idx = labels(i-1,0)-1;
00438 while (idx>=0 && merge_map[idx] != (unsigned int)idx )
00439 idx = merge_map[idx];
00440 if (idx>=0) {
00441 labels(i,0) = idx+1;
00442 ++count[idx];
00443 }
00444 else{
00445 count.push_back(1);
00446 merge_map.push_back(merge_map.size());
00447 labels(i,0) = count.size();
00448 }
00449 }
00450
00451 for (unsigned int j=1; j<nj; ++j) {
00452 if (labels(0,j)!=1)
00453 continue;
00454
00455 int idx = labels(0,j-1)-1;
00456 while (idx>=0 && merge_map[idx] != (unsigned int)idx )
00457 idx = merge_map[idx];
00458 if (idx>=0) {
00459 labels(0,j) = idx+1;
00460 ++count[idx];
00461 }
00462 else {
00463 count.push_back(1);
00464 merge_map.push_back(merge_map.size());
00465 labels(0,j) = count.size();
00466 }
00467 }
00468
00469
00470 for (unsigned int j=1; j<nj; ++j)
00471 {
00472 for (unsigned int i=1; i<ni; ++i)
00473 {
00474 if (labels(i,j)!=1)
00475 continue;
00476
00477 int idx1 = labels(i-1,j)-1, idx2 = labels(i,j-1)-1;
00478 while (idx1>=0 && merge_map[idx1] != (unsigned int)idx1 )
00479 idx1 = merge_map[idx1];
00480 while (idx2>=0 && merge_map[idx2] != (unsigned int)idx2 )
00481 idx2 = merge_map[idx2];
00482 int idx = -1;
00483 if (idx1>=0)
00484 idx = idx1;
00485 if (idx2>=0)
00486 {
00487 if (idx == -1 || idx1 == idx2)
00488 idx = idx2;
00489 else {
00490 labels(i,j) = idx1+1;
00491 count[idx1] += count[idx2]+1;
00492 count[idx2] = 0;
00493 merge_map[idx2] = idx1;
00494 continue;
00495 }
00496 }
00497
00498 if (idx >= 0 ) {
00499 labels(i,j) = idx+1;
00500 ++count[idx];
00501 }
00502 else {
00503 count.push_back(1);
00504 merge_map.push_back(merge_map.size());
00505 labels(i,j) = count.size();
00506 }
00507 }
00508 }
00509 vcl_cout << "num ground labels = "<<count.size() << vcl_endl;
00510
00511
00512 for (unsigned int j=0; j<nj; ++j) {
00513 for (unsigned int i=0; i<ni; ++i) {
00514 if (labels(i,j)==0)
00515 continue;
00516
00517 int idx = labels(i,j)-1;
00518 while (idx>=0 && merge_map[idx] != (unsigned int)idx )
00519 idx = merge_map[idx];
00520 if (count[idx] <= min_size){
00521 labels_(i,j) = 1;
00522 }
00523 }
00524 }
00525 }
00526
00527
00528
00529
00530
00531 template <class T>
00532 void bmdl_classify<T>::threshold_building_area()
00533 {
00534 vcl_vector<T> new_means;
00535 vcl_vector<unsigned int> new_areas;
00536 vcl_vector<unsigned int> label_map(building_area_.size(),1);
00537
00538 for (unsigned int i=0; i<building_area_.size(); ++i){
00539 if (building_area_[i] >= area_threshold_)
00540 {
00541 label_map[i] = new_areas.size()+2;
00542 new_means.push_back(building_mean_hgt_[i]);
00543 new_areas.push_back(building_area_[i]);
00544 }
00545 }
00546
00547
00548 unsigned int ni = labels_.ni();
00549 unsigned int nj = labels_.nj();
00550 for (unsigned int j=0; j<nj; ++j) {
00551 for (unsigned int i=0; i<ni; ++i) {
00552 if (labels_(i,j)>=2)
00553 labels_(i,j) = label_map[labels_(i,j)-2];
00554 }
00555 }
00556 building_area_.swap(new_areas);
00557 building_mean_hgt_.swap(new_means);
00558
00559 vcl_cout << "After thresholding by area there are "
00560 <<building_area_.size()<<" buildings" << vcl_endl;
00561 }
00562
00563
00564
00565 template <class T>
00566 void bmdl_classify<T>::refine_buildings()
00567 {
00568
00569 assert(first_return_.ni() > 0);
00570 assert(first_return_.nj() > 0);
00571 assert(last_return_.ni() == first_return_.ni());
00572 assert(last_return_.nj() == first_return_.nj());
00573 assert(labels_.ni() == first_return_.ni());
00574 assert(labels_.nj() == first_return_.nj());
00575 assert(hgt_stdev_ > 0.0);
00576
00577 expand_buildings(building_mean_hgt_, building_area_);
00578
00579
00580
00581 #if 0
00582 vcl_vector<bool> valid = close_buildings(building_mean_hgt_.size());
00583
00584 vcl_vector<T> new_means;
00585 vcl_vector<unsigned int> idx_map(building_mean_hgt_.size(),0);
00586 unsigned cnt = 1;
00587 for (unsigned int i=0; i<valid.size(); ++i) {
00588 if (valid[i]) {
00589 new_means.push_back(building_mean_hgt_[i]);
00590 idx_map[i] = ++cnt;
00591 }
00592 }
00593 building_mean_hgt_.swap(new_means);
00594
00595
00596 for (unsigned int j=0; j<nj; ++j) {
00597 for (unsigned int i=0; i<ni; ++i) {
00598 if (labels_(i,j) > 1)
00599 labels_(i,j) = idx_map[labels_(i,j)-2];
00600 }
00601 }
00602 #endif // 0
00603 }
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614 template <class T>
00615 bmdl_classify<T>::merge_map::merge_map(bmdl_classify<T>* c)
00616 : classifier_(c)
00617 {
00618 assert(c);
00619 idx_map_.resize(classifier_->building_mean_hgt_.size());
00620 for (unsigned int i=0; i<idx_map_.size(); ++i)
00621 idx_map_[i] = i;
00622 }
00623
00624
00625 template <class T>
00626 bmdl_classify<T>::merge_map::~merge_map()
00627 {
00628 vcl_vector<T>& mean = classifier_->building_mean_hgt_;
00629 vcl_vector<unsigned int>& count = classifier_->building_area_;
00630
00631
00632 vcl_vector<vcl_pair<T,int> > unique;
00633 for (unsigned int i=0; i<idx_map_.size(); ++i)
00634 {
00635 if (idx_map_[i] == i) {
00636 unique.push_back(vcl_pair<T,int>(mean[i],i));
00637 continue;
00638 }
00639 unsigned int i2 = i;
00640 while (idx_map_[i2] != i2 )
00641 idx_map_[i] = i2 = idx_map_[i2];
00642 }
00643 vcl_sort(unique.begin(), unique.end());
00644
00645 vcl_vector<T> new_mean(unique.size(),0.0);
00646 vcl_vector<unsigned int> new_count(unique.size(),0);
00647
00648 vcl_vector<unsigned int> unique_map(idx_map_.size(),0);
00649 for (unsigned int i=0; i<unique.size(); ++i) {
00650 unique_map[unique[i].second] = i;
00651 new_mean[i] = unique[i].first;
00652 new_count[i] = count[unique[i].second];
00653 }
00654 for (unsigned int i=0; i<unique_map.size(); ++i)
00655 if (idx_map_[i] != i)
00656 unique_map[i] = unique_map[idx_map_[i]];
00657
00658 vil_image_view<unsigned int>& labels = classifier_->labels_;
00659 unsigned int ni = labels.ni();
00660 unsigned int nj = labels.nj();
00661 for (unsigned int j=0; j<nj; ++j) {
00662 for (unsigned int i=0; i<ni; ++i) {
00663 if (labels(i,j)>=2)
00664 labels(i,j) = unique_map[labels(i,j)-2]+2;
00665 }
00666 }
00667 mean.swap(new_mean);
00668 count.swap(new_count);
00669 }
00670
00671
00672 template <class T>
00673 unsigned int
00674 bmdl_classify<T>::merge_map::translate(unsigned int idx) const
00675 {
00676 while (idx_map_[idx] != idx) idx = idx_map_[idx];
00677 return idx;
00678 }
00679
00680
00681 template <class T>
00682 void bmdl_classify<T>::merge_map::merge(unsigned int idx1, unsigned int idx2)
00683 {
00684 idx1 = translate(idx1);
00685 idx2 = translate(idx2);
00686 if (idx1 == idx2)
00687 return;
00688
00689 vcl_vector<T>& mean = classifier_->building_mean_hgt_;
00690 vcl_vector<unsigned int>& count = classifier_->building_area_;
00691
00692 mean[idx1] = (mean[idx1]*count[idx1] + mean[idx2]*count[idx2])
00693 /(count[idx1]+count[idx2]);
00694 count[idx1] += count[idx2];
00695 count[idx2] = 0;
00696 idx_map_[idx2] = idx1;
00697 }
00698
00699
00700
00701
00702
00703
00704 template <class T>
00705 T bmdl_classify<T>::interpolate_parabola(T y_1, T y_0, T y_2, T& root_offset) const
00706 {
00707 T diff1 = y_2 - y_1;
00708 T diff2 = 2 * y_0 - y_1 - y_2;
00709
00710 root_offset = vcl_abs(vcl_sqrt(diff1*diff1/4 + 2*diff2*y_0) / diff2);
00711 return diff1 / (2 * diff2);
00712 }
00713
00714
00715
00716
00717 template <class T>
00718 void bmdl_classify<T>::histogram(const vcl_vector<T>& data, vcl_vector<unsigned int>& bins,
00719 T minv, T maxv) const
00720 {
00721 assert(maxv > minv);
00722 int num_bins = bins.size();
00723 assert(num_bins > 0);
00724 T binsize = (maxv-minv)/num_bins;
00725
00726 for (unsigned int i=0; i<data.size(); ++i)
00727 {
00728 int bin = static_cast<int>((data[i]-minv)/binsize);
00729 if (bin >= num_bins || bin < 0)
00730 continue;
00731 ++bins[bin];
00732 }
00733 }
00734
00735
00736
00737
00738 template <class T>
00739 void bmdl_classify<T>::fit_gaussian_to_peak(const vcl_vector<T>& data, T minv, T maxv,
00740 T& mean, T& stdev) const
00741 {
00742 unsigned int num_bins = 100;
00743 T binsize = (maxv-minv)/num_bins;
00744 vcl_vector<unsigned int> hist(100,0);
00745 histogram(data,hist,minv,maxv);
00746
00747
00748 unsigned int peakv = 0;
00749 unsigned int peaki = 0;
00750 for (unsigned int i=0; i<num_bins; ++i) {
00751 if (hist[i] > peakv) {
00752 peakv = hist[i];
00753 peaki = i;
00754 }
00755 }
00756
00757
00758 unsigned int pp = (peaki+1 < num_bins)?hist[peaki+1]:0;
00759 unsigned int pm = (peaki >= 1) ?hist[peaki-1]:0;
00760 T ro;
00761 T shift = interpolate_parabola(T(pm),T(peakv),T(pp),ro);
00762 ro *= 3;
00763 maxv = (peaki+shift+ro)*binsize+minv;
00764 minv = (peaki+shift-ro)*binsize+minv;
00765
00766
00767 mean = 0;
00768 stdev = 0;
00769 unsigned count = 0;
00770 for (unsigned int i=0; i<data.size(); ++i) {
00771 if (data[i] > minv && data[i] < maxv) {
00772 ++count;
00773 mean += data[i];
00774 stdev += data[i]*data[i];
00775 }
00776 }
00777
00778 mean /= count;
00779 stdev /= count;
00780 stdev -= mean*mean;
00781 stdev = vcl_sqrt(stdev);
00782 }
00783
00784
00785
00786
00787 template <class T>
00788 void bmdl_classify<T>::range(const vil_image_view<T>& image,
00789 T& minv, T& maxv) const
00790 {
00791 const unsigned int ni= image.ni();
00792 const unsigned int nj = image.nj();
00793 for (unsigned int j=0; j<nj; ++j) {
00794 for (unsigned int i=0; i<ni; ++i) {
00795 const T& val = image(i,j);
00796 if (vnl_math_isfinite(val)) {
00797 if (val > maxv) maxv = val;
00798 if (val < minv) minv = val;
00799 }
00800 }
00801 }
00802 }
00803
00804
00805
00806
00807 template <class T>
00808 bool bmdl_classify<T>::expand_buildings(vcl_vector<T>& means,
00809 vcl_vector<unsigned int>& sizes)
00810 {
00811 bool changed = false;
00812 unsigned int ni=first_return_.ni();
00813 unsigned int nj=last_return_.nj();
00814
00815 T zthresh = T(0.01);
00816 assert(zthresh > 0);
00817
00818 merge_map merge(this);
00819
00820 for (unsigned int j=0; j<nj; ++j)
00821 {
00822 for (unsigned int i=0; i<ni; ++i)
00823 {
00824
00825 if (labels_(i,j) != 1)
00826 continue;
00827
00828
00829 vcl_set<int> n;
00830 if (i>0 && labels_(i-1,j) > 1) {
00831 unsigned int idx = merge.translate(labels_(i-1,j)-2);
00832 if (vnl_math_sqr(first_return_(i,j) - first_return_(i-1,j)) < zthresh ||
00833 vnl_math_sqr(last_return_(i,j) - last_return_(i-1,j)) < zthresh )
00834 n.insert(idx);
00835 }
00836 if (j>0 && labels_(i,j-1) > 1) {
00837 unsigned int idx = merge.translate(labels_(i,j-1)-2);
00838 if (vnl_math_sqr(first_return_(i,j) - first_return_(i,j-1)) < zthresh ||
00839 vnl_math_sqr(last_return_(i,j) - last_return_(i,j-1)) < zthresh )
00840 n.insert(idx);
00841 }
00842 if (i<ni-1 && labels_(i+1,j) > 1) {
00843 unsigned int idx = merge.translate(labels_(i+1,j)-2);
00844 if (vnl_math_sqr(first_return_(i,j) - first_return_(i+1,j)) < zthresh ||
00845 vnl_math_sqr(last_return_(i,j) - last_return_(i+1,j)) < zthresh )
00846 n.insert(idx);
00847 }
00848 if (j<nj-1 && labels_(i,j+1) > 1) {
00849 unsigned int idx = merge.translate(labels_(i,j+1)-2);
00850 if (vnl_math_sqr(first_return_(i,j) - first_return_(i,j+1)) < zthresh ||
00851 vnl_math_sqr(last_return_(i,j) - last_return_(i,j+1)) < zthresh )
00852 n.insert(idx);
00853 }
00854 if (n.empty())
00855 continue;
00856
00857 for (vcl_set<int>::iterator itr=n.begin(); itr!=n.end(); ++itr) {
00858
00859 if (labels_(i,j) > 1) {
00860 unsigned int other = labels_(i,j)-2;
00861 merge.merge(other,*itr);
00862 }
00863 else {
00864 labels_(i,j) = *itr+2;
00865 changed = true;
00866 }
00867 }
00868 }
00869 }
00870
00871 return changed;
00872 }
00873
00874
00875
00876
00877
00878 template <class T>
00879 bool bmdl_classify<T>::dilate_buildings(unsigned int num)
00880 {
00881 bool changed = false;
00882 unsigned int ni=first_return_.ni()-1;
00883 unsigned int nj=last_return_.nj()-1;
00884
00885 for (unsigned int j=1; j<nj; ++j)
00886 {
00887 for (unsigned int i=1; i<ni; ++i)
00888 {
00889
00890 if (labels_(i,j) != 1)
00891 continue;
00892
00893
00894 vcl_map<int,unsigned int> n;
00895 int offset_x[] = {-1, 0, 0, 1,-1, 1, 1,-1};
00896 int offset_y[] = { 0,-1, 1, 0,-1,-1, 1, 1};
00897 unsigned total = 0;
00898 for (unsigned int k=0; k<8; ++k)
00899 {
00900 int idx = labels_(i+offset_x[k], j+offset_y[k])-2;
00901 if (idx<0) continue;
00902 ++total;
00903 vcl_map<int,unsigned int>::iterator itr = n.find(idx);
00904 if (itr == n.end() && k < 4)
00905 n.insert(vcl_pair<int,unsigned int>(idx,1));
00906 else
00907 ++(itr->second);
00908 }
00909
00910 if (n.empty())
00911 continue;
00912
00913 if (total < num)
00914 continue;
00915
00916 unsigned int max = 0;
00917 for (vcl_map<int,unsigned>::iterator itr=n.begin(); itr!=n.end(); ++itr)
00918 {
00919 if (itr->second > max) {
00920 max = itr->second;
00921 labels_(i,j) = itr->first+2;
00922 ++building_area_[itr->first];
00923 changed = true;
00924 }
00925 }
00926 }
00927 }
00928
00929 return changed;
00930 }
00931
00932
00933
00934 template <class T>
00935 bool bmdl_classify<T>::greedy_merge()
00936 {
00937 unsigned int ni=labels_.ni();
00938 unsigned int nj=labels_.nj();
00939
00940 typedef vcl_pair<unsigned int,unsigned int> upair;
00941 vcl_set<upair> adjacent;
00942
00943 for (unsigned int j=0; j<nj; ++j) {
00944 for (unsigned int i=1; i<ni; ++i) {
00945 unsigned int l1 = labels_(i,j);
00946 unsigned int l2 = labels_(i-1,j);
00947 if (l1<2 || l2<2 || l1==l2) continue;
00948 if (l1>l2) vcl_swap(l1,l2);
00949 adjacent.insert(upair(l1-2,l2-2));
00950 }
00951 }
00952
00953 for (unsigned int j=1; j<nj; ++j) {
00954 for (unsigned int i=0; i<ni; ++i) {
00955 unsigned int l1 = labels_(i,j);
00956 unsigned int l2 = labels_(i,j-1);
00957 if (l1<2 || l2<2 || l1==l2) continue;
00958 if (l1>l2) vcl_swap(l1,l2);
00959 adjacent.insert(upair(l1-2,l2-2));
00960 }
00961 }
00962
00963 vcl_vector<upair> to_merge;
00964 for (vcl_set<upair>::iterator itr=adjacent.begin();
00965 itr!=adjacent.end(); ++itr)
00966 {
00967 unsigned int idx1 = itr->first;
00968 unsigned int idx2 = itr->second;
00969 if (vcl_abs(building_mean_hgt_[idx1] - building_mean_hgt_[idx2]) < height_resolution_)
00970 to_merge.push_back(*itr);
00971 }
00972
00973 if (to_merge.empty())
00974 return false;
00975
00976 merge_map merge(this);
00977
00978 for (unsigned int i=0; i<to_merge.size(); ++i)
00979 {
00980 unsigned int idx1 = merge.translate(to_merge[i].first);
00981 unsigned int idx2 = merge.translate(to_merge[i].second);
00982 merge.merge(idx1,idx2);
00983 }
00984
00985 return true;
00986 }
00987
00988
00989
00990 template <class T>
00991 vcl_vector<bool>
00992 bmdl_classify<T>::close_buildings(unsigned int num_labels)
00993 {
00994 unsigned int ni=labels_.ni();
00995 unsigned int nj=labels_.nj();
00996 vil_image_view<unsigned int> new_labels(ni,nj);
00997 vcl_vector<vgl_box_2d<int> > building_bounds(num_labels);
00998
00999
01000
01001 for (unsigned int j=0; j<nj; ++j) {
01002 for (unsigned int i=0; i<ni; ++i) {
01003 new_labels(i,j) = (labels_(i,j)==1)?1:0;
01004 if (labels_(i,j)>1)
01005 building_bounds[labels_(i,j)-2].add(vgl_point_2d<int>(i,j));
01006 }
01007 }
01008
01009
01010 unsigned int bni=0, bnj=0;
01011 for (unsigned int l=0; l<num_labels; ++l) {
01012 unsigned int w = building_bounds[l].width()+1;
01013 unsigned int h = building_bounds[l].height()+1;
01014 if (w > bni) bni = w;
01015 if (h > bnj) bnj = h;
01016 }
01017
01018 vcl_cout << "max bounds = " << bni<<", "<<bnj<<vcl_endl;
01019 bni += 4;
01020 bnj += 4;
01021 vil_image_view<bool> full_mask(bni,bnj);
01022 vil_image_view<bool> full_work(bni,bnj);
01023
01024 vil_structuring_element se;
01025 se.set_to_disk(1);
01026 vcl_vector<bool> valid(num_labels,false);
01027 for (unsigned l=0; l<num_labels; ++l) {
01028 const vgl_box_2d<int>& bbox = building_bounds[l];
01029
01030 if (bbox.width()==0 || bbox.height()==0)
01031 continue;
01032
01033 #ifdef DEBUG
01034 vcl_cout << "closing "<<l<<" of "<<num_labels<<vcl_endl;
01035 vcl_cout << " from "<<building_bounds[l].min_point()<<" to "<<building_bounds[l].max_point()<<vcl_endl;
01036 #endif // DEBUG
01037
01038 int min_x=bbox.min_x()-2, min_y=bbox.min_y()-2;
01039 if (min_x < 0) min_x = 0;
01040 if (min_y < 0) min_y = 0;
01041 int max_x=bbox.max_x()+2, max_y=bbox.max_y()+2;
01042 if (max_x >= int(ni)) max_x = ni-1;
01043 if (max_y >= int(nj)) max_y = nj-1;
01044
01045 unsigned lni = max_x - min_x + 1;
01046 unsigned lnj = max_y - min_y + 1;
01047
01048
01049 vil_image_view<bool> mask(lni,lnj);
01050 vil_image_view<bool> work(lni,lnj);
01051
01052
01053 for (unsigned int j=0; j<lnj; ++j) {
01054 for (unsigned int i=0; i<lni; ++i) {
01055 mask(i,j) = labels_(min_x+i,min_y+j)-2 == l;
01056 }
01057 }
01058
01059 vil_binary_dilate(mask,work,se);
01060 vil_binary_erode(work,mask,se);
01061
01062 vil_binary_erode(mask,work,se);
01063 vil_binary_dilate(work,mask,se);
01064
01065
01066 for (unsigned int j=0; j<lnj; ++j) {
01067 for (unsigned int i=0; i<lni; ++i) {
01068 if (mask(i,j)){
01069 new_labels(min_x+i,min_y+j) = l+2;
01070 valid[l] = true;
01071 }
01072 }
01073 }
01074 }
01075 labels_ = new_labels;
01076 return valid;
01077 }
01078
01079
01080
01081 template <class T>
01082 vil_image_view<unsigned int> bmdl_classify<T>::bin_heights(T binsize)
01083 {
01084 unsigned int ni=last_return_.ni();
01085 unsigned int nj=last_return_.nj();
01086
01087 vil_image_view<unsigned int> bin_img(ni,nj);
01088
01089 for (unsigned int j=0; j<nj; ++j)
01090 {
01091 for (unsigned int i=0; i<ni; ++i)
01092 {
01093 if (labels_(i,j) < 2)
01094 {
01095 bin_img(i,j) = labels_(i,j);
01096 continue;
01097 }
01098 int bin = static_cast<int>((last_return_(i,j) - last_min_)/binsize);
01099 bin_img(i,j) = bin+2;
01100 }
01101 }
01102 return bin_img;
01103 }
01104
01105
01106
01107
01108 #define BMDL_CLASSIFY_INSTANTIATE(T) \
01109 template class bmdl_classify<T >
01110
01111
01112 #endif // bmdl_classify_txx_