examples/surf/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 #define QVIMAGE_ITERATOR_WRITE(TYPE, IMAGE, ITERATOR)   {}                                      \
00040         TYPE * __qv_image_iterator_##ITERATOR##__ = IMAGE.getWriteData();                       \
00041         const uInt __qv_iterator_col_inc_##ITERATOR##__ = IMAGE.getChannels();                  \
00042         const uInt __qv_iterator_row_inc_##ITERATOR##__ = IMAGE.getStep()/sizeof(TYPE);         \
00043         const uInt __qv_iterator_new_line_inc_##ITERATOR##__ = __qv_iterator_row_inc_##ITERATOR##__ - IMAGE.getCols();
00044 
00045 #define QVIMAGE_ITERATOR_READ(TYPE, IMAGE, ITERATOR)                                            \
00046         const TYPE * __qv_image_iterator_##ITERATOR##__ = IMAGE.getReadData();                  \
00047         const uInt __qv_iterator_col_inc_##ITERATOR##__ = IMAGE.getChannels();                  \
00048         const uInt __qv_iterator_row_inc_##ITERATOR##__ = IMAGE.getStep()/sizeof(TYPE);         \
00049         const uInt __qv_iterator_new_line_inc_##ITERATOR##__ = __qv_iterator_row_inc_##ITERATOR##__ - IMAGE.getCols();
00050 
00051 
00052 QList<QPoint> MaxIPPRel( QVImage<sFloat> &image1, QVImage<sFloat> &image2, QVImage<sFloat> &image3, float threshold)  // blockSize(3x3x3) = 3
00053 { 
00054   
00055   QList<QPoint> listMax;
00056   float max1, min1, aux; int xmax, ymax;
00057   float max2, min2;
00058   float max3, min3;
00059   float max, min;
00060   QRect image1ROI=image1.getROI();
00061   QRect image2ROI=image2.getROI();
00062   QRect image3ROI=image3.getROI();
00063 
00064   int rows=image3.getRows(), cols=image3.getCols();
00065   QVImage<sFloat> imageMax1(cols,rows), imageMax2(cols,rows), imageMax3(cols,rows);
00066   int beginx=image3.getROI().x(), beginy=image3.getROI().y();
00067   int endx=image3.getROI().width()+beginx, endy=image3.getROI().height()+beginy;
00068   imageMax1.setMarginROI(beginx);
00069   imageMax2.setMarginROI(beginx);
00070   imageMax3.setMarginROI(beginx);
00071 
00072   image1.setMarginROI(beginx);
00073   imageMax1.setMarginROI(beginx);
00074   FilterMax(image1,imageMax1,3,3,QPoint(beginx+1,beginy+1));
00075   image2.setMarginROI(beginx);
00076   imageMax2.setMarginROI(beginx);
00077   FilterMax(image2,imageMax2,3,3,QPoint(beginx+1,beginy+1));
00078   imageMax3.setMarginROI(beginx);
00079   FilterMax(image3,imageMax3,3,3,QPoint(beginx+1,beginy+1));
00080 
00081   // dejamos los ROI como estaban
00082   image1.setROI(image1ROI);
00083   image2.setROI(image2ROI);
00084   image3.setROI(image3ROI);
00085 
00086 
00087   // aqui hay que examinar los tres maximos para encontrar el maximo vertical y marcarlo en imageMax2
00088 
00089   QVIMAGE_INIT_READ(sFloat,imageMax1);
00090   QVIMAGE_INIT_WRITE(sFloat,imageMax2);
00091   QVIMAGE_INIT_READ(sFloat,imageMax3);
00092   QVIMAGE_INIT_READ(sFloat,image2);
00093 
00094   QMap<sFloat,QPoint> listMap;
00095   sFloat faux;
00096   for(int row=beginy; row<endy; ++row)
00097   {  for(int col=beginx; col<endx; ++col)
00098      { faux = QVIMAGE_PIXEL(imageMax2,col,row,0);
00099        if ((faux == QVIMAGE_PIXEL(image2,col,row,0)) && (faux > QVIMAGE_PIXEL(imageMax1,col,row,0)) && (faux > QVIMAGE_PIXEL(imageMax3,col,row,0)))
00100          {  listMap.insertMulti(faux,QPoint(col,row));
00101          }
00102      }
00103   }
00104  QList<QPoint> valuesList = listMap.values();
00105  QList<QPoint> listFiltered;
00106  int miThreshold = threshold * valuesList.size();  // threshold es el % de elementos a mostrar
00107  for(int i=valuesList.size()-miThreshold; i<valuesList.size(); ++i)
00108    listFiltered.append(valuesList[i]);
00109  return(listFiltered);
00110 }
00111 
00112 
00114 // Second type sequential access iterators
00116 #define QVIMAGE_ITERATOR_INIT2(TYPE, IMAGE)     {}                                                                      \
00117         const uInt __qv_iterator_col_inc_##IMAGE##__ = IMAGE.getChannels();                                             \
00118         const uInt __qv_iterator_row_inc_##IMAGE##__ = IMAGE.getStep()/sizeof(TYPE);                                    \
00119         const uInt __qv_iterator_new_line_inc_##IMAGE##__ = __qv_iterator_row_inc_##IMAGE##__ - IMAGE.getCols();
00120 
00121 #define QVIMAGE_ITERATOR_ROW_INCREMENT(IMAGE)           ( __qv_iterator_row_inc_##IMAGE##__ )
00122 #define QVIMAGE_ITERATOR_COL_INCREMENT(IMAGE)           ( __qv_iterator_col_inc_##IMAGE##__ )
00123 #define QVIMAGE_ITERATOR_NEW_LINE_INCREMENT(IMAGE)      ( __qv_iterator_new_line_inc_##IMAGE##__ )
00124 
00125 QList<QPoint> MaxIPPAbs( QVImage<sFloat> &image1, QVImage<sFloat> &image2, QVImage<sFloat> &image3, float threshold)  // blockSize(3x3x3) = 3
00126 { 
00127   
00128   QList<QPoint> listMax;
00129   float max1, min1, aux; int xmax, ymax;
00130   float max2, min2;
00131   float max3, min3;
00132   float max, min;
00133   QRect image1ROI=image1.getROI();
00134   QRect image2ROI=image2.getROI();
00135   QRect image3ROI=image3.getROI();
00136 
00137   int rows=image3.getRows(), cols=image3.getCols();
00138   QVImage<sFloat> imageMax1(cols,rows), imageMax2(cols,rows), imageMax3(cols,rows);
00139   int beginx=image3.getROI().x(), beginy=image3.getROI().y();
00140   int endx=image3.getROI().width()+beginx, endy=image3.getROI().height()+beginy;
00141   imageMax1.setMarginROI(beginx);
00142   imageMax2.setMarginROI(beginx);
00143   imageMax3.setMarginROI(beginx);
00144 
00145   image1.setMarginROI(beginx);
00146   imageMax1.setMarginROI(beginx);
00147   FilterMax(image1,imageMax1,3,3,QPoint(beginx+1,beginy+1));
00148   image2.setMarginROI(beginx);
00149   imageMax2.setMarginROI(beginx);
00150   FilterMax(image2,imageMax2,3,3,QPoint(beginx+1,beginy+1));
00151   imageMax3.setMarginROI(beginx);
00152   FilterMax(image3,imageMax3,3,3,QPoint(beginx+1,beginy+1));
00153 
00154   // dejamos los ROI como estaban
00155   image1.setROI(image1ROI);
00156   image2.setROI(image2ROI);
00157   image3.setROI(image3ROI);
00158 
00159 
00160   // aqui hay que examinar los tres maximos para encontrar el maximo vertical y marcarlo en imageMax2
00161 
00162   QVIMAGE_INIT_READ(sFloat,imageMax1);
00163   QVIMAGE_INIT_WRITE(sFloat,imageMax2);
00164   QVIMAGE_INIT_READ(sFloat,imageMax3);
00165   QVIMAGE_INIT_READ(sFloat,image2);
00166 
00167         /*QVIMAGE_ITERATOR_INIT2(sFloat, imageMax1);
00168         QVIMAGE_ITERATOR_INIT2(sFloat, imageMax2);
00169         QVIMAGE_ITERATOR_INIT2(sFloat, imageMax3);
00170         QVIMAGE_ITERATOR_INIT2(sFloat, image2);*/
00171 
00172         const sFloat    *imageMax1Ptr = &imageMax1(beginx, beginy);
00173         const sFloat    *imageMax2Ptr = &imageMax2(beginx, beginy);
00174         const sFloat    *imageMax3Ptr = &imageMax3(beginx, beginy);
00175         const sFloat    *image2Ptr = &image2(beginx, beginy);
00176 
00177   QList<QPoint> listFiltered;
00178   sFloat faux;
00179   for(int row=beginy; row<endy; ++row,  imageMax1Ptr = &QVIMAGE_PIXEL(imageMax1,0,row,0), imageMax2Ptr = &QVIMAGE_PIXEL(imageMax2,0,row,0),
00180                                         imageMax3Ptr = &QVIMAGE_PIXEL(imageMax3,0,row,0), image2Ptr = &QVIMAGE_PIXEL(image2,0,row,0) )
00181   {  for(int col=beginx; col<endx; ++col, ++imageMax1Ptr, ++imageMax2Ptr, ++imageMax3Ptr, ++image2Ptr)
00182      { faux = *imageMax2Ptr;
00183        if ((faux > threshold) && (faux == *image2Ptr) && (faux > *imageMax1Ptr) && (faux > *imageMax3Ptr))
00184          {  listFiltered.append(QPoint(col,row));
00185          }
00186      }
00187   }
00188  return(listFiltered);
00189 }
00190 
00191 
00192 void detHessianRowsNaive1(const QVImage<sInt> &integralImage, QVImage<sFloat> &hessian, int octave, int scale)
00193 {  // OJO. Se aplica la máscara dando saltos dependiendo de la octava en la que estemos. step=2^octava.
00194         const int cols = integralImage.getROI().width(), rows = integralImage.getROI().height();
00195         const int sizeMask=9 + 6*octave + scale*(6 << octave);
00196         const int step= 1;
00197         const int colsHessian = cols/step, rowsHessian = rows/step;
00198         const int marginHessian = ((sizeMask)/2)/step+1; // Obtenemos un margen para el ROI de la imagen del hessiano.
00199         const int marginImage = sizeMask/2;  // Obtenemos un margen para el ROI de la imagen integral.
00200         const int w = 5 + 4*octave + scale*(4 << octave); // anchura de la parte de la máscara que se evalúa para Dxx y Dyy
00201         const int h = 3 + 2*octave + scale*(2 << octave); // altura de la parte de la máscara que se evalúa para Dxx y Dyy
00202         const int margin = 2 + 1*octave + scale*(1<<octave); // márgen de la máscara que no se usa para Dxx y Dyy
00203         const int marginDxy = 1 + 1*octave + scale*(1<<octave);// márgen de la máscara que no se usa para Dxy
00204         const int wDxy = 3 + 2*octave + scale*(2 << octave); // anchura y altura de la parte de la máscara que se evalúa para Dxy
00205         const int hDxy = 3 + 2*octave + scale*(2 << octave);
00206         const int beginxDxx=0, beginyDxx=margin;
00207         const int beginxDyy=margin, beginyDyy=0;
00208         const int beginxDxy=marginDxy, beginyDxy=marginDxy;
00209         register sFloat Dxx, Dyy, Dxy;
00210         const float division = 1.0/(sizeMask*sizeMask*sizeMask*sizeMask);
00211 
00212 
00213         QVIMAGE_INIT_WRITE(sFloat,hessian);
00214 
00215         QVIMAGE_ITERATOR_READ(sInt, integralImage, itIntegral);
00216         __qv_image_iterator_itIntegral__ += integralImage.getROI().y()*__qv_iterator_row_inc_itIntegral__+integralImage.getROI().x();
00217 
00218         // Dyy
00219         const sInt *itaDyy, *itcDyy, *iteDyy, *itgDyy, *itbDyy, *itdDyy, *itfDyy, *ithDyy;  // recorreran las filas calculando la máscara
00220         const sInt *itaDxx, *itcDxx, *iteDxx, *itgDxx, *itbDxx, *itdDxx, *itfDxx, *ithDxx;  // recorreran las filas calculando la máscara
00221         const sInt *itaDxy, *itbDxy, *itcDxy, *itdDxy, *iteDxy, *itfDxy, *itgDxy, *ithDxy;  // recorreran las filas calculando la máscara
00222         const sInt *itiDxy, *itjDxy, *itkDxy, *itlDxy, *itmDxy, *itnDxy, *itoDxy, *itpDxy;  // recorreran las filas calculando la máscara
00223         const sInt *itbeginaDyy, *itbegincDyy, *itbegineDyy, *itbegingDyy, *itbeginbDyy, *itbegindDyy, *itbeginfDyy, *itbeginhDyy;  // punteros al comienzo de cada fila
00224         const sInt *itbeginaDxx, *itbegincDxx, *itbegineDxx, *itbegingDxx, *itbeginbDxx, *itbegindDxx, *itbeginfDxx, *itbeginhDxx;  // punteros al comienzo de cada fila
00225         const sInt *itbeginaDxy, *itbeginbDxy, *itbegincDxy, *itbegindDxy, *itbegineDxy, *itbeginfDxy, *itbegingDxy, *itbeginhDxy;  // punteros al comienzo de cada fila
00226         const sInt *itbeginiDxy, *itbeginjDxy, *itbeginkDxy, *itbeginlDxy, *itbeginmDxy, *itbeginnDxy, *itbeginoDxy, *itbeginpDxy;  // punteros al comienzo de cada fila
00227         
00228         const sInt *punteroComienzoDyy=__qv_image_iterator_itIntegral__+beginxDyy;
00229         const sInt *punteroComienzoDxx=__qv_image_iterator_itIntegral__+beginyDxx*__qv_iterator_row_inc_itIntegral__;
00230         const sInt *punteroComienzoDxy=__qv_image_iterator_itIntegral__+beginyDxy*__qv_iterator_row_inc_itIntegral__+beginxDxy;
00231 
00232         itbeginaDyy = punteroComienzoDyy;
00233         itbeginbDyy = punteroComienzoDyy + w;
00234         itbegincDyy = punteroComienzoDyy+h*__qv_iterator_row_inc_itIntegral__;
00235         itbegindDyy = punteroComienzoDyy+h*__qv_iterator_row_inc_itIntegral__+w;
00236         itbegineDyy = punteroComienzoDyy+2*h*__qv_iterator_row_inc_itIntegral__;
00237         itbeginfDyy = punteroComienzoDyy+2*h*__qv_iterator_row_inc_itIntegral__+w;
00238         itbegingDyy = punteroComienzoDyy+3*h*__qv_iterator_row_inc_itIntegral__;
00239         itbeginhDyy = punteroComienzoDyy+3*h*__qv_iterator_row_inc_itIntegral__+w;
00240 
00241         itbeginaDxx = punteroComienzoDxx;
00242         itbeginbDxx = punteroComienzoDxx + h;
00243         itbegincDxx = punteroComienzoDxx+ 2*h;
00244         itbegindDxx = punteroComienzoDxx+ 3*h;
00245         itbegineDxx = punteroComienzoDxx+w*__qv_iterator_row_inc_itIntegral__;
00246         itbeginfDxx = punteroComienzoDxx+w*__qv_iterator_row_inc_itIntegral__+h;
00247         itbegingDxx = punteroComienzoDxx+w*__qv_iterator_row_inc_itIntegral__+2*h;
00248         itbeginhDxx = punteroComienzoDxx+w*__qv_iterator_row_inc_itIntegral__+3*h;
00249 
00250         itbeginaDxy = punteroComienzoDxy;
00251         itbeginbDxy = punteroComienzoDxy + wDxy;
00252         itbegincDxy = punteroComienzoDxy+ wDxy+1;
00253         itbegindDxy = punteroComienzoDxy+ 2*wDxy+1;
00254         itbegineDxy = punteroComienzoDxy+wDxy*__qv_iterator_row_inc_itIntegral__;
00255         itbeginfDxy = punteroComienzoDxy+wDxy*__qv_iterator_row_inc_itIntegral__+wDxy;
00256         itbegingDxy = punteroComienzoDxy+wDxy*__qv_iterator_row_inc_itIntegral__+wDxy+1;
00257         itbeginhDxy = punteroComienzoDxy+wDxy*__qv_iterator_row_inc_itIntegral__+2*wDxy+1;
00258         itbeginiDxy = punteroComienzoDxy+(wDxy+1)*__qv_iterator_row_inc_itIntegral__;
00259         itbeginjDxy = punteroComienzoDxy+(wDxy+1)*__qv_iterator_row_inc_itIntegral__+wDxy;
00260         itbeginkDxy = punteroComienzoDxy+(wDxy+1)*__qv_iterator_row_inc_itIntegral__+wDxy+1;
00261         itbeginlDxy = punteroComienzoDxy+(wDxy+1)*__qv_iterator_row_inc_itIntegral__+2*wDxy+1;
00262         itbeginmDxy = punteroComienzoDxy+(2*wDxy+1)*__qv_iterator_row_inc_itIntegral__;
00263         itbeginnDxy = punteroComienzoDxy+(2*wDxy+1)*__qv_iterator_row_inc_itIntegral__+wDxy;
00264         itbeginoDxy = punteroComienzoDxy+(2*wDxy+1)*__qv_iterator_row_inc_itIntegral__+wDxy+1;
00265         itbeginpDxy = punteroComienzoDxy+(2*wDxy+1)*__qv_iterator_row_inc_itIntegral__+2*wDxy+1;
00266 
00267         for(int row=0,rowh=marginHessian; row<rows-sizeMask; 
00268                 row++, ++rowh, 
00269                 itbeginaDyy+=__qv_iterator_row_inc_itIntegral__, itbeginbDyy+=__qv_iterator_row_inc_itIntegral__,  itbegincDyy+=__qv_iterator_row_inc_itIntegral__, itbegindDyy+=__qv_iterator_row_inc_itIntegral__,  itbegineDyy+=__qv_iterator_row_inc_itIntegral__, itbeginfDyy+=__qv_iterator_row_inc_itIntegral__,  itbegingDyy+=__qv_iterator_row_inc_itIntegral__, itbeginhDyy+=__qv_iterator_row_inc_itIntegral__,
00270 
00271                 itbeginaDxx+=__qv_iterator_row_inc_itIntegral__, itbeginbDxx+=__qv_iterator_row_inc_itIntegral__,  itbegincDxx+=__qv_iterator_row_inc_itIntegral__, itbegindDxx+=__qv_iterator_row_inc_itIntegral__,  itbegineDxx+=__qv_iterator_row_inc_itIntegral__, itbeginfDxx+=__qv_iterator_row_inc_itIntegral__,  itbegingDxx+=__qv_iterator_row_inc_itIntegral__, itbeginhDxx+=__qv_iterator_row_inc_itIntegral__,
00272 
00273                 itbeginaDxy+=__qv_iterator_row_inc_itIntegral__, itbeginbDxy+=__qv_iterator_row_inc_itIntegral__,  itbegincDxy+=__qv_iterator_row_inc_itIntegral__, itbegindDxy+=__qv_iterator_row_inc_itIntegral__,  itbegineDxy+=__qv_iterator_row_inc_itIntegral__, itbeginfDxy+=__qv_iterator_row_inc_itIntegral__,  itbegingDxy+=__qv_iterator_row_inc_itIntegral__, itbeginhDxy+=__qv_iterator_row_inc_itIntegral__,
00274                 itbeginiDxy+=__qv_iterator_row_inc_itIntegral__, itbeginjDxy+=__qv_iterator_row_inc_itIntegral__,  itbeginkDxy+=__qv_iterator_row_inc_itIntegral__, itbeginlDxy+=__qv_iterator_row_inc_itIntegral__,  itbeginmDxy+=__qv_iterator_row_inc_itIntegral__, itbeginnDxy+=__qv_iterator_row_inc_itIntegral__,  itbeginoDxy+=__qv_iterator_row_inc_itIntegral__, itbeginpDxy+=__qv_iterator_row_inc_itIntegral__
00275            ) // lo haremos para todas las filas
00276         {
00277                 itaDyy = itbeginaDyy; itbDyy = itbeginbDyy; itcDyy = itbegincDyy; itdDyy = itbegindDyy;
00278                 iteDyy = itbegineDyy; itfDyy = itbeginfDyy; itgDyy = itbegingDyy; ithDyy = itbeginhDyy;
00279 
00280                 itaDxx = itbeginaDxx; itbDxx = itbeginbDxx; itcDxx = itbegincDxx; itdDxx = itbegindDxx;
00281                 iteDxx = itbegineDxx; itfDxx = itbeginfDxx; itgDxx = itbegingDxx; ithDxx = itbeginhDxx;
00282 
00283                 itaDxy = itbeginaDxy; itbDxy = itbeginbDxy; itcDxy = itbegincDxy; itdDxy = itbegindDxy;
00284                 iteDxy = itbegineDxy; itfDxy = itbeginfDxy; itgDxy = itbegingDxy; ithDxy = itbeginhDxy;
00285                 itiDxy = itbeginiDxy; itjDxy = itbeginjDxy; itkDxy = itbeginkDxy; itlDxy = itbeginlDxy;
00286                 itmDxy = itbeginmDxy; itnDxy = itbeginnDxy; itoDxy = itbeginoDxy; itpDxy = itbeginpDxy;
00287 
00288                 for(int col=0,colh=marginHessian; col<cols-sizeMask; 
00289                         col++, ++colh, 
00290                         itaDyy+=step, itbDyy+=step, itcDyy+=step, itdDyy+=step, iteDyy+=step, itfDyy+=step, itgDyy+=step, ithDyy+=step,
00291                         itaDxx+=step, itbDxx+=step, itcDxx+=step, itdDxx+=step, iteDxx+=step, itfDxx+=step, itgDxx+=step, ithDxx+=step,
00292                         itaDxy+=step, itbDxy+=step, itcDxy+=step, itdDxy+=step, iteDxy+=step, itfDxy+=step, itgDxy+=step, ithDxy+=step,
00293                         itiDxy+=step, itjDxy+=step, itkDxy+=step, itlDxy+=step, itmDxy+=step, itnDxy+=step, itoDxy+=step, itpDxy+=step)
00294                 {       sInt Dyy, Dxx, Dxy;
00295                         sFloat det;
00296                         Dyy=(((*itaDyy)-(*itbDyy)+(*ithDyy)-(*itgDyy)+3*((*itdDyy)+(*iteDyy)-(*itcDyy)-(*itfDyy))));
00297                         Dxx=((*itaDxx)+(*ithDxx)-(*itdDxx)-(*iteDxx)+3*((*itfDxx)+(*itcDxx)-(*itbDxx)-(*itgDxx)));
00298                         Dxy=(((*itaDxy)-(*itbDxy)-(*iteDxy)+(*itfDxy))+((*itkDxy)-(*itlDxy)-(*itoDxy)+(*itpDxy))-((*itcDxy)-(*itdDxy)-(*itgDxy)+(*ithDxy))-((*itiDxy)-(*itjDxy)-(*itmDxy)+(*itnDxy)));
00299 
00300                         det = ( Dxx * Dyy -0.81*Dxy*Dxy );
00301                         det = (det < 0.0) ? 0.0 : det*division;
00302                         QVIMAGE_PIXEL(hessian,colh,rowh,0) = det;
00303 //      if ((colh==634)) std::cout << " col=" << col << " row=" << row;
00304                 }
00305         }
00306 
00307 }
00308 
00309 
00310 void detHessianRowsNaive(const QVImage<sInt> &integralImage, QVImage<sFloat> &hessian, int octave, int scale)
00311 {  // OJO. Se aplica la máscara dando saltos dependiendo de la octava en la que estemos. step=2^octava.
00312         const int cols = integralImage.getROI().width(), rows = integralImage.getROI().height();
00313         const int sizeMask=9 + 6*octave + scale*(6 << octave);
00314         const int step= 1 << octave;
00315         const int colsHessian = cols/step, rowsHessian = rows/step;
00316         const int marginHessian = ((sizeMask)/2)/step; // Obtenemos un margen para el ROI de la imagen del hessiano.
00317         const int marginImage = sizeMask/2+step/2;  // Obtenemos un margen para el ROI de la imagen integral.
00318         const int w = 5 + 4*octave + scale*(4 << octave); // anchura de la parte de la máscara que se evalúa para Dxx y Dyy
00319         const int h = 3 + 2*octave + scale*(2 << octave); // altura de la parte de la máscara que se evalúa para Dxx y Dyy
00320         const int margin = 2 + 1*octave + scale*(1<<octave); // márgen de la máscara que no se usa para Dxx y Dyy
00321         const int marginDxy = 1 + 1*octave + scale*(1<<octave);// márgen de la máscara que no se usa para Dxy
00322         const int wDxy = 3 + 2*octave + scale*(2 << octave); // anchura y altura de la parte de la máscara que se evalúa para Dxy
00323         const int hDxy = 3 + 2*octave + scale*(2 << octave);
00324         const int beginxDxx=0, beginyDxx=margin;
00325         const int beginxDyy=margin, beginyDyy=0;
00326         const int beginxDxy=marginDxy, beginyDxy=marginDxy;
00327         register sFloat Dxx, Dyy, Dxy;
00328         const float division = 1.0/(sizeMask*sizeMask*sizeMask*sizeMask);
00329 
00330 
00331         QVIMAGE_INIT_WRITE(sFloat,hessian);
00332 
00333         QVIMAGE_ITERATOR_READ(sInt, integralImage, itIntegral);
00334         __qv_image_iterator_itIntegral__ += integralImage.getROI().y()*__qv_iterator_row_inc_itIntegral__+integralImage.getROI().x();
00335 
00336         // Dyy
00337         const sInt *itaDyy, *itcDyy, *iteDyy, *itgDyy, *itbDyy, *itdDyy, *itfDyy, *ithDyy;  // recorreran las filas calculando la máscara
00338         const sInt *itaDxx, *itcDxx, *iteDxx, *itgDxx, *itbDxx, *itdDxx, *itfDxx, *ithDxx;  // recorreran las filas calculando la máscara
00339         const sInt *itaDxy, *itbDxy, *itcDxy, *itdDxy, *iteDxy, *itfDxy, *itgDxy, *ithDxy;  // recorreran las filas calculando la máscara
00340         const sInt *itiDxy, *itjDxy, *itkDxy, *itlDxy, *itmDxy, *itnDxy, *itoDxy, *itpDxy;  // recorreran las filas calculando la máscara
00341         const sInt *itbeginaDyy, *itbegincDyy, *itbegineDyy, *itbegingDyy, *itbeginbDyy, *itbegindDyy, *itbeginfDyy, *itbeginhDyy;  // punteros al comienzo de cada fila
00342         const sInt *itbeginaDxx, *itbegincDxx, *itbegineDxx, *itbegingDxx, *itbeginbDxx, *itbegindDxx, *itbeginfDxx, *itbeginhDxx;  // punteros al comienzo de cada fila
00343         const sInt *itbeginaDxy, *itbeginbDxy, *itbegincDxy, *itbegindDxy, *itbegineDxy, *itbeginfDxy, *itbegingDxy, *itbeginhDxy;  // punteros al comienzo de cada fila
00344         const sInt *itbeginiDxy, *itbeginjDxy, *itbeginkDxy, *itbeginlDxy, *itbeginmDxy, *itbeginnDxy, *itbeginoDxy, *itbeginpDxy;  // punteros al comienzo de cada fila
00345         
00346         const sInt *punteroComienzoDyy=__qv_image_iterator_itIntegral__+beginxDyy;
00347         const sInt *punteroComienzoDxx=__qv_image_iterator_itIntegral__+beginyDxx*__qv_iterator_row_inc_itIntegral__;
00348         const sInt *punteroComienzoDxy=__qv_image_iterator_itIntegral__+beginyDxy*__qv_iterator_row_inc_itIntegral__+beginxDxy;
00349 
00350         itbeginaDyy = punteroComienzoDyy;
00351         itbeginbDyy = punteroComienzoDyy + w;
00352         itbegincDyy = punteroComienzoDyy+h*__qv_iterator_row_inc_itIntegral__;
00353         itbegindDyy = punteroComienzoDyy+h*__qv_iterator_row_inc_itIntegral__+w;
00354         itbegineDyy = punteroComienzoDyy+2*h*__qv_iterator_row_inc_itIntegral__;
00355         itbeginfDyy = punteroComienzoDyy+2*h*__qv_iterator_row_inc_itIntegral__+w;
00356         itbegingDyy = punteroComienzoDyy+3*h*__qv_iterator_row_inc_itIntegral__;
00357         itbeginhDyy = punteroComienzoDyy+3*h*__qv_iterator_row_inc_itIntegral__+w;
00358 
00359         itbeginaDxx = punteroComienzoDxx;
00360         itbeginbDxx = punteroComienzoDxx + h;
00361         itbegincDxx = punteroComienzoDxx+ 2*h;
00362         itbegindDxx = punteroComienzoDxx+ 3*h;
00363         itbegineDxx = punteroComienzoDxx+w*__qv_iterator_row_inc_itIntegral__;
00364         itbeginfDxx = punteroComienzoDxx+w*__qv_iterator_row_inc_itIntegral__+h;
00365         itbegingDxx = punteroComienzoDxx+w*__qv_iterator_row_inc_itIntegral__+2*h;
00366         itbeginhDxx = punteroComienzoDxx+w*__qv_iterator_row_inc_itIntegral__+3*h;
00367 
00368         itbeginaDxy = punteroComienzoDxy;
00369         itbeginbDxy = punteroComienzoDxy + wDxy;
00370         itbegincDxy = punteroComienzoDxy+ wDxy+1;
00371         itbegindDxy = punteroComienzoDxy+ 2*wDxy+1;
00372         itbegineDxy = punteroComienzoDxy+wDxy*__qv_iterator_row_inc_itIntegral__;
00373         itbeginfDxy = punteroComienzoDxy+wDxy*__qv_iterator_row_inc_itIntegral__+wDxy;
00374         itbegingDxy = punteroComienzoDxy+wDxy*__qv_iterator_row_inc_itIntegral__+wDxy+1;
00375         itbeginhDxy = punteroComienzoDxy+wDxy*__qv_iterator_row_inc_itIntegral__+2*wDxy+1;
00376         itbeginiDxy = punteroComienzoDxy+(wDxy+1)*__qv_iterator_row_inc_itIntegral__;
00377         itbeginjDxy = punteroComienzoDxy+(wDxy+1)*__qv_iterator_row_inc_itIntegral__+wDxy;
00378         itbeginkDxy = punteroComienzoDxy+(wDxy+1)*__qv_iterator_row_inc_itIntegral__+wDxy+1;
00379         itbeginlDxy = punteroComienzoDxy+(wDxy+1)*__qv_iterator_row_inc_itIntegral__+2*wDxy+1;
00380         itbeginmDxy = punteroComienzoDxy+(2*wDxy+1)*__qv_iterator_row_inc_itIntegral__;
00381         itbeginnDxy = punteroComienzoDxy+(2*wDxy+1)*__qv_iterator_row_inc_itIntegral__+wDxy;
00382         itbeginoDxy = punteroComienzoDxy+(2*wDxy+1)*__qv_iterator_row_inc_itIntegral__+wDxy+1;
00383         itbeginpDxy = punteroComienzoDxy+(2*wDxy+1)*__qv_iterator_row_inc_itIntegral__+2*wDxy+1;
00384 
00385         const int incRowStep=step*__qv_iterator_row_inc_itIntegral__;
00386         const float norm_Dxy=0.81/(wDxy*wDxy*hDxy*hDxy);
00387         const float norm_Dxx=1.0/(w*w*h*h);
00388         for(int row=0,rowh=marginHessian; row<rows-sizeMask; 
00389                 row+=step, ++rowh, 
00390                 itbeginaDyy+=incRowStep, itbeginbDyy+=incRowStep, itbegincDyy+=incRowStep, itbegindDyy+=incRowStep,  itbegineDyy+=incRowStep,
00391                 itbeginfDyy+=incRowStep,  itbegingDyy+=incRowStep, itbeginhDyy+=incRowStep,
00392                 itbeginaDxx+=incRowStep, itbeginbDxx+=incRowStep,  itbegincDxx+=incRowStep, itbegindDxx+=incRowStep,  itbegineDxx+=incRowStep,
00393                 itbeginfDxx+=incRowStep,  itbegingDxx+=incRowStep, itbeginhDxx+=incRowStep,
00394 
00395                 itbeginaDxy+=incRowStep, itbeginbDxy+=incRowStep,  itbegincDxy+=incRowStep, itbegindDxy+=incRowStep,  itbegineDxy+=incRowStep,
00396                 itbeginfDxy+=incRowStep,  itbegingDxy+=incRowStep, itbeginhDxy+=incRowStep,
00397                 itbeginiDxy+=incRowStep, itbeginjDxy+=incRowStep,  itbeginkDxy+=incRowStep, itbeginlDxy+=incRowStep,  itbeginmDxy+=incRowStep,
00398                 itbeginnDxy+=incRowStep,  itbeginoDxy+=incRowStep, itbeginpDxy+=incRowStep
00399            ) // lo haremos para todas las filas
00400         {
00401                 itaDyy = itbeginaDyy; itbDyy = itbeginbDyy; itcDyy = itbegincDyy; itdDyy = itbegindDyy;
00402                 iteDyy = itbegineDyy; itfDyy = itbeginfDyy; itgDyy = itbegingDyy; ithDyy = itbeginhDyy;
00403 
00404                 itaDxx = itbeginaDxx; itbDxx = itbeginbDxx; itcDxx = itbegincDxx; itdDxx = itbegindDxx;
00405                 iteDxx = itbegineDxx; itfDxx = itbeginfDxx; itgDxx = itbegingDxx; ithDxx = itbeginhDxx;
00406 
00407                 itaDxy = itbeginaDxy; itbDxy = itbeginbDxy; itcDxy = itbegincDxy; itdDxy = itbegindDxy;
00408                 iteDxy = itbegineDxy; itfDxy = itbeginfDxy; itgDxy = itbegingDxy; ithDxy = itbeginhDxy;
00409                 itiDxy = itbeginiDxy; itjDxy = itbeginjDxy; itkDxy = itbeginkDxy; itlDxy = itbeginlDxy;
00410                 itmDxy = itbeginmDxy; itnDxy = itbeginnDxy; itoDxy = itbeginoDxy; itpDxy = itbeginpDxy;
00411 
00412                 for(int col=0,colh=marginHessian; col<cols-sizeMask; 
00413                         col+=step, ++colh, 
00414                         itaDyy+=step, itbDyy+=step, itcDyy+=step, itdDyy+=step, iteDyy+=step, itfDyy+=step, itgDyy+=step, ithDyy+=step,
00415                         itaDxx+=step, itbDxx+=step, itcDxx+=step, itdDxx+=step, iteDxx+=step, itfDxx+=step, itgDxx+=step, ithDxx+=step,
00416                         itaDxy+=step, itbDxy+=step, itcDxy+=step, itdDxy+=step, iteDxy+=step, itfDxy+=step, itgDxy+=step, ithDxy+=step,
00417                         itiDxy+=step, itjDxy+=step, itkDxy+=step, itlDxy+=step, itmDxy+=step, itnDxy+=step, itoDxy+=step, itpDxy+=step)
00418                 {       sInt Dyy, Dxx, Dxy;
00419                         sFloat det;
00420                         Dyy=(((*itaDyy)-(*itbDyy)+(*ithDyy)-(*itgDyy)+3*((*itdDyy)+(*iteDyy)-(*itcDyy)-(*itfDyy))));
00421                         Dxx=((*itaDxx)+(*ithDxx)-(*itdDxx)-(*iteDxx)+3*((*itfDxx)+(*itcDxx)-(*itbDxx)-(*itgDxx)));
00422                         Dxy=(((*itaDxy)-(*itbDxy)-(*iteDxy)+(*itfDxy))+((*itkDxy)-(*itlDxy)-(*itoDxy)+(*itpDxy))-((*itcDxy)-(*itdDxy)-(*itgDxy)+(*ithDxy))-((*itiDxy)-(*itjDxy)-(*itmDxy)+(*itnDxy)));
00423 
00424                         det = ( Dxx * Dyy * norm_Dxx - Dxy*Dxy*norm_Dxy );
00425                         det = (det < 0.0) ? 0.0 : det;
00426                         QVIMAGE_PIXEL(hessian,colh,rowh,0) = det;
00427 //      if ((colh==634)) std::cout << " col=" << col << " row=" << row;
00428                 }
00429         }
00430 
00431 }
00432 
00433 
00434 QList<QVPolyline> addBlobs(QList<QVPolyline> listBlobs, QList<QPoint> listPoints, int octave, int scale)
00435 { const int radius=4+3*octave+scale*(3<<octave);
00436   const int sizeMask=9 + 6*octave + scale*(6 << octave);
00437   const int step= 1 << octave;
00438 
00439   for(QList<QPoint>::const_iterator i=listPoints.constBegin(); i!=listPoints.constEnd(); ++i)
00440         listBlobs.append(QVPolyline::ellipse(10,i->x()*step,i->y()*step,radius,radius,0));
00441   return(listBlobs);
00442 }
00443 
00444 
00445 QList<QVPolyline> getBlobsRowsNaive(QVImage<sInt> &integralInt, float THRESHOLD)
00446 {       int cols=integralInt.getCols(), rows=integralInt.getRows();
00447         QVImage<sFloat> approxHessian0[4]={QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows),
00448                                         QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows)};
00449         QVImage<sFloat> approxHessian1[4]={QVImage<sFloat>(cols/2,rows/2),QVImage<sFloat>(cols/2,rows/2),
00450                                         QVImage<sFloat>(cols/2,rows/2),QVImage<sFloat>(cols/2,rows/2)};
00451         QVImage<sFloat> approxHessian2[4]={QVImage<sFloat>(cols/4,rows/4),QVImage<sFloat>(cols/4,rows/4),
00452                                         QVImage<sFloat>(cols/4,rows/4),QVImage<sFloat>(cols/4,rows/4)};
00453         QList<QVPolyline> listBlobs;
00454 
00455         int oct=0;
00456         for(int sca=0; sca<4; ++sca)
00457           detHessianRowsNaive(integralInt,approxHessian0[sca],oct,sca);
00458         listBlobs=addBlobs(listBlobs,MaxIPPRel(approxHessian0[0],approxHessian0[1],approxHessian0[2], THRESHOLD),oct,1);
00459         listBlobs=addBlobs(listBlobs,MaxIPPRel(approxHessian0[1],approxHessian0[2],approxHessian0[3], THRESHOLD),oct,2);
00460 /*
00461         oct=1;
00462         Resize(approxHessian0[1], approxHessian1[0],IPPI_INTER_NN);
00463         detHessianRows(integralInt,approxHessian1[1],oct,1);
00464         detHessianRows(integralInt,approxHessian1[2],oct,2);
00465         detHessianRows(integralInt,approxHessian1[3],oct,3);
00466         listBlobs=addBlobs(listBlobs,MaxIPP(approxHessian1[0],approxHessian1[1],approxHessian1[2], THRESHOLD),oct,1);
00467         listBlobs=addBlobs(listBlobs,MaxIPP(approxHessian1[1],approxHessian1[2],approxHessian1[3], THRESHOLD),oct,2);
00468 
00469         oct=2;
00470         Resize(approxHessian1[1], approxHessian2[0],IPPI_INTER_NN);
00471         detHessianRows(integralInt,approxHessian2[1],oct,1);
00472         detHessianRows(integralInt,approxHessian2[2],oct,2);
00473         detHessianRows(integralInt,approxHessian2[3],oct,3);
00474         listBlobs=addBlobs(listBlobs,MaxIPP(approxHessian2[0],approxHessian2[1],approxHessian2[2], THRESHOLD),oct,1);
00475         listBlobs=addBlobs(listBlobs,MaxIPP(approxHessian2[1],approxHessian2[2],approxHessian2[3], THRESHOLD),oct,2);
00476 */
00477 
00478         return(listBlobs);
00479 }
00480 
00481 
00482 class MyWorker: public QVWorker
00483         {
00484         public:
00485                 MyWorker(QString name): QVWorker(name)
00486                         { 
00487                         addProperty<double>("Threshold", inputFlag, 100.0, "Threshold",1.0,10000.0);
00488                         addProperty< QVImage<uChar> >("Input image", inputFlag|outputFlag);
00489                         addProperty< QVImage<uChar> >("Output image 1", outputFlag);
00490                         addProperty< QVImage<sFloat> >("Output image 2", outputFlag);
00491                         addProperty< QVImage<sFloat> >("Output image 3", outputFlag);
00492                         addProperty< QVImage<sFloat> >("Output image 4", outputFlag);
00493                         addProperty< QVImage<sFloat> >("Output image 5", outputFlag);
00494                         addProperty< QVImage<sFloat> >("Output image 6", outputFlag);
00495                         addProperty< QList<QVPolyline> >("BlobsMax1",outputFlag);
00496 //                      addProperty< QList<QVPolyline> >("BlobsMax2",outputFlag);
00497                         }
00498 
00499                 void iterate()
00500                         {
00501                         sFloat THRESHOLD = getPropertyValue<sFloat>("Threshold");
00502                         QVImage<uChar> input0 = getPropertyValue< QVImage<uChar> >("Input image");
00503                         uInt rows = input0.getRows()*2, cols = input0.getCols()*2;
00504 
00505                         QVImage<uChar> input(cols, rows);
00506                         Resize(input0, input,IPPI_INTER_NN);
00507                         timeFlag("double size");
00508                         QVImage<uChar> imageGaussian(cols,rows);
00509                         //input.setROI(1,1,cols-2,rows-2);
00510                         FilterGauss(input,imageGaussian,3,QPoint(1,1));
00511                         QVImage<sInt> integralInt(cols,rows);
00512                         integralInt.setROI(1,1,cols-2,rows-2);
00513                         Integral(imageGaussian,integralInt,0,QPoint(1,1));
00514 
00515                         timeFlag("integral");
00516 
00517 
00518 
00519                         QList<QVPolyline> listBlobs; //=getBlobsRows(integralInt,THRESHOLD);
00520 
00521 
00522         QVImage<sFloat> approxHessian0[4]={QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows),
00523                                         QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows)};
00524         QVImage<sFloat> approxHessian1[4]={QVImage<sFloat>(cols/2,rows/2),QVImage<sFloat>(cols/2,rows/2),
00525                                         QVImage<sFloat>(cols/2,rows/2),QVImage<sFloat>(cols/2,rows/2)};
00526         QVImage<sFloat> approxHessian2[4]={QVImage<sFloat>(cols/4,rows/4),QVImage<sFloat>(cols/4,rows/4),
00527                                         QVImage<sFloat>(cols/4,rows/4),QVImage<sFloat>(cols/4,rows/4)};
00528 /*
00529         QVImage<sFloat> approxHessian0[4]={QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows),
00530                                         QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows)};
00531         QVImage<sFloat> approxHessian1[4]={QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows),
00532                                         QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows)};
00533         QVImage<sFloat> approxHessian2[4]={QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows),
00534                                         QVImage<sFloat>(cols,rows),QVImage<sFloat>(cols,rows)};
00535 */
00536         int oct=0;
00537 
00538 
00539         timeFlag("a cero");
00540         Set(approxHessian0[0],0.0);
00541         Set(approxHessian0[1],0.0);
00542         Set(approxHessian0[2],0.0);
00543         Set(approxHessian0[3],0.0);
00544 
00545         for(int sca=0; sca<4; ++sca)
00546           detHessianRowsNaive(integralInt,approxHessian0[sca],oct,sca);
00547         timeFlag("nuevo oct0");
00548 
00549         listBlobs=addBlobs(listBlobs,MaxIPPAbs(approxHessian0[0],approxHessian0[1],approxHessian0[2], THRESHOLD),oct,1);
00550         listBlobs=addBlobs(listBlobs,MaxIPPAbs(approxHessian0[1],approxHessian0[2],approxHessian0[3], THRESHOLD),oct,2);
00551 
00552         timeFlag("lista de blobs oct0");
00553 
00554         oct=1;
00555         Set(approxHessian1[0],0.0);
00556         Set(approxHessian1[1],0.0);
00557         Set(approxHessian1[2],0.0);
00558         Set(approxHessian1[3],0.0);
00559         timeFlag("a cero1");
00560 
00561         Resize(approxHessian0[1], approxHessian1[0],IPPI_INTER_NN);
00562         detHessianRowsNaive(integralInt,approxHessian1[1],oct,1);
00563         detHessianRowsNaive(integralInt,approxHessian1[2],oct,2);
00564         detHessianRowsNaive(integralInt,approxHessian1[3],oct,3);
00565         timeFlag("nuevo oct1");
00566         listBlobs=addBlobs(listBlobs,MaxIPPAbs(approxHessian1[0],approxHessian1[1],approxHessian1[2], THRESHOLD),oct,1);
00567         listBlobs=addBlobs(listBlobs,MaxIPPAbs(approxHessian1[1],approxHessian1[2],approxHessian1[3], THRESHOLD),oct,2);
00568         timeFlag("lista de blobs oct1");
00569 
00570 
00571         oct=2;
00572         Set(approxHessian2[0],0.0);
00573         Set(approxHessian2[1],0.0);
00574         Set(approxHessian2[2],0.0);
00575         Set(approxHessian2[3],0.0);
00576         timeFlag("a cero2");
00577 
00578         Resize(approxHessian1[1], approxHessian2[0],IPPI_INTER_NN);
00579         detHessianRowsNaive(integralInt,approxHessian2[1],oct,1);
00580         detHessianRowsNaive(integralInt,approxHessian2[2],oct,2);
00581         detHessianRowsNaive(integralInt,approxHessian2[3],oct,3);
00582         timeFlag("nuevo oct2");
00583 
00584         listBlobs=addBlobs(listBlobs,MaxIPPAbs(approxHessian2[0],approxHessian2[1],approxHessian2[2], THRESHOLD),oct,1);
00585         listBlobs=addBlobs(listBlobs,MaxIPPAbs(approxHessian2[1],approxHessian2[2],approxHessian2[3], THRESHOLD),oct,2);
00586         timeFlag("lista de blobs oct2");
00587 
00588 
00589 
00590                         setPropertyValue< QVImage<uChar> >("Output image 1", imageGaussian);
00591                         setPropertyValue< QList<QVPolyline > >("BlobsMax1",listBlobs);
00592                         setPropertyValue< QVImage<sFloat> >("Output image 2", approxHessian1[0]);
00593                         setPropertyValue< QVImage<sFloat> >("Output image 3", approxHessian1[1]);
00594                         setPropertyValue< QVImage<sFloat> >("Output image 4", approxHessian1[2]);
00595                         setPropertyValue< QVImage<sFloat> >("Output image 5", approxHessian1[3]);
00596 //                      setPropertyValue< QVImage<uChar> >("Output image 2", imageGaussian);
00597 //                      setPropertyValue< QList<QVPolyline > >("BlobsMax2",listBlobs2);
00598 
00599                         timeFlag("shows");
00600 
00601                         }
00602         };
00603 
00604 int main(int argc, char *argv[])
00605         {   ippSetNumThreads(1);
00606         QVApplication app(argc, argv,
00607                 "Example program for QVision library. It is an implementation of the SURF algorithm."
00608                 );
00609 
00610         QVMPlayerCamera camera1("Video 1");
00611         MyWorker worker("Surf Worker");
00612 
00613         camera1.link(&worker,"Input image");
00614 
00615         QVDefaultGUI interface;
00616 
00617 
00618         QVImageCanvas imageCanvas1("Output image 1");
00619         imageCanvas1.linkProperty(worker,"Output image 1");
00620         imageCanvas1.linkProperty(worker,"BlobsMax1", Qt::green);
00621         QVImageCanvas imageCanvas2("Output image 2");
00622         imageCanvas2.linkProperty(worker,"Output image 2");
00623         QVImageCanvas imageCanvas3("Output image 3");
00624         imageCanvas3.linkProperty(worker,"Output image 3");
00625         QVImageCanvas imageCanvas4("Output image 4");
00626         imageCanvas4.linkProperty(worker,"Output image 4");
00627         QVImageCanvas imageCanvas5("Output image 5");
00628         imageCanvas5.linkProperty(worker,"Output image 5");
00629 
00630 /*      QVImageCanvas imageCanvas2("Output image 2");
00631         imageCanvas2.linkProperty(worker,"Output image 2");*/
00632 //      imageCanvas2.linkProperty(worker,"BlobsMax2", Qt::green);
00633 
00634 
00635         return app.exec();
00636         }
00637 
00638 #endif