From a2d0cc878cb605c771cf7ca2979dcf9974ea5897 Mon Sep 17 00:00:00 2001 From: Vladislav Sovrasov Date: Fri, 3 Jun 2016 10:38:30 +0300 Subject: [PATCH 01/10] Implement internal HAL for GEMM and matrix decompositions --- CMakeLists.txt | 5 + cmake/OpenCVFindLibsPerf.cmake | 13 + cmake/templates/cvconfig.h.in | 3 + modules/core/include/opencv2/core/hal/hal.hpp | 26 +- .../core/include/opencv2/core/hal/interface.h | 15 + modules/core/include/opencv2/core/matx.hpp | 2 +- modules/core/src/hal_internal.cpp | 485 ++++++++++++++++++ modules/core/src/hal_internal.hpp | 96 ++++ modules/core/src/hal_replacement.hpp | 134 +++++ modules/core/src/lapack.cpp | 37 +- modules/core/src/matmul.cpp | 250 +++++++-- modules/core/src/matrix_decomp.cpp | 19 +- modules/imgproc/src/hal_replacement.hpp | 19 + 13 files changed, 1028 insertions(+), 76 deletions(-) create mode 100644 modules/core/src/hal_internal.cpp create mode 100644 modules/core/src/hal_internal.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f0085b6c8..e5453c34c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -221,6 +221,7 @@ OCV_OPTION(WITH_VA "Include VA support" OFF OCV_OPTION(WITH_VA_INTEL "Include Intel VA-API/OpenCL support" OFF IF (UNIX AND NOT ANDROID) ) OCV_OPTION(WITH_GDAL "Include GDAL Support" OFF IF (NOT ANDROID AND NOT IOS AND NOT WINRT) ) OCV_OPTION(WITH_GPHOTO2 "Include gPhoto2 library support" ON IF (UNIX AND NOT ANDROID) ) +OCV_OPTION(WITH_LAPACK "Include Lapack library support" ON IF (UNIX AND NOT ANDROID) ) # OpenCV build components # =================================================== @@ -1157,6 +1158,10 @@ if(DEFINED WITH_VA_INTEL) status(" Use Intel VA-API/OpenCL:" HAVE_VA_INTEL THEN "YES (MSDK: ${VA_INTEL_MSDK_ROOT} OpenCL: ${VA_INTEL_IOCL_ROOT})" ELSE NO) endif(DEFINED WITH_VA_INTEL) +if(DEFINED WITH_LAPACK) +status(" Use Lapack:" HAVE_LAPACK THEN "YES" ELSE NO) +endif(DEFINED WITH_LAPACK) + status(" Use Eigen:" HAVE_EIGEN THEN "YES (ver ${EIGEN_WORLD_VERSION}.${EIGEN_MAJOR_VERSION}.${EIGEN_MINOR_VERSION})" ELSE NO) status(" Use Cuda:" HAVE_CUDA THEN "YES (ver ${CUDA_VERSION_STRING})" ELSE NO) status(" Use OpenCL:" HAVE_OPENCL THEN YES ELSE NO) diff --git a/cmake/OpenCVFindLibsPerf.cmake b/cmake/OpenCVFindLibsPerf.cmake index d1bc5419a..59ee42d32 100644 --- a/cmake/OpenCVFindLibsPerf.cmake +++ b/cmake/OpenCVFindLibsPerf.cmake @@ -2,6 +2,19 @@ # Detect other 3rd-party performance and math libraries # ---------------------------------------------------------------------------- +# --- Lapack --- +if(WITH_LAPACK) + find_package(LAPACK) + if(LAPACK_FOUND) + find_path(LAPACK_INCLUDE_DIR "lapacke.h") + if(LAPACK_INCLUDE_DIR) + set(HAVE_LAPACK 1) + ocv_include_directories(${LAPACK_INCLUDE_DIR}) + list(APPEND OPENCV_LINKER_LIBS ${LAPACK_LIBRARIES}) + endif() + endif(LAPACK_FOUND) +endif(WITH_LAPACK) + # --- TBB --- if(WITH_TBB) include("${OpenCV_SOURCE_DIR}/cmake/OpenCVDetectTBB.cmake") diff --git a/cmake/templates/cvconfig.h.in b/cmake/templates/cvconfig.h.in index c80720dcd..b86d44a6c 100644 --- a/cmake/templates/cvconfig.h.in +++ b/cmake/templates/cvconfig.h.in @@ -197,3 +197,6 @@ /* Intel VA-API/OpenCL */ #cmakedefine HAVE_VA_INTEL + +/* Lapack */ +#cmakedefine HAVE_LAPACK diff --git a/modules/core/include/opencv2/core/hal/hal.hpp b/modules/core/include/opencv2/core/hal/hal.hpp index 09bcd72d5..382941893 100644 --- a/modules/core/include/opencv2/core/hal/hal.hpp +++ b/modules/core/include/opencv2/core/hal/hal.hpp @@ -49,17 +49,6 @@ #include "opencv2/core/cvstd.hpp" #include "opencv2/core/hal/interface.h" -//! @cond IGNORED -#define CALL_HAL(name, fun, ...) \ - int res = fun(__VA_ARGS__); \ - if (res == CV_HAL_ERROR_OK) \ - return; \ - else if (res != CV_HAL_ERROR_NOT_IMPLEMENTED) \ - CV_Error_(cv::Error::StsInternal, \ - ("HAL implementation " CVAUX_STR(name) " ==> " CVAUX_STR(fun) " returned %d (0x%08x)", res, res)); -//! @endcond - - namespace cv { namespace hal { //! @addtogroup core_hal_functions @@ -75,6 +64,21 @@ CV_EXPORTS int LU32f(float* A, size_t astep, int m, float* b, size_t bstep, int CV_EXPORTS int LU64f(double* A, size_t astep, int m, double* b, size_t bstep, int n); CV_EXPORTS bool Cholesky32f(float* A, size_t astep, int m, float* b, size_t bstep, int n); CV_EXPORTS bool Cholesky64f(double* A, size_t astep, int m, double* b, size_t bstep, int n); +CV_EXPORTS void SVD32f(float* At, size_t astep, float* W, float* U, size_t ustep, float* Vt, size_t vstep, int m, int n, int flags); +CV_EXPORTS void SVD64f(double* At, size_t astep, double* W, double* U, size_t ustep, double* Vt, size_t vstep, int m, int n, int flags); + +CV_EXPORTS void gemm32f(const float* src1, size_t src1_step, const float* src2, size_t src2_step, + float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags); +CV_EXPORTS void gemm64f(const double* src1, size_t src1_step, const double* src2, size_t src2_step, + double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags); +CV_EXPORTS void gemm32fc(const float* src1, size_t src1_step, const float* src2, size_t src2_step, + float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags); +CV_EXPORTS void gemm64fc(const double* src1, size_t src1_step, const double* src2, size_t src2_step, + double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags); CV_EXPORTS int normL1_(const uchar* a, const uchar* b, int n); CV_EXPORTS float normL1_(const float* a, const float* b, int n); diff --git a/modules/core/include/opencv2/core/hal/interface.h b/modules/core/include/opencv2/core/hal/interface.h index 2bb7b19f2..4a97e659e 100644 --- a/modules/core/include/opencv2/core/hal/interface.h +++ b/modules/core/include/opencv2/core/hal/interface.h @@ -158,6 +158,21 @@ typedef signed char schar; #define CV_HAL_DFT_IS_INPLACE 1024 //! @} +//! @name SVD flags +//! @{ +#define CV_HAL_SVD_NO_UV 1 +#define CV_HAL_SVD_SHORT_UV 2 +#define CV_HAL_SVD_MODIFY_A 4 +#define CV_HAL_SVD_FULL_UV 8 +//! @} + +//! @name Gemm flags +//! @{ +#define CV_HAL_GEMM_1_T 1 +#define CV_HAL_GEMM_2_T 2 +#define CV_HAL_GEMM_3_T 4 +//! @} + //! @} #endif diff --git a/modules/core/include/opencv2/core/matx.hpp b/modules/core/include/opencv2/core/matx.hpp index e4d72f7ed..a4c0fbb11 100644 --- a/modules/core/include/opencv2/core/matx.hpp +++ b/modules/core/include/opencv2/core/matx.hpp @@ -438,7 +438,7 @@ template struct Matx_DetOp return p; for( int i = 0; i < m; i++ ) p *= temp(i, i); - return 1./p; + return p; } }; diff --git a/modules/core/src/hal_internal.cpp b/modules/core/src/hal_internal.cpp new file mode 100644 index 000000000..096ac0b40 --- /dev/null +++ b/modules/core/src/hal_internal.cpp @@ -0,0 +1,485 @@ +/*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. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez 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 "hal_internal.hpp" + +#ifdef HAVE_LAPACK + +#include +#include +#include +#include +#include +#include +#include + +#define HAL_GEMM_SMALL_COMPLEX_MATRIX_THRESH 100 +#define HAL_GEMM_SMALL_MATRIX_THRESH 100 +#define HAL_SVD_SMALL_MATRIX_THRESH 25 +#define HAL_LU_SMALL_MATRIX_THRESH 100 +#define HAL_CHOLESKY_SMALL_MATRIX_THRESH 100 + +//lapack stores matrices in column-major order so transposing is neded everywhere +template static inline void +transpose_square_inplace(fptype *src, size_t src_ld, size_t m) +{ + for(size_t i = 0; i < m - 1; i++) + for(size_t j = i + 1; j < m; j++) + std::swap(src[j*src_ld + i], src[i*src_ld + j]); +} + +template static inline void +transpose(const fptype *src, size_t src_ld, fptype* dst, size_t dst_ld, size_t m, size_t n) +{ + for(size_t i = 0; i < m; i++) + for(size_t j = 0; j < n; j++) + dst[j*dst_ld + i] = src[i*src_ld + j]; +} + +template static inline void +copy_matrix(const fptype *src, size_t src_ld, fptype* dst, size_t dst_ld, size_t m, size_t n) +{ + for(size_t i = 0; i < m; i++) + for(size_t j = 0; j < n; j++) + dst[i*dst_ld + j] = src[i*src_ld + j]; +} + +template static inline void +set_value(fptype *dst, size_t dst_ld, fptype value, size_t m, size_t n) +{ + for(size_t i = 0; i < m; i++) + for(size_t j = 0; j < n; j++) + dst[i*dst_ld + j] = value; +} + +template static inline int +lapack_LU(fptype* a, size_t a_step, int m, fptype* b, size_t b_step, int n, int* info) +{ + int lda = a_step / sizeof(fptype), sign = 0; + int* piv = new int[m]; + + transpose_square_inplace(a, lda, m); + + if(b) + { + if(n == 1 && b_step == sizeof(fptype)) + { + if(typeid(fptype) == typeid(float)) + sgesv_(&m, &n, (float*)a, &lda, piv, (float*)b, &m, info); + else if(typeid(fptype) == typeid(double)) + dgesv_(&m, &n, (double*)a, &lda, piv, (double*)b, &m, info); + } + else + { + int ldb = b_step / sizeof(fptype); + fptype* tmpB = new fptype[m*n]; + + transpose(b, ldb, tmpB, m, m, n); + + if(typeid(fptype) == typeid(float)) + sgesv_(&m, &n, (float*)a, &lda, piv, (float*)tmpB, &m, info); + else if(typeid(fptype) == typeid(double)) + dgesv_(&m, &n, (double*)a, &lda, piv, (double*)tmpB, &m, info); + + transpose(tmpB, m, b, ldb, n, m); + delete[] tmpB; + } + } + else + { + if(typeid(fptype) == typeid(float)) + sgetrf_(&m, &m, (float*)a, &lda, piv, info); + else if(typeid(fptype) == typeid(double)) + dgetrf_(&m, &m, (double*)a, &lda, piv, info); + } + + if(*info == 0) + { + for(int i = 0; i < m; i++) + sign ^= piv[i] != i + 1; + *info = sign ? -1 : 1; + } + else + *info = 0; //in opencv LU function zero means error + + delete[] piv; + return CV_HAL_ERROR_OK; +} + +template static inline int +lapack_Cholesky(fptype* a, size_t a_step, int m, fptype* b, size_t b_step, int n, bool* info) +{ + int lapackStatus; + int lda = a_step / sizeof(fptype); + char L[] = {'L', '\0'}; + + if(b) + { + if(n == 1 && b_step == sizeof(fptype)) + { + if(typeid(fptype) == typeid(float)) + 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); + } + else + { + int ldb = b_step / sizeof(fptype); + fptype* tmpB = new fptype[m*n]; + transpose(b, ldb, tmpB, m, m, n); + + if(typeid(fptype) == typeid(float)) + 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); + + transpose(tmpB, m, b, ldb, n, m); + delete[] tmpB; + } + } + else + { + if(typeid(fptype) == typeid(float)) + spotrf_(L, &m, (float*)a, &lda, &lapackStatus); + else if(typeid(fptype) == typeid(double)) + dpotrf_(L, &m, (double*)a, &lda, &lapackStatus); + } + + if(lapackStatus == 0) *info = true; + else *info = false; //in opencv Cholesky function false means error + + return CV_HAL_ERROR_OK; +} + +template static inline int +lapack_SVD(fptype* a, size_t a_step, fptype *w, fptype* u, size_t u_step, fptype* vt, size_t v_step, int m, int n, int flags, int* info) +{ + int lda = a_step / sizeof(fptype); + int ldv = v_step / sizeof(fptype); + int ldu = u_step / sizeof(fptype); + int lwork = -1; + int* iworkBuf = new int[8*std::min(m, n)]; + fptype work1 = 0; + + //A already transposed and m>=n + char mode[] = { ' ', '\0'}; + if(flags & CV_HAL_SVD_NO_UV) + { + ldv = 1; + mode[0] = 'N'; + } + else if((flags & CV_HAL_SVD_SHORT_UV) && (flags & CV_HAL_SVD_MODIFY_A)) //short SVD, U stored in a + mode[0] = 'O'; + else if((flags & CV_HAL_SVD_SHORT_UV) && !(flags & CV_HAL_SVD_MODIFY_A)) //short SVD, U stored in u if m>=n + mode[0] = 'S'; + else if(flags & CV_HAL_SVD_FULL_UV) //full SVD, U stored in u or in a + mode[0] = 'A'; + + if((flags & CV_HAL_SVD_MODIFY_A) && (flags & CV_HAL_SVD_FULL_UV)) //U stored in a + { + u = new fptype[m*m]; + ldu = m; + } + + 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); + 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); + + lwork = 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); + 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); + + if(!(flags & CV_HAL_SVD_NO_UV)) + transpose_square_inplace(vt, ldv, n); + + if((flags & CV_HAL_SVD_MODIFY_A) && (flags & CV_HAL_SVD_FULL_UV)) + { + for(int i = 0; i < m; i++) + for(int j = 0; j < m; j++) + a[i*lda + j] = u[i*m + j]; + delete[] u; + } + + delete[] iworkBuf; + delete[] buffer; + return CV_HAL_ERROR_OK; +} + +template static inline int +lapack_gemm(const fptype *src1, size_t src1_step, const fptype *src2, size_t src2_step, fptype alpha, + const fptype *src3, size_t src3_step, fptype beta, fptype *dst, size_t dst_step, int a_m, int a_n, int d_n, int flags) +{ + int ldsrc1 = src1_step / sizeof(fptype); + int ldsrc2 = src2_step / sizeof(fptype); + int ldsrc3 = src3_step / sizeof(fptype); + int lddst = dst_step / sizeof(fptype); + int c_m, c_n, d_m; + CBLAS_TRANSPOSE transA, transB; + + if(flags & CV_HAL_GEMM_2_T) + { + transB = CblasTrans; + if(flags & CV_HAL_GEMM_1_T ) + { + d_m = a_n; + } + else + { + d_m = a_m; + } + } + else + { + transB = CblasNoTrans; + if(flags & CV_HAL_GEMM_1_T ) + { + d_m = a_n; + } + else + { + d_m = a_m; + } + } + + if(flags & CV_HAL_GEMM_3_T) + { + c_m = d_n; + c_n = d_m; + } + else + { + c_m = d_m; + c_n = d_n; + } + + if(flags & CV_HAL_GEMM_1_T ) + { + transA = CblasTrans; + std::swap(a_n, a_m); + } + else + { + transA = CblasNoTrans; + } + + if(src3 != dst && beta != 0.0 && src3_step != 0) { + if(flags & CV_HAL_GEMM_3_T) + transpose(src3, ldsrc3, dst, lddst, c_m, c_n); + else + copy_matrix(src3, ldsrc3, dst, lddst, c_m, c_n); + } + else if (src3 == dst && (flags & CV_HAL_GEMM_3_T)) //actually transposing C in this case done by openCV + return CV_HAL_ERROR_NOT_IMPLEMENTED; + else if(src3_step == 0 && beta != 0.0) + set_value(dst, lddst, (fptype)0.0, d_m, d_n); + + if(typeid(fptype) == typeid(float)) + cblas_sgemm(CblasRowMajor, transA, transB, a_m, d_n, a_n, (float)alpha, (float*)src1, ldsrc1, (float*)src2, ldsrc2, (float)beta, (float*)dst, lddst); + else if(typeid(fptype) == typeid(double)) + cblas_dgemm(CblasRowMajor, transA, transB, a_m, d_n, a_n, (double)alpha, (double*)src1, ldsrc1, (double*)src2, ldsrc2, (double)beta, (double*)dst, lddst); + + return CV_HAL_ERROR_OK; +} + + +template static inline int +lapack_gemm_c(const fptype *src1, size_t src1_step, const fptype *src2, size_t src2_step, fptype alpha, + const fptype *src3, size_t src3_step, fptype beta, fptype *dst, size_t dst_step, int a_m, int a_n, int d_n, int flags) +{ + int ldsrc1 = src1_step / sizeof(std::complex); + int ldsrc2 = src2_step / sizeof(std::complex); + int ldsrc3 = src3_step / sizeof(std::complex); + int lddst = dst_step / sizeof(std::complex); + int c_m, c_n, d_m; + CBLAS_TRANSPOSE transA, transB; + std::complex cAlpha(alpha, 0.0); + std::complex cBeta(beta, 0.0); + + if(flags & CV_HAL_GEMM_2_T) + { + transB = CblasTrans; + if(flags & CV_HAL_GEMM_1_T ) + { + d_m = a_n; + } + else + { + d_m = a_m; + } + } + else + { + transB = CblasNoTrans; + if(flags & CV_HAL_GEMM_1_T ) + { + d_m = a_n; + } + else + { + d_m = a_m; + } + } + + if(flags & CV_HAL_GEMM_3_T) + { + c_m = d_n; + c_n = d_m; + } + else + { + c_m = d_m; + c_n = d_n; + } + + if(flags & CV_HAL_GEMM_1_T ) + { + transA = CblasTrans; + std::swap(a_n, a_m); + } + else + { + transA = CblasNoTrans; + } + + if(src3 != dst && beta != 0.0 && src3_step != 0) { + if(flags & CV_HAL_GEMM_3_T) + transpose((std::complex*)src3, ldsrc3, (std::complex*)dst, lddst, c_m, c_n); + else + copy_matrix((std::complex*)src3, ldsrc3, (std::complex*)dst, lddst, c_m, c_n); + } + else if (src3 == dst && (flags & CV_HAL_GEMM_3_T)) //actually transposing C in this case done by openCV + return CV_HAL_ERROR_NOT_IMPLEMENTED; + else if(src3_step == 0 && beta != 0.0) + set_value((std::complex*)dst, lddst, std::complex(0.0, 0.0), d_m, d_n); + + if(typeid(fptype) == typeid(float)) + cblas_cgemm(CblasRowMajor, transA, transB, a_m, d_n, a_n, &cAlpha, (void*)src1, ldsrc1, (void*)src2, ldsrc2, &cBeta, (void*)dst, lddst); + else if(typeid(fptype) == typeid(double)) + cblas_zgemm(CblasRowMajor, transA, transB, a_m, d_n, a_n, &cAlpha, (void*)src1, ldsrc1, (void*)src2, ldsrc2, &cBeta, (void*)dst, lddst); + + return CV_HAL_ERROR_OK; +} +int lapack_LU32f(float* a, size_t a_step, int m, float* b, size_t b_step, int n, int* info) +{ + if(m < HAL_LU_SMALL_MATRIX_THRESH) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + return lapack_LU(a, a_step, m, b, b_step, n, info); +} + +int lapack_LU64f(double* a, size_t a_step, int m, double* b, size_t b_step, int n, int* info) +{ + if(m < HAL_LU_SMALL_MATRIX_THRESH) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + return lapack_LU(a, a_step, m, b, b_step, n, info); +} + +int lapack_Cholesky32f(float* a, size_t a_step, int m, float* b, size_t b_step, int n, bool *info) +{ + if(m < HAL_CHOLESKY_SMALL_MATRIX_THRESH) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + return lapack_Cholesky(a, a_step, m, b, b_step, n, info); +} + +int lapack_Cholesky64f(double* a, size_t a_step, int m, double* b, size_t b_step, int n, bool *info) +{ + if(m < HAL_CHOLESKY_SMALL_MATRIX_THRESH) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + return lapack_Cholesky(a, a_step, m, b, b_step, n, info); +} + +int lapack_SVD32f(float* a, size_t a_step, float *w, float* u, size_t u_step, float* vt, size_t v_step, int m, int n, int flags) +{ + + if(m < HAL_SVD_SMALL_MATRIX_THRESH) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + int info; + return lapack_SVD(a, a_step, w, u, u_step, vt, v_step, m, n, flags, &info); +} + +int lapack_SVD64f(double* a, size_t a_step, double *w, double* u, size_t u_step, double* vt, size_t v_step, int m, int n, int flags) +{ + + if(m < HAL_SVD_SMALL_MATRIX_THRESH) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + int info; + return lapack_SVD(a, a_step, w, u, u_step, vt, v_step, m, n, flags, &info); +} + +int lapack_gemm32f(const float *src1, size_t src1_step, const float *src2, size_t src2_step, float alpha, + const float *src3, size_t src3_step, float beta, float *dst, size_t dst_step, int m, int n, int k, int flags) +{ + if(m < HAL_GEMM_SMALL_MATRIX_THRESH) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + return lapack_gemm(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m, n, k, flags); +} + +int lapack_gemm64f(const double *src1, size_t src1_step, const double *src2, size_t src2_step, double alpha, + const double *src3, size_t src3_step, double beta, double *dst, size_t dst_step, int m, int n, int k, int flags) +{ + if(m < HAL_GEMM_SMALL_MATRIX_THRESH) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + return lapack_gemm(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m, n, k, flags); +} + +int lapack_gemm32fc(const float *src1, size_t src1_step, const float *src2, size_t src2_step, float alpha, + const float *src3, size_t src3_step, float beta, float *dst, size_t dst_step, int m, int n, int k, int flags) +{ + if(m < HAL_GEMM_SMALL_COMPLEX_MATRIX_THRESH) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + return lapack_gemm_c(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m, n, k, flags); +} +int lapack_gemm64fc(const double *src1, size_t src1_step, const double *src2, size_t src2_step, double alpha, + const double *src3, size_t src3_step, double beta, double *dst, size_t dst_step, int m, int n, int k, int flags) +{ + if(m < HAL_GEMM_SMALL_COMPLEX_MATRIX_THRESH) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + return lapack_gemm_c(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m, n, k, flags); +} + +#endif //HAVE_LAPACK diff --git a/modules/core/src/hal_internal.hpp b/modules/core/src/hal_internal.hpp new file mode 100644 index 000000000..26bc142e0 --- /dev/null +++ b/modules/core/src/hal_internal.hpp @@ -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. +// +// +// 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. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez 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*/ + +#ifndef OPENCV_CORE_HAL_INTERNAL_HPP +#define OPENCV_CORE_HAL_INTERNAL_HPP + +#include "precomp.hpp" + +#ifdef HAVE_LAPACK + +int lapack_LU32f(float* a, size_t a_step, int m, float* b, size_t b_step, int n, int* info); +int lapack_LU64f(double* a, size_t a_step, int m, double* b, size_t b_step, int n, int* info); +int lapack_Cholesky32f(float* a, size_t a_step, int m, float* b, size_t b_step, int n, bool* info); +int lapack_Cholesky64f(double* a, size_t a_step, int m, double* b, size_t b_step, int n, bool* info); +int lapack_SVD32f(float* a, size_t a_step, float* w, float* u, size_t u_step, float* vt, size_t v_step, int m, int n, int flags); +int lapack_SVD64f(double* a, size_t a_step, double* w, double* u, size_t u_step, double* vt, size_t v_step, int m, int n, int flags); +int lapack_gemm32f(const float* src1, size_t src1_step, const float* src2, size_t src2_step, + float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, + int m, int n, int k, int flags); +int lapack_gemm64f(const double* src1, size_t src1_step, const double* src2, size_t src2_step, + double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, + int m, int n, int k, int flags); +int lapack_gemm32fc(const float* src1, size_t src1_step, const float* src2, size_t src2_step, + float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, + int m, int n, int k, int flags); +int lapack_gemm64fc(const double* src1, size_t src1_step, const double* src2, size_t src2_step, + double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, + int m, int n, int k, int flags); + +#undef cv_hal_LU32f +#define cv_hal_LU32f lapack_LU32f +#undef cv_hal_LU64f +#define cv_hal_LU64f lapack_LU64f + +#undef cv_hal_Cholesky32f +#define cv_hal_Cholesky32f lapack_Cholesky32f +#undef cv_hal_Cholesky64f +#define cv_hal_Cholesky64f lapack_Cholesky64f + +#undef cv_hal_SVD32f +#define cv_hal_SVD32f lapack_SVD32f +#undef cv_hal_SVD64f +#define cv_hal_SVD64f lapack_SVD64f + +#undef cv_hal_gemm32f +#define cv_hal_gemm32f lapack_gemm32f +#undef cv_hal_gemm64f +#define cv_hal_gemm64f lapack_gemm64f +#undef cv_hal_gemm32fc +#define cv_hal_gemm32fc lapack_gemm32fc +#undef cv_hal_gemm64fc +#define cv_hal_gemm64fc lapack_gemm64fc + +#endif //HAVE_LAPACK +#endif //OPENCV_CORE_HAL_INTERNAL_HPP diff --git a/modules/core/src/hal_replacement.hpp b/modules/core/src/hal_replacement.hpp index 93476c459..605ae3863 100644 --- a/modules/core/src/hal_replacement.hpp +++ b/modules/core/src/hal_replacement.hpp @@ -472,14 +472,148 @@ inline int hal_ni_dctFree2D(cvhalDFT *context) { return CV_HAL_ERROR_NOT_IMPLEME #define cv_hal_dctFree2D hal_ni_dctFree2D //! @endcond + +/** +Performs \f$LU\f$ decomposition of square matrix \f$A=P*L*U\f$ (where \f$P\f$ is permutation matrix) and solves matrix equation \f$A*X=B\f$. +Function returns the \f$sign\f$ of permutation \f$P\f$ via parameter info. +@param src1 pointer to input matrix \f$A\f$ stored in row major order. After finish of work src1 contains at least \f$U\f$ part of \f$LU\f$ +decomposition which is appropriate for determainant calculation: \f$det(A)=sign*\prod_{j=1}^{M}a_{jj}\f$. +@param src1_step number of bytes each matrix \f$A\f$ row occupies. +@param m size of square matrix \f$A\f$. +@param src2 pointer to \f$M\times N\f$ matrix \f$B\f$ which is the right-hand side of system \f$A*X=B\f$. \f$B\f$ stored in row major order. +If src2 is null pointer only \f$LU\f$ decomposition will be performed. After finish of work src2 contains solution \f$X\f$ of system \f$A*X=B\f$. +@param src2_step number of bytes each matrix \f$B\f$ row occupies. +@param n number of right-hand vectors in \f$M\times N\f$ matrix \f$B\f$. +@param info indicates success of decomposition. If *info is equals to zero decomposition failed, othervise *info is equals to \f$sign\f$. + */ +//! @addtogroup core_hal_interface_decomp_lu LU matrix decomposition +//! @{ +inline int hal_ni_LU32f(float* src1, size_t src1_step, int m, float* src2, size_t src2_step, int n, int* info) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_LU64f(double* src1, size_t src1_step, int m, double* src2, size_t src2_step, int n, int* info) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } //! @} +/** +Performs Cholesky decomposition of matrix \f$A = L*L^T\f$ and solves matrix equation \f$A*X=B\f$. +@param src1 pointer to input matrix \f$A\f$ stored in row major order. After finish of work src1 contains lower triangular matrix \f$L\f$. +@param src1_step number of bytes each matrix \f$A\f$ row occupies. +@param m size of square matrix \f$A\f$. +@param src2 pointer to \f$M\times N\f$ matrix \f$B\f$ which is the right-hand side of system \f$A*X=B\f$. B stored in row major order. +If src2 is null pointer only Cholesky decomposition will be performed. After finish of work src2 contains solution \f$X\f$ of system \f$A*X=B\f$. +@param src2_step number of bytes each matrix \f$B\f$ row occupies. +@param n number of right-hand vectors in \f$M\times N\f$ matrix \f$B\f$. +@param info indicates success of decomposition. If *info is false decomposition failed. + */ + +//! @addtogroup core_hal_interface_decomp_cholesky Cholesky matrix decomposition +//! @{ +inline int hal_ni_Cholesky32f(float* src1, size_t src1_step, int m, float* src2, size_t src2_step, int n, bool* info) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_Cholesky64f(double* src1, size_t src1_step, int m, double* src2, size_t src2_step, int n, bool* info) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +//! @} + +/** +Performs singular value decomposition of \f$M\times N\f$(\f$M>N\f$) matrix \f$A = U*\Sigma*V^T\f$. +@param src pointer to input \f$M\times N\f$ matrix \f$A\f$ stored in column major order. +After finish of work src will be filled with rows of \f$U\f$ or not modified (depends of flag CV_HAL_SVD_MODIFY_A). +@param src_step number of bytes each matrix \f$A\f$ column occupies. +@param w pointer to array for singular values of matrix \f$A\f$ (i. e. first \f$N\f$ diagonal elements of matrix \f$\Sigma\f$). +@param u pointer to output \f$M\times N\f$ or \f$M\times M\f$ matrix \f$U\f$ (size depends of flags). Pointer must be valid if flag CV_HAL_SVD_MODIFY_A not used. +@param u_step number of bytes each matrix \f$U\f$ row occupies. +@param vt pointer to array for \f$N\times N\f$ matrix \f$V^T\f$. +@param vt_step number of bytes each matrix \f$V^T\f$ row occupies. +@param m number fo rows in matrix \f$A\f$. +@param n number of columns in matrix \f$A\f$. +@param flags algorithm options (combination of CV_HAL_SVD_FULL_UV, ...). + */ +//! @addtogroup core_hal_interface_decomp_svd Singular value matrix decomposition +//! @{ +inline int hal_ni_SVD32f(float* src, size_t src_step, float* w, float* u, size_t u_step, float* vt, size_t vt_step, int m, int n, int flags) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_SVD64f(double* src, size_t src_step, double* w, double* u, size_t u_step, double* vt, size_t vt_step, int m, int n, int flags) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +//! @} + + + +//! @cond IGNORED +#define cv_hal_LU32f hal_ni_LU32f +#define cv_hal_LU64f hal_ni_LU64f +#define cv_hal_Cholesky32f hal_ni_Cholesky32f +#define cv_hal_Cholesky64f hal_ni_Cholesky64f +#define cv_hal_SVD32f hal_ni_SVD32f +#define cv_hal_SVD64f hal_ni_SVD64f +//! @endcond + + +/** +The function performs generalized matrix multiplication similar to the gemm functions in BLAS level 3: +\f$D = \alpha*AB+\beta*C\f$ + +@param src1 pointer to input \f$M\times N\f$ matrix \f$A\f$ or \f$A^T\f$ stored in row major order. +@param src1_step number of bytes each matrix \f$A\f$ or \f$A^T\f$ row occupies. +@param src2 pointer to input \f$N\times K\f$ matrix \f$B\f$ or \f$B^T\f$ stored in row major order. +@param src2_step number of bytes each matrix \f$B\f$ or \f$B^T\f$ row occupies. +@param alpha \f$\alpha\f$ multiplier before \f$AB\f$ +@param src3 pointer to input \f$M\times K\f$ matrix \f$C\f$ or \f$C^T\f$ stored in row major order. +@param src3_step number of bytes each matrix \f$C\f$ or \f$C^T\f$ row occupies. +@param beta \f$\beta\f$ multiplier before \f$C\f$ +@param dst pointer to input \f$M\times K\f$ matrix \f$D\f$ stored in row major order. +@param dst_step number of bytes each matrix \f$D\f$ row occupies. +@param m number of rows in matrix \f$A\f$ or \f$A^T\f$, equals to number of rows in matrix \f$D\f$ +@param n number of columns in matrix \f$A\f$ or \f$A^T\f$ +@param k number of columns in matrix \f$B\f$ or \f$B^T\f$, equals to number of columns in matrix \f$D\f$ +@param flags algorithm options (combination of CV_HAL_GEMM_1_T, ...). + */ + +//! @addtogroup core_hal_interface_matrix_multiplication Matrix multiplication +//! @{ +inline int hal_ni_gemm32f(const float* src1, size_t src1_step, const float* src2, size_t src2_step, + float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, + int m, int n, int k, int flags) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_gemm64f(const double* src1, size_t src1_step, const double* src2, size_t src2_step, + double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, + int m, int n, int k, int flags) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_gemm32fc(const float* src1, size_t src1_step, const float* src2, size_t src2_step, + float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, + int m, int n, int k, int flags) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_gemm64fc(const double* src1, size_t src1_step, const double* src2, size_t src2_step, + double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, + int m, int n, int k, int flags) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +//! @} + +//! @cond IGNORED +#define cv_hal_gemm32f hal_ni_gemm32f +#define cv_hal_gemm64f hal_ni_gemm64f +#define cv_hal_gemm32fc hal_ni_gemm32fc +#define cv_hal_gemm64fc hal_ni_gemm64fc +//! @endcond + +//! @} + + #if defined __GNUC__ # pragma GCC diagnostic pop #elif defined _MSC_VER # pragma warning( pop ) #endif +#include "hal_internal.hpp" #include "custom_hal.hpp" +//! @cond IGNORED +#define CALL_HAL_RET(name, fun, retval, ...) \ + int res = fun(__VA_ARGS__, &retval); \ + if (res == CV_HAL_ERROR_OK) \ + return retval; \ + else if (res != CV_HAL_ERROR_NOT_IMPLEMENTED) \ + CV_Error_(cv::Error::StsInternal, \ + ("HAL implementation " CVAUX_STR(name) " ==> " CVAUX_STR(fun) " returned %d (0x%08x)", res, res)); + + +#define CALL_HAL(name, fun, ...) \ + int res = fun(__VA_ARGS__); \ + if (res == CV_HAL_ERROR_OK) \ + return; \ + else if (res != CV_HAL_ERROR_NOT_IMPLEMENTED) \ + CV_Error_(cv::Error::StsInternal, \ + ("HAL implementation " CVAUX_STR(name) " ==> " CVAUX_STR(fun) " returned %d (0x%08x)", res, res)); +//! @endcond + #endif diff --git a/modules/core/src/lapack.cpp b/modules/core/src/lapack.cpp index 4fcf3c792..3711ca9e1 100644 --- a/modules/core/src/lapack.cpp +++ b/modules/core/src/lapack.cpp @@ -570,11 +570,44 @@ JacobiSVDImpl_(_Tp* At, size_t astep, _Tp* _W, _Tp* Vt, size_t vstep, static void JacobiSVD(float* At, size_t astep, float* W, float* Vt, size_t vstep, int m, int n, int n1=-1) { - JacobiSVDImpl_(At, astep, W, Vt, vstep, m, n, !Vt ? 0 : n1 < 0 ? n : n1, FLT_MIN, FLT_EPSILON*2); + hal::SVD32f(At, astep, W, NULL, astep, Vt, vstep, m, n, n1); } static void JacobiSVD(double* At, size_t astep, double* W, double* Vt, size_t vstep, int m, int n, int n1=-1) { + hal::SVD64f(At, astep, W, NULL, astep, Vt, vstep, m, n, n1); +} + +template static inline int +decodeSVDParameters(const fptype* U, const fptype* Vt, int m, int n, int n1) +{ + int halSVDFlag = 0; + if(Vt == NULL) + halSVDFlag = CV_HAL_SVD_NO_UV; + else if(n1 <= 0 || n1 == n) + { + halSVDFlag = CV_HAL_SVD_SHORT_UV; + if(U == NULL) + halSVDFlag |= CV_HAL_SVD_MODIFY_A; + } + else if(n1 == m) + { + halSVDFlag = CV_HAL_SVD_FULL_UV; + if(U == NULL) + halSVDFlag |= CV_HAL_SVD_MODIFY_A; + } + return halSVDFlag; +} + +void hal::SVD32f(float* At, size_t astep, float* W, float* U, size_t ustep, float* Vt, size_t vstep, int m, int n, int n1) +{ + CALL_HAL(SVD32f, cv_hal_SVD32f, At, astep, W, U, ustep, Vt, vstep, m, n, decodeSVDParameters(U, Vt, m, n, n1)) + JacobiSVDImpl_(At, astep, W, Vt, vstep, m, n, !Vt ? 0 : n1 < 0 ? n : n1, FLT_MIN, FLT_EPSILON*2); +} + +void hal::SVD64f(double* At, size_t astep, double* W, double* U, size_t ustep, double* Vt, size_t vstep, int m, int n, int n1) +{ + CALL_HAL(SVD64f, cv_hal_SVD64f, At, astep, W, U, ustep, Vt, vstep, m, n, decodeSVDParameters(U, Vt, m, n, n1)) JacobiSVDImpl_(At, astep, W, Vt, vstep, m, n, !Vt ? 0 : n1 < 0 ? n : n1, DBL_MIN, DBL_EPSILON*10); } @@ -745,7 +778,6 @@ double cv::determinant( InputArray _mat ) { for( int i = 0; i < rows; i++ ) result *= a.at(i,i); - result = 1./result; } } } @@ -769,7 +801,6 @@ double cv::determinant( InputArray _mat ) { for( int i = 0; i < rows; i++ ) result *= a.at(i,i); - result = 1./result; } } } diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.cpp index cf83ecea8..4b0690a8b 100644 --- a/modules/core/src/matmul.cpp +++ b/modules/core/src/matmul.cpp @@ -864,73 +864,39 @@ static bool ocl_gemm( InputArray matA, InputArray matB, double alpha, return k.run(2, globalsize, block_size!=1 ? localsize : NULL, false); } #endif -} -void cv::gemm( InputArray matA, InputArray matB, double alpha, - InputArray matC, double beta, OutputArray _matD, int flags ) +static void _gemmImplInternal( Mat A, Mat B, double alpha, + Mat C, double beta, Mat D, int flags ) { -#ifdef HAVE_CLAMDBLAS - CV_OCL_RUN(ocl::haveAmdBlas() && matA.dims() <= 2 && matB.dims() <= 2 && matC.dims() <= 2 && _matD.isUMat() && - matA.cols() > 20 && matA.rows() > 20 && matB.cols() > 20, // since it works incorrect for small sizes - ocl_gemm_amdblas(matA, matB, alpha, matC, beta, _matD, flags)) -#endif - -#ifdef HAVE_OPENCL - CV_OCL_RUN(_matD.isUMat() && matA.dims() <= 2 && matB.dims() <= 2 && matC.dims() <= 2, - ocl_gemm(matA, matB, alpha, matC, beta, _matD, flags)) -#endif - const int block_lin_size = 128; const int block_size = block_lin_size * block_lin_size; static double zero[] = {0,0,0,0}; static float zerof[] = {0,0,0,0}; - Mat A = matA.getMat(), B = matB.getMat(), C = beta != 0 ? matC.getMat() : Mat(); Size a_size = A.size(), d_size; int i, len = 0, type = A.type(); - CV_Assert( type == B.type() && (type == CV_32FC1 || type == CV_64FC1 || type == CV_32FC2 || type == CV_64FC2) ); - switch( flags & (GEMM_1_T|GEMM_2_T) ) { case 0: d_size = Size( B.cols, a_size.height ); len = B.rows; - CV_Assert( a_size.width == len ); break; case 1: d_size = Size( B.cols, a_size.width ); len = B.rows; - CV_Assert( a_size.height == len ); break; case 2: d_size = Size( B.rows, a_size.height ); len = B.cols; - CV_Assert( a_size.width == len ); break; case 3: d_size = Size( B.rows, a_size.width ); len = B.cols; - CV_Assert( a_size.height == len ); break; } - if( !C.empty() ) - { - CV_Assert( C.type() == type && - (((flags&GEMM_3_T) == 0 && C.rows == d_size.height && C.cols == d_size.width) || - ((flags&GEMM_3_T) != 0 && C.rows == d_size.width && C.cols == d_size.height))); - } - - _matD.create( d_size.height, d_size.width, type ); - Mat D = _matD.getMat(); - if( (flags & GEMM_3_T) != 0 && C.data == D.data ) - { - transpose( C, C ); - flags &= ~GEMM_3_T; - } - if( flags == 0 && 2 <= len && len <= 4 && (len == d_size.width || len == d_size.height) ) { if( type == CV_32F ) @@ -1194,8 +1160,7 @@ void cv::gemm( InputArray matA, InputArray matB, double alpha, GEMMSingleMulFunc singleMulFunc; GEMMBlockMulFunc blockMulFunc; GEMMStoreFunc storeFunc; - Mat *matD = &D, tmat; - size_t tmat_size = 0; + Mat *matD = &D; const uchar* Cdata = C.data; size_t Cstep = C.data ? (size_t)C.step : 0; AutoBuffer buf; @@ -1226,13 +1191,6 @@ void cv::gemm( InputArray matA, InputArray matB, double alpha, storeFunc = (GEMMStoreFunc)GEMMStore_64fc; } - if( D.data == A.data || D.data == B.data ) - { - tmat_size = (size_t)d_size.width*d_size.height*CV_ELEM_SIZE(type); - // Allocate tmat later, once the size of buf is known - matD = &tmat; - } - if( (d_size.width == 1 || len == 1) && !(flags & GEMM_2_T) && B.isContinuous() ) { b_step = d_size.width == 1 ? 0 : CV_ELEM_SIZE(type); @@ -1306,10 +1264,6 @@ void cv::gemm( InputArray matA, InputArray matB, double alpha, (d_size.width <= block_lin_size && d_size.height <= block_lin_size && len <= block_lin_size) ) { - if( tmat_size > 0 ) { - buf.allocate(tmat_size); - tmat = Mat(d_size.height, d_size.width, type, (uchar*)buf ); - } singleMulFunc( A.ptr(), A.step, B.ptr(), b_step, Cdata, Cstep, matD->ptr(), matD->step, a_size, d_size, alpha, beta, flags ); } @@ -1369,14 +1323,12 @@ void cv::gemm( InputArray matA, InputArray matB, double alpha, flags &= ~GEMM_1_T; } - buf.allocate(d_buf_size + b_buf_size + a_buf_size + tmat_size); + buf.allocate(d_buf_size + b_buf_size + a_buf_size); d_buf = (uchar*)buf; b_buf = d_buf + d_buf_size; if( is_a_t ) a_buf = b_buf + b_buf_size; - if( tmat_size > 0 ) - tmat = Mat(d_size.height, d_size.width, type, b_buf + b_buf_size + a_buf_size ); for( i = 0; i < d_size.height; i += di ) { @@ -1455,12 +1407,200 @@ void cv::gemm( InputArray matA, InputArray matB, double alpha, } } } - - if( matD != &D ) - matD->copyTo(D); } } +template inline static void +_callInternalGemmImpl(const fptype *src1, size_t src1_step, const fptype *src2, size_t src2_step, fptype alpha, + const fptype *src3, size_t src3_step, fptype beta, fptype *dst, size_t dst_step, int m_a, int n_a, int n_d, int flags, int type) +{ + CV_StaticAssert(GEMM_1_T == CV_HAL_GEMM_1_T, "Incompatible GEMM_1_T flag in HAL"); + CV_StaticAssert(GEMM_2_T == CV_HAL_GEMM_2_T, "Incompatible GEMM_2_T flag in HAL"); + CV_StaticAssert(GEMM_3_T == CV_HAL_GEMM_3_T, "Incompatible GEMM_3_T flag in HAL"); + + int b_m, b_n, c_m, c_n, m_d; + + if(flags & GEMM_2_T) + { + b_m = n_d; + if(flags & GEMM_1_T ) + { + b_n = m_a; + m_d = n_a; + } + else + { + b_n = n_a; + m_d = m_a; + } + } + else + { + b_n = n_d; + if(flags & GEMM_1_T ) + { + b_m = m_a; + m_d = n_a; + } + else + { + m_d = m_a; + b_m = n_a; + } + } + + if(flags & GEMM_3_T) + { + c_m = n_d; + c_n = m_d; + } + else + { + c_m = m_d; + c_n = n_d; + } + + Mat A, B, C; + if(src1 != NULL) + A = Mat(m_a, n_a, type, (void*)src1, src1_step); + if(src2 != NULL) + B = Mat(b_m, b_n, type, (void*)src2, src2_step); + if(src3 != NULL && beta != 0.0) + C = Mat(c_m, c_n, type, (void*)src3, src3_step); + Mat D(m_d, n_d, type, (void*)dst, dst_step); + + _gemmImplInternal(A, B, alpha, C, beta, D, flags); +} + +} + +void cv::hal::gemm32f(const float* src1, size_t src1_step, const float* src2, size_t src2_step, + float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags) +{ + + CALL_HAL(gemm32f, cv_hal_gemm32f, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) + _callInternalGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_32F); +} + +void cv::hal::gemm64f(const double* src1, size_t src1_step, const double* src2, size_t src2_step, + double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags) +{ + CALL_HAL(gemm64f, cv_hal_gemm64f, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) + _callInternalGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_64F); +} + +CV_EXPORTS void cv::hal::gemm32fc(const float* src1, size_t src1_step, const float* src2, size_t src2_step, + float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags) +{ + CALL_HAL(gemm32fc, cv_hal_gemm32fc, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) + _callInternalGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_32FC2); +} + +CV_EXPORTS void cv::hal::gemm64fc(const double* src1, size_t src1_step, const double* src2, size_t src2_step, + double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags) +{ + CALL_HAL(gemm64fc, cv_hal_gemm64fc, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) + _callInternalGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_64FC2); +} + +void cv::gemm( InputArray matA, InputArray matB, double alpha, + InputArray matC, double beta, OutputArray _matD, int flags ) +{ +#ifdef HAVE_CLAMDBLAS + CV_OCL_RUN(ocl::haveAmdBlas() && matA.dims() <= 2 && matB.dims() <= 2 && matC.dims() <= 2 && _matD.isUMat() && + matA.cols() > 20 && matA.rows() > 20 && matB.cols() > 20, // since it works incorrect for small sizes + ocl_gemm_amdblas(matA, matB, alpha, matC, beta, _matD, flags)) +#endif + +#ifdef HAVE_OPENCL + CV_OCL_RUN(_matD.isUMat() && matA.dims() <= 2 && matB.dims() <= 2 && matC.dims() <= 2, + ocl_gemm(matA, matB, alpha, matC, beta, _matD, flags)) +#endif + + Mat A = matA.getMat(), B = matB.getMat(), C = beta != 0.0 ? matC.getMat() : Mat(); + Size a_size = A.size(), d_size; + int len = 0, type = A.type(); + + CV_Assert( type == B.type() && (type == CV_32FC1 || type == CV_64FC1 || type == CV_32FC2 || type == CV_64FC2) ); + + switch( flags & (GEMM_1_T|GEMM_2_T) ) + { + case 0: + d_size = Size( B.cols, a_size.height ); + len = B.rows; + CV_Assert( a_size.width == len ); + break; + case 1: + d_size = Size( B.cols, a_size.width ); + len = B.rows; + CV_Assert( a_size.height == len ); + break; + case 2: + d_size = Size( B.rows, a_size.height ); + len = B.cols; + CV_Assert( a_size.width == len ); + break; + case 3: + d_size = Size( B.rows, a_size.width ); + len = B.cols; + CV_Assert( a_size.height == len ); + break; + } + + if( !C.empty() ) + { + CV_Assert( C.type() == type && + (((flags&GEMM_3_T) == 0 && C.rows == d_size.height && C.cols == d_size.width) || + ((flags&GEMM_3_T) != 0 && C.rows == d_size.width && C.cols == d_size.height))); + } + + _matD.create( d_size.height, d_size.width, type ); + Mat D = _matD.getMat(); + if( (flags & GEMM_3_T) != 0 && C.data == D.data ) + { + transpose( C, C ); + flags &= ~GEMM_3_T; + } + + Mat *DProxyPtr = &D, DProxy; + if( D.data == A.data || D.data == B.data ) + { + DProxy = Mat(d_size.height, d_size.width, D.type()); + DProxyPtr = &DProxy; + } + + if( type == CV_32FC1 ) + hal::gemm32f(A.ptr(), A.step, B.ptr(), B.step, static_cast(alpha), + C.ptr(), C.step, static_cast(beta), + DProxyPtr->ptr(), DProxyPtr->step, + a_size.height, a_size.width, DProxyPtr->cols, flags); + else if( type == CV_64FC1 ) + hal::gemm64f(A.ptr(), A.step, B.ptr(), B.step, alpha, + C.ptr(), C.step, beta, + DProxyPtr->ptr(), DProxyPtr->step, + a_size.height, a_size.width, DProxyPtr->cols, flags); + else if( type == CV_32FC2 ) + hal::gemm32fc(A.ptr(), A.step, B.ptr(), B.step, static_cast(alpha), + C.ptr(), C.step, static_cast(beta), + DProxyPtr->ptr(), DProxyPtr->step, + a_size.height, a_size.width, DProxyPtr->cols, flags); + else + { + CV_Assert( type == CV_64FC2 ); + hal::gemm64fc(A.ptr(), A.step, B.ptr(), B.step, alpha, + C.ptr(), C.step, beta, + D.ptr(), D.step, + a_size.height, a_size.width, DProxyPtr->cols, flags); + } + + if(DProxyPtr != &D) + DProxyPtr->copyTo(D); +} + /****************************************************************************************\ * Transform * \****************************************************************************************/ diff --git a/modules/core/src/matrix_decomp.cpp b/modules/core/src/matrix_decomp.cpp index 3fe9eca72..dc9c01493 100644 --- a/modules/core/src/matrix_decomp.cpp +++ b/modules/core/src/matrix_decomp.cpp @@ -89,8 +89,6 @@ LUImpl(_Tp* A, size_t astep, int m, _Tp* b, size_t bstep, int n, _Tp eps) for( k = 0; k < n; k++ ) b[j*bstep + k] += alpha*b[i*bstep + k]; } - - A[i*astep + i] = -d; } if( b ) @@ -101,7 +99,7 @@ LUImpl(_Tp* A, size_t astep, int m, _Tp* b, size_t bstep, int n, _Tp eps) _Tp s = b[i*bstep + j]; for( k = i+1; k < m; k++ ) s -= A[i*astep + k]*b[k*bstep + j]; - b[i*bstep + j] = s*A[i*astep + i]; + b[i*bstep + j] = s/A[i*astep + i]; } } @@ -111,13 +109,19 @@ LUImpl(_Tp* A, size_t astep, int m, _Tp* b, size_t bstep, int n, _Tp eps) int LU32f(float* A, size_t astep, int m, float* b, size_t bstep, int n) { - return LUImpl(A, astep, m, b, bstep, n, FLT_EPSILON*10); + int output; + CALL_HAL_RET(LU32f, cv_hal_LU32f, output, A, astep, m, b, bstep, n) + output = LUImpl(A, astep, m, b, bstep, n, FLT_EPSILON*10); + return output; } int LU64f(double* A, size_t astep, int m, double* b, size_t bstep, int n) { - return LUImpl(A, astep, m, b, bstep, n, DBL_EPSILON*100); + int output; + CALL_HAL_RET(LU64f, cv_hal_LU64f, output, A, astep, m, b, bstep, n) + output = LUImpl(A, astep, m, b, bstep, n, DBL_EPSILON*100); + return output; } template static inline bool @@ -193,14 +197,17 @@ CholImpl(_Tp* A, size_t astep, int m, _Tp* b, size_t bstep, int n) return true; } - bool Cholesky32f(float* A, size_t astep, int m, float* b, size_t bstep, int n) { + bool output; + CALL_HAL_RET(Cholesky32f, cv_hal_Cholesky32f, output, A, astep, m, b, bstep, n) return CholImpl(A, astep, m, b, bstep, n); } bool Cholesky64f(double* A, size_t astep, int m, double* b, size_t bstep, int n) { + bool output; + CALL_HAL_RET(Cholesky64f, cv_hal_Cholesky64f, output, A, astep, m, b, bstep, n) return CholImpl(A, astep, m, b, bstep, n); } diff --git a/modules/imgproc/src/hal_replacement.hpp b/modules/imgproc/src/hal_replacement.hpp index 2b681f6cf..e42cc44ad 100644 --- a/modules/imgproc/src/hal_replacement.hpp +++ b/modules/imgproc/src/hal_replacement.hpp @@ -309,4 +309,23 @@ inline int hal_ni_warpPerspectve(int src_type, const uchar *src_data, size_t src #include "custom_hal.hpp" +//! @cond IGNORED +#define CALL_HAL_RET(name, fun, retval, ...) \ + int res = fun(__VA_ARGS__, &retval); \ + if (res == CV_HAL_ERROR_OK) \ + return retval; \ + else if (res != CV_HAL_ERROR_NOT_IMPLEMENTED) \ + CV_Error_(cv::Error::StsInternal, \ + ("HAL implementation " CVAUX_STR(name) " ==> " CVAUX_STR(fun) " returned %d (0x%08x)", res, res)); + + +#define CALL_HAL(name, fun, ...) \ + int res = fun(__VA_ARGS__); \ + if (res == CV_HAL_ERROR_OK) \ + return; \ + else if (res != CV_HAL_ERROR_NOT_IMPLEMENTED) \ + CV_Error_(cv::Error::StsInternal, \ + ("HAL implementation " CVAUX_STR(name) " ==> " CVAUX_STR(fun) " returned %d (0x%08x)", res, res)); +//! @endcond + #endif From 055f5c73959f84092c8f38527ae510c44487deaa Mon Sep 17 00:00:00 2001 From: Vladislav Sovrasov Date: Tue, 7 Jun 2016 10:58:12 +0300 Subject: [PATCH 02/10] Change names of some internal functions --- modules/core/src/matmul.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.cpp index 4b0690a8b..88097ca00 100644 --- a/modules/core/src/matmul.cpp +++ b/modules/core/src/matmul.cpp @@ -865,7 +865,7 @@ static bool ocl_gemm( InputArray matA, InputArray matB, double alpha, } #endif -static void _gemmImplInternal( Mat A, Mat B, double alpha, +static void gemmImpl( Mat A, Mat B, double alpha, Mat C, double beta, Mat D, int flags ) { const int block_lin_size = 128; @@ -1411,7 +1411,7 @@ static void _gemmImplInternal( Mat A, Mat B, double alpha, } template inline static void -_callInternalGemmImpl(const fptype *src1, size_t src1_step, const fptype *src2, size_t src2_step, fptype alpha, +callGemmImpl(const fptype *src1, size_t src1_step, const fptype *src2, size_t src2_step, fptype alpha, const fptype *src3, size_t src3_step, fptype beta, fptype *dst, size_t dst_step, int m_a, int n_a, int n_d, int flags, int type) { CV_StaticAssert(GEMM_1_T == CV_HAL_GEMM_1_T, "Incompatible GEMM_1_T flag in HAL"); @@ -1469,7 +1469,7 @@ _callInternalGemmImpl(const fptype *src1, size_t src1_step, const fptype *src2, C = Mat(c_m, c_n, type, (void*)src3, src3_step); Mat D(m_d, n_d, type, (void*)dst, dst_step); - _gemmImplInternal(A, B, alpha, C, beta, D, flags); + gemmImpl(A, B, alpha, C, beta, D, flags); } } @@ -1480,7 +1480,7 @@ void cv::hal::gemm32f(const float* src1, size_t src1_step, const float* src2, si { CALL_HAL(gemm32f, cv_hal_gemm32f, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) - _callInternalGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_32F); + callGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_32F); } void cv::hal::gemm64f(const double* src1, size_t src1_step, const double* src2, size_t src2_step, @@ -1488,7 +1488,7 @@ void cv::hal::gemm64f(const double* src1, size_t src1_step, const double* src2, int m_a, int n_a, int n_d, int flags) { CALL_HAL(gemm64f, cv_hal_gemm64f, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) - _callInternalGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_64F); + callGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_64F); } CV_EXPORTS void cv::hal::gemm32fc(const float* src1, size_t src1_step, const float* src2, size_t src2_step, @@ -1496,7 +1496,7 @@ CV_EXPORTS void cv::hal::gemm32fc(const float* src1, size_t src1_step, const flo int m_a, int n_a, int n_d, int flags) { CALL_HAL(gemm32fc, cv_hal_gemm32fc, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) - _callInternalGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_32FC2); + callGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_32FC2); } CV_EXPORTS void cv::hal::gemm64fc(const double* src1, size_t src1_step, const double* src2, size_t src2_step, @@ -1504,7 +1504,7 @@ CV_EXPORTS void cv::hal::gemm64fc(const double* src1, size_t src1_step, const do int m_a, int n_a, int n_d, int flags) { CALL_HAL(gemm64fc, cv_hal_gemm64fc, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) - _callInternalGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_64FC2); + callGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_64FC2); } void cv::gemm( InputArray matA, InputArray matB, double alpha, From 46fb46c54ed992d1f3147672c7d199589604e4ad Mon Sep 17 00:00:00 2001 From: Vladislav Sovrasov Date: Tue, 7 Jun 2016 12:31:11 +0300 Subject: [PATCH 03/10] Add an extended version of CalibrateCamera function --- modules/calib3d/include/opencv2/calib3d.hpp | 26 +++ .../include/opencv2/calib3d/calib3d_c.h | 1 + modules/calib3d/src/calibration.cpp | 174 ++++++++++++++++-- modules/calib3d/src/compat_ptsetreg.cpp | 2 + .../calib3d/test/test_cameracalibration.cpp | 92 ++++++++- 5 files changed, 267 insertions(+), 28 deletions(-) diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d.hpp index e26e8c13f..6d1253fc3 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d.hpp @@ -767,6 +767,14 @@ k-th translation vector (see the next output parameter description) brings the c from the model coordinate space (in which object points are specified) to the world coordinate space, that is, a real position of the calibration pattern in the k-th pattern view (k=0.. *M* -1). @param tvecs Output vector of translation vectors estimated for each pattern view. +@param stdDeviationsIntrinsics Output vector of standard deviations estimated for intrinsic parameters. + Order of deviations values: +\f$(f_x, f_y, c_x, c_y, k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6 , s_1, s_2, s_3, + s_4, \tau_x, \tau_y)\f$ If one of parameters is not estimated, it's deviation is equals to zero. +@param stdDeviationsExtrinsics Output vector of standard deviations estimated for extrinsic parameters. + Order of deviations values: \f$(R_1, T_1, \dotsc , R_M, T_M)\f$ where M is number of pattern views, + \f$R_i, T_i\f$ are concatenated 1x3 vectors. + @param perViewErrors Output vector of average re-projection errors estimated for each pattern view. @param flags Different flags that may be zero or a combination of the following values: - **CV_CALIB_USE_INTRINSIC_GUESS** cameraMatrix contains valid initial values of fx, fy, cx, cy that are optimized further. Otherwise, (cx, cy) is initially set to the image @@ -841,6 +849,24 @@ The function returns the final re-projection error. @sa findChessboardCorners, solvePnP, initCameraMatrix2D, stereoCalibrate, undistort */ +CV_EXPORTS_AS(calibrateCameraExtended) double calibrateCamera( InputArrayOfArrays objectPoints, + InputArrayOfArrays imagePoints, Size imageSize, + InputOutputArray cameraMatrix, InputOutputArray distCoeffs, + OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, + OutputArray stdDeviationsIntrinsics, + OutputArray stdDeviationsExtrinsics, + OutputArray perViewErrors, + int flags = 0, TermCriteria criteria = TermCriteria( + TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) ); + +/** @overload double calibrateCamera( InputArrayOfArrays objectPoints, + InputArrayOfArrays imagePoints, Size imageSize, + InputOutputArray cameraMatrix, InputOutputArray distCoeffs, + OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, + OutputArray stdDeviations, OutputArray perViewErrors, + int flags = 0, TermCriteria criteria = TermCriteria( + TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) ) + */ CV_EXPORTS_W double calibrateCamera( InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, Size imageSize, InputOutputArray cameraMatrix, InputOutputArray distCoeffs, diff --git a/modules/calib3d/include/opencv2/calib3d/calib3d_c.h b/modules/calib3d/include/opencv2/calib3d/calib3d_c.h index 0e77aa883..ebb9b523f 100644 --- a/modules/calib3d/include/opencv2/calib3d/calib3d_c.h +++ b/modules/calib3d/include/opencv2/calib3d/calib3d_c.h @@ -246,6 +246,7 @@ CVAPI(void) cvDrawChessboardCorners( CvArr* image, CvSize pattern_size, #define CV_CALIB_TILTED_MODEL 262144 #define CV_CALIB_FIX_TAUX_TAUY 524288 +#define CV_CALIB_NINTRINSIC 18 /* Finds intrinsic and extrinsic camera parameters from a few views of known calibration pattern */ diff --git a/modules/calib3d/src/calibration.cpp b/modules/calib3d/src/calibration.cpp index b8f569aeb..fee02f5b9 100644 --- a/modules/calib3d/src/calibration.cpp +++ b/modules/calib3d/src/calibration.cpp @@ -1181,7 +1181,6 @@ CV_IMPL void cvFindExtrinsicCameraParams2( const CvMat* objectPoints, cvConvert( &_t, tvec ); } - CV_IMPL void cvInitIntrinsicParams2D( const CvMat* objectPoints, const CvMat* imagePoints, const CvMat* npoints, CvSize imageSize, CvMat* cameraMatrix, @@ -1270,15 +1269,37 @@ CV_IMPL void cvInitIntrinsicParams2D( const CvMat* objectPoints, cvConvert( &_a, cameraMatrix ); } +static void subMatrix(const cv::Mat& src, cv::Mat& dst, const std::vector& cols, + const std::vector& rows) { + int nonzeros_cols = cv::countNonZero(cols); + cv::Mat tmp(src.rows, nonzeros_cols, CV_64FC1); -/* finds intrinsic and extrinsic camera parameters - from a few views of known calibration pattern */ -CV_IMPL double cvCalibrateCamera2( const CvMat* objectPoints, + for (int i = 0, j = 0; i < (int)cols.size(); i++) + { + if (cols[i]) + { + src.col(i).copyTo(tmp.col(j++)); + } + } + + int nonzeros_rows = cv::countNonZero(rows); + dst.create(nonzeros_rows, nonzeros_cols, CV_64FC1); + for (int i = 0, j = 0; i < (int)rows.size(); i++) + { + if (rows[i]) + { + tmp.row(i).copyTo(dst.row(j++)); + } + } +} + +static double cvCalibrateCamera2Internal( const CvMat* objectPoints, const CvMat* imagePoints, const CvMat* npoints, CvSize imageSize, CvMat* cameraMatrix, CvMat* distCoeffs, - CvMat* rvecs, CvMat* tvecs, int flags, CvTermCriteria termCrit ) + CvMat* rvecs, CvMat* tvecs, CvMat* stdDevs, + CvMat* perViewErrors, int flags, CvTermCriteria termCrit ) { - const int NINTRINSIC = 18; + const int NINTRINSIC = CV_CALIB_NINTRINSIC; double reprojErr = 0; Matx33d A; @@ -1338,6 +1359,20 @@ CV_IMPL double cvCalibrateCamera2( const CvMat* objectPoints, "1xn or nx1 array or 1-channel nx3 array, where n is the number of views" ); } + if( stdDevs ) + { + cn = CV_MAT_CN(stdDevs->type); + if( !CV_IS_MAT(stdDevs) || + (CV_MAT_DEPTH(stdDevs->type) != CV_32F && CV_MAT_DEPTH(stdDevs->type) != CV_64F) || + ((stdDevs->rows != (nimages*6 + NINTRINSIC) || stdDevs->cols*cn != 1) && + (stdDevs->rows != 1 || stdDevs->cols != (nimages*6 + NINTRINSIC) || cn != 1)) ) +#define STR__(x) #x +#define STR_(x) STR__(x) + CV_Error( CV_StsBadArg, "the output array of standard deviations vectors must be 1-channel " + "1x(n*6 + NINTRINSIC) or (n*6 + NINTRINSIC)x1 array, where n is the number of views," + " NINTRINSIC = " STR_(CV_CALIB_NINTRINSIC)); + } + if( (CV_MAT_TYPE(cameraMatrix->type) != CV_32FC1 && CV_MAT_TYPE(cameraMatrix->type) != CV_64FC1) || cameraMatrix->rows != 3 || cameraMatrix->cols != 3 ) @@ -1367,6 +1402,7 @@ CV_IMPL double cvCalibrateCamera2( const CvMat* objectPoints, Mat matM( 1, total, CV_64FC3 ); Mat _m( 1, total, CV_64FC2 ); + Mat allErrors(1, total, CV_64FC2); if(CV_MAT_CN(objectPoints->type) == 3) { cvarrToMat(objectPoints).convertTo(matM, CV_64F); @@ -1518,6 +1554,7 @@ CV_IMPL double cvCalibrateCamera2( const CvMat* objectPoints, double* _errNorm = 0; bool proceed = solver.updateAlt( _param, _JtJ, _JtErr, _errNorm ); double *param = solver.param->data.db, *pparam = solver.prevParam->data.db; + bool calcJ = solver.state == CvLevMarq::CALC_J || (!proceed && stdDevs); if( flags & CALIB_FIX_ASPECT_RATIO ) { @@ -1528,8 +1565,10 @@ CV_IMPL double cvCalibrateCamera2( const CvMat* objectPoints, A(0, 0) = param[0]; A(1, 1) = param[1]; A(0, 2) = param[2]; A(1, 2) = param[3]; std::copy(param + 4, param + 4 + 14, k); - if( !proceed ) + if ( !proceed && !stdDevs && !perViewErrors ) break; + else if ( !proceed && stdDevs ) + cvZero(_JtJ); reprojErr = 0; @@ -1543,6 +1582,7 @@ CV_IMPL double cvCalibrateCamera2( const CvMat* objectPoints, CvMat _Mi(matM.colRange(pos, pos + ni)); CvMat _mi(_m.colRange(pos, pos + ni)); + CvMat _me(allErrors.colRange(pos, pos + ni)); _Je.resize(ni*2); _Ji.resize(ni*2); _err.resize(ni*2); CvMat _dpdr(_Je.colRange(0, 3)); @@ -1552,7 +1592,7 @@ CV_IMPL double cvCalibrateCamera2( const CvMat* objectPoints, CvMat _dpdk(_Ji.colRange(4, NINTRINSIC)); CvMat _mp(_err.reshape(2, 1)); - if( solver.state == CvLevMarq::CALC_J ) + if( calcJ ) { cvProjectPoints2( &_Mi, &_ri, &_ti, &matA, &_k, &_mp, &_dpdr, &_dpdt, (flags & CALIB_FIX_FOCAL_LENGTH) ? 0 : &_dpdf, @@ -1563,8 +1603,10 @@ CV_IMPL double cvCalibrateCamera2( const CvMat* objectPoints, cvProjectPoints2( &_Mi, &_ri, &_ti, &matA, &_k, &_mp ); cvSub( &_mp, &_mi, &_mp ); + if (perViewErrors || stdDevs) + cvCopy(&_mp, &_me); - if( solver.state == CvLevMarq::CALC_J ) + if( calcJ ) { Mat JtJ(cvarrToMat(_JtJ)), JtErr(cvarrToMat(_JtErr)); @@ -1581,15 +1623,52 @@ CV_IMPL double cvCalibrateCamera2( const CvMat* objectPoints, } if( _errNorm ) *_errNorm = reprojErr; + + if( !proceed ) + { + if( stdDevs ) + { + Mat mask = cvarrToMat(solver.mask); + int nparams_nz = countNonZero(mask); + Mat JtJinv, JtJN; + JtJN.create(nparams_nz, nparams_nz, CV_64F); + subMatrix(cvarrToMat(_JtJ), JtJN, mask, mask); + completeSymm(JtJN, false); + cv::invert(JtJN, JtJinv, DECOMP_SVD); + //sigma2 is deviation of the noise + //see any papers about variance of the least squares estimator for + //detailed description of the variance estimation methods + double sigma2 = norm(allErrors, NORM_L2SQR) / (total - nparams_nz); + Mat stdDevsM = cvarrToMat(stdDevs); + int j = 0; + for ( int s = 0; s < nparams; s++ ) + if( mask.data[s] ) + { + stdDevsM.at(s) = std::sqrt(JtJinv.at(j,j) * sigma2); + j++; + } + else + stdDevsM.at(s) = 0.; + } + break; + } } // 4. store the results cvConvert( &matA, cameraMatrix ); cvConvert( &_k, distCoeffs ); - for( i = 0; i < nimages; i++ ) + for( i = 0, pos = 0; i < nimages; i++ ) { CvMat src, dst; + if( perViewErrors ) + { + ni = npoints->data.i[i*npstep]; + perViewErrors->data.db[i] = std::sqrt(cv::norm(allErrors.colRange(pos, pos + ni), + NORM_L2SQR) / ni); + pos+=ni; + } + if( rvecs ) { src = cvMat( 3, 1, CV_64F, solver.param->data.db + NINTRINSIC + i*6 ); @@ -1622,6 +1701,17 @@ CV_IMPL double cvCalibrateCamera2( const CvMat* objectPoints, } +/* finds intrinsic and extrinsic camera parameters + from a few views of known calibration pattern */ +CV_IMPL double cvCalibrateCamera2( const CvMat* objectPoints, + const CvMat* imagePoints, const CvMat* npoints, + CvSize imageSize, CvMat* cameraMatrix, CvMat* distCoeffs, + CvMat* rvecs, CvMat* tvecs, int flags, CvTermCriteria termCrit ) +{ + return cvCalibrateCamera2Internal(objectPoints, imagePoints, npoints, imageSize, cameraMatrix, + distCoeffs, rvecs, tvecs, NULL, NULL, flags, termCrit); +} + void cvCalibrationMatrixValues( const CvMat *calibMatr, CvSize imgSize, double apertureWidth, double apertureHeight, double *fovx, double *fovy, double *focalLength, CvPoint2D64f *principalPoint, double *pasp ) @@ -1772,7 +1862,7 @@ double cvStereoCalibrate( const CvMat* _objectPoints, const CvMat* _imagePoints1 if( !(flags & (CV_CALIB_FIX_INTRINSIC|CV_CALIB_USE_INTRINSIC_GUESS))) { cvCalibrateCamera2( objectPoints, imagePoints[k], - npoints, imageSize, &K[k], &Dist[k], 0, 0, flags ); + npoints, imageSize, &K[k], &Dist[k], NULL, NULL, flags ); } } @@ -3091,7 +3181,6 @@ static void collectCalibrationData( InputArrayOfArrays objectPoints, } } - static Mat prepareCameraMatrix(Mat& cameraMatrix0, int rtype) { Mat cameraMatrix = Mat::eye(3, 3, rtype); @@ -3287,10 +3376,23 @@ cv::Mat cv::initCameraMatrix2D( InputArrayOfArrays objectPoints, } + double cv::calibrateCamera( InputArrayOfArrays _objectPoints, InputArrayOfArrays _imagePoints, Size imageSize, InputOutputArray _cameraMatrix, InputOutputArray _distCoeffs, OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, int flags, TermCriteria criteria ) +{ + return calibrateCamera(_objectPoints, _imagePoints, imageSize, _cameraMatrix, _distCoeffs, + _rvecs, _tvecs, noArray(), noArray(), noArray(), flags, criteria); +} + +double cv::calibrateCamera(InputArrayOfArrays _objectPoints, + InputArrayOfArrays _imagePoints, + Size imageSize, InputOutputArray _cameraMatrix, InputOutputArray _distCoeffs, + OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, + OutputArray stdDeviationsIntrinsics, + OutputArray stdDeviationsExtrinsics, + OutputArray _perViewErrors, int flags, TermCriteria criteria ) { int rtype = CV_64F; Mat cameraMatrix = _cameraMatrix.getMat(); @@ -3304,14 +3406,17 @@ double cv::calibrateCamera( InputArrayOfArrays _objectPoints, int nimages = int(_objectPoints.total()); CV_Assert( nimages > 0 ); - Mat objPt, imgPt, npoints, rvecM, tvecM; + Mat objPt, imgPt, npoints, rvecM, tvecM, stdDeviationsM, errorsM; - bool rvecs_needed = _rvecs.needed(), tvecs_needed = _tvecs.needed(); + bool rvecs_needed = _rvecs.needed(), tvecs_needed = _tvecs.needed(), + stddev_needed = stdDeviationsIntrinsics.needed(), errors_needed = _perViewErrors.needed(), + stddev_ext_needed = stdDeviationsExtrinsics.needed(); bool rvecs_mat_vec = _rvecs.isMatVector(); bool tvecs_mat_vec = _tvecs.isMatVector(); - if( rvecs_needed ) { + if( rvecs_needed ) + { _rvecs.create(nimages, 1, CV_64FC3); if(rvecs_mat_vec) @@ -3320,7 +3425,8 @@ double cv::calibrateCamera( InputArrayOfArrays _objectPoints, rvecM = _rvecs.getMat(); } - if( tvecs_needed ) { + if( tvecs_needed ) + { _tvecs.create(nimages, 1, CV_64FC3); if(tvecs_mat_vec) @@ -3329,16 +3435,46 @@ double cv::calibrateCamera( InputArrayOfArrays _objectPoints, tvecM = _tvecs.getMat(); } + if( stddev_needed || stddev_ext_needed ) + { + stdDeviationsM.create(nimages*6 + CV_CALIB_NINTRINSIC, 1, CV_64F); + } + + if( errors_needed ) + { + _perViewErrors.create(nimages, 1, CV_64F); + errorsM = _perViewErrors.getMat(); + } + collectCalibrationData( _objectPoints, _imagePoints, noArray(), objPt, imgPt, 0, npoints ); CvMat c_objPt = objPt, c_imgPt = imgPt, c_npoints = npoints; CvMat c_cameraMatrix = cameraMatrix, c_distCoeffs = distCoeffs; - CvMat c_rvecM = rvecM, c_tvecM = tvecM; + CvMat c_rvecM = rvecM, c_tvecM = tvecM, c_stdDev = stdDeviationsM, c_errors = errorsM; - double reprojErr = cvCalibrateCamera2(&c_objPt, &c_imgPt, &c_npoints, imageSize, + double reprojErr = cvCalibrateCamera2Internal(&c_objPt, &c_imgPt, &c_npoints, imageSize, &c_cameraMatrix, &c_distCoeffs, rvecs_needed ? &c_rvecM : NULL, - tvecs_needed ? &c_tvecM : NULL, flags, criteria ); + tvecs_needed ? &c_tvecM : NULL, + stddev_needed ? &c_stdDev : NULL, + errors_needed ? &c_errors : NULL, flags, criteria ); + + if( stddev_needed ) + { + stdDeviationsIntrinsics.create(CV_CALIB_NINTRINSIC, 1, CV_64F); + Mat stdDeviationsIntrinsicsMat = stdDeviationsIntrinsics.getMat(); + std::memcpy(stdDeviationsIntrinsicsMat.ptr(), stdDeviationsM.ptr(), + CV_CALIB_NINTRINSIC*sizeof(double)); + } + + if ( stddev_ext_needed ) + { + stdDeviationsExtrinsics.create(nimages*6, 1, CV_64F); + Mat stdDeviationsExtrinsicsMat = stdDeviationsExtrinsics.getMat(); + std::memcpy(stdDeviationsExtrinsicsMat.ptr(), + stdDeviationsM.ptr() + CV_CALIB_NINTRINSIC*sizeof(double), + nimages*6*sizeof(double)); + } // overly complicated and inefficient rvec/ tvec handling to support vector for(int i = 0; i < nimages; i++ ) diff --git a/modules/calib3d/src/compat_ptsetreg.cpp b/modules/calib3d/src/compat_ptsetreg.cpp index e0f387da3..774129e42 100644 --- a/modules/calib3d/src/compat_ptsetreg.cpp +++ b/modules/calib3d/src/compat_ptsetreg.cpp @@ -241,6 +241,8 @@ bool CvLevMarq::updateAlt( const CvMat*& _param, CvMat*& _JtJ, CvMat*& _JtErr, d cvNorm(param, prevParam, CV_RELATIVE_L2) < criteria.epsilon ) { _param = param; + _JtJ = JtJ; + _JtErr = JtErr; state = DONE; return false; } diff --git a/modules/calib3d/test/test_cameracalibration.cpp b/modules/calib3d/test/test_cameracalibration.cpp index 49d73fc61..b82c4b21b 100644 --- a/modules/calib3d/test/test_cameracalibration.cpp +++ b/modules/calib3d/test/test_cameracalibration.cpp @@ -259,7 +259,7 @@ protected: virtual void calibrate( int imageCount, int* pointCounts, CvSize imageSize, CvPoint2D64f* imagePoints, CvPoint3D64f* objectPoints, double* distortionCoeffs, double* cameraMatrix, double* translationVectors, - double* rotationMatrices, int flags ) = 0; + double* rotationMatrices, double *stdDevs, double* perViewErrors, int flags ) = 0; virtual void project( int pointCount, CvPoint3D64f* objectPoints, double* rotationMatrix, double* translationVector, double* cameraMatrix, double* distortion, CvPoint2D64f* imagePoints ) = 0; @@ -303,9 +303,13 @@ void CV_CameraCalibrationTest::run( int start_from ) double* transVects; double* rotMatrs; + double* stdDevs; + double* perViewErrors; double* goodTransVects; double* goodRotMatrs; + double* goodPerViewErrors; + double* goodStdDevs; double cameraMatrix[3*3]; double distortion[5]={0,0,0,0,0}; @@ -424,9 +428,13 @@ void CV_CameraCalibrationTest::run( int start_from ) /* Allocate memory for translate vectors and rotmatrixs*/ transVects = (double*)cvAlloc(3 * 1 * numImages * sizeof(double)); rotMatrs = (double*)cvAlloc(3 * 3 * numImages * sizeof(double)); + stdDevs = (double*)cvAlloc((CV_CALIB_NINTRINSIC + 6*numImages) * sizeof(double)); + perViewErrors = (double*)cvAlloc(numImages * sizeof(double)); goodTransVects = (double*)cvAlloc(3 * 1 * numImages * sizeof(double)); goodRotMatrs = (double*)cvAlloc(3 * 3 * numImages * sizeof(double)); + goodPerViewErrors = (double*)cvAlloc(numImages * sizeof(double)); + goodStdDevs = (double*)cvAlloc((CV_CALIB_NINTRINSIC + 6*numImages) * sizeof(double)); /* Read object points */ i = 0;/* shift for current point */ @@ -501,6 +509,13 @@ void CV_CameraCalibrationTest::run( int start_from ) } } + /* Read good stdDeviations */ + for (i = 0; i < CV_CALIB_NINTRINSIC + numImages*6; i++) + { + values_read = fscanf(file, "%lf", goodStdDevs + i); + CV_Assert(values_read == 1); + } + calibFlags = 0 // + CV_CALIB_FIX_PRINCIPAL_POINT // + CV_CALIB_ZERO_TANGENT_DIST @@ -526,6 +541,8 @@ void CV_CameraCalibrationTest::run( int start_from ) cameraMatrix, transVects, rotMatrs, + stdDevs, + perViewErrors, calibFlags ); /* ---- Reproject points to the image ---- */ @@ -553,6 +570,8 @@ void CV_CameraCalibrationTest::run( int start_from ) meanDy = 0; for( currImage = 0; currImage < numImages; currImage++ ) { + double imageMeanDx = 0; + double imageMeanDy = 0; for( currPoint = 0; currPoint < etalonSize.width * etalonSize.height; currPoint++ ) { rx = reprojectPoints[i].x; @@ -563,6 +582,9 @@ void CV_CameraCalibrationTest::run( int start_from ) meanDx += dx; meanDy += dy; + imageMeanDx += dx*dx; + imageMeanDy += dy*dy; + dx = fabs(dx); dy = fabs(dy); @@ -573,6 +595,13 @@ void CV_CameraCalibrationTest::run( int start_from ) maxDy = dy; i++; } + goodPerViewErrors[currImage] = sqrt( (imageMeanDx + imageMeanDy) / + (etalonSize.width * etalonSize.height)); + + //only for c-version of test (it does not provides evaluation of perViewErrors + //and returns zeros) + if(perViewErrors[currImage] == 0.0) + perViewErrors[currImage] = goodPerViewErrors[currImage]; } meanDx /= numImages * etalonSize.width * etalonSize.height; @@ -613,6 +642,23 @@ void CV_CameraCalibrationTest::run( int start_from ) if( code < 0 ) goto _exit_; + /* ----- Compare per view re-projection errors ----- */ + code = compare(perViewErrors,goodPerViewErrors, numImages,0.1,"per view errors vector"); + if( code < 0 ) + goto _exit_; + + /* ----- Compare standard deviations of parameters ----- */ + //only for c-version of test (it does not provides evaluation of stdDevs + //and returns zeros) + for ( i = 0; i < CV_CALIB_NINTRINSIC + 6*numImages; i++) + { + if(stdDevs[i] == 0.0) + stdDevs[i] = goodStdDevs[i]; + } + code = compare(stdDevs,goodStdDevs, CV_CALIB_NINTRINSIC + 6*numImages,.5,"stdDevs vector"); + if( code < 0 ) + goto _exit_; + if( maxDx > 1.0 ) { ts->printf( cvtest::TS::LOG, @@ -636,8 +682,12 @@ void CV_CameraCalibrationTest::run( int start_from ) cvFree(&transVects); cvFree(&rotMatrs); + cvFree(&stdDevs); + cvFree(&perViewErrors); cvFree(&goodTransVects); cvFree(&goodRotMatrs); + cvFree(&goodPerViewErrors); + cvFree(&goodStdDevs); fclose(file); file = 0; @@ -676,20 +726,28 @@ protected: virtual void calibrate( int imageCount, int* pointCounts, CvSize imageSize, CvPoint2D64f* imagePoints, CvPoint3D64f* objectPoints, double* distortionCoeffs, double* cameraMatrix, double* translationVectors, - double* rotationMatrices, int flags ); + double* rotationMatrices, double *stdDevs, double* perViewErrors, int flags ); virtual void project( int pointCount, CvPoint3D64f* objectPoints, double* rotationMatrix, double* translationVector, double* cameraMatrix, double* distortion, CvPoint2D64f* imagePoints ); }; -void CV_CameraCalibrationTest_C::calibrate( int imageCount, int* pointCounts, +void CV_CameraCalibrationTest_C::calibrate(int imageCount, int* pointCounts, CvSize imageSize, CvPoint2D64f* imagePoints, CvPoint3D64f* objectPoints, double* distortionCoeffs, double* cameraMatrix, double* translationVectors, - double* rotationMatrices, int flags ) + double* rotationMatrices, double *stdDevs, double *perViewErrors, int flags ) { int i, total = 0; for( i = 0; i < imageCount; i++ ) + { + perViewErrors[i] = 0.0; total += pointCounts[i]; + } + + for( i = 0; i < CV_CALIB_NINTRINSIC + imageCount*6; i++) + { + stdDevs[i] = 0.0; + } CvMat _objectPoints = cvMat(1, total, CV_64FC3, objectPoints); CvMat _imagePoints = cvMat(1, total, CV_64FC2, imagePoints); @@ -700,8 +758,7 @@ void CV_CameraCalibrationTest_C::calibrate( int imageCount, int* pointCounts, CvMat _translationVectors = cvMat(imageCount, 3, CV_64F, translationVectors); cvCalibrateCamera2(&_objectPoints, &_imagePoints, &_pointCounts, imageSize, - &_cameraMatrix, &_distCoeffs, &_rotationMatrices, &_translationVectors, - flags); + &_cameraMatrix, &_distCoeffs, &_rotationMatrices, &_translationVectors, flags); } void CV_CameraCalibrationTest_C::project( int pointCount, CvPoint3D64f* objectPoints, @@ -728,22 +785,24 @@ protected: virtual void calibrate( int imageCount, int* pointCounts, CvSize imageSize, CvPoint2D64f* imagePoints, CvPoint3D64f* objectPoints, double* distortionCoeffs, double* cameraMatrix, double* translationVectors, - double* rotationMatrices, int flags ); + double* rotationMatrices, double *stdDevs, double* perViewErrors, int flags ); virtual void project( int pointCount, CvPoint3D64f* objectPoints, double* rotationMatrix, double* translationVector, double* cameraMatrix, double* distortion, CvPoint2D64f* imagePoints ); }; -void CV_CameraCalibrationTest_CPP::calibrate( int imageCount, int* pointCounts, +void CV_CameraCalibrationTest_CPP::calibrate(int imageCount, int* pointCounts, CvSize _imageSize, CvPoint2D64f* _imagePoints, CvPoint3D64f* _objectPoints, double* _distortionCoeffs, double* _cameraMatrix, double* translationVectors, - double* rotationMatrices, int flags ) + double* rotationMatrices, double *stdDevs, double *perViewErrors, int flags ) { vector > objectPoints( imageCount ); vector > imagePoints( imageCount ); Size imageSize = _imageSize; Mat cameraMatrix, distCoeffs(1,4,CV_64F,Scalar::all(0)); vector rvecs, tvecs; + Mat stdDevsMatInt, stdDevsMatExt; + Mat perViewErrorsMat; CvPoint3D64f* op = _objectPoints; CvPoint2D64f* ip = _imagePoints; @@ -770,8 +829,23 @@ void CV_CameraCalibrationTest_CPP::calibrate( int imageCount, int* pointCounts, distCoeffs, rvecs, tvecs, + stdDevsMatInt, + stdDevsMatExt, + perViewErrorsMat, flags ); + assert( stdDevsMatInt.type() == CV_64F ); + assert( stdDevsMatInt.total() == static_cast(CV_CALIB_NINTRINSIC) ); + memcpy( stdDevs, stdDevsMatInt.ptr(), CV_CALIB_NINTRINSIC*sizeof(double) ); + + assert( stdDevsMatExt.type() == CV_64F ); + assert( stdDevsMatExt.total() == static_cast(6*imageCount) ); + memcpy( stdDevs + CV_CALIB_NINTRINSIC, stdDevsMatExt.ptr(), 6*imageCount*sizeof(double) ); + + assert( perViewErrorsMat.type() == CV_64F); + assert( perViewErrorsMat.total() == static_cast(imageCount) ); + memcpy( perViewErrors, perViewErrorsMat.ptr(), imageCount*sizeof(double) ); + assert( cameraMatrix.type() == CV_64FC1 ); memcpy( _cameraMatrix, cameraMatrix.ptr(), 9*sizeof(double) ); From c62eda023d2a355d8a68426fdc66844a86affc95 Mon Sep 17 00:00:00 2001 From: Ankit Yadav Date: Sat, 11 Jun 2016 17:56:58 +0530 Subject: [PATCH 04/10] Fix typo --- doc/py_tutorials/py_imgproc/py_grabcut/py_grabcut.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/py_tutorials/py_imgproc/py_grabcut/py_grabcut.markdown b/doc/py_tutorials/py_imgproc/py_grabcut/py_grabcut.markdown index 98392b314..a44a727f7 100644 --- a/doc/py_tutorials/py_imgproc/py_grabcut/py_grabcut.markdown +++ b/doc/py_tutorials/py_imgproc/py_grabcut/py_grabcut.markdown @@ -17,7 +17,7 @@ graph cuts](http://dl.acm.org/citation.cfm?id=1015720) . An algorithm was needed extraction with minimal user interaction, and the result was GrabCut. How it works from user point of view ? Initially user draws a rectangle around the foreground region -(foreground region shoule be completely inside the rectangle). Then algorithm segments it +(foreground region should be completely inside the rectangle). Then algorithm segments it iteratively to get the best result. Done. But in some cases, the segmentation won't be fine, like, it may have marked some foreground region as background and vice versa. In that case, user need to do fine touch-ups. Just give some strokes on the images where some faulty results are there. Strokes From 4a529cd6417443cafb6ee22131262e9b67bb6308 Mon Sep 17 00:00:00 2001 From: Philipp Nordhus Date: Sat, 11 Jun 2016 15:17:52 +0200 Subject: [PATCH 05/10] Return reference on iterator indirection/subscript --- modules/core/include/opencv2/core/mat.hpp | 4 ++-- modules/core/include/opencv2/core/mat.inl.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index dd0d4a455..a0560a197 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -2880,9 +2880,9 @@ public: //! copy operator MatConstIterator_& operator = (const MatConstIterator_& it); //! returns the current matrix element - _Tp operator *() const; + const _Tp& operator *() const; //! returns the i-th matrix element, relative to the current - _Tp operator [](ptrdiff_t i) const; + const _Tp& operator [](ptrdiff_t i) const; //! shifts the iterator forward by the specified number of elements MatConstIterator_& operator += (ptrdiff_t ofs); diff --git a/modules/core/include/opencv2/core/mat.inl.hpp b/modules/core/include/opencv2/core/mat.inl.hpp index 1ac1f040a..2ba152f37 100644 --- a/modules/core/include/opencv2/core/mat.inl.hpp +++ b/modules/core/include/opencv2/core/mat.inl.hpp @@ -2550,7 +2550,7 @@ MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator = (const MatConstIterat } template inline -_Tp MatConstIterator_<_Tp>::operator *() const +const _Tp& MatConstIterator_<_Tp>::operator *() const { return *(_Tp*)(this->ptr); } @@ -2656,7 +2656,7 @@ MatConstIterator_<_Tp> operator - (const MatConstIterator_<_Tp>& a, ptrdiff_t of } template inline -_Tp MatConstIterator_<_Tp>::operator [](ptrdiff_t i) const +const _Tp& MatConstIterator_<_Tp>::operator [](ptrdiff_t i) const { return *(_Tp*)MatConstIterator::operator [](i); } From f4ebc504d1c31e5b3da77df5128c5b3bdd25ab06 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 15 Jun 2016 15:51:19 +0300 Subject: [PATCH 06/10] cmake: refactor HAL attaching process --- CMakeLists.txt | 44 +++++++++++++++++++++---------- cmake/OpenCVUtils.cmake | 1 + cmake/templates/custom_hal.hpp.in | 2 +- modules/core/CMakeLists.txt | 2 +- 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f0085b6c8..04ace8fdc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -602,26 +602,42 @@ endif() include(cmake/OpenCVDetectVTK.cmake) -# -- Custom HAL replacement -- -# Package config in: OpenCV_HALConfig.cmake or opencv_hal-config.cmake -# Use variables: OpenCV_HAL_LIBRARIES, OpenCV_HAL_HEADERS and OpenCV_HAL_INCLUDE_DIRS variables -find_package(OpenCV_HAL NO_MODULE QUIET) -set(_includes "") -if (OpenCV_HAL_FOUND) + +# ---------------------------------------------------------------------------- +# OpenCV HAL +# ---------------------------------------------------------------------------- +set(_hal_includes "") +macro(ocv_hal_register HAL_LIBRARIES_VAR HAL_HEADERS_VAR HAL_INCLUDE_DIRS_VAR) # 1. libraries - foreach (l ${OpenCV_HAL_LIBRARIES}) - get_filename_component(l "${l}" ABSOLUTE) - set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} ${l}) + foreach (l ${${HAL_LIBRARIES_VAR}}) + if(NOT TARGET ${l}) + get_filename_component(l "${l}" ABSOLUTE) + endif() + list(APPEND OPENCV_HAL_LINKER_LIBS ${l}) endforeach() # 2. headers - foreach (h ${OpenCV_HAL_HEADERS}) - set(_includes "${_includes}\n#include \"${h}\"") + foreach (h ${${HAL_HEADERS_VAR}}) + set(_hal_includes "${_hal_includes}\n#include \"${h}\"") endforeach() # 3. include paths - ocv_include_directories(${OpenCV_HAL_INCLUDE_DIRS}) + ocv_include_directories(${${HAL_INCLUDE_DIRS_VAR}}) +endmacro() + +if(NOT DEFINED OpenCV_HAL) + set(OpenCV_HAL "OpenCV_HAL") endif() +foreach(hal ${OpenCV_HAL}) + ocv_debug_message(STATUS "OpenCV HAL: ${hal} ...") + ocv_clear_vars(OpenCV_HAL_LIBRARIES OpenCV_HAL_HEADERS OpenCV_HAL_INCLUDE_DIRS) + find_package(${hal} NO_MODULE QUIET) + if(${hal}_FOUND) + ocv_hal_register(OpenCV_HAL_LIBRARIES OpenCV_HAL_HEADERS OpenCV_HAL_INCLUDE_DIRS) + list(APPEND OpenCV_USED_HAL "${hal} (ver ${${hal}_VERSION})") + endif() +endforeach() configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/custom_hal.hpp.in" "${CMAKE_BINARY_DIR}/custom_hal.hpp" @ONLY) -unset(_includes) +unset(_hal_includes) + # ---------------------------------------------------------------------------- # Add CUDA libraries (needed for apps/tools, samples) @@ -1160,7 +1176,7 @@ endif(DEFINED WITH_VA_INTEL) status(" Use Eigen:" HAVE_EIGEN THEN "YES (ver ${EIGEN_WORLD_VERSION}.${EIGEN_MAJOR_VERSION}.${EIGEN_MINOR_VERSION})" ELSE NO) status(" Use Cuda:" HAVE_CUDA THEN "YES (ver ${CUDA_VERSION_STRING})" ELSE NO) status(" Use OpenCL:" HAVE_OPENCL THEN YES ELSE NO) -status(" Use custom HAL:" OpenCV_HAL_FOUND THEN "YES (ver ${OpenCV_HAL_VERSION}, ${OpenCV_HAL_CONFIG})" ELSE "NO") +status(" Use custom HAL:" OpenCV_USED_HAL THEN "YES (${OpenCV_USED_HAL})" ELSE "NO") if(HAVE_CUDA) status("") diff --git a/cmake/OpenCVUtils.cmake b/cmake/OpenCVUtils.cmake index 735b94f52..a17e25548 100644 --- a/cmake/OpenCVUtils.cmake +++ b/cmake/OpenCVUtils.cmake @@ -126,6 +126,7 @@ endfunction() # clears all passed variables macro(ocv_clear_vars) foreach(_var ${ARGN}) + unset(${_var}) unset(${_var} CACHE) endforeach() endmacro() diff --git a/cmake/templates/custom_hal.hpp.in b/cmake/templates/custom_hal.hpp.in index f1c651595..c62f17dac 100644 --- a/cmake/templates/custom_hal.hpp.in +++ b/cmake/templates/custom_hal.hpp.in @@ -1,6 +1,6 @@ #ifndef _CUSTOM_HAL_INCLUDED_ #define _CUSTOM_HAL_INCLUDED_ -@_includes@ +@_hal_includes@ #endif diff --git a/modules/core/CMakeLists.txt b/modules/core/CMakeLists.txt index 8a68c9028..171fa9b08 100644 --- a/modules/core/CMakeLists.txt +++ b/modules/core/CMakeLists.txt @@ -1,6 +1,6 @@ set(the_description "The Core Functionality") ocv_add_module(core - PRIVATE_REQUIRED ${ZLIB_LIBRARIES} "${OPENCL_LIBRARIES}" "${VA_LIBRARIES}" + PRIVATE_REQUIRED ${ZLIB_LIBRARIES} "${OPENCL_LIBRARIES}" "${VA_LIBRARIES}" "${OPENCV_HAL_LINKER_LIBS}" OPTIONAL opencv_cudev WRAP java python) From 45bd56e28aeacf45bab8f70f872736f9c35c9f06 Mon Sep 17 00:00:00 2001 From: Philipp Hasper Date: Wed, 15 Jun 2016 16:41:39 +0200 Subject: [PATCH 07/10] rigidTransform: only four DoF combinations of translation, rotation, and uniform scaling equals four degrees of freedom --- modules/video/include/opencv2/video/tracking.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/video/include/opencv2/video/tracking.hpp b/modules/video/include/opencv2/video/tracking.hpp index d6954fecc..c0da7c7a3 100644 --- a/modules/video/include/opencv2/video/tracking.hpp +++ b/modules/video/include/opencv2/video/tracking.hpp @@ -226,7 +226,7 @@ CV_EXPORTS_W void calcOpticalFlowFarneback( InputArray prev, InputArray next, In @param dst Second input 2D point set of the same size and the same type as A, or another image. @param fullAffine If true, the function finds an optimal affine transformation with no additional restrictions (6 degrees of freedom). Otherwise, the class of transformations to choose from is -limited to combinations of translation, rotation, and uniform scaling (5 degrees of freedom). +limited to combinations of translation, rotation, and uniform scaling (4 degrees of freedom). The function finds an optimal affine transform *[A|b]* (a 2 x 3 floating-point matrix) that approximates best the affine transformation between: From 777e1d38ba5d16602dfc702036b4f0a68789742e Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 16 Jun 2016 14:29:36 +0300 Subject: [PATCH 08/10] cmake: fix JNI configuration problem for Android samples Some CMake 3.x (2.8.12.2 is fine) provides broken build configurations with following build error message: ld: fatal error: -soname: must take a non-empty argument Linker command line sample contains this: "-shared -Wl,-soname, -o" --- cmake/OpenCVDetectAndroidSDK.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/OpenCVDetectAndroidSDK.cmake b/cmake/OpenCVDetectAndroidSDK.cmake index 58a95597a..c8f7cba41 100644 --- a/cmake/OpenCVDetectAndroidSDK.cmake +++ b/cmake/OpenCVDetectAndroidSDK.cmake @@ -287,7 +287,7 @@ macro(add_android_project target path) set(android_proj_NATIVE_DEPS ${android_proj_NATIVE_DEPS} android) endif() - add_library(${JNI_LIB_NAME} MODULE ${android_proj_jni_files}) + add_library(${JNI_LIB_NAME} SHARED ${android_proj_jni_files}) ocv_target_include_modules_recurse(${JNI_LIB_NAME} ${android_proj_NATIVE_DEPS}) ocv_target_include_directories(${JNI_LIB_NAME} "${path}/jni") ocv_target_link_libraries(${JNI_LIB_NAME} ${OPENCV_LINKER_LIBS} ${android_proj_NATIVE_DEPS}) From 7188e6e2acdc4c581d42096cc4e5a1ea03f51cbe Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 18 Jan 2016 14:11:02 +0300 Subject: [PATCH 09/10] android: update build scripts --- platforms/android/build-tests/test_cmake_build.py | 5 +++++ platforms/android/build_sdk.py | 14 ++------------ 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/platforms/android/build-tests/test_cmake_build.py b/platforms/android/build-tests/test_cmake_build.py index 0e84928f0..f02915c61 100644 --- a/platforms/android/build-tests/test_cmake_build.py +++ b/platforms/android/build-tests/test_cmake_build.py @@ -2,6 +2,9 @@ import unittest import os, sys, subprocess, argparse, shutil, re +import logging as log + +log.basicConfig(format='%(message)s', level=log.DEBUG) CMAKE_TEMPLATE='''\ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) @@ -83,10 +86,12 @@ class TestCmakeBuild(unittest.TestCase): "-DANDROID_TOOLCHAIN_NAME=%s" % self.toolchain, self.srcdir ] + log.info("Executing: %s" % cmd) retcode = subprocess.call(cmd) self.assertEqual(retcode, 0, "cmake failed") cmd = ["ninja"] + log.info("Executing: %s" % cmd) retcode = subprocess.call(cmd) self.assertEqual(retcode, 0, "make failed") diff --git a/platforms/android/build_sdk.py b/platforms/android/build_sdk.py index 812b465e7..61c9f7d34 100755 --- a/platforms/android/build_sdk.py +++ b/platforms/android/build_sdk.py @@ -73,8 +73,7 @@ class ABI: def __str__(self): return "%s (%s)" % (self.name, self.toolchain) def haveIPP(self): - return False - # return self.name == "x86" or self.name == "x86_64" + return self.name == "x86" or self.name == "x86_64" ABIs = [ ABI("2", "armeabi-v7a", "arm-linux-androideabi-4.8", cmake_name="armeabi-v7a with NEON"), @@ -143,7 +142,7 @@ class Builder: cmd.append(self.opencvdir) if self.use_ccache == True: - cmd.extend(["-DNDK_CCACHE=ccache", "-DENABLE_PRECOMPILED_HEADERS=OFF"]) + cmd.append("-DNDK_CCACHE=ccache") if do_install: cmd.extend(["-DBUILD_TESTS=ON", "-DINSTALL_TESTS=ON"]) execute(cmd) @@ -238,15 +237,6 @@ class Builder: log.info("Copy docs: %s", self.docdest) shutil.copytree(self.docdest, os.path.join(self.resultdest, "sdk", "java", "javadoc")) - # Patch cmake config - with open(os.path.join(self.resultdest, "sdk", "native", "jni", "OpenCVConfig.cmake"), "r+t") as f: - contents = f.read() - contents, count = re.subn(r'OpenCV_ANDROID_NATIVE_API_LEVEL \d+', "OpenCV_ANDROID_NATIVE_API_LEVEL 8", contents) - f.seek(0) - f.write(contents) - f.truncate() - log.info("Patch cmake config: %s (%d changes)", f.name, count) - # Clean samples path = os.path.join(self.resultdest, "samples") for item in os.listdir(path): From c6c651212cc60a13b46996b62e24df5bd3e2c38d Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 11 Jan 2016 17:54:14 +0300 Subject: [PATCH 10/10] cmake: refactoring of OpenCVConfig - removed OpenCV_LIB_DIR* vars (they are broken and not required anymore) - OpenCVConfig.cmake doesn't contain ANDROID/CUDA code if there is no such support - removed OpenCV2_INCLUDE_DIRS_CONFIGCMAKE, merged into OpenCV_INCLUDE_DIRS_CONFIGCMAKE - fix hard-coded relative paths for OpenCV_INSTALL_PATH - removed OpenCV_TBB_ARCH - switch OpenCVConfig.cmake into 2-level mode for Android SDK --- CMakeLists.txt | 128 +++++---- cmake/OpenCVFindIPP.cmake | 2 +- cmake/OpenCVGenConfig.cmake | 146 ++++------ cmake/OpenCVUtils.cmake | 28 +- cmake/templates/OpenCVConfig-ANDROID.cmake.in | 13 + cmake/templates/OpenCVConfig-CUDA.cmake.in | 53 ++++ cmake/templates/OpenCVConfig-IPPICV.cmake.in | 7 + cmake/templates/OpenCVConfig.cmake.in | 268 +++--------------- .../OpenCVConfig.root-ANDROID.cmake.in | 50 ++++ .../OpenCVConfig.root-WIN32.cmake.in} | 50 +--- 10 files changed, 323 insertions(+), 422 deletions(-) create mode 100644 cmake/templates/OpenCVConfig-ANDROID.cmake.in create mode 100644 cmake/templates/OpenCVConfig-CUDA.cmake.in create mode 100644 cmake/templates/OpenCVConfig-IPPICV.cmake.in create mode 100644 cmake/templates/OpenCVConfig.root-ANDROID.cmake.in rename cmake/{OpenCVConfig.cmake => templates/OpenCVConfig.root-WIN32.cmake.in} (72%) diff --git a/CMakeLists.txt b/CMakeLists.txt index f043acd61..18887f471 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,8 +86,10 @@ if (POLICY CMP0042) cmake_policy(SET CMP0042 OLD) endif() +include(cmake/OpenCVUtils.cmake) + # must go before the project command -set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Configs" FORCE) +ocv_update(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Configs" FORCE) if(DEFINED CMAKE_BUILD_TYPE) set_property( CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CMAKE_CONFIGURATION_TYPES} ) endif() @@ -100,8 +102,6 @@ if(MSVC) set(CMAKE_USE_RELATIVE_PATHS ON CACHE INTERNAL "" FORCE) endif() -include(cmake/OpenCVUtils.cmake) - ocv_cmake_eval(DEBUG_PRE ONCE) ocv_clear_vars(OpenCVModules_TARGETS) @@ -304,50 +304,50 @@ include(cmake/OpenCVVersion.cmake) # ---------------------------------------------------------------------------- # Save libs and executables in the same place -set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/bin" CACHE PATH "Output directory for applications" ) +set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/bin" CACHE PATH "Output directory for applications") -if (ANDROID) - if (ANDROID_ABI MATCHES "NEON") +if(ANDROID) + if(ANDROID_ABI MATCHES "NEON") set(ENABLE_NEON ON) endif() - if (ANDROID_ABI MATCHES "VFPV3") + if(ANDROID_ABI MATCHES "VFPV3") set(ENABLE_VFPV3 ON) endif() endif() if(ANDROID OR WIN32) - set(OPENCV_DOC_INSTALL_PATH doc) + ocv_update(OPENCV_DOC_INSTALL_PATH doc) else() - set(OPENCV_DOC_INSTALL_PATH share/OpenCV/doc) + ocv_update(OPENCV_DOC_INSTALL_PATH share/OpenCV/doc) endif() if(WIN32 AND CMAKE_HOST_SYSTEM_NAME MATCHES Windows) if(DEFINED OpenCV_RUNTIME AND DEFINED OpenCV_ARCH) - set(OpenCV_INSTALL_BINARIES_PREFIX "${OpenCV_ARCH}/${OpenCV_RUNTIME}/") + ocv_update(OpenCV_INSTALL_BINARIES_PREFIX "${OpenCV_ARCH}/${OpenCV_RUNTIME}/") else() message(STATUS "Can't detect runtime and/or arch") - set(OpenCV_INSTALL_BINARIES_PREFIX "") + ocv_update(OpenCV_INSTALL_BINARIES_PREFIX "") endif() elseif(ANDROID) - set(OpenCV_INSTALL_BINARIES_PREFIX "sdk/native/") + ocv_update(OpenCV_INSTALL_BINARIES_PREFIX "sdk/native/") else() - set(OpenCV_INSTALL_BINARIES_PREFIX "") + ocv_update(OpenCV_INSTALL_BINARIES_PREFIX "") endif() if(ANDROID) - set(OPENCV_SAMPLES_BIN_INSTALL_PATH "${OpenCV_INSTALL_BINARIES_PREFIX}samples/${ANDROID_NDK_ABI_NAME}") + ocv_update(OPENCV_SAMPLES_BIN_INSTALL_PATH "${OpenCV_INSTALL_BINARIES_PREFIX}samples/${ANDROID_NDK_ABI_NAME}") else() - set(OPENCV_SAMPLES_BIN_INSTALL_PATH "${OpenCV_INSTALL_BINARIES_PREFIX}samples") + ocv_update(OPENCV_SAMPLES_BIN_INSTALL_PATH "${OpenCV_INSTALL_BINARIES_PREFIX}samples") endif() if(ANDROID) - set(OPENCV_BIN_INSTALL_PATH "${OpenCV_INSTALL_BINARIES_PREFIX}bin/${ANDROID_NDK_ABI_NAME}") + ocv_update(OPENCV_BIN_INSTALL_PATH "${OpenCV_INSTALL_BINARIES_PREFIX}bin/${ANDROID_NDK_ABI_NAME}") else() - set(OPENCV_BIN_INSTALL_PATH "${OpenCV_INSTALL_BINARIES_PREFIX}bin") + ocv_update(OPENCV_BIN_INSTALL_PATH "${OpenCV_INSTALL_BINARIES_PREFIX}bin") endif() if(NOT OPENCV_TEST_INSTALL_PATH) - set(OPENCV_TEST_INSTALL_PATH "${OPENCV_BIN_INSTALL_PATH}") + ocv_update(OPENCV_TEST_INSTALL_PATH "${OPENCV_BIN_INSTALL_PATH}") endif() if (OPENCV_TEST_DATA_PATH) @@ -356,66 +356,74 @@ endif() if(OPENCV_TEST_DATA_PATH AND NOT OPENCV_TEST_DATA_INSTALL_PATH) if(ANDROID) - set(OPENCV_TEST_DATA_INSTALL_PATH "sdk/etc/testdata") + ocv_update(OPENCV_TEST_DATA_INSTALL_PATH "sdk/etc/testdata") elseif(WIN32) - set(OPENCV_TEST_DATA_INSTALL_PATH "testdata") + ocv_update(OPENCV_TEST_DATA_INSTALL_PATH "testdata") else() - set(OPENCV_TEST_DATA_INSTALL_PATH "share/OpenCV/testdata") + ocv_update(OPENCV_TEST_DATA_INSTALL_PATH "share/OpenCV/testdata") endif() endif() if(ANDROID) - set(LIBRARY_OUTPUT_PATH "${OpenCV_BINARY_DIR}/lib/${ANDROID_NDK_ABI_NAME}") - set(3P_LIBRARY_OUTPUT_PATH "${OpenCV_BINARY_DIR}/3rdparty/lib/${ANDROID_NDK_ABI_NAME}") - set(OPENCV_LIB_INSTALL_PATH sdk/native/libs/${ANDROID_NDK_ABI_NAME}) - set(OPENCV_3P_LIB_INSTALL_PATH sdk/native/3rdparty/libs/${ANDROID_NDK_ABI_NAME}) - set(OPENCV_CONFIG_INSTALL_PATH sdk/native/jni) - set(OPENCV_INCLUDE_INSTALL_PATH sdk/native/jni/include) - set(OPENCV_SAMPLES_SRC_INSTALL_PATH samples/native) - set(OPENCV_OTHER_INSTALL_PATH sdk/etc) + set(LIBRARY_OUTPUT_PATH "${OpenCV_BINARY_DIR}/lib/${ANDROID_NDK_ABI_NAME}") + ocv_update(3P_LIBRARY_OUTPUT_PATH "${OpenCV_BINARY_DIR}/3rdparty/lib/${ANDROID_NDK_ABI_NAME}") + ocv_update(OPENCV_LIB_INSTALL_PATH sdk/native/libs/${ANDROID_NDK_ABI_NAME}) + ocv_update(OPENCV_3P_LIB_INSTALL_PATH sdk/native/3rdparty/libs/${ANDROID_NDK_ABI_NAME}) + ocv_update(OPENCV_CONFIG_INSTALL_PATH sdk/native/jni) + ocv_update(OPENCV_INCLUDE_INSTALL_PATH sdk/native/jni/include) + ocv_update(OPENCV_SAMPLES_SRC_INSTALL_PATH samples/native) + ocv_update(OPENCV_OTHER_INSTALL_PATH sdk/etc) else() - set(LIBRARY_OUTPUT_PATH "${OpenCV_BINARY_DIR}/lib") - set(3P_LIBRARY_OUTPUT_PATH "${OpenCV_BINARY_DIR}/3rdparty/lib${LIB_SUFFIX}") + set(LIBRARY_OUTPUT_PATH "${OpenCV_BINARY_DIR}/lib") + ocv_update(3P_LIBRARY_OUTPUT_PATH "${OpenCV_BINARY_DIR}/3rdparty/lib${LIB_SUFFIX}") if(WIN32 AND CMAKE_HOST_SYSTEM_NAME MATCHES Windows) if(OpenCV_STATIC) - set(OPENCV_LIB_INSTALL_PATH "${OpenCV_INSTALL_BINARIES_PREFIX}staticlib${LIB_SUFFIX}") + ocv_update(OPENCV_LIB_INSTALL_PATH "${OpenCV_INSTALL_BINARIES_PREFIX}staticlib${LIB_SUFFIX}") else() - set(OPENCV_LIB_INSTALL_PATH "${OpenCV_INSTALL_BINARIES_PREFIX}lib${LIB_SUFFIX}") + ocv_update(OPENCV_LIB_INSTALL_PATH "${OpenCV_INSTALL_BINARIES_PREFIX}lib${LIB_SUFFIX}") endif() - set(OPENCV_3P_LIB_INSTALL_PATH "${OpenCV_INSTALL_BINARIES_PREFIX}staticlib${LIB_SUFFIX}") - set(OPENCV_SAMPLES_SRC_INSTALL_PATH samples/native) - set(OPENCV_JAR_INSTALL_PATH java) - set(OPENCV_OTHER_INSTALL_PATH etc) + ocv_update(OPENCV_3P_LIB_INSTALL_PATH "${OpenCV_INSTALL_BINARIES_PREFIX}staticlib${LIB_SUFFIX}") + ocv_update(OPENCV_SAMPLES_SRC_INSTALL_PATH samples/native) + ocv_update(OPENCV_JAR_INSTALL_PATH java) + ocv_update(OPENCV_OTHER_INSTALL_PATH etc) + ocv_update(OPENCV_CONFIG_INSTALL_PATH "") else() - set(OPENCV_LIB_INSTALL_PATH lib${LIB_SUFFIX}) - set(OPENCV_3P_LIB_INSTALL_PATH share/OpenCV/3rdparty/${OPENCV_LIB_INSTALL_PATH}) - set(OPENCV_SAMPLES_SRC_INSTALL_PATH share/OpenCV/samples) - set(OPENCV_JAR_INSTALL_PATH share/OpenCV/java) - set(OPENCV_OTHER_INSTALL_PATH share/OpenCV) - endif() - set(OPENCV_INCLUDE_INSTALL_PATH "include") + ocv_update(OPENCV_LIB_INSTALL_PATH lib${LIB_SUFFIX}) + ocv_update(OPENCV_3P_LIB_INSTALL_PATH share/OpenCV/3rdparty/${OPENCV_LIB_INSTALL_PATH}) + ocv_update(OPENCV_SAMPLES_SRC_INSTALL_PATH share/OpenCV/samples) + ocv_update(OPENCV_JAR_INSTALL_PATH share/OpenCV/java) + ocv_update(OPENCV_OTHER_INSTALL_PATH share/OpenCV) - math(EXPR SIZEOF_VOID_P_BITS "8 * ${CMAKE_SIZEOF_VOID_P}") - if(LIB_SUFFIX AND NOT SIZEOF_VOID_P_BITS EQUAL LIB_SUFFIX) - set(OPENCV_CONFIG_INSTALL_PATH lib${LIB_SUFFIX}/cmake/opencv) - else() - set(OPENCV_CONFIG_INSTALL_PATH share/OpenCV) + if(NOT DEFINED OPENCV_CONFIG_INSTALL_PATH) + math(EXPR SIZEOF_VOID_P_BITS "8 * ${CMAKE_SIZEOF_VOID_P}") + if(LIB_SUFFIX AND NOT SIZEOF_VOID_P_BITS EQUAL LIB_SUFFIX) + ocv_update(OPENCV_CONFIG_INSTALL_PATH lib${LIB_SUFFIX}/cmake/opencv) + else() + ocv_update(OPENCV_CONFIG_INSTALL_PATH share/OpenCV) + endif() + endif() endif() + ocv_update(OPENCV_INCLUDE_INSTALL_PATH "include") endif() -set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${OPENCV_LIB_INSTALL_PATH}") +ocv_update(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${OPENCV_LIB_INSTALL_PATH}") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) if(INSTALL_TO_MANGLED_PATHS) set(OPENCV_INCLUDE_INSTALL_PATH ${OPENCV_INCLUDE_INSTALL_PATH}/opencv-${OPENCV_VERSION}) - string(REPLACE "OpenCV" "OpenCV-${OPENCV_VERSION}" OPENCV_3P_LIB_INSTALL_PATH "${OPENCV_3P_LIB_INSTALL_PATH}") - string(REPLACE "OpenCV" "OpenCV-${OPENCV_VERSION}" OPENCV_SAMPLES_SRC_INSTALL_PATH "${OPENCV_SAMPLES_SRC_INSTALL_PATH}") - string(REPLACE "OpenCV" "OpenCV-${OPENCV_VERSION}" OPENCV_CONFIG_INSTALL_PATH "${OPENCV_CONFIG_INSTALL_PATH}") - string(REPLACE "OpenCV" "OpenCV-${OPENCV_VERSION}" OPENCV_DOC_INSTALL_PATH "${OPENCV_DOC_INSTALL_PATH}") - string(REPLACE "OpenCV" "OpenCV-${OPENCV_VERSION}" OPENCV_JAR_INSTALL_PATH "${OPENCV_JAR_INSTALL_PATH}") - string(REPLACE "OpenCV" "OpenCV-${OPENCV_VERSION}" OPENCV_TEST_DATA_INSTALL_PATH "${OPENCV_TEST_DATA_INSTALL_PATH}") - string(REPLACE "OpenCV" "OpenCV-${OPENCV_VERSION}" OPENCV_OTHER_INSTALL_PATH "${OPENCV_OTHER_INSTALL_PATH}") + foreach(v + OPENCV_3P_LIB_INSTALL_PATH + OPENCV_SAMPLES_SRC_INSTALL_PATH + OPENCV_CONFIG_INSTALL_PATH + OPENCV_DOC_INSTALL_PATH + OPENCV_JAR_INSTALL_PATH + OPENCV_TEST_DATA_INSTALL_PATH + OPENCV_OTHER_INSTALL_PATH + ) + string(REPLACE "OpenCV" "OpenCV-${OPENCV_VERSION}" ${v} "${${v}}") + string(REPLACE "opencv" "opencv-${OPENCV_VERSION}" ${v} "${${v}}") + endforeach() endif() @@ -440,7 +448,7 @@ endif() # ---------------------------------------------------------------------------- # Path for build/platform -specific headers # ---------------------------------------------------------------------------- -set(OPENCV_CONFIG_FILE_INCLUDE_DIR "${CMAKE_BINARY_DIR}/" CACHE PATH "Where to create the platform-dependant cvconfig.h") +ocv_update(OPENCV_CONFIG_FILE_INCLUDE_DIR "${CMAKE_BINARY_DIR}/" CACHE PATH "Where to create the platform-dependant cvconfig.h") ocv_include_directories(${OPENCV_CONFIG_FILE_INCLUDE_DIR}) # ---------------------------------------------------------------------------- @@ -453,7 +461,7 @@ set(OPENCV_EXTRA_MODULES_PATH "" CACHE PATH "Where to look for additional OpenCV # ---------------------------------------------------------------------------- find_host_package(Git QUIET) -if(GIT_FOUND) +if(NOT DEFINED OPENCV_VCSVERSION AND GIT_FOUND) execute_process(COMMAND "${GIT_EXECUTABLE}" describe --tags --always --dirty --match "[0-9].[0-9].[0-9]*" WORKING_DIRECTORY "${OpenCV_SOURCE_DIR}" OUTPUT_VARIABLE OPENCV_VCSVERSION @@ -464,7 +472,7 @@ if(GIT_FOUND) if(NOT GIT_RESULT EQUAL 0) set(OPENCV_VCSVERSION "unknown") endif() -else() +elseif(NOT DEFINED OPENCV_VCSVERSION) # We don't have git: set(OPENCV_VCSVERSION "unknown") endif() diff --git a/cmake/OpenCVFindIPP.cmake b/cmake/OpenCVFindIPP.cmake index 3bff76693..43172112f 100644 --- a/cmake/OpenCVFindIPP.cmake +++ b/cmake/OpenCVFindIPP.cmake @@ -146,7 +146,7 @@ macro(ipp_detect_version) IMPORTED_LOCATION ${IPP_LIBRARY_DIR}/${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX} ) list(APPEND IPP_LIBRARIES ipp${name}) - if (NOT BUILD_SHARED_LIBS OR NOT INSTALL_CREATE_DISTRIB) + if (NOT BUILD_SHARED_LIBS) # CMake doesn't support "install(TARGETS ${IPP_PREFIX}${name} " command with imported targets install(FILES ${IPP_LIBRARY_DIR}/${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX} DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) diff --git a/cmake/OpenCVGenConfig.cmake b/cmake/OpenCVGenConfig.cmake index 3770d05b4..29517cdb1 100644 --- a/cmake/OpenCVGenConfig.cmake +++ b/cmake/OpenCVGenConfig.cmake @@ -11,47 +11,20 @@ else() set(OpenCV_USE_MANGLED_PATHS_CONFIGCMAKE FALSE) endif() -if(NOT OpenCV_CUDA_CC) - set(OpenCV_CUDA_CC_CONFIGCMAKE "\"\"") - set(OpenCV_CUDA_VERSION "") -else() - set(OpenCV_CUDA_CC_CONFIGCMAKE "${OpenCV_CUDA_CC}") - set(OpenCV_CUDA_VERSION ${CUDA_VERSION_STRING}) +if(HAVE_CUDA) + ocv_cmake_configure("${CMAKE_CURRENT_LIST_DIR}/templates/OpenCVConfig-CUDA.cmake.in" CUDA_CONFIGCMAKE @ONLY) endif() -if(NOT ANDROID_NATIVE_API_LEVEL) - set(OpenCV_ANDROID_NATIVE_API_LEVEL_CONFIGCMAKE 0) -else() - set(OpenCV_ANDROID_NATIVE_API_LEVEL_CONFIGCMAKE "${ANDROID_NATIVE_API_LEVEL}") -endif() - -if(CMAKE_GENERATOR MATCHES "Visual" OR CMAKE_GENERATOR MATCHES "Xcode") - set(OpenCV_ADD_DEBUG_RELEASE_CONFIGCMAKE TRUE) -else() - set(OpenCV_ADD_DEBUG_RELEASE_CONFIGCMAKE FALSE) -endif() - - - -if(WIN32) - if(MINGW) - set(OPENCV_LINK_LIBRARY_SUFFIX ".dll.a") +if(ANDROID) + if(NOT ANDROID_NATIVE_API_LEVEL) + set(OpenCV_ANDROID_NATIVE_API_LEVEL_CONFIGCMAKE 0) else() - set(OPENCV_LINK_LIBRARY_SUFFIX ".lib") + set(OpenCV_ANDROID_NATIVE_API_LEVEL_CONFIGCMAKE "${ANDROID_NATIVE_API_LEVEL}") endif() + ocv_cmake_configure("${CMAKE_CURRENT_LIST_DIR}/templates/OpenCVConfig-ANDROID.cmake.in" ANDROID_CONFIGCMAKE @ONLY) endif() -#build list of modules available for the OpenCV user -set(OpenCV_LIB_COMPONENTS "") -foreach(m ${OPENCV_MODULES_PUBLIC}) - list(INSERT OpenCV_LIB_COMPONENTS 0 ${${m}_MODULE_DEPS_OPT} ${m}) -endforeach() -ocv_list_unique(OpenCV_LIB_COMPONENTS) -set(OPENCV_MODULES_CONFIGCMAKE ${OpenCV_LIB_COMPONENTS}) -ocv_list_filterout(OpenCV_LIB_COMPONENTS "^opencv_") -if(OpenCV_LIB_COMPONENTS) - list(REMOVE_ITEM OPENCV_MODULES_CONFIGCMAKE ${OpenCV_LIB_COMPONENTS}) -endif() +set(OPENCV_MODULES_CONFIGCMAKE ${OPENCV_MODULES_PUBLIC}) if(BUILD_FAT_JAVA_LIB AND HAVE_opencv_java) list(APPEND OPENCV_MODULES_CONFIGCMAKE opencv_java) @@ -62,33 +35,20 @@ endif() # ------------------------------------------------------------------------------------------- set(OpenCV_INCLUDE_DIRS_CONFIGCMAKE "\"${OPENCV_CONFIG_FILE_INCLUDE_DIR}\" \"${OpenCV_SOURCE_DIR}/include\" \"${OpenCV_SOURCE_DIR}/include/opencv\"") -set(OpenCV2_INCLUDE_DIRS_CONFIGCMAKE "") foreach(m ${OPENCV_MODULES_BUILD}) if(EXISTS "${OPENCV_MODULE_${m}_LOCATION}/include") - list(APPEND OpenCV2_INCLUDE_DIRS_CONFIGCMAKE "${OPENCV_MODULE_${m}_LOCATION}/include") + set(OpenCV_INCLUDE_DIRS_CONFIGCMAKE "${OpenCV_INCLUDE_DIRS_CONFIGCMAKE} \"${OPENCV_MODULE_${m}_LOCATION}/include\"") endif() endforeach() -if(ANDROID AND NOT BUILD_SHARED_LIBS AND HAVE_TBB) - #export TBB headers location because static linkage of TBB might be troublesome if application wants to use TBB itself - list(APPEND OpenCV2_INCLUDE_DIRS_CONFIGCMAKE ${TBB_INCLUDE_DIRS}) -endif() +export(TARGETS ${OpenCVModules_TARGETS} FILE "${CMAKE_BINARY_DIR}/OpenCVModules.cmake") -set(modules_file_suffix "") -if(ANDROID) - # the REPLACE here is needed, because OpenCVModules_armeabi.cmake includes - # OpenCVModules_armeabi-*.cmake, which would match OpenCVModules_armeabi-v7a*.cmake. - string(REPLACE - _ modules_file_suffix "_${ANDROID_NDK_ABI_NAME}") -endif() - -export(TARGETS ${OpenCVModules_TARGETS} FILE "${CMAKE_BINARY_DIR}/OpenCVModules${modules_file_suffix}.cmake") - -if(TARGET ippicv AND (NOT BUILD_SHARED_LIBS OR NOT INSTALL_CREATE_DISTRIB)) +if(TARGET ippicv AND NOT BUILD_SHARED_LIBS) set(USE_IPPICV TRUE) - file(RELATIVE_PATH INSTALL_PATH_RELATIVE_IPPICV ${CMAKE_BINARY_DIR} ${IPPICV_LOCATION_PATH}) + file(RELATIVE_PATH IPPICV_INSTALL_PATH_RELATIVE_CONFIGCMAKE ${CMAKE_BINARY_DIR} ${IPPICV_LOCATION_PATH}) + ocv_cmake_configure("${CMAKE_CURRENT_LIST_DIR}/templates/OpenCVConfig-IPPICV.cmake.in" IPPICV_CONFIGCMAKE @ONLY) else() set(USE_IPPICV FALSE) - set(INSTALL_PATH_RELATIVE_IPPICV "non-existed-path") endif() configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/OpenCVConfig.cmake.in" "${CMAKE_BINARY_DIR}/OpenCVConfig.cmake" @ONLY) @@ -98,58 +58,60 @@ configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/OpenCVConfig-version.cmake. # -------------------------------------------------------------------------------------------- # Part 2/3: ${BIN_DIR}/unix-install/OpenCVConfig.cmake -> For use *with* "make install" # ------------------------------------------------------------------------------------------- -set(OpenCV_INCLUDE_DIRS_CONFIGCMAKE "\"\${OpenCV_INSTALL_PATH}/${OPENCV_INCLUDE_INSTALL_PATH}/opencv" "\${OpenCV_INSTALL_PATH}/${OPENCV_INCLUDE_INSTALL_PATH}\"") +file(RELATIVE_PATH OpenCV_INSTALL_PATH_RELATIVE_CONFIGCMAKE "${CMAKE_INSTALL_PREFIX}/${OPENCV_CONFIG_INSTALL_PATH}/" ${CMAKE_INSTALL_PREFIX}) +set(OpenCV_INCLUDE_DIRS_CONFIGCMAKE "\"\${OpenCV_INSTALL_PATH}/${OPENCV_INCLUDE_INSTALL_PATH}\" \"\${OpenCV_INSTALL_PATH}/${OPENCV_INCLUDE_INSTALL_PATH}/opencv\"") -set(OpenCV2_INCLUDE_DIRS_CONFIGCMAKE "\"\"") -set(OpenCV_3RDPARTY_LIB_DIRS_CONFIGCMAKE "\"\${OpenCV_INSTALL_PATH}/${OPENCV_3P_LIB_INSTALL_PATH}\"") +if(USE_IPPICV) + file(RELATIVE_PATH IPPICV_INSTALL_PATH_RELATIVE_CONFIGCMAKE "${CMAKE_INSTALL_PREFIX}" ${IPPICV_INSTALL_PATH}) + ocv_cmake_configure("${CMAKE_CURRENT_LIST_DIR}/templates/OpenCVConfig-IPPICV.cmake.in" IPPICV_CONFIGCMAKE @ONLY) +endif() -if(UNIX) # ANDROID configuration is created here also - #http://www.vtk.org/Wiki/CMake/Tutorials/Packaging reference - # For a command "find_package( [major[.minor]] [EXACT] [REQUIRED|QUIET])" - # cmake will look in the following dir on unix: - # /(share|lib)/cmake/*/ (U) - # /(share|lib)/*/ (U) - # /(share|lib)/*/(cmake|CMake)/ (U) - if(USE_IPPICV) - file(RELATIVE_PATH INSTALL_PATH_RELATIVE_IPPICV "${CMAKE_INSTALL_PREFIX}/${OPENCV_CONFIG_INSTALL_PATH}/" ${IPPICV_INSTALL_PATH}) +function(ocv_gen_config TMP_DIR NESTED_PATH ROOT_NAME) + ocv_path_join(__install_nested "${OPENCV_CONFIG_INSTALL_PATH}" "${NESTED_PATH}") + ocv_path_join(__tmp_nested "${TMP_DIR}" "${NESTED_PATH}") + + file(RELATIVE_PATH OpenCV_INSTALL_PATH_RELATIVE_CONFIGCMAKE "${CMAKE_INSTALL_PREFIX}/${__install_nested}" "${CMAKE_INSTALL_PREFIX}/") + + configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/OpenCVConfig-version.cmake.in" "${TMP_DIR}/OpenCVConfig-version.cmake" @ONLY) + + configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/OpenCVConfig.cmake.in" "${__tmp_nested}/OpenCVConfig.cmake" @ONLY) + install(EXPORT OpenCVModules DESTINATION "${__install_nested}" FILE OpenCVModules.cmake COMPONENT dev) + install(FILES + "${TMP_DIR}/OpenCVConfig-version.cmake" + "${__tmp_nested}/OpenCVConfig.cmake" + DESTINATION "${CMAKE_INSTALL_PREFIX}/${__install_nested}" COMPONENT dev) + + if(ROOT_NAME) + # Root config file + configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/${ROOT_NAME}" "${TMP_DIR}/OpenCVConfig.cmake" @ONLY) + install(FILES + "${TMP_DIR}/OpenCVConfig-version.cmake" + "${TMP_DIR}/OpenCVConfig.cmake" + DESTINATION "${CMAKE_INSTALL_PREFIX}/${OPENCV_CONFIG_INSTALL_PATH}" COMPONENT dev) endif() - configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/OpenCVConfig.cmake.in" "${CMAKE_BINARY_DIR}/unix-install/OpenCVConfig.cmake" @ONLY) - configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/OpenCVConfig-version.cmake.in" "${CMAKE_BINARY_DIR}/unix-install/OpenCVConfig-version.cmake" @ONLY) - install(FILES "${CMAKE_BINARY_DIR}/unix-install/OpenCVConfig.cmake" DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}/ COMPONENT dev) - install(FILES ${CMAKE_BINARY_DIR}/unix-install/OpenCVConfig-version.cmake DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}/ COMPONENT dev) - install(EXPORT OpenCVModules DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}/ FILE OpenCVModules${modules_file_suffix}.cmake COMPONENT dev) +endfunction() + +if(UNIX AND NOT ANDROID) + ocv_gen_config("${CMAKE_BINARY_DIR}/unix-install" "" "") endif() if(ANDROID) - install(FILES "${OpenCV_SOURCE_DIR}/platforms/android/android.toolchain.cmake" DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}/ COMPONENT dev) + ocv_gen_config("${CMAKE_BINARY_DIR}/unix-install" "abi-${ANDROID_NDK_ABI_NAME}" "OpenCVConfig.root-ANDROID.cmake.in") + install(FILES "${OpenCV_SOURCE_DIR}/platforms/android/android.toolchain.cmake" DESTINATION "${OPENCV_CONFIG_INSTALL_PATH}" COMPONENT dev) endif() # -------------------------------------------------------------------------------------------- # Part 3/3: ${BIN_DIR}/win-install/OpenCVConfig.cmake -> For use within binary installers/packages # -------------------------------------------------------------------------------------------- if(WIN32) - set(OpenCV_INCLUDE_DIRS_CONFIGCMAKE "\"\${OpenCV_CONFIG_PATH}/include\" \"\${OpenCV_CONFIG_PATH}/include/opencv\"") - set(OpenCV2_INCLUDE_DIRS_CONFIGCMAKE "\"\"") - - exec_program(mkdir ARGS "-p \"${CMAKE_BINARY_DIR}/win-install/\"" OUTPUT_VARIABLE RET_VAL) - if(USE_IPPICV) - file(RELATIVE_PATH INSTALL_PATH_RELATIVE_IPPICV "${CMAKE_INSTALL_PREFIX}/${OpenCV_INSTALL_BINARIES_PREFIX}staticlib" ${IPPICV_INSTALL_PATH}) - endif() - configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/OpenCVConfig.cmake.in" "${CMAKE_BINARY_DIR}/win-install/OpenCVConfig.cmake" @ONLY) - configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/OpenCVConfig-version.cmake.in" "${CMAKE_BINARY_DIR}/win-install/OpenCVConfig-version.cmake" @ONLY) - if (CMAKE_HOST_SYSTEM_NAME MATCHES Windows) + if(CMAKE_HOST_SYSTEM_NAME MATCHES Windows) if(BUILD_SHARED_LIBS) - install(FILES "${CMAKE_BINARY_DIR}/win-install/OpenCVConfig.cmake" DESTINATION "${OpenCV_INSTALL_BINARIES_PREFIX}lib" COMPONENT dev) - install(EXPORT OpenCVModules DESTINATION "${OpenCV_INSTALL_BINARIES_PREFIX}lib" FILE OpenCVModules${modules_file_suffix}.cmake COMPONENT dev) + set(_lib_suffix "lib") else() - install(FILES "${CMAKE_BINARY_DIR}/win-install/OpenCVConfig.cmake" DESTINATION "${OpenCV_INSTALL_BINARIES_PREFIX}staticlib" COMPONENT dev) - install(EXPORT OpenCVModules DESTINATION "${OpenCV_INSTALL_BINARIES_PREFIX}staticlib" FILE OpenCVModules${modules_file_suffix}.cmake COMPONENT dev) + set(_lib_suffix "staticlib") endif() - install(FILES "${CMAKE_BINARY_DIR}/win-install/OpenCVConfig-version.cmake" DESTINATION ./ COMPONENT dev) - install(FILES "${OpenCV_SOURCE_DIR}/cmake/OpenCVConfig.cmake" DESTINATION ./ COMPONENT dev) - else () - install(FILES "${CMAKE_BINARY_DIR}/win-install/OpenCVConfig.cmake" DESTINATION "${OpenCV_INSTALL_BINARIES_PREFIX}lib/cmake/opencv-${OPENCV_VERSION}" COMPONENT dev) - install(EXPORT OpenCVModules DESTINATION "${OpenCV_INSTALL_BINARIES_PREFIX}lib/cmake/opencv-${OPENCV_VERSION}" FILE OpenCVModules${modules_file_suffix}.cmake COMPONENT dev) - install(FILES "${CMAKE_BINARY_DIR}/win-install/OpenCVConfig-version.cmake" DESTINATION "lib/cmake/opencv-${OPENCV_VERSION}" COMPONENT dev) - endif () + ocv_gen_config("${CMAKE_BINARY_DIR}/win-install" "${OpenCV_INSTALL_BINARIES_PREFIX}${_lib_suffix}" "OpenCVConfig.root-WIN32.cmake.in") + else() + ocv_gen_config("${CMAKE_BINARY_DIR}/win-install" "" "") + endif() endif() diff --git a/cmake/OpenCVUtils.cmake b/cmake/OpenCVUtils.cmake index a17e25548..281610087 100644 --- a/cmake/OpenCVUtils.cmake +++ b/cmake/OpenCVUtils.cmake @@ -30,6 +30,19 @@ function(ocv_cmake_eval var_name) endif() endfunction() +macro(ocv_cmake_configure file_name var_name) + configure_file(${file_name} "${CMAKE_BINARY_DIR}/CMakeConfig-${var_name}.cmake" ${ARGN}) + file(READ "${CMAKE_BINARY_DIR}/CMakeConfig-${var_name}.cmake" ${var_name}) +endmacro() + +macro(ocv_update VAR) + if(NOT DEFINED ${VAR}) + set(${VAR} ${ARGN}) + else() + #ocv_debug_message("Preserve old value for ${VAR}: ${${VAR}}") + endif() +endmacro() + # Search packages for host system instead of packages for target system # in case of cross compilation thess macro should be defined by toolchain file if(NOT COMMAND find_host_package) @@ -71,6 +84,19 @@ macro(ocv_check_environment_variables) endforeach() endmacro() +macro(ocv_path_join result_var P1 P2) + string(REGEX REPLACE "^[/]+" "" P2 "${P2}") + if("${P1}" STREQUAL "") + set(${result_var} "${P2}") + elseif("${P1}" STREQUAL "/") + set(${result_var} "/${P2}") + elseif("${P2}" STREQUAL "") + set(${result_var} "${P1}") + else() + set(${result_var} "${P1}/${P2}") + endif() +endmacro() + # rename modules target to world if needed macro(_ocv_fix_target target_var) if(BUILD_opencv_world) @@ -359,7 +385,7 @@ macro(CHECK_MODULE module_name define) endmacro() -set(OPENCV_BUILD_INFO_FILE "${OpenCV_BINARY_DIR}/version_string.tmp") +set(OPENCV_BUILD_INFO_FILE "${CMAKE_BINARY_DIR}/version_string.tmp") file(REMOVE "${OPENCV_BUILD_INFO_FILE}") function(ocv_output_status msg) message(STATUS "${msg}") diff --git a/cmake/templates/OpenCVConfig-ANDROID.cmake.in b/cmake/templates/OpenCVConfig-ANDROID.cmake.in new file mode 100644 index 000000000..1787acab3 --- /dev/null +++ b/cmake/templates/OpenCVConfig-ANDROID.cmake.in @@ -0,0 +1,13 @@ +# Android API level from which OpenCV has been compiled is remembered +set(OpenCV_ANDROID_NATIVE_API_LEVEL "@OpenCV_ANDROID_NATIVE_API_LEVEL_CONFIGCMAKE@") + +# ============================================================== +# Check OpenCV availability +# ============================================================== +if(OpenCV_ANDROID_NATIVE_API_LEVEL GREATER ANDROID_NATIVE_API_LEVEL) + if(NOT OpenCV_FIND_QUIETLY) + message(WARNING "Minimum required by OpenCV API level is android-${OpenCV_ANDROID_NATIVE_API_LEVEL}") + endif() + set(OpenCV_FOUND 0) + return() +endif() diff --git a/cmake/templates/OpenCVConfig-CUDA.cmake.in b/cmake/templates/OpenCVConfig-CUDA.cmake.in new file mode 100644 index 000000000..0d261dd84 --- /dev/null +++ b/cmake/templates/OpenCVConfig-CUDA.cmake.in @@ -0,0 +1,53 @@ +# Version Compute Capability from which OpenCV has been compiled is remembered +set(OpenCV_COMPUTE_CAPABILITIES "@OpenCV_CUDA_CC@") + +set(OpenCV_CUDA_VERSION "@CUDA_VERSION_STRING@") +set(OpenCV_USE_CUBLAS "@HAVE_CUBLAS@") +set(OpenCV_USE_CUFFT "@HAVE_CUFFT@") +set(OpenCV_USE_NVCUVID "@HAVE_NVCUVID@") + +if(NOT CUDA_FOUND) + find_host_package(CUDA ${OpenCV_CUDA_VERSION} EXACT REQUIRED) +else() + if(NOT CUDA_VERSION_STRING VERSION_EQUAL OpenCV_CUDA_VERSION) + message(FATAL_ERROR "OpenCV static library was compiled with CUDA ${OpenCV_CUDA_VERSION} support. Please, use the same version or rebuild OpenCV with CUDA ${CUDA_VERSION_STRING}") + endif() +endif() + +set(OpenCV_CUDA_LIBS_ABSPATH ${CUDA_LIBRARIES}) + +if(${CUDA_VERSION} VERSION_LESS "5.5") + list(APPEND OpenCV_CUDA_LIBS_ABSPATH ${CUDA_npp_LIBRARY}) +else() + find_cuda_helper_libs(nppc) + find_cuda_helper_libs(nppi) + find_cuda_helper_libs(npps) + list(APPEND OpenCV_CUDA_LIBS_ABSPATH ${CUDA_nppc_LIBRARY} ${CUDA_nppi_LIBRARY} ${CUDA_npps_LIBRARY}) +endif() + +if(OpenCV_USE_CUBLAS) + list(APPEND OpenCV_CUDA_LIBS_ABSPATH ${CUDA_CUBLAS_LIBRARIES}) +endif() + +if(OpenCV_USE_CUFFT) + list(APPEND OpenCV_CUDA_LIBS_ABSPATH ${CUDA_CUFFT_LIBRARIES}) +endif() + +if(OpenCV_USE_NVCUVID) + list(APPEND OpenCV_CUDA_LIBS_ABSPATH ${CUDA_nvcuvid_LIBRARIES}) +endif() + +if(WIN32) + list(APPEND OpenCV_CUDA_LIBS_ABSPATH ${CUDA_nvcuvenc_LIBRARIES}) +endif() + +set(OpenCV_CUDA_LIBS_RELPATH "") +foreach(l ${OpenCV_CUDA_LIBS_ABSPATH}) + get_filename_component(_tmp ${l} PATH) + if(NOT ${_tmp} MATCHES "-Wl.*") + list(APPEND OpenCV_CUDA_LIBS_RELPATH ${_tmp}) + endif() +endforeach() + +list(REMOVE_DUPLICATES OpenCV_CUDA_LIBS_RELPATH) +link_directories(${OpenCV_CUDA_LIBS_RELPATH}) diff --git a/cmake/templates/OpenCVConfig-IPPICV.cmake.in b/cmake/templates/OpenCVConfig-IPPICV.cmake.in new file mode 100644 index 000000000..33cf2d437 --- /dev/null +++ b/cmake/templates/OpenCVConfig-IPPICV.cmake.in @@ -0,0 +1,7 @@ +if(NOT TARGET ippicv) + add_library(ippicv STATIC IMPORTED) + set_target_properties(ippicv PROPERTIES + IMPORTED_LINK_INTERFACE_LIBRARIES "" + IMPORTED_LOCATION "${OpenCV_INSTALL_PATH}/@IPPICV_INSTALL_PATH_RELATIVE_CONFIGCMAKE@" + ) +endif() diff --git a/cmake/templates/OpenCVConfig.cmake.in b/cmake/templates/OpenCVConfig.cmake.in index 468732b8b..dfe9aeafe 100644 --- a/cmake/templates/OpenCVConfig.cmake.in +++ b/cmake/templates/OpenCVConfig.cmake.in @@ -29,125 +29,15 @@ # # Advanced variables: # - OpenCV_SHARED : Use OpenCV as shared library -# - OpenCV_CONFIG_PATH : Path to this OpenCVConfig.cmake -# - OpenCV_INSTALL_PATH : OpenCV location (not set on Windows) +# - OpenCV_INSTALL_PATH : OpenCV location # - OpenCV_LIB_COMPONENTS : Present OpenCV modules list # - OpenCV_USE_MANGLED_PATHS : Mangled OpenCV path flag -# - OpenCV_MODULES_SUFFIX : The suffix for OpenCVModules-XXX.cmake file # # Deprecated variables: # - OpenCV_VERSION_TWEAK : Always "0" # # =================================================================================== -# Search packages for host system instead of packages for target system. -# in case of cross compilation thess macro should be defined by toolchain file - -if(NOT COMMAND find_host_package) - macro(find_host_package) - find_package(${ARGN}) - endmacro() -endif() - -if(NOT COMMAND find_host_program) - macro(find_host_program) - find_program(${ARGN}) - endmacro() -endif() - -if(NOT DEFINED OpenCV_MODULES_SUFFIX) - if(ANDROID) - string(REPLACE - _ OpenCV_MODULES_SUFFIX "_${ANDROID_NDK_ABI_NAME}") - else() - set(OpenCV_MODULES_SUFFIX "") - endif() -endif() - -if("@USE_IPPICV@" STREQUAL "TRUE") # value is defined by package builder (use STREQUAL to comply new CMake policy CMP0012) - if(NOT TARGET ippicv) - if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/@INSTALL_PATH_RELATIVE_IPPICV@") - add_library(ippicv STATIC IMPORTED) - set_target_properties(ippicv PROPERTIES - IMPORTED_LINK_INTERFACE_LIBRARIES "" - IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/@INSTALL_PATH_RELATIVE_IPPICV@" - ) - endif() - endif() -endif() - -if(NOT TARGET opencv_core) - # Extract directory name from full path of the file currently being processed. - # Note that CMake 2.8.3 introduced CMAKE_CURRENT_LIST_DIR. We reimplement it - # for older versions of CMake to support these as well. - if(CMAKE_VERSION VERSION_LESS "2.8.3") - get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) - endif() - - include(${CMAKE_CURRENT_LIST_DIR}/OpenCVModules${OpenCV_MODULES_SUFFIX}.cmake) -endif() - -# TODO All things below should be reviewed. What is about of moving this code into related modules (special vars/hooks/files) - -# Version Compute Capability from which OpenCV has been compiled is remembered -set(OpenCV_COMPUTE_CAPABILITIES @OpenCV_CUDA_CC_CONFIGCMAKE@) - -set(OpenCV_CUDA_VERSION @OpenCV_CUDA_VERSION@) -set(OpenCV_USE_CUBLAS @HAVE_CUBLAS@) -set(OpenCV_USE_CUFFT @HAVE_CUFFT@) -set(OpenCV_USE_NVCUVID @HAVE_NVCUVID@) - -# Android API level from which OpenCV has been compiled is remembered -if(ANDROID) - set(OpenCV_ANDROID_NATIVE_API_LEVEL @OpenCV_ANDROID_NATIVE_API_LEVEL_CONFIGCMAKE@) -else() - set(OpenCV_ANDROID_NATIVE_API_LEVEL 0) -endif() - -# Some additional settings are required if OpenCV is built as static libs -set(OpenCV_SHARED @BUILD_SHARED_LIBS@) - -# Enables mangled install paths, that help with side by side installs -set(OpenCV_USE_MANGLED_PATHS @OpenCV_USE_MANGLED_PATHS_CONFIGCMAKE@) - -# Extract the directory where *this* file has been installed (determined at cmake run-time) -if(CMAKE_VERSION VERSION_LESS "2.8.12") - get_filename_component(OpenCV_CONFIG_PATH "${CMAKE_CURRENT_LIST_FILE}" PATH CACHE) -else() - get_filename_component(OpenCV_CONFIG_PATH "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY CACHE) -endif() - -if(NOT WIN32 OR ANDROID) - if(ANDROID) - set(OpenCV_INSTALL_PATH "${OpenCV_CONFIG_PATH}/../../..") - else() - set(OpenCV_INSTALL_PATH "${OpenCV_CONFIG_PATH}/../..") - endif() - # Get the absolute path with no ../.. relative marks, to eliminate implicit linker warnings - if(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} VERSION_LESS 2.8) - get_filename_component(OpenCV_INSTALL_PATH "${OpenCV_INSTALL_PATH}" ABSOLUTE) - else() - get_filename_component(OpenCV_INSTALL_PATH "${OpenCV_INSTALL_PATH}" REALPATH) - endif() -endif() - -# ====================================================== -# Include directories to add to the user project: -# ====================================================== - -# Provide the include directories to the caller -set(OpenCV_INCLUDE_DIRS @OpenCV_INCLUDE_DIRS_CONFIGCMAKE@) - -# ====================================================== -# Link directories to add to the user project: -# ====================================================== - -# Provide the libs directories to the caller -set(OpenCV_LIB_DIR_OPT @OpenCV_LIB_DIRS_CONFIGCMAKE@ CACHE PATH "Path where release OpenCV libraries are located") -set(OpenCV_LIB_DIR_DBG @OpenCV_LIB_DIRS_CONFIGCMAKE@ CACHE PATH "Path where debug OpenCV libraries are located") -set(OpenCV_3RDPARTY_LIB_DIR_OPT @OpenCV_3RDPARTY_LIB_DIRS_CONFIGCMAKE@ CACHE PATH "Path where release 3rdparty OpenCV dependencies are located") -set(OpenCV_3RDPARTY_LIB_DIR_DBG @OpenCV_3RDPARTY_LIB_DIRS_CONFIGCMAKE@ CACHE PATH "Path where debug 3rdparty OpenCV dependencies are located") -mark_as_advanced(FORCE OpenCV_LIB_DIR_OPT OpenCV_LIB_DIR_DBG OpenCV_3RDPARTY_LIB_DIR_OPT OpenCV_3RDPARTY_LIB_DIR_DBG OpenCV_CONFIG_PATH) - # ====================================================== # Version variables: # ====================================================== @@ -158,28 +48,48 @@ SET(OpenCV_VERSION_PATCH @OPENCV_VERSION_PATCH@) SET(OpenCV_VERSION_TWEAK 0) SET(OpenCV_VERSION_STATUS "@OPENCV_VERSION_STATUS@") -# ==================================================================== -# Link libraries: e.g. opencv_core;opencv_imgproc; etc... -# ==================================================================== +# Extract directory name from full path of the file currently being processed. +# Note that CMake 2.8.3 introduced CMAKE_CURRENT_LIST_DIR. We reimplement it +# for older versions of CMake to support these as well. +if(CMAKE_VERSION VERSION_LESS "2.8.3") + get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +endif() -SET(OpenCV_LIB_COMPONENTS @OPENCV_MODULES_CONFIGCMAKE@) -list(REMOVE_ITEM OpenCV_LIB_COMPONENTS opencv_hal) -SET(OpenCV_WORLD_COMPONENTS @OPENCV_WORLD_MODULES@) +# Extract the directory where *this* file has been installed (determined at cmake run-time) +# Get the absolute path with no ../.. relative marks, to eliminate implicit linker warnings +set(OpenCV_CONFIG_PATH "${CMAKE_CURRENT_LIST_DIR}") +get_filename_component(OpenCV_INSTALL_PATH "${OpenCV_CONFIG_PATH}/@OpenCV_INSTALL_PATH_RELATIVE_CONFIGCMAKE@" REALPATH) -# ============================================================== -# Extra include directories, needed by OpenCV 2 new structure -# ============================================================== -SET(OpenCV2_INCLUDE_DIRS @OpenCV2_INCLUDE_DIRS_CONFIGCMAKE@) -if(OpenCV2_INCLUDE_DIRS) - list(APPEND OpenCV_INCLUDE_DIRS ${OpenCV2_INCLUDE_DIRS}) +# Search packages for host system instead of packages for target system. +# in case of cross compilation thess macro should be defined by toolchain file +if(NOT COMMAND find_host_package) + macro(find_host_package) + find_package(${ARGN}) + endmacro() +endif() +if(NOT COMMAND find_host_program) + macro(find_host_program) + find_program(${ARGN}) + endmacro() +endif() - set(OpenCV_ADD_DEBUG_RELEASE @OpenCV_ADD_DEBUG_RELEASE_CONFIGCMAKE@) - if(OpenCV_ADD_DEBUG_RELEASE) - set(OpenCV_LIB_DIR_OPT "${OpenCV_LIB_DIR_OPT}/Release") - set(OpenCV_LIB_DIR_DBG "${OpenCV_LIB_DIR_DBG}/Debug") - set(OpenCV_3RDPARTY_LIB_DIR_OPT "${OpenCV_3RDPARTY_LIB_DIR_OPT}/Release") - set(OpenCV_3RDPARTY_LIB_DIR_DBG "${OpenCV_3RDPARTY_LIB_DIR_DBG}/Debug") - endif() + +@CUDA_CONFIGCMAKE@ +@ANDROID_CONFIGCMAKE@ + +@IPPICV_CONFIGCMAKE@ + +# Some additional settings are required if OpenCV is built as static libs +set(OpenCV_SHARED @BUILD_SHARED_LIBS@) + +# Enables mangled install paths, that help with side by side installs +set(OpenCV_USE_MANGLED_PATHS @OpenCV_USE_MANGLED_PATHS_CONFIGCMAKE@) + +set(OpenCV_LIB_COMPONENTS @OPENCV_MODULES_CONFIGCMAKE@) +set(OpenCV_INCLUDE_DIRS @OpenCV_INCLUDE_DIRS_CONFIGCMAKE@) + +if(NOT TARGET opencv_core) + include(${CMAKE_CURRENT_LIST_DIR}/OpenCVModules${OpenCV_MODULES_SUFFIX}.cmake) endif() if(NOT CMAKE_VERSION VERSION_LESS "2.8.11") @@ -196,22 +106,6 @@ if(NOT CMAKE_VERSION VERSION_LESS "2.8.11") endforeach() endif() -# ============================================================== -# Check OpenCV availability -# ============================================================== -if(ANDROID AND OpenCV_ANDROID_NATIVE_API_LEVEL GREATER ANDROID_NATIVE_API_LEVEL) - message(FATAL_ERROR "Minimum required by OpenCV API level is android-${OpenCV_ANDROID_NATIVE_API_LEVEL}") - #always FATAL_ERROR because we can't say to the caller that OpenCV is not found - #http://www.mail-archive.com/cmake@cmake.org/msg37831.html - if(OpenCV_FIND_REQUIRED) - message(FATAL_ERROR "Minimum required by OpenCV API level is android-${OpenCV_ANDROID_NATIVE_API_LEVEL}") - elseif(NOT OpenCV_FIND_QUIETLY) - message(WARNING "Minimum required by OpenCV API level is android-${OpenCV_ANDROID_NATIVE_API_LEVEL}") - endif() - set(OpenCV_FOUND "OpenCV_FOUND-NOTFOUND") - return()#Android toolchain requires CMake > 2.6 -endif() - # ============================================================== # Form list of modules (components) to find # ============================================================== @@ -223,6 +117,8 @@ if(NOT OpenCV_FIND_COMPONENTS) endif() endif() +set(OpenCV_WORLD_COMPONENTS @OPENCV_WORLD_MODULES@) + # expand short module names and see if requested components exist set(OpenCV_FIND_COMPONENTS_ "") foreach(__cvcomponent ${OpenCV_FIND_COMPONENTS}) @@ -276,89 +172,11 @@ foreach(__cvcomponent ${OpenCV_FIND_COMPONENTS}) endforeach() set(OpenCV_FIND_COMPONENTS ${OpenCV_FIND_COMPONENTS_}) -# ============================================================== -# Resolve dependencies -# ============================================================== -if(OpenCV_USE_MANGLED_PATHS) - set(OpenCV_LIB_SUFFIX ".${OpenCV_VERSION_MAJOR}.${OpenCV_VERSION_MINOR}.${OpenCV_VERSION_PATCH}") -else() - set(OpenCV_LIB_SUFFIX "") -endif() - -foreach(__opttype OPT DBG) - SET(OpenCV_LIBS_${__opttype} "${OpenCV_LIBS}") - SET(OpenCV_EXTRA_LIBS_${__opttype} "") - - # CUDA - if(OpenCV_CUDA_VERSION) - if(NOT CUDA_FOUND) - find_host_package(CUDA ${OpenCV_CUDA_VERSION} EXACT REQUIRED) - else() - if(NOT CUDA_VERSION_STRING VERSION_EQUAL OpenCV_CUDA_VERSION) - message(FATAL_ERROR "OpenCV static library was compiled with CUDA ${OpenCV_CUDA_VERSION} support. Please, use the same version or rebuild OpenCV with CUDA ${CUDA_VERSION_STRING}") - endif() - endif() - - set(OpenCV_CUDA_LIBS_ABSPATH ${CUDA_LIBRARIES}) - - if(${CUDA_VERSION} VERSION_LESS "5.5") - list(APPEND OpenCV_CUDA_LIBS_ABSPATH ${CUDA_npp_LIBRARY}) - else() - find_cuda_helper_libs(nppc) - find_cuda_helper_libs(nppi) - find_cuda_helper_libs(npps) - list(APPEND OpenCV_CUDA_LIBS_ABSPATH ${CUDA_nppc_LIBRARY} ${CUDA_nppi_LIBRARY} ${CUDA_npps_LIBRARY}) - endif() - - if(OpenCV_USE_CUBLAS) - list(APPEND OpenCV_CUDA_LIBS_ABSPATH ${CUDA_CUBLAS_LIBRARIES}) - endif() - - if(OpenCV_USE_CUFFT) - list(APPEND OpenCV_CUDA_LIBS_ABSPATH ${CUDA_CUFFT_LIBRARIES}) - endif() - - if(OpenCV_USE_NVCUVID) - list(APPEND OpenCV_CUDA_LIBS_ABSPATH ${CUDA_nvcuvid_LIBRARIES}) - endif() - - if(WIN32) - list(APPEND OpenCV_CUDA_LIBS_ABSPATH ${CUDA_nvcuvenc_LIBRARIES}) - endif() - - set(OpenCV_CUDA_LIBS_RELPATH "") - foreach(l ${OpenCV_CUDA_LIBS_ABSPATH}) - get_filename_component(_tmp ${l} PATH) - if(NOT ${_tmp} MATCHES "-Wl.*") - list(APPEND OpenCV_CUDA_LIBS_RELPATH ${_tmp}) - endif() - endforeach() - - list(REMOVE_DUPLICATES OpenCV_CUDA_LIBS_RELPATH) - link_directories(${OpenCV_CUDA_LIBS_RELPATH}) - endif() -endforeach() - # ============================================================== # Compatibility stuff # ============================================================== -if(CMAKE_BUILD_TYPE MATCHES "Debug") - SET(OpenCV_LIB_DIR ${OpenCV_LIB_DIR_DBG} ${OpenCV_3RDPARTY_LIB_DIR_DBG}) -else() - SET(OpenCV_LIB_DIR ${OpenCV_LIB_DIR_OPT} ${OpenCV_3RDPARTY_LIB_DIR_OPT}) -endif() set(OpenCV_LIBRARIES ${OpenCV_LIBS}) -if(CMAKE_CROSSCOMPILING AND OpenCV_SHARED AND (CMAKE_SYSTEM_NAME MATCHES "Linux")) - foreach(dir ${OpenCV_LIB_DIR}) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath-link,${dir}") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-rpath-link,${dir}") - set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-rpath-link,${dir}") - endforeach() -endif() - - - # # Some macroses for samples # @@ -376,7 +194,7 @@ endmacro() # adds include directories in such way that directories from the OpenCV source tree go first function(ocv_include_directories) set(__add_before "") - file(TO_CMAKE_PATH "${OpenCV_DIR}" __baseDir) + file(TO_CMAKE_PATH "${OpenCV_INSTALL_PATH}" __baseDir) foreach(dir ${ARGN}) get_filename_component(__abs_dir "${dir}" ABSOLUTE) if("${__abs_dir}" MATCHES "^${__baseDir}") diff --git a/cmake/templates/OpenCVConfig.root-ANDROID.cmake.in b/cmake/templates/OpenCVConfig.root-ANDROID.cmake.in new file mode 100644 index 000000000..7ceeec4c7 --- /dev/null +++ b/cmake/templates/OpenCVConfig.root-ANDROID.cmake.in @@ -0,0 +1,50 @@ +# =================================================================================== +# The OpenCV CMake configuration file +# +# ** File generated automatically, do not modify ** +# +# Usage from an external project: +# In your CMakeLists.txt, add these lines: +# +# find_package(OpenCV REQUIRED) +# include_directories(${OpenCV_INCLUDE_DIRS}) # Not needed for CMake >= 2.8.11 +# target_link_libraries(MY_TARGET_NAME ${OpenCV_LIBS}) +# +# Or you can search for specific OpenCV modules: +# +# find_package(OpenCV REQUIRED core videoio) +# +# If the module is found then OPENCV__FOUND is set to TRUE. +# +# This file will define the following variables: +# - OpenCV_LIBS : The list of all imported targets for OpenCV modules. +# - OpenCV_INCLUDE_DIRS : The OpenCV include directories. +# - OpenCV_ANDROID_NATIVE_API_LEVEL : Minimum required level of Android API. +# - OpenCV_VERSION : The version of this OpenCV build: "@OPENCV_VERSION_PLAIN@" +# - OpenCV_VERSION_MAJOR : Major version part of OpenCV_VERSION: "@OPENCV_VERSION_MAJOR@" +# - OpenCV_VERSION_MINOR : Minor version part of OpenCV_VERSION: "@OPENCV_VERSION_MINOR@" +# - OpenCV_VERSION_PATCH : Patch version part of OpenCV_VERSION: "@OPENCV_VERSION_PATCH@" +# - OpenCV_VERSION_STATUS : Development status of this build: "@OPENCV_VERSION_STATUS@" +# +# =================================================================================== + +# Extract directory name from full path of the file currently being processed. +# Note that CMake 2.8.3 introduced CMAKE_CURRENT_LIST_DIR. We reimplement it +# for older versions of CMake to support these as well. +if(CMAKE_VERSION VERSION_LESS "2.8.3") + get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +endif() + +if(NOT DEFINED OpenCV_CONFIG_SUBDIR) + set(OpenCV_CONFIG_SUBDIR "/abi-${ANDROID_NDK_ABI_NAME}") +endif() + +set(OpenCV_CONFIG_PATH "${CMAKE_CURRENT_LIST_DIR}${OpenCV_CONFIG_SUBDIR}") +if(EXISTS "${OpenCV_CONFIG_PATH}/OpenCVConfig.cmake") + include("${OpenCV_CONFIG_PATH}/OpenCVConfig.cmake") +else() + if(NOT OpenCV_FIND_QUIETLY) + message(WARNING "Found OpenCV Android Pack but it has no binaries compatible with your ABI (can't find: ${OpenCV_CONFIG_SUBDIR})") + endif() + set(OpenCV_FOUND FALSE) +endif() diff --git a/cmake/OpenCVConfig.cmake b/cmake/templates/OpenCVConfig.root-WIN32.cmake.in similarity index 72% rename from cmake/OpenCVConfig.cmake rename to cmake/templates/OpenCVConfig.root-WIN32.cmake.in index fdc371b19..e40140fb7 100644 --- a/cmake/OpenCVConfig.cmake +++ b/cmake/templates/OpenCVConfig.root-WIN32.cmake.in @@ -17,20 +17,16 @@ # # This file will define the following variables: # - OpenCV_LIBS : The list of libraries to link against. -# - OpenCV_LIB_DIR : The directory(es) where lib files are. Calling LINK_DIRECTORIES -# with this path is NOT needed. # - OpenCV_INCLUDE_DIRS : The OpenCV include directories. # - OpenCV_COMPUTE_CAPABILITIES : The version of compute capability -# - OpenCV_ANDROID_NATIVE_API_LEVEL : Minimum required level of Android API -# - OpenCV_VERSION : The version of this OpenCV build. Example: "2.4.0" -# - OpenCV_VERSION_MAJOR : Major version part of OpenCV_VERSION. Example: "2" -# - OpenCV_VERSION_MINOR : Minor version part of OpenCV_VERSION. Example: "4" -# - OpenCV_VERSION_PATCH : Patch version part of OpenCV_VERSION. Example: "0" +# - OpenCV_VERSION : The version of this OpenCV build: "@OPENCV_VERSION_PLAIN@" +# - OpenCV_VERSION_MAJOR : Major version part of OpenCV_VERSION: "@OPENCV_VERSION_MAJOR@" +# - OpenCV_VERSION_MINOR : Minor version part of OpenCV_VERSION: "@OPENCV_VERSION_MINOR@" +# - OpenCV_VERSION_PATCH : Patch version part of OpenCV_VERSION: "@OPENCV_VERSION_PATCH@" +# - OpenCV_VERSION_STATUS : Development status of this build: "@OPENCV_VERSION_STATUS@" # # Advanced variables: # - OpenCV_SHARED -# - OpenCV_CONFIG_PATH -# - OpenCV_LIB_COMPONENTS # # =================================================================================== # @@ -64,13 +60,11 @@ endif() if(MSVC) if(CMAKE_CL_64) set(OpenCV_ARCH x64) - set(OpenCV_TBB_ARCH intel64) elseif((CMAKE_GENERATOR MATCHES "ARM") OR ("${arch_hint}" STREQUAL "ARM") OR (CMAKE_VS_EFFECTIVE_PLATFORMS MATCHES "ARM|arm")) # see Modules/CmakeGenericSystem.cmake set(OpenCV_ARCH ARM) else() set(OpenCV_ARCH x86) - set(OpenCV_TBB_ARCH ia32) endif() if(MSVC_VERSION EQUAL 1400) set(OpenCV_RUNTIME vc8) @@ -99,22 +93,13 @@ elseif(MINGW) endif() endif() -if(CMAKE_VERSION VERSION_GREATER 2.6.2) - unset(OpenCV_CONFIG_PATH CACHE) -endif() - if(NOT OpenCV_FIND_QUIETLY) message(STATUS "OpenCV ARCH: ${OpenCV_ARCH}") message(STATUS "OpenCV RUNTIME: ${OpenCV_RUNTIME}") message(STATUS "OpenCV STATIC: ${OpenCV_STATIC}") endif() -if(CMAKE_VERSION VERSION_LESS "2.8.12") - get_filename_component(OpenCV_CONFIG_PATH "${CMAKE_CURRENT_LIST_FILE}" PATH CACHE) -else() - get_filename_component(OpenCV_CONFIG_PATH "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY CACHE) -endif() - +get_filename_component(OpenCV_CONFIG_PATH "${CMAKE_CURRENT_LIST_FILE}" PATH) if(OpenCV_RUNTIME AND OpenCV_ARCH) if(OpenCV_STATIC AND EXISTS "${OpenCV_CONFIG_PATH}/${OpenCV_ARCH}/${OpenCV_RUNTIME}/staticlib/OpenCVConfig.cmake") if(OpenCV_CUDA AND EXISTS "${OpenCV_CONFIG_PATH}/gpu/${OpenCV_ARCH}/${OpenCV_RUNTIME}/staticlib/OpenCVConfig.cmake") @@ -132,28 +117,8 @@ if(OpenCV_RUNTIME AND OpenCV_ARCH) endif() if(OpenCV_LIB_PATH AND EXISTS "${OpenCV_LIB_PATH}/OpenCVConfig.cmake") - set(OpenCV_LIB_DIR_OPT "${OpenCV_LIB_PATH}" CACHE PATH "Path where release OpenCV libraries are located" FORCE) - set(OpenCV_LIB_DIR_DBG "${OpenCV_LIB_PATH}" CACHE PATH "Path where debug OpenCV libraries are located" FORCE) - set(OpenCV_3RDPARTY_LIB_DIR_OPT "${OpenCV_LIB_PATH}" CACHE PATH "Path where release 3rdparty OpenCV dependencies are located" FORCE) - set(OpenCV_3RDPARTY_LIB_DIR_DBG "${OpenCV_LIB_PATH}" CACHE PATH "Path where debug 3rdparty OpenCV dependencies are located" FORCE) - include("${OpenCV_LIB_PATH}/OpenCVConfig.cmake") - if(OpenCV_CUDA) - set(_OpenCV_LIBS "") - foreach(_lib ${OpenCV_LIBS}) - string(REPLACE "${OpenCV_CONFIG_PATH}/gpu/${OpenCV_ARCH}/${OpenCV_RUNTIME}" "${OpenCV_CONFIG_PATH}/${OpenCV_ARCH}/${OpenCV_RUNTIME}" _lib2 "${_lib}") - if(NOT EXISTS "${_lib}" AND EXISTS "${_lib2}") - list(APPEND _OpenCV_LIBS "${_lib2}") - else() - list(APPEND _OpenCV_LIBS "${_lib}") - endif() - endforeach() - set(OpenCV_LIBS ${_OpenCV_LIBS}) - endif() - set(OpenCV_FOUND TRUE CACHE BOOL "" FORCE) - set(OPENCV_FOUND TRUE CACHE BOOL "" FORCE) - if(NOT OpenCV_FIND_QUIETLY) message(STATUS "Found OpenCV ${OpenCV_VERSION} in ${OpenCV_LIB_PATH}") if(NOT OpenCV_LIB_PATH MATCHES "/staticlib") @@ -173,6 +138,5 @@ else() You should manually point CMake variable OpenCV_DIR to your build of OpenCV library." ) endif() - set(OpenCV_FOUND FALSE CACHE BOOL "" FORCE) - set(OPENCV_FOUND FALSE CACHE BOOL "" FORCE) + set(OpenCV_FOUND FALSE) endif()