examples/albertoBlobs/albertoBlobs.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 
00040 #include <stdio.h>
00041 #include <stdlib.h>
00042 #include <iostream>
00043 #include <QDebug>
00044 
00045 #include <QVApplication>
00046 #include <QVMPlayerCamera>
00047 #include <QVDefaultGUI>
00048 #include <QVImageCanvas>
00049 
00050 #include <QVPolyline>
00051 #include <QVMatrix>
00052 
00053 #include <qvdta.h>
00054 #include <qvip.h>
00055 
00056 // Comment this if you don't want inpainting.
00057 //#define INPAINTING
00058 #ifndef DOXYGEN_IGNORE_THIS
00059 
00060 #define IMAGE_ROISIZE(Image)    ((IppiSize){ Image.getROI().width(), Image.getROI().height() })
00061 
00062 Q_DECLARE_METATYPE(QList<sFloat>);
00063 class QVHessianPointDetector: public QVWorker
00064         {
00065         private:
00066                 /*const QVImage<sFloat> FilterGauss(const QVImage<sFloat> &image, const int size, const double sigma)
00067                         {
00068                         const uInt cols = image.getCols(), rows = image.getRows();
00069                         const QVVector kernel = QVVector::gaussianDistribution(size, sigma);
00070                 
00071                         QVImage<sFloat> imageSFloat = image, rowFiltered(cols, rows), filtered(cols, rows);
00072                 
00073                         Set(0, filtered);
00074                         FilterRow(imageSFloat, rowFiltered, kernel);
00075                         FilterColumn(rowFiltered, filtered, kernel);
00076                 
00077                         return filtered;
00078                         }*/
00079 
00080         public:
00081                 QVHessianPointDetector(QString name): QVWorker(name)
00082                         {
00083                         addProperty< QVImage<uChar,1> >("Input image", inputFlag|outputFlag);
00084                         addProperty< QVImage<uChar,1> >("Feature response image", outputFlag);
00085                         addProperty< QList < QPointF > >("Feature locations", outputFlag);
00086                         addProperty< QList < sFloat > >("Feature responses", outputFlag);
00087                         addProperty< int >("Max number of corners", inputFlag, 300, "Maximal number of corners to detect", 10, 1000);
00088 
00089                         addProperty<int>("first gaussian size", inputFlag, 4, "Minimal length of a contour to be considered", 1, 100);
00090                         addProperty<int>("second gaussian size", inputFlag, 50, "Minimal length of a contour to be considered", 1, 100);
00091                         //addProperty<double>("threshold", inputFlag, 4, "Minimal length of a contour to be considered", 0, 255);
00092                         //addProperty< QVImage<uChar,1> >("Output image", outputFlag);
00093                         //addProperty< QVImage<uChar,1> >("Input image", inputFlag|outputFlag);
00094                         addProperty< QVImage<uChar,1> >("A", outputFlag);
00095                         addProperty< QVImage<uChar,1> >("B", outputFlag);
00096                         }
00097 
00098                 void iterate()
00099                         {
00100                         //std::cout << "EO -1" << std::endl;
00101                         // 0. Read input parameters
00102                         QVImage<sFloat,1> image = getPropertyValue< QVImage<uChar,1> >("Input image");
00103                         const int firstSize = getPropertyValue< int >("first gaussian size");
00104                         const int secondSize = getPropertyValue< int >("second gaussian size");
00105                         //const double threshold = getPropertyValue< int >("threshold");
00106                         const uInt cols = image.getCols(), rows = image.getRows();
00107                         const int maxNumberCorners = getPropertyValue< int >("Max number of corners");
00108 
00109                         QVImage<sFloat> firstGauss(cols, rows);
00110                         FilterGauss(image, firstGauss, ippMskSize5x5);
00111 
00112                         timeFlag("Gaussian image");
00113 
00114                         QVImage<sFloat> cornerResponseImage(cols, rows);
00115                         Set(0, cornerResponseImage);
00116                         FilterHarrisCornerResponseImage(firstGauss, cornerResponseImage);
00117                         timeFlag("Corner response image");
00118 
00119                         QVImage<sFloat> cornerResponseImage2(cols, rows);
00120                         FilterGauss(cornerResponseImage, cornerResponseImage2, ippMskSize5x5, QPoint(2,2));
00121 
00122                         QVImage<sFloat> equalized(cols, rows);
00123                         Set(0, equalized);
00124                         FilterEqualizeHistogram(cornerResponseImage2, equalized);
00125                 
00126                         equalized.resetROI();
00127 
00128                         timeFlag("Gaussian image2");
00129 
00130                         // 3. Store locations and intensities of points.
00131                         const QList< QPair<sFloat, QPointF> > maximalPointsPlusResponses = GetMaximalResponsePoints1bis(cornerResponseImage2);
00132 
00133                         const QList<sFloat> actualResponses = getFirstPairList<sFloat, QPointF>(maximalPointsPlusResponses);
00134                         const QList<QPointF> points = getSecondPairList<sFloat, QPointF>(maximalPointsPlusResponses);
00135                         const QList<QPointF> actualPoints = getSecondPairList<sFloat, QPointF>(maximalPointsPlusResponses);
00136                         timeFlag("Get corners and intensity responses");
00137                 
00138                         const int size = actualResponses.size();
00139                         setPropertyValue< QList<sFloat> >("Feature responses", actualResponses.mid(MAX(0,size-maxNumberCorners),maxNumberCorners) );
00140                         setPropertyValue< QList<QPointF> >("Feature locations", actualPoints.mid(MAX(0,size-maxNumberCorners),maxNumberCorners) );
00141                         timeFlag("Store properties values");
00142                         }
00143         };
00144 
00145 
00146 class AlbertoOperatorWorker: public QVWorker
00147         {
00148         private:
00149                 const QVImage<sFloat> FilterGauss(const QVImage<sFloat> &image, const int size, const double sigma)
00150                         {
00151                         const uInt cols = image.getCols(), rows = image.getRows();
00152                         const QVVector kernel = QVVector::gaussianDistribution(size, sigma);
00153                 
00154                         QVImage<sFloat> imageSFloat = image, rowFiltered(cols, rows), filtered(cols, rows);
00155                 
00156                         Set(0, filtered);
00157                         FilterRow(imageSFloat, rowFiltered, kernel);
00158                         FilterColumn(rowFiltered, filtered, kernel);
00159                 
00160                         return filtered;
00161                         }
00162 
00163         public:
00164                 AlbertoOperatorWorker(QString name): QVWorker(name)
00165                         {
00166                         addProperty<int>("first gaussian size", inputFlag, 4, "Minimal length of a contour to be considered", 4, 100);
00167                         addProperty<int>("second gaussian size", inputFlag, 50, "Minimal length of a contour to be considered", 4, 100);
00168                         addProperty<double>("threshold", inputFlag, 4, "Minimal length of a contour to be considered", 0, 255);
00169                         addProperty< QVImage<uChar,1> >("Output image", outputFlag);
00170                         addProperty< QVImage<uChar,1> >("Input image", inputFlag|outputFlag);
00171                         }
00172 
00173                 void iterate()
00174                         {
00175                         // 0. Read input parameters
00176                         QVImage<sFloat,1> image = getPropertyValue< QVImage<uChar,1> >("Input image");
00177                         const int firstSize = getPropertyValue< int >("first gaussian size");
00178                         const int size = getPropertyValue< int >("second gaussian size");
00179                         const double threshold = getPropertyValue< int >("threshold");
00180                         const uInt cols = image.getCols(), rows = image.getRows();
00181 
00182                         QVImage<sFloat> firstGauss = FilterGauss(image, firstSize, firstSize/4);
00183                         timeFlag("Gaussian image");
00184 
00185                         QVImage<sFloat> cornerResponseImage(cols, rows);
00186                         FilterHessianCornerResponseImage(firstGauss, cornerResponseImage);
00187                         
00188                         timeFlag("Corner response image");
00189 
00190                         QVImage<sFloat> gaussFiltered2 = FilterGauss(cornerResponseImage, size, size/4);
00191                         timeFlag("Gaussian image2");
00192 
00193                         QVImage<sFloat> equalized(cols, rows);
00194                         FilterEqualizeHistogram(gaussFiltered2, equalized);
00195 
00196                         timeFlag("Image equalization");
00197                         QVImage<sFloat> temp(cols, rows), result(cols, rows);
00198                         result = image;
00199 
00200                         Set(0, temp);
00201 
00202                         QVIMAGE_INIT_READ(sFloat,equalized);
00203                         QVIMAGE_INIT_WRITE(sFloat,temp);
00204                         QVIMAGE_INIT_WRITE(sFloat,result);
00205 
00206                         const int vcol = size/2 + firstSize/2, vrow = size/2 + firstSize/2;
00207                         for (int i = 0; i < cols - size; i++)
00208                                 for (int j = 0; j < rows - size; j++)
00209                                         QVIMAGE_PIXEL(temp, i+ vcol, j + vrow, 0) = QVIMAGE_PIXEL(equalized, i, j, 0);
00210 
00211                         timeFlag("Displaced filtered image");
00212 
00213                         #ifdef INPAINTING
00214                         // 3. Inpainting
00215                         const int radius = 4;
00216                         // 3.1. Obtaining mask image.
00217                         QVImage<uChar> maskForImage(cols, rows);
00218                         Set(0, maskForImage);
00219 
00220                         for (int i = 0; i < cols; i++)
00221                                 for (int j = 0; j < rows; j++)
00222                                         if (QVIMAGE_PIXEL(temp, i, j, 0) <= threshold)
00223                                                 maskForImage(i, j) = 255;
00224 
00225                         // 3.1. Get distances using fast marching algorithm
00226                         QVImage<uChar> buffer;
00227                         FastMarchingGetBufferSize(maskForImage, buffer);
00228 
00229                         QVImage<sFloat> distances(cols, rows);
00230                         Set(0, distances);
00231                         FastMarching(maskForImage, distances, radius, buffer);
00232                         timeFlag("Get distances using fast marching algorithm");
00233 
00234                         // 3.2. Inpainting
00235                         QVImage<uChar> imageUChar = image, inpaint(cols,rows);
00236                         Inpaint(imageUChar, maskForImage, distances, inpaint, radius);
00237                         setPropertyValue< QVImage<uChar,1> >("Output image",inpaint);
00238                         timeFlag("Inpainting");
00239                         #else
00240                         for (int i = 0; i < cols; i++)
00241                                 for (int j = 0; j < cols; j++)
00242                                         if (QVIMAGE_PIXEL(temp, i, j, 0) <= threshold)
00243                                                 QVIMAGE_PIXEL(result, i, j, 0) = 0;
00244 
00245                         timeFlag("Mixing source and filtered image");
00246 
00247                         setPropertyValue< QVImage<uChar,1> >("Output image",result);
00248 
00249                         timeFlag("Publish results");
00250                         #endif
00251                         }
00252         };
00253 
00254 int main(int argc, char *argv[])
00255         {
00256         QVApplication app(argc, argv,
00257                 "Example program for QVision library. Obtains several features from input video frames."
00258                 );
00259 
00260         AlbertoOperatorWorker albertoWorker("Alberto Operator Worker");
00261         QVHessianPointDetector albertoWorker2("Alberto Operator Worker 2");
00262 
00263         QVMPlayerCamera camera("Video");
00264 
00265         camera.link(&albertoWorker,"Input image");
00266         albertoWorker.linkProperty("Input image", &albertoWorker2,"Input image", QVWorker::SynchronousLink);
00267 
00268         QVDefaultGUI interface;
00269 
00270         QVImageCanvas imageCanvas("Original");
00271         imageCanvas.linkProperty(albertoWorker,"Input image");
00272 
00273         QVImageCanvas albertoCanvas("Alberto");
00274         albertoCanvas.linkProperty(albertoWorker,"Output image");
00275 
00276         QVImageCanvas albertoCanvas2("Points");
00277         albertoCanvas2.linkProperty(albertoWorker2,"Input image");
00278         albertoCanvas2.linkProperty(albertoWorker2, "Feature locations", Qt::blue, false);
00279 
00280         //albertoCanvas2.linkProperty(albertoWorker2, "Feature locations", Qt::blue, false);
00281 
00282         return app.exec();
00283         }
00284 
00285 #endif