farneback_optical_flow.cpp 4.14 KB
Newer Older
1 2 3
#include <iostream>
#include <vector>
#include <sstream>
4
#include <cmath>
5

6 7 8 9
#include "opencv2/core.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/video.hpp"
10
#include "opencv2/cudaoptflow.hpp"
11
#include "opencv2/cudaarithm.hpp"
12 13 14

using namespace std;
using namespace cv;
15
using namespace cv::cuda;
16 17 18 19 20 21 22 23

template <typename T>
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);
}

24
static void colorizeFlow(const Mat &u, const Mat &v, Mat &dst)
25 26
{
    double uMin, uMax;
27
    cv::minMaxLoc(u, &uMin, &uMax, 0, 0);
28
    double vMin, vMax;
29
    cv::minMaxLoc(v, &vMin, &vMax, 0, 0);
30 31
    uMin = ::abs(uMin); uMax = ::abs(uMax);
    vMin = ::abs(vMin); vMax = ::abs(vMax);
32
    float dMax = static_cast<float>(::max(::max(uMin, uMax), ::max(vMin, vMax)));
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

    dst.create(u.size(), CV_8UC3);
    for (int y = 0; y < u.rows; ++y)
    {
        for (int x = 0; x < u.cols; ++x)
        {
            dst.at<uchar>(y,3*x) = 0;
            dst.at<uchar>(y,3*x+1) = (uchar)mapVal(-v.at<float>(y,x), -dMax, dMax, 0.f, 255.f);
            dst.at<uchar>(y,3*x+2) = (uchar)mapVal(u.at<float>(y,x), -dMax, dMax, 0.f, 255.f);
        }
    }
}

int main(int argc, char **argv)
{
    CommandLineParser cmd(argc, argv,
49 50
            "{ l left  | ../data/basketball1.png | specify left image }"
            "{ r right | ../data/basketball2.png | specify right image }"
51
            "{ h help  | | print help message }");
52

53 54
    cmd.about("Farneback's optical flow sample.");
    if (cmd.has("help") || !cmd.check())
55
    {
56 57
        cmd.printMessage();
        cmd.printErrors();
58 59 60
        return 0;
    }

61

62 63 64 65 66 67 68 69 70 71 72 73 74
    string pathL = cmd.get<string>("left");
    string pathR = cmd.get<string>("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);
75 76
    GpuMat d_flow;
    Ptr<cuda::FarnebackOpticalFlow> d_calc = cuda::FarnebackOpticalFlow::create();
77 78 79 80 81 82 83 84 85 86 87 88 89 90
    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();
91
            d_calc->calc(d_frameL, d_frameR, d_flow);
92
            tc1 = getTickCount();
93 94 95 96 97 98

            GpuMat planes[2];
            cuda::split(d_flow, planes);

            planes[0].download(flowx);
            planes[1].download(flowy);
99 100 101 102 103
        }
        else
        {
            tc0 = getTickCount();
            calcOpticalFlowFarneback(
104 105
                        frameL, frameR, flowxy, d_calc->getPyrScale(), d_calc->getNumLevels(), d_calc->getWinSize(),
                        d_calc->getNumIters(), d_calc->getPolyN(), d_calc->getPolySigma(), d_calc->getFlags());
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
            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)));
121
        putText(image, s.str(), Point(5, 65), FONT_HERSHEY_SIMPLEX, 1., Scalar(255,0,255), 2);
122 123 124

        s.str("");
        s << "total FPS: " << cvRound((getTickFrequency()/(t1-t0)));
125
        putText(image, s.str(), Point(5, 105), FONT_HERSHEY_SIMPLEX, 1., Scalar(255,0,255), 2);
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140

        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;
}