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