1#include <iostream>
2#include <vector>
3#include <iomanip>
4
5#include "opencv2/core/ocl.hpp"
6#include "opencv2/core/utility.hpp"
7#include "opencv2/imgcodecs.hpp"
8#include "opencv2/videoio.hpp"
9#include "opencv2/highgui/highgui.hpp"
10#include "opencv2/video/video.hpp"
11
12using namespace std;
13using namespace cv;
14
15typedef unsigned char uchar;
16#define LOOP_NUM 10
17int64 work_begin = 0;
18int64 work_end = 0;
19
20static void workBegin()
21{
22    work_begin = getTickCount();
23}
24static void workEnd()
25{
26    work_end += (getTickCount() - work_begin);
27}
28static double getTime()
29{
30    return work_end * 1000. / getTickFrequency();
31}
32
33template <typename T> inline T clamp (T x, T a, T b)
34{
35    return ((x) > (a) ? ((x) < (b) ? (x) : (b)) : (a));
36}
37
38template <typename T> inline T mapValue(T x, T a, T b, T c, T d)
39{
40    x = clamp(x, a, b);
41    return c + (d - c) * (x - a) / (b - a);
42}
43
44static void getFlowField(const Mat& u, const Mat& v, Mat& flowField)
45{
46    float maxDisplacement = 1.0f;
47
48    for (int i = 0; i < u.rows; ++i)
49    {
50        const float* ptr_u = u.ptr<float>(i);
51        const float* ptr_v = v.ptr<float>(i);
52
53        for (int j = 0; j < u.cols; ++j)
54        {
55            float d = max(fabsf(ptr_u[j]), fabsf(ptr_v[j]));
56
57            if (d > maxDisplacement)
58                maxDisplacement = d;
59        }
60    }
61
62    flowField.create(u.size(), CV_8UC4);
63
64    for (int i = 0; i < flowField.rows; ++i)
65    {
66        const float* ptr_u = u.ptr<float>(i);
67        const float* ptr_v = v.ptr<float>(i);
68
69
70        Vec4b* row = flowField.ptr<Vec4b>(i);
71
72        for (int j = 0; j < flowField.cols; ++j)
73        {
74            row[j][0] = 0;
75            row[j][1] = static_cast<unsigned char> (mapValue (-ptr_v[j], -maxDisplacement, maxDisplacement, 0.0f, 255.0f));
76            row[j][2] = static_cast<unsigned char> (mapValue ( ptr_u[j], -maxDisplacement, maxDisplacement, 0.0f, 255.0f));
77            row[j][3] = 255;
78        }
79    }
80}
81
82
83int main(int argc, const char* argv[])
84{
85    const char* keys =
86        "{ h help     | false           | print help message }"
87        "{ l left     |                 | specify left image }"
88        "{ r right    |                 | specify right image }"
89        "{ o output   | tvl1_output.jpg | specify output save path }"
90        "{ c camera   | 0               | enable camera capturing }"
91        "{ m cpu_mode | false           | run without OpenCL }"
92        "{ v video    |                 | use video as input }";
93
94    CommandLineParser cmd(argc, argv, keys);
95
96    if (cmd.has("help"))
97    {
98        cout << "Usage: pyrlk_optical_flow [options]" << endl;
99        cout << "Available options:" << endl;
100        cmd.printMessage();
101        return EXIT_SUCCESS;
102    }
103
104    string fname0 = cmd.get<string>("l");
105    string fname1 = cmd.get<string>("r");
106    string vdofile = cmd.get<string>("v");
107    string outpath = cmd.get<string>("o");
108    bool useCPU = cmd.get<bool>("s");
109    bool useCamera = cmd.get<bool>("c");
110    int inputName = cmd.get<int>("c");
111
112    UMat frame0, frame1;
113    imread(fname0, cv::IMREAD_GRAYSCALE).copyTo(frame0);
114    imread(fname1, cv::IMREAD_GRAYSCALE).copyTo(frame1);
115    cv::Ptr<cv::DenseOpticalFlow> alg = cv::createOptFlow_DualTVL1();
116
117    UMat flow;
118    Mat show_flow;
119    vector<UMat> flow_vec;
120    if (frame0.empty() || frame1.empty())
121        useCamera = true;
122
123    if (useCamera)
124    {
125        VideoCapture capture;
126        UMat frame, frameCopy;
127        UMat frame0Gray, frame1Gray;
128        UMat ptr0, ptr1;
129
130        if(vdofile.empty())
131            capture.open( inputName );
132        else
133            capture.open(vdofile.c_str());
134
135        if(!capture.isOpened())
136        {
137            if(vdofile.empty())
138                cout << "Capture from CAM " << inputName << " didn't work" << endl;
139            else
140                cout << "Capture from file " << vdofile << " failed" <<endl;
141            goto nocamera;
142        }
143
144        cout << "In capture ..." << endl;
145        for(int i = 0;; i++)
146        {
147            if( !capture.read(frame) )
148                break;
149
150            if (i == 0)
151            {
152                frame.copyTo( frame0 );
153                cvtColor(frame0, frame0Gray, COLOR_BGR2GRAY);
154            }
155            else
156            {
157                if (i%2 == 1)
158                {
159                    frame.copyTo(frame1);
160                    cvtColor(frame1, frame1Gray, COLOR_BGR2GRAY);
161                    ptr0 = frame0Gray;
162                    ptr1 = frame1Gray;
163                }
164                else
165                {
166                    frame.copyTo(frame0);
167                    cvtColor(frame0, frame0Gray, COLOR_BGR2GRAY);
168                    ptr0 = frame1Gray;
169                    ptr1 = frame0Gray;
170                }
171
172                alg->calc(ptr0, ptr1, flow);
173                split(flow, flow_vec);
174
175                if (i%2 == 1)
176                    frame1.copyTo(frameCopy);
177                else
178                    frame0.copyTo(frameCopy);
179                getFlowField(flow_vec[0].getMat(ACCESS_READ), flow_vec[1].getMat(ACCESS_READ), show_flow);
180                imshow("tvl1 optical flow field", show_flow);
181            }
182
183            char key = (char)waitKey(10);
184            if (key == 27)
185                break;
186            else if (key == 'm' || key == 'M')
187            {
188                ocl::setUseOpenCL(!cv::ocl::useOpenCL());
189                cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL" : "CPU") << " mode\n";
190            }
191        }
192
193        capture.release();
194    }
195    else
196    {
197nocamera:
198        if (cmd.has("cpu_mode"))
199        {
200            ocl::setUseOpenCL(false);
201            std::cout << "OpenCL was disabled" << std::endl;
202        }
203        for(int i = 0; i <= LOOP_NUM; i ++)
204        {
205            cout << "loop" << i << endl;
206
207            if (i > 0) workBegin();
208
209            alg->calc(frame0, frame1, flow);
210            split(flow, flow_vec);
211
212            if (i > 0 && i <= LOOP_NUM)
213                workEnd();
214
215            if (i == LOOP_NUM)
216            {
217                if (useCPU)
218                    cout << "average CPU time (noCamera) : ";
219                else
220                    cout << "average GPU time (noCamera) : ";
221                cout << getTime() / LOOP_NUM << " ms" << endl;
222
223                getFlowField(flow_vec[0].getMat(ACCESS_READ), flow_vec[1].getMat(ACCESS_READ), show_flow);
224                imshow("PyrLK [Sparse]", show_flow);
225                imwrite(outpath, show_flow);
226            }
227        }
228    }
229
230    waitKey();
231
232    return EXIT_SUCCESS;
233}
234