diff --git a/doc/py_tutorials/py_imgproc/py_pyramids/py_pyramids.markdown b/doc/py_tutorials/py_imgproc/py_pyramids/py_pyramids.markdown index 63fde0a130..602ab29ad6 100644 --- a/doc/py_tutorials/py_imgproc/py_pyramids/py_pyramids.markdown +++ b/doc/py_tutorials/py_imgproc/py_pyramids/py_pyramids.markdown @@ -117,7 +117,7 @@ for i in range(5,0,-1): LS = [] for la,lb in zip(lpA,lpB): rows,cols,dpt = la.shape - ls = np.hstack((la[:,0:cols/2], lb[:,cols/2:])) + ls = np.hstack((la[:,0:cols//2], lb[:,cols//2:])) LS.append(ls) # now reconstruct @@ -127,7 +127,7 @@ for i in range(1,6): ls_ = cv.add(ls_, LS[i]) # image with direct connecting each half -real = np.hstack((A[:,:cols/2],B[:,cols/2:])) +real = np.hstack((A[:,:cols//2],B[:,cols//2:])) cv.imwrite('Pyramid_blending2.jpg',ls_) cv.imwrite('Direct_blending.jpg',real) diff --git a/modules/core/include/opencv2/core/cv_cpu_dispatch.h b/modules/core/include/opencv2/core/cv_cpu_dispatch.h index 8365b10ba9..ab5a67d4c8 100644 --- a/modules/core/include/opencv2/core/cv_cpu_dispatch.h +++ b/modules/core/include/opencv2/core/cv_cpu_dispatch.h @@ -55,7 +55,7 @@ # ifdef _MSC_VER # include # if defined(_M_X64) -# define CV_POPCNT_U64 _mm_popcnt_u64 +# define CV_POPCNT_U64 (int)_mm_popcnt_u64 # endif # define CV_POPCNT_U32 _mm_popcnt_u32 # else diff --git a/modules/dnn/src/onnx/onnx_importer.cpp b/modules/dnn/src/onnx/onnx_importer.cpp index 7c230f28c8..4a2153d5a7 100644 --- a/modules/dnn/src/onnx/onnx_importer.cpp +++ b/modules/dnn/src/onnx/onnx_importer.cpp @@ -58,7 +58,6 @@ class ONNXImporter Mat getBlob(const std::string& input_name); LayerParams getLayerParams(const opencv_onnx::NodeProto& node_proto); - bool isCeilMode(const LayerParams& layerParams); void addConstant(const std::string& name, const Mat& blob); void addLayer(LayerParams& layerParams, @@ -68,6 +67,7 @@ class ONNXImporter void expandMid(const std::string& prefix, opencv_onnx::NodeProto& node_proto, const std::string& input, size_t n); + void addNegation(const LayerParams& layerParams, opencv_onnx::NodeProto& node_proto, int input_id); public: ONNXImporter(Net& net, const char *onnxFile); ONNXImporter(Net& net, const char* buffer, size_t sizeBuffer); @@ -530,6 +530,32 @@ void ONNXImporter::expandMid(const std::string& prefix, opencv_onnx::NodeProto& } } +/** @brief Multiply one of node_proto inputs by -1 + * @param layerParams parameters of the node + * @param node_proto node which input will be replaced + * @param input_id id of input to be multiplied by -1 + */ +void ONNXImporter::addNegation(const LayerParams& layerParams, opencv_onnx::NodeProto& node_proto, int input_id) +{ + LayerParams powerParams; + powerParams.name = layerParams.name + "/neg"; + powerParams.type = "Power"; + powerParams.set("scale", -1.f); + + //Create Power layer + int id = dstNet.addLayer(powerParams.name, powerParams.type, powerParams); + //Connect to input + IterLayerId_t layerId = layer_id.find(node_proto.input(input_id)); + CV_Assert(layerId != layer_id.end()); + dstNet.connect(layerId->second.layerId, layerId->second.outputId, id, 0); + //Add shape + layer_id.insert(std::make_pair(powerParams.name, LayerInfo(id, 0))); + outShapes[powerParams.name] = outShapes[node_proto.input(input_id)]; + + //Replace input to Power + node_proto.set_input(input_id, powerParams.name); +} + void ONNXImporter::addConstant(const std::string& name, const Mat& blob) { constBlobs.insert(std::make_pair(name, blob)); @@ -1057,7 +1083,19 @@ void ONNXImporter::parseBias(LayerParams& layerParams, const opencv_onnx::NodePr opencv_onnx::NodeProto node_proto = node_proto_; const std::string& layer_type = node_proto.op_type(); bool isSub = layer_type == "Sub"; - CV_CheckEQ(node_proto.input_size(), 2, ""); + CV_Assert((node_proto.input_size() == 2) || (layer_type == "Sum" && node_proto.input_size() > 2)); + + if (layer_type == "Sum" && node_proto.input_size() > 2) + { + for (int i = 0; i < node_proto.input_size(); ++i) + { + if (layer_id.find(node_proto.input(i)) == layer_id.end()) + { + CV_Error(Error::StsNotImplemented, "Sum of constants is not implemented for inputs > 2"); + } + } + } + bool is_const_0 = layer_id.find(node_proto.input(0)) == layer_id.end(); bool is_const_1 = layer_id.find(node_proto.input(1)) == layer_id.end(); if (is_const_0 && is_const_1) @@ -1072,29 +1110,42 @@ void ONNXImporter::parseBias(LayerParams& layerParams, const opencv_onnx::NodePr else if (is_const_0 || is_const_1) { int const_blob_id = is_const_0 ? 0 : 1; + int input_id = 1 - const_blob_id; Mat blob = getBlob(node_proto, const_blob_id); int blob_total = blob.total(); + + const float inputScale = isSub && is_const_0 ? -1.f : 1.f; + const float constScale = isSub && is_const_1 ? -1.f : 1.f; + if (blob_total == 1) { layerParams.type = "Power"; - layerParams.set("shift", (isSub ? -1 : 1) * blob.ptr()[0]); + layerParams.set("scale", inputScale); + layerParams.set("shift", constScale * blob.ptr()[0]); } else { - MatShape inpShape = outShapes[node_proto.input(1 - const_blob_id)]; + MatShape inpShape = outShapes[node_proto.input(input_id)]; if (shape(blob) == inpShape) { LayerParams constParams; constParams.name = layerParams.name + "/const"; constParams.type = "Const"; - constParams.blobs.push_back((isSub ? -1 : 1) * blob); + constParams.blobs.push_back(blob); int id = dstNet.addLayer(constParams.name, constParams.type, constParams); layer_id.insert(std::make_pair(constParams.name, LayerInfo(id, 0))); outShapes[constParams.name] = shape(blob); layerParams.type = "Eltwise"; + float coeffs[] = {1., isSub ? -1.f : 1.f}; + layerParams.set("coeff", DictValue::arrayReal(coeffs, 2)); node_proto.set_input(const_blob_id, constParams.name); } else { + if (inputScale < 0.f) + { + addNegation(layerParams, node_proto, input_id); + } + layerParams.type = "Scale"; layerParams.set("bias_term", true); int axis = 1; @@ -1109,7 +1160,7 @@ void ONNXImporter::parseBias(LayerParams& layerParams, const opencv_onnx::NodePr } layerParams.set("axis", axis); blob = blob.reshape(1, 1); - layerParams.blobs.push_back((isSub ? -1 : 1) * blob); + layerParams.blobs.push_back(constScale * blob); } } } @@ -1126,23 +1177,7 @@ void ONNXImporter::parseBias(LayerParams& layerParams, const opencv_onnx::NodePr { if (isSub) { - LayerParams powerParams; - powerParams.name = layerParams.name + "/neg"; - powerParams.type = "Power"; - powerParams.set("scale", -1); - - //Create Power layer - int id = dstNet.addLayer(powerParams.name, powerParams.type, powerParams); - //Connect to input - IterLayerId_t layerId = layer_id.find(node_proto.input(1)); - CV_Assert(layerId != layer_id.end()); - dstNet.connect(layerId->second.layerId, layerId->second.outputId, id, 0); - //Add shape - layer_id.insert(std::make_pair(powerParams.name, LayerInfo(id, 0))); - outShapes[powerParams.name] = outShapes[node_proto.input(1)]; - - //Replace input to Power - node_proto.set_input(1, powerParams.name); + addNegation(layerParams, node_proto, 1); } layerParams.type = "Scale"; layerParams.set("bias_term", true); diff --git a/modules/dnn/test/test_onnx_importer.cpp b/modules/dnn/test/test_onnx_importer.cpp index 5d324b8aac..5909f2ce6e 100644 --- a/modules/dnn/test/test_onnx_importer.cpp +++ b/modules/dnn/test/test_onnx_importer.cpp @@ -991,6 +991,14 @@ TEST_P(Test_ONNX_layers, ConvResizePool1d) testONNXModels("conv_resize_pool_1d"); } +TEST_P(Test_ONNX_layers, SubFromConst) +{ + testONNXModels("sub_from_const1"); + testONNXModels("sub_from_const_eltwise"); + testONNXModels("sub_from_const_broadcast"); +} + + TEST_P(Test_ONNX_layers, Quantized_Convolution) { testONNXModels("quantized_conv_uint8_weights", npy, 0.004, 0.02); diff --git a/modules/highgui/CMakeLists.txt b/modules/highgui/CMakeLists.txt index c5541241a4..5c0f1e3278 100644 --- a/modules/highgui/CMakeLists.txt +++ b/modules/highgui/CMakeLists.txt @@ -266,7 +266,7 @@ if(APPLE) add_apple_compiler_options(${the_module}) endif() -if(MSVC) +if(MSVC AND NOT BUILD_SHARED_LIBS AND BUILD_WITH_STATIC_CRT) set_target_properties(${the_module} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /NODEFAULTLIB:libcmt.lib /DEBUG") endif() diff --git a/modules/imgcodecs/CMakeLists.txt b/modules/imgcodecs/CMakeLists.txt index 24f89e6e38..cc512f3e19 100644 --- a/modules/imgcodecs/CMakeLists.txt +++ b/modules/imgcodecs/CMakeLists.txt @@ -152,7 +152,7 @@ if(APPLE) add_apple_compiler_options(${the_module}) endif() -if(MSVC) +if(MSVC AND NOT BUILD_SHARED_LIBS AND BUILD_WITH_STATIC_CRT) set_target_properties(${the_module} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /NODEFAULTLIB:libcmt.lib /DEBUG") endif() diff --git a/modules/imgproc/src/filter.simd.hpp b/modules/imgproc/src/filter.simd.hpp index 94dbce060c..966de94c0b 100644 --- a/modules/imgproc/src/filter.simd.hpp +++ b/modules/imgproc/src/filter.simd.hpp @@ -1160,6 +1160,81 @@ struct SymmColumnVec_32s8u Mat kernel; }; +struct SymmColumnVec_32f8u +{ + SymmColumnVec_32f8u() { symmetryType = 0; delta = 0; } + SymmColumnVec_32f8u(const Mat& _kernel, int _symmetryType, int, double _delta) + { + symmetryType = _symmetryType; + kernel = _kernel; + delta = (float)_delta; + CV_Assert( (symmetryType & (KERNEL_SYMMETRICAL | KERNEL_ASYMMETRICAL)) != 0 ); + } + + int operator()(const uchar** _src, uchar* _dst, int width) const + { + CV_INSTRUMENT_REGION(); + + int _ksize = kernel.rows + kernel.cols - 1; + if( _ksize == 1 ) return 0; + const int ksize2 = _ksize / 2; + const float* ky = kernel.ptr() + ksize2; + int i = 0, k; + bool symmetrical = (symmetryType & KERNEL_SYMMETRICAL) != 0; + const float** src = (const float**)_src; + + if( symmetrical ) + { + for( ; i <= width - v_uint8::nlanes; i += v_uint8::nlanes ) + { + v_float32 v_ky0 = vx_setall_f32(ky[0]); + v_float32 v32_delta = vx_setall_f32(delta); + const float* S = src[0] + i; + v_float32 s0 = v_muladd(v_ky0, vx_load(S), v32_delta); + v_float32 s1 = v_muladd(v_ky0, vx_load(S + v_float32::nlanes), v32_delta); + v_float32 s2 = v_muladd(v_ky0, vx_load(S + 2*v_float32::nlanes), v32_delta); + v_float32 s3 = v_muladd(v_ky0, vx_load(S + 3*v_float32::nlanes), v32_delta); + for( k = 1; k <= ksize2; k++ ) + { + v_float32 v_kyk = vx_setall_f32(ky[k]); + const float* S0 = src[k] + i; + const float* S1 = src[-k] + i; + s0 = v_muladd(v_kyk, vx_load(S0) + vx_load(S1), s0); + s1 = v_muladd(v_kyk, vx_load(S0 + v_float32::nlanes) + vx_load(S1 + v_float32::nlanes), s1); + s2 = v_muladd(v_kyk, vx_load(S0 + 2*v_float32::nlanes) + vx_load(S1 + 2*v_float32::nlanes), s2); + s3 = v_muladd(v_kyk, vx_load(S0 + 3*v_float32::nlanes) + vx_load(S1 + 3*v_float32::nlanes), s3); + } + v_store(_dst + i, v_pack_u(v_pack(v_round(s0), v_round(s1)), v_pack(v_round(s2), v_round(s3)))); + } + } + else + { + for( ; i <= width - v_uint8::nlanes; i += v_uint8::nlanes ) + { + v_float32 s0 = vx_setall_f32(delta); + v_float32 s1 = vx_setall_f32(delta); + v_float32 s2 = vx_setall_f32(delta); + v_float32 s3 = vx_setall_f32(delta); + for( k = 1; k <= ksize2; k++ ) + { + v_float32 v_kyk = vx_setall_f32(ky[k]); + const float* S0 = src[k] + i; + const float* S1 = src[-k] + i; + s0 = v_muladd(v_kyk, vx_load(S0) - vx_load(S1), s0); + s1 = v_muladd(v_kyk, vx_load(S0 + v_float32::nlanes) - vx_load(S1 + v_float32::nlanes), s1); + s2 = v_muladd(v_kyk, vx_load(S0 + 2*v_float32::nlanes) - vx_load(S1 + 2*v_float32::nlanes), s2); + s3 = v_muladd(v_kyk, vx_load(S0 + 3*v_float32::nlanes) - vx_load(S1 + 3*v_float32::nlanes), s3); + } + v_store(_dst + i, v_pack_u(v_pack(v_round(s0), v_round(s1)), v_pack(v_round(s2), v_round(s3)))); + } + } + return i; + } + int symmetryType; + float delta; + Mat kernel; +}; + struct SymmColumnSmallVec_32s16s { @@ -2341,6 +2416,7 @@ typedef RowNoVec RowVec_32f; typedef SymmRowSmallNoVec SymmRowSmallVec_8u32s; typedef SymmRowSmallNoVec SymmRowSmallVec_32f; typedef ColumnNoVec SymmColumnVec_32s8u; +typedef ColumnNoVec SymmColumnVec_32f8u; typedef ColumnNoVec SymmColumnVec_32f16s; typedef ColumnNoVec SymmColumnVec_32f; typedef SymmColumnSmallNoVec SymmColumnSmallVec_32s16s; @@ -3031,8 +3107,9 @@ Ptr getLinearColumnFilter( (kernel, anchor, delta, symmetryType, FixedPtCastEx(bits), SymmColumnVec_32s8u(kernel, symmetryType, bits, delta)); if( ddepth == CV_8U && sdepth == CV_32F ) - return makePtr, ColumnNoVec> > - (kernel, anchor, delta, symmetryType); + return makePtr, SymmColumnVec_32f8u> > + (kernel, anchor, delta, symmetryType, Cast(), + SymmColumnVec_32f8u(kernel, symmetryType, 0, delta)); if( ddepth == CV_8U && sdepth == CV_64F ) return makePtr, ColumnNoVec> > (kernel, anchor, delta, symmetryType); diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 9bfc2bf8ad..9d8f588083 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -103,8 +103,10 @@ if(MSVC) endforeach(flag_var) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:msvcrtd.lib") - set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:libcmt.lib") - set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /NODEFAULTLIB:libcmtd.lib") + if(NOT BUILD_WITH_STATIC_CRT) + set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:libcmt.lib") + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /NODEFAULTLIB:libcmtd.lib") + endif() endif() endif()