mirror of https://github.com/opencv/opencv.git
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_contribpull/13104/head
parent
841741aa52
commit
96bf26611e
23 changed files with 4308 additions and 2633 deletions
@ -0,0 +1,72 @@ |
||||
// 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
|
@ -1,111 +0,0 @@ |
||||
/*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) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// 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,
|
||||
// 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 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 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 "../perf_precomp.hpp" |
||||
#include "opencv2/ts/ocl_perf.hpp" |
||||
|
||||
#ifdef HAVE_OPENCL |
||||
|
||||
namespace opencv_test { |
||||
namespace ocl { |
||||
|
||||
///////////// OpticalFlow Dual TVL1 ////////////////////////
|
||||
typedef tuple< tuple<int, double>, bool> OpticalFlowDualTVL1Params; |
||||
typedef TestBaseWithParam<OpticalFlowDualTVL1Params> OpticalFlowDualTVL1Fixture; |
||||
|
||||
OCL_PERF_TEST_P(OpticalFlowDualTVL1Fixture, OpticalFlowDualTVL1, |
||||
::testing::Combine( |
||||
::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); |
||||
ASSERT_FALSE(frame1.empty()) << "can't load RubberWhale2.png"; |
||||
|
||||
const Size srcSize = frame0.size(); |
||||
|
||||
const OpticalFlowDualTVL1Params params = GetParam(); |
||||
const tuple<int, double> filteringScale = get<0>(params); |
||||
const int medianFiltering = get<0>(filteringScale); |
||||
const double scaleStep = get<1>(filteringScale); |
||||
const bool useInitFlow = get<1>(params); |
||||
double eps = 0.9; |
||||
|
||||
UMat uFrame0; frame0.copyTo(uFrame0); |
||||
UMat uFrame1; frame1.copyTo(uFrame1); |
||||
UMat uFlow(srcSize, CV_32FC2); |
||||
declare.in(uFrame0, uFrame1, WARMUP_READ).out(uFlow, WARMUP_READ); |
||||
|
||||
//create algorithm
|
||||
cv::Ptr<cv::DualTVL1OpticalFlow> alg = cv::createOptFlow_DualTVL1(); |
||||
|
||||
//set parameters
|
||||
alg->setScaleStep(scaleStep); |
||||
alg->setMedianFiltering(medianFiltering); |
||||
|
||||
if (useInitFlow) |
||||
{ |
||||
//calculate initial flow as result of optical flow
|
||||
alg->calc(uFrame0, uFrame1, uFlow); |
||||
} |
||||
|
||||
//set flag to use initial flow
|
||||
alg->setUseInitialFlow(useInitFlow); |
||||
OCL_TEST_CYCLE() |
||||
alg->calc(uFrame0, uFrame1, uFlow); |
||||
|
||||
SANITY_CHECK(uFlow, eps, ERROR_RELATIVE); |
||||
} |
||||
} |
||||
|
||||
} // namespace opencv_test::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
@ -0,0 +1,66 @@ |
||||
// 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
|
@ -1,31 +0,0 @@ |
||||
#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
|
@ -0,0 +1,40 @@ |
||||
// 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
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,521 @@ |
||||
// 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. |
||||
|
||||
#define EPS 0.001f |
||||
#define INF 1E+10F |
||||
|
||||
__kernel void dis_precomputeStructureTensor_hor(__global const short *I0x, |
||||
__global const short *I0y, |
||||
int patch_size, int patch_stride, |
||||
int w, int h, int ws, |
||||
__global float *I0xx_aux_ptr, |
||||
__global float *I0yy_aux_ptr, |
||||
__global float *I0xy_aux_ptr, |
||||
__global float *I0x_aux_ptr, |
||||
__global float *I0y_aux_ptr) |
||||
{ |
||||
|
||||
int i = get_global_id(0); |
||||
|
||||
if (i >= h) return; |
||||
|
||||
const __global short *x_row = I0x + i * w; |
||||
const __global short *y_row = I0y + i * w; |
||||
|
||||
float sum_xx = 0.0f, sum_yy = 0.0f, sum_xy = 0.0f, sum_x = 0.0f, sum_y = 0.0f; |
||||
float8 x_vec = convert_float8(vload8(0, x_row)); |
||||
float8 y_vec = convert_float8(vload8(0, y_row)); |
||||
sum_xx = dot(x_vec.lo, x_vec.lo) + dot(x_vec.hi, x_vec.hi); |
||||
sum_yy = dot(y_vec.lo, y_vec.lo) + dot(y_vec.hi, y_vec.hi); |
||||
sum_xy = dot(x_vec.lo, y_vec.lo) + dot(x_vec.hi, y_vec.hi); |
||||
sum_x = dot(x_vec.lo, 1.0f) + dot(x_vec.hi, 1.0f); |
||||
sum_y = dot(y_vec.lo, 1.0f) + dot(y_vec.hi, 1.0f); |
||||
|
||||
I0xx_aux_ptr[i * ws] = sum_xx; |
||||
I0yy_aux_ptr[i * ws] = sum_yy; |
||||
I0xy_aux_ptr[i * ws] = sum_xy; |
||||
I0x_aux_ptr[i * ws] = sum_x; |
||||
I0y_aux_ptr[i * ws] = sum_y; |
||||
|
||||
int js = 1; |
||||
for (int j = patch_size; j < w; j++) |
||||
{ |
||||
short x_val1 = x_row[j]; |
||||
short x_val2 = x_row[j - patch_size]; |
||||
short y_val1 = y_row[j]; |
||||
short y_val2 = y_row[j - patch_size]; |
||||
sum_xx += (x_val1 * x_val1 - x_val2 * x_val2); |
||||
sum_yy += (y_val1 * y_val1 - y_val2 * y_val2); |
||||
sum_xy += (x_val1 * y_val1 - x_val2 * y_val2); |
||||
sum_x += (x_val1 - x_val2); |
||||
sum_y += (y_val1 - y_val2); |
||||
if ((j - patch_size + 1) % patch_stride == 0) |
||||
{ |
||||
int index = i * ws + js; |
||||
I0xx_aux_ptr[index] = sum_xx; |
||||
I0yy_aux_ptr[index] = sum_yy; |
||||
I0xy_aux_ptr[index] = sum_xy; |
||||
I0x_aux_ptr[index] = sum_x; |
||||
I0y_aux_ptr[index] = sum_y; |
||||
js++; |
||||
} |
||||
} |
||||
} |
||||
|
||||
__kernel void dis_precomputeStructureTensor_ver(__global const float *I0xx_aux_ptr, |
||||
__global const float *I0yy_aux_ptr, |
||||
__global const float *I0xy_aux_ptr, |
||||
__global const float *I0x_aux_ptr, |
||||
__global const float *I0y_aux_ptr, |
||||
int patch_size, int patch_stride, |
||||
int w, int h, int ws, |
||||
__global float *I0xx_ptr, |
||||
__global float *I0yy_ptr, |
||||
__global float *I0xy_ptr, |
||||
__global float *I0x_ptr, |
||||
__global float *I0y_ptr) |
||||
{ |
||||
int j = get_global_id(0); |
||||
|
||||
if (j >= ws) return; |
||||
|
||||
float sum_xx, sum_yy, sum_xy, sum_x, sum_y; |
||||
sum_xx = sum_yy = sum_xy = sum_x = sum_y = 0.0f; |
||||
|
||||
for (int i = 0; i < patch_size; i++) |
||||
{ |
||||
sum_xx += I0xx_aux_ptr[i * ws + j]; |
||||
sum_yy += I0yy_aux_ptr[i * ws + j]; |
||||
sum_xy += I0xy_aux_ptr[i * ws + j]; |
||||
sum_x += I0x_aux_ptr[i * ws + j]; |
||||
sum_y += I0y_aux_ptr[i * ws + j]; |
||||
} |
||||
I0xx_ptr[j] = sum_xx; |
||||
I0yy_ptr[j] = sum_yy; |
||||
I0xy_ptr[j] = sum_xy; |
||||
I0x_ptr[j] = sum_x; |
||||
I0y_ptr[j] = sum_y; |
||||
|
||||
int is = 1; |
||||
for (int i = patch_size; i < h; i++) |
||||
{ |
||||
sum_xx += (I0xx_aux_ptr[i * ws + j] - I0xx_aux_ptr[(i - patch_size) * ws + j]); |
||||
sum_yy += (I0yy_aux_ptr[i * ws + j] - I0yy_aux_ptr[(i - patch_size) * ws + j]); |
||||
sum_xy += (I0xy_aux_ptr[i * ws + j] - I0xy_aux_ptr[(i - patch_size) * ws + j]); |
||||
sum_x += (I0x_aux_ptr[i * ws + j] - I0x_aux_ptr[(i - patch_size) * ws + j]); |
||||
sum_y += (I0y_aux_ptr[i * ws + j] - I0y_aux_ptr[(i - patch_size) * ws + j]); |
||||
|
||||
if ((i - patch_size + 1) % patch_stride == 0) |
||||
{ |
||||
I0xx_ptr[is * ws + j] = sum_xx; |
||||
I0yy_ptr[is * ws + j] = sum_yy; |
||||
I0xy_ptr[is * ws + j] = sum_xy; |
||||
I0x_ptr[is * ws + j] = sum_x; |
||||
I0y_ptr[is * ws + j] = sum_y; |
||||
is++; |
||||
} |
||||
} |
||||
} |
||||
|
||||
__kernel void dis_densification(__global const float *sx, __global const float *sy, |
||||
__global const uchar *i0, __global const uchar *i1, |
||||
int psz, int pstr, |
||||
int w, int h, int ws, |
||||
__global float *ux, __global float *uy) |
||||
{ |
||||
int x = get_global_id(0); |
||||
int y = get_global_id(1); |
||||
int i, j; |
||||
|
||||
if (x >= w || y >= h) return; |
||||
|
||||
int start_is, end_is; |
||||
int start_js, end_js; |
||||
|
||||
end_is = min(y / pstr, (h - psz) / pstr); |
||||
start_is = max(0, y - psz + pstr) / pstr; |
||||
start_is = min(start_is, end_is); |
||||
|
||||
end_js = min(x / pstr, (w - psz) / pstr); |
||||
start_js = max(0, x - psz + pstr) / pstr; |
||||
start_js = min(start_js, end_js); |
||||
|
||||
float coef, sum_coef = 0.0f; |
||||
float sum_Ux = 0.0f; |
||||
float sum_Uy = 0.0f; |
||||
|
||||
int i_l, i_u; |
||||
int j_l, j_u; |
||||
float i_m, j_m, diff; |
||||
|
||||
i = y; |
||||
j = x; |
||||
|
||||
/* Iterate through all the patches that overlap the current location (i,j) */ |
||||
for (int is = start_is; is <= end_is; is++) |
||||
for (int js = start_js; js <= end_js; js++) |
||||
{ |
||||
float sx_val = sx[is * ws + js]; |
||||
float sy_val = sy[is * ws + js]; |
||||
uchar2 i1_vec1, i1_vec2; |
||||
|
||||
j_m = min(max(j + sx_val, 0.0f), w - 1.0f - EPS); |
||||
i_m = min(max(i + sy_val, 0.0f), h - 1.0f - EPS); |
||||
j_l = (int)j_m; |
||||
j_u = j_l + 1; |
||||
i_l = (int)i_m; |
||||
i_u = i_l + 1; |
||||
i1_vec1 = vload2(0, i1 + i_u * w + j_l); |
||||
i1_vec2 = vload2(0, i1 + i_l * w + j_l); |
||||
diff = (j_m - j_l) * (i_m - i_l) * i1_vec1.y + |
||||
(j_u - j_m) * (i_m - i_l) * i1_vec1.x + |
||||
(j_m - j_l) * (i_u - i_m) * i1_vec2.y + |
||||
(j_u - j_m) * (i_u - i_m) * i1_vec2.x - i0[i * w + j]; |
||||
coef = 1 / max(1.0f, fabs(diff)); |
||||
sum_Ux += coef * sx_val; |
||||
sum_Uy += coef * sy_val; |
||||
sum_coef += coef; |
||||
} |
||||
|
||||
ux[i * w + j] = sum_Ux / sum_coef; |
||||
uy[i * w + j] = sum_Uy / sum_coef; |
||||
} |
||||
|
||||
#define INIT_BILINEAR_WEIGHTS(Ux, Uy) \ |
||||
i_I1 = min(max(i + Uy + bsz, i_lower_limit), i_upper_limit); \ |
||||
j_I1 = min(max(j + Ux + bsz, j_lower_limit), j_upper_limit); \ |
||||
\ |
||||
w11 = (i_I1 - floor(i_I1)) * (j_I1 - floor(j_I1)); \ |
||||
w10 = (i_I1 - floor(i_I1)) * (floor(j_I1) + 1 - j_I1); \ |
||||
w01 = (floor(i_I1) + 1 - i_I1) * (j_I1 - floor(j_I1)); \ |
||||
w00 = (floor(i_I1) + 1 - i_I1) * (floor(j_I1) + 1 - j_I1); |
||||
|
||||
float computeSSDMeanNorm(const __global uchar *I0_ptr, const __global uchar *I1_ptr, |
||||
int I0_stride, int I1_stride, |
||||
float w00, float w01, float w10, float w11, int patch_sz, int i) |
||||
{ |
||||
float sum_diff = 0.0f, sum_diff_sq = 0.0f; |
||||
int n = patch_sz * patch_sz; |
||||
|
||||
uchar8 I1_vec1, I1_vec2, I0_vec; |
||||
uchar I1_val1, I1_val2; |
||||
|
||||
I0_vec = vload8(0, I0_ptr + i * I0_stride); |
||||
I1_vec1 = vload8(0, I1_ptr + i * I1_stride); |
||||
I1_vec2 = vload8(0, I1_ptr + (i + 1) * I1_stride); |
||||
I1_val1 = I1_ptr[i * I1_stride + 8]; |
||||
I1_val2 = I1_ptr[(i + 1) * I1_stride + 8]; |
||||
|
||||
float8 vec = w00 * convert_float8(I1_vec1) + w01 * convert_float8((uchar8)(I1_vec1.s123, I1_vec1.s4567, I1_val1)) + |
||||
w10 * convert_float8(I1_vec2) + w11 * convert_float8((uchar8)(I1_vec2.s123, I1_vec2.s4567, I1_val2)) - |
||||
convert_float8(I0_vec); |
||||
|
||||
sum_diff = (dot(vec.lo, 1.0) + dot(vec.hi, 1.0)); |
||||
sum_diff_sq = (dot(vec.lo, vec.lo) + dot(vec.hi, vec.hi)); |
||||
|
||||
sum_diff = sub_group_reduce_add(sum_diff); |
||||
sum_diff_sq = sub_group_reduce_add(sum_diff_sq); |
||||
|
||||
return sum_diff_sq - sum_diff * sum_diff / n; |
||||
} |
||||
|
||||
__kernel void dis_patch_inverse_search_fwd_1(__global const float *Ux_ptr, __global const float *Uy_ptr, |
||||
__global const uchar *I0_ptr, __global const uchar *I1_ptr, |
||||
int border_size, int patch_size, int patch_stride, |
||||
int w, int h, int ws, int hs, int pyr_level, |
||||
__global float *Sx_ptr, __global float *Sy_ptr) |
||||
{ |
||||
int id = get_global_id(0); |
||||
int is = id / 8; |
||||
if (id >= (hs * 8)) return; |
||||
|
||||
int i = is * patch_stride; |
||||
int j = 0; |
||||
int psz = patch_size; |
||||
int psz2 = psz / 2; |
||||
int w_ext = w + 2 * border_size; |
||||
int bsz = border_size; |
||||
|
||||
float i_lower_limit = bsz - psz + 1.0f; |
||||
float i_upper_limit = bsz + h - 1.0f; |
||||
float j_lower_limit = bsz - psz + 1.0f; |
||||
float j_upper_limit = bsz + w - 1.0f; |
||||
float i_I1, j_I1, w00, w01, w10, w11; |
||||
|
||||
float prev_Ux = Ux_ptr[(i + psz2) * w + j + psz2]; |
||||
float prev_Uy = Uy_ptr[(i + psz2) * w + j + psz2]; |
||||
Sx_ptr[is * ws] = prev_Ux; |
||||
Sy_ptr[is * ws] = prev_Uy; |
||||
j += patch_stride; |
||||
|
||||
int sid = get_sub_group_local_id(); |
||||
for (int js = 1; js < ws; js++, j += patch_stride) |
||||
{ |
||||
float min_SSD, cur_SSD; |
||||
float Ux = Ux_ptr[(i + psz2) * w + j + psz2]; |
||||
float Uy = Uy_ptr[(i + psz2) * w + j + psz2]; |
||||
|
||||
INIT_BILINEAR_WEIGHTS(Ux, Uy); |
||||
min_SSD = computeSSDMeanNorm(I0_ptr + i * w + j, I1_ptr + (int)i_I1 * w_ext + (int)j_I1, |
||||
w, w_ext, w00, w01, w10, w11, psz, sid); |
||||
|
||||
INIT_BILINEAR_WEIGHTS(prev_Ux, prev_Uy); |
||||
cur_SSD = computeSSDMeanNorm(I0_ptr + i * w + j, I1_ptr + (int)i_I1 * w_ext + (int)j_I1, |
||||
w, w_ext, w00, w01, w10, w11, psz, sid); |
||||
if (cur_SSD < min_SSD) |
||||
{ |
||||
Ux = prev_Ux; |
||||
Uy = prev_Uy; |
||||
} |
||||
|
||||
prev_Ux = Ux; |
||||
prev_Uy = Uy; |
||||
Sx_ptr[is * ws + js] = Ux; |
||||
Sy_ptr[is * ws + js] = Uy; |
||||
} |
||||
} |
||||
|
||||
float3 processPatchMeanNorm(const __global uchar *I0_ptr, const __global uchar *I1_ptr, |
||||
const __global short *I0x_ptr, const __global short *I0y_ptr, |
||||
int I0_stride, int I1_stride, float w00, float w01, float w10, |
||||
float w11, int patch_sz, float x_grad_sum, float y_grad_sum) |
||||
{ |
||||
float sum_diff = 0.0, sum_diff_sq = 0.0; |
||||
float sum_I0x_mul = 0.0, sum_I0y_mul = 0.0; |
||||
int n = patch_sz * patch_sz; |
||||
uchar8 I1_vec1, I1_vec2; |
||||
uchar I1_val1, I1_val2; |
||||
|
||||
for (int i = 0; i < 8; i++) |
||||
{ |
||||
uchar8 I0_vec = vload8(0, I0_ptr + i * I0_stride); |
||||
|
||||
I1_vec1 = (i == 0) ? vload8(0, I1_ptr + i * I1_stride) : I1_vec2; |
||||
I1_vec2 = vload8(0, I1_ptr + (i + 1) * I1_stride); |
||||
I1_val1 = (i == 0) ? I1_ptr[i * I1_stride + patch_sz] : I1_val2; |
||||
I1_val2 = I1_ptr[(i + 1) * I1_stride + patch_sz]; |
||||
|
||||
float8 vec = w00 * convert_float8(I1_vec1) + w01 * convert_float8((uchar8)(I1_vec1.s123, I1_vec1.s4567, I1_val1)) + |
||||
w10 * convert_float8(I1_vec2) + w11 * convert_float8((uchar8)(I1_vec2.s123, I1_vec2.s4567, I1_val2)) - |
||||
convert_float8(I0_vec); |
||||
|
||||
sum_diff += (dot(vec.lo, 1.0) + dot(vec.hi, 1.0)); |
||||
sum_diff_sq += (dot(vec.lo, vec.lo) + dot(vec.hi, vec.hi)); |
||||
|
||||
short8 I0x_vec = vload8(0, I0x_ptr + i * I0_stride); |
||||
short8 I0y_vec = vload8(0, I0y_ptr + i * I0_stride); |
||||
|
||||
sum_I0x_mul += dot(vec.lo, convert_float4(I0x_vec.lo)); |
||||
sum_I0x_mul += dot(vec.hi, convert_float4(I0x_vec.hi)); |
||||
sum_I0y_mul += dot(vec.lo, convert_float4(I0y_vec.lo)); |
||||
sum_I0y_mul += dot(vec.hi, convert_float4(I0y_vec.hi)); |
||||
} |
||||
|
||||
float dst_dUx = sum_I0x_mul - sum_diff * x_grad_sum / n; |
||||
float dst_dUy = sum_I0y_mul - sum_diff * y_grad_sum / n; |
||||
float SSD = sum_diff_sq - sum_diff * sum_diff / n; |
||||
|
||||
return (float3)(SSD, dst_dUx, dst_dUy); |
||||
} |
||||
|
||||
__kernel void dis_patch_inverse_search_fwd_2(__global const float *Ux_ptr, __global const float *Uy_ptr, |
||||
__global const uchar *I0_ptr, __global const uchar *I1_ptr, |
||||
__global const short *I0x_ptr, __global const short *I0y_ptr, |
||||
__global const float *xx_ptr, __global const float *yy_ptr, |
||||
__global const float *xy_ptr, |
||||
__global const float *x_ptr, __global const float *y_ptr, |
||||
int border_size, int patch_size, int patch_stride, |
||||
int w, int h, int ws, int hs, int num_inner_iter, int pyr_level, |
||||
__global float *Sx_ptr, __global float *Sy_ptr) |
||||
{ |
||||
int js = get_global_id(0); |
||||
int is = get_global_id(1); |
||||
int i = is * patch_stride; |
||||
int j = js * patch_stride; |
||||
int psz = patch_size; |
||||
int psz2 = psz / 2; |
||||
int w_ext = w + 2 * border_size; |
||||
int bsz = border_size; |
||||
int index = is * ws + js; |
||||
|
||||
if (js >= ws || is >= hs) return; |
||||
|
||||
float Ux = Sx_ptr[index]; |
||||
float Uy = Sy_ptr[index]; |
||||
float cur_Ux = Ux; |
||||
float cur_Uy = Uy; |
||||
float cur_xx = xx_ptr[index]; |
||||
float cur_yy = yy_ptr[index]; |
||||
float cur_xy = xy_ptr[index]; |
||||
float detH = cur_xx * cur_yy - cur_xy * cur_xy; |
||||
|
||||
if (fabs(detH) < EPS) detH = EPS; |
||||
|
||||
float invH11 = cur_yy / detH; |
||||
float invH12 = -cur_xy / detH; |
||||
float invH22 = cur_xx / detH; |
||||
float prev_SSD = INF, SSD; |
||||
float x_grad_sum = x_ptr[index]; |
||||
float y_grad_sum = y_ptr[index]; |
||||
|
||||
float i_lower_limit = bsz - psz + 1.0f; |
||||
float i_upper_limit = bsz + h - 1.0f; |
||||
float j_lower_limit = bsz - psz + 1.0f; |
||||
float j_upper_limit = bsz + w - 1.0f; |
||||
float dUx, dUy, i_I1, j_I1, w00, w01, w10, w11, dx, dy; |
||||
float3 res; |
||||
|
||||
for (int t = 0; t < num_inner_iter; t++) |
||||
{ |
||||
INIT_BILINEAR_WEIGHTS(cur_Ux, cur_Uy); |
||||
res = processPatchMeanNorm(I0_ptr + i * w + j, |
||||
I1_ptr + (int)i_I1 * w_ext + (int)j_I1, I0x_ptr + i * w + j, |
||||
I0y_ptr + i * w + j, w, w_ext, w00, w01, w10, w11, psz, |
||||
x_grad_sum, y_grad_sum); |
||||
|
||||
SSD = res.x; |
||||
dUx = res.y; |
||||
dUy = res.z; |
||||
dx = invH11 * dUx + invH12 * dUy; |
||||
dy = invH12 * dUx + invH22 * dUy; |
||||
|
||||
cur_Ux -= dx; |
||||
cur_Uy -= dy; |
||||
|
||||
if (SSD >= prev_SSD) |
||||
break; |
||||
prev_SSD = SSD; |
||||
} |
||||
|
||||
float2 vec = (float2)(cur_Ux - Ux, cur_Uy - Uy); |
||||
if (dot(vec, vec) <= (float)(psz * psz)) |
||||
{ |
||||
Sx_ptr[index] = cur_Ux; |
||||
Sy_ptr[index] = cur_Uy; |
||||
} |
||||
} |
||||
|
||||
__kernel void dis_patch_inverse_search_bwd_1(__global const uchar *I0_ptr, __global const uchar *I1_ptr, |
||||
int border_size, int patch_size, int patch_stride, |
||||
int w, int h, int ws, int hs, int pyr_level, |
||||
__global float *Sx_ptr, __global float *Sy_ptr) |
||||
{ |
||||
int id = get_global_id(0); |
||||
int is = id / 8; |
||||
if (id >= (hs * 8)) return; |
||||
|
||||
is = (hs - 1 - is); |
||||
int i = is * patch_stride; |
||||
int j = (ws - 2) * patch_stride; |
||||
int psz = patch_size; |
||||
int psz2 = psz / 2; |
||||
int w_ext = w + 2 * border_size; |
||||
int bsz = border_size; |
||||
|
||||
float i_lower_limit = bsz - psz + 1.0f; |
||||
float i_upper_limit = bsz + h - 1.0f; |
||||
float j_lower_limit = bsz - psz + 1.0f; |
||||
float j_upper_limit = bsz + w - 1.0f; |
||||
float i_I1, j_I1, w00, w01, w10, w11; |
||||
|
||||
int sid = get_sub_group_local_id(); |
||||
for (int js = (ws - 2); js > -1; js--, j -= patch_stride) |
||||
{ |
||||
float min_SSD, cur_SSD; |
||||
float2 Ux = vload2(0, Sx_ptr + is * ws + js); |
||||
float2 Uy = vload2(0, Sy_ptr + is * ws + js); |
||||
|
||||
INIT_BILINEAR_WEIGHTS(Ux.x, Uy.x); |
||||
min_SSD = computeSSDMeanNorm(I0_ptr + i * w + j, I1_ptr + (int)i_I1 * w_ext + (int)j_I1, |
||||
w, w_ext, w00, w01, w10, w11, psz, sid); |
||||
|
||||
INIT_BILINEAR_WEIGHTS(Ux.y, Uy.y); |
||||
cur_SSD = computeSSDMeanNorm(I0_ptr + i * w + j, I1_ptr + (int)i_I1 * w_ext + (int)j_I1, |
||||
w, w_ext, w00, w01, w10, w11, psz, sid); |
||||
if (cur_SSD < min_SSD) |
||||
{ |
||||
Sx_ptr[is * ws + js] = Ux.y; |
||||
Sy_ptr[is * ws + js] = Uy.y; |
||||
} |
||||
} |
||||
} |
||||
|
||||
__kernel void dis_patch_inverse_search_bwd_2(__global const uchar *I0_ptr, __global const uchar *I1_ptr, |
||||
__global const short *I0x_ptr, __global const short *I0y_ptr, |
||||
__global const float *xx_ptr, __global const float *yy_ptr, |
||||
__global const float *xy_ptr, |
||||
__global const float *x_ptr, __global const float *y_ptr, |
||||
int border_size, int patch_size, int patch_stride, |
||||
int w, int h, int ws, int hs, int num_inner_iter, |
||||
__global float *Sx_ptr, __global float *Sy_ptr) |
||||
{ |
||||
int js = get_global_id(0); |
||||
int is = get_global_id(1); |
||||
if (js >= ws || is >= hs) return; |
||||
|
||||
js = (ws - 1 - js); |
||||
is = (hs - 1 - is); |
||||
|
||||
int j = js * patch_stride; |
||||
int i = is * patch_stride; |
||||
int psz = patch_size; |
||||
int psz2 = psz / 2; |
||||
int w_ext = w + 2 * border_size; |
||||
int bsz = border_size; |
||||
int index = is * ws + js; |
||||
|
||||
float Ux = Sx_ptr[index]; |
||||
float Uy = Sy_ptr[index]; |
||||
float cur_Ux = Ux; |
||||
float cur_Uy = Uy; |
||||
float cur_xx = xx_ptr[index]; |
||||
float cur_yy = yy_ptr[index]; |
||||
float cur_xy = xy_ptr[index]; |
||||
float detH = cur_xx * cur_yy - cur_xy * cur_xy; |
||||
|
||||
if (fabs(detH) < EPS) detH = EPS; |
||||
|
||||
float invH11 = cur_yy / detH; |
||||
float invH12 = -cur_xy / detH; |
||||
float invH22 = cur_xx / detH; |
||||
float prev_SSD = INF, SSD; |
||||
float x_grad_sum = x_ptr[index]; |
||||
float y_grad_sum = y_ptr[index]; |
||||
|
||||
float i_lower_limit = bsz - psz + 1.0f; |
||||
float i_upper_limit = bsz + h - 1.0f; |
||||
float j_lower_limit = bsz - psz + 1.0f; |
||||
float j_upper_limit = bsz + w - 1.0f; |
||||
float dUx, dUy, i_I1, j_I1, w00, w01, w10, w11, dx, dy; |
||||
float3 res; |
||||
|
||||
for (int t = 0; t < num_inner_iter; t++) |
||||
{ |
||||
INIT_BILINEAR_WEIGHTS(cur_Ux, cur_Uy); |
||||
res = processPatchMeanNorm(I0_ptr + i * w + j, |
||||
I1_ptr + (int)i_I1 * w_ext + (int)j_I1, I0x_ptr + i * w + j, |
||||
I0y_ptr + i * w + j, w, w_ext, w00, w01, w10, w11, psz, |
||||
x_grad_sum, y_grad_sum); |
||||
|
||||
SSD = res.x; |
||||
dUx = res.y; |
||||
dUy = res.z; |
||||
dx = invH11 * dUx + invH12 * dUy; |
||||
dy = invH12 * dUx + invH22 * dUy; |
||||
|
||||
cur_Ux -= dx; |
||||
cur_Uy -= dy; |
||||
|
||||
if (SSD >= prev_SSD) |
||||
break; |
||||
prev_SSD = SSD; |
||||
} |
||||
|
||||
float2 vec = (float2)(cur_Ux - Ux, cur_Uy - Uy); |
||||
if ((dot(vec, vec)) <= (float)(psz * psz)) |
||||
{ |
||||
Sx_ptr[index] = cur_Ux; |
||||
Sy_ptr[index] = cur_Uy; |
||||
} |
||||
} |
@ -1,378 +0,0 @@ |
||||
/*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) 2010-2012, Multicoreware, Inc., all rights reserved. |
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. |
||||
// Third party copyrights are property of their respective owners. |
||||
// |
||||
// @Authors |
||||
// Jin Ma jin@multicorewareinc.com |
||||
// |
||||
// 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 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 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*/ |
||||
|
||||
__kernel void centeredGradientKernel(__global const float* src_ptr, int src_col, int src_row, int src_step, |
||||
__global float* dx, __global float* dy, int d_step) |
||||
{ |
||||
int x = get_global_id(0); |
||||
int y = get_global_id(1); |
||||
|
||||
if((x < src_col)&&(y < src_row)) |
||||
{ |
||||
int src_x1 = (x + 1) < (src_col -1)? (x + 1) : (src_col - 1); |
||||
int src_x2 = (x - 1) > 0 ? (x -1) : 0; |
||||
dx[y * d_step+ x] = 0.5f * (src_ptr[y * src_step + src_x1] - src_ptr[y * src_step+ src_x2]); |
||||
|
||||
int src_y1 = (y+1) < (src_row - 1) ? (y + 1) : (src_row - 1); |
||||
int src_y2 = (y - 1) > 0 ? (y - 1) : 0; |
||||
dy[y * d_step+ x] = 0.5f * (src_ptr[src_y1 * src_step + x] - src_ptr[src_y2 * src_step+ x]); |
||||
} |
||||
|
||||
} |
||||
|
||||
inline float bicubicCoeff(float x_) |
||||
{ |
||||
|
||||
float x = fabs(x_); |
||||
if (x <= 1.0f) |
||||
return x * x * (1.5f * x - 2.5f) + 1.0f; |
||||
else if (x < 2.0f) |
||||
return x * (x * (-0.5f * x + 2.5f) - 4.0f) + 2.0f; |
||||
else |
||||
return 0.0f; |
||||
} |
||||
|
||||
__kernel void warpBackwardKernel(__global const float* I0, int I0_step, int I0_col, int I0_row, |
||||
image2d_t tex_I1, image2d_t tex_I1x, image2d_t tex_I1y, |
||||
__global const float* u1, int u1_step, |
||||
__global const float* u2, |
||||
__global float* I1w, |
||||
__global float* I1wx, /*int I1wx_step,*/ |
||||
__global float* I1wy, /*int I1wy_step,*/ |
||||
__global float* grad, /*int grad_step,*/ |
||||
__global float* rho, |
||||
int I1w_step, |
||||
int u2_step, |
||||
int u1_offset_x, |
||||
int u1_offset_y, |
||||
int u2_offset_x, |
||||
int u2_offset_y) |
||||
{ |
||||
int x = get_global_id(0); |
||||
int y = get_global_id(1); |
||||
|
||||
if(x < I0_col&&y < I0_row) |
||||
{ |
||||
//float u1Val = u1(y, x); |
||||
float u1Val = u1[(y + u1_offset_y) * u1_step + x + u1_offset_x]; |
||||
//float u2Val = u2(y, x); |
||||
float u2Val = u2[(y + u2_offset_y) * u2_step + x + u2_offset_x]; |
||||
|
||||
float wx = x + u1Val; |
||||
float wy = y + u2Val; |
||||
|
||||
int xmin = ceil(wx - 2.0f); |
||||
int xmax = floor(wx + 2.0f); |
||||
|
||||
int ymin = ceil(wy - 2.0f); |
||||
int ymax = floor(wy + 2.0f); |
||||
|
||||
float sum = 0.0f; |
||||
float sumx = 0.0f; |
||||
float sumy = 0.0f; |
||||
float wsum = 0.0f; |
||||
sampler_t sampleri = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST; |
||||
for (int cy = ymin; cy <= ymax; ++cy) |
||||
{ |
||||
for (int cx = xmin; cx <= xmax; ++cx) |
||||
{ |
||||
float w = bicubicCoeff(wx - cx) * bicubicCoeff(wy - cy); |
||||
//sum += w * tex2D(tex_I1 , cx, cy); |
||||
int2 cood = (int2)(cx, cy); |
||||
sum += w * read_imagef(tex_I1, sampleri, cood).x; |
||||
//sumx += w * tex2D(tex_I1x, cx, cy); |
||||
sumx += w * read_imagef(tex_I1x, sampleri, cood).x; |
||||
//sumy += w * tex2D(tex_I1y, cx, cy); |
||||
sumy += w * read_imagef(tex_I1y, sampleri, cood).x; |
||||
wsum += w; |
||||
} |
||||
} |
||||
float coeff = 1.0f / wsum; |
||||
float I1wVal = sum * coeff; |
||||
float I1wxVal = sumx * coeff; |
||||
float I1wyVal = sumy * coeff; |
||||
I1w[y * I1w_step + x] = I1wVal; |
||||
I1wx[y * I1w_step + x] = I1wxVal; |
||||
I1wy[y * I1w_step + x] = I1wyVal; |
||||
float Ix2 = I1wxVal * I1wxVal; |
||||
float Iy2 = I1wyVal * I1wyVal; |
||||
|
||||
// store the |Grad(I1)|^2 |
||||
grad[y * I1w_step + x] = Ix2 + Iy2; |
||||
|
||||
// compute the constant part of the rho function |
||||
float I0Val = I0[y * I0_step + x]; |
||||
rho[y * I1w_step + x] = I1wVal - I1wxVal * u1Val - I1wyVal * u2Val - I0Val; |
||||
} |
||||
} |
||||
|
||||
inline float readImage(__global const float *image, int x, int y, int rows, int cols, int elemCntPerRow) |
||||
{ |
||||
int i0 = clamp(x, 0, cols - 1); |
||||
int j0 = clamp(y, 0, rows - 1); |
||||
|
||||
return image[j0 * elemCntPerRow + i0]; |
||||
} |
||||
|
||||
__kernel void warpBackwardKernelNoImage2d(__global const float* I0, int I0_step, int I0_col, int I0_row, |
||||
__global const float* tex_I1, __global const float* tex_I1x, __global const float* tex_I1y, |
||||
__global const float* u1, int u1_step, |
||||
__global const float* u2, |
||||
__global float* I1w, |
||||
__global float* I1wx, /*int I1wx_step,*/ |
||||
__global float* I1wy, /*int I1wy_step,*/ |
||||
__global float* grad, /*int grad_step,*/ |
||||
__global float* rho, |
||||
int I1w_step, |
||||
int u2_step, |
||||
int I1_step, |
||||
int I1x_step) |
||||
{ |
||||
int x = get_global_id(0); |
||||
int y = get_global_id(1); |
||||
|
||||
if(x < I0_col&&y < I0_row) |
||||
{ |
||||
//float u1Val = u1(y, x); |
||||
float u1Val = u1[y * u1_step + x]; |
||||
//float u2Val = u2(y, x); |
||||
float u2Val = u2[y * u2_step + x]; |
||||
|
||||
float wx = x + u1Val; |
||||
float wy = y + u2Val; |
||||
|
||||
int xmin = ceil(wx - 2.0f); |
||||
int xmax = floor(wx + 2.0f); |
||||
|
||||
int ymin = ceil(wy - 2.0f); |
||||
int ymax = floor(wy + 2.0f); |
||||
|
||||
float sum = 0.0f; |
||||
float sumx = 0.0f; |
||||
float sumy = 0.0f; |
||||
float wsum = 0.0f; |
||||
|
||||
for (int cy = ymin; cy <= ymax; ++cy) |
||||
{ |
||||
for (int cx = xmin; cx <= xmax; ++cx) |
||||
{ |
||||
float w = bicubicCoeff(wx - cx) * bicubicCoeff(wy - cy); |
||||
|
||||
int2 cood = (int2)(cx, cy); |
||||
sum += w * readImage(tex_I1, cood.x, cood.y, I0_col, I0_row, I1_step); |
||||
sumx += w * readImage(tex_I1x, cood.x, cood.y, I0_col, I0_row, I1x_step); |
||||
sumy += w * readImage(tex_I1y, cood.x, cood.y, I0_col, I0_row, I1x_step); |
||||
wsum += w; |
||||
} |
||||
} |
||||
|
||||
float coeff = 1.0f / wsum; |
||||
|
||||
float I1wVal = sum * coeff; |
||||
float I1wxVal = sumx * coeff; |
||||
float I1wyVal = sumy * coeff; |
||||
|
||||
I1w[y * I1w_step + x] = I1wVal; |
||||
I1wx[y * I1w_step + x] = I1wxVal; |
||||
I1wy[y * I1w_step + x] = I1wyVal; |
||||
|
||||
float Ix2 = I1wxVal * I1wxVal; |
||||
float Iy2 = I1wyVal * I1wyVal; |
||||
|
||||
// store the |Grad(I1)|^2 |
||||
grad[y * I1w_step + x] = Ix2 + Iy2; |
||||
|
||||
// compute the constant part of the rho function |
||||
float I0Val = I0[y * I0_step + x]; |
||||
rho[y * I1w_step + x] = I1wVal - I1wxVal * u1Val - I1wyVal * u2Val - I0Val; |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
__kernel void estimateDualVariablesKernel(__global const float* u1, int u1_col, int u1_row, int u1_step, |
||||
__global const float* u2, |
||||
__global float* p11, int p11_step, |
||||
__global float* p12, |
||||
__global float* p21, |
||||
__global float* p22, |
||||
float taut, |
||||
int u2_step, |
||||
int u1_offset_x, |
||||
int u1_offset_y, |
||||
int u2_offset_x, |
||||
int u2_offset_y) |
||||
{ |
||||
int x = get_global_id(0); |
||||
int y = get_global_id(1); |
||||
|
||||
if(x < u1_col && y < u1_row) |
||||
{ |
||||
int src_x1 = (x + 1) < (u1_col - 1) ? (x + 1) : (u1_col - 1); |
||||
float u1x = u1[(y + u1_offset_y) * u1_step + src_x1 + u1_offset_x] - u1[(y + u1_offset_y) * u1_step + x + u1_offset_x]; |
||||
|
||||
int src_y1 = (y + 1) < (u1_row - 1) ? (y + 1) : (u1_row - 1); |
||||
float u1y = u1[(src_y1 + u1_offset_y) * u1_step + x + u1_offset_x] - u1[(y + u1_offset_y) * u1_step + x + u1_offset_x]; |
||||
|
||||
int src_x2 = (x + 1) < (u1_col - 1) ? (x + 1) : (u1_col - 1); |
||||
float u2x = u2[(y + u2_offset_y) * u2_step + src_x2 + u2_offset_x] - u2[(y + u2_offset_y) * u2_step + x + u2_offset_x]; |
||||
|
||||
int src_y2 = (y + 1) < (u1_row - 1) ? (y + 1) : (u1_row - 1); |
||||
float u2y = u2[(src_y2 + u2_offset_y) * u2_step + x + u2_offset_x] - u2[(y + u2_offset_y) * u2_step + x + u2_offset_x]; |
||||
|
||||
float g1 = hypot(u1x, u1y); |
||||
float g2 = hypot(u2x, u2y); |
||||
|
||||
float ng1 = 1.0f + taut * g1; |
||||
float ng2 = 1.0f + taut * g2; |
||||
|
||||
p11[y * p11_step + x] = (p11[y * p11_step + x] + taut * u1x) / ng1; |
||||
p12[y * p11_step + x] = (p12[y * p11_step + x] + taut * u1y) / ng1; |
||||
p21[y * p11_step + x] = (p21[y * p11_step + x] + taut * u2x) / ng2; |
||||
p22[y * p11_step + x] = (p22[y * p11_step + x] + taut * u2y) / ng2; |
||||
} |
||||
|
||||
} |
||||
|
||||
inline float divergence(__global const float* v1, __global const float* v2, int y, int x, int v1_step, int v2_step) |
||||
{ |
||||
|
||||
if (x > 0 && y > 0) |
||||
{ |
||||
float v1x = v1[y * v1_step + x] - v1[y * v1_step + x - 1]; |
||||
float v2y = v2[y * v2_step + x] - v2[(y - 1) * v2_step + x]; |
||||
return v1x + v2y; |
||||
} |
||||
else |
||||
{ |
||||
if (y > 0) |
||||
return v1[y * v1_step + 0] + v2[y * v2_step + 0] - v2[(y - 1) * v2_step + 0]; |
||||
else |
||||
{ |
||||
if (x > 0) |
||||
return v1[0 * v1_step + x] - v1[0 * v1_step + x - 1] + v2[0 * v2_step + x]; |
||||
else |
||||
return v1[0 * v1_step + 0] + v2[0 * v2_step + 0]; |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
__kernel void estimateUKernel(__global const float* I1wx, int I1wx_col, int I1wx_row, int I1wx_step, |
||||
__global const float* I1wy, /*int I1wy_step,*/ |
||||
__global const float* grad, /*int grad_step,*/ |
||||
__global const float* rho_c, /*int rho_c_step,*/ |
||||
__global const float* p11, /*int p11_step,*/ |
||||
__global const float* p12, /*int p12_step,*/ |
||||
__global const float* p21, /*int p21_step,*/ |
||||
__global const float* p22, /*int p22_step,*/ |
||||
__global float* u1, int u1_step, |
||||
__global float* u2, |
||||
__global float* error, float l_t, float theta, int u2_step, |
||||
int u1_offset_x, |
||||
int u1_offset_y, |
||||
int u2_offset_x, |
||||
int u2_offset_y, |
||||
char calc_error) |
||||
{ |
||||
int x = get_global_id(0); |
||||
int y = get_global_id(1); |
||||
|
||||
if(x < I1wx_col && y < I1wx_row) |
||||
{ |
||||
float I1wxVal = I1wx[y * I1wx_step + x]; |
||||
float I1wyVal = I1wy[y * I1wx_step + x]; |
||||
float gradVal = grad[y * I1wx_step + x]; |
||||
float u1OldVal = u1[(y + u1_offset_y) * u1_step + x + u1_offset_x]; |
||||
float u2OldVal = u2[(y + u2_offset_y) * u2_step + x + u2_offset_x]; |
||||
|
||||
float rho = rho_c[y * I1wx_step + x] + (I1wxVal * u1OldVal + I1wyVal * u2OldVal); |
||||
|
||||
// estimate the values of the variable (v1, v2) (thresholding operator TH) |
||||
|
||||
float d1 = 0.0f; |
||||
float d2 = 0.0f; |
||||
|
||||
if (rho < -l_t * gradVal) |
||||
{ |
||||
d1 = l_t * I1wxVal; |
||||
d2 = l_t * I1wyVal; |
||||
} |
||||
else if (rho > l_t * gradVal) |
||||
{ |
||||
d1 = -l_t * I1wxVal; |
||||
d2 = -l_t * I1wyVal; |
||||
} |
||||
else if (gradVal > 1.192092896e-07f) |
||||
{ |
||||
float fi = -rho / gradVal; |
||||
d1 = fi * I1wxVal; |
||||
d2 = fi * I1wyVal; |
||||
} |
||||
|
||||
float v1 = u1OldVal + d1; |
||||
float v2 = u2OldVal + d2; |
||||
|
||||
// compute the divergence of the dual variable (p1, p2) |
||||
|
||||
float div_p1 = divergence(p11, p12, y, x, I1wx_step, I1wx_step); |
||||
float div_p2 = divergence(p21, p22, y, x, I1wx_step, I1wx_step); |
||||
|
||||
// estimate the values of the optical flow (u1, u2) |
||||
|
||||
float u1NewVal = v1 + theta * div_p1; |
||||
float u2NewVal = v2 + theta * div_p2; |
||||
|
||||
u1[(y + u1_offset_y) * u1_step + x + u1_offset_x] = u1NewVal; |
||||
u2[(y + u2_offset_y) * u2_step + x + u2_offset_x] = u2NewVal; |
||||
|
||||
if(calc_error) |
||||
{ |
||||
float n1 = (u1OldVal - u1NewVal) * (u1OldVal - u1NewVal); |
||||
float n2 = (u2OldVal - u2NewVal) * (u2OldVal - u2NewVal); |
||||
error[y * I1wx_step + x] = n1 + n2; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,129 @@ |
||||
/*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 materials 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 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 "precomp.hpp" |
||||
#include<iostream> |
||||
#include<fstream> |
||||
|
||||
namespace cv { |
||||
|
||||
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
|
||||
|
||||
float tag; |
||||
file.read((char*) &tag, sizeof(float)); |
||||
if ( tag != FLOW_TAG_FLOAT ) |
||||
return flow; |
||||
|
||||
int width, height; |
||||
|
||||
file.read((char*) &width, 4); |
||||
file.read((char*) &height, 4); |
||||
|
||||
flow.create(height, width); |
||||
|
||||
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; |
||||
} |
||||
|
||||
CV_EXPORTS_W bool writeOpticalFlow( const String& path, InputArray flow ) |
||||
{ |
||||
const int nChannels = 2; |
||||
|
||||
Mat input = flow.getMat(); |
||||
if ( input.channels() != nChannels || input.depth() != CV_32F || path.length() == 0 ) |
||||
return false; |
||||
|
||||
std::ofstream file(path.c_str(), std::ofstream::binary); |
||||
if ( !file.good() ) |
||||
return false; |
||||
|
||||
int nRows, nCols; |
||||
|
||||
nRows = (int) input.size().height; |
||||
nCols = (int) input.size().width; |
||||
|
||||
const int headerSize = 12; |
||||
char header[headerSize]; |
||||
memcpy(header, FLOW_TAG_STRING, 4); |
||||
// 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; |
||||
|
||||
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; |
||||
} |
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,96 @@ |
||||
/*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" |
||||
#include "opencv2/ts/ocl_test.hpp" |
||||
|
||||
#ifdef HAVE_OPENCL |
||||
|
||||
namespace opencv_test { namespace { |
||||
|
||||
PARAM_TEST_CASE(OCL_DenseOpticalFlow_DIS, int) |
||||
{ |
||||
int preset; |
||||
|
||||
virtual void SetUp() |
||||
{ |
||||
preset = GET_PARAM(0); |
||||
} |
||||
}; |
||||
|
||||
OCL_TEST_P(OCL_DenseOpticalFlow_DIS, Mat) |
||||
{ |
||||
Mat frame1, frame2, GT; |
||||
|
||||
frame1 = imread(TS::ptr()->get_data_path() + "optflow/RubberWhale1.png"); |
||||
frame2 = imread(TS::ptr()->get_data_path() + "optflow/RubberWhale2.png"); |
||||
|
||||
CV_Assert(!frame1.empty() && !frame2.empty()); |
||||
|
||||
cvtColor(frame1, frame1, COLOR_BGR2GRAY); |
||||
cvtColor(frame2, frame2, COLOR_BGR2GRAY); |
||||
|
||||
Ptr<DenseOpticalFlow> algo; |
||||
|
||||
// iterate over presets:
|
||||
for (int i = 0; i < cvtest::ocl::test_loop_times; i++) |
||||
{ |
||||
Mat flow; |
||||
UMat ocl_flow; |
||||
|
||||
algo = DISOpticalFlow::create(preset); |
||||
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); |
||||
|
||||
EXPECT_MAT_SIMILAR(flow, ocl_flow, 6e-3); |
||||
} |
||||
} |
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Video, OCL_DenseOpticalFlow_DIS, |
||||
Values(DISOpticalFlow::PRESET_ULTRAFAST, |
||||
DISOpticalFlow::PRESET_FAST, |
||||
DISOpticalFlow::PRESET_MEDIUM)); |
||||
|
||||
}} // namespace
|
||||
|
||||
#endif // HAVE_OPENCL
|
@ -1,117 +0,0 @@ |
||||
/*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) 2010-2012, Institute Of Software Chinese Academy Of Science, 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.
|
||||
//
|
||||
// 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 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 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" |
||||
#include "opencv2/ts/ocl_test.hpp" |
||||
|
||||
#ifdef HAVE_OPENCL |
||||
|
||||
namespace opencv_test { |
||||
namespace ocl { |
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Optical_flow_tvl1
|
||||
namespace |
||||
{ |
||||
IMPLEMENT_PARAM_CLASS(UseInitFlow, bool) |
||||
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() |
||||
{ |
||||
useInitFlow = GET_PARAM(0); |
||||
medianFiltering = GET_PARAM(1); |
||||
scaleStep = GET_PARAM(2); |
||||
} |
||||
}; |
||||
|
||||
OCL_TEST_P(OpticalFlowTVL1, Mat) |
||||
{ |
||||
cv::Mat frame0 = readImage("optflow/RubberWhale1.png", cv::IMREAD_GRAYSCALE); |
||||
ASSERT_FALSE(frame0.empty()); |
||||
|
||||
cv::Mat frame1 = readImage("optflow/RubberWhale2.png", cv::IMREAD_GRAYSCALE); |
||||
ASSERT_FALSE(frame1.empty()); |
||||
|
||||
cv::Mat flow; cv::UMat uflow; |
||||
|
||||
//create algorithm
|
||||
cv::Ptr<cv::DualTVL1OpticalFlow> alg = cv::createOptFlow_DualTVL1(); |
||||
|
||||
//set parameters
|
||||
alg->setScaleStep(scaleStep); |
||||
alg->setMedianFiltering(medianFiltering); |
||||
|
||||
//create initial flow as result of algorithm calculation
|
||||
if (useInitFlow) |
||||
{ |
||||
OCL_ON(alg->calc(frame0, frame1, uflow)); |
||||
uflow.copyTo(flow); |
||||
} |
||||
|
||||
//set flag to use initial flow as it is ready to use
|
||||
alg->setUseInitialFlow(useInitFlow); |
||||
|
||||
OCL_OFF(alg->calc(frame0, frame1, flow)); |
||||
OCL_ON(alg->calc(frame0, frame1, uflow)); |
||||
|
||||
EXPECT_MAT_SIMILAR(flow, uflow, 1e-2); |
||||
} |
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Video, OpticalFlowTVL1, |
||||
Combine( |
||||
Values(UseInitFlow(false), UseInitFlow(true)), |
||||
Values(MedianFiltering(3), MedianFiltering(-1)), |
||||
Values(ScaleStep(0.3),ScaleStep(0.5)) |
||||
) |
||||
); |
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
@ -0,0 +1,147 @@ |
||||
/*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" |
||||
|
||||
namespace opencv_test { namespace { |
||||
|
||||
static string getDataDir() { return TS::ptr()->get_data_path(); } |
||||
|
||||
static string getRubberWhaleFrame1() { return getDataDir() + "optflow/RubberWhale1.png"; } |
||||
|
||||
static string getRubberWhaleFrame2() { return getDataDir() + "optflow/RubberWhale2.png"; } |
||||
|
||||
static string getRubberWhaleGroundTruth() { return getDataDir() + "optflow/RubberWhale.flo"; } |
||||
|
||||
static bool isFlowCorrect(float u) { return !cvIsNaN(u) && (fabs(u) < 1e9); } |
||||
|
||||
static float calcRMSE(Mat flow1, Mat flow2) |
||||
{ |
||||
float sum = 0; |
||||
int counter = 0; |
||||
const int rows = flow1.rows; |
||||
const int cols = flow1.cols; |
||||
|
||||
for (int y = 0; y < rows; ++y) |
||||
{ |
||||
for (int x = 0; x < cols; ++x) |
||||
{ |
||||
Vec2f flow1_at_point = flow1.at<Vec2f>(y, x); |
||||
Vec2f flow2_at_point = flow2.at<Vec2f>(y, x); |
||||
|
||||
float u1 = flow1_at_point[0]; |
||||
float v1 = flow1_at_point[1]; |
||||
float u2 = flow2_at_point[0]; |
||||
float v2 = flow2_at_point[1]; |
||||
|
||||
if (isFlowCorrect(u1) && isFlowCorrect(u2) && isFlowCorrect(v1) && isFlowCorrect(v2)) |
||||
{ |
||||
sum += (u1 - u2) * (u1 - u2) + (v1 - v2) * (v1 - v2); |
||||
counter++; |
||||
} |
||||
} |
||||
} |
||||
return (float)sqrt(sum / (1e-9 + counter)); |
||||
} |
||||
|
||||
bool readRubberWhale(Mat &dst_frame_1, Mat &dst_frame_2, Mat &dst_GT) |
||||
{ |
||||
const string frame1_path = getRubberWhaleFrame1(); |
||||
const string frame2_path = getRubberWhaleFrame2(); |
||||
const string gt_flow_path = getRubberWhaleGroundTruth(); |
||||
|
||||
dst_frame_1 = imread(frame1_path); |
||||
dst_frame_2 = imread(frame2_path); |
||||
dst_GT = readOpticalFlow(gt_flow_path); |
||||
|
||||
if (dst_frame_1.empty() || dst_frame_2.empty() || dst_GT.empty()) |
||||
return false; |
||||
else |
||||
return true; |
||||
} |
||||
|
||||
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); |
||||
|
||||
Ptr<DenseOpticalFlow> algo; |
||||
|
||||
// iterate over presets:
|
||||
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]); |
||||
} |
||||
} |
||||
|
||||
TEST(DenseOpticalFlow_VariationalRefinement, ReferenceAccuracy) |
||||
{ |
||||
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
|
@ -0,0 +1,160 @@ |
||||
/*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" |
||||
|
||||
namespace opencv_test { namespace { |
||||
|
||||
typedef tuple<Size> OFParams; |
||||
typedef TestWithParam<OFParams> DenseOpticalFlow_DIS; |
||||
typedef TestWithParam<OFParams> DenseOpticalFlow_VariationalRefinement; |
||||
|
||||
TEST_P(DenseOpticalFlow_DIS, MultithreadReproducibility) |
||||
{ |
||||
double MAX_DIF = 0.01; |
||||
double MAX_MEAN_DIF = 0.001; |
||||
int loopsCount = 2; |
||||
RNG rng(0); |
||||
|
||||
OFParams params = GetParam(); |
||||
Size size = get<0>(params); |
||||
|
||||
int nThreads = cv::getNumThreads(); |
||||
if (nThreads == 1) |
||||
throw SkipTestException("Single thread environment"); |
||||
for (int iter = 0; iter <= loopsCount; iter++) |
||||
{ |
||||
Mat frame1(size, CV_8U); |
||||
randu(frame1, 0, 255); |
||||
Mat frame2(size, CV_8U); |
||||
randu(frame2, 0, 255); |
||||
|
||||
Ptr<DISOpticalFlow> algo = DISOpticalFlow::create(); |
||||
int psz = rng.uniform(4, 16); |
||||
int pstr = rng.uniform(1, psz - 1); |
||||
int grad_iter = rng.uniform(1, 64); |
||||
int var_iter = rng.uniform(0, 10); |
||||
bool use_mean_normalization = !!rng.uniform(0, 2); |
||||
bool use_spatial_propagation = !!rng.uniform(0, 2); |
||||
algo->setFinestScale(0); |
||||
algo->setPatchSize(psz); |
||||
algo->setPatchStride(pstr); |
||||
algo->setGradientDescentIterations(grad_iter); |
||||
algo->setVariationalRefinementIterations(var_iter); |
||||
algo->setUseMeanNormalization(use_mean_normalization); |
||||
algo->setUseSpatialPropagation(use_spatial_propagation); |
||||
|
||||
cv::setNumThreads(nThreads); |
||||
Mat resMultiThread; |
||||
algo->calc(frame1, frame2, resMultiThread); |
||||
|
||||
cv::setNumThreads(1); |
||||
Mat resSingleThread; |
||||
algo->calc(frame1, frame2, resSingleThread); |
||||
|
||||
EXPECT_LE(cv::norm(resSingleThread, resMultiThread, NORM_INF), MAX_DIF); |
||||
EXPECT_LE(cv::norm(resSingleThread, resMultiThread, NORM_L1), MAX_MEAN_DIF * frame1.total()); |
||||
|
||||
// resulting flow should be within the frame bounds:
|
||||
double min_val, max_val; |
||||
minMaxLoc(resMultiThread, &min_val, &max_val); |
||||
EXPECT_LE(abs(min_val), sqrt( static_cast<double>(size.height * size.height + size.width * size.width)) ); |
||||
EXPECT_LE(abs(max_val), sqrt( static_cast<double>(size.height * size.height + size.width * size.width)) ); |
||||
} |
||||
} |
||||
|
||||
INSTANTIATE_TEST_CASE_P(FullSet, DenseOpticalFlow_DIS, Values(szODD, szQVGA)); |
||||
|
||||
TEST_P(DenseOpticalFlow_VariationalRefinement, MultithreadReproducibility) |
||||
{ |
||||
double MAX_DIF = 0.01; |
||||
double MAX_MEAN_DIF = 0.001; |
||||
float input_flow_rad = 5.0; |
||||
int loopsCount = 2; |
||||
RNG rng(0); |
||||
|
||||
OFParams params = GetParam(); |
||||
Size size = get<0>(params); |
||||
|
||||
int nThreads = cv::getNumThreads(); |
||||
if (nThreads == 1) |
||||
throw SkipTestException("Single thread environment"); |
||||
for (int iter = 0; iter <= loopsCount; iter++) |
||||
{ |
||||
Mat frame1(size, CV_8U); |
||||
randu(frame1, 0, 255); |
||||
Mat frame2(size, CV_8U); |
||||
randu(frame2, 0, 255); |
||||
Mat flow(size, CV_32FC2); |
||||
randu(flow, -input_flow_rad, input_flow_rad); |
||||
|
||||
Ptr<VariationalRefinement> var = VariationalRefinement::create(); |
||||
var->setAlpha(rng.uniform(1.0f, 100.0f)); |
||||
var->setGamma(rng.uniform(0.1f, 10.0f)); |
||||
var->setDelta(rng.uniform(0.1f, 10.0f)); |
||||
var->setSorIterations(rng.uniform(1, 20)); |
||||
var->setFixedPointIterations(rng.uniform(1, 20)); |
||||
var->setOmega(rng.uniform(1.01f, 1.99f)); |
||||
|
||||
cv::setNumThreads(nThreads); |
||||
Mat resMultiThread; |
||||
flow.copyTo(resMultiThread); |
||||
var->calc(frame1, frame2, resMultiThread); |
||||
|
||||
cv::setNumThreads(1); |
||||
Mat resSingleThread; |
||||
flow.copyTo(resSingleThread); |
||||
var->calc(frame1, frame2, resSingleThread); |
||||
|
||||
EXPECT_LE(cv::norm(resSingleThread, resMultiThread, NORM_INF), MAX_DIF); |
||||
EXPECT_LE(cv::norm(resSingleThread, resMultiThread, NORM_L1), MAX_MEAN_DIF * frame1.total()); |
||||
|
||||
// resulting flow should be within the frame bounds:
|
||||
double min_val, max_val; |
||||
minMaxLoc(resMultiThread, &min_val, &max_val); |
||||
EXPECT_LE(abs(min_val), sqrt( static_cast<double>(size.height * size.height + size.width * size.width)) ); |
||||
EXPECT_LE(abs(max_val), sqrt( static_cast<double>(size.height * size.height + size.width * size.width)) ); |
||||
} |
||||
} |
||||
|
||||
INSTANTIATE_TEST_CASE_P(FullSet, DenseOpticalFlow_VariationalRefinement, Values(szODD, szQVGA)); |
||||
|
||||
}} // namespace
|
@ -1,173 +0,0 @@ |
||||
/*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" |
||||
|
||||
namespace opencv_test { namespace { |
||||
|
||||
//#define DUMP
|
||||
|
||||
// first four bytes, should be the same in little endian
|
||||
const float FLO_TAG_FLOAT = 202021.25f; // check for this when READING the file
|
||||
|
||||
#ifdef DUMP |
||||
// 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; |
||||
|
||||
file.write((const char*) &flow.cols, sizeof(int)); |
||||
file.write((const char*) &flow.rows, sizeof(int)); |
||||
|
||||
for (int i = 0; i < flow.rows; ++i) |
||||
{ |
||||
for (int j = 0; j < flow.cols; ++j) |
||||
{ |
||||
const Point2f u = flow(i, j); |
||||
|
||||
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:
|
||||
// http://vision.middlebury.edu/flow/data/
|
||||
void readOpticalFlowFromFile(Mat_<Point2f>& flow, const string& fileName) |
||||
{ |
||||
std::ifstream file(fileName.c_str(), std::ios_base::binary); |
||||
|
||||
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) |
||||
{ |
||||
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) |
||||
{ |
||||
return !cvIsNaN(u.x) && !cvIsNaN(u.y) && (fabs(u.x) < 1e9) && (fabs(u.y) < 1e9); |
||||
} |
||||
|
||||
void check(const Mat_<Point2f>& gold, const Mat_<Point2f>& flow, double threshold = 0.1, double expectedAccuracy = 0.95) |
||||
{ |
||||
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); |
||||
const Point2f u2 = flow(i, j); |
||||
|
||||
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); |
||||
} |
||||
|
||||
TEST(Video_calcOpticalFlowDual_TVL1, Regression) |
||||
{ |
||||
const string frame1_path = TS::ptr()->get_data_path() + "optflow/RubberWhale1.png"; |
||||
const string frame2_path = TS::ptr()->get_data_path() + "optflow/RubberWhale2.png"; |
||||
const string gold_flow_path = TS::ptr()->get_data_path() + "optflow/tvl1_flow.flo"; |
||||
|
||||
Mat frame1 = imread(frame1_path, IMREAD_GRAYSCALE); |
||||
Mat frame2 = imread(frame2_path, IMREAD_GRAYSCALE); |
||||
ASSERT_FALSE(frame1.empty()); |
||||
ASSERT_FALSE(frame2.empty()); |
||||
|
||||
Mat_<Point2f> flow; |
||||
Ptr<DualTVL1OpticalFlow> tvl1 = cv::DualTVL1OpticalFlow::create(); |
||||
|
||||
tvl1->calc(frame1, frame2, flow); |
||||
|
||||
#ifdef DUMP |
||||
writeOpticalFlowToFile(flow, gold_flow_path); |
||||
#else |
||||
Mat_<Point2f> gold; |
||||
readOpticalFlowFromFile(gold, gold_flow_path); |
||||
|
||||
ASSERT_EQ(gold.rows, flow.rows); |
||||
ASSERT_EQ(gold.cols, flow.cols); |
||||
|
||||
check(gold, flow); |
||||
#endif |
||||
} |
||||
|
||||
}} // namespace
|
@ -0,0 +1,73 @@ |
||||
|
||||
#include "opencv2/core/utility.hpp" |
||||
#include "opencv2/highgui.hpp" |
||||
#include "opencv2/imgproc.hpp" |
||||
#include "opencv2/video.hpp" |
||||
|
||||
using namespace std; |
||||
using namespace cv; |
||||
|
||||
static void help() |
||||
{ |
||||
printf("Usage: dis_optflow <video_file>\n"); |
||||
} |
||||
|
||||
int main(int argc, char **argv) |
||||
{ |
||||
VideoCapture cap; |
||||
|
||||
if (argc < 2) |
||||
{ |
||||
help(); |
||||
exit(1); |
||||
} |
||||
|
||||
cap.open(argv[1]); |
||||
if(!cap.isOpened()) |
||||
{ |
||||
printf("ERROR: Cannot open file %s\n", argv[1]); |
||||
return -1; |
||||
} |
||||
|
||||
Mat prevgray, gray, rgb, frame; |
||||
Mat flow, flow_uv[2]; |
||||
Mat mag, ang; |
||||
Mat hsv_split[3], hsv; |
||||
char ret; |
||||
|
||||
namedWindow("flow", 1); |
||||
namedWindow("orig", 1); |
||||
|
||||
Ptr<DenseOpticalFlow> algorithm = DISOpticalFlow::create(DISOpticalFlow::PRESET_MEDIUM); |
||||
|
||||
while(true) |
||||
{ |
||||
cap >> frame; |
||||
if (frame.empty()) |
||||
break; |
||||
|
||||
cvtColor(frame, gray, COLOR_BGR2GRAY); |
||||
|
||||
if (!prevgray.empty()) |
||||
{ |
||||
algorithm->calc(prevgray, gray, flow); |
||||
split(flow, flow_uv); |
||||
multiply(flow_uv[1], -1, flow_uv[1]); |
||||
cartToPolar(flow_uv[0], flow_uv[1], mag, ang, true); |
||||
normalize(mag, mag, 0, 1, NORM_MINMAX); |
||||
hsv_split[0] = ang; |
||||
hsv_split[1] = mag; |
||||
hsv_split[2] = Mat::ones(ang.size(), ang.type()); |
||||
merge(hsv_split, 3, hsv); |
||||
cvtColor(hsv, rgb, COLOR_HSV2BGR); |
||||
imshow("flow", rgb); |
||||
imshow("orig", frame); |
||||
} |
||||
|
||||
if ((ret = (char)waitKey(20)) > 0) |
||||
break; |
||||
std::swap(prevgray, gray); |
||||
} |
||||
|
||||
return 0; |
||||
} |
@ -1,204 +0,0 @@ |
||||
#include <iostream> |
||||
#include <fstream> |
||||
|
||||
#include <opencv2/core/utility.hpp> |
||||
#include "opencv2/video.hpp" |
||||
#include "opencv2/imgcodecs.hpp" |
||||
#include "opencv2/highgui.hpp" |
||||
|
||||
using namespace cv; |
||||
using namespace std; |
||||
|
||||
inline bool isFlowCorrect(Point2f u) |
||||
{ |
||||
return !cvIsNaN(u.x) && !cvIsNaN(u.y) && fabs(u.x) < 1e9 && fabs(u.y) < 1e9; |
||||
} |
||||
|
||||
static Vec3b computeColor(float fx, float fy) |
||||
{ |
||||
static bool first = true; |
||||
|
||||
// relative lengths of color transitions:
|
||||
// these are chosen based on perceptual similarity
|
||||
// (e.g. one can distinguish more shades between red and yellow
|
||||
// than between yellow and green)
|
||||
const int RY = 15; |
||||
const int YG = 6; |
||||
const int GC = 4; |
||||
const int CB = 11; |
||||
const int BM = 13; |
||||
const int MR = 6; |
||||
const int NCOLS = RY + YG + GC + CB + BM + MR; |
||||
static Vec3i colorWheel[NCOLS]; |
||||
|
||||
if (first) |
||||
{ |
||||
int k = 0; |
||||
|
||||
for (int i = 0; i < RY; ++i, ++k) |
||||
colorWheel[k] = Vec3i(255, 255 * i / RY, 0); |
||||
|
||||
for (int i = 0; i < YG; ++i, ++k) |
||||
colorWheel[k] = Vec3i(255 - 255 * i / YG, 255, 0); |
||||
|
||||
for (int i = 0; i < GC; ++i, ++k) |
||||
colorWheel[k] = Vec3i(0, 255, 255 * i / GC); |
||||
|
||||
for (int i = 0; i < CB; ++i, ++k) |
||||
colorWheel[k] = Vec3i(0, 255 - 255 * i / CB, 255); |
||||
|
||||
for (int i = 0; i < BM; ++i, ++k) |
||||
colorWheel[k] = Vec3i(255 * i / BM, 0, 255); |
||||
|
||||
for (int i = 0; i < MR; ++i, ++k) |
||||
colorWheel[k] = Vec3i(255, 0, 255 - 255 * i / MR); |
||||
|
||||
first = false; |
||||
} |
||||
|
||||
const float rad = sqrt(fx * fx + fy * fy); |
||||
const float a = atan2(-fy, -fx) / (float)CV_PI; |
||||
|
||||
const float fk = (a + 1.0f) / 2.0f * (NCOLS - 1); |
||||
const int k0 = static_cast<int>(fk); |
||||
const int k1 = (k0 + 1) % NCOLS; |
||||
const float f = fk - k0; |
||||
|
||||
Vec3b pix; |
||||
|
||||
for (int b = 0; b < 3; b++) |
||||
{ |
||||
const float col0 = colorWheel[k0][b] / 255.f; |
||||
const float col1 = colorWheel[k1][b] / 255.f; |
||||
|
||||
float col = (1 - f) * col0 + f * col1; |
||||
|
||||
if (rad <= 1) |
||||
col = 1 - rad * (1 - col); // increase saturation with radius
|
||||
else |
||||
col *= .75; // out of range
|
||||
|
||||
pix[2 - b] = static_cast<uchar>(255.f * col); |
||||
} |
||||
|
||||
return pix; |
||||
} |
||||
|
||||
static void drawOpticalFlow(const Mat_<Point2f>& flow, Mat& dst, float maxmotion = -1) |
||||
{ |
||||
dst.create(flow.size(), CV_8UC3); |
||||
dst.setTo(Scalar::all(0)); |
||||
|
||||
// determine motion range:
|
||||
float maxrad = maxmotion; |
||||
|
||||
if (maxmotion <= 0) |
||||
{ |
||||
maxrad = 1; |
||||
for (int y = 0; y < flow.rows; ++y) |
||||
{ |
||||
for (int x = 0; x < flow.cols; ++x) |
||||
{ |
||||
Point2f u = flow(y, x); |
||||
|
||||
if (!isFlowCorrect(u)) |
||||
continue; |
||||
|
||||
maxrad = max(maxrad, sqrt(u.x * u.x + u.y * u.y)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
for (int y = 0; y < flow.rows; ++y) |
||||
{ |
||||
for (int x = 0; x < flow.cols; ++x) |
||||
{ |
||||
Point2f u = flow(y, x); |
||||
|
||||
if (isFlowCorrect(u)) |
||||
dst.at<Vec3b>(y, x) = computeColor(u.x / maxrad, u.y / maxrad); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// binary file format for flow data specified here:
|
||||
// http://vision.middlebury.edu/flow/data/
|
||||
static void writeOpticalFlowToFile(const Mat_<Point2f>& flow, const string& fileName) |
||||
{ |
||||
static const char FLO_TAG_STRING[] = "PIEH"; |
||||
|
||||
ofstream file(fileName.c_str(), ios_base::binary); |
||||
|
||||
file << FLO_TAG_STRING; |
||||
|
||||
file.write((const char*) &flow.cols, sizeof(int)); |
||||
file.write((const char*) &flow.rows, sizeof(int)); |
||||
|
||||
for (int i = 0; i < flow.rows; ++i) |
||||
{ |
||||
for (int j = 0; j < flow.cols; ++j) |
||||
{ |
||||
const Point2f u = flow(i, j); |
||||
|
||||
file.write((const char*) &u.x, sizeof(float)); |
||||
file.write((const char*) &u.y, sizeof(float)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
int main(int argc, const char* argv[]) |
||||
{ |
||||
cv::CommandLineParser parser(argc, argv, "{help h || show help message}" |
||||
"{ @frame0 | | frame 0}{ @frame1 | | frame 1}{ @output | | output flow}"); |
||||
if (parser.has("help")) |
||||
{ |
||||
parser.printMessage(); |
||||
return 0; |
||||
} |
||||
string frame0_name = parser.get<string>("@frame0"); |
||||
string frame1_name = parser.get<string>("@frame1"); |
||||
string file = parser.get<string>("@output"); |
||||
if (frame0_name.empty() || frame1_name.empty() || file.empty()) |
||||
{ |
||||
cerr << "Usage : " << argv[0] << " [<frame0>] [<frame1>] [<output_flow>]" << endl; |
||||
return -1; |
||||
} |
||||
|
||||
Mat frame0 = imread(frame0_name, IMREAD_GRAYSCALE); |
||||
Mat frame1 = imread(frame1_name, IMREAD_GRAYSCALE); |
||||
|
||||
if (frame0.empty()) |
||||
{ |
||||
cerr << "Can't open image [" << parser.get<string>("frame0") << "]" << endl; |
||||
return -1; |
||||
} |
||||
if (frame1.empty()) |
||||
{ |
||||
cerr << "Can't open image [" << parser.get<string>("frame1") << "]" << endl; |
||||
return -1; |
||||
} |
||||
|
||||
if (frame1.size() != frame0.size()) |
||||
{ |
||||
cerr << "Images should be of equal sizes" << endl; |
||||
return -1; |
||||
} |
||||
|
||||
Mat_<Point2f> flow; |
||||
Ptr<DualTVL1OpticalFlow> tvl1 = cv::DualTVL1OpticalFlow::create(); |
||||
|
||||
const double start = (double)getTickCount(); |
||||
tvl1->calc(frame0, frame1, flow); |
||||
const double timeSec = (getTickCount() - start) / getTickFrequency(); |
||||
cout << "calcOpticalFlowDual_TVL1 : " << timeSec << " sec" << endl; |
||||
|
||||
Mat out; |
||||
drawOpticalFlow(flow, out); |
||||
if (!file.empty()) |
||||
writeOpticalFlowToFile(flow, file); |
||||
|
||||
imshow("Flow", out); |
||||
waitKey(); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,114 @@ |
||||
#!/usr/bin/env python |
||||
|
||||
''' |
||||
example to show optical flow estimation using DISOpticalFlow |
||||
|
||||
USAGE: dis_opt_flow.py [<video_source>] |
||||
|
||||
Keys: |
||||
1 - toggle HSV flow visualization |
||||
2 - toggle glitch |
||||
3 - toggle spatial propagation of flow vectors |
||||
4 - toggle temporal propagation of flow vectors |
||||
ESC - exit |
||||
''' |
||||
|
||||
# Python 2/3 compatibility |
||||
from __future__ import print_function |
||||
|
||||
import numpy as np |
||||
import cv2 as cv |
||||
import video |
||||
|
||||
|
||||
def draw_flow(img, flow, step=16): |
||||
h, w = img.shape[:2] |
||||
y, x = np.mgrid[step/2:h:step, step/2:w:step].reshape(2,-1).astype(int) |
||||
fx, fy = flow[y,x].T |
||||
lines = np.vstack([x, y, x+fx, y+fy]).T.reshape(-1, 2, 2) |
||||
lines = np.int32(lines + 0.5) |
||||
vis = cv.cvtColor(img, cv.COLOR_GRAY2BGR) |
||||
cv.polylines(vis, lines, 0, (0, 255, 0)) |
||||
for (x1, y1), (x2, y2) in lines: |
||||
cv.circle(vis, (x1, y1), 1, (0, 255, 0), -1) |
||||
return vis |
||||
|
||||
|
||||
def draw_hsv(flow): |
||||
h, w = flow.shape[:2] |
||||
fx, fy = flow[:,:,0], flow[:,:,1] |
||||
ang = np.arctan2(fy, fx) + np.pi |
||||
v = np.sqrt(fx*fx+fy*fy) |
||||
hsv = np.zeros((h, w, 3), np.uint8) |
||||
hsv[...,0] = ang*(180/np.pi/2) |
||||
hsv[...,1] = 255 |
||||
hsv[...,2] = np.minimum(v*4, 255) |
||||
bgr = cv.cvtColor(hsv, cv.COLOR_HSV2BGR) |
||||
return bgr |
||||
|
||||
|
||||
def warp_flow(img, flow): |
||||
h, w = flow.shape[:2] |
||||
flow = -flow |
||||
flow[:,:,0] += np.arange(w) |
||||
flow[:,:,1] += np.arange(h)[:,np.newaxis] |
||||
res = cv.remap(img, flow, None, cv.INTER_LINEAR) |
||||
return res |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
import sys |
||||
print(__doc__) |
||||
try: |
||||
fn = sys.argv[1] |
||||
except IndexError: |
||||
fn = 0 |
||||
|
||||
cam = video.create_capture(fn) |
||||
ret, prev = cam.read() |
||||
prevgray = cv.cvtColor(prev, cv.COLOR_BGR2GRAY) |
||||
show_hsv = False |
||||
show_glitch = False |
||||
use_spatial_propagation = False |
||||
use_temporal_propagation = True |
||||
cur_glitch = prev.copy() |
||||
inst = cv.DISOpticalFlow.create(cv.DISOPTICAL_FLOW_PRESET_MEDIUM) |
||||
inst.setUseSpatialPropagation(use_spatial_propagation) |
||||
|
||||
flow = None |
||||
while True: |
||||
ret, img = cam.read() |
||||
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) |
||||
if flow is not None and use_temporal_propagation: |
||||
#warp previous flow to get an initial approximation for the current flow: |
||||
flow = inst.calc(prevgray, gray, warp_flow(flow,flow)) |
||||
else: |
||||
flow = inst.calc(prevgray, gray, None) |
||||
prevgray = gray |
||||
|
||||
cv.imshow('flow', draw_flow(gray, flow)) |
||||
if show_hsv: |
||||
cv.imshow('flow HSV', draw_hsv(flow)) |
||||
if show_glitch: |
||||
cur_glitch = warp_flow(cur_glitch, flow) |
||||
cv.imshow('glitch', cur_glitch) |
||||
|
||||
ch = 0xFF & cv.waitKey(5) |
||||
if ch == 27: |
||||
break |
||||
if ch == ord('1'): |
||||
show_hsv = not show_hsv |
||||
print('HSV flow visualization is', ['off', 'on'][show_hsv]) |
||||
if ch == ord('2'): |
||||
show_glitch = not show_glitch |
||||
if show_glitch: |
||||
cur_glitch = img.copy() |
||||
print('glitch is', ['off', 'on'][show_glitch]) |
||||
if ch == ord('3'): |
||||
use_spatial_propagation = not use_spatial_propagation |
||||
inst.setUseSpatialPropagation(use_spatial_propagation) |
||||
print('spatial propagation is', ['off', 'on'][use_spatial_propagation]) |
||||
if ch == ord('4'): |
||||
use_temporal_propagation = not use_temporal_propagation |
||||
print('temporal propagation is', ['off', 'on'][use_temporal_propagation]) |
||||
cv.destroyAllWindows() |
Loading…
Reference in new issue