Merge remote-tracking branch 'upstream/3.4' into merge-3.4
[platform/upstream/opencv.git] / samples / tapi / dense_optical_flow.cpp
1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html
4
5 #include <iostream>
6 #include <iomanip>
7 #include <vector>
8
9 #include "opencv2/core/ocl.hpp"
10 #include "opencv2/core/utility.hpp"
11 #include "opencv2/imgcodecs.hpp"
12 #include "opencv2/videoio.hpp"
13 #include "opencv2/highgui.hpp"
14 #include "opencv2/video.hpp"
15
16 using namespace std;
17 using namespace cv;
18
19 static Mat getVisibleFlow(InputArray flow)
20 {
21     vector<UMat> flow_vec;
22     split(flow, flow_vec);
23     UMat magnitude, angle;
24     cartToPolar(flow_vec[0], flow_vec[1], magnitude, angle, true);
25     magnitude.convertTo(magnitude, CV_32F, 0.2);
26     vector<UMat> hsv_vec;
27     hsv_vec.push_back(angle);
28     hsv_vec.push_back(UMat::ones(angle.size(), angle.type()));
29     hsv_vec.push_back(magnitude);
30     UMat hsv;
31     merge(hsv_vec, hsv);
32     Mat img;
33     cvtColor(hsv, img, COLOR_HSV2BGR);
34     return img;
35 }
36
37 static Size fitSize(const Size & sz,  const Size & bounds)
38 {
39     CV_Assert(!sz.empty());
40     if (sz.width > bounds.width || sz.height > bounds.height)
41     {
42         double scale = std::min((double)bounds.width / sz.width, (double)bounds.height / sz.height);
43         return Size(cvRound(sz.width * scale), cvRound(sz.height * scale));
44     }
45     return sz;
46 }
47
48 int main(int argc, const char* argv[])
49 {
50     const char* keys =
51             "{ h help     |     | print help message }"
52             "{ c camera   | 0   | capture video from camera (device index starting from 0) }"
53             "{ a algorithm | fb | algorithm (supported: 'fb', 'dis')}"
54             "{ m cpu      |     | run without OpenCL }"
55             "{ v video    |     | use video as input }"
56             "{ o original |     | use original frame size (do not resize to 640x480)}"
57             ;
58     CommandLineParser parser(argc, argv, keys);
59     parser.about("This sample demonstrates using of dense optical flow algorithms.");
60     if (parser.has("help"))
61     {
62         parser.printMessage();
63         return 0;
64     }
65     int camera = parser.get<int>("camera");
66     string algorithm = parser.get<string>("algorithm");
67     bool useCPU = parser.has("cpu");
68     string filename = parser.get<string>("video");
69     bool useOriginalSize = parser.has("original");
70     if (!parser.check())
71     {
72         parser.printErrors();
73         return 1;
74     }
75
76     VideoCapture cap;
77     if(filename.empty())
78         cap.open(camera);
79     else
80         cap.open(filename);
81     if (!cap.isOpened())
82     {
83         cout << "Can not open video stream: '" << (filename.empty() ? "<camera>" : filename) << "'" << endl;
84         return 2;
85     }
86
87     Ptr<DenseOpticalFlow> alg;
88     if (algorithm == "fb")
89         alg = FarnebackOpticalFlow::create();
90     else if (algorithm == "dis")
91         alg = DISOpticalFlow::create(DISOpticalFlow::PRESET_FAST);
92     else
93     {
94         cout << "Invalid algorithm: " << algorithm << endl;
95         return 3;
96     }
97
98     ocl::setUseOpenCL(!useCPU);
99
100     cout << "Press 'm' to toggle CPU/GPU processing mode" << endl;
101     cout << "Press ESC or 'q' to exit" << endl;
102
103     UMat prevFrame, frame, input_frame, flow;
104     for(;;)
105     {
106         if (!cap.read(input_frame) || input_frame.empty())
107         {
108             cout << "Finished reading: empty frame" << endl;
109             break;
110         }
111         Size small_size = fitSize(input_frame.size(), Size(640, 480));
112         if (!useOriginalSize && small_size != input_frame.size())
113             resize(input_frame, frame, small_size);
114         else
115             frame = input_frame;
116         cvtColor(frame, frame, COLOR_BGR2GRAY);
117         imshow("frame", frame);
118         if (!prevFrame.empty())
119         {
120             int64 t = getTickCount();
121             alg->calc(prevFrame, frame, flow);
122             t = getTickCount() - t;
123             {
124                 Mat img = getVisibleFlow(flow);
125                 ostringstream buf;
126                 buf << "Algo: " << algorithm << " | "
127                     << "Mode: " << (useCPU ? "CPU" : "GPU") << " | "
128                     << "FPS: " << fixed << setprecision(1) << (getTickFrequency() / (double)t);
129                 putText(img, buf.str(), Point(10, 30), FONT_HERSHEY_PLAIN, 2.0, Scalar(0, 0, 255), 2, LINE_AA);
130                 imshow("Dense optical flow field", img);
131             }
132         }
133         frame.copyTo(prevFrame);
134
135         // interact with user
136         const char key = (char)waitKey(30);
137         if (key == 27 || key == 'q') // ESC
138         {
139             cout << "Exit requested" << endl;
140             break;
141         }
142         else if (key == 'm')
143         {
144             useCPU = !useCPU;
145             ocl::setUseOpenCL(!useCPU);
146             cout << "Set processing mode to: " << (useCPU ? "CPU" : "GPU") << endl;
147         }
148     }
149
150     return 0;
151 }