Merge remote-tracking branch 'upstream/3.4' into merge-3.4

pull/18944/head
Alexander Alekhin 4 years ago
commit 2155296a13
  1. 5
      cmake/OpenCVFindLibsPerf.cmake
  2. 2
      doc/py_tutorials/py_calib3d/py_calibration/py_calibration.markdown
  3. 2
      doc/tutorials/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_.markdown
  4. 3
      modules/core/src/copy.cpp
  5. 32
      modules/core/src/matrix_wrap.cpp
  6. 153
      modules/core/test/test_mat.cpp
  7. 2
      modules/dnn/include/opencv2/dnn/all_layers.hpp
  8. 195
      modules/dnn/src/layers/pooling_layer.cpp
  9. 16
      modules/dnn/src/ocl4dnn/src/ocl4dnn_pool.cpp
  10. 13
      modules/dnn/src/onnx/onnx_importer.cpp
  11. 81
      modules/dnn/test/test_onnx_importer.cpp
  12. 2
      modules/videoio/src/cap_openni2.cpp

@ -51,7 +51,10 @@ endif(WITH_CUDA)
# --- Eigen ---
if(WITH_EIGEN AND NOT HAVE_EIGEN)
if(NOT OPENCV_SKIP_EIGEN_FIND_PACKAGE_CONFIG)
if((OPENCV_FORCE_EIGEN_FIND_PACKAGE_CONFIG
OR NOT (CMAKE_VERSION VERSION_LESS "3.0.0") # Eigen3Targets.cmake required CMake 3.0.0+
) AND NOT OPENCV_SKIP_EIGEN_FIND_PACKAGE_CONFIG
)
find_package(Eigen3 CONFIG QUIET) # Ceres 2.0.0 CMake scripts doesn't work with CMake's FindEigen3.cmake module (due to missing EIGEN3_VERSION_STRING)
endif()
if(NOT Eigen3_FOUND)

@ -209,7 +209,7 @@ find the average error, we calculate the arithmetical mean of the errors calcula
calibration images.
@code{.py}
mean_error = 0
for i in xrange(len(objpoints)):
for i in range(len(objpoints)):
imgpoints2, _ = cv.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
error = cv.norm(imgpoints[i], imgpoints2, cv.NORM_L2)/len(imgpoints2)
mean_error += error

@ -32,7 +32,7 @@ automatically available with the platform (e.g. APPLE GCD) but chances are that
have access to a parallel framework either directly or by enabling the option in CMake and rebuild the library.
The second (weak) precondition is more related to the task you want to achieve as not all computations
are suitable / can be adatapted to be run in a parallel way. To remain simple, tasks that can be split
are suitable / can be adapted to be run in a parallel way. To remain simple, tasks that can be split
into multiple elementary operations with no memory dependency (no possible race condition) are easily
parallelizable. Computer vision processing are often easily parallelizable as most of the time the processing of
one pixel does not depend to the state of other pixels.

@ -1032,8 +1032,7 @@ void flip( InputArray _src, OutputArray _dst, int flip_mode )
}
if ((size.width == 1 && flip_mode > 0) ||
(size.height == 1 && flip_mode == 0) ||
(size.height == 1 && size.width == 1 && flip_mode < 0))
(size.height == 1 && flip_mode == 0))
{
return _src.copyTo(_dst);
}

@ -915,7 +915,7 @@ bool _InputArray::isContinuous(int i) const
if( k == STD_ARRAY_MAT )
{
const Mat* vv = (const Mat*)obj;
CV_Assert(i > 0 && i < sz.height);
CV_Assert(i >= 0 && i < sz.height);
return vv[i].isContinuous();
}
@ -949,21 +949,21 @@ bool _InputArray::isSubmatrix(int i) const
if( k == STD_VECTOR_MAT )
{
const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
CV_Assert((size_t)i < vv.size());
CV_Assert(i >= 0 && (size_t)i < vv.size());
return vv[i].isSubmatrix();
}
if( k == STD_ARRAY_MAT )
{
const Mat* vv = (const Mat*)obj;
CV_Assert(i < sz.height);
CV_Assert(i >= 0 && i < sz.height);
return vv[i].isSubmatrix();
}
if( k == STD_VECTOR_UMAT )
{
const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
CV_Assert((size_t)i < vv.size());
CV_Assert(i >= 0 && (size_t)i < vv.size());
return vv[i].isSubmatrix();
}
@ -994,9 +994,7 @@ size_t _InputArray::offset(int i) const
if( k == STD_VECTOR_MAT )
{
const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
if( i < 0 )
return 1;
CV_Assert( i < (int)vv.size() );
CV_Assert( i >= 0 && i < (int)vv.size() );
return (size_t)(vv[i].ptr() - vv[i].datastart);
}
@ -1004,16 +1002,14 @@ size_t _InputArray::offset(int i) const
if( k == STD_ARRAY_MAT )
{
const Mat* vv = (const Mat*)obj;
if( i < 0 )
return 1;
CV_Assert( i < sz.height );
CV_Assert( i >= 0 && i < sz.height );
return (size_t)(vv[i].ptr() - vv[i].datastart);
}
if( k == STD_VECTOR_UMAT )
{
const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
CV_Assert((size_t)i < vv.size());
CV_Assert(i >= 0 && (size_t)i < vv.size());
return vv[i].offset;
}
@ -1027,7 +1023,7 @@ size_t _InputArray::offset(int i) const
if (k == STD_VECTOR_CUDA_GPU_MAT)
{
const std::vector<cuda::GpuMat>& vv = *(const std::vector<cuda::GpuMat>*)obj;
CV_Assert((size_t)i < vv.size());
CV_Assert(i >= 0 && (size_t)i < vv.size());
return (size_t)(vv[i].data - vv[i].datastart);
}
@ -1057,25 +1053,21 @@ size_t _InputArray::step(int i) const
if( k == STD_VECTOR_MAT )
{
const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
if( i < 0 )
return 1;
CV_Assert( i < (int)vv.size() );
CV_Assert( i >= 0 && i < (int)vv.size() );
return vv[i].step;
}
if( k == STD_ARRAY_MAT )
{
const Mat* vv = (const Mat*)obj;
if( i < 0 )
return 1;
CV_Assert( i < sz.height );
CV_Assert( i >= 0 && i < sz.height );
return vv[i].step;
}
if( k == STD_VECTOR_UMAT )
{
const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
CV_Assert((size_t)i < vv.size());
CV_Assert(i >= 0 && (size_t)i < vv.size());
return vv[i].step;
}
@ -1087,7 +1079,7 @@ size_t _InputArray::step(int i) const
if (k == STD_VECTOR_CUDA_GPU_MAT)
{
const std::vector<cuda::GpuMat>& vv = *(const std::vector<cuda::GpuMat>*)obj;
CV_Assert((size_t)i < vv.size());
CV_Assert(i >= 0 && (size_t)i < vv.size());
return vv[i].step;
}

@ -9,6 +9,8 @@
#include "opencv2/core/eigen.hpp"
#endif
#include "opencv2/core/cuda.hpp"
namespace opencv_test { namespace {
class Core_ReduceTest : public cvtest::BaseTest
@ -1974,6 +1976,157 @@ TEST(Core_InputArray, fetch_MatExpr)
}
#ifdef CV_CXX11
class TestInputArrayRangeChecking {
static const char *kind2str(cv::_InputArray ia)
{
switch (ia.kind())
{
#define C(x) case cv::_InputArray::x: return #x
C(MAT);
C(UMAT);
C(EXPR);
C(MATX);
C(STD_VECTOR);
C(STD_ARRAY);
C(NONE);
C(STD_VECTOR_VECTOR);
C(STD_BOOL_VECTOR);
C(STD_VECTOR_MAT);
C(STD_ARRAY_MAT);
C(STD_VECTOR_UMAT);
C(CUDA_GPU_MAT);
C(STD_VECTOR_CUDA_GPU_MAT);
#undef C
default:
return "<unsupported>";
}
}
static void banner(cv::_InputArray ia, const char *label, const char *name)
{
std::cout << std::endl
<< label << " = " << name << ", Kind: " << kind2str(ia)
<< std::endl;
}
template<typename I, typename F>
static void testA(I ia, F f, const char *mfname)
{
banner(ia, "f", mfname);
EXPECT_THROW(f(ia, -1), cv::Exception)
<< "f(ia, " << -1 << ") should throw cv::Exception";
for (int i = 0; i < int(ia.size()); i++)
{
EXPECT_NO_THROW(f(ia, i))
<< "f(ia, " << i << ") should not throw an exception";
}
EXPECT_THROW(f(ia, int(ia.size())), cv::Exception)
<< "f(ia, " << ia.size() << ") should throw cv::Exception";
}
template<typename I, typename F>
static void testB(I ia, F f, const char *mfname)
{
banner(ia, "f", mfname);
EXPECT_THROW(f(ia, -1), cv::Exception)
<< "f(ia, " << -1 << ") should throw cv::Exception";
for (int i = 0; i < int(ia.size()); i++)
{
EXPECT_NO_THROW(f(ia, i))
<< "f(ia, " << i << ") should not throw an exception";
}
EXPECT_THROW(f(ia, int(ia.size())), cv::Exception)
<< "f(ia, " << ia.size() << ") should throw cv::Exception";
}
static void test_isContinuous()
{
auto f = [](cv::_InputArray ia, int i) { (void)ia.isContinuous(i); };
cv::Mat M;
cv::UMat uM;
std::vector<cv::Mat> vec = {M, M};
std::array<cv::Mat, 2> arr = {M, M};
std::vector<cv::UMat> uvec = {uM, uM};
testA(vec, f, "isContinuous");
testA(arr, f, "isContinuous");
testA(uvec, f, "isContinuous");
}
static void test_isSubmatrix()
{
auto f = [](cv::_InputArray ia, int i) { (void)ia.isSubmatrix(i); };
cv::Mat M;
cv::UMat uM;
std::vector<cv::Mat> vec = {M, M};
std::array<cv::Mat, 2> arr = {M, M};
std::vector<cv::UMat> uvec = {uM, uM};
testA(vec, f, "isSubmatrix");
testA(arr, f, "isSubmatrix");
testA(uvec, f, "isSubmatrix");
}
static void test_offset()
{
auto f = [](cv::_InputArray ia, int i) { return ia.offset(i); };
cv::Mat M;
cv::UMat uM;
cv::cuda::GpuMat gM;
std::vector<cv::Mat> vec = {M, M};
std::array<cv::Mat, 2> arr = {M, M};
std::vector<cv::UMat> uvec = {uM, uM};
std::vector<cv::cuda::GpuMat> gvec = {gM, gM};
testB(vec, f, "offset");
testB(arr, f, "offset");
testB(uvec, f, "offset");
testB(gvec, f, "offset");
}
static void test_step()
{
auto f = [](cv::_InputArray ia, int i) { return ia.step(i); };
cv::Mat M;
cv::UMat uM;
cv::cuda::GpuMat gM;
std::vector<cv::Mat> vec = {M, M};
std::array<cv::Mat, 2> arr = {M, M};
std::vector<cv::UMat> uvec = {uM, uM};
std::vector<cv::cuda::GpuMat> gvec = {gM, gM};
testB(vec, f, "step");
testB(arr, f, "step");
testB(uvec, f, "step");
testB(gvec, f, "step");
}
public:
static void run()
{
test_isContinuous();
test_isSubmatrix();
test_offset();
test_step();
}
};
TEST(Core_InputArray, range_checking)
{
TestInputArrayRangeChecking::run();
}
#endif
TEST(Core_Vectors, issue_13078)
{
float floats_[] = { 1, 2, 3, 4, 5, 6, 7, 8 };

@ -248,8 +248,6 @@ CV__DNN_INLINE_NS_BEGIN
int type;
std::vector<size_t> kernel_size, strides;
std::vector<size_t> pads_begin, pads_end;
CV_DEPRECATED_EXTERNAL Size kernel, stride, pad;
CV_DEPRECATED_EXTERNAL int pad_l, pad_t, pad_r, pad_b;
bool globalPooling; //!< Flag is true if at least one of the axes is global pooled.
std::vector<bool> isGlobalPooling;
bool computeMaxIdx;

@ -95,8 +95,6 @@ public:
computeMaxIdx = true;
globalPooling = false;
isGlobalPooling = std::vector<bool>(3, false);
stride = Size(1, 1);
pad_t = pad_l = pad_b = pad_r = 0;
hasDynamicShapes = params.get<bool>("has_dynamic_shapes", false);
shapesInitialized = !hasDynamicShapes;
@ -118,16 +116,6 @@ public:
getPoolingKernelParams(params, kernel_size, isGlobalPooling, pads_begin, pads_end, strides, padMode);
globalPooling = isGlobalPooling[0] || isGlobalPooling[1] || isGlobalPooling[2];
if (kernel_size.size() == 2) {
kernel = Size(kernel_size[1], kernel_size[0]);
stride = Size(strides[1], strides[0]);
pad = Size(pads_begin[1], pads_begin[0]);
pad_t = pads_begin[0];
pad_l = pads_begin[1];
pad_b = pads_end[0];
pad_r = pads_end[1];
}
}
else if (params.has("pooled_w") || params.has("pooled_h"))
{
@ -175,17 +163,20 @@ public:
finalKernel.push_back(isGlobalPooling[idx] ? inp[i] : kernel_size[idx]);
}
kernel_size = finalKernel;
kernel = Size(kernel_size[1], kernel_size[0]);
}
getConvPoolPaddings(inp, kernel_size, strides, padMode, pads_begin, pads_end);
if (pads_begin.size() == 2) {
pad_t = pads_begin[0];
pad_l = pads_begin[1];
pad_b = pads_end[0];
pad_r = pads_end[1];
if (inputs[0].dims == 3)
{
//Pool1D
kernel_size.erase(kernel_size.begin() + 1);
strides.erase(strides.begin() + 1);
pads_begin.erase(pads_begin.begin() + 1);
pads_end.erase(pads_end.begin() + 1);
}
#ifdef HAVE_OPENCL
poolOp.release();
#endif
@ -205,9 +196,11 @@ public:
return false;
if (kernel_size.size() == 3)
return preferableTarget == DNN_TARGET_CPU;
if (kernel_size.size() == 1)
return false;
if (preferableTarget == DNN_TARGET_MYRIAD || preferableTarget == DNN_TARGET_HDDL) {
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1)
if (type == MAX && (pad_l == 1 && pad_t == 1) && stride == Size(2, 2) ) {
if (type == MAX && (pads_begin[1] == 1 && pads_begin[0] == 1) && (strides[0] == 2 && strides[1] == 2)) {
return !isMyriadX();
}
#endif
@ -219,21 +212,30 @@ public:
#endif
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
{
return !computeMaxIdx && type != STOCHASTIC;
return !computeMaxIdx && type != STOCHASTIC && kernel_size.size() > 1;
}
if (backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE || backendId == DNN_BACKEND_VKCOM)
else if (backendId == DNN_BACKEND_OPENCV)
{
if (kernel_size.size() == 3)
return (backendId == DNN_BACKEND_OPENCV && preferableTarget == DNN_TARGET_CPU);
if (kernel_size.empty() || kernel_size.size() == 2)
return backendId == DNN_BACKEND_OPENCV ||
(backendId == DNN_BACKEND_HALIDE && haveHalide() &&
(type == MAX || (type == AVE && !pad_t && !pad_l && !pad_b && !pad_r))) ||
(backendId == DNN_BACKEND_VKCOM && haveVulkan() &&
(type == MAX || type == AVE));
return preferableTarget == DNN_TARGET_CPU;
if (kernel_size.size() <= 2)
return true;
else
return false;
}
else if (backendId == DNN_BACKEND_HALIDE)
{
if (kernel_size.empty() || kernel_size.size() == 2)
return haveHalide() &&
(type == MAX || (type == AVE && !pads_begin[0] && !pads_begin[1] && !pads_end[0] && !pads_end[1]));
}
else if (backendId == DNN_BACKEND_VKCOM)
{
if (kernel_size.empty() || kernel_size.size() == 2)
return haveVulkan() &&
(type == MAX || type == AVE);
return false;
}
return false;
}
@ -253,12 +255,25 @@ public:
config.in_shape = shape(inputs[0]);
config.out_shape = shape(outputs[0]);
config.kernel = kernel;
config.pad_l = pad_l;
config.pad_t = pad_t;
config.pad_r = pad_r;
config.pad_b = pad_b;
config.stride = stride;
if (inputs[0].dims == 3)
{
//Pool1D
config.kernel = Size(kernel_size[0], 1);
config.stride = Size(strides[0], 1);
config.pad_l = pads_begin[0];
config.pad_t = 0;
config.pad_r = pads_end[0];
config.pad_b = 0;
}
else
{
config.kernel = Size(kernel_size[1], kernel_size[0]);
config.stride = Size(strides[1], strides[0]);
config.pad_l = pads_begin[1];
config.pad_t = pads_begin[0];
config.pad_r = pads_end[1];
config.pad_b = pads_end[0];
}
config.channels = inputs[0].size[1];
config.pool_method = type == MAX ? LIBDNN_POOLING_METHOD_MAX :
(type == AVE ? LIBDNN_POOLING_METHOD_AVE :
@ -575,7 +590,6 @@ public:
public:
const Mat* src, *rois;
Mat *dst, *mask;
Size kernel, stride;
int pad_l, pad_t, pad_r, pad_b;
bool avePoolPaddedArea;
int nstripes;
@ -601,7 +615,7 @@ public:
CV_Assert_N(
src.isContinuous(), dst.isContinuous(),
src.type() == CV_32F, src.type() == dst.type(),
src.dims == 4 || src.dims == 5, dst.dims == 4 || dst.dims == 5,
src.dims == 3 || src.dims == 4 || src.dims == 5, dst.dims == 3 || dst.dims == 4 || dst.dims == 5,
(((poolingType == ROI || poolingType == PSROI) &&
dst.size[0] == rois.size[0]) || src.size[0] == dst.size[0]),
poolingType == PSROI || src.size[1] == dst.size[1],
@ -609,6 +623,9 @@ public:
PoolingInvoker p;
bool isPool1D = src.dims == 3;
bool isPool3D = src.dims == 5;
p.src = &src;
p.rois = &rois;
p.dst = &dst;
@ -619,12 +636,10 @@ public:
p.pads_end = pads_end;
p.mask = &mask;
p.kernel = Size(kernel_size[1], kernel_size[0]);
p.stride = Size(strides[1], strides[0]);
p.pad_l = pads_begin.back();
p.pad_t = pads_begin[pads_begin.size() - 2];
p.pad_t = isPool1D ? 0 : pads_begin[pads_begin.size() - 2];
p.pad_r = pads_end.back();
p.pad_b = pads_end[pads_end.size() - 2];
p.pad_b = isPool1D ? 0 : pads_end[pads_end.size() - 2];
p.avePoolPaddedArea = avePoolPaddedArea;
p.nstripes = nstripes;
@ -634,11 +649,11 @@ public:
if( !computeMaxIdx )
{
int height = src.size[src.dims - 2];
int height = isPool1D ? 1 : src.size[src.dims - 2];
int width = src.size[src.dims - 1];
int kernel_d = (kernel_size.size() == 3) ? kernel_size[0] : 1;
int kernel_h = kernel_size[kernel_size.size() - 2];
int kernel_d = isPool3D ? kernel_size[0] : 1;
int kernel_h = isPool1D ? 1 : kernel_size[kernel_size.size() - 2];
int kernel_w = kernel_size.back();
p.ofsbuf.resize(kernel_d * kernel_h * kernel_w);
@ -658,13 +673,15 @@ public:
{
int channels = dst->size[1];
bool isPool3D = src->dims == 5;
bool isPool2D = src->dims == 4;
int depth = !isPool2D? dst->size[2] : 1;
int height = dst->size[dst->dims - 2];
bool isPool1D = src->dims == 3;
int depth = isPool3D? dst->size[2] : 1;
int height = isPool1D? 1 : dst->size[dst->dims - 2];
int width = dst->size[dst->dims - 1];
int inp_depth = !isPool2D? src->size[2] : 1;
int inp_height = src->size[src->dims - 2];
int inp_depth = isPool3D? src->size[2] : 1;
int inp_height = isPool1D? 1 : src->size[src->dims - 2];
int inp_width = src->size[src->dims - 1];
size_t total = dst->total();
@ -672,12 +689,12 @@ public:
size_t stripeStart = r.start*stripeSize;
size_t stripeEnd = std::min(r.end*stripeSize, total);
int kernel_d = !isPool2D? kernel_size[0] : 1;
int kernel_h = kernel_size[kernel_size.size() - 2];
int kernel_d = isPool3D? kernel_size[0] : 1;
int kernel_h = isPool1D? 1 : kernel_size[kernel_size.size() - 2];
int kernel_w = kernel_size.back();
int stride_d = !isPool2D? strides[0] : 0;
int stride_h = strides[strides.size() - 2];
int stride_d = isPool3D? strides[0] : 0;
int stride_h = isPool1D? 1 :strides[strides.size() - 2];
int stride_w = strides.back();
bool compMaxIdx = computeMaxIdx;
@ -868,7 +885,24 @@ public:
}
}
else
#else
CV_UNUSED(isPool2D);
#endif
if( isPool1D )
{
const float* first = srcData + xstart;
const float* last = srcData + xend;
const float* max_elem = std::max_element(first, last);
if (max_elem!=last)
{
dstData[x0] = *max_elem;
if( compMaxIdx )
{
dstMaskData[x0] = std::distance(first, max_elem);
}
}
}
else
{
float max_val = -FLT_MAX;
if( compMaxIdx )
@ -942,6 +976,14 @@ public:
}
else
#endif
if( isPool1D )
{
const float* first = srcData + xstart;
const float* last = srcData + xend;
float sum_val = std::accumulate(first, last, 0.f);
dstData[x0] = sum_val*inv_kernel_area;
}
else
{
float sum_val = 0.f;
for (int d = dstart; d < dend; ++d) {
@ -1055,20 +1097,26 @@ public:
Halide::Buffer<float> inputBuffer = halideBuffer(inputs[0]);
const int inWidth = inputBuffer.width();
const int inHeight = inputBuffer.height();
const size_t kernelHeight = kernel_size[0];
const size_t kernelWidth = kernel_size[1];
const size_t strideHeight = strides[0];
const size_t strideWidth = strides[1];
const size_t paddingTop = pads_begin[0];
const size_t paddingLeft = pads_begin[1];
Halide::Var x("x"), y("y"), c("c"), n("n");
Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
Halide::RDom r(0, kernel.width, 0, kernel.height);
Halide::RDom r(0, kernelWidth, 0, kernelHeight);
Halide::Expr kx, ky;
if(pad_l || pad_t)
if(paddingLeft || paddingTop)
{
kx = clamp(x * stride.width + r.x - pad_l, 0, inWidth - 1);
ky = clamp(y * stride.height + r.y - pad_t, 0, inHeight - 1);
kx = clamp(x * strideWidth + r.x - paddingLeft, 0, inWidth - 1);
ky = clamp(y * strideHeight + r.y - paddingTop, 0, inHeight - 1);
}
else
{
kx = min(x * stride.width + r.x, inWidth - 1);
ky = min(y * stride.height + r.y, inHeight - 1);
kx = min(x * strideWidth + r.x, inWidth - 1);
ky = min(y * strideHeight + r.y, inHeight - 1);
}
// Halide::argmax returns tuple (r.x, r.y, max).
@ -1076,17 +1124,17 @@ public:
// Compute offset from argmax in range [0, kernel_size).
Halide::Expr max_index;
if(pad_l || pad_t)
if(paddingLeft || paddingTop)
{
max_index = clamp(y * stride.height + res[1] - pad_t,
max_index = clamp(y * strideHeight + res[1] - paddingTop,
0, inHeight - 1) * inWidth +
clamp(x * stride.width + res[0] - pad_l,
clamp(x * strideWidth + res[0] - paddingLeft,
0, inWidth - 1);
}
else
{
max_index = min(y * stride.height + res[1], inHeight - 1) * inWidth +
min(x * stride.width + res[0], inWidth - 1);
max_index = min(y * strideHeight + res[1], inHeight - 1) * inWidth +
min(x * strideWidth + res[0], inWidth - 1);
}
top(x, y, c, n) = { res[2], Halide::cast<float>(max_index) };
return Ptr<BackendNode>(new HalideBackendNode(top));
@ -1100,21 +1148,25 @@ public:
Halide::Buffer<float> inputBuffer = halideBuffer(inputs[0]);
const int inW = inputBuffer.width(), inH = inputBuffer.height();
if ((inW - kernel.width) % stride.width || (inH - kernel.height) % stride.height)
const size_t kernelHeight = kernel_size[0];
const size_t kernelWidth = kernel_size[1];
const size_t strideHeight = strides[0];
const size_t strideWidth = strides[1];
if ((inW - kernelWidth) % strideWidth || (inH - kernelHeight) % strideHeight)
{
CV_Error(cv::Error::StsNotImplemented,
"Halide backend for average pooling with partial "
"kernels is not implemented");
}
const float norm = 1.0f / (kernel.width * kernel.height);
const float norm = 1.0f / (kernelWidth * kernelHeight);
Halide::Var x("x"), y("y"), c("c"), n("n");
Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
Halide::RDom r(0, kernel.width, 0, kernel.height);
Halide::RDom r(0, kernelWidth, 0, kernelHeight);
top(x, y, c, n) = sum(
inputBuffer(x * stride.width + r.x,
y * stride.height + r.y, c, n)) * norm;
inputBuffer(x * strideWidth + r.x,
y * strideHeight + r.y, c, n)) * norm;
return Ptr<BackendNode>(new HalideBackendNode(top));
#endif // HAVE_HALIDE
return Ptr<BackendNode>();
@ -1176,6 +1228,7 @@ public:
{
CV_Assert(inputs.size() != 0);
bool isPool1D = inputs[0].size() == 3;
std::vector<int> inpShape(inputs[0].begin() + 2, inputs[0].end());
std::vector<int> outShape(inputs[0].begin(), inputs[0].begin() + 2);
@ -1204,14 +1257,15 @@ public:
}
else if (padMode.empty())
{
for (int i = 0; i < local_kernel.size(); i++) {
int addedDims = isPool1D? inpShape.size() : local_kernel.size();
for (int i = 0; i < addedDims; i++) {
float dst = (float) (inpShape[i] + pads_begin[i] + pads_end[i] - local_kernel[i]) / strides[i];
outShape.push_back(1 + (ceilMode ? ceil(dst) : floor(dst)));
}
// If we have padding, ensure that the last pooling starts strictly
// inside the image (instead of at the padding); otherwise clip the last.
for (int i = 0; i < pads_end.size(); i++) {
for (int i = 0; i < addedDims; i++) {
if (pads_end[i] && (outShape[2 + i] - 1) * strides[i] >= inpShape[i] + pads_end[i]) {
--outShape[2 + i];
CV_Assert((outShape[2 + i] - 1) * strides[i] < inpShape[i] + pads_end[i]);
@ -1255,7 +1309,8 @@ public:
{
CV_UNUSED(inputs); // suppress unused variable warning
long flops = 0;
size_t karea = std::accumulate(kernel_size.begin(), kernel_size.end(),
bool isPool1D = inputs[0].size() == 3;
size_t karea = std::accumulate(kernel_size.begin(), isPool1D? kernel_size.begin() + 1 : kernel_size.end(),
1, std::multiplies<size_t>());
for(int i = 0; i < outputs.size(); i++)
{

@ -51,18 +51,20 @@ template<typename Dtype>
OCL4DNNPool<Dtype>::OCL4DNNPool(OCL4DNNPoolConfig config)
{
int dims = config.in_shape.size();
int spatial_dims = 2;
int spatial_dims = config.in_shape.size()-2;
channels_ = config.channels;
pool_method_ = config.pool_method;
avePoolPaddedArea = config.avePoolPaddedArea;
computeMaxIdx = config.computeMaxIdx;
use_half = config.use_half;
kernel_shape_.push_back(config.kernel.height);
kernel_shape_.push_back(config.kernel.width);
stride_.push_back(config.stride.height);
stride_.push_back(config.stride.width);
for (int i = 0; i < spatial_dims; ++i)
{
kernel_shape_.push_back(i == 0 ? config.kernel.height : config.kernel.width);
stride_.push_back(i == 0 ? config.stride.height : config.stride.width);
im_in_shape_.push_back(config.in_shape[dims - spatial_dims + i]);
im_out_shape_.push_back(config.out_shape[dims - spatial_dims + i]);
}
@ -75,10 +77,10 @@ OCL4DNNPool<Dtype>::OCL4DNNPool(OCL4DNNPoolConfig config)
pad_l_ = config.pad_l;
pad_r_ = config.pad_r;
pad_b_ = config.pad_b;
height_ = im_in_shape_[0];
width_ = im_in_shape_[1];
pooled_height_ = im_out_shape_[0];
pooled_width_ = im_out_shape_[1];
height_ = spatial_dims == 1? 1 : im_in_shape_[0];
width_ = im_in_shape_.back();
pooled_height_ = spatial_dims == 1? 1 : im_out_shape_[0];
pooled_width_ = im_out_shape_.back();
count_ = 1;
for (int i = 0; i < config.out_shape.size(); ++i)

@ -500,14 +500,17 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
MatShape inpShape = outShapes[node_proto.input(0)];
DictValue axes = layerParams.get("axes");
bool keepdims = layerParams.get<int>("keepdims");
MatShape targetShape = inpShape;
MatShape targetShape;
std::vector<bool> shouldDelete(inpShape.size(), false);
for (int i = 0; i < axes.size(); i++) {
int axis = clamp(axes.get<int>(i), inpShape.size());
if (keepdims) {
targetShape[axis] = 1;
} else {
targetShape.erase(targetShape.begin() + axis);
shouldDelete[axis] = true;
}
for (int axis = 0; axis < inpShape.size(); ++axis){
if (!shouldDelete[axis])
targetShape.push_back(inpShape[axis]);
else if (keepdims)
targetShape.push_back(1);
}
if (inpShape.size() == 3 && axes.size() <= 2)

@ -756,6 +756,9 @@ TEST_P(Test_ONNX_layers, Conv1d_variable_weight_bias)
TEST_P(Test_ONNX_layers, GatherMultiOutput)
{
if (cvtest::skipUnstableTests && backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
throw SkipTestException("Skip unstable test: https://github.com/opencv/opencv/issues/18937");
#if defined(INF_ENGINE_RELEASE)
if (target == DNN_TARGET_MYRIAD)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE);
@ -785,6 +788,84 @@ TEST_P(Test_ONNX_layers, DynamicAxes)
testONNXModels("maxpooling_sigmoid_dynamic_axes");
}
TEST_P(Test_ONNX_layers, MaxPool1d)
{
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
{
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
}
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
{
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
}
testONNXModels("maxpooling_1d");
}
TEST_P(Test_ONNX_layers, MaxPoolSigmoid1d)
{
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
{
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
}
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
{
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
}
testONNXModels("maxpooling_sigmoid_1d");
}
TEST_P(Test_ONNX_layers, MaxPool1d_Twise)
{
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
{
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
}
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
{
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
}
testONNXModels("two_maxpooling_1d");
}
TEST_P(Test_ONNX_layers, AvePool1d)
{
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
{
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
}
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
{
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
}
testONNXModels("average_pooling_1d");
}
TEST_P(Test_ONNX_layers, PoolConv1d)
{
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
{
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
}
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
{
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
}
testONNXModels("pool_conv_1d");
}
TEST_P(Test_ONNX_layers, ConvResizePool1d)
{
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
{
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
}
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
{
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
}
testONNXModels("conv_resize_pool_1d");
}
INSTANTIATE_TEST_CASE_P(/*nothing*/, Test_ONNX_layers, dnnBackendsAndTargets());
class Test_ONNX_nets : public Test_ONNX_layers

@ -116,11 +116,11 @@ public:
CvCapture_OpenNI2(const char * filename);
virtual ~CvCapture_OpenNI2();
virtual int getCaptureDomain() CV_OVERRIDE { return cv::CAP_OPENNI2; }
virtual double getProperty(int propIdx) const CV_OVERRIDE;
virtual bool setProperty(int probIdx, double propVal) CV_OVERRIDE;
virtual bool grabFrame() CV_OVERRIDE;
virtual IplImage* retrieveFrame(int outputType) CV_OVERRIDE;
virtual int getCaptureDomain() CV_OVERRIDE { return cv::CAP_OPENNI2; }
bool isOpened() const;

Loading…
Cancel
Save