Path: blob/master/samples/gpu/opticalflow_nvidia_api.cpp
16337 views
#if defined _MSC_VER && _MSC_VER >= 14001#pragma warning( disable : 4201 4408 4127 4100)2#endif34#include <iostream>5#include <iomanip>6#include <memory>7#include <exception>8#include <ctime>9#include <ctype.h>1011#include <iostream>12#include <iomanip>13#include "opencv2/core/cuda.hpp"14#include "opencv2/cudalegacy.hpp"15#include "opencv2/highgui.hpp"1617#include "opencv2/core/core_c.h" // FIXIT legacy API18#include "opencv2/highgui/highgui_c.h" // FIXIT legacy API1920#if !defined(HAVE_CUDA)21int main( int, const char** )22{23std::cout << "Please compile the library with CUDA support" << std::endl;24return -1;25}26#else2728//using std::shared_ptr;29using cv::Ptr;3031#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"4142Ptr<INCVMemAllocator> g_pGPUMemAllocator;43Ptr<INCVMemAllocator> g_pHostMemAllocator;4445class RgbToMonochrome46{47public:48float operator ()(unsigned char b, unsigned char g, unsigned char r)49{50float _r = static_cast<float>(r)/255.0f;51float _g = static_cast<float>(g)/255.0f;52float _b = static_cast<float>(b)/255.0f;53return (_r + _g + _b)/3.0f;54}55};5657class RgbToR58{59public:60float operator ()(unsigned char /*b*/, unsigned char /*g*/, unsigned char r)61{62return static_cast<float>(r)/255.0f;63}64};656667class RgbToG68{69public:70float operator ()(unsigned char /*b*/, unsigned char g, unsigned char /*r*/)71{72return static_cast<float>(g)/255.0f;73}74};7576class RgbToB77{78public:79float operator ()(unsigned char b, unsigned char /*g*/, unsigned char /*r*/)80{81return static_cast<float>(b)/255.0f;82}83};8485template<class T>86NCVStatus CopyData(IplImage *image, Ptr<NCVMatrixAlloc<Ncv32f> >& dst)87{88dst = Ptr<NCVMatrixAlloc<Ncv32f> > (new NCVMatrixAlloc<Ncv32f> (*g_pHostMemAllocator, image->width, image->height));89ncvAssertReturn (dst->isMemAllocated (), NCV_ALLOCATOR_BAD_ALLOC);9091unsigned char *row = reinterpret_cast<unsigned char*> (image->imageData);92T convert;93for (int i = 0; i < image->height; ++i)94{95for (int j = 0; j < image->width; ++j)96{97if (image->nChannels < 3)98{99dst->ptr ()[j + i*dst->stride ()] = static_cast<float> (*(row + j*image->nChannels))/255.0f;100}101else102{103unsigned char *color = row + j * image->nChannels;104dst->ptr ()[j +i*dst->stride ()] = convert (color[0], color[1], color[2]);105}106}107row += image->widthStep;108}109return NCV_SUCCESS;110}111112template<class T>113NCVStatus CopyData(const IplImage *image, const NCVMatrixAlloc<Ncv32f> &dst)114{115unsigned char *row = reinterpret_cast<unsigned char*> (image->imageData);116T convert;117for (int i = 0; i < image->height; ++i)118{119for (int j = 0; j < image->width; ++j)120{121if (image->nChannels < 3)122{123dst.ptr ()[j + i*dst.stride ()] = static_cast<float>(*(row + j*image->nChannels))/255.0f;124}125else126{127unsigned char *color = row + j * image->nChannels;128dst.ptr ()[j +i*dst.stride()] = convert (color[0], color[1], color[2]);129}130}131row += image->widthStep;132}133return NCV_SUCCESS;134}135136static NCVStatus LoadImages (const char *frame0Name,137const char *frame1Name,138int &width,139int &height,140Ptr<NCVMatrixAlloc<Ncv32f> > &src,141Ptr<NCVMatrixAlloc<Ncv32f> > &dst,142IplImage *&firstFrame,143IplImage *&lastFrame)144{145IplImage *image;146image = cvLoadImage (frame0Name);147if (image == 0)148{149std::cout << "Could not open '" << frame0Name << "'\n";150return NCV_FILE_ERROR;151}152153firstFrame = image;154// copy data to src155ncvAssertReturnNcvStat (CopyData<RgbToMonochrome> (image, src));156157IplImage *image2;158image2 = cvLoadImage (frame1Name);159if (image2 == 0)160{161std::cout << "Could not open '" << frame1Name << "'\n";162return NCV_FILE_ERROR;163}164lastFrame = image2;165166ncvAssertReturnNcvStat (CopyData<RgbToMonochrome> (image2, dst));167168width = image->width;169height = image->height;170171return NCV_SUCCESS;172}173174template<typename T>175inline T Clamp (T x, T a, T b)176{177return ((x) > (a) ? ((x) < (b) ? (x) : (b)) : (a));178}179180template<typename T>181inline T MapValue (T x, T a, T b, T c, T d)182{183x = Clamp (x, a, b);184return c + (d - c) * (x - a) / (b - a);185}186187static NCVStatus ShowFlow (NCVMatrixAlloc<Ncv32f> &u, NCVMatrixAlloc<Ncv32f> &v, const char *name)188{189IplImage *flowField;190191NCVMatrixAlloc<Ncv32f> host_u(*g_pHostMemAllocator, u.width(), u.height());192ncvAssertReturn(host_u.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC);193194NCVMatrixAlloc<Ncv32f> host_v (*g_pHostMemAllocator, u.width (), u.height ());195ncvAssertReturn (host_v.isMemAllocated (), NCV_ALLOCATOR_BAD_ALLOC);196197ncvAssertReturnNcvStat (u.copySolid (host_u, 0));198ncvAssertReturnNcvStat (v.copySolid (host_v, 0));199200float *ptr_u = host_u.ptr ();201float *ptr_v = host_v.ptr ();202203float maxDisplacement = 1.0f;204205for (Ncv32u i = 0; i < u.height (); ++i)206{207for (Ncv32u j = 0; j < u.width (); ++j)208{209float d = std::max ( fabsf(*ptr_u), fabsf(*ptr_v) );210if (d > maxDisplacement) maxDisplacement = d;211++ptr_u;212++ptr_v;213}214ptr_u += u.stride () - u.width ();215ptr_v += v.stride () - v.width ();216}217218CvSize image_size = cvSize (u.width (), u.height ());219flowField = cvCreateImage (image_size, IPL_DEPTH_8U, 4);220if (flowField == 0) return NCV_NULL_PTR;221222unsigned char *row = reinterpret_cast<unsigned char *> (flowField->imageData);223224ptr_u = host_u.ptr();225ptr_v = host_v.ptr();226for (int i = 0; i < flowField->height; ++i)227{228for (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}237row += flowField->widthStep;238ptr_u += u.stride () - u.width ();239ptr_v += v.stride () - v.width ();240}241242cvShowImage (name, flowField);243244return NCV_SUCCESS;245}246247static IplImage *CreateImage (NCVMatrixAlloc<Ncv32f> &h_r, NCVMatrixAlloc<Ncv32f> &h_g, NCVMatrixAlloc<Ncv32f> &h_b)248{249CvSize imageSize = cvSize (h_r.width (), h_r.height ());250IplImage *image = cvCreateImage (imageSize, IPL_DEPTH_8U, 4);251if (image == 0) return 0;252253unsigned char *row = reinterpret_cast<unsigned char*> (image->imageData);254255for (int i = 0; i < image->height; ++i)256{257for (int j = 0; j < image->width; ++j)258{259int offset = j * image->nChannels;260int pos = i * h_r.stride () + j;261row[offset + 0] = static_cast<unsigned char> (h_b.ptr ()[pos] * 255.0f);262row[offset + 1] = static_cast<unsigned char> (h_g.ptr ()[pos] * 255.0f);263row[offset + 2] = static_cast<unsigned char> (h_r.ptr ()[pos] * 255.0f);264row[offset + 3] = 255;265}266row += image->widthStep;267}268return image;269}270271static void PrintHelp ()272{273std::cout << "Usage help:\n";274std::cout << std::setiosflags(std::ios::left);275std::cout << "\t" << std::setw(15) << PARAM_ALPHA << " - set alpha\n";276std::cout << "\t" << std::setw(15) << PARAM_GAMMA << " - set gamma\n";277std::cout << "\t" << std::setw(15) << PARAM_INNER << " - set number of inner iterations\n";278std::cout << "\t" << std::setw(15) << PARAM_LEFT << " - specify left image\n";279std::cout << "\t" << std::setw(15) << PARAM_RIGHT << " - specify right image\n";280std::cout << "\t" << std::setw(15) << PARAM_OUTER << " - set number of outer iterations\n";281std::cout << "\t" << std::setw(15) << PARAM_SCALE << " - set pyramid scale factor\n";282std::cout << "\t" << std::setw(15) << PARAM_SOLVER << " - set number of basic solver iterations\n";283std::cout << "\t" << std::setw(15) << PARAM_TIME_STEP << " - set frame interpolation time step\n";284std::cout << "\t" << std::setw(15) << PARAM_HELP << " - display this help message\n";285}286287static int ProcessCommandLine(int argc, char **argv,288Ncv32f &timeStep,289char *&frame0Name,290char *&frame1Name,291NCVBroxOpticalFlowDescriptor &desc)292{293timeStep = 0.25f;294for (int iarg = 1; iarg < argc; ++iarg)295{296if (strcmp(argv[iarg], PARAM_LEFT) == 0)297{298if (iarg + 1 < argc)299{300frame0Name = argv[++iarg];301}302else303return -1;304}305if (strcmp(argv[iarg], PARAM_RIGHT) == 0)306{307if (iarg + 1 < argc)308{309frame1Name = argv[++iarg];310}311else312return -1;313}314else if(strcmp(argv[iarg], PARAM_SCALE) == 0)315{316if (iarg + 1 < argc)317desc.scale_factor = static_cast<Ncv32f>(atof(argv[++iarg]));318else319return -1;320}321else if(strcmp(argv[iarg], PARAM_ALPHA) == 0)322{323if (iarg + 1 < argc)324desc.alpha = static_cast<Ncv32f>(atof(argv[++iarg]));325else326return -1;327}328else if(strcmp(argv[iarg], PARAM_GAMMA) == 0)329{330if (iarg + 1 < argc)331desc.gamma = static_cast<Ncv32f>(atof(argv[++iarg]));332else333return -1;334}335else if(strcmp(argv[iarg], PARAM_INNER) == 0)336{337if (iarg + 1 < argc)338desc.number_of_inner_iterations = static_cast<Ncv32u>(atoi(argv[++iarg]));339else340return -1;341}342else if(strcmp(argv[iarg], PARAM_OUTER) == 0)343{344if (iarg + 1 < argc)345desc.number_of_outer_iterations = static_cast<Ncv32u>(atoi(argv[++iarg]));346else347return -1;348}349else if(strcmp(argv[iarg], PARAM_SOLVER) == 0)350{351if (iarg + 1 < argc)352desc.number_of_solver_iterations = static_cast<Ncv32u>(atoi(argv[++iarg]));353else354return -1;355}356else if(strcmp(argv[iarg], PARAM_TIME_STEP) == 0)357{358if (iarg + 1 < argc)359timeStep = static_cast<Ncv32f>(atof(argv[++iarg]));360else361return -1;362}363else if(strcmp(argv[iarg], PARAM_HELP) == 0)364{365PrintHelp ();366return 0;367}368}369return 0;370}371372373int main(int argc, char **argv)374{375char *frame0Name = 0, *frame1Name = 0;376Ncv32f timeStep = 0.01f;377378NCVBroxOpticalFlowDescriptor desc;379380desc.alpha = 0.197f;381desc.gamma = 50.0f;382desc.number_of_inner_iterations = 10;383desc.number_of_outer_iterations = 77;384desc.number_of_solver_iterations = 10;385desc.scale_factor = 0.8f;386387int result = ProcessCommandLine (argc, argv, timeStep, frame0Name, frame1Name, desc);388if (argc == 1 || result)389{390PrintHelp();391return result;392}393394cv::cuda::printShortCudaDeviceInfo(cv::cuda::getDevice());395396std::cout << "OpenCV / NVIDIA Computer Vision\n";397std::cout << "Optical Flow Demo: Frame Interpolation\n";398std::cout << "=========================================\n";399std::cout << "Press:\n ESC to quit\n 'a' to move to the previous frame\n 's' to move to the next frame\n";400401int devId;402ncvAssertCUDAReturn(cudaGetDevice(&devId), -1);403cudaDeviceProp devProp;404ncvAssertCUDAReturn(cudaGetDeviceProperties(&devProp, devId), -1);405std::cout << "Using GPU: " << devId << "(" << devProp.name <<406"), arch=" << devProp.major << "." << devProp.minor << std::endl;407408g_pGPUMemAllocator = Ptr<INCVMemAllocator> (new NCVMemNativeAllocator (NCVMemoryTypeDevice, static_cast<Ncv32u>(devProp.textureAlignment)));409ncvAssertPrintReturn (g_pGPUMemAllocator->isInitialized (), "Device memory allocator isn't initialized", -1);410411g_pHostMemAllocator = Ptr<INCVMemAllocator> (new NCVMemNativeAllocator (NCVMemoryTypeHostPageable, static_cast<Ncv32u>(devProp.textureAlignment)));412ncvAssertPrintReturn (g_pHostMemAllocator->isInitialized (), "Host memory allocator isn't initialized", -1);413414int width, height;415416Ptr<NCVMatrixAlloc<Ncv32f> > src_host;417Ptr<NCVMatrixAlloc<Ncv32f> > dst_host;418419IplImage *firstFrame, *lastFrame;420if (frame0Name != 0 && frame1Name != 0)421{422ncvAssertReturnNcvStat (LoadImages (frame0Name, frame1Name, width, height, src_host, dst_host, firstFrame, lastFrame));423}424else425{426ncvAssertReturnNcvStat (LoadImages ("frame10.bmp", "frame11.bmp", width, height, src_host, dst_host, firstFrame, lastFrame));427}428429Ptr<NCVMatrixAlloc<Ncv32f> > src (new NCVMatrixAlloc<Ncv32f> (*g_pGPUMemAllocator, src_host->width (), src_host->height ()));430ncvAssertReturn(src->isMemAllocated(), -1);431432Ptr<NCVMatrixAlloc<Ncv32f> > dst (new NCVMatrixAlloc<Ncv32f> (*g_pGPUMemAllocator, src_host->width (), src_host->height ()));433ncvAssertReturn (dst->isMemAllocated (), -1);434435ncvAssertReturnNcvStat (src_host->copySolid ( *src, 0 ));436ncvAssertReturnNcvStat (dst_host->copySolid ( *dst, 0 ));437438#if defined SAFE_MAT_DECL439#undef SAFE_MAT_DECL440#endif441#define SAFE_MAT_DECL(name, allocator, sx, sy) \442NCVMatrixAlloc<Ncv32f> name(*allocator, sx, sy);\443ncvAssertReturn(name.isMemAllocated(), -1);444445SAFE_MAT_DECL (u, g_pGPUMemAllocator, width, height);446SAFE_MAT_DECL (v, g_pGPUMemAllocator, width, height);447448SAFE_MAT_DECL (uBck, g_pGPUMemAllocator, width, height);449SAFE_MAT_DECL (vBck, g_pGPUMemAllocator, width, height);450451SAFE_MAT_DECL (h_r, g_pHostMemAllocator, width, height);452SAFE_MAT_DECL (h_g, g_pHostMemAllocator, width, height);453SAFE_MAT_DECL (h_b, g_pHostMemAllocator, width, height);454455std::cout << "Estimating optical flow\nForward...\n";456457if (NCV_SUCCESS != NCVBroxOpticalFlow (desc, *g_pGPUMemAllocator, *src, *dst, u, v, 0))458{459std::cout << "Failed\n";460return -1;461}462463std::cout << "Backward...\n";464if (NCV_SUCCESS != NCVBroxOpticalFlow (desc, *g_pGPUMemAllocator, *dst, *src, uBck, vBck, 0))465{466std::cout << "Failed\n";467return -1;468}469470// matrix for temporary data471SAFE_MAT_DECL (d_temp, g_pGPUMemAllocator, width, height);472473// first frame color components (GPU memory)474SAFE_MAT_DECL (d_r, g_pGPUMemAllocator, width, height);475SAFE_MAT_DECL (d_g, g_pGPUMemAllocator, width, height);476SAFE_MAT_DECL (d_b, g_pGPUMemAllocator, width, height);477478// second frame color components (GPU memory)479SAFE_MAT_DECL (d_rt, g_pGPUMemAllocator, width, height);480SAFE_MAT_DECL (d_gt, g_pGPUMemAllocator, width, height);481SAFE_MAT_DECL (d_bt, g_pGPUMemAllocator, width, height);482483// intermediate frame color components (GPU memory)484SAFE_MAT_DECL (d_rNew, g_pGPUMemAllocator, width, height);485SAFE_MAT_DECL (d_gNew, g_pGPUMemAllocator, width, height);486SAFE_MAT_DECL (d_bNew, g_pGPUMemAllocator, width, height);487488// interpolated forward flow489SAFE_MAT_DECL (ui, g_pGPUMemAllocator, width, height);490SAFE_MAT_DECL (vi, g_pGPUMemAllocator, width, height);491492// interpolated backward flow493SAFE_MAT_DECL (ubi, g_pGPUMemAllocator, width, height);494SAFE_MAT_DECL (vbi, g_pGPUMemAllocator, width, height);495496// occlusion masks497SAFE_MAT_DECL (occ0, g_pGPUMemAllocator, width, height);498SAFE_MAT_DECL (occ1, g_pGPUMemAllocator, width, height);499500// prepare color components on host and copy them to device memory501ncvAssertReturnNcvStat (CopyData<RgbToR> (firstFrame, h_r));502ncvAssertReturnNcvStat (CopyData<RgbToG> (firstFrame, h_g));503ncvAssertReturnNcvStat (CopyData<RgbToB> (firstFrame, h_b));504505ncvAssertReturnNcvStat (h_r.copySolid ( d_r, 0 ));506ncvAssertReturnNcvStat (h_g.copySolid ( d_g, 0 ));507ncvAssertReturnNcvStat (h_b.copySolid ( d_b, 0 ));508509ncvAssertReturnNcvStat (CopyData<RgbToR> (lastFrame, h_r));510ncvAssertReturnNcvStat (CopyData<RgbToG> (lastFrame, h_g));511ncvAssertReturnNcvStat (CopyData<RgbToB> (lastFrame, h_b));512513ncvAssertReturnNcvStat (h_r.copySolid ( d_rt, 0 ));514ncvAssertReturnNcvStat (h_g.copySolid ( d_gt, 0 ));515ncvAssertReturnNcvStat (h_b.copySolid ( d_bt, 0 ));516517std::cout << "Interpolating...\n";518std::cout.precision (4);519520std::vector<IplImage*> frames;521frames.push_back (firstFrame);522523// compute interpolated frames524for (Ncv32f timePos = timeStep; timePos < 1.0f; timePos += timeStep)525{526ncvAssertCUDAReturn (cudaMemset (ui.ptr (), 0, ui.pitch () * ui.height ()), NCV_CUDA_ERROR);527ncvAssertCUDAReturn (cudaMemset (vi.ptr (), 0, vi.pitch () * vi.height ()), NCV_CUDA_ERROR);528529ncvAssertCUDAReturn (cudaMemset (ubi.ptr (), 0, ubi.pitch () * ubi.height ()), NCV_CUDA_ERROR);530ncvAssertCUDAReturn (cudaMemset (vbi.ptr (), 0, vbi.pitch () * vbi.height ()), NCV_CUDA_ERROR);531532ncvAssertCUDAReturn (cudaMemset (occ0.ptr (), 0, occ0.pitch () * occ0.height ()), NCV_CUDA_ERROR);533ncvAssertCUDAReturn (cudaMemset (occ1.ptr (), 0, occ1.pitch () * occ1.height ()), NCV_CUDA_ERROR);534535NppStInterpolationState state;536// interpolation state should be filled once except pSrcFrame0, pSrcFrame1, and pNewFrame537// we will only need to reset buffers content to 0 since interpolator doesn't do this itself538state.size = NcvSize32u (width, height);539state.nStep = d_r.pitch ();540state.pSrcFrame0 = d_r.ptr ();541state.pSrcFrame1 = d_rt.ptr ();542state.pFU = u.ptr ();543state.pFV = v.ptr ();544state.pBU = uBck.ptr ();545state.pBV = vBck.ptr ();546state.pos = timePos;547state.pNewFrame = d_rNew.ptr ();548state.ppBuffers[0] = occ0.ptr ();549state.ppBuffers[1] = occ1.ptr ();550state.ppBuffers[2] = ui.ptr ();551state.ppBuffers[3] = vi.ptr ();552state.ppBuffers[4] = ubi.ptr ();553state.ppBuffers[5] = vbi.ptr ();554555// interpolate red channel556nppiStInterpolateFrames (&state);557558// reset buffers559ncvAssertCUDAReturn (cudaMemset (ui.ptr (), 0, ui.pitch () * ui.height ()), NCV_CUDA_ERROR);560ncvAssertCUDAReturn (cudaMemset (vi.ptr (), 0, vi.pitch () * vi.height ()), NCV_CUDA_ERROR);561562ncvAssertCUDAReturn (cudaMemset (ubi.ptr (), 0, ubi.pitch () * ubi.height ()), NCV_CUDA_ERROR);563ncvAssertCUDAReturn (cudaMemset (vbi.ptr (), 0, vbi.pitch () * vbi.height ()), NCV_CUDA_ERROR);564565ncvAssertCUDAReturn (cudaMemset (occ0.ptr (), 0, occ0.pitch () * occ0.height ()), NCV_CUDA_ERROR);566ncvAssertCUDAReturn (cudaMemset (occ1.ptr (), 0, occ1.pitch () * occ1.height ()), NCV_CUDA_ERROR);567568// interpolate green channel569state.pSrcFrame0 = d_g.ptr ();570state.pSrcFrame1 = d_gt.ptr ();571state.pNewFrame = d_gNew.ptr ();572573nppiStInterpolateFrames (&state);574575// reset buffers576ncvAssertCUDAReturn (cudaMemset (ui.ptr (), 0, ui.pitch () * ui.height ()), NCV_CUDA_ERROR);577ncvAssertCUDAReturn (cudaMemset (vi.ptr (), 0, vi.pitch () * vi.height ()), NCV_CUDA_ERROR);578579ncvAssertCUDAReturn (cudaMemset (ubi.ptr (), 0, ubi.pitch () * ubi.height ()), NCV_CUDA_ERROR);580ncvAssertCUDAReturn (cudaMemset (vbi.ptr (), 0, vbi.pitch () * vbi.height ()), NCV_CUDA_ERROR);581582ncvAssertCUDAReturn (cudaMemset (occ0.ptr (), 0, occ0.pitch () * occ0.height ()), NCV_CUDA_ERROR);583ncvAssertCUDAReturn (cudaMemset (occ1.ptr (), 0, occ1.pitch () * occ1.height ()), NCV_CUDA_ERROR);584585// interpolate blue channel586state.pSrcFrame0 = d_b.ptr ();587state.pSrcFrame1 = d_bt.ptr ();588state.pNewFrame = d_bNew.ptr ();589590nppiStInterpolateFrames (&state);591592// copy to host memory593ncvAssertReturnNcvStat (d_rNew.copySolid (h_r, 0));594ncvAssertReturnNcvStat (d_gNew.copySolid (h_g, 0));595ncvAssertReturnNcvStat (d_bNew.copySolid (h_b, 0));596597// convert to IplImage598IplImage *newFrame = CreateImage (h_r, h_g, h_b);599if (newFrame == 0)600{601std::cout << "Could not create new frame in host memory\n";602break;603}604frames.push_back (newFrame);605std::cout << timePos * 100.0f << "%\r";606}607std::cout << std::setw (5) << "100%\n";608609frames.push_back (lastFrame);610611Ncv32u currentFrame;612currentFrame = 0;613614ShowFlow (u, v, "Forward flow");615ShowFlow (uBck, vBck, "Backward flow");616617cvShowImage ("Interpolated frame", frames[currentFrame]);618619bool qPressed = false;620while ( !qPressed )621{622int key = toupper (cvWaitKey (10));623switch (key)624{625case 27:626qPressed = true;627break;628case 'A':629if (currentFrame > 0) --currentFrame;630cvShowImage ("Interpolated frame", frames[currentFrame]);631break;632case 'S':633if (currentFrame < frames.size()-1) ++currentFrame;634cvShowImage ("Interpolated frame", frames[currentFrame]);635break;636}637}638639cvDestroyAllWindows ();640641std::vector<IplImage*>::iterator iter;642for (iter = frames.begin (); iter != frames.end (); ++iter)643{644cvReleaseImage (&(*iter));645}646647return 0;648}649650#endif651652653