00001 #include "brip_watershed.h"
00002
00003
00004 #include <vcl_cmath.h>
00005 #include <vnl/vnl_numeric_traits.h>
00006 #include <vnl/vnl_math.h>
00007 #include <vgl/vgl_point_2d.h>
00008 #include <vil1/vil1_rgb.h>
00009 #include "brip_vil1_float_ops.h"
00010
00011
00012 static int n_col[8]={-1, 0, 1,-1,1,-1,0,1};
00013 static int n_row[8]={-1,-1,-1, 0,0, 1,1,1};
00014
00015 brip_watershed::brip_watershed(brip_watershed_params const& bwp)
00016 : brip_watershed_params(bwp)
00017 {
00018 max_region_label_ = 1;
00019 }
00020
00021 brip_watershed::~brip_watershed()
00022 {
00023 for (vcl_map<unsigned int, vcl_vector<unsigned int>* >::iterator
00024 mit = region_adjacency_.begin();
00025 mit != region_adjacency_.end(); mit++)
00026 delete (*mit).second;
00027 }
00028
00029
00030 void brip_watershed::print_region_array()
00031 {
00032 vcl_cout << "\n\n";
00033 int rows = region_label_array_.rows(), cols = region_label_array_.cols();
00034 for (int r = 0; r<rows; r++)
00035 {
00036 for (int c = 0; c<cols; c++)
00037 vcl_cout << region_label_array_[r][c] << ' ';
00038 vcl_cout << '\n';
00039 }
00040 vcl_cout << vcl_endl << vcl_endl;
00041 }
00042
00043 void brip_watershed::print_neighborhood(int col, int row, unsigned int lab)
00044 {
00045 int rows = region_label_array_.rows(), cols = region_label_array_.cols();
00046 int k = 0, m = 0;
00047 for (int n = 0; n<8; n++, k++, m++)
00048 {
00049 int rn = row + n_row[n];
00050 int cn = col + n_col[n];
00051 if (rn<0||rn>=rows||cn<0||cn>=cols)
00052 {
00053 vcl_cout << "Neighborhood out of range\n";
00054 return;
00055 }
00056 if (k>2)
00057 {
00058 vcl_cout << '\n';
00059 k = 0;
00060 }
00061 if (m == 4)
00062 {
00063 vcl_cout << lab << ' ' << region_label_array_[rn][cn];
00064 k++;
00065 }
00066 else
00067 vcl_cout << region_label_array_[rn][cn] << ' ';
00068 }
00069 vcl_cout << vcl_endl;
00070 }
00071
00072 void brip_watershed::print_adjacency_map()
00073 {
00074 for (vcl_map<unsigned int, vcl_vector<unsigned int>* >::iterator
00075 mit = region_adjacency_.begin();
00076 mit != region_adjacency_.end(); mit++)
00077 {
00078 unsigned int reg = (*mit).first;
00079 vcl_vector<unsigned int>* adj_regs = (*mit).second;
00080 vcl_cout << "R[" << reg << "]:(";
00081 if (adj_regs)
00082 for (vcl_vector<unsigned int>::iterator rit = adj_regs->begin();
00083 rit != adj_regs->end(); rit++)
00084 vcl_cout << (*rit) << ' ';
00085 vcl_cout << ")\n";
00086 }
00087 }
00088
00089 void brip_watershed::set_image(vil1_memory_image_of<float> const& image)
00090 {
00091 image_ = image;
00092 int w = image_.width(), h = image_.height();
00093 vil1_memory_image_of<float> Ix(w, h), Iy(w, h);
00094 vil1_memory_image_of<float> gauss =
00095 brip_vil1_float_ops::gaussian(image_, sigma_);
00096 brip_vil1_float_ops::gradient_3x3(gauss, Ix, Iy);
00097 gradient_mag_image_.resize(w,h);
00098 for (int r = 0; r<h; r++)
00099 {
00100 for (int c = 0; c<w; c++)
00101 {
00102 float gx = Ix(c,r), gy = Iy(c,r);
00103 gradient_mag_image_(c,r) = vcl_sqrt(gx*gx+gy*gy);
00104
00105 }
00106
00107 }
00108 region_label_array_.resize(h,w);
00109 region_label_array_.fill(UNLABELED);
00110 }
00111
00112
00113
00114
00115 bool brip_watershed::compute_seeds()
00116 {
00117 int w = gradient_mag_image_.width(), h = gradient_mag_image_.height();
00118 max_region_label_ = 1;
00119 for (int r = 2; r<h-2; r++)
00120 for (int c = 2;c<w-2;c++)
00121 {
00122 float min_grad = vnl_numeric_traits<float>::maxval;
00123 float max_grad = -min_grad;
00124 int min_i = 0, min_j=0;
00125 for (int i = -1;i<=1; i++)
00126 for (int j = -1;j<=1; j++)
00127 {
00128 float g = gradient_mag_image_(c+j, r+i);
00129 max_grad = vnl_math_max(max_grad, g);
00130 if (g<min_grad)
00131 {
00132 min_grad = g;
00133 min_i = i;
00134 min_j = j;
00135 }
00136 }
00137 float diff = max_grad-min_grad;
00138
00139
00140
00141 if (!min_i&&!min_j&&diff>thresh_)
00142 {
00143 max_region_label_++;
00144 region_label_array_[r][c] = max_region_label_;
00145 if (verbose_)
00146 {
00147 vcl_cout << "\nS(c:" << c << " r:" << r << ')' << vcl_endl;
00148 this->print_neighborhood(c, r, max_region_label_);
00149 }
00150 }
00151 }
00152 return max_region_label_ != 0;
00153 }
00154
00155
00156
00157 bool brip_watershed::initialize_queue()
00158 {
00159 int w = gradient_mag_image_.width(), h = gradient_mag_image_.height();
00160 for (int r = 2; r<h-2; r++)
00161 for (int c = 2;c<w-2;c++)
00162 for (int n = 0;n<8; n++)
00163 {
00164 int cn = c+n_col[n], rn = r+n_row[n];
00165 unsigned int lab = region_label_array_[rn][cn];
00166 if (lab>BOUNDARY)
00167
00168 {
00169 vgl_point_2d<int> location(c,r);
00170 vgl_point_2d<int> nearest(cn,rn);
00171 float cost = gradient_mag_image_(c, r);
00172 brip_region_pixel_sptr pix =
00173 new brip_region_pixel(location, nearest, cost, 0, lab);
00174 priority_queue_.push(pix);
00175 }
00176 }
00177
00178 return priority_queue_.size()>0;
00179 }
00180
00181
00182
00183 bool brip_watershed::grow_regions()
00184 {
00185 int n_boundary_pix=0, n_region_pix = 0;
00186 int rs = region_label_array_.rows(), cs = region_label_array_.cols();
00187 while (priority_queue_.size() != 0)
00188 {
00189
00190 brip_region_pixel_sptr pix = priority_queue_.top();
00191 if (!pix)
00192 return false;
00193 priority_queue_.pop();
00194
00195 unsigned int lab = pix->label_;
00196 if (lab <= BOUNDARY)
00197 continue;
00198 vgl_point_2d<int> location = pix->location_;
00199 vgl_point_2d<int> nearest = pix->nearest_;
00200 if (verbose_)
00201 {
00202 vcl_cout << "\nN(c:" << location.x() << " r:" << location.y() << ")\n";
00203 this->print_neighborhood(location.x(), location.y(), lab);
00204 }
00205 for (int n = 0; n<8; n++)
00206 {
00207
00208 int rn = location.y()+n_row[n];
00209 int cn = location.x()+n_col[n];
00210 if (rn<1||cn<1||rn>rs-2||cn>cs-2)
00211 continue;
00212 unsigned int n_lab = region_label_array_[rn][cn];
00213
00214
00215
00216 if (n_lab>BOUNDARY&&n_lab!=lab)
00217 {
00218
00219 this->add_adjacency(lab, n_lab);
00220 this->add_adjacency(n_lab, lab);
00221 lab = BOUNDARY;
00222 n_boundary_pix++;
00223 break;
00224 }
00225 }
00226 pix->label_=lab;
00227 region_label_array_[location.y()][location.x()]=lab;
00228
00229 if (lab>BOUNDARY)
00230 for (int n = 0; n<8; n++)
00231 {
00232
00233 int rn = location.y()+n_row[n];
00234 int cn = location.x()+n_col[n];
00235 if (rn<1||cn<1||rn>rs-2||cn>cs-2)
00236 continue;
00237 unsigned int n_lab = region_label_array_[rn][cn];
00238 if (n_lab != UNLABELED)
00239 continue;
00240
00241 vgl_point_2d<int> n_location(cn, rn);
00242 float cost = gradient_mag_image_(cn, rn);
00243 brip_region_pixel_sptr pix =
00244 new brip_region_pixel(n_location, nearest, cost, 0, lab);
00245 priority_queue_.push(pix);
00246
00247 region_label_array_[rn][cn] = lab;
00248 n_region_pix++;
00249 }
00250 if (verbose_)
00251 {
00252 vcl_cout << '\n';
00253 this->print_neighborhood(location.x(), location.y(), lab);
00254 }
00255 }
00256 if (verbose_)
00257 vcl_cout << "Found " << n_boundary_pix << " boundary pixels and "
00258 << n_region_pix << " region pixels\n";
00259 return n_region_pix>0||n_boundary_pix>0;
00260 }
00261
00262
00263 bool brip_watershed::add_adjacency(const unsigned int reg,
00264 const unsigned int adj_reg)
00265 {
00266 vcl_map<unsigned int, vcl_vector<unsigned int>* >::iterator adi;
00267 adi = region_adjacency_.find(reg);
00268
00269 if (adi !=region_adjacency_.end())
00270 {
00271 vcl_vector<unsigned int> * vec = region_adjacency_[reg];
00272
00273 for (unsigned int i =0 ; i < vec->size(); i++)
00274 if ((*vec)[i] == adj_reg)
00275 return false;
00276
00277 vec->push_back(adj_reg);
00278 }
00279 else
00280 {
00281 vcl_vector<unsigned int>* adj_array = new vcl_vector<unsigned int>;
00282 adj_array->push_back(adj_reg);
00283 region_adjacency_[reg]=adj_array;
00284 }
00285 return true;
00286 }
00287
00288 bool brip_watershed::adjacent_regions(const unsigned int reg,
00289 vcl_vector<unsigned int>& adj_regs)
00290 {
00291 adj_regs.clear();
00292 vcl_map<unsigned int, vcl_vector<unsigned int>* >::iterator adi;
00293 adi = region_adjacency_.find(reg);
00294
00295 if (adi !=region_adjacency_.end())
00296 {
00297 adj_regs = *(region_adjacency_[reg]);
00298 return true;
00299 }
00300 else
00301 return false;
00302 }
00303
00304 bool brip_watershed::compute_regions()
00305 {
00306 if (!compute_seeds())
00307 {
00308 vcl_cout << "In brip_watershed::compute_regions() - no seeds\n";
00309 return false;
00310 }
00311
00312 if (!initialize_queue())
00313 {
00314 vcl_cout << "In brip_watershed::compute_regions() - queue initialization failed\n";
00315 return false;
00316 }
00317 if (!grow_regions())
00318 {
00319 vcl_cout << "In brip_watershed::grow_regions() - failed\n";
00320 return false;
00321 }
00322
00323 return true;
00324 }
00325
00326
00327
00328 vil1_image brip_watershed::overlay_image()
00329 {
00330
00331 vil1_memory_image_of<unsigned char> cimage =
00332 brip_vil1_float_ops::convert_to_byte(image_);
00333
00334 int w = cimage.width(), h = cimage.height();
00335 vil1_memory_image_of<vil1_rgb<unsigned char> > overlay(w,h);
00336 for (int row = 0; row<h; row++)
00337 for (int col = 0; col<w; col++)
00338 if (region_label_array_[row][col]>BOUNDARY)
00339 {
00340 overlay(col,row).r = cimage(col,row);
00341 overlay(col,row).g = cimage(col,row);
00342 overlay(col,row).b = cimage(col,row);
00343 }
00344 else
00345 {
00346 overlay(col,row).r = 0;
00347 overlay(col,row).g = 255;
00348 overlay(col,row).b = 0;
00349 }
00350 return overlay;
00351 }