Opencv simple C++ tutorial and code to achieve optical flow and farneback optical flow of moving an object in OpenCV video. Let's check the video example and the achieved result on my blog. Working and well-described code is included. 

optical flow Farneback

Optical Flow Farneback parameters remarks

You need 2 images at least to calculate optical flow, the previous image (prevgray) and the current image (img). !! The previous image must be initialized first !! Both images have to be grayscale. 

The result is stored in flowUmat which has the same size as inputs but the format is CV_32FC2

calcOpticalFlowFarneback(prevgray, img, flowUmat, 0.4112281.20);
  • 0.4- Image pyramid or simple image scale
  • 1 is the number of pyramid layers. 1 means that flow is calculated only from the previous image. 
  • 12 is the window size. Flow is computed over the window larger value is more robust to the noise. 
  • 2 mean number of iterations of the algorithm
  • 8 is polynomial degree expansion recommended value is 5 - 7
  • 1.2 standard deviation used to smooth used derivatives recommended values from 1.1 - 1,5

calcOpticalFlowFarneback(prevgray, img, flowUmat, 0.4, 1, 12, 2, 8, 1.2, 0);


calcOpticalFlowFarneback Example

My gopro video is captured at Old Town Square in Prague.


Opencv Tutorial C++ code calcOpticalFlowFarneback


#include "opencv2\highgui.hpp"
#include "opencv2\imgproc.hpp"
#include "opencv2\objdetect\objdetect.hpp"
#include "opencv2/video/tracking.hpp"
#include <vector>
#include <stdio.h>
#include <Windows.h>
#include <iostream>
using namespace cv;
using namespace std;

int main(int argcconst char** argv)
{
 // add your file name
 VideoCapture cap("yourFile.mp4");
 Mat flow, frame;
 // some faster than mat image container
 UMat  flowUmat, prevgray;
 for (;;)
 {
  bool Is = cap.grab();
  if (Is == false) {
    // if video capture failed
   cout << "Video Capture Fail" << endl;
   break;
  }
  else {
   Mat img;
   Mat original;
   // capture frame from video file
   cap.retrieve(img, CV_CAP_OPENNI_BGR_IMAGE);
   resize(img, img, Size(640480));
   // save original for later
   img.copyTo(original);
   // just make current frame gray
   cvtColor(img, img, COLOR_BGR2GRAY);
   // For all optical flow you need a sequence of images.. Or at least 2 of them. Previous
                           //and current frame
   // if there is no current frame
   // go to this part and fill previous frame
   //else {
   // img.copyTo(prevgray);
   //   }
   // if previous frame is not empty.. There is a picture of previous frame. Do some 
//optical flow alg. 
   if (prevgray.empty() == false ) {
    // calculate optical flow 
    calcOpticalFlowFarneback(prevgray, img, flowUmat, 0.4112281.20);
    // copy Umat container to standard Mat
    flowUmat.copyTo(flow);
        // By y += 5, x += 5 you can specify the grid 
    for (int y = 0; y < original.rows; y += 5) {
     for (int x = 0; x < original.cols; x += 5)  {
              // get the flow from y, x position * 10 for better visibility
              const Point2f flowatxy = flow.at<Point2f>(y, x) * 10;
              // draw line at flow direction
       line(original, Point(x, y), Point(cvRound(x + flowatxy.x), cvRound(y + flowatxy.y)), Scalar(255,0,0));
       // draw initial point
       circle(original, Point(x, y), 1Scalar(000), -1);
     }
    }
    // draw the results
    namedWindow("prew", WINDOW_AUTOSIZE);
    imshow("prew", original);
    // fill previous image again
    img.copyTo(prevgray);
   }
   else {
    // fill previous image in case prevgray.empty() == true
    img.copyTo(prevgray);
   }
   int key1 = waitKey(20);
 }
 }
}