Fixed calc_output_scale with NO_OUTPUT_SCALE flag set.
[profile/ivi/opencv.git] / samples / gpu / opticalflow_nvidia_api.cpp
1 #if defined _MSC_VER && _MSC_VER >= 1400
2 #pragma warning( disable : 4201 4408 4127 4100)
3 #endif
4
5 #include <iostream>
6 #include <iomanip>
7 #include <memory>
8 #include <exception>
9 #include <ctime>
10 #include <ctype.h>
11
12 #include "cvconfig.h"
13 #include <iostream>
14 #include <iomanip>
15 #include "opencv2/core/cuda.hpp"
16 #include "opencv2/cudalegacy.hpp"
17 #include "opencv2/highgui/highgui.hpp"
18 #include "opencv2/highgui/highgui_c.h"
19
20 #if !defined(HAVE_CUDA)
21 int main( int, const char** )
22 {
23     std::cout << "Please compile the library with CUDA support" << std::endl;
24     return -1;
25 }
26 #else
27
28 //using std::tr1::shared_ptr;
29 using cv::Ptr;
30
31 #define PARAM_LEFT  "--left"
32 #define PARAM_RIGHT "--right"
33 #define PARAM_SCALE "--scale"
34 #define PARAM_ALPHA "--alpha"
35 #define PARAM_GAMMA "--gamma"
36 #define PARAM_INNER "--inner"
37 #define PARAM_OUTER "--outer"
38 #define PARAM_SOLVER "--solver"
39 #define PARAM_TIME_STEP "--time-step"
40 #define PARAM_HELP "--help"
41
42 Ptr<INCVMemAllocator> g_pGPUMemAllocator;
43 Ptr<INCVMemAllocator> g_pHostMemAllocator;
44
45 class RgbToMonochrome
46 {
47 public:
48     float operator ()(unsigned char b, unsigned char g, unsigned char r)
49     {
50         float _r = static_cast<float>(r)/255.0f;
51         float _g = static_cast<float>(g)/255.0f;
52         float _b = static_cast<float>(b)/255.0f;
53         return (_r + _g + _b)/3.0f;
54     }
55 };
56
57 class RgbToR
58 {
59 public:
60     float operator ()(unsigned char /*b*/, unsigned char /*g*/, unsigned char r)
61     {
62         return static_cast<float>(r)/255.0f;
63     }
64 };
65
66
67 class RgbToG
68 {
69 public:
70     float operator ()(unsigned char /*b*/, unsigned char g, unsigned char /*r*/)
71     {
72         return static_cast<float>(g)/255.0f;
73     }
74 };
75
76 class RgbToB
77 {
78 public:
79     float operator ()(unsigned char b, unsigned char /*g*/, unsigned char /*r*/)
80     {
81         return static_cast<float>(b)/255.0f;
82     }
83 };
84
85 template<class T>
86 NCVStatus CopyData(IplImage *image, Ptr<NCVMatrixAlloc<Ncv32f> >& dst)
87 {
88     dst = Ptr<NCVMatrixAlloc<Ncv32f> > (new NCVMatrixAlloc<Ncv32f> (*g_pHostMemAllocator, image->width, image->height));
89     ncvAssertReturn (dst->isMemAllocated (), NCV_ALLOCATOR_BAD_ALLOC);
90
91     unsigned char *row = reinterpret_cast<unsigned char*> (image->imageData);
92     T convert;
93     for (int i = 0; i < image->height; ++i)
94     {
95         for (int j = 0; j < image->width; ++j)
96         {
97             if (image->nChannels < 3)
98             {
99                 dst->ptr ()[j + i*dst->stride ()] = static_cast<float> (*(row + j*image->nChannels))/255.0f;
100             }
101             else
102             {
103                 unsigned char *color = row + j * image->nChannels;
104                 dst->ptr ()[j +i*dst->stride ()] = convert (color[0], color[1], color[2]);
105             }
106         }
107         row += image->widthStep;
108     }
109     return NCV_SUCCESS;
110 }
111
112 template<class T>
113 NCVStatus CopyData(const IplImage *image, const NCVMatrixAlloc<Ncv32f> &dst)
114 {
115     unsigned char *row = reinterpret_cast<unsigned char*> (image->imageData);
116     T convert;
117     for (int i = 0; i < image->height; ++i)
118     {
119         for (int j = 0; j < image->width; ++j)
120         {
121             if (image->nChannels < 3)
122             {
123                 dst.ptr ()[j + i*dst.stride ()] = static_cast<float>(*(row + j*image->nChannels))/255.0f;
124             }
125             else
126             {
127                 unsigned char *color = row + j * image->nChannels;
128                 dst.ptr ()[j +i*dst.stride()] = convert (color[0], color[1], color[2]);
129             }
130         }
131         row += image->widthStep;
132     }
133     return NCV_SUCCESS;
134 }
135
136 static NCVStatus LoadImages (const char *frame0Name,
137                       const char *frame1Name,
138                       int &width,
139                       int &height,
140                       Ptr<NCVMatrixAlloc<Ncv32f> > &src,
141                       Ptr<NCVMatrixAlloc<Ncv32f> > &dst,
142                       IplImage *&firstFrame,
143                       IplImage *&lastFrame)
144 {
145     IplImage *image;
146     image = cvLoadImage (frame0Name);
147     if (image == 0)
148     {
149         std::cout << "Could not open '" << frame0Name << "'\n";
150         return NCV_FILE_ERROR;
151     }
152
153     firstFrame = image;
154     // copy data to src
155     ncvAssertReturnNcvStat (CopyData<RgbToMonochrome> (image, src));
156
157     IplImage *image2;
158     image2 = cvLoadImage (frame1Name);
159     if (image2 == 0)
160     {
161         std::cout << "Could not open '" << frame1Name << "'\n";
162         return NCV_FILE_ERROR;
163     }
164     lastFrame = image2;
165
166     ncvAssertReturnNcvStat (CopyData<RgbToMonochrome> (image2, dst));
167
168     width  = image->width;
169     height = image->height;
170
171     return NCV_SUCCESS;
172 }
173
174 template<typename T>
175 inline T Clamp (T x, T a, T b)
176 {
177     return ((x) > (a) ? ((x) < (b) ? (x) : (b)) : (a));
178 }
179
180 template<typename T>
181 inline T MapValue (T x, T a, T b, T c, T d)
182 {
183     x = Clamp (x, a, b);
184     return c + (d - c) * (x - a) / (b - a);
185 }
186
187 static NCVStatus ShowFlow (NCVMatrixAlloc<Ncv32f> &u, NCVMatrixAlloc<Ncv32f> &v, const char *name)
188 {
189     IplImage *flowField;
190
191     NCVMatrixAlloc<Ncv32f> host_u(*g_pHostMemAllocator, u.width(), u.height());
192     ncvAssertReturn(host_u.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC);
193
194     NCVMatrixAlloc<Ncv32f> host_v (*g_pHostMemAllocator, u.width (), u.height ());
195     ncvAssertReturn (host_v.isMemAllocated (), NCV_ALLOCATOR_BAD_ALLOC);
196
197     ncvAssertReturnNcvStat (u.copySolid (host_u, 0));
198     ncvAssertReturnNcvStat (v.copySolid (host_v, 0));
199
200     float *ptr_u = host_u.ptr ();
201     float *ptr_v = host_v.ptr ();
202
203     float maxDisplacement = 1.0f;
204
205     for (Ncv32u i = 0; i < u.height (); ++i)
206     {
207         for (Ncv32u j = 0; j < u.width (); ++j)
208         {
209             float d = std::max ( fabsf(*ptr_u), fabsf(*ptr_v) );
210             if (d > maxDisplacement) maxDisplacement = d;
211             ++ptr_u;
212             ++ptr_v;
213         }
214         ptr_u += u.stride () - u.width ();
215         ptr_v += v.stride () - v.width ();
216     }
217
218     CvSize image_size = cvSize (u.width (), u.height ());
219     flowField = cvCreateImage (image_size, IPL_DEPTH_8U, 4);
220     if (flowField == 0) return NCV_NULL_PTR;
221
222     unsigned char *row = reinterpret_cast<unsigned char *> (flowField->imageData);
223
224     ptr_u = host_u.ptr();
225     ptr_v = host_v.ptr();
226     for (int i = 0; i < flowField->height; ++i)
227     {
228         for (int j = 0; j < flowField->width; ++j)
229         {
230             (row + j * flowField->nChannels)[0] = 0;
231             (row + j * flowField->nChannels)[1] = static_cast<unsigned char> (MapValue (-(*ptr_v), -maxDisplacement, maxDisplacement, 0.0f, 255.0f));
232             (row + j * flowField->nChannels)[2] = static_cast<unsigned char> (MapValue (*ptr_u   , -maxDisplacement, maxDisplacement, 0.0f, 255.0f));
233             (row + j * flowField->nChannels)[3] = 255;
234             ++ptr_u;
235             ++ptr_v;
236         }
237         row += flowField->widthStep;
238         ptr_u += u.stride () - u.width ();
239         ptr_v += v.stride () - v.width ();
240     }
241
242     cvShowImage (name, flowField);
243
244     return NCV_SUCCESS;
245 }
246
247 static IplImage *CreateImage (NCVMatrixAlloc<Ncv32f> &h_r, NCVMatrixAlloc<Ncv32f> &h_g, NCVMatrixAlloc<Ncv32f> &h_b)
248 {
249     CvSize imageSize = cvSize (h_r.width (), h_r.height ());
250     IplImage *image  = cvCreateImage (imageSize, IPL_DEPTH_8U, 4);
251     if (image == 0) return 0;
252
253     unsigned char *row = reinterpret_cast<unsigned char*> (image->imageData);
254
255     for (int i = 0; i < image->height; ++i)
256     {
257         for (int j = 0; j < image->width; ++j)
258         {
259             int offset = j * image->nChannels;
260             int pos    = i * h_r.stride () + j;
261             row[offset + 0] = static_cast<unsigned char> (h_b.ptr ()[pos] * 255.0f);
262             row[offset + 1] = static_cast<unsigned char> (h_g.ptr ()[pos] * 255.0f);
263             row[offset + 2] = static_cast<unsigned char> (h_r.ptr ()[pos] * 255.0f);
264             row[offset + 3] = 255;
265         }
266         row += image->widthStep;
267     }
268     return image;
269 }
270
271 static void PrintHelp ()
272 {
273     std::cout << "Usage help:\n";
274     std::cout << std::setiosflags(std::ios::left);
275     std::cout << "\t" << std::setw(15) << PARAM_ALPHA << " - set alpha\n";
276     std::cout << "\t" << std::setw(15) << PARAM_GAMMA << " - set gamma\n";
277     std::cout << "\t" << std::setw(15) << PARAM_INNER << " - set number of inner iterations\n";
278     std::cout << "\t" << std::setw(15) << PARAM_LEFT << " - specify left image\n";
279     std::cout << "\t" << std::setw(15) << PARAM_RIGHT << " - specify right image\n";
280     std::cout << "\t" << std::setw(15) << PARAM_OUTER << " - set number of outer iterations\n";
281     std::cout << "\t" << std::setw(15) << PARAM_SCALE << " - set pyramid scale factor\n";
282     std::cout << "\t" << std::setw(15) << PARAM_SOLVER << " - set number of basic solver iterations\n";
283     std::cout << "\t" << std::setw(15) << PARAM_TIME_STEP << " - set frame interpolation time step\n";
284     std::cout << "\t" << std::setw(15) << PARAM_HELP << " - display this help message\n";
285 }
286
287 static int ProcessCommandLine(int argc, char **argv,
288                        Ncv32f &timeStep,
289                        char *&frame0Name,
290                        char *&frame1Name,
291                        NCVBroxOpticalFlowDescriptor &desc)
292 {
293     timeStep = 0.25f;
294     for (int iarg = 1; iarg < argc; ++iarg)
295     {
296         if (strcmp(argv[iarg], PARAM_LEFT) == 0)
297         {
298             if (iarg + 1 < argc)
299             {
300                 frame0Name = argv[++iarg];
301             }
302             else
303                 return -1;
304         }
305         if (strcmp(argv[iarg], PARAM_RIGHT) == 0)
306         {
307             if (iarg + 1 < argc)
308             {
309                 frame1Name = argv[++iarg];
310             }
311             else
312                 return -1;
313         }
314         else if(strcmp(argv[iarg], PARAM_SCALE) == 0)
315         {
316             if (iarg + 1 < argc)
317                 desc.scale_factor = static_cast<Ncv32f>(atof(argv[++iarg]));
318             else
319                 return -1;
320         }
321         else if(strcmp(argv[iarg], PARAM_ALPHA) == 0)
322         {
323             if (iarg + 1 < argc)
324                 desc.alpha = static_cast<Ncv32f>(atof(argv[++iarg]));
325             else
326                 return -1;
327         }
328         else if(strcmp(argv[iarg], PARAM_GAMMA) == 0)
329         {
330             if (iarg + 1 < argc)
331                 desc.gamma = static_cast<Ncv32f>(atof(argv[++iarg]));
332             else
333                 return -1;
334         }
335         else if(strcmp(argv[iarg], PARAM_INNER) == 0)
336         {
337             if (iarg + 1 < argc)
338                 desc.number_of_inner_iterations = static_cast<Ncv32u>(atoi(argv[++iarg]));
339             else
340                 return -1;
341         }
342         else if(strcmp(argv[iarg], PARAM_OUTER) == 0)
343         {
344             if (iarg + 1 < argc)
345                 desc.number_of_outer_iterations = static_cast<Ncv32u>(atoi(argv[++iarg]));
346             else
347                 return -1;
348         }
349         else if(strcmp(argv[iarg], PARAM_SOLVER) == 0)
350         {
351             if (iarg + 1 < argc)
352                 desc.number_of_solver_iterations = static_cast<Ncv32u>(atoi(argv[++iarg]));
353             else
354                 return -1;
355         }
356         else if(strcmp(argv[iarg], PARAM_TIME_STEP) == 0)
357         {
358             if (iarg + 1 < argc)
359                 timeStep = static_cast<Ncv32f>(atof(argv[++iarg]));
360             else
361                 return -1;
362         }
363         else if(strcmp(argv[iarg], PARAM_HELP) == 0)
364         {
365             PrintHelp ();
366             return 0;
367         }
368     }
369     return 0;
370 }
371
372
373 int main(int argc, char **argv)
374 {
375     char *frame0Name = 0, *frame1Name = 0;
376     Ncv32f timeStep = 0.01f;
377
378     NCVBroxOpticalFlowDescriptor desc;
379
380     desc.alpha = 0.197f;
381     desc.gamma = 50.0f;
382     desc.number_of_inner_iterations  = 10;
383     desc.number_of_outer_iterations  = 77;
384     desc.number_of_solver_iterations = 10;
385     desc.scale_factor = 0.8f;
386
387     int result = ProcessCommandLine (argc, argv, timeStep, frame0Name, frame1Name, desc);
388     if (argc == 1 || result)
389     {
390         PrintHelp();
391         return result;
392     }
393
394     cv::cuda::printShortCudaDeviceInfo(cv::cuda::getDevice());
395
396     std::cout << "OpenCV / NVIDIA Computer Vision\n";
397     std::cout << "Optical Flow Demo: Frame Interpolation\n";
398     std::cout << "=========================================\n";
399     std::cout << "Press:\n ESC to quit\n 'a' to move to the previous frame\n 's' to move to the next frame\n";
400
401     int devId;
402     ncvAssertCUDAReturn(cudaGetDevice(&devId), -1);
403     cudaDeviceProp devProp;
404     ncvAssertCUDAReturn(cudaGetDeviceProperties(&devProp, devId), -1);
405     std::cout << "Using GPU: " << devId << "(" << devProp.name <<
406         "), arch=" << devProp.major << "." << devProp.minor << std::endl;
407
408     g_pGPUMemAllocator  = Ptr<INCVMemAllocator> (new NCVMemNativeAllocator (NCVMemoryTypeDevice, static_cast<Ncv32u>(devProp.textureAlignment)));
409     ncvAssertPrintReturn (g_pGPUMemAllocator->isInitialized (), "Device memory allocator isn't initialized", -1);
410
411     g_pHostMemAllocator = Ptr<INCVMemAllocator> (new NCVMemNativeAllocator (NCVMemoryTypeHostPageable, static_cast<Ncv32u>(devProp.textureAlignment)));
412     ncvAssertPrintReturn (g_pHostMemAllocator->isInitialized (), "Host memory allocator isn't initialized", -1);
413
414     int width, height;
415
416     Ptr<NCVMatrixAlloc<Ncv32f> > src_host;
417     Ptr<NCVMatrixAlloc<Ncv32f> > dst_host;
418
419     IplImage *firstFrame, *lastFrame;
420     if (frame0Name != 0 && frame1Name != 0)
421     {
422         ncvAssertReturnNcvStat (LoadImages (frame0Name, frame1Name, width, height, src_host, dst_host, firstFrame, lastFrame));
423     }
424     else
425     {
426         ncvAssertReturnNcvStat (LoadImages ("frame10.bmp", "frame11.bmp", width, height, src_host, dst_host, firstFrame, lastFrame));
427     }
428
429     Ptr<NCVMatrixAlloc<Ncv32f> > src (new NCVMatrixAlloc<Ncv32f> (*g_pGPUMemAllocator, src_host->width (), src_host->height ()));
430     ncvAssertReturn(src->isMemAllocated(), -1);
431
432     Ptr<NCVMatrixAlloc<Ncv32f> > dst (new NCVMatrixAlloc<Ncv32f> (*g_pGPUMemAllocator, src_host->width (), src_host->height ()));
433     ncvAssertReturn (dst->isMemAllocated (), -1);
434
435     ncvAssertReturnNcvStat (src_host->copySolid ( *src, 0 ));
436     ncvAssertReturnNcvStat (dst_host->copySolid ( *dst, 0 ));
437
438 #if defined SAFE_MAT_DECL
439 #undef SAFE_MAT_DECL
440 #endif
441 #define SAFE_MAT_DECL(name, allocator, sx, sy) \
442     NCVMatrixAlloc<Ncv32f> name(*allocator, sx, sy);\
443     ncvAssertReturn(name.isMemAllocated(), -1);
444
445     SAFE_MAT_DECL (u, g_pGPUMemAllocator, width, height);
446     SAFE_MAT_DECL (v, g_pGPUMemAllocator, width, height);
447
448     SAFE_MAT_DECL (uBck, g_pGPUMemAllocator, width, height);
449     SAFE_MAT_DECL (vBck, g_pGPUMemAllocator, width, height);
450
451     SAFE_MAT_DECL (h_r, g_pHostMemAllocator, width, height);
452     SAFE_MAT_DECL (h_g, g_pHostMemAllocator, width, height);
453     SAFE_MAT_DECL (h_b, g_pHostMemAllocator, width, height);
454
455     std::cout << "Estimating optical flow\nForward...\n";
456
457     if (NCV_SUCCESS != NCVBroxOpticalFlow (desc, *g_pGPUMemAllocator, *src, *dst, u, v, 0))
458     {
459         std::cout << "Failed\n";
460         return -1;
461     }
462
463     std::cout << "Backward...\n";
464     if (NCV_SUCCESS != NCVBroxOpticalFlow (desc, *g_pGPUMemAllocator, *dst, *src, uBck, vBck, 0))
465     {
466         std::cout << "Failed\n";
467         return -1;
468     }
469
470     // matrix for temporary data
471     SAFE_MAT_DECL (d_temp, g_pGPUMemAllocator, width, height);
472
473     // first frame color components (GPU memory)
474     SAFE_MAT_DECL (d_r, g_pGPUMemAllocator, width, height);
475     SAFE_MAT_DECL (d_g, g_pGPUMemAllocator, width, height);
476     SAFE_MAT_DECL (d_b, g_pGPUMemAllocator, width, height);
477
478     // second frame color components (GPU memory)
479     SAFE_MAT_DECL (d_rt, g_pGPUMemAllocator, width, height);
480     SAFE_MAT_DECL (d_gt, g_pGPUMemAllocator, width, height);
481     SAFE_MAT_DECL (d_bt, g_pGPUMemAllocator, width, height);
482
483     // intermediate frame color components (GPU memory)
484     SAFE_MAT_DECL (d_rNew, g_pGPUMemAllocator, width, height);
485     SAFE_MAT_DECL (d_gNew, g_pGPUMemAllocator, width, height);
486     SAFE_MAT_DECL (d_bNew, g_pGPUMemAllocator, width, height);
487
488     // interpolated forward flow
489     SAFE_MAT_DECL (ui, g_pGPUMemAllocator, width, height);
490     SAFE_MAT_DECL (vi, g_pGPUMemAllocator, width, height);
491
492     // interpolated backward flow
493     SAFE_MAT_DECL (ubi, g_pGPUMemAllocator, width, height);
494     SAFE_MAT_DECL (vbi, g_pGPUMemAllocator, width, height);
495
496     // occlusion masks
497     SAFE_MAT_DECL (occ0, g_pGPUMemAllocator, width, height);
498     SAFE_MAT_DECL (occ1, g_pGPUMemAllocator, width, height);
499
500     // prepare color components on host and copy them to device memory
501     ncvAssertReturnNcvStat (CopyData<RgbToR> (firstFrame, h_r));
502     ncvAssertReturnNcvStat (CopyData<RgbToG> (firstFrame, h_g));
503     ncvAssertReturnNcvStat (CopyData<RgbToB> (firstFrame, h_b));
504
505     ncvAssertReturnNcvStat (h_r.copySolid ( d_r, 0 ));
506     ncvAssertReturnNcvStat (h_g.copySolid ( d_g, 0 ));
507     ncvAssertReturnNcvStat (h_b.copySolid ( d_b, 0 ));
508
509     ncvAssertReturnNcvStat (CopyData<RgbToR> (lastFrame, h_r));
510     ncvAssertReturnNcvStat (CopyData<RgbToG> (lastFrame, h_g));
511     ncvAssertReturnNcvStat (CopyData<RgbToB> (lastFrame, h_b));
512
513     ncvAssertReturnNcvStat (h_r.copySolid ( d_rt, 0 ));
514     ncvAssertReturnNcvStat (h_g.copySolid ( d_gt, 0 ));
515     ncvAssertReturnNcvStat (h_b.copySolid ( d_bt, 0 ));
516
517     std::cout << "Interpolating...\n";
518     std::cout.precision (4);
519
520     std::vector<IplImage*> frames;
521     frames.push_back (firstFrame);
522
523     // compute interpolated frames
524     for (Ncv32f timePos = timeStep; timePos < 1.0f; timePos += timeStep)
525     {
526         ncvAssertCUDAReturn (cudaMemset (ui.ptr (), 0, ui.pitch () * ui.height ()), NCV_CUDA_ERROR);
527         ncvAssertCUDAReturn (cudaMemset (vi.ptr (), 0, vi.pitch () * vi.height ()), NCV_CUDA_ERROR);
528
529         ncvAssertCUDAReturn (cudaMemset (ubi.ptr (), 0, ubi.pitch () * ubi.height ()), NCV_CUDA_ERROR);
530         ncvAssertCUDAReturn (cudaMemset (vbi.ptr (), 0, vbi.pitch () * vbi.height ()), NCV_CUDA_ERROR);
531
532         ncvAssertCUDAReturn (cudaMemset (occ0.ptr (), 0, occ0.pitch () * occ0.height ()), NCV_CUDA_ERROR);
533         ncvAssertCUDAReturn (cudaMemset (occ1.ptr (), 0, occ1.pitch () * occ1.height ()), NCV_CUDA_ERROR);
534
535         NppStInterpolationState state;
536         // interpolation state should be filled once except pSrcFrame0, pSrcFrame1, and pNewFrame
537         // we will only need to reset buffers content to 0 since interpolator doesn't do this itself
538         state.size  = NcvSize32u (width, height);
539         state.nStep = d_r.pitch ();
540         state.pSrcFrame0 = d_r.ptr ();
541         state.pSrcFrame1 = d_rt.ptr ();
542         state.pFU = u.ptr ();
543         state.pFV = v.ptr ();
544         state.pBU = uBck.ptr ();
545         state.pBV = vBck.ptr ();
546         state.pos = timePos;
547         state.pNewFrame = d_rNew.ptr ();
548         state.ppBuffers[0] = occ0.ptr ();
549         state.ppBuffers[1] = occ1.ptr ();
550         state.ppBuffers[2] = ui.ptr ();
551         state.ppBuffers[3] = vi.ptr ();
552         state.ppBuffers[4] = ubi.ptr ();
553         state.ppBuffers[5] = vbi.ptr ();
554
555         // interpolate red channel
556         nppiStInterpolateFrames (&state);
557
558         // reset buffers
559         ncvAssertCUDAReturn (cudaMemset (ui.ptr (), 0, ui.pitch () * ui.height ()), NCV_CUDA_ERROR);
560         ncvAssertCUDAReturn (cudaMemset (vi.ptr (), 0, vi.pitch () * vi.height ()), NCV_CUDA_ERROR);
561
562         ncvAssertCUDAReturn (cudaMemset (ubi.ptr (), 0, ubi.pitch () * ubi.height ()), NCV_CUDA_ERROR);
563         ncvAssertCUDAReturn (cudaMemset (vbi.ptr (), 0, vbi.pitch () * vbi.height ()), NCV_CUDA_ERROR);
564
565         ncvAssertCUDAReturn (cudaMemset (occ0.ptr (), 0, occ0.pitch () * occ0.height ()), NCV_CUDA_ERROR);
566         ncvAssertCUDAReturn (cudaMemset (occ1.ptr (), 0, occ1.pitch () * occ1.height ()), NCV_CUDA_ERROR);
567
568         // interpolate green channel
569         state.pSrcFrame0 = d_g.ptr ();
570         state.pSrcFrame1 = d_gt.ptr ();
571         state.pNewFrame  = d_gNew.ptr ();
572
573         nppiStInterpolateFrames (&state);
574
575         // reset buffers
576         ncvAssertCUDAReturn (cudaMemset (ui.ptr (), 0, ui.pitch () * ui.height ()), NCV_CUDA_ERROR);
577         ncvAssertCUDAReturn (cudaMemset (vi.ptr (), 0, vi.pitch () * vi.height ()), NCV_CUDA_ERROR);
578
579         ncvAssertCUDAReturn (cudaMemset (ubi.ptr (), 0, ubi.pitch () * ubi.height ()), NCV_CUDA_ERROR);
580         ncvAssertCUDAReturn (cudaMemset (vbi.ptr (), 0, vbi.pitch () * vbi.height ()), NCV_CUDA_ERROR);
581
582         ncvAssertCUDAReturn (cudaMemset (occ0.ptr (), 0, occ0.pitch () * occ0.height ()), NCV_CUDA_ERROR);
583         ncvAssertCUDAReturn (cudaMemset (occ1.ptr (), 0, occ1.pitch () * occ1.height ()), NCV_CUDA_ERROR);
584
585         // interpolate blue channel
586         state.pSrcFrame0 = d_b.ptr ();
587         state.pSrcFrame1 = d_bt.ptr ();
588         state.pNewFrame  = d_bNew.ptr ();
589
590         nppiStInterpolateFrames (&state);
591
592         // copy to host memory
593         ncvAssertReturnNcvStat (d_rNew.copySolid (h_r, 0));
594         ncvAssertReturnNcvStat (d_gNew.copySolid (h_g, 0));
595         ncvAssertReturnNcvStat (d_bNew.copySolid (h_b, 0));
596
597         // convert to IplImage
598         IplImage *newFrame = CreateImage (h_r, h_g, h_b);
599         if (newFrame == 0)
600         {
601             std::cout << "Could not create new frame in host memory\n";
602             break;
603         }
604         frames.push_back (newFrame);
605         std::cout << timePos * 100.0f << "%\r";
606     }
607     std::cout << std::setw (5) << "100%\n";
608
609     frames.push_back (lastFrame);
610
611     Ncv32u currentFrame;
612     currentFrame = 0;
613
614     ShowFlow (u, v, "Forward flow");
615     ShowFlow (uBck, vBck, "Backward flow");
616
617     cvShowImage ("Interpolated frame", frames[currentFrame]);
618
619     bool qPressed = false;
620     while ( !qPressed )
621     {
622         int key = toupper (cvWaitKey (10));
623         switch (key)
624         {
625         case 27:
626             qPressed = true;
627             break;
628         case 'A':
629             if (currentFrame > 0) --currentFrame;
630             cvShowImage ("Interpolated frame", frames[currentFrame]);
631             break;
632         case 'S':
633             if (currentFrame < frames.size()-1) ++currentFrame;
634             cvShowImage ("Interpolated frame", frames[currentFrame]);
635             break;
636         }
637     }
638
639     cvDestroyAllWindows ();
640
641     std::vector<IplImage*>::iterator iter;
642     for (iter = frames.begin (); iter != frames.end (); ++iter)
643     {
644         cvReleaseImage (&(*iter));
645     }
646
647     return 0;
648 }
649
650 #endif