Skip to content

Commit f52a2cf

Browse files
committed
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
2 parents 95fd61c + 5e90802 commit f52a2cf

File tree

14 files changed

+181
-40
lines changed

14 files changed

+181
-40
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@ OCV_OPTION(BUILD_OBJC "Enable Objective-C support"
464464
# OpenCV installation options
465465
# ===================================================
466466
OCV_OPTION(INSTALL_CREATE_DISTRIB "Change install rules to build the distribution package" OFF )
467+
OCV_OPTION(INSTALL_BIN_EXAMPLES "Install prebuilt examples" WIN32 IF BUILD_EXAMPLES)
467468
OCV_OPTION(INSTALL_C_EXAMPLES "Install C examples" OFF )
468469
OCV_OPTION(INSTALL_PYTHON_EXAMPLES "Install Python examples" OFF )
469470
OCV_OPTION(INSTALL_ANDROID_EXAMPLES "Install Android examples" OFF IF ANDROID )

cmake/OpenCVModule.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1364,8 +1364,8 @@ function(ocv_add_samples)
13641364
add_dependencies(${the_target} opencv_videoio_plugins)
13651365
endif()
13661366

1367-
if(WIN32)
1368-
install(TARGETS ${the_target} RUNTIME DESTINATION "samples/${module_id}" COMPONENT samples)
1367+
if(INSTALL_BIN_EXAMPLES)
1368+
install(TARGETS ${the_target} RUNTIME DESTINATION "${OPENCV_SAMPLES_BIN_INSTALL_PATH}/${module_id}" COMPONENT samples)
13691369
endif()
13701370
endforeach()
13711371
endif()

doc/py_tutorials/py_imgproc/py_contours/py_contour_properties/py_contour_properties.markdown

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ pixelpoints = np.transpose(np.nonzero(mask))
7878
Here, two methods, one using Numpy functions, next one using OpenCV function (last commented line)
7979
are given to do the same. Results are also same, but with a slight difference. Numpy gives
8080
coordinates in **(row, column)** format, while OpenCV gives coordinates in **(x,y)** format. So
81-
basically the answers will be interchanged. Note that, **row = x** and **column = y**.
81+
basically the answers will be interchanged. Note that, **row = y** and **column = x**.
8282

8383
7. Maximum Value, Minimum Value and their locations
8484
---------------------------------------------------

modules/core/src/matrix_wrap.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,6 +1248,7 @@ void _OutputArray::create(int d, const int* sizes, int mtype, int i,
12481248
{
12491249
CV_Assert( i < 0 );
12501250
Mat& m = *(Mat*)obj;
1251+
CV_Assert(!(m.empty() && fixedType() && fixedSize()) && "Can't reallocate empty Mat with locked layout (probably due to misused 'const' modifier)");
12511252
if (allowTransposed && !m.empty() &&
12521253
d == 2 && m.dims == 2 &&
12531254
m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] &&
@@ -1261,13 +1262,13 @@ void _OutputArray::create(int d, const int* sizes, int mtype, int i,
12611262
if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 )
12621263
mtype = m.type();
12631264
else
1264-
CV_CheckTypeEQ(m.type(), CV_MAT_TYPE(mtype), "");
1265+
CV_CheckTypeEQ(m.type(), CV_MAT_TYPE(mtype), "Can't reallocate Mat with locked type (probably due to misused 'const' modifier)");
12651266
}
12661267
if(fixedSize())
12671268
{
1268-
CV_CheckEQ(m.dims, d, "");
1269+
CV_CheckEQ(m.dims, d, "Can't reallocate Mat with locked size (probably due to misused 'const' modifier)");
12691270
for(int j = 0; j < d; ++j)
1270-
CV_CheckEQ(m.size[j], sizes[j], "");
1271+
CV_CheckEQ(m.size[j], sizes[j], "Can't reallocate Mat with locked size (probably due to misused 'const' modifier)");
12711272
}
12721273
m.create(d, sizes, mtype);
12731274
return;
@@ -1277,6 +1278,7 @@ void _OutputArray::create(int d, const int* sizes, int mtype, int i,
12771278
{
12781279
CV_Assert( i < 0 );
12791280
UMat& m = *(UMat*)obj;
1281+
CV_Assert(!(m.empty() && fixedType() && fixedSize()) && "Can't reallocate empty UMat with locked layout (probably due to misused 'const' modifier)");
12801282
if (allowTransposed && !m.empty() &&
12811283
d == 2 && m.dims == 2 &&
12821284
m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] &&
@@ -1290,13 +1292,13 @@ void _OutputArray::create(int d, const int* sizes, int mtype, int i,
12901292
if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 )
12911293
mtype = m.type();
12921294
else
1293-
CV_CheckTypeEQ(m.type(), CV_MAT_TYPE(mtype), "");
1295+
CV_CheckTypeEQ(m.type(), CV_MAT_TYPE(mtype), "Can't reallocate UMat with locked type (probably due to misused 'const' modifier)");
12941296
}
12951297
if(fixedSize())
12961298
{
1297-
CV_CheckEQ(m.dims, d, "");
1299+
CV_CheckEQ(m.dims, d, "Can't reallocate UMat with locked size (probably due to misused 'const' modifier)");
12981300
for(int j = 0; j < d; ++j)
1299-
CV_CheckEQ(m.size[j], sizes[j], "");
1301+
CV_CheckEQ(m.size[j], sizes[j], "Can't reallocate UMat with locked size (probably due to misused 'const' modifier)");
13001302
}
13011303
m.create(d, sizes, mtype);
13021304
return;

modules/core/src/ocl.cpp

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3311,7 +3311,7 @@ KernelArg KernelArg::Constant(const Mat& m)
33113311
struct Kernel::Impl
33123312
{
33133313
Impl(const char* kname, const Program& prog) :
3314-
refcount(1), handle(NULL), isInProgress(false), nu(0)
3314+
refcount(1), handle(NULL), isInProgress(false), isAsyncRun(false), nu(0)
33153315
{
33163316
cl_program ph = (cl_program)prog.ptr();
33173317
cl_int retval = 0;
@@ -3388,6 +3388,7 @@ struct Kernel::Impl
33883388
enum { MAX_ARRS = 16 };
33893389
UMatData* u[MAX_ARRS];
33903390
bool isInProgress;
3391+
bool isAsyncRun; // true if kernel was scheduled in async mode
33913392
int nu;
33923393
std::list<Image2D> images;
33933394
bool haveTempDstUMats;
@@ -3667,13 +3668,45 @@ bool Kernel::run(int dims, size_t _globalsize[], size_t _localsize[],
36673668
}
36683669

36693670

3671+
static bool isRaiseErrorOnReuseAsyncKernel()
3672+
{
3673+
static bool initialized = false;
3674+
static bool value = false;
3675+
if (!initialized)
3676+
{
3677+
value = cv::utils::getConfigurationParameterBool("OPENCV_OPENCL_RAISE_ERROR_REUSE_ASYNC_KERNEL", false);
3678+
initialized = true;
3679+
}
3680+
return value;
3681+
}
3682+
36703683
bool Kernel::Impl::run(int dims, size_t globalsize[], size_t localsize[],
36713684
bool sync, int64* timeNS, const Queue& q)
36723685
{
36733686
CV_INSTRUMENT_REGION_OPENCL_RUN(name.c_str());
36743687

3675-
if (!handle || isInProgress)
3688+
if (!handle)
3689+
{
3690+
CV_LOG_ERROR(NULL, "OpenCL kernel has zero handle: " << name);
36763691
return false;
3692+
}
3693+
3694+
if (isAsyncRun)
3695+
{
3696+
CV_LOG_ERROR(NULL, "OpenCL kernel can't be reused in async mode: " << name);
3697+
if (isRaiseErrorOnReuseAsyncKernel())
3698+
CV_Assert(0);
3699+
return false; // OpenCV 5.0: raise error
3700+
}
3701+
isAsyncRun = !sync;
3702+
3703+
if (isInProgress)
3704+
{
3705+
CV_LOG_ERROR(NULL, "Previous OpenCL kernel launch is not finished: " << name);
3706+
if (isRaiseErrorOnReuseAsyncKernel())
3707+
CV_Assert(0);
3708+
return false; // OpenCV 5.0: raise error
3709+
}
36773710

36783711
cl_command_queue qq = getQueue(q);
36793712
if (haveTempDstUMats)

modules/dnn/src/ocl4dnn/src/math_functions.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
#include <vector>
4747
#include "opencl_kernels_dnn.hpp"
4848

49+
#include "opencv2/core/utils/logger.hpp"
50+
4951
namespace cv { namespace dnn { namespace ocl4dnn {
5052

5153
enum gemm_data_type_t
@@ -238,10 +240,6 @@ static bool ocl4dnnFastImageGEMM(const CBLAS_TRANSPOSE TransA,
238240
kernel_name += "_float";
239241
}
240242

241-
ocl::Kernel oclk_gemm_float(kernel_name.c_str(), ocl::dnn::gemm_image_oclsrc, opts);
242-
if (oclk_gemm_float.empty())
243-
return false;
244-
245243
while (C_start_y < M)
246244
{
247245
blockC_width = std::min(static_cast<int>(N) - C_start_x, blocksize);
@@ -348,6 +346,10 @@ static bool ocl4dnnFastImageGEMM(const CBLAS_TRANSPOSE TransA,
348346
}
349347
local[1] = 1;
350348

349+
ocl::Kernel oclk_gemm_float(kernel_name.c_str(), ocl::dnn::gemm_image_oclsrc, opts);
350+
if (oclk_gemm_float.empty())
351+
return false;
352+
351353
cl_uint arg_idx = 0;
352354
if (is_image_a)
353355
oclk_gemm_float.set(arg_idx++, ocl::KernelArg::PtrReadOnly(A));
@@ -378,7 +380,10 @@ static bool ocl4dnnFastImageGEMM(const CBLAS_TRANSPOSE TransA,
378380
oclk_gemm_float.set(arg_idx++, isFirstColBlock);
379381

380382
if (!oclk_gemm_float.run(2, global, local, false))
383+
{
384+
CV_LOG_WARNING(NULL, "OpenCL kernel enqueue failed: " << kernel_name);
381385
return false;
386+
}
382387

383388
if (TransA == CblasNoTrans)
384389
A_start_x += blockA_width;

modules/dnn/src/onnx/onnx_importer.cpp

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -392,24 +392,21 @@ void ONNXImporter::populateNet(Net dstNet)
392392
layerParams.set("ave_pool_padded_area", framework_name == "pytorch");
393393
}
394394
else if (layer_type == "GlobalAveragePool" || layer_type == "GlobalMaxPool" ||
395-
layer_type == "ReduceMean" || layer_type == "ReduceSum")
395+
layer_type == "ReduceMean" || layer_type == "ReduceSum" || layer_type == "ReduceMax")
396396
{
397397
CV_Assert(node_proto.input_size() == 1);
398398
layerParams.type = "Pooling";
399399
String pool;
400-
if (layer_type == "GlobalMaxPool")
400+
if (layer_type == "GlobalMaxPool" || layer_type == "ReduceMax")
401401
pool = "MAX";
402402
else if (layer_type == "ReduceSum")
403403
pool = "SUM";
404404
else
405405
pool = "AVE";
406406
layerParams.set("pool", pool);
407-
layerParams.set("global_pooling", layer_type == "GlobalAveragePool" || layer_type == "GlobalMaxPool");
408-
if (layer_type == "ReduceMean" || layer_type == "ReduceSum")
407+
layerParams.set("global_pooling", !layerParams.has("axes"));
408+
if (layerParams.has("axes") && (layer_type == "ReduceMean" || layer_type == "ReduceSum" || layer_type == "ReduceMax"))
409409
{
410-
if (!layerParams.has("axes"))
411-
CV_Error(Error::StsNotImplemented, "Unsupported mode of " + layer_type + " operation.");
412-
413410
MatShape inpShape = outShapes[node_proto.input(0)];
414411
DictValue axes = layerParams.get("axes");
415412
bool keepdims = layerParams.get<int>("keepdims");
@@ -487,6 +484,36 @@ void ONNXImporter::populateNet(Net dstNet)
487484
layerParams.type = "Reshape";
488485
layerParams.set("dim", DictValue::arrayInt(&targetShape[0], targetShape.size()));
489486

487+
node_proto.set_input(0, node_proto.output(0));
488+
node_proto.set_output(0, layerParams.name);
489+
}
490+
else if (!layerParams.has("axes") && (layer_type == "ReduceMean" || layer_type == "ReduceSum" || layer_type == "ReduceMax"))
491+
{
492+
CV_CheckEQ(layerParams.get<int>("keepdims"), 0, (layer_type + " layer only supports keepdims = false").c_str());
493+
LayerParams reshapeLp;
494+
reshapeLp.name = layerParams.name + "/reshape";
495+
reshapeLp.type = "Reshape";
496+
CV_Assert(layer_id.find(reshapeLp.name) == layer_id.end());
497+
int newShape[] = {1, 1, 1, -1};
498+
reshapeLp.set("dim", DictValue::arrayInt(&newShape[0], 4));
499+
500+
opencv_onnx::NodeProto proto;
501+
proto.add_input(node_proto.input(0));
502+
proto.add_output(reshapeLp.name);
503+
addLayer(dstNet, reshapeLp, proto, layer_id, outShapes);
504+
505+
LayerParams poolLp = layerParams;
506+
poolLp.name = layerParams.name + "/pool";
507+
CV_Assert(layer_id.find(poolLp.name) == layer_id.end());
508+
509+
node_proto.set_input(0, reshapeLp.name);
510+
node_proto.set_output(0, poolLp.name);
511+
addLayer(dstNet, poolLp, node_proto, layer_id, outShapes);
512+
513+
layerParams.type = "Reshape";
514+
int targetShape[] = {1};
515+
layerParams.set("dim", DictValue::arrayInt(&targetShape[0], 1));
516+
490517
node_proto.set_input(0, node_proto.output(0));
491518
node_proto.set_output(0, layerParams.name);
492519
}
@@ -653,7 +680,7 @@ void ONNXImporter::populateNet(Net dstNet)
653680
LayerParams constParams;
654681
constParams.name = layerParams.name + "/const";
655682
constParams.type = "Const";
656-
constParams.blobs.push_back(blob);
683+
constParams.blobs.push_back((isSub ? -1 : 1) * blob);
657684
int id = dstNet.addLayer(constParams.name, constParams.type, constParams);
658685
layer_id.insert(std::make_pair(constParams.name, LayerInfo(id, 0)));
659686
outShapes[constParams.name] = shape(blob);
@@ -1024,6 +1051,16 @@ void ONNXImporter::populateNet(Net dstNet)
10241051
}
10251052
else
10261053
{
1054+
// Scale layer allocate output with the first input shape
1055+
if (total(outShapes[node_proto.input(0)]) < total(outShapes[node_proto.input(1)]))
1056+
{
1057+
opencv_onnx::NodeProto proto;
1058+
proto.add_input(node_proto.input(1));
1059+
proto.add_input(node_proto.input(0));
1060+
proto.add_output(layerParams.name);
1061+
node_proto = proto;
1062+
}
1063+
10271064
if (isDiv)
10281065
{
10291066
LayerParams powerParams;
@@ -1427,8 +1464,10 @@ void ONNXImporter::populateNet(Net dstNet)
14271464
case opencv_onnx::TensorProto_DataType_INT64: type = CV_32S; break;
14281465
default: type = blob.type();
14291466
}
1430-
blob.convertTo(blob, type);
1431-
addConstant(layerParams.name, blob, constBlobs, outShapes);
1467+
Mat dst;
1468+
blob.convertTo(dst, type);
1469+
dst.dims = blob.dims;
1470+
addConstant(layerParams.name, dst, constBlobs, outShapes);
14321471
continue;
14331472
}
14341473
else
@@ -1477,6 +1516,8 @@ void ONNXImporter::populateNet(Net dstNet)
14771516
{
14781517
outShape.erase(outShape.begin() + axis);
14791518
out.reshape(0, outShape);
1519+
} else {
1520+
out.dims = 1;
14801521
}
14811522
addConstant(layerParams.name, out, constBlobs, outShapes);
14821523
continue;
@@ -1557,7 +1598,9 @@ void ONNXImporter::populateNet(Net dstNet)
15571598
Mat shapes = getBlob(node_proto, constBlobs, node_proto.input_size() - 1);
15581599
CV_CheckEQ(shapes.size[0], 4, "");
15591600
CV_CheckEQ(shapes.size[1], 1, "");
1560-
CV_CheckTypeEQ(shapes.depth(), CV_32S, "");
1601+
CV_CheckDepth(shapes.depth(), shapes.depth() == CV_32S || shapes.depth() == CV_32F, "");
1602+
if (shapes.depth() == CV_32F)
1603+
shapes.convertTo(shapes, CV_32S);
15611604
int height = shapes.at<int>(2);
15621605
int width = shapes.at<int>(3);
15631606
if (node_proto.input_size() == 3)

modules/dnn/src/opencl/prior_box.cl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,6 @@ __kernel void clip(const int nthreads,
114114
for (int index = get_global_id(0); index < nthreads; index += get_global_size(0))
115115
{
116116
Dtype4 vec = vload4(index, dst);
117-
vstore4(clamp(vec, 0.0f, 1.0f), index, dst);
117+
vstore4(clamp(vec, (Dtype)0.0f, (Dtype)1.0f), index, dst);
118118
}
119119
}

modules/dnn/test/test_onnx_importer.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,18 @@ TEST_P(Test_ONNX_layers, ReduceSum)
275275
testONNXModels("reduce_sum");
276276
}
277277

278+
TEST_P(Test_ONNX_layers, ReduceMaxGlobal)
279+
{
280+
testONNXModels("reduce_max");
281+
}
282+
283+
TEST_P(Test_ONNX_layers, Scale)
284+
{
285+
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
286+
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
287+
testONNXModels("scale");
288+
}
289+
278290
TEST_P(Test_ONNX_layers, ReduceMean3D)
279291
{
280292
if (backend == DNN_BACKEND_CUDA)
@@ -664,6 +676,11 @@ TEST_P(Test_ONNX_layers, MatmulWithTwoInputs)
664676
testONNXModels("matmul_with_two_inputs");
665677
}
666678

679+
TEST_P(Test_ONNX_layers, ResizeOpset11_Torch1_6)
680+
{
681+
testONNXModels("resize_opset11_torch1.6");
682+
}
683+
667684
INSTANTIATE_TEST_CASE_P(/*nothing*/, Test_ONNX_layers, dnnBackendsAndTargets());
668685

669686
class Test_ONNX_nets : public Test_ONNX_layers

modules/imgcodecs/src/loadsave.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,19 @@ struct ImageCodecInitializer
197197
std::vector<ImageEncoder> encoders;
198198
};
199199

200-
static ImageCodecInitializer codecs;
200+
static
201+
ImageCodecInitializer& getCodecs()
202+
{
203+
#ifdef CV_CXX11
204+
static ImageCodecInitializer g_codecs;
205+
return g_codecs;
206+
#else
207+
// C++98 doesn't guarantee correctness of multi-threaded initialization of static global variables
208+
// (memory leak here is not critical, use C++11 to avoid that)
209+
static ImageCodecInitializer* g_codecs = new ImageCodecInitializer();
210+
return *g_codecs;
211+
#endif
212+
}
201213

202214
/**
203215
* Find the decoders
@@ -211,6 +223,7 @@ static ImageDecoder findDecoder( const String& filename ) {
211223
size_t i, maxlen = 0;
212224

213225
/// iterate through list of registered codecs
226+
ImageCodecInitializer& codecs = getCodecs();
214227
for( i = 0; i < codecs.decoders.size(); i++ )
215228
{
216229
size_t len = codecs.decoders[i]->signatureLength();
@@ -248,6 +261,7 @@ static ImageDecoder findDecoder( const Mat& buf )
248261
if( buf.rows*buf.cols < 1 || !buf.isContinuous() )
249262
return ImageDecoder();
250263

264+
ImageCodecInitializer& codecs = getCodecs();
251265
for( i = 0; i < codecs.decoders.size(); i++ )
252266
{
253267
size_t len = codecs.decoders[i]->signatureLength();
@@ -280,6 +294,7 @@ static ImageEncoder findEncoder( const String& _ext )
280294
for( ext++; len < 128 && isalnum(ext[len]); len++ )
281295
;
282296

297+
ImageCodecInitializer& codecs = getCodecs();
283298
for( size_t i = 0; i < codecs.encoders.size(); i++ )
284299
{
285300
String description = codecs.encoders[i]->getDescription();

0 commit comments

Comments
 (0)