farneback_optical_flow.cpp 3.95 KB
Newer Older
wester committed
1 2 3 4
#include <iostream>
#include <vector>
#include <sstream>

wester committed
5 6 7 8
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/video/video.hpp"
#include "opencv2/gpu/gpu.hpp"
wester committed
9 10 11

using namespace std;
using namespace cv;
wester committed
12
using namespace cv::gpu;
wester committed
13 14 15 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);
}

static void colorizeFlow(const Mat &u, const Mat &v, Mat &dst)
{
    double uMin, uMax;
wester committed
24
    minMaxLoc(u, &uMin, &uMax, 0, 0);
wester committed
25
    double vMin, vMax;
wester committed
26 27 28
    minMaxLoc(v, &vMin, &vMax, 0, 0);
    uMin = std::abs(uMin); uMax = std::abs(uMax);
    vMin = std::abs(vMin); vMax = std::abs(vMax);
wester committed
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
    float dMax = static_cast<float>(::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<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,
wester committed
46 47 48
            "{ l | left | | specify left image }"
            "{ r | right | | specify right image }"
            "{ h | help | false | print help message }");
wester committed
49

wester committed
50
    if (cmd.get<bool>("help"))
wester committed
51
    {
wester committed
52 53 54 55
        cout << "Farneback's optical flow sample.\n\n"
             << "Usage: farneback_optical_flow_gpu [arguments]\n\n"
             << "Arguments:\n";
        cmd.printParams();
wester committed
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
        return 0;
    }

    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);
wester committed
72 73
    GpuMat d_flowx, d_flowy;
    FarnebackOpticalFlow d_calc;
wester committed
74 75 76 77 78 79 80 81 82 83 84 85 86 87
    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();
wester committed
88
            d_calc(d_frameL, d_frameR, d_flowx, d_flowy);
wester committed
89
            tc1 = getTickCount();
wester committed
90 91
            d_flowx.download(flowx);
            d_flowy.download(flowy);
wester committed
92 93 94 95 96
        }
        else
        {
            tc0 = getTickCount();
            calcOpticalFlowFarneback(
wester committed
97 98
                        frameL, frameR, flowxy, d_calc.pyrScale, d_calc.numLevels, d_calc.winSize,
                        d_calc.numIters, d_calc.polyN, d_calc.polySigma, d_calc.flags);
wester committed
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
            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;
}