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 <qvimageio.h>
00042 #include <qvipp.h>
00043
00044 #include <QVApplication>
00045 #include <QVDefaultGUI>
00046 #include <QVVideoReaderBlock>
00047 #include <QVImageCanvas>
00048 #include <QVProcessingBlock>
00049 #include <QVImage>
00050
00051 #include <qvgpukltflow.h>
00052
00053 #ifdef Q_WS_X11
00054 #include <X11/Xlib.h>
00055 #endif
00056
00057
00058 TVL1_FlowEstimator *flowEstimator = 0;
00059
00060
00061 class FlowImageCanvas: public QVImageCanvas {
00062 public:
00063 FlowImageCanvas(const QString name=QString(),QWidget *parent=0) : QVImageCanvas(name,parent) {
00064 addProperty<int>("flow grid size",inputFlag);
00065 };
00066 void custom_viewer() {
00067 QVImage<sFloat,1> flowX = getPropertyValue<QVImage<sFloat,1> >("flowX");
00068 QVImage<sFloat,1> flowY = getPropertyValue<QVImage<sFloat,1> >("flowY");
00069 int flow_grid_size = getPropertyValue<int>("flow grid size");
00070
00071 getQVPainter()->setPen(Qt::white);
00072
00073 for(int ix=0; ix<flowX.getCols(); ix+=flow_grid_size) {
00074 for(int iy=0; iy<flowX.getRows(); iy+=flow_grid_size) {
00075 getQVPainter()->drawLine(QPointF(ix,iy),
00076 QPointF(ix+flow_grid_size*flowX(ix,iy)/2,
00077 iy+flow_grid_size*flowY(ix,iy)/2));
00078 getQVPainter()->drawEllipse(QPoint(ix,iy), 1, 1);
00079 }
00080 }
00081 }
00082 };
00083
00084
00085 class gridCanvasCanvas: public QVImageCanvas {
00086 public:
00087 gridCanvasCanvas(const QString name=QString(),QWidget *parent=0) : QVImageCanvas(name,parent) {
00088
00089 };
00090 void custom_viewer() {
00091
00092 int move, span = 180;
00093 QVImage<uChar,1> imageIn = getPropertyValue<QVImage<uChar,1> >("image In");
00094 move = getPropertyValue<double> ("move");
00095
00096 getQVPainter()->setPen(Qt::blue);
00097 QPen p = getQVPainter()->pen();
00098 p.setWidth(20);
00099 getQVPainter()->setPen(p);
00100 QRectF rectangle(imageIn.getCols()/2-imageIn.getRows()/4 , imageIn.getRows()/4, imageIn.getRows()/2, imageIn.getRows()/2);
00101 QRectF rectangle2(imageIn.getCols()/2-imageIn.getRows()/4 , imageIn.getRows()/4, imageIn.getRows()/2, imageIn.getRows()/2);
00102
00103
00104 getQVPainter()->drawPie(rectangle, move *16, -span*16 );
00105
00106 getQVPainter()->drawPie(rectangle2, (move*16) , span*16);
00107 }
00108 };
00109
00110
00111
00112 class MyProcessingBlock : public QVProcessingBlock {
00113 private:
00114 QVImage <uChar,1> oldImage;
00115 public:
00116 MyProcessingBlock(QString name): QVProcessingBlock(name) {
00117 addProperty<QVImage<uChar,1> >("image In",inputFlag|outputFlag);
00118 addProperty<double> ("move", outputFlag);
00119 addProperty<double> ("lambda",inputFlag, 10.0, "Lambda", 0.0, 20.0);
00120 addProperty<double> ("theta",inputFlag, 0.02, "Theta", 0.0, 1.0);
00121 addProperty<double> ("tau",inputFlag, 0.25, "Tau", 0.0, 1.0);
00122 addProperty<int> ("nIterations",inputFlag, 10, "nIterations", 1, 50);
00123 addProperty<int> ("nOuterIterations",inputFlag, 4, "nOuterIterations", 1, 30);
00124 addProperty<int> ("nLevels",inputFlag, 4, "Pyramid levels", 1, 8);
00125 addProperty<double> ("Sensitivity", inputFlag, 0.01, "Sensitivity", 0.0, 0.1);
00126 addProperty<int>("flow grid size",inputFlag|outputFlag,10 ,"Flow grid size",5,10);
00127 addProperty<QVImage<uChar,1> >("flowX",outputFlag);
00128 addProperty<QVImage<uChar,1> >("flowY",outputFlag);
00129 }
00130
00131 void iterate() {
00132 QVImage<uChar,1> imageIn = getPropertyValue<QVImage<uChar,1> >("image In");
00133 QVImage<sFloat, 1> x = QVImage<sFloat, 1>(imageIn.getCols(), imageIn.getRows());
00134 QVImage<sFloat,1 > y = QVImage<sFloat, 1>(imageIn.getCols(), imageIn.getRows());
00135 static QVPyramid *p1,*p2;
00136 static double z = 0;
00137 bool reset = false;
00138
00139
00140 if(getIteration() == 0) {
00141 InitGLEWCg();
00142 reset = true;
00143 }
00144
00145
00146 static int width = 0, height = 0, nLevels = 0, nIterations = 0, nOuterIterations = 0;
00147 static double lambda = 0.0, tau = 0.0, theta = 0.0;
00148
00149 if(width != imageIn.getCols()) {
00150 width = imageIn.getCols();
00151 reset = true;
00152 }
00153 if(height != imageIn.getRows()) {
00154 height = imageIn.getRows();
00155 reset = true;
00156 }
00157 if(nLevels != getPropertyValue<int>("nLevels")) {
00158 nLevels = getPropertyValue<int>("nLevels");
00159 reset = true;
00160 }
00161 if(nIterations != getPropertyValue<int>("nIterations")) {
00162 nIterations = getPropertyValue<int>("nIterations");
00163 reset = true;
00164 }
00165 if(nOuterIterations != getPropertyValue<int>("nOuterIterations")) {
00166 nOuterIterations = getPropertyValue<int>("nOuterIterations");
00167 reset = true;
00168 }
00169 if(lambda != getPropertyValue<double>("lambda")) {
00170 lambda = getPropertyValue<double>("lambda");
00171 reset = true;
00172 }
00173 if(tau != getPropertyValue<double>("tau")) {
00174 tau = getPropertyValue<double>("tau");
00175 reset = true;
00176 }
00177 if(theta != getPropertyValue<double>("theta")) {
00178 theta = getPropertyValue<double>("theta");
00179 reset = true;
00180 }
00181
00182 if(reset) {
00183 if(flowEstimator != 0)
00184 flowEstimator->deallocate();
00185 qvInitFlowGPU(flowEstimator, width, height, nLevels, nIterations, nOuterIterations, lambda, tau, theta);
00186 if(p1 != 0)
00187 delete p1;
00188 if(p2 != 0)
00189 delete p2;
00190 p1 = new QVPyramid(width, height, nLevels);
00191 p2 = new QVPyramid(width, height, nLevels);
00192 }
00193 timeFlag("Reset flow estimator");
00194
00195 QVImage<uChar,1> left=oldImage, right=imageIn;
00196 if(not reset) {
00197 p1->buildPyramid(left);
00198 p2->buildPyramid(right);
00199 }
00200 timeFlag("Pyramids");
00201 if(not reset) {
00202 qvOpticalFlowGPU(flowEstimator, p1, p2, x, y);
00203 }
00204 timeFlag("Flow");
00205 if(not reset) {
00206 oldImage = imageIn;
00207 double vx, vy, px, py;
00208 for (int ix = 0; ix < x.getCols(); ix++) {
00209 for (int iy = 0; iy < x.getRows(); iy++){
00210 vx = x(ix,iy);
00211 vy = y(ix,iy);
00212 px = ix - width/2;
00213 py = iy - height/2;
00214 if (ix != width/2 && iy != height/2)
00215 z += (px * vy - py * vx) / (px*px + py*py);
00216 }
00217 }
00218 }
00219 timeFlag("Wheel");
00220
00221 double sensitivity = getPropertyValue<double> ("Sensitivity");
00222 setPropertyValue<QVImage <uChar,1> >("image In", imageIn);
00223 setPropertyValue<QVImage <sFloat,1> >("flowX", x);
00224 setPropertyValue<QVImage <sFloat,1> >("flowY", y);
00225 setPropertyValue<double>("move",-z*sensitivity);
00226 }
00227 };
00228
00229 int main( int argc, char** argv)
00230 {
00231
00232 initShadersEnvironment();
00233
00234 #ifdef Q_WS_X11
00235
00236
00237 XInitThreads();
00238 #endif
00239
00240 QVApplication app(argc,argv);
00241 QVDefaultGUI gui;
00242 QVVideoReaderBlock camera("Camera");
00243 MyProcessingBlock processingBlock("My processing block");
00244 QVImageCanvas videoCanvas ("Input video");
00245 FlowImageCanvas flowCanvas ("Flow image");
00246 gridCanvasCanvas gridCanvas ("Output grid");
00247
00248 camera.linkProperty(&processingBlock,"image In");
00249 processingBlock.linkProperty("image In",&videoCanvas);
00250 processingBlock.linkProperty("flowX", &flowCanvas);
00251 processingBlock.linkProperty("flowY", &flowCanvas);
00252 processingBlock.linkProperty("flow grid size", &flowCanvas,"flow grid size");
00253 processingBlock.linkProperty("image In",&gridCanvas);
00254 processingBlock.linkProperty("move", &gridCanvas);
00255
00256 return app.exec();
00257 }