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
12 using namespace std;
13 using namespace cv;
14
15 typedef unsigned char uchar;
16 #define LOOP_NUM 10
17 int64 work_begin = 0;
18 int64 work_end = 0;
19
workBegin()20 static void workBegin()
21 {
22 work_begin = getTickCount();
23 }
workEnd()24 static void workEnd()
25 {
26 work_end += (getTickCount() - work_begin);
27 }
getTime()28 static double getTime()
29 {
30 return work_end * 1000. / getTickFrequency();
31 }
32
clamp(T x,T a,T b)33 template <typename T> inline T clamp (T x, T a, T b)
34 {
35 return ((x) > (a) ? ((x) < (b) ? (x) : (b)) : (a));
36 }
37
mapValue(T x,T a,T b,T c,T d)38 template <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
getFlowField(const Mat & u,const Mat & v,Mat & flowField)44 static 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
main(int argc,const char * argv[])83 int 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 {
197 nocamera:
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