00001 /*!@file Features/ColorHist.C */ 00002 00003 00004 // //////////////////////////////////////////////////////////////////// // 00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00006 // by the University of Southern California (USC) and the iLab at USC. // 00007 // See http://iLab.usc.edu for information about this project. // 00008 // //////////////////////////////////////////////////////////////////// // 00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00011 // in Visual Environments, and Applications'' by Christof Koch and // 00012 // Laurent Itti, California Institute of Technology, 2001 (patent // 00013 // pending; application number 09/912,225 filed July 23, 2001; see // 00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00015 // //////////////////////////////////////////////////////////////////// // 00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00017 // // 00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00019 // redistribute it and/or modify it under the terms of the GNU General // 00020 // Public License as published by the Free Software Foundation; either // 00021 // version 2 of the License, or (at your option) any later version. // 00022 // // 00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00026 // PURPOSE. See the GNU General Public License for more details. // 00027 // // 00028 // You should have received a copy of the GNU General Public License // 00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00031 // Boston, MA 02111-1307 USA. // 00032 // //////////////////////////////////////////////////////////////////// // 00033 // 00034 // Primary maintainer for this file: Lior Elazary 00035 // $HeadURL$ 00036 // $Id$ 00037 // 00038 00039 #include "Features/ColorHist.H" 00040 #include "Image/DrawOps.H" 00041 #include "Image/MathOps.H" 00042 #include "Image/Kernels.H" 00043 #include "Image/CutPaste.H" 00044 #include "Image/ColorOps.H" 00045 #include "Image/FilterOps.H" 00046 #include "Image/ShapeOps.H" 00047 #include "SIFT/FeatureVector.H" 00048 00049 00050 ColorHist::ColorHist() 00051 { 00052 } 00053 00054 ColorHist::~ColorHist() 00055 { 00056 } 00057 00058 std::vector<float> ColorHist::createFeatureVector(const Image<PixRGB<byte> >& img) 00059 { 00060 00061 if (!img.initialized()) 00062 return std::vector<float>(); 00063 00064 Image<float> lum,rg,by; 00065 getLAB(img, lum, rg, by); 00066 00067 //Smooth the image 00068 Image<float> kernel = gaussian<float>(0.0F, 1.4, lum.getWidth(),1.0F); 00069 Image<float> kernel2 = gaussian<float>(0.0F, 1.4, lum.getWidth(),1.0F); 00070 Image<float> kernel3 = gaussian<float>(0.0F, 1.4, lum.getWidth(),1.0F); 00071 //// do the convolution: 00072 lum = sepFilter(lum, kernel, kernel, CONV_BOUNDARY_CLEAN); 00073 rg = sepFilter(rg, kernel2, kernel2, CONV_BOUNDARY_CLEAN); 00074 by = sepFilter(by, kernel3, kernel3, CONV_BOUNDARY_CLEAN); 00075 00076 00077 std::vector<float> lumFv = createFeatureVector(lum); 00078 std::vector<float> rgFv = createFeatureVector(rg); 00079 std::vector<float> byFv = createFeatureVector(by); 00080 00081 std::vector<float> fv = lumFv; 00082 fv.insert(fv.end(), rgFv.begin(), rgFv.end()); 00083 fv.insert(fv.end(), byFv.begin(), byFv.end()); 00084 00085 return fv; 00086 00087 } 00088 00089 std::vector<float> ColorHist::createFeatureVector(const Image<float>& img) 00090 { 00091 FeatureVector fv; 00092 // check this scale 00093 const int radius = std::min(img.getWidth()/2, img.getHeight()/2); 00094 //const float gausssig = float(radius); // 1/2 width of descript window 00095 //const float gaussfac = -0.5f/(gausssig * gausssig); 00096 00097 const int xi = img.getWidth()/2; 00098 const int yi = img.getHeight()/2; 00099 00100 Image<float> gradmag, gradorie; 00101 gradientSobel(img, gradmag, gradorie); 00102 00103 // Scan a window of diameter 2*radius+1 around the point of 00104 // interest, and we will cumulate local samples into a 4x4 grid 00105 // of bins, with interpolation. NOTE: rx and ry loop over a 00106 // square that is assumed centered around the point of interest. 00107 for (int ry = -radius; ry < radius; ry++) 00108 for (int rx = -radius; rx < radius; rx++) 00109 { 00110 // get the coords in the image frame of reference: 00111 const float orgX = rx + float(xi); 00112 const float orgY = ry + float(yi); 00113 00114 if (! gradmag.coordsOk(orgX, orgY)) // outside image 00115 continue; // forget this coordinate 00116 00117 // find the fractional coords of the corresponding bin 00118 // (we subdivide our window into a 4x4 grid of bins): 00119 const float xf = 2.0f + 2.0f * float(rx)/float(radius); 00120 const float yf = 2.0f + 2.0f * float(ry)/float(radius); 00121 00122 // find the Gaussian weight from distance to center and 00123 // get weighted gradient magnitude: 00124 const float gaussFactor = 1; //expf((rx*rx + ry*ry) * gaussfac); 00125 const float weightedMagnitude = 00126 gaussFactor * gradmag.getValInterp(orgX, orgY); 00127 00128 // get the gradient orientation relative to the keypoint 00129 // orientation and scale it for 8 orientation bins: 00130 float gradAng = gradorie.getValInterp(orgX, orgY); 00131 gradAng=fmod(gradAng, 2*M_PI); //bring the range from 0 to M_PI 00132 00133 //convert from -M_PI to M_PI 00134 if (gradAng < 0.0) 00135 gradAng += 2*M_PI; //convert to -M_PI to M_PI 00136 if (gradAng >= M_PI) 00137 gradAng -= 2*M_PI; 00138 //split to eight bins 00139 const float orient = (gradAng + M_PI) * 8 / (2 * M_PI); 00140 00141 // will be interpolated into 2 x 2 x 2 bins: 00142 fv.addValue(xf, yf, orient, weightedMagnitude); 00143 } 00144 00145 return fv.getFeatureVector(); 00146 00147 } 00148 00149 00150 // ###################################################################### 00151 /* So things look consistent in everyone's emacs... */ 00152 /* Local Variables: */ 00153 /* indent-tabs-mode: nil */ 00154 /* End: */