core/vil/algo/vil_blob_finder.cxx

Go to the documentation of this file.
00001 //:
00002 // \file
00003 // \brief Finds connected regions in a boolean image.
00004 // \author Tim Cootes
00005 
00006 #include "vil_blob_finder.h"
00007 #include "vil_trace_4con_boundary.h"
00008 #include "vil_trace_8con_boundary.h"
00009 #include "vil_flood_fill.h"
00010 
00011 //: Default constructor
00012 vil_blob_finder::vil_blob_finder()
00013   : i_((unsigned int)(-1)),j_((unsigned int)(-1)) {} // certainly outside image
00014 
00015 //: Construct to work on image (takes deep copy)
00016 vil_blob_finder::vil_blob_finder(const vil_image_view<bool>& image)
00017   : i_(0),j_(0)
00018 {
00019   image_.deep_copy(image);
00020 }
00021 
00022 //: Define image to work on (deep copy taken)
00023 void vil_blob_finder::set_image(const vil_image_view<bool>& image)
00024 {
00025   i_=0; j_=0;
00026   image_.deep_copy(image);
00027 }
00028 
00029 //: Define image to work on and use as workspace
00030 //  Image will be erased during process. Avoids the copy in set_image()
00031 void vil_blob_finder::set_work_image(vil_image_view<bool>& image)
00032 {
00033   i_=0; j_=0;
00034   image_ = image;
00035 }
00036 
00037 //: Delete region in image with boundary (bi,bj)
00038 void delete_blob(vil_image_view<bool>& image,
00039                  const vcl_vector<int>& bi, const vcl_vector<int>& bj)
00040 {
00041   const unsigned n = bi.size();
00042   const unsigned ni = image.ni();
00043   for (unsigned k=0;k<n;++k)
00044   {
00045     int j = bj[k];
00046 
00047     // Delete all neighbours to the right
00048     unsigned int i = bi[k];
00049     while (i<ni && image(i,j)) image(i++,j)=false;
00050 
00051     // Delete all neighbours to the left
00052     i=bi[k];
00053     while (i>0 && image(i-1,j)) image(--i,j)=false;
00054   }
00055 }
00056 
00057 //: Get boundary pixels of next blob in current image.
00058 // Uses four connected boundary representation.
00059 // Return false if no more regions
00060 bool vil_blob_finder::next_4con_region(vcl_vector<int>& bi, vcl_vector<int>& bj)
00061 {
00062   // Start from current pixel (i_,j_), run over rows until matching pixel found
00063   for (; j_<image_.nj(); ++j_,i_=0)
00064   {
00065     for (; i_<image_.ni(); ++i_)
00066     {
00067       if (image_(i_,j_))
00068       {
00069         vil_trace_4con_boundary(bi,bj,image_,i_,j_);
00070          // Delete blob by flood filling it with false
00071         vil_flood_fill4(image_,bi[0],bj[0],true,false);
00072         return true;
00073       }
00074     }
00075   }
00076 
00077   return false;  // Reached end of image without finding another blob
00078 }
00079 
00080 //: Get pixels of next blob in current image.
00081 // Uses four connected boundary representation.
00082 // Return false if no more regions
00083 bool vil_blob_finder::next_4con_region(vcl_vector<vil_chord>& region)
00084 {
00085   region.resize(0);
00086   // Start from current pixel (i_,j_), run over rows until matching pixel found
00087   for (; j_<image_.nj(); ++j_,i_=0)
00088   {
00089     for (; i_<image_.ni(); ++i_)
00090     {
00091       if (image_(i_,j_))
00092       {
00093          // Delete blob by flood filling it with false
00094         vil_flood_fill4(image_,i_,j_,true,false,region);
00095         return true;
00096       }
00097     }
00098   }
00099 
00100   return false;  // Reached end of image without finding another blob
00101 }
00102 
00103 //: Get pixels of next blob in current image.
00104 // Uses 8 connected boundary representation.
00105 // Return false if no more regions
00106 bool vil_blob_finder::next_8con_region(vcl_vector<vil_chord>& region)
00107 {
00108   region.resize(0);
00109   // Start from current pixel (i_,j_), run over rows until matching pixel found
00110   for (; j_<image_.nj(); ++j_,i_=0)
00111   {
00112     for (; i_<image_.ni(); ++i_)
00113     {
00114       if (image_(i_,j_))
00115       {
00116          // Delete blob by flood filling it with false
00117         vil_flood_fill8(image_,i_,j_,true,false,region);
00118         return true;
00119       }
00120     }
00121   }
00122 
00123   return false;  // Reached end of image without finding another blob
00124 }
00125 
00126 //: Get longest blob boundary in current image
00127 //  Assumes image has been initialised, and that next_4con_region not
00128 //  yet called.  Erases internal image during this call, so any
00129 //  subsequent calls will not work.
00130 void vil_blob_finder::longest_4con_boundary(vcl_vector<int>& bi, vcl_vector<int>& bj)
00131 {
00132   bi.resize(0); bj.resize(0);
00133   vcl_vector<int> tmp_bi,tmp_bj;
00134   while (next_4con_region(tmp_bi,tmp_bj))
00135   {
00136     if (tmp_bi.size()>bi.size())
00137     {
00138       vcl_swap(bi,tmp_bi);
00139       vcl_swap(bj,tmp_bj);
00140     }
00141   }
00142 }
00143 
00144 //: Get number of blobs in given image
00145 unsigned vil_blob_finder::n_4con_regions(const vil_image_view<bool>& image)
00146 {
00147   set_image(image);
00148   unsigned n=0;
00149   vcl_vector<int> tmp_bi,tmp_bj;
00150   while (next_4con_region(tmp_bi,tmp_bj)) n++;
00151   return n;
00152 }
00153 
00154 
00155 //-----------------------------------------------------
00156 
00157 //: Get boundary pixels of next blob in current image.
00158 // Uses four connected boundary representation.
00159 // Return false if no more regions
00160 bool vil_blob_finder::next_8con_region(vcl_vector<int>& bi, vcl_vector<int>& bj)
00161 {
00162   // Start from current pixel (i_,j_), run over rows until matching pixel found
00163   for (; j_<image_.nj(); ++j_,i_=0)
00164   {
00165     for (; i_<image_.ni(); ++i_)
00166     {
00167       if (image_(i_,j_))
00168       {
00169         vil_trace_8con_boundary(bi,bj,image_,i_,j_);
00170          // Delete blob by flood filling it with false
00171         vil_flood_fill8(image_,bi[0],bj[0],true,false);
00172         return true;
00173       }
00174     }
00175   }
00176 
00177   return false;  // Reached end of image without finding another blob
00178 }
00179 
00180 //: Get longest blob boundary in current image
00181 //  Assumes image has been initialised, and that next_8con_region not
00182 //  yet called.  Erases internal image during this call, so any
00183 //  subsequent calls will not work.
00184 void vil_blob_finder::longest_8con_boundary(vcl_vector<int>& bi, vcl_vector<int>& bj)
00185 {
00186   bi.resize(0); bj.resize(0);
00187   vcl_vector<int> tmp_bi,tmp_bj;
00188   while (next_8con_region(tmp_bi,tmp_bj))
00189   {
00190     if (tmp_bi.size()>bi.size())
00191     {
00192       vcl_swap(bi,tmp_bi);
00193       vcl_swap(bj,tmp_bj);
00194     }
00195   }
00196 }
00197 
00198 //: Get largest blob region in current image
00199 unsigned vil_blob_finder::largest_8con_region(vcl_vector<vil_chord>& region)
00200 {
00201   region.resize(0); 
00202   vcl_vector<vil_chord> tmp_region;
00203   unsigned max_area=0;
00204   while (next_8con_region(tmp_region))
00205   {
00206     unsigned area = vil_area(tmp_region);
00207     if (area>max_area)
00208     {
00209       vcl_swap(region,tmp_region);
00210       max_area=area;
00211     }
00212   }
00213   return max_area;
00214 }
00215 
00216 //: Get largest blob region in current image
00217 unsigned vil_blob_finder::largest_4con_region(vcl_vector<vil_chord>& region)
00218 {
00219   region.resize(0); 
00220   vcl_vector<vil_chord> tmp_region;
00221   unsigned max_area=0;
00222   while (next_4con_region(tmp_region))
00223   {
00224     unsigned area = vil_area(tmp_region);
00225     if (area>max_area)
00226     {
00227       vcl_swap(region,tmp_region);
00228       max_area=area;
00229     }
00230   }
00231   return max_area;
00232 }
00233 
00234 //: Get number of blobs in given image
00235 unsigned vil_blob_finder::n_8con_regions(const vil_image_view<bool>& image)
00236 {
00237   set_image(image);
00238   unsigned n=0;
00239   vcl_vector<int> tmp_bi,tmp_bj;
00240   while (next_8con_region(tmp_bi,tmp_bj)) n++;
00241   return n;
00242 }
00243 
00244 

Generated on Sat Nov 22 05:07:50 2008 for core/vil by  doxygen 1.5.1