00001 /*!@file Channels/DescriptorVec.C descriptor vector generator for obj rec */ 00002 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: Laurent Itti <itti@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Channels/DescriptorVec.C $ 00035 // $Id: DescriptorVec.C 9412 2008-03-10 23:10:15Z farhan $ 00036 // 00037 00038 #include "Channels/DescriptorVec.H" 00039 00040 #include "Channels/ChannelOpts.H" 00041 #include "Component/ModelOptionDef.H" 00042 #include "Component/OptionManager.H" 00043 #include "Image/CutPaste.H" 00044 #include "SIFT/VisualObject.H" 00045 #include "SIFT/Keypoint.H" 00046 #include "Image/ColorOps.H" 00047 #include "Image/FilterOps.H" 00048 #include "Image/MathOps.H" 00049 #include "Image/ShapeOps.H" 00050 #include "Image/Transforms.H" 00051 #include "Image/fancynorm.H" 00052 00053 #include "GUI/DebugWin.H" 00054 #include "Image/DrawOps.H" 00055 00056 #include <cstdlib> 00057 #include <iostream> 00058 00059 // Used by: Retina 00060 static const ModelOptionDef OPT_DescriptorVecFOV = 00061 { MODOPT_ARG(Dims), "DescriptorVecFOV", &MOC_CHANNEL, OPTEXP_CORE, 00062 "Use the given fovea size for constructing DescriptorVec.", 00063 "descriptor-vec-fov", '\0', "<w>x<h>", "75x75" }; 00064 00065 // ###################################################################### 00066 DescriptorVec::DescriptorVec(OptionManager& mgr, 00067 const std::string& descrName, 00068 const std::string& tagName, 00069 ComplexChannel *cc) 00070 : ModelComponent(mgr, descrName, tagName), 00071 itsComplexChannel(cc), itsFoveaSize(&OPT_DescriptorVecFOV, this), 00072 itsFeatureHistogram(100), 00073 itsFEngine(0), 00074 itsFV(0) 00075 { 00076 itsFoveaSize.setVal(Dims(80,80)); 00077 } 00078 00079 // ###################################################################### 00080 DescriptorVec::~DescriptorVec() 00081 {} 00082 00083 // ###################################################################### 00084 void DescriptorVec::setInputImg(const Image<PixRGB<byte> >& img) 00085 { 00086 itsInputImg = img; 00087 } 00088 00089 // ###################################################################### 00090 void DescriptorVec::setFovea(Point2D<int> loc) 00091 { 00092 int locX = loc.i; 00093 int locY = loc.j; 00094 int foveaW = itsFoveaSize.getVal().w(); 00095 int foveaH = itsFoveaSize.getVal().h(); 00096 00097 LINFO("Getting descriptor from loc %i,%i", loc.i, loc.j); 00098 LINFO("Fovea size: %ix%i", foveaW, foveaH); 00099 if (itsComplexChannel->hasInput()){ 00100 //get the input image 00101 Image<PixRGB<byte> > img = itsInputImg; 00102 int imgW = img.getWidth(); 00103 int imgH = img.getHeight(); 00104 00105 LINFO("Image size: %ix%i", imgW, imgH); 00106 00107 //Adjest the fovea location so we dont go outside the image 00108 int tl_x = locX - ((foveaW-1)/2); 00109 int tl_y = locY - ((foveaH-1)/2); 00110 00111 //Sift the fovea position if nessesary 00112 if (tl_x < 0) tl_x = 0; if (tl_y < 0) tl_y = 0; 00113 if (tl_x+foveaW > imgW) tl_x = imgW - foveaW; 00114 if (tl_y+foveaH > imgH) tl_y = imgH - foveaH; 00115 00116 //adjust locX/locX if tl_x/tl_y has changed 00117 locX = tl_x + ((foveaW-1)/2); 00118 locY = tl_y + ((foveaH-1)/2); 00119 00120 itsFoveaLoc = Point2D<int>(locX, locY); 00121 00122 //get only the fovea region 00123 if (itsFoveaSize.getVal().w() < img.getWidth()) //crop if our fovea is smaller then img 00124 { 00125 img= crop(img, Point2D<int>(tl_x, tl_y), itsFoveaSize.getVal()); 00126 } 00127 00128 //float angle = getDominateOrientation(luminance(img)); 00129 00130 //Rotate the image around the main angle 00131 //itsFoveaImg = rotate(img, img.getWidth()/2, img.getHeight()/2, angle); 00132 itsFoveaImg = img; //rotate(img, img.getWidth()/2, img.getHeight()/2, angle); 00133 00134 //itsFoveaImg = toRGB(img); 00135 00136 } else { 00137 LINFO("No input image in VC"); 00138 } 00139 00140 00141 } 00142 00143 // ###################################################################### 00144 void DescriptorVec::setFoveaSize(Dims &d) 00145 { 00146 itsFoveaSize.setVal(d); 00147 } 00148 00149 // ###################################################################### 00150 void DescriptorVec::setFoveaSize(int foveaRadius) 00151 { 00152 Dims fr(foveaRadius, foveaRadius); 00153 itsFoveaSize.setVal(fr); 00154 } 00155 00156 // ###################################################################### 00157 Dims DescriptorVec::getFoveaSize() 00158 { 00159 return itsFoveaSize.getVal(); 00160 } 00161 00162 // ###################################################################### 00163 float DescriptorVec::getDominateOrientation(const Image<float> &img){ 00164 //get main orientation 00165 const int ORIENTARRAY = 36; 00166 Image<float> gradmag, gradori; 00167 gradientSobel(luminance(img), gradmag, gradori); 00168 00169 //Add orientations to the histogram 00170 Histogram OV(ORIENTARRAY); 00171 for (int y=0; y<img.getHeight(); y++){ 00172 for(int x=0; x<img.getWidth(); x++){ 00173 const float gradVal = gradmag.getVal(x, y); 00174 float angle = gradori.getVal(x, y) + M_PI; 00175 00176 angle = 0.5F * angle * ORIENTARRAY / M_PI; 00177 while (angle < 0.0F) angle += ORIENTARRAY; 00178 while (angle >= ORIENTARRAY) angle -= ORIENTARRAY; 00179 00180 OV.addValueInterp(angle, 1 * gradVal); 00181 00182 } 00183 } 00184 00185 // smooth the orientation histogram 3 times: 00186 for (int i = 0; i < 3; i++) OV.smooth(); 00187 00188 // find the max in the histogram: 00189 float maxPeakVal; int maxLoc; 00190 OV.findMax(maxLoc, maxPeakVal); 00191 00192 // get value to the left of current value 00193 const float leftval = OV.getValue((maxLoc == 0) ? ORIENTARRAY-1 : maxLoc-1); 00194 00195 // get value to the right of current value 00196 const float rightval = OV.getValue((maxLoc == ORIENTARRAY-1) ? 0 : maxLoc+1); 00197 00198 // interpolate the values to get the orientation of the peak: 00199 // with f(x) = ax^2 + bx + c 00200 // f(-1) = x0 = leftval 00201 // f( 0) = x1 = midval 00202 // f(+1) = x2 = rightval 00203 // => a = (x0+x2)/2 - x1 00204 // b = (x2-x0)/2 00205 // c = x1 00206 // f'(x) = 0 => x = -b/2a 00207 const float a = 0.5f * (leftval + rightval) - maxPeakVal; 00208 00209 const float b = 0.5f * (rightval - leftval); 00210 float realangle = float(maxLoc) - 0.5F * b / a; 00211 00212 realangle *= 2.0F * M_PI / ORIENTARRAY; // [0:36] to [0:2pi] 00213 realangle -= M_PI; // [0:2pi] to [-pi:pi] 00214 00215 00216 /* 00217 float realangle; 00218 00219 // Find orientation peak: 00220 for (int bin = 0; bin < ORIENTARRAY; bin++) 00221 { 00222 // consider the peak centered around 'bin': 00223 const float midval = OV.getValue(bin); 00224 00225 // if current value much smaller than global peak, forget it: 00226 if (midval < 0.8F * maxPeakValue) continue; 00227 00228 // get value to the left of current value 00229 const float leftval = OV.getValue((bin == 0) ? ORIENTARRAY-1 : bin-1); 00230 00231 // get value to the right of current value 00232 const float rightval = OV.getValue((bin == ORIENTARRAY-1) ? 0 : bin+1); 00233 00234 // only consider local peaks: 00235 if (leftval >= midval) continue; 00236 if (rightval >= midval) continue; 00237 00238 // interpolate the values to get the orientation of the peak: 00239 // with f(x) = ax^2 + bx + c 00240 // f(-1) = x0 = leftval 00241 // f( 0) = x1 = midval 00242 // f(+1) = x2 = rightval 00243 // => a = (x0+x2)/2 - x1 00244 // b = (x2-x0)/2 00245 // c = x1 00246 // f'(x) = 0 => x = -b/2a 00247 const float a = 0.5f * (leftval + rightval) - midval; 00248 00249 const float b = 0.5f * (rightval - leftval); 00250 realangle = float(bin) - 0.5F * b / a; 00251 00252 realangle *= 2.0F * M_PI / ORIENTARRAY; // [0:36] to [0:2pi] 00253 realangle -= M_PI; // [0:2pi] to [-pi:pi] 00254 break; 00255 }*/ 00256 00257 return realangle; 00258 00259 } 00260 00261 // ###################################################################### 00262 //! Return the image under the fovea 00263 Image<PixRGB<byte> > DescriptorVec::getFoveaImage() { 00264 00265 00266 if (itsFoveaImg.initialized()){ 00267 /*rutz::shared_ptr<VisualObject> 00268 obj(new VisualObject("NewObject", "NewObject", itsFoveaImg)); 00269 00270 itsFoveaImg = obj->getKeypointImage();*/ 00271 00272 } else { 00273 LINFO("No input image in VC"); 00274 } 00275 00276 return itsFoveaImg; 00277 } 00278 00279 // ###################################################################### 00280 //! Return the image of the histogram under the fovea 00281 Image<PixRGB<byte> > DescriptorVec::getHistogramImage() { 00282 00283 //return Image<PixRGB<byte> >(); 00284 return itsFoveaImg; 00285 00286 } 00287 00288 // ###################################################################### 00289 //! Build a SIFT descriptor vector 00290 void DescriptorVec::buildSIFTDV() 00291 { 00292 rutz::shared_ptr<VisualObject> 00293 obj(new VisualObject("NewObject", "NewObject", itsFoveaImg)); 00294 00295 std::vector< rutz::shared_ptr<Keypoint> > keypoints = obj->getKeypoints(); 00296 00297 //add the keypoints to our DV 00298 for (unsigned int i=0; i<keypoints.size(); i++) 00299 { 00300 00301 std::vector<double> fv; 00302 00303 for(unsigned int j=0; j<keypoints[i]->getFVlength(); j++) 00304 fv.push_back((byte)keypoints[i]->getFVelement(j)); 00305 //itsFV.push_back(fv); 00306 } 00307 00308 } 00309 00310 void DescriptorVec::buildFftDV() 00311 { 00312 00313 /* 00314 Image<float> gradmag, gradori; 00315 //TODO: This was already computed in DomnateOri, can be opt 00316 gradientSobel(luminance(itsFoveaImg), gradmag, gradori); 00317 00318 00319 // itsFoveaImg = toRGB(Image<byte>(gradmag)); 00320 00321 if (itsFEngine == 0) 00322 itsFEngine = new FourierEngine<double>(gradmag.getDims()); 00323 itsFTImg = itsFEngine->fft(gradmag); 00324 00325 if (!itsFV.initialized()){ 00326 itsFV = logmagnitude(itsFTImg); 00327 // itsFV = phase(itsFTImg); 00328 } else { 00329 //itsFV = phase(itsFTImg); 00330 itsFV = logmagnitude(itsFTImg); 00331 } 00332 00333 //inplaceNormalize(itsFV, 0.0f, 255.0f); 00334 00335 */ 00336 /*inplaceNormalize(img, 0.0f, 99.0f); 00337 Point2D<int> p; float maxval, minval; 00338 findMax(img, p, maxval); 00339 findMin(img, p, minval); 00340 LINFO("Max %f min %f", maxval, minval); 00341 itsFeatureHistogram.clear(); 00342 for (int y=0; y<img.getHeight(); y++){ 00343 for(int x=0; x<img.getWidth(); x++){ 00344 float val = img.getVal(x, y); 00345 printf("%0.2f ", val); 00346 itsFeatureHistogram.addValueInterp(val, 1); 00347 } 00348 } 00349 printf("\n");*/ 00350 00351 //itsFeatureHistogram((Image<byte>)img); 00352 00353 } 00354 // ###################################################################### 00355 void DescriptorVec::buildParticleCountDV() 00356 { 00357 00358 //Count the saliency values in the fovea region 00359 ComplexChannel& cc = dynamic_cast<ComplexChannel&>(*itsComplexChannel->subChan(0)); 00360 00361 const LevelSpec lspec = itsComplexChannel->getModelParamVal<LevelSpec>("LevelSpec"); 00362 const int smlevel = lspec.mapLevel(); 00363 int x=int(itsFoveaLoc.i / double(1 << smlevel) + 0.49); 00364 int y=int(itsFoveaLoc.j / double(1 << smlevel) + 0.49); 00365 00366 itsFV.clear(); 00367 int FVi = 0; 00368 for (uint i = 0; i < cc.numChans(); i++) 00369 { 00370 nub::ref<ChannelBase> cb = cc.subChan(i); 00371 if (dynamic_cast<ComplexChannel*>(cb.get()) != 0) //we have a complex channel 00372 { 00373 LINFO("Complex channel %i %s", i, cb->descriptiveName().c_str()); 00374 } else { 00375 SingleChannel& sc = dynamic_cast<SingleChannel&>(*cb); 00376 LINFO("Single channel %i", i); 00377 for (uint j=0; j< sc.numSubmaps(); j++) 00378 { 00379 Image<float> submap = sc.getSubmap(j); 00380 00381 itsFV.push_back(submap.getVal(x, y)); 00382 LINFO("FV%i %s:%i", FVi++, sc.descriptiveName().c_str(), j); 00383 /*submap = crop(submap, //get only the fovea region 00384 Point2D<int>(itsFoveaLoc.i - ((itsFoveaSize.getVal().w()-1)/2), 00385 itsFoveaLoc.j - ((itsFoveaSize.getVal().h())-1)/2), 00386 itsFoveaSize.getVal());*/ 00387 00388 00389 /*submap = maxNormalize(submap, 0.0F, 10.0F, VCXNORM_MAXNORM); 00390 Point2D<int> p; float maxVal, minVal, midVal; 00391 findMax(submap, p, maxVal); 00392 findMin(submap, p, minVal); 00393 midVal = (maxVal-minVal)/2; 00394 00395 int nParticles = countThresh(submap, midVal); //countParticles(submap, 1.0F); 00396 00397 LINFO("Channel %s:%i max is %0.2f min is %0.2f mid %0.2f, p=%i", 00398 sc.descriptiveName().c_str(),j, maxVal, minVal, midVal, 00399 nParticles); 00400 printf("%i ", nParticles); 00401 //SHOWIMG(submap); */ 00402 } 00403 00404 } 00405 } 00406 } 00407 00408 // ###################################################################### 00409 void DescriptorVec::buildDV() 00410 { 00411 const LevelSpec lspec = itsComplexChannel->getModelParamVal<LevelSpec>("LevelSpec"); 00412 const int smlevel = lspec.mapLevel(); 00413 00414 int x=int(itsFoveaLoc.i / double(1 << smlevel) + 0.49); 00415 int y=int(itsFoveaLoc.j / double(1 << smlevel) + 0.49); 00416 00417 int foveaW = int(itsFoveaSize.getVal().w() / double(1 << smlevel) + 0.49); 00418 int foveaH = int(itsFoveaSize.getVal().h() / double(1 << smlevel) + 0.49); 00419 00420 //Adjest the fovea location so we dont go outside the image 00421 int tl_x = x - (foveaW/2); 00422 int tl_y = y - (foveaH/2); 00423 00424 00425 //Go through all the submaps building the DV 00426 itsFV.clear(); //clear the FV 00427 uint numSubmaps = itsComplexChannel->numSubmaps(); 00428 for (uint i = 0; i < numSubmaps; i++) 00429 { 00430 Image<float> submap = itsComplexChannel->getSubmap(i); 00431 //Image<float> submap = itsComplexChannel->getRawCSmap(i); 00432 00433 00434 //itsFV.push_back(submap.getVal(x,y)); 00435 00436 //get only the fovea region 00437 if (foveaW < submap.getWidth()) //crop if our fovea is smaller 00438 submap = crop(submap, Point2D<int>(tl_x, tl_y), Dims(foveaW, foveaH)); 00439 //submap = maxNormalize(submap, 0.0F, 10.0F, VCXNORM_MAXNORM); 00440 00441 00442 00443 /* Point2D<int> p; float maxVal, minVal, midVal; 00444 findMax(submap, p, maxVal); 00445 findMin(submap, p, minVal); 00446 midVal = (maxVal-minVal)/2; 00447 int nParticles = countThresh(submap, 1.0F); //countParticles(submap, 1.0F); 00448 itsFV.push_back(nParticles); */ 00449 00450 float maxVal; Point2D<int> maxLoc; 00451 findMax(submap, maxLoc, maxVal); 00452 00453 //SHOWIMG(rescale(submap, 255, 255)); 00454 00455 itsFV.push_back(maxVal); 00456 00457 } 00458 } 00459 00460 // ###################################################################### 00461 void DescriptorVec::buildRawDV() 00462 { 00463 00464 bool salientLocationWithinSubmaps = true; 00465 Point2D<int> objSalientLoc(-1,-1); //the feature location 00466 00467 const LevelSpec lspec = itsComplexChannel->getModelParamVal<LevelSpec>("LevelSpec"); 00468 const int smlevel = lspec.mapLevel(); 00469 00470 int x=int(itsFoveaLoc.i / double(1 << smlevel) + 0.49); 00471 int y=int(itsFoveaLoc.j / double(1 << smlevel) + 0.49); 00472 00473 int foveaW = int(itsFoveaSize.getVal().w() / double(1 << smlevel) + 0.49); 00474 int foveaH = int(itsFoveaSize.getVal().h() / double(1 << smlevel) + 0.49); 00475 00476 int tl_x = x - (foveaW/2); 00477 int tl_y = y - (foveaH/2); 00478 00479 Dims mapDims = itsComplexChannel->getSubmap(0).getDims(); 00480 00481 //Shift the fovea location so we dont go outside the image 00482 //Sift the fovea position if nessesary 00483 if (tl_x < 0) tl_x = 0; if (tl_y < 0) tl_y = 0; 00484 if (tl_x+foveaW > mapDims.w()) tl_x = mapDims.w() - foveaW; 00485 if (tl_y+foveaH > mapDims.h()) tl_y = mapDims.h() - foveaH; 00486 00487 if (!salientLocationWithinSubmaps) 00488 { 00489 //Find the most salient location within the fovea 00490 Image<float> SMap = itsComplexChannel->getOutput(); 00491 00492 Image<float> tmp = SMap; //TODO need to resize to fovea 00493 //Find the max location within the fovea 00494 00495 float maxVal; Point2D<int> maxLoc; 00496 findMax(tmp, maxLoc, maxVal); 00497 //convert back to original SMap cordinates 00498 // objSalientLoc.i=tl_x+maxLoc.i; 00499 // objSalientLoc.j=tl_y+maxLoc.j; 00500 objSalientLoc.i=x; 00501 objSalientLoc.j=y; 00502 itsAttentionLoc = objSalientLoc; 00503 } 00504 00505 //Go through all the submaps building the DV 00506 itsFV.clear(); //clear the FV 00507 uint numSubmaps = itsComplexChannel->numSubmaps(); 00508 for (uint i = 0; i < numSubmaps; i++) 00509 { 00510 //Image<float> submap = itsComplexChannel->getSubmap(i); 00511 Image<float> submap = itsComplexChannel->getRawCSmap(i); 00512 00513 // resize submap to fixed scale if necessary: 00514 if (submap.getWidth() > mapDims.w()) 00515 submap = downSize(submap, mapDims); 00516 else if (submap.getWidth() < mapDims.w()) 00517 submap = rescale(submap, mapDims); //TODO convert to quickInterpolate 00518 00519 00520 if (salientLocationWithinSubmaps) //get the location from the salient location within each submap 00521 { 00522 Image<float> tmp = submap; 00523 //get only the fovea region 00524 00525 if (foveaW < tmp.getWidth()) //crop if our fovea is smaller 00526 tmp = crop(tmp, Point2D<int>(tl_x, tl_y), Dims(foveaW, foveaH)); 00527 // tmp = maxNormalize(tmp, 0.0F, 10.0F, VCXNORM_MAXNORM); //find salient locations 00528 00529 //Find the max location within the fovea 00530 float maxVal; Point2D<int> maxLoc; findMax(tmp, maxLoc, maxVal); 00531 //LINFO("%i: Max val %f, loc(%i,%i)", i, maxVal, maxLoc.i, maxLoc.j); 00532 00533 objSalientLoc.i=tl_x+maxLoc.i; 00534 objSalientLoc.j=tl_y+maxLoc.j; 00535 00536 } 00537 00538 if (objSalientLoc.i < 0) objSalientLoc.i = 0; 00539 if (objSalientLoc.j < 0) objSalientLoc.j = 0; 00540 00541 if (objSalientLoc.i > submap.getWidth()-1) objSalientLoc.i = submap.getWidth()-1; 00542 if (objSalientLoc.j > submap.getHeight()-1) objSalientLoc.j = submap.getHeight()-1; 00543 00544 00545 00546 // LINFO("Location from %i,%i: (%i,%i)", objSalientLoc.i, objSalientLoc.j, 00547 // submap.getWidth(), submap.getHeight()); 00548 float featureVal = submap.getVal(objSalientLoc.i,objSalientLoc.j); 00549 itsFV.push_back(featureVal); 00550 // SHOWIMG(rescale(submap, 255, 255)); 00551 00552 } 00553 } 00554 00555 // ###################################################################### 00556 void DescriptorVec::buildLocalDV() 00557 { 00558 00559 Point2D<int> objSalientLoc(-1,-1); //the feature location 00560 00561 00562 //Go through all the submaps building the DV 00563 itsFV.clear(); //clear the FV 00564 uint numSubmaps = itsComplexChannel->numSubmaps(); 00565 for (uint i = 0; i < numSubmaps; i++) 00566 { 00567 //Image<float> submap = itsComplexChannel->getSubmap(i); 00568 Image<float> submap = itsComplexChannel->getRawCSmap(i); 00569 00570 //Find the max location within the fovea 00571 float maxVal; Point2D<int> maxLoc; findMax(submap, maxLoc, maxVal); 00572 //SHOWIMG(submap); 00573 00574 float featureVal = submap.getVal(maxLoc.i,maxLoc.j); 00575 itsFV.push_back(featureVal); 00576 // SHOWIMG(rescale(submap, 255, 255)); 00577 00578 } 00579 } 00580 // ###################################################################### 00581 void DescriptorVec::buildSingleChannelFV(SingleChannel &sc) 00582 { 00583 const LevelSpec lspec = itsComplexChannel->getModelParamVal<LevelSpec>("LevelSpec"); 00584 const int smlevel = lspec.mapLevel(); 00585 int x=int(itsFoveaLoc.i / double(1 << smlevel) + 0.49); 00586 int y=int(itsFoveaLoc.j / double(1 << smlevel) + 0.49); 00587 00588 //LINFO("Single channel %s", sc.descriptiveName().c_str()); 00589 for (uint j=0; j< sc.numSubmaps(); j++) 00590 { 00591 Image<float> submap = sc.getSubmap(j); 00592 itsFV.push_back(submap.getVal(x, y)); 00593 } 00594 00595 } 00596 00597 uint DescriptorVec::getFVSize() 00598 { 00599 ASSERT(itsComplexChannel != NULL); 00600 return itsComplexChannel->numSubmaps(); 00601 } 00602 00603 // ###################################################################### 00604 const std::vector<double>& DescriptorVec::getFV() const 00605 { 00606 return itsFV; 00607 } 00608 00609 // ###################################################################### 00610 /* So things look consistent in everyone's emacs... */ 00611 /* Local Variables: */ 00612 /* indent-tabs-mode: nil */ 00613 /* End: */