00001 00002 /*!@file Gist/test-SuperPixel.C testing SuperPixel segmentation algorithm */ 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 // d // 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/test-SuperPixel.C $ 00035 // $Id: test-SuperPixel.C 12962 2010-03-06 02:13:53Z irock $ 00036 // 00037 ////////////////////////////////////////////////////////////////////////// 00038 // 00039 // Implementation of boundary detection algorithm described in: 00040 // 00041 // Real-time texture boundary detection from ridges 00042 // in the standard deviation space 00043 // Ray Hidayat and Richard Green 00044 // BMCV 2009 00045 00046 #ifndef TEST_VARIANCE_RIDGE_DETECTOR 00047 #define TEST_VARIANCE_RIDGE_DETECTOR 00048 00049 //#include "Image/OpenCVUtil.H" 00050 00051 #include "Component/ModelManager.H" 00052 #include "Media/FrameSeries.H" 00053 #include "Transport/FrameIstream.H" 00054 00055 #include "Raster/Raster.H" 00056 #include "Image/CutPaste.H" // for inplacePaste() 00057 #include "Image/LowPass.H" 00058 00059 #include "Image/ColorOps.H" 00060 #include "Image/MathOps.H" 00061 00062 00063 00064 #include "Image/DrawOps.H" 00065 #include "Image/Kernels.H" 00066 #include "Image/FilterOps.H" 00067 00068 #include "Image/ImageSet.H" 00069 #include "Image/PyramidOps.H" 00070 #include "Raster/Raster.H" 00071 00072 #include "Util/Timer.H" 00073 #include <cstdio> 00074 00075 #include "Gist/ContourBoundaryDetector.H" 00076 00077 Image<float> getGabor(Image<float> img, 00078 float angle, float filter_period, 00079 float elongation, int size); 00080 00081 //Image<float> getCanny(Image<byte> img); 00082 00083 00084 00085 int main(int argc, char **argv) 00086 { 00087 // instantiate a model manager: 00088 ModelManager manager("test VRD Boundary Detection"); 00089 00090 // Instantiate our various ModelComponents: 00091 00092 nub::soft_ref<InputFrameSeries> ifs(new InputFrameSeries(manager)); 00093 manager.addSubComponent(ifs); 00094 00095 nub::soft_ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager)); 00096 manager.addSubComponent(ofs); 00097 00098 rutz::shared_ptr<ContourBoundaryDetector> 00099 cbd(new ContourBoundaryDetector()); 00100 00101 manager.exportOptions(MC_RECURSE); 00102 00103 // Parse command-line: 00104 if (manager.parseCommandLine(argc, argv, "[window_size] ", 0, 1) 00105 == false) return(1); 00106 00107 // get the operation mode 00108 int r = 8; 00109 if(manager.numExtraArgs() > 0) 00110 r = manager.getExtraArgAs<uint>(0); 00111 00112 // let's do it! 00113 manager.start(); 00114 00115 ifs->updateNext(); 00116 Image<PixRGB<byte> > ima = ifs->readRGB(); 00117 // ima = Image<PixRGB<byte> >(ima.getDims(),ZEROS); 00118 // drawFilledRect(ima, 00119 // Rectangle(Point2D<int>(180, 100), Dims(100, 100)), 00120 // PixRGB<byte>(255,0,0)); 00121 00122 Image<float> fIma(luminance(ima)); 00123 Image<float> tempFIma = fIma; 00124 inplaceNormalize(tempFIma, 0.0f,255.0f); 00125 Image<byte> bIma(tempFIma); 00126 00127 Timer timer(1000000); timer.reset(); 00128 Image<float> boundaryMap = cbd->getVarianceRidgeBoundaryMap(ima, r); 00129 LINFO("time: %f ms", timer.get()/1000.0); 00130 00131 // get non-max suppressed boundary map image 00132 00133 float mVal = 32; 00134 float bVal = 255 - mVal; 00135 inplaceNormalize(boundaryMap, 0.0f,bVal); 00136 Image<byte> dBmapc(boundaryMap); 00137 00138 Image<byte> dImaR, dImaG, dImaB; 00139 getComponents(ima, dImaR, dImaG, dImaB); 00140 inplaceNormalize(dImaR, byte(0), byte(mVal)); 00141 inplaceNormalize(dImaG, byte(0), byte(mVal)); 00142 inplaceNormalize(dImaB, byte(0), byte(mVal)); 00143 Image<PixRGB<byte> > dBmap = toRGB(dBmapc); 00144 Image<PixRGB<byte> > dIma = makeRGB(dImaR,dImaG,dImaB); 00145 00146 // the non-max suppressed boundary map image 00147 Image<float> dBmapNMStemp = cbd->getNmsBoundaryMap(); 00148 inplaceNormalize(dBmapNMStemp, 0.0F, 255.0F); 00149 Image<PixRGB<byte> > dBmapNMS = toRGB(Image<byte>(dBmapNMStemp)); 00150 00151 // the contour boundary map image 00152 Image<float> dCBmapTemp = cbd->getEdgelBoundaryMap(); 00153 inplaceNormalize(dCBmapTemp, 0.0F, bVal); 00154 Image<PixRGB<byte> > dCBmap = toRGB(Image<byte>(dCBmapTemp)); 00155 00156 // setup the display map 00157 uint w = ima.getWidth(); 00158 uint h = ima.getHeight(); 00159 Image<PixRGB<byte> > dispIma(4*w,2*h,ZEROS); 00160 inplacePaste(dispIma, ima, Point2D<int>(0,0)); 00161 inplacePaste(dispIma, Image<PixRGB<byte> >(dBmap), Point2D<int>(w,0)); 00162 //inplacePaste(dispIma, Image<PixRGB<byte> >(dIma+dBmap), Point2D<int>(w,0)); 00163 inplacePaste(dispIma, dBmapNMS, Point2D<int>(0,h)); 00164 inplacePaste(dispIma, Image<PixRGB<byte> >(dIma+dCBmap), Point2D<int>(w,h)); 00165 inplacePaste(dispIma, cbd->getContourBoundaryMap(), Point2D<int>(2*w,0)); 00166 00167 // angle at 4th param: 0 degrees 00168 //Image<float> gaborImg = getGabor(fIma, 0.0, 2.50, 1.0, 5); 00169 // Image<float> gaborImg = getGabor(fIma,0,7,1,9); 00170 // -------------- 00171 // Image<float> gaborImg = getCanny(fIma); 00172 // inplaceNormalize(gaborImg, 0.0F, 255.0F); 00173 // Image<PixRGB<byte> > dGaborImg = toRGB(Image<byte>(gaborImg)); 00174 // inplacePaste(dispIma, Image<PixRGB<byte> >(dGaborImg), 00175 // Point2D<int>(w,h)); 00176 00177 // Image<float> rDir0 = itsRDirMax[0]; 00178 // inplaceNormalize(rDir0, 0.0F, 255.0F); 00179 // Image<PixRGB<byte> > dRDir0 = toRGB(Image<byte>(rDir0)); 00180 // inplacePaste(dispIma, dRDir0, Point2D<int>(2*w,0)); 00181 00182 // Image<float> rDir1 = itsRDirMax[1]; 00183 // inplaceNormalize(rDir1, 0.0F, 255.0F); 00184 // Image<PixRGB<byte> > dRDir1 = toRGB(Image<byte>(rDir1)); 00185 // inplacePaste(dispIma, dRDir1, Point2D<int>(3*w,0)); 00186 00187 // Image<float> rDir2 = itsRDirMax[2]; 00188 // inplaceNormalize(rDir2, 0.0F, 255.0F); 00189 // Image<PixRGB<byte> > dRDir2 = toRGB(Image<byte>(rDir2)); 00190 // inplacePaste(dispIma, dRDir2, Point2D<int>(2*w,h)); 00191 00192 // Image<float> rDir3 = itsRDirMax[3]; 00193 // inplaceNormalize(rDir3, 0.0F, 255.0F); 00194 // Image<PixRGB<byte> > dRDir3 = toRGB(Image<byte>(rDir3)); 00195 // inplacePaste(dispIma, dRDir3, Point2D<int>(3*w,h)); 00196 00197 // 300, 140 00198 drawRect(dispIma, 00199 Rectangle(Point2D<int>(w+156, 68), Dims(8, 8)), 00200 PixRGB<byte>(255,0,0)); 00201 drawRect(dispIma, 00202 Rectangle(Point2D<int>(w+152, 64), Dims(16, 16)), 00203 PixRGB<byte>(255,255,0)); 00204 00205 drawRect(dispIma, 00206 Rectangle(Point2D<int>(156, h+68), Dims(8, 8)), 00207 PixRGB<byte>(255,0,0)); 00208 drawRect(dispIma, 00209 Rectangle(Point2D<int>(152, h+64), Dims(16, 16)), 00210 PixRGB<byte>(255,255,0)); 00211 00212 //ofs->writeRGB(boundaryMap, "VRD Boundary Detection"); 00213 ofs->writeRGB(dispIma, "VRD Boundary Detection"); 00214 ofs->updateNext(); 00215 Raster::waitForKey(); 00216 00217 return 0; 00218 } 00219 00220 // ###################################################################### 00221 Image<float> getGabor 00222 (Image<float> img, float angle, float filter_period, 00223 float elongation, int size) 00224 { 00225 const double major_stddev = filter_period / 3.0; 00226 const double minor_stddev = major_stddev * elongation; 00227 00228 // We have to add 90 to the angle here when constructing the gabor 00229 // filter. That's because the angle used to build the gabor filter 00230 // actually specifies the direction along which the grating 00231 // varies. This direction is orthogonal to the the direction of the 00232 // contours that the grating will detect. 00233 const double theta = angle + 90.0f; 00234 00235 // In concept, we want to filter with four phases of the filter: odd 00236 // on+off, and even on+off (that would be xox, oxo, xo, and ox). But 00237 // since the on version just produces the negation of the off version, 00238 // we can get the summed output of both by just taking the absolute 00239 // value of the outputs of one of them. So we only need to convolve 00240 // with the filter in two phases, then take the absolute value (i.e., 00241 // we're doing |xox| and |xo|). 00242 00243 Image<float> g0 = gaborFilter3(major_stddev, minor_stddev, 00244 filter_period, 0.0f, theta, size); 00245 Image<float> g90 = gaborFilter3(major_stddev, minor_stddev, 00246 filter_period, 90.0f, theta, size); 00247 00248 LDEBUG("angle = %.2f, period = %.2f pix, size = %dx%d pix", 00249 angle, filter_period, g0.getWidth(), g0.getHeight()); 00250 00251 Image<float> f0, f90; 00252 Image<float> result(img.getDims(), NO_INIT); 00253 00254 Image<float> temp = energyNorm(img); 00255 f0 = optConvolve(temp, g0); 00256 f90 = optConvolve(temp, g90); 00257 00258 result = f0 + f90; 00259 00260 return result; 00261 } 00262 00263 // // ###################################################################### 00264 // Image<float> getCanny(Image<byte> img) 00265 // { 00266 // Image<float> ret; 00267 // IplImage *cvImg = cvCreateImage(cvGetSize(img2ipl(img)),8,1); 00268 // int ap = 7; 00269 // cvCanny(img2ipl(img),cvImg, ap*ap*100, ap*ap*200, 7); 00270 // return ipl2gray(cvImg); 00271 // } 00272 00273 #endif 00274 00275 // ###################################################################### 00276 /* So things look consistent in everyone's emacs... */ 00277 /* Local Variables: */ 00278 /* indent-tabs-mode: nil */ 00279 /* End: */