diff --git a/cmake/OpenCVFindLAPACK.cmake b/cmake/OpenCVFindLAPACK.cmake index 226825d15b..9b1b60f19e 100644 --- a/cmake/OpenCVFindLAPACK.cmake +++ b/cmake/OpenCVFindLAPACK.cmake @@ -51,6 +51,23 @@ macro(ocv_lapack_check) if(NOT "${OPENCV_CBLAS_H_PATH_${_lapack_impl}}" STREQUAL "${OPENCV_LAPACKE_H_PATH_${_lapack_impl}}") list(APPEND _lapack_content "#include \"${OPENCV_LAPACKE_H_PATH_${_lapack_impl}}\"") endif() + list(APPEND _lapack_content " +#if defined(LAPACK_GLOBAL) || defined(LAPACK_NAME) +/* + * Using netlib's reference LAPACK implementation version >= 3.4.0 (first with C interface). + * Use LAPACK_xxxx to transparently (via predefined lapack macros) deal with pre and post 3.9.1 versions. + * LAPACK 3.9.1 introduces LAPACK_FORTRAN_STRLEN_END and modifies (through preprocessing) the declarations of the following functions used in opencv + * sposv_, dposv_, spotrf_, dpotrf_, sgesdd_, dgesdd_, sgels_, dgels_ + * which end up with an extra parameter. + * So we also need to preprocess the function calls in opencv coding by prefixing them with LAPACK_. + * The good news is the preprocessing works fine whatever netlib's LAPACK version. + */ +#define OCV_LAPACK_FUNC(f) LAPACK_##f +#else +/* Using other LAPACK implementations so fall back to opencv's assumption until now */ +#define OCV_LAPACK_FUNC(f) f##_ +#endif +") if(${_lapack_add_extern_c}) list(APPEND _lapack_content "}") endif() diff --git a/modules/core/src/hal_internal.cpp b/modules/core/src/hal_internal.cpp index 483281d1f7..cbe02780d2 100644 --- a/modules/core/src/hal_internal.cpp +++ b/modules/core/src/hal_internal.cpp @@ -163,9 +163,9 @@ lapack_Cholesky(fptype* a, size_t a_step, int m, fptype* b, size_t b_step, int n if(n == 1 && b_step == sizeof(fptype)) { if(typeid(fptype) == typeid(float)) - sposv_(L, &m, &n, (float*)a, &lda, (float*)b, &m, &lapackStatus); + OCV_LAPACK_FUNC(sposv)(L, &m, &n, (float*)a, &lda, (float*)b, &m, &lapackStatus); else if(typeid(fptype) == typeid(double)) - dposv_(L, &m, &n, (double*)a, &lda, (double*)b, &m, &lapackStatus); + OCV_LAPACK_FUNC(dposv)(L, &m, &n, (double*)a, &lda, (double*)b, &m, &lapackStatus); } else { @@ -174,9 +174,9 @@ lapack_Cholesky(fptype* a, size_t a_step, int m, fptype* b, size_t b_step, int n transpose(b, ldb, tmpB, m, m, n); if(typeid(fptype) == typeid(float)) - sposv_(L, &m, &n, (float*)a, &lda, (float*)tmpB, &m, &lapackStatus); + OCV_LAPACK_FUNC(sposv)(L, &m, &n, (float*)a, &lda, (float*)tmpB, &m, &lapackStatus); else if(typeid(fptype) == typeid(double)) - dposv_(L, &m, &n, (double*)a, &lda, (double*)tmpB, &m, &lapackStatus); + OCV_LAPACK_FUNC(dposv)(L, &m, &n, (double*)a, &lda, (double*)tmpB, &m, &lapackStatus); transpose(tmpB, m, b, ldb, n, m); delete[] tmpB; @@ -185,9 +185,9 @@ lapack_Cholesky(fptype* a, size_t a_step, int m, fptype* b, size_t b_step, int n else { if(typeid(fptype) == typeid(float)) - spotrf_(L, &m, (float*)a, &lda, &lapackStatus); + OCV_LAPACK_FUNC(spotrf)(L, &m, (float*)a, &lda, &lapackStatus); else if(typeid(fptype) == typeid(double)) - dpotrf_(L, &m, (double*)a, &lda, &lapackStatus); + OCV_LAPACK_FUNC(dpotrf)(L, &m, (double*)a, &lda, &lapackStatus); } if(lapackStatus == 0) *info = true; @@ -227,17 +227,17 @@ lapack_SVD(fptype* a, size_t a_step, fptype *w, fptype* u, size_t u_step, fptype } if(typeid(fptype) == typeid(float)) - sgesdd_(mode, &m, &n, (float*)a, &lda, (float*)w, (float*)u, &ldu, (float*)vt, &ldv, (float*)&work1, &lwork, iworkBuf, info); + OCV_LAPACK_FUNC(sgesdd)(mode, &m, &n, (float*)a, &lda, (float*)w, (float*)u, &ldu, (float*)vt, &ldv, (float*)&work1, &lwork, iworkBuf, info); else if(typeid(fptype) == typeid(double)) - dgesdd_(mode, &m, &n, (double*)a, &lda, (double*)w, (double*)u, &ldu, (double*)vt, &ldv, (double*)&work1, &lwork, iworkBuf, info); + OCV_LAPACK_FUNC(dgesdd)(mode, &m, &n, (double*)a, &lda, (double*)w, (double*)u, &ldu, (double*)vt, &ldv, (double*)&work1, &lwork, iworkBuf, info); lwork = (int)round(work1); //optimal buffer size fptype* buffer = new fptype[lwork + 1]; if(typeid(fptype) == typeid(float)) - sgesdd_(mode, &m, &n, (float*)a, &lda, (float*)w, (float*)u, &ldu, (float*)vt, &ldv, (float*)buffer, &lwork, iworkBuf, info); + OCV_LAPACK_FUNC(sgesdd)(mode, &m, &n, (float*)a, &lda, (float*)w, (float*)u, &ldu, (float*)vt, &ldv, (float*)buffer, &lwork, iworkBuf, info); else if(typeid(fptype) == typeid(double)) - dgesdd_(mode, &m, &n, (double*)a, &lda, (double*)w, (double*)u, &ldu, (double*)vt, &ldv, (double*)buffer, &lwork, iworkBuf, info); + OCV_LAPACK_FUNC(dgesdd)(mode, &m, &n, (double*)a, &lda, (double*)w, (double*)u, &ldu, (double*)vt, &ldv, (double*)buffer, &lwork, iworkBuf, info); if(!(flags & CV_HAL_SVD_NO_UV)) transpose_square_inplace(vt, ldv, n); @@ -288,18 +288,18 @@ lapack_QR(fptype* a, size_t a_step, int m, int n, int k, fptype* b, size_t b_ste if (k == 1 && b_step == sizeof(fptype)) { if (typeid(fptype) == typeid(float)) - sgels_(mode, &m, &n, &k, (float*)tmpA, &ldtmpA, (float*)b, &m, (float*)&work1, &lwork, info); + OCV_LAPACK_FUNC(sgels)(mode, &m, &n, &k, (float*)tmpA, &ldtmpA, (float*)b, &m, (float*)&work1, &lwork, info); else if (typeid(fptype) == typeid(double)) - dgels_(mode, &m, &n, &k, (double*)tmpA, &ldtmpA, (double*)b, &m, (double*)&work1, &lwork, info); + OCV_LAPACK_FUNC(dgels)(mode, &m, &n, &k, (double*)tmpA, &ldtmpA, (double*)b, &m, (double*)&work1, &lwork, info); lwork = cvRound(work1); //optimal buffer size std::vector workBufMemHolder(lwork + 1); fptype* buffer = &workBufMemHolder.front(); if (typeid(fptype) == typeid(float)) - sgels_(mode, &m, &n, &k, (float*)tmpA, &ldtmpA, (float*)b, &m, (float*)buffer, &lwork, info); + OCV_LAPACK_FUNC(sgels)(mode, &m, &n, &k, (float*)tmpA, &ldtmpA, (float*)b, &m, (float*)buffer, &lwork, info); else if (typeid(fptype) == typeid(double)) - dgels_(mode, &m, &n, &k, (double*)tmpA, &ldtmpA, (double*)b, &m, (double*)buffer, &lwork, info); + OCV_LAPACK_FUNC(dgels)(mode, &m, &n, &k, (double*)tmpA, &ldtmpA, (double*)b, &m, (double*)buffer, &lwork, info); } else { @@ -309,18 +309,18 @@ lapack_QR(fptype* a, size_t a_step, int m, int n, int k, fptype* b, size_t b_ste transpose(b, ldb, tmpB, m, m, k); if (typeid(fptype) == typeid(float)) - sgels_(mode, &m, &n, &k, (float*)tmpA, &ldtmpA, (float*)tmpB, &m, (float*)&work1, &lwork, info); + OCV_LAPACK_FUNC(sgels)(mode, &m, &n, &k, (float*)tmpA, &ldtmpA, (float*)tmpB, &m, (float*)&work1, &lwork, info); else if (typeid(fptype) == typeid(double)) - dgels_(mode, &m, &n, &k, (double*)tmpA, &ldtmpA, (double*)tmpB, &m, (double*)&work1, &lwork, info); + OCV_LAPACK_FUNC(dgels)(mode, &m, &n, &k, (double*)tmpA, &ldtmpA, (double*)tmpB, &m, (double*)&work1, &lwork, info); lwork = cvRound(work1); //optimal buffer size std::vector workBufMemHolder(lwork + 1); fptype* buffer = &workBufMemHolder.front(); if (typeid(fptype) == typeid(float)) - sgels_(mode, &m, &n, &k, (float*)tmpA, &ldtmpA, (float*)tmpB, &m, (float*)buffer, &lwork, info); + OCV_LAPACK_FUNC(sgels)(mode, &m, &n, &k, (float*)tmpA, &ldtmpA, (float*)tmpB, &m, (float*)buffer, &lwork, info); else if (typeid(fptype) == typeid(double)) - dgels_(mode, &m, &n, &k, (double*)tmpA, &ldtmpA, (double*)tmpB, &m, (double*)buffer, &lwork, info); + OCV_LAPACK_FUNC(dgels)(mode, &m, &n, &k, (double*)tmpA, &ldtmpA, (double*)tmpB, &m, (double*)buffer, &lwork, info); transpose(tmpB, m, b, ldb, k, m); } diff --git a/modules/dnn/src/onnx/onnx_importer.cpp b/modules/dnn/src/onnx/onnx_importer.cpp index b80644287c..45fa424930 100644 --- a/modules/dnn/src/onnx/onnx_importer.cpp +++ b/modules/dnn/src/onnx/onnx_importer.cpp @@ -1711,7 +1711,16 @@ void ONNXImporter::parseMul(LayerParams& layerParams, const opencv_onnx::NodePro blob = blob.reshape(1, 1); if (blob.total() == 1) { float blob_value = blob.ptr()[0]; - float coeff = isDiv ? 1.0 / blob_value : blob_value; + float coeff = blob_value; + if (isDiv) + { + coeff = 1.f / blob_value; + if (constId == 0) + { + // Power layer calculates (x*scale + shift)^power, so const/x -> (x * (1/const) + 0)^(-1) + layerParams.set("power", -1.f); + } + } layerParams.set("scale", coeff); layerParams.type = "Power"; } diff --git a/modules/dnn/test/test_onnx_importer.cpp b/modules/dnn/test/test_onnx_importer.cpp index 55339462c8..a980df8a67 100644 --- a/modules/dnn/test/test_onnx_importer.cpp +++ b/modules/dnn/test/test_onnx_importer.cpp @@ -1338,6 +1338,11 @@ TEST_P(Test_ONNX_layers, SubFromConst) testONNXModels("sub_from_const_broadcast"); } +TEST_P(Test_ONNX_layers, DivConst) +{ + testONNXModels("div_const"); +} + TEST_P(Test_ONNX_layers, Quantized_Convolution) {