parent
87f3451ec6
commit
b0536279eb
6 changed files with 981 additions and 211 deletions
@ -0,0 +1,198 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other GpuMaterials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or bpied warranties, including, but not limited to, the bpied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp" |
||||
|
||||
using namespace cv; |
||||
using namespace cv::gpu; |
||||
using namespace std; |
||||
|
||||
#if !defined (HAVE_CUDA) |
||||
|
||||
void cv::gpu::BroxOpticalFlow::operator ()(const GpuMat&, const GpuMat&, GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } |
||||
void cv::gpu::interpolateFrames(const GpuMat&, const GpuMat&, const GpuMat&, const GpuMat&, const GpuMat&, const GpuMat&, float, GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } |
||||
|
||||
#else |
||||
|
||||
namespace |
||||
{ |
||||
size_t getBufSize(const NCVBroxOpticalFlowDescriptor& desc, const NCVMatrix<Ncv32f>& frame0, const NCVMatrix<Ncv32f>& frame1, |
||||
NCVMatrix<Ncv32f>& u, NCVMatrix<Ncv32f>& v, const cudaDeviceProp& devProp) |
||||
{ |
||||
NCVMemStackAllocator gpuCounter(static_cast<Ncv32u>(devProp.textureAlignment)); |
||||
CV_Assert(gpuCounter.isInitialized()); |
||||
|
||||
NCVStatus ncvStat = NCVBroxOpticalFlow(desc, gpuCounter, frame0, frame1, u, v, 0); |
||||
CV_Assert(ncvStat == NCV_SUCCESS); |
||||
|
||||
return gpuCounter.maxSize(); |
||||
} |
||||
} |
||||
|
||||
namespace |
||||
{ |
||||
void outputHandler(const char* msg)
|
||||
{
|
||||
CV_Error(CV_GpuApiCallError, msg);
|
||||
} |
||||
} |
||||
|
||||
void cv::gpu::BroxOpticalFlow::operator ()(const GpuMat& frame0, const GpuMat& frame1, GpuMat& u, GpuMat& v, Stream& s)
|
||||
{ |
||||
ncvSetDebugOutputHandler(outputHandler); |
||||
|
||||
CV_Assert(frame0.type() == CV_32FC1); |
||||
CV_Assert(frame1.size() == frame0.size() && frame1.type() == frame0.type()); |
||||
|
||||
u.create(frame0.size(), CV_32FC1); |
||||
v.create(frame0.size(), CV_32FC1); |
||||
|
||||
cudaDeviceProp devProp; |
||||
cudaSafeCall( cudaGetDeviceProperties(&devProp, getDevice()) ); |
||||
|
||||
NCVBroxOpticalFlowDescriptor desc; |
||||
|
||||
desc.alpha = alpha; |
||||
desc.gamma = gamma; |
||||
desc.scale_factor = scale_factor; |
||||
desc.number_of_inner_iterations = inner_iterations; |
||||
desc.number_of_outer_iterations = outer_iterations; |
||||
desc.number_of_solver_iterations = solver_iterations; |
||||
|
||||
NCVMemSegment frame0MemSeg; |
||||
frame0MemSeg.begin.memtype = NCVMemoryTypeDevice; |
||||
frame0MemSeg.begin.ptr = const_cast<uchar*>(frame0.data); |
||||
frame0MemSeg.size = frame0.step * frame0.rows; |
||||
|
||||
NCVMemSegment frame1MemSeg; |
||||
frame1MemSeg.begin.memtype = NCVMemoryTypeDevice; |
||||
frame1MemSeg.begin.ptr = const_cast<uchar*>(frame1.data); |
||||
frame1MemSeg.size = frame1.step * frame1.rows; |
||||
|
||||
NCVMemSegment uMemSeg; |
||||
uMemSeg.begin.memtype = NCVMemoryTypeDevice; |
||||
uMemSeg.begin.ptr = u.ptr(); |
||||
uMemSeg.size = u.step * u.rows; |
||||
|
||||
NCVMemSegment vMemSeg; |
||||
vMemSeg.begin.memtype = NCVMemoryTypeDevice; |
||||
vMemSeg.begin.ptr = v.ptr(); |
||||
vMemSeg.size = v.step * v.rows; |
||||
|
||||
NCVMatrixReuse<Ncv32f> frame0Mat(frame0MemSeg, devProp.textureAlignment, frame0.cols, frame0.rows, frame0.step); |
||||
NCVMatrixReuse<Ncv32f> frame1Mat(frame1MemSeg, devProp.textureAlignment, frame1.cols, frame1.rows, frame1.step); |
||||
NCVMatrixReuse<Ncv32f> uMat(uMemSeg, devProp.textureAlignment, u.cols, u.rows, u.step); |
||||
NCVMatrixReuse<Ncv32f> vMat(vMemSeg, devProp.textureAlignment, v.cols, v.rows, v.step); |
||||
|
||||
cudaStream_t stream = StreamAccessor::getStream(s); |
||||
|
||||
size_t bufSize = getBufSize(desc, frame0Mat, frame1Mat, uMat, vMat, devProp); |
||||
|
||||
ensureSizeIsEnough(1, bufSize, CV_8UC1, buf); |
||||
|
||||
NCVMemStackAllocator gpuAllocator(NCVMemoryTypeDevice, bufSize, static_cast<Ncv32u>(devProp.textureAlignment), buf.ptr()); |
||||
CV_Assert(gpuAllocator.isInitialized()); |
||||
|
||||
NCVStatus ncvStat = NCVBroxOpticalFlow(desc, gpuAllocator, frame0Mat, frame1Mat, uMat, vMat, stream); |
||||
CV_Assert(ncvStat == NCV_SUCCESS); |
||||
} |
||||
|
||||
void cv::gpu::interpolateFrames(const GpuMat& frame0, const GpuMat& frame1, const GpuMat& fu, const GpuMat& fv, const GpuMat& bu, const GpuMat& bv,
|
||||
float pos, GpuMat& newFrame, GpuMat& buf, Stream& s) |
||||
{ |
||||
CV_Assert(frame0.type() == CV_32FC1); |
||||
CV_Assert(frame1.size() == frame0.size() && frame1.type() == frame0.type()); |
||||
CV_Assert(fu.size() == frame0.size() && fu.type() == frame0.type()); |
||||
CV_Assert(fv.size() == frame0.size() && fv.type() == frame0.type()); |
||||
CV_Assert(bu.size() == frame0.size() && bu.type() == frame0.type()); |
||||
CV_Assert(bv.size() == frame0.size() && bv.type() == frame0.type()); |
||||
|
||||
newFrame.create(frame0.size(), frame0.type()); |
||||
|
||||
buf.create(6 * frame0.rows, frame0.cols, CV_32FC1); |
||||
buf.setTo(Scalar::all(0)); |
||||
|
||||
// occlusion masks
|
||||
GpuMat occ0 = buf.rowRange(0 * frame0.rows, 1 * frame0.rows); |
||||
GpuMat occ1 = buf.rowRange(1 * frame0.rows, 2 * frame0.rows); |
||||
|
||||
// interpolated forward flow
|
||||
GpuMat fui = buf.rowRange(2 * frame0.rows, 3 * frame0.rows); |
||||
GpuMat fvi = buf.rowRange(3 * frame0.rows, 4 * frame0.rows); |
||||
|
||||
// interpolated backward flow
|
||||
GpuMat bui = buf.rowRange(4 * frame0.rows, 5 * frame0.rows); |
||||
GpuMat bvi = buf.rowRange(5 * frame0.rows, 6 * frame0.rows); |
||||
|
||||
size_t step = frame0.step; |
||||
|
||||
CV_Assert(frame1.step == step && fu.step == step && fv.step == step && bu.step == step && bv.step == step && newFrame.step == step && buf.step == step); |
||||
|
||||
cudaStream_t stream = StreamAccessor::getStream(s); |
||||
NppStStreamHandler h(stream); |
||||
|
||||
NppStInterpolationState state; |
||||
|
||||
state.size = NcvSize32u(frame0.cols, frame0.rows); |
||||
state.nStep = static_cast<Ncv32u>(step); |
||||
state.pSrcFrame0 = const_cast<Ncv32f*>(frame0.ptr<Ncv32f>()); |
||||
state.pSrcFrame1 = const_cast<Ncv32f*>(frame1.ptr<Ncv32f>()); |
||||
state.pFU = const_cast<Ncv32f*>(fu.ptr<Ncv32f>()); |
||||
state.pFV = const_cast<Ncv32f*>(fv.ptr<Ncv32f>()); |
||||
state.pBU = const_cast<Ncv32f*>(bu.ptr<Ncv32f>()); |
||||
state.pBV = const_cast<Ncv32f*>(bv.ptr<Ncv32f>()); |
||||
state.pos = pos; |
||||
state.pNewFrame = newFrame.ptr<Ncv32f>(); |
||||
state.ppBuffers[0] = occ0.ptr<Ncv32f>(); |
||||
state.ppBuffers[1] = occ1.ptr<Ncv32f>(); |
||||
state.ppBuffers[2] = fui.ptr<Ncv32f>(); |
||||
state.ppBuffers[3] = fvi.ptr<Ncv32f>(); |
||||
state.ppBuffers[4] = bui.ptr<Ncv32f>(); |
||||
state.ppBuffers[5] = bvi.ptr<Ncv32f>(); |
||||
|
||||
nppSafeCall( nppiStInterpolateFrames(&state) ); |
||||
|
||||
if (stream == 0) |
||||
cudaSafeCall( cudaDeviceSynchronize() ); |
||||
} |
||||
|
||||
#endif /* HAVE_CUDA */ |
@ -0,0 +1,227 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp" |
||||
|
||||
#ifdef HAVE_CUDA |
||||
|
||||
//#define DUMP
|
||||
|
||||
struct BroxOpticalFlow : testing::TestWithParam< cv::gpu::DeviceInfo > |
||||
{ |
||||
cv::gpu::DeviceInfo devInfo; |
||||
|
||||
cv::Mat frame0; |
||||
cv::Mat frame1; |
||||
|
||||
cv::Mat u_gold; |
||||
cv::Mat v_gold; |
||||
|
||||
virtual void SetUp() |
||||
{ |
||||
devInfo = GetParam(); |
||||
|
||||
cv::gpu::setDevice(devInfo.deviceID()); |
||||
|
||||
frame0 = readImage("opticalflow/frame0.png", cv::IMREAD_GRAYSCALE); |
||||
ASSERT_FALSE(frame0.empty()); |
||||
frame0.convertTo(frame0, CV_32F, 1.0 / 255.0); |
||||
|
||||
frame1 = readImage("opticalflow/frame1.png", cv::IMREAD_GRAYSCALE); |
||||
ASSERT_FALSE(frame1.empty()); |
||||
frame1.convertTo(frame1, CV_32F, 1.0 / 255.0); |
||||
|
||||
#ifndef DUMP |
||||
|
||||
std::ifstream f((std::string(cvtest::TS::ptr()->get_data_path()) + "opticalflow/opticalflow_gold.bin").c_str(), std::ios_base::binary); |
||||
|
||||
int rows, cols; |
||||
|
||||
f.read((char*)&rows, sizeof(rows)); |
||||
f.read((char*)&cols, sizeof(cols)); |
||||
|
||||
u_gold.create(rows, cols, CV_32FC1); |
||||
|
||||
for (int i = 0; i < u_gold.rows; ++i) |
||||
f.read((char*)u_gold.ptr(i), u_gold.cols * sizeof(float)); |
||||
|
||||
v_gold.create(rows, cols, CV_32FC1); |
||||
|
||||
for (int i = 0; i < v_gold.rows; ++i) |
||||
f.read((char*)v_gold.ptr(i), v_gold.cols * sizeof(float)); |
||||
|
||||
#endif |
||||
} |
||||
}; |
||||
|
||||
TEST_P(BroxOpticalFlow, Regression) |
||||
{ |
||||
PRINT_PARAM(devInfo); |
||||
|
||||
cv::Mat u; |
||||
cv::Mat v; |
||||
|
||||
cv::gpu::BroxOpticalFlow d_flow(0.197f /*alpha*/, 50.0f /*gamma*/, 0.8f /*scale_factor*/,
|
||||
10 /*inner_iterations*/, 77 /*outer_iterations*/, 10 /*solver_iterations*/); |
||||
|
||||
ASSERT_NO_THROW( |
||||
cv::gpu::GpuMat d_u;
|
||||
cv::gpu::GpuMat d_v; |
||||
d_flow(cv::gpu::GpuMat(frame0), cv::gpu::GpuMat(frame1), d_u, d_v); |
||||
d_u.download(u); |
||||
d_v.download(v); |
||||
d_flow.buf.release(); |
||||
); |
||||
|
||||
#ifndef DUMP |
||||
|
||||
EXPECT_MAT_NEAR(u_gold, u, 0); |
||||
EXPECT_MAT_NEAR(v_gold, v, 0); |
||||
|
||||
#else |
||||
|
||||
std::ofstream f((std::string(cvtest::TS::ptr()->get_data_path()) + "opticalflow/opticalflow_gold.bin").c_str(), std::ios_base::binary); |
||||
|
||||
f.write((char*)&u.rows, sizeof(u.rows)); |
||||
f.write((char*)&u.cols, sizeof(u.cols)); |
||||
|
||||
for (int i = 0; i < u.rows; ++i) |
||||
f.write((char*)u.ptr(i), u.cols * sizeof(float)); |
||||
|
||||
for (int i = 0; i < v.rows; ++i) |
||||
f.write((char*)v.ptr(i), v.cols * sizeof(float)); |
||||
|
||||
#endif |
||||
} |
||||
|
||||
INSTANTIATE_TEST_CASE_P(Video, BroxOpticalFlow, testing::ValuesIn(devices())); |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct InterpolateFrames : testing::TestWithParam< cv::gpu::DeviceInfo > |
||||
{ |
||||
cv::gpu::DeviceInfo devInfo; |
||||
|
||||
cv::Mat frame0; |
||||
cv::Mat frame1; |
||||
|
||||
cv::Mat newFrame_gold; |
||||
|
||||
virtual void SetUp() |
||||
{ |
||||
devInfo = GetParam(); |
||||
|
||||
cv::gpu::setDevice(devInfo.deviceID()); |
||||
|
||||
frame0 = readImage("opticalflow/frame0.png", cv::IMREAD_GRAYSCALE); |
||||
ASSERT_FALSE(frame0.empty()); |
||||
frame0.convertTo(frame0, CV_32F, 1.0 / 255.0); |
||||
|
||||
frame1 = readImage("opticalflow/frame1.png", cv::IMREAD_GRAYSCALE); |
||||
ASSERT_FALSE(frame1.empty()); |
||||
frame1.convertTo(frame1, CV_32F, 1.0 / 255.0); |
||||
|
||||
#ifndef DUMP |
||||
|
||||
std::ifstream f((std::string(cvtest::TS::ptr()->get_data_path()) + "opticalflow/interpolate_frames_gold.bin").c_str(), std::ios_base::binary); |
||||
|
||||
int rows, cols; |
||||
|
||||
f.read((char*)&rows, sizeof(rows)); |
||||
f.read((char*)&cols, sizeof(cols)); |
||||
|
||||
newFrame_gold.create(rows, cols, CV_32FC1); |
||||
|
||||
for (int i = 0; i < newFrame_gold.rows; ++i) |
||||
f.read((char*)newFrame_gold.ptr(i), newFrame_gold.cols * sizeof(float)); |
||||
|
||||
#endif |
||||
} |
||||
}; |
||||
|
||||
TEST_P(InterpolateFrames, Regression) |
||||
{ |
||||
PRINT_PARAM(devInfo); |
||||
|
||||
cv::Mat newFrame; |
||||
|
||||
cv::gpu::BroxOpticalFlow d_flow(0.197f /*alpha*/, 50.0f /*gamma*/, 0.8f /*scale_factor*/,
|
||||
10 /*inner_iterations*/, 77 /*outer_iterations*/, 10 /*solver_iterations*/); |
||||
|
||||
ASSERT_NO_THROW( |
||||
cv::gpu::GpuMat d_frame0(frame0); |
||||
cv::gpu::GpuMat d_frame1(frame1); |
||||
cv::gpu::GpuMat d_fu;
|
||||
cv::gpu::GpuMat d_fv; |
||||
cv::gpu::GpuMat d_bu;
|
||||
cv::gpu::GpuMat d_bv; |
||||
cv::gpu::GpuMat d_newFrame; |
||||
cv::gpu::GpuMat d_buf; |
||||
d_flow(d_frame0, d_frame1, d_fu, d_fv); |
||||
d_flow(d_frame1, d_frame0, d_bu, d_bv); |
||||
cv::gpu::interpolateFrames(d_frame0, d_frame1, d_fu, d_fv, d_bu, d_bv, 0.5f, d_newFrame, d_buf); |
||||
d_newFrame.download(newFrame); |
||||
d_flow.buf.release(); |
||||
); |
||||
|
||||
#ifndef DUMP |
||||
|
||||
EXPECT_MAT_NEAR(newFrame_gold, newFrame, 1e-4); |
||||
|
||||
#else |
||||
|
||||
std::ofstream f((std::string(cvtest::TS::ptr()->get_data_path()) + "opticalflow/interpolate_frames_gold.bin").c_str(), std::ios_base::binary); |
||||
|
||||
f.write((char*)&newFrame.rows, sizeof(newFrame.rows)); |
||||
f.write((char*)&newFrame.cols, sizeof(newFrame.cols)); |
||||
|
||||
for (int i = 0; i < newFrame.rows; ++i) |
||||
f.write((char*)newFrame.ptr(i), newFrame.cols * sizeof(float)); |
||||
|
||||
#endif |
||||
} |
||||
|
||||
INSTANTIATE_TEST_CASE_P(Video, InterpolateFrames, testing::ValuesIn(devices())); |
||||
|
||||
#endif |
@ -0,0 +1,340 @@ |
||||
#include <iostream> |
||||
#include <iomanip> |
||||
#include <string> |
||||
|
||||
#include "cvconfig.h" |
||||
#include "opencv2/core/core.hpp" |
||||
#include "opencv2/highgui/highgui.hpp" |
||||
#include "opencv2/gpu/gpu.hpp" |
||||
|
||||
#ifdef HAVE_CUDA |
||||
#include "NPP_staging/NPP_staging.hpp" |
||||
#endif |
||||
|
||||
using namespace std; |
||||
using namespace cv; |
||||
using namespace cv::gpu; |
||||
|
||||
#if !defined(HAVE_CUDA) |
||||
|
||||
int main(int argc, const char* argv[]) |
||||
{ |
||||
cout << "Please compile the library with CUDA support" << endl; |
||||
return -1; |
||||
} |
||||
|
||||
#else |
||||
|
||||
#define PARAM_INPUT "--input" |
||||
#define PARAM_SCALE "--scale" |
||||
#define PARAM_ALPHA "--alpha" |
||||
#define PARAM_GAMMA "--gamma" |
||||
#define PARAM_INNER "--inner" |
||||
#define PARAM_OUTER "--outer" |
||||
#define PARAM_SOLVER "--solver" |
||||
#define PARAM_TIME_STEP "--time-step" |
||||
#define PARAM_HELP "--help" |
||||
|
||||
void printHelp() |
||||
{ |
||||
cout << "Usage help:\n"; |
||||
cout << setiosflags(ios::left); |
||||
cout << "\t" << setw(15) << PARAM_ALPHA << " - set alpha\n"; |
||||
cout << "\t" << setw(15) << PARAM_GAMMA << " - set gamma\n"; |
||||
cout << "\t" << setw(15) << PARAM_INNER << " - set number of inner iterations\n"; |
||||
cout << "\t" << setw(15) << PARAM_INPUT << " - specify input file names (2 image files)\n"; |
||||
cout << "\t" << setw(15) << PARAM_OUTER << " - set number of outer iterations\n"; |
||||
cout << "\t" << setw(15) << PARAM_SCALE << " - set pyramid scale factor\n"; |
||||
cout << "\t" << setw(15) << PARAM_SOLVER << " - set number of basic solver iterations\n"; |
||||
cout << "\t" << setw(15) << PARAM_TIME_STEP << " - set frame interpolation time step\n"; |
||||
cout << "\t" << setw(15) << PARAM_HELP << " - display this help message\n"; |
||||
} |
||||
|
||||
int processCommandLine(int argc, const char* argv[], float& timeStep, string& frame0Name, string& frame1Name, BroxOpticalFlow& flow) |
||||
{ |
||||
timeStep = 0.25f; |
||||
|
||||
for (int iarg = 1; iarg < argc; ++iarg) |
||||
{ |
||||
if (strcmp(argv[iarg], PARAM_INPUT) == 0) |
||||
{ |
||||
if (iarg + 2 < argc) |
||||
{ |
||||
frame0Name = argv[++iarg]; |
||||
frame1Name = argv[++iarg]; |
||||
} |
||||
else |
||||
return -1; |
||||
} |
||||
else if(strcmp(argv[iarg], PARAM_SCALE) == 0) |
||||
{ |
||||
if (iarg + 1 < argc) |
||||
flow.scale_factor = static_cast<float>(atof(argv[++iarg])); |
||||
else |
||||
return -1; |
||||
} |
||||
else if(strcmp(argv[iarg], PARAM_ALPHA) == 0) |
||||
{ |
||||
if (iarg + 1 < argc) |
||||
flow.alpha = static_cast<float>(atof(argv[++iarg])); |
||||
else |
||||
return -1; |
||||
} |
||||
else if(strcmp(argv[iarg], PARAM_GAMMA) == 0) |
||||
{ |
||||
if (iarg + 1 < argc) |
||||
flow.gamma = static_cast<float>(atof(argv[++iarg])); |
||||
else |
||||
return -1; |
||||
} |
||||
else if(strcmp(argv[iarg], PARAM_INNER) == 0) |
||||
{ |
||||
if (iarg + 1 < argc) |
||||
flow.inner_iterations = atoi(argv[++iarg]); |
||||
else |
||||
return -1; |
||||
} |
||||
else if(strcmp(argv[iarg], PARAM_OUTER) == 0) |
||||
{ |
||||
if (iarg + 1 < argc) |
||||
flow.outer_iterations = atoi(argv[++iarg]); |
||||
else |
||||
return -1; |
||||
} |
||||
else if(strcmp(argv[iarg], PARAM_SOLVER) == 0) |
||||
{ |
||||
if (iarg + 1 < argc) |
||||
flow.solver_iterations = atoi(argv[++iarg]); |
||||
else |
||||
return -1; |
||||
} |
||||
else if(strcmp(argv[iarg], PARAM_TIME_STEP) == 0) |
||||
{ |
||||
if (iarg + 1 < argc) |
||||
timeStep = static_cast<float>(atof(argv[++iarg])); |
||||
else |
||||
return -1; |
||||
} |
||||
else if(strcmp(argv[iarg], PARAM_HELP) == 0) |
||||
{ |
||||
printHelp(); |
||||
return 0; |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
template <typename T> inline T clamp (T x, T a, T b) |
||||
{ |
||||
return ((x) > (a) ? ((x) < (b) ? (x) : (b)) : (a)); |
||||
} |
||||
|
||||
template <typename T> inline T mapValue(T x, T a, T b, T c, T d) |
||||
{ |
||||
x = clamp(x, a, b); |
||||
return c + (d - c) * (x - a) / (b - a); |
||||
} |
||||
|
||||
void getFlowField(const Mat& u, const Mat& v, Mat& flowField) |
||||
{ |
||||
float maxDisplacement = 1.0f; |
||||
|
||||
for (int i = 0; i < u.rows; ++i) |
||||
{ |
||||
const float* ptr_u = u.ptr<float>(i); |
||||
const float* ptr_v = v.ptr<float>(i); |
||||
|
||||
for (int j = 0; j < u.cols; ++j) |
||||
{ |
||||
float d = max(fabsf(ptr_u[j]), fabsf(ptr_v[j])); |
||||
|
||||
if (d > maxDisplacement)
|
||||
maxDisplacement = d; |
||||
} |
||||
} |
||||
|
||||
flowField.create(u.size(), CV_8UC4); |
||||
|
||||
for (int i = 0; i < flowField.rows; ++i) |
||||
{ |
||||
const float* ptr_u = u.ptr<float>(i); |
||||
const float* ptr_v = v.ptr<float>(i); |
||||
|
||||
Vec4b* row = flowField.ptr<Vec4b>(i); |
||||
|
||||
for (int j = 0; j < flowField.cols; ++j) |
||||
{ |
||||
row[j][0] = 0; |
||||
row[j][1] = static_cast<unsigned char> (mapValue (-ptr_v[j], -maxDisplacement, maxDisplacement, 0.0f, 255.0f)); |
||||
row[j][2] = static_cast<unsigned char> (mapValue ( ptr_u[j], -maxDisplacement, maxDisplacement, 0.0f, 255.0f)); |
||||
row[j][3] = 255; |
||||
} |
||||
} |
||||
} |
||||
|
||||
int main(int argc, const char* argv[]) |
||||
{ |
||||
string frame0Name, frame1Name; |
||||
float timeStep = 0.01f; |
||||
|
||||
BroxOpticalFlow d_flow(0.197f /*alpha*/, 50.0f /*gamma*/, 0.8f /*scale_factor*/,
|
||||
10 /*inner_iterations*/, 77 /*outer_iterations*/, 10 /*solver_iterations*/); |
||||
|
||||
int result = processCommandLine(argc, argv, timeStep, frame0Name, frame1Name, d_flow); |
||||
if (argc == 1 || result) |
||||
{ |
||||
printHelp(); |
||||
return result; |
||||
} |
||||
|
||||
if (frame0Name.empty() || frame1Name.empty()) |
||||
{ |
||||
cout << "Missing input file names\n"; |
||||
return -1; |
||||
} |
||||
|
||||
Mat frame0Color = imread(frame0Name); |
||||
Mat frame1Color = imread(frame1Name); |
||||
|
||||
if (frame0Color.empty() || frame1Color.empty()) |
||||
{ |
||||
cout << "Can't load input images\n"; |
||||
return -1; |
||||
} |
||||
|
||||
cout << "OpenCV / NVIDIA Computer Vision\n"; |
||||
cout << "Optical Flow Demo: Frame Interpolation\n"; |
||||
cout << "=========================================\n"; |
||||
cout << "Press:\n ESC to quit\n 'a' to move to the previous frame\n 's' to move to the next frame\n"; |
||||
|
||||
frame0Color.convertTo(frame0Color, CV_32F, 1.0 / 255.0); |
||||
frame1Color.convertTo(frame1Color, CV_32F, 1.0 / 255.0); |
||||
|
||||
Mat frame0Gray, frame1Gray; |
||||
|
||||
cvtColor(frame0Color, frame0Gray, COLOR_BGR2GRAY); |
||||
cvtColor(frame1Color, frame1Gray, COLOR_BGR2GRAY); |
||||
|
||||
GpuMat d_frame0(frame0Gray); |
||||
GpuMat d_frame1(frame1Gray); |
||||
|
||||
Mat fu, fv; |
||||
Mat bu, bv; |
||||
|
||||
GpuMat d_fu, d_fv; |
||||
GpuMat d_bu, d_bv; |
||||
|
||||
cout << "Estimating optical flow\nForward...\n"; |
||||
|
||||
d_flow(d_frame0, d_frame1, d_fu, d_fv); |
||||
d_flow(d_frame1, d_frame0, d_bu, d_bv); |
||||
|
||||
d_fu.download(fu); |
||||
d_fv.download(fv); |
||||
|
||||
d_bu.download(bu); |
||||
d_bv.download(bv); |
||||
|
||||
// first frame color components (GPU memory)
|
||||
GpuMat d_b, d_g, d_r; |
||||
|
||||
// second frame color components (GPU memory)
|
||||
GpuMat d_bt, d_gt, d_rt; |
||||
|
||||
// prepare color components on host and copy them to device memory
|
||||
Mat channels[3]; |
||||
|
||||
cv::split(frame0Color, channels); |
||||
|
||||
d_b.upload(channels[0]); |
||||
d_g.upload(channels[1]); |
||||
d_r.upload(channels[2]); |
||||
|
||||
cv::split(frame1Color, channels); |
||||
|
||||
d_bt.upload(channels[0]); |
||||
d_gt.upload(channels[1]); |
||||
d_rt.upload(channels[2]); |
||||
|
||||
cout << "Interpolating...\n"; |
||||
cout.precision (4); |
||||
|
||||
// temporary buffer
|
||||
GpuMat d_buf; |
||||
|
||||
// intermediate frame color components (GPU memory)
|
||||
GpuMat d_rNew, d_gNew, d_bNew; |
||||
|
||||
GpuMat d_newFrame; |
||||
|
||||
vector<Mat> frames; |
||||
frames.reserve(1.0f / timeStep + 2); |
||||
|
||||
frames.push_back(frame0Color); |
||||
|
||||
// compute interpolated frames
|
||||
for (float timePos = timeStep; timePos < 1.0f; timePos += timeStep) |
||||
{ |
||||
// interpolate blue channel
|
||||
interpolateFrames(d_b, d_bt, d_fu, d_fv, d_bu, d_bv, timePos, d_bNew, d_buf); |
||||
// interpolate green channel
|
||||
interpolateFrames(d_g, d_gt, d_fu, d_fv, d_bu, d_bv, timePos, d_gNew, d_buf); |
||||
// interpolate red channel
|
||||
interpolateFrames(d_r, d_rt, d_fu, d_fv, d_bu, d_bv, timePos, d_rNew, d_buf); |
||||
|
||||
GpuMat channels[] = {d_bNew, d_gNew, d_rNew}; |
||||
merge(channels, 3, d_newFrame); |
||||
|
||||
Mat newFrame; |
||||
d_newFrame.download(newFrame); |
||||
|
||||
frames.push_back(newFrame); |
||||
|
||||
cout << timePos * 100.0f << "%\r"; |
||||
} |
||||
cout << setw (5) << "100%\n"; |
||||
|
||||
frames.push_back(frame1Color); |
||||
|
||||
int currentFrame; |
||||
currentFrame = 0; |
||||
|
||||
Mat flowFieldForward; |
||||
Mat flowFieldBackward; |
||||
|
||||
getFlowField(fu, fv, flowFieldForward); |
||||
getFlowField(bu, bv, flowFieldBackward); |
||||
|
||||
imshow("Forward flow", flowFieldForward); |
||||
imshow("Backward flow", flowFieldBackward); |
||||
|
||||
imshow("Interpolated frame", frames[currentFrame]); |
||||
|
||||
bool qPressed = false; |
||||
while (!qPressed) |
||||
{ |
||||
int key = toupper(waitKey(10)); |
||||
switch (key) |
||||
{ |
||||
case 27: |
||||
qPressed = true; |
||||
break; |
||||
case 'A': |
||||
if (currentFrame > 0)
|
||||
--currentFrame; |
||||
|
||||
imshow("Interpolated frame", frames[currentFrame]); |
||||
break; |
||||
case 'S': |
||||
if (currentFrame < frames.size() - 1) |
||||
++currentFrame; |
||||
|
||||
imshow("Interpolated frame", frames[currentFrame]); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
#endif |
Loading…
Reference in new issue