Path: blob/master/samples/tapi/pyrlk_optical_flow.cpp
16337 views
#include <iostream>1#include <vector>2#include <iomanip>34#include "opencv2/core/utility.hpp"5#include "opencv2/imgcodecs.hpp"6#include "opencv2/videoio.hpp"7#include "opencv2/highgui.hpp"8#include "opencv2/core/ocl.hpp"9#include "opencv2/video/video.hpp"1011using namespace std;12using namespace cv;1314typedef unsigned char uchar;15#define LOOP_NUM 1016int64 work_begin = 0;17int64 work_end = 0;1819static void workBegin()20{21work_begin = getTickCount();22}23static void workEnd()24{25work_end += (getTickCount() - work_begin);26}27static double getTime()28{29return work_end * 1000. / getTickFrequency();30}3132static void drawArrows(UMat& _frame, const vector<Point2f>& prevPts, const vector<Point2f>& nextPts, const vector<uchar>& status,33Scalar line_color = Scalar(0, 0, 255))34{35Mat frame = _frame.getMat(ACCESS_WRITE);36for (size_t i = 0; i < prevPts.size(); ++i)37{38if (status[i])39{40int line_thickness = 1;4142Point p = prevPts[i];43Point q = nextPts[i];4445double angle = atan2((double) p.y - q.y, (double) p.x - q.x);4647double hypotenuse = sqrt( (double)(p.y - q.y)*(p.y - q.y) + (double)(p.x - q.x)*(p.x - q.x) );4849if (hypotenuse < 1.0)50continue;5152// Here we lengthen the arrow by a factor of three.53q.x = (int) (p.x - 3 * hypotenuse * cos(angle));54q.y = (int) (p.y - 3 * hypotenuse * sin(angle));5556// Now we draw the main line of the arrow.57line(frame, p, q, line_color, line_thickness);5859// Now draw the tips of the arrow. I do some scaling so that the60// tips look proportional to the main line of the arrow.6162p.x = (int) (q.x + 9 * cos(angle + CV_PI / 4));63p.y = (int) (q.y + 9 * sin(angle + CV_PI / 4));64line(frame, p, q, line_color, line_thickness);6566p.x = (int) (q.x + 9 * cos(angle - CV_PI / 4));67p.y = (int) (q.y + 9 * sin(angle - CV_PI / 4));68line(frame, p, q, line_color, line_thickness);69}70}71}727374int main(int argc, const char* argv[])75{76const char* keys =77"{ h help | | print help message }"78"{ l left | | specify left image }"79"{ r right | | specify right image }"80"{ c camera | 0 | enable camera capturing }"81"{ v video | | use video as input }"82"{ o output | pyrlk_output.jpg| specify output save path when input is images }"83"{ points | 1000 | specify points count [GoodFeatureToTrack] }"84"{ min_dist | 0 | specify minimal distance between points [GoodFeatureToTrack] }"85"{ m cpu_mode | false | run without OpenCL }";8687CommandLineParser cmd(argc, argv, keys);8889if (cmd.has("help"))90{91cout << "Usage: pyrlk_optical_flow [options]" << endl;92cout << "Available options:" << endl;93cmd.printMessage();94return EXIT_SUCCESS;95}9697bool defaultPicturesFail = true;98string fname0 = cmd.get<string>("left");99string fname1 = cmd.get<string>("right");100string vdofile = cmd.get<string>("video");101string outfile = cmd.get<string>("output");102int points = cmd.get<int>("points");103double minDist = cmd.get<double>("min_dist");104int inputName = cmd.get<int>("c");105106UMat frame0;107imread(fname0, cv::IMREAD_GRAYSCALE).copyTo(frame0);108UMat frame1;109imread(fname1, cv::IMREAD_GRAYSCALE).copyTo(frame1);110111vector<cv::Point2f> pts(points);112vector<cv::Point2f> nextPts(points);113vector<unsigned char> status(points);114vector<float> err;115116cout << "Points count : " << points << endl << endl;117118if (frame0.empty() || frame1.empty())119{120VideoCapture capture;121UMat frame, frameCopy;122UMat frame0Gray, frame1Gray;123UMat ptr0, ptr1;124125if(vdofile.empty())126capture.open( inputName );127else128capture.open(vdofile.c_str());129130int c = inputName ;131if(!capture.isOpened())132{133if(vdofile.empty())134cout << "Capture from CAM " << c << " didn't work" << endl;135else136cout << "Capture from file " << vdofile << " failed" <<endl;137if (defaultPicturesFail)138return EXIT_FAILURE;139goto nocamera;140}141142cout << "In capture ..." << endl;143for(int i = 0;; i++)144{145if( !capture.read(frame) )146break;147148if (i == 0)149{150frame.copyTo( frame0 );151cvtColor(frame0, frame0Gray, COLOR_BGR2GRAY);152}153else154{155if (i%2 == 1)156{157frame.copyTo(frame1);158cvtColor(frame1, frame1Gray, COLOR_BGR2GRAY);159ptr0 = frame0Gray;160ptr1 = frame1Gray;161}162else163{164frame.copyTo(frame0);165cvtColor(frame0, frame0Gray, COLOR_BGR2GRAY);166ptr0 = frame1Gray;167ptr1 = frame0Gray;168}169170171pts.clear();172goodFeaturesToTrack(ptr0, pts, points, 0.01, 0.0);173if(pts.size() == 0)174continue;175calcOpticalFlowPyrLK(ptr0, ptr1, pts, nextPts, status, err);176177if (i%2 == 1)178frame1.copyTo(frameCopy);179else180frame0.copyTo(frameCopy);181drawArrows(frameCopy, pts, nextPts, status, Scalar(255, 0, 0));182imshow("PyrLK [Sparse]", frameCopy);183}184char key = (char)waitKey(10);185186if (key == 27)187break;188else if (key == 'm' || key == 'M')189{190ocl::setUseOpenCL(!cv::ocl::useOpenCL());191cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL" : "CPU") << " mode\n";192}193}194capture.release();195}196else197{198nocamera:199if (cmd.has("cpu_mode"))200{201ocl::setUseOpenCL(false);202std::cout << "OpenCL was disabled" << std::endl;203}204for(int i = 0; i <= LOOP_NUM; i ++)205{206cout << "loop" << i << endl;207if (i > 0) workBegin();208209goodFeaturesToTrack(frame0, pts, points, 0.01, minDist);210calcOpticalFlowPyrLK(frame0, frame1, pts, nextPts, status, err);211212if (i > 0 && i <= LOOP_NUM)213workEnd();214215if (i == LOOP_NUM)216{217cout << "average time (noCamera) : ";218219cout << getTime() / LOOP_NUM << " ms" << endl;220221drawArrows(frame0, pts, nextPts, status, Scalar(255, 0, 0));222imshow("PyrLK [Sparse]", frame0);223imwrite(outfile, frame0);224}225}226}227228waitKey();229230return EXIT_SUCCESS;231}232233234