00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00039 #include <GL/glew.h>
00040
00041 #include<QVApplication>
00042 #include<QVDefaultGUI>
00043 #include<QVVideoReaderBlock>
00044 #include<QVImageCanvas>
00045 #include<QVProcessingBlock>
00046 #include<QVImage>
00047 #include<qvipp.h>
00048
00049 #include <qvgpukltflow.h>
00050 #include <QVKLTFeatureTracking>
00051
00052 #ifdef Q_WS_X11
00053 #include <X11/Xlib.h>
00054 #endif
00055
00056
00057 typedef QHash< int, QVKLTFeatureTracking> TrackingHash;
00058 Q_DECLARE_METATYPE(TrackingHash);
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 class MyQVImageCanvas: public QVImageCanvas {
00094 public:
00095 MyQVImageCanvas(const QString name=QString(),QWidget *parent=0) : QVImageCanvas(name,parent) {
00096 addProperty<TrackingHash>("Trackings", inputFlag);
00097 };
00098
00099
00100 void custom_viewer() {
00101 QHash<int, QVKLTFeatureTracking> trackings = getPropertyValue<TrackingHash>("Trackings");
00102 getQVPainter()->setBackgroundMode(Qt::OpaqueMode);
00103 foreach(QVKLTFeatureTracking ft, trackings) {
00104 QList<QVKLTTrackerFeature> tracking = ft.getFeatureList();
00105
00106 if(tracking.size()==1)
00107 getQVPainter()->setPen(Qt::red);
00108 else
00109 getQVPainter()->setPen(Qt::green);
00110 getQVPainter()->drawEllipse(tracking.last().getPosition(), 2.0, 2.0);
00111
00112 getQVPainter()->setPen(Qt::blue);
00113 for(int j=0; j < tracking.size()-1; j++) {
00114 getQVPainter()->drawLine(tracking[j].getPosition(), tracking[j+1].getPosition());
00115 }
00116 }
00117 getQVPainter()->drawText(25,25,QString("%1 features").arg(trackings.size()));
00118 };
00119 };
00120
00121 class MyProcessingBlock : public QVProcessingBlock {
00122 private:
00123 QVKLTTracker *tracker,*matchTracker;
00124 QVTrackingManager* trackingManager;
00125 QHash<int,QVKLTTrackerFeature> features;
00126 QVImage<uChar,1> imageIn,keyImage;
00127 public:
00128 MyProcessingBlock(QString name): QVProcessingBlock(name) {
00129 tracker = 0;
00130 matchTracker = 0;
00131 trackingManager = 0;
00132 addProperty<QVImage<uChar,1> >("imageIn",inputFlag|outputFlag);
00133 addProperty<int>("nTrackedFrames",inputFlag,10,"Number of frames before redetection",1,30);
00134 addProperty<bool>("trackWithGain",inputFlag,true,"Wether track using gain or not");
00135 addProperty<int>("featuresWidth",inputFlag,64,"Features width",8,128);
00136 addProperty<int>("featuresHeight",inputFlag,64,"Features height",8,128);
00137 addProperty<int>("nIterations",inputFlag,10,"number of KLT iterations",10,30);
00138 addProperty<int>("nLevels",inputFlag,4,"Number of levels of pyramid",1,4);
00139 addProperty<int>("levelSkip",inputFlag,1,"Levels of pyramid to skip",1,3);
00140 addProperty<int>("windowWidth",inputFlag,7,"Window width used by KLT",1,21);
00141 addProperty<float>("trackBorderMargin",inputFlag,20.0,"Border margin for tracking features",10.0,50.0);
00142 addProperty<float>("detectBorderMargin",inputFlag,20.0,"Border margin for detecting features",1.0,100.0);
00143 addProperty<float>("convergenceThreshold",inputFlag,0.1,"Convergence threshold for KLT",0.01,0.5);
00144 addProperty<float>("SSD_Threshold",inputFlag,5000.0,"SSD threshold for KLT",1000.0,10000.0);
00145 addProperty<int>("minDistance",inputFlag,7,"Minimum distance between features",3,25);
00146 addProperty<float>("minCornerness",inputFlag,50.0,"Minimum value for cornerness",20.0,100.0);
00147 addProperty<QHash<int,QVKLTFeatureTracking> > ("Trackings",outputFlag);
00148
00149 addProperty<QVImage<uChar,1> >("Matching images",outputFlag);
00150 addProperty< QList<QPointFMatching> >("Matching correspondences", outputFlag);
00151
00152
00153
00154
00155 addTrigger("Follow from key frame");
00156 };
00157
00158 void processTrigger(QString name) {
00159 if(name == QString("Follow from key frame")) {
00160 keyImage = imageIn;
00161 }
00162 }
00163
00164
00165 void ResetTracker(int width, int height, bool trackWithGain, int featuresWidth, int featuresHeight,
00166 int nIterations, int nLevels, int levelSkip,int windowWidth,
00167 float trackBorderMargin, float detectBorderMargin, float convergenceThreshold,
00168 float SSD_Threshold, int minDistance, float minCornerness) {
00169
00170 if(tracker != 0) {
00171 delete tracker;
00172 }
00173 tracker = new QVKLTTracker(width, height, trackWithGain, featuresWidth, featuresHeight,
00174 nIterations, nLevels, levelSkip, windowWidth,
00175 trackBorderMargin, detectBorderMargin, convergenceThreshold,
00176 SSD_Threshold, minDistance, minCornerness);
00177 if(matchTracker != 0) {
00178 delete matchTracker;
00179 }
00180 matchTracker = new QVKLTTracker(width, height, trackWithGain, featuresWidth, featuresHeight,
00181 nIterations, nLevels, levelSkip, windowWidth,
00182 trackBorderMargin, detectBorderMargin, convergenceThreshold,
00183 SSD_Threshold, minDistance, minCornerness);
00184
00185
00186 if (trackingManager != 0){
00187 delete trackingManager;
00188 }
00189 trackingManager = new QVTrackingManager(true);
00190 }
00191
00192 void iterate() {
00193 bool reset = false;
00194
00195
00196 if(getIteration() == 0)
00197 {
00198 InitGLEWCg();
00199 reset = true;
00200 }
00201
00202
00203 static bool trackWithGain;
00204 static int width = 0, height = 0, featuresWidth = 0,
00205 featuresHeight = 0, nIterations = 0, nLevels = 0,
00206 levelSkip = 0, windowWidth = 0, minDistance = 0;
00207 static float trackBorderMargin = 0.0, detectBorderMargin = 0.0,
00208 convergenceThreshold = 0.0, SSD_Threshold = 0.0,
00209 minCornerness = 0.0;
00210
00211 int nTrackedFrames = getPropertyValue<float>("nTrackedFrames");
00212 imageIn = getPropertyValue<QVImage<uChar,1> >("imageIn");
00213
00214 if ( (width != imageIn.getCols()) or (height != imageIn.getRows()) or
00215 (trackWithGain != getPropertyValue<bool>("trackWithGain")) or
00216 (featuresWidth != getPropertyValue<int>("featuresWidth")) or
00217 (featuresHeight != getPropertyValue<int>("featuresHeight")) or
00218 (nIterations != getPropertyValue<int>("nIterations")) or
00219 (nLevels != getPropertyValue<int>("nLevels")) or
00220 (levelSkip != getPropertyValue<int>("levelSkip")) or
00221 (windowWidth != getPropertyValue<int>("windowWidth")) or
00222 (trackBorderMargin != getPropertyValue<float>("trackBorderMargin")) or
00223 (detectBorderMargin != getPropertyValue<float>("detectBorderMargin")) or
00224 (convergenceThreshold != getPropertyValue<float>("convergenceThreshold")) or
00225 (SSD_Threshold != getPropertyValue<float>("SSD_Threshold")) or
00226 (minDistance != getPropertyValue<int>("minDistance")) or
00227 (minCornerness != getPropertyValue<float>("minCornerness")) )
00228 {
00229 width = imageIn.getCols();
00230 height = imageIn.getRows();
00231 trackWithGain = getPropertyValue<bool>("trackWithGain");
00232 featuresWidth = getPropertyValue<int>("featuresWidth");
00233 featuresHeight = getPropertyValue<int>("featuresHeight");
00234 nIterations = getPropertyValue<int>("nIterations");
00235 nLevels = getPropertyValue<int>("nLevels");
00236 levelSkip = getPropertyValue<int>("levelSkip");
00237 windowWidth = getPropertyValue<int>("windowWidth");
00238 trackBorderMargin = getPropertyValue<float>("trackBorderMargin");
00239 detectBorderMargin = getPropertyValue<float>("detectBorderMargin");
00240 convergenceThreshold = getPropertyValue<float>("convergenceThreshold");
00241 SSD_Threshold = getPropertyValue<float>("SSD_Threshold");
00242 minDistance = getPropertyValue<int>("minDistance");
00243 minCornerness = getPropertyValue<float>("minCornerness");
00244 reset = true;
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310 timeFlag("Read properties");
00311
00312
00313 if(reset)
00314 {
00315 ResetTracker(width, height, trackWithGain, featuresWidth, featuresHeight,
00316 nIterations, nLevels, levelSkip, windowWidth,
00317 trackBorderMargin, detectBorderMargin, convergenceThreshold,
00318 SSD_Threshold, minDistance, minCornerness);
00319 features.clear();
00320 tracker->detect(imageIn, features);
00321 }
00322
00323 timeFlag("Reset tracker");
00324
00325
00326 if(not reset)
00327 {
00328 if (getIteration() % nTrackedFrames == 0)
00329
00330
00331 tracker->redetect(imageIn, features);
00332
00333 else
00334
00335
00336 tracker->track(imageIn, features);
00337
00338 }
00339 timeFlag("GPU tracking");
00340
00341
00342 trackingManager->updateTrackings(&features);
00343 timeFlag("Tracking manager update");
00344
00345
00346 setPropertyValue<TrackingHash>("Trackings", trackingManager->getTrackings());
00347 timeFlag("Write properties");
00348
00349 if(keyImage.getSize() == imageIn.getSize())
00350 {
00351 QVImage<uChar,1> imagesLeftAndRight;
00352 imagesLeftAndRight = QVImage<uChar,1>(imageIn.getCols()*2,imageIn.getRows());
00353 Copy(keyImage,imagesLeftAndRight,QPoint(0, 0));
00354 Copy(imageIn,imagesLeftAndRight,QPoint(imageIn.getCols(),0));
00355 imagesLeftAndRight.resetROI();
00356
00357 QHash<int,QVKLTTrackerFeature> featuresKeyframe, featuresInput;
00358 matchTracker->detect(keyImage, featuresKeyframe);
00359 featuresInput = featuresKeyframe;
00360 matchTracker->track(imageIn, featuresInput);
00361
00362
00363 QList<QPointFMatching> correspondences;
00364 const QPointF offset(keyImage.getCols(), 0);
00365
00366 for(QHash<int, QVKLTTrackerFeature>::iterator i = featuresInput.begin(); i != featuresInput.end(); i++)
00367 {
00368 QVKLTTrackerFeature ftInput = i.value();
00369 QVKLTTrackerFeature ftKey = featuresKeyframe.value(i.key());
00370 correspondences << QPointFMatching(ftKey.getPosition(), ftInput.getPosition()+offset);
00371 }
00372
00373
00374 setPropertyValue< QList<QPointFMatching> >("Matching correspondences", correspondences);
00375 setPropertyValue<QVImage<uChar,1> >("Matching images", imagesLeftAndRight);
00376
00377
00378 }
00379 }
00380 };
00381
00382 int main( int argc, char** argv)
00383 {
00384
00385 initShadersEnvironment();
00386
00387 #ifdef Q_WS_X11
00388
00389
00390 XInitThreads();
00391 #endif
00392
00393 QVApplication app(argc,argv);
00394 QVDefaultGUI gui;
00395 QVVideoReaderBlock camera("Camera");
00396
00397 MyProcessingBlock processingBlock("My processing block");
00398 camera.linkProperty(&processingBlock,"imageIn");
00399
00400 MyQVImageCanvas imageCanvas("Canvas");
00401 processingBlock.linkProperty("imageIn",&imageCanvas);
00402 processingBlock.linkProperty("Trackings", &imageCanvas, "Trackings");
00403
00404 QVImageCanvas referenceFrame("Matchings");
00405 processingBlock.linkProperty("Matching images", referenceFrame);
00406 processingBlock.linkProperty("Matching correspondences", referenceFrame);
00407 referenceFrame.setRadius("Matching correspondences", 2);
00408
00409 return app.exec();
00410 }