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_