Commit 96bf2661 authored by Vadim Pisarevsky's avatar Vadim Pisarevsky Committed by Alexander Alekhin

Merge pull request #13084 from vpisarev:shuffle_optflow_algos

* moved DIS optical flow from opencv_contrib to opencv, moved TVL1 from opencv to opencv_contrib

* fixed compile warning

* TVL1 optical flow example moved to opencv_contrib
parent 841741aa
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "../perf_precomp.hpp"
#include "opencv2/ts/ocl_perf.hpp"
namespace opencv_test { namespace {
#ifdef HAVE_OPENCL
void MakeArtificialExample(UMat &dst_frame1, UMat &dst_frame2);
typedef tuple<String, Size> DISParams;
typedef TestBaseWithParam<DISParams> DenseOpticalFlow_DIS;
OCL_PERF_TEST_P(DenseOpticalFlow_DIS, perf,
Combine(Values("PRESET_ULTRAFAST", "PRESET_FAST", "PRESET_MEDIUM"), Values(szVGA, sz720p, sz1080p)))
{
DISParams params = GetParam();
// use strings to print preset names in the perf test results:
String preset_string = get<0>(params);
int preset = DISOpticalFlow::PRESET_FAST;
if (preset_string == "PRESET_ULTRAFAST")
preset = DISOpticalFlow::PRESET_ULTRAFAST;
else if (preset_string == "PRESET_FAST")
preset = DISOpticalFlow::PRESET_FAST;
else if (preset_string == "PRESET_MEDIUM")
preset = DISOpticalFlow::PRESET_MEDIUM;
Size sz = get<1>(params);
UMat frame1(sz, CV_8U);
UMat frame2(sz, CV_8U);
UMat flow;
MakeArtificialExample(frame1, frame2);
Ptr<DenseOpticalFlow> algo = DISOpticalFlow::create(preset);
OCL_TEST_CYCLE_N(10)
{
algo->calc(frame1, frame2, flow);
}
SANITY_CHECK_NOTHING();
}
void MakeArtificialExample(UMat &dst_frame1, UMat &dst_frame2)
{
int src_scale = 2;
int OF_scale = 6;
double sigma = dst_frame1.cols / 300;
UMat tmp(Size(dst_frame1.cols / (1 << src_scale), dst_frame1.rows / (1 << src_scale)), CV_8U);
randu(tmp, 0, 255);
resize(tmp, dst_frame1, dst_frame1.size(), 0.0, 0.0, INTER_LINEAR_EXACT);
resize(tmp, dst_frame2, dst_frame2.size(), 0.0, 0.0, INTER_LINEAR_EXACT);
Mat displacement_field(Size(dst_frame1.cols / (1 << OF_scale), dst_frame1.rows / (1 << OF_scale)),
CV_32FC2);
randn(displacement_field, 0.0, sigma);
resize(displacement_field, displacement_field, dst_frame2.size(), 0.0, 0.0, INTER_CUBIC);
for (int i = 0; i < displacement_field.rows; i++)
for (int j = 0; j < displacement_field.cols; j++)
displacement_field.at<Vec2f>(i, j) += Vec2f((float)j, (float)i);
remap(dst_frame2, dst_frame2, displacement_field, Mat(), INTER_LINEAR, BORDER_REPLICATE);
}
#endif // HAVE_OPENCL
}} // namespace
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "perf_precomp.hpp"
namespace opencv_test { namespace {
void MakeArtificialExample(Mat &dst_frame1, Mat &dst_frame2);
typedef tuple<String, Size> DISParams;
typedef TestBaseWithParam<DISParams> DenseOpticalFlow_DIS;
PERF_TEST_P(DenseOpticalFlow_DIS, perf,
Combine(Values("PRESET_ULTRAFAST", "PRESET_FAST", "PRESET_MEDIUM"), Values(szVGA, sz720p, sz1080p)))
{
DISParams params = GetParam();
// use strings to print preset names in the perf test results:
String preset_string = get<0>(params);
int preset = DISOpticalFlow::PRESET_FAST;
if (preset_string == "PRESET_ULTRAFAST")
preset = DISOpticalFlow::PRESET_ULTRAFAST;
else if (preset_string == "PRESET_FAST")
preset = DISOpticalFlow::PRESET_FAST;
else if (preset_string == "PRESET_MEDIUM")
preset = DISOpticalFlow::PRESET_MEDIUM;
Size sz = get<1>(params);
Mat frame1(sz, CV_8U);
Mat frame2(sz, CV_8U);
Mat flow;
MakeArtificialExample(frame1, frame2);
TEST_CYCLE_N(10)
{
Ptr<DenseOpticalFlow> algo = DISOpticalFlow::create(preset);
algo->calc(frame1, frame2, flow);
}
SANITY_CHECK_NOTHING();
}
void MakeArtificialExample(Mat &dst_frame1, Mat &dst_frame2)
{
int src_scale = 2;
int OF_scale = 6;
double sigma = dst_frame1.cols / 300;
Mat tmp(Size(dst_frame1.cols / (1 << src_scale), dst_frame1.rows / (1 << src_scale)), CV_8U);
randu(tmp, 0, 255);
resize(tmp, dst_frame1, dst_frame1.size(), 0.0, 0.0, INTER_LINEAR_EXACT);
resize(tmp, dst_frame2, dst_frame2.size(), 0.0, 0.0, INTER_LINEAR_EXACT);
Mat displacement_field(Size(dst_frame1.cols / (1 << OF_scale), dst_frame1.rows / (1 << OF_scale)),
CV_32FC2);
randn(displacement_field, 0.0, sigma);
resize(displacement_field, displacement_field, dst_frame2.size(), 0.0, 0.0, INTER_CUBIC);
for (int i = 0; i < displacement_field.rows; i++)
for (int j = 0; j < displacement_field.cols; j++)
displacement_field.at<Vec2f>(i, j) += Vec2f((float)j, (float)i);
remap(dst_frame2, dst_frame2, displacement_field, Mat(), INTER_LINEAR, BORDER_REPLICATE);
}
}} // namespace
...@@ -6,5 +6,11 @@ ...@@ -6,5 +6,11 @@
#include "opencv2/ts.hpp" #include "opencv2/ts.hpp"
#include <opencv2/video.hpp> #include <opencv2/video.hpp>
#include "opencv2/ts/ts_perf.hpp"
namespace cvtest
{
using namespace perf;
}
#endif #endif
#include "perf_precomp.hpp"
namespace opencv_test { namespace {
using namespace perf;
typedef TestBaseWithParam< std::pair<string, string> > ImagePair;
std::pair<string, string> impair(const char* im1, const char* im2)
{
return std::make_pair(string(im1), string(im2));
}
PERF_TEST_P(ImagePair, OpticalFlowDual_TVL1, testing::Values(impair("cv/optflow/RubberWhale1.png", "cv/optflow/RubberWhale2.png")))
{
declare.time(260);
Mat frame1 = imread(getDataPath(GetParam().first), IMREAD_GRAYSCALE);
Mat frame2 = imread(getDataPath(GetParam().second), IMREAD_GRAYSCALE);
ASSERT_FALSE(frame1.empty());
ASSERT_FALSE(frame2.empty());
Mat flow;
Ptr<DenseOpticalFlow> tvl1 = createOptFlow_DualTVL1();
TEST_CYCLE() tvl1->calc(frame1, frame2, flow);
SANITY_CHECK_NOTHING();
}
}} // namespace
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "perf_precomp.hpp"
namespace opencv_test { namespace {
typedef tuple<Size, int, int> VarRefParams;
typedef TestBaseWithParam<VarRefParams> DenseOpticalFlow_VariationalRefinement;
PERF_TEST_P(DenseOpticalFlow_VariationalRefinement, perf, Combine(Values(szQVGA, szVGA), Values(5, 10), Values(5, 10)))
{
VarRefParams params = GetParam();
Size sz = get<0>(params);
int sorIter = get<1>(params);
int fixedPointIter = get<2>(params);
Mat frame1(sz, CV_8U);
Mat frame2(sz, CV_8U);
Mat flow(sz, CV_32FC2);
randu(frame1, 0, 255);
randu(frame2, 0, 255);
flow.setTo(0.0f);
TEST_CYCLE_N(10)
{
Ptr<VariationalRefinement> var = VariationalRefinement::create();
var->setAlpha(20.0f);
var->setGamma(10.0f);
var->setDelta(5.0f);
var->setSorIterations(sorIter);
var->setFixedPointIterations(fixedPointIter);
var->calc(frame1, frame2, flow);
}
SANITY_CHECK_NOTHING();
}
}} // namespace
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -10,14 +10,10 @@ ...@@ -10,14 +10,10 @@
// License Agreement // License Agreement
// For Open Source Computer Vision Library // For Open Source Computer Vision Library
// //
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners. // Third party copyrights are property of their respective owners.
// //
// @Authors
// Fangfang Bai, fangfang@multicorewareinc.com
// Jin Ma, jin@multicorewareinc.com
//
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met: // are permitted provided that the following conditions are met:
// //
...@@ -31,7 +27,7 @@ ...@@ -31,7 +27,7 @@
// * The name of the copyright holders may not be used to endorse or promote products // * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission. // derived from this software without specific prior written permission.
// //
// This software is provided by the copyright holders and contributors as is and // 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 // any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed. // 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, // In no event shall the Intel Corporation or contributors be liable for any direct,
...@@ -43,69 +39,91 @@ ...@@ -43,69 +39,91 @@
// the use of this software, even if advised of the possibility of such damage. // the use of this software, even if advised of the possibility of such damage.
// //
//M*/ //M*/
#include "precomp.hpp"
#include<iostream>
#include<fstream>
#include "../perf_precomp.hpp" namespace cv {
#include "opencv2/ts/ocl_perf.hpp"
#ifdef HAVE_OPENCL const float FLOW_TAG_FLOAT = 202021.25f;
const char *FLOW_TAG_STRING = "PIEH";
CV_EXPORTS_W Mat readOpticalFlow( const String& path )
{
Mat_<Point2f> flow;
std::ifstream file(path.c_str(), std::ios_base::binary);
if ( !file.good() )
return flow; // no file - return empty matrix
namespace opencv_test { float tag;
namespace ocl { file.read((char*) &tag, sizeof(float));
if ( tag != FLOW_TAG_FLOAT )
return flow;
///////////// OpticalFlow Dual TVL1 //////////////////////// int width, height;
typedef tuple< tuple<int, double>, bool> OpticalFlowDualTVL1Params;
typedef TestBaseWithParam<OpticalFlowDualTVL1Params> OpticalFlowDualTVL1Fixture;
OCL_PERF_TEST_P(OpticalFlowDualTVL1Fixture, OpticalFlowDualTVL1, file.read((char*) &width, 4);
::testing::Combine( file.read((char*) &height, 4);
::testing::Values(make_tuple<int, double>(-1, 0.3),
make_tuple<int, double>(3, 0.5)),
::testing::Bool()
)
)
{
Mat frame0 = imread(getDataPath("cv/optflow/RubberWhale1.png"), cv::IMREAD_GRAYSCALE);
ASSERT_FALSE(frame0.empty()) << "can't load RubberWhale1.png";
Mat frame1 = imread(getDataPath("cv/optflow/RubberWhale2.png"), cv::IMREAD_GRAYSCALE); flow.create(height, width);
ASSERT_FALSE(frame1.empty()) << "can't load RubberWhale2.png";
const Size srcSize = frame0.size(); for ( int i = 0; i < flow.rows; ++i )
{
for ( int j = 0; j < flow.cols; ++j )
{
Point2f u;
file.read((char*) &u.x, sizeof(float));
file.read((char*) &u.y, sizeof(float));
if ( !file.good() )
{
flow.release();
return flow;
}
flow(i, j) = u;
}
}
file.close();
return flow;
}
const OpticalFlowDualTVL1Params params = GetParam(); CV_EXPORTS_W bool writeOpticalFlow( const String& path, InputArray flow )
const tuple<int, double> filteringScale = get<0>(params); {
const int medianFiltering = get<0>(filteringScale); const int nChannels = 2;
const double scaleStep = get<1>(filteringScale);
const bool useInitFlow = get<1>(params);
double eps = 0.9;
UMat uFrame0; frame0.copyTo(uFrame0); Mat input = flow.getMat();
UMat uFrame1; frame1.copyTo(uFrame1); if ( input.channels() != nChannels || input.depth() != CV_32F || path.length() == 0 )
UMat uFlow(srcSize, CV_32FC2); return false;
declare.in(uFrame0, uFrame1, WARMUP_READ).out(uFlow, WARMUP_READ);
//create algorithm std::ofstream file(path.c_str(), std::ofstream::binary);
cv::Ptr<cv::DualTVL1OpticalFlow> alg = cv::createOptFlow_DualTVL1(); if ( !file.good() )
return false;
//set parameters int nRows, nCols;
alg->setScaleStep(scaleStep);
alg->setMedianFiltering(medianFiltering);
if (useInitFlow) nRows = (int) input.size().height;
{ nCols = (int) input.size().width;
//calculate initial flow as result of optical flow
alg->calc(uFrame0, uFrame1, uFlow);
}
//set flag to use initial flow const int headerSize = 12;
alg->setUseInitialFlow(useInitFlow); char header[headerSize];
OCL_TEST_CYCLE() memcpy(header, FLOW_TAG_STRING, 4);
alg->calc(uFrame0, uFrame1, uFlow); // size of ints is known - has been asserted in the current function
memcpy(header + 4, reinterpret_cast<const char*>(&nCols), sizeof(nCols));
memcpy(header + 8, reinterpret_cast<const char*>(&nRows), sizeof(nRows));
file.write(header, headerSize);
if ( !file.good() )
return false;
SANITY_CHECK(uFlow, eps, ERROR_RELATIVE); int row;
char* p;
for ( row = 0; row < nRows; row++ )
{
p = input.ptr<char>(row);
file.write(p, nCols * nChannels * sizeof(float));
if ( !file.good() )
return false;
} }
file.close();
return true;
} }
} // namespace opencv_test::ocl }
#endif // HAVE_OPENCL
This diff is collapsed.
This diff is collapsed.
...@@ -7,12 +7,10 @@ ...@@ -7,12 +7,10 @@
// copy or use the software. // copy or use the software.
// //
// //
// License Agreement // Intel License Agreement
// For Open Source Computer Vision Library // For Open Source Computer Vision Library
// //
// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. // Copyright (C) 2000, Intel Corporation, all rights reserved.
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
// Third party copyrights are property of their respective owners. // Third party copyrights are property of their respective owners.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
...@@ -25,7 +23,7 @@ ...@@ -25,7 +23,7 @@
// this list of conditions and the following disclaimer in the documentation // this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. // and/or other materials provided with the distribution.
// //
// * The name of the copyright holders may not be used to endorse or promote products // * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission. // derived from this software without specific prior written permission.
// //
// This software is provided by the copyright holders and contributors "as is" and // This software is provided by the copyright holders and contributors "as is" and
...@@ -46,72 +44,53 @@ ...@@ -46,72 +44,53 @@
#ifdef HAVE_OPENCL #ifdef HAVE_OPENCL
namespace opencv_test { namespace opencv_test { namespace {
namespace ocl {
///////////////////////////////////////////////////////////////////////////////////////////////// PARAM_TEST_CASE(OCL_DenseOpticalFlow_DIS, int)
// Optical_flow_tvl1
namespace
{ {
IMPLEMENT_PARAM_CLASS(UseInitFlow, bool) int preset;
IMPLEMENT_PARAM_CLASS(MedianFiltering, int)
IMPLEMENT_PARAM_CLASS(ScaleStep, double)
}
PARAM_TEST_CASE(OpticalFlowTVL1, UseInitFlow, MedianFiltering, ScaleStep)
{
bool useInitFlow;
int medianFiltering;
double scaleStep;
virtual void SetUp() virtual void SetUp()
{ {
useInitFlow = GET_PARAM(0); preset = GET_PARAM(0);
medianFiltering = GET_PARAM(1);
scaleStep = GET_PARAM(2);
} }
}; };
OCL_TEST_P(OpticalFlowTVL1, Mat) OCL_TEST_P(OCL_DenseOpticalFlow_DIS, Mat)
{ {
cv::Mat frame0 = readImage("optflow/RubberWhale1.png", cv::IMREAD_GRAYSCALE); Mat frame1, frame2, GT;
ASSERT_FALSE(frame0.empty());
cv::Mat frame1 = readImage("optflow/RubberWhale2.png", cv::IMREAD_GRAYSCALE); frame1 = imread(TS::ptr()->get_data_path() + "optflow/RubberWhale1.png");
ASSERT_FALSE(frame1.empty()); frame2 = imread(TS::ptr()->get_data_path() + "optflow/RubberWhale2.png");
cv::Mat flow; cv::UMat uflow; CV_Assert(!frame1.empty() && !frame2.empty());
//create algorithm cvtColor(frame1, frame1, COLOR_BGR2GRAY);
cv::Ptr<cv::DualTVL1OpticalFlow> alg = cv::createOptFlow_DualTVL1(); cvtColor(frame2, frame2, COLOR_BGR2GRAY);
//set parameters Ptr<DenseOpticalFlow> algo;
alg->setScaleStep(scaleStep);
alg->setMedianFiltering(medianFiltering);
//create initial flow as result of algorithm calculation // iterate over presets:
if (useInitFlow) for (int i = 0; i < cvtest::ocl::test_loop_times; i++)
{ {
OCL_ON(alg->calc(frame0, frame1, uflow)); Mat flow;
uflow.copyTo(flow); UMat ocl_flow;
}
//set flag to use initial flow as it is ready to use algo = DISOpticalFlow::create(preset);
alg->setUseInitialFlow(useInitFlow); OCL_OFF(algo->calc(frame1, frame2, flow));
OCL_ON(algo->calc(frame1, frame2, ocl_flow));
ASSERT_EQ(flow.rows, ocl_flow.rows);
ASSERT_EQ(flow.cols, ocl_flow.cols);
OCL_OFF(alg->calc(frame0, frame1, flow)); EXPECT_MAT_SIMILAR(flow, ocl_flow, 6e-3);
OCL_ON(alg->calc(frame0, frame1, uflow)); }
EXPECT_MAT_SIMILAR(flow, uflow, 1e-2);
} }
OCL_INSTANTIATE_TEST_CASE_P(Video, OpticalFlowTVL1, OCL_INSTANTIATE_TEST_CASE_P(Video, OCL_DenseOpticalFlow_DIS,
Combine( Values(DISOpticalFlow::PRESET_ULTRAFAST,
Values(UseInitFlow(false), UseInitFlow(true)), DISOpticalFlow::PRESET_FAST,
Values(MedianFiltering(3), MedianFiltering(-1)), DISOpticalFlow::PRESET_MEDIUM));
Values(ScaleStep(0.3),ScaleStep(0.5))
)
);
} } // namespace opencv_test::ocl }} // namespace
#endif // HAVE_OPENCL #endif // HAVE_OPENCL
...@@ -43,131 +43,105 @@ ...@@ -43,131 +43,105 @@
namespace opencv_test { namespace { namespace opencv_test { namespace {
//#define DUMP static string getDataDir() { return TS::ptr()->get_data_path(); }
// first four bytes, should be the same in little endian static string getRubberWhaleFrame1() { return getDataDir() + "optflow/RubberWhale1.png"; }
const float FLO_TAG_FLOAT = 202021.25f; // check for this when READING the file
#ifdef DUMP static string getRubberWhaleFrame2() { return getDataDir() + "optflow/RubberWhale2.png"; }
// binary file format for flow data specified here:
// http://vision.middlebury.edu/flow/data/
void writeOpticalFlowToFile(const Mat_<Point2f>& flow, const string& fileName)
{
const char FLO_TAG_STRING[] = "PIEH"; // use this when WRITING the file
ofstream file(fileName.c_str(), ios_base::binary);
file << FLO_TAG_STRING; static string getRubberWhaleGroundTruth() { return getDataDir() + "optflow/RubberWhale.flo"; }
file.write((const char*) &flow.cols, sizeof(int)); static bool isFlowCorrect(float u) { return !cvIsNaN(u) && (fabs(u) < 1e9); }
file.write((const char*) &flow.rows, sizeof(int));
for (int i = 0; i < flow.rows; ++i) static float calcRMSE(Mat flow1, Mat flow2)
{ {
for (int j = 0; j < flow.cols; ++j) float sum = 0;
{ int counter = 0;
const Point2f u = flow(i, j); const int rows = flow1.rows;
const int cols = flow1.cols;
file.write((const char*) &u.x, sizeof(float));
file.write((const char*) &u.y, sizeof(float));
}
}
}
#endif
// binary file format for flow data specified here: for (int y = 0; y < rows; ++y)
// http://vision.middlebury.edu/flow/data/
void readOpticalFlowFromFile(Mat_<Point2f>& flow, const string& fileName)
{ {
std::ifstream file(fileName.c_str(), std::ios_base::binary); for (int x = 0; x < cols; ++x)
float tag;
file.read((char*) &tag, sizeof(float));
CV_Assert( tag == FLO_TAG_FLOAT );
Size size;
file.read((char*) &size.width, sizeof(int));
file.read((char*) &size.height, sizeof(int));
flow.create(size);
for (int i = 0; i < flow.rows; ++i)
{ {
for (int j = 0; j < flow.cols; ++j) Vec2f flow1_at_point = flow1.at<Vec2f>(y, x);
{ Vec2f flow2_at_point = flow2.at<Vec2f>(y, x);
Point2f u;
file.read((char*) &u.x, sizeof(float));
file.read((char*) &u.y, sizeof(float));
flow(i, j) = u;
}
}
file.close();
}
bool isFlowCorrect(Point2f u) float u1 = flow1_at_point[0];
{ float v1 = flow1_at_point[1];
return !cvIsNaN(u.x) && !cvIsNaN(u.y) && (fabs(u.x) < 1e9) && (fabs(u.y) < 1e9); float u2 = flow2_at_point[0];
} float v2 = flow2_at_point[1];
void check(const Mat_<Point2f>& gold, const Mat_<Point2f>& flow, double threshold = 0.1, double expectedAccuracy = 0.95) if (isFlowCorrect(u1) && isFlowCorrect(u2) && isFlowCorrect(v1) && isFlowCorrect(v2))
{
threshold = threshold*threshold;
size_t gold_counter = 0;
size_t valid_counter = 0;
for (int i = 0; i < gold.rows; ++i)
{
for (int j = 0; j < gold.cols; ++j)
{ {
const Point2f u1 = gold(i, j); sum += (u1 - u2) * (u1 - u2) + (v1 - v2) * (v1 - v2);
const Point2f u2 = flow(i, j); counter++;
if (isFlowCorrect(u1))
{
gold_counter++;
if (isFlowCorrect(u2))
{
const Point2f diff = u1 - u2;
double err = diff.ddot(diff);
if (err <= threshold)
valid_counter++;
}
}
} }
} }
EXPECT_GE(valid_counter, expectedAccuracy * gold_counter);
} }
return (float)sqrt(sum / (1e-9 + counter));
}
TEST(Video_calcOpticalFlowDual_TVL1, Regression) bool readRubberWhale(Mat &dst_frame_1, Mat &dst_frame_2, Mat &dst_GT)
{ {
const string frame1_path = TS::ptr()->get_data_path() + "optflow/RubberWhale1.png"; const string frame1_path = getRubberWhaleFrame1();
const string frame2_path = TS::ptr()->get_data_path() + "optflow/RubberWhale2.png"; const string frame2_path = getRubberWhaleFrame2();
const string gold_flow_path = TS::ptr()->get_data_path() + "optflow/tvl1_flow.flo"; const string gt_flow_path = getRubberWhaleGroundTruth();
Mat frame1 = imread(frame1_path, IMREAD_GRAYSCALE); dst_frame_1 = imread(frame1_path);
Mat frame2 = imread(frame2_path, IMREAD_GRAYSCALE); dst_frame_2 = imread(frame2_path);
ASSERT_FALSE(frame1.empty()); dst_GT = readOpticalFlow(gt_flow_path);
ASSERT_FALSE(frame2.empty());
if (dst_frame_1.empty() || dst_frame_2.empty() || dst_GT.empty())
Mat_<Point2f> flow; return false;
Ptr<DualTVL1OpticalFlow> tvl1 = cv::DualTVL1OpticalFlow::create(); else
return true;
}
tvl1->calc(frame1, frame2, flow); TEST(DenseOpticalFlow_DIS, ReferenceAccuracy)
{
Mat frame1, frame2, GT;
ASSERT_TRUE(readRubberWhale(frame1, frame2, GT));
int presets[] = {DISOpticalFlow::PRESET_ULTRAFAST, DISOpticalFlow::PRESET_FAST, DISOpticalFlow::PRESET_MEDIUM};
float target_RMSE[] = {0.86f, 0.74f, 0.49f};
cvtColor(frame1, frame1, COLOR_BGR2GRAY);
cvtColor(frame2, frame2, COLOR_BGR2GRAY);
#ifdef DUMP Ptr<DenseOpticalFlow> algo;
writeOpticalFlowToFile(flow, gold_flow_path);
#else
Mat_<Point2f> gold;
readOpticalFlowFromFile(gold, gold_flow_path);
ASSERT_EQ(gold.rows, flow.rows); // iterate over presets:
ASSERT_EQ(gold.cols, flow.cols); for (int i = 0; i < 3; i++)
{
Mat flow;
algo = DISOpticalFlow::create(presets[i]);
algo->calc(frame1, frame2, flow);
ASSERT_EQ(GT.rows, flow.rows);
ASSERT_EQ(GT.cols, flow.cols);
EXPECT_LE(calcRMSE(GT, flow), target_RMSE[i]);
}
}
check(gold, flow); TEST(DenseOpticalFlow_VariationalRefinement, ReferenceAccuracy)
#endif {
Mat frame1, frame2, GT;
ASSERT_TRUE(readRubberWhale(frame1, frame2, GT));
float target_RMSE = 0.86f;
cvtColor(frame1, frame1, COLOR_BGR2GRAY);
cvtColor(frame2, frame2, COLOR_BGR2GRAY);
Ptr<VariationalRefinement> var_ref;
var_ref = VariationalRefinement::create();
var_ref->setAlpha(20.0f);
var_ref->setDelta(5.0f);
var_ref->setGamma(10.0f);
var_ref->setSorIterations(25);
var_ref->setFixedPointIterations(25);
Mat flow(frame1.size(), CV_32FC2);
flow.setTo(0.0f);
var_ref->calc(frame1, frame2, flow);
ASSERT_EQ(GT.rows, flow.rows);
ASSERT_EQ(GT.cols, flow.cols);
EXPECT_LE(calcRMSE(GT, flow), target_RMSE);
} }
}} // namespace }} // namespace
This diff is collapsed.
...@@ -6,5 +6,10 @@ ...@@ -6,5 +6,10 @@
#include "opencv2/ts.hpp" #include "opencv2/ts.hpp"
#include "opencv2/video.hpp" #include "opencv2/video.hpp"
#include <opencv2/ts/ts_perf.hpp>
namespace opencv_test {
using namespace perf;
}
#endif #endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -50,7 +50,7 @@ int main(int argc, const char* argv[]) ...@@ -50,7 +50,7 @@ int main(int argc, const char* argv[])
const char* keys = const char* keys =
"{ h help | | print help message }" "{ h help | | print help message }"
"{ c camera | 0 | capture video from camera (device index starting from 0) }" "{ c camera | 0 | capture video from camera (device index starting from 0) }"
"{ a algorithm | fb | algorithm (supported: 'fb', 'tvl')}" "{ a algorithm | fb | algorithm (supported: 'fb', 'dis')}"
"{ m cpu | | run without OpenCL }" "{ m cpu | | run without OpenCL }"
"{ v video | | use video as input }" "{ v video | | use video as input }"
"{ o original | | use original frame size (do not resize to 640x480)}" "{ o original | | use original frame size (do not resize to 640x480)}"
...@@ -84,11 +84,11 @@ int main(int argc, const char* argv[]) ...@@ -84,11 +84,11 @@ int main(int argc, const char* argv[])
return 2; return 2;
} }
cv::Ptr<cv::DenseOpticalFlow> alg; Ptr<DenseOpticalFlow> alg;
if (algorithm == "fb") if (algorithm == "fb")
alg = cv::FarnebackOpticalFlow::create(); alg = FarnebackOpticalFlow::create();
else if (algorithm == "tvl") else if (algorithm == "dis")
alg = cv::DualTVL1OpticalFlow::create(); alg = DISOpticalFlow::create(DISOpticalFlow::PRESET_FAST);
else else
{ {
cout << "Invalid algorithm: " << algorithm << endl; cout << "Invalid algorithm: " << algorithm << endl;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment