dense_optical_flow.cpp 4.68 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 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 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html

#include <iostream>
#include <iomanip>
#include <vector>

#include "opencv2/core/ocl.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/video.hpp"

using namespace std;
using namespace cv;

static Mat getVisibleFlow(InputArray flow)
{
    vector<UMat> flow_vec;
    split(flow, flow_vec);
    UMat magnitude, angle;
    cartToPolar(flow_vec[0], flow_vec[1], magnitude, angle, true);
    magnitude.convertTo(magnitude, CV_32F, 0.2);
    vector<UMat> hsv_vec;
    hsv_vec.push_back(angle);
    hsv_vec.push_back(UMat::ones(angle.size(), angle.type()));
    hsv_vec.push_back(magnitude);
    UMat hsv;
    merge(hsv_vec, hsv);
    Mat img;
    cvtColor(hsv, img, COLOR_HSV2BGR);
    return img;
}

static Size fitSize(const Size & sz,  const Size & bounds)
{
    CV_Assert(sz.area() > 0);
    if (sz.width > bounds.width || sz.height > bounds.height)
    {
        double scale = std::min((double)bounds.width / sz.width, (double)bounds.height / sz.height);
        return Size(cvRound(sz.width * scale), cvRound(sz.height * scale));
    }
    return sz;
}

int main(int argc, const char* argv[])
{
    const char* keys =
            "{ h help     |     | print help message }"
            "{ c camera   | 0   | capture video from camera (device index starting from 0) }"
            "{ a algorithm | fb | algorithm (supported: 'fb', 'tvl')}"
            "{ m cpu      |     | run without OpenCL }"
            "{ v video    |     | use video as input }"
            "{ o original |     | use original frame size (do not resize to 640x480)}"
            ;
    CommandLineParser parser(argc, argv, keys);
    parser.about("This sample demonstrates using of dense optical flow algorithms.");
    if (parser.has("help"))
    {
        parser.printMessage();
        return 0;
    }
    int camera = parser.get<int>("camera");
    string algorithm = parser.get<string>("algorithm");
    bool useCPU = parser.has("cpu");
    string filename = parser.get<string>("video");
    bool useOriginalSize = parser.has("original");
    if (!parser.check())
    {
        parser.printErrors();
        return 1;
    }

    VideoCapture cap;
    if(filename.empty())
        cap.open(camera);
    else
        cap.open(filename);
    if (!cap.isOpened())
    {
        cout << "Can not open video stream: '" << (filename.empty() ? "<camera>" : filename) << "'" << endl;
        return 2;
    }

    cv::Ptr<cv::DenseOpticalFlow> alg;
    if (algorithm == "fb")
        alg = cv::FarnebackOpticalFlow::create();
    else if (algorithm == "tvl")
        alg = cv::DualTVL1OpticalFlow::create();
    else
    {
        cout << "Invalid algorithm: " << algorithm << endl;
        return 3;
    }

    ocl::setUseOpenCL(!useCPU);

    cout << "Press 'm' to toggle CPU/GPU processing mode" << endl;
    cout << "Press ESC or 'q' to exit" << endl;

    UMat prevFrame, frame, input_frame, flow;
    for(;;)
    {
        if (!cap.read(input_frame) || input_frame.empty())
        {
            cout << "Finished reading: empty frame" << endl;
            break;
        }
        Size small_size = fitSize(input_frame.size(), Size(640, 480));
        if (!useOriginalSize && small_size != input_frame.size())
            resize(input_frame, frame, small_size);
        else
            frame = input_frame;
        cvtColor(frame, frame, COLOR_BGR2GRAY);
        imshow("frame", frame);
        if (!prevFrame.empty())
        {
            int64 t = getTickCount();
            alg->calc(prevFrame, frame, flow);
            t = getTickCount() - t;
            {
                Mat img = getVisibleFlow(flow);
                ostringstream buf;
                buf << "Algo: " << algorithm << " | "
                    << "Mode: " << (useCPU ? "CPU" : "GPU") << " | "
                    << "FPS: " << fixed << setprecision(1) << (getTickFrequency() / (double)t);
                putText(img, buf.str(), Point(10, 30), FONT_HERSHEY_PLAIN, 2.0, Scalar(0, 0, 255), 2, LINE_AA);
                imshow("Dense optical flow field", img);
            }
        }
        frame.copyTo(prevFrame);

        // interact with user
        const char key = (char)waitKey(30);
        if (key == 27 || key == 'q') // ESC
        {
            cout << "Exit requested" << endl;
            break;
        }
        else if (key == 'm')
        {
            useCPU = !useCPU;
            ocl::setUseOpenCL(!useCPU);
            cout << "Set processing mode to: " << (useCPU ? "CPU" : "GPU") << endl;
        }
    }

    return 0;
}