From 35d63083f98685e0b96fbae79db203ed783d672f Mon Sep 17 00:00:00 2001 From: Alexey Spizhevoy Date: Mon, 20 Feb 2012 08:31:10 +0000 Subject: [PATCH] Added Farneback's optical flow sample --- samples/gpu/farneback_optical_flow.cpp | 133 +++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 samples/gpu/farneback_optical_flow.cpp diff --git a/samples/gpu/farneback_optical_flow.cpp b/samples/gpu/farneback_optical_flow.cpp new file mode 100644 index 0000000..a88b2da --- /dev/null +++ b/samples/gpu/farneback_optical_flow.cpp @@ -0,0 +1,133 @@ +#include +#include +#include + +#include "opencv2/core/core.hpp" +#include "opencv2/highgui/highgui.hpp" +#include "opencv2/video/video.hpp" +#include "opencv2/gpu/gpu.hpp" + +using namespace std; +using namespace cv; +using namespace cv::gpu; + +template +inline T mapVal(T x, T a, T b, T c, T d) +{ + x = ::max(::min(x, b), a); + return c + (d-c) * (x-a) / (b-a); +} + +void colorizeFlow(const Mat &u, const Mat &v, Mat &dst) +{ + double uMin, uMax; + minMaxLoc(u, &uMin, &uMax, 0, 0); + double vMin, vMax; + minMaxLoc(v, &vMin, &vMax, 0, 0); + uMin = ::abs(uMin); uMax = ::abs(uMax); + vMin = ::abs(vMin); vMax = ::abs(vMax); + float dMax = ::max(::max(uMin, uMax), ::max(vMin, vMax)); + + dst.create(u.size(), CV_8UC3); + for (int y = 0; y < u.rows; ++y) + { + for (int x = 0; x < u.cols; ++x) + { + dst.at(y,3*x) = 0; + dst.at(y,3*x+1) = (uchar)mapVal(-v.at(y,x), -dMax, dMax, 0.f, 255.f); + dst.at(y,3*x+2) = (uchar)mapVal(u.at(y,x), -dMax, dMax, 0.f, 255.f); + } + } +} + +int main(int argc, char **argv) +{ + CommandLineParser cmd(argc, argv, + "{ l | left | | specify left image }" + "{ r | right | | specify right image }" + "{ h | help | false | print help message }"); + + if (cmd.get("help")) + { + cout << "Farneback's optical flow sample.\n\n" + << "Usage: farneback_optical_flow_gpu [arguments]\n\n" + << "Arguments:\n"; + cmd.printParams(); + return 0; + } + + string pathL = cmd.get("left"); + string pathR = cmd.get("right"); + if (pathL.empty()) cout << "Specify left image path\n"; + if (pathR.empty()) cout << "Specify right image path\n"; + if (pathL.empty() || pathR.empty()) return -1; + + Mat frameL = imread(pathL, IMREAD_GRAYSCALE); + Mat frameR = imread(pathR, IMREAD_GRAYSCALE); + if (frameL.empty()) cout << "Can't open '" << pathL << "'\n"; + if (frameR.empty()) cout << "Can't open '" << pathR << "'\n"; + if (frameL.empty() || frameR.empty()) return -1; + + GpuMat d_frameL(frameL), d_frameR(frameR); + GpuMat d_flowx, d_flowy; + FarnebackOpticalFlow d_calc; + Mat flowxy, flowx, flowy, image; + + bool running = true, gpuMode = true; + int64 t, t0=0, t1=1, tc0, tc1; + + cout << "Use 'm' for CPU/GPU toggling\n"; + + while (running) + { + t = getTickCount(); + + if (gpuMode) + { + tc0 = getTickCount(); + d_calc(d_frameL, d_frameR, d_flowx, d_flowy); + tc1 = getTickCount(); + d_flowx.download(flowx); + d_flowy.download(flowy); + } + else + { + tc0 = getTickCount(); + calcOpticalFlowFarneback( + frameL, frameR, flowxy, d_calc.pyrScale, d_calc.numLevels, d_calc.winSize, + d_calc.numIters, d_calc.polyN, d_calc.polySigma, d_calc.flags); + tc1 = getTickCount(); + + Mat planes[] = {flowx, flowy}; + split(flowxy, planes); + flowx = planes[0]; flowy = planes[1]; + } + + colorizeFlow(flowx, flowy, image); + + stringstream s; + s << "mode: " << (gpuMode?"GPU":"CPU"); + putText(image, s.str(), Point(5, 25), FONT_HERSHEY_SIMPLEX, 1., Scalar(255,0,255), 2); + + s.str(""); + s << "opt. flow FPS: " << cvRound((getTickFrequency()/(tc1-tc0))); + putText(image, s.str(), Point(5, 65), FONT_HERSHEY_SIMPLEX, 1., Scalar(255,0,255), 2.); + + s.str(""); + s << "total FPS: " << cvRound((getTickFrequency()/(t1-t0))); + putText(image, s.str(), Point(5, 105), FONT_HERSHEY_SIMPLEX, 1., Scalar(255,0,255), 2.); + + imshow("flow", image); + + char ch = (char)waitKey(3); + if (ch == 27) + running = false; + else if (ch == 'm' || ch == 'M') + gpuMode = !gpuMode; + + t0 = t; + t1 = getTickCount(); + } + + return 0; +} -- 2.7.4