// // Copyright (C) : Please refer to the COPYRIGHT file distributed // with this source distribution. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // /////////////////////////////////////////////////////////////////////////////// #include "Silhouette.h" #include "SteerableViewMap.h" #include "../image/ImagePyramid.h" #include "../image/Image.h" #include #include "../geometry/Geom.h" using namespace Geometry; //soc #include //soc #include #include extern "C" { #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" #include "intern/IMB_png.h" } SteerableViewMap::SteerableViewMap(unsigned int nbOrientations){ _nbOrientations = nbOrientations; _bound = cos(M_PI/(float)_nbOrientations); for(unsigned i=0; i<_nbOrientations; ++i){ _directions.push_back(Vec2d(cos((float)i*M_PI/(float)_nbOrientations), sin((float)i*M_PI/(float)_nbOrientations))); } Build(); } void SteerableViewMap::Build(){ _imagesPyramids = new ImagePyramid*[_nbOrientations+1]; // one more map to store the complete visible VM memset((_imagesPyramids),0,(_nbOrientations+1)*sizeof(ImagePyramid*)); } SteerableViewMap::SteerableViewMap(const SteerableViewMap& iBrother){ _nbOrientations = iBrother._nbOrientations; unsigned i; _bound = iBrother._bound; _directions = iBrother._directions; _mapping = iBrother._mapping; _imagesPyramids = new ImagePyramid*[_nbOrientations+1]; // one more map to store the complete visible VM for(i=0;i<_nbOrientations+1;++i) _imagesPyramids[i] = new GaussianPyramid(*(dynamic_cast(iBrother._imagesPyramids[i]))); } SteerableViewMap::~SteerableViewMap(){ Clear(); } void SteerableViewMap::Clear(){ unsigned i; if(_imagesPyramids){ for(i=0; i<=_nbOrientations; ++i){ if(_imagesPyramids[i]) delete (_imagesPyramids)[i]; } delete [] _imagesPyramids; _imagesPyramids = 0; } if(!_mapping.empty()){ for(map::iterator m=_mapping.begin(), mend=_mapping.end(); m!=mend; ++m){ delete [] (*m).second; } _mapping.clear(); } } void SteerableViewMap::Reset(){ Clear(); Build(); } double SteerableViewMap::ComputeWeight(const Vec2d& dir, unsigned i){ double dotp = fabs(dir*_directions[i]); if(dotp < _bound) return 0; if(dotp>1) dotp = 1; return cos((float)_nbOrientations/2.0*acos(dotp)); } double * SteerableViewMap::AddFEdge(FEdge *iFEdge){ unsigned i; unsigned id = iFEdge->getId().getFirst(); map::iterator o = _mapping.find(id); if(o!=_mapping.end()){ return (*o).second; } double * res = new double[_nbOrientations]; for(i=0; i<_nbOrientations; ++i){ res[i] = 0; } Vec3r o2d3 = iFEdge->orientation2d(); Vec2r o2d2(o2d3.x(), o2d3.y()); real norm = o2d2.norm(); if(norm < 1e-6){ return res; } o2d2/=norm; for(i=0; i<_nbOrientations; ++i){ res[i] = ComputeWeight(o2d2, i); } _mapping[id] = res; return res; } unsigned SteerableViewMap::getSVMNumber(const Vec2f& orient){ Vec2f dir(orient); //soc unsigned res = 0; real norm = dir.norm(); if(norm < 1e-6){ return _nbOrientations+1; } dir/=norm; double maxw = 0.f; unsigned winner = _nbOrientations+1; for(unsigned i=0; i<_nbOrientations; ++i){ double w = ComputeWeight(dir, i); if(w>maxw){ maxw = w; winner = i; } } return winner; } unsigned SteerableViewMap::getSVMNumber(unsigned id){ map::iterator o = _mapping.find(id); if(o!=_mapping.end()){ double* wvalues= (*o).second; double maxw = 0.f; unsigned winner = _nbOrientations+1; for(unsigned i=0; i<_nbOrientations; ++i){ double w = wvalues[i]; if(w>maxw){ maxw = w; winner = i; } } return winner; } return _nbOrientations+1; } void SteerableViewMap::buildImagesPyramids(GrayImage **steerableBases, bool copy, unsigned iNbLevels, float iSigma){ for(unsigned i=0; i<=_nbOrientations; ++i){ ImagePyramid * svm = (_imagesPyramids)[i]; if(svm) delete svm; if(copy) svm = new GaussianPyramid(*(steerableBases[i]), iNbLevels, iSigma); else svm = new GaussianPyramid(steerableBases[i], iNbLevels, iSigma); _imagesPyramids[i] = svm; } } float SteerableViewMap::readSteerableViewMapPixel(unsigned iOrientation, int iLevel, int x, int y){ ImagePyramid *pyramid = _imagesPyramids[iOrientation]; if(pyramid==0){ cout << "Warning: this steerable ViewMap level doesn't exist" << endl; return 0; } if((x<0) || (x>=pyramid->width()) || (y<0) || (y>=pyramid->height())) return 0; //float v = pyramid->pixel(x,pyramid->height()-1-y,iLevel)*255.f; float v = pyramid->pixel(x,pyramid->height()-1-y,iLevel)/32.f; // we encode both the directionality and the lines counting on 8 bits // (because of frame buffer). Thus, we allow until 8 lines to pass through // the same pixel, so that we can discretize the Pi/_nbOrientations angle into // 32 slices. Therefore, for example, in the vertical direction, a vertical line // will have the value 32 on each pixel it passes through. return v; } float SteerableViewMap::readCompleteViewMapPixel(int iLevel, int x, int y){ return readSteerableViewMapPixel(_nbOrientations,iLevel,x,y); } unsigned int SteerableViewMap::getNumberOfPyramidLevels() const{ if(_imagesPyramids[0]) return _imagesPyramids[0]->getNumberOfLevels(); return 0; } void SteerableViewMap::saveSteerableViewMap() const { for(unsigned i=0; i<=_nbOrientations; ++i){ if(_imagesPyramids[i] == 0){ cerr << "SteerableViewMap warning: orientation " << i <<" of steerable View Map whas not been computed yet" << endl; continue; } int ow = _imagesPyramids[i]->width(0); int oh = _imagesPyramids[i]->height(0); //soc QString base("SteerableViewMap"); string base("SteerableViewMap"); stringstream filename; for(int j=0; j<_imagesPyramids[i]->getNumberOfLevels(); ++j){ //soc float coeff = 1;//1/255.f; //100*255;//*pow(2,j); //soc QImage qtmp(ow, oh, QImage::Format_RGB32); ImBuf *ibuf = IMB_allocImBuf(ow, oh, 32, IB_rect, 0); int rowbytes = ow*4; char *pix; for(int y=0;ypixel(x,y,j)); if(c>255) c=255; //int c = (int)(_imagesPyramids[i]->pixel(x,y,j)); //soc qtmp.setPixel(x,y,qRgb(c,c,c)); pix = (char*)ibuf->rect + y*rowbytes + x*4; pix[0] = pix [1] = pix[2] = c; } } //soc qtmp.save(base+QString::number(i)+"-"+QString::number(j)+".png", "PNG"); filename << base; filename << i << "-" << j << ".png"; imb_savepng(ibuf, const_cast(filename.str().c_str()), 0); } // QString base("SteerableViewMap"); // for(unsigned j=0; j<_imagesPyramids[i]->getNumberOfLevels(); ++j){ // GrayImage * img = _imagesPyramids[i]->getLevel(j); // int ow = img->width(); // int oh = img->height(); // float coeff = 1; //100*255;//*pow(2,j); // QImage qtmp(ow, oh, 32); // for(unsigned y=0;ypixel(x,y)); // if(c>255) // c=255; // //int c = (int)(_imagesPyramids[i]->pixel(x,y,j)); // qtmp.setPixel(x,y,qRgb(c,c,c)); // } // } // qtmp.save(base+QString::number(i)+"-"+QString::number(j)+".png", "PNG"); // } // } }