contrib/brl/bseg/bmdl/bmdl_classify.h
Go to the documentation of this file.
00001 // This is brl/bseg/bmdl/bmdl_classify.h
00002 #ifndef bmdl_classify_h_
00003 #define bmdl_classify_h_
00004 //:
00005 // \file
00006 // \brief Classify each pixel in lidar images
00007 //
00008 // \author Matt Leotta
00009 // \date Oct. 14, 2008
00010 
00011 #include <vcl_vector.h>
00012 #include <vil/vil_image_view.h>
00013 
00014 template <class T>
00015 class bmdl_classify
00016 {
00017  public:
00018   //: Constructor
00019   // \param height_noise_stdev is the standard deviation in lidar height
00020   //        This parameter can be set manually or estimated
00021   // \param area_threshold is the minimum area allowed for buildings
00022   // \param height_resolution is the height difference below which buildings are merged
00023   // \param gnd_threshold is the minimum height above the ground considered for buildings and vegetation
00024   // \param veg_threshold is the minimum distance between first and last returns for vegetation
00025   bmdl_classify(unsigned int area_threshold = 6,
00026                 T height_resolution = 0.5,
00027                 T gnd_threshold = 2.0,
00028                 T veg_threshold_ = 1.0);
00029 
00030   //: Set the first and last return images
00031   void set_lidar_data(const vil_image_view<T>& first_return,
00032                       const vil_image_view<T>& last_return);
00033 
00034   //: Set the bare earth image
00035   void set_bare_earth(const vil_image_view<T>& bare_earth);
00036 
00037   //: Estimate a constant bare earth model
00038   // This function returns the constant height
00039   // and also uses it to fill the bare earth image
00040   T estimate_bare_earth();
00041 
00042   //: Estimate the standard deviation in height due to noise
00043   //  Returns the estimate and stores it internally for later use
00044   T estimate_height_noise_stdev();
00045 
00046   //: Manually specify the standard deviation in lidar height from noise
00047   // \note This parameter is not currently used.  Use ground and vegetation thresholds instead.
00048   void set_height_noise_stdev(T stdev) { hgt_stdev_ = stdev; }
00049   //: Specify the building area threshold
00050   void set_area_threshold(unsigned int area) { area_threshold_ = area; }
00051   //: Specify the ground threshold
00052   void set_ground_threshold(T gnd_threshold) { gnd_threshold_ = gnd_threshold; }
00053   //: Specify the vegetation threshold
00054   void set_vegetation_threshold(T veg_threshold) { veg_threshold_ = veg_threshold; }
00055 
00056   //: Access the first returns image
00057   const vil_image_view<T>& first_return() const {return first_return_;}
00058 
00059   //: Access the last returns image
00060   const vil_image_view<T>& last_return() const {return last_return_;}
00061 
00062   //: Access the bare earth image
00063   const vil_image_view<T>& bare_earth() const {return bare_earth_;}
00064 
00065   //: Access the minimum height in the first return image
00066   T first_min() const {return first_min_;}
00067   //: Access the maximum height in the first return image
00068   T first_max() const {return first_max_;}
00069   //: Access the minimum height in the last return image
00070   T last_min() const {return last_min_;}
00071   //: Access the maximum height in the last return image
00072   T last_max() const {return last_max_;}
00073 
00074   //: Classify each pixel as Ground (0), Vegetation (1), or Building (>=2)
00075   // Each building is given an index sequentially starting with 2
00076   // and sorted by mean height.
00077   // \note This is the main function you should call, it runs all the steps
00078   void label_lidar();
00079 
00080   //: Perform an initial segmentation at each pixel using thresholds
00081   // Classify each pixel as Ground (0), Vegetation (1), or Building (2)
00082   // Results are stored in the labels image
00083   void segment();
00084 
00085   //: Cluster pixels on buildings into groups of adjacent pixels with similar heights.
00086   //  Assign a new label to each groups.
00087   //  Returns building mean heights and pixel counts by reference
00088   void cluster_buildings();
00089 
00090   //: Replace small holes in buildings from ground to vegetation (unclaimed) labels
00091   // Holes are switch if area is less than \a min_size
00092   void fill_ground_holes(unsigned int min_size);
00093 
00094   //: Threshold buildings by area.
00095   // All buildings with area (in pixels) less than the threshold
00096   // are removed and replace with a vegetation label.
00097   void threshold_building_area();
00098 
00099   //: Dilate buildings into unclaimed (vegetation) pixel
00100   //  Only claim a vegetation pixel if surrounded by
00101   //  \a num pixels from the same building
00102   bool dilate_buildings(unsigned int num=6);
00103 
00104   //: Greedy merging of adjacent buildings
00105   bool greedy_merge();
00106 
00107   //: Refine the building regions
00108   void refine_buildings();
00109 
00110   //: Access the resulting label image
00111   const vil_image_view<unsigned int>& labels() const { return labels_; }
00112 
00113   //: Access the resulting height image
00114   const vil_image_view<T>& heights() const { return heights_; }
00115   //: Access the mean building heights
00116   const vcl_vector<T>& mean_heights() const { return building_mean_hgt_; }
00117   //: Access the building areas in pixels
00118   const vcl_vector<unsigned int>& building_area() const { return building_area_; }
00119 
00120  private:
00121   //: A helper class to manage merging of buildings
00122   class merge_map
00123   {
00124    public:
00125     //: Constructor
00126     merge_map(bmdl_classify<T>* c);
00127     //: Destructor - simplify merge map and apply to classifier
00128     ~merge_map();
00129     //: translate old index to temporary merged index
00130     unsigned int translate(unsigned int idx) const;
00131     //: merge two indices
00132     void merge(unsigned int idx1, unsigned int idx2);
00133    private:
00134     bmdl_classify<T>* classifier_;
00135     vcl_vector<unsigned int> idx_map_;
00136   };
00137 
00138   friend class merge_map;
00139 
00140   //: Parabolic interpolation of 3 points \p y_0, \p y_1, \p y_2
00141   //  \returns the peak value by reference in \p y_peak
00142   //  \returns the peak location offset from the x of \p y_0
00143   T interpolate_parabola(T y_1, T y_0, T y_2, T& root_offset) const;
00144 
00145   //: Compute a histogram of the data
00146   // Does not reset the initial bin values to zero
00147   void histogram(const vcl_vector<T>& data, vcl_vector<unsigned int>& bins,
00148                  T minv, T maxv) const;
00149 
00150   //: Find the maximum peak in the data and fit a gaussian to it
00151   // Search in the range \a minv to \a maxv
00152   void fit_gaussian_to_peak(const vcl_vector<T>& data, T minv, T maxv,
00153                             T& mean, T& stdev) const;
00154 
00155   //: Expand the range (minv, maxv) with the data in \a image
00156   // Only finite values count
00157   void range(const vil_image_view<T>& image,
00158              T& minv, T& maxv) const;
00159 
00160   //: Search for nearby pixel that can be added to each building
00161   //  Return true if any changes are made
00162   bool expand_buildings(vcl_vector<T>& means,
00163                         vcl_vector<unsigned int>& sizes);
00164 
00165   //: Group building pixel by height into bins of size \a binsize
00166   vil_image_view<unsigned int> bin_heights(T binsize = 0.5);
00167 
00168 
00169   //: Morphological clean up on each building independently
00170   vcl_vector<bool> close_buildings(unsigned int num_labels);
00171 
00172   //: first return image
00173   vil_image_view<T> first_return_;
00174   //: last return image
00175   vil_image_view<T> last_return_;
00176   //: bare earth estimate image
00177   vil_image_view<T> bare_earth_;
00178 
00179   //: The estimated standard deviation of noise in height
00180   T hgt_stdev_;
00181   //: A threshold on the minimum building area
00182   unsigned int area_threshold_;
00183   //: The minimum height difference that does not merge
00184   T height_resolution_;
00185   //: The minimum height above the ground for buildings
00186   T gnd_threshold_;
00187   //: The minimum distance between first and last returns for vegetation
00188   T veg_threshold_;
00189   //: The range spanned by the first returns
00190   T first_min_, first_max_;
00191   //: The range spanned by the last returns
00192   T last_min_, last_max_;
00193 
00194   //: The mean height of each building
00195   vcl_vector<T> building_mean_hgt_;
00196   //: The area in pixels of each building
00197   vcl_vector<unsigned int> building_area_;
00198 
00199   //: computed segmentation labels
00200   vil_image_view<unsigned int> labels_;
00201   //: clean up height estimates for use in meshing
00202   vil_image_view<T> heights_;
00203 };
00204 
00205 #endif // bmdl_classify_h_