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 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.
calcOpticalFlowFarneback(prevgray, img, flowUmat, 0.4, 1, 12, 2, 8, 1.2, 0);
- 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
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 argc, const 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(640, 480));
// 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.4, 1, 12, 2, 8, 1.2, 0);
// 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), 1, Scalar(0, 0, 0), -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);
}
}
}
