examples/tutorial/features4/features.cpp

00001 /*
00002  *      Copyright (C) 2007. 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 
00036 #include <QVApplication>
00037 #include <QVMPlayerCamera>
00038 #include <QVGUI>
00039 #include <QVImageCanvas>
00040 #include <QVPolyline>
00041 #include <QVFilterSelectorWorker>
00042 #include <QVNumericPlot>
00043 
00044 #ifndef DOXYGEN_IGNORE_THIS
00045 class CannyOperatorWorker: public QVWorker
00046         {
00047         public:
00048                 CannyOperatorWorker(QString name): QVWorker(name)
00049                         {
00050                         addProperty<double>("cannyHigh", inputFlag, 150, "High threshold for Canny operator", 50, 1000);
00051                         addProperty<double>("cannyLow", inputFlag, 50, "Low threshold for Canny operator", 10, 500);
00052                         addProperty<bool>("applyIPE", inputFlag, TRUE, "If we want to apply the IPE algorithm");
00053                         addProperty<double>("paramIPE", inputFlag, 5.0, "IPE parameter (max. allowed distance to line)", 1.0, 25.0);
00054                         addProperty<bool>("intersectLines", inputFlag, TRUE, "If we want IPE to postprocess polyline (intersecting lines)");
00055                         addProperty<int>("minLengthContour", inputFlag, 25, "Minimal length of a contour to be considered", 1, 150);
00056                         addProperty<int>("showNothingCannyImage", inputFlag, 0, "If we want nothing|Canny|original image to be shown",0,2);
00057                         addProperty<bool>("showContours", inputFlag, TRUE, "If we want contours to be shown");
00058 
00059                         addProperty< QVImage<uChar,1> >("Output image", outputFlag);
00060                         addProperty< QVImage<uChar,3> >("Input image", inputFlag|outputFlag);
00061                         addProperty< QList<QVPolyline> >("Output contours", outputFlag);
00062                         addProperty<int>("Num output contours", outputFlag);
00063                         }
00064 
00065                 void iterate()
00066                         {
00067                         // 0. Read input parameters
00068                         const double cannyHigh = getPropertyValue<double>("cannyHigh");
00069                         const double cannyLow = getPropertyValue<double>("cannyLow");
00070                         const bool applyIPE = getPropertyValue<bool>("applyIPE");
00071                         const double paramIPE = getPropertyValue<double>("paramIPE");
00072                         const bool intersectLines = getPropertyValue<bool>("intersectLines");
00073                         const int minLengthContour = getPropertyValue<int>("minLengthContour");
00074                         const int showNothingCannyImage = getPropertyValue<int>("showNothingCannyImage");
00075                         const bool showContours = getPropertyValue<bool>("showContours");
00076                         QVImage<uChar,1> image = getPropertyValue< QVImage<uChar,3> >("Input image");
00077                         const uInt cols = image.getCols(), rows = image.getRows();
00078 
00079                         QVImage<sFloat> imageFloat(cols, rows), dX(cols, rows), dY(cols, rows), dXNeg(cols, rows);
00080                         QVImage<uChar> canny(cols, rows), buffer;
00081 
00082                         // 1. Convert image from uChar to sShort
00083                         Convert(image, imageFloat);
00084                         timeFlag("Convert image from uChar to sShort");
00085                 
00086                         // 2. Obtain horizontal and vertical gradients from image
00087                         FilterSobelHorizMask(imageFloat,dY,3);
00088                         FilterSobelVertMask(imageFloat,dX,3);
00089                         MulC(dX, dXNeg, -1);
00090                         timeFlag("Obtain horizontal and vertical gradients from image");
00091                 
00092                         // 3. Apply Canny operator
00093                         CannyGetSize(canny, buffer);
00094                         Canny(dXNeg, dY, canny, buffer, cannyLow,cannyHigh);
00095                         timeFlag("Apply Canny operator");
00096 
00097                         // 4. Get contours
00098                         const QList<QVPolyline> contourList = getLineContoursThreshold8Connectivity(canny, 128);
00099                         timeFlag("Get contours");
00100 
00101                         QList<QVPolyline> outputList;
00102                         foreach(QVPolyline contour,contourList)
00103                                 {
00104                                 if(contour.size() > minLengthContour)
00105                                         {
00106                                         if(applyIPE)
00107                                                 {
00108                                                 QVPolyline IPEcontour;
00109                                                 IterativePointElimination(contour,IPEcontour,paramIPE,FALSE,intersectLines);
00110                                                 outputList.append(IPEcontour);
00111                                                 }
00112                                         else
00113                                                 outputList.append(contour);
00114                                         }
00115                                 }
00116                         timeFlag("IPE on contours");
00117 
00118                         // 5. Publish resulting data
00119                         if(showNothingCannyImage == 1)
00120                                 setPropertyValue< QVImage<uChar,1> >("Output image",canny);
00121                         else if(showNothingCannyImage == 2)
00122                                 setPropertyValue< QVImage<uChar,1> >("Output image",image);
00123                         else    {
00124                                 QVImage<uChar> whiteImage(cols, rows);
00125                                 Set(whiteImage,255);
00126                                 setPropertyValue< QVImage<uChar,1> >("Output image",whiteImage);
00127                                 }
00128                         if(showContours)
00129                                 setPropertyValue< QList< QVPolyline> >("Output contours",outputList);
00130                         else
00131                                 setPropertyValue< QList< QVPolyline> >("Output contours",QList<QVPolyline>());
00132 
00133                         setPropertyValue<int>("Num output contours",outputList.size());
00134                         timeFlag("Publish results");
00135                         }
00136         };
00137 
00138 class ContourExtractorWorker: public QVWorker
00139         {
00140         public:
00141                 ContourExtractorWorker(QString name): QVWorker(name)
00142                         {
00143                         addProperty<int>("Threshold", inputFlag, 128, "Threshold for a point to count as pertaining to a region", 0, 255);
00144                         addProperty<int>("MinAreaIPE", inputFlag, 0, "Minimal area to keep points in the IPE algorithm", 0, 50);
00145                         addProperty< QVImage<uChar,3> >("Input image", inputFlag|outputFlag);
00146                         addProperty< QList<QVPolyline> >("Internal contours", outputFlag);
00147                         addProperty< QList<QVPolyline> >("External contours", outputFlag);
00148                         addProperty<int>("Num internal contours", outputFlag);
00149                         addProperty<int>("Num External contours", outputFlag);
00150                         }
00151 
00152                 void iterate()
00153                         {
00154                         // 0. Read input parameters
00155                         QVImage<uChar,1> image = getPropertyValue< QVImage<uChar,3> >("Input image");
00156                         const uInt      threshold = getPropertyValue< int >("Threshold"),
00157                                         minAreaIPE = getPropertyValue< int >("MinAreaIPE");
00158 
00159                         timeFlag("Read input parameters");
00160                 
00161                         // 1. Get contours from image
00162                         const QList<QVPolyline> contours = getConnectedSetBorderContoursThreshold(image, threshold);
00163                         timeFlag("Get contours from image");
00164 
00165                         // 2. Apply IPE
00166                         QList<QVPolyline> ipeContours;
00167 
00168                         foreach(QVPolyline polyline, contours)
00169                                 {
00170                                 QVPolyline ipePolyline;
00171                                 IterativePointElimination(polyline, ipePolyline, minAreaIPE);
00172                                 if (ipePolyline.size() > 0)
00173                                         ipeContours.append(ipePolyline);
00174                                 }
00175 
00176                         timeFlag("IPE filtering");
00177 
00178                         // 3. Export contours to output property
00179                         QList<QVPolyline> internalContours, externalContours;
00180 
00181                         foreach(QVPolyline polyline, ipeContours)
00182                                 if (polyline.direction)
00183                                         internalContours.append(polyline);
00184                                 else
00185                                         externalContours.append(polyline);
00186 
00187                         setPropertyValue< QList< QVPolyline> >("Internal contours",internalContours);
00188                         setPropertyValue< QList< QVPolyline> >("External contours",externalContours);
00189                         setPropertyValue<int>("Num internal contours",internalContours.size());
00190                         setPropertyValue<int>("Num External contours",externalContours.size());
00191                         timeFlag("Computed output contours");
00192                         }
00193         };
00194 
00195 class HarrisExtractorWorker: public QVWorker
00196         {
00197         public:
00198                 HarrisExtractorWorker(QString name): QVWorker(name)
00199                         {
00200                         addProperty< int >("Points", inputFlag, 15, "window size ", 1, 100);
00201                         addProperty< double >("Threshold", inputFlag, 1.0, "window size ", 0.0, 256.0);
00202                         addProperty< QVImage<uChar,3> >("Input image", inputFlag|outputFlag);
00203                         addProperty< QList<QPointF> >("Corners", outputFlag);
00204                         }
00205 
00206                 void iterate()
00207                         {
00208                         // 0. Read input parameters
00209                         QVImage<uChar> image = getPropertyValue< QVImage<uChar,3> >("Input image");
00210                         const double threshold = getPropertyValue<double>("Threshold");
00211                         const int pointNumber = getPropertyValue<int>("Points");
00212                         timeFlag("grab Frame");
00213                 
00214                         // 1. Obtain corner response image.
00215                         QVImage<sFloat> cornerResponseImage(image.getRows(), image.getCols());
00216                         FilterHessianCornerResponseImage(image, cornerResponseImage);
00217                         timeFlag("Corner response image");
00218 
00219                         // 2. Local maximal filter.
00220                         QList<QPointF> hotPoints = GetMaximalResponsePoints3(cornerResponseImage, threshold);
00221                         timeFlag("Local maximal filter");
00222 
00223                         // 3. Output resulting data.
00224                         setPropertyValue< QList<QPointF> >("Corners", hotPoints.mid(MAX(0,hotPoints.size() - pointNumber)));
00225                         }
00226         };
00227 
00228 int main(int argc, char *argv[])
00229         {
00230         QVApplication app(argc, argv,
00231                 "Example program for QVision library. Obtains several features from input video frames."
00232                 );
00233 
00234         QVFilterSelectorWorker<uChar, 3> filterWorker("Filter worker");
00235         CannyOperatorWorker cannyWorker("Canny Operator Worker");
00236         ContourExtractorWorker contoursWorker("Contours Extractor Worker");
00237         HarrisExtractorWorker cornersWorker("Corners Worker");
00238 
00239         QVImageCanvas filteredCanvas("Input");
00240         filteredCanvas.linkProperty(filterWorker, "Output image");
00241 
00242         filterWorker.linkProperty("Output image", &cannyWorker, "Input image", QVWorker::AsynchronousLink);
00243         filterWorker.linkProperty("Output image", &contoursWorker, "Input image", QVWorker::AsynchronousLink);
00244         filterWorker.linkProperty("Output image", &cornersWorker, "Input image", QVWorker::AsynchronousLink);
00245 
00246         QVGUI interface;
00247 
00248         QVMPlayerCamera camera("Video");
00249         camera.link(&filterWorker, "Input image");
00250 
00251         QVImageCanvas cannyCanvas("Canny");
00252         cannyCanvas.linkProperty(cannyWorker,"Output image");
00253         cannyCanvas.linkProperty(cannyWorker,"Output contours");
00254 
00255         QVImageCanvas contourCanvas("Contours");
00256         contourCanvas.linkProperty(contoursWorker, "Input image");
00257         contourCanvas.linkProperty(contoursWorker,"Internal contours", Qt::red);
00258         contourCanvas.linkProperty(contoursWorker,"External contours", Qt::blue);
00259 
00260         QVImageCanvas cornersCanvas("Corners");
00261         cornersCanvas.linkProperty(cornersWorker, "Input image");
00262         cornersCanvas.linkProperty(cornersWorker,"Corners", Qt::blue, false);
00263 
00264         QVNumericPlot numericPlot("Num contours");
00265         numericPlot.linkProperty(cannyWorker, "Num output contours");
00266         numericPlot.linkProperty(contoursWorker);
00267 
00268         return app.exec();
00269         }
00270 
00271 #endif

Generated on Thu Jul 17 17:23:27 2008 for QVision by  doxygen 1.5.3