APImage.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2007 by Zoran Mesec   *
00003  *   zoran.mesec@gmail.com   *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 #include <string>
00021 #include <math.h>
00022 #include "APImage.h"
00023 
00024 #ifdef USE_VIGRA
00025         using namespace vigra;
00026 #endif
00027 
00028 APImage::APImage(string p) {
00029 this->path=p;
00030 }
00031 
00032 bool APImage::open() {
00033 
00034 #ifdef USE_VIGRA
00035     try
00036     {
00037         // read image given as first argument
00038         // file type is determined automatically
00039         ImageImportInfo info(this->path.c_str());
00040         //cout << this->path.c_str() << "Size:"<< info.width() <<"\n";
00041 
00042         if(info.isGrayscale())
00043         {
00044             // create a gray scale image of appropriate size
00045             vigra::BImage in(info.width(), info.height());
00046             this->imgBW=new BImage(info.width(), info.height());
00047             // import the image just read
00048             importImage(info, destImage(*this->imgBW));
00049         }
00050         else
00051         {
00052 
00053             BRGBImage in(info.width(), info.height());
00054 
00055             //TODO: this does not work. How to make a conversion from RGB to BW image in vigra???
00056             this->imgBW=new BImage(info.width(), info.height());
00057 
00058             importImage(info, destImage(in));
00059 
00060             // create image iterator that points to upper left corner
00061             // of source image
00062             vigra::BRGBImage::Iterator sy = in.upperLeft();
00063 
00064             // create image iterator that points past the lower right corner of
00065             // source image (similarly to the past-the-end iterator in the STL)
00066             vigra::BRGBImage::Iterator send = in.lowerRight();
00067 
00068             // create image iterator that points to upper left corner
00069             // of destination image
00070             vigra::BImage::Iterator dy = (*this->imgBW).upperLeft();
00071 
00072             // iterate down the first column of the images
00073             for(; sy.y != send.y; ++sy.y, ++dy.y)
00074             {
00075                 // create image iterator that points to the first
00076                 // pixel of the current row of the source image
00077                 vigra::BRGBImage::Iterator sx = sy;
00078 
00079                 // create image iterator that points to the first
00080                 // pixel of the current row of the destination image
00081                 vigra::BImage::Iterator dx = dy;
00082 
00083                 // iterate across current row
00084                 for(; sx.x != send.x; ++sx.x, ++dx.x)
00085                 {
00086                     RGBValue<int,0u,1u,2u> pixel = *sx;
00087                     // calculate grayscale value
00088                     // Y = 0.3*R + 0.59*G + 0.11*B
00089                     *dx = vigra::round(0.3*pixel.red() + 0.59*pixel.green() + 0.11*pixel.blue());
00090                 }
00091             }
00092             //exportAPImage(srcAPImageRange(*this->imgBW), vigra::APImageExportInfo("ttt.jpg"));
00093         }
00094         return true;
00095     }
00096     catch (...)
00097     {
00098         // catch any errors that might have occured and print their reason
00099         return false;
00100     }
00101 #endif
00102 }
00103 void APImage::convolute(int* kernel,int dim1, int dim2,double scale) {
00104     /*CvScalar s;
00105     int offsetX=floor(dim1/2);
00106     int offsetY=floor(dim2/2);
00107     int xStart=0;
00108     int yStart=0;
00109 
00110     double pixelSum=0;
00111    // bool outOfRange=false;
00112     int tmpX=0;
00113     int tmpY=0;
00114     double max=0;
00115 
00116     for(int i=0;i<imgBW->height;i++) {
00117         for(int j=0; j<imgBW->width;j++) {
00118             //s=cvGet2D(imgBW,i,j);
00119             outOfRange=true;
00120             if(j-offsetX<0) {
00121                 outOfRange=true;
00122             }
00123             if(i-offsetX<0)
00124 
00125             pixelSum=0;
00126             xStart=i-offsetX;
00127             yStart=j-offsetY;
00128             for(int k=0;k<dim1;k++) {
00129                 tmpX=xStart+k;
00130                 for(int l=0;l<dim2;l++) {
00131                     tmpY=yStart+l;
00132                     if((tmpX)<0 ||tmpY<0 || tmpX>=imgBW->height || tmpY>=imgBW->width)  {
00133                         pixelSum+=kernel[k*dim2+l]*(rand()%256);
00134                     } else {
00135 
00136                         s=cvGet2D(imgBW,xStart+k,yStart+l);
00137                         //cout << " "<< s.val[0] << "\n";
00138 
00139                         pixelSum+=kernel[k*dim2+l]*s.val[0];
00140                     }
00141                     //cout << "\nPixelSum:"<< pixelSum;
00142                 }
00143             }
00144             s.val[0]=pixelSum*0.004;
00145             cvSet2D(imgBW,i,j,s); // set the (i,j) pixel value
00146             if(pixelSum>max) max=pixelSum;
00147             //cout << " "<< pixelSum;
00148             //this->convolution[i][j]=pixelSum;
00149             //s=cvGet2D(imgBW,i,j);
00150 //          s.val[0]=rand()%255;
00151 //          cvSet2D(imgBW,i,j,s); // set the (i,j) pixel value
00152         }
00153         //out << "\n";
00154     }*/
00155 }
00156 int APImage::getPixel(int x,int y) {
00157 #ifdef USE_VIGRA
00158     return (*this->imgBW)(x,y);
00159 #endif
00160 #ifdef USE_OPENCV
00161     CvScalar s=cvGet2D(imgBW,x,y);
00162     s.val[0];
00163 #endif
00164 }
00165 int APImage::getWidth() {
00166         return this->imgBW->width();
00167 }
00168 int APImage::getWidthBW() {
00169         return this->imgBW->width();
00170 }
00171 int APImage::getHeight() {
00172         return this->imgBW->height();
00173 }
00174 int APImage::getHeightBW() {
00175         return this->imgBW->height();
00176 }
00177 APImage* APImage::getCopy() {
00178         return new APImage("");
00179 }
00180 void APImage::scale(double factor) {
00181 //#ifdef USE_OPENCV
00182         /*IplAPImage *resized= cvCreateAPImage(cvSize(round(this->getWidthBW()/factor),round(this->getHeightBW()/factor)), imgBW->depth ,imgBW->nChannels);
00183         cvResize(imgBW,resized);
00184         this->imgBW=resized;*/
00185 //#endif
00186 }
00187 void APImage::show() {
00188 #ifdef USE_VIGRA
00189     string add = "00det_";
00190     add.append(this->getPath());
00191 
00192     cout << "Results:"<< add << endl;
00193     exportImage(srcImageRange(*this->imgBW), ImageExportInfo(add.c_str()));
00194 #endif
00195 #ifdef USE_OPENCV
00196     cvNamedWindow( "Image view", 1 );
00197     cvShowAPImage( "Image view", this->img);
00198     cvWaitKey(0); // very important, contains event processing loop inside
00199     cvDestroyWindow( "Image view" );
00200 #endif
00201         //cvReleaseAPImage( &img );
00202 }
00203 void APImage::drawCircle(int x,int y, int radius) {
00204     //cout << "Circle:" << x << "," << y << ",radius:"<<radius<<"\n";
00205 #ifdef USE_VIGRA
00206 
00207     (*this->imgBW)(x,y) = 255;
00208     (*this->imgBW)(x+1,y+1) = 255;
00209     (*this->imgBW)(x-1,y-1) = 255;
00210     (*this->imgBW)(x-1,y+1) = 255;
00211     (*this->imgBW)(x+1,y-1) = 255;
00212 
00213 #endif
00214     //cout << "EOF CIRCLE DRAWING" <<endl;
00215 
00216 #ifdef USE_OPENCV
00217     cvCircle(this->img, cvPoint(x,y), radius, cvScalar(0,255,0), 1);
00218     cvCircle(this->img, cvPoint(x,y), 0, cvScalar(0,255,0), 1);
00219 #endif
00220 
00221 }
00222 void APImage::drawRectangle(int x,int y, int radius) {
00223     //cvRectangle(this->img,cvPoint(x-radius,y-radius),cvPoint(x+radius,y+radius),cvScalar(0,255,0));
00224 }
00225 
00226 void APImage::drawLine(int x1,int y1, int x2,int y2) {
00227     //cout << "Draw line:("<< x1<< ","<<y1<<")->("<<x2<<","<<y2<<")\n";
00228 #ifdef USE_OPENCV
00229     cvLine(this->img,cvPoint(x1,y1),cvPoint(x2,y2),cvScalar(0,255,255));
00230 #endif
00231 
00232 }
00233 
00234 void APImage::smooth() {
00235         //TODO: create a gaussian mask and call the function convolute
00236 }
00240 void APImage::integrate() {
00241 
00242     /*cout << "Height:"<< this->getHeightBW() <<"\n";
00243     cout << "Width:"<< this->getWidthBW() <<"\n";*/
00244 
00245     /*for(int i=0;i<10;i++) {
00246         for(int j=0; j<10;j++) {
00247             cout << this->getPixel(j,i)<<" ";
00248         }
00249         cout << "\n";
00250     }*/
00251 
00252     this->integral.clear();
00253     this->integral.resize(this->getWidthBW());
00254     for(int i=0;i<this->getWidthBW();i++) {
00255         this->integral[i].resize(this->getHeightBW());
00256         for(int j=0; j<this->getHeightBW();j++) {
00257             //cout << i << ","<< j<<"\n";
00258             this->integral[i][j]=this->_getValue4Integral(i,j-1)+this->_getValue4Integral(i-1,j)+this->getPixel(i,j)-this->_getValue4Integral(i-1,j-1);
00259         }
00260         //cout << "\n";
00261     }
00262 
00263      /*for(int i=0;i<10;i++) {
00264         for(int j=0; j<10;j++) {
00265             cout << this->getIntegralPixel(j,i)<<" ";
00266         }
00267         cout << "\n";
00268     }
00269 
00270     cout << this->getRegionSum(2,1,2,3) <<"dddddd\n";*/
00271 }
00272 int APImage::_getValue4Integral(int x, int y) {
00273 if(x==-1 || y==-1) return 0;
00274 else return this->integral[x][y];
00275 }
00276 int APImage::getIntegralPixel(int x,int y) {
00277  return this->integral[x][y];
00278 }
00279 int APImage::getRegionSum(int y1, int x1, int y2, int x2) {
00280     if(x1<=0) x1=1;
00281     if(y1<=0) y1=1;
00282     if(x2<=0) x2=1;
00283     if(y2<=0) y2=1;
00284     if(x1>=this->getWidthBW()) x1=this->getWidthBW()-1;
00285     if(x2>=this->getWidthBW()) x2=this->getWidthBW()-1;
00286     if(y1>=this->getHeightBW()) y1=this->getHeightBW()-1;
00287     if(y2>=this->getHeightBW()) y2=this->getHeightBW()-1;
00288  return this->integral[x2][y2]+this->integral[x1-1][y1-1]-this->integral[x1-1][y2]-this->integral[x2][y1-1];
00289 }
00290 string APImage::getPath() {
00291         return this->path;
00292 }
00293 
00294 /*double APImage::getPointOrientation(int x, int y) {
00295 
00296  return 0.0;
00297 }*/
00298 
00299 template <class SrcIterator, class SrcAccessor, class BackInsertable>
00300 void APImage::_cannyEdgelList1(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00301                BackInsertable & edgels, double scale,vector<int>* point )
00302 {
00303     _cannyEdgelList(src.first, src.second, src.third, edgels, scale, point);
00304 }
00305 
00306 template <class SrcIterator, class SrcAccessor, class BackInsertable>
00307 void APImage::_cannyEdgelList(SrcIterator ul, SrcIterator lr, SrcAccessor src,
00308                         BackInsertable & edgels, double scale, vector<int>* point)
00309 {
00310     int w = lr.x - ul.x;
00311     int h = lr.y - ul.y;
00312 
00313     // calculate image gradients
00314     typedef typename
00315         NumericTraits<typename SrcAccessor::value_type>::RealPromote
00316         TmpType;
00317 
00318     BasicImage<TmpType> tmp(w,h), dx(w,h), dy(w,h);
00319 
00320     Kernel1D<double> smooth, grad;
00321 
00322     smooth.initGaussian(scale);
00323     grad.initGaussianDerivative(scale, 1);
00324 
00325     separableConvolveX(srcIterRange(ul, lr, src), destImage(tmp), kernel1d(grad));
00326     separableConvolveY(srcImageRange(tmp), destImage(dx), kernel1d(smooth));
00327 
00328     separableConvolveY(srcIterRange(ul, lr, src), destImage(tmp), kernel1d(grad));
00329     separableConvolveX(srcImageRange(tmp), destImage(dy), kernel1d(smooth));
00330 
00331     combineTwoImages(srcImageRange(dx), srcImage(dy), destImage(tmp),
00332                      MagnitudeFunctor<TmpType>());
00333 
00334 
00335     // find edgels
00336     internalCannyFindEdgels(dx, dy, tmp, edgels, point);
00337 }
00338 
00339 template <class Image1, class Image2, class BackInsertable>
00340 void APImage::_internalCannyFindEdgels(Image1 const & gx,
00341                              Image1 const & gy,
00342                              Image2 const & magnitude,
00343                              BackInsertable & edgels, vector<int>* p)
00344 {
00345     typedef typename Image1::value_type PixelType;
00346     double t = 0.5 / VIGRA_CSTD::sin(M_PI/8.0);
00347 
00348     //last element in edgel list is edgel that holds orientation
00349     //of interest point
00350 
00351     //orientation assignment
00352     vector<int > point= *p;
00353     PixelType gradx = gx(p[0],p[1]);
00354     PixelType grady = gy(p[0],p[1]);
00355 
00356     double orientation = VIGRA_CSTD::atan2(-grady, gradx) - M_PI * 1.5;
00357     if(orientation < 0.0)
00358         orientation += 2.0*M_PI;
00359     Edgel edgel;
00360     edgel.orientation=orientation;
00361     edgels.push_back(edgel);
00362     //EOF orientation assignment
00363 
00364     for(int y=1; y<gx.height()-1; ++y)
00365     {
00366         for(int x=1; x<gx.width()-1; ++x)
00367         {
00368             gradx = gx(x,y);
00369             grady = gy(x,y);
00370             double mag = magnitude(x, y);
00371 
00372             int dx = (int)VIGRA_CSTD::floor(gradx*t/mag + 0.5);
00373             int dy = (int)VIGRA_CSTD::floor(grady*t/mag + 0.5);
00374 
00375             int x1 = x - dx,
00376                 x2 = x + dx,
00377                 y1 = y - dy,
00378                 y2 = y + dy;
00379 
00380             PixelType m1 = magnitude(x1, y1);
00381             PixelType m3 = magnitude(x2, y2);
00382 
00383             if(m1 < mag && m3 <= mag)
00384             {
00385                 Edgel edgel;
00386 
00387                 // local maximum => quadratic interpolation of sub-pixel location
00388                 PixelType del = (m1 - m3) / 2.0 / (m1 + m3 - 2.0*mag);
00389                 edgel.x = x + dx*del;
00390                 edgel.y = y + dy*del;
00391                 edgel.strength = mag;
00392                 orientation = VIGRA_CSTD::atan2(-grady, gradx) - M_PI * 1.5;
00393                 if(orientation < 0.0)
00394                     orientation += 2.0*M_PI;
00395                 edgel.orientation = orientation;
00396                 edgels.push_back(edgel);
00397             }
00398         }
00399     }
00400 }
00401 
00402 void APImage::test() {
00403             // empty edgel list
00404             /*std::vector<vigra::Edgel> edgels;
00405 
00406             // find edgels at scale of the interest point
00407             vigra::cannyEdgelList(srcIterRange( this->imgBW->upperLeft() + vigra::Diff2D(250, 250),
00408                                                 this->imgBW->upperLeft() + vigra::Diff2D(550, 450)),
00409                                   edgels, 1.2, );
00410             cout << "Size:" << edgels.size() << endl;
00411             vector<vigra::Edgel>::iterator iter2 = edgels.begin();
00412             int a=0;
00413             while( iter2 != edgels.end()) { //loop over every canny pixel
00414                 vigra::Edgel edgePoint=*iter2;
00415                 //cout << edgePoint.strength << endl;
00416                 if(edgePoint.strength>5) {
00417                      this->drawCircle(round(edgePoint.x)+250,round(edgePoint.y)+250,0);
00418                     a++;
00419                 }
00420                 iter2++;
00421             }
00422             cout << a << endl;*/
00423 }

Generated on Mon Sep 9 01:25:42 2013 for Hugintrunk by  doxygen 1.3.9.1