00001 /*!@file Gist/ContourBoundaryDetector.H Detect meaningful contours by 00002 weighting longer countour chains more */ 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Christian Siagian <siagian@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Gist/ContourBoundaryDetector.H $ 00035 // $Id: $ 00036 // 00037 ////////////////////////////////////////////////////////////////////////// 00038 // 00039 // Detect meaningful contours by weighting longer countour chains more 00040 // 00041 // Based on Hidayat's Variance Ridge boundary detector. 00042 // However, we thin and parameterize the boundary to contours. 00043 // 00044 // 00045 // Real-time texture boundary detection from ridges 00046 // in the standard deviation space 00047 // Ray Hidayat and Richard Green 00048 // BMCV 2009 00049 00050 #ifndef CONTOUR_BOUNDARY_DETECTOR 00051 #define CONTOUR_BOUNDARY_DETECTOR 00052 00053 #define NUM_GRADIENT_DIRECTIONS 8 00054 #define NUM_RIDGE_DIRECTIONS NUM_GRADIENT_DIRECTIONS/2 00055 #define BOUNDARY_STEP_SIZE NUM_GRADIENT_DIRECTIONS 00056 #define DEFAULT_NEIGHBORHOOD_RAD 8 00057 00058 #include "Image/Image.H" 00059 #include "Raster/Raster.H" 00060 00061 #include "GUI/XWinManaged.H" 00062 00063 struct Edgel 00064 { 00065 Edgel() { }; 00066 00067 Edgel(const Point2D<int> inPt, 00068 const float inAngle, 00069 const int inAngleIndex, 00070 const float inVal) : 00071 pt(inPt), 00072 angle(inAngle), 00073 angleIndex(inAngleIndex), 00074 val(inVal) 00075 { 00076 } 00077 00078 Point2D<int> pt; 00079 float angle; 00080 int angleIndex; // -1 means no value 00081 float val; 00082 00083 bool operator < (const Edgel& e) 00084 { 00085 return val < e.val; 00086 } 00087 }; 00088 00089 struct Contour 00090 { 00091 Contour() { }; 00092 00093 Contour(const std::vector<rutz::shared_ptr<Edgel> > inEdgels) : 00094 edgels(inEdgels) 00095 { 00096 } 00097 00098 std::vector<rutz::shared_ptr<Edgel> > edgels; 00099 }; 00100 00101 00102 //! Contour boundary detector implementing: 00103 //! Real-time texture boundary detection from ridges 00104 //! in the standard deviation space 00105 //! Ray Hidayat and Richard Green 00106 //! BMCV 2009 00107 class ContourBoundaryDetector 00108 { 00109 public: 00110 00111 // ###################################################################### 00112 //! @name Constructor, assigment and destructor 00113 //@{ 00114 00115 //! constructor 00116 ContourBoundaryDetector(); 00117 00118 //! destructor 00119 ~ContourBoundaryDetector(); 00120 00121 //@} 00122 00123 // ###################################################################### 00124 //! @name Compute functions 00125 //@{ 00126 00127 //! the full procedure to calculate 00128 //! contour boundary 00129 void computeContourBoundary 00130 (Image<PixRGB<byte> > ima, int r = -1); 00131 00132 //! get the variance ridge boundary 00133 Image<float> getVarianceRidgeBoundaryMap 00134 (Image<PixRGB<byte> > ima, int r = -1); 00135 00136 //! get the contour boundary map 00137 //! assume computeContourBoundary or 00138 //! or other compute functions that includes 00139 //! variance ridge boundary map computation 00140 //! is already called on the same image 00141 Image<float> getVarianceRidgeBoundaryMap(); 00142 00143 //! get the Non-max Suppressed 00144 //! Variance Ridge (VR) boundary 00145 Image<float> getNmsBoundaryMap 00146 (Image<PixRGB<byte> > ima, int r = -1); 00147 00148 //! get the non-max suppressed VR boundary map 00149 //! assume computeContourBoundary or 00150 //! or other necessary compute functions, which includes 00151 //! Non-max Suppressed VR boundary map computation 00152 //! is already called on the same image 00153 Image<float> getNmsBoundaryMap(); 00154 00155 // get the contour boundary edgels 00156 Image<float> getEdgelBoundaryMap 00157 (Image<PixRGB<byte> > ima, int r = -1); 00158 00159 //! get the non-max suppressed VR boundary map 00160 //! assume computeContourBoundary or 00161 //! or other necessary compute functions, which includes 00162 //! edgel boundary map computation 00163 //! is already called on the same image 00164 Image<float> getEdgelBoundaryMap(); 00165 00166 //! get the contour boundary map 00167 Image<PixRGB<byte> > getContourBoundaryMap 00168 (Image<PixRGB<byte> > ima, int r = -1); 00169 00170 //! get the contour boundary map 00171 //! assume computeContourBoundary or 00172 //! or other necessary compute functions, which includes 00173 //! contour boundary map computation 00174 //! are already called on the same image 00175 Image<PixRGB<byte> > getContourBoundaryMap(); 00176 00177 //! display the gradient magnitude image 00178 void displayGradImage(std::vector<Image<float> > gradImg); 00179 00180 //@} 00181 00182 // ###################################################################### 00183 //! @name Access functions 00184 //@{ 00185 00186 //! get contour boundaries 00187 inline std::vector<rutz::shared_ptr<Contour> > getContourBoundaries(); 00188 00189 //@} 00190 00191 private: 00192 00193 // ###################################################################### 00194 //! @name Compute functions (all the inner-working functions) 00195 //@{ 00196 00197 //! compute the Variance Ridge Boundary map 00198 void computeVarianceRidgeBoundaryMap(); 00199 00200 //! compute the non-max suppressed 00201 //! variance ridge boundary map 00202 void computeNmsBoundaryMap(); 00203 00204 //! compute the contour boundary edgels 00205 void computeContourBoundaryEdgels(); 00206 00207 //! compute the contour boundary map 00208 void computeContourBoundaryMap(); 00209 00210 //! calculate the local standard deviation of the image 00211 Image<float> getLabStandardDeviation 00212 (Image<PixRGB<byte> > ima, int r = 8); 00213 00214 //! VarianceRidgeDetector: box-blur the image for local mean 00215 Image<float> boxBlur 00216 (Image<float> ridgeImg, int rad); 00217 00218 //! VarianceRidgeDetector: square combine the Lab channels 00219 Image<float> sqCombine 00220 (Image<float> a, Image<float> b, Image<float> c); 00221 00222 //! VarianceRidgeDetector: 00223 //! calculate gradient of the standard dev. image 00224 std::vector<Image<float> > calculateGradient 00225 (Image<float> varImg, int r = 8); 00226 00227 //! VarianceRidgeDetector: 00228 //! compute the ridge of the gradient image 00229 Image<float> getRidge 00230 (std::vector<Image<float> > gradImg, int r = 8); 00231 00232 //! substract the gradient magnitude from the ridge image 00233 Image<float> substractGradImg 00234 (Image<float> ridgeImg, std::vector<Image<float> > gradImg); 00235 00236 //! compute the contour boundary edgels 00237 Image<float> getContourBoundaryEdgels(); 00238 00239 //! compute the non-max suppresion image 00240 Image<float> getNonMaxSuppression(Image<float> bImg); 00241 00242 //! group the boundary edgels to contours 00243 void connectContourEdgels(); 00244 00245 //! check if the contour can be lengthened with the new edgel 00246 bool addEdgelToContour 00247 (int &i, int &j, 00248 rutz::shared_ptr<Edgel> &edgel, 00249 rutz::shared_ptr<Contour> &contour, 00250 int sign); 00251 00252 //! get the location of where to look for next edgels 00253 //! given a direction 00254 void getEdgelDirectionNeighborhood 00255 (int ci, int cj, int dir, int sign, 00256 int &ni1, int &nj1, int &ni2, int &nj2, int &ni3, int &nj3); 00257 00258 //! given two edgels 00259 //! figure out if the they can be connected 00260 bool isLegalDirection 00261 (int ci, int cj, int cd, int sign, 00262 int ni, int nj, int nd); 00263 00264 //! create an image representation of the contours 00265 Image<PixRGB<byte> > getContourBoundaryImage(); 00266 00267 //! display contour boundary 1 contour at a time 00268 void displayContourBoundary(); 00269 00270 //@} 00271 00272 //! its current input image 00273 Image<PixRGB<byte> > itsImage; 00274 00275 //! the radius of considered neighborhood 00276 int itsRadius; 00277 00278 //! the ridge direction map 00279 std::vector<Image<float> > itsRidgeDirection; 00280 00281 //! the maximum values (for each pixel) of the ridge direction map 00282 std::vector<Image<float> > itsRidgeDirectionMax; 00283 00284 //! the winning index (for each pixel) of the ridge direction map 00285 Image<float> itsRidgeDirectionIndex; 00286 00287 //! boundary map image (from Variance Ridge Detector) 00288 Image<float> itsBoundaryImage; 00289 00290 //! the ridge direction map 00291 std::vector<Image<float> > itsRidgeDirectionNMS; 00292 00293 //! the non-max suppressed version of the boundary map 00294 //! We use our own 5x5 kernel 00295 Image<float> itsBoundaryImageNMS; 00296 00297 //! the raw gradient standard deviation values 00298 std::vector<std::vector<Image<float> > > itsDVin; 00299 00300 //! list of edgels in all RF edgel locations 00301 Image<std::vector<rutz::shared_ptr<Edgel> > > itsEdgels; 00302 00303 //! edgel boundary map image 00304 Image<float> itsEdgelBoundaryImage; 00305 00306 //! the list of contour Boundaries 00307 std::vector<rutz::shared_ptr<Contour> > itsContourBoundaries; 00308 00309 //! contour storage based on location 00310 Image<rutz::shared_ptr<Contour> > itsContourMap; 00311 00312 //! contour boundary image 00313 Image<PixRGB<byte> > itsContourBoundaryImage; 00314 00315 //! region segmentation image 00316 Image<PixRGB<byte> > itsRegionSegmentationImage; 00317 00318 //! debug window 00319 rutz::shared_ptr<XWinManaged> itsWin; 00320 }; 00321 00322 // ###################################################################### 00323 // Implementation for ContourBoundaryDetector inline functions 00324 // ###################################################################### 00325 inline std::vector<rutz::shared_ptr<Contour> > 00326 ContourBoundaryDetector::getContourBoundaries() 00327 { return itsContourBoundaries; } 00328 00329 #endif 00330 00331 // ###################################################################### 00332 /* So things look consistent in everyone's emacs... */ 00333 /* Local Variables: */ 00334 /* indent-tabs-mode: nil */ 00335 /* End: */