00001
00002 #include "sdet_watershed_region_proc.h"
00003
00004
00005 #include <vcl_algorithm.h>
00006 #include <vnl/vnl_numeric_traits.h>
00007 #include <vil1/vil1_memory_image_of.h>
00008 #include <vsol/vsol_box_2d.h>
00009 #include <brip/brip_vil1_float_ops.h>
00010 #include <brip/brip_roi.h>
00011 #include <brip/brip_watershed.h>
00012 #include <bdgl/bdgl_region_algs.h>
00013 #include <sdet/sdet_region.h>
00014
00015
00016 static bool region_intensity_compare_increasing(sdet_region_sptr const r1,
00017 sdet_region_sptr const r2)
00018 {
00019 return r2->Io() > r1->Io();
00020 }
00021
00022
00023 static bool region_intensity_compare_decreasing(sdet_region_sptr const r1,
00024 sdet_region_sptr const r2)
00025 {
00026 return r1->Io() > r2->Io();
00027 }
00028
00029
00030 static bool region_area_compare_increasing(sdet_region_sptr const r1,
00031 sdet_region_sptr const r2)
00032 {
00033 return r2->Npix() > r1->Npix();
00034 }
00035
00036
00037 static bool region_area_compare_decreasing(sdet_region_sptr const r1,
00038 sdet_region_sptr const r2)
00039 {
00040 return r1->Npix() > r2->Npix();
00041 }
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 sdet_watershed_region_proc::sdet_watershed_region_proc(sdet_watershed_region_proc_params& wrpp)
00052 : sdet_watershed_region_proc_params(wrpp)
00053 {
00054 regions_valid_ = false;
00055 region_image_valid_ =false;
00056 boundaries_valid_ = false;
00057 min_label_ = 0;
00058 max_label_ = 0;
00059 }
00060
00061
00062 sdet_watershed_region_proc::~sdet_watershed_region_proc()
00063 {
00064 for (vcl_map<sdet_region_sptr, vcl_vector<sdet_region_sptr>* >::iterator
00065 rait = region_adjacency_.begin(); rait != region_adjacency_.end(); ++rait)
00066 delete (*rait).second;
00067 }
00068
00069
00070 void sdet_watershed_region_proc::clip_image()
00071 {
00072 if (!image_ || !roi_)
00073 return;
00074 vsol_box_2d_sptr box = roi_->region(0);
00075 if (! brip_vil1_float_ops::chip(image_, box, clip_))
00076 vcl_cout << "sdet_watershed_region_proc::chip_out_roi(.) - failed\n";
00077 }
00078
00079
00080
00081
00082 void sdet_watershed_region_proc::set_image(vil1_image const& image,
00083 vsol_box_2d_sptr const& box)
00084 {
00085 if (!image)
00086 {
00087 vcl_cout <<"In sdet_watershed_region_proc::set_image(.) - null input\n";
00088 return;
00089 }
00090
00091 image_ = brip_vil1_float_ops::convert_to_float(image);
00092
00093 if (box)
00094 {
00095 roi_ = new brip_roi(image.width(), image.height());
00096 roi_->add_region(box);
00097 this->clip_image();
00098 }
00099 regions_valid_ = false;
00100 region_image_valid_ =false;
00101 boundaries_valid_ = false;
00102 }
00103
00104
00105
00106
00107
00108 void sdet_watershed_region_proc::scan_region_data(vbl_array_2d<unsigned int> const & lab_array)
00109 {
00110 int rows = lab_array.rows(), cols = lab_array.cols();
00111 int n_regions = max_label_ - min_label_ +1;
00112
00113 for (int r = 0; r<rows; r++)
00114 for (int c = 0; c<cols; c++)
00115 {
00116 int imgc = c, imgr = r;
00117 if (roi_)
00118 {
00119 imgc = roi_->ic(c);
00120 imgr = roi_->ir(r);
00121 }
00122 unsigned int lab = lab_array[r][c];
00123 if (lab<min_label_ || lab>max_label_)
00124 continue;
00125 int index = lab-min_label_;
00126
00127 unsigned short v = (unsigned short) image_(imgc, imgr);
00128 regions_[index]->IncrementMeans(float(imgc), float(imgr), v);
00129 }
00130
00131 for (int i = 0; i<n_regions; i++)
00132 regions_[i]->InitPixelArrays();
00133
00134 for (int r = 0; r<rows; r++)
00135 for (int c = 0; c<cols; c++)
00136 {
00137 int imgc = c, imgr = r;
00138 if (roi_)
00139 {
00140 imgc = roi_->ic(c);
00141 imgr = roi_->ir(r);
00142 }
00143 unsigned int lab = lab_array[r][c];
00144 if (lab<min_label_ || lab>max_label_)
00145 continue;
00146 int index = lab-min_label_;
00147
00148 unsigned short v = (unsigned short) image_(imgc, imgr);
00149 regions_[index]->InsertInPixelArrays(float(imgc), float(imgr), v);
00150 regions_[index]->ComputeIntensityStdev();
00151 }
00152 }
00153
00154 bool sdet_watershed_region_proc::add_adjacency(sdet_region_sptr const& reg,
00155 sdet_region_sptr const& adj_reg)
00156 {
00157 vcl_map<sdet_region_sptr, vcl_vector<sdet_region_sptr>* >::iterator rai;
00158 rai = region_adjacency_.find(reg);
00159
00160 if (rai !=region_adjacency_.end())
00161 {
00162 vcl_vector<sdet_region_sptr> * vec = region_adjacency_[reg];
00163
00164 for (unsigned int i =0 ; i < vec->size(); ++i)
00165 if ((*vec)[i] == adj_reg)
00166 return false;
00167
00168 vec->push_back(adj_reg);
00169 }
00170 else
00171 {
00172 vcl_vector<sdet_region_sptr>* adj_array = new vcl_vector<sdet_region_sptr>;
00173 adj_array->push_back(adj_reg);
00174 region_adjacency_[reg]=adj_array;
00175 }
00176 return true;
00177 }
00178
00179 bool
00180 sdet_watershed_region_proc::remove_adjacencies(sdet_region_sptr const& reg)
00181 {
00182 vcl_map<sdet_region_sptr, vcl_vector<sdet_region_sptr>* >::iterator rai;
00183 rai = region_adjacency_.find(reg);
00184 if (rai ==region_adjacency_.end())
00185 return false;
00186 vcl_vector<sdet_region_sptr>* adjacencies = (*rai).second;
00187 region_adjacency_.erase(rai);
00188 delete adjacencies;
00189 return true;
00190 }
00191
00192 bool sdet_watershed_region_proc::
00193 adjacent_regions(sdet_region_sptr const& reg,
00194 vcl_vector<sdet_region_sptr>& adj_regs)
00195 {
00196 adj_regs.clear();
00197 vcl_map<sdet_region_sptr, vcl_vector<sdet_region_sptr>* >::iterator rai;
00198 rai = region_adjacency_.find(reg);
00199
00200 if (rai !=region_adjacency_.end())
00201 {
00202 vcl_vector<sdet_region_sptr> * vec = region_adjacency_[reg];
00203 adj_regs = *vec;
00204 return true;
00205 }
00206 return false;
00207 }
00208
00209 static bool found_in_regions(sdet_region_sptr const &r,
00210 vcl_vector<sdet_region_sptr> const & regions)
00211 {
00212 bool found = false;
00213 for (vcl_vector<sdet_region_sptr>::const_iterator rit = regions.begin();
00214 rit != regions.end() && !found; rit++)
00215 if ((*rit).ptr() == r.ptr())
00216 found = true;
00217 return found;
00218 }
00219
00220 static
00221 void add_new_adjacent_regs(vcl_vector<sdet_region_sptr> const& new_adj_regs,
00222 vcl_vector<sdet_region_sptr>& adj_regs)
00223 {
00224 for (vcl_vector<sdet_region_sptr>::const_iterator rit = new_adj_regs.begin();
00225 rit != new_adj_regs.end(); rit++)
00226 if (!found_in_regions(*rit, adj_regs))
00227 adj_regs.push_back(*rit);
00228 }
00229
00230 bool sdet_watershed_region_proc::merge_regions()
00231 {
00232
00233 switch (merge_priority_)
00234 {
00235 case DARK:
00236 vcl_sort(regions_.begin(),
00237 regions_.end(), region_intensity_compare_increasing);
00238 break;
00239 case LIGHT:
00240 vcl_sort(regions_.begin(),
00241 regions_.end(), region_intensity_compare_decreasing);
00242 break;
00243 case SMALL:
00244 vcl_sort(regions_.begin(),
00245 regions_.end(), region_area_compare_increasing);
00246 break;
00247 case BIG:
00248 vcl_sort(regions_.begin(),
00249 regions_.end(), region_area_compare_decreasing);
00250 break;
00251 default:
00252 ;
00253 }
00254
00255 if (verbose_)
00256 {
00257 vcl_cout << "Regions before merge\n";
00258 this->print_region_info();
00259 }
00260
00261 vcl_vector<sdet_region_sptr> new_regions;
00262 vcl_vector<sdet_region_sptr> merged_regions;
00263 for (vcl_vector<sdet_region_sptr>::iterator rit = regions_.begin();
00264 rit != regions_.end(); rit++)
00265 {
00266 sdet_region_sptr& r = *rit;
00267 if (found_in_regions(r, merged_regions))
00268 continue;
00269 sdet_region_sptr& rm = r;
00270 vcl_vector<sdet_region_sptr> adj_regs;
00271 if (!adjacent_regions(r, adj_regs))
00272 continue;
00273 bool merged = false;
00274 vcl_vector<sdet_region_sptr> temp_adj;
00275 for (vcl_vector<sdet_region_sptr>::iterator arit = adj_regs.begin();
00276 arit != adj_regs.end(); arit++)
00277 {
00278 sdet_region_sptr& ar = *arit;
00279 if (found_in_regions(ar, merged_regions))
00280 continue;
00281 if (r->Npix()<min_area_ || ar->Npix()<min_area_)
00282 continue;
00283 #ifdef DEBUG
00284 vcl_cout << "R[" << r->label() <<"]:vs:[" << ar->label() << "]\n";
00285 #endif
00286 if (bdgl_region_algs::
00287 earth_mover_distance(r->cast_to_digital_region(),
00288 ar->cast_to_digital_region()) > merge_tol_)
00289 {
00290
00291 temp_adj.push_back(ar);
00292 continue;
00293 }
00294
00295 vdgl_digital_region_sptr temp;
00296 if (bdgl_region_algs::merge(rm->cast_to_digital_region(),
00297 ar->cast_to_digital_region(), temp))
00298 {
00299 rm = new sdet_region(*temp);
00300 merged = true;
00301 merged_regions.push_back(ar);
00302
00303
00304 vcl_vector<sdet_region_sptr> new_adj_regs;
00305 if (adjacent_regions(ar, new_adj_regs))
00306 add_new_adjacent_regs(new_adj_regs, temp_adj);
00307 }
00308 }
00309
00310 if (merged)
00311 {
00312 merged_regions.push_back(r);
00313 new_regions.push_back(rm);
00314 this->remove_adjacencies(r);
00315 rm->set_label(++max_label_);
00316 #ifdef DEBUG
00317 vcl_cout << "New Region[" << rm->label() << "](" << rm->Npix()
00318 << ")(Xo: " << rm->Xo() << " Yo: " << rm ->Yo()
00319 << " Io: " << rm ->Io() <<')' << vcl_endl;
00320 #endif
00321 for (vcl_vector<sdet_region_sptr>::iterator arit = temp_adj.begin();
00322 arit != temp_adj.end(); arit++)
00323 this->add_adjacency(rm, *arit);
00324 }
00325 }
00326 if (verbose_)
00327 {
00328 vcl_cout << "# merged regions " << merged_regions.size() << '\n'
00329 << "# new regions " << new_regions.size() << '\n';
00330 }
00331
00332 vcl_vector<sdet_region_sptr> temp2;
00333 for (vcl_vector<sdet_region_sptr>::iterator rit = regions_.begin();
00334 rit != regions_.end(); rit++)
00335 if (!found_in_regions(*rit, merged_regions))
00336 temp2.push_back(*rit);
00337
00338 for (vcl_vector<sdet_region_sptr>::iterator rit = new_regions.begin();
00339 rit != new_regions.end(); rit++)
00340 temp2.push_back(*rit);
00341
00342 regions_ = temp2;
00343 if (verbose_)
00344 {
00345 vcl_cout << "Regions after merge\n";
00346 this->print_region_info();
00347 }
00348 boundaries_valid_ = false;
00349 return true;
00350 }
00351
00352
00353
00354 bool sdet_watershed_region_proc::extract_regions()
00355 {
00356 if (regions_valid_)
00357 return true;
00358
00359
00360 if (!image_)
00361 {
00362 vcl_cout << "In sdet_watershed_region_proc::extract_regions() - no image\n";
00363 return false;
00364 }
00365
00366 vcl_cout << "sdet_watershed_region_proc::extract_regions(): width = "
00367 << image_.width() << " height = " << image_.height() << vcl_endl;
00368
00369
00370
00371 regions_.clear();
00372
00373 brip_watershed watershed(wp_);
00374 if (roi_)
00375 watershed.set_image(clip_);
00376 else
00377 watershed.set_image(image_);
00378 if (!watershed.compute_regions())
00379 return false;
00380 overlay_image_ = watershed.overlay_image();
00381 vil1_memory_image_of<vil1_rgb<unsigned char> > color_image =
00382 brip_vil1_float_ops::convert_to_rgb(image_, 0, 255);
00383 if (roi_)
00384 overlay_image_ =
00385 brip_vil1_float_ops::insert_chip_in_image(color_image, overlay_image_, roi_);
00386
00387
00388 vbl_array_2d<unsigned int>& lab_array = watershed.region_label_array();
00389 min_label_ = watershed.min_region_label();
00390 max_label_ = watershed.max_region_label();
00391 int n_labs = max_label_ - min_label_ + 1;
00392
00393
00394 regions_.resize(n_labs);
00395 for (int n = 0; n<n_labs; n++)
00396 {
00397 regions_[n] = new sdet_region();
00398 regions_[n]->set_label(n+min_label_);
00399 }
00400
00401 vcl_vector<unsigned int> adj_regs;
00402 for (int n = 0; n<n_labs; n++)
00403 {
00404 unsigned int ln = min_label_ + n;
00405 sdet_region_sptr rn = regions_[n];
00406 if (watershed.adjacent_regions(ln, adj_regs))
00407 for (unsigned int i = 0; i<adj_regs.size(); ++i)
00408 this->add_adjacency(rn, regions_[adj_regs[i]-min_label_]);
00409 }
00410
00411
00412 this->scan_region_data(lab_array);
00413
00414
00415 vcl_sort(regions_.begin(),
00416 regions_.end(), region_intensity_compare_increasing);
00417 regions_valid_ = true;
00418 boundaries_valid_ = false;
00419 return true;
00420 }
00421
00422
00423
00424
00425 void sdet_watershed_region_proc::clear()
00426 {
00427 regions_.clear();
00428 }
00429
00430
00431
00432
00433 vil1_image sdet_watershed_region_proc::get_residual_image()
00434 {
00435 if (!image_ || !regions_valid_)
00436 {
00437 vcl_cout << "In sdet_watershed_region_proc::get_residual_image() - no regions\n";
00438 return 0;
00439 }
00440 int xsize = image_.width(), ysize = image_.height();
00441 vil1_memory_image_of<unsigned char> res_image(xsize, ysize);
00442 res_image.fill(0);
00443 float min_res = (float)vnl_numeric_traits<unsigned short>::maxval;
00444 for (vcl_vector<sdet_region_sptr>::iterator rit = regions_.begin();
00445 rit != regions_.end(); rit++)
00446 for ((*rit)->reset(); (*rit)->next();)
00447 {
00448 float res = (*rit)->Ir();
00449 if (res<min_res)
00450 min_res = res;
00451 }
00452
00453 for (vcl_vector<sdet_region_sptr>::iterator rit = regions_.begin();
00454 rit != regions_.end(); rit++)
00455 for ((*rit)->reset(); (*rit)->next();)
00456 {
00457 int x = int((*rit)->X()), y = int((*rit)->Y());
00458 float res = (*rit)->Ir();
00459 float is = res-min_res;
00460 if (is>255)
00461 is = 255;
00462 unsigned char pix = (unsigned char)is;
00463 res_image(x, y)=pix;
00464 }
00465 return res_image;
00466 }
00467
00468 void sdet_watershed_region_proc::print_region_info()
00469 {
00470 if (!regions_valid_)
00471 return;
00472 int index = 0;
00473 for (vcl_vector<sdet_region_sptr>::iterator rit = regions_.begin();
00474 rit != regions_.end(); rit++, index++)
00475 {
00476 unsigned int npix = (*rit)->Npix();
00477 if (npix<min_area_)
00478 continue;
00479 vcl_cout << "R[" << (*rit)->label() << "](Np:" << npix << " Io:"
00480 << (*rit)->Io() << " Xo:" << (*rit)->Xo()
00481 << " Yo:" << (*rit)->Yo() << "):sd"<< (*rit)->Io_sd() << vcl_endl;
00482 }
00483 }
00484
00485 bool sdet_watershed_region_proc::compute_region_image()
00486 {
00487 if (!regions_valid_ || !image_)
00488 return false;
00489
00490 int w = image_.width(), h = image_.height();
00491 region_image_.resize(w, h);
00492 region_image_.fill(255);
00493 for (vcl_vector<sdet_region_sptr>::iterator rit = regions_.begin();
00494 rit != regions_.end(); rit++)
00495 for ((*rit)->reset(); (*rit)->next();)
00496 {
00497 int c = int((*rit)->X()), r = int((*rit)->Y());
00498 if (c<0 || r<0 || c>=w || r>=h)
00499 continue;
00500 unsigned char val = (unsigned char)(*rit)->I();
00501 region_image_(c,r) = val;
00502 }
00503 region_image_valid_ = true;
00504 return true;
00505 }
00506
00507 vil1_image sdet_watershed_region_proc::region_image()
00508 {
00509 vil1_image out;
00510 if (!region_image_valid_)
00511 if (!this->compute_region_image())
00512 return out;
00513 return region_image_;
00514 }
00515
00516 void sdet_watershed_region_proc::compute_boundaries()
00517 {
00518 for (vcl_vector<sdet_region_sptr>::iterator rit = regions_.begin();
00519 rit != regions_.end(); rit++)
00520 {
00521 if ((*rit)->Npix()<min_area_)
00522 continue;
00523 if ((*rit)->boundary())
00524 boundaries_.push_back((*rit)->boundary());
00525 }
00526 boundaries_valid_ = true;
00527 }
00528
00529 vcl_vector<vsol_polygon_2d_sptr> sdet_watershed_region_proc::boundaries()
00530 {
00531 if (!boundaries_valid_)
00532 this->compute_boundaries();
00533 return boundaries_;
00534 }