00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00083 Convert(image, imageFloat);
00084 timeFlag("Convert image from uChar to sShort");
00085
00086
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
00093 CannyGetSize(canny, buffer);
00094 Canny(dXNeg, dY, canny, buffer, cannyLow,cannyHigh);
00095 timeFlag("Apply Canny operator");
00096
00097
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
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
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
00162 const QList<QVPolyline> contours = getConnectedSetBorderContoursThreshold(image, threshold);
00163 timeFlag("Get contours from image");
00164
00165
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
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
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
00215 QVImage<sFloat> cornerResponseImage(image.getRows(), image.getCols());
00216 FilterHessianCornerResponseImage(image, cornerResponseImage);
00217 timeFlag("Corner response image");
00218
00219
00220 QList<QPointF> hotPoints = GetMaximalResponsePoints3(cornerResponseImage, threshold);
00221 timeFlag("Local maximal filter");
00222
00223
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