examples/surfVariasVersiones/surf.cpp

00001 /*
00002  *      Copyright (C) 2007, 2008. PARP Research Group.
00003  *      <http://perception.inf.um.es>
00004  *      University of Murcia, Spain.
00005  *
00006  *      This file is part of the QVision library.
00007  *
00008  *      QVision is free software: you can redistribute it and/or modify
00009  *      it under the terms of the GNU Lesser General Public License as
00010  *      published by the Free Software Foundation, version 3 of the License.
00011  *
00012  *      QVision is distributed in the hope that it will be useful,
00013  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *      GNU Lesser General Public License for more details.
00016  *
00017  *      You should have received a copy of the GNU Lesser General Public
00018  *      License along with QVision. If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #include <iostream>
00026 #include <QDebug>
00027 #include <QVector>
00028 #include <QMap>
00029 
00030 #include <qvcore/qvapplication.h>
00031 #include <qvcameras/qvmplayercamera.h>
00032 #include <qvgui/qvdefaultgui.h>
00033 #include <qvip/qvipp/qvipp.h>
00034 #include <qvip/qvpolyline.h>
00035 #include <qvdta/qvdta.h>
00036 
00037 #ifndef DOXYGEN_IGNORE_THIS
00038 
00039 
00040 class PointPlusValue
00041         { QPoint point;
00042           float value;
00043 
00044         public:
00045                 PointPlusValue() : point(0,0), value(0.0) {}
00046                 PointPlusValue(int x, int y, float v): point(x,y), value(v) {}
00047                 QPoint getPoint() {return point;}
00048                 float getValue() {return value;}
00049                 bool operator<(const PointPlusValue &ppv) const { return (value < ppv.value);}
00050         };
00051 
00052 
00053 inline sFloat rectArea(const QVImage<sFloat> &integralImage, int x0, int y0, int x1, int y1)
00054 { // Calculates the rectangular area defined by (left,top)-(right,bottom) by using an integral image.
00055   // OJO, documentar que la imagen integral tiene que tener una fila y una columna más que la original
00056   // y cómo se utilizan para obtener el área de un rectángulo dado.
00057 
00058         QVIMAGE_INIT_READ(sFloat,integralImage);
00059         return(QVIMAGE_PIXEL(integralImage,x1,y1,0)
00060                 -QVIMAGE_PIXEL(integralImage,x1,y0,0)
00061                 -QVIMAGE_PIXEL(integralImage,x0,y1,0)
00062                 +QVIMAGE_PIXEL(integralImage,x0,y0,0));
00063 }
00064 
00065 
00066 void ApplyDyyIPP(QVImage<sFloat> &integral, QVImage<sFloat> &imageDyy, int octave, int scale)
00067 {
00068         int rows=integral.getRows(), cols=integral.getCols();
00069         QVImage<sFloat> aux(cols,rows),auxab(cols,rows),auxde(cols,rows),auxcf(cols,rows),
00070                         auxdecf(cols,rows),auxdecf3(cols,rows), auxhg(cols,rows), 
00071                         auxabhg(cols,rows), auxabcdefgh(cols,rows);
00072         aux=integral;
00073 
00074 
00075 // The magic numbers correspond to the 9x9 mask
00076 
00077         const int incMargin = 1, incWidth=4, incHeight=2;
00078         const int margin=2 + incMargin*octave + scale*(incMargin<<octave);  // increment of the margin of the mask
00079         const int width = 5 + incWidth*octave + scale*(incWidth << octave);
00080         const int height = 3 + incHeight*octave + scale*(incHeight << octave);
00081         const int destx= 4 + (incMargin+incHeight)*octave + scale*((incMargin+incHeight)<<octave);
00082 
00083         integral.setROI(margin,0,cols-(width+margin),rows-destx); // (a) los numeros son para una mascara de 9x9
00084         aux.setROI(width+margin,0,cols-(width+margin),rows-destx); // (b)
00085         Sub(aux,integral,auxab,QPoint(destx,destx));  // auxab = (a-b)
00086         auxab.setAnchor(0,0);
00087 
00088         integral.setROI(width+margin,height,cols-(width+margin),rows-2*height);  // (d)
00089         aux.setROI(margin,2*height,cols-(width+margin),rows-2*height); // (e)
00090         Add(integral,aux,auxde,QPoint(destx,destx));  // auxde = (d+e)
00091         auxde.setAnchor(0,0);
00092 
00093         integral.setROI(margin,height,cols-(margin+width),rows-2*height);  // (c)
00094         aux.setROI(margin+width,2*height,cols-(margin+width),rows-2*height); // (f)
00095         Add(integral,aux,auxcf,QPoint(destx,destx));  // auxcf = (c+f)
00096         auxcf.setAnchor(0,0);
00097 
00098         auxde.setROI(destx,destx,cols-destx,rows-destx);  // (d+e)
00099         auxcf.setROI(destx,destx,cols-destx,rows-destx); // (c+f)
00100         Sub(auxcf,auxde,auxdecf,QPoint(destx,destx));  // auxdecf = (d+e)-(c+f)
00101         auxdecf.setAnchor(0,0);
00102         
00103         MulC(auxdecf,auxdecf3,3.0,QPoint(destx,destx));  // auxdecf3 = 3*((d+e)-(c+f))
00104         auxdecf3.setAnchor(0,0);
00105 
00106         integral.setROI(margin+width,3*height,cols-(margin+width),rows-3*height);  // (h)
00107         aux.setROI(margin,3*height,cols-(margin+width),rows-3*height); // (g)
00108         auxhg.setAnchor(0,0);
00109         Sub(aux,integral,auxhg,QPoint(destx,destx));  // aux2 = (h-g)
00110 
00111         auxab.setROI(destx,destx,cols-destx,rows-destx);  // (a-b)
00112         auxhg.setROI(destx,destx,cols-destx,rows-destx); // (h-g)
00113         auxabhg.setAnchor(0,0);
00114         Add(auxab,auxhg,auxabhg,QPoint(destx,destx));  // auxabhg = (a-b)+(h-g)
00115 
00116         auxabhg.setROI(destx,destx,cols-destx,rows-destx);  // (a-b)+(h-g)
00117         auxdecf3.setROI(destx,destx,cols-destx,rows-destx); // 3*((d+e)-(c+f))
00118 
00119         Add(auxabhg,auxdecf3,auxabcdefgh,QPoint(destx,destx));  // auxabcdefgh = (a-b)+(h-g)+3*((d+e)-(c+f))
00120 
00121         MulC(auxabcdefgh,imageDyy,1.0/(width*height),QPoint(destx,destx)); 
00122 
00123         imageDyy.setROI(0,0,cols,rows); imageDyy.setAnchor(0,0);
00124 
00125 
00126 }
00127 
00128 void ApplyDxxIPP(QVImage<sFloat> &integral, QVImage<sFloat> &imageDxx, int octave, int scale)
00129 {
00130         int rows=integral.getRows(), cols=integral.getCols();
00131         QVImage<sFloat> aux(cols,rows),auxab(cols,rows),auxde(cols,rows),auxcf(cols,rows),
00132                         auxdecf(cols,rows),auxdecf3(cols,rows), auxhg(cols,rows), 
00133                         auxabhg(cols,rows), auxabcdefgh(cols,rows);
00134         aux=integral;
00135 
00136 
00137 // The magic numbers correspond to the 9x9 mask
00138 
00139         const int incMargin = 1, incWidth=4, incHeight=2;
00140         const int margin=2 + incMargin*octave + scale*(incMargin<<octave);  // increment of the margin of the mask
00141         const int width = 5 + incWidth*octave + scale*(incWidth << octave);
00142         const int height = 3 + incHeight*octave + scale*(incHeight << octave);
00143         const int destx= 4 + (incMargin+incHeight)*octave + scale*((incMargin+incHeight)<<octave);
00144 
00145         integral.setROI(0,margin,cols-destx,rows-(margin+width)); // (a) los numeros son para una mascara de 9x9
00146         aux.setROI(0,margin+width,cols-destx,rows-(margin+width)); // (b)
00147         Sub(aux,integral,auxab,QPoint(destx,destx));  // auxab = (a-b)
00148         auxab.setAnchor(0,0);
00149 
00150         integral.setROI(height,margin+width,cols-2*height,rows-(margin+width));  // (d)
00151         aux.setROI(2*height,margin,cols-2*height,rows-(margin+width)); // (e)
00152         Add(integral,aux,auxde,QPoint(destx,destx));  // auxde = (d+e)
00153         auxde.setAnchor(0,0);
00154 
00155         integral.setROI(height,margin,cols-2*height,rows-(margin+width));  // (c)
00156         aux.setROI(2*height,margin+width,cols-2*height,rows-(margin+width)); // (f)
00157         Add(integral,aux,auxcf,QPoint(destx,destx));  // auxcf = (c+f)
00158         auxcf.setAnchor(0,0);
00159 
00160         auxde.setROI(destx,destx,cols-destx,rows-destx);  // (d+e)
00161         auxcf.setROI(destx,destx,cols-destx,rows-destx); // (c+f)
00162         Sub(auxcf,auxde,auxdecf,QPoint(destx,destx));  // auxdecf = (d+e)-(c+f)
00163         auxdecf.setAnchor(0,0);
00164         
00165         MulC(auxdecf,auxdecf3,3.0,QPoint(destx,destx));  // auxdecf3 = 3*((d+e)-(c+f))
00166         auxdecf3.setAnchor(0,0);
00167 
00168         integral.setROI(3*height,(margin+width),cols-3*height,rows-(margin+width));  // (h)
00169         aux.setROI(3*height,margin,cols-3*height,rows-(margin+width)); // (g)
00170         auxhg.setAnchor(0,0);
00171         Sub(aux,integral,auxhg,QPoint(destx,destx));  // aux2 = (h-g)
00172 
00173         auxab.setROI(destx,destx,cols-destx,rows-destx);  // (a-b)
00174         auxhg.setROI(destx,destx,cols-destx,rows-destx); // (h-g)
00175         auxabhg.setAnchor(0,0);
00176         Add(auxab,auxhg,auxabhg,QPoint(destx,destx));  // auxabhg = (a-b)+(h-g)
00177 
00178         auxabhg.setROI(destx,destx,cols-destx,rows-destx);  // (a-b)+(h-g)
00179         auxdecf3.setROI(destx,destx,cols-destx,rows-destx); // 3*((d+e)-(c+f))
00180         auxabcdefgh.setAnchor(destx,destx);
00181         Add(auxabhg,auxdecf3,auxabcdefgh,QPoint(destx,destx));  // auxabcdefgh = (a-b)+(h-g)+3*((d+e)-(c+f))
00182 
00183         MulC(auxabcdefgh,imageDxx,1.0/(width*height),QPoint(destx,destx)); 
00184 
00185         imageDxx.setROI(0,0,cols,rows); imageDxx.setAnchor(0,0);
00186 
00187 }
00188 
00189 void ApplyDxyIPP(QVImage<sFloat> &integral, QVImage<sFloat> &imageDxy, int octave, int scale)
00190 {
00191         int rows=integral.getRows(), cols=integral.getCols();
00192         QVImage<sFloat> aux(cols,rows),auxab(cols,rows),auxde(cols,rows),auxcf(cols,rows),
00193                         auxdecf(cols,rows),auxdecf3(cols,rows), auxhg(cols,rows), 
00194                         auxabhg(cols,rows), auxabcdefgh(cols,rows), auxijkl(cols,rows), auxmnop(cols,rows), diag1(cols,rows), diag2(cols,rows);
00195         aux=integral;
00196 
00197 
00198 // The magic numbers correspond to the 9x9 mask
00199 
00200         const int incMargin = 1, incWidth=2, incHeight=2;
00201         const int margin=1 + incMargin*octave + scale*(incMargin<<octave);  // increment of the margin of the mask
00202         const int interMargin = 1;
00203         const int width = 3 + incWidth*octave + scale*(incWidth << octave);
00204         const int height = 3 + incHeight*octave + scale*(incHeight << octave);
00205         const int destx= 4 + (incMargin+incHeight)*octave + scale*((incMargin+incHeight)<<octave);
00206         const int totalwidth=margin+width+interMargin+width+margin;
00207 
00208         integral.setROI(margin,margin,cols-destx,rows-destx); // (a) los numeros son para una mascara de 9x9
00209         aux.setROI(destx,destx,cols-destx,rows-destx); // (d)
00210         Add(aux,integral,auxab,QPoint(destx,destx));  // auxab = (a+d)
00211         auxab.setAnchor(0,0);
00212 
00213         integral.setROI(destx,margin,cols-destx,rows-destx);  // (b)
00214         aux.setROI(margin,destx,cols-destx,rows-destx); // (c)
00215         Add(integral,aux,auxde,QPoint(destx,destx));  // auxde = (c+b)
00216         auxde.setAnchor(0,0);
00217 
00218         auxde.setROI(destx,destx,cols-destx,rows-destx);  // (a+d)
00219         auxab.setROI(destx,destx,cols-destx,rows-destx); // (c+b)
00220         Sub(auxde,auxab,auxdecf,QPoint(destx,destx));  // auxdecf = (a+d)-(c+d)
00221         auxdecf.setAnchor(0,0);
00222 
00223         integral.setROI(margin+width+interMargin,margin,cols-(totalwidth-margin),rows-destx); // (e)
00224         aux.setROI(totalwidth-margin,destx,cols-(totalwidth-margin),rows-destx); // (h)
00225         Add(aux,integral,auxab,QPoint(destx,destx));  // auxab = (e+h)
00226         auxab.setAnchor(0,0);
00227 
00228         integral.setROI((totalwidth-margin),margin,cols-(totalwidth-margin),rows-destx);  // (f)
00229         aux.setROI(margin+width+interMargin,destx,cols-(totalwidth-margin),rows-destx); // (g)
00230         Add(integral,aux,auxde,QPoint(destx,destx));  // auxde = (f+g)
00231         auxde.setAnchor(0,0);
00232 
00233         auxde.setROI(destx,destx,cols-destx,rows-destx);  // (e+h)
00234         auxab.setROI(destx,destx,cols-destx,rows-destx); // (f+g)
00235         Sub(auxde,auxab,auxabhg,QPoint(destx,destx));  // auxabhg = (e+h)-(f+g)
00236         auxabhg.setAnchor(0,0);
00237 
00238         integral.setROI(margin,(margin+width+interMargin),cols-destx,rows-(totalwidth-margin)); // (i)
00239         aux.setROI(destx,(totalwidth-margin),cols-destx,rows-(totalwidth-margin)); // (l)
00240         Add(aux,integral,auxab,QPoint(destx,destx));  // auxab = (i+l)
00241         auxab.setAnchor(0,0);
00242 
00243         integral.setROI(margin,(totalwidth-margin),cols-destx,rows-(totalwidth-margin));  // (k)
00244         aux.setROI(destx,(margin+width+interMargin),cols-destx,rows-(totalwidth-margin)); // (j)
00245         Add(integral,aux,auxde,QPoint(destx,destx));  // auxde = (j+k)
00246         auxde.setAnchor(0,0);
00247 
00248         auxde.setROI(destx,destx,cols-destx,rows-destx);  // (j+k)
00249         auxab.setROI(destx,destx,cols-destx,rows-destx); // (i+l)
00250         Sub(auxde,auxab,auxijkl,QPoint(destx,destx));  // auxijkl = (e+h)-(f+g)
00251         auxijkl.setAnchor(0,0);
00252 
00253         integral.setROI((margin+width+interMargin),(margin+width+interMargin),cols-(totalwidth-margin),rows-(totalwidth-margin)); // (i)
00254         aux.setROI((totalwidth-margin),(totalwidth-margin),cols-(totalwidth-margin),rows-(totalwidth-margin)); // (l)
00255         Add(aux,integral,auxab,QPoint(destx,destx));  // auxab = (m+p)
00256         auxab.setAnchor(0,0);
00257 
00258         integral.setROI((totalwidth-margin),(margin+width+interMargin),cols-(totalwidth-margin),rows-(totalwidth-margin));  // (k)
00259         aux.setROI((margin+width+interMargin),(totalwidth-margin),cols-(totalwidth-margin),rows-(totalwidth-margin)); // (j)
00260         Add(integral,aux,auxde,QPoint(destx,destx));  // auxde = (n+o)
00261         auxde.setAnchor(0,0);
00262 
00263         auxde.setROI(destx,destx,cols-destx,rows-destx);  // (n+o)
00264         auxab.setROI(destx,destx,cols-destx,rows-destx); // (m+p)
00265         Sub(auxde,auxab,auxmnop,QPoint(destx,destx));  // auxijkl = (e+h)-(f+g)
00266         auxmnop.setAnchor(0,0);
00267 
00268         auxdecf.setROI(destx,destx,cols-destx,rows-destx);
00269         auxmnop.setROI(destx,destx,cols-destx,rows-destx);
00270         Add(auxdecf,auxmnop,diag1,QPoint(destx,destx));
00271 
00272         auxijkl.setROI(destx,destx,cols-destx,rows-destx);
00273         auxabhg.setROI(destx,destx,cols-destx,rows-destx);
00274         Add(auxijkl,auxabhg,diag2,QPoint(destx,destx));
00275 
00276         diag1.setROI(destx,destx,cols-destx,rows-destx);
00277         diag2.setROI(destx,destx,cols-destx,rows-destx);
00278         Sub(diag2,diag1,auxabcdefgh,QPoint(destx,destx));
00279 
00280         MulC(auxabcdefgh,imageDxy,1.0/(width*height),QPoint(destx,destx)); 
00281 }
00282 
00283 void detHessianIPP(QVImage<sFloat> &integral, QVImage<sFloat> &detHessian, int octave, int scale)
00284 {       // Suponemos que la máscara Dyy está compuesta de los puntos a,b,c,d,e,f,g y h siendo las
00285         // esquinas de los tres rectángulos con los que se pretende hacer la operacion:
00286         // (abcd)-2*(cdef)-(efgh)  donde abcd es el área del rectangulo formado por esos 4 puntos.
00287         // Operando llegamos a que consiste en calcular: (a-b) + 3(d+e-c-f) + (h-g)
00288 
00289 // HAY QUE COMPROBAR QUE LAS DIMENSIONES DE LAS IMAGENES SON LA MISMA
00290 
00291         int rows=integral.getRows(), cols=integral.getCols();
00292         QVImage<sFloat> imageDxx(cols,rows), imageDyy(cols,rows), imageDxy(cols,rows), squared(cols,rows),multiplied(cols,rows), squared81(cols,rows);
00293 
00294         const int incCenter = 3;  // de una escala a otra el centro se desplaza 3 pixels
00295         const int destx= 4 + (incCenter)*octave + scale*(incCenter<<octave);
00296         const float MINVAL = 0.0;  // minimal significant value
00297 
00298         ApplyDxxIPP(integral,imageDxx,octave,scale);
00299         ApplyDyyIPP(integral,imageDyy,octave,scale); 
00300         ApplyDxyIPP(integral,imageDxy,octave,scale);
00301 
00302         imageDxx.setMarginROI(destx);
00303         imageDyy.setMarginROI(destx);
00304         imageDxy.setMarginROI(destx);
00305 
00306         Sqr(imageDxy,squared,QPoint(destx,destx));
00307         MulC(squared,squared81,0.81,QPoint(destx,destx));  // 0.81 is a magic number for normalizing the value of the approximate determinant.
00308 
00309         Mul(imageDxx,imageDyy,multiplied,QPoint(destx,destx));
00310 
00311         squared81.setMarginROI(destx);
00312         multiplied.setMarginROI(destx);
00313         Sub(squared81,multiplied,detHessian,QPoint(destx,destx));
00314         detHessian.setMarginROI(destx);
00315         Threshold_Val(detHessian,MINVAL,0.0,ippCmpLess);  // remove the values less than a mininum.
00316 
00317         detHessian.setAnchor(0,0);
00318         detHessian.setMarginROI(destx);
00319 
00320 
00321 }
00322 
00323 QList<QPoint> MaxIPP( QVImage<sFloat> &image1, QVImage<sFloat> &image2, QVImage<sFloat> &image3, float percentage, int threshold)  // blockSize(3x3x3) = 3
00324 { 
00325   
00326   QList<QPoint> listMax;
00327   float max1, min1, aux; int xmax, ymax;
00328   float max2, min2;
00329   float max3, min3;
00330   float max, min;
00331   QRect image1ROI=image1.getROI();
00332   QRect image2ROI=image2.getROI();
00333   QRect image3ROI=image3.getROI();
00334 
00335   int rows=image3.getRows(), cols=image3.getCols();
00336   QVImage<sFloat> imageMax1(cols,rows), imageMax2(cols,rows), imageMax3(cols,rows);
00337   int beginx=image3.getROI().x(), beginy=image3.getROI().y();
00338   int endx=image3.getROI().width()+beginx, endy=image3.getROI().height()+beginy;
00339   imageMax1.setMarginROI(beginx);
00340   imageMax2.setMarginROI(beginx);
00341   imageMax3.setMarginROI(beginx);
00342 
00343   image1.setMarginROI(beginx);
00344   imageMax1.setMarginROI(beginx);
00345   FilterMax(image1,imageMax1,3,3,QPoint(beginx+1,beginy+1));
00346   image2.setMarginROI(beginx);
00347   imageMax2.setMarginROI(beginx);
00348   FilterMax(image2,imageMax2,3,3,QPoint(beginx+1,beginy+1));
00349   imageMax3.setMarginROI(beginx);
00350   FilterMax(image3,imageMax3,3,3,QPoint(beginx+1,beginy+1));
00351 
00352   // dejamos los ROI como estaban
00353   image1.setROI(image1ROI);
00354   image2.setROI(image2ROI);
00355   image3.setROI(image3ROI);
00356 
00357 
00358   // aqui hay que examinar los tres maximos para encontrar el maximo vertical y marcarlo en imageMax2
00359 
00360   QVIMAGE_INIT_READ(sFloat,imageMax1);
00361   QVIMAGE_INIT_WRITE(sFloat,imageMax2);
00362   QVIMAGE_INIT_READ(sFloat,imageMax3);
00363   QVIMAGE_INIT_READ(sFloat,image2);
00364 
00365   QMap<sFloat,QPoint> listMap;
00366   sFloat faux, fmaxvalue=-1e30, fminvalue=1e30;
00367   for(int i=beginx; i<endx; ++i)
00368   {  for(int j=beginy; j<endy; ++j)
00369      { faux = QVIMAGE_PIXEL(imageMax2,i,j,0);
00370        if ((faux > threshold) && (faux == QVIMAGE_PIXEL(image2,i,j,0)) && (faux > QVIMAGE_PIXEL(imageMax1,i,j,0)) && (faux > QVIMAGE_PIXEL(imageMax3,i,j,0)))
00371          {  listMap.insertMulti(faux,QPoint(i,j));
00372          }
00373      }
00374   }
00375  QList<QPoint> valuesList = listMap.values();
00376  QList<QPoint> listFiltered;
00377  int miPercentage= percentage * valuesList.size();  // threshold es el % de elementos a mostrar
00378  for(int i=valuesList.size()-miPercentage; i<valuesList.size(); ++i)
00379    listFiltered.append(valuesList[i]);
00380  return(listFiltered);
00381 }
00382 
00383 
00384 
00385 float applyDxx(const QVImage<sFloat> &integralImage, int x, int y, int octave, int scale) 
00386         { 
00387         // las octavas comienzan en 0 y el incremento se multiplica por 2^octava antes de usarse
00388         // dim = dim + scale*(6 << octave)
00389         int w = 5 + 4*octave + scale*(4 << octave);  // ancho de la máscara de 9x9 (5x3) e incremento de ese ancho en cada escala (4 pixels)
00390         int h = 3 + 2*octave + scale*(2 << octave);  // alto de la máscara de 9x9 (5x3) e incremento de ese alto en cada escala (2 pixels)
00391 
00392         float a,b,c,d,e,f,g,hh;
00393         QVIMAGE_INIT_READ(sFloat,integralImage);
00394         a = QVIMAGE_PIXEL(integralImage,x-h/2-h,  y-w/2,0);
00395         b = QVIMAGE_PIXEL(integralImage,x-h/2,    y-w/2,0);
00396         c = QVIMAGE_PIXEL(integralImage,x+h/2+1,  y-w/2,0);
00397         d = QVIMAGE_PIXEL(integralImage,x+h+h/2+1,    y-w/2,0);
00398         e = QVIMAGE_PIXEL(integralImage,x-h/2-h,  y+w/2+1,0);
00399         f = QVIMAGE_PIXEL(integralImage,x-h/2,  y+w/2+1,0);
00400         g = QVIMAGE_PIXEL(integralImage,x+h/2+1,y+w/2+1,0);
00401         hh = QVIMAGE_PIXEL(integralImage,x+h/2+h+1,y+w/2+1,0);
00402 
00403         return((a+hh-d-e+3*(f+c-b-g))/(w*h));
00404         }
00405 
00406 float applyDyy(const QVImage<sFloat> &integralImage, int x, int y, int octave, int scale) 
00407         { 
00408         // las octavas comienzan en 0 y el incremento se multiplica por 2^octava antes de usarse
00409         // dim = dim + scale*(6 << octave)
00410         int w = 5 + 4*octave + scale*(4 << octave);  // anchohreshold  de la máscara de 9x9 (5x3) e incremento de ese ancho en cada escala (4 pixels)
00411         int h = 3 + 2*octave + scale*(2 << octave);  // alto de la máscara de 9x9 (5x3) e incremento de ese alto en cada escala (2 pixels)
00412         float a,b,c,d,e,f,g,hh;
00413         QVIMAGE_INIT_READ(sFloat,integralImage);
00414         a = QVIMAGE_PIXEL(integralImage,x-w/2,y-h-h/2,0);
00415         c = QVIMAGE_PIXEL(integralImage,x-w/2,y-h/2,0);
00416         e = QVIMAGE_PIXEL(integralImage,x-w/2,y+h/2+1,0);
00417         g = QVIMAGE_PIXEL(integralImage,x-w/2,y+h+h/2+1,0);
00418         b = QVIMAGE_PIXEL(integralImage,x+w/2+1,y-h-h/2,0);
00419         d = QVIMAGE_PIXEL(integralImage,x+w/2+1,y-h/2,0);
00420         f = QVIMAGE_PIXEL(integralImage,x+w/2+1,y+h/2+1,0);
00421         hh = QVIMAGE_PIXEL(integralImage,x+w/2+1,y+h+h/2+1,0);
00422 
00423         return((a-b+hh-g+3*(d+e-c-f))/(w*h));
00424 
00425         }
00426 
00427 float applyDxy(const QVImage<sFloat> &integralImage, int x, int y, int octave, int scale) 
00428         { 
00429         // las octavas comienzan en 0 y el incremento se multiplica por 2^octava antes de usarse
00430         // dim = dim + scale*(6 << octave)
00431         int w = 3 + 2*octave + scale*(2 << octave);  // ancho de la máscara de 9x9 (5x3) e incremento de ese ancho en cada escala (4 pixels)
00432         int h = 3 + 2*octave + scale*(2 << octave);  // alto de la máscara de 9x9 (5x3) e incremento de ese alto en cada escala (2 pixels)
00433         float a,b,c,d,e,f,g,hh,i,j,k,l,m,n,o,p;
00434         QVIMAGE_INIT_READ(sFloat,integralImage);
00435         a = QVIMAGE_PIXEL(integralImage,x-w,y-h,0);
00436         c = QVIMAGE_PIXEL(integralImage,x-w,y,0);
00437         i = QVIMAGE_PIXEL(integralImage,x-w,y+1,0);
00438         k = QVIMAGE_PIXEL(integralImage,x-w,y+h+1,0);
00439         b = QVIMAGE_PIXEL(integralImage,x,y-h,0);
00440         d = QVIMAGE_PIXEL(integralImage,x,y,0);
00441         j = QVIMAGE_PIXEL(integralImage,x,y+1,0);
00442         l = QVIMAGE_PIXEL(integralImage,x,y+h+1,0);
00443         e = QVIMAGE_PIXEL(integralImage,x+1,y-h,0);
00444         g = QVIMAGE_PIXEL(integralImage,x+1,y,0);
00445         m = QVIMAGE_PIXEL(integralImage,x+1,y+1,0);
00446         o = QVIMAGE_PIXEL(integralImage,x+1,y+h+1,0);
00447         f = QVIMAGE_PIXEL(integralImage,x+w+1,y-h,0);
00448         hh = QVIMAGE_PIXEL(integralImage,x+w+1,y,0);
00449         n = QVIMAGE_PIXEL(integralImage,x+w+1,y+1,0);
00450         p = QVIMAGE_PIXEL(integralImage,x+w+1,y+h+1,0);
00451 
00452         return(((a+d-b-c)+(m+p-n-o)-(e+hh-f-g)-(i+l-j-k))/(w*h));
00453         }
00454 
00455 
00456 void detHessianColumns(const QVImage<sFloat> &integralImage, QVImage<sFloat> &hessian, int octave, int scale)
00457 {  // OJO. Se aplica la máscara dando saltos dependiendo de la octava en la que estemos. step=2^octava.
00458         sFloat det;
00459         int cols = integralImage.getCols(), rows = integralImage.getRows();
00460         int sizeMask=9 + 6*octave + scale*(6 << octave);
00461         int step= 1 << octave;
00462         int colsHessian = cols/step, rowsHessian = rows/step;
00463         int marginHessian = ((sizeMask)/2)/step+1; // Obtenemos un margen para el ROI de la imagen del hessiano.
00464         int marginImage = marginHessian*step;  // Obtenemos un margen para el ROI de la imagen integral.
00465         int w = 5 + 4*octave + scale*(4 << octave); 
00466         int h = 3 + 2*octave + scale*(2 << octave);
00467         int margin = 2 + 1*octave + scale*(1<<octave);
00468         int marginDxy = 1 + 1*octave + scale*(1<<octave);
00469         int wDxy = 3 + 2*octave + scale*(2 << octave); 
00470         int hDxy = 3 + 2*octave + scale*(2 << octave);
00471         int beginxDxx=0, beginyDxx=margin;
00472         int beginxDyy=margin, beginyDyy=0;
00473         int beginxDxy=marginDxy, beginyDxy=marginDxy;
00474         int xDyy,yDyy,xDxx,yDxx,xDxy,yDxy;
00475         sFloat aDxx,bDxx,cDxx,dDxx,eDxx,fDxx,gDxx,hDxx;
00476         sFloat aDyy,bDyy,cDyy,dDyy,eDyy,fDyy,gDyy,hDyy;
00477         sFloat aDxy,bDxy,cDxy,dDxy,eDxy,fDxy,gDxy,HDxy,iDxy,jDxy,kDxy,lDxy,mDxy,nDxy,oDxy,pDxy;
00478         sFloat Dxx, Dyy, Dxy;
00479         QVImage<sFloat> imageDxx(cols,rows), imageDyy(cols,rows), imageDxy(cols,rows);
00480         QVImage<sFloat> imageDet(cols,rows);
00481 
00482 
00483         QVIMAGE_INIT_READ(sFloat,integralImage);
00484 
00485         // Dyy
00486         QVIMAGE_INIT_WRITE(sFloat,imageDyy);
00487         for(xDyy=beginxDyy; xDyy<cols-sizeMask; ++xDyy) // lo haremos para todas las columnas
00488         {
00489             for(int offset=0; offset < h; ++offset) // damos h pasadas de h en h filas
00490             {
00491                 yDyy=beginyDyy+offset;
00492                 // primera fila Dyy
00493                 aDyy = QVIMAGE_PIXEL(integralImage,xDyy,yDyy,0);
00494                 bDyy = QVIMAGE_PIXEL(integralImage,xDyy+w,yDyy,0);
00495                 cDyy = QVIMAGE_PIXEL(integralImage,xDyy,yDyy+h,0);
00496                 dDyy = QVIMAGE_PIXEL(integralImage,xDyy+w,yDyy+h,0);
00497                 eDyy = QVIMAGE_PIXEL(integralImage,xDyy,yDyy+2*h,0);
00498                 fDyy = QVIMAGE_PIXEL(integralImage,xDyy+w,yDyy+2*h,0);
00499 
00500                 for(int yDyy=beginyDyy+offset; yDyy<rows-sizeMask; yDyy += h ) // OJO, hay que ir de H en H y repetir H veces.
00501                 { 
00502                         gDyy = QVIMAGE_PIXEL(integralImage,xDyy,yDyy+2*h+h,0);
00503                         hDyy = QVIMAGE_PIXEL(integralImage,xDyy+w,yDyy+2*h+h,0);
00504                 
00505                         Dyy = ((aDyy-bDyy+hDyy-gDyy+3*(dDyy+eDyy-cDyy-fDyy))/(w*h));
00506                         aDyy = cDyy;
00507                         bDyy = dDyy;
00508                         cDyy = eDyy;
00509                         dDyy = fDyy;
00510                         eDyy = gDyy;
00511                         fDyy = hDyy;
00512 
00513                         QVIMAGE_PIXEL(imageDyy,xDyy+w/2,yDyy+h+h/2,0) = Dyy;
00514                 }
00515             }
00516         }
00517 
00518 
00519         // Dxx
00520         QVIMAGE_INIT_WRITE(sFloat,imageDxx);
00521         for(xDxx=beginxDxx; xDxx<cols-sizeMask; ++xDxx) // lo haremos para todas las columnas
00522         {
00523             for(int offset=0; offset < w; ++offset) // damos w pasadas de w en w filas
00524             {
00525                 yDxx=beginyDxx+offset;
00526                 // primera fila Dxx
00527                 aDxx = QVIMAGE_PIXEL(integralImage,xDxx,yDxx,0);
00528                 bDxx = QVIMAGE_PIXEL(integralImage,xDxx+h,yDxx,0);
00529                 cDxx = QVIMAGE_PIXEL(integralImage,xDxx+2*h,yDxx,0);
00530                 dDxx = QVIMAGE_PIXEL(integralImage,xDxx+3*h,yDxx,0);
00531 
00532                 for(int yDxx=beginyDxx+offset; yDxx<rows-sizeMask; yDxx += w ) // OJO, hay que ir de H en H y repetir H veces.
00533                 { 
00534                         eDxx = QVIMAGE_PIXEL(integralImage,xDxx,yDxx+w,0);
00535                         fDxx = QVIMAGE_PIXEL(integralImage,xDxx+h,yDxx+w,0);
00536                         gDxx = QVIMAGE_PIXEL(integralImage,xDxx+2*h,yDxx+w,0);
00537                         hDxx = QVIMAGE_PIXEL(integralImage,xDxx+3*h,yDxx+w,0);
00538                         Dxx = ((aDxx+hDxx-dDxx-eDxx+3*(fDxx+cDxx-bDxx-gDxx))/(w*h));
00539 
00540                         aDxx=eDxx;
00541                         bDxx=fDxx;
00542                         cDxx=gDxx;
00543                         dDxx=hDxx;
00544 
00545                         QVIMAGE_PIXEL(imageDxx,xDxx+h+h/2,yDxx+w/2,0) = Dxx;
00546 
00547                 }
00548             }
00549         }
00550 
00551 
00552 // Dxy. Para entenderlo es mejor mirar el dibujo en una cuadrícula.
00553         QVIMAGE_INIT_WRITE(sFloat,imageDxy);
00554         for(xDxy=beginxDxy; xDxy<cols-sizeMask; ++xDxy) // lo haremos para todas las columnas
00555         {
00556             for(int offset=0; offset < hDxy+1; ++offset) // damos h+1 pasadas de h+1 en h+1 filas
00557             {
00558                 yDxy=beginyDxy+offset;
00559                 // primera fila Dxy
00560                 aDxy = QVIMAGE_PIXEL(integralImage,xDxy,yDxy,0);
00561                 bDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy,yDxy,0);
00562                 cDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy+1,yDxy,0);
00563                 dDxy = QVIMAGE_PIXEL(integralImage,xDxy+2*wDxy+1,yDxy,0);
00564                 eDxy = QVIMAGE_PIXEL(integralImage,xDxy,yDxy+wDxy,0);
00565                 fDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy,yDxy+wDxy,0);
00566                 gDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy+1,yDxy+wDxy,0);
00567                 HDxy = QVIMAGE_PIXEL(integralImage,xDxy+2*wDxy+1,yDxy+wDxy,0);
00568 
00569                 for(int yDxy=beginyDxy+offset; yDxy<rows-sizeMask; yDxy += hDxy+1 ) // OJO, hay que ir de H en H y repetir H veces.
00570                 { 
00571                         iDxy = QVIMAGE_PIXEL(integralImage,xDxy,yDxy+wDxy+1,0);
00572                         jDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy,yDxy+wDxy+1,0);
00573                         kDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy+1,yDxy+wDxy+1,0);
00574                         lDxy = QVIMAGE_PIXEL(integralImage,xDxy+2*wDxy+1,yDxy+wDxy+1,0);
00575                         mDxy = QVIMAGE_PIXEL(integralImage,xDxy,yDxy+2*wDxy+1,0);
00576                         nDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy,yDxy+2*wDxy+1,0);
00577                         oDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy+1,yDxy+2*wDxy+1,0);
00578                         pDxy = QVIMAGE_PIXEL(integralImage,xDxy+2*wDxy+1,yDxy+2*wDxy+1,0);
00579                         
00580                         Dxy = (((aDxy-bDxy-eDxy+fDxy)+(kDxy-lDxy-oDxy+pDxy)-(cDxy-dDxy-gDxy+HDxy)-(iDxy-jDxy-mDxy+nDxy))/(wDxy*hDxy));
00581                         aDxy=iDxy;
00582                         bDxy=jDxy;
00583                         cDxy=kDxy;
00584                         dDxy=lDxy;
00585                         eDxy=mDxy;
00586                         fDxy=nDxy;
00587                         gDxy=oDxy;
00588                         HDxy=pDxy;
00589                         
00590                         QVIMAGE_PIXEL(imageDxy,xDxy+wDxy,yDxy+wDxy,0) = Dxy;
00591                 }
00592             }
00593         }
00594 
00595         QVIMAGE_INIT_WRITE(sFloat,hessian);
00596         
00597 
00598         for(int j=marginImage,jh=marginHessian; j<rows-marginImage;j+=step,++jh) //j=j+(1<<octave))
00599                 for(int i=marginImage,ih=marginHessian; i<cols-marginImage;i+=step,++ih) // i=i+(1<<octave))
00600                         { const register float Dxy_apply=QVIMAGE_PIXEL(imageDxy,i,j,0);
00601                         det = ( QVIMAGE_PIXEL(imageDxx,i,j,0)
00602                                 *
00603                                 QVIMAGE_PIXEL(imageDyy,i,j,0)
00604                                 -0.81*Dxy_apply*Dxy_apply
00605                                 );
00606                         det = (det < 0.0) ? 0.0 : det;
00607                         QVIMAGE_PIXEL(hessian,ih,jh,0) = det;
00608                         }
00609 
00610         hessian.setMarginROI(marginHessian);
00611         integralImage.setMarginROI(marginImage);
00612 
00613 }
00614 
00615 
00616 
00617 void detHessianFewColumns(const QVImage<sFloat> &integralImage, QVImage<sFloat> &hessian, int octave, int scale)
00618 {  // OJO. Se aplica la máscara dando saltos dependiendo de la octava en la que estemos. step=2^octava.
00619         sFloat det;
00620         int cols = integralImage.getCols(), rows = integralImage.getRows();
00621         int sizeMask=9 + 6*octave + scale*(6 << octave);
00622         int step= 1 << octave;
00623         int colsHessian = cols/step, rowsHessian = rows/step;
00624         int marginHessian = ((sizeMask)/2)/step+1; // Obtenemos un margen para el ROI de la imagen del hessiano.
00625         int marginImage = marginHessian*step;  // Obtenemos un margen para el ROI de la imagen integral.
00626         int w = 5 + 4*octave + scale*(4 << octave); 
00627         int h = 3 + 2*octave + scale*(2 << octave);
00628         int margin = 2 + 1*octave + scale*(1<<octave);
00629         int marginDxy = 1 + 1*octave + scale*(1<<octave);
00630         int wDxy = 3 + 2*octave + scale*(2 << octave); 
00631         int hDxy = 3 + 2*octave + scale*(2 << octave);
00632         int beginxDxx=0, beginyDxx=margin;
00633         int beginxDyy=margin, beginyDyy=0;
00634         int beginxDxy=marginDxy, beginyDxy=marginDxy;
00635         int xDyy,yDyy,xDxx,yDxx,xDxy,yDxy;
00636         sFloat aDxx,bDxx,cDxx,dDxx,eDxx,fDxx,gDxx,hDxx;
00637         sFloat aDyy,bDyy,cDyy,dDyy,eDyy,fDyy,gDyy,hDyy;
00638         sFloat aDxy,bDxy,cDxy,dDxy,eDxy,fDxy,gDxy,HDxy,iDxy,jDxy,kDxy,lDxy,mDxy,nDxy,oDxy,pDxy;
00639         sFloat Dxx, Dyy, Dxy;
00640         QVImage<sFloat> imageDxx(cols,rows), imageDyy(cols,rows), imageDxy(cols,rows);
00641         QVImage<sFloat> imageDet(cols,rows);
00642         int numRowsPerIteration=rows;
00643         int limitNumRowsPerIteration;
00644 
00645 
00646         QVIMAGE_INIT_READ(sFloat,integralImage);
00647 
00648         // Dyy
00649         QVIMAGE_INIT_WRITE(sFloat,imageDyy);
00650         for(int y=beginyDyy; y<rows-sizeMask; y += numRowsPerIteration)
00651         {       limitNumRowsPerIteration = ((y+numRowsPerIteration) < (cols-sizeMask)) ? numRowsPerIteration : ((y+numRowsPerIteration) - (cols-sizeMask));
00652                 for(xDyy=beginxDyy; xDyy<cols-sizeMask; ++xDyy) // lo haremos para todas las columnas
00653                 {
00654                         for(int offset=0; offset < h; ++offset) // damos h pasadas de h en h filas
00655                         {
00656                                 yDyy=y+offset;
00657                                 // primera fila Dyy
00658                                 aDyy = QVIMAGE_PIXEL(integralImage,xDyy,yDyy,0);
00659                                 bDyy = QVIMAGE_PIXEL(integralImage,xDyy+w,yDyy,0);
00660                                 cDyy = QVIMAGE_PIXEL(integralImage,xDyy,yDyy+h,0);
00661                                 dDyy = QVIMAGE_PIXEL(integralImage,xDyy+w,yDyy+h,0);
00662                                 eDyy = QVIMAGE_PIXEL(integralImage,xDyy,yDyy+2*h,0);
00663                                 fDyy = QVIMAGE_PIXEL(integralImage,xDyy+w,yDyy+2*h,0);
00664                 
00665                                 for(;yDyy < y+limitNumRowsPerIteration; yDyy += h ) // OJO, hay que ir de H en H y repetir H veces.
00666                                 { 
00667                                         gDyy = QVIMAGE_PIXEL(integralImage,xDyy,yDyy+2*h+h,0);
00668                                         hDyy = QVIMAGE_PIXEL(integralImage,xDyy+w,yDyy+2*h+h,0);
00669                                 
00670                                         Dyy = ((aDyy-bDyy+hDyy-gDyy+3*(dDyy+eDyy-cDyy-fDyy))/(w*h));
00671                                         aDyy = cDyy;
00672                                         bDyy = dDyy;
00673                                         cDyy = eDyy;
00674                                         dDyy = fDyy;
00675                                         eDyy = gDyy;
00676                                         fDyy = hDyy;
00677                 
00678                                         QVIMAGE_PIXEL(imageDyy,xDyy+w/2,yDyy+h+h/2,0) = Dyy;
00679                                 }
00680                         }
00681                 }
00682         }
00683 
00684         // Dxx
00685         QVIMAGE_INIT_WRITE(sFloat,imageDxx);
00686         for(int y=beginyDxx; y<rows-sizeMask; y += numRowsPerIteration)
00687         {       limitNumRowsPerIteration = ((y+numRowsPerIteration) < (cols-sizeMask)) ? numRowsPerIteration : ((y+numRowsPerIteration) - (cols-sizeMask));
00688                 for(xDxx=beginxDxx; xDxx<cols-sizeMask; ++xDxx) // lo haremos para todas las columnas
00689                 {
00690                         for(int offset=0; offset < w; ++offset) // damos w pasadas de w en w filas
00691                         {
00692                                 yDxx=y+offset;
00693                                 // primera fila Dxx
00694                                 aDxx = QVIMAGE_PIXEL(integralImage,xDxx,yDxx,0);
00695                                 bDxx = QVIMAGE_PIXEL(integralImage,xDxx+h,yDxx,0);
00696                                 cDxx = QVIMAGE_PIXEL(integralImage,xDxx+2*h,yDxx,0);
00697                                 dDxx = QVIMAGE_PIXEL(integralImage,xDxx+3*h,yDxx,0);
00698                 
00699                                 for(; yDxx<y+limitNumRowsPerIteration; yDxx += w ) // OJO, hay que ir de H en H y repetir H veces.
00700                                 { 
00701                                         eDxx = QVIMAGE_PIXEL(integralImage,xDxx,yDxx+w,0);
00702                                         fDxx = QVIMAGE_PIXEL(integralImage,xDxx+h,yDxx+w,0);
00703                                         gDxx = QVIMAGE_PIXEL(integralImage,xDxx+2*h,yDxx+w,0);
00704                                         hDxx = QVIMAGE_PIXEL(integralImage,xDxx+3*h,yDxx+w,0);
00705                                         Dxx = ((aDxx+hDxx-dDxx-eDxx+3*(fDxx+cDxx-bDxx-gDxx))/(w*h));
00706                 
00707                                         aDxx=eDxx;
00708                                         bDxx=fDxx;
00709                                         cDxx=gDxx;
00710                                         dDxx=hDxx;
00711                 
00712                                         QVIMAGE_PIXEL(imageDxx,xDxx+h+h/2,yDxx+w/2,0) = Dxx;
00713                 
00714                                 }
00715                         }
00716                 }
00717         }
00718 
00719 // Dxy. Para entenderlo es mejor mirar el dibujo en una cuadrícula.
00720         QVIMAGE_INIT_WRITE(sFloat,imageDxy);
00721 
00722         for(int y=beginyDxx; y<rows-sizeMask; y += numRowsPerIteration)
00723         {       limitNumRowsPerIteration = ((y+numRowsPerIteration) < (cols-sizeMask)) ? numRowsPerIteration : ((y+numRowsPerIteration) - (cols-sizeMask));
00724                 for(xDxy=beginxDxy; xDxy<cols-sizeMask; ++xDxy) // lo haremos para todas las columnas
00725                 {
00726                         for(int offset=0; offset < hDxy+1; ++offset) // damos h+1 pasadas de h+1 en h+1 filas
00727                         {
00728                                 yDxy=y+offset;
00729                                 // primera fila Dxy
00730                                 aDxy = QVIMAGE_PIXEL(integralImage,xDxy,yDxy,0);
00731                                 bDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy,yDxy,0);
00732                                 cDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy+1,yDxy,0);
00733                                 dDxy = QVIMAGE_PIXEL(integralImage,xDxy+2*wDxy+1,yDxy,0);
00734                                 eDxy = QVIMAGE_PIXEL(integralImage,xDxy,yDxy+wDxy,0);
00735                                 fDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy,yDxy+wDxy,0);
00736                                 gDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy+1,yDxy+wDxy,0);
00737                                 HDxy = QVIMAGE_PIXEL(integralImage,xDxy+2*wDxy+1,yDxy+wDxy,0);
00738                 
00739                                 for(; yDxy<y+limitNumRowsPerIteration; yDxy += hDxy+1 ) // OJO, hay que ir de H en H y repetir H veces.
00740                                 { 
00741                                         iDxy = QVIMAGE_PIXEL(integralImage,xDxy,yDxy+wDxy+1,0);
00742                                         jDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy,yDxy+wDxy+1,0);
00743                                         kDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy+1,yDxy+wDxy+1,0);
00744                                         lDxy = QVIMAGE_PIXEL(integralImage,xDxy+2*wDxy+1,yDxy+wDxy+1,0);
00745                                         mDxy = QVIMAGE_PIXEL(integralImage,xDxy,yDxy+2*wDxy+1,0);
00746                                         nDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy,yDxy+2*wDxy+1,0);
00747                                         oDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy+1,yDxy+2*wDxy+1,0);
00748                                         pDxy = QVIMAGE_PIXEL(integralImage,xDxy+2*wDxy+1,yDxy+2*wDxy+1,0);
00749                                         
00750                                         Dxy = (((aDxy-bDxy-eDxy+fDxy)+(kDxy-lDxy-oDxy+pDxy)-(cDxy-dDxy-gDxy+HDxy)-(iDxy-jDxy-mDxy+nDxy))/(wDxy*hDxy));
00751                                         aDxy=iDxy;
00752                                         bDxy=jDxy;
00753                                         cDxy=kDxy;
00754                                         dDxy=lDxy;
00755                                         eDxy=mDxy;
00756                                         fDxy=nDxy;
00757                                         gDxy=oDxy;
00758                                         HDxy=pDxy;
00759                                         
00760                                         QVIMAGE_PIXEL(imageDxy,xDxy+wDxy,yDxy+wDxy,0) = Dxy;
00761                                 }
00762                         }
00763                 }
00764         }
00765 
00766         QVIMAGE_INIT_WRITE(sFloat,hessian);
00767         
00768 
00769         for(int j=marginImage,jh=marginHessian; j<rows-marginImage;j+=step,++jh) //j=j+(1<<octave))
00770                 for(int i=marginImage,ih=marginHessian; i<cols-marginImage;i+=step,++ih) // i=i+(1<<octave))
00771                         { const register float Dxy_apply=QVIMAGE_PIXEL(imageDxy,i,j,0);
00772                         det = ( QVIMAGE_PIXEL(imageDxx,i,j,0)
00773                                 *
00774                                 QVIMAGE_PIXEL(imageDyy,i,j,0)
00775                                 -0.81*Dxy_apply*Dxy_apply
00776                                 );
00777                         det = (det < 0.0) ? 0.0 : det;
00778                         QVIMAGE_PIXEL(hessian,ih,jh,0) = det;
00779                         }
00780 
00781         hessian.setMarginROI(marginHessian);
00782         integralImage.setMarginROI(marginImage);
00783 
00784 }
00785 
00786 
00787 void detHessianRowsColumns(const QVImage<sFloat> &integralImage, QVImage<sFloat> &hessian, int octave, int scale)
00788 {  // OJO. Se aplica la máscara dando saltos dependiendo de la octava en la que estemos. step=2^octava.
00789    // pero primero lo hace horizontalmente para luego hacerlo verticalmente.
00790 
00791         int cols = integralImage.getCols(), rows = integralImage.getRows();
00792         int sizeMask=9 + 6*octave + scale*(6 << octave);
00793         int step= 1 << octave;
00794         int marginHessian = ((sizeMask)/2)/step+1; // Obtenemos un margen para el ROI de la imagen del hessiano.
00795         int marginImage = marginHessian*step;  // Obtenemos un margen para el ROI de la imagen integral.
00796         int w = 5 + 4*octave + scale*(4 << octave); 
00797         int h = 3 + 2*octave + scale*(2 << octave);
00798         int margin = 2 + 1*octave + scale*(1<<octave);
00799         int marginDxy = 1 + 1*octave + scale*(1<<octave);
00800         int beginxDxx=0, beginyDxx=margin;
00801         int beginxDyy=margin, beginyDyy=0;
00802         int beginxDxy=marginDxy, beginyDxy=marginDxy;
00803         int blockJump=1;
00804         int xDyy,yDyy,xDxx,yDxx,xDxy,yDxy;
00805         sFloat aDyy[blockJump],bDyy[blockJump],cDyy[blockJump],dDyy[blockJump],eDyy[blockJump],fDyy[blockJump],gDyy[blockJump],hDyy[blockJump];
00806         sFloat *blocksDyy[8]={aDyy,bDyy,cDyy,dDyy,eDyy,fDyy,gDyy,hDyy};
00807         QVImage<sFloat> imageDxx(cols,rows), imageDyy(cols,rows), imageDxy(cols,rows);
00808         QVImage<sFloat> imageDet(cols,rows);
00809         sFloat *t1, *t2;
00810 
00811 
00812         QVIMAGE_INIT_READ(sFloat,integralImage);
00813         // Dyy
00814         QVIMAGE_INIT_WRITE(sFloat,imageDyy);
00815 
00816         for(xDyy=beginxDyy; xDyy<cols-sizeMask; xDyy += blockJump) // lo haremos para todas las columnas pero dando saltos
00817         {
00818             int limit=((xDyy+blockJump) < (cols-sizeMask)) ? blockJump : ((xDyy+blockJump) - (cols-sizeMask));
00819             for(int offsety=0; offsety < h; ++offsety) // damos h pasadas de h en h filas
00820             {
00821                 yDyy=beginyDyy+offsety;
00822                 // primera fila Dyy
00823 
00824                 // para no salirnos en la última iteración
00825                 for(int offsetx=0; offsetx < limit; ++offsetx)
00826                 {       
00827                         blocksDyy[0][offsetx] = QVIMAGE_PIXEL(integralImage,offsetx+xDyy,yDyy,0);
00828                         blocksDyy[1][offsetx] = QVIMAGE_PIXEL(integralImage,offsetx+xDyy+w,yDyy,0);
00829                         blocksDyy[2][offsetx] = QVIMAGE_PIXEL(integralImage,offsetx+xDyy,yDyy+h,0);
00830                         blocksDyy[3][offsetx] = QVIMAGE_PIXEL(integralImage,offsetx+xDyy+w,yDyy+h,0);
00831                         blocksDyy[4][offsetx] = QVIMAGE_PIXEL(integralImage,offsetx+xDyy,yDyy+2*h,0);
00832                         blocksDyy[5][offsetx] = QVIMAGE_PIXEL(integralImage,offsetx+xDyy+w,yDyy+2*h,0);
00833                 }
00834                 for(int yDyy=beginyDyy+offsety; yDyy<rows-sizeMask; yDyy += h ) // OJO, hay que ir de H en H y repetir H veces.
00835                 { 
00836                         for(int offsetx=0; offsetx < limit; ++offsetx)
00837                         {       
00838                                 blocksDyy[6][offsetx] = QVIMAGE_PIXEL(integralImage,offsetx+xDyy,yDyy+2*h+h,0);
00839                                 blocksDyy[7][offsetx] = QVIMAGE_PIXEL(integralImage,offsetx+xDyy+w,yDyy+2*h+h,0);
00840                         }
00841                         for(int k=0; k<limit; ++k)
00842                                 QVIMAGE_PIXEL(imageDyy,k+xDyy+w/2,yDyy+h+h/2,0) = ((blocksDyy[0][k]-blocksDyy[1][k]+blocksDyy[7][k]-blocksDyy[6][k]+3*(blocksDyy[3][k]+blocksDyy[4][k]-blocksDyy[2][k]-blocksDyy[5][k]))/(w*h));
00843 
00844 
00845                         t1=blocksDyy[0]; t2=blocksDyy[1];
00846                         blocksDyy[0]=blocksDyy[2];
00847                         blocksDyy[1]=blocksDyy[3];
00848                         blocksDyy[2]=blocksDyy[4];
00849                         blocksDyy[3]=blocksDyy[5];
00850                         blocksDyy[4]=blocksDyy[6];
00851                         blocksDyy[5]=blocksDyy[7];
00852                         blocksDyy[6]=t1;
00853                         blocksDyy[7]=t2;
00854 
00855                 }
00856 
00857             }
00858         }
00859 
00860         hessian = imageDyy;
00861 /*
00862         // Dxx
00863         QVIMAGE_INIT_WRITE(sFloat,imageDxx);
00864         for(xDxx=beginxDxx; xDxx<cols-sizeMask; ++xDxx) // lo haremos para todas las columnas
00865         {
00866             for(int offset=0; offset < w; ++offset) // damos w pasadas de w en w filas
00867             {
00868                 yDxx=beginyDxx+offset;
00869                 // primera fila Dxx
00870                 aDxx = QVIMAGE_PIXEL(integralImage,xDxx,yDxx,0);
00871                 bDxx = QVIMAGE_PIXEL(integralImage,xDxx+h,yDxx,0);
00872                 cDxx = QVIMAGE_PIXEL(integralImage,xDxx+2*h,yDxx,0);
00873                 dDxx = QVIMAGE_PIXEL(integralImage,xDxx+3*h,yDxx,0);
00874 
00875                 for(int yDxx=beginyDxx+offset; yDxx<rows-sizeMask; yDxx += w ) // OJO, hay que ir de H en H y repetir H veces.
00876                 { 
00877                         eDxx = QVIMAGE_PIXEL(integralImage,xDxx,yDxx+w,0);
00878                         fDxx = QVIMAGE_PIXEL(integralImage,xDxx+h,yDxx+w,0);
00879                         gDxx = QVIMAGE_PIXEL(integralImage,xDxx+2*h,yDxx+w,0);
00880                         hDxx = QVIMAGE_PIXEL(integralImage,xDxx+3*h,yDxx+w,0);
00881                         Dxx = ((aDxx+hDxx-dDxx-eDxx+3*(fDxx+cDxx-bDxx-gDxx))/(w*h));
00882 
00883                         aDxx=eDxx;
00884                         bDxx=fDxx;
00885                         cDxx=gDxx;
00886                         dDxx=hDxx;
00887 
00888                         QVIMAGE_PIXEL(imageDxx,xDxx+h+h/2,yDxx+w/2,0) = Dxx;
00889 
00890                 }
00891             }
00892         }
00893 
00894 
00895 // Dxy. Para entenderlo es mejor mirar el dibujo en una cuadrícula.
00896         QVIMAGE_INIT_WRITE(sFloat,imageDxy);
00897         for(xDxy=beginxDxy; xDxy<cols-sizeMask; ++xDxy) // lo haremos para todas las columnas
00898         {
00899             for(int offset=0; offset < hDxy+1; ++offset) // damos h+1 pasadas de h+1 en h+1 filas
00900             {
00901                 yDxy=beginyDxy+offset;
00902                 // primera fila Dxy
00903                 aDxy = QVIMAGE_PIXEL(integralImage,xDxy,yDxy,0);
00904                 bDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy,yDxy,0);
00905                 cDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy+1,yDxy,0);
00906                 dDxy = QVIMAGE_PIXEL(integralImage,xDxy+2*wDxy+1,yDxy,0);
00907                 eDxy = QVIMAGE_PIXEL(integralImage,xDxy,yDxy+wDxy,0);
00908                 fDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy,yDxy+wDxy,0);
00909                 gDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy+1,yDxy+wDxy,0);
00910                 HDxy = QVIMAGE_PIXEL(integralImage,xDxy+2*wDxy+1,yDxy+wDxy,0);
00911 
00912                 for(int yDxy=beginyDxy+offset; yDxy<rows-sizeMask; yDxy += hDxy+1 ) // OJO, hay que ir de H en H y repetir H veces.
00913                 { 
00914                         iDxy = QVIMAGE_PIXEL(integralImage,xDxy,yDxy+wDxy+1,0);
00915                         jDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy,yDxy+wDxy+1,0);
00916                         kDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy+1,yDxy+wDxy+1,0);
00917                         lDxy = QVIMAGE_PIXEL(integralImage,xDxy+2*wDxy+1,yDxy+wDxy+1,0);
00918                         mDxy = QVIMAGE_PIXEL(integralImage,xDxy,yDxy+2*wDxy+1,0);
00919                         nDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy,yDxy+2*wDxy+1,0);
00920                         oDxy = QVIMAGE_PIXEL(integralImage,xDxy+wDxy+1,yDxy+2*wDxy+1,0);
00921                         pDxy = QVIMAGE_PIXEL(integralImage,xDxy+2*wDxy+1,yDxy+2*wDxy+1,0);
00922                         
00923                         Dxy = (((aDxy-bDxy-eDxy+fDxy)+(kDxy-lDxy-oDxy+pDxy)-(cDxy-dDxy-gDxy+HDxy)-(iDxy-jDxy-mDxy+nDxy))/(wDxy*hDxy));
00924                         aDxy=iDxy;
00925                         bDxy=jDxy;
00926                         cDxy=kDxy;
00927                         dDxy=lDxy;
00928                         eDxy=mDxy;
00929                         fDxy=nDxy;
00930                         gDxy=oDxy;
00931                         HDxy=pDxy;
00932                         
00933                         QVIMAGE_PIXEL(imageDxy,xDxy+wDxy,yDxy+wDxy,0) = Dxy;
00934                 }
00935             }
00936         }
00937 
00938         QVIMAGE_INIT_WRITE(sFloat,hessian);
00939         
00940 
00941         for(int j=marginImage,jh=marginHessian; j<rows-marginImage;j+=step,++jh) //j=j+(1<<octave))
00942                 for(int i=marginImage,ih=marginHessian; i<cols-marginImage;i+=step,++ih) // i=i+(1<<octave))
00943                         { const register float Dxy_apply=QVIMAGE_PIXEL(imageDxy,i,j,0);
00944                         det = ( QVIMAGE_PIXEL(imageDxx,i,j,0)
00945                                 *
00946                                 QVIMAGE_PIXEL(imageDyy,i,j,0)
00947                                 -0.81*Dxy_apply*Dxy_apply
00948                                 );
00949                         det = (det < 0.0) ? 0.0 : det;
00950                         QVIMAGE_PIXEL(hessian,ih,jh,0) = det;
00951                         }
00952 */
00953         hessian.setMarginROI(marginHessian);
00954         integralImage.setMarginROI(marginImage);
00955 
00956 }
00957 
00958 
00959 void detHessian(const QVImage<sFloat> &integral, QVImage<sFloat> &hessian, int octave, int scale)
00960 {  // OJO. Se aplica la máscara dando saltos dependiendo de la octava en la que estemos. step=2^octava.
00961         QVIMAGE_INIT_WRITE(sFloat,hessian);
00962         sFloat det;
00963         int cols = integral.getCols(), rows = integral.getRows();
00964         int sizeMask=9 + 6*octave + scale*(6 << octave);
00965         int step= 1 << octave;
00966         int colsHessian = cols/step, rowsHessian = rows/step;
00967         int marginHessian = ((sizeMask)/2)/step+1; // Obtenemos un margen para el ROI de la imagen del hessiano.
00968         int marginImage = marginHessian*step;  // Obtenemos un margen para el ROI de la imagen integral.
00969         for(int j=marginImage,jh=marginHessian; j<rows-marginImage;j+=step,++jh) //j=j+(1<<octave))
00970                 for(int i=marginImage,ih=marginHessian; i<cols-marginImage;i+=step,++ih) // i=i+(1<<octave))
00971                         { const float Dxy_apply=applyDxy(integral,i,j,octave,scale);
00972                         det = ( applyDxx(integral,i,j,octave,scale)
00973                                 *
00974                                 applyDyy(integral,i,j,octave,scale)
00975                                 -0.81*Dxy_apply*Dxy_apply
00976                                 );
00977                         det = (det < 0.0) ? 0.0 : det;
00978                         QVIMAGE_PIXEL(hessian,ih,jh,0) = det;
00979                         }
00980         hessian.setMarginROI(marginHessian);
00981         integral.setMarginROI(marginImage);
00982 }
00983 
00984 
00985 QList<QVPolyline> addBlobsIPP(QList<QVPolyline> listBlobs, QList<QPoint> listPoints, int octave, int scale)
00986 { int radius=4+3*octave+scale*(3<<octave);
00987   for(QList<QPoint>::const_iterator i=listPoints.constBegin(); i!=listPoints.constEnd(); ++i)
00988         listBlobs.append(QVPolyline::ellipse(10,i->x(),i->y(),radius,radius,0));
00989   return(listBlobs);
00990 }
00991 
00992 QList<QVPolyline> addBlobs(QList<QVPolyline> listBlobs, QList<QPoint> listPoints, int octave, int scale)
00993 { int radius=4+3*octave+scale*(3<<octave);
00994   int sizeMask=9 + 6*octave + scale*(6 << octave);
00995   int step= 1 << octave;
00996 
00997   for(QList<QPoint>::const_iterator i=listPoints.constBegin(); i!=listPoints.constEnd(); ++i)
00998         listBlobs.append(QVPolyline::ellipse(10,i->x()*step,i->y()*step,radius,radius,0));
00999   return(listBlobs);
01000 }
01001 
01002 
01003 QList<QVPolyline> getBlobsIPP(QVImage<sFloat> &integralFloat, float percentage, float THRESHOLD)
01004 {       int cols=integralFloat.getCols(), rows=integralFloat.getRows();
01005         QVImage<sFloat> approxHessian[4]={QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows),
01006                                         QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows)};
01007         QList<QVPolyline> listBlobs;
01008 
01009 
01010         for(int sca=0; sca<4; ++sca)
01011           detHessianIPP(integralFloat,approxHessian[sca],0,sca);
01012         listBlobs=addBlobsIPP(listBlobs,MaxIPP(approxHessian[0],approxHessian[1],approxHessian[2], percentage,THRESHOLD),0,1);
01013         listBlobs=addBlobsIPP(listBlobs,MaxIPP(approxHessian[1],approxHessian[2],approxHessian[3], percentage,THRESHOLD),0,2);
01014 
01015 
01016         for(int oct=1; oct<3; ++oct)
01017         {  approxHessian[0]=approxHessian[1];
01018            for(int sca=1; sca<4; ++sca)
01019              detHessianIPP(integralFloat,approxHessian[sca],oct,sca);
01020            listBlobs=addBlobsIPP(listBlobs,MaxIPP(approxHessian[0],approxHessian[1],approxHessian[2], percentage,THRESHOLD),oct,1);
01021            listBlobs=addBlobsIPP(listBlobs,MaxIPP(approxHessian[1],approxHessian[2],approxHessian[3], percentage,THRESHOLD),oct,2);
01022         }
01023 
01024         return(listBlobs);
01025 }
01026 
01027 QList<QVPolyline> getBlobs(QVImage<sFloat> &integralFloat, float percentage, float THRESHOLD)
01028 {       int cols=integralFloat.getCols(), rows=integralFloat.getRows();
01029         QVImage<sFloat> approxHessian0[4]={QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows),
01030                                         QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows)};
01031         QVImage<sFloat> approxHessian1[4]={QVImage<sFloat>(cols/2,rows/2),QVImage<sFloat>(cols/2,rows/2),
01032                                         QVImage<sFloat>(cols/2,rows/2),QVImage<sFloat>(cols/2,rows/2)};
01033         QVImage<sFloat> approxHessian2[4]={QVImage<sFloat>(cols/4,rows/4),QVImage<sFloat>(cols/4,rows/4),
01034                                         QVImage<sFloat>(cols/4,rows/4),QVImage<sFloat>(cols/4,rows/4)};
01035         QList<QVPolyline> listBlobs;
01036 
01037         int oct=0;
01038         for(int sca=0; sca<4; ++sca)
01039           detHessian(integralFloat,approxHessian0[sca],oct,sca);
01040         listBlobs=addBlobs(listBlobs,MaxIPP(approxHessian0[0],approxHessian0[1],approxHessian0[2], percentage,THRESHOLD),oct,1);
01041         listBlobs=addBlobs(listBlobs,MaxIPP(approxHessian0[1],approxHessian0[2],approxHessian0[3], percentage,THRESHOLD),oct,2);
01042 
01043         oct=1;
01044         Resize(approxHessian0[1], approxHessian1[0],IPPI_INTER_NN);
01045         detHessian(integralFloat,approxHessian1[1],oct,1);
01046         detHessian(integralFloat,approxHessian1[2],oct,2);
01047         detHessian(integralFloat,approxHessian1[3],oct,3);
01048         listBlobs=addBlobs(listBlobs,MaxIPP(approxHessian1[0],approxHessian1[1],approxHessian1[2],percentage, THRESHOLD),oct,1);
01049         listBlobs=addBlobs(listBlobs,MaxIPP(approxHessian1[1],approxHessian1[2],approxHessian1[3], percentage,THRESHOLD),oct,2);
01050 
01051         oct=2;
01052         Resize(approxHessian1[1], approxHessian2[0],IPPI_INTER_NN);
01053         detHessian(integralFloat,approxHessian2[1],oct,1);
01054         detHessian(integralFloat,approxHessian2[2],oct,2);
01055         detHessian(integralFloat,approxHessian2[3],oct,3);
01056         listBlobs=addBlobs(listBlobs,MaxIPP(approxHessian2[0],approxHessian2[1],approxHessian2[2], percentage,THRESHOLD),oct,1);
01057         listBlobs=addBlobs(listBlobs,MaxIPP(approxHessian2[1],approxHessian2[2],approxHessian2[3], percentage,THRESHOLD),oct,2);
01058 
01059 
01060         return(listBlobs);
01061 }
01062 
01063 
01064 
01065 class MyWorker: public QVWorker
01066         {
01067         public:
01068                 MyWorker(QString name): QVWorker(name)
01069                         { 
01070                         addProperty("Octave", inputFlag, 0, "octave ", 0, 3);
01071                         addProperty<int>("Threshold", inputFlag, 600, "Threshold",0,10000);
01072                         addProperty<float>("Percentage",inputFlag,1.0,"Percentage",0.01,1.0);
01073 //                      addProperty< QVImage<sFloat> >("Integral", outputFlag);
01074                         addProperty< QVImage<uChar> >("Input image", inputFlag|outputFlag);
01075                         addProperty< QVImage<uChar> >("Output image 1", outputFlag);
01076 /*                      addProperty< QVImage<uChar> >("Output image 2", outputFlag);
01077                         addProperty< QVImage<uChar> >("Output image 3", outputFlag);*/
01078 /*                      addProperty< QVImage<sFloat> >("h1", outputFlag);
01079                         addProperty< QVImage<sFloat> >("h2", outputFlag);
01080                         addProperty< QVImage<sFloat> >("h3", outputFlag);
01081                         addProperty< QVImage<sFloat> >("h4", outputFlag);*/
01082 //                      addProperty< QVImage<sFloat> >("ApproxHessian3", outputFlag);
01083 //                      addProperty< QVImage<sFloat> >("ApproxHessian4", outputFlag);
01084 //                      addProperty< QList<QPoint> >("ListPoints",outputFlag);
01085 //                      addProperty< QList<QPoint> >("ListPoints2",outputFlag);
01086                         addProperty< QList<QVPolyline> >("BlobsMax1",outputFlag);
01087 /*                      addProperty< QList<QVPolyline> >("BlobsMax2",outputFlag);
01088                         addProperty< QList<QVPolyline> >("BlobsMax3",outputFlag);*/
01089                         }
01090 
01091                 void iterate()
01092                         {
01093 //                      const int sizeMax = getPropertyValue<int>("Window size");
01094                         int octave=getPropertyValue<int>("Octave");
01095                         sInt THRESHOLD = getPropertyValue<sInt>("Threshold");
01096                         sFloat percentage = getPropertyValue<sFloat>("Percentage");
01097                         QVImage<uChar> input0 = getPropertyValue< QVImage<uChar> >("Input image");
01098                         uInt rows = input0.getRows()*2, cols = input0.getCols()*2;
01099 
01100                         QVImage<uChar> input(cols, rows);
01101                         Resize(input0, input,IPPI_INTER_NN);
01102 
01103                         timeFlag("double size");
01104 
01105                         QVImage<sFloat> imageGaussian(cols,rows);
01106                         FilterGauss(input,imageGaussian,3);
01107 
01108                         ++cols; ++rows;
01109                         QVImage<sFloat> integralFloat(cols,rows);
01110                         Integral(imageGaussian,integralFloat,0);
01111 
01112                         QVImage<sFloat> Dyy1(cols,rows);
01113                         QVImage<sFloat> Dyy2(cols,rows);
01114 
01115                         timeFlag("gaussian");
01116 
01117 
01118 //QList<QVPolyline> listBlobs2=getBlobs(integralFloat,THRESHOLD);
01119 QList<QVPolyline> listBlobs1;
01120 
01121 {       int cols=integralFloat.getCols(), rows=integralFloat.getRows();
01122         QVImage<sFloat> approxHessian0[4]={QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows),
01123                                         QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows)};
01124         QVImage<sFloat> approxHessian1[4]={QVImage<sFloat>(cols/2,rows/2),QVImage<sFloat>(cols/2,rows/2),
01125                                         QVImage<sFloat>(cols/2,rows/2),QVImage<sFloat>(cols/2,rows/2)};
01126 
01127 
01128         for(int sca=0; sca<4; ++sca)
01129           detHessianColumns(integralFloat,approxHessian0[sca],0,sca);
01130 
01131         listBlobs1=addBlobs(listBlobs1,MaxIPP(approxHessian0[0],approxHessian0[1],approxHessian0[2], percentage, THRESHOLD),0,1);
01132         listBlobs1=addBlobs(listBlobs1,MaxIPP(approxHessian0[1],approxHessian0[2],approxHessian0[3], percentage, THRESHOLD),0,2);
01133 timeFlag("columnas primera octava");
01134 
01135         for(int oct=1; oct<2; ++oct)
01136         {  Resize(approxHessian0[1], approxHessian1[0],IPPI_INTER_NN);
01137            //approxHessian1[0]=approxHessian0[1];
01138            detHessianColumns(integralFloat,approxHessian1[1],oct,1);
01139            detHessianColumns(integralFloat,approxHessian1[2],oct,2);
01140            detHessianColumns(integralFloat,approxHessian1[3],oct,3);
01141            listBlobs1=addBlobs(listBlobs1,MaxIPP(approxHessian1[0],approxHessian1[1],approxHessian1[2], percentage, THRESHOLD),oct,1);
01142            listBlobs1=addBlobs(listBlobs1,MaxIPP(approxHessian1[1],approxHessian1[2],approxHessian1[3], percentage,THRESHOLD),oct,2);
01143         }
01144 //timeFlag("segunda octava");
01145 }
01146 timeFlag("columnas");
01147 
01148 /*
01149 QList<QVPolyline> listBlobs2;
01150 
01151 {       int cols=integralFloat.getCols(), rows=integralFloat.getRows();
01152         QVImage<sFloat> approxHessian0[4]={QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows),
01153                                         QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows)};
01154         QVImage<sFloat> approxHessian1[4]={QVImage<sFloat>(cols/2,rows/2),QVImage<sFloat>(cols/2,rows/2),
01155                                         QVImage<sFloat>(cols/2,rows/2),QVImage<sFloat>(cols/2,rows/2)};
01156 
01157         for(int sca=0; sca<4; ++sca)
01158           detHessianFewColumns(integralFloat,approxHessian0[sca],0,sca);
01159 
01160         listBlobs2=addBlobs(listBlobs2,MaxIPP(approxHessian0[0],approxHessian0[1],approxHessian0[2], THRESHOLD),0,1);
01161         listBlobs2=addBlobs(listBlobs2,MaxIPP(approxHessian0[1],approxHessian0[2],approxHessian0[3], THRESHOLD),0,2);
01162 
01163 timeFlag("pocascolumnas primera octava");
01164 
01165         for(int oct=1; oct<2; ++oct)
01166         {  Resize(approxHessian0[1], approxHessian1[0],IPPI_INTER_NN);
01167            //approxHessian1[0]=approxHessian0[1];
01168            detHessianFewColumns(integralFloat,approxHessian1[1],oct,1);
01169            detHessianFewColumns(integralFloat,approxHessian1[2],oct,2);
01170            detHessianFewColumns(integralFloat,approxHessian1[3],oct,3);
01171            listBlobs2=addBlobs(listBlobs2,MaxIPP(approxHessian1[0],approxHessian1[1],approxHessian1[2], THRESHOLD),oct,1);
01172            listBlobs2=addBlobs(listBlobs2,MaxIPP(approxHessian1[1],approxHessian1[2],approxHessian1[3], THRESHOLD),oct,2);
01173         }
01174 //timeFlag("segunda octava");
01175 timeFlag("pocasColumnas");
01176 }
01177 
01178 QList<QVPolyline> listBlobs3;
01179 
01180 {       int cols=integralFloat.getCols(), rows=integralFloat.getRows();
01181         QVImage<sFloat> approxHessian0[4]={QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows),
01182                                         QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows)};
01183         QVImage<sFloat> approxHessian1[4]={QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows),
01184                                         QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows)};
01185 
01186 
01187         for(int sca=0; sca<4; ++sca)
01188           detHessianIPP(integralFloat,approxHessian0[sca],0,sca);
01189 
01190         listBlobs3=addBlobs(listBlobs3,MaxIPP(approxHessian0[0],approxHessian0[1],approxHessian0[2], THRESHOLD),0,1);
01191         listBlobs3=addBlobs(listBlobs3,MaxIPP(approxHessian0[1],approxHessian0[2],approxHessian0[3], THRESHOLD),0,2);
01192 timeFlag("IPP primera octava");
01193 
01194         for(int oct=1; oct<2; ++oct)
01195         {  approxHessian1[0]=approxHessian0[1];
01196            //approxHessian1[0]=approxHessian0[1];
01197            detHessianIPP(integralFloat,approxHessian1[1],oct,1);
01198            detHessianIPP(integralFloat,approxHessian1[2],oct,2);
01199            detHessianIPP(integralFloat,approxHessian1[3],oct,3);
01200            listBlobs3=addBlobs(listBlobs3,MaxIPP(approxHessian1[0],approxHessian1[1],approxHessian1[2], THRESHOLD),oct,1);
01201            listBlobs3=addBlobs(listBlobs3,MaxIPP(approxHessian1[1],approxHessian1[2],approxHessian1[3], THRESHOLD),oct,2);
01202         }
01203 //timeFlag("segunda octava");
01204 }
01205 timeFlag("IPP");
01206 */
01207 
01208 //                      QList<QVPolyline> listBlobs2 = getBlobs(integralFloat, THRESHOLD);
01209 
01210 //                      timeFlag("Hessian");
01211 
01212 
01213                         setPropertyValue< QVImage<uChar> >("Output image 1", imageGaussian);
01214 //                      setPropertyValue< QVImage<uChar> >("Output image 2", imageGaussian);
01215 //                      setPropertyValue< QVImage<uChar> >("Output image 3", imageGaussian);
01216 //                      setPropertyValue< QVImage<sFloat> >("Integral", integralFloat);
01217 //                      setPropertyValue< QVImage<sFloat> >("h1", Dyy1);
01218 //                      setPropertyValue< QVImage<sFloat> >("h2", Dyy2);
01219 //                      setPropertyValue< QVImage<sFloat> >("h3",Dyy3);
01220 //                      setPropertyValue< QVImage<sFloat> >("h4",Dyy4);
01221 
01222                         setPropertyValue< QList<QVPolyline > >("BlobsMax1",listBlobs1);
01223 //                      setPropertyValue< QList<QVPolyline > >("BlobsMax2",listBlobs2);
01224 //                      setPropertyValue< QList<QVPolyline > >("BlobsMax3",listBlobs3);
01225 
01226 //                      setPropertyValue< QList<QPoint> >("ListPoints",listMax[0]);
01227 //                      setPropertyValue< QList<QPoint> >("ListPoints2",listMax[1]);
01228                         timeFlag("shows");
01229 
01230                         }
01231         };
01232 
01233 int main(int argc, char *argv[])
01234         {  // ippSetNumThreads(1);
01235         QVApplication app(argc, argv,
01236                 "Example program for QVision library. It is an implementation of the SURF algorithm."
01237                 );
01238 
01239         QVMPlayerCamera camera1("Video 1");
01240         MyWorker worker("Surf Worker");
01241 
01242         camera1.link(&worker,"Input image");
01243 
01244         QVDefaultGUI interface;
01245 
01246 
01247         QVImageCanvas imageCanvas("Output image 1");
01248         imageCanvas.linkProperty(worker,"Output image 1");
01249 //      imageCanvas.linkProperty(worker,"ListPoints", Qt::green);
01250 //      imageCanvas.linkProperty(worker,"ListPoints2", Qt::red);
01251         imageCanvas.linkProperty(worker,"BlobsMax1", Qt::green);
01252 
01253 /*      QVImageCanvas imageCanvas1("Output image 2");
01254         imageCanvas1.linkProperty(worker,"Output image 2");*/
01255 //      imageCanvas.linkProperty(worker,"ListPoints", Qt::green);
01256 //      imageCanvas.linkProperty(worker,"ListPoints2", Qt::red);
01257 //      imageCanvas1.linkProperty(worker,"BlobsMax2", Qt::red);
01258 
01259 //      QVImageCanvas imageCanvas2("Output image 3");
01260 //      imageCanvas2.linkProperty(worker,"Output image 3");
01261 //      imageCanvas2.linkProperty(worker,"BlobsMax3", Qt::blue);
01262 
01263 //      QVImageCanvas imageCanvasIntegral("Integral");
01264 //      imageCanvasIntegral.linkProperty(worker,"Integral");
01265 
01266 //              QVImageCanvas imageCanvas1("ApproxHessian 1");
01267 //              imageCanvas1.linkProperty(worker,"h1");
01268 //  
01269 //         QVImageCanvas imageCanvas2("ApproxHessian 2");
01270 //         imageCanvas2.linkProperty(worker,"h2");
01271 
01272 //      QVImageCanvas imageCanvas3("ApproxHessian 3");
01273 //      imageCanvas3.linkProperty(worker,"h3");
01274 // 
01275 //        QVImageCanvas imageCanvas4("ApproxHessian 4");
01276 //        imageCanvas4.linkProperty(worker,"h4");
01277 
01278 // 
01279 //      QVImageCanvas imageCanvas3("ApproxHessian 3");
01280 //      imageCanvas3.linkProperty(worker,"ApproxHessian3");
01281 // 
01282 //      QVImageCanvas imageCanvas4("ApproxHessian 4");
01283 //      imageCanvas4.linkProperty(worker,"ApproxHessian4");
01284 
01285         //imageCanvas3.setLowHigh(low,high);
01286 
01287         /*QVImageCanvas imageCanvas1("Corner response image 1"), imageCanvas2("Corner response image 2");
01288         imageCanvas1.linkProperty(worker, "Corner response image 1");
01289         imageCanvas2.linkProperty(worker, "Corner response image 2");*/
01290 
01291         return app.exec();
01292         }
01293 
01294 #endif