2
2
#include < vector>
3
3
4
4
#include " opencv2/core.hpp"
5
- #include < opencv2/core/utility.hpp>
5
+ #include " opencv2/core/utility.hpp"
6
6
#include " opencv2/imgproc.hpp"
7
7
#include " opencv2/highgui.hpp"
8
8
#include " opencv2/video.hpp"
9
9
#include " opencv2/cudaoptflow.hpp"
10
10
#include " opencv2/cudaimgproc.hpp"
11
+ #include " opencv2/cudaarithm.hpp"
11
12
12
13
using namespace std ;
13
14
using namespace cv ;
@@ -66,6 +67,132 @@ static void drawArrows(Mat& frame, const vector<Point2f>& prevPts, const vector<
66
67
}
67
68
}
68
69
70
+ inline bool isFlowCorrect (Point2f u)
71
+ {
72
+ return !cvIsNaN (u.x ) && !cvIsNaN (u.y ) && fabs (u.x ) < 1e9 && fabs (u.y ) < 1e9 ;
73
+ }
74
+
75
+ static Vec3b computeColor (float fx, float fy)
76
+ {
77
+ static bool first = true ;
78
+
79
+ // relative lengths of color transitions:
80
+ // these are chosen based on perceptual similarity
81
+ // (e.g. one can distinguish more shades between red and yellow
82
+ // than between yellow and green)
83
+ const int RY = 15 ;
84
+ const int YG = 6 ;
85
+ const int GC = 4 ;
86
+ const int CB = 11 ;
87
+ const int BM = 13 ;
88
+ const int MR = 6 ;
89
+ const int NCOLS = RY + YG + GC + CB + BM + MR;
90
+ static Vec3i colorWheel[NCOLS];
91
+
92
+ if (first)
93
+ {
94
+ int k = 0 ;
95
+
96
+ for (int i = 0 ; i < RY; ++i, ++k)
97
+ colorWheel[k] = Vec3i (255 , 255 * i / RY, 0 );
98
+
99
+ for (int i = 0 ; i < YG; ++i, ++k)
100
+ colorWheel[k] = Vec3i (255 - 255 * i / YG, 255 , 0 );
101
+
102
+ for (int i = 0 ; i < GC; ++i, ++k)
103
+ colorWheel[k] = Vec3i (0 , 255 , 255 * i / GC);
104
+
105
+ for (int i = 0 ; i < CB; ++i, ++k)
106
+ colorWheel[k] = Vec3i (0 , 255 - 255 * i / CB, 255 );
107
+
108
+ for (int i = 0 ; i < BM; ++i, ++k)
109
+ colorWheel[k] = Vec3i (255 * i / BM, 0 , 255 );
110
+
111
+ for (int i = 0 ; i < MR; ++i, ++k)
112
+ colorWheel[k] = Vec3i (255 , 0 , 255 - 255 * i / MR);
113
+
114
+ first = false ;
115
+ }
116
+
117
+ const float rad = sqrt (fx * fx + fy * fy);
118
+ const float a = atan2 (-fy, -fx) / (float )CV_PI;
119
+
120
+ const float fk = (a + 1 .0f ) / 2 .0f * (NCOLS - 1 );
121
+ const int k0 = static_cast <int >(fk);
122
+ const int k1 = (k0 + 1 ) % NCOLS;
123
+ const float f = fk - k0;
124
+
125
+ Vec3b pix;
126
+
127
+ for (int b = 0 ; b < 3 ; b++)
128
+ {
129
+ const float col0 = colorWheel[k0][b] / 255 .0f ;
130
+ const float col1 = colorWheel[k1][b] / 255 .0f ;
131
+
132
+ float col = (1 - f) * col0 + f * col1;
133
+
134
+ if (rad <= 1 )
135
+ col = 1 - rad * (1 - col); // increase saturation with radius
136
+ else
137
+ col *= .75 ; // out of range
138
+
139
+ pix[2 - b] = static_cast <uchar>(255.0 * col);
140
+ }
141
+
142
+ return pix;
143
+ }
144
+
145
+ static void drawOpticalFlow (const Mat_<float >& flowx, const Mat_<float >& flowy, Mat& dst, float maxmotion = -1 )
146
+ {
147
+ dst.create (flowx.size (), CV_8UC3);
148
+ dst.setTo (Scalar::all (0 ));
149
+
150
+ // determine motion range:
151
+ float maxrad = maxmotion;
152
+
153
+ if (maxmotion <= 0 )
154
+ {
155
+ maxrad = 1 ;
156
+ for (int y = 0 ; y < flowx.rows ; ++y)
157
+ {
158
+ for (int x = 0 ; x < flowx.cols ; ++x)
159
+ {
160
+ Point2f u (flowx (y, x), flowy (y, x));
161
+
162
+ if (!isFlowCorrect (u))
163
+ continue ;
164
+
165
+ maxrad = max (maxrad, sqrt (u.x * u.x + u.y * u.y ));
166
+ }
167
+ }
168
+ }
169
+
170
+ for (int y = 0 ; y < flowx.rows ; ++y)
171
+ {
172
+ for (int x = 0 ; x < flowx.cols ; ++x)
173
+ {
174
+ Point2f u (flowx (y, x), flowy (y, x));
175
+
176
+ if (isFlowCorrect (u))
177
+ dst.at <Vec3b>(y, x) = computeColor (u.x / maxrad, u.y / maxrad);
178
+ }
179
+ }
180
+ }
181
+
182
+ static void showFlow (const char * name, const GpuMat& d_flow)
183
+ {
184
+ GpuMat planes[2 ];
185
+ cuda::split (d_flow, planes);
186
+
187
+ Mat flowx (planes[0 ]);
188
+ Mat flowy (planes[1 ]);
189
+
190
+ Mat out;
191
+ drawOpticalFlow (flowx, flowy, out, 10 );
192
+
193
+ imshow (name, out);
194
+ }
195
+
69
196
template <typename T> inline T clamp (T x, T a, T b)
70
197
{
71
198
return ((x) > (a) ? ((x) < (b) ? (x) : (b)) : (a));
@@ -148,7 +275,7 @@ int main(int argc, const char* argv[])
148
275
149
276
// Sparse
150
277
151
- Ptr<cuda::SparsePyrLKOpticalFlow> d_pyrLK = cuda::SparsePyrLKOpticalFlow::create (
278
+ Ptr<cuda::SparsePyrLKOpticalFlow> d_pyrLK_sparse = cuda::SparsePyrLKOpticalFlow::create (
152
279
Size (winSize, winSize), maxLevel, iters);
153
280
154
281
GpuMat d_frame0 (frame0);
@@ -157,7 +284,16 @@ int main(int argc, const char* argv[])
157
284
GpuMat d_nextPts;
158
285
GpuMat d_status;
159
286
160
- d_pyrLK->calc (useGray ? d_frame0Gray : d_frame0, useGray ? d_frame1Gray : d_frame1, d_prevPts, d_nextPts, d_status);
287
+ d_pyrLK_sparse->calc (useGray ? d_frame0Gray : d_frame0, useGray ? d_frame1Gray : d_frame1, d_prevPts, d_nextPts, d_status);
288
+
289
+ // Dense
290
+
291
+ Ptr<cuda::DensePyrLKOpticalFlow> d_pyrLK_dense = cuda::DensePyrLKOpticalFlow::create (
292
+ Size (winSize, winSize), maxLevel, iters);
293
+
294
+ GpuMat d_flow (frame0.size (), CV_32FC2);
295
+
296
+ d_pyrLK_dense->calc (d_frame0Gray, d_frame1Gray, d_flow);
161
297
162
298
// Draw arrows
163
299
@@ -171,9 +307,12 @@ int main(int argc, const char* argv[])
171
307
download (d_status, status);
172
308
173
309
drawArrows (frame0, prevPts, nextPts, status, Scalar (255 , 0 , 0 ));
174
-
175
310
imshow (" PyrLK [Sparse]" , frame0);
176
311
312
+ // Draw flows
313
+
314
+ showFlow (" PyrLK [Dense] Flow Field" , d_flow);
315
+
177
316
waitKey ();
178
317
179
318
return 0 ;
0 commit comments