From a11ff876d4783985f38950dfaa6179aba5211d52 Mon Sep 17 00:00:00 2001 From: berak Date: Wed, 26 Aug 2015 15:19:26 +0200 Subject: [PATCH 001/156] enable VideoWriter class for java fixing fourcc --- modules/java/generator/gen_java.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/java/generator/gen_java.py b/modules/java/generator/gen_java.py index bfb585bf8..a40bbe572 100755 --- a/modules/java/generator/gen_java.py +++ b/modules/java/generator/gen_java.py @@ -13,8 +13,6 @@ else: class_ignore_list = ( #core "FileNode", "FileStorage", "KDTree", "KeyPoint", "DMatch", - #videoio - "VideoWriter", ) const_ignore_list = ( @@ -186,6 +184,7 @@ type_dict = { "env" : { "j_type" : "", "jn_type" : "", "jni_type" : "JNIEnv*"}, "cls" : { "j_type" : "", "jn_type" : "", "jni_type" : "jclass"}, "bool" : { "j_type" : "boolean", "jn_type" : "boolean", "jni_type" : "jboolean", "suffix" : "Z" }, + "char" : { "j_type" : "char", "jn_type" : "char", "jni_type" : "jchar", "suffix" : "C" }, "int" : { "j_type" : "int", "jn_type" : "int", "jni_type" : "jint", "suffix" : "I" }, "long" : { "j_type" : "int", "jn_type" : "int", "jni_type" : "jint", "suffix" : "I" }, "float" : { "j_type" : "float", "jn_type" : "float", "jni_type" : "jfloat", "suffix" : "F" }, From c1392f64a44c92b0e932b48aae2ba1017fccfaef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorena=20Garc=C3=ADa?= Date: Thu, 3 Sep 2015 07:38:25 +0200 Subject: [PATCH 002/156] ml_svm_tutorials version note added Added note to point out code is for version 3.0 despite compatibility of tutorial > version 2.0 --- .../ml/introduction_to_svm/introduction_to_svm.markdown | 2 ++ doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown | 3 +++ 2 files changed, 5 insertions(+) diff --git a/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.markdown b/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.markdown index 6bc5abb3e..5cc4bc508 100644 --- a/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.markdown +++ b/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.markdown @@ -94,6 +94,8 @@ the weight vector \f$\beta\f$ and the bias \f$\beta_{0}\f$ of the optimal hyperp Source Code ----------- +@note The following code has been implemented with OpenCV 3.0 classes and functions. An equivalent version of the code using OpenCV 2.4 can be found in [this page.](http://docs.opencv.org/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html#introductiontosvms) + @include cpp/tutorial_code/ml/introduction_to_svm/introduction_to_svm.cpp Explanation diff --git a/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown b/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown index 4f8f8f34e..68f4d4481 100644 --- a/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown +++ b/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown @@ -89,6 +89,9 @@ Source Code You may also find the source code in `samples/cpp/tutorial_code/ml/non_linear_svms` folder of the OpenCV source library or [download it from here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp). +@note The following code has been implemented with OpenCV 3.0 classes and functions. An equivalent version of the code +using OpenCV 2.4 can be found in [this page.](http://docs.opencv.org/doc/tutorials/ml/non_linear_svms/non_linear_svms.html#nonlinearsvms) + @include cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp Explanation From f034320731f8c2b3be386f0041c8241e0d0213a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorena=20Garc=C3=ADa?= Date: Thu, 3 Sep 2015 18:16:29 +0200 Subject: [PATCH 003/156] Change in links Explicit link to 2.4 docs --- .../ml/introduction_to_svm/introduction_to_svm.markdown | 2 +- doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.markdown b/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.markdown index 5cc4bc508..8a1985007 100644 --- a/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.markdown +++ b/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.markdown @@ -94,7 +94,7 @@ the weight vector \f$\beta\f$ and the bias \f$\beta_{0}\f$ of the optimal hyperp Source Code ----------- -@note The following code has been implemented with OpenCV 3.0 classes and functions. An equivalent version of the code using OpenCV 2.4 can be found in [this page.](http://docs.opencv.org/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html#introductiontosvms) +@note The following code has been implemented with OpenCV 3.0 classes and functions. An equivalent version of the code using OpenCV 2.4 can be found in [this page.](http://docs.opencv.org/2.4/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html#introductiontosvms) @include cpp/tutorial_code/ml/introduction_to_svm/introduction_to_svm.cpp diff --git a/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown b/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown index 68f4d4481..52b544dd0 100644 --- a/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown +++ b/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown @@ -90,7 +90,7 @@ You may also find the source code in `samples/cpp/tutorial_code/ml/non_linear_sv [download it from here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp). @note The following code has been implemented with OpenCV 3.0 classes and functions. An equivalent version of the code -using OpenCV 2.4 can be found in [this page.](http://docs.opencv.org/doc/tutorials/ml/non_linear_svms/non_linear_svms.html#nonlinearsvms) +using OpenCV 2.4 can be found in [this page.](http://docs.opencv.org/2.4/doc/tutorials/ml/non_linear_svms/non_linear_svms.html#nonlinearsvms) @include cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp From 68a0347ff9729ef90ba957a06e5eda8d11efb4f7 Mon Sep 17 00:00:00 2001 From: Alexey Ershov Date: Mon, 31 Aug 2015 02:33:15 +0300 Subject: [PATCH 004/156] fallback path & sample timing implemented fixed trailing whitespaces renamed files *vaapi* to *va_intel* changed names vaapi* to va_intel* --- CMakeLists.txt | 13 +- cmake/OpenCVFindLibsVideo.cmake | 20 +- cmake/OpenCVFindVA.cmake | 19 + cmake/OpenCVFindVAAPI.cmake | 44 -- cmake/OpenCVFindVA_INTEL.cmake | 44 ++ cmake/templates/cvconfig.h.in | 7 +- modules/core/CMakeLists.txt | 2 +- .../opencv2/core/{vaapi.hpp => va_intel.hpp} | 43 +- modules/core/src/precomp.hpp | 2 +- modules/core/src/va_intel.cpp | 517 ++++++++++++++++++ modules/core/src/vaapi.cpp | 302 ---------- samples/CMakeLists.txt | 4 +- samples/{vaapi => va_intel}/CMakeLists.txt | 14 +- samples/{vaapi => va_intel}/display.cpp.inc | 16 +- .../va_intel_interop.cpp} | 119 +++- 15 files changed, 741 insertions(+), 425 deletions(-) create mode 100644 cmake/OpenCVFindVA.cmake delete mode 100644 cmake/OpenCVFindVAAPI.cmake create mode 100644 cmake/OpenCVFindVA_INTEL.cmake rename modules/core/include/opencv2/core/{vaapi.hpp => va_intel.hpp} (54%) create mode 100644 modules/core/src/va_intel.cpp delete mode 100644 modules/core/src/vaapi.cpp rename samples/{vaapi => va_intel}/CMakeLists.txt (68%) rename samples/{vaapi => va_intel}/display.cpp.inc (90%) rename samples/{vaapi/vaapi_interop.cpp => va_intel/va_intel_interop.cpp} (85%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f378e745..a18169fbd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -205,7 +205,8 @@ OCV_OPTION(WITH_OPENCLAMDBLAS "Include AMD OpenCL BLAS library support" ON OCV_OPTION(WITH_DIRECTX "Include DirectX support" ON IF (WIN32 AND NOT WINRT) ) OCV_OPTION(WITH_INTELPERC "Include Intel Perceptual Computing support" OFF IF (WIN32 AND NOT WINRT) ) OCV_OPTION(WITH_IPP_A "Include Intel IPP_A support" OFF IF (MSVC OR X86 OR X86_64) ) -OCV_OPTION(WITH_VAAPI "Include VA-API support" OFF IF (UNIX AND NOT ANDROID) ) +OCV_OPTION(WITH_VA "Include VA support" OFF IF (UNIX AND NOT ANDROID) ) +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) ) @@ -1066,9 +1067,13 @@ if(DEFINED WITH_IPP_A) status(" Use IPP Async:" HAVE_IPP_A THEN "YES" ELSE NO) endif(DEFINED WITH_IPP_A) -if(DEFINED WITH_VAAPI) -status(" Use Intel VA-API:" HAVE_VAAPI THEN "YES (MSDK: ${VAAPI_MSDK_ROOT} OpenCL: ${VAAPI_IOCL_ROOT})" ELSE NO) -endif(DEFINED WITH_VAAPI) +if(DEFINED WITH_VA) +status(" Use VA:" HAVE_VA THEN "YES" ELSE NO) +endif(DEFINED WITH_VA) + +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) 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) diff --git a/cmake/OpenCVFindLibsVideo.cmake b/cmake/OpenCVFindLibsVideo.cmake index 4c4081d37..cce583b5d 100644 --- a/cmake/OpenCVFindLibsVideo.cmake +++ b/cmake/OpenCVFindLibsVideo.cmake @@ -318,10 +318,18 @@ if(WITH_GPHOTO2) CHECK_MODULE(libgphoto2 HAVE_GPHOTO2) endif(WITH_GPHOTO2) -# --- VA-API --- -if(WITH_VAAPI) - include("${OpenCV_SOURCE_DIR}/cmake/OpenCVFindVAAPI.cmake") - if(VAAPI_IOCL_INCLUDE_DIR) - ocv_include_directories(${VAAPI_IOCL_INCLUDE_DIR}) +# --- VA & VA_INTEL --- +if(WITH_VA_INTEL) + include("${OpenCV_SOURCE_DIR}/cmake/OpenCVFindVA_INTEL.cmake") + if(VA_INTEL_IOCL_INCLUDE_DIR) + ocv_include_directories(${VA_INTEL_IOCL_INCLUDE_DIR}) endif() -endif(WITH_VAAPI) + set(WITH_VA YES) +endif(WITH_VA_INTEL) + +if(WITH_VA) + include("${OpenCV_SOURCE_DIR}/cmake/OpenCVFindVA.cmake") + if(VA_INCLUDE_DIR) + ocv_include_directories(${VA_INCLUDE_DIR}) + endif() +endif(WITH_VA) diff --git a/cmake/OpenCVFindVA.cmake b/cmake/OpenCVFindVA.cmake new file mode 100644 index 000000000..03e24a034 --- /dev/null +++ b/cmake/OpenCVFindVA.cmake @@ -0,0 +1,19 @@ +# Main variables: +# HAVE_VA for conditional compilation OpenCV with/without libva + +if(UNIX AND NOT ANDROID) + find_path( + VA_INCLUDE_DIR + NAMES va/va.h + PATHS "/usr/include" + PATH_SUFFIXES include + DOC "Path to libva headers") +endif() + +if(VA_INCLUDE_DIR) + set(HAVE_VA TRUE) + set(VA_LIBRARIES "-lva") +else() + set(HAVE_VA FALSE) + message(WARNING "libva installation is not found.") +endif() diff --git a/cmake/OpenCVFindVAAPI.cmake b/cmake/OpenCVFindVAAPI.cmake deleted file mode 100644 index 2cb56219e..000000000 --- a/cmake/OpenCVFindVAAPI.cmake +++ /dev/null @@ -1,44 +0,0 @@ -# Main variables: -# VAAPI_MSDK_INCLUDE_DIR and VAAPI_IOCL_INCLUDE_DIR to use VAAPI -# HAVE_VAAPI for conditional compilation OpenCV with/without VAAPI - -# VAAPI_MSDK_ROOT - root of Intel MSDK installation -# VAAPI_IOCL_ROOT - root of Intel OCL installation - -if(UNIX AND NOT ANDROID) - if($ENV{VAAPI_MSDK_ROOT}) - set(VAAPI_MSDK_ROOT $ENV{VAAPI_MSDK_ROOT}) - else() - set(VAAPI_MSDK_ROOT "/opt/intel/mediasdk") - endif() - - if($ENV{VAAPI_IOCL_ROOT}) - set(VAAPI_IOCL_ROOT $ENV{VAAPI_IOCL_ROOT}) - else() - set(VAAPI_IOCL_ROOT "/opt/intel/opencl") - endif() - - find_path( - VAAPI_MSDK_INCLUDE_DIR - NAMES mfxdefs.h - PATHS ${VAAPI_MSDK_ROOT} - PATH_SUFFIXES include - DOC "Path to Intel MSDK headers") - - find_path( - VAAPI_IOCL_INCLUDE_DIR - NAMES CL/va_ext.h - PATHS ${VAAPI_IOCL_ROOT} - PATH_SUFFIXES include - DOC "Path to Intel OpenCL headers") -endif() - -if(VAAPI_MSDK_INCLUDE_DIR AND VAAPI_IOCL_INCLUDE_DIR) - set(HAVE_VAAPI TRUE) - set(VAAPI_EXTRA_LIBS "-lva" "-lva-drm") -else() - set(HAVE_VAAPI FALSE) - message(WARNING "Intel MSDK & OpenCL installation is not found.") -endif() - -mark_as_advanced(FORCE VAAPI_MSDK_INCLUDE_DIR VAAPI_IOCL_INCLUDE_DIR) diff --git a/cmake/OpenCVFindVA_INTEL.cmake b/cmake/OpenCVFindVA_INTEL.cmake new file mode 100644 index 000000000..8cb6c2594 --- /dev/null +++ b/cmake/OpenCVFindVA_INTEL.cmake @@ -0,0 +1,44 @@ +# Main variables: +# VA_INTEL_MSDK_INCLUDE_DIR and VA_INTEL_IOCL_INCLUDE_DIR to use VA_INTEL +# HAVE_VA_INTEL for conditional compilation OpenCV with/without VA_INTEL + +# VA_INTEL_MSDK_ROOT - root of Intel MSDK installation +# VA_INTEL_IOCL_ROOT - root of Intel OCL installation + +if(UNIX AND NOT ANDROID) + if($ENV{VA_INTEL_MSDK_ROOT}) + set(VA_INTEL_MSDK_ROOT $ENV{VA_INTEL_MSDK_ROOT}) + else() + set(VA_INTEL_MSDK_ROOT "/opt/intel/mediasdk") + endif() + + if($ENV{VA_INTEL_IOCL_ROOT}) + set(VA_INTEL_IOCL_ROOT $ENV{VA_INTEL_IOCL_ROOT}) + else() + set(VA_INTEL_IOCL_ROOT "/opt/intel/opencl") + endif() + + find_path( + VA_INTEL_MSDK_INCLUDE_DIR + NAMES mfxdefs.h + PATHS ${VA_INTEL_MSDK_ROOT} + PATH_SUFFIXES include + DOC "Path to Intel MSDK headers") + + find_path( + VA_INTEL_IOCL_INCLUDE_DIR + NAMES CL/va_ext.h + PATHS ${VA_INTEL_IOCL_ROOT} + PATH_SUFFIXES include + DOC "Path to Intel OpenCL headers") +endif() + +if(VA_INTEL_MSDK_INCLUDE_DIR AND VA_INTEL_IOCL_INCLUDE_DIR) + set(HAVE_VA_INTEL TRUE) + set(VA_INTEL_LIBRARIES "-lva" "-lva-drm") +else() + set(HAVE_VA_INTEL FALSE) + message(WARNING "Intel MSDK & OpenCL installation is not found.") +endif() + +mark_as_advanced(FORCE VA_INTEL_MSDK_INCLUDE_DIR VA_INTEL_IOCL_INCLUDE_DIR) diff --git a/cmake/templates/cvconfig.h.in b/cmake/templates/cvconfig.h.in index fce5748c2..608372967 100644 --- a/cmake/templates/cvconfig.h.in +++ b/cmake/templates/cvconfig.h.in @@ -189,5 +189,8 @@ /* gPhoto2 library */ #cmakedefine HAVE_GPHOTO2 -/* Intel VA-API */ -#cmakedefine HAVE_VAAPI +/* VA library (libva) */ +#cmakedefine HAVE_VA + +/* Intel VA-API/OpenCL */ +#cmakedefine HAVE_VA_INTEL diff --git a/modules/core/CMakeLists.txt b/modules/core/CMakeLists.txt index dbedc5b06..14fac578a 100644 --- a/modules/core/CMakeLists.txt +++ b/modules/core/CMakeLists.txt @@ -1,7 +1,7 @@ set(the_description "The Core Functionality") ocv_add_module(core opencv_hal - PRIVATE_REQUIRED ${ZLIB_LIBRARIES} "${OPENCL_LIBRARIES}" + PRIVATE_REQUIRED ${ZLIB_LIBRARIES} "${OPENCL_LIBRARIES}" "${VA_LIBRARIES}" OPTIONAL opencv_cudev WRAP java python) diff --git a/modules/core/include/opencv2/core/vaapi.hpp b/modules/core/include/opencv2/core/va_intel.hpp similarity index 54% rename from modules/core/include/opencv2/core/vaapi.hpp rename to modules/core/include/opencv2/core/va_intel.hpp index 19f9fe6ac..f4bb8a650 100644 --- a/modules/core/include/opencv2/core/vaapi.hpp +++ b/modules/core/include/opencv2/core/va_intel.hpp @@ -5,36 +5,36 @@ // Copyright (C) 2015, Itseez, Inc., all rights reserved. // Third party copyrights are property of their respective owners. -#ifndef __OPENCV_CORE_VAAPI_HPP__ -#define __OPENCV_CORE_VAAPI_HPP__ +#ifndef __OPENCV_CORE_VA_INTEL_HPP__ +#define __OPENCV_CORE_VA_INTEL_HPP__ #ifndef __cplusplus -# error vaapi.hpp header must be compiled as C++ +# error va_intel.hpp header must be compiled as C++ #endif #include "opencv2/core.hpp" #include "ocl.hpp" -#if defined(HAVE_VAAPI) +#if defined(HAVE_VA) # include "va/va.h" -#else // HAVE_VAAPI +#else // HAVE_VA # if !defined(_VA_H_) typedef void* VADisplay; typedef unsigned int VASurfaceID; # endif // !_VA_H_ -#endif // HAVE_VAAPI +#endif // HAVE_VA -namespace cv { namespace vaapi { +namespace cv { namespace va_intel { -/** @addtogroup core_vaapi -This section describes CL-VA (VA-API) interoperability. +/** @addtogroup core_va_intel +This section describes Intel VA-API/OpenCL (CL-VA) interoperability. -To enable CL-VA interoperability support, configure OpenCV using CMake with WITH_VAAPI=ON . Currently VA-API is +To enable CL-VA interoperability support, configure OpenCV using CMake with WITH_VA_INTEL=ON . Currently VA-API is supported on Linux only. You should also install Intel Media Server Studio (MSS) to use this feature. You may -have to specify the path(s) to MSS components for cmake in environment variables: VAAPI_MSDK_ROOT for Media SDK -(default is "/opt/intel/mediasdk"), and VAAPI_IOCL_ROOT for Intel OpenCL (default is "/opt/intel/opencl"). +have to specify the path(s) to MSS components for cmake in environment variables: VA_INTEL_MSDK_ROOT for Media SDK +(default is "/opt/intel/mediasdk"), and VA_INTEL_IOCL_ROOT for Intel OpenCL (default is "/opt/intel/opencl"). -To use VA-API interoperability you should first create VADisplay (libva), and then call initializeContextFromVA() +To use CL-VA interoperability you should first create VADisplay (libva), and then call initializeContextFromVA() function to create OpenCL context and set up interoperability. */ //! @{ @@ -46,29 +46,32 @@ using namespace cv::ocl; // TODO static functions in the Context class /** @brief Creates OpenCL context from VA. -@param display - VADisplay for which CL interop should be established. +@param display - VADisplay for which CL interop should be established. +@param tryInterop - try to set up for interoperability, if true; set up for use slow copy if false. @return Returns reference to OpenCL Context */ -CV_EXPORTS Context& initializeContextFromVA(VADisplay display); +CV_EXPORTS Context& initializeContextFromVA(VADisplay display, bool tryInterop = true); -} // namespace cv::vaapi::ocl +} // namespace cv::va_intel::ocl /** @brief Converts InputArray to VASurfaceID object. +@param display - VADisplay object. @param src - source InputArray. @param surface - destination VASurfaceID object. @param size - size of image represented by VASurfaceID object. */ -CV_EXPORTS void convertToVASurface(InputArray src, VASurfaceID surface, Size size); +CV_EXPORTS void convertToVASurface(VADisplay display, InputArray src, VASurfaceID surface, Size size); /** @brief Converts VASurfaceID object to OutputArray. +@param display - VADisplay object. @param surface - source VASurfaceID object. @param size - size of image represented by VASurfaceID object. @param dst - destination OutputArray. */ -CV_EXPORTS void convertFromVASurface(VASurfaceID surface, Size size, OutputArray dst); +CV_EXPORTS void convertFromVASurface(VADisplay display, VASurfaceID surface, Size size, OutputArray dst); //! @} -}} // namespace cv::vaapi +}} // namespace cv::va_intel -#endif /* __OPENCV_CORE_VAAPI_HPP__ */ +#endif /* __OPENCV_CORE_VA_INTEL_HPP__ */ diff --git a/modules/core/src/precomp.hpp b/modules/core/src/precomp.hpp index e20a66f69..88064c85b 100644 --- a/modules/core/src/precomp.hpp +++ b/modules/core/src/precomp.hpp @@ -50,7 +50,7 @@ #include "opencv2/core/core_c.h" #include "opencv2/core/cuda.hpp" #include "opencv2/core/opengl.hpp" -#include "opencv2/core/vaapi.hpp" +#include "opencv2/core/va_intel.hpp" #include "opencv2/core/private.hpp" #include "opencv2/core/private.cuda.hpp" diff --git a/modules/core/src/va_intel.cpp b/modules/core/src/va_intel.cpp new file mode 100644 index 000000000..9111ed77f --- /dev/null +++ b/modules/core/src/va_intel.cpp @@ -0,0 +1,517 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +// Copyright (C) 2015, Itseez, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. + +#include "precomp.hpp" + +#ifdef HAVE_VA +# include +#else // HAVE_VA +# define NO_VA_SUPPORT_ERROR CV_ErrorNoReturn(cv::Error::StsBadFunc, "OpenCV was build without VA support (libva)") +#endif // HAVE_VA + +using namespace cv; + +//////////////////////////////////////////////////////////////////////// +// CL-VA Interoperability + +#ifdef HAVE_OPENCL +# include "opencv2/core/opencl/runtime/opencl_core.hpp" +# include "opencv2/core.hpp" +# include "opencv2/core/ocl.hpp" +# include "opencl_kernels_core.hpp" +#endif // HAVE_OPENCL + +#if defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL) +# include +#endif // HAVE_VA_INTEL && HAVE_OPENCL + +namespace cv { namespace va_intel { + +#if defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL) + +static clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn clGetDeviceIDsFromVA_APIMediaAdapterINTEL = NULL; +static clCreateFromVA_APIMediaSurfaceINTEL_fn clCreateFromVA_APIMediaSurfaceINTEL = NULL; +static clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn clEnqueueAcquireVA_APIMediaSurfacesINTEL = NULL; +static clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn clEnqueueReleaseVA_APIMediaSurfacesINTEL = NULL; + +static bool contextInitialized = false; + +#endif // HAVE_VA_INTEL && HAVE_OPENCL + +namespace ocl { + +Context& initializeContextFromVA(VADisplay display, bool tryInterop) +{ + (void)display; (void)tryInterop; +#if !defined(HAVE_VA) + NO_VA_SUPPORT_ERROR; +#else // !HAVE_VA +# if (defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL)) + contextInitialized = false; + if (tryInterop) + { + cl_uint numPlatforms; + cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms"); + if (numPlatforms == 0) + CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms"); + + std::vector platforms(numPlatforms); + status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get platform Id list"); + + // For CL-VA interop, we must find platform/device with "cl_intel_va_api_media_sharing" extension. + // With standard initialization procedure, we should examine platform extension string for that. + // But in practice, the platform ext string doesn't contain it, while device ext string does. + // Follow Intel procedure (see tutorial), we should obtain device IDs by extension call. + // Note that we must obtain function pointers using specific platform ID, and can't provide pointers in advance. + // So, we iterate and select the first platform, for which we got non-NULL pointers, device, and CL context. + + int found = -1; + cl_context context = 0; + cl_device_id device = 0; + + for (int i = 0; i < (int)numPlatforms; ++i) + { + // Get extension function pointers + + clGetDeviceIDsFromVA_APIMediaAdapterINTEL = (clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn) + clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromVA_APIMediaAdapterINTEL"); + clCreateFromVA_APIMediaSurfaceINTEL = (clCreateFromVA_APIMediaSurfaceINTEL_fn) + clGetExtensionFunctionAddressForPlatform(platforms[i], "clCreateFromVA_APIMediaSurfaceINTEL"); + clEnqueueAcquireVA_APIMediaSurfacesINTEL = (clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn) + clGetExtensionFunctionAddressForPlatform(platforms[i], "clEnqueueAcquireVA_APIMediaSurfacesINTEL"); + clEnqueueReleaseVA_APIMediaSurfacesINTEL = (clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn) + clGetExtensionFunctionAddressForPlatform(platforms[i], "clEnqueueReleaseVA_APIMediaSurfacesINTEL"); + + if (((void*)clGetDeviceIDsFromVA_APIMediaAdapterINTEL == NULL) || + ((void*)clCreateFromVA_APIMediaSurfaceINTEL == NULL) || + ((void*)clEnqueueAcquireVA_APIMediaSurfacesINTEL == NULL) || + ((void*)clEnqueueReleaseVA_APIMediaSurfacesINTEL == NULL)) + { + continue; + } + + // Query device list + + cl_uint numDevices = 0; + + status = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(platforms[i], CL_VA_API_DISPLAY_INTEL, display, + CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, 0, NULL, &numDevices); + if ((status != CL_SUCCESS) || !(numDevices > 0)) + continue; + numDevices = 1; // initializeContextFromHandle() expects only 1 device + status = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(platforms[i], CL_VA_API_DISPLAY_INTEL, display, + CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, numDevices, &device, NULL); + if (status != CL_SUCCESS) + continue; + + // Creating CL-VA media sharing OpenCL context + + cl_context_properties props[] = { + CL_CONTEXT_VA_API_DISPLAY_INTEL, (cl_context_properties) display, + CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE, // no explicit sync required + 0 + }; + + context = clCreateContext(props, numDevices, &device, NULL, NULL, &status); + if (status != CL_SUCCESS) + { + clReleaseDevice(device); + } + else + { + found = i; + break; + } + } + + if (found >= 0) + { + contextInitialized = true; + Context& ctx = Context::getDefault(false); + initializeContextFromHandle(ctx, platforms[found], context, device); + return ctx; + } + } +# endif // HAVE_VA_INTEL && HAVE_OPENCL + { + Context& ctx = Context::getDefault(false); + return ctx; + } +#endif // !HAVE_VA +} + +#if defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL) +static bool ocl_convert_nv12_to_bgr(cl_mem clImageY, cl_mem clImageUV, cl_mem clBuffer, int step, int cols, int rows) +{ + ocl::Kernel k; + k.create("YUV2BGR_NV12_8u", cv::ocl::core::cvtclr_dx_oclsrc, ""); + if (k.empty()) + return false; + + k.args(clImageY, clImageUV, clBuffer, step, cols, rows); + + size_t globalsize[] = { cols, rows }; + return k.run(2, globalsize, 0, false); +} + +static bool ocl_convert_bgr_to_nv12(cl_mem clBuffer, int step, int cols, int rows, cl_mem clImageY, cl_mem clImageUV) +{ + ocl::Kernel k; + k.create("BGR2YUV_NV12_8u", cv::ocl::core::cvtclr_dx_oclsrc, ""); + if (k.empty()) + return false; + + k.args(clBuffer, step, cols, rows, clImageY, clImageUV); + + size_t globalsize[] = { cols, rows }; + return k.run(2, globalsize, 0, false); +} +#endif // HAVE_VA_INTEL && HAVE_OPENCL + +} // namespace cv::va_intel::ocl + +#if defined(HAVE_VA) +const int NCHANNELS = 3; + +static void copy_convert_nv12_to_bgr(const VAImage& image, const unsigned char* buffer, Mat& bgr) +{ + const float d1 = 16.0f; + const float d2 = 128.0f; + + static const float coeffs[5] = + { + 1.163999557f, + 2.017999649f, + -0.390999794f, + -0.812999725f, + 1.5959997177f + }; + + const size_t srcOffsetY = image.offsets[0]; + const size_t srcOffsetUV = image.offsets[1]; + + const size_t srcStepY = image.pitches[0]; + const size_t srcStepUV = image.pitches[1]; + + const size_t dstStep = bgr.step; + + const unsigned char* srcY0 = buffer + srcOffsetY; + const unsigned char* srcUV = buffer + srcOffsetUV; + + unsigned char* dst0 = bgr.data; + + for (int y = 0; y < bgr.rows; y += 2) + { + const unsigned char* srcY1 = srcY0 + srcStepY; + unsigned char *dst1 = dst0 + dstStep; + + for (int x = 0; x < bgr.cols; x += 2) + { + float Y0 = float(srcY0[x+0]); + float Y1 = float(srcY0[x+1]); + float Y2 = float(srcY1[x+0]); + float Y3 = float(srcY1[x+1]); + + float U = float(srcUV[2*(x/2)+0]) - d2; + float V = float(srcUV[2*(x/2)+1]) - d2; + + Y0 = std::max(0.0f, Y0 - d1) * coeffs[0]; + Y1 = std::max(0.0f, Y1 - d1) * coeffs[0]; + Y2 = std::max(0.0f, Y2 - d1) * coeffs[0]; + Y3 = std::max(0.0f, Y3 - d1) * coeffs[0]; + + float ruv = coeffs[4]*V; + float guv = coeffs[3]*V + coeffs[2]*U; + float buv = coeffs[1]*U; + + dst0[(x+0)*NCHANNELS+0] = saturate_cast(Y0 + buv); + dst0[(x+0)*NCHANNELS+1] = saturate_cast(Y0 + guv); + dst0[(x+0)*NCHANNELS+2] = saturate_cast(Y0 + ruv); + + dst0[(x+1)*NCHANNELS+0] = saturate_cast(Y1 + buv); + dst0[(x+1)*NCHANNELS+1] = saturate_cast(Y1 + guv); + dst0[(x+1)*NCHANNELS+2] = saturate_cast(Y1 + ruv); + + dst1[(x+0)*NCHANNELS+0] = saturate_cast(Y2 + buv); + dst1[(x+0)*NCHANNELS+1] = saturate_cast(Y2 + guv); + dst1[(x+0)*NCHANNELS+2] = saturate_cast(Y2 + ruv); + + dst1[(x+1)*NCHANNELS+0] = saturate_cast(Y3 + buv); + dst1[(x+1)*NCHANNELS+1] = saturate_cast(Y3 + guv); + dst1[(x+1)*NCHANNELS+2] = saturate_cast(Y3 + ruv); + } + + srcY0 = srcY1 + srcStepY; + srcUV += srcStepUV; + dst0 = dst1 + dstStep; + } +} + +static void copy_convert_bgr_to_nv12(const VAImage& image, const Mat& bgr, unsigned char* buffer) +{ + const float d1 = 16.0f; + const float d2 = 128.0f; + + static const float coeffs[8] = + { + 0.256999969f, 0.50399971f, 0.09799957f, -0.1479988098f, + -0.2909994125f, 0.438999176f, -0.3679990768f, -0.0709991455f + }; + + const size_t dstOffsetY = image.offsets[0]; + const size_t dstOffsetUV = image.offsets[1]; + + const size_t dstStepY = image.pitches[0]; + const size_t dstStepUV = image.pitches[1]; + + const size_t srcStep = bgr.step; + + const unsigned char* src0 = bgr.data; + + unsigned char* dstY0 = buffer + dstOffsetY; + unsigned char* dstUV = buffer + dstOffsetUV; + + for (int y = 0; y < bgr.rows; y += 2) + { + const unsigned char *src1 = src0 + srcStep; + unsigned char* dstY1 = dstY0 + dstStepY; + + for (int x = 0; x < bgr.cols; x += 2) + { + float B0 = float(src0[(x+0)*NCHANNELS+0]); + float G0 = float(src0[(x+0)*NCHANNELS+1]); + float R0 = float(src0[(x+0)*NCHANNELS+2]); + + float B1 = float(src0[(x+1)*NCHANNELS+0]); + float G1 = float(src0[(x+1)*NCHANNELS+1]); + float R1 = float(src0[(x+1)*NCHANNELS+2]); + + float B2 = float(src1[(x+0)*NCHANNELS+0]); + float G2 = float(src1[(x+0)*NCHANNELS+1]); + float R2 = float(src1[(x+0)*NCHANNELS+2]); + + float B3 = float(src1[(x+1)*NCHANNELS+0]); + float G3 = float(src1[(x+1)*NCHANNELS+1]); + float R3 = float(src1[(x+1)*NCHANNELS+2]); + + float Y0 = coeffs[0]*R0 + coeffs[1]*G0 + coeffs[2]*B0 + d1; + float Y1 = coeffs[0]*R1 + coeffs[1]*G1 + coeffs[2]*B1 + d1; + float Y2 = coeffs[0]*R2 + coeffs[1]*G2 + coeffs[2]*B2 + d1; + float Y3 = coeffs[0]*R3 + coeffs[1]*G3 + coeffs[2]*B3 + d1; + + float U = coeffs[3]*R0 + coeffs[4]*G0 + coeffs[5]*B0 + d2; + float V = coeffs[5]*R0 + coeffs[6]*G0 + coeffs[7]*B0 + d2; + + dstY0[x+0] = saturate_cast(Y0); + dstY0[x+1] = saturate_cast(Y1); + dstY1[x+0] = saturate_cast(Y2); + dstY1[x+1] = saturate_cast(Y3); + + dstUV[2*(x/2)+0] = saturate_cast(U); + dstUV[2*(x/2)+1] = saturate_cast(V); + } + + src0 = src1 + srcStep; + dstY0 = dstY1 + dstStepY; + dstUV += dstStepUV; + } +} +#endif // HAVE_VA + +void convertToVASurface(VADisplay display, InputArray src, VASurfaceID surface, Size size) +{ + (void)display; (void)src; (void)surface; (void)size; +#if !defined(HAVE_VA) + NO_VA_SUPPORT_ERROR; +#else // !HAVE_VA + const int stype = CV_8UC3; + + int srcType = src.type(); + CV_Assert(srcType == stype); + + Size srcSize = src.size(); + CV_Assert(srcSize.width == size.width && srcSize.height == size.height); + + UMat u = src.getUMat(); + + // TODO Add support for roi + CV_Assert(u.offset == 0); + CV_Assert(u.isContinuous()); + +# if (defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL)) + if (contextInitialized) + { + cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ); + + using namespace cv::ocl; + Context& ctx = Context::getDefault(); + cl_context context = (cl_context)ctx.ptr(); + + cl_int status = 0; + + cl_mem clImageY = clCreateFromVA_APIMediaSurfaceINTEL(context, CL_MEM_WRITE_ONLY, &surface, 0, &status); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromVA_APIMediaSurfaceINTEL failed (Y plane)"); + cl_mem clImageUV = clCreateFromVA_APIMediaSurfaceINTEL(context, CL_MEM_WRITE_ONLY, &surface, 1, &status); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromVA_APIMediaSurfaceINTEL failed (UV plane)"); + + cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr(); + + cl_mem images[2] = { clImageY, clImageUV }; + status = clEnqueueAcquireVA_APIMediaSurfacesINTEL(q, 2, images, 0, NULL, NULL); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireVA_APIMediaSurfacesINTEL failed"); + if (!ocl::ocl_convert_bgr_to_nv12(clBuffer, (int)u.step[0], u.cols, u.rows, clImageY, clImageUV)) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: ocl_convert_bgr_to_nv12 failed"); + clEnqueueReleaseVA_APIMediaSurfacesINTEL(q, 2, images, 0, NULL, NULL); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseVA_APIMediaSurfacesINTEL failed"); + + status = clFinish(q); // TODO Use events + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed"); + + status = clReleaseMemObject(clImageY); // TODO RAII + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (Y plane)"); + status = clReleaseMemObject(clImageUV); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (UV plane)"); + } + else +# endif // HAVE_VA_INTEL && HAVE_OPENCL + { + VAStatus status = 0; + + status = vaSyncSurface(display, surface); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaSyncSurface failed"); + + VAImage image; + status = vaDeriveImage(display, surface, &image); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaDeriveImage failed"); + + unsigned char* buffer = 0; + status = vaMapBuffer(display, image.buf, (void **)&buffer); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaMapBuffer failed"); + + CV_Assert(image.format.fourcc == VA_FOURCC_NV12); + + Mat m = u.getMat(ACCESS_READ); + copy_convert_bgr_to_nv12(image, m, buffer); + + status = vaUnmapBuffer(display, image.buf); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaUnmapBuffer failed"); + + status = vaDestroyImage(display, image.image_id); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaDestroyImage failed"); + } +#endif // !HAVE_VA +} + +void convertFromVASurface(VADisplay display, VASurfaceID surface, Size size, OutputArray dst) +{ + (void)display; (void)surface; (void)dst; (void)size; +#if !defined(HAVE_VA) + NO_VA_SUPPORT_ERROR; +#else // !HAVE_VA + const int dtype = CV_8UC3; + + // TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying! + dst.create(size, dtype); + UMat u = dst.getUMat(); + + // TODO Add support for roi + CV_Assert(u.offset == 0); + CV_Assert(u.isContinuous()); + +# if (defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL)) + if (contextInitialized) + { + cl_mem clBuffer = (cl_mem)u.handle(ACCESS_WRITE); + + using namespace cv::ocl; + Context& ctx = Context::getDefault(); + cl_context context = (cl_context)ctx.ptr(); + + cl_int status = 0; + + cl_mem clImageY = clCreateFromVA_APIMediaSurfaceINTEL(context, CL_MEM_READ_ONLY, &surface, 0, &status); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromVA_APIMediaSurfaceINTEL failed (Y plane)"); + cl_mem clImageUV = clCreateFromVA_APIMediaSurfaceINTEL(context, CL_MEM_READ_ONLY, &surface, 1, &status); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromVA_APIMediaSurfaceINTEL failed (UV plane)"); + + cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr(); + + cl_mem images[2] = { clImageY, clImageUV }; + status = clEnqueueAcquireVA_APIMediaSurfacesINTEL(q, 2, images, 0, NULL, NULL); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireVA_APIMediaSurfacesINTEL failed"); + if (!ocl::ocl_convert_nv12_to_bgr(clImageY, clImageUV, clBuffer, (int)u.step[0], u.cols, u.rows)) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: ocl_convert_nv12_to_bgr failed"); + status = clEnqueueReleaseVA_APIMediaSurfacesINTEL(q, 2, images, 0, NULL, NULL); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseVA_APIMediaSurfacesINTEL failed"); + + status = clFinish(q); // TODO Use events + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed"); + + status = clReleaseMemObject(clImageY); // TODO RAII + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (Y plane)"); + status = clReleaseMemObject(clImageUV); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (UV plane)"); + } + else +# endif // HAVE_VA_INTEL && HAVE_OPENCL + { + VAStatus status = 0; + + status = vaSyncSurface(display, surface); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaSyncSurface failed"); + + VAImage image; + status = vaDeriveImage(display, surface, &image); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaDeriveImage failed"); + + unsigned char* buffer = 0; + status = vaMapBuffer(display, image.buf, (void **)&buffer); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaMapBuffer failed"); + + CV_Assert(image.format.fourcc == VA_FOURCC_NV12); + + Mat m = u.getMat(ACCESS_WRITE); + copy_convert_nv12_to_bgr(image, buffer, m); + + status = vaUnmapBuffer(display, image.buf); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaUnmapBuffer failed"); + + status = vaDestroyImage(display, image.image_id); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaDestroyImage failed"); + } +#endif // !HAVE_VA +} + +}} // namespace cv::va_intel diff --git a/modules/core/src/vaapi.cpp b/modules/core/src/vaapi.cpp deleted file mode 100644 index 39390bbac..000000000 --- a/modules/core/src/vaapi.cpp +++ /dev/null @@ -1,302 +0,0 @@ -// This file is part of OpenCV project. -// It is subject to the license terms in the LICENSE file found in the top-level directory -// of this distribution and at http://opencv.org/license.html. - -// Copyright (C) 2015, Itseez, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. - -#include "precomp.hpp" - -#ifdef HAVE_VAAPI -#else // HAVE_VAAPI -# define NO_VAAPI_SUPPORT_ERROR CV_ErrorNoReturn(cv::Error::StsBadFunc, "OpenCV was build without VA-API support") -#endif // HAVE_VAAPI - -using namespace cv; - -//////////////////////////////////////////////////////////////////////// -// CL-VA Interoperability - -#ifdef HAVE_OPENCL -# include "opencv2/core/opencl/runtime/opencl_core.hpp" -# include "opencv2/core.hpp" -# include "opencv2/core/ocl.hpp" -# include "opencl_kernels_core.hpp" -#else // HAVE_OPENCL -# define NO_OPENCL_SUPPORT_ERROR CV_ErrorNoReturn(cv::Error::StsBadFunc, "OpenCV was build without OpenCL support") -#endif // HAVE_OPENCL - -#if defined(HAVE_VAAPI) && defined(HAVE_OPENCL) -# include -#endif // HAVE_VAAPI && HAVE_OPENCL - -namespace cv { namespace vaapi { - -#if defined(HAVE_VAAPI) && defined(HAVE_OPENCL) - -static clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn clGetDeviceIDsFromVA_APIMediaAdapterINTEL = NULL; -static clCreateFromVA_APIMediaSurfaceINTEL_fn clCreateFromVA_APIMediaSurfaceINTEL = NULL; -static clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn clEnqueueAcquireVA_APIMediaSurfacesINTEL = NULL; -static clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn clEnqueueReleaseVA_APIMediaSurfacesINTEL = NULL; - -static bool contextInitialized = false; - -#endif // HAVE_VAAPI && HAVE_OPENCL - -namespace ocl { - -Context& initializeContextFromVA(VADisplay display) -{ - (void)display; -#if !defined(HAVE_VAAPI) - NO_VAAPI_SUPPORT_ERROR; -#elif !defined(HAVE_OPENCL) - NO_OPENCL_SUPPORT_ERROR; -#else - contextInitialized = false; - - cl_uint numPlatforms; - cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms"); - if (numPlatforms == 0) - CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms"); - - std::vector platforms(numPlatforms); - status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get platform Id list"); - - // For CL-VA interop, we must find platform/device with "cl_intel_va_api_media_sharing" extension. - // With standard initialization procedure, we should examine platform extension string for that. - // But in practice, the platform ext string doesn't contain it, while device ext string does. - // Follow Intel procedure (see tutorial), we should obtain device IDs by extension call. - // Note that we must obtain function pointers using specific platform ID, and can't provide pointers in advance. - // So, we iterate and select the first platform, for which we got non-NULL pointers, device, and CL context. - - int found = -1; - cl_context context = 0; - cl_device_id device = 0; - - for (int i = 0; i < (int)numPlatforms; ++i) - { - // Get extension function pointers - - clGetDeviceIDsFromVA_APIMediaAdapterINTEL = (clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn) - clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromVA_APIMediaAdapterINTEL"); - clCreateFromVA_APIMediaSurfaceINTEL = (clCreateFromVA_APIMediaSurfaceINTEL_fn) - clGetExtensionFunctionAddressForPlatform(platforms[i], "clCreateFromVA_APIMediaSurfaceINTEL"); - clEnqueueAcquireVA_APIMediaSurfacesINTEL = (clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn) - clGetExtensionFunctionAddressForPlatform(platforms[i], "clEnqueueAcquireVA_APIMediaSurfacesINTEL"); - clEnqueueReleaseVA_APIMediaSurfacesINTEL = (clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn) - clGetExtensionFunctionAddressForPlatform(platforms[i], "clEnqueueReleaseVA_APIMediaSurfacesINTEL"); - - if (((void*)clGetDeviceIDsFromVA_APIMediaAdapterINTEL == NULL) || - ((void*)clCreateFromVA_APIMediaSurfaceINTEL == NULL) || - ((void*)clEnqueueAcquireVA_APIMediaSurfacesINTEL == NULL) || - ((void*)clEnqueueReleaseVA_APIMediaSurfacesINTEL == NULL)) - { - continue; - } - - // Query device list - - cl_uint numDevices = 0; - - status = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(platforms[i], CL_VA_API_DISPLAY_INTEL, display, - CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, 0, NULL, &numDevices); - if ((status != CL_SUCCESS) || !(numDevices > 0)) - continue; - numDevices = 1; // initializeContextFromHandle() expects only 1 device - status = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(platforms[i], CL_VA_API_DISPLAY_INTEL, display, - CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, numDevices, &device, NULL); - if (status != CL_SUCCESS) - continue; - - // Creating CL-VA media sharing OpenCL context - - cl_context_properties props[] = { - CL_CONTEXT_VA_API_DISPLAY_INTEL, (cl_context_properties) display, - CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE, // no explicit sync required - 0 - }; - - context = clCreateContext(props, numDevices, &device, NULL, NULL, &status); - if (status != CL_SUCCESS) - { - clReleaseDevice(device); - } - else - { - found = i; - break; - } - } - - if (found < 0) - CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for VA-API interop"); - - Context& ctx = Context::getDefault(false); - initializeContextFromHandle(ctx, platforms[found], context, device); - contextInitialized = true; - return ctx; -#endif -} - -#if defined(HAVE_VAAPI) && defined(HAVE_OPENCL) -static bool ocl_convert_nv12_to_bgr(cl_mem clImageY, cl_mem clImageUV, cl_mem clBuffer, int step, int cols, int rows) -{ - ocl::Kernel k; - k.create("YUV2BGR_NV12_8u", cv::ocl::core::cvtclr_dx_oclsrc, ""); - if (k.empty()) - return false; - - k.args(clImageY, clImageUV, clBuffer, step, cols, rows); - - size_t globalsize[] = { cols, rows }; - return k.run(2, globalsize, 0, false); -} - -static bool ocl_convert_bgr_to_nv12(cl_mem clBuffer, int step, int cols, int rows, cl_mem clImageY, cl_mem clImageUV) -{ - ocl::Kernel k; - k.create("BGR2YUV_NV12_8u", cv::ocl::core::cvtclr_dx_oclsrc, ""); - if (k.empty()) - return false; - - k.args(clBuffer, step, cols, rows, clImageY, clImageUV); - - size_t globalsize[] = { cols, rows }; - return k.run(2, globalsize, 0, false); -} -#endif // HAVE_VAAPI && HAVE_OPENCL - -} // namespace cv::vaapi::ocl - -void convertToVASurface(InputArray src, VASurfaceID surface, Size size) -{ - (void)src; (void)surface; (void)size; -#if !defined(HAVE_VAAPI) - NO_VAAPI_SUPPORT_ERROR; -#elif !defined(HAVE_OPENCL) - NO_OPENCL_SUPPORT_ERROR; -#else - if (!contextInitialized) - CV_Error(cv::Error::OpenCLInitError, "OpenCL: Context for VA-API interop hasn't been created"); - - const int stype = CV_8UC4; - - int srcType = src.type(); - CV_Assert(srcType == stype); - - Size srcSize = src.size(); - CV_Assert(srcSize.width == size.width && srcSize.height == size.height); - - UMat u = src.getUMat(); - - // TODO Add support for roi - CV_Assert(u.offset == 0); - CV_Assert(u.isContinuous()); - - cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ); - - using namespace cv::ocl; - Context& ctx = Context::getDefault(); - cl_context context = (cl_context)ctx.ptr(); - - cl_int status = 0; - - cl_mem clImageY = clCreateFromVA_APIMediaSurfaceINTEL(context, CL_MEM_WRITE_ONLY, &surface, 0, &status); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromVA_APIMediaSurfaceINTEL failed (Y plane)"); - cl_mem clImageUV = clCreateFromVA_APIMediaSurfaceINTEL(context, CL_MEM_WRITE_ONLY, &surface, 1, &status); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromVA_APIMediaSurfaceINTEL failed (UV plane)"); - - cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr(); - - cl_mem images[2] = { clImageY, clImageUV }; - status = clEnqueueAcquireVA_APIMediaSurfacesINTEL(q, 2, images, 0, NULL, NULL); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireVA_APIMediaSurfacesINTEL failed"); - if (!ocl::ocl_convert_bgr_to_nv12(clBuffer, (int)u.step[0], u.cols, u.rows, clImageY, clImageUV)) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: ocl_convert_bgr_to_nv12 failed"); - clEnqueueReleaseVA_APIMediaSurfacesINTEL(q, 2, images, 0, NULL, NULL); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseVA_APIMediaSurfacesINTEL failed"); - - status = clFinish(q); // TODO Use events - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed"); - - status = clReleaseMemObject(clImageY); // TODO RAII - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (Y plane)"); - status = clReleaseMemObject(clImageUV); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (UV plane)"); -#endif -} - -void convertFromVASurface(VASurfaceID surface, Size size, OutputArray dst) -{ - (void)surface; (void)dst; (void)size; -#if !defined(HAVE_VAAPI) - NO_VAAPI_SUPPORT_ERROR; -#elif !defined(HAVE_OPENCL) - NO_OPENCL_SUPPORT_ERROR; -#else - if (!contextInitialized) - CV_Error(cv::Error::OpenCLInitError, "OpenCL: Context for VA-API interop hasn't been created"); - - const int dtype = CV_8UC4; - - // TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying! - dst.create(size, dtype); - UMat u = dst.getUMat(); - - // TODO Add support for roi - CV_Assert(u.offset == 0); - CV_Assert(u.isContinuous()); - - cl_mem clBuffer = (cl_mem)u.handle(ACCESS_WRITE); - - using namespace cv::ocl; - Context& ctx = Context::getDefault(); - cl_context context = (cl_context)ctx.ptr(); - - cl_int status = 0; - - cl_mem clImageY = clCreateFromVA_APIMediaSurfaceINTEL(context, CL_MEM_READ_ONLY, &surface, 0, &status); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromVA_APIMediaSurfaceINTEL failed (Y plane)"); - cl_mem clImageUV = clCreateFromVA_APIMediaSurfaceINTEL(context, CL_MEM_READ_ONLY, &surface, 1, &status); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromVA_APIMediaSurfaceINTEL failed (UV plane)"); - - cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr(); - - cl_mem images[2] = { clImageY, clImageUV }; - status = clEnqueueAcquireVA_APIMediaSurfacesINTEL(q, 2, images, 0, NULL, NULL); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireVA_APIMediaSurfacesINTEL failed"); - if (!ocl::ocl_convert_nv12_to_bgr(clImageY, clImageUV, clBuffer, (int)u.step[0], u.cols, u.rows)) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: ocl_convert_nv12_to_bgr failed"); - status = clEnqueueReleaseVA_APIMediaSurfacesINTEL(q, 2, images, 0, NULL, NULL); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseVA_APIMediaSurfacesINTEL failed"); - - status = clFinish(q); // TODO Use events - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed"); - - status = clReleaseMemObject(clImageY); // TODO RAII - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (Y plane)"); - status = clReleaseMemObject(clImageUV); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (UV plane)"); -#endif -} - -}} // namespace cv::vaapi diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 7c45bece7..216b21eda 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -22,8 +22,8 @@ if((NOT ANDROID) AND HAVE_OPENGL) add_subdirectory(opengl) endif() -if(UNIX AND NOT ANDROID AND HAVE_VAAPI) - add_subdirectory(vaapi) +if(UNIX AND NOT ANDROID AND HAVE_VA_INTEL) + add_subdirectory(va_intel) endif() if(ANDROID AND BUILD_ANDROID_EXAMPLES) diff --git a/samples/vaapi/CMakeLists.txt b/samples/va_intel/CMakeLists.txt similarity index 68% rename from samples/vaapi/CMakeLists.txt rename to samples/va_intel/CMakeLists.txt index 4c03a316a..13d701d41 100644 --- a/samples/vaapi/CMakeLists.txt +++ b/samples/va_intel/CMakeLists.txt @@ -1,23 +1,23 @@ -SET(OPENCV_VAAPI_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_imgcodecs opencv_videoio opencv_highgui) +SET(OPENCV_VA_INTEL_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_imgcodecs opencv_videoio opencv_highgui) -ocv_check_dependencies(${OPENCV_VAAPI_SAMPLES_REQUIRED_DEPS}) +ocv_check_dependencies(${OPENCV_VA_INTEL_SAMPLES_REQUIRED_DEPS}) if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND) - set(project "vaapi") + set(project "va_intel") string(TOUPPER "${project}" project_upper) project("${project}_samples") - ocv_include_modules_recurse(${OPENCV_VAAPI_SAMPLES_REQUIRED_DEPS}) + ocv_include_modules_recurse(${OPENCV_VA_INTEL_SAMPLES_REQUIRED_DEPS}) # --------------------------------------------- # Define executable targets # --------------------------------------------- - MACRO(OPENCV_DEFINE_VAAPI_EXAMPLE name srcs) + MACRO(OPENCV_DEFINE_VA_INTEL_EXAMPLE name srcs) set(the_target "example_${project}_${name}") add_executable(${the_target} ${srcs}) - ocv_target_link_libraries(${the_target} ${OPENCV_LINKER_LIBS} ${OPENCV_VAAPI_SAMPLES_REQUIRED_DEPS} ${VAAPI_EXTRA_LIBS}) + ocv_target_link_libraries(${the_target} ${OPENCV_LINKER_LIBS} ${OPENCV_VA_INTEL_SAMPLES_REQUIRED_DEPS} ${VA_INTEL_LIBRARIES}) set_target_properties(${the_target} PROPERTIES OUTPUT_NAME "${project}-example-${name}" @@ -33,6 +33,6 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND) foreach(sample_filename ${all_samples}) get_filename_component(sample ${sample_filename} NAME_WE) file(GLOB sample_srcs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${sample}.*) - OPENCV_DEFINE_VAAPI_EXAMPLE(${sample} ${sample_srcs}) + OPENCV_DEFINE_VA_INTEL_EXAMPLE(${sample} ${sample_srcs}) endforeach() endif() diff --git a/samples/vaapi/display.cpp.inc b/samples/va_intel/display.cpp.inc similarity index 90% rename from samples/vaapi/display.cpp.inc rename to samples/va_intel/display.cpp.inc index f192f0dd5..ccf4aac5a 100644 --- a/samples/vaapi/display.cpp.inc +++ b/samples/va_intel/display.cpp.inc @@ -10,9 +10,9 @@ #include #include -#define VAAPI_PCI_DIR "/sys/bus/pci/devices" -#define VAAPI_DRI_DIR "/dev/dri/" -#define VAAPI_PCI_DISPLAY_CONTROLLER_CLASS 0x03 +#define VA_INTEL_PCI_DIR "/sys/bus/pci/devices" +#define VA_INTEL_DRI_DIR "/dev/dri/" +#define VA_INTEL_PCI_DISPLAY_CONTROLLER_CLASS 0x03 namespace va { @@ -70,7 +70,7 @@ static unsigned readId(const char* devName, const char* idName) long int id = 0; char fileName[256]; - snprintf(fileName, sizeof(fileName), "%s/%s/%s", VAAPI_PCI_DIR, devName, idName); + snprintf(fileName, sizeof(fileName), "%s/%s/%s", VA_INTEL_PCI_DIR, devName, idName); FILE* file = fopen(fileName, "r"); if (file) @@ -88,14 +88,14 @@ static int findAdapter(unsigned desiredVendorId) int adapterIndex = -1; int numAdapters = 0; - Directory dir(VAAPI_PCI_DIR); + Directory dir(VA_INTEL_PCI_DIR); for (int i = 0; i < dir.count(); ++i) { const char* name = dir[i]->d_name; unsigned classId = readId(name, "class"); - if ((classId >> 16) == VAAPI_PCI_DISPLAY_CONTROLLER_CLASS) + if ((classId >> 16) == VA_INTEL_PCI_DISPLAY_CONTROLLER_CLASS) { unsigned vendorId = readId(name, "vendor"); if (vendorId == desiredVendorId) @@ -122,9 +122,9 @@ public: numbers[1] = adapterIndex; for (int i = 0; i < NUM_NODES; ++i) { - int sz = sizeof(VAAPI_DRI_DIR) + strlen(names[i]) + 3; + int sz = sizeof(VA_INTEL_DRI_DIR) + strlen(names[i]) + 3; paths[i] = new char [sz]; - snprintf(paths[i], sz, "%s%s%d", VAAPI_DRI_DIR, names[i], numbers[i]); + snprintf(paths[i], sz, "%s%s%d", VA_INTEL_DRI_DIR, names[i], numbers[i]); } } ~NodeInfo() diff --git a/samples/vaapi/vaapi_interop.cpp b/samples/va_intel/va_intel_interop.cpp similarity index 85% rename from samples/vaapi/vaapi_interop.cpp rename to samples/va_intel/va_intel_interop.cpp index a0d3ece96..c41806222 100644 --- a/samples/vaapi/vaapi_interop.cpp +++ b/samples/va_intel/va_intel_interop.cpp @@ -24,6 +24,8 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include + #include #include #include @@ -39,7 +41,7 @@ #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/core/vaapi.hpp" +#include "opencv2/core/va_intel.hpp" #define CHECK_VASTATUS(va_status,func) \ if (va_status != VA_STATUS_SUCCESS) { \ @@ -129,7 +131,55 @@ static VASliceParameterBufferMPEG2 slice_param={ #define CLIP_WIDTH 16 #define CLIP_HEIGHT 16 -static void dumpSurface(VADisplay display, VASurfaceID surface_id, const char* fileName) +class Timer +{ +public: + enum UNITS + { + USEC = 0, + MSEC, + SEC + }; + + Timer() : m_t0(0), m_diff(0) + { + m_tick_frequency = (float)cv::getTickFrequency(); + + m_unit_mul[USEC] = 1000000; + m_unit_mul[MSEC] = 1000; + m_unit_mul[SEC] = 1; + } + + void clear() + { + m_t0 = m_diff = 0; + } + + void start() + { + m_t0 = cv::getTickCount(); + } + + void stop() + { + m_diff = cv::getTickCount() - m_t0; + } + + float time(UNITS u = MSEC) + { + float sec = m_diff / m_tick_frequency; + + return sec * m_unit_mul[u]; + } + +public: + float m_tick_frequency; + int64 m_t0; + int64 m_diff; + int m_unit_mul[3]; +}; + +static void dumpSurface(VADisplay display, VASurfaceID surface_id, const char* fileName, bool doInterop) { VAStatus va_status; @@ -153,7 +203,8 @@ static void dumpSurface(VADisplay display, VASurfaceID surface_id, const char* f printf("image.pitches[0..2] = 0x%08x 0x%08x 0x%08x\n", image.pitches[0], image.pitches[1], image.pitches[2]); printf("image.offsets[0..2] = 0x%08x 0x%08x 0x%08x\n", image.offsets[0], image.offsets[1], image.offsets[2]); */ - FILE* out = fopen(fileName, "wb"); + std::string fn = std::string(fileName) + std::string(doInterop ? ".gpu" : ".cpu"); + FILE* out = fopen(fn.c_str(), "wb"); if (!out) { perror(fileName); @@ -169,10 +220,8 @@ static void dumpSurface(VADisplay display, VASurfaceID surface_id, const char* f CHECK_VASTATUS(va_status, "vaDestroyImage"); } -int main(int argc,char **argv) +static float run(const char* fn1, const char* fn2, bool doInterop) { - (void)argc; (void)argv; - VAEntrypoint entrypoints[5]; int num_entrypoints,vld_entrypoint; VAConfigAttrib attrib; @@ -181,24 +230,10 @@ int main(int argc,char **argv) VAContextID context_id; VABufferID pic_param_buf,iqmatrix_buf,slice_param_buf,slice_data_buf; VAStatus va_status; + Timer t; - if (argc < 3) - { - fprintf(stderr, - "Usage: vaapi_interop file1 file2\n\n" - "where: file1 is to be created, contains original surface data (NV12)\n" - " file2 is to be created, contains processed surface data (NV12)\n"); - exit(0); - } - - if (!va::openDisplay()) - { - fprintf(stderr, "Failed to open VA display for CL-VA interoperability\n"); - exit(1); - } - fprintf(stderr, "VA display opened successfully\n"); - - cv::vaapi::ocl::initializeContextFromVA(va::display); + fprintf(stderr, "Run on %s\n", doInterop ? "GPU" : "CPU"); + cv::va_intel::ocl::initializeContextFromVA(va::display, doInterop); va_status = vaQueryConfigEntrypoints(va::display, VAProfileMPEG2Main, entrypoints, &num_entrypoints); @@ -294,22 +329,50 @@ int main(int argc,char **argv) va_status = vaSyncSurface(va::display, surface_id); CHECK_VASTATUS(va_status, "vaSyncSurface"); - dumpSurface(va::display, surface_id, argv[1]); + dumpSurface(va::display, surface_id, fn1, doInterop); cv::Size size(CLIP_WIDTH,CLIP_HEIGHT); cv::UMat u; - cv::vaapi::convertFromVASurface(surface_id, size, u); + t.start(); + cv::va_intel::convertFromVASurface(va::display, surface_id, size, u); cv::blur(u, u, cv::Size(7, 7), cv::Point(-3, -3)); - cv::vaapi::convertToVASurface(u, surface_id, size); + cv::va_intel::convertToVASurface(va::display, u, surface_id, size); + t.stop(); - dumpSurface(va::display, surface_id, argv[2]); + dumpSurface(va::display, surface_id, fn2, doInterop); vaDestroySurfaces(va::display,&surface_id,1); vaDestroyConfig(va::display,config_id); vaDestroyContext(va::display,context_id); - vaTerminate(va::display); + return t.time(Timer::MSEC); +} + +int main(int argc,char **argv) +{ + if (argc < 3) + { + fprintf(stderr, + "Usage: va_intel_interop file1 file2\n\n" + "where: file1 is to be created, contains original surface data (NV12)\n" + " file2 is to be created, contains processed surface data (NV12)\n"); + exit(0); + } + + if (!va::openDisplay()) + { + fprintf(stderr, "Failed to open VA display for CL-VA interoperability\n"); + exit(1); + } + fprintf(stderr, "VA display opened successfully\n"); + + float gpuTime = run(argv[1], argv[2], true); + float cpuTime = run(argv[1], argv[2], false); + + fprintf(stderr, "GPU processing time, msec: %7.3f\n", gpuTime); + fprintf(stderr, "CPU processing time, msec: %7.3f\n", cpuTime); + va::closeDisplay(); return 0; } From e15dabf1db1ed31221f75f1bf14f364f7e191232 Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Thu, 27 Aug 2015 12:17:23 +0300 Subject: [PATCH 005/156] documentation patch --- modules/highgui/include/opencv2/highgui.hpp | 408 +++++++++++--------- 1 file changed, 219 insertions(+), 189 deletions(-) diff --git a/modules/highgui/include/opencv2/highgui.hpp b/modules/highgui/include/opencv2/highgui.hpp index 54dbe7c91..006059566 100644 --- a/modules/highgui/include/opencv2/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui.hpp @@ -82,42 +82,44 @@ It provides easy interface to: See below the example used to generate the figure: @code int main(int argc, char *argv[]) + { + int value = 50; int value2 = 0; - cvNamedWindow("main1",CV_WINDOW_NORMAL); - cvNamedWindow("main2",CV_WINDOW_AUTOSIZE | CV_GUI_NORMAL); - cvCreateTrackbar( "track1", "main1", &value, 255, NULL);//OK tested - char* nameb1 = "button1"; - char* nameb2 = "button2"; - cvCreateButton(nameb1,callbackButton,nameb1,CV_CHECKBOX,1); + namedWindow("main1",WINDOW_NORMAL); + namedWindow("main2",WINDOW_AUTOSIZE | CV_GUI_NORMAL); + createTrackbar( "track1", "main1", &value, 255, NULL); - cvCreateButton(nameb2,callbackButton,nameb2,CV_CHECKBOX,0); - cvCreateTrackbar( "track2", NULL, &value2, 255, NULL); - cvCreateButton("button5",callbackButton1,NULL,CV_RADIOBOX,0); - cvCreateButton("button6",callbackButton2,NULL,CV_RADIOBOX,1); + String nameb1 = "button1"; + String nameb2 = "button2"; - cvSetMouseCallback( "main2",on_mouse,NULL ); + createButton(nameb1,callbackButton,&nameb1,QT_CHECKBOX,1); + createButton(nameb2,callbackButton,NULL,QT_CHECKBOX,0); + createTrackbar( "track2", NULL, &value2, 255, NULL); + createButton("button5",callbackButton1,NULL,QT_RADIOBOX,0); + createButton("button6",callbackButton2,NULL,QT_RADIOBOX,1); - IplImage* img1 = cvLoadImage("files/flower.jpg"); - IplImage* img2 = cvCreateImage(cvGetSize(img1),8,3); - CvCapture* video = cvCaptureFromFile("files/hockey.avi"); - IplImage* img3 = cvCreateImage(cvGetSize(cvQueryFrame(video)),8,3); + setMouseCallback( "main2",on_mouse,NULL ); - while(cvWaitKey(33) != 27) + Mat img1 = imread("files/flower.jpg"); + VideoCapture video; + video.open("files/hockey.avi"); + + Mat img2,img3; + + while( waitKey(33) != 27 ) { - cvAddS(img1,cvScalarAll(value),img2); - cvAddS(cvQueryFrame(video),cvScalarAll(value2),img3); - cvShowImage("main1",img2); - cvShowImage("main2",img3); + img1.convertTo(img2,-1,1,value); + video >> img3; + + imshow("main1",img2); + imshow("main2",img3); } - cvDestroyAllWindows(); - cvReleaseImage(&img1); - cvReleaseImage(&img2); - cvReleaseImage(&img3); - cvReleaseCapture(&video); + destroyAllWindows(); + return 0; } @endcode @@ -140,7 +142,7 @@ It provides easy interface to: cv::Mat image = cv::imread("Assets/sample.jpg"); cv::Mat converted = cv::Mat(image.rows, image.cols, CV_8UC4); - cvtColor(image, converted, CV_BGR2BGRA); + cv::cvtColor(image, converted, COLOR_BGR2BGRA); cv::imshow(windowName, converted); // this will create window if it hasn't been created before int state = 42; @@ -174,79 +176,100 @@ namespace cv //! Flags for cv::namedWindow enum WindowFlags { - WINDOW_NORMAL = 0x00000000, //!< the user can resize the window (no constraint) / also use to switch a fullscreen window to a normal size - WINDOW_AUTOSIZE = 0x00000001, //!< the user cannot resize the window, the size is constrainted by the image displayed - WINDOW_OPENGL = 0x00001000, //!< window with opengl support + WINDOW_NORMAL = 0x00000000, //!< the user can resize the window (no constraint) / also use to switch a fullscreen window to a normal size. + WINDOW_AUTOSIZE = 0x00000001, //!< the user cannot resize the window, the size is constrainted by the image displayed. + WINDOW_OPENGL = 0x00001000, //!< window with opengl support. - WINDOW_FULLSCREEN = 1, //!< change the window to fullscreen - WINDOW_FREERATIO = 0x00000100, //!< the image expends as much as it can (no ratio constraint) - WINDOW_KEEPRATIO = 0x00000000 //!< the ratio of the image is respected + WINDOW_FULLSCREEN = 1, //!< change the window to fullscreen. + WINDOW_FREERATIO = 0x00000100, //!< the image expends as much as it can (no ratio constraint). + WINDOW_KEEPRATIO = 0x00000000 //!< the ratio of the image is respected. }; //! Flags for cv::setWindowProperty / cv::getWindowProperty enum WindowPropertyFlags { - WND_PROP_FULLSCREEN = 0, //!< fullscreen property (can be WINDOW_NORMAL or WINDOW_FULLSCREEN) - WND_PROP_AUTOSIZE = 1, //!< autosize property (can be WINDOW_NORMAL or WINDOW_AUTOSIZE) - WND_PROP_ASPECT_RATIO = 2, //!< window's aspect ration (can be set to WINDOW_FREERATIO or WINDOW_KEEPRATIO); - WND_PROP_OPENGL = 3 //!< opengl support + WND_PROP_FULLSCREEN = 0, //!< fullscreen property (can be WINDOW_NORMAL or WINDOW_FULLSCREEN). + WND_PROP_AUTOSIZE = 1, //!< autosize property (can be WINDOW_NORMAL or WINDOW_AUTOSIZE). + WND_PROP_ASPECT_RATIO = 2, //!< window's aspect ration (can be set to WINDOW_FREERATIO or WINDOW_KEEPRATIO). + WND_PROP_OPENGL = 3 //!< opengl support. }; -enum { EVENT_MOUSEMOVE = 0, - EVENT_LBUTTONDOWN = 1, - EVENT_RBUTTONDOWN = 2, - EVENT_MBUTTONDOWN = 3, - EVENT_LBUTTONUP = 4, - EVENT_RBUTTONUP = 5, - EVENT_MBUTTONUP = 6, - EVENT_LBUTTONDBLCLK = 7, - EVENT_RBUTTONDBLCLK = 8, - EVENT_MBUTTONDBLCLK = 9, - EVENT_MOUSEWHEEL = 10, - EVENT_MOUSEHWHEEL = 11 +//! Mouse Events see cv::MouseCallback +enum MouseEventTypes { + EVENT_MOUSEMOVE = 0, //!< indicates that the mouse pointer has moved over the window. + EVENT_LBUTTONDOWN = 1, //!< indicates that the left mouse button is pressed. + EVENT_RBUTTONDOWN = 2, //!< indicates that the right mouse button is pressed. + EVENT_MBUTTONDOWN = 3, //!< indicates that the middle mouse button is pressed. + EVENT_LBUTTONUP = 4, //!< indicates that left mouse button is released. + EVENT_RBUTTONUP = 5, //!< indicates that right mouse button is released. + EVENT_MBUTTONUP = 6, //!< indicates that middle mouse button is released. + EVENT_LBUTTONDBLCLK = 7, //!< indicates that left mouse button is double clicked. + EVENT_RBUTTONDBLCLK = 8, //!< indicates that right mouse button is double clicked. + EVENT_MBUTTONDBLCLK = 9, //!< indicates that middle mouse button is double clicked. + EVENT_MOUSEWHEEL = 10,//!< positive and negative values mean forward and backward scrolling, respectively. + EVENT_MOUSEHWHEEL = 11 //!< positive and negative values mean right and left scrolling, respectively. }; -enum { EVENT_FLAG_LBUTTON = 1, - EVENT_FLAG_RBUTTON = 2, - EVENT_FLAG_MBUTTON = 4, - EVENT_FLAG_CTRLKEY = 8, - EVENT_FLAG_SHIFTKEY = 16, - EVENT_FLAG_ALTKEY = 32 +//! Mouse Event Flags see cv::MouseCallback +enum MouseEventFlags { + EVENT_FLAG_LBUTTON = 1, //!< indicates that the left mouse button is down. + EVENT_FLAG_RBUTTON = 2, //!< indicates that the right mouse button is down. + EVENT_FLAG_MBUTTON = 4, //!< indicates that the middle mouse button is down. + EVENT_FLAG_CTRLKEY = 8, //!< indicates that CTRL Key is pressed. + EVENT_FLAG_SHIFTKEY = 16,//!< indicates that SHIFT Key is pressed. + EVENT_FLAG_ALTKEY = 32 //!< indicates that ALT Key is pressed. }; //! Qt font weight enum QtFontWeights { - QT_FONT_LIGHT = 25, //!< QFont::Light ( Weight of 25 ) - QT_FONT_NORMAL = 50, //!< QFont::Normal ( Weight of 50 ) - QT_FONT_DEMIBOLD = 63, //!< QFont::DemiBold ( Weight of 63 ) - QT_FONT_BOLD = 75, //!< QFont::Bold ( Weight of 75 ) - QT_FONT_BLACK = 87 //!< QFont::Black ( Weight of 87 ) + QT_FONT_LIGHT = 25, //!< Weight of 25 + QT_FONT_NORMAL = 50, //!< Weight of 50 + QT_FONT_DEMIBOLD = 63, //!< Weight of 63 + QT_FONT_BOLD = 75, //!< Weight of 75 + QT_FONT_BLACK = 87 //!< Weight of 87 }; //! Qt font style enum QtFontStyles { - QT_STYLE_NORMAL = 0, //!< QFont::StyleNormal - QT_STYLE_ITALIC = 1, //!< QFont::StyleItalic - QT_STYLE_OBLIQUE = 2 //!< QFont::StyleOblique + QT_STYLE_NORMAL = 0, //!< Normal font. + QT_STYLE_ITALIC = 1, //!< Italic font. + QT_STYLE_OBLIQUE = 2 //!< Oblique font. }; //! Qt "button" type enum QtButtonTypes { - QT_PUSH_BUTTON = 0, //!< Push button - QT_CHECKBOX = 1, //!< Checkbox button - QT_RADIOBOX = 2 //!< Radiobox button + QT_PUSH_BUTTON = 0, //!< Push button. + QT_CHECKBOX = 1, //!< Checkbox button. + QT_RADIOBOX = 2 //!< Radiobox button. }; - +/** @brief Callback function for mouse events. see cv::setMouseCallback +@param event one of the cv::MouseEventTypes constants. +@param x The x-coordinate of the mouse event. +@param y The y-coordinate of the mouse event. +@param flags one of the cv::MouseEventFlags constants. +@param userdata The optional parameter. + */ typedef void (*MouseCallback)(int event, int x, int y, int flags, void* userdata); + +/** @brief Callback function for Trackbar see cv::createTrackbar +@param pos current position of the specified trackbar. +@param userdata The optional parameter. + */ typedef void (*TrackbarCallback)(int pos, void* userdata); + +/** @brief Callback function defined to be called every frame. See cv::setOpenGlDrawCallback +@param userdata The optional parameter. + */ typedef void (*OpenGlDrawCallback)(void* userdata); + +/** @brief Callback function for a button created by cv::createButton +@param state current state of the button. It could be -1 for a push button, 0 or 1 for a check/radio box button. +@param userdata The optional parameter. + */ typedef void (*ButtonCallback)(int state, void* userdata); /** @brief Creates a window. -@param winname Name of the window in the window caption that may be used as a window identifier. -@param flags Flags of the window. The supported flags are: (cv::WindowFlags) - The function namedWindow creates a window that can be used as a placeholder for images and trackbars. Created windows are referred to by their names. @@ -267,14 +290,17 @@ Qt backend supports additional flags: - **CV_GUI_NORMAL or CV_GUI_EXPANDED:** CV_GUI_NORMAL is the old way to draw the window without statusbar and toolbar, whereas CV_GUI_EXPANDED is a new enhanced GUI. By default, flags == WINDOW_AUTOSIZE | WINDOW_KEEPRATIO | CV_GUI_EXPANDED + +@param winname Name of the window in the window caption that may be used as a window identifier. +@param flags Flags of the window. The supported flags are: (cv::WindowFlags) */ CV_EXPORTS_W void namedWindow(const String& winname, int flags = WINDOW_AUTOSIZE); -/** @brief Destroys a window. - -@param winname Name of the window to be destroyed. +/** @brief Destroys the specified window. The function destroyWindow destroys the window with the given name. + +@param winname Name of the window to be destroyed. */ CV_EXPORTS_W void destroyWindow(const String& winname); @@ -288,8 +314,6 @@ CV_EXPORTS_W int startWindowThread(); /** @brief Waits for a pressed key. -@param delay Delay in milliseconds. 0 is the special value that means "forever". - The function waitKey waits for a key event infinitely (when \f$\texttt{delay}\leq 0\f$ ) or for delay milliseconds, when it is positive. Since the OS has a minimum time between switching threads, the function will not wait exactly delay ms, it will wait at least delay ms, depending on what else is @@ -306,16 +330,15 @@ takes care of event processing. The function only works if there is at least one HighGUI window created and the window is active. If there are several HighGUI windows, any of them can be active. + +@param delay Delay in milliseconds. 0 is the special value that means "forever". */ CV_EXPORTS_W int waitKey(int delay = 0); /** @brief Displays an image in the specified window. -@param winname Name of the window. -@param mat Image to be shown. - The function imshow displays an image in the specified window. If the window was created with the -WINDOW_AUTOSIZE flag, the image is shown with its original size, however it is still limited by the screen resolution. +cv::WINDOW_AUTOSIZE flag, the image is shown with its original size, however it is still limited by the screen resolution. Otherwise, the image is scaled to fit the window. The function may scale the image, depending on its depth: - If the image is 8-bit unsigned, it is displayed as is. @@ -324,77 +347,81 @@ Otherwise, the image is scaled to fit the window. The function may scale the ima - If the image is 32-bit floating-point, the pixel values are multiplied by 255. That is, the value range [0,1] is mapped to [0,255]. -If window was created with OpenGL support, imshow also support ogl::Buffer , ogl::Texture2D and +If window was created with OpenGL support, cv::imshow also support ogl::Buffer , ogl::Texture2D and cuda::GpuMat as input. -If the window was not created before this function, it is assumed creating a window with WINDOW_AUTOSIZE. +If the window was not created before this function, it is assumed creating a window with cv::WINDOW_AUTOSIZE. If you need to show an image that is bigger than the screen resolution, you will need to call namedWindow("", WINDOW_NORMAL) before the imshow. @note This function should be followed by cv::waitKey function which displays the image for specified -milliseconds. Otherwise, it won't display the image. For example, cv::waitKey(0) will display the window -infinitely until any keypress (it is suitable for image display). cv::waitKey(25) will display a frame +milliseconds. Otherwise, it won't display the image. For example, **waitKey(0)** will display the window +infinitely until any keypress (it is suitable for image display). **waitKey(25)** will display a frame for 25 ms, after which display will be automatically closed. (If you put it in a loop to read videos, it will display the video frame-by-frame) @note -[Windows Backend Only] Pressing Ctrl+C will copy the image to the clipboard. +[__Windows Backend Only__] Pressing Ctrl+C will copy the image to the clipboard. -[Windows Backend Only] Pressing Ctrl+S will show a dialog to save the image. +[__Windows Backend Only__] Pressing Ctrl+S will show a dialog to save the image. +@param winname Name of the window. +@param mat Image to be shown. */ CV_EXPORTS_W void imshow(const String& winname, InputArray mat); /** @brief Resizes window to the specified size -@param winname Window name -@param width The new window width -@param height The new window height - @note - The specified window size is for the image area. Toolbars are not counted. -- Only windows created without WINDOW_AUTOSIZE flag can be resized. +- Only windows created without cv::WINDOW_AUTOSIZE flag can be resized. + +@param winname Window name. +@param width The new window width. +@param height The new window height. */ CV_EXPORTS_W void resizeWindow(const String& winname, int width, int height); /** @brief Moves window to the specified position -@param winname Window name -@param x The new x-coordinate of the window -@param y The new y-coordinate of the window +@param winname Name of the window. +@param x The new x-coordinate of the window. +@param y The new y-coordinate of the window. */ CV_EXPORTS_W void moveWindow(const String& winname, int x, int y); /** @brief Changes parameters of a window dynamically. +The function setWindowProperty enables changing properties of a window. + @param winname Name of the window. @param prop_id Window property to edit. The supported operation flags are: (cv::WindowPropertyFlags) @param prop_value New value of the window property. The supported flags are: (cv::WindowFlags) - -The function setWindowProperty enables changing properties of a window. */ CV_EXPORTS_W void setWindowProperty(const String& winname, int prop_id, double prop_value); /** @brief Updates window title +@param winname Name of the window. +@param title New title. */ CV_EXPORTS_W void setWindowTitle(const String& winname, const String& title); /** @brief Provides parameters of a window. +The function getWindowProperty returns properties of a window. + @param winname Name of the window. @param prop_id Window property to retrieve. The following operation flags are available: (cv::WindowPropertyFlags) -See setWindowProperty to know the meaning of the returned values. - -The function getWindowProperty returns properties of a window. +@sa setWindowProperty */ CV_EXPORTS_W double getWindowProperty(const String& winname, int prop_id); /** @brief Sets mouse handler for the specified window -@param winname Window name +@param winname Name of the window. @param onMouse Mouse callback. See OpenCV samples, such as , on how to specify and use the callback. @@ -402,18 +429,16 @@ use the callback. */ CV_EXPORTS void setMouseCallback(const String& winname, MouseCallback onMouse, void* userdata = 0); -/** @brief Gets the mouse-wheel motion delta, when handling mouse-wheel events EVENT_MOUSEWHEEL and -EVENT_MOUSEHWHEEL. - -@param flags The mouse callback flags parameter. +/** @brief Gets the mouse-wheel motion delta, when handling mouse-wheel events cv::EVENT_MOUSEWHEEL and +cv::EVENT_MOUSEHWHEEL. For regular mice with a scroll-wheel, delta will be a multiple of 120. The value 120 corresponds to a one notch rotation of the wheel or the threshold for action to be taken and one such action should occur for each delta. Some high-precision mice with higher-resolution freely-rotating wheels may generate smaller values. -For EVENT_MOUSEWHEEL positive and negative values mean forward and backward scrolling, -respectively. For EVENT_MOUSEHWHEEL, where available, positive and negative values mean right and +For cv::EVENT_MOUSEWHEEL positive and negative values mean forward and backward scrolling, +respectively. For cv::EVENT_MOUSEHWHEEL, where available, positive and negative values mean right and left scrolling, respectively. With the C API, the macro CV_GET_WHEEL_DELTA(flags) can be used alternatively. @@ -421,11 +446,25 @@ With the C API, the macro CV_GET_WHEEL_DELTA(flags) can be used alternatively. @note Mouse-wheel events are currently supported only on Windows. + +@param flags The mouse callback flags parameter. */ CV_EXPORTS int getMouseWheelDelta(int flags); /** @brief Creates a trackbar and attaches it to the specified window. +The function createTrackbar creates a trackbar (a slider or range control) with the specified name +and range, assigns a variable value to be a position synchronized with the trackbar and specifies +the callback function onChange to be called on the trackbar position change. The created trackbar is +displayed in the specified window winname. + +@note + +[__Qt Backend Only__] winname can be empty (or NULL) if the trackbar should be attached to the +control panel. + +Clicking the label of each trackbar enables editing the trackbar values manually. + @param trackbarname Name of the created trackbar. @param winname Name of the window that will be used as a parent of the created trackbar. @param value Optional pointer to an integer variable whose value reflects the position of the @@ -437,19 +476,6 @@ position and the second parameter is the user data (see the next parameter). If the NULL pointer, no callbacks are called, but only value is updated. @param userdata User data that is passed as is to the callback. It can be used to handle trackbar events without using global variables. - -The function createTrackbar creates a trackbar (a slider or range control) with the specified name -and range, assigns a variable value to be a position synchronized with the trackbar and specifies -the callback function onChange to be called on the trackbar position change. The created trackbar is -displayed in the specified window winname. - -@note - -**[Qt Backend Only]** winname can be empty (or NULL) if the trackbar should be attached to the -control panel. - -Clicking the label of each trackbar enables editing the trackbar values manually. - */ CV_EXPORTS int createTrackbar(const String& trackbarname, const String& winname, int* value, int count, @@ -458,63 +484,62 @@ CV_EXPORTS int createTrackbar(const String& trackbarname, const String& winname, /** @brief Returns the trackbar position. -@param trackbarname Name of the trackbar. -@param winname Name of the window that is the parent of the trackbar. - The function returns the current position of the specified trackbar. @note -**[Qt Backend Only]** winname can be empty (or NULL) if the trackbar is attached to the control +[__Qt Backend Only__] winname can be empty (or NULL) if the trackbar is attached to the control panel. +@param trackbarname Name of the trackbar. +@param winname Name of the window that is the parent of the trackbar. */ CV_EXPORTS_W int getTrackbarPos(const String& trackbarname, const String& winname); /** @brief Sets the trackbar position. -@param trackbarname Name of the trackbar. -@param winname Name of the window that is the parent of trackbar. -@param pos New position. - The function sets the position of the specified trackbar in the specified window. @note -**[Qt Backend Only]** winname can be empty (or NULL) if the trackbar is attached to the control +[__Qt Backend Only__] winname can be empty (or NULL) if the trackbar is attached to the control panel. + +@param trackbarname Name of the trackbar. +@param winname Name of the window that is the parent of trackbar. +@param pos New position. */ CV_EXPORTS_W void setTrackbarPos(const String& trackbarname, const String& winname, int pos); /** @brief Sets the trackbar maximum position. -@param trackbarname Name of the trackbar. -@param winname Name of the window that is the parent of trackbar. -@param maxval New maximum position. - The function sets the maximum position of the specified trackbar in the specified window. @note -**[Qt Backend Only]** winname can be empty (or NULL) if the trackbar is attached to the control +[__Qt Backend Only__] winname can be empty (or NULL) if the trackbar is attached to the control panel. + +@param trackbarname Name of the trackbar. +@param winname Name of the window that is the parent of trackbar. +@param maxval New maximum position. */ CV_EXPORTS_W void setTrackbarMax(const String& trackbarname, const String& winname, int maxval); //! @addtogroup highgui_opengl OpenGL support //! @{ +/** @brief Displays OpenGL 2D texture in the specified window. + +@param winname Name of the window. +@param tex OpenGL 2D texture data. + */ CV_EXPORTS void imshow(const String& winname, const ogl::Texture2D& tex); /** @brief Sets a callback function to be called to draw on top of displayed image. -@param winname Name of the window. -@param onOpenGlDraw Pointer to the function to be called every frame. This function should be -prototyped as void Foo(void\*) . -@param userdata Pointer passed to the callback function. *(Optional)* - The function setOpenGlDrawCallback can be used to draw 3D data on the window. See the example of -callback function below: : +callback function below: @code void on_opengl(void* param) { @@ -545,18 +570,23 @@ callback function below: : } } @endcode + +@param winname Name of the window. +@param onOpenGlDraw Pointer to the function to be called every frame. This function should be +prototyped as void Foo(void\*) . +@param userdata Pointer passed to the callback function.(__Optional__) */ CV_EXPORTS void setOpenGlDrawCallback(const String& winname, OpenGlDrawCallback onOpenGlDraw, void* userdata = 0); /** @brief Sets the specified window as current OpenGL context. -@param winname Window name +@param winname Name of the window. */ CV_EXPORTS void setOpenGlContext(const String& winname); -/** @brief Force window to redraw its context and call draw callback ( setOpenGlDrawCallback ). +/** @brief Force window to redraw its context and call draw callback ( See cv::setOpenGlDrawCallback ). -@param winname Window name +@param winname Name of the window. */ CV_EXPORTS void updateWindow(const String& winname); @@ -564,102 +594,103 @@ CV_EXPORTS void updateWindow(const String& winname); //! @addtogroup highgui_qt //! @{ -// Only for Qt +/** @brief QtFont available only for Qt. See cv::fontQt + */ struct QtFont { - const char* nameFont; // Qt: nameFont - Scalar color; // Qt: ColorFont -> cvScalar(blue_component, green_component, red_component[, alpha_component]) - int font_face; // Qt: bool italic - const int* ascii; // font data and metrics + const char* nameFont; //!< Name of the font + Scalar color; //!< Color of the font. Scalar(blue_component, green_component, red_component[, alpha_component]) + int font_face; //!< See cv::QtFontStyles + const int* ascii; //!< font data and metrics const int* greek; const int* cyrillic; float hscale, vscale; - float shear; // slope coefficient: 0 - normal, >0 - italic - int thickness; // Qt: weight - float dx; // horizontal interval between letters - int line_type; // Qt: PointSize + float shear; //!< slope coefficient: 0 - normal, >0 - italic + int thickness; //!< See cv::QtFontWeights + float dx; //!< horizontal interval between letters + int line_type; //!< PointSize }; /** @brief Creates the font to draw a text on an image. +The function fontQt creates a cv::QtFont object. This cv::QtFont is not compatible with putText . + +A basic usage of this function is the following: : +@code + QtFont font = fontQt("Times"); + addText( img1, "Hello World !", Point(50,50), font); +@endcode + @param nameFont Name of the font. The name should match the name of a system font (such as *Times*). If the font is not found, a default one is used. @param pointSize Size of the font. If not specified, equal zero or negative, the point size of the font is set to a system-dependent default value. Generally, this is 12 points. -@param color Color of the font in BGRA where A = 255 is fully transparent. Use the macro CV _ RGB +@param color Color of the font in BGRA where A = 255 is fully transparent. Use the macro CV_RGB for simplicity. -@param weight Font weight. Available operation flags are : (cv::QtFontWeights) You can also specify a positive integer for better control. -@param style Font style. The following operation flags are available: (cv::QtFontStyles) +@param weight Font weight. Available operation flags are : cv::QtFontWeights You can also specify a positive integer for better control. +@param style Font style. Available operation flags are : cv::QtFontStyles @param spacing Spacing between characters. It can be negative or positive. - -The function fontQt creates a QtFont object. This QtFont is not compatible with putText . - -A basic usage of this function is the following: : -@code - QtFont font = fontQt(''Times''); - addText( img1, ``Hello World !'', Point(50,50), font); -@endcode */ CV_EXPORTS QtFont fontQt(const String& nameFont, int pointSize = -1, Scalar color = Scalar::all(0), int weight = QT_FONT_NORMAL, int style = QT_STYLE_NORMAL, int spacing = 0); -/** @brief Creates the font to draw a text on an image. +/** @brief Draws a text on the image. + +The function addText draws *text* on the image *img* using a specific font *font* (see example cv::fontQt +) @param img 8-bit 3-channel image where the text should be drawn. @param text Text to write on an image. @param org Point(x,y) where the text should start on an image. @param font Font to use to draw a text. - -The function addText draws *text* on an image *img* using a specific font *font* (see example cv::fontQt -) */ CV_EXPORTS void addText( const Mat& img, const String& text, Point org, const QtFont& font); /** @brief Displays a text on a window image as an overlay for a specified duration. +The function displayOverlay displays useful information/tips on top of the window for a certain +amount of time *delayms*. The function does not modify the image, displayed in the window, that is, +after the specified delay the original content of the window is restored. + @param winname Name of the window. @param text Overlay text to write on a window image. @param delayms The period (in milliseconds), during which the overlay text is displayed. If this function is called before the previous overlay text timed out, the timer is restarted and the text is updated. If this value is zero, the text never disappears. - -The function displayOverlay displays useful information/tips on top of the window for a certain -amount of time *delayms*. The function does not modify the image, displayed in the window, that is, -after the specified delay the original content of the window is restored. */ CV_EXPORTS void displayOverlay(const String& winname, const String& text, int delayms = 0); /** @brief Displays a text on the window statusbar during the specified period of time. +The function displayStatusBar displays useful information/tips on top of the window for a certain +amount of time *delayms* . This information is displayed on the window statusbar (the window must be +created with the CV_GUI_EXPANDED flags). + @param winname Name of the window. @param text Text to write on the window statusbar. @param delayms Duration (in milliseconds) to display the text. If this function is called before the previous text timed out, the timer is restarted and the text is updated. If this value is zero, the text never disappears. - -The function displayStatusBar displays useful information/tips on top of the window for a certain -amount of time *delayms* . This information is displayed on the window statusbar (the window must be -created with the CV_GUI_EXPANDED flags). */ CV_EXPORTS void displayStatusBar(const String& winname, const String& text, int delayms = 0); /** @brief Saves parameters of the specified window. -@param windowName Name of the window. - The function saveWindowParameters saves size, location, flags, trackbars value, zoom and panning -location of the window window_name . +location of the window windowName. + +@param windowName Name of the window. */ CV_EXPORTS void saveWindowParameters(const String& windowName); /** @brief Loads parameters of the specified window. -@param windowName Name of the window. - The function loadWindowParameters loads size, location, flags, trackbars value, zoom and panning -location of the window window_name . +location of the window windowName. + +@param windowName Name of the window. */ CV_EXPORTS void loadWindowParameters(const String& windowName); @@ -669,21 +700,11 @@ CV_EXPORTS void stopLoop(); /** @brief Attaches a button to the control panel. -@param bar_name - Name of the button. -@param on_change Pointer to the function to be called every time the button changes its state. -This function should be prototyped as void Foo(int state,\*void); . *state* is the current state -of the button. It could be -1 for a push button, 0 or 1 for a check/radio box button. -@param userdata Pointer passed to the callback function. -@param type Optional type of the button. Available types are: (cv::QtButtonTypes) -@param initial_button_state Default state of the button. Use for checkbox and radiobox. Its -value could be 0 or 1. *(Optional)* - The function createButton attaches a button to the control panel. Each button is added to a buttonbar to the right of the last button. A new buttonbar is created if nothing was attached to the control panel before, or if the last element attached to the control panel was a trackbar. -See below various examples of the createButton function call: : +See below various examples of the cv::createButton function call: : @code createButton(NULL,callbackButton);//create a push button "button 0", that will call callbackButton. createButton("button2",callbackButton,NULL,QT_CHECKBOX,0); @@ -691,6 +712,15 @@ See below various examples of the createButton function call: : createButton("button5",callbackButton1,NULL,QT_RADIOBOX); createButton("button6",callbackButton2,NULL,QT_PUSH_BUTTON,1); @endcode + +@param bar_name Name of the button. +@param on_change Pointer to the function to be called every time the button changes its state. +This function should be prototyped as void Foo(int state,\*void); . *state* is the current state +of the button. It could be -1 for a push button, 0 or 1 for a check/radio box button. +@param userdata Pointer passed to the callback function. +@param type Optional type of the button. Available types are: (cv::QtButtonTypes) +@param initial_button_state Default state of the button. Use for checkbox and radiobox. Its +value could be 0 or 1. (__Optional__) */ CV_EXPORTS int createButton( const String& bar_name, ButtonCallback on_change, void* userdata = 0, int type = QT_PUSH_BUTTON, From 949410b347d2fa471c815a8676a1e9e0c0e53780 Mon Sep 17 00:00:00 2001 From: Alexey Ershov Date: Mon, 7 Sep 2015 21:11:05 +0300 Subject: [PATCH 006/156] separated UMat & Mat usage in interop/copy paths --- modules/core/src/va_intel.cpp | 37 +++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/modules/core/src/va_intel.cpp b/modules/core/src/va_intel.cpp index 9111ed77f..fe063a96e 100644 --- a/modules/core/src/va_intel.cpp +++ b/modules/core/src/va_intel.cpp @@ -340,15 +340,15 @@ void convertToVASurface(VADisplay display, InputArray src, VASurfaceID surface, Size srcSize = src.size(); CV_Assert(srcSize.width == size.width && srcSize.height == size.height); - UMat u = src.getUMat(); - - // TODO Add support for roi - CV_Assert(u.offset == 0); - CV_Assert(u.isContinuous()); - # if (defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL)) if (contextInitialized) { + UMat u = src.getUMat(); + + // TODO Add support for roi + CV_Assert(u.offset == 0); + CV_Assert(u.isContinuous()); + cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ); using namespace cv::ocl; @@ -390,6 +390,12 @@ void convertToVASurface(VADisplay display, InputArray src, VASurfaceID surface, else # endif // HAVE_VA_INTEL && HAVE_OPENCL { + Mat m = src.getMat(ACCESS_READ); + + // TODO Add support for roi + CV_Assert(m.data == m.datastart); + CV_Assert(m.isContinuous()); + VAStatus status = 0; status = vaSyncSurface(display, surface); @@ -408,7 +414,6 @@ void convertToVASurface(VADisplay display, InputArray src, VASurfaceID surface, CV_Assert(image.format.fourcc == VA_FOURCC_NV12); - Mat m = u.getMat(ACCESS_READ); copy_convert_bgr_to_nv12(image, m, buffer); status = vaUnmapBuffer(display, image.buf); @@ -432,15 +437,16 @@ void convertFromVASurface(VADisplay display, VASurfaceID surface, Size size, Out // TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying! dst.create(size, dtype); - UMat u = dst.getUMat(); - - // TODO Add support for roi - CV_Assert(u.offset == 0); - CV_Assert(u.isContinuous()); # if (defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL)) if (contextInitialized) { + UMat u = dst.getUMat(); + + // TODO Add support for roi + CV_Assert(u.offset == 0); + CV_Assert(u.isContinuous()); + cl_mem clBuffer = (cl_mem)u.handle(ACCESS_WRITE); using namespace cv::ocl; @@ -482,6 +488,12 @@ void convertFromVASurface(VADisplay display, VASurfaceID surface, Size size, Out else # endif // HAVE_VA_INTEL && HAVE_OPENCL { + Mat m = dst.getMat(ACCESS_WRITE); + + // TODO Add support for roi + CV_Assert(m.data == m.datastart); + CV_Assert(m.isContinuous()); + VAStatus status = 0; status = vaSyncSurface(display, surface); @@ -500,7 +512,6 @@ void convertFromVASurface(VADisplay display, VASurfaceID surface, Size size, Out CV_Assert(image.format.fourcc == VA_FOURCC_NV12); - Mat m = u.getMat(ACCESS_WRITE); copy_convert_nv12_to_bgr(image, buffer, m); status = vaUnmapBuffer(display, image.buf); From 5937e58a11012957cd3b05cb9e01382ff25c899c Mon Sep 17 00:00:00 2001 From: Alexey Ershov Date: Tue, 8 Sep 2015 19:29:19 +0300 Subject: [PATCH 007/156] fixed argument in call to {Input|Output}Array.getMat() --- modules/core/src/va_intel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/core/src/va_intel.cpp b/modules/core/src/va_intel.cpp index fe063a96e..76aeb41b8 100644 --- a/modules/core/src/va_intel.cpp +++ b/modules/core/src/va_intel.cpp @@ -390,7 +390,7 @@ void convertToVASurface(VADisplay display, InputArray src, VASurfaceID surface, else # endif // HAVE_VA_INTEL && HAVE_OPENCL { - Mat m = src.getMat(ACCESS_READ); + Mat m = src.getMat(); // TODO Add support for roi CV_Assert(m.data == m.datastart); @@ -488,7 +488,7 @@ void convertFromVASurface(VADisplay display, VASurfaceID surface, Size size, Out else # endif // HAVE_VA_INTEL && HAVE_OPENCL { - Mat m = dst.getMat(ACCESS_WRITE); + Mat m = dst.getMat(); // TODO Add support for roi CV_Assert(m.data == m.datastart); From e0b3751c17badfcc7bb4788b76518b5f17ffb42d Mon Sep 17 00:00:00 2001 From: Alexey Ershov Date: Tue, 8 Sep 2015 21:01:57 +0300 Subject: [PATCH 008/156] added run iteration without timing to complete internal initializations --- samples/va_intel/va_intel_interop.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/samples/va_intel/va_intel_interop.cpp b/samples/va_intel/va_intel_interop.cpp index c41806222..4c6ffb0f4 100644 --- a/samples/va_intel/va_intel_interop.cpp +++ b/samples/va_intel/va_intel_interop.cpp @@ -45,7 +45,7 @@ #define CHECK_VASTATUS(va_status,func) \ if (va_status != VA_STATUS_SUCCESS) { \ - fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \ + fprintf(stderr,"%s:%s (%d) failed(status=0x%08x),exit\n", __func__, func, __LINE__, va_status); \ exit(1); \ } @@ -334,6 +334,9 @@ static float run(const char* fn1, const char* fn2, bool doInterop) cv::Size size(CLIP_WIDTH,CLIP_HEIGHT); cv::UMat u; + cv::va_intel::convertFromVASurface(va::display, surface_id, size, u); + cv::blur(u, u, cv::Size(7, 7), cv::Point(-3, -3)); + cv::va_intel::convertToVASurface(va::display, u, surface_id, size); t.start(); cv::va_intel::convertFromVASurface(va::display, surface_id, size, u); cv::blur(u, u, cv::Size(7, 7), cv::Point(-3, -3)); From b15a9d675e70204b3df11ba9d017bf909e39b808 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 8 Sep 2015 22:42:05 +0300 Subject: [PATCH 009/156] cmake: use copy_if_different --- cmake/OpenCVDetectAndroidSDK.cmake | 4 ++-- cmake/OpenCVPCHSupport.cmake | 2 +- modules/java/CMakeLists.txt | 12 ++++++------ modules/java/android_test/CMakeLists.txt | 6 +++--- modules/java/pure_test/CMakeLists.txt | 6 +++--- modules/videoio/CMakeLists.txt | 8 ++++---- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/cmake/OpenCVDetectAndroidSDK.cmake b/cmake/OpenCVDetectAndroidSDK.cmake index 3bfb10e2d..bc9dcd042 100644 --- a/cmake/OpenCVDetectAndroidSDK.cmake +++ b/cmake/OpenCVDetectAndroidSDK.cmake @@ -240,7 +240,7 @@ macro(add_android_project target path) foreach(f ${android_proj_files}) add_custom_command( OUTPUT "${android_proj_bin_dir}/${f}" - COMMAND ${CMAKE_COMMAND} -E copy "${path}/${f}" "${android_proj_bin_dir}/${f}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${path}/${f}" "${android_proj_bin_dir}/${f}" MAIN_DEPENDENCY "${path}/${f}" COMMENT "Copying ${f}") list(APPEND android_proj_file_deps "${path}/${f}" "${android_proj_bin_dir}/${f}") @@ -353,7 +353,7 @@ macro(add_android_project target path) set(__android_project_chain ${target} CACHE INTERNAL "auxiliary variable used for Android progects chaining") # put the final .apk to the OpenCV's bin folder - add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${android_proj_bin_dir}/bin/${target}-debug.apk" "${OpenCV_BINARY_DIR}/bin/${target}.apk") + add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${android_proj_bin_dir}/bin/${target}-debug.apk" "${OpenCV_BINARY_DIR}/bin/${target}.apk") if(INSTALL_ANDROID_EXAMPLES AND "${target}" MATCHES "^example-") #apk install(FILES "${OpenCV_BINARY_DIR}/bin/${target}.apk" DESTINATION "samples" COMPONENT samples) diff --git a/cmake/OpenCVPCHSupport.cmake b/cmake/OpenCVPCHSupport.cmake index 1c03f36f9..910235eaa 100644 --- a/cmake/OpenCVPCHSupport.cmake +++ b/cmake/OpenCVPCHSupport.cmake @@ -277,7 +277,7 @@ MACRO(ADD_PRECOMPILED_HEADER _targetName _input) ADD_CUSTOM_COMMAND( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${_name}" - COMMAND ${CMAKE_COMMAND} -E copy "${_input}" "${CMAKE_CURRENT_BINARY_DIR}/${_name}" # ensure same directory! Required by gcc + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_input}" "${CMAKE_CURRENT_BINARY_DIR}/${_name}" # ensure same directory! Required by gcc DEPENDS "${_input}" ) diff --git a/modules/java/CMakeLists.txt b/modules/java/CMakeLists.txt index 3a113d5cc..17d190781 100644 --- a/modules/java/CMakeLists.txt +++ b/modules/java/CMakeLists.txt @@ -81,7 +81,7 @@ macro(copy_common_tests _src_location _dst_location _deps) foreach(f ${_files}) add_custom_command( OUTPUT "${_dst}/${f}" - COMMAND ${CMAKE_COMMAND} -E copy "${_src}/${f}" "${_dst}/${f}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_src}/${f}" "${_dst}/${f}" MAIN_DEPENDENCY "${_src}/${f}" COMMENT "Copying ${f}") list(APPEND ${_deps} "${_src}/${f}" "${_dst}/${f}") @@ -102,7 +102,7 @@ macro(copy_modules_tests _modules _dst_location _deps) foreach (f ${_files}) add_custom_command( OUTPUT "${_dst}/${_tree}/${f}" - COMMAND ${CMAKE_COMMAND} -E copy "${_src}/${f}" "${_dst}/${_tree}/${f}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_src}/${f}" "${_dst}/${_tree}/${f}" MAIN_DEPENDENCY "${_src}/${f}" COMMENT "Copying ${f}") list(APPEND ${_deps} "${_src}/${f}" "${_dst}/${_tree}/${f}") @@ -208,7 +208,7 @@ foreach(java_file ${step3_input_files}) string(REPLACE "+" "/" java_file_name "${java_file_name}") set(output_name "${OpenCV_BINARY_DIR}/src/org/opencv/${java_file_name}") add_custom_command(OUTPUT "${output_name}" - COMMAND ${CMAKE_COMMAND} -E copy "${java_file}" "${output_name}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${java_file}" "${output_name}" MAIN_DEPENDENCY "${java_file}" DEPENDS ${step1_depends} ${generated_java_sources} ${handwritten_java_sources} COMMENT "Generating src/org/opencv/${java_file_name}" @@ -239,7 +239,7 @@ if(ANDROID) foreach(jni_file ${handwritten_cpp_sources} ${handwritten_h_sources} ${generated_cpp_sources}) get_filename_component(jni_file_name "${jni_file}" NAME) add_custom_command(OUTPUT "${OpenCV_BINARY_DIR}/jni/${jni_file_name}" - COMMAND ${CMAKE_COMMAND} -E copy "${jni_file}" "${OpenCV_BINARY_DIR}/jni/${jni_file_name}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${jni_file}" "${OpenCV_BINARY_DIR}/jni/${jni_file_name}" DEPENDS "${jni_file}" ${java_hdr_deps} COMMENT "Generating jni/${jni_file_name}" ) @@ -257,9 +257,9 @@ if(ANDROID AND ANDROID_EXECUTABLE) add_custom_command(OUTPUT ${lib_target_files} "${OpenCV_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" COMMAND ${CMAKE_COMMAND} -E remove ${lib_target_files} - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" "${OpenCV_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" "${OpenCV_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" COMMAND ${ANDROID_EXECUTABLE} --silent create lib-project --path \"${OpenCV_BINARY_DIR}\" --target \"${lib_target_sdk_target}\" --name OpenCV --package org.opencv 2>\"${CMAKE_CURRENT_BINARY_DIR}/create_lib_project.log\" - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" "${OpenCV_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" "${OpenCV_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" MAIN_DEPENDENCY "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" DEPENDS ${android_step3_input_files} ${android_copied_files} COMMENT "Generating OpenCV Android library project. SDK target: ${lib_target_sdk_target}" diff --git a/modules/java/android_test/CMakeLists.txt b/modules/java/android_test/CMakeLists.txt index e19573228..f6261a7c0 100644 --- a/modules/java/android_test/CMakeLists.txt +++ b/modules/java/android_test/CMakeLists.txt @@ -21,7 +21,7 @@ file(GLOB_RECURSE test_files RELATIVE "${test_dir}" "${test_dir}/res/*" "${test_ foreach(f ${test_files} ${ANDROID_MANIFEST_FILE} ".classpath" ".project") add_custom_command( OUTPUT "${opencv_test_java_bin_dir}/${f}" - COMMAND ${CMAKE_COMMAND} -E copy "${test_dir}/${f}" "${opencv_test_java_bin_dir}/${f}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${test_dir}/${f}" "${opencv_test_java_bin_dir}/${f}" MAIN_DEPENDENCY "${test_dir}/${f}" COMMENT "Copying ${f}") list(APPEND opencv_test_java_file_deps "${test_dir}/${f}" "${opencv_test_java_bin_dir}/${f}") @@ -49,7 +49,7 @@ get_filename_component(java_name "${java_location}" NAME) # build java part add_custom_command( OUTPUT "${opencv_test_java_bin_dir}/bin/OpenCVTest-debug.apk" - COMMAND ${CMAKE_COMMAND} -E copy "${java_location}" "${opencv_test_java_bin_dir}/libs/${ANDROID_NDK_ABI_NAME}/${java_name}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${java_location}" "${opencv_test_java_bin_dir}/libs/${ANDROID_NDK_ABI_NAME}/${java_name}" COMMAND ${ANT_EXECUTABLE} -q -noinput -k debug COMMAND ${CMAKE_COMMAND} -E touch "${opencv_test_java_bin_dir}/bin/OpenCVTest-debug.apk" # needed because ant does not update the timestamp of updated apk WORKING_DIRECTORY "${opencv_test_java_bin_dir}" @@ -62,7 +62,7 @@ add_dependencies(${PROJECT_NAME} opencv_java ${__android_project_chain}) set(__android_project_chain ${PROJECT_NAME} CACHE INTERNAL "auxiliary variable used for Android progects chaining" FORCE) # put the final .apk to the OpenCV's bin folder -add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${opencv_test_java_bin_dir}/bin/OpenCVTest-debug.apk" "${OpenCV_BINARY_DIR}/bin/${PROJECT_NAME}.apk") +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${opencv_test_java_bin_dir}/bin/OpenCVTest-debug.apk" "${OpenCV_BINARY_DIR}/bin/${PROJECT_NAME}.apk") add_dependencies(opencv_tests ${PROJECT_NAME}) diff --git a/modules/java/pure_test/CMakeLists.txt b/modules/java/pure_test/CMakeLists.txt index 6c9766c7d..7d7841499 100644 --- a/modules/java/pure_test/CMakeLists.txt +++ b/modules/java/pure_test/CMakeLists.txt @@ -24,7 +24,7 @@ file(GLOB_RECURSE test_files RELATIVE "${test_dir}" "${test_dir}/src/*") file(GLOB_RECURSE test_lib_files RELATIVE "${test_dir}" "${test_dir}/lib/*.jar") foreach(f ${test_files} ${test_lib_files}) add_custom_command(OUTPUT "${opencv_test_java_bin_dir}/${f}" - COMMAND ${CMAKE_COMMAND} -E copy "${test_dir}/${f}" "${opencv_test_java_bin_dir}/${f}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${test_dir}/${f}" "${opencv_test_java_bin_dir}/${f}" DEPENDS "${test_dir}/${f}" COMMENT "Copying ${f}" ) @@ -33,13 +33,13 @@ endforeach() # Copy the OpenCV jar after it has been generated. add_custom_command(OUTPUT "${opencv_test_java_bin_dir}/bin/${JAR_NAME}" - COMMAND ${CMAKE_COMMAND} -E copy "${JAR_FILE}" "${opencv_test_java_bin_dir}/bin/${JAR_NAME}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${JAR_FILE}" "${opencv_test_java_bin_dir}/bin/${JAR_NAME}" DEPENDS "${JAR_FILE}" COMMENT "Copying the OpenCV jar" ) add_custom_command(OUTPUT "${opencv_test_java_bin_dir}/build.xml" - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/build.xml" "${opencv_test_java_bin_dir}/build.xml" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/build.xml" "${opencv_test_java_bin_dir}/build.xml" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/build.xml" COMMENT "Copying build.xml" ) diff --git a/modules/videoio/CMakeLists.txt b/modules/videoio/CMakeLists.txt index 2f5bed972..9e91a8a60 100644 --- a/modules/videoio/CMakeLists.txt +++ b/modules/videoio/CMakeLists.txt @@ -249,16 +249,16 @@ if(WIN32 AND WITH_FFMPEG) if(MSVC_IDE) add_custom_command(TARGET ${the_module} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/Release/${ffmpeg_bare_name_ver}" - COMMAND ${CMAKE_COMMAND} -E copy "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/Debug/${ffmpeg_bare_name_ver}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/Release/${ffmpeg_bare_name_ver}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/Debug/${ffmpeg_bare_name_ver}" COMMENT "Copying ${ffmpeg_path} to the output directory") elseif(MSVC AND (CMAKE_GENERATOR MATCHES "Visual")) add_custom_command(TARGET ${the_module} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}/${ffmpeg_bare_name_ver}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}/${ffmpeg_bare_name_ver}" COMMENT "Copying ${ffmpeg_path} to the output directory") else() add_custom_command(TARGET ${the_module} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/${ffmpeg_bare_name_ver}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/${ffmpeg_bare_name_ver}" COMMENT "Copying ${ffmpeg_path} to the output directory") endif() From cea2dafa0f2e130b88ff05728e30b528deb3e2ef Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Thu, 3 Sep 2015 17:18:59 +0300 Subject: [PATCH 010/156] man/unmap, preventing getMat/getUMat from temp object, fix thread-unsafe code in `UMat::getMat()` --- modules/core/include/opencv2/core/mat.hpp | 1 + modules/core/src/ocl.cpp | 58 ++++++++++++++--------- modules/core/src/umatrix.cpp | 34 ++++++++----- modules/core/test/test_umat.cpp | 28 ++++++++--- 4 files changed, 82 insertions(+), 39 deletions(-) diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index e85bf6fa5..5c5284f8d 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -496,6 +496,7 @@ struct CV_EXPORTS UMatData void* handle; void* userdata; int allocatorFlags_; + int mapcount; }; diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 1074f9b01..f6e27302f 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -4514,6 +4514,7 @@ public: CV_Assert(u->refcount >= 0); CV_Assert(u->handle != 0 && u->urefcount == 0); + CV_Assert(u->mapcount == 0); if(u->tempUMat()) { CV_Assert(u->origdata); @@ -4572,12 +4573,16 @@ public: else { cl_int retval = 0; - void* data = clEnqueueMapBuffer(q, (cl_mem)u->handle, CL_TRUE, - (CL_MAP_READ | CL_MAP_WRITE), - 0, u->size, 0, 0, 0, &retval); - CV_OclDbgAssert(retval == CL_SUCCESS); - CV_OclDbgAssert(clEnqueueUnmapMemObject(q, (cl_mem)u->handle, data, 0, 0, 0) == CL_SUCCESS); - CV_OclDbgAssert(clFinish(q) == CL_SUCCESS); + if (u->tempUMat()) + { + CV_Assert(u->mapcount == 0); + void* data = clEnqueueMapBuffer(q, (cl_mem)u->handle, CL_TRUE, + (CL_MAP_READ | CL_MAP_WRITE), + 0, u->size, 0, 0, 0, &retval); + CV_OclDbgAssert(retval == CL_SUCCESS); + CV_OclDbgAssert(clEnqueueUnmapMemObject(q, (cl_mem)u->handle, data, 0, 0, 0) == CL_SUCCESS); + CV_OclDbgAssert(clFinish(q) == CL_SUCCESS); + } } } u->markHostCopyObsolete(false); @@ -4715,11 +4720,16 @@ public: } #endif - cl_int retval = 0; - u->data = (uchar*)clEnqueueMapBuffer(q, (cl_mem)u->handle, CL_TRUE, - (CL_MAP_READ | CL_MAP_WRITE), - 0, u->size, 0, 0, 0, &retval); - if(u->data && retval == CL_SUCCESS) + cl_int retval = CL_SUCCESS; + if (!u->deviceMemMapped()) + { + CV_Assert(u->refcount == 1); + CV_Assert(u->mapcount++ == 0); + u->data = (uchar*)clEnqueueMapBuffer(q, (cl_mem)u->handle, CL_TRUE, + (CL_MAP_READ | CL_MAP_WRITE), + 0, u->size, 0, 0, 0, &retval); + } + if (u->data && retval == CL_SUCCESS) { u->markHostCopyObsolete(false); u->markDeviceMemMapped(true); @@ -4765,7 +4775,6 @@ public: if( !u->copyOnMap() && u->deviceMemMapped() ) { CV_Assert(u->data != NULL); - u->markDeviceMemMapped(false); #ifdef HAVE_OPENCL_SVM if ((u->allocatorFlags_ & svm::OPENCL_SVM_BUFFER_MASK) != 0) { @@ -4792,16 +4801,21 @@ public: return; } #endif - CV_Assert( (retval = clEnqueueUnmapMemObject(q, - (cl_mem)u->handle, u->data, 0, 0, 0)) == CL_SUCCESS ); - if (Device::getDefault().isAMD()) - { - // required for multithreaded applications (see stitching test) - CV_OclDbgAssert(clFinish(q) == CL_SUCCESS); - } - if (u->refcount == 0) + { + CV_Assert(u->mapcount-- == 1); + CV_Assert((retval = clEnqueueUnmapMemObject(q, + (cl_mem)u->handle, u->data, 0, 0, 0)) == CL_SUCCESS); + if (Device::getDefault().isAMD()) + { + // required for multithreaded applications (see stitching test) + CV_OclDbgAssert(clFinish(q) == CL_SUCCESS); + } + u->markDeviceMemMapped(false); u->data = 0; + u->markDeviceCopyObsolete(false); + u->markHostCopyObsolete(true); + } } else if( u->copyOnMap() && u->deviceCopyObsolete() ) { @@ -4811,9 +4825,9 @@ public: #endif CV_Assert( (retval = clEnqueueWriteBuffer(q, (cl_mem)u->handle, CL_TRUE, 0, u->size, alignedPtr.getAlignedPtr(), 0, 0, 0)) == CL_SUCCESS ); + u->markDeviceCopyObsolete(false); + u->markHostCopyObsolete(true); } - u->markDeviceCopyObsolete(false); - u->markHostCopyObsolete(true); } bool checkContinuous(int dims, const size_t sz[], diff --git a/modules/core/src/umatrix.cpp b/modules/core/src/umatrix.cpp index ad7efae16..b7c60726a 100644 --- a/modules/core/src/umatrix.cpp +++ b/modules/core/src/umatrix.cpp @@ -60,7 +60,7 @@ static Mutex umatLocks[UMAT_NLOCKS]; UMatData::UMatData(const MatAllocator* allocator) { prevAllocator = currAllocator = allocator; - urefcount = refcount = 0; + urefcount = refcount = mapcount = 0; data = origdata = 0; size = 0; flags = 0; @@ -73,6 +73,7 @@ UMatData::~UMatData() { prevAllocator = currAllocator = 0; urefcount = refcount = 0; + CV_Assert(mapcount == 0); data = origdata = 0; size = 0; flags = 0; @@ -221,6 +222,7 @@ UMat Mat::getUMat(int accessFlags, UMatUsageFlags usageFlags) const UMat hdr; if(!data) return hdr; + CV_Assert((!u || u->mapcount==0) && "Don't get UMat from temp-Mat!"); accessFlags |= ACCESS_RW; UMatData* temp_u = u; if(!temp_u) @@ -637,18 +639,28 @@ Mat UMat::getMat(int accessFlags) const { if(!u) return Mat(); + CV_Assert(!u->tempUMat() && "Don't get Mat from temp UMat! Use copyTo()."); // TODO Support ACCESS_READ (ACCESS_WRITE) without unnecessary data transfers accessFlags |= ACCESS_RW; - u->currAllocator->map(u, accessFlags); - CV_Assert(u->data != 0); - Mat hdr(dims, size.p, type(), u->data + offset, step.p); - hdr.flags = flags; - hdr.u = u; - hdr.datastart = u->data; - hdr.data = u->data + offset; - hdr.datalimit = hdr.dataend = u->data + u->size; - CV_XADD(&hdr.u->refcount, 1); - return hdr; + UMatDataAutoLock autolock(u); + if(CV_XADD(&u->refcount, 1) == 0) + u->currAllocator->map(u, accessFlags); + if (u->data != 0) + { + Mat hdr(dims, size.p, type(), u->data + offset, step.p); + hdr.flags = flags; + hdr.u = u; + hdr.datastart = u->data; + hdr.data = u->data + offset; + hdr.datalimit = hdr.dataend = u->data + u->size; + return hdr; + } + else + { + CV_XADD(&u->refcount, -1); + CV_Assert(u->data != 0 && "Error mapping of UMat to host memory."); + return Mat(); + } } void* UMat::handle(int accessFlags) const diff --git a/modules/core/test/test_umat.cpp b/modules/core/test/test_umat.cpp index 56a7a1817..7c1310dd0 100644 --- a/modules/core/test/test_umat.cpp +++ b/modules/core/test/test_umat.cpp @@ -243,9 +243,11 @@ TEST_P(UMatBasicTests, GetUMat) EXPECT_MAT_NEAR(ub, ua, 0); } { - Mat b; - b = a.getUMat(ACCESS_RW).getMat(ACCESS_RW); - EXPECT_MAT_NEAR(b, a, 0); + UMat u = a.getUMat(ACCESS_RW); + { + Mat b = u.getMat(ACCESS_RW); + EXPECT_MAT_NEAR(b, a, 0); + } } { Mat b; @@ -253,9 +255,11 @@ TEST_P(UMatBasicTests, GetUMat) EXPECT_MAT_NEAR(b, a, 0); } { - UMat ub; - ub = ua.getMat(ACCESS_RW).getUMat(ACCESS_RW); - EXPECT_MAT_NEAR(ub, ua, 0); + Mat m = ua.getMat(ACCESS_RW); + { + UMat ub = m.getUMat(ACCESS_RW); + EXPECT_MAT_NEAR(ub, ua, 0); + } } } @@ -1268,5 +1272,17 @@ TEST(UMat, DISABLED_Test_same_behaviour_write_and_write) ASSERT_TRUE(exceptionDetected); // data race } +TEST(UMat, mat_umat_sync) +{ + UMat u(10, 10, CV_8UC1, Scalar(1)); + { + Mat m = u.getMat(ACCESS_RW).reshape(1); + m.setTo(Scalar(255)); + } + + UMat uDiff; + compare(u, 255, uDiff, CMP_NE); + ASSERT_EQ(0, countNonZero(uDiff)); +} } } // namespace cvtest::ocl From ad70ab404cb6954aa08b4172b32fd40e23100c8d Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 8 Sep 2015 04:06:04 +0300 Subject: [PATCH 011/156] ocl: workaround for getUMat() --- modules/core/include/opencv2/core/mat.hpp | 1 + modules/core/src/matrix.cpp | 15 ++-- modules/core/src/ocl.cpp | 42 +++++----- modules/core/src/umatrix.cpp | 94 ++++++++++++++++++++--- modules/core/test/test_umat.cpp | 48 +++++++++++- modules/video/src/lkpyramid.cpp | 2 +- 6 files changed, 159 insertions(+), 43 deletions(-) diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index 5c5284f8d..3133876e4 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -497,6 +497,7 @@ struct CV_EXPORTS UMatData void* userdata; int allocatorFlags_; int mapcount; + UMatData* originalUMatData; }; diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index c0ad8c4ec..9d9dda329 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -208,17 +208,14 @@ public: if(!u) return; - CV_Assert(u->urefcount >= 0); - CV_Assert(u->refcount >= 0); - if(u->refcount == 0) + CV_Assert(u->urefcount == 0); + CV_Assert(u->refcount == 0); + if( !(u->flags & UMatData::USER_ALLOCATED) ) { - if( !(u->flags & UMatData::USER_ALLOCATED) ) - { - fastFree(u->origdata); - u->origdata = 0; - } - delete u; + fastFree(u->origdata); + u->origdata = 0; } + delete u; } }; diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index f6e27302f..1345c52e3 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -4453,8 +4453,11 @@ public: #endif { tempUMatFlags = UMatData::TEMP_UMAT; - handle = clCreateBuffer(ctx_handle, CL_MEM_USE_HOST_PTR|createFlags, - u->size, u->origdata, &retval); + if (u->origdata == cv::alignPtr(u->origdata, 4)) // There are OpenCL runtime issues for less aligned data + { + handle = clCreateBuffer(ctx_handle, CL_MEM_USE_HOST_PTR|createFlags, + u->size, u->origdata, &retval); + } if((!handle || retval < 0) && !(accessFlags & ACCESS_FAST)) { handle = clCreateBuffer(ctx_handle, CL_MEM_COPY_HOST_PTR|CL_MEM_READ_WRITE|createFlags, @@ -4510,17 +4513,17 @@ public: if(!u) return; - CV_Assert(u->urefcount >= 0); - CV_Assert(u->refcount >= 0); + CV_Assert(u->urefcount == 0); + CV_Assert(u->refcount == 0 && "UMat deallocation error: some derived Mat is still alive"); - CV_Assert(u->handle != 0 && u->urefcount == 0); + CV_Assert(u->handle != 0); CV_Assert(u->mapcount == 0); if(u->tempUMat()) { CV_Assert(u->origdata); // UMatDataAutoLock lock(u); - if( u->hostCopyObsolete() && u->refcount > 0 ) + if (u->hostCopyObsolete()) { #ifdef HAVE_OPENCL_SVM if ((u->allocatorFlags_ & svm::OPENCL_SVM_BUFFER_MASK) != 0) @@ -4579,7 +4582,12 @@ public: void* data = clEnqueueMapBuffer(q, (cl_mem)u->handle, CL_TRUE, (CL_MAP_READ | CL_MAP_WRITE), 0, u->size, 0, 0, 0, &retval); + CV_Assert(u->origdata == data); CV_OclDbgAssert(retval == CL_SUCCESS); + if (u->originalUMatData) + { + CV_Assert(u->originalUMatData->data == data); + } CV_OclDbgAssert(clEnqueueUnmapMemObject(q, (cl_mem)u->handle, data, 0, 0, 0) == CL_SUCCESS); CV_OclDbgAssert(clFinish(q) == CL_SUCCESS); } @@ -4587,6 +4595,10 @@ public: } u->markHostCopyObsolete(false); } + else + { + // nothing + } #ifdef HAVE_OPENCL_SVM if ((u->allocatorFlags_ & svm::OPENCL_SVM_BUFFER_MASK) != 0) { @@ -4612,16 +4624,12 @@ public: if(u->data && u->copyOnMap() && u->data != u->origdata) fastFree(u->data); u->data = u->origdata; - if(u->refcount == 0) - { - u->currAllocator->deallocate(u); - u = NULL; - } + u->currAllocator->deallocate(u); + u = NULL; } else { CV_Assert(u->origdata == NULL); - CV_Assert(u->refcount == 0); if(u->data && u->copyOnMap() && u->data != u->origdata) { fastFree(u->data); @@ -4670,17 +4678,13 @@ public: delete u; u = NULL; } - CV_Assert(u == NULL || u->refcount); + CV_Assert(u == NULL); } + // synchronized call (external UMatDataAutoLock, see UMat::getMat) void map(UMatData* u, int accessFlags) const { - if(!u) - return; - - CV_Assert( u->handle != 0 ); - - UMatDataAutoLock autolock(u); + CV_Assert(u && u->handle); if(accessFlags & ACCESS_WRITE) u->markDeviceCopyObsolete(true); diff --git a/modules/core/src/umatrix.cpp b/modules/core/src/umatrix.cpp index b7c60726a..7bfeff1df 100644 --- a/modules/core/src/umatrix.cpp +++ b/modules/core/src/umatrix.cpp @@ -67,6 +67,7 @@ UMatData::UMatData(const MatAllocator* allocator) handle = 0; userdata = 0; allocatorFlags_ = 0; + originalUMatData = NULL; } UMatData::~UMatData() @@ -80,6 +81,50 @@ UMatData::~UMatData() handle = 0; userdata = 0; allocatorFlags_ = 0; + if (originalUMatData) + { + UMatData* u = originalUMatData; + CV_XADD(&(u->urefcount), -1); + CV_XADD(&(u->refcount), -1); + bool showWarn = false; + if (u->refcount == 0) + { + if (u->urefcount > 0) + showWarn = true; + // simulate Mat::deallocate + if (u->mapcount != 0) + { + (u->currAllocator ? u->currAllocator : /* TODO allocator ? allocator :*/ Mat::getStdAllocator())->unmap(u); + } + else + { + // we don't do "map", so we can't do "unmap" + } + } + if (u->refcount == 0 && u->urefcount == 0) // oops, we need to free resources + { + showWarn = true; + // simulate UMat::deallocate + u->currAllocator->deallocate(u); + } +#ifndef NDEBUG + if (showWarn) + { + static int warn_message_showed = 0; + if (warn_message_showed++ < 100) + { + fflush(stdout); + fprintf(stderr, "\n! OPENCV warning: getUMat()/getMat() call chain possible problem." + "\n! Base object is dead, while nested/derived object is still alive or processed." + "\n! Please check lifetime of UMat/Mat objects!\n"); + fflush(stderr); + } + } +#else + (void)showWarn; +#endif + originalUMatData = NULL; + } } void UMatData::lock() @@ -222,20 +267,34 @@ UMat Mat::getUMat(int accessFlags, UMatUsageFlags usageFlags) const UMat hdr; if(!data) return hdr; - CV_Assert((!u || u->mapcount==0) && "Don't get UMat from temp-Mat!"); + Size wholeSize; + Point ofs; + locateROI(wholeSize, ofs); + Size sz(cols, rows); + if (ofs.x != 0 || ofs.y != 0) + { + Mat src = *this; + int dtop = ofs.y; + int dbottom = wholeSize.height - src.rows - ofs.y; + int dleft = ofs.x; + int dright = wholeSize.width - src.cols - ofs.x; + src.adjustROI(dtop, dbottom, dleft, dright); + return src.getUMat(accessFlags, usageFlags)(cv::Rect(ofs.x, ofs.y, sz.width, sz.height)); + } + CV_Assert(data == datastart); + accessFlags |= ACCESS_RW; - UMatData* temp_u = u; - if(!temp_u) + UMatData* new_u = NULL; { MatAllocator *a = allocator, *a0 = getStdAllocator(); if(!a) a = a0; - temp_u = a->allocate(dims, size.p, type(), data, step.p, accessFlags, usageFlags); + new_u = a->allocate(dims, size.p, type(), data, step.p, accessFlags, usageFlags); } bool allocated = false; try { - allocated = UMat::getStdAllocator()->allocate(temp_u, accessFlags, usageFlags); + allocated = UMat::getStdAllocator()->allocate(new_u, accessFlags, usageFlags); } catch (const cv::Exception& e) { @@ -243,14 +302,26 @@ UMat Mat::getUMat(int accessFlags, UMatUsageFlags usageFlags) const } if (!allocated) { - allocated = getStdAllocator()->allocate(temp_u, accessFlags, usageFlags); + allocated = getStdAllocator()->allocate(new_u, accessFlags, usageFlags); CV_Assert(allocated); } + if (u != NULL) + { +#ifdef HAVE_OPENCL + if (ocl::useOpenCL() && new_u->currAllocator == ocl::getOpenCLAllocator()) + { + CV_Assert(new_u->tempUMat()); + } +#endif + new_u->originalUMatData = u; + CV_XADD(&(u->refcount), 1); + CV_XADD(&(u->urefcount), 1); + } hdr.flags = flags; setSize(hdr, dims, size.p, step.p); finalizeHdr(hdr); - hdr.u = temp_u; - hdr.offset = data - datastart; + hdr.u = new_u; + hdr.offset = 0; //data - datastart; hdr.addref(); return hdr; } @@ -639,7 +710,6 @@ Mat UMat::getMat(int accessFlags) const { if(!u) return Mat(); - CV_Assert(!u->tempUMat() && "Don't get Mat from temp UMat! Use copyTo()."); // TODO Support ACCESS_READ (ACCESS_WRITE) without unnecessary data transfers accessFlags |= ACCESS_RW; UMatDataAutoLock autolock(u); @@ -668,10 +738,10 @@ void* UMat::handle(int accessFlags) const if( !u ) return 0; - // check flags: if CPU copy is newer, copy it back to GPU. - if( u->deviceCopyObsolete() ) + CV_Assert(u->refcount == 0); + CV_Assert(!u->deviceCopyObsolete() || u->copyOnMap()); + if (u->deviceCopyObsolete()) { - CV_Assert(u->refcount == 0 || u->origdata); u->currAllocator->unmap(u); } diff --git a/modules/core/test/test_umat.cpp b/modules/core/test/test_umat.cpp index 7c1310dd0..bdd38a0a1 100644 --- a/modules/core/test/test_umat.cpp +++ b/modules/core/test/test_umat.cpp @@ -263,7 +263,7 @@ TEST_P(UMatBasicTests, GetUMat) } } -INSTANTIATE_TEST_CASE_P(UMat, UMatBasicTests, Combine(testing::Values(CV_8U), testing::Values(1, 2), +INSTANTIATE_TEST_CASE_P(UMat, UMatBasicTests, Combine(testing::Values(CV_8U, CV_64F), testing::Values(1, 2), testing::Values(cv::Size(1, 1), cv::Size(1, 128), cv::Size(128, 1), cv::Size(128, 128), cv::Size(640, 480)), Bool())); //////////////////////////////////////////////////////////////// Reshape //////////////////////////////////////////////////////////////////////// @@ -1084,7 +1084,7 @@ TEST(UMat, unmap_in_class) Mat dst; m.convertTo(dst, CV_32FC1); // some additional CPU-based per-pixel processing into dst - intermediateResult = dst.getUMat(ACCESS_READ); + intermediateResult = dst.getUMat(ACCESS_READ); // this violates lifetime of base(dst) / derived (intermediateResult) objects. Use copyTo? std::cout << "data processed..." << std::endl; } // problem is here: dst::~Mat() std::cout << "leave ProcessData()" << std::endl; @@ -1285,4 +1285,48 @@ TEST(UMat, mat_umat_sync) ASSERT_EQ(0, countNonZero(uDiff)); } +TEST(UMat, testTempObjects_UMat) +{ + UMat u(10, 10, CV_8UC1, Scalar(1)); + { + UMat u2 = u.getMat(ACCESS_RW).getUMat(ACCESS_RW); + u2.setTo(Scalar(255)); + } + + UMat uDiff; + compare(u, 255, uDiff, CMP_NE); + ASSERT_EQ(0, countNonZero(uDiff)); +} + +TEST(UMat, testTempObjects_Mat) +{ + Mat m(10, 10, CV_8UC1, Scalar(1)); + { + Mat m2; + ASSERT_ANY_THROW(m2 = m.getUMat(ACCESS_RW).getMat(ACCESS_RW)); + } +} + +TEST(UMat, testWrongLifetime_UMat) +{ + UMat u(10, 10, CV_8UC1, Scalar(1)); + { + UMat u2 = u.getMat(ACCESS_RW).getUMat(ACCESS_RW); + u.release(); // base object + u2.release(); // derived object, should show warning message + } +} + +TEST(UMat, testWrongLifetime_Mat) +{ + Mat m(10, 10, CV_8UC1, Scalar(1)); + { + UMat u = m.getUMat(ACCESS_RW); + Mat m2 = u.getMat(ACCESS_RW); + m.release(); // base object + m2.release(); // map of derived object + u.release(); // derived object, should show warning message + } +} + } } // namespace cvtest::ocl diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 43dde7df7..a34e73d51 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -1009,7 +1009,7 @@ namespace cv idxArg = kernel.set(idxArg, (int)winSize.height); // int c_winSize_y idxArg = kernel.set(idxArg, (int)iters); // int c_iters idxArg = kernel.set(idxArg, (char)calcErr); //char calcErr - return kernel.run(2, globalThreads, localThreads, false); + return kernel.run(2, globalThreads, localThreads, true); // sync=true because ocl::Image2D lifetime is not handled well for temp UMat } private: inline static bool isDeviceCPU() From 933ad0e710e538e7b223a55fe14faf8832c187e6 Mon Sep 17 00:00:00 2001 From: Alexey Ershov Date: Thu, 10 Sep 2015 14:36:40 +0300 Subject: [PATCH 012/156] changed call to getDefault: false to true in fallback initialization --- modules/core/src/va_intel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/va_intel.cpp b/modules/core/src/va_intel.cpp index 76aeb41b8..32fbb2dfd 100644 --- a/modules/core/src/va_intel.cpp +++ b/modules/core/src/va_intel.cpp @@ -142,7 +142,7 @@ Context& initializeContextFromVA(VADisplay display, bool tryInterop) } # endif // HAVE_VA_INTEL && HAVE_OPENCL { - Context& ctx = Context::getDefault(false); + Context& ctx = Context::getDefault(true); return ctx; } #endif // !HAVE_VA From f533c05644559cf05556e65a0dd28a775f376580 Mon Sep 17 00:00:00 2001 From: Alexey Ershov Date: Thu, 10 Sep 2015 15:41:04 +0300 Subject: [PATCH 013/156] sample changed to execute only one mode (interop on/off) per run --- samples/va_intel/va_intel_interop.cpp | 66 +++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/samples/va_intel/va_intel_interop.cpp b/samples/va_intel/va_intel_interop.cpp index 4c6ffb0f4..1175a14aa 100644 --- a/samples/va_intel/va_intel_interop.cpp +++ b/samples/va_intel/va_intel_interop.cpp @@ -203,7 +203,7 @@ static void dumpSurface(VADisplay display, VASurfaceID surface_id, const char* f printf("image.pitches[0..2] = 0x%08x 0x%08x 0x%08x\n", image.pitches[0], image.pitches[1], image.pitches[2]); printf("image.offsets[0..2] = 0x%08x 0x%08x 0x%08x\n", image.offsets[0], image.offsets[1], image.offsets[2]); */ - std::string fn = std::string(fileName) + std::string(doInterop ? ".gpu" : ".cpu"); + std::string fn = std::string(fileName) + std::string(doInterop ? ".on" : ".off"); FILE* out = fopen(fn.c_str(), "wb"); if (!out) { @@ -232,7 +232,6 @@ static float run(const char* fn1, const char* fn2, bool doInterop) VAStatus va_status; Timer t; - fprintf(stderr, "Run on %s\n", doInterop ? "GPU" : "CPU"); cv::va_intel::ocl::initializeContextFromVA(va::display, doInterop); va_status = vaQueryConfigEntrypoints(va::display, VAProfileMPEG2Main, entrypoints, @@ -352,13 +351,58 @@ static float run(const char* fn1, const char* fn2, bool doInterop) return t.time(Timer::MSEC); } -int main(int argc,char **argv) +class CmdlineParser { - if (argc < 3) +public: + CmdlineParser(int argc, char** argv): + m_argc(argc), m_argv(argv) + {} + // true => go, false => usage/exit; extra args/unknown options are ignored for simplicity + bool run() + { + int n = 0; + m_files[0] = m_files[1] = 0; + m_interop = true; + for (int i = 1; i < m_argc; ++i) + { + const char *arg = m_argv[i]; + if (arg[0] == '-') // option + { + if (!strcmp(arg, "-f")) + m_interop = false; + } + else // parameter + { + if (n < 2) + m_files[n++] = arg; + } + } + return bool(n >= 2); + } + bool isInterop() const + { + return m_interop; + } + const char* getFile(int n) const + { + return ((n >= 0) && (n < 2)) ? m_files[n] : 0; + } +private: + int m_argc; + char** m_argv; + const char* m_files[2]; + bool m_interop; +}; + +int main(int argc, char** argv) +{ + CmdlineParser cmd(argc, argv); + if (!cmd.run()) { fprintf(stderr, - "Usage: va_intel_interop file1 file2\n\n" - "where: file1 is to be created, contains original surface data (NV12)\n" + "Usage: va_intel_interop [-f] file1 file2\n\n" + "where: -f option indicates interop is off (fallback mode); interop is on by default\n" + " file1 is to be created, contains original surface data (NV12)\n" " file2 is to be created, contains processed surface data (NV12)\n"); exit(0); } @@ -370,11 +414,13 @@ int main(int argc,char **argv) } fprintf(stderr, "VA display opened successfully\n"); - float gpuTime = run(argv[1], argv[2], true); - float cpuTime = run(argv[1], argv[2], false); + const char* file0 = cmd.getFile(0); + const char* file1 = cmd.getFile(1); + bool doInterop = cmd.isInterop(); - fprintf(stderr, "GPU processing time, msec: %7.3f\n", gpuTime); - fprintf(stderr, "CPU processing time, msec: %7.3f\n", cpuTime); + float time = run(file0, file1, doInterop); + + fprintf(stderr, "Interop %s: processing time, msec: %7.3f\n", (doInterop ? "ON " : "OFF"), time); va::closeDisplay(); return 0; From 10d8e956f4d129848337eac13c427b4c2550b273 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Thu, 10 Sep 2015 17:12:22 +0300 Subject: [PATCH 014/156] Enabled pthreads backend for mingw --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 72b1f478f..287d519b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -188,7 +188,7 @@ OCV_OPTION(WITH_QUICKTIME "Use QuickTime for Video I/O insted of QTKit" OFF OCV_OPTION(WITH_TBB "Include Intel TBB support" OFF IF (NOT IOS AND NOT WINRT) ) OCV_OPTION(WITH_OPENMP "Include OpenMP support" OFF) OCV_OPTION(WITH_CSTRIPES "Include C= support" OFF IF (WIN32 AND NOT WINRT) ) -OCV_OPTION(WITH_PTHREADS_PF "Use pthreads-based parallel_for" ON IF (NOT WIN32) ) +OCV_OPTION(WITH_PTHREADS_PF "Use pthreads-based parallel_for" ON IF (NOT WIN32 OR MINGW) ) OCV_OPTION(WITH_TIFF "Include TIFF support" ON IF (NOT IOS) ) OCV_OPTION(WITH_UNICAP "Include Unicap support (GPL)" OFF IF (UNIX AND NOT APPLE AND NOT ANDROID) ) OCV_OPTION(WITH_V4L "Include Video 4 Linux support" ON IF (UNIX AND NOT ANDROID) ) From 22bb5d1fcce7b80d08f0bbcf4970926f35cde2de Mon Sep 17 00:00:00 2001 From: Alexey Ershov Date: Thu, 10 Sep 2015 19:30:19 +0300 Subject: [PATCH 015/156] implemented sample build in fallback mode without interop --- cmake/OpenCVFindVA.cmake | 2 +- samples/CMakeLists.txt | 2 +- samples/va_intel/CMakeLists.txt | 2 +- samples/va_intel/display.cpp.inc | 79 ++++++++++++++++++++++++--- samples/va_intel/va_intel_interop.cpp | 14 +++++ 5 files changed, 88 insertions(+), 11 deletions(-) diff --git a/cmake/OpenCVFindVA.cmake b/cmake/OpenCVFindVA.cmake index 03e24a034..96df665f8 100644 --- a/cmake/OpenCVFindVA.cmake +++ b/cmake/OpenCVFindVA.cmake @@ -12,7 +12,7 @@ endif() if(VA_INCLUDE_DIR) set(HAVE_VA TRUE) - set(VA_LIBRARIES "-lva") + set(VA_LIBRARIES "-lva" "-lva-x11") else() set(HAVE_VA FALSE) message(WARNING "libva installation is not found.") diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 216b21eda..2b0e74ccd 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -22,7 +22,7 @@ if((NOT ANDROID) AND HAVE_OPENGL) add_subdirectory(opengl) endif() -if(UNIX AND NOT ANDROID AND HAVE_VA_INTEL) +if(UNIX AND NOT ANDROID AND (HAVE_VA OR HAVE_VA_INTEL)) add_subdirectory(va_intel) endif() diff --git a/samples/va_intel/CMakeLists.txt b/samples/va_intel/CMakeLists.txt index 13d701d41..ddf63edb4 100644 --- a/samples/va_intel/CMakeLists.txt +++ b/samples/va_intel/CMakeLists.txt @@ -17,7 +17,7 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND) set(the_target "example_${project}_${name}") add_executable(${the_target} ${srcs}) - ocv_target_link_libraries(${the_target} ${OPENCV_LINKER_LIBS} ${OPENCV_VA_INTEL_SAMPLES_REQUIRED_DEPS} ${VA_INTEL_LIBRARIES}) + ocv_target_link_libraries(${the_target} ${OPENCV_LINKER_LIBS} ${OPENCV_VA_INTEL_SAMPLES_REQUIRED_DEPS} ${VA_LIBRARIES} ${VA_INTEL_LIBRARIES}) set_target_properties(${the_target} PROPERTIES OUTPUT_NAME "${project}-example-${name}" diff --git a/samples/va_intel/display.cpp.inc b/samples/va_intel/display.cpp.inc index ccf4aac5a..f8aeb00e7 100644 --- a/samples/va_intel/display.cpp.inc +++ b/samples/va_intel/display.cpp.inc @@ -7,24 +7,38 @@ #include #include +#include "cvconfig.h" + #include -#include +#if defined(HAVE_VA_INTEL) +# include +#elif defined(HAVE_VA) +# include +# include +#endif //HAVE_VA_INTEL / HAVE_VA + +namespace va { + +#if defined(HAVE_VA_INTEL) || defined(HAVE_VA) + +bool openDisplay(); +void closeDisplay(); + +VADisplay display = NULL; +bool initialized = false; + +#endif //HAVE_VA_INTEL || HAVE_VA + +#if defined(HAVE_VA_INTEL) #define VA_INTEL_PCI_DIR "/sys/bus/pci/devices" #define VA_INTEL_DRI_DIR "/dev/dri/" #define VA_INTEL_PCI_DISPLAY_CONTROLLER_CLASS 0x03 -namespace va { - static unsigned readId(const char* devName, const char* idName); static int findAdapter(unsigned desiredVendorId); -bool openDisplay(); -void closeDisplay(); - int drmfd = -1; -VADisplay display = NULL; -bool initialized = false; class Directory { @@ -205,4 +219,53 @@ void closeDisplay() } } +#elif defined(HAVE_VA) + +static Display* x11Display = 0; + +bool openDisplay() +{ + if (!initialized) + { + display = 0; + + x11Display = XOpenDisplay(""); + if (x11Display != 0) + { + display = vaGetDisplay(x11Display); + if (display) + { + int majorVersion = 0, minorVersion = 0; + if (vaInitialize(display, &majorVersion, &minorVersion) == VA_STATUS_SUCCESS) + { + initialized = true; + return true; + } + display = 0; + } + XCloseDisplay(x11Display); + x11Display = 0; + } + + return false; // Can't initialize X11/VA display + } + return true; +} + +void closeDisplay() +{ + if (initialized) + { + if (display) + vaTerminate(display); + if (x11Display) + XCloseDisplay(x11Display); + display = 0; + x11Display = 0; + initialized = false; + } +} + +#endif // HAVE_VA_INTEL / HAVE_VA + } // namespace va diff --git a/samples/va_intel/va_intel_interop.cpp b/samples/va_intel/va_intel_interop.cpp index 1175a14aa..996ac375e 100644 --- a/samples/va_intel/va_intel_interop.cpp +++ b/samples/va_intel/va_intel_interop.cpp @@ -42,6 +42,7 @@ #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/core/va_intel.hpp" +#include "cvconfig.h" #define CHECK_VASTATUS(va_status,func) \ if (va_status != VA_STATUS_SUCCESS) { \ @@ -362,14 +363,20 @@ public: { int n = 0; m_files[0] = m_files[1] = 0; +#if defined(HAVE_VA_INTEL) m_interop = true; +#elif defined(HAVE_VA) + m_interop = false; +#endif //HAVE_VA_INTEL / HAVE_VA for (int i = 1; i < m_argc; ++i) { const char *arg = m_argv[i]; if (arg[0] == '-') // option { +#if defined(HAVE_VA_INTEL) if (!strcmp(arg, "-f")) m_interop = false; +#endif //HAVE_VA_INTEL } else // parameter { @@ -400,8 +407,15 @@ int main(int argc, char** argv) if (!cmd.run()) { fprintf(stderr, +#if defined(HAVE_VA_INTEL) "Usage: va_intel_interop [-f] file1 file2\n\n" + "Interop ON/OFF version\n\n" "where: -f option indicates interop is off (fallback mode); interop is on by default\n" +#elif defined(HAVE_VA) + "Usage: va_intel_interop file1 file2\n\n" + "Interop OFF only version\n\n" + "where:\n" +#endif //HAVE_VA_INTEL / HAVE_VA " file1 is to be created, contains original surface data (NV12)\n" " file2 is to be created, contains processed surface data (NV12)\n"); exit(0); From a275489f0a5e3fc033ba7221f0829872a0893663 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Thu, 27 Aug 2015 16:53:44 +0300 Subject: [PATCH 016/156] HAL universal intrinsics tests and documentation --- modules/hal/include/opencv2/hal.hpp | 13 + modules/hal/include/opencv2/hal/defs.h | 20 +- modules/hal/include/opencv2/hal/intrin.hpp | 28 + .../hal/include/opencv2/hal/intrin_cpp.hpp | 1069 +++++++++++++++-- .../hal/include/opencv2/hal/intrin_neon.hpp | 31 +- .../hal/include/opencv2/hal/intrin_sse.hpp | 66 +- modules/hal/test/test_intrin.cpp | 864 +++++++++++++ modules/hal/test/test_intrin_utils.hpp | 234 ++++ modules/hal/test/test_main.cpp | 3 + modules/hal/test/test_precomp.hpp | 11 + 10 files changed, 2226 insertions(+), 113 deletions(-) create mode 100644 modules/hal/test/test_intrin.cpp create mode 100644 modules/hal/test/test_intrin_utils.hpp create mode 100644 modules/hal/test/test_main.cpp create mode 100644 modules/hal/test/test_precomp.hpp diff --git a/modules/hal/include/opencv2/hal.hpp b/modules/hal/include/opencv2/hal.hpp index 95d1ac66c..9d448757d 100644 --- a/modules/hal/include/opencv2/hal.hpp +++ b/modules/hal/include/opencv2/hal.hpp @@ -49,10 +49,21 @@ /** @defgroup hal Hardware Acceleration Layer + @{ + @defgroup hal_intrin Universal intrinsics + @{ + @defgroup hal_intrin_impl Private implementation helpers + @} + @defgroup hal_utils Platform-dependent utils + @} */ + namespace cv { namespace hal { +//! @addtogroup hal +//! @{ + namespace Error { enum @@ -93,6 +104,8 @@ void sqrt(const double* src, double* dst, int len); void invSqrt(const float* src, float* dst, int len); void invSqrt(const double* src, double* dst, int len); +//! @} + }} //cv::hal #endif //__OPENCV_HAL_HPP__ diff --git a/modules/hal/include/opencv2/hal/defs.h b/modules/hal/include/opencv2/hal/defs.h index 1c30073a0..f7d5f3556 100644 --- a/modules/hal/include/opencv2/hal/defs.h +++ b/modules/hal/include/opencv2/hal/defs.h @@ -45,6 +45,9 @@ #ifndef __OPENCV_DEF_H__ #define __OPENCV_DEF_H__ +//! @addtogroup hal_utils +//! @{ + #if !defined _CRT_SECURE_NO_DEPRECATE && defined _MSC_VER && _MSC_VER > 1300 # define _CRT_SECURE_NO_DEPRECATE /* to avoid multiple Visual Studio warnings */ #endif @@ -335,9 +338,6 @@ Cv64suf; # include "tegra_round.hpp" #endif -//! @addtogroup core_utils -//! @{ - #if CV_VFP // 1. general scheme #define ARM_ROUND(_value, _asm_string) \ @@ -567,15 +567,19 @@ CV_INLINE int cvIsInf( float value ) return (ieee754.u & 0x7fffffff) == 0x7f800000; } +//! @} + #include namespace cv { +//! @addtogroup hal_utils +//! @{ + /////////////// saturate_cast (used in image & signal processing) /////////////////// -/** - Template function for accurate conversion from one primitive type to another. +/** @brief Template function for accurate conversion from one primitive type to another. The functions saturate_cast resemble the standard C++ cast operations, such as static_cast\() and others. They perform an efficient and accurate conversion from one primitive type to another @@ -618,8 +622,6 @@ template static inline _Tp saturate_cast(int64 v) { return _Tp( /** @overload */ template static inline _Tp saturate_cast(uint64 v) { return _Tp(v); } -//! @cond IGNORED - template<> inline uchar saturate_cast(schar v) { return (uchar)std::max((int)v, 0); } template<> inline uchar saturate_cast(ushort v) { return (uchar)std::min((unsigned)v, (unsigned)UCHAR_MAX); } template<> inline uchar saturate_cast(int v) { return (uchar)((unsigned)v <= UCHAR_MAX ? v : v > 0 ? UCHAR_MAX : 0); } @@ -664,12 +666,10 @@ template<> inline int saturate_cast(double v) { return cvRound(v) template<> inline unsigned saturate_cast(float v) { return cvRound(v); } template<> inline unsigned saturate_cast(double v) { return cvRound(v); } -//! @endcond +//! @} } #endif // __cplusplus -//! @} core_utils - #endif //__OPENCV_HAL_H__ diff --git a/modules/hal/include/opencv2/hal/intrin.hpp b/modules/hal/include/opencv2/hal/intrin.hpp index 767c5780d..c8d59c964 100644 --- a/modules/hal/include/opencv2/hal/intrin.hpp +++ b/modules/hal/include/opencv2/hal/intrin.hpp @@ -48,6 +48,7 @@ #include #include #include +#include "opencv2/hal/defs.h" #define OPENCV_HAL_ADD(a, b) ((a) + (b)) #define OPENCV_HAL_AND(a, b) ((a) & (b)) @@ -59,6 +60,10 @@ // access from within opencv code more accessible namespace cv { +//! @addtogroup hal_intrin +//! @{ + +//! @cond IGNORED template struct V_TypeTraits { typedef _Tp int_type; @@ -82,6 +87,7 @@ template<> struct V_TypeTraits typedef int sum_type; typedef ushort w_type; + typedef unsigned q_type; enum { delta = 128, shift = 8 }; @@ -99,6 +105,7 @@ template<> struct V_TypeTraits typedef int sum_type; typedef short w_type; + typedef int q_type; enum { delta = 128, shift = 8 }; @@ -265,8 +272,22 @@ template<> struct V_TypeTraits } }; +template struct V_SIMD128Traits +{ + enum { nlanes = 16 / sizeof(T) }; +}; + +//! @endcond + +//! @} + } +#ifdef CV_DOXYGEN +# undef CV_SSE2 +# undef CV_NEON +#endif + #if CV_SSE2 #include "opencv2/hal/intrin_sse.hpp" @@ -281,12 +302,19 @@ template<> struct V_TypeTraits #endif +//! @addtogroup hal_intrin +//! @{ + #ifndef CV_SIMD128 +//! Set to 1 if current compiler supports vector extensions (NEON or SSE is enabled) #define CV_SIMD128 0 #endif #ifndef CV_SIMD128_64F +//! Set to 1 if current intrinsics implementation supports 64-bit float vectors #define CV_SIMD128_64F 0 #endif +//! @} + #endif diff --git a/modules/hal/include/opencv2/hal/intrin_cpp.hpp b/modules/hal/include/opencv2/hal/intrin_cpp.hpp index 683305cc2..e1b1044a3 100644 --- a/modules/hal/include/opencv2/hal/intrin_cpp.hpp +++ b/modules/hal/include/opencv2/hal/intrin_cpp.hpp @@ -45,25 +45,233 @@ #ifndef __OPENCV_HAL_INTRIN_CPP_HPP__ #define __OPENCV_HAL_INTRIN_CPP_HPP__ +#include +#include + namespace cv { +/** @addtogroup hal_intrin + +"Universal intrinsics" is a types and functions set intended to simplify vectorization of code on +different platforms. Currently there are two supported SIMD extensions: __SSE/SSE2__ on x86 +architectures and __NEON__ on ARM architectures, both allow working with 128 bit registers +containing packed values of different types. In case when there is no SIMD extension available +during compilation, fallback C++ implementation of intrinsics will be chosen and code will work as +expected although it could be slower. + +### Types + +There are several types representing 128-bit register as a vector of packed values, each type is +implemented as a structure based on a one SIMD register. + +- cv::v_uint8x16 and cv::v_int8x16: sixteen 8-bit integer values (unsigned/signed) - char +- cv::v_uint16x8 and cv::v_int16x8: eight 16-bit integer values (unsigned/signed) - short +- cv::v_uint32x4 and cv::v_int32x4: four 32-bit integer values (unsgined/signed) - int +- cv::v_uint64x2 and cv::v_int64x2: two 64-bit integer values (unsigned/signed) - int64 +- cv::v_float32x4: four 32-bit floating point values (signed) - float +- cv::v_float64x2: two 64-bit floating point valies (signed) - double + +@note +cv::v_float64x2 is not implemented in NEON variant, if you want to use this type, don't forget to +check the CV_SIMD128_64F preprocessor definition: +@code +#if CV_SIMD128_64F +//... +#endif +@endcode + +### Load and store operations + +These operations allow to set contents of the register explicitly or by loading it from some memory +block and to save contents of the register to memory block. + +- Constructors: +@ref v_reg::v_reg(const _Tp *ptr) "from memory", +@ref v_reg::v_reg(_Tp s0, _Tp s1) "from two values", ... +- Other create methods: +@ref v_setall_s8, @ref v_setall_u8, ..., +@ref v_setzero_u8, @ref v_setzero_s8, ... +- Memory operations: +@ref v_load, @ref v_load_aligned, @ref v_load_halves, +@ref v_store, @ref v_store_aligned, +@ref v_store_high, @ref v_store_low + +### Value reordering + +These operations allow to reorder or recombine elements in one or multiple vectors. + +- Interleave, deinterleave (3 and 4 channels): @ref v_load_deinterleave, @ref v_store_interleave +- Expand: @ref v_load_expand, @ref v_load_expand_q, @ref v_expand +- Pack: @ref v_pack, @ref v_pack_u, @ref v_rshr_pack, @ref v_rshr_pack_u, +@ref v_pack_store, @ref v_pack_u_store, @ref v_rshr_pack_store, @ref v_rshr_pack_u_store +- Recombine: @ref v_zip, @ref v_recombine, @ref v_combine_low, @ref v_combine_high +- Extract: @ref v_extract + + +### Arithmetic, bitwise and comparison operations + +Element-wise binary and unary operations. + +- Arithmetics: +@ref operator+(const v_reg &a, const v_reg &b) "+", +@ref operator-(const v_reg &a, const v_reg &b) "-", +@ref operator*(const v_reg &a, const v_reg &b) "*", +@ref operator/(const v_reg &a, const v_reg &b) "/", +@ref v_mul_expand + +- Non-saturating arithmetics: @ref v_add_wrap, @ref v_sub_wrap + +- Bitwise shifts: +@ref operator<<(const v_reg &a, int s) "<<", +@ref operator>>(const v_reg &a, int s) ">>", +@ref v_shl, @ref v_shr + +- Bitwise logic: +@ref operator&(const v_reg &a, const v_reg &b) "&", +@ref operator|(const v_reg &a, const v_reg &b) "|", +@ref operator^(const v_reg &a, const v_reg &b) "^", +@ref operator~(const v_reg &a) "~" + +- Comparison: +@ref operator>(const v_reg &a, const v_reg &b) ">", +@ref operator>=(const v_reg &a, const v_reg &b) ">=", +@ref operator<(const v_reg &a, const v_reg &b) "<", +@ref operator<=(const v_reg &a, const v_reg &b) "<=", +@ref operator==(const v_reg &a, const v_reg &b) "==", +@ref operator!=(const v_reg &a, const v_reg &b) "!=" + +- min/max: @ref v_min, @ref v_max + +### Reduce and mask + +Most of these operations return only one value. + +- Reduce: @ref v_reduce_min, @ref v_reduce_max, @ref v_reduce_sum +- Mask: @ref v_signmask, @ref v_check_all, @ref v_check_any, @ref v_select + +### Other math + +- Some frequent operations: @ref v_sqrt, @ref v_invsqrt, @ref v_magnitude, @ref v_sqr_magnitude +- Absolute values: @ref v_abs, @ref v_absdiff + +### Conversions + +Different type conversions and casts: + +- Rounding: @ref v_round, @ref v_floor, @ref v_ceil, @ref v_trunc, +- To float: @ref v_cvt_f32, @ref v_cvt_f64 +- Reinterpret: @ref v_reinterpret_as_u8, @ref v_reinterpret_as_s8, ... + +### Matrix operations + +In these operations vectors represent matrix rows/columns: @ref v_dotprod, @ref v_matmul, @ref v_transpose4x4 + +### Usability + +Most operations are implemented only for some subset of the available types, following matrices +shows the applicability of different operations to the types. + +Regular integers: + +| Operations\\Types | uint 8x16 | int 8x16 | uint 16x8 | int 16x8 | uint 32x4 | int 32x4 | +|-------------------|:-:|:-:|:-:|:-:|:-:|:-:| +|load, store | x | x | x | x | x | x | +|interleave | x | x | x | x | x | x | +|expand | x | x | x | x | x | x | +|expand_q | x | x | | | | | +|add, sub | x | x | x | x | x | x | +|add_wrap, sub_wrap | x | x | x | x | | | +|mul | | | x | x | x | x | +|mul_expand | | | x | x | x | | +|compare | x | x | x | x | x | x | +|shift | | | x | x | x | x | +|dotprod | | | | x | | | +|logical | x | x | x | x | x | x | +|min, max | x | x | x | x | x | x | +|absdiff | x | x | x | x | x | x | +|reduce | | | | | x | x | +|mask | x | x | x | x | x | x | +|pack | x | x | x | x | x | x | +|pack_u | x | | x | | | | +|unpack | x | x | x | x | x | x | +|extract | x | x | x | x | x | x | +|cvt_flt32 | | | | | | x | +|cvt_flt64 | | | | | | x | +|transpose4x4 | | | | | x | x | + +Big integers: + +| Operations\\Types | uint 64x2 | int 64x2 | +|-------------------|:-:|:-:| +|load, store | x | x | +|add, sub | x | x | +|shift | x | x | +|logical | x | x | +|extract | x | x | + +Floating point: + +| Operations\\Types | float 32x4 | float 64x2 | +|-------------------|:-:|:-:| +|load, store | x | x | +|interleave | x | | +|add, sub | x | x | +|mul | x | x | +|div | x | x | +|compare | x | x | +|min, max | x | x | +|absdiff | x | x | +|reduce | x | | +|mask | x | x | +|unpack | x | x | +|cvt_flt32 | | x | +|cvt_flt64 | x | | +|sqrt, abs | x | x | +|float math | x | x | +|transpose4x4 | x | | + + + @{ */ + template struct v_reg { +//! @cond IGNORED typedef _Tp lane_type; typedef v_reg::int_type, n> int_vec; typedef v_reg::abs_type, n> abs_vec; enum { nlanes = n }; +// !@endcond + /** @brief Constructor + + Initializes register with data from memory + @param ptr pointer to memory block with data for register */ explicit v_reg(const _Tp* ptr) { for( int i = 0; i < n; i++ ) s[i] = ptr[i]; } + + /** @brief Constructor + + Initializes register with two 64-bit values */ v_reg(_Tp s0, _Tp s1) { s[0] = s0; s[1] = s1; } + + /** @brief Constructor + + Initializes register with four 32-bit values */ v_reg(_Tp s0, _Tp s1, _Tp s2, _Tp s3) { s[0] = s0; s[1] = s1; s[2] = s2; s[3] = s3; } + + /** @brief Constructor + + Initializes register with eight 16-bit values */ v_reg(_Tp s0, _Tp s1, _Tp s2, _Tp s3, _Tp s4, _Tp s5, _Tp s6, _Tp s7) { s[0] = s0; s[1] = s1; s[2] = s2; s[3] = s3; s[4] = s4; s[5] = s5; s[6] = s6; s[7] = s7; } + + /** @brief Constructor + + Initializes register with sixteen 8-bit values */ v_reg(_Tp s0, _Tp s1, _Tp s2, _Tp s3, _Tp s4, _Tp s5, _Tp s6, _Tp s7, _Tp s8, _Tp s9, _Tp s10, _Tp s11, @@ -75,15 +283,31 @@ template struct v_reg s[12] = s12; s[13] = s13; s[14] = s14; s[15] = s15; } + /** @brief Default constructor + + Does not initialize anything*/ v_reg() {} + + /** @brief Copy constructor */ v_reg(const v_reg<_Tp, n> & r) { for( int i = 0; i < n; i++ ) s[i] = r.s[i]; } + /** @brief Access first value - _Tp get(const int i) const { return s[i]; } + Returns value of the first lane according to register type, for example: + @code{.cpp} + v_int32x4 r(1, 2, 3, 4); + int v = r.get0(); // returns 1 + v_uint64x2 r(1, 2); + uint64_t v = r.get0(); // returns 1 + @endcode + */ _Tp get0() const { return s[0]; } + +//! @cond IGNORED + _Tp get(const int i) const { return s[i]; } v_reg<_Tp, n> high() const { v_reg<_Tp, n> c; @@ -116,13 +340,37 @@ template struct v_reg { size_t bytes = std::min(sizeof(_Tp2)*n2, sizeof(_Tp)*n); v_reg<_Tp2, n2> c; - memcpy(&c.s[0], &s[0], bytes); + std::memcpy(&c.s[0], &s[0], bytes); return c; } _Tp s[n]; +//! @endcond }; +/** @brief Sixteen 8-bit unsigned integer values */ +typedef v_reg v_uint8x16; +/** @brief Sixteen 8-bit signed integer values */ +typedef v_reg v_int8x16; +/** @brief Eight 16-bit unsigned integer values */ +typedef v_reg v_uint16x8; +/** @brief Eight 16-bit signed integer values */ +typedef v_reg v_int16x8; +/** @brief Four 32-bit unsigned integer values */ +typedef v_reg v_uint32x4; +/** @brief Four 32-bit signed integer values */ +typedef v_reg v_int32x4; +/** @brief Four 32-bit floating point values (single precision) */ +typedef v_reg v_float32x4; +/** @brief Two 64-bit floating point values (double precision) */ +typedef v_reg v_float64x2; +/** @brief Two 64-bit unsigned integer values */ +typedef v_reg v_uint64x2; +/** @brief Two 64-bit signed integer values */ +typedef v_reg v_int64x2; + +//! @brief Helper macro +//! @ingroup hal_intrin_impl #define OPENCV_HAL_IMPL_BIN_OP(bin_op) \ template inline v_reg<_Tp, n> \ operator bin_op (const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ @@ -140,11 +388,28 @@ template inline v_reg<_Tp, n>& \ return a; \ } +/** @brief Add values + +For all types. */ OPENCV_HAL_IMPL_BIN_OP(+) + +/** @brief Subtract values + +For all types. */ OPENCV_HAL_IMPL_BIN_OP(-) + +/** @brief Multiply values + +For 16- and 32-bit integer types and floating types. */ OPENCV_HAL_IMPL_BIN_OP(*) + +/** @brief Divide values + +For floating types only. */ OPENCV_HAL_IMPL_BIN_OP(/) +//! @brief Helper macro +//! @ingroup hal_intrin_impl #define OPENCV_HAL_IMPL_BIT_OP(bit_op) \ template inline v_reg<_Tp, n> operator bit_op \ (const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ @@ -166,10 +431,24 @@ template inline v_reg<_Tp, n>& operator \ return a; \ } +/** @brief Bitwise AND + +Only for integer types. */ OPENCV_HAL_IMPL_BIT_OP(&) + +/** @brief Bitwise OR + +Only for integer types. */ OPENCV_HAL_IMPL_BIT_OP(|) + +/** @brief Bitwise XOR + +Only for integer types.*/ OPENCV_HAL_IMPL_BIT_OP(^) +/** @brief Bitwise NOT + +Only for integer types.*/ template inline v_reg<_Tp, n> operator ~ (const v_reg<_Tp, n>& a) { v_reg<_Tp, n> c; @@ -178,6 +457,8 @@ template inline v_reg<_Tp, n> operator ~ (const v_reg<_Tp, return c; } +//! @brief Helper macro +//! @ingroup hal_intrin_impl #define OPENCV_HAL_IMPL_MATH_FUNC(func, cfunc, _Tp2) \ template inline v_reg<_Tp2, n> func(const v_reg<_Tp, n>& a) \ { \ @@ -187,27 +468,59 @@ template inline v_reg<_Tp2, n> func(const v_reg<_Tp, n>& a) return c; \ } +/** @brief Square root of elements + +Only for floating point types.*/ OPENCV_HAL_IMPL_MATH_FUNC(v_sqrt, std::sqrt, _Tp) + +//! @cond IGNORED OPENCV_HAL_IMPL_MATH_FUNC(v_sin, std::sin, _Tp) OPENCV_HAL_IMPL_MATH_FUNC(v_cos, std::cos, _Tp) OPENCV_HAL_IMPL_MATH_FUNC(v_exp, std::exp, _Tp) OPENCV_HAL_IMPL_MATH_FUNC(v_log, std::log, _Tp) +//! @endcond + +/** @brief Absolute value of elements + +Only for floating point types.*/ OPENCV_HAL_IMPL_MATH_FUNC(v_abs, (typename V_TypeTraits<_Tp>::abs_type)std::abs, typename V_TypeTraits<_Tp>::abs_type) + +/** @brief Round elements + +Only for floating point types.*/ OPENCV_HAL_IMPL_MATH_FUNC(v_round, cvRound, int) + +/** @brief Floor elements + +Only for floating point types.*/ OPENCV_HAL_IMPL_MATH_FUNC(v_floor, cvFloor, int) + +/** @brief Ceil elements + +Only for floating point types.*/ OPENCV_HAL_IMPL_MATH_FUNC(v_ceil, cvCeil, int) + +/** @brief Truncate elements + +Only for floating point types.*/ OPENCV_HAL_IMPL_MATH_FUNC(v_trunc, int, int) -#define OPENCV_HAL_IMPL_MINMAX_FUNC(func, hfunc, cfunc) \ +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_MINMAX_FUNC(func, cfunc) \ template inline v_reg<_Tp, n> func(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ { \ v_reg<_Tp, n> c; \ for( int i = 0; i < n; i++ ) \ c.s[i] = cfunc(a.s[i], b.s[i]); \ return c; \ -} \ -template inline _Tp hfunc(const v_reg<_Tp, n>& a) \ +} + +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_REDUCE_MINMAX_FUNC(func, cfunc) \ +template inline _Tp func(const v_reg<_Tp, n>& a) \ { \ _Tp c = a.s[0]; \ for( int i = 1; i < n; i++ ) \ @@ -215,9 +528,49 @@ template inline _Tp hfunc(const v_reg<_Tp, n>& a) \ return c; \ } -OPENCV_HAL_IMPL_MINMAX_FUNC(v_min, v_reduce_min, std::min) -OPENCV_HAL_IMPL_MINMAX_FUNC(v_max, v_reduce_max, std::max) +/** @brief Choose min values for each pair +Scheme: +@code +{A1 A2 ...} +{B1 B2 ...} +-------------- +{min(A1,B1) min(A2,B2) ...} +@endcode +For all types except 64-bit integer. */ +OPENCV_HAL_IMPL_MINMAX_FUNC(v_min, std::min) + +/** @brief Choose max values for each pair + +Scheme: +@code +{A1 A2 ...} +{B1 B2 ...} +-------------- +{max(A1,B1) max(A2,B2) ...} +@endcode +For all types except 64-bit integer. */ +OPENCV_HAL_IMPL_MINMAX_FUNC(v_max, std::max) + +/** @brief Find one min value + +Scheme: +@code +{A1 A2 A3 ...} => min(A1,A2,A3,...) +@endcode +For 32-bit integer and 32-bit floating point types. */ +OPENCV_HAL_IMPL_REDUCE_MINMAX_FUNC(v_reduce_min, std::min) + +/** @brief Find one max value + +Scheme: +@code +{A1 A2 A3 ...} => max(A1,A2,A3,...) +@endcode +For 32-bit integer and 32-bit floating point types. */ +OPENCV_HAL_IMPL_REDUCE_MINMAX_FUNC(v_reduce_max, std::max) + +//! @cond IGNORED template inline void v_minmax( const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, v_reg<_Tp, n>& minval, v_reg<_Tp, n>& maxval ) @@ -228,8 +581,10 @@ inline void v_minmax( const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, maxval.s[i] = std::max(a.s[i], b.s[i]); } } +//! @endcond - +//! @brief Helper macro +//! @ingroup hal_intrin_impl #define OPENCV_HAL_IMPL_CMP_OP(cmp_op) \ template \ inline v_reg<_Tp, n> operator cmp_op(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ @@ -241,13 +596,38 @@ inline v_reg<_Tp, n> operator cmp_op(const v_reg<_Tp, n>& a, const v_reg<_Tp, n> return c; \ } +/** @brief Less-than comparison + +For all types except 64-bit integer values. */ OPENCV_HAL_IMPL_CMP_OP(<) + +/** @brief Greater-than comparison + +For all types except 64-bit integer values. */ OPENCV_HAL_IMPL_CMP_OP(>) + +/** @brief Less-than or equal comparison + +For all types except 64-bit integer values. */ OPENCV_HAL_IMPL_CMP_OP(<=) + +/** @brief Greater-than or equal comparison + +For all types except 64-bit integer values. */ OPENCV_HAL_IMPL_CMP_OP(>=) + +/** @brief Equal comparison + +For all types except 64-bit integer values. */ OPENCV_HAL_IMPL_CMP_OP(==) + +/** @brief Not equal comparison + +For all types except 64-bit integer values. */ OPENCV_HAL_IMPL_CMP_OP(!=) +//! @brief Helper macro +//! @ingroup hal_intrin_impl #define OPENCV_HAL_IMPL_ADD_SUB_OP(func, bin_op, cast_op, _Tp2) \ template \ inline v_reg<_Tp2, n> func(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ @@ -259,10 +639,73 @@ inline v_reg<_Tp2, n> func(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ return c; \ } -OPENCV_HAL_IMPL_ADD_SUB_OP(v_add_wrap, +, (_Tp), _Tp) -OPENCV_HAL_IMPL_ADD_SUB_OP(v_sub_wrap, -, (_Tp), _Tp) -OPENCV_HAL_IMPL_ADD_SUB_OP(v_absdiff, -, (rtype)std::abs, typename V_TypeTraits<_Tp>::abs_type) +/** @brief Add values without saturation +For 8- and 16-bit integer values. */ +OPENCV_HAL_IMPL_ADD_SUB_OP(v_add_wrap, +, (_Tp), _Tp) + +/** @brief Subtract values without saturation + +For 8- and 16-bit integer values. */ +OPENCV_HAL_IMPL_ADD_SUB_OP(v_sub_wrap, -, (_Tp), _Tp) + +//! @cond IGNORED +template inline T _absdiff(T a, T b) +{ + return a > b ? a - b : b - a; +} +//! @endcond + +/** @brief Absolute difference + +Returns \f$ |a - b| \f$ converted to corresponding unsigned type. +Example: +@code{.cpp} +v_int32x4 a, b; // {1, 2, 3, 4} and {4, 3, 2, 1} +v_uint32x4 c = v_absdiff(a, b); // result is {3, 1, 1, 3} +@endcode +For 8-, 16-, 32-bit integer source types. */ +template +inline v_reg::abs_type, n> v_absdiff(const v_reg<_Tp, n>& a, const v_reg<_Tp, n> & b) +{ + typedef typename V_TypeTraits<_Tp>::abs_type rtype; + v_reg c; + const rtype mask = std::numeric_limits<_Tp>::is_signed ? (1 << (sizeof(rtype)*8 - 1)) : 0; + for( int i = 0; i < n; i++ ) + { + rtype ua = a.s[i] ^ mask; + rtype ub = b.s[i] ^ mask; + c.s[i] = _absdiff(ua, ub); + } + return c; +} + +/** @overload + +For 32-bit floating point values */ +inline v_float32x4 v_absdiff(const v_float32x4& a, const v_float32x4& b) +{ + v_float32x4 c; + for( int i = 0; i < c.nlanes; i++ ) + c.s[i] = _absdiff(a.s[i], b.s[i]); + return c; +} + +/** @overload + +For 64-bit floating point values */ +inline v_float64x2 v_absdiff(const v_float64x2& a, const v_float64x2& b) +{ + v_float64x2 c; + for( int i = 0; i < c.nlanes; i++ ) + c.s[i] = _absdiff(a.s[i], b.s[i]); + return c; +} + +/** @brief Inversed square root + +Returns \f$ 1/sqrt(a) \f$ +For floating point types only. */ template inline v_reg<_Tp, n> v_invsqrt(const v_reg<_Tp, n>& a) { @@ -272,6 +715,10 @@ inline v_reg<_Tp, n> v_invsqrt(const v_reg<_Tp, n>& a) return c; } +/** @brief Magnitude + +Returns \f$ sqrt(a^2 + b^2) \f$ +For floating point types only. */ template inline v_reg<_Tp, n> v_magnitude(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) { @@ -281,7 +728,10 @@ inline v_reg<_Tp, n> v_magnitude(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) return c; } +/** @brief Square of the magnitude +Returns \f$ a^2 + b^2 \f$ +For floating point types only. */ template inline v_reg<_Tp, n> v_sqr_magnitude(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) { @@ -291,6 +741,10 @@ inline v_reg<_Tp, n> v_sqr_magnitude(const v_reg<_Tp, n>& a, const v_reg<_Tp, n> return c; } +/** @brief Multiply and add + +Returns \f$ a*b + c \f$ +For floating point types only. */ template inline v_reg<_Tp, n> v_muladd(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, const v_reg<_Tp, n>& c) @@ -301,6 +755,18 @@ inline v_reg<_Tp, n> v_muladd(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, return d; } +/** @brief Dot product of elements + +Multiply values in two registers and sum adjacent result pairs. +Scheme: +@code + {A1 A2 ...} // 16-bit +x {B1 B2 ...} // 16-bit +------------- +{A1B1+A2B2 ...} // 32-bit +@endcode +Implemented only for 16-bit signed source type (v_int16x8). +*/ template inline v_reg::w_type, n/2> v_dotprod(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) { @@ -311,6 +777,25 @@ template inline v_reg::w_type, n return c; } +/** @brief Multiply and expand + +Multiply values two registers and store results in two registers with wider pack type. +Scheme: +@code + {A B C D} // 32-bit +x {E F G H} // 32-bit +--------------- +{AE BF} // 64-bit + {CG DH} // 64-bit +@endcode +Example: +@code{.cpp} +v_uint32x4 a, b; // {1,2,3,4} and {2,2,2,2} +v_uint64x2 c, d; // results +v_mul_expand(a, b, c, d); // c, d = {2,4}, {6, 8} +@endcode +Implemented only for 16- and unsigned 32-bit source types (v_int16x8, v_uint16x8, v_uint32x4). +*/ template inline void v_mul_expand(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, v_reg::w_type, n/2>& c, v_reg::w_type, n/2>& d) @@ -318,11 +803,12 @@ template inline void v_mul_expand(const v_reg<_Tp, n>& a, c typedef typename V_TypeTraits<_Tp>::w_type w_type; for( int i = 0; i < (n/2); i++ ) { - c.s[i] = (w_type)a.s[i]*b.s[i]*2; + c.s[i] = (w_type)a.s[i]*b.s[i]; d.s[i] = (w_type)a.s[i+(n/2)]*b.s[i+(n/2)]; } } +//! @cond IGNORED template inline void v_hsum(const v_reg<_Tp, n>& a, v_reg::w_type, n/2>& c) { @@ -332,7 +818,10 @@ template inline void v_hsum(const v_reg<_Tp, n>& a, c.s[i] = (w_type)a.s[i*2] + a.s[i*2+1]; } } +//! @endcond +//! @brief Helper macro +//! @ingroup hal_intrin_impl #define OPENCV_HAL_IMPL_SHIFT_OP(shift_op) \ template inline v_reg<_Tp, n> operator shift_op(const v_reg<_Tp, n>& a, int imm) \ { \ @@ -342,9 +831,23 @@ template inline v_reg<_Tp, n> operator shift_op(const v_reg return c; \ } +/** @brief Bitwise shift left + +For 16-, 32- and 64-bit integer values. */ OPENCV_HAL_IMPL_SHIFT_OP(<<) + +/** @brief Bitwise shift right + +For 16-, 32- and 64-bit integer values. */ OPENCV_HAL_IMPL_SHIFT_OP(>>) +/** @brief Sum packed values + +Scheme: +@code +{A1 A2 A3 ...} => sum{A1,A2,A3,...} +@endcode +For 32-bit integer and 32-bit floating point types.*/ template inline typename V_TypeTraits<_Tp>::sum_type v_reduce_sum(const v_reg<_Tp, n>& a) { typename V_TypeTraits<_Tp>::sum_type c = a.s[0]; @@ -353,6 +856,15 @@ template inline typename V_TypeTraits<_Tp>::sum_type v_redu return c; } +/** @brief Get negative values mask + +Returned value is a bit mask with bits set to 1 on places corresponding to negative packed values indexes. +Example: +@code{.cpp} +v_int32x4 r; // set to {-1, -1, 1, 1} +int mask = v_signmask(r); // mask = 3 <== 00000000 00000000 00000000 00000011 +@endcode +For all types except 64-bit. */ template inline int v_signmask(const v_reg<_Tp, n>& a) { int mask = 0; @@ -361,6 +873,10 @@ template inline int v_signmask(const v_reg<_Tp, n>& a) return mask; } +/** @brief Check if all packed values are less than zero + +Unsigned values will be casted to signed: `uchar 254 => char -2`. +For all types except 64-bit. */ template inline bool v_check_all(const v_reg<_Tp, n>& a) { for( int i = 0; i < n; i++ ) @@ -369,6 +885,10 @@ template inline bool v_check_all(const v_reg<_Tp, n>& a) return true; } +/** @brief Check if any of packed values is less than zero + +Unsigned values will be casted to signed: `uchar 254 => char -2`. +For all types except 64-bit. */ template inline bool v_check_any(const v_reg<_Tp, n>& a) { for( int i = 0; i < n; i++ ) @@ -377,15 +897,36 @@ template inline bool v_check_any(const v_reg<_Tp, n>& a) return false; } +/** @brief Bitwise select + +Return value will be built by combining values a and b using the following scheme: +If the i-th bit in _mask_ is 1 + select i-th bit from _a_ +else + select i-th bit from _b_ */ template inline v_reg<_Tp, n> v_select(const v_reg<_Tp, n>& mask, const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) { + typedef V_TypeTraits<_Tp> Traits; + typedef typename Traits::int_type int_type; v_reg<_Tp, n> c; for( int i = 0; i < n; i++ ) - c.s[i] = V_TypeTraits<_Tp>::reinterpret_int(mask.s[i]) < 0 ? b.s[i] : a.s[i]; + { + int_type m = Traits::reinterpret_int(mask.s[i]); + c.s[i] = Traits::reinterpret_from_int((Traits::reinterpret_int(a.s[i]) & m) + | (Traits::reinterpret_int(b.s[i]) & ~m)); + } return c; } +/** @brief Expand values to the wider pack type + +Copy contents of register to two registers with 2x wider pack type. +Scheme: +@code + int32x4 int64x2 int64x2 +{A B C D} ==> {A B} , {C D} +@endcode */ template inline void v_expand(const v_reg<_Tp, n>& a, v_reg::w_type, n/2>& b0, v_reg::w_type, n/2>& b1) @@ -397,6 +938,7 @@ template inline void v_expand(const v_reg<_Tp, n>& a, } } +//! @cond IGNORED template inline v_reg::int_type, n> v_reinterpret_as_int(const v_reg<_Tp, n>& a) { @@ -414,7 +956,19 @@ template inline v_reg::uint_type c.s[i] = V_TypeTraits<_Tp>::reinterpret_uint(a.s[i]); return c; } +//! @endcond +/** @brief Interleave two vectors + +Scheme: +@code + {A1 A2 A3 A4} + {B1 B2 B3 B4} +--------------- + {A1 B1 A2 B2} and {A3 B3 A4 B4} +@endcode +For all types except 64-bit. +*/ template inline void v_zip( const v_reg<_Tp, n>& a0, const v_reg<_Tp, n>& a1, v_reg<_Tp, n>& b0, v_reg<_Tp, n>& b1 ) { @@ -431,50 +985,102 @@ template inline void v_zip( const v_reg<_Tp, n>& a0, const } } -template inline v_reg<_Tp, n> v_load(const _Tp* ptr) +/** @brief Load register contents from memory + +@param ptr pointer to memory block with data +@return register object + +@note Returned type will be detected from passed pointer type, for example uchar ==> cv::v_uint8x16, int ==> cv::v_int32x4, etc. + */ +template +inline v_reg<_Tp, V_SIMD128Traits<_Tp>::nlanes> v_load(const _Tp* ptr) { - return v_reg<_Tp, n>(ptr); + return v_reg<_Tp, V_SIMD128Traits<_Tp>::nlanes>(ptr); } -template inline v_reg<_Tp, n> v_load_aligned(const _Tp* ptr) +/** @brief Load register contents from memory (aligned) + +similar to cv::v_load, but source memory block should be aligned (to 16-byte boundary) + */ +template +inline v_reg<_Tp, V_SIMD128Traits<_Tp>::nlanes> v_load_aligned(const _Tp* ptr) { - return v_reg<_Tp, n>(ptr); + return v_reg<_Tp, V_SIMD128Traits<_Tp>::nlanes>(ptr); } -template inline void v_load_halves(const _Tp* loptr, const _Tp* hiptr) +/** @brief Load register contents from two memory blocks + +@param loptr memory block containing data for first half (0..n/2) +@param hiptr memory block containing data for second half (n/2..n) + +@code{.cpp} +int lo[2] = { 1, 2 }, hi[2] = { 3, 4 }; +v_int32x4 r = v_load_halves(lo, hi); +@endcode + */ +template +inline v_reg<_Tp, V_SIMD128Traits<_Tp>::nlanes> v_load_halves(const _Tp* loptr, const _Tp* hiptr) { - v_reg<_Tp, n> c; - for( int i = 0; i < n/2; i++ ) + v_reg<_Tp, V_SIMD128Traits<_Tp>::nlanes> c; + for( int i = 0; i < c.nlanes/2; i++ ) { c.s[i] = loptr[i]; - c.s[i+n/2] = hiptr[i]; + c.s[i+c.nlanes/2] = hiptr[i]; } return c; } -template inline v_reg::w_type, n> v_load_expand(const _Tp* ptr) +/** @brief Load register contents from memory with double expand + +Same as cv::v_load, but result pack type will be 2x wider than memory type. + +@code{.cpp} +short buf[4] = {1, 2, 3, 4}; // type is int16 +v_int32x4 r = v_load_expand(buf); // r = {1, 2, 3, 4} - type is int32 +@endcode +For 8-, 16-, 32-bit integer source types. */ +template +inline v_reg::w_type, V_SIMD128Traits<_Tp>::nlanes / 2> +v_load_expand(const _Tp* ptr) { typedef typename V_TypeTraits<_Tp>::w_type w_type; - v_reg c; - for( int i = 0; i < n; i++ ) + v_reg::nlanes> c; + for( int i = 0; i < c.nlanes; i++ ) { c.s[i] = ptr[i]; } return c; } -template inline v_reg::w_type>::w_type, n> v_load_expand_q(const _Tp* ptr) +/** @brief Load register contents from memory with quad expand + +Same as cv::v_load_expand, but result type is 4 times wider than source. +@code{.cpp} +char buf[4] = {1, 2, 3, 4}; // type is int8 +v_int32x4 r = v_load_q(buf); // r = {1, 2, 3, 4} - type is int32 +@endcode +For 8-bit integer source types. */ +template +inline v_reg::q_type, V_SIMD128Traits<_Tp>::nlanes / 4> +v_load_expand_q(const _Tp* ptr) { - typedef typename V_TypeTraits::w_type>::w_type w_type; - v_reg c; - for( int i = 0; i < n; i++ ) + typedef typename V_TypeTraits<_Tp>::q_type q_type; + v_reg::nlanes> c; + for( int i = 0; i < c.nlanes; i++ ) { c.s[i] = ptr[i]; } return c; } +/** @brief Load and deinterleave (4 channels) + +Load data from memory deinterleave and store to 4 registers. +Scheme: +@code +{A1 B1 C1 D1 A2 B2 C2 D2 ...} ==> {A1 A2 ...}, {B1 B2 ...}, {C1 C2 ...}, {D1 D2 ...} +@endcode +For all types except 64-bit. */ template inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a, v_reg<_Tp, n>& b, v_reg<_Tp, n>& c) { @@ -487,6 +1093,14 @@ template inline void v_load_deinterleave(const _Tp* ptr, v_ } } +/** @brief Load and deinterleave (3 channels) + +Load data from memory deinterleave and store to 3 registers. +Scheme: +@code +{A1 B1 C1 A2 B2 C2 ...} ==> {A1 A2 ...}, {B1 B2 ...}, {C1 C2 ...} +@endcode +For all types except 64-bit. */ template inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a, v_reg<_Tp, n>& b, v_reg<_Tp, n>& c, @@ -502,6 +1116,14 @@ inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a, } } +/** @brief Interleave and store (3 channels) + +Interleave and store data from 3 registers to memory. +Scheme: +@code +{A1 A2 ...}, {B1 B2 ...}, {C1 C2 ...}, {D1 D2 ...} ==> {A1 B1 C1 D1 A2 B2 C2 D2 ...} +@endcode +For all types except 64-bit. */ template inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, const v_reg<_Tp, n>& c) @@ -515,6 +1137,14 @@ inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a, } } +/** @brief Interleave and store (4 channels) + +Interleave and store data from 4 registers to memory. +Scheme: +@code +{A1 A2 ...}, {B1 B2 ...}, {C1 C2 ...}, {D1 D2 ...} ==> {A1 B1 C1 D1 A2 B2 C2 D2 ...} +@endcode +For all types except 64-bit. */ template inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, const v_reg<_Tp, n>& c, const v_reg<_Tp, n>& d) @@ -529,6 +1159,14 @@ template inline void v_store_interleave( _Tp* ptr, const v_ } } +/** @brief Store data to memory + +Store register contents to memory. +Scheme: +@code + REG {A B C D} ==> MEM {A B C D} +@endcode +Pointer can be unaligned. */ template inline void v_store(_Tp* ptr, const v_reg<_Tp, n>& a) { @@ -536,6 +1174,13 @@ inline void v_store(_Tp* ptr, const v_reg<_Tp, n>& a) ptr[i] = a.s[i]; } +/** @brief Store data to memory (lower half) + +Store lower half of register contents to memory. +Scheme: +@code + REG {A B C D} ==> MEM {A B} +@endcode */ template inline void v_store_low(_Tp* ptr, const v_reg<_Tp, n>& a) { @@ -543,6 +1188,13 @@ inline void v_store_low(_Tp* ptr, const v_reg<_Tp, n>& a) ptr[i] = a.s[i]; } +/** @brief Store data to memory (higher half) + +Store higher half of register contents to memory. +Scheme: +@code + REG {A B C D} ==> MEM {C D} +@endcode */ template inline void v_store_high(_Tp* ptr, const v_reg<_Tp, n>& a) { @@ -550,6 +1202,14 @@ inline void v_store_high(_Tp* ptr, const v_reg<_Tp, n>& a) ptr[i] = a.s[i+(n/2)]; } +/** @brief Store data to memory (aligned) + +Store register contents to memory. +Scheme: +@code + REG {A B C D} ==> MEM {A B C D} +@endcode +Pointer __should__ be aligned by 16-byte boundary. */ template inline void v_store_aligned(_Tp* ptr, const v_reg<_Tp, n>& a) { @@ -557,6 +1217,16 @@ inline void v_store_aligned(_Tp* ptr, const v_reg<_Tp, n>& a) ptr[i] = a.s[i]; } +/** @brief Combine vector from first elements of two vectors + +Scheme: +@code + {A1 A2 A3 A4} + {B1 B2 B3 B4} +--------------- + {A1 A2 B1 B2} +@endcode +For all types except 64-bit. */ template inline v_reg<_Tp, n> v_combine_low(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) { @@ -569,6 +1239,16 @@ inline v_reg<_Tp, n> v_combine_low(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& return c; } +/** @brief Combine vector from last elements of two vectors + +Scheme: +@code + {A1 A2 A3 A4} + {B1 B2 B3 B4} +--------------- + {A3 A4 B3 B4} +@endcode +For all types except 64-bit. */ template inline v_reg<_Tp, n> v_combine_high(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) { @@ -581,6 +1261,12 @@ inline v_reg<_Tp, n> v_combine_high(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& return c; } +/** @brief Combine two vectors from lower and higher parts of two other vectors + +@code{.cpp} +low = cv::v_combine_low(a, b); +high = cv::v_combine_high(a, b); +@endcode */ template inline void v_recombine(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, v_reg<_Tp, n>& low, v_reg<_Tp, n>& high) @@ -594,18 +1280,41 @@ inline void v_recombine(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, } } +/** @brief Vector extract + +Scheme: +@code + {A1 A2 A3 A4} + {B1 B2 B3 B4} +======================== +shift = 1 {A2 A3 A4 B1} +shift = 2 {A3 A4 B1 B2} +shift = 3 {A4 B1 B2 B3} +@endcode +Restriction: 0 <= shift < nlanes + +Usage: +@code +v_int32x4 a, b, c; +c = v_extract<2>(a, b); +@endcode +For integer types only. */ template inline v_reg<_Tp, n> v_extract(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) { v_reg<_Tp, n> r; + const int shift = n - s; int i = 0; - for (; i < s; ++i) - r.s[i] = a.s[i+n-s]; + for (; i < shift; ++i) + r.s[i] = a.s[i+s]; for (; i < n; ++i) - r.s[i] = b.s[i-s]; + r.s[i] = b.s[i-shift]; return r; } +/** @brief Round + +Rounds each value. Input type is float vector ==> output type is int vector.*/ template inline v_reg v_round(const v_reg& a) { v_reg c; @@ -614,6 +1323,9 @@ template inline v_reg v_round(const v_reg& a) return c; } +/** @brief Floor + +Floor each value. Input type is float vector ==> output type is int vector.*/ template inline v_reg v_floor(const v_reg& a) { v_reg c; @@ -622,6 +1334,9 @@ template inline v_reg v_floor(const v_reg& a) return c; } +/** @brief Ceil + +Ceil each value. Input type is float vector ==> output type is int vector.*/ template inline v_reg v_ceil(const v_reg& a) { v_reg c; @@ -630,6 +1345,9 @@ template inline v_reg v_ceil(const v_reg& a) return c; } +/** @brief Trunc + +Truncate each value. Input type is float vector ==> output type is int vector.*/ template inline v_reg v_trunc(const v_reg& a) { v_reg c; @@ -638,6 +1356,7 @@ template inline v_reg v_trunc(const v_reg& a) return c; } +/** @overload */ template inline v_reg v_round(const v_reg& a) { v_reg c; @@ -649,6 +1368,7 @@ template inline v_reg v_round(const v_reg& a) return c; } +/** @overload */ template inline v_reg v_floor(const v_reg& a) { v_reg c; @@ -660,6 +1380,7 @@ template inline v_reg v_floor(const v_reg& a) return c; } +/** @overload */ template inline v_reg v_ceil(const v_reg& a) { v_reg c; @@ -671,6 +1392,7 @@ template inline v_reg v_ceil(const v_reg& a) return c; } +/** @overload */ template inline v_reg v_trunc(const v_reg& a) { v_reg c; @@ -682,6 +1404,9 @@ template inline v_reg v_trunc(const v_reg& a) return c; } +/** @brief Convert to float + +Supported input type is cv::v_int32x4. */ template inline v_reg v_cvt_f32(const v_reg& a) { v_reg c; @@ -690,6 +1415,9 @@ template inline v_reg v_cvt_f32(const v_reg& a) return c; } +/** @brief Convert to double + +Supported input type is cv::v_int32x4. */ template inline v_reg v_cvt_f64(const v_reg& a) { v_reg c; @@ -698,6 +1426,9 @@ template inline v_reg v_cvt_f64(const v_reg& a) return c; } +/** @brief Convert to double + +Supported input type is cv::v_float32x4. */ template inline v_reg v_cvt_f64(const v_reg& a) { v_reg c; @@ -706,6 +1437,21 @@ template inline v_reg v_cvt_f64(const v_reg& a) return c; } +/** @brief Transpose 4x4 matrix + +Scheme: +@code +a0 {A1 A2 A3 A4} +a1 {B1 B2 B3 B4} +a2 {C1 C2 C3 C4} +a3 {D1 D2 D3 D4} +=============== +b0 {A1 B1 C1 D1} +b1 {A2 B2 C2 D2} +b2 {A3 B3 C3 D3} +b3 {A4 B4 C4 D4} +@endcode +*/ template inline void v_transpose4x4( v_reg<_Tp, 4>& a0, const v_reg<_Tp, 4>& a1, const v_reg<_Tp, 4>& a2, const v_reg<_Tp, 4>& a3, @@ -718,41 +1464,105 @@ inline void v_transpose4x4( v_reg<_Tp, 4>& a0, const v_reg<_Tp, 4>& a1, b3 = v_reg<_Tp, 4>(a0.s[3], a1.s[3], a2.s[3], a3.s[3]); } -typedef v_reg v_uint8x16; -typedef v_reg v_int8x16; -typedef v_reg v_uint16x8; -typedef v_reg v_int16x8; -typedef v_reg v_uint32x4; -typedef v_reg v_int32x4; -typedef v_reg v_float32x4; -typedef v_reg v_float32x8; -typedef v_reg v_float64x2; -typedef v_reg v_uint64x2; -typedef v_reg v_int64x2; +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_INIT_ZERO(_Tpvec, _Tp, suffix) \ +inline _Tpvec v_setzero_##suffix() { return _Tpvec::zero(); } -#define OPENCV_HAL_IMPL_C_INIT(_Tpvec, _Tp, suffix) \ -inline _Tpvec v_setzero_##suffix() { return _Tpvec::zero(); } \ -inline _Tpvec v_setall_##suffix(_Tp val) { return _Tpvec::all(val); } \ +//! @name Init with zero +//! @{ +//! @brief Create new vector with zero elements +OPENCV_HAL_IMPL_C_INIT_ZERO(v_uint8x16, uchar, u8) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_int8x16, schar, s8) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_uint16x8, ushort, u16) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_int16x8, short, s16) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_uint32x4, unsigned, u32) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_int32x4, int, s32) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_float32x4, float, f32) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_float64x2, double, f64) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_uint64x2, uint64, u64) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_int64x2, int64, s64) +//! @} + +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_INIT_VAL(_Tpvec, _Tp, suffix) \ +inline _Tpvec v_setall_##suffix(_Tp val) { return _Tpvec::all(val); } + +//! @name Init with value +//! @{ +//! @brief Create new vector with elements set to a specific value +OPENCV_HAL_IMPL_C_INIT_VAL(v_uint8x16, uchar, u8) +OPENCV_HAL_IMPL_C_INIT_VAL(v_int8x16, schar, s8) +OPENCV_HAL_IMPL_C_INIT_VAL(v_uint16x8, ushort, u16) +OPENCV_HAL_IMPL_C_INIT_VAL(v_int16x8, short, s16) +OPENCV_HAL_IMPL_C_INIT_VAL(v_uint32x4, unsigned, u32) +OPENCV_HAL_IMPL_C_INIT_VAL(v_int32x4, int, s32) +OPENCV_HAL_IMPL_C_INIT_VAL(v_float32x4, float, f32) +OPENCV_HAL_IMPL_C_INIT_VAL(v_float64x2, double, f64) +OPENCV_HAL_IMPL_C_INIT_VAL(v_uint64x2, uint64, u64) +OPENCV_HAL_IMPL_C_INIT_VAL(v_int64x2, int64, s64) +//! @} + +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_REINTERPRET(_Tpvec, _Tp, suffix) \ template inline _Tpvec \ v_reinterpret_as_##suffix(const v_reg<_Tp0, n0>& a) \ -{ return a.template reinterpret_as<_Tp, _Tpvec::nlanes>(a); } +{ return a.template reinterpret_as<_Tp, _Tpvec::nlanes>(); } -OPENCV_HAL_IMPL_C_INIT(v_uint8x16, uchar, u8) -OPENCV_HAL_IMPL_C_INIT(v_int8x16, schar, s8) -OPENCV_HAL_IMPL_C_INIT(v_uint16x8, ushort, u16) -OPENCV_HAL_IMPL_C_INIT(v_int16x8, short, s16) -OPENCV_HAL_IMPL_C_INIT(v_uint32x4, unsigned, u32) -OPENCV_HAL_IMPL_C_INIT(v_int32x4, int, s32) -OPENCV_HAL_IMPL_C_INIT(v_float32x4, float, f32) -OPENCV_HAL_IMPL_C_INIT(v_float64x2, double, f64) -OPENCV_HAL_IMPL_C_INIT(v_uint64x2, uint64, u64) -OPENCV_HAL_IMPL_C_INIT(v_uint64x2, int64, s64) +//! @name Reinterpret +//! @{ +//! @brief Convert vector to different type without modifying underlying data. +OPENCV_HAL_IMPL_C_REINTERPRET(v_uint8x16, uchar, u8) +OPENCV_HAL_IMPL_C_REINTERPRET(v_int8x16, schar, s8) +OPENCV_HAL_IMPL_C_REINTERPRET(v_uint16x8, ushort, u16) +OPENCV_HAL_IMPL_C_REINTERPRET(v_int16x8, short, s16) +OPENCV_HAL_IMPL_C_REINTERPRET(v_uint32x4, unsigned, u32) +OPENCV_HAL_IMPL_C_REINTERPRET(v_int32x4, int, s32) +OPENCV_HAL_IMPL_C_REINTERPRET(v_float32x4, float, f32) +OPENCV_HAL_IMPL_C_REINTERPRET(v_float64x2, double, f64) +OPENCV_HAL_IMPL_C_REINTERPRET(v_uint64x2, uint64, u64) +OPENCV_HAL_IMPL_C_REINTERPRET(v_int64x2, int64, s64) +//! @} -#define OPENCV_HAL_IMPL_C_SHIFT(_Tpvec, _Tp) \ +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_SHIFTL(_Tpvec, _Tp) \ template inline _Tpvec v_shl(const _Tpvec& a) \ -{ return a << n; } \ +{ return a << n; } + +//! @name Left shift +//! @{ +//! @brief Shift left +OPENCV_HAL_IMPL_C_SHIFTL(v_uint16x8, ushort) +OPENCV_HAL_IMPL_C_SHIFTL(v_int16x8, short) +OPENCV_HAL_IMPL_C_SHIFTL(v_uint32x4, unsigned) +OPENCV_HAL_IMPL_C_SHIFTL(v_int32x4, int) +OPENCV_HAL_IMPL_C_SHIFTL(v_uint64x2, uint64) +OPENCV_HAL_IMPL_C_SHIFTL(v_int64x2, int64) +//! @} + +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_SHIFTR(_Tpvec, _Tp) \ template inline _Tpvec v_shr(const _Tpvec& a) \ -{ return a >> n; } \ +{ return a >> n; } + +//! @name Right shift +//! @{ +//! @brief Shift right +OPENCV_HAL_IMPL_C_SHIFTR(v_uint16x8, ushort) +OPENCV_HAL_IMPL_C_SHIFTR(v_int16x8, short) +OPENCV_HAL_IMPL_C_SHIFTR(v_uint32x4, unsigned) +OPENCV_HAL_IMPL_C_SHIFTR(v_int32x4, int) +OPENCV_HAL_IMPL_C_SHIFTR(v_uint64x2, uint64) +OPENCV_HAL_IMPL_C_SHIFTR(v_int64x2, int64) +//! @} + +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_RSHIFTR(_Tpvec, _Tp) \ template inline _Tpvec v_rshr(const _Tpvec& a) \ { \ _Tpvec c; \ @@ -761,15 +1571,20 @@ template inline _Tpvec v_rshr(const _Tpvec& a) \ return c; \ } -OPENCV_HAL_IMPL_C_SHIFT(v_uint16x8, ushort) -OPENCV_HAL_IMPL_C_SHIFT(v_int16x8, short) -OPENCV_HAL_IMPL_C_SHIFT(v_uint32x4, unsigned) -OPENCV_HAL_IMPL_C_SHIFT(v_int32x4, int) -OPENCV_HAL_IMPL_C_SHIFT(v_uint64x2, uint64) -OPENCV_HAL_IMPL_C_SHIFT(v_int64x2, int64) +//! @name Rounding shift +//! @{ +//! @brief Rounding shift right +OPENCV_HAL_IMPL_C_RSHIFTR(v_uint16x8, ushort) +OPENCV_HAL_IMPL_C_RSHIFTR(v_int16x8, short) +OPENCV_HAL_IMPL_C_RSHIFTR(v_uint32x4, unsigned) +OPENCV_HAL_IMPL_C_RSHIFTR(v_int32x4, int) +OPENCV_HAL_IMPL_C_RSHIFTR(v_uint64x2, uint64) +OPENCV_HAL_IMPL_C_RSHIFTR(v_int64x2, int64) +//! @} - -#define OPENCV_HAL_IMPL_C_PACK(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix) \ +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_PACK(_Tpvec, _Tpnvec, _Tpn, pack_suffix) \ inline _Tpnvec v_##pack_suffix(const _Tpvec& a, const _Tpvec& b) \ { \ _Tpnvec c; \ @@ -779,7 +1594,30 @@ inline _Tpnvec v_##pack_suffix(const _Tpvec& a, const _Tpvec& b) \ c.s[i+_Tpvec::nlanes] = saturate_cast<_Tpn>(b.s[i]); \ } \ return c; \ -} \ +} + +//! @name Pack +//! @{ +//! @brief Pack values from two vectors to one +//! +//! Return vector type have twice more elements than input vector types. Variant with _u_ suffix also +//! converts to corresponding unsigned type. +//! +//! - pack: for 16-, 32- and 64-bit integer input types +//! - pack_u: for 16- and 32-bit signed integer input types +OPENCV_HAL_IMPL_C_PACK(v_uint16x8, v_uint8x16, uchar, pack) +OPENCV_HAL_IMPL_C_PACK(v_int16x8, v_int8x16, schar, pack) +OPENCV_HAL_IMPL_C_PACK(v_uint32x4, v_uint16x8, ushort, pack) +OPENCV_HAL_IMPL_C_PACK(v_int32x4, v_int16x8, short, pack) +OPENCV_HAL_IMPL_C_PACK(v_uint64x2, v_uint32x4, unsigned, pack) +OPENCV_HAL_IMPL_C_PACK(v_int64x2, v_int32x4, int, pack) +OPENCV_HAL_IMPL_C_PACK(v_int16x8, v_uint8x16, uchar, pack_u) +OPENCV_HAL_IMPL_C_PACK(v_int32x4, v_uint16x8, ushort, pack_u) +//! @} + +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_RSHR_PACK(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix) \ template inline _Tpnvec v_rshr_##pack_suffix(const _Tpvec& a, const _Tpvec& b) \ { \ _Tpnvec c; \ @@ -789,27 +1627,98 @@ template inline _Tpnvec v_rshr_##pack_suffix(const _Tpvec& a, const _Tpve c.s[i+_Tpvec::nlanes] = saturate_cast<_Tpn>((b.s[i] + ((_Tp)1 << (n - 1))) >> n); \ } \ return c; \ -} \ +} + +//! @name Pack with rounding shift +//! @{ +//! @brief Pack values from two vectors to one with rounding shift +//! +//! Values from the input vectors will be shifted right by _n_ bits with rounding, converted to narrower +//! type and returned in the result vector. Variant with _u_ suffix converts to unsigned type. +//! +//! - pack: for 16-, 32- and 64-bit integer input types +//! - pack_u: for 16- and 32-bit signed integer input types +OPENCV_HAL_IMPL_C_RSHR_PACK(v_uint16x8, ushort, v_uint8x16, uchar, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK(v_int16x8, short, v_int8x16, schar, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK(v_uint32x4, unsigned, v_uint16x8, ushort, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK(v_int32x4, int, v_int16x8, short, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK(v_uint64x2, uint64, v_uint32x4, unsigned, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK(v_int64x2, int64, v_int32x4, int, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK(v_int16x8, short, v_uint8x16, uchar, pack_u) +OPENCV_HAL_IMPL_C_RSHR_PACK(v_int32x4, int, v_uint16x8, ushort, pack_u) +//! @} + +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_PACK_STORE(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix) \ inline void v_##pack_suffix##_store(_Tpn* ptr, const _Tpvec& a) \ { \ for( int i = 0; i < _Tpvec::nlanes; i++ ) \ ptr[i] = saturate_cast<_Tpn>(a.s[i]); \ -} \ +} + +//! @name Pack and store +//! @{ +//! @brief Store values from the input vector into memory with pack +//! +//! Values will be stored into memory with saturating conversion to narrower type. +//! Variant with _u_ suffix converts to corresponding unsigned type. +//! +//! - pack: for 16-, 32- and 64-bit integer input types +//! - pack_u: for 16- and 32-bit signed integer input types +OPENCV_HAL_IMPL_C_PACK_STORE(v_uint16x8, ushort, v_uint8x16, uchar, pack) +OPENCV_HAL_IMPL_C_PACK_STORE(v_int16x8, short, v_int8x16, schar, pack) +OPENCV_HAL_IMPL_C_PACK_STORE(v_uint32x4, unsigned, v_uint16x8, ushort, pack) +OPENCV_HAL_IMPL_C_PACK_STORE(v_int32x4, int, v_int16x8, short, pack) +OPENCV_HAL_IMPL_C_PACK_STORE(v_uint64x2, uint64, v_uint32x4, unsigned, pack) +OPENCV_HAL_IMPL_C_PACK_STORE(v_int64x2, int64, v_int32x4, int, pack) +OPENCV_HAL_IMPL_C_PACK_STORE(v_int16x8, short, v_uint8x16, uchar, pack_u) +OPENCV_HAL_IMPL_C_PACK_STORE(v_int32x4, int, v_uint16x8, ushort, pack_u) +//! @} + +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix) \ template inline void v_rshr_##pack_suffix##_store(_Tpn* ptr, const _Tpvec& a) \ { \ for( int i = 0; i < _Tpvec::nlanes; i++ ) \ ptr[i] = saturate_cast<_Tpn>((a.s[i] + ((_Tp)1 << (n - 1))) >> n); \ } -OPENCV_HAL_IMPL_C_PACK(v_uint16x8, ushort, v_uint8x16, uchar, pack) -OPENCV_HAL_IMPL_C_PACK(v_int16x8, short, v_int8x16, schar, pack) -OPENCV_HAL_IMPL_C_PACK(v_int16x8, short, v_uint8x16, uchar, pack_u) -OPENCV_HAL_IMPL_C_PACK(v_uint32x4, unsigned, v_uint16x8, ushort, pack) -OPENCV_HAL_IMPL_C_PACK(v_int32x4, int, v_int16x8, short, pack) -OPENCV_HAL_IMPL_C_PACK(v_int32x4, int, v_uint16x8, ushort, pack_u) -OPENCV_HAL_IMPL_C_PACK(v_uint64x2, uint64, v_uint32x4, unsigned, pack) -OPENCV_HAL_IMPL_C_PACK(v_int64x2, int64, v_int32x4, int, pack) +//! @name Pack and store with rounding shift +//! @{ +//! @brief Store values from the input vector into memory with pack +//! +//! Values will be shifted _n_ bits right with rounding, converted to narrower type and stored into +//! memory. Variant with _u_ suffix converts to unsigned type. +//! +//! - pack: for 16-, 32- and 64-bit integer input types +//! - pack_u: for 16- and 32-bit signed integer input types +OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_uint16x8, ushort, v_uint8x16, uchar, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int16x8, short, v_int8x16, schar, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_uint32x4, unsigned, v_uint16x8, ushort, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int32x4, int, v_int16x8, short, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_uint64x2, uint64, v_uint32x4, unsigned, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int64x2, int64, v_int32x4, int, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int16x8, short, v_uint8x16, uchar, pack_u) +OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int32x4, int, v_uint16x8, ushort, pack_u) +//! @} +/** @brief Matrix multiplication + +Scheme: +@code +{A0 A1 A2 A3} |V0| +{B0 B1 B2 B3} |V1| +{C0 C1 C2 C3} |V2| +{D0 D1 D2 D3} x |V3| +==================== +{R0 R1 R2 R3}, where: +R0 = A0V0 + A1V1 + A2V2 + A3V3, +R1 = B0V0 + B1V1 + B2V2 + B3V3 +... +@endcode +*/ inline v_float32x4 v_matmul(const v_float32x4& v, const v_float32x4& m0, const v_float32x4& m1, const v_float32x4& m2, const v_float32x4& m3) @@ -820,6 +1729,8 @@ inline v_float32x4 v_matmul(const v_float32x4& v, const v_float32x4& m0, v.s[0]*m0.s[3] + v.s[1]*m1.s[3] + v.s[2]*m2.s[3] + v.s[3]*m3.s[3]); } +//! @} + } #endif diff --git a/modules/hal/include/opencv2/hal/intrin_neon.hpp b/modules/hal/include/opencv2/hal/intrin_neon.hpp index e326696d6..d53971f96 100644 --- a/modules/hal/include/opencv2/hal/intrin_neon.hpp +++ b/modules/hal/include/opencv2/hal/intrin_neon.hpp @@ -48,6 +48,8 @@ namespace cv { +//! @cond IGNORED + #define CV_SIMD128 1 struct v_uint8x16 @@ -278,14 +280,15 @@ void v_rshr_##pack##_store(_Tp* ptr, const _Tpwvec& a) \ } OPENCV_HAL_IMPL_NEON_PACK(v_uint8x16, uchar, uint8x8_t, u8, v_uint16x8, u16, pack, n) -OPENCV_HAL_IMPL_NEON_PACK(v_uint8x16, uchar, uint8x8_t, u8, v_int16x8, s16, pack_u, un) OPENCV_HAL_IMPL_NEON_PACK(v_int8x16, schar, int8x8_t, s8, v_int16x8, s16, pack, n) OPENCV_HAL_IMPL_NEON_PACK(v_uint16x8, ushort, uint16x4_t, u16, v_uint32x4, u32, pack, n) -OPENCV_HAL_IMPL_NEON_PACK(v_uint16x8, ushort, uint16x4_t, u16, v_int32x4, s32, pack_u, un) OPENCV_HAL_IMPL_NEON_PACK(v_int16x8, short, int16x4_t, s16, v_int32x4, s32, pack, n) OPENCV_HAL_IMPL_NEON_PACK(v_uint32x4, unsigned, uint32x2_t, u32, v_uint64x2, u64, pack, n) OPENCV_HAL_IMPL_NEON_PACK(v_int32x4, int, int32x2_t, s32, v_int64x2, s64, pack, n) +OPENCV_HAL_IMPL_NEON_PACK(v_uint8x16, uchar, uint8x8_t, u8, v_int16x8, s16, pack_u, un) +OPENCV_HAL_IMPL_NEON_PACK(v_uint16x8, ushort, uint16x4_t, u16, v_int32x4, s32, pack_u, un) + inline v_float32x4 v_matmul(const v_float32x4& v, const v_float32x4& m0, const v_float32x4& m1, const v_float32x4& m2, const v_float32x4& m3) @@ -374,7 +377,7 @@ inline v_int32x4 v_dotprod(const v_int16x8& a, const v_int16x8& b) { int32x4_t c = vmull_s16(vget_low_s16(a.val), vget_low_s16(b.val)); int32x4_t d = vmull_s16(vget_high_s16(a.val), vget_high_s16(b.val)); - int32x4x2_t cd = vtrnq_s32(c, d); + int32x4x2_t cd = vuzpq_s32(c, d); return v_int32x4(vaddq_s32(cd.val[0], cd.val[1])); } @@ -497,6 +500,16 @@ OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint16x8, v_absdiff, vabdq_u16) OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint32x4, v_absdiff, vabdq_u32) OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_float32x4, v_absdiff, vabdq_f32) +#define OPENCV_HAL_IMPL_NEON_BIN_FUNC2(_Tpvec, _Tpvec2, cast, func, intrin) \ +inline _Tpvec2 func(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return _Tpvec2(cast(intrin(a.val, b.val))); \ +} + +OPENCV_HAL_IMPL_NEON_BIN_FUNC2(v_int8x16, v_uint8x16, vreinterpretq_u8_s8, v_absdiff, vabdq_s8) +OPENCV_HAL_IMPL_NEON_BIN_FUNC2(v_int16x8, v_uint16x8, vreinterpretq_u16_s16, v_absdiff, vabdq_s16) +OPENCV_HAL_IMPL_NEON_BIN_FUNC2(v_int32x4, v_uint32x4, vreinterpretq_u32_s32, v_absdiff, vabdq_s32) + inline v_float32x4 v_magnitude(const v_float32x4& a, const v_float32x4& b) { v_float32x4 x(vmlaq_f32(vmulq_f32(a.val, a.val), b.val, b.val)); @@ -641,13 +654,13 @@ inline bool v_check_all(const v_float32x4& a) { return v_check_all(v_reinterpret_as_u32(a)); } inline bool v_check_any(const v_int8x16& a) -{ return v_check_all(v_reinterpret_as_u8(a)); } +{ return v_check_any(v_reinterpret_as_u8(a)); } inline bool v_check_any(const v_int16x8& a) -{ return v_check_all(v_reinterpret_as_u16(a)); } +{ return v_check_any(v_reinterpret_as_u16(a)); } inline bool v_check_any(const v_int32x4& a) -{ return v_check_all(v_reinterpret_as_u32(a)); } +{ return v_check_any(v_reinterpret_as_u32(a)); } inline bool v_check_any(const v_float32x4& a) -{ return v_check_all(v_reinterpret_as_u32(a)); } +{ return v_check_any(v_reinterpret_as_u32(a)); } #define OPENCV_HAL_IMPL_NEON_SELECT(_Tpvec, suffix, usuffix) \ inline _Tpvec v_select(const _Tpvec& mask, const _Tpvec& a, const _Tpvec& b) \ @@ -678,6 +691,8 @@ OPENCV_HAL_IMPL_NEON_EXPAND(v_uint8x16, v_uint16x8, uchar, u8) OPENCV_HAL_IMPL_NEON_EXPAND(v_int8x16, v_int16x8, schar, s8) OPENCV_HAL_IMPL_NEON_EXPAND(v_uint16x8, v_uint32x4, ushort, u16) OPENCV_HAL_IMPL_NEON_EXPAND(v_int16x8, v_int32x4, short, s16) +OPENCV_HAL_IMPL_NEON_EXPAND(v_uint32x4, v_uint64x2, uint, u32) +OPENCV_HAL_IMPL_NEON_EXPAND(v_int32x4, v_int64x2, int, s32) inline v_uint32x4 v_load_expand_q(const uchar* ptr) { @@ -840,6 +855,8 @@ inline v_float32x4 v_cvt_f32(const v_int32x4& a) return v_float32x4(vcvtq_f32_s32(a.val)); } +//! @endcond + } #endif diff --git a/modules/hal/include/opencv2/hal/intrin_sse.hpp b/modules/hal/include/opencv2/hal/intrin_sse.hpp index 0c30f7d5b..e237ccd93 100644 --- a/modules/hal/include/opencv2/hal/intrin_sse.hpp +++ b/modules/hal/include/opencv2/hal/intrin_sse.hpp @@ -51,6 +51,8 @@ namespace cv { +//! @cond IGNORED + struct v_uint8x16 { typedef uchar lane_type; @@ -296,6 +298,11 @@ OPENCV_HAL_IMPL_SSE_INIT_FROM_FLT(v_int32x4, s32) OPENCV_HAL_IMPL_SSE_INIT_FROM_FLT(v_uint64x2, u64) OPENCV_HAL_IMPL_SSE_INIT_FROM_FLT(v_int64x2, s64) +inline v_float32x4 v_reinterpret_as_f32(const v_float32x4& a) {return a; } +inline v_float64x2 v_reinterpret_as_f64(const v_float64x2& a) {return a; } +inline v_float32x4 v_reinterpret_as_f32(const v_float64x2& a) {return v_float32x4(_mm_castpd_ps(a.val)); } +inline v_float64x2 v_reinterpret_as_f64(const v_float32x4& a) {return v_float64x2(_mm_castps_pd(a.val)); } + //////////////// PACK /////////////// inline v_uint8x16 v_pack(const v_uint16x8& a, const v_uint16x8& b) { @@ -430,6 +437,17 @@ inline void v_pack_u_store(ushort* ptr, const v_int32x4& a) _mm_storel_epi64((__m128i*)ptr, r); } +template inline +v_uint16x8 v_rshr_pack_u(const v_int32x4& a, const v_int32x4& b) +{ + __m128i delta = _mm_set1_epi32(1 << (n-1)), delta32 = _mm_set1_epi32(32768); + __m128i a1 = _mm_sub_epi32(_mm_srai_epi32(_mm_add_epi32(a.val, delta), n), delta32); + __m128i a2 = _mm_sub_epi16(_mm_packs_epi32(a1, a1), _mm_set1_epi16(-32768)); + __m128i b1 = _mm_sub_epi32(_mm_srai_epi32(_mm_add_epi32(b.val, delta), n), delta32); + __m128i b2 = _mm_sub_epi16(_mm_packs_epi32(b1, b1), _mm_set1_epi16(-32768)); + return v_uint16x8(_mm_unpacklo_epi64(a2, b2)); +} + template inline void v_rshr_pack_u_store(ushort* ptr, const v_int32x4& a) { @@ -460,7 +478,7 @@ void v_rshr_pack_store(short* ptr, const v_int32x4& a) { __m128i delta = _mm_set1_epi32(1 << (n-1)); __m128i a1 = _mm_srai_epi32(_mm_add_epi32(a.val, delta), n); - _mm_storel_epi64((__m128i*)ptr, a1); + _mm_storel_epi64((__m128i*)ptr, _mm_packs_epi32(a1, a1)); } @@ -469,7 +487,7 @@ inline v_uint32x4 v_pack(const v_uint64x2& a, const v_uint64x2& b) { __m128i v0 = _mm_unpacklo_epi32(a.val, b.val); // a0 a1 0 0 __m128i v1 = _mm_unpackhi_epi32(a.val, b.val); // b0 b1 0 0 - return v_uint32x4(_mm_unpacklo_epi64(v0, v1)); + return v_uint32x4(_mm_unpacklo_epi32(v0, v1)); } inline void v_pack_store(unsigned* ptr, const v_uint64x2& a) @@ -483,7 +501,7 @@ inline v_int32x4 v_pack(const v_int64x2& a, const v_int64x2& b) { __m128i v0 = _mm_unpacklo_epi32(a.val, b.val); // a0 a1 0 0 __m128i v1 = _mm_unpackhi_epi32(a.val, b.val); // b0 b1 0 0 - return v_int32x4(_mm_unpacklo_epi64(v0, v1)); + return v_int32x4(_mm_unpacklo_epi32(v0, v1)); } inline void v_pack_store(int* ptr, const v_int64x2& a) @@ -501,7 +519,7 @@ v_uint32x4 v_rshr_pack(const v_uint64x2& a, const v_uint64x2& b) __m128i b1 = _mm_srli_epi64(_mm_add_epi64(b.val, delta2.val), n); __m128i v0 = _mm_unpacklo_epi32(a1, b1); // a0 a1 0 0 __m128i v1 = _mm_unpackhi_epi32(a1, b1); // b0 b1 0 0 - return v_uint32x4(_mm_unpacklo_epi64(v0, v1)); + return v_uint32x4(_mm_unpacklo_epi32(v0, v1)); } template inline @@ -534,7 +552,7 @@ v_int32x4 v_rshr_pack(const v_int64x2& a, const v_int64x2& b) __m128i b1 = v_srai_epi64(_mm_add_epi64(b.val, delta2.val), n); __m128i v0 = _mm_unpacklo_epi32(a1, b1); // a0 a1 0 0 __m128i v1 = _mm_unpackhi_epi32(a1, b1); // b0 b1 0 0 - return v_int32x4(_mm_unpacklo_epi64(v0, v1)); + return v_int32x4(_mm_unpacklo_epi32(v0, v1)); } template inline @@ -630,8 +648,8 @@ inline void v_mul_expand(const v_int16x8& a, const v_int16x8& b, { __m128i v0 = _mm_mullo_epi16(a.val, b.val); __m128i v1 = _mm_mulhi_epi16(a.val, b.val); - c.val = _mm_unpacklo_epi32(v0, v1); - d.val = _mm_unpackhi_epi32(v0, v1); + c.val = _mm_unpacklo_epi16(v0, v1); + d.val = _mm_unpackhi_epi16(v0, v1); } inline void v_mul_expand(const v_uint16x8& a, const v_uint16x8& b, @@ -639,8 +657,8 @@ inline void v_mul_expand(const v_uint16x8& a, const v_uint16x8& b, { __m128i v0 = _mm_mullo_epi16(a.val, b.val); __m128i v1 = _mm_mulhi_epu16(a.val, b.val); - c.val = _mm_unpacklo_epi32(v0, v1); - d.val = _mm_unpackhi_epi32(v0, v1); + c.val = _mm_unpacklo_epi16(v0, v1); + d.val = _mm_unpackhi_epi16(v0, v1); } inline void v_mul_expand(const v_uint32x4& a, const v_uint32x4& b, @@ -869,6 +887,18 @@ inline _Tpuvec v_absdiff(const _Tpsvec& a, const _Tpsvec& b) \ OPENCV_HAL_IMPL_SSE_ABSDIFF_8_16(v_uint8x16, v_int8x16, 8, (int)0x80808080) OPENCV_HAL_IMPL_SSE_ABSDIFF_8_16(v_uint16x8, v_int16x8, 16, (int)0x80008000) +inline v_uint32x4 v_absdiff(const v_uint32x4& a, const v_uint32x4& b) +{ + return v_max(a, b) - v_min(a, b); +} + +inline v_uint32x4 v_absdiff(const v_int32x4& a, const v_int32x4& b) +{ + __m128i d = _mm_sub_epi32(a.val, b.val); + __m128i m = _mm_cmpgt_epi32(b.val, a.val); + return v_uint32x4(_mm_sub_epi32(_mm_xor_si128(d, m), m)); +} + #define OPENCV_HAL_IMPL_SSE_MISC_FLT_OP(_Tpvec, _Tp, _Tpreg, suffix, absmask_vec) \ inline _Tpvec v_absdiff(const _Tpvec& a, const _Tpvec& b) \ { \ @@ -1047,8 +1077,8 @@ OPENCV_HAL_IMPL_SSE_SELECT(v_uint16x8, si128) OPENCV_HAL_IMPL_SSE_SELECT(v_int16x8, si128) OPENCV_HAL_IMPL_SSE_SELECT(v_uint32x4, si128) OPENCV_HAL_IMPL_SSE_SELECT(v_int32x4, si128) -OPENCV_HAL_IMPL_SSE_SELECT(v_uint64x2, si128) -OPENCV_HAL_IMPL_SSE_SELECT(v_int64x2, si128) +// OPENCV_HAL_IMPL_SSE_SELECT(v_uint64x2, si128) +// OPENCV_HAL_IMPL_SSE_SELECT(v_int64x2, si128) OPENCV_HAL_IMPL_SSE_SELECT(v_float32x4, ps) OPENCV_HAL_IMPL_SSE_SELECT(v_float64x2, pd) @@ -1257,7 +1287,7 @@ inline void v_load_deinterleave(const uchar* ptr, v_uint8x16& a, v_uint8x16& b, __m128i v0 = _mm_unpacklo_epi8(u0, u2); // a0 a8 b0 b8 ... __m128i v1 = _mm_unpackhi_epi8(u0, u2); // a2 a10 b2 b10 ... __m128i v2 = _mm_unpacklo_epi8(u1, u3); // a4 a12 b4 b12 ... - __m128i v3 = _mm_unpackhi_epi8(u1, u3); // a6 a14 b4 b14 ... + __m128i v3 = _mm_unpackhi_epi8(u1, u3); // a6 a14 b6 b14 ... u0 = _mm_unpacklo_epi8(v0, v2); // a0 a4 a8 a12 ... u1 = _mm_unpacklo_epi8(v1, v3); // a2 a6 a10 a14 ... @@ -1266,13 +1296,13 @@ inline void v_load_deinterleave(const uchar* ptr, v_uint8x16& a, v_uint8x16& b, v0 = _mm_unpacklo_epi8(u0, u1); // a0 a2 a4 a6 ... v1 = _mm_unpacklo_epi8(u2, u3); // a1 a3 a5 a7 ... - v2 = _mm_unpackhi_epi8(u0, u1); // b0 b2 b4 b6 ... - v3 = _mm_unpackhi_epi8(u2, u3); // b1 b3 b5 b7 ... + v2 = _mm_unpackhi_epi8(u0, u1); // c0 c2 c4 c6 ... + v3 = _mm_unpackhi_epi8(u2, u3); // c1 c3 c5 c7 ... a.val = _mm_unpacklo_epi8(v0, v1); - b.val = _mm_unpacklo_epi8(v2, v3); - c.val = _mm_unpackhi_epi8(v0, v1); - d.val = _mm_unpacklo_epi8(v2, v3); + b.val = _mm_unpackhi_epi8(v0, v1); + c.val = _mm_unpacklo_epi8(v2, v3); + d.val = _mm_unpackhi_epi8(v2, v3); } inline void v_load_deinterleave(const ushort* ptr, v_uint16x8& a, v_uint16x8& b, v_uint16x8& c) @@ -1560,6 +1590,8 @@ inline v_float64x2 v_cvt_f64(const v_float32x4& a) return v_float64x2(_mm_cvtps_pd(a.val)); } +//! @endcond + } #endif diff --git a/modules/hal/test/test_intrin.cpp b/modules/hal/test/test_intrin.cpp new file mode 100644 index 000000000..ae043dd20 --- /dev/null +++ b/modules/hal/test/test_intrin.cpp @@ -0,0 +1,864 @@ +#include "test_intrin_utils.hpp" +#include + +using namespace cv; + +template struct TheTest +{ + typedef typename R::lane_type LaneType; + + TheTest & test_loadstore() + { + AlignedData data; + AlignedData out; + + // check if addresses are aligned and unaligned respectively + EXPECT_EQ((size_t)0, (size_t)&data.a.d % 16); + EXPECT_NE((size_t)0, (size_t)&data.u.d % 16); + EXPECT_EQ((size_t)0, (size_t)&out.a.d % 16); + EXPECT_NE((size_t)0, (size_t)&out.u.d % 16); + + // check some initialization methods + R r1 = data.a; + R r2 = v_load(data.u.d); + R r3 = v_load_aligned(data.a.d); + R r4(r2); + EXPECT_EQ(data.a[0], r1.get0()); + EXPECT_EQ(data.u[0], r2.get0()); + EXPECT_EQ(data.a[0], r3.get0()); + EXPECT_EQ(data.u[0], r4.get0()); + + // check some store methods + out.u.clear(); + out.a.clear(); + v_store(out.u.d, r1); + v_store_aligned(out.a.d, r2); + EXPECT_EQ(data.a, out.a); + EXPECT_EQ(data.u, out.u); + + // check more store methods + Data d, res(0); + R r5 = d; + v_store_high(res.mid(), r5); + v_store_low(res.d, r5); + EXPECT_EQ(d, res); + + // check halves load correctness + res.clear(); + R r6 = v_load_halves(d.d, d.mid()); + v_store(res.d, r6); + EXPECT_EQ(d, res); + + // zero, all + Data resZ = RegTrait::zero(); + Data resV = RegTrait::all(8); + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ((LaneType)0, resZ[i]); + EXPECT_EQ((LaneType)8, resV[i]); + } + + // reinterpret_as + v_uint8x16 vu8 = v_reinterpret_as_u8(r1); out.a.clear(); v_store((uchar*)out.a.d, vu8); EXPECT_EQ(data.a, out.a); + v_int8x16 vs8 = v_reinterpret_as_s8(r1); out.a.clear(); v_store((schar*)out.a.d, vs8); EXPECT_EQ(data.a, out.a); + v_uint16x8 vu16 = v_reinterpret_as_u16(r1); out.a.clear(); v_store((ushort*)out.a.d, vu16); EXPECT_EQ(data.a, out.a); + v_int16x8 vs16 = v_reinterpret_as_s16(r1); out.a.clear(); v_store((short*)out.a.d, vs16); EXPECT_EQ(data.a, out.a); + v_uint32x4 vu32 = v_reinterpret_as_u32(r1); out.a.clear(); v_store((unsigned*)out.a.d, vu32); EXPECT_EQ(data.a, out.a); + v_int32x4 vs32 = v_reinterpret_as_s32(r1); out.a.clear(); v_store((int*)out.a.d, vs32); EXPECT_EQ(data.a, out.a); + v_uint64x2 vu64 = v_reinterpret_as_u64(r1); out.a.clear(); v_store((uint64*)out.a.d, vu64); EXPECT_EQ(data.a, out.a); + v_int64x2 vs64 = v_reinterpret_as_s64(r1); out.a.clear(); v_store((int64*)out.a.d, vs64); EXPECT_EQ(data.a, out.a); + v_float32x4 vf32 = v_reinterpret_as_f32(r1); out.a.clear(); v_store((float*)out.a.d, vf32); EXPECT_EQ(data.a, out.a); +#if CV_SIMD128_64F + v_float64x2 vf64 = v_reinterpret_as_f64(r1); out.a.clear(); v_store((double*)out.a.d, vf64); EXPECT_EQ(data.a, out.a); +#endif + + return *this; + } + + TheTest & test_interleave() + { + Data data1, data2, data3, data4; + data2 += 20; + data3 += 40; + data4 += 60; + + + R a = data1, b = data2, c = data3; + R d = data1, e = data2, f = data3, g = data4; + + LaneType buf3[R::nlanes * 3]; + LaneType buf4[R::nlanes * 4]; + + v_store_interleave(buf3, a, b, c); + v_store_interleave(buf4, d, e, f, g); + + Data z(0); + a = b = c = d = e = f = g = z; + + v_load_deinterleave(buf3, a, b, c); + v_load_deinterleave(buf4, d, e, f, g); + + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(data1, Data(a)); + EXPECT_EQ(data2, Data(b)); + EXPECT_EQ(data3, Data(c)); + + EXPECT_EQ(data1, Data(d)); + EXPECT_EQ(data2, Data(e)); + EXPECT_EQ(data3, Data(f)); + EXPECT_EQ(data4, Data(g)); + } + + return *this; + } + + // v_expand and v_load_expand + TheTest & test_expand() + { + typedef typename RegTrait::w_reg Rx2; + Data dataA; + R a = dataA; + + Data resB = v_load_expand(dataA.d); + + Rx2 c, d; + v_expand(a, c, d); + + Data resC = c, resD = d; + const int n = Rx2::nlanes; + for (int i = 0; i < n; ++i) + { + EXPECT_EQ(dataA[i], resB[i]); + EXPECT_EQ(dataA[i], resC[i]); + EXPECT_EQ(dataA[i + n], resD[i]); + } + + return *this; + } + + TheTest & test_expand_q() + { + typedef typename RegTrait::q_reg Rx4; + Data data; + Data out = v_load_expand_q(data.d); + const int n = Rx4::nlanes; + for (int i = 0; i < n; ++i) + EXPECT_EQ(data[i], out[i]); + + return *this; + } + + TheTest & test_addsub() + { + Data dataA, dataB; + dataB.reverse(); + R a = dataA, b = dataB; + + Data resC = a + b, resD = a - b; + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(saturate_cast(dataA[i] + dataB[i]), resC[i]); + EXPECT_EQ(saturate_cast(dataA[i] - dataB[i]), resD[i]); + } + + return *this; + } + + TheTest & test_addsub_wrap() + { + Data dataA, dataB; + dataB.reverse(); + R a = dataA, b = dataB; + + Data resC = v_add_wrap(a, b), + resD = v_sub_wrap(a, b); + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ((LaneType)(dataA[i] + dataB[i]), resC[i]); + EXPECT_EQ((LaneType)(dataA[i] - dataB[i]), resD[i]); + } + return *this; + } + + TheTest & test_mul() + { + Data dataA, dataB; + dataB.reverse(); + R a = dataA, b = dataB; + + Data resC = a * b; + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(dataA[i] * dataB[i], resC[i]); + } + + return *this; + } + + TheTest & test_div() + { + Data dataA, dataB; + dataB.reverse(); + R a = dataA, b = dataB; + + Data resC = a / b; + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(dataA[i] / dataB[i], resC[i]); + } + + return *this; + } + + TheTest & test_mul_expand() + { + typedef typename RegTrait::w_reg Rx2; + Data dataA, dataB(2); + R a = dataA, b = dataB; + Rx2 c, d; + + v_mul_expand(a, b, c, d); + + Data resC = c, resD = d; + const int n = R::nlanes / 2; + for (int i = 0; i < n; ++i) + { + EXPECT_EQ((typename Rx2::lane_type)dataA[i] * dataB[i], resC[i]); + EXPECT_EQ((typename Rx2::lane_type)dataA[i + n] * dataB[i + n], resD[i]); + } + + return *this; + } + + template + TheTest & test_shift() + { + Data dataA; + R a = dataA; + + Data resB = a << s, resC = v_shl(a), resD = a >> s, resE = v_shr(a); + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(dataA[i] << s, resB[i]); + EXPECT_EQ(dataA[i] << s, resC[i]); + EXPECT_EQ(dataA[i] >> s, resD[i]); + EXPECT_EQ(dataA[i] >> s, resE[i]); + } + return *this; + } + + TheTest & test_cmp() + { + Data dataA, dataB; + dataB.reverse(); + dataB += 1; + R a = dataA, b = dataB; + + Data resC = (a == b); + Data resD = (a != b); + Data resE = (a > b); + Data resF = (a >= b); + Data resG = (a < b); + Data resH = (a <= b); + + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(dataA[i] == dataB[i], resC[i] != 0); + EXPECT_EQ(dataA[i] != dataB[i], resD[i] != 0); + EXPECT_EQ(dataA[i] > dataB[i], resE[i] != 0); + EXPECT_EQ(dataA[i] >= dataB[i], resF[i] != 0); + EXPECT_EQ(dataA[i] < dataB[i], resG[i] != 0); + EXPECT_EQ(dataA[i] <= dataB[i], resH[i] != 0); + } + return *this; + } + + TheTest & test_dot_prod() + { + typedef typename RegTrait::w_reg Rx2; + Data dataA, dataB(2); + R a = dataA, b = dataB; + + Data res = v_dotprod(a, b); + + const int n = R::nlanes / 2; + for (int i = 0; i < n; ++i) + { + EXPECT_EQ(dataA[i*2] * dataB[i*2] + dataA[i*2 + 1] * dataB[i*2 + 1], res[i]); + } + return *this; + } + + TheTest & test_logic() + { + Data dataA, dataB(2); + R a = dataA, b = dataB; + + Data resC = a & b, resD = a | b, resE = a ^ b, resF = ~a; + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(dataA[i] & dataB[i], resC[i]); + EXPECT_EQ(dataA[i] | dataB[i], resD[i]); + EXPECT_EQ(dataA[i] ^ dataB[i], resE[i]); + EXPECT_EQ((LaneType)~dataA[i], resF[i]); + } + + return *this; + } + + TheTest & test_sqrt_abs() + { + Data dataA, dataD; + dataD *= -1.0; + R a = dataA, d = dataD; + + Data resB = v_sqrt(a), resC = v_invsqrt(a), resE = v_abs(d); + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_FLOAT_EQ((float)std::sqrt(dataA[i]), (float)resB[i]); + EXPECT_FLOAT_EQ((float)1/std::sqrt(dataA[i]), (float)resC[i]); + EXPECT_FLOAT_EQ((float)abs(dataA[i]), (float)resE[i]); + } + + return *this; + } + + TheTest & test_min_max() + { + Data dataA, dataB; + dataB.reverse(); + R a = dataA, b = dataB; + + Data resC = v_min(a, b), resD = v_max(a, b); + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(std::min(dataA[i], dataB[i]), resC[i]); + EXPECT_EQ(std::max(dataA[i], dataB[i]), resD[i]); + } + + return *this; + } + + TheTest & test_absdiff() + { + typedef typename RegTrait::u_reg Ru; + typedef typename Ru::lane_type u_type; + Data dataA(std::numeric_limits::max()), + dataB(std::numeric_limits::min()); + dataA[0] = (LaneType)-1; + dataB[0] = 1; + dataA[1] = 2; + dataB[1] = (LaneType)-2; + R a = dataA, b = dataB; + Data resC = v_absdiff(a, b); + const u_type mask = std::numeric_limits::is_signed ? (u_type)(1 << (sizeof(u_type)*8 - 1)) : 0; + for (int i = 0; i < Ru::nlanes; ++i) + { + u_type uA = dataA[i] ^ mask; + u_type uB = dataB[i] ^ mask; + EXPECT_EQ(uA > uB ? uA - uB : uB - uA, resC[i]); + } + return *this; + } + + TheTest & test_float_absdiff() + { + Data dataA(std::numeric_limits::max()), + dataB(std::numeric_limits::min()); + dataA[0] = -1; + dataB[0] = 1; + dataA[1] = 2; + dataB[1] = -2; + R a = dataA, b = dataB; + Data resC = v_absdiff(a, b); + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(dataA[i] > dataB[i] ? dataA[i] - dataB[i] : dataB[i] - dataA[i], resC[i]); + } + return *this; + } + + TheTest & test_reduce() + { + Data dataA; + R a = dataA; + EXPECT_EQ((LaneType)1, v_reduce_min(a)); + EXPECT_EQ((LaneType)R::nlanes, v_reduce_max(a)); + EXPECT_EQ((LaneType)(1 + R::nlanes)*2, v_reduce_sum(a)); + return *this; + } + + TheTest & test_mask() + { + Data dataA, dataB, dataC, dataD(1), dataE(2); + dataA[1] *= (LaneType)-1; + dataC *= (LaneType)-1; + R a = dataA, b = dataB, c = dataC, d = dataD, e = dataE; + + int m = v_signmask(a); + EXPECT_EQ(2, m); + + EXPECT_EQ(false, v_check_all(a)); + EXPECT_EQ(false, v_check_all(b)); + EXPECT_EQ(true, v_check_all(c)); + + EXPECT_EQ(true, v_check_any(a)); + EXPECT_EQ(false, v_check_any(b)); + EXPECT_EQ(true, v_check_any(c)); + + typedef V_TypeTraits Traits; + typedef typename Traits::int_type int_type; + + R f = v_select(b, d, e); + Data resF = f; + for (int i = 0; i < R::nlanes; ++i) + { + int_type m2 = Traits::reinterpret_int(dataB[i]); + EXPECT_EQ((Traits::reinterpret_int(dataD[i]) & m2) + | (Traits::reinterpret_int(dataE[i]) & ~m2), + Traits::reinterpret_int(resF[i])); + } + + return *this; + } + + template + TheTest & test_pack() + { + typedef typename RegTrait::w_reg Rx2; + typedef typename Rx2::lane_type w_type; + Data dataA, dataB; + dataA += std::numeric_limits::is_signed ? -10 : 10; + dataB *= 10; + Rx2 a = dataA, b = dataB; + + Data resC = v_pack(a, b); + Data resD = v_rshr_pack(a, b); + + Data resE(0); + v_pack_store(resE.d, b); + + Data resF(0); + v_rshr_pack_store(resF.d, b); + + const int n = Rx2::nlanes; + const w_type add = (w_type)1 << (s - 1); + for (int i = 0; i < n; ++i) + { + EXPECT_EQ(saturate_cast(dataA[i]), resC[i]); + EXPECT_EQ(saturate_cast(dataB[i]), resC[i + n]); + EXPECT_EQ(saturate_cast((dataA[i] + add) >> s), resD[i]); + EXPECT_EQ(saturate_cast((dataB[i] + add) >> s), resD[i + n]); + EXPECT_EQ(saturate_cast(dataB[i]), resE[i]); + EXPECT_EQ((LaneType)0, resE[i + n]); + EXPECT_EQ(saturate_cast((dataB[i] + add) >> s), resF[i]); + EXPECT_EQ((LaneType)0, resF[i + n]); + } + return *this; + } + + template + TheTest & test_pack_u() + { + typedef typename RegTrait::w_reg Rx2; + typedef typename RegTrait::int_reg Ri2; + typedef typename Ri2::lane_type w_type; + + Data dataA, dataB; + dataA += -10; + dataB *= 10; + Ri2 a = dataA, b = dataB; + + Data resC = v_pack_u(a, b); + Data resD = v_rshr_pack_u(a, b); + + Data resE(0); + v_pack_u_store(resE.d, b); + + Data resF(0); + v_rshr_pack_u_store(resF.d, b); + + const int n = Ri2::nlanes; + const w_type add = (w_type)1 << (s - 1); + for (int i = 0; i < n; ++i) + { + EXPECT_EQ(saturate_cast(dataA[i]), resC[i]); + EXPECT_EQ(saturate_cast(dataB[i]), resC[i + n]); + EXPECT_EQ(saturate_cast((dataA[i] + add) >> s), resD[i]); + EXPECT_EQ(saturate_cast((dataB[i] + add) >> s), resD[i + n]); + EXPECT_EQ(saturate_cast(dataB[i]), resE[i]); + EXPECT_EQ((LaneType)0, resE[i + n]); + EXPECT_EQ(saturate_cast((dataB[i] + add) >> s), resF[i]); + EXPECT_EQ((LaneType)0, resF[i + n]); + } + return *this; + } + + TheTest & test_unpack() + { + Data dataA, dataB; + dataB *= 10; + R a = dataA, b = dataB; + + R c, d, e, f, lo, hi; + v_zip(a, b, c, d); + v_recombine(a, b, e, f); + lo = v_combine_low(a, b); + hi = v_combine_high(a, b); + + Data resC = c, resD = d, resE = e, resF = f, resLo = lo, resHi = hi; + + const int n = R::nlanes/2; + for (int i = 0; i < n; ++i) + { + EXPECT_EQ(dataA[i], resC[i*2]); + EXPECT_EQ(dataB[i], resC[i*2+1]); + EXPECT_EQ(dataA[i+n], resD[i*2]); + EXPECT_EQ(dataB[i+n], resD[i*2+1]); + + EXPECT_EQ(dataA[i], resE[i]); + EXPECT_EQ(dataB[i], resE[i+n]); + EXPECT_EQ(dataA[i+n], resF[i]); + EXPECT_EQ(dataB[i+n], resF[i+n]); + + EXPECT_EQ(dataA[i], resLo[i]); + EXPECT_EQ(dataB[i], resLo[i+n]); + EXPECT_EQ(dataA[i+n], resHi[i]); + EXPECT_EQ(dataB[i+n], resHi[i+n]); + } + + return *this; + } + + template + TheTest & test_extract() + { + Data dataA, dataB; + dataB *= 10; + R a = dataA, b = dataB; + + Data resC = v_extract(a, b); + + for (int i = 0; i < R::nlanes; ++i) + { + if (i + s >= R::nlanes) + EXPECT_EQ(dataB[i - R::nlanes + s], resC[i]); + else + EXPECT_EQ(dataA[i + s], resC[i]); + } + + return *this; + } + + TheTest & test_float_math() + { + typedef typename RegTrait::int_reg Ri; + Data data1, data2, data3; + data1 *= 1.1; + data2 += 10; + R a1 = data1, a2 = data2, a3 = data3; + + Data resB = v_round(a1), + resC = v_trunc(a1), + resD = v_floor(a1), + resE = v_ceil(a1); + + Data resF = v_magnitude(a1, a2), + resG = v_sqr_magnitude(a1, a2), + resH = v_muladd(a1, a2, a3); + + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(cvRound(data1[i]), resB[i]); + EXPECT_EQ((typename Ri::lane_type)data1[i], resC[i]); + EXPECT_EQ(cvFloor(data1[i]), resD[i]); + EXPECT_EQ(cvCeil(data1[i]), resE[i]); + + EXPECT_DOUBLE_EQ(std::sqrt(data1[i]*data1[i] + data2[i]*data2[i]), resF[i]); + EXPECT_DOUBLE_EQ(data1[i]*data1[i] + data2[i]*data2[i], resG[i]); + EXPECT_DOUBLE_EQ(data1[i]*data2[i] + data3[i], resH[i]); + } + + return *this; + } + + TheTest & test_float_cvt32() + { + typedef v_float32x4 Rt; + Data dataA; + dataA *= 1.1; + R a = dataA; + Rt b = v_cvt_f32(a); + Data resB = b; + int n = std::min(Rt::nlanes, R::nlanes); + for (int i = 0; i < n; ++i) + { + EXPECT_EQ((typename Rt::lane_type)dataA[i], resB[i]); + } + return *this; + } + + TheTest & test_float_cvt64() + { +#if CV_SIMD128_64F + typedef v_float64x2 Rt; + Data dataA; + dataA *= 1.1; + R a = dataA; + Rt b = v_cvt_f64(a); + Data resB = b; + int n = std::min(Rt::nlanes, R::nlanes); + for (int i = 0; i < n; ++i) + { + EXPECT_EQ((typename Rt::lane_type)dataA[i], resB[i]); + } +#endif + return *this; + } + + TheTest & test_matmul() + { + Data dataV, dataA, dataB, dataC, dataD; + dataB.reverse(); + dataC += 2; + dataD *= 0.3; + R v = dataV, a = dataA, b = dataB, c = dataC, d = dataD; + + Data res = v_matmul(v, a, b, c, d); + for (int i = 0; i < R::nlanes; ++i) + { + LaneType val = dataV[0] * dataA[i] + + dataV[1] * dataB[i] + + dataV[2] * dataC[i] + + dataV[3] * dataD[i]; + EXPECT_DOUBLE_EQ(val, res[i]); + } + return *this; + } + + TheTest & test_transpose() + { + Data dataA, dataB, dataC, dataD; + dataB *= 5; + dataC *= 10; + dataD *= 15; + R a = dataA, b = dataB, c = dataC, d = dataD; + R e, f, g, h; + v_transpose4x4(a, b, c, d, + e, f, g, h); + + Data res[4] = {e, f, g, h}; + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(dataA[i], res[i][0]); + EXPECT_EQ(dataB[i], res[i][1]); + EXPECT_EQ(dataC[i], res[i][2]); + EXPECT_EQ(dataD[i], res[i][3]); + } + return *this; + } + +}; + + +//============= 8-bit integer ===================================================================== + +TEST(hal_intrin, uint8x16) { + TheTest() + .test_loadstore() + .test_interleave() + .test_expand() + .test_expand_q() + .test_addsub() + .test_addsub_wrap() + .test_cmp() + .test_logic() + .test_min_max() + .test_absdiff() + .test_mask() + .test_pack<1>().test_pack<2>().test_pack<3>().test_pack<8>() + .test_pack_u<1>().test_pack_u<2>().test_pack_u<3>().test_pack_u<8>() + .test_unpack() + .test_extract<0>().test_extract<1>().test_extract<8>().test_extract<15>() + ; +} + +TEST(hal_intrin, int8x16) { + TheTest() + .test_loadstore() + .test_interleave() + .test_expand() + .test_expand_q() + .test_addsub() + .test_addsub_wrap() + .test_cmp() + .test_logic() + .test_min_max() + .test_absdiff() + .test_mask() + .test_pack<1>().test_pack<2>().test_pack<3>().test_pack<8>() + .test_unpack() + .test_extract<0>().test_extract<1>().test_extract<8>().test_extract<15>() + ; +} + +//============= 16-bit integer ===================================================================== + +TEST(hal_intrin, uint16x8) { + TheTest() + .test_loadstore() + .test_interleave() + .test_expand() + .test_addsub() + .test_addsub_wrap() + .test_mul() + .test_mul_expand() + .test_cmp() + .test_shift<1>() + .test_shift<8>() + .test_logic() + .test_min_max() + .test_absdiff() + .test_mask() + .test_pack<1>().test_pack<2>().test_pack<7>().test_pack<16>() + .test_pack_u<1>().test_pack_u<2>().test_pack_u<7>().test_pack_u<16>() + .test_unpack() + .test_extract<0>().test_extract<1>().test_extract<4>().test_extract<7>() + ; +} + +TEST(hal_intrin, int16x8) { + TheTest() + .test_loadstore() + .test_interleave() + .test_expand() + .test_addsub() + .test_addsub_wrap() + .test_mul() + .test_mul_expand() + .test_cmp() + .test_shift<1>() + .test_shift<8>() + .test_dot_prod() + .test_logic() + .test_min_max() + .test_absdiff() + .test_mask() + .test_pack<1>().test_pack<2>().test_pack<7>().test_pack<16>() + .test_unpack() + .test_extract<0>().test_extract<1>().test_extract<4>().test_extract<7>() + ; +} + +//============= 32-bit integer ===================================================================== + +TEST(hal_intrin, uint32x4) { + TheTest() + .test_loadstore() + .test_interleave() + .test_expand() + .test_addsub() + .test_mul() + .test_mul_expand() + .test_cmp() + .test_shift<1>() + .test_shift<8>() + .test_logic() + .test_min_max() + .test_absdiff() + .test_reduce() + .test_mask() + .test_pack<1>().test_pack<2>().test_pack<15>().test_pack<32>() + .test_unpack() + .test_extract<0>().test_extract<1>().test_extract<2>().test_extract<3>() + .test_transpose() + ; +} + +TEST(hal_intrin, int32x4) { + TheTest() + .test_loadstore() + .test_interleave() + .test_expand() + .test_addsub() + .test_mul() + .test_cmp() + .test_shift<1>().test_shift<8>() + .test_logic() + .test_min_max() + .test_absdiff() + .test_reduce() + .test_mask() + .test_pack<1>().test_pack<2>().test_pack<15>().test_pack<32>() + .test_unpack() + .test_extract<0>().test_extract<1>().test_extract<2>().test_extract<3>() + .test_float_cvt32() + .test_float_cvt64() + .test_transpose() + ; +} + +//============= 64-bit integer ===================================================================== + +TEST(hal_intrin, uint64x2) { + TheTest() + .test_loadstore() + .test_addsub() + .test_shift<1>().test_shift<8>() + .test_logic() + .test_extract<0>().test_extract<1>() + ; +} + +TEST(hal_intrin, int64x2) { + TheTest() + .test_loadstore() + .test_addsub() + .test_shift<1>().test_shift<8>() + .test_logic() + .test_extract<0>().test_extract<1>() + ; +} + +//============= Floating point ===================================================================== + +TEST(hal_intrin, float32x4) { + TheTest() + .test_loadstore() + .test_interleave() + .test_addsub() + .test_mul() + .test_div() + .test_cmp() + .test_sqrt_abs() + .test_min_max() + .test_float_absdiff() + .test_reduce() + .test_mask() + .test_unpack() + .test_float_math() + .test_float_cvt64() + .test_matmul() + .test_transpose() + ; +} + +#if CV_SIMD128_64F +TEST(hal_intrin, float64x2) { + TheTest() + .test_loadstore() + .test_addsub() + .test_mul() + .test_div() + .test_cmp() + .test_sqrt_abs() + .test_min_max() + .test_float_absdiff() + .test_mask() + .test_unpack() + .test_float_math() + .test_float_cvt32() + ; +} +#endif diff --git a/modules/hal/test/test_intrin_utils.hpp b/modules/hal/test/test_intrin_utils.hpp new file mode 100644 index 000000000..47473ae46 --- /dev/null +++ b/modules/hal/test/test_intrin_utils.hpp @@ -0,0 +1,234 @@ +#ifndef _TEST_UTILS_HPP_ +#define _TEST_UTILS_HPP_ + +#include "opencv2/hal/intrin.hpp" +#include "opencv2/ts.hpp" +#include +#include + +template struct Data; +template struct initializer; + +template <> struct initializer<16> +{ + template static R init(const Data & d) + { + return R(d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); + } +}; + +template <> struct initializer<8> +{ + template static R init(const Data & d) + { + return R(d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7]); + } +}; + +template <> struct initializer<4> +{ + template static R init(const Data & d) + { + return R(d[0], d[1], d[2], d[3]); + } +}; + +template <> struct initializer<2> +{ + template static R init(const Data & d) + { + return R(d[0], d[1]); + } +}; + +//================================================================================================== + +template struct Data +{ + typedef typename R::lane_type LaneType; + Data() + { + for (int i = 0; i < R::nlanes; ++i) + d[i] = (LaneType)(i + 1); + } + Data(LaneType val) + { + fill(val); + } + Data(const R & r) + { + *this = r; + } + operator R () + { + return initializer().init(*this); + } + Data & operator=(const R & r) + { + v_store(d, r); + return *this; + } + template Data & operator*=(T m) + { + for (int i = 0; i < R::nlanes; ++i) + d[i] *= (LaneType)m; + return *this; + } + template Data & operator+=(T m) + { + for (int i = 0; i < R::nlanes; ++i) + d[i] += (LaneType)m; + return *this; + } + void fill(LaneType val) + { + for (int i = 0; i < R::nlanes; ++i) + d[i] = val; + } + void reverse() + { + for (int i = 0; i < R::nlanes / 2; ++i) + std::swap(d[i], d[R::nlanes - i - 1]); + } + const LaneType & operator[](int i) const + { + CV_Assert(i >= 0 && i < R::nlanes); + return d[i]; + } + LaneType & operator[](int i) + { + CV_Assert(i >= 0 && i < R::nlanes); + return d[i]; + } + const LaneType * mid() const + { + return d + R::nlanes / 2; + } + LaneType * mid() + { + return d + R::nlanes / 2; + } + bool operator==(const Data & other) const + { + for (int i = 0; i < R::nlanes; ++i) + if (d[i] != other.d[i]) + return false; + return true; + } + void clear() + { + fill(0); + } + bool isZero() const + { + return isValue(0); + } + bool isValue(uchar val) const + { + for (int i = 0; i < R::nlanes; ++i) + if (d[i] != val) + return false; + return true; + } + + LaneType d[R::nlanes]; +}; + +template struct AlignedData +{ + Data CV_DECL_ALIGNED(16) a; // aligned + char dummy; + Data u; // unaligned +}; + +template std::ostream & operator<<(std::ostream & out, const Data & d) +{ + out << "{ "; + for (int i = 0; i < R::nlanes; ++i) + { + // out << std::hex << +V_TypeTraits::reinterpret_int(d.d[i]); + out << +d.d[i]; + if (i + 1 < R::nlanes) + out << ", "; + } + out << " }"; + return out; +} + +//================================================================================================== + +template struct RegTrait; + +template <> struct RegTrait { + typedef cv::v_uint16x8 w_reg; + typedef cv::v_uint32x4 q_reg; + typedef cv::v_uint8x16 u_reg; + static cv::v_uint8x16 zero() { return cv::v_setzero_u8(); } + static cv::v_uint8x16 all(uchar val) { return cv::v_setall_u8(val); } +}; +template <> struct RegTrait { + typedef cv::v_int16x8 w_reg; + typedef cv::v_int32x4 q_reg; + typedef cv::v_uint8x16 u_reg; + static cv::v_int8x16 zero() { return cv::v_setzero_s8(); } + static cv::v_int8x16 all(schar val) { return cv::v_setall_s8(val); } +}; + +template <> struct RegTrait { + typedef cv::v_uint32x4 w_reg; + typedef cv::v_int16x8 int_reg; + typedef cv::v_uint16x8 u_reg; + static cv::v_uint16x8 zero() { return cv::v_setzero_u16(); } + static cv::v_uint16x8 all(ushort val) { return cv::v_setall_u16(val); } +}; + +template <> struct RegTrait { + typedef cv::v_int32x4 w_reg; + typedef cv::v_uint16x8 u_reg; + static cv::v_int16x8 zero() { return cv::v_setzero_s16(); } + static cv::v_int16x8 all(short val) { return cv::v_setall_s16(val); } +}; + +template <> struct RegTrait { + typedef cv::v_uint64x2 w_reg; + typedef cv::v_int32x4 int_reg; + typedef cv::v_uint32x4 u_reg; + static cv::v_uint32x4 zero() { return cv::v_setzero_u32(); } + static cv::v_uint32x4 all(unsigned val) { return cv::v_setall_u32(val); } +}; + +template <> struct RegTrait { + typedef cv::v_int64x2 w_reg; + typedef cv::v_uint32x4 u_reg; + static cv::v_int32x4 zero() { return cv::v_setzero_s32(); } + static cv::v_int32x4 all(int val) { return cv::v_setall_s32(val); } +}; + +template <> struct RegTrait { + static cv::v_uint64x2 zero() { return cv::v_setzero_u64(); } + static cv::v_uint64x2 all(uint64 val) { return cv::v_setall_u64(val); } +}; + +template <> struct RegTrait { + static cv::v_int64x2 zero() { return cv::v_setzero_s64(); } + static cv::v_int64x2 all(int64 val) { return cv::v_setall_s64(val); } +}; + +template <> struct RegTrait { + typedef cv::v_int32x4 int_reg; + typedef cv::v_float32x4 u_reg; + static cv::v_float32x4 zero() { return cv::v_setzero_f32(); } + static cv::v_float32x4 all(float val) { return cv::v_setall_f32(val); } +}; + +#if CV_SIMD128_64F +template <> struct RegTrait { + typedef cv::v_int32x4 int_reg; + typedef cv::v_float64x2 u_reg; + static cv::v_float64x2 zero() { return cv::v_setzero_f64(); } + static cv::v_float64x2 all(double val) { return cv::v_setall_f64(val); } +}; + +#endif + +#endif diff --git a/modules/hal/test/test_main.cpp b/modules/hal/test/test_main.cpp new file mode 100644 index 000000000..d337a5ba7 --- /dev/null +++ b/modules/hal/test/test_main.cpp @@ -0,0 +1,3 @@ +#include "opencv2/ts.hpp" + +CV_TEST_MAIN("cv") diff --git a/modules/hal/test/test_precomp.hpp b/modules/hal/test/test_precomp.hpp new file mode 100644 index 000000000..387b7ba2b --- /dev/null +++ b/modules/hal/test/test_precomp.hpp @@ -0,0 +1,11 @@ +#ifndef __OPENCV_HAL_TEST_PRECOMP_HPP__ +#define __OPENCV_HAL_TEST_PRECOMP_HPP__ + +#include +#include +#include "opencv2/ts.hpp" +#include "opencv2/hal.hpp" +#include "opencv2/hal/defs.h" +#include "opencv2/hal/intrin.hpp" + +#endif From e1be6d088833edc5013dfc8c1a0db433a7ce8712 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Tue, 14 Jul 2015 13:23:37 +0300 Subject: [PATCH 017/156] Refactor a section of icvRotatingCalipers to work around a GCC bug https://bugs.launchpad.net/ubuntu/+source/gcc-4.9/+bug/1474304 --- modules/imgproc/src/rotcalipers.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/modules/imgproc/src/rotcalipers.cpp b/modules/imgproc/src/rotcalipers.cpp index bfcc6ea26..c80636bdc 100644 --- a/modules/imgproc/src/rotcalipers.cpp +++ b/modules/imgproc/src/rotcalipers.cpp @@ -184,24 +184,28 @@ static void rotatingCalipers( const Point2f* points, int n, int mode, float* out /* compute cosine of angle between calipers side and polygon edge */ /* dp - dot product */ - float dp0 = base_a * vect[seq[0]].x + base_b * vect[seq[0]].y; - float dp1 = -base_b * vect[seq[1]].x + base_a * vect[seq[1]].y; - float dp2 = -base_a * vect[seq[2]].x - base_b * vect[seq[2]].y; - float dp3 = base_b * vect[seq[3]].x - base_a * vect[seq[3]].y; + float dp[4] = { + +base_a * vect[seq[0]].x + base_b * vect[seq[0]].y, + -base_b * vect[seq[1]].x + base_a * vect[seq[1]].y, + -base_a * vect[seq[2]].x - base_b * vect[seq[2]].y, + +base_b * vect[seq[3]].x - base_a * vect[seq[3]].y, + }; - float cosalpha = dp0 * inv_vect_length[seq[0]]; - float maxcos = cosalpha; + float maxcos = dp[0] * inv_vect_length[seq[0]]; /* number of calipers edges, that has minimal angle with edge */ int main_element = 0; /* choose minimal angle */ - cosalpha = dp1 * inv_vect_length[seq[1]]; - maxcos = (cosalpha > maxcos) ? (main_element = 1, cosalpha) : maxcos; - cosalpha = dp2 * inv_vect_length[seq[2]]; - maxcos = (cosalpha > maxcos) ? (main_element = 2, cosalpha) : maxcos; - cosalpha = dp3 * inv_vect_length[seq[3]]; - maxcos = (cosalpha > maxcos) ? (main_element = 3, cosalpha) : maxcos; + for ( i = 1; i < 4; ++i ) + { + float cosalpha = dp[i] * inv_vect_length[seq[i]]; + if (cosalpha > maxcos) + { + main_element = i; + maxcos = cosalpha; + } + } /*rotate calipers*/ { From a3b515c524b2a35bf178584bb2407ce70a828613 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Wed, 29 Jul 2015 18:03:48 +0300 Subject: [PATCH 018/156] flann: fix AutotunedIndex crashing if a KDTree index is selected Backport of mariusmuja/flann@f8ca6df3. --- modules/flann/include/opencv2/flann/autotuned_index.h | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/flann/include/opencv2/flann/autotuned_index.h b/modules/flann/include/opencv2/flann/autotuned_index.h index 0670d19e2..6ffb9297c 100644 --- a/modules/flann/include/opencv2/flann/autotuned_index.h +++ b/modules/flann/include/opencv2/flann/autotuned_index.h @@ -377,6 +377,7 @@ private: // evaluate kdtree for all parameter combinations for (size_t i = 0; i < FLANN_ARRAY_LEN(testTrees); ++i) { CostData cost; + cost.params["algorithm"] = FLANN_INDEX_KDTREE; cost.params["trees"] = testTrees[i]; evaluate_kdtree(cost); From ec0508269af3e75970701e41755bd11bf527e623 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Thu, 30 Jul 2015 18:03:48 +0300 Subject: [PATCH 019/156] NearestNeighborTest: use ts->get_rng() instead of (implicit) theRNG() This ensures that test data is not dependent on the order the tests are executed in. --- modules/features2d/test/test_nearestneighbors.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/features2d/test/test_nearestneighbors.cpp b/modules/features2d/test/test_nearestneighbors.cpp index df5602520..fb0dbe606 100644 --- a/modules/features2d/test/test_nearestneighbors.cpp +++ b/modules/features2d/test/test_nearestneighbors.cpp @@ -127,7 +127,7 @@ int NearestNeighborTest::checkFind( const Mat& data ) void NearestNeighborTest::run( int /*start_from*/ ) { int code = cvtest::TS::OK, tempCode; Mat desc( featuresCount, dims, CV_32FC1 ); - randu( desc, Scalar(minValue), Scalar(maxValue) ); + ts->get_rng().fill( desc, RNG::UNIFORM, minValue, maxValue ); createModel( desc ); From cd13b30fdef45314e21e4d0e5cef6739915e53f7 Mon Sep 17 00:00:00 2001 From: Tsukasa Sugiura Date: Sat, 12 Sep 2015 01:42:25 +0900 Subject: [PATCH 020/156] Fix LineAA in case of 4 channel Fix bug when enter 4 channel image to LineAA function. --- modules/imgproc/src/drawing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/src/drawing.cpp b/modules/imgproc/src/drawing.cpp index c2db76482..5c4c7e792 100644 --- a/modules/imgproc/src/drawing.cpp +++ b/modules/imgproc/src/drawing.cpp @@ -610,12 +610,12 @@ LineAA( Mat& img, Point pt1, Point pt2, const void* color ) ICV_PUT_POINT(); ICV_PUT_POINT(); - tptr += step; + tptr += 4; a = (ep_corr * FilterTable[dist] >> 8) & 0xff; ICV_PUT_POINT(); ICV_PUT_POINT(); - tptr += step; + tptr += 4; a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff; ICV_PUT_POINT(); ICV_PUT_POINT(); From 11981c31f0057b694d31dc7083d19ea9e738d51f Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 14 Aug 2015 17:57:54 +0300 Subject: [PATCH 021/156] fixed valgrind warning in polylines --- modules/imgproc/src/drawing.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/imgproc/src/drawing.cpp b/modules/imgproc/src/drawing.cpp index c2db76482..3246f2791 100644 --- a/modules/imgproc/src/drawing.cpp +++ b/modules/imgproc/src/drawing.cpp @@ -2232,6 +2232,7 @@ void cv::polylines(InputOutputArray _img, InputArrayOfArrays pts, Mat p = pts.getMat(manyContours ? i : -1); if( p.total() == 0 ) { + ptsptr[i] = NULL; npts[i] = 0; continue; } From 0303e8067ec2118a4a91644b523434d2613db75b Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 15 Aug 2015 00:35:38 +0300 Subject: [PATCH 022/156] fixed memory leak in core ds tests --- modules/core/test/test_ds.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/modules/core/test/test_ds.cpp b/modules/core/test/test_ds.cpp index 25a5f11b1..def3fe20e 100644 --- a/modules/core/test/test_ds.cpp +++ b/modules/core/test/test_ds.cpp @@ -491,6 +491,7 @@ class Core_SeqBaseTest : public Core_DynStructBaseTest { public: Core_SeqBaseTest(); + virtual ~Core_SeqBaseTest(); void clear(); void run( int ); @@ -501,11 +502,14 @@ protected: int test_seq_ops( int iters ); }; - Core_SeqBaseTest::Core_SeqBaseTest() { } +Core_SeqBaseTest::~Core_SeqBaseTest() +{ + clear(); +} void Core_SeqBaseTest::clear() { @@ -1206,6 +1210,7 @@ class Core_SetTest : public Core_DynStructBaseTest { public: Core_SetTest(); + virtual ~Core_SetTest(); void clear(); void run( int ); @@ -1219,6 +1224,10 @@ Core_SetTest::Core_SetTest() { } +Core_SetTest::~Core_SetTest() +{ + clear(); +} void Core_SetTest::clear() { @@ -1417,6 +1426,7 @@ class Core_GraphTest : public Core_DynStructBaseTest { public: Core_GraphTest(); + virtual ~Core_GraphTest(); void clear(); void run( int ); @@ -1430,6 +1440,10 @@ Core_GraphTest::Core_GraphTest() { } +Core_GraphTest::~Core_GraphTest() +{ + clear(); +} void Core_GraphTest::clear() { @@ -2042,6 +2056,8 @@ void Core_GraphScanTest::run( int ) CV_TS_SEQ_CHECK_CONDITION( vtx_count == 0 && edge_count == 0, "Not every vertex/edge has been visited" ); update_progressbar(); + + cvReleaseGraphScanner( &scanner ); } // for a random graph the test just checks that every graph vertex and @@ -2106,8 +2122,6 @@ void Core_GraphScanTest::run( int ) catch(int) { } - - cvReleaseGraphScanner( &scanner ); } From 2a8ef1d06531a6f2198a614493c6b1b37f5b5490 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 15 Aug 2015 10:06:09 +0300 Subject: [PATCH 023/156] fixed memory leaks in cvtyuv tests --- modules/imgproc/test/test_cvtyuv.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/modules/imgproc/test/test_cvtyuv.cpp b/modules/imgproc/test/test_cvtyuv.cpp index 0cce64cdb..7407523fe 100644 --- a/modules/imgproc/test/test_cvtyuv.cpp +++ b/modules/imgproc/test/test_cvtyuv.cpp @@ -548,7 +548,7 @@ void referenceRGB2YUV(const Mat& rgb, Mat& yuv, RGBreader* rgbReader, YUVwriter* struct ConversionYUV { - ConversionYUV( const int code ) + explicit ConversionYUV( const int code ) { yuvReader_ = YUVreader :: getReader(code); yuvWriter_ = YUVwriter :: getWriter(code); @@ -557,6 +557,24 @@ struct ConversionYUV grayWriter_ = GRAYwriter:: getWriter(code); } + ~ConversionYUV() + { + if (yuvReader_) + delete yuvReader_; + + if (yuvWriter_) + delete yuvWriter_; + + if (rgbReader_) + delete rgbReader_; + + if (rgbReader_) + delete rgbReader_; + + if (grayWriter_) + delete grayWriter_; + } + int getDcn() { return (rgbWriter_ != 0) ? rgbWriter_->channels() : ((grayWriter_ != 0) ? grayWriter_->channels() : yuvWriter_->channels()); From 7eba9055e0a81f975399ec09089f32884f1ec91f Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 15 Aug 2015 10:09:31 +0300 Subject: [PATCH 024/156] fixed memory leaks in floodfill tests --- modules/imgproc/test/test_floodfill.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/imgproc/test/test_floodfill.cpp b/modules/imgproc/test/test_floodfill.cpp index d919b1602..bb34449fd 100644 --- a/modules/imgproc/test/test_floodfill.cpp +++ b/modules/imgproc/test/test_floodfill.cpp @@ -508,6 +508,8 @@ _exit_: comp[7] = new_val.val[2]; #endif comp[8] = 0; + + cvReleaseMemStorage(&st); } From 5547398786bc6490a47aa69a3f492ce1e51e0593 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 15 Aug 2015 10:11:52 +0300 Subject: [PATCH 025/156] fixed memory leaks in warpAffine tests --- modules/imgproc/test/test_imgwarp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/imgproc/test/test_imgwarp.cpp b/modules/imgproc/test/test_imgwarp.cpp index 4ffd50b41..441d06243 100644 --- a/modules/imgproc/test/test_imgwarp.cpp +++ b/modules/imgproc/test/test_imgwarp.cpp @@ -1383,6 +1383,9 @@ TEST(Imgproc_cvWarpAffine, regression) int h = src->height; cv2DRotationMatrix(cvPoint2D32f(w*0.5f, h*0.5f), 45.0, 1.0, &M); cvWarpAffine(src, dst, &M); + + cvReleaseImage(&src); + cvReleaseImage(&dst); } TEST(Imgproc_fitLine_vector_3d, regression) From e390c8c728c071071d202b66a0c8cee31b6c4c50 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 15 Aug 2015 16:25:25 +0300 Subject: [PATCH 026/156] fixed typo --- modules/features2d/test/test_nearestneighbors.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/features2d/test/test_nearestneighbors.cpp b/modules/features2d/test/test_nearestneighbors.cpp index fb0dbe606..f8bc9880c 100644 --- a/modules/features2d/test/test_nearestneighbors.cpp +++ b/modules/features2d/test/test_nearestneighbors.cpp @@ -67,13 +67,13 @@ protected: virtual void run( int start_from ); virtual void createModel( const Mat& data ) = 0; virtual int findNeighbors( Mat& points, Mat& neighbors ) = 0; - virtual int checkGetPoins( const Mat& data ); + virtual int checkGetPoints( const Mat& data ); virtual int checkFindBoxed(); virtual int checkFind( const Mat& data ); virtual void releaseModel() = 0; }; -int NearestNeighborTest::checkGetPoins( const Mat& ) +int NearestNeighborTest::checkGetPoints( const Mat& ) { return cvtest::TS::OK; } @@ -131,7 +131,7 @@ void NearestNeighborTest::run( int /*start_from*/ ) { createModel( desc ); - tempCode = checkGetPoins( desc ); + tempCode = checkGetPoints( desc ); if( tempCode != cvtest::TS::OK ) { ts->printf( cvtest::TS::LOG, "bad accuracy of GetPoints \n" ); From 7e26cf569fe5fcaed788a27a6fa66b610d9efbe9 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sun, 16 Aug 2015 11:46:48 +0300 Subject: [PATCH 027/156] typo --- modules/imgproc/test/test_cvtyuv.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/test/test_cvtyuv.cpp b/modules/imgproc/test/test_cvtyuv.cpp index 7407523fe..5db497269 100644 --- a/modules/imgproc/test/test_cvtyuv.cpp +++ b/modules/imgproc/test/test_cvtyuv.cpp @@ -568,8 +568,8 @@ struct ConversionYUV if (rgbReader_) delete rgbReader_; - if (rgbReader_) - delete rgbReader_; + if (rgbWriter_) + delete rgbWriter_; if (grayWriter_) delete grayWriter_; From e7ac52d17a414a055ffcd3f412de5976553f4994 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 20 Aug 2015 12:20:38 +0300 Subject: [PATCH 028/156] fixed "Conditional jump or move depends on uninitialised value" warning --- modules/imgproc/test/test_imgwarp.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/imgproc/test/test_imgwarp.cpp b/modules/imgproc/test/test_imgwarp.cpp index 441d06243..2260cf510 100644 --- a/modules/imgproc/test/test_imgwarp.cpp +++ b/modules/imgproc/test/test_imgwarp.cpp @@ -1377,6 +1377,8 @@ TEST(Imgproc_cvWarpAffine, regression) IplImage* src = cvCreateImage(cvSize(100, 100), IPL_DEPTH_8U, 1); IplImage* dst = cvCreateImage(cvSize(100, 100), IPL_DEPTH_8U, 1); + cvZero(src); + float m[6]; CvMat M = cvMat( 2, 3, CV_32F, m ); int w = src->width; From d81a0df489516aed803f02c8d4a3666591e5d7ba Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 20 Aug 2015 13:28:10 +0300 Subject: [PATCH 029/156] fixed memory leak caused by illegal memory access --- modules/imgproc/test/test_imgwarp_strict.cpp | 30 ++++---------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/modules/imgproc/test/test_imgwarp_strict.cpp b/modules/imgproc/test/test_imgwarp_strict.cpp index 00d383a02..4756b7f42 100644 --- a/modules/imgproc/test/test_imgwarp_strict.cpp +++ b/modules/imgproc/test/test_imgwarp_strict.cpp @@ -651,8 +651,7 @@ private: }; CV_Remap_Test::CV_Remap_Test() : - CV_ImageWarpBaseTest(), mapx(), mapy(), - borderType(-1), borderValue() + CV_ImageWarpBaseTest(), borderType(-1) { funcs[0] = &CV_Remap_Test::remap_nearest; funcs[1] = &CV_Remap_Test::remap_generic; @@ -673,7 +672,7 @@ void CV_Remap_Test::generate_test_data() // generating the mapx, mapy matrices static const int mapx_types[] = { CV_16SC2, CV_32FC1, CV_32FC2 }; mapx.create(dst.size(), mapx_types[rng.uniform(0, sizeof(mapx_types) / sizeof(int))]); - mapy = Mat(); + mapy.release(); const int n = std::min(std::min(src.cols, src.rows) / 10 + 1, 2); float _n = 0; //static_cast(-n); @@ -700,7 +699,7 @@ void CV_Remap_Test::generate_test_data() { MatIterator_ begin_y = mapy.begin(), end_y = mapy.end(); for ( ; begin_y != end_y; ++begin_y) - begin_y[0] = static_cast(rng.uniform(0, 1024)); + *begin_y = static_cast(rng.uniform(0, 1024)); } break; @@ -708,7 +707,7 @@ void CV_Remap_Test::generate_test_data() { MatIterator_ begin_y = mapy.begin(), end_y = mapy.end(); for ( ; begin_y != end_y; ++begin_y) - begin_y[0] = static_cast(rng.uniform(0, 1024)); + *begin_y = static_cast(rng.uniform(0, 1024)); } break; } @@ -725,8 +724,8 @@ void CV_Remap_Test::generate_test_data() MatIterator_ begin_y = mapy.begin(); for ( ; begin_x != end_x; ++begin_x, ++begin_y) { - begin_x[0] = rng.uniform(_n, fscols); - begin_y[0] = rng.uniform(_n, fsrows); + *begin_x = rng.uniform(_n, fscols); + *begin_y = rng.uniform(_n, fsrows); } } break; @@ -794,23 +793,6 @@ void CV_Remap_Test::prepare_test_data_for_reference_func() { CV_ImageWarpBaseTest::prepare_test_data_for_reference_func(); convert_maps(); -/* - const int ksize = 3; - Mat kernel = getStructuringElement(CV_MOP_ERODE, Size(ksize, ksize)); - Mat mask(src.size(), CV_8UC1, Scalar::all(255)), dst_mask; - cv::erode(src, erode_src, kernel); - cv::erode(mask, dst_mask, kernel, Point(-1, -1), 1, BORDER_CONSTANT, Scalar::all(0)); - bitwise_not(dst_mask, mask); - src.copyTo(erode_src, mask); - dst_mask.release(); - - mask = Scalar::all(0); - kernel = getStructuringElement(CV_MOP_DILATE, kernel.size()); - cv::dilate(src, dilate_src, kernel); - cv::dilate(mask, dst_mask, kernel, Point(-1, -1), 1, BORDER_CONSTANT, Scalar::all(255)); - src.copyTo(dilate_src, dst_mask); - dst_mask.release(); -*/ } void CV_Remap_Test::run_reference_func() From 274b361ca32085d5add70f9dcd43db3149515c3e Mon Sep 17 00:00:00 2001 From: Dikay900 Date: Sat, 12 Sep 2015 12:19:44 +0200 Subject: [PATCH 030/156] proposed change by psyill --- 3rdparty/tbb/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/3rdparty/tbb/CMakeLists.txt b/3rdparty/tbb/CMakeLists.txt index 24b6f6b79..93d943523 100644 --- a/3rdparty/tbb/CMakeLists.txt +++ b/3rdparty/tbb/CMakeLists.txt @@ -212,7 +212,13 @@ else() endif() ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef -Wmissing-declarations) -string(REPLACE "-Werror=non-virtual-dtor" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + +# filter out flags that are not handled well by the TBB code +foreach(var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG) + string(REPLACE "-Werror=non-virtual-dtor" "" ${var} "${${var}}") + string(REPLACE "-fvisibility=hidden" "" ${var} "${${var}}") + string(REPLACE "-fvisibility-inlines-hidden" "" ${var} "${${var}}") +endforeach() if (WIN32) set(tbb_debug_postfix "_debug") # to fit pragmas in _windef.h inside TBB From f7d36bbad5b9ea45636a8dee7854ef0539c98370 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 31 Aug 2015 17:20:52 +0300 Subject: [PATCH 031/156] fixed memory leaks in modules/features2d/test/test_nearestneighbors.cpp --- modules/features2d/test/test_nearestneighbors.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/features2d/test/test_nearestneighbors.cpp b/modules/features2d/test/test_nearestneighbors.cpp index f8bc9880c..84079fdc7 100644 --- a/modules/features2d/test/test_nearestneighbors.cpp +++ b/modules/features2d/test/test_nearestneighbors.cpp @@ -161,7 +161,7 @@ void NearestNeighborTest::run( int /*start_from*/ ) { class CV_FlannTest : public NearestNeighborTest { public: - CV_FlannTest() {} + CV_FlannTest() : NearestNeighborTest(), index(NULL) { } protected: void createIndex( const Mat& data, const IndexParams& params ); int knnSearch( Mat& points, Mat& neighbors ); @@ -172,6 +172,9 @@ protected: void CV_FlannTest::createIndex( const Mat& data, const IndexParams& params ) { + // release previously allocated index + releaseModel(); + index = new Index( data, params ); } @@ -238,7 +241,11 @@ int CV_FlannTest::radiusSearch( Mat& points, Mat& neighbors ) void CV_FlannTest::releaseModel() { - delete index; + if (index) + { + delete index; + index = NULL; + } } //--------------------------------------- From cf0f47f589a8524c37eaabc0977abf79bb1d3be9 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 31 Aug 2015 17:30:42 +0300 Subject: [PATCH 032/156] fixed memory leak in descriptor regression tests --- modules/features2d/test/test_descriptors_regression.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/features2d/test/test_descriptors_regression.cpp b/modules/features2d/test/test_descriptors_regression.cpp index 5ebf508d8..717cae58d 100644 --- a/modules/features2d/test/test_descriptors_regression.cpp +++ b/modules/features2d/test/test_descriptors_regression.cpp @@ -60,7 +60,7 @@ static void writeMatInBin( const Mat& mat, const string& filename ) fwrite( (void*)&mat.rows, sizeof(int), 1, f ); fwrite( (void*)&mat.cols, sizeof(int), 1, f ); fwrite( (void*)&type, sizeof(int), 1, f ); - int dataSize = (int)(mat.step * mat.rows * mat.channels()); + int dataSize = (int)(mat.step * mat.rows); fwrite( (void*)&dataSize, sizeof(int), 1, f ); fwrite( (void*)mat.ptr(), 1, dataSize, f ); fclose(f); @@ -82,13 +82,14 @@ static Mat readMatFromBin( const string& filename ) int step = dataSize / rows / CV_ELEM_SIZE(type); CV_Assert(step >= cols); - Mat m = Mat(rows, step, type).colRange(0, cols); + Mat returnMat = Mat(rows, step, type).colRange(0, cols); - size_t elements_read = fread( m.ptr(), 1, dataSize, f ); + size_t elements_read = fread( returnMat.ptr(), 1, dataSize, f ); CV_Assert(elements_read == (size_t)(dataSize)); + fclose(f); - return m; + return returnMat; } return Mat(); } From 1d77d697efd113e5d912ae7136f79088d6363eab Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 1 Sep 2015 11:40:23 +0300 Subject: [PATCH 033/156] fixed memory leak in GBTrees --- modules/ml/src/gbt.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/ml/src/gbt.cpp b/modules/ml/src/gbt.cpp index 0ebe19ea3..e41d6c2a1 100644 --- a/modules/ml/src/gbt.cpp +++ b/modules/ml/src/gbt.cpp @@ -1274,13 +1274,18 @@ CvGBTrees::calc_error( CvMLData* _data, int type, std::vector *resp ) return -FLT_MAX; float* pred_resp = 0; + bool needsFreeing = false; + if (resp) { resp->resize(n); pred_resp = &((*resp)[0]); } else + { pred_resp = new float[n]; + needsFreeing = true; + } Sample_predictor predictor = Sample_predictor(this, pred_resp, _data->get_values(), _data->get_missing(), _sample_idx); @@ -1313,6 +1318,9 @@ CvGBTrees::calc_error( CvMLData* _data, int type, std::vector *resp ) err = err / (float)n; } + if (needsFreeing) + delete[]pred_resp; + return err; } From ee2008abe8ea6507f54d0641d01a6fbc8b83e735 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 1 Sep 2015 13:22:49 +0300 Subject: [PATCH 034/156] fixed "Conditional jump or move depends on uninitialised value(s)" in GBD --- modules/ml/src/gbt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ml/src/gbt.cpp b/modules/ml/src/gbt.cpp index e41d6c2a1..76baa0001 100644 --- a/modules/ml/src/gbt.cpp +++ b/modules/ml/src/gbt.cpp @@ -243,7 +243,7 @@ CvGBTrees::train( const CvMat* _train_data, int _tflag, for (int i=1; idata.fl[i]) - class_labels->data.i[k]) && (kdata.fl[i]) - class_labels->data.i[k])) k++; if (k == j) { From df21a24f8151c0a46b915fe2b2a4bf0a8e8eef09 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 3 Sep 2015 17:21:04 +0300 Subject: [PATCH 035/156] initialize padding of CvString with zeros --- modules/core/src/datastructs.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/core/src/datastructs.cpp b/modules/core/src/datastructs.cpp index 519d00ee5..34ed64dbe 100644 --- a/modules/core/src/datastructs.cpp +++ b/modules/core/src/datastructs.cpp @@ -352,6 +352,7 @@ CV_IMPL CvString cvMemStorageAllocString( CvMemStorage* storage, const char* ptr, int len ) { CvString str; + memset(&str, 0, sizeof(CvString)); str.len = len >= 0 ? len : (int)strlen(ptr); str.ptr = (char*)cvMemStorageAlloc( storage, str.len + 1 ); From 3143f2fb503977f5670cef513ce3411671af18d0 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 3 Sep 2015 13:25:29 +0300 Subject: [PATCH 036/156] fixed uninitialized memory writing/reading in flann --- modules/flann/include/opencv2/flann/kmeans_index.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/flann/include/opencv2/flann/kmeans_index.h b/modules/flann/include/opencv2/flann/kmeans_index.h index b49b8ddde..226fc71f3 100644 --- a/modules/flann/include/opencv2/flann/kmeans_index.h +++ b/modules/flann/include/opencv2/flann/kmeans_index.h @@ -441,6 +441,8 @@ public: } root_ = pool_.allocate(); + std::memset(root_, 0, sizeof(KMeansNode)); + computeNodeStatistics(root_, indices_, (int)size_); computeClustering(root_, indices_, (int)size_, branching_,0); } @@ -864,11 +866,11 @@ private: variance -= distance_(centers[c], ZeroIterator(), veclen_); node->childs[c] = pool_.allocate(); + std::memset(node->childs[c], 0, sizeof(KMeansNode)); node->childs[c]->radius = radiuses[c]; node->childs[c]->pivot = centers[c]; node->childs[c]->variance = variance; node->childs[c]->mean_radius = mean_radius; - node->childs[c]->indices = NULL; computeClustering(node->childs[c],indices+start, end-start, branching, level+1); start=end; } From 5eb67cc2cbbec9be5aaf690579abcb67538e350e Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 2 Sep 2015 18:15:05 +0300 Subject: [PATCH 037/156] fix for corrent modules dependencies --- cmake/OpenCVModule.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index 30325eb30..5e7a03d5b 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -56,6 +56,8 @@ foreach(mod ${OPENCV_MODULES_BUILD} ${OPENCV_MODULES_DISABLED_USER} ${OPENCV_MOD if(HAVE_${mod}) unset(HAVE_${mod} CACHE) endif() + unset(OPENCV_MODULE_${mod}_DEPS CACHE) + unset(OPENCV_MODULE_${mod}_DEPS_EXT CACHE) unset(OPENCV_MODULE_${mod}_REQ_DEPS CACHE) unset(OPENCV_MODULE_${mod}_OPT_DEPS CACHE) unset(OPENCV_MODULE_${mod}_PRIVATE_REQ_DEPS CACHE) From b57be28920b0f8f3aafed017a33d197433e6e758 Mon Sep 17 00:00:00 2001 From: Adam Gibson Date: Mon, 14 Sep 2015 00:00:22 +0800 Subject: [PATCH 038/156] Various Python samples updated for Python 2/3 compatibility. --- samples/python2/_coverage.py | 7 +++++-- samples/python2/_doc.py | 14 +++++++++++--- samples/python2/browse.py | 20 ++++++++++++++------ samples/python2/calibrate.py | 17 ++++++++++------- samples/python2/camshift.py | 12 ++++++++++-- samples/python2/coherence.py | 16 ++++++++++++---- samples/python2/common.py | 26 +++++++++++++++++++++----- samples/python2/deconvolution.py | 7 +++++-- samples/python2/demo.py | 24 ++++++++++++++++++------ samples/python2/dft.py | 5 ++++- samples/python2/distrans.py | 8 +++++--- samples/python2/edge.py | 5 ++++- samples/python2/facedetect.py | 5 ++++- samples/python2/fitline.py | 18 +++++++++++++++--- samples/python2/floodfill.py | 11 +++++++---- samples/python2/gabor_threads.py | 9 ++++++--- samples/python2/grabcut.py | 29 ++++++++++++++++------------- samples/python2/houghcircles.py | 5 ++++- samples/python2/houghlines.py | 5 ++++- samples/python2/inpaint.py | 7 +++++-- samples/python2/kalman.py | 9 ++++++++- samples/python2/lappyr.py | 10 +++++++++- samples/python2/lk_homography.py | 5 ++++- samples/python2/lk_track.py | 5 ++++- samples/python2/logpolar.py | 6 +++++- samples/python2/morphology.py | 28 ++++++++++++++++++++++------ samples/python2/mosse.py | 10 +++++++++- samples/python2/mouse_and_match.py | 8 ++++++-- samples/python2/opencv_version.py | 11 +++++++---- samples/python2/peopledetect.py | 13 ++++++++----- samples/python2/squares.py | 7 +++++++ samples/python2/turing.py | 12 ++++++++++-- samples/python2/video.py | 9 ++++++--- samples/python2/video_threaded.py | 4 +++- 34 files changed, 288 insertions(+), 99 deletions(-) diff --git a/samples/python2/_coverage.py b/samples/python2/_coverage.py index 4b23370b5..5ec3e18a9 100755 --- a/samples/python2/_coverage.py +++ b/samples/python2/_coverage.py @@ -4,6 +4,9 @@ Utility for measuring python opencv API coverage by samples. ''' +# Python 2/3 compatibility +from __future__ import print_function + from glob import glob import cv2 import re @@ -13,7 +16,7 @@ if __name__ == '__main__': found = set() for fn in glob('*.py'): - print ' --- ', fn + print(' --- ', fn) code = open(fn).read() found |= set(re.findall('cv2?\.\w+', code)) @@ -23,4 +26,4 @@ if __name__ == '__main__': f.write('\n'.join(sorted(cv2_unused))) r = 1.0 * len(cv2_used) / len(cv2_callable) - print '\ncv2 api coverage: %d / %d (%.1f%%)' % ( len(cv2_used), len(cv2_callable), r*100 ) + print('\ncv2 api coverage: %d / %d (%.1f%%)' % ( len(cv2_used), len(cv2_callable), r*100 )) diff --git a/samples/python2/_doc.py b/samples/python2/_doc.py index fe2b6f32b..eddf26fba 100755 --- a/samples/python2/_doc.py +++ b/samples/python2/_doc.py @@ -5,12 +5,20 @@ Scans current directory for *.py files and reports ones with missing __doc__ string. ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + from glob import glob if __name__ == '__main__': - print '--- undocumented files:' + print('--- undocumented files:') for fn in glob('*.py'): loc = {} - execfile(fn, loc) + if PY3: + exec(open(fn).read(), loc) + else: + execfile(fn, loc) if '__doc__' not in loc: - print fn + print(fn) diff --git a/samples/python2/browse.py b/samples/python2/browse.py index 462cd1762..317a8db11 100755 --- a/samples/python2/browse.py +++ b/samples/python2/browse.py @@ -12,6 +12,14 @@ browse.py [image filename] ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + xrange = range + import numpy as np import cv2 @@ -19,21 +27,21 @@ import cv2 import sys if __name__ == '__main__': - print 'This sample shows how to implement a simple hi resolution image navigation.' - print 'USAGE: browse.py [image filename]' - print + print('This sample shows how to implement a simple hi resolution image navigation.') + print('USAGE: browse.py [image filename]') + print() if len(sys.argv) > 1: fn = sys.argv[1] - print 'loading %s ...' % fn + print('loading %s ...' % fn) img = cv2.imread(fn) if img is None: - print 'Failed to load fn:', fn + print('Failed to load fn:', fn) sys.exit(1) else: sz = 4096 - print 'generating %dx%d procedural image ...' % (sz, sz) + print('generating %dx%d procedural image ...' % (sz, sz)) img = np.zeros((sz, sz), np.uint8) track = np.cumsum(np.random.rand(500000, 2)-0.5, axis=0) track = np.int32(track*10 + (sz/2, sz/2)) diff --git a/samples/python2/calibrate.py b/samples/python2/calibrate.py index 9f6f60cb7..24e4aa7d0 100755 --- a/samples/python2/calibrate.py +++ b/samples/python2/calibrate.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 @@ -41,10 +44,10 @@ if __name__ == '__main__': img_points = [] h, w = 0, 0 for fn in img_names: - print 'processing %s...' % fn, + print('processing %s...' % fn,) img = cv2.imread(fn, 0) if img is None: - print "Failed to load", fn + print("Failed to load", fn) continue h, w = img.shape[:2] @@ -58,15 +61,15 @@ if __name__ == '__main__': path, name, ext = splitfn(fn) cv2.imwrite('%s/%s_chess.bmp' % (debug_dir, name), vis) if not found: - print 'chessboard not found' + print('chessboard not found') continue img_points.append(corners.reshape(-1, 2)) obj_points.append(pattern_points) - print 'ok' + print('ok') rms, camera_matrix, dist_coefs, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, (w, h), None, None) - print "RMS:", rms - print "camera matrix:\n", camera_matrix - print "distortion coefficients: ", dist_coefs.ravel() + print("RMS:", rms) + print("camera matrix:\n", camera_matrix) + print("distortion coefficients: ", dist_coefs.ravel()) cv2.destroyAllWindows() diff --git a/samples/python2/camshift.py b/samples/python2/camshift.py index 72c790803..862d5126a 100755 --- a/samples/python2/camshift.py +++ b/samples/python2/camshift.py @@ -22,6 +22,14 @@ Keys: b - toggle back-projected probability visualization ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + xrange = range + import numpy as np import cv2 @@ -103,7 +111,7 @@ class App(object): try: cv2.ellipse(vis, track_box, (0, 0, 255), 2) except: - print track_box + print(track_box) cv2.imshow('camshift', vis) @@ -121,5 +129,5 @@ if __name__ == '__main__': video_src = sys.argv[1] except: video_src = 0 - print __doc__ + print(__doc__) App(video_src).run() diff --git a/samples/python2/coherence.py b/samples/python2/coherence.py index 46d7414af..8ca61fcb2 100755 --- a/samples/python2/coherence.py +++ b/samples/python2/coherence.py @@ -9,6 +9,14 @@ inspired by http://www.mia.uni-saarland.de/Publications/weickert-dagm03.pdf ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + xrange = range + import numpy as np import cv2 @@ -16,7 +24,7 @@ def coherence_filter(img, sigma = 11, str_sigma = 11, blend = 0.5, iter_n = 4): h, w = img.shape[:2] for i in xrange(iter_n): - print i, + print(i) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) eigen = cv2.cornerEigenValsAndVecs(gray, str_sigma, 3) @@ -34,7 +42,7 @@ def coherence_filter(img, sigma = 11, str_sigma = 11, blend = 0.5, iter_n = 4): img1 = ero img1[m] = dil[m] img = np.uint8(img*(1.0 - blend) + img1*blend) - print 'done' + print('done') return img @@ -54,7 +62,7 @@ if __name__ == '__main__': sigma = cv2.getTrackbarPos('sigma', 'control')*2+1 str_sigma = cv2.getTrackbarPos('str_sigma', 'control')*2+1 blend = cv2.getTrackbarPos('blend', 'control') / 10.0 - print 'sigma: %d str_sigma: %d blend_coef: %f' % (sigma, str_sigma, blend) + print('sigma: %d str_sigma: %d blend_coef: %f' % (sigma, str_sigma, blend)) dst = coherence_filter(src, sigma=sigma, str_sigma = str_sigma, blend = blend) cv2.imshow('dst', dst) @@ -64,7 +72,7 @@ if __name__ == '__main__': cv2.createTrackbar('str_sigma', 'control', 9, 15, nothing) - print 'Press SPACE to update the image\n' + print('Press SPACE to update the image\n') cv2.imshow('src', src) update() diff --git a/samples/python2/common.py b/samples/python2/common.py index 0ad811ae2..785fb6c8f 100755 --- a/samples/python2/common.py +++ b/samples/python2/common.py @@ -4,6 +4,14 @@ This module contains some common routines used by other samples. ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + from functools import reduce + import numpy as np import cv2 @@ -70,7 +78,8 @@ def mtx2rvec(R): axis = np.cross(vt[0], vt[1]) return axis * np.arctan2(s, c) -def draw_str(dst, (x, y), s): +def draw_str(dst, target, s): + x, y = target cv2.putText(dst, s, (x+1, y+1), cv2.FONT_HERSHEY_PLAIN, 1.0, (0, 0, 0), thickness = 2, lineType=cv2.LINE_AA) cv2.putText(dst, s, (x, y), cv2.FONT_HERSHEY_PLAIN, 1.0, (255, 255, 255), lineType=cv2.LINE_AA) @@ -135,12 +144,12 @@ def clock(): @contextmanager def Timer(msg): - print msg, '...', + print(msg, '...',) start = clock() try: yield finally: - print "%.2f ms" % ((clock()-start)*1000) + print("%.2f ms" % ((clock()-start)*1000)) class StatValue: def __init__(self, smooth_coef = 0.5): @@ -192,7 +201,11 @@ class RectSelector: def grouper(n, iterable, fillvalue=None): '''grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx''' args = [iter(iterable)] * n - return it.izip_longest(fillvalue=fillvalue, *args) + if PY3: + output = it.zip_longest(fillvalue=fillvalue, *args) + else: + output = it.izip_longest(fillvalue=fillvalue, *args) + return output def mosaic(w, imgs): '''Make a grid from images. @@ -201,7 +214,10 @@ def mosaic(w, imgs): imgs -- images (must have same size and format) ''' imgs = iter(imgs) - img0 = imgs.next() + if PY3: + img0 = next(imgs) + else: + img0 = imgs.next() pad = np.zeros_like(img0) imgs = it.chain([img0], imgs) rows = grouper(w, imgs, pad) diff --git a/samples/python2/deconvolution.py b/samples/python2/deconvolution.py index bbb1567bd..ce798538b 100755 --- a/samples/python2/deconvolution.py +++ b/samples/python2/deconvolution.py @@ -30,6 +30,9 @@ Examples: [1] http://en.wikipedia.org/wiki/Wiener_deconvolution ''' +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 @@ -63,7 +66,7 @@ def defocus_kernel(d, sz=65): if __name__ == '__main__': - print __doc__ + print(__doc__) import sys, getopt opts, args = getopt.getopt(sys.argv[1:], '', ['circle', 'angle=', 'd=', 'snr=']) opts = dict(opts) @@ -76,7 +79,7 @@ if __name__ == '__main__': img = cv2.imread(fn, 0) if img is None: - print 'Failed to load fn1:', fn1 + print('Failed to load fn1:', fn1) sys.exit(1) img = np.float32(img)/255.0 diff --git a/samples/python2/demo.py b/samples/python2/demo.py index 03d624ddc..864953a31 100755 --- a/samples/python2/demo.py +++ b/samples/python2/demo.py @@ -4,16 +4,25 @@ Sample-launcher application. ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + # local modules from common import splitfn # built-in modules -import sys import webbrowser -import Tkinter as tk from glob import glob from subprocess import Popen -from ScrolledText import ScrolledText + +if PY3: + import tkinter as tk + from tkinter.scrolledtext import ScrolledText +else: + import Tkinter as tk + from ScrolledText import ScrolledText #from IPython.Shell import IPShellEmbed @@ -97,14 +106,17 @@ class App: run_btn.pack() def on_link(self, url): - print url + print(url) webbrowser.open(url) def on_demo_select(self, evt): name = self.demos_lb.get( self.demos_lb.curselection()[0] ) fn = self.samples[name] loc = {} - execfile(fn, loc) + if PY3: + exec(open(fn).read(), loc) + else: + execfile(fn, loc) descr = loc.get('__doc__', 'no-description') self.linker.reset() @@ -152,7 +164,7 @@ class App: def on_run(self, *args): cmd = self.cmd_entry.get() - print 'running:', cmd + print('running:', cmd) Popen(sys.executable + ' ' + cmd, shell=True) def run(self): diff --git a/samples/python2/dft.py b/samples/python2/dft.py index a1622b53e..d617438a8 100755 --- a/samples/python2/dft.py +++ b/samples/python2/dft.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +# Python 2/3 compatibility +from __future__ import print_function + import cv2 import numpy as np import sys @@ -57,7 +60,7 @@ if __name__ == "__main__": im = cv2.imread(sys.argv[1]) else : im = cv2.imread('../data/baboon.jpg') - print "usage : python dft.py " + print("usage : python dft.py ") # convert to grayscale im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) diff --git a/samples/python2/distrans.py b/samples/python2/distrans.py index 819a06c9b..00e173d52 100755 --- a/samples/python2/distrans.py +++ b/samples/python2/distrans.py @@ -11,6 +11,8 @@ Keys: v - toggle voronoi mode ''' +# Python 2/3 compatibility +from __future__ import print_function import numpy as np import cv2 @@ -23,11 +25,11 @@ if __name__ == '__main__': fn = sys.argv[1] except: fn = '../data/fruits.jpg' - print __doc__ + print(__doc__) img = cv2.imread(fn, 0) if img is None: - print 'Failed to load fn:', fn + print('Failed to load fn:', fn) sys.exit(1) cm = make_cmap('jet') @@ -62,7 +64,7 @@ if __name__ == '__main__': break if ch == ord('v'): voronoi = not voronoi - print 'showing', ['distance', 'voronoi'][voronoi] + print('showing', ['distance', 'voronoi'][voronoi]) update() if need_update: update() diff --git a/samples/python2/edge.py b/samples/python2/edge.py index 413bf8859..61d8466bc 100755 --- a/samples/python2/edge.py +++ b/samples/python2/edge.py @@ -10,6 +10,9 @@ Usage: ''' +# Python 2/3 compatibility +from __future__ import print_function + import cv2 # relative module @@ -20,7 +23,7 @@ import sys if __name__ == '__main__': - print __doc__ + print(__doc__) try: fn = sys.argv[1] diff --git a/samples/python2/facedetect.py b/samples/python2/facedetect.py index 8c6b27ab1..2349087dc 100755 --- a/samples/python2/facedetect.py +++ b/samples/python2/facedetect.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 @@ -24,7 +27,7 @@ def draw_rects(img, rects, color): if __name__ == '__main__': import sys, getopt - print help_message + print(help_message) args, video_src = getopt.getopt(sys.argv[1:], '', ['cascade=', 'nested-cascade=']) try: diff --git a/samples/python2/fitline.py b/samples/python2/fitline.py index 1c0d9e770..95fb2b8d1 100755 --- a/samples/python2/fitline.py +++ b/samples/python2/fitline.py @@ -22,6 +22,11 @@ f - change distance function ESC - exit ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + import numpy as np import cv2 @@ -43,7 +48,11 @@ def sample_line(p1, p2, n, noise=0.0): return p1 + (p2-p1)*t + np.random.normal(size=(n, 2))*noise dist_func_names = it.cycle('DIST_L2 DIST_L1 DIST_L12 DIST_FAIR DIST_WELSCH DIST_HUBER'.split()) -cur_func_name = dist_func_names.next() + +if PY3: + cur_func_name = next(dist_func_names) +else: + cur_func_name = dist_func_names.next() def update(_=None): noise = cv2.getTrackbarPos('noise', 'fit line') @@ -71,7 +80,7 @@ def update(_=None): cv2.imshow('fit line', img) if __name__ == '__main__': - print __doc__ + print(__doc__) cv2.namedWindow('fit line') cv2.createTrackbar('noise', 'fit line', 3, 50, update) @@ -81,6 +90,9 @@ if __name__ == '__main__': update() ch = cv2.waitKey(0) & 0xFF if ch == ord('f'): - cur_func_name = dist_func_names.next() + if PY3: + cur_func_name = next(dist_func_names) + else: + cur_func_name = dist_func_names.next() if ch == 27: break diff --git a/samples/python2/floodfill.py b/samples/python2/floodfill.py index 5152f30c1..161c6323f 100755 --- a/samples/python2/floodfill.py +++ b/samples/python2/floodfill.py @@ -14,6 +14,9 @@ Keys: ESC - exit ''' +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 @@ -23,11 +26,11 @@ if __name__ == '__main__': fn = sys.argv[1] except: fn = '../data/fruits.jpg' - print __doc__ + print(__doc__) img = cv2.imread(fn, True) if img is None: - print 'Failed to load image file:', fn + print('Failed to load image file:', fn) sys.exit(1) h, w = img.shape[:2] @@ -68,10 +71,10 @@ if __name__ == '__main__': break if ch == ord('f'): fixed_range = not fixed_range - print 'using %s range' % ('floating', 'fixed')[fixed_range] + print('using %s range' % ('floating', 'fixed')[fixed_range]) update() if ch == ord('c'): connectivity = 12-connectivity - print 'connectivity =', connectivity + print('connectivity =', connectivity) update() cv2.destroyAllWindows() diff --git a/samples/python2/gabor_threads.py b/samples/python2/gabor_threads.py index b004fb758..f7d62c17e 100755 --- a/samples/python2/gabor_threads.py +++ b/samples/python2/gabor_threads.py @@ -14,6 +14,9 @@ gabor_threads.py [image filename] ''' +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 from multiprocessing.pool import ThreadPool @@ -48,7 +51,7 @@ if __name__ == '__main__': import sys from common import Timer - print __doc__ + print(__doc__) try: img_fn = sys.argv[1] except: @@ -56,7 +59,7 @@ if __name__ == '__main__': img = cv2.imread(img_fn) if img is None: - print 'Failed to load image file:', img_fn + print('Failed to load image file:', img_fn) sys.exit(1) filters = build_filters() @@ -66,7 +69,7 @@ if __name__ == '__main__': with Timer('running multi-threaded'): res2 = process_threaded(img, filters) - print 'res1 == res2: ', (res1 == res2).all() + print('res1 == res2: ', (res1 == res2).all()) cv2.imshow('img', img) cv2.imshow('result', res2) cv2.waitKey() diff --git a/samples/python2/grabcut.py b/samples/python2/grabcut.py index 2c8aa1ef1..19378e6cc 100644 --- a/samples/python2/grabcut.py +++ b/samples/python2/grabcut.py @@ -27,6 +27,9 @@ Key 's' - To save the results =============================================================================== ''' +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 import sys @@ -72,13 +75,13 @@ def onmouse(event,x,y,flags,param): cv2.rectangle(img,(ix,iy),(x,y),BLUE,2) rect = (min(ix,x),min(iy,y),abs(ix-x),abs(iy-y)) rect_or_mask = 0 - print " Now press the key 'n' a few times until no further change \n" + print(" Now press the key 'n' a few times until no further change \n") # draw touchup curves if event == cv2.EVENT_LBUTTONDOWN: if rect_over == False: - print "first draw rectangle \n" + print("first draw rectangle \n") else: drawing = True cv2.circle(img,(x,y),thickness,value['color'],-1) @@ -98,14 +101,14 @@ def onmouse(event,x,y,flags,param): if __name__ == '__main__': # print documentation - print __doc__ + print(__doc__) # Loading images if len(sys.argv) == 2: filename = sys.argv[1] # for drawing purposes else: - print "No input image given, so loading default image, ../data/lena.jpg \n" - print "Correct Usage: python grabcut.py \n" + print("No input image given, so loading default image, ../data/lena.jpg \n") + print("Correct Usage: python grabcut.py \n") filename = '../data/lena.jpg' img = cv2.imread(filename) @@ -119,8 +122,8 @@ if __name__ == '__main__': cv2.setMouseCallback('input',onmouse) cv2.moveWindow('input',img.shape[1]+10,90) - print " Instructions: \n" - print " Draw a rectangle around the object using right mouse button \n" + print(" Instructions: \n") + print(" Draw a rectangle around the object using right mouse button \n") while(1): @@ -132,10 +135,10 @@ if __name__ == '__main__': if k == 27: # esc to exit break elif k == ord('0'): # BG drawing - print " mark background regions with left mouse button \n" + print(" mark background regions with left mouse button \n") value = DRAW_BG elif k == ord('1'): # FG drawing - print " mark foreground regions with left mouse button \n" + print(" mark foreground regions with left mouse button \n") value = DRAW_FG elif k == ord('2'): # PR_BG drawing value = DRAW_PR_BG @@ -145,9 +148,9 @@ if __name__ == '__main__': bar = np.zeros((img.shape[0],5,3),np.uint8) res = np.hstack((img2,bar,img,bar,output)) cv2.imwrite('grabcut_output.png',res) - print " Result saved as image \n" + print(" Result saved as image \n") elif k == ord('r'): # reset everything - print "resetting \n" + print("resetting \n") rect = (0,0,1,1) drawing = False rectangle = False @@ -158,8 +161,8 @@ if __name__ == '__main__': mask = np.zeros(img.shape[:2],dtype = np.uint8) # mask initialized to PR_BG output = np.zeros(img.shape,np.uint8) # output image to be shown elif k == ord('n'): # segment the image - print """ For finer touchups, mark foreground and background after pressing keys 0-3 - and again press 'n' \n""" + print(""" For finer touchups, mark foreground and background after pressing keys 0-3 + and again press 'n' \n""") if (rect_or_mask == 0): # grabcut with rect bgdmodel = np.zeros((1,65),np.float64) fgdmodel = np.zeros((1,65),np.float64) diff --git a/samples/python2/houghcircles.py b/samples/python2/houghcircles.py index 9d68c2ce8..fe87d8f3e 100755 --- a/samples/python2/houghcircles.py +++ b/samples/python2/houghcircles.py @@ -6,13 +6,16 @@ Usage: ./houghcircles.py [] image argument defaults to ../data/board.jpg ''' +# Python 2/3 compatibility +from __future__ import print_function + import cv2 import numpy as np import sys if __name__ == '__main__': - print __doc__ + print(__doc__) try: fn = sys.argv[1] except: diff --git a/samples/python2/houghlines.py b/samples/python2/houghlines.py index cd25a56f8..674b26ec7 100755 --- a/samples/python2/houghlines.py +++ b/samples/python2/houghlines.py @@ -4,6 +4,9 @@ This example illustrates how to use Hough Transform to find lines Usage: ./houghlines.py [] image argument defaults to ../data/pic1.png ''' +# Python 2/3 compatibility +from __future__ import print_function + import cv2 import numpy as np import sys @@ -15,7 +18,7 @@ if __name__ == '__main__': fn = sys.argv[1] except: fn = "../data/pic1.png" - print __doc__ + print(__doc__) src = cv2.imread(fn) dst = cv2.Canny(src, 50, 200) cdst = cv2.cvtColor(dst, cv2.COLOR_GRAY2BGR) diff --git a/samples/python2/inpaint.py b/samples/python2/inpaint.py index 4ff1ddb6e..0ca72f1a2 100755 --- a/samples/python2/inpaint.py +++ b/samples/python2/inpaint.py @@ -15,6 +15,9 @@ Keys: ESC - exit ''' +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 from common import Sketcher @@ -26,11 +29,11 @@ if __name__ == '__main__': except: fn = '../data/fruits.jpg' - print __doc__ + print(__doc__) img = cv2.imread(fn) if img is None: - print 'Failed to load image file:', fn + print('Failed to load image file:', fn) sys.exit(1) img_mark = img.copy() diff --git a/samples/python2/kalman.py b/samples/python2/kalman.py index 101f1ea56..8e3748b4d 100755 --- a/samples/python2/kalman.py +++ b/samples/python2/kalman.py @@ -11,6 +11,13 @@ Pressing any key (except ESC) will reset the tracking with a different speed. Pressing ESC will stop the program. """ +# Python 2/3 compatibility +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + long = int + import cv2 from math import cos, sin import numpy as np @@ -21,7 +28,7 @@ if __name__ == "__main__": img_width = 500 kalman = cv2.KalmanFilter(2, 1, 0) - code = -1L + code = long(-1) cv2.namedWindow("Kalman") diff --git a/samples/python2/lappyr.py b/samples/python2/lappyr.py index 3cf2679b0..19f5bd918 100755 --- a/samples/python2/lappyr.py +++ b/samples/python2/lappyr.py @@ -12,6 +12,14 @@ References: Alexander Mordvintsev 6/10/12 ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + xrange = range + import numpy as np import cv2 import video @@ -38,7 +46,7 @@ def merge_lappyr(levels): if __name__ == '__main__': import sys - print __doc__ + print(__doc__) try: fn = sys.argv[1] diff --git a/samples/python2/lk_homography.py b/samples/python2/lk_homography.py index ae8b2d49b..a9e92546c 100755 --- a/samples/python2/lk_homography.py +++ b/samples/python2/lk_homography.py @@ -20,6 +20,9 @@ SPACE - start tracking r - toggle RANSAC ''' +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 import video @@ -108,7 +111,7 @@ def main(): except: video_src = 0 - print __doc__ + print(__doc__) App(video_src).run() cv2.destroyAllWindows() diff --git a/samples/python2/lk_track.py b/samples/python2/lk_track.py index 1ff90ff7e..8aa94fe64 100755 --- a/samples/python2/lk_track.py +++ b/samples/python2/lk_track.py @@ -18,6 +18,9 @@ Keys ESC - exit ''' +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 import video @@ -93,7 +96,7 @@ def main(): except: video_src = 0 - print __doc__ + print(__doc__) App(video_src).run() cv2.destroyAllWindows() diff --git a/samples/python2/logpolar.py b/samples/python2/logpolar.py index 783c7b81a..60695bfd8 100644 --- a/samples/python2/logpolar.py +++ b/samples/python2/logpolar.py @@ -1,4 +1,8 @@ #!/usr/bin/env python + +# Python 2/3 compatibility +from __future__ import print_function + import cv2 if __name__ == '__main__': @@ -10,7 +14,7 @@ if __name__ == '__main__': img = cv2.imread(fn) if img is None: - print 'Failed to load image file:', fn + print('Failed to load image file:', fn) sys.exit(1) img2 = cv2.logPolar(img, (img.shape[0]/2, img.shape[1]/2), 40, cv2.WARP_FILL_OUTLIERS) diff --git a/samples/python2/morphology.py b/samples/python2/morphology.py index 76fa76c69..be287d33d 100755 --- a/samples/python2/morphology.py +++ b/samples/python2/morphology.py @@ -12,12 +12,17 @@ Keys: ESC - exit ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + import numpy as np import cv2 if __name__ == '__main__': - print __doc__ + print(__doc__) import sys from itertools import cycle @@ -31,15 +36,20 @@ if __name__ == '__main__': img = cv2.imread(fn) if img is None: - print 'Failed to load image file:', fn + print('Failed to load image file:', fn) sys.exit(1) cv2.imshow('original', img) modes = cycle(['erode/dilate', 'open/close', 'blackhat/tophat', 'gradient']) str_modes = cycle(['ellipse', 'rect', 'cross']) - cur_mode = modes.next() - cur_str_mode = str_modes.next() + + if PY3: + cur_mode = next(modes) + cur_str_mode = next(str_modes) + else: + cur_mode = modes.next() + cur_str_mode = str_modes.next() def update(dummy=None): sz = cv2.getTrackbarPos('op/size', 'morphology') @@ -73,8 +83,14 @@ if __name__ == '__main__': if ch == 27: break if ch == ord('1'): - cur_mode = modes.next() + if PY3: + cur_mode = next(modes) + else: + cur_mode = modes.next() if ch == ord('2'): - cur_str_mode = str_modes.next() + if PY3: + cur_str_mode = next(str_modes) + else: + cur_str_mode = str_modes.next() update() cv2.destroyAllWindows() diff --git a/samples/python2/mosse.py b/samples/python2/mosse.py index 81196dcc3..29a3a697f 100755 --- a/samples/python2/mosse.py +++ b/samples/python2/mosse.py @@ -21,6 +21,14 @@ Keys: http://www.cs.colostate.edu/~bolme/publications/Bolme2010Tracking.pdf ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + xrange = range + import numpy as np import cv2 from common import draw_str, RectSelector @@ -178,7 +186,7 @@ class App: if __name__ == '__main__': - print __doc__ + print (__doc__) import sys, getopt opts, args = getopt.getopt(sys.argv[1:], '', ['pause']) opts = dict(opts) diff --git a/samples/python2/mouse_and_match.py b/samples/python2/mouse_and_match.py index 7937140e3..c0b03d77e 100755 --- a/samples/python2/mouse_and_match.py +++ b/samples/python2/mouse_and_match.py @@ -8,6 +8,10 @@ Demonstrate using a mouse to interact with an image: When they let go of the mouse, it correlates (using matchTemplate) that patch with the image. ESC to exit ''' + +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 @@ -46,7 +50,7 @@ def onmouse(event, x, y, flags, param): cv2.rectangle(img, (sel[0], sel[1]), (sel[2], sel[3]), (0,255,255), 1) cv2.imshow("gray", img) else: - print "selection is complete" + print("selection is complete") drag_start = None if __name__ == '__main__': @@ -61,7 +65,7 @@ if __name__ == '__main__': for infile in glob.glob( os.path.join(path, '*.*') ): ext = os.path.splitext(infile)[1][1:] #get the filename extenstion if ext == "png" or ext == "jpg" or ext == "bmp" or ext == "tiff" or ext == "pbm": - print infile + print(infile) img=cv2.imread(infile,1) if img == None: diff --git a/samples/python2/opencv_version.py b/samples/python2/opencv_version.py index 8c966f18e..44f197736 100644 --- a/samples/python2/opencv_version.py +++ b/samples/python2/opencv_version.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +# Python 2/3 compatibility +from __future__ import print_function + import cv2 if __name__ == '__main__': @@ -10,9 +13,9 @@ if __name__ == '__main__': param = "" if ("--build" == param): - print cv2.getBuildInformation() + print(cv2.getBuildInformation()) elif ("--help" == param): - print "\t--build\n\t\tprint complete build info" - print "\t--help\n\t\tprint this help" + print("\t--build\n\t\tprint complete build info") + print("\t--help\n\t\tprint this help") else: - print "Welcome to OpenCV" + print("Welcome to OpenCV") diff --git a/samples/python2/peopledetect.py b/samples/python2/peopledetect.py index 9d945dbcc..c8843e05e 100755 --- a/samples/python2/peopledetect.py +++ b/samples/python2/peopledetect.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 @@ -27,20 +30,20 @@ if __name__ == '__main__': from glob import glob import itertools as it - print help_message + print(help_message) hog = cv2.HOGDescriptor() hog.setSVMDetector( cv2.HOGDescriptor_getDefaultPeopleDetector() ) for fn in it.chain(*map(glob, sys.argv[1:])): - print fn, ' - ', + print(fn, ' - ',) try: img = cv2.imread(fn) if img is None: - print 'Failed to load image file:', fn + print('Failed to load image file:', fn) continue except: - print 'loading error' + print('loading error') continue found, w = hog.detectMultiScale(img, winStride=(8,8), padding=(32,32), scale=1.05) @@ -53,7 +56,7 @@ if __name__ == '__main__': found_filtered.append(r) draw_detections(img, found) draw_detections(img, found_filtered, 3) - print '%d (%d) found' % (len(found_filtered), len(found)) + print('%d (%d) found' % (len(found_filtered), len(found))) cv2.imshow('img', img) ch = 0xFF & cv2.waitKey() if ch == 27: diff --git a/samples/python2/squares.py b/samples/python2/squares.py index 84160a291..512ad617d 100755 --- a/samples/python2/squares.py +++ b/samples/python2/squares.py @@ -6,6 +6,13 @@ Simple "Square Detector" program. Loads several images sequentially and tries to find squares in each image. ''' +# Python 2/3 compatibility +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + xrange = range + import numpy as np import cv2 diff --git a/samples/python2/turing.py b/samples/python2/turing.py index 94816e6c3..f9926ba90 100755 --- a/samples/python2/turing.py +++ b/samples/python2/turing.py @@ -7,6 +7,14 @@ Multiscale Turing Patterns generator Inspired by http://www.jonathanmccabe.com/Cyclic_Symmetric_Multi-Scale_Turing_Patterns.pdf ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + xrange = range + import numpy as np import cv2 from common import draw_str @@ -20,7 +28,7 @@ Press ESC to stop. ''' if __name__ == '__main__': - print help_message + print(help_message) w, h = 512, 512 @@ -30,7 +38,7 @@ if __name__ == '__main__': if '-o' in args: fn = args['-o'] out = cv2.VideoWriter(args['-o'], cv2.VideoWriter_fourcc(*'DIB '), 30.0, (w, h), False) - print 'writing %s ...' % fn + print('writing %s ...' % fn) a = np.zeros((h, w), np.float32) cv2.randu(a, np.array([0]), np.array([1])) diff --git a/samples/python2/video.py b/samples/python2/video.py index 227b13f37..8bdec7440 100755 --- a/samples/python2/video.py +++ b/samples/python2/video.py @@ -29,6 +29,9 @@ Keys: ''' +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np from numpy import pi, sin, cos @@ -162,7 +165,7 @@ def create_capture(source = 0, fallback = presets['chess']): cap.set(cv2.CAP_PROP_FRAME_WIDTH, w) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, h) if cap is None or not cap.isOpened(): - print 'Warning: unable to open video source: ', source + print('Warning: unable to open video source: ', source) if fallback is not None: return create_capture(fallback, None) return cap @@ -171,7 +174,7 @@ if __name__ == '__main__': import sys import getopt - print __doc__ + print(__doc__) args, sources = getopt.getopt(sys.argv[1:], '', 'shotdir=') args = dict(args) @@ -194,6 +197,6 @@ if __name__ == '__main__': for i, img in enumerate(imgs): fn = '%s/shot_%d_%03d.bmp' % (shotdir, i, shot_idx) cv2.imwrite(fn, img) - print fn, 'saved' + print(fn, 'saved') shot_idx += 1 cv2.destroyAllWindows() diff --git a/samples/python2/video_threaded.py b/samples/python2/video_threaded.py index a638791c8..76d764b62 100755 --- a/samples/python2/video_threaded.py +++ b/samples/python2/video_threaded.py @@ -15,6 +15,8 @@ Keyboard shortcuts: space - switch between multi and single threaded processing ''' +# Python 2/3 compatibility +from __future__ import print_function import numpy as np import cv2 @@ -37,7 +39,7 @@ class DummyTask: if __name__ == '__main__': import sys - print __doc__ + print(__doc__) try: fn = sys.argv[1] From 37d300f250cbcc3b42d672fceb1d9f72433b2ed5 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 14 Sep 2015 00:12:06 +0800 Subject: [PATCH 039/156] Correction of minor typo. --- .../py_gui/py_video_display/py_video_display.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/py_tutorials/py_gui/py_video_display/py_video_display.markdown b/doc/py_tutorials/py_gui/py_video_display/py_video_display.markdown index b82e9f582..7b532ac9a 100644 --- a/doc/py_tutorials/py_gui/py_video_display/py_video_display.markdown +++ b/doc/py_tutorials/py_gui/py_video_display/py_video_display.markdown @@ -113,7 +113,7 @@ platform dependent. Following codecs works fine for me. - In OSX : *(I don't have access to OSX. Can some one fill this?)* FourCC code is passed as cv2.VideoWriter_fourcc('M','J','P','G') or -cv2.VideoWriter_fourcc(\*'MJPG) for MJPG. +cv2.VideoWriter_fourcc(\*'MJPG') for MJPG. Below code capture from a Camera, flip every frame in vertical direction and saves it. @code{.py} From a413423ff6499b66037b3c51f416b7c5af14eab3 Mon Sep 17 00:00:00 2001 From: Adam Gibson Date: Mon, 14 Sep 2015 12:24:08 +0800 Subject: [PATCH 040/156] Reverted _doc.py to Python 2-only version. Interim measure to prevent docs from failing during build, until all samples are updated with Python 2/3 compatibility. --- samples/python2/_doc.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/samples/python2/_doc.py b/samples/python2/_doc.py index eddf26fba..fe2b6f32b 100755 --- a/samples/python2/_doc.py +++ b/samples/python2/_doc.py @@ -5,20 +5,12 @@ Scans current directory for *.py files and reports ones with missing __doc__ string. ''' -# Python 2/3 compatibility -from __future__ import print_function -import sys -PY3 = sys.version_info[0] == 3 - from glob import glob if __name__ == '__main__': - print('--- undocumented files:') + print '--- undocumented files:' for fn in glob('*.py'): loc = {} - if PY3: - exec(open(fn).read(), loc) - else: - execfile(fn, loc) + execfile(fn, loc) if '__doc__' not in loc: - print(fn) + print fn From 4f2612fcfd151def98c02d5f6113683e9c2a90e2 Mon Sep 17 00:00:00 2001 From: Adam Gibson Date: Mon, 14 Sep 2015 13:03:16 +0800 Subject: [PATCH 041/156] Removed trailing whitespace from squares.py compatibility comment. --- samples/python2/squares.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/python2/squares.py b/samples/python2/squares.py index 512ad617d..cc33144de 100755 --- a/samples/python2/squares.py +++ b/samples/python2/squares.py @@ -6,7 +6,7 @@ Simple "Square Detector" program. Loads several images sequentially and tries to find squares in each image. ''' -# Python 2/3 compatibility +# Python 2/3 compatibility import sys PY3 = sys.version_info[0] == 3 From 603864dba282fe5d497c4a1b39ec5aac2cc4aebb Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Mon, 14 Sep 2015 12:15:56 +0300 Subject: [PATCH 042/156] Warning fix --- modules/hal/test/test_intrin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/hal/test/test_intrin.cpp b/modules/hal/test/test_intrin.cpp index ae043dd20..681fe3fd0 100644 --- a/modules/hal/test/test_intrin.cpp +++ b/modules/hal/test/test_intrin.cpp @@ -317,7 +317,7 @@ template struct TheTest for (int i = 0; i < R::nlanes; ++i) { EXPECT_FLOAT_EQ((float)std::sqrt(dataA[i]), (float)resB[i]); - EXPECT_FLOAT_EQ((float)1/std::sqrt(dataA[i]), (float)resC[i]); + EXPECT_FLOAT_EQ(1/(float)std::sqrt(dataA[i]), (float)resC[i]); EXPECT_FLOAT_EQ((float)abs(dataA[i]), (float)resE[i]); } From fcf971bded521365b09389cdbfbcf0bdfe103b84 Mon Sep 17 00:00:00 2001 From: Philip Salvaggio Date: Mon, 14 Sep 2015 09:25:32 -0400 Subject: [PATCH 043/156] Improved documentation for connectedComponentsWithStats. --- modules/imgproc/include/opencv2/imgproc.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index f57edb6d7..d8ded742c 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -3404,8 +3404,9 @@ CV_EXPORTS_W int connectedComponents(InputArray image, OutputArray labels, @param labels destination labeled image @param stats statistics output for each label, including the background label, see below for available statistics. Statistics are accessed via stats(label, COLUMN) where COLUMN is one of -cv::ConnectedComponentsTypes -@param centroids floating point centroid (x,y) output for each label, including the background label +cv::ConnectedComponentsTypes. The data type is CV_32S. +@param centroids centroid output for each label, including the background label. Centroids are +accessed via centroids(label, 0) for x and centroids(label, 1) for y. The data type CV_64F. @param connectivity 8 or 4 for 8-way or 4-way connectivity respectively @param ltype output image label type. Currently CV_32S and CV_16U are supported. */ From e0ef2936459341530b0fff815e79f3c0608db6e1 Mon Sep 17 00:00:00 2001 From: art-programmer Date: Mon, 14 Sep 2015 19:35:53 -0500 Subject: [PATCH 044/156] Update em.cpp Fix a bug. When reading from a saved model, function decomposeCovs() will be called. And if covMatType is COV_MAT_DIAGONAL, covsEigenValues is computed using SVD and eigen values are sorted so that the order of eigen values is not preserved. This would lead to different result when calling function predict2. This issues is discussed here: http://stackoverflow.com/questions/23485982/got-different-empredict-results-after-emread-saved-model-in-opencv. --- modules/ml/src/em.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ml/src/em.cpp b/modules/ml/src/em.cpp index 59c1352e4..c837b0d63 100644 --- a/modules/ml/src/em.cpp +++ b/modules/ml/src/em.cpp @@ -379,7 +379,7 @@ public: } else if(covMatType == COV_MAT_DIAGONAL) { - covsEigenValues[clusterIndex] = svd.w; + covsEigenValues[clusterIndex] = covs[clusterIndex].diag().clone(); //Preserve the original order of eigen values. } else //COV_MAT_GENERIC { From 1a18fa1c9466c1195729ea2601da31700a936c33 Mon Sep 17 00:00:00 2001 From: Renato Florentino Garcia Date: Wed, 16 Sep 2015 21:16:23 -0300 Subject: [PATCH 045/156] Correct a typo. --- modules/core/include/opencv2/core/matx.hpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/core/include/opencv2/core/matx.hpp b/modules/core/include/opencv2/core/matx.hpp index 2a17744e5..9bbcc37a7 100644 --- a/modules/core/include/opencv2/core/matx.hpp +++ b/modules/core/include/opencv2/core/matx.hpp @@ -494,7 +494,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0) template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1) { - CV_StaticAssert(channels >= 2, "Matx should have at least 2 elaments."); + CV_StaticAssert(channels >= 2, "Matx should have at least 2 elements."); val[0] = v0; val[1] = v1; for(int i = 2; i < channels; i++) val[i] = _Tp(0); } @@ -502,7 +502,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1) template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2) { - CV_StaticAssert(channels >= 3, "Matx should have at least 3 elaments."); + CV_StaticAssert(channels >= 3, "Matx should have at least 3 elements."); val[0] = v0; val[1] = v1; val[2] = v2; for(int i = 3; i < channels; i++) val[i] = _Tp(0); } @@ -510,7 +510,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2) template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3) { - CV_StaticAssert(channels >= 4, "Matx should have at least 4 elaments."); + CV_StaticAssert(channels >= 4, "Matx should have at least 4 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; for(int i = 4; i < channels; i++) val[i] = _Tp(0); } @@ -518,7 +518,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3) template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4) { - CV_StaticAssert(channels >= 5, "Matx should have at least 5 elaments."); + CV_StaticAssert(channels >= 5, "Matx should have at least 5 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; for(int i = 5; i < channels; i++) val[i] = _Tp(0); } @@ -526,7 +526,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4) template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5) { - CV_StaticAssert(channels >= 6, "Matx should have at least 6 elaments."); + CV_StaticAssert(channels >= 6, "Matx should have at least 6 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; val[5] = v5; for(int i = 6; i < channels; i++) val[i] = _Tp(0); @@ -535,7 +535,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5) template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6) { - CV_StaticAssert(channels >= 7, "Matx should have at least 7 elaments."); + CV_StaticAssert(channels >= 7, "Matx should have at least 7 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; val[5] = v5; val[6] = v6; for(int i = 7; i < channels; i++) val[i] = _Tp(0); @@ -544,7 +544,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6) template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7) { - CV_StaticAssert(channels >= 8, "Matx should have at least 8 elaments."); + CV_StaticAssert(channels >= 8, "Matx should have at least 8 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7; for(int i = 8; i < channels; i++) val[i] = _Tp(0); @@ -553,7 +553,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _T template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8) { - CV_StaticAssert(channels >= 9, "Matx should have at least 9 elaments."); + CV_StaticAssert(channels >= 9, "Matx should have at least 9 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7; val[8] = v8; @@ -563,7 +563,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _T template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9) { - CV_StaticAssert(channels >= 10, "Matx should have at least 10 elaments."); + CV_StaticAssert(channels >= 10, "Matx should have at least 10 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7; val[8] = v8; val[9] = v9; @@ -574,7 +574,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _T template inline Matx<_Tp,m,n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9, _Tp v10, _Tp v11) { - CV_StaticAssert(channels == 12, "Matx should have at least 12 elaments."); + CV_StaticAssert(channels == 12, "Matx should have at least 12 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7; val[8] = v8; val[9] = v9; val[10] = v10; val[11] = v11; @@ -583,7 +583,7 @@ Matx<_Tp,m,n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp template inline Matx<_Tp,m,n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9, _Tp v10, _Tp v11, _Tp v12, _Tp v13, _Tp v14, _Tp v15) { - CV_StaticAssert(channels == 16, "Matx should have at least 16 elaments."); + CV_StaticAssert(channels == 16, "Matx should have at least 16 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7; val[8] = v8; val[9] = v9; val[10] = v10; val[11] = v11; From e9037644c3eac665748ad9a80da3f127cce1716d Mon Sep 17 00:00:00 2001 From: StevenPuttemans Date: Thu, 17 Sep 2015 14:15:20 +0200 Subject: [PATCH 046/156] add link to contributing guidelines --- CONTRIBUTING.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..1e13c8996 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +## Contributing guidelines + +All guidelines for contributing to the OpenCV repository can be found at [`How to contribute guideline`](https://github.com/Itseez/opencv/wiki/How_to_contribute). From aa485ccd753ffa5174ceba53049dd93fb757d94b Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Wed, 16 Sep 2015 14:00:36 +0300 Subject: [PATCH 047/156] TLS keys leak fix; Disables TLS copy constructor and operator, as they can lead to errors and reservation of too much keys in TLS storage; gather method was added to TLS to gather data from all threads; --- modules/core/include/opencv2/core/utility.hpp | 12 ++++ modules/core/src/system.cpp | 56 +++++++++++++++---- 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/modules/core/include/opencv2/core/utility.hpp b/modules/core/include/opencv2/core/utility.hpp index dcb625b3d..7e89dc28e 100644 --- a/modules/core/include/opencv2/core/utility.hpp +++ b/modules/core/include/opencv2/core/utility.hpp @@ -520,6 +520,7 @@ protected: TLSDataContainer(); virtual ~TLSDataContainer(); + void gatherData(std::vector &data) const; #if OPENCV_ABI_COMPATIBILITY > 300 void* getData() const; void release(); @@ -546,9 +547,20 @@ public: inline ~TLSData() { release(); } // Release key and delete associated data inline T* get() const { return (T*)getData(); } // Get data assosiated with key + // Get data from all threads + inline void gather(std::vector &data) const + { + std::vector &dataVoid = reinterpret_cast&>(data); + gatherData(dataVoid); + } + private: virtual void* createDataInstance() const {return new T;} // Wrapper to allocate data by template virtual void deleteDataInstance(void* pData) const {delete (T*)pData;} // Wrapper to release data by template + + // Disable TLS copy operations + TLSData(TLSData &) {}; + TLSData& operator =(const TLSData &) {return *this;}; }; /** @brief Designed for command line parsing diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index 743341daf..337414918 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -1034,7 +1034,7 @@ class TlsStorage public: TlsStorage() { - tlsSlots = 0; + tlsSlots.reserve(32); threads.reserve(32); } ~TlsStorage() @@ -1077,15 +1077,27 @@ public: size_t reserveSlot() { AutoLock guard(mtxGlobalAccess); - tlsSlots++; - return (tlsSlots-1); + + // Find unused slots + for(size_t slot = 0; slot < tlsSlots.size(); slot++) + { + if(!tlsSlots[slot]) + { + tlsSlots[slot] = 1; + return slot; + } + } + + // Create new slot + tlsSlots.push_back(1); + return (tlsSlots.size()-1); } // Release TLS storage index and pass assosiated data to caller void releaseSlot(size_t slotIdx, std::vector &dataVec) { AutoLock guard(mtxGlobalAccess); - CV_Assert(tlsSlots > slotIdx); + CV_Assert(tlsSlots.size() > slotIdx); for(size_t i = 0; i < threads.size(); i++) { @@ -1096,15 +1108,14 @@ public: threads[i]->slots[slotIdx] = 0; } } - // If we removing last element, decriment slots size to save space - if(tlsSlots-1 == slotIdx) - tlsSlots--; + + tlsSlots[slotIdx] = 0; } // Get data by TLS storage index void* getData(size_t slotIdx) const { - CV_Assert(tlsSlots > slotIdx); + CV_Assert(tlsSlots.size() > slotIdx); ThreadData* threadData = (ThreadData*)tls.GetData(); if(threadData && threadData->slots.size() > slotIdx) @@ -1113,10 +1124,24 @@ public: return NULL; } + // Gather data from threads by TLS storage index + void gather(size_t slotIdx, std::vector &dataVec) + { + AutoLock guard(mtxGlobalAccess); + CV_Assert(tlsSlots.size() > slotIdx); + + for(size_t i = 0; i < threads.size(); i++) + { + std::vector& thread_slots = threads[i]->slots; + if (thread_slots.size() > slotIdx && thread_slots[slotIdx]) + dataVec.push_back(thread_slots[slotIdx]); + } + } + // Set data to storage index void setData(size_t slotIdx, void* pData) { - CV_Assert(pData != NULL); + CV_Assert(tlsSlots.size() > slotIdx && pData != NULL); ThreadData* threadData = (ThreadData*)tls.GetData(); if(!threadData) @@ -1131,7 +1156,11 @@ public: } if(slotIdx >= threadData->slots.size()) - threadData->slots.resize(slotIdx+1); + { + AutoLock guard(mtxGlobalAccess); + while(slotIdx >= threadData->slots.size()) + threadData->slots.push_back(NULL); + } threadData->slots[slotIdx] = pData; } @@ -1139,7 +1168,7 @@ private: TlsAbstraction tls; // TLS abstraction layer instance Mutex mtxGlobalAccess; // Shared objects operation guard - size_t tlsSlots; // TLS storage counter + std::vector tlsSlots; // TLS keys state std::vector threads; // Array for all allocated data. Thread data pointers are placed here to allow data cleanup }; @@ -1159,6 +1188,11 @@ TLSDataContainer::~TLSDataContainer() CV_Assert(key_ == -1); // Key must be released in child object } +void TLSDataContainer::gatherData(std::vector &data) const +{ + getTlsStorage().gather(key_, data); +} + void TLSDataContainer::release() { std::vector data; From f88e9a748a37e5df00912524e590fb295e7dab70 Mon Sep 17 00:00:00 2001 From: jisli Date: Tue, 8 Sep 2015 16:35:40 -0700 Subject: [PATCH 048/156] update ffmpeg support Migration have been done for these ffmpeg/libav changes: 2013-12-11 - 29c83d2 / b9fb59d,409a143 / 9431356,44967ab / d7b3ee9 - lavc 55.45.101 / 55.28.1 - avcodec.h av_frame_alloc(), av_frame_unref() and av_frame_free() now can and should be used instead of avcodec_alloc_frame(), avcodec_get_frame_defaults() and avcodec_free_frame() respectively. The latter three functions are deprecated. 2012-10-08 - ae77266 / 78071a1 - lavu 51.74.100 / 51.42.0 - pixfmt.h Rename PixelFormat to AVPixelFormat and all PIX_FMT_* to AV_PIX_FMT_*. To provide backwards compatibility, PixelFormat is now #defined as AVPixelFormat. Note that this can break user code that includes pixfmt.h and uses the 'PixelFormat' identifier. Such code should either #undef PixelFormat or stop using the PixelFormat name. --- modules/videoio/src/cap_ffmpeg_impl.hpp | 86 +++++++++++++++---------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index 93c730a1b..4f743ec76 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -127,12 +127,6 @@ extern "C" { #define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__) #endif -/* PIX_FMT_RGBA32 macro changed in newer ffmpeg versions */ -#ifndef PIX_FMT_RGBA32 -#define PIX_FMT_RGBA32 PIX_FMT_RGB32 -#endif - - #if defined WIN32 || defined _WIN32 #include #elif defined __linux__ || defined __APPLE__ @@ -166,6 +160,20 @@ extern "C" { # define CV_CODEC(name) name #endif +#if LIBAVUTIL_BUILD < (LIBAVUTIL_VERSION_MICRO >= 100 \ + ? CALC_FFMPEG_VERSION(51, 74, 100) : CALC_FFMPEG_VERSION(51, 42, 0)) +#define AVPixelFormat PixelFormat +#define AV_PIX_FMT_BGR24 PIX_FMT_BGR24 +#define AV_PIX_FMT_RGB24 PIX_FMT_RGB24 +#define AV_PIX_FMT_GRAY8 PIX_FMT_GRAY8 +#define AV_PIX_FMT_YUV422P PIX_FMT_YUV422P +#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P +#define AV_PIX_FMT_YUV444P PIX_FMT_YUV444P +#define AV_PIX_FMT_YUVJ420P PIX_FMT_YUVJ420P +#define AV_PIX_FMT_GRAY16LE PIX_FMT_GRAY16LE +#define AV_PIX_FMT_GRAY16BE PIX_FMT_GRAY16BE +#endif + static int get_number_of_cpus(void) { #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(52, 111, 0) @@ -311,8 +319,10 @@ void CvCapture_FFMPEG::close() if( picture ) { - // FFmpeg and Libav added avcodec_free_frame in different versions. #if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \ + ? CALC_FFMPEG_VERSION(55, 45, 101) : CALC_FFMPEG_VERSION(55, 28, 1)) + av_frame_free(&picture); +#elif LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \ ? CALC_FFMPEG_VERSION(54, 59, 100) : CALC_FFMPEG_VERSION(54, 28, 0)) avcodec_free_frame(&picture); #else @@ -629,13 +639,18 @@ bool CvCapture_FFMPEG::open( const char* _filename ) video_stream = i; video_st = ic->streams[i]; +#if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \ + ? CALC_FFMPEG_VERSION(55, 45, 101) : CALC_FFMPEG_VERSION(55, 28, 1)) + picture = av_frame_alloc(); +#else picture = avcodec_alloc_frame(); +#endif rgb_picture.data[0] = (uint8_t*)malloc( - avpicture_get_size( PIX_FMT_BGR24, + avpicture_get_size( AV_PIX_FMT_BGR24, enc->width, enc->height )); avpicture_fill( (AVPicture*)&rgb_picture, rgb_picture.data[0], - PIX_FMT_BGR24, enc->width, enc->height ); + AV_PIX_FMT_BGR24, enc->width, enc->height ); frame.width = enc->width; frame.height = enc->height; @@ -735,7 +750,7 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* if( !video_st || !picture->data[0] ) return false; - avpicture_fill((AVPicture*)&rgb_picture, rgb_picture.data[0], PIX_FMT_RGB24, + avpicture_fill((AVPicture*)&rgb_picture, rgb_picture.data[0], AV_PIX_FMT_RGB24, video_st->codec->width, video_st->codec->height); if( img_convert_ctx == NULL || @@ -753,7 +768,7 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* video_st->codec->width, video_st->codec->height, video_st->codec->pix_fmt, video_st->codec->width, video_st->codec->height, - PIX_FMT_BGR24, + AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL ); @@ -1107,10 +1122,15 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo uint8_t * picture_buf; int size; +#if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \ + ? CALC_FFMPEG_VERSION(55, 45, 101) : CALC_FFMPEG_VERSION(55, 28, 1)) + picture = av_frame_alloc(); +#else picture = avcodec_alloc_frame(); +#endif if (!picture) return NULL; - size = avpicture_get_size( (PixelFormat) pix_fmt, width, height); + size = avpicture_get_size( (AVPixelFormat) pix_fmt, width, height); if(alloc){ picture_buf = (uint8_t *) malloc(size); if (!picture_buf) @@ -1119,7 +1139,7 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo return NULL; } avpicture_fill((AVPicture *)picture, picture_buf, - (PixelFormat) pix_fmt, width, height); + (AVPixelFormat) pix_fmt, width, height); } else { } @@ -1227,7 +1247,7 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc, #endif c->gop_size = 12; /* emit one intra frame every twelve frames at most */ - c->pix_fmt = (PixelFormat) pixel_format; + c->pix_fmt = (AVPixelFormat) pixel_format; if (c->codec_id == CV_CODEC(CODEC_ID_MPEG2VIDEO)) { c->max_b_frames = 2; @@ -1402,12 +1422,12 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int #endif // check parameters - if (input_pix_fmt == PIX_FMT_BGR24) { + if (input_pix_fmt == AV_PIX_FMT_BGR24) { if (cn != 3) { return false; } } - else if (input_pix_fmt == PIX_FMT_GRAY8) { + else if (input_pix_fmt == AV_PIX_FMT_GRAY8) { if (cn != 1) { return false; } @@ -1420,13 +1440,13 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int assert( input_picture ); // let input_picture point to the raw data buffer of 'image' avpicture_fill((AVPicture *)input_picture, (uint8_t *) data, - (PixelFormat)input_pix_fmt, width, height); + (AVPixelFormat)input_pix_fmt, width, height); if( !img_convert_ctx ) { img_convert_ctx = sws_getContext(width, height, - (PixelFormat)input_pix_fmt, + (AVPixelFormat)input_pix_fmt, c->width, c->height, c->pix_fmt, @@ -1444,7 +1464,7 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int } else{ avpicture_fill((AVPicture *)picture, (uint8_t *) data, - (PixelFormat)input_pix_fmt, width, height); + (AVPixelFormat)input_pix_fmt, width, height); } picture->pts = frame_idx; @@ -1601,10 +1621,10 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, /* determine optimal pixel format */ if (is_color) { - input_pix_fmt = PIX_FMT_BGR24; + input_pix_fmt = AV_PIX_FMT_BGR24; } else { - input_pix_fmt = PIX_FMT_GRAY8; + input_pix_fmt = AV_PIX_FMT_GRAY8; } /* Lookup codec_id for given fourcc */ @@ -1679,21 +1699,21 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, break; #endif case CV_CODEC(CODEC_ID_HUFFYUV): - codec_pix_fmt = PIX_FMT_YUV422P; + codec_pix_fmt = AV_PIX_FMT_YUV422P; break; case CV_CODEC(CODEC_ID_MJPEG): case CV_CODEC(CODEC_ID_LJPEG): - codec_pix_fmt = PIX_FMT_YUVJ420P; + codec_pix_fmt = AV_PIX_FMT_YUVJ420P; bitrate_scale = 3; break; case CV_CODEC(CODEC_ID_RAWVIDEO): - codec_pix_fmt = input_pix_fmt == PIX_FMT_GRAY8 || - input_pix_fmt == PIX_FMT_GRAY16LE || - input_pix_fmt == PIX_FMT_GRAY16BE ? input_pix_fmt : PIX_FMT_YUV420P; + codec_pix_fmt = input_pix_fmt == AV_PIX_FMT_GRAY8 || + input_pix_fmt == AV_PIX_FMT_GRAY16LE || + input_pix_fmt == AV_PIX_FMT_GRAY16BE ? input_pix_fmt : AV_PIX_FMT_YUV420P; break; default: // good for lossy formats, MPEG, etc. - codec_pix_fmt = PIX_FMT_YUV420P; + codec_pix_fmt = AV_PIX_FMT_YUV420P; break; } @@ -1918,7 +1938,7 @@ struct OutputMediaStream_FFMPEG void write(unsigned char* data, int size, int keyFrame); // add a video output stream to the container - static AVStream* addVideoStream(AVFormatContext *oc, CV_CODEC_ID codec_id, int w, int h, int bitrate, double fps, PixelFormat pixel_format); + static AVStream* addVideoStream(AVFormatContext *oc, CV_CODEC_ID codec_id, int w, int h, int bitrate, double fps, AVPixelFormat pixel_format); AVOutputFormat* fmt_; AVFormatContext* oc_; @@ -1965,7 +1985,7 @@ void OutputMediaStream_FFMPEG::close() } } -AVStream* OutputMediaStream_FFMPEG::addVideoStream(AVFormatContext *oc, CV_CODEC_ID codec_id, int w, int h, int bitrate, double fps, PixelFormat pixel_format) +AVStream* OutputMediaStream_FFMPEG::addVideoStream(AVFormatContext *oc, CV_CODEC_ID codec_id, int w, int h, int bitrate, double fps, AVPixelFormat pixel_format) { AVCodec* codec = avcodec_find_encoder(codec_id); if (!codec) @@ -2108,7 +2128,7 @@ bool OutputMediaStream_FFMPEG::open(const char* fileName, int width, int height, oc_->max_delay = (int)(0.7 * AV_TIME_BASE); // This reduces buffer underrun warnings with MPEG // set a few optimal pixel formats for lossless codecs of interest.. - PixelFormat codec_pix_fmt = PIX_FMT_YUV420P; + AVPixelFormat codec_pix_fmt = AV_PIX_FMT_YUV420P; int bitrate_scale = 64; // TODO -- safe to ignore output audio stream? @@ -2317,15 +2337,15 @@ bool InputMediaStream_FFMPEG::open(const char* fileName, int* codec, int* chroma switch (enc->pix_fmt) { - case PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV420P: *chroma_format = ::VideoChromaFormat_YUV420; break; - case PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV422P: *chroma_format = ::VideoChromaFormat_YUV422; break; - case PIX_FMT_YUV444P: + case AV_PIX_FMT_YUV444P: *chroma_format = ::VideoChromaFormat_YUV444; break; From f0282337e38fabc070e5597699322c449ffd4dac Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Mon, 14 Sep 2015 15:15:24 +0200 Subject: [PATCH 049/156] simplify error conditions `A || !A` is `true` so write `(A && B) || !A` as `B || !A` --- modules/calib3d/src/fisheye.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/calib3d/src/fisheye.cpp b/modules/calib3d/src/fisheye.cpp index a11bea0ce..78c066afb 100644 --- a/modules/calib3d/src/fisheye.cpp +++ b/modules/calib3d/src/fisheye.cpp @@ -512,7 +512,7 @@ void cv::fisheye::estimateNewCameraMatrixForUndistortRectify(InputArray K, Input OutputArray P, double balance, const Size& new_size, double fov_scale) { CV_Assert( K.size() == Size(3, 3) && (K.depth() == CV_32F || K.depth() == CV_64F)); - CV_Assert((D.empty() || D.total() == 4) && (D.depth() == CV_32F || D.depth() == CV_64F || D.empty())); + CV_Assert(D.empty() || ((D.total() == 4) && (D.depth() == CV_32F || D.depth() == CV_64F))); int w = image_size.width, h = image_size.height; balance = std::min(std::max(balance, 0.0), 1.0); @@ -694,12 +694,12 @@ double cv::fisheye::calibrate(InputArrayOfArrays objectPoints, InputArrayOfArray CV_Assert(!objectPoints.empty() && !imagePoints.empty() && objectPoints.total() == imagePoints.total()); CV_Assert(objectPoints.type() == CV_32FC3 || objectPoints.type() == CV_64FC3); CV_Assert(imagePoints.type() == CV_32FC2 || imagePoints.type() == CV_64FC2); - CV_Assert((!K.empty() && K.size() == Size(3,3)) || K.empty()); - CV_Assert((!D.empty() && D.total() == 4) || D.empty()); - CV_Assert((!rvecs.empty() && rvecs.channels() == 3) || rvecs.empty()); - CV_Assert((!tvecs.empty() && tvecs.channels() == 3) || tvecs.empty()); + CV_Assert(K.empty() || (K.size() == Size(3,3))); + CV_Assert(D.empty() || (D.total() == 4)); + CV_Assert(rvecs.empty() || (rvecs.channels() == 3)); + CV_Assert(tvecs.empty() || (tvecs.channels() == 3)); - CV_Assert(((flags & CALIB_USE_INTRINSIC_GUESS) && !K.empty() && !D.empty()) || !(flags & CALIB_USE_INTRINSIC_GUESS)); + CV_Assert((!K.empty() && !D.empty()) || !(flags & CALIB_USE_INTRINSIC_GUESS)); using namespace cv::internal; //-------------------------------Initialization @@ -825,12 +825,12 @@ double cv::fisheye::stereoCalibrate(InputArrayOfArrays objectPoints, InputArrayO CV_Assert(imagePoints1.type() == CV_32FC2 || imagePoints1.type() == CV_64FC2); CV_Assert(imagePoints2.type() == CV_32FC2 || imagePoints2.type() == CV_64FC2); - CV_Assert((!K1.empty() && K1.size() == Size(3,3)) || K1.empty()); - CV_Assert((!D1.empty() && D1.total() == 4) || D1.empty()); - CV_Assert((!K2.empty() && K1.size() == Size(3,3)) || K2.empty()); - CV_Assert((!D2.empty() && D1.total() == 4) || D2.empty()); + CV_Assert(K1.empty() || (K1.size() == Size(3,3))); + CV_Assert(D1.empty() || (D1.total() == 4)); + CV_Assert(K2.empty() || (K1.size() == Size(3,3))); + CV_Assert(D2.empty() || (D1.total() == 4)); - CV_Assert(((flags & CALIB_FIX_INTRINSIC) && !K1.empty() && !K2.empty() && !D1.empty() && !D2.empty()) || !(flags & CALIB_FIX_INTRINSIC)); + CV_Assert((!K1.empty() && !K2.empty() && !D1.empty() && !D2.empty()) || !(flags & CALIB_FIX_INTRINSIC)); //-------------------------------Initialization From 4094b2d7a57eecae3b68f792ed070aedf4be1f6c Mon Sep 17 00:00:00 2001 From: Sergey Alexandrov Date: Fri, 18 Sep 2015 13:12:58 +0200 Subject: [PATCH 050/156] Use stream argument when launching bilateral filter kernel --- modules/cudaimgproc/src/cuda/bilateral_filter.cu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/cudaimgproc/src/cuda/bilateral_filter.cu b/modules/cudaimgproc/src/cuda/bilateral_filter.cu index 20d2bd9d7..f81adc7a9 100644 --- a/modules/cudaimgproc/src/cuda/bilateral_filter.cu +++ b/modules/cudaimgproc/src/cuda/bilateral_filter.cu @@ -136,7 +136,7 @@ namespace cv { namespace cuda { namespace device float sigma_color2_inv_half = -0.5f/(sigma_color * sigma_color); cudaSafeCall( cudaFuncSetCacheConfig (bilateral_kernel >, cudaFuncCachePreferL1) ); - bilateral_kernel<<>>((PtrStepSz)src, (PtrStepSz)dst, b, kernel_size, sigma_spatial2_inv_half, sigma_color2_inv_half); + bilateral_kernel<<>>((PtrStepSz)src, (PtrStepSz)dst, b, kernel_size, sigma_spatial2_inv_half, sigma_color2_inv_half); cudaSafeCall ( cudaGetLastError () ); if (stream == 0) From 08dd126f08299ac08147083fb188d87e56f4302d Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Thu, 10 Sep 2015 18:22:35 +0200 Subject: [PATCH 051/156] do not parse empty default values and improve error messages --- modules/core/include/opencv2/core/utility.hpp | 2 +- modules/core/src/command_line_parser.cpp | 24 +++++++++++++------ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/modules/core/include/opencv2/core/utility.hpp b/modules/core/include/opencv2/core/utility.hpp index dcb625b3d..1e44d2e62 100644 --- a/modules/core/include/opencv2/core/utility.hpp +++ b/modules/core/include/opencv2/core/utility.hpp @@ -618,7 +618,7 @@ For the described keys: # Bad call $ ./app -fps=aaa ERRORS: - Exception: can not convert: [aaa] to [double] + Parameter 'fps': can not convert: [aaa] to [double] @endcode */ class CV_EXPORTS CommandLineParser diff --git a/modules/core/src/command_line_parser.cpp b/modules/core/src/command_line_parser.cpp index 2753ef30a..0c50391f5 100644 --- a/modules/core/src/command_line_parser.cpp +++ b/modules/core/src/command_line_parser.cpp @@ -97,23 +97,28 @@ void CommandLineParser::getByName(const String& name, bool space_delete, int typ { for (size_t j = 0; j < impl->data[i].keys.size(); j++) { - if (name.compare(impl->data[i].keys[j]) == 0) + if (name == impl->data[i].keys[j]) { String v = impl->data[i].def_value; if (space_delete) v = impl->cat_string(v); + + // it is an error if we just got the default value here + if(v.empty()) + break; + from_str(v, type, dst); return; } } } impl->error = true; - impl->error_message = impl->error_message + "Unknown parameter " + name + "\n"; + impl->error_message = impl->error_message + "Missing parameter: '" + name + "'\n"; } - catch (std::exception& e) + catch (Exception& e) { impl->error = true; - impl->error_message = impl->error_message + "Exception: " + String(e.what()) + "\n"; + impl->error_message = impl->error_message + "Parameter '"+ name + "': " + e.err + "\n"; } } @@ -128,17 +133,22 @@ void CommandLineParser::getByIndex(int index, bool space_delete, int type, void* { String v = impl->data[i].def_value; if (space_delete == true) v = impl->cat_string(v); + + // it is an error if we just got the default value here + if(v.empty()) + break; + from_str(v, type, dst); return; } } impl->error = true; - impl->error_message = impl->error_message + "Unknown parameter #" + format("%d", index) + "\n"; + impl->error_message = impl->error_message + "Missing parameter #" + format("%d", index) + "\n"; } - catch(std::exception & e) + catch(Exception& e) { impl->error = true; - impl->error_message = impl->error_message + "Exception: " + String(e.what()) + "\n"; + impl->error_message = impl->error_message + format("Parameter #%d: ", index) + e.err + "\n"; } } From 96cc6184109be7527f7fccec463c629e28bbedbe Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Tue, 15 Sep 2015 14:54:02 +0200 Subject: [PATCH 052/156] has() should only test for the presence of the argument and not consider its value. treat arguments with a set default value as present. --- modules/core/include/opencv2/core/utility.hpp | 4 ++++ modules/core/src/command_line_parser.cpp | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/core/include/opencv2/core/utility.hpp b/modules/core/include/opencv2/core/utility.hpp index 1e44d2e62..d99901b1b 100644 --- a/modules/core/include/opencv2/core/utility.hpp +++ b/modules/core/include/opencv2/core/utility.hpp @@ -607,6 +607,10 @@ For example: } @endcode +Note that there are no default values for `help` and `timestamp` so we can check their presence using the `has()` method. +Arguments with default values are considered to be always present. Use the `get()` method in these cases to check their +actual value instead. + ### Usage For the described keys: diff --git a/modules/core/src/command_line_parser.cpp b/modules/core/src/command_line_parser.cpp index 0c50391f5..a7c1edc69 100644 --- a/modules/core/src/command_line_parser.cpp +++ b/modules/core/src/command_line_parser.cpp @@ -334,9 +334,9 @@ bool CommandLineParser::has(const String& name) const { for (size_t j = 0; j < impl->data[i].keys.size(); j++) { - if (name.compare(impl->data[i].keys[j]) == 0 && String("true").compare(impl->data[i].def_value) == 0) + if (name == impl->data[i].keys[j]) { - return true; + return !impl->cat_string(impl->data[i].def_value).empty(); } } } From 31da83357448061320637add8700576ff62cad9f Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Thu, 17 Sep 2015 11:57:00 +0200 Subject: [PATCH 053/156] ts/ts_perf: fix wrong has() usage `has()` only tests for an argument presence which is always true for arguments with default values. Use `get()` to check the value instead. --- modules/ts/src/ts_perf.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/ts/src/ts_perf.cpp b/modules/ts/src/ts_perf.cpp index ef8f0af9a..c9e872b4c 100644 --- a/modules/ts/src/ts_perf.cpp +++ b/modules/ts/src/ts_perf.cpp @@ -783,7 +783,7 @@ void TestBase::Init(const std::vector & availableImpls, ; cv::CommandLineParser args(argc, argv, command_line_keys); - if (args.has("help")) + if (args.get("help")) { args.printMessage(); return; @@ -791,7 +791,7 @@ void TestBase::Init(const std::vector & availableImpls, ::testing::AddGlobalTestEnvironment(new PerfEnvironment); - param_impl = args.has("perf_run_cpu") ? "plain" : args.get("perf_impl"); + param_impl = args.get("perf_run_cpu") ? "plain" : args.get("perf_impl"); std::string perf_strategy = args.get("perf_strategy"); if (perf_strategy == "default") { @@ -816,24 +816,24 @@ void TestBase::Init(const std::vector & availableImpls, param_seed = args.get("perf_seed"); param_time_limit = std::max(0., args.get("perf_time_limit")); param_force_samples = args.get("perf_force_samples"); - param_write_sanity = args.has("perf_write_sanity"); - param_verify_sanity = args.has("perf_verify_sanity"); + param_write_sanity = args.get("perf_write_sanity"); + param_verify_sanity = args.get("perf_verify_sanity"); #ifndef WINRT - test_ipp_check = !args.has("perf_ipp_check") ? getenv("OPENCV_IPP_CHECK") != NULL : true; + test_ipp_check = !args.get("perf_ipp_check") ? getenv("OPENCV_IPP_CHECK") != NULL : true; #else test_ipp_check = false; #endif param_threads = args.get("perf_threads"); #ifdef CV_COLLECT_IMPL_DATA - param_collect_impl = args.has("perf_collect_impl"); + param_collect_impl = args.get("perf_collect_impl"); #endif #ifdef ANDROID param_affinity_mask = args.get("perf_affinity_mask"); log_power_checkpoints = args.has("perf_log_power_checkpoints"); #endif - bool param_list_impls = args.has("perf_list_impls"); + bool param_list_impls = args.get("perf_list_impls"); if (param_list_impls) { @@ -861,7 +861,7 @@ void TestBase::Init(const std::vector & availableImpls, #ifdef HAVE_CUDA - bool printOnly = args.has("perf_cuda_info_only"); + bool printOnly = args.get("perf_cuda_info_only"); if (printOnly) exit(0); From 8e088d38a50f381285102fb687934b62cc261b3b Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Sat, 19 Sep 2015 16:16:13 +0300 Subject: [PATCH 054/156] draft implementation of alternative CameraBridge via GLES a simple sample will look like: ```java public class MainActivity extends Activity implements CameraGLSurfaceView.CameraTextureListener { CameraGLSurfaceView mView; ByteBuffer buf; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); mView = new CameraGLSurfaceView(this, null); mView.setCameraTextureListener(this); setContentView(mView); buf = ByteBuffer.allocateDirect(1920*1080*4); } @Override protected void onPause() { mView.onPause(); super.onPause(); } @Override protected void onResume() { super.onResume(); mView.onResume(); } @Override public void onCameraViewStarted(int width, int height) { // TODO Auto-generated method stub } @Override public void onCameraViewStopped() { // TODO Auto-generated method stub } @Override public boolean onCameraFrame(int texIn, int texOut, int width, int height) { Log.i("MAIN", "onCameraFrame"); int w=width, h=height; /* // option 1: // just return 'false' to display texIn on screen retutn false; */ /* // option 2: // fast copy texIn to texOut GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texOut); GLES20.glCopyTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 0, 0, w, h, 0); return true; */ // option 3: // read, modify and write back pixels GLES20.glReadPixels(0, 0, w, h, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf); buf.rewind(); // red line for(int i=0; i= 21) + mRenderer = new Camera2Renderer(this); + else*/ + mRenderer = new CameraRenderer(this); + + setEGLContextClientVersion(2); + setRenderer(mRenderer); + setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); + } + + public void setCameraTextureListener(CameraTextureListener texListener) + { + mTexListener = texListener; + } + + public CameraTextureListener getCameraTextureListener() + { + return mTexListener; + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + super.surfaceCreated(holder); + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + super.surfaceDestroyed(holder); + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + super.surfaceChanged(holder, format, w, h); + } + + @Override + public void onResume() { + super.onResume(); + mRenderer.onResume(); + } + + @Override + public void onPause() { + mRenderer.onPause(); + super.onPause(); + } + + @Override + public boolean onTouchEvent(MotionEvent e) { + if(e.getAction() == MotionEvent.ACTION_DOWN) + ((Activity)getContext()).openOptionsMenu(); + return true; + } +} diff --git a/modules/java/generator/src/java/android+CameraRenderer.java b/modules/java/generator/src/java/android+CameraRenderer.java new file mode 100644 index 000000000..ae8edda01 --- /dev/null +++ b/modules/java/generator/src/java/android+CameraRenderer.java @@ -0,0 +1,353 @@ +package org.opencv.android; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.util.List; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import org.opencv.android.CameraGLSurfaceView.CameraTextureListener; + +import android.opengl.GLES11Ext; +import android.opengl.GLES20; +import android.opengl.GLSurfaceView; +import android.os.Build; +import android.util.Log; +import android.annotation.TargetApi; +import android.graphics.SurfaceTexture; +import android.hardware.Camera; +import android.hardware.Camera.Size; + +@TargetApi(15) +public class CameraRenderer implements GLSurfaceView.Renderer, + SurfaceTexture.OnFrameAvailableListener { + + public static final String LOGTAG = "CameraRenderer"; + + // shaders + private final String vss = "" + + "attribute vec2 vPosition;\n" + + "attribute vec2 vTexCoord;\n" + "varying vec2 texCoord;\n" + + "void main() {\n" + " texCoord = vTexCoord;\n" + + " gl_Position = vec4 ( vPosition.x, vPosition.y, 0.0, 1.0 );\n" + + "}"; + + private final String fssOES = "" + + "#extension GL_OES_EGL_image_external : require\n" + + "precision mediump float;\n" + + "uniform samplerExternalOES sTexture;\n" + + "varying vec2 texCoord;\n" + + "void main() {\n" + + " gl_FragColor = texture2D(sTexture,texCoord);\n" + "}"; + + private final String fss2D = "" + + "precision mediump float;\n" + + "uniform sampler2D sTexture;\n" + + "varying vec2 texCoord;\n" + + "void main() {\n" + + " gl_FragColor = texture2D(sTexture,texCoord);\n" + "}"; + + // coord-s + private final float vertices[] = { + -1, -1, + -1, 1, + 1, -1, + 1, 1 }; + private final float texCoordOES[] = { + 0, 1, + 0, 0, + 1, 1, + 1, 0 }; + private final float texCoord2D[] = { + 0, 0, + 0, 1, + 1, 0, + 1, 1 }; + + private int[] texCamera = {0}, texFBO = {0}, texDraw = {0}; + private int[] FBO = {0}; + private int progOES, prog2D; + private int vPosOES, vTCOES, vPos2D, vTC2D; + + private FloatBuffer vert, texOES, tex2D; + + private Camera mCamera; + private boolean mPreviewStarted = false; + private int mPreviewWidth, mPreviewHeight; + + private SurfaceTexture mSTexture; + + private boolean mGLInit = false; + private boolean mUpdateST = false; + + private CameraGLSurfaceView mView; + + CameraRenderer(CameraGLSurfaceView view) { + mView = view; + int bytes = vertices.length * Float.SIZE / Byte.SIZE; + vert = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer(); + texOES = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer(); + tex2D = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer(); + vert.put(vertices).position(0); + texOES.put(texCoordOES).position(0); + tex2D.put(texCoord2D).position(0); + } + + public void onResume() { + //nothing + Log.i(LOGTAG, "onResume"); + } + + public void onPause() { + Log.i(LOGTAG, "onPause"); + mGLInit = false; + mUpdateST = false; + + if(mCamera != null) { + mCamera.stopPreview(); + mCamera.release(); + mCamera = null; + } + + if(mSTexture != null) { + mSTexture.release(); + mSTexture = null; + deleteTex(texCamera); + } + } + + public void onSurfaceCreated(GL10 unused, EGLConfig config) { + GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + + progOES = loadShader(vss, fssOES); + vPosOES = GLES20.glGetAttribLocation(progOES, "vPosition"); + vTCOES = GLES20.glGetAttribLocation(progOES, "vTexCoord"); + GLES20.glEnableVertexAttribArray(vPosOES); + GLES20.glEnableVertexAttribArray(vTCOES); + + prog2D = loadShader(vss, fss2D); + vPos2D = GLES20.glGetAttribLocation(prog2D, "vPosition"); + vTC2D = GLES20.glGetAttribLocation(prog2D, "vTexCoord"); + GLES20.glEnableVertexAttribArray(vPos2D); + GLES20.glEnableVertexAttribArray(vTC2D); + + initTexOES(texCamera); + mSTexture = new SurfaceTexture(texCamera[0]); + mSTexture.setOnFrameAvailableListener(this); + + mCamera = Camera.open(); + try { + mCamera.setPreviewTexture(mSTexture); + } catch (IOException ioe) { + } + + mGLInit = true; + } + + public void onDrawFrame(GL10 unused) { + if (!mGLInit) + return; + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); + + synchronized (this) { + if (mUpdateST) { + mSTexture.updateTexImage(); + mUpdateST = false; + } + } + + CameraTextureListener texListener = mView.getCameraTextureListener(); + if(texListener != null) { + Log.d(LOGTAG, "haveUserCallback"); + // texCamera(OES) -> texFBO + drawTex(texCamera[0], true, FBO[0]); + + // call user code (texFBO -> texDraw) + boolean modified = texListener.onCameraFrame(texFBO[0], texDraw[0], mPreviewWidth, mPreviewHeight); + + if(modified) { + // texDraw -> screen + drawTex(texDraw[0], false, 0); + } else { + // texFBO -> screen + drawTex(texFBO[0], false, 0); + } + } else { + // texCamera(OES) -> screen + drawTex(texCamera[0], true, 0); + } + } + + public void onSurfaceChanged(GL10 unused, int width, int height) { + Log.i(LOGTAG, "onSurfaceChanged("+width+"x"+height+")"); + + if(mCamera == null) + return; + if(mPreviewStarted) { + mCamera.stopPreview(); + mPreviewStarted = false; + } + + Camera.Parameters param = mCamera.getParameters(); + List psize = param.getSupportedPreviewSizes(); + int bestWidth = 0, bestHeight = 0; + if (psize.size() > 0) { + float aspect = (float)width / height; + for (Size size : psize) { + int w = size.width, h = size.height; + Log.d(LOGTAG, "checking camera preview size: "+w+"x"+h); + if ( w <= width && h <= height && + w >= bestWidth && h >= bestHeight && + Math.abs(aspect - (float)w/h) < 0.2 ) { + bestWidth = w; + bestHeight = h; + } + } + if(bestWidth > 0 && bestHeight > 0) { + param.setPreviewSize(bestWidth, bestHeight); + Log.i(LOGTAG, "selected size: "+bestWidth+" x "+bestHeight); + + GLES20.glViewport(0, 0, bestWidth, bestWidth); + initFBO(bestWidth, bestHeight); + mPreviewWidth = bestWidth; + mPreviewHeight = bestHeight; + } + } + //param.set("orientation", "landscape"); + mCamera.setParameters(param); + mCamera.startPreview(); + mPreviewStarted = true; + } + + public synchronized void onFrameAvailable(SurfaceTexture st) { + mUpdateST = true; + mView.requestRender(); + } + + private void initTexOES(int[] tex) { + if(tex.length == 1) { + GLES20.glGenTextures(1, tex, 0); + GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0]); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); + } + } + + private void deleteTex(int[] tex) { + if(tex.length == 1) { + GLES20.glDeleteTextures(1, tex, 0); + } + } + + private static int loadShader(String vss, String fss) { + int vshader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); + GLES20.glShaderSource(vshader, vss); + GLES20.glCompileShader(vshader); + int[] compiled = new int[1]; + GLES20.glGetShaderiv(vshader, GLES20.GL_COMPILE_STATUS, compiled, 0); + if (compiled[0] == 0) { + Log.e(LOGTAG, "Could not compile vertex shader"); + Log.v(LOGTAG, "Could not compile vertex shader:"+GLES20.glGetShaderInfoLog(vshader)); + GLES20.glDeleteShader(vshader); + vshader = 0; + } + + int fshader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); + GLES20.glShaderSource(fshader, fss); + GLES20.glCompileShader(fshader); + GLES20.glGetShaderiv(fshader, GLES20.GL_COMPILE_STATUS, compiled, 0); + if (compiled[0] == 0) { + Log.e("Renderer", "Could not compile fragment shader"); + Log.v("Renderer", "Could not compile fragment shader:"+GLES20.glGetShaderInfoLog(fshader)); + GLES20.glDeleteShader(fshader); + fshader = 0; + } + + int program = GLES20.glCreateProgram(); + GLES20.glAttachShader(program, vshader); + GLES20.glAttachShader(program, fshader); + GLES20.glLinkProgram(program); + + return program; + } + + private void releaseFBO() + { + + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); + GLES20.glDeleteFramebuffers(1, FBO, 0); + + deleteTex(texFBO); + deleteTex(texDraw); + } + + private void initFBO(int width, int height) + { + Log.d(LOGTAG, "initFBO("+width+"x"+height+")"); + releaseFBO(); + + GLES20.glGenTextures(1, texDraw, 0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texDraw[0]); + GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); + + GLES20.glGenTextures(1, texFBO, 0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texFBO[0]); + GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); + + //int hFBO; + GLES20.glGenFramebuffers(1, FBO, 0); + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, FBO[0]); + GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, texFBO[0], 0); + Log.d(LOGTAG, "initFBO status: " + GLES20.glGetError()); + + if (GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER) != GLES20.GL_FRAMEBUFFER_COMPLETE) + Log.e(LOGTAG, "initFBO failed: " + GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER)); + + //GLES20.glViewport(0, 0, width, height); + } + + // draw texture to FBO or to screen if fbo == 0 + private void drawTex(int tex, boolean isOES, int fbo) + { + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbo); + GLES20.glViewport(0, 0, mPreviewWidth, mPreviewHeight); + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); + + if(isOES) { + GLES20.glUseProgram(progOES); + GLES20.glVertexAttribPointer(vPosOES, 2, GLES20.GL_FLOAT, false, 4*2, vert); + GLES20.glVertexAttribPointer(vTCOES, 2, GLES20.GL_FLOAT, false, 4*2, texOES); + } else { + GLES20.glUseProgram(prog2D); + GLES20.glVertexAttribPointer(vPos2D, 2, GLES20.GL_FLOAT, false, 4*2, vert); + GLES20.glVertexAttribPointer(vTC2D, 2, GLES20.GL_FLOAT, false, 4*2, tex2D); + } + + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + + if(isOES) { + GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex); + GLES20.glUniform1i(GLES20.glGetUniformLocation(progOES, "sTexture"), 0); + } else { + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex); + GLES20.glUniform1i(GLES20.glGetUniformLocation(prog2D, "sTexture"), 0); + } + + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); + GLES20.glFlush(); + } +} \ No newline at end of file From d3071db0d7907032e8adee92939f45effba28657 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sun, 20 Sep 2015 13:14:41 +0300 Subject: [PATCH 055/156] add some CommandLineParser tests --- modules/core/test/test_utils.cpp | 179 +++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 modules/core/test/test_utils.cpp diff --git a/modules/core/test/test_utils.cpp b/modules/core/test/test_utils.cpp new file mode 100644 index 000000000..f69a063eb --- /dev/null +++ b/modules/core/test/test_utils.cpp @@ -0,0 +1,179 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +#include "test_precomp.hpp" + +using namespace cv; + +namespace { + +static const char * const keys = + "{ h help | | print help }" + "{ i info | false | print info }" + "{ t true | true | true value }" + "{ n unused | | dummy }" +; + +TEST(CommandLineParser, testHas_noValues) +{ + const char* argv[] = {"", "-h", "--info"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys); + EXPECT_TRUE(parser.has("help")); + EXPECT_TRUE(parser.has("h")); + EXPECT_TRUE(parser.has("info")); + EXPECT_TRUE(parser.has("i")); + EXPECT_FALSE(parser.has("n")); + EXPECT_FALSE(parser.has("unused")); + EXPECT_FALSE(parser.has("q")); // TODO Throw ??? +} +TEST(CommandLineParser, testHas_TrueValues) +{ + const char* argv[] = {"", "-h=TRUE", "--info=true"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys); + EXPECT_TRUE(parser.has("help")); + EXPECT_TRUE(parser.has("h")); + EXPECT_TRUE(parser.has("info")); + EXPECT_TRUE(parser.has("i")); + EXPECT_FALSE(parser.has("n")); + EXPECT_FALSE(parser.has("unused")); + EXPECT_FALSE(parser.has("q")); // TODO Throw ??? +} +TEST(CommandLineParser, testHas_TrueValues1) +{ + const char* argv[] = {"", "-h=1", "--info=1"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys); + EXPECT_TRUE(parser.has("help")); + EXPECT_TRUE(parser.has("h")); + EXPECT_TRUE(parser.has("info")); + EXPECT_TRUE(parser.has("i")); + EXPECT_FALSE(parser.has("n")); + EXPECT_FALSE(parser.has("unused")); + EXPECT_FALSE(parser.has("q")); // TODO Throw ??? +} +TEST(CommandLineParser, testHas_FalseValues0) +{ + const char* argv[] = {"", "-h=0", "--info=0"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys); + EXPECT_TRUE(parser.has("help")); + EXPECT_TRUE(parser.has("h")); + EXPECT_TRUE(parser.has("info")); + EXPECT_TRUE(parser.has("i")); + EXPECT_FALSE(parser.has("n")); + EXPECT_FALSE(parser.has("unused")); + EXPECT_FALSE(parser.has("q")); // TODO Throw ??? +} + +TEST(CommandLineParser, testBoolOption_noArgs) +{ + const char* argv[] = {""}; + const int argc = 1; + cv::CommandLineParser parser(argc, argv, keys); + EXPECT_FALSE(parser.get("help")); + EXPECT_FALSE(parser.get("h")); + EXPECT_FALSE(parser.get("info")); + EXPECT_FALSE(parser.get("i")); + EXPECT_TRUE(parser.get("true")); // default is true + EXPECT_TRUE(parser.get("t")); +} + +TEST(CommandLineParser, testBoolOption_noValues) +{ + const char* argv[] = {"", "-h", "--info"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys); + EXPECT_TRUE(parser.get("help")); + EXPECT_TRUE(parser.get("h")); + EXPECT_TRUE(parser.get("info")); + EXPECT_TRUE(parser.get("i")); +} + +TEST(CommandLineParser, testBoolOption_TrueValues) +{ + const char* argv[] = {"", "-h=TRUE", "--info=true"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys); + //EXPECT_TRUE(parser.get("help")); + //EXPECT_TRUE(parser.get("h")); + EXPECT_TRUE(parser.get("info")); + EXPECT_TRUE(parser.get("i")); + EXPECT_FALSE(parser.get("unused")); + EXPECT_FALSE(parser.get("n")); +} + +TEST(CommandLineParser, testBoolOption_FalseValues) +{ + const char* argv[] = {"", "--help=FALSE", "-i=false"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys); + EXPECT_FALSE(parser.get("help")); + EXPECT_FALSE(parser.get("h")); + EXPECT_FALSE(parser.get("info")); + EXPECT_FALSE(parser.get("i")); +} + + +static const char * const keys2 = + "{ h help | | print help }" + "{ @arg1 | default1 | param1 }" + "{ @arg2 | | param2 }" + "{ n unused | | dummy }" +; + +TEST(CommandLineParser, testPositional_noArgs) +{ + const char* argv[] = {""}; + const int argc = 1; + cv::CommandLineParser parser(argc, argv, keys2); + //EXPECT_FALSE(parser.has("arg1")); + //EXPECT_FALSE(parser.has("arg2")); + //EXPECT_EQ("default1", parser.get("arg1")); + EXPECT_EQ("default1", parser.get(0)); + //??? EXPECT_ANY_THROW(parser.get("arg2")); + //??? EXPECT_ANY_THROW(parser.get(1)); +} + +TEST(CommandLineParser, testPositional_default) +{ + const char* argv[] = {"", "test1", "test2"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys2); + //EXPECT_TRUE(parser.has("arg1")); + //EXPECT_TRUE(parser.has("arg2")); + //EXPECT_EQ("test1", parser.get("arg1")); + //EXPECT_EQ("test2", parser.get("arg2")); + EXPECT_EQ("test1", parser.get(0)); + EXPECT_EQ("test2", parser.get(1)); +} + +TEST(CommandLineParser, testPositional_withFlagsBefore) +{ + const char* argv[] = {"", "-h", "test1", "test2"}; + const int argc = 4; + cv::CommandLineParser parser(argc, argv, keys2); + //EXPECT_TRUE(parser.has("arg1")); + //EXPECT_TRUE(parser.has("arg2")); + //EXPECT_EQ("test1", parser.get("arg1")); + //EXPECT_EQ("test2", parser.get("arg2")); + EXPECT_EQ("test1", parser.get(0)); + EXPECT_EQ("test2", parser.get(1)); +} + +TEST(CommandLineParser, testPositional_withFlagsAfter) +{ + const char* argv[] = {"", "test1", "test2", "-h"}; + const int argc = 4; + cv::CommandLineParser parser(argc, argv, keys2); + //EXPECT_TRUE(parser.has("arg1")); + //EXPECT_TRUE(parser.has("arg2")); + //EXPECT_EQ("test1", parser.get("arg1")); + //EXPECT_EQ("test2", parser.get("arg2")); + EXPECT_EQ("test1", parser.get(0)); + EXPECT_EQ("test2", parser.get(1)); +} + +} // namespace From dff9d2288b8bb47a486b01deaa8a16fe953e91b5 Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Mon, 21 Sep 2015 00:34:15 +0300 Subject: [PATCH 056/156] Update window_w32.cpp --- modules/highgui/src/window_w32.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index 08a137ab2..988aedaf6 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -1909,7 +1909,8 @@ static void showSaveDialog(CvWindow* window) if (GetSaveFileName(&ofn)) { - cv::Mat tmp; cv::flip(cv::Mat(sz.cy, sz.cx, CV_8UC(channels), data), tmp, 0); + cv::Mat tmp; + cv::flip(cv::Mat(sz.cy, sz.cx, CV_8UC(channels), data, (sz.cx * channels + 3) & -4), tmp, 0); cv::imwrite(szFileName, tmp); } } From 2f7c926670775fabf887e748f06a198369268aa8 Mon Sep 17 00:00:00 2001 From: berak Date: Tue, 8 Sep 2015 14:45:13 +0200 Subject: [PATCH 057/156] remove usage of obsolete _dataAsRows flag --- modules/core/include/opencv2/core.hpp | 10 +++++----- modules/core/src/lda.cpp | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/core/include/opencv2/core.hpp b/modules/core/include/opencv2/core.hpp index d7289a627..40d678206 100644 --- a/modules/core/include/opencv2/core.hpp +++ b/modules/core/include/opencv2/core.hpp @@ -2381,8 +2381,7 @@ class CV_EXPORTS LDA { public: /** @brief constructor - Initializes a LDA with num_components (default 0) and specifies how - samples are aligned (default dataAsRow=true). + Initializes a LDA with num_components (default 0). */ explicit LDA(int num_components = 0); @@ -2413,15 +2412,17 @@ public: */ ~LDA(); - /** Compute the discriminants for data in src and labels. + /** Compute the discriminants for data in src (row aligned) and labels. */ void compute(InputArrayOfArrays src, InputArray labels); /** Projects samples into the LDA subspace. + src may be one or more row aligned samples. */ Mat project(InputArray src); /** Reconstructs projections from the LDA subspace. + src may be one or more row aligned projections. */ Mat reconstruct(InputArray src); @@ -2437,11 +2438,10 @@ public: static Mat subspaceReconstruct(InputArray W, InputArray mean, InputArray src); protected: - bool _dataAsRow; + bool _dataAsRow; // unused, but needed for 3.0 ABI compatibility. int _num_components; Mat _eigenvectors; Mat _eigenvalues; - void lda(InputArrayOfArrays src, InputArray labels); }; diff --git a/modules/core/src/lda.cpp b/modules/core/src/lda.cpp index 5e20b5e6a..76e8db29a 100644 --- a/modules/core/src/lda.cpp +++ b/modules/core/src/lda.cpp @@ -937,9 +937,9 @@ public: // Linear Discriminant Analysis implementation //------------------------------------------------------------------------------ -LDA::LDA(int num_components) : _num_components(num_components) { } +LDA::LDA(int num_components) : _dataAsRow(true), _num_components(num_components) { } -LDA::LDA(InputArrayOfArrays src, InputArray labels, int num_components) : _num_components(num_components) +LDA::LDA(InputArrayOfArrays src, InputArray labels, int num_components) : _dataAsRow(true), _num_components(num_components) { this->compute(src, labels); //! compute eigenvectors and eigenvalues } @@ -1106,14 +1106,14 @@ void LDA::compute(InputArrayOfArrays _src, InputArray _lbls) { } } -// Projects samples into the LDA subspace. +// Projects one or more row aligned samples into the LDA subspace. Mat LDA::project(InputArray src) { - return subspaceProject(_eigenvectors, Mat(), _dataAsRow ? src : src.getMat().t()); + return subspaceProject(_eigenvectors, Mat(), src); } -// Reconstructs projections from the LDA subspace. +// Reconstructs projections from the LDA subspace from one or more row aligned samples. Mat LDA::reconstruct(InputArray src) { - return subspaceReconstruct(_eigenvectors, Mat(), _dataAsRow ? src : src.getMat().t()); + return subspaceReconstruct(_eigenvectors, Mat(), src); } } From 5de01fde534e1ec1adbf9241d2644cd8cdab9302 Mon Sep 17 00:00:00 2001 From: Elena Shipunova Date: Mon, 7 Sep 2015 13:50:30 +0300 Subject: [PATCH 058/156] do not proceed with removing zero-length slice --- modules/core/src/datastructs.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/core/src/datastructs.cpp b/modules/core/src/datastructs.cpp index 34ed64dbe..2612de6c5 100644 --- a/modules/core/src/datastructs.cpp +++ b/modules/core/src/datastructs.cpp @@ -1695,6 +1695,9 @@ cvSeqRemoveSlice( CvSeq* seq, CvSlice slice ) slice.end_index = slice.start_index + length; + if ( slice.start_index == slice.end_index ) + return; + if( slice.end_index < total ) { CvSeqReader reader_to, reader_from; From 7d245e0f29b3c611a2fdd378d28df28505b1691d Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Thu, 30 Jul 2015 18:42:29 +0300 Subject: [PATCH 059/156] Added more resize_area tests to ensure right rounding behavior for half and quarter downscaling --- modules/imgproc/test/test_imgwarp.cpp | 102 ++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/modules/imgproc/test/test_imgwarp.cpp b/modules/imgproc/test/test_imgwarp.cpp index 2260cf510..c2cf2bfc6 100644 --- a/modules/imgproc/test/test_imgwarp.cpp +++ b/modules/imgproc/test/test_imgwarp.cpp @@ -1538,6 +1538,108 @@ TEST(Imgproc_resize_area, regression) ASSERT_EQ(cvtest::norm(one_channel_diff, cv::NORM_INF), 0); } +TEST(Imgproc_resize_area, regression_half_round) +{ + static uchar input_data[32 * 32]; + for(int i = 0; i < 32 * 32; ++i) + input_data[i] = i % 2 + 253 + i / (16 * 32); + + static uchar expected_data[16 * 16]; + for(int i = 0; i < 16 * 16; ++i) + expected_data[i] = 254 + i / (16 * 8); + + cv::Mat src(32, 32, CV_8UC1, input_data); + cv::Mat expected(16, 16, CV_8UC1, expected_data); + cv::Mat actual(expected.size(), expected.type()); + + cv::resize(src, actual, cv::Size(), 0.5, 0.5, INTER_AREA); + + ASSERT_EQ(actual.type(), expected.type()); + ASSERT_EQ(actual.size(), expected.size()); + + Mat diff; + absdiff(actual, expected, diff); + + float elem_diff = 0.5f; + Size dsize = actual.size(); + bool next = true; + for (int dy = 0; dy < dsize.height && next; ++dy) + { + uchar* eD = expected.ptr(dy); + uchar* aD = actual.ptr(dy); + + for (int dx = 0; dx < dsize.width && next; ++dx) + if (fabs(static_cast(aD[dx] - eD[dx])) > elem_diff) + { + cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Inf norm: %f\n", static_cast(norm(actual, expected, NORM_INF))); + cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Error in : (%d, %d)\n", dx, dy); + + const int radius = 3; + int rmin = MAX(dy - radius, 0), rmax = MIN(dy + radius, dsize.height); + int cmin = MAX(dx - radius, 0), cmax = MIN(dx + radius, dsize.width); + + std::cout << "Abs diff:" << std::endl << diff << std::endl; + std::cout << "actual result:\n" << actual(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; + std::cout << "expected result:\n" << expected(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; + + next = false; + } + } + + ASSERT_EQ(norm(diff, cv::NORM_INF), 0); +} + +TEST(Imgproc_resize_area, regression_quarter_round) +{ + static uchar input_data[32 * 32]; + for(int i = 0; i < 32 * 32; ++i) + input_data[i] = i % 2 + 253 + i / (16 * 32); + + static uchar expected_data[8 * 8]; + for(int i = 0; i < 8 * 8; ++i) + expected_data[i] = 254; + + cv::Mat src(32, 32, CV_8UC1, input_data); + cv::Mat expected(8, 8, CV_8UC1, expected_data); + cv::Mat actual(expected.size(), expected.type()); + + cv::resize(src, actual, cv::Size(), 0.25, 0.25, INTER_AREA); + + ASSERT_EQ(actual.type(), expected.type()); + ASSERT_EQ(actual.size(), expected.size()); + + Mat diff; + absdiff(actual, expected, diff); + + float elem_diff = 0.5f; + Size dsize = actual.size(); + bool next = true; + for (int dy = 0; dy < dsize.height && next; ++dy) + { + uchar* eD = expected.ptr(dy); + uchar* aD = actual.ptr(dy); + + for (int dx = 0; dx < dsize.width && next; ++dx) + if (fabs(static_cast(aD[dx] - eD[dx])) > elem_diff) + { + cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Inf norm: %f\n", static_cast(norm(actual, expected, NORM_INF))); + cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Error in : (%d, %d)\n", dx, dy); + + const int radius = 3; + int rmin = MAX(dy - radius, 0), rmax = MIN(dy + radius, dsize.height); + int cmin = MAX(dx - radius, 0), cmax = MIN(dx + radius, dsize.width); + + std::cout << "Abs diff:" << std::endl << diff << std::endl; + std::cout << "actual result:\n" << actual(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; + std::cout << "expected result:\n" << expected(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; + + next = false; + } + } + + ASSERT_EQ(norm(diff, cv::NORM_INF), 0); +} + ////////////////////////////////////////////////////////////////////////// From 4a0152c731fc919bbc15d0d19c31445fc060e391 Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Fri, 31 Jul 2015 15:01:33 +0300 Subject: [PATCH 060/156] Resize area result verification moved to the separate function fix position of assert expected/actual parameter --- modules/imgproc/test/test_imgwarp.cpp | 153 +++++++++----------------- 1 file changed, 49 insertions(+), 104 deletions(-) diff --git a/modules/imgproc/test/test_imgwarp.cpp b/modules/imgproc/test/test_imgwarp.cpp index c2cf2bfc6..0568cbce0 100644 --- a/modules/imgproc/test/test_imgwarp.cpp +++ b/modules/imgproc/test/test_imgwarp.cpp @@ -1372,6 +1372,49 @@ void CV_GetQuadSubPixTest::prepare_to_validation( int /*test_case_idx*/ ) dst.convertTo(dst0, dst0.depth()); } +////////////////////////////// resizeArea ///////////////////////////////// + +template +static void check_resize_area(const Mat& expected, const Mat& actual, double tolerance = 1.0) +{ + ASSERT_EQ(actual.type(), expected.type()); + ASSERT_EQ(actual.size(), expected.size()); + + Mat diff; + absdiff(actual, expected, diff); + + Mat one_channel_diff = diff; //.reshape(1); + + Size dsize = actual.size(); + bool next = true; + for (int dy = 0; dy < dsize.height && next; ++dy) + { + const T* eD = expected.ptr(dy); + const T* aD = actual.ptr(dy); + + for (int dx = 0; dx < dsize.width && next; ++dx) + if (fabs(static_cast(aD[dx] - eD[dx])) > tolerance) + { + cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Inf norm: %f\n", static_cast(norm(actual, expected, NORM_INF))); + cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Error in : (%d, %d)\n", dx, dy); + + const int radius = 3; + int rmin = MAX(dy - radius, 0), rmax = MIN(dy + radius, dsize.height); + int cmin = MAX(dx - radius, 0), cmax = MIN(dx + radius, dsize.width); + + std::cout << "Abs diff:" << std::endl << diff << std::endl; + std::cout << "actual result:\n" << actual(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; + std::cout << "expected result:\n" << expected(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; + + next = false; + } + } + + ASSERT_EQ(0, norm(one_channel_diff, cv::NORM_INF)); +} + +/////////////////////////////////////////////////////////////////////////// + TEST(Imgproc_cvWarpAffine, regression) { IplImage* src = cvCreateImage(cvSize(100, 100), IPL_DEPTH_8U, 1); @@ -1501,52 +1544,18 @@ TEST(Imgproc_resize_area, regression) cv::resize(src, actual, cv::Size(), 0.3, 0.3, INTER_AREA); - ASSERT_EQ(actual.type(), expected.type()); - ASSERT_EQ(actual.size(), expected.size()); - - Mat diff; - absdiff(actual, expected, diff); - - Mat one_channel_diff = diff; //.reshape(1); - - float elem_diff = 1.0f; - Size dsize = actual.size(); - bool next = true; - for (int dy = 0; dy < dsize.height && next; ++dy) - { - ushort* eD = expected.ptr(dy); - ushort* aD = actual.ptr(dy); - - for (int dx = 0; dx < dsize.width && next; ++dx) - if (fabs(static_cast(aD[dx] - eD[dx])) > elem_diff) - { - cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Inf norm: %f\n", static_cast(norm(actual, expected, NORM_INF))); - cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Error in : (%d, %d)\n", dx, dy); - - const int radius = 3; - int rmin = MAX(dy - radius, 0), rmax = MIN(dy + radius, dsize.height); - int cmin = MAX(dx - radius, 0), cmax = MIN(dx + radius, dsize.width); - - std::cout << "Abs diff:" << std::endl << diff << std::endl; - std::cout << "actual result:\n" << actual(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; - std::cout << "expected result:\n" << expected(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; - - next = false; - } - } - - ASSERT_EQ(cvtest::norm(one_channel_diff, cv::NORM_INF), 0); + check_resize_area(expected, actual, 1.0); } TEST(Imgproc_resize_area, regression_half_round) { static uchar input_data[32 * 32]; for(int i = 0; i < 32 * 32; ++i) - input_data[i] = i % 2 + 253 + i / (16 * 32); + input_data[i] = (uchar)(i % 2 + 253 + i / (16 * 32)); static uchar expected_data[16 * 16]; for(int i = 0; i < 16 * 16; ++i) - expected_data[i] = 254 + i / (16 * 8); + expected_data[i] = (uchar)(254 + i / (16 * 8)); cv::Mat src(32, 32, CV_8UC1, input_data); cv::Mat expected(16, 16, CV_8UC1, expected_data); @@ -1554,46 +1563,14 @@ TEST(Imgproc_resize_area, regression_half_round) cv::resize(src, actual, cv::Size(), 0.5, 0.5, INTER_AREA); - ASSERT_EQ(actual.type(), expected.type()); - ASSERT_EQ(actual.size(), expected.size()); - - Mat diff; - absdiff(actual, expected, diff); - - float elem_diff = 0.5f; - Size dsize = actual.size(); - bool next = true; - for (int dy = 0; dy < dsize.height && next; ++dy) - { - uchar* eD = expected.ptr(dy); - uchar* aD = actual.ptr(dy); - - for (int dx = 0; dx < dsize.width && next; ++dx) - if (fabs(static_cast(aD[dx] - eD[dx])) > elem_diff) - { - cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Inf norm: %f\n", static_cast(norm(actual, expected, NORM_INF))); - cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Error in : (%d, %d)\n", dx, dy); - - const int radius = 3; - int rmin = MAX(dy - radius, 0), rmax = MIN(dy + radius, dsize.height); - int cmin = MAX(dx - radius, 0), cmax = MIN(dx + radius, dsize.width); - - std::cout << "Abs diff:" << std::endl << diff << std::endl; - std::cout << "actual result:\n" << actual(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; - std::cout << "expected result:\n" << expected(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; - - next = false; - } - } - - ASSERT_EQ(norm(diff, cv::NORM_INF), 0); + check_resize_area(expected, actual, 0.5); } TEST(Imgproc_resize_area, regression_quarter_round) { static uchar input_data[32 * 32]; for(int i = 0; i < 32 * 32; ++i) - input_data[i] = i % 2 + 253 + i / (16 * 32); + input_data[i] = (uchar)(i % 2 + 253 + i / (16 * 32)); static uchar expected_data[8 * 8]; for(int i = 0; i < 8 * 8; ++i) @@ -1605,39 +1582,7 @@ TEST(Imgproc_resize_area, regression_quarter_round) cv::resize(src, actual, cv::Size(), 0.25, 0.25, INTER_AREA); - ASSERT_EQ(actual.type(), expected.type()); - ASSERT_EQ(actual.size(), expected.size()); - - Mat diff; - absdiff(actual, expected, diff); - - float elem_diff = 0.5f; - Size dsize = actual.size(); - bool next = true; - for (int dy = 0; dy < dsize.height && next; ++dy) - { - uchar* eD = expected.ptr(dy); - uchar* aD = actual.ptr(dy); - - for (int dx = 0; dx < dsize.width && next; ++dx) - if (fabs(static_cast(aD[dx] - eD[dx])) > elem_diff) - { - cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Inf norm: %f\n", static_cast(norm(actual, expected, NORM_INF))); - cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Error in : (%d, %d)\n", dx, dy); - - const int radius = 3; - int rmin = MAX(dy - radius, 0), rmax = MIN(dy + radius, dsize.height); - int cmin = MAX(dx - radius, 0), cmax = MIN(dx + radius, dsize.width); - - std::cout << "Abs diff:" << std::endl << diff << std::endl; - std::cout << "actual result:\n" << actual(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; - std::cout << "expected result:\n" << expected(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; - - next = false; - } - } - - ASSERT_EQ(norm(diff, cv::NORM_INF), 0); + check_resize_area(expected, actual, 0.5); } From 344d9fd83f048d083783eaa792bccefed83c7815 Mon Sep 17 00:00:00 2001 From: Gleb Gladilov Date: Mon, 20 Jul 2015 15:10:46 +0300 Subject: [PATCH 061/156] Fixed minMaxLoc and test functions --- modules/core/src/stat.cpp | 12 ++++++++++-- modules/ts/src/ts_func.cpp | 15 ++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 0a4c0415c..ebb845a14 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -2331,8 +2331,8 @@ void cv::minMaxIdx(InputArray _src, double* minVal, size_t minidx = 0, maxidx = 0; int iminval = INT_MAX, imaxval = INT_MIN; - float fminval = FLT_MAX, fmaxval = -FLT_MAX; - double dminval = DBL_MAX, dmaxval = -DBL_MAX; + float fminval = std::numeric_limits::infinity(), fmaxval = -fminval; + double dminval = std::numeric_limits::infinity(), dmaxval = -dminval; size_t startidx = 1; int *minval = &iminval, *maxval = &imaxval; int planeSize = (int)it.size*cn; @@ -2345,6 +2345,14 @@ void cv::minMaxIdx(InputArray _src, double* minVal, for( size_t i = 0; i < it.nplanes; i++, ++it, startidx += planeSize ) func( ptrs[0], ptrs[1], minval, maxval, &minidx, &maxidx, planeSize, startidx ); + if (!src.empty() && mask.empty()) + { + if( minidx == 0 ) + minidx = 1; + if( maxidx == 0 ) + maxidx = 1; + } + if( minidx == 0 ) dminval = dmaxval = 0; else if( depth == CV_32F ) diff --git a/modules/ts/src/ts_func.cpp b/modules/ts/src/ts_func.cpp index f5fed678d..202a96f36 100644 --- a/modules/ts/src/ts_func.cpp +++ b/modules/ts/src/ts_func.cpp @@ -980,12 +980,12 @@ minMaxLoc_(const _Tp* src, size_t total, size_t startidx, for( size_t i = 0; i < total; i++ ) { _Tp val = src[i]; - if( minval > val ) + if( minval > val || !minpos ) { minval = val; minpos = startidx + i; } - if( maxval < val ) + if( maxval < val || !maxpos ) { maxval = val; maxpos = startidx + i; @@ -997,12 +997,12 @@ minMaxLoc_(const _Tp* src, size_t total, size_t startidx, for( size_t i = 0; i < total; i++ ) { _Tp val = src[i]; - if( minval > val && mask[i] ) + if( (minval > val || !minpos) && mask[i] ) { minval = val; minpos = startidx + i; } - if( maxval < val && mask[i] ) + if( (maxval < val || !maxpos) && mask[i] ) { maxval = val; maxpos = startidx + i; @@ -1049,8 +1049,8 @@ void minMaxLoc(const Mat& src, double* _minval, double* _maxval, size_t startidx = 1, total = planes[0].total(); size_t i, nplanes = it.nplanes; int depth = src.depth(); - double maxval = depth < CV_32F ? INT_MIN : depth == CV_32F ? -FLT_MAX : -DBL_MAX; - double minval = depth < CV_32F ? INT_MAX : depth == CV_32F ? FLT_MAX : DBL_MAX; + double minval = 0; + double maxval = 0; size_t maxidx = 0, minidx = 0; for( i = 0; i < nplanes; i++, ++it, startidx += total ) @@ -1093,9 +1093,6 @@ void minMaxLoc(const Mat& src, double* _minval, double* _maxval, } } - if( minidx == 0 ) - minval = maxval = 0; - if( _maxval ) *_maxval = maxval; if( _minval ) From 2bc448696681f9722ba31b0a264c6e629ecbefc0 Mon Sep 17 00:00:00 2001 From: Gleb Gladilov Date: Tue, 21 Jul 2015 18:08:30 +0300 Subject: [PATCH 062/156] Added test of minMaxLoc on filling with maximums of int --- modules/core/test/test_arithm.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index 8bd45ee39..0471ffc0b 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -1792,7 +1792,6 @@ INSTANTIATE_TEST_CASE_P(Arithm, SubtractOutputMatNotEmpty, testing::Combine( testing::Values(-1, CV_16S, CV_32S, CV_32F), testing::Bool())); - TEST(Core_FindNonZero, singular) { Mat img(10, 10, CV_8U, Scalar::all(0)); @@ -1816,3 +1815,21 @@ TEST(Core_BoolVector, support) ASSERT_EQ( nz, countNonZero(test) ); ASSERT_FLOAT_EQ((float)nz/n, (float)(mean(test)[0])); } + +TEST(MinMaxLoc, Mat_IntMax_Without_Mask) +{ + Mat_ mat(50, 50); + int iMaxVal = numeric_limits::max(); + mat.setTo(iMaxVal); + + double min, max; + Point minLoc, maxLoc; + + minMaxLoc(mat, &min, &max, &minLoc, &maxLoc, Mat()); + + ASSERT_EQ(iMaxVal, min); + ASSERT_EQ(iMaxVal, max); + + ASSERT_EQ(Point(0, 0), minLoc); + ASSERT_EQ(Point(0, 0), maxLoc); +} From 5dd76a47919985447514289da101ebc6c8e11ad4 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Mon, 8 Jun 2015 16:08:58 +0300 Subject: [PATCH 063/156] Set CPACK_DEBIAN_PACKAGE_ARCHITECTURE instead of CPACK_DEBIAN_ARCHITECTURE Because that's the variable actually used by CPack. --- cmake/OpenCVPackaging.cmake | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmake/OpenCVPackaging.cmake b/cmake/OpenCVPackaging.cmake index 59d602c5d..eb3594736 100644 --- a/cmake/OpenCVPackaging.cmake +++ b/cmake/OpenCVPackaging.cmake @@ -20,21 +20,21 @@ endif(NOT OPENCV_CUSTOM_PACKAGE_INFO) #arch if(X86) - set(CPACK_DEBIAN_ARCHITECTURE "i386") + set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "i386") set(CPACK_RPM_PACKAGE_ARCHITECTURE "i686") elseif(X86_64) - set(CPACK_DEBIAN_ARCHITECTURE "amd64") + set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64") set(CPACK_RPM_PACKAGE_ARCHITECTURE "x86_64") elseif(ARM) - set(CPACK_DEBIAN_ARCHITECTURE "armhf") + set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "armhf") set(CPACK_RPM_PACKAGE_ARCHITECTURE "armhf") else() - set(CPACK_DEBIAN_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) + set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) set(CPACK_RPM_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) endif() if(CPACK_GENERATOR STREQUAL "DEB") - set(OPENCV_PACKAGE_ARCH_SUFFIX ${CPACK_DEBIAN_ARCHITECTURE}) + set(OPENCV_PACKAGE_ARCH_SUFFIX ${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}) elseif(CPACK_GENERATOR STREQUAL "RPM") set(OPENCV_PACKAGE_ARCH_SUFFIX ${CPACK_RPM_PACKAGE_ARCHITECTURE}) else() From c0cc51cb4b6677697b940cda943c239fc2849f24 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Mon, 8 Jun 2015 18:01:24 +0300 Subject: [PATCH 064/156] Add ARM64 packaging support --- cmake/OpenCVPackaging.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/OpenCVPackaging.cmake b/cmake/OpenCVPackaging.cmake index eb3594736..60af2008f 100644 --- a/cmake/OpenCVPackaging.cmake +++ b/cmake/OpenCVPackaging.cmake @@ -28,6 +28,9 @@ elseif(X86_64) elseif(ARM) set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "armhf") set(CPACK_RPM_PACKAGE_ARCHITECTURE "armhf") +elseif(AARCH64) + set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64") + set(CPACK_RPM_PACKAGE_ARCHITECTURE "aarch64") else() set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) set(CPACK_RPM_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) From 0e5fec288c836363883400aac4d679eab354231e Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Tue, 19 May 2015 18:17:28 +0300 Subject: [PATCH 065/156] check that current directory has write access --- cmake/templates/opencv_run_all_tests_unix.sh.in | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cmake/templates/opencv_run_all_tests_unix.sh.in b/cmake/templates/opencv_run_all_tests_unix.sh.in index 7b946af13..a21bb03fd 100644 --- a/cmake/templates/opencv_run_all_tests_unix.sh.in +++ b/cmake/templates/opencv_run_all_tests_unix.sh.in @@ -55,6 +55,15 @@ OPENCV_TEST_PATH=@CMAKE_INSTALL_PREFIX@/@OPENCV_TEST_INSTALL_PATH@ OPENCV_PYTHON_TESTS=@OPENCV_PYTHON_TESTS_LIST@ export OPENCV_TEST_DATA_PATH=@CMAKE_INSTALL_PREFIX@/share/OpenCV/testdata +CUR_DIR=`pwd` +if [ -d "$CUR_DIR" -a -w "$CUR_DIR" ]; then + echo "${TEXT_CYAN}CUR_DIR : $CUR_DIR${TEXT_RESET}" +else + echo "${TEXT_RED}Error: Do not have permissions to write to $CUR_DIR${TEXT_RESET}" + echo "${TEXT_RED}Please run the script from directory with write access${TEXT_RESET}" + exit 1 +fi + # Run tests SUMMARY_STATUS=0 From ea35fee5b824b438be98d9a140f1b73557963833 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Tue, 19 May 2015 18:22:30 +0300 Subject: [PATCH 066/156] save tests console output to separate log files --- cmake/templates/opencv_run_all_tests_unix.sh.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/templates/opencv_run_all_tests_unix.sh.in b/cmake/templates/opencv_run_all_tests_unix.sh.in index a21bb03fd..9789a6b7f 100644 --- a/cmake/templates/opencv_run_all_tests_unix.sh.in +++ b/cmake/templates/opencv_run_all_tests_unix.sh.in @@ -88,7 +88,7 @@ do fi echo "${TEXT_CYAN}[$test_name]${TEXT_RESET} RUN : $cmd" - $cmd | sed -r "$seg_reg" + eval "$cmd" | tee "$test_name.log" | sed -r "$seg_reg" ret=${PIPESTATUS[0]} echo "${TEXT_CYAN}[$test_name]${TEXT_RESET} RETURN_CODE : $ret" @@ -114,7 +114,7 @@ do seg_reg="s/^/${TEXT_CYAN}[$test_name]${TEXT_RESET} /" # append test name echo "${TEXT_CYAN}[$test_name]${TEXT_RESET} RUN : $cmd" - eval "$cmd" | sed -r "$seg_reg" + eval "$cmd" | tee "$test_name.log" | sed -r "$seg_reg" ret=${PIPESTATUS[0]} echo "${TEXT_CYAN}[$test_name]${TEXT_RESET} RETURN_CODE : $ret" From 6282ff0887ae5c3daaac759b9e821d6062ae4113 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Tue, 19 May 2015 18:23:10 +0300 Subject: [PATCH 067/156] exclude dates from report names --- cmake/templates/opencv_run_all_tests_unix.sh.in | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cmake/templates/opencv_run_all_tests_unix.sh.in b/cmake/templates/opencv_run_all_tests_unix.sh.in index 9789a6b7f..f92d7c613 100644 --- a/cmake/templates/opencv_run_all_tests_unix.sh.in +++ b/cmake/templates/opencv_run_all_tests_unix.sh.in @@ -73,9 +73,8 @@ PASSED_TESTS="" for t in "$OPENCV_TEST_PATH/"opencv_test_* "$OPENCV_TEST_PATH/"opencv_perf_*; do test_name=`basename "$t"` - report="$test_name-`date --rfc-3339=date`.xml" - cmd="$t --perf_min_samples=1 --perf_force_samples=1 --gtest_output=xml:\"$report\"" + cmd="$t --perf_min_samples=1 --perf_force_samples=1 --gtest_output=xml:$test_name.xml" seg_reg="s/^/${TEXT_CYAN}[$test_name]${TEXT_RESET} /" # append test name if [ $COLOR_OUTPUT -eq 1 ]; then @@ -107,9 +106,8 @@ done for t in $OPENCV_PYTHON_TESTS; do test_name=`basename "$t"` - report="$test_name-`date --rfc-3339=date`.xml" - cmd="py.test --junitxml $report \"$OPENCV_TEST_PATH\"/$t" + cmd="py.test --junitxml $test_name.xml \"$OPENCV_TEST_PATH\"/$t" seg_reg="s/^/${TEXT_CYAN}[$test_name]${TEXT_RESET} /" # append test name From 55df326589b708dd765ee67e17eaa903164d7891 Mon Sep 17 00:00:00 2001 From: Dikay900 Date: Sat, 19 Sep 2015 14:05:38 +0200 Subject: [PATCH 068/156] PR #4003 --- modules/videoio/include/opencv2/videoio/cap_ios.h | 2 ++ modules/videoio/src/cap_ios_video_camera.mm | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/modules/videoio/include/opencv2/videoio/cap_ios.h b/modules/videoio/include/opencv2/videoio/cap_ios.h index cf7f2e4ff..1a9875b25 100644 --- a/modules/videoio/include/opencv2/videoio/cap_ios.h +++ b/modules/videoio/include/opencv2/videoio/cap_ios.h @@ -71,6 +71,7 @@ @property (nonatomic, readonly) BOOL captureSessionLoaded; @property (nonatomic, assign) int defaultFPS; +@property (nonatomic, readonly) AVCaptureVideoPreviewLayer *captureVideoPreviewLayer; @property (nonatomic, assign) AVCaptureDevicePosition defaultAVCaptureDevicePosition; @property (nonatomic, assign) AVCaptureVideoOrientation defaultAVCaptureVideoOrientation; @property (nonatomic, assign) BOOL useAVCaptureVideoPreviewLayer; @@ -145,6 +146,7 @@ - (void)layoutPreviewLayer; - (void)saveVideo; - (NSURL *)videoFileURL; +- (NSString *)videoFileString; @end diff --git a/modules/videoio/src/cap_ios_video_camera.mm b/modules/videoio/src/cap_ios_video_camera.mm index 0acec6686..1ae70e298 100644 --- a/modules/videoio/src/cap_ios_video_camera.mm +++ b/modules/videoio/src/cap_ios_video_camera.mm @@ -41,7 +41,9 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} -@interface CvVideoCamera () +@interface CvVideoCamera () { + int recordingCountDown; +} - (void)createVideoDataOutput; - (void)createVideoFileOutput; @@ -98,6 +100,7 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} - (void)start; { + recordingCountDown = 10; [super start]; if (self.recordVideo == YES) { @@ -551,7 +554,8 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} }); - if (self.recordVideo == YES) { + recordingCountDown--; + if (self.recordVideo == YES && recordingCountDown < 0) { lastSampleTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer); // CMTimeShow(lastSampleTime); if (self.recordAssetWriter.status != AVAssetWriterStatusWriting) { @@ -571,6 +575,8 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} withPresentationTime:lastSampleTime] ) { NSLog(@"Video Writing Error"); } + if (pixelBuffer != nullptr) + CVPixelBufferRelease(pixelBuffer); } } From c7bfdc2063285d864d7e713c4fa2b6c2716330b9 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Wed, 6 May 2015 13:10:39 +0300 Subject: [PATCH 069/156] Added explicit deb package dependency from libtbb-dev if TBB is enabled. --- cmake/OpenCVPackaging.cmake | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmake/OpenCVPackaging.cmake b/cmake/OpenCVPackaging.cmake index 60af2008f..2330decda 100644 --- a/cmake/OpenCVPackaging.cmake +++ b/cmake/OpenCVPackaging.cmake @@ -99,6 +99,14 @@ if(HAVE_CUDA) set(CPACK_COMPONENT_dev_DEPENDS libs) endif() +if(HAVE_TBB AND NOT BUILD_TBB) + if(CPACK_DEB_DEV_PACKAGE_DEPENDS) + set(CPACK_DEB_DEV_PACKAGE_DEPENDS "${CPACK_DEB_DEV_PACKAGE_DEPENDS}, libtbb-dev") + else() + set(CPACK_DEB_DEV_PACKAGE_DEPENDS "libtbb-dev") + endif() +endif() + if(NOT OPENCV_CUSTOM_PACKAGE_INFO) set(CPACK_COMPONENT_LIBS_DESCRIPTION "Open Computer Vision Library") set(CPACK_DEBIAN_COMPONENT_LIBS_NAME "lib${CMAKE_PROJECT_NAME}") From bd5a222d84684a888bcc8d5b13b823b77ea90728 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Thu, 4 Jun 2015 15:42:27 +0300 Subject: [PATCH 070/156] Debian packages header update to fix conflict with OpenCV from deb repo. --- cmake/OpenCVPackaging.cmake | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/cmake/OpenCVPackaging.cmake b/cmake/OpenCVPackaging.cmake index 2330decda..894f669e5 100644 --- a/cmake/OpenCVPackaging.cmake +++ b/cmake/OpenCVPackaging.cmake @@ -107,6 +107,35 @@ if(HAVE_TBB AND NOT BUILD_TBB) endif() endif() +set(STD_OPENCV_LIBS opencv-data libopencv-calib3d2.4 libopencv-contrib2.4 libopencv-core2.4 + libopencv-features2d2.4 libopencv-flann2.4 libopencv-gpu2.4 libopencv-imgproc2.4 + libopencv-ml2.4 libopencv-ocl2.4 libopencv-stitching2.4 libopencv-ts2.4 libopencv-videostab2.4) + +set(STD_OPENCV_DEV libopencv-calib3d-dev libopencv-contrib-dev libopencv-core-dev + libopencv-dev libopencv-features2d-dev libopencv-flann-dev libopencv-gpu-dev + libopencv-highgui-dev libopencv-imgproc-dev libopencv-legacy-dev libopencv-ml-dev + libopencv-objdetect-dev libopencv-ocl-dev libopencv-photo-dev libopencv-stitching-dev + libopencv-superres-dev libopencv-ts-dev libopencv-video-dev libopencv-videostab-dev) + +string(REPLACE ";" ", " CPACK_COMPONENT_LIBS_CONFLICTS "${STD_OPENCV_LIBS}") +string(REPLACE ";" ", " CPACK_COMPONENT_LIBS_PROVIDES "${STD_OPENCV_LIBS}") +string(REPLACE ";" ", " CPACK_COMPONENT_LIBS_REPLACES "${STD_OPENCV_LIBS}") + +string(REPLACE ";" ", " CPACK_COMPONENT_DEV_CONFLICTS "${STD_OPENCV_DEV}") +string(REPLACE ";" ", " CPACK_COMPONENT_DEV_PROVIDES "${STD_OPENCV_DEV}") +string(REPLACE ";" ", " CPACK_COMPONENT_DEV_REPLACES "${STD_OPENCV_DEV}") + +set(CPACK_COMPONENT_PYTHON_CONFLICTS python-opencv) +set(CPACK_COMPONENT_PYTHON_PROVIDES python-opencv) +set(CPACK_COMPONENT_PYTHON_REPLACES python-opencv) + +set(CPACK_COMPONENT_JAVA_CONFLICTS "libopencv2.4-java, libopencv2.4-jni") +set(CPACK_COMPONENT_JAVA_PROVIDES "libopencv2.4-java, libopencv2.4-jni") +set(CPACK_COMPONENT_JAVA_REPLACES "libopencv2.4-java, libopencv2.4-jni") + +set(CPACK_COMPONENT_DOCS_CONFLICTS opencv-doc) +set(CPACK_COMPONENT_SAMPLES_CONFLICTS opencv-doc) + if(NOT OPENCV_CUSTOM_PACKAGE_INFO) set(CPACK_COMPONENT_LIBS_DESCRIPTION "Open Computer Vision Library") set(CPACK_DEBIAN_COMPONENT_LIBS_NAME "lib${CMAKE_PROJECT_NAME}") From 7749eb5d1f43091a535dcaeba23c5af792c75f5d Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Tue, 25 Aug 2015 18:50:06 +0300 Subject: [PATCH 071/156] Add missing packages to the Debian conflict list And refactor the code to make sure that the dev and runtime package lists are in sync. --- cmake/OpenCVPackaging.cmake | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/cmake/OpenCVPackaging.cmake b/cmake/OpenCVPackaging.cmake index 894f669e5..b3943e79a 100644 --- a/cmake/OpenCVPackaging.cmake +++ b/cmake/OpenCVPackaging.cmake @@ -107,15 +107,14 @@ if(HAVE_TBB AND NOT BUILD_TBB) endif() endif() -set(STD_OPENCV_LIBS opencv-data libopencv-calib3d2.4 libopencv-contrib2.4 libopencv-core2.4 - libopencv-features2d2.4 libopencv-flann2.4 libopencv-gpu2.4 libopencv-imgproc2.4 - libopencv-ml2.4 libopencv-ocl2.4 libopencv-stitching2.4 libopencv-ts2.4 libopencv-videostab2.4) +set(STD_OPENCV_LIBS opencv-data) +set(STD_OPENCV_DEV libopencv-dev) -set(STD_OPENCV_DEV libopencv-calib3d-dev libopencv-contrib-dev libopencv-core-dev - libopencv-dev libopencv-features2d-dev libopencv-flann-dev libopencv-gpu-dev - libopencv-highgui-dev libopencv-imgproc-dev libopencv-legacy-dev libopencv-ml-dev - libopencv-objdetect-dev libopencv-ocl-dev libopencv-photo-dev libopencv-stitching-dev - libopencv-superres-dev libopencv-ts-dev libopencv-video-dev libopencv-videostab-dev) +foreach(module calib3d contrib core features2d flann gpu highgui imgproc legacy + ml objdetect ocl photo stitching superres ts video videostab) + list(APPEND STD_OPENCV_LIBS "libopencv-${module}2.4") + list(APPEND STD_OPENCV_DEV "libopencv-${module}-dev") +endforeach() string(REPLACE ";" ", " CPACK_COMPONENT_LIBS_CONFLICTS "${STD_OPENCV_LIBS}") string(REPLACE ";" ", " CPACK_COMPONENT_LIBS_PROVIDES "${STD_OPENCV_LIBS}") From 2eab5eb6c080b319674366a375c49b02497e9ea9 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Wed, 26 Aug 2015 13:42:21 +0300 Subject: [PATCH 072/156] Only conflict with packages corresponding to modules that are built --- cmake/OpenCVPackaging.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/OpenCVPackaging.cmake b/cmake/OpenCVPackaging.cmake index b3943e79a..1574ffa73 100644 --- a/cmake/OpenCVPackaging.cmake +++ b/cmake/OpenCVPackaging.cmake @@ -112,8 +112,10 @@ set(STD_OPENCV_DEV libopencv-dev) foreach(module calib3d contrib core features2d flann gpu highgui imgproc legacy ml objdetect ocl photo stitching superres ts video videostab) - list(APPEND STD_OPENCV_LIBS "libopencv-${module}2.4") - list(APPEND STD_OPENCV_DEV "libopencv-${module}-dev") + if(HAVE_opencv_${module}) + list(APPEND STD_OPENCV_LIBS "libopencv-${module}2.4") + list(APPEND STD_OPENCV_DEV "libopencv-${module}-dev") + endif() endforeach() string(REPLACE ";" ", " CPACK_COMPONENT_LIBS_CONFLICTS "${STD_OPENCV_LIBS}") From 32a4ec156bc9f56ad2520ffbf29b0bb6a71d718b Mon Sep 17 00:00:00 2001 From: Dikay900 Date: Sat, 19 Sep 2015 14:15:40 +0200 Subject: [PATCH 073/156] changes to reflect 3.0 status --- cmake/OpenCVPackaging.cmake | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/cmake/OpenCVPackaging.cmake b/cmake/OpenCVPackaging.cmake index 1574ffa73..21a82a478 100644 --- a/cmake/OpenCVPackaging.cmake +++ b/cmake/OpenCVPackaging.cmake @@ -110,10 +110,12 @@ endif() set(STD_OPENCV_LIBS opencv-data) set(STD_OPENCV_DEV libopencv-dev) -foreach(module calib3d contrib core features2d flann gpu highgui imgproc legacy - ml objdetect ocl photo stitching superres ts video videostab) +foreach(module calib3d core cudaarithm cudabgsegm cudacodec cudafeatures2d cudafilters + cudaimgproc cudalegacy cudaobjdetect cudaoptflow cudastereo cudawarping + cudev features2d flann hal highgui imgcodecs imgproc ml objdetect ocl + photo shape stitching superres ts video videoio videostab viz) if(HAVE_opencv_${module}) - list(APPEND STD_OPENCV_LIBS "libopencv-${module}2.4") + list(APPEND STD_OPENCV_LIBS "libopencv-${module}3.0") list(APPEND STD_OPENCV_DEV "libopencv-${module}-dev") endif() endforeach() @@ -130,9 +132,9 @@ set(CPACK_COMPONENT_PYTHON_CONFLICTS python-opencv) set(CPACK_COMPONENT_PYTHON_PROVIDES python-opencv) set(CPACK_COMPONENT_PYTHON_REPLACES python-opencv) -set(CPACK_COMPONENT_JAVA_CONFLICTS "libopencv2.4-java, libopencv2.4-jni") -set(CPACK_COMPONENT_JAVA_PROVIDES "libopencv2.4-java, libopencv2.4-jni") -set(CPACK_COMPONENT_JAVA_REPLACES "libopencv2.4-java, libopencv2.4-jni") +set(CPACK_COMPONENT_JAVA_CONFLICTS "libopencv3.0-java, libopencv3.0-jni") +set(CPACK_COMPONENT_JAVA_PROVIDES "libopencv3.0-java, libopencv3.0-jni") +set(CPACK_COMPONENT_JAVA_REPLACES "libopencv3.0-java, libopencv3.0-jni") set(CPACK_COMPONENT_DOCS_CONFLICTS opencv-doc) set(CPACK_COMPONENT_SAMPLES_CONFLICTS opencv-doc) From 33e659786f8a13da46ea3892dae0300d7baff6e2 Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Mon, 21 Sep 2015 18:11:20 +0300 Subject: [PATCH 074/156] Fix for cmp16s condition during IPP compare type convert; --- modules/core/src/arithm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index 1b8705983..a9240f8d4 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -4692,7 +4692,7 @@ static void cmp16s(const short* src1, size_t step1, const short* src2, size_t st CV_IPP_CHECK() { IppCmpOp op = convert_cmp(*(int *)_cmpop); - if( op > 0 ) + if( op >= 0 ) { fixSteps(size, sizeof(dst[0]), step1, step2, step); if (0 <= ippiCompare_16s_C1R(src1, (int)step1, src2, (int)step2, dst, (int)step, ippiSize(size), op)) From be507b20cda0e0c1e59c61213ad30fcbd9174051 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 22 Sep 2015 15:02:43 +0300 Subject: [PATCH 075/156] fix perf tests --- modules/ts/src/ts_perf.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/modules/ts/src/ts_perf.cpp b/modules/ts/src/ts_perf.cpp index c9e872b4c..6201dff7d 100644 --- a/modules/ts/src/ts_perf.cpp +++ b/modules/ts/src/ts_perf.cpp @@ -819,10 +819,8 @@ void TestBase::Init(const std::vector & availableImpls, param_write_sanity = args.get("perf_write_sanity"); param_verify_sanity = args.get("perf_verify_sanity"); -#ifndef WINRT +#ifdef HAVE_IPP test_ipp_check = !args.get("perf_ipp_check") ? getenv("OPENCV_IPP_CHECK") != NULL : true; -#else - test_ipp_check = false; #endif param_threads = args.get("perf_threads"); #ifdef CV_COLLECT_IMPL_DATA @@ -916,7 +914,7 @@ void TestBase::Init(const std::vector & availableImpls, if (!args.check()) { args.printErrors(); - return; + exit(); } timeLimitDefault = param_time_limit == 0.0 ? 1 : (int64)(param_time_limit * cv::getTickFrequency()); From 12f01b778b702071398ee70eb2979195a6cdbe6d Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 22 Sep 2015 15:02:43 +0300 Subject: [PATCH 076/156] fix perf tests --- modules/ts/src/ts_perf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ts/src/ts_perf.cpp b/modules/ts/src/ts_perf.cpp index 6201dff7d..1a959f176 100644 --- a/modules/ts/src/ts_perf.cpp +++ b/modules/ts/src/ts_perf.cpp @@ -914,7 +914,7 @@ void TestBase::Init(const std::vector & availableImpls, if (!args.check()) { args.printErrors(); - exit(); + exit(1); } timeLimitDefault = param_time_limit == 0.0 ? 1 : (int64)(param_time_limit * cv::getTickFrequency()); From d430e802f2cdb4a144caaad45199f3c222b31f69 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 22 Sep 2015 15:15:38 +0300 Subject: [PATCH 077/156] cmdparser: allow empty strings --- modules/core/src/command_line_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/command_line_parser.cpp b/modules/core/src/command_line_parser.cpp index a7c1edc69..967095941 100644 --- a/modules/core/src/command_line_parser.cpp +++ b/modules/core/src/command_line_parser.cpp @@ -104,7 +104,7 @@ void CommandLineParser::getByName(const String& name, bool space_delete, int typ v = impl->cat_string(v); // it is an error if we just got the default value here - if(v.empty()) + if (v.empty() && type != Param::STRING) break; from_str(v, type, dst); From eb2e061e3f4ef433771f0b2c2b577cc5a956fd33 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 22 Sep 2015 15:35:25 +0300 Subject: [PATCH 078/156] fix Android camera datarace (mCameraFrameReady) --- .../java/generator/src/java/android+JavaCameraView.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/java/generator/src/java/android+JavaCameraView.java b/modules/java/generator/src/java/android+JavaCameraView.java index fca29db6e..f4405c350 100644 --- a/modules/java/generator/src/java/android+JavaCameraView.java +++ b/modules/java/generator/src/java/android+JavaCameraView.java @@ -328,6 +328,7 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb @Override public void run() { do { + boolean hasFrame = false; synchronized (JavaCameraView.this) { try { while (!mCameraFrameReady && !mStopThread) { @@ -337,11 +338,14 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb e.printStackTrace(); } if (mCameraFrameReady) + { mChainIdx = 1 - mChainIdx; + mCameraFrameReady = false; + hasFrame = true; + } } - if (!mStopThread && mCameraFrameReady) { - mCameraFrameReady = false; + if (!mStopThread && hasFrame) { if (!mFrameChain[1 - mChainIdx].empty()) deliverAndDrawFrame(mCameraFrame[1 - mChainIdx]); } From 2ced3ba27644b828f7f40dac77bf3ea75aedee0f Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Tue, 22 Sep 2015 12:16:09 +0200 Subject: [PATCH 079/156] CommandLineParser: throw on programmer error requesting a previously undeclared key is most likely an programming error. e.g. a typo "--unused vs --unsued". So throw in those cases. Add an according failure testcase. --- modules/core/src/command_line_parser.cpp | 40 ++++++++++++++---------- modules/core/test/test_utils.cpp | 16 +++++++--- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/modules/core/src/command_line_parser.cpp b/modules/core/src/command_line_parser.cpp index 967095941..4ef4f7dee 100644 --- a/modules/core/src/command_line_parser.cpp +++ b/modules/core/src/command_line_parser.cpp @@ -37,7 +37,7 @@ struct CommandLineParser::Impl }; -static String get_type_name(int type) +static const char* get_type_name(int type) { if( type == Param::INT ) return "int"; @@ -78,14 +78,11 @@ static void from_str(const String& str, int type, void* dst) else if( type == Param::STRING ) *(String*)dst = str; else - throw cv::Exception(CV_StsBadArg, "unknown/unsupported parameter type", "", __FILE__, __LINE__); + CV_Error(Error::StsBadArg, "unknown/unsupported parameter type"); if (ss.fail()) { - String err_msg = "can not convert: [" + str + - + "] to [" + get_type_name(type) + "]"; - - throw cv::Exception(CV_StsBadArg, err_msg, "", __FILE__, __LINE__); + CV_Error_(Error::StsBadArg, ("can not convert: [%s] to [%s]", str.c_str(), get_type_name(type))); } } @@ -103,23 +100,27 @@ void CommandLineParser::getByName(const String& name, bool space_delete, int typ if (space_delete) v = impl->cat_string(v); - // it is an error if we just got the default value here - if (v.empty() && type != Param::STRING) - break; + // the key was neither specified nor has it a default value + if(v.empty() && type != Param::STRING) { + impl->error = true; + impl->error_message = impl->error_message + "Missing parameter: '" + name + "'\n"; + return; + } from_str(v, type, dst); return; } } } - impl->error = true; - impl->error_message = impl->error_message + "Missing parameter: '" + name + "'\n"; } catch (Exception& e) { impl->error = true; impl->error_message = impl->error_message + "Parameter '"+ name + "': " + e.err + "\n"; + return; } + + CV_Error_(Error::StsBadArg, ("undeclared key '%s' requested", name.c_str())); } @@ -134,22 +135,25 @@ void CommandLineParser::getByIndex(int index, bool space_delete, int type, void* String v = impl->data[i].def_value; if (space_delete == true) v = impl->cat_string(v); - // it is an error if we just got the default value here - if(v.empty()) - break; - + // the key was neither specified nor has it a default value + if(v.empty() && type != Param::STRING) { + impl->error = true; + impl->error_message = impl->error_message + format("Missing parameter #%d\n", index); + return; + } from_str(v, type, dst); return; } } - impl->error = true; - impl->error_message = impl->error_message + "Missing parameter #" + format("%d", index) + "\n"; } catch(Exception& e) { impl->error = true; impl->error_message = impl->error_message + format("Parameter #%d: ", index) + e.err + "\n"; + return; } + + CV_Error_(Error::StsBadArg, ("undeclared position %d requested", index)); } static bool cmp_params(const CommandLineParserParams & p1, const CommandLineParserParams & p2) @@ -340,6 +344,8 @@ bool CommandLineParser::has(const String& name) const } } } + + CV_Error_(Error::StsBadArg, ("undeclared key '%s' requested", name.c_str())); return false; } diff --git a/modules/core/test/test_utils.cpp b/modules/core/test/test_utils.cpp index f69a063eb..86387eb9d 100644 --- a/modules/core/test/test_utils.cpp +++ b/modules/core/test/test_utils.cpp @@ -15,6 +15,18 @@ static const char * const keys = "{ n unused | | dummy }" ; +TEST(CommandLineParser, testFailure) +{ + const char* argv[] = {"", "-q"}; + const int argc = 2; + cv::CommandLineParser parser(argc, argv, keys); + EXPECT_ANY_THROW(parser.has("q")); + EXPECT_ANY_THROW(parser.get("q")); + EXPECT_ANY_THROW(parser.get(0)); + + parser.get("h"); + EXPECT_FALSE(parser.check()); +} TEST(CommandLineParser, testHas_noValues) { const char* argv[] = {"", "-h", "--info"}; @@ -26,7 +38,6 @@ TEST(CommandLineParser, testHas_noValues) EXPECT_TRUE(parser.has("i")); EXPECT_FALSE(parser.has("n")); EXPECT_FALSE(parser.has("unused")); - EXPECT_FALSE(parser.has("q")); // TODO Throw ??? } TEST(CommandLineParser, testHas_TrueValues) { @@ -39,7 +50,6 @@ TEST(CommandLineParser, testHas_TrueValues) EXPECT_TRUE(parser.has("i")); EXPECT_FALSE(parser.has("n")); EXPECT_FALSE(parser.has("unused")); - EXPECT_FALSE(parser.has("q")); // TODO Throw ??? } TEST(CommandLineParser, testHas_TrueValues1) { @@ -52,7 +62,6 @@ TEST(CommandLineParser, testHas_TrueValues1) EXPECT_TRUE(parser.has("i")); EXPECT_FALSE(parser.has("n")); EXPECT_FALSE(parser.has("unused")); - EXPECT_FALSE(parser.has("q")); // TODO Throw ??? } TEST(CommandLineParser, testHas_FalseValues0) { @@ -65,7 +74,6 @@ TEST(CommandLineParser, testHas_FalseValues0) EXPECT_TRUE(parser.has("i")); EXPECT_FALSE(parser.has("n")); EXPECT_FALSE(parser.has("unused")); - EXPECT_FALSE(parser.has("q")); // TODO Throw ??? } TEST(CommandLineParser, testBoolOption_noArgs) From a3888065556b1fa455969aa69f9d2c71aea811e6 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Tue, 22 Sep 2015 17:02:58 +0200 Subject: [PATCH 080/156] enable additional CommandLineParser tests --- modules/core/test/test_utils.cpp | 36 +++++++++++++++++--------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/modules/core/test/test_utils.cpp b/modules/core/test/test_utils.cpp index 86387eb9d..f961b9344 100644 --- a/modules/core/test/test_utils.cpp +++ b/modules/core/test/test_utils.cpp @@ -137,12 +137,14 @@ TEST(CommandLineParser, testPositional_noArgs) const char* argv[] = {""}; const int argc = 1; cv::CommandLineParser parser(argc, argv, keys2); - //EXPECT_FALSE(parser.has("arg1")); - //EXPECT_FALSE(parser.has("arg2")); - //EXPECT_EQ("default1", parser.get("arg1")); + EXPECT_TRUE(parser.has("@arg1")); + EXPECT_FALSE(parser.has("@arg2")); + EXPECT_EQ("default1", parser.get("@arg1")); EXPECT_EQ("default1", parser.get(0)); - //??? EXPECT_ANY_THROW(parser.get("arg2")); - //??? EXPECT_ANY_THROW(parser.get(1)); + + parser.get("@arg2"); + parser.get(1); + EXPECT_TRUE(parser.check()); } TEST(CommandLineParser, testPositional_default) @@ -150,10 +152,10 @@ TEST(CommandLineParser, testPositional_default) const char* argv[] = {"", "test1", "test2"}; const int argc = 3; cv::CommandLineParser parser(argc, argv, keys2); - //EXPECT_TRUE(parser.has("arg1")); - //EXPECT_TRUE(parser.has("arg2")); - //EXPECT_EQ("test1", parser.get("arg1")); - //EXPECT_EQ("test2", parser.get("arg2")); + EXPECT_TRUE(parser.has("@arg1")); + EXPECT_TRUE(parser.has("@arg2")); + EXPECT_EQ("test1", parser.get("@arg1")); + EXPECT_EQ("test2", parser.get("@arg2")); EXPECT_EQ("test1", parser.get(0)); EXPECT_EQ("test2", parser.get(1)); } @@ -163,10 +165,10 @@ TEST(CommandLineParser, testPositional_withFlagsBefore) const char* argv[] = {"", "-h", "test1", "test2"}; const int argc = 4; cv::CommandLineParser parser(argc, argv, keys2); - //EXPECT_TRUE(parser.has("arg1")); - //EXPECT_TRUE(parser.has("arg2")); - //EXPECT_EQ("test1", parser.get("arg1")); - //EXPECT_EQ("test2", parser.get("arg2")); + EXPECT_TRUE(parser.has("@arg1")); + EXPECT_TRUE(parser.has("@arg2")); + EXPECT_EQ("test1", parser.get("@arg1")); + EXPECT_EQ("test2", parser.get("@arg2")); EXPECT_EQ("test1", parser.get(0)); EXPECT_EQ("test2", parser.get(1)); } @@ -176,10 +178,10 @@ TEST(CommandLineParser, testPositional_withFlagsAfter) const char* argv[] = {"", "test1", "test2", "-h"}; const int argc = 4; cv::CommandLineParser parser(argc, argv, keys2); - //EXPECT_TRUE(parser.has("arg1")); - //EXPECT_TRUE(parser.has("arg2")); - //EXPECT_EQ("test1", parser.get("arg1")); - //EXPECT_EQ("test2", parser.get("arg2")); + EXPECT_TRUE(parser.has("@arg1")); + EXPECT_TRUE(parser.has("@arg2")); + EXPECT_EQ("test1", parser.get("@arg1")); + EXPECT_EQ("test2", parser.get("@arg2")); EXPECT_EQ("test1", parser.get(0)); EXPECT_EQ("test2", parser.get(1)); } From 74fc9acdd1ae975ecf4d89824d8b0ee329199b68 Mon Sep 17 00:00:00 2001 From: berak Date: Sat, 19 Sep 2015 10:10:33 +0200 Subject: [PATCH 081/156] initialize temp_train_samples in SVM::autoTrain add smoke test --- modules/ml/src/svm.cpp | 4 ++-- modules/ml/test/test_svmtrainauto.cpp | 31 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/modules/ml/src/svm.cpp b/modules/ml/src/svm.cpp index 812e2839b..402de3f1d 100644 --- a/modules/ml/src/svm.cpp +++ b/modules/ml/src/svm.cpp @@ -1795,10 +1795,10 @@ public: if( !do_train( temp_train_samples, temp_train_responses )) continue; - for( i = 0; i < train_sample_count; i++ ) + for( i = 0; i < test_sample_count; i++ ) { j = sidx[(i+start+train_sample_count) % sample_count]; - memcpy(temp_train_samples.ptr(i), samples.ptr(j), sample_size); + memcpy(temp_test_samples.ptr(i), samples.ptr(j), sample_size); } predict(temp_test_samples, temp_test_responses, 0); diff --git a/modules/ml/test/test_svmtrainauto.cpp b/modules/ml/test/test_svmtrainauto.cpp index 918d2b711..3c4b72924 100644 --- a/modules/ml/test/test_svmtrainauto.cpp +++ b/modules/ml/test/test_svmtrainauto.cpp @@ -87,3 +87,34 @@ void CV_SVMTrainAutoTest::run( int /*start_from*/ ) } TEST(ML_SVM, trainauto) { CV_SVMTrainAutoTest test; test.safe_run(); } + + +TEST(ML_SVM, trainAuto_regression_5369) +{ + int datasize = 100; + cv::Mat samples = cv::Mat::zeros( datasize, 2, CV_32FC1 ); + cv::Mat responses = cv::Mat::zeros( datasize, 1, CV_32S ); + + RNG rng(0); // fixed! + for (int i = 0; i < datasize; ++i) + { + int response = rng.uniform(0, 2); // Random from {0, 1}. + samples.at( i, 0 ) = 0; + samples.at( i, 1 ) = (0.5f - response) * rng.uniform(0.f, 1.2f) + response; + responses.at( i, 0 ) = response; + } + + cv::Ptr data = TrainData::create( samples, cv::ml::ROW_SAMPLE, responses ); + cv::Ptr svm = SVM::create(); + svm->trainAuto( data, 10 ); // 2-fold cross validation. + + float test_data0[2] = {0.25f, 0.25f}; + cv::Mat test_point0 = cv::Mat( 1, 2, CV_32FC1, test_data0 ); + float result0 = svm->predict( test_point0 ); + float test_data1[2] = {0.75f, 0.75f}; + cv::Mat test_point1 = cv::Mat( 1, 2, CV_32FC1, test_data1 ); + float result1 = svm->predict( test_point1 ); + + EXPECT_EQ(0., result0); + EXPECT_EQ(1., result1); +} From 769fe82743ae5494d028316394ce19a2d0ebff61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enes=20Ate=C5=9F?= Date: Wed, 23 Sep 2015 13:19:17 +0200 Subject: [PATCH 082/156] XML file path correction in documentation exact path is images/CameraCalibration/VID5 --- .../cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml b/samples/cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml index 9976bccb3..98269ecb6 100644 --- a/samples/cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml +++ b/samples/cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml @@ -16,7 +16,7 @@ To use an input video -> give the path of the input video, like "/tmp/x.avi" To use an image list -> give the path to the XML or YAML file containing the list of the images, like "/tmp/circles_list.xml" --> - "images/CameraCalibraation/VID5/VID5.xml" + "images/CameraCalibration/VID5/VID5.xml" 0 @@ -43,4 +43,4 @@ 1 - \ No newline at end of file + From 1dd7f546afc1e305d3c53d06242ce8fcf917fe90 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Wed, 23 Sep 2015 12:03:44 +0200 Subject: [PATCH 083/156] CommandLineParser: add special value to disallow empty strings some mandatory string keys like paths must not be empty. Add the special default value `` so the CommandLineParser can enforce this and generate an according error message for us. --- modules/core/include/opencv2/core/utility.hpp | 5 ++- modules/core/src/command_line_parser.cpp | 42 ++++++++++--------- modules/core/test/test_utils.cpp | 23 ++++++++-- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/modules/core/include/opencv2/core/utility.hpp b/modules/core/include/opencv2/core/utility.hpp index 22011ddd2..4d7d7df66 100644 --- a/modules/core/include/opencv2/core/utility.hpp +++ b/modules/core/include/opencv2/core/utility.hpp @@ -609,7 +609,7 @@ For example: const String keys = "{help h usage ? | | print this message }" "{@image1 | | image1 for compare }" - "{@image2 | | image2 for compare }" + "{@image2 || image2 for compare }" "{@repeat |1 | number }" "{path |. | path to file }" "{fps | -1.0 | fps for output video }" @@ -623,6 +623,9 @@ Note that there are no default values for `help` and `timestamp` so we can check Arguments with default values are considered to be always present. Use the `get()` method in these cases to check their actual value instead. +String keys like `get("@image1")` return the empty string `""` by default - even with an empty default value. +Use the special `` default value to enforce that the returned string must not be empty. (like in `get("@image2")`) + ### Usage For the described keys: diff --git a/modules/core/src/command_line_parser.cpp b/modules/core/src/command_line_parser.cpp index 4ef4f7dee..658c3c700 100644 --- a/modules/core/src/command_line_parser.cpp +++ b/modules/core/src/command_line_parser.cpp @@ -4,6 +4,20 @@ namespace cv { +namespace { +static const char* noneValue = ""; + +static String cat_string(const String& str) +{ + int left = 0, right = (int)str.length(); + while( left <= right && str[left] == ' ' ) + left++; + while( right > left && str[right-1] == ' ' ) + right--; + return left >= right ? String("") : str.substr(left, right-left); +} +} + struct CommandLineParserParams { public: @@ -27,7 +41,6 @@ struct CommandLineParser::Impl std::vector split_range_string(const String& str, char fs, char ss) const; std::vector split_string(const String& str, char symbol = ' ', bool create_empty_item = false) const; - String cat_string(const String& str) const; void apply_params(const String& key, const String& value); void apply_params(int i, String value); @@ -98,10 +111,10 @@ void CommandLineParser::getByName(const String& name, bool space_delete, int typ { String v = impl->data[i].def_value; if (space_delete) - v = impl->cat_string(v); + v = cat_string(v); // the key was neither specified nor has it a default value - if(v.empty() && type != Param::STRING) { + if((v.empty() && type != Param::STRING) || v == noneValue) { impl->error = true; impl->error_message = impl->error_message + "Missing parameter: '" + name + "'\n"; return; @@ -133,10 +146,10 @@ void CommandLineParser::getByIndex(int index, bool space_delete, int type, void* if (impl->data[i].number == index) { String v = impl->data[i].def_value; - if (space_delete == true) v = impl->cat_string(v); + if (space_delete == true) v = cat_string(v); // the key was neither specified nor has it a default value - if(v.empty() && type != Param::STRING) { + if((v.empty() && type != Param::STRING) || v == noneValue) { impl->error = true; impl->error_message = impl->error_message + format("Missing parameter #%d\n", index); return; @@ -198,7 +211,7 @@ CommandLineParser::CommandLineParser(int argc, const char* const argv[], const S CommandLineParserParams p; p.keys = impl->split_string(l[0]); p.def_value = l[1]; - p.help_message = impl->cat_string(l[2]); + p.help_message = cat_string(l[2]); p.number = -1; if (p.keys.size() <= 0) { @@ -317,16 +330,6 @@ void CommandLineParser::Impl::sort_params() std::sort (data.begin(), data.end(), cmp_params); } -String CommandLineParser::Impl::cat_string(const String& str) const -{ - int left = 0, right = (int)str.length(); - while( left <= right && str[left] == ' ' ) - left++; - while( right > left && str[right-1] == ' ' ) - right--; - return left >= right ? String("") : str.substr(left, right-left); -} - String CommandLineParser::getPathToApplication() const { return impl->path_to_app; @@ -340,7 +343,8 @@ bool CommandLineParser::has(const String& name) const { if (name == impl->data[i].keys[j]) { - return !impl->cat_string(impl->data[i].def_value).empty(); + const String v = cat_string(impl->data[i].def_value); + return !v.empty() && v != noneValue; } } } @@ -404,7 +408,7 @@ void CommandLineParser::printMessage() const printf(", "); } } - String dv = impl->cat_string(impl->data[i].def_value); + String dv = cat_string(impl->data[i].def_value); if (dv.compare("") != 0) { printf(" (value:%s)", dv.c_str()); @@ -424,7 +428,7 @@ void CommandLineParser::printMessage() const printf("%s", k.c_str()); - String dv = impl->cat_string(impl->data[i].def_value); + String dv = cat_string(impl->data[i].def_value); if (dv.compare("") != 0) { printf(" (value:%s)", dv.c_str()); diff --git a/modules/core/test/test_utils.cpp b/modules/core/test/test_utils.cpp index f961b9344..0f1188de0 100644 --- a/modules/core/test/test_utils.cpp +++ b/modules/core/test/test_utils.cpp @@ -142,9 +142,8 @@ TEST(CommandLineParser, testPositional_noArgs) EXPECT_EQ("default1", parser.get("@arg1")); EXPECT_EQ("default1", parser.get(0)); - parser.get("@arg2"); - parser.get(1); - EXPECT_TRUE(parser.check()); + EXPECT_EQ("", parser.get("@arg2")); + EXPECT_EQ("", parser.get(1)); } TEST(CommandLineParser, testPositional_default) @@ -186,4 +185,22 @@ TEST(CommandLineParser, testPositional_withFlagsAfter) EXPECT_EQ("test2", parser.get(1)); } +TEST(CommandLineParser, testEmptyStringValue) +{ + static const char * const keys3 = + "{ @pos0 | | empty default value }" + "{ @pos1 | | forbid empty default value }"; + + const char* argv[] = {""}; + const int argc = 1; + cv::CommandLineParser parser(argc, argv, keys3); + // EXPECT_TRUE(parser.has("@pos0")); + EXPECT_EQ("", parser.get("@pos0")); + EXPECT_TRUE(parser.check()); + + EXPECT_FALSE(parser.has("@pos1")); + parser.get(1); + EXPECT_FALSE(parser.check()); +} + } // namespace From 5feca50f58881399d1c73a708de49fbb1221f2c4 Mon Sep 17 00:00:00 2001 From: Alexey Ershov Date: Fri, 18 Sep 2015 02:25:49 +0300 Subject: [PATCH 084/156] changed device detection procedure, added resizing surface to bigger size removed unused context_id2; changed blur size 7x7 to 3x3; added short comments removed unnecessary call to convertFromVASurface() replaced dumpSurface() with writeImage() added infile cmdline parameter, input image loaded by imread() --- cmake/OpenCVFindVA.cmake | 2 +- samples/va_intel/display.cpp.inc | 146 ++++----- samples/va_intel/va_intel_interop.cpp | 456 +++++++++----------------- 3 files changed, 205 insertions(+), 399 deletions(-) diff --git a/cmake/OpenCVFindVA.cmake b/cmake/OpenCVFindVA.cmake index 96df665f8..5079e5631 100644 --- a/cmake/OpenCVFindVA.cmake +++ b/cmake/OpenCVFindVA.cmake @@ -12,7 +12,7 @@ endif() if(VA_INCLUDE_DIR) set(HAVE_VA TRUE) - set(VA_LIBRARIES "-lva" "-lva-x11") + set(VA_LIBRARIES "-lva" "-lva-drm") else() set(HAVE_VA FALSE) message(WARNING "libva installation is not found.") diff --git a/samples/va_intel/display.cpp.inc b/samples/va_intel/display.cpp.inc index f8aeb00e7..56e71d26e 100644 --- a/samples/va_intel/display.cpp.inc +++ b/samples/va_intel/display.cpp.inc @@ -10,27 +10,16 @@ #include "cvconfig.h" #include -#if defined(HAVE_VA_INTEL) # include -#elif defined(HAVE_VA) -# include -# include -#endif //HAVE_VA_INTEL / HAVE_VA namespace va { -#if defined(HAVE_VA_INTEL) || defined(HAVE_VA) - bool openDisplay(); void closeDisplay(); VADisplay display = NULL; bool initialized = false; -#endif //HAVE_VA_INTEL || HAVE_VA - -#if defined(HAVE_VA_INTEL) - #define VA_INTEL_PCI_DIR "/sys/bus/pci/devices" #define VA_INTEL_DRI_DIR "/dev/dri/" #define VA_INTEL_PCI_DISPLAY_CONTROLLER_CLASS 0x03 @@ -161,46 +150,74 @@ private: char* paths[NUM_NODES]; }; +static bool openDeviceIntel(); +static bool openDeviceGeneric(); + +static bool openDeviceIntel() +{ + const unsigned IntelVendorID = 0x8086; + + int adapterIndex = findAdapter(IntelVendorID); + if (adapterIndex >= 0) + { + NodeInfo nodes(adapterIndex); + + for (int i = 0; i < nodes.count(); ++i) + { + drmfd = open(nodes.path(i), O_RDWR); + if (drmfd >= 0) + { + display = vaGetDisplayDRM(drmfd); + if (display) + return true; + close(drmfd); + drmfd = -1; + } + } + } + return false; +} + +static bool openDeviceGeneric() +{ + static const char* device_paths[] = { "/dev/dri/renderD128", "/dev/dri/card0" }; + static const int num_devices = sizeof(device_paths) / sizeof(device_paths[0]); + + for (int i = 0; i < num_devices; ++i) + { + drmfd = open(device_paths[i], O_RDWR); + if (drmfd >= 0) + { + display = vaGetDisplayDRM(drmfd); + if (display) + return true; + close(drmfd); + drmfd = -1; + } + } + return false; +} + bool openDisplay() { if (!initialized) { - const unsigned IntelVendorID = 0x8086; - drmfd = -1; display = 0; - int adapterIndex = findAdapter(IntelVendorID); - if (adapterIndex >= 0) + if (openDeviceIntel() || openDeviceGeneric()) { - NodeInfo nodes(adapterIndex); - - for (int i = 0; i < nodes.count(); ++i) + int majorVersion = 0, minorVersion = 0; + if (vaInitialize(display, &majorVersion, &minorVersion) == VA_STATUS_SUCCESS) { - drmfd = open(nodes.path(i), O_RDWR); - if (drmfd >= 0) - { - display = vaGetDisplayDRM(drmfd); - if (display) - { - int majorVersion = 0, minorVersion = 0; - if (vaInitialize(display, &majorVersion, &minorVersion) == VA_STATUS_SUCCESS) - { - initialized = true; - return true; - } - display = 0; - } - close(drmfd); - drmfd = -1; - } + initialized = true; + return true; } + close(drmfd); + display = 0; + drmfd = -1; } - - if (adapterIndex < 0) - return false; // Can't find Intel display adapter - if ((drmfd < 0) || !display) - return false; // Can't load VA display + return false; // Can't open VA display } return true; } @@ -219,53 +236,4 @@ void closeDisplay() } } -#elif defined(HAVE_VA) - -static Display* x11Display = 0; - -bool openDisplay() -{ - if (!initialized) - { - display = 0; - - x11Display = XOpenDisplay(""); - if (x11Display != 0) - { - display = vaGetDisplay(x11Display); - if (display) - { - int majorVersion = 0, minorVersion = 0; - if (vaInitialize(display, &majorVersion, &minorVersion) == VA_STATUS_SUCCESS) - { - initialized = true; - return true; - } - display = 0; - } - XCloseDisplay(x11Display); - x11Display = 0; - } - - return false; // Can't initialize X11/VA display - } - return true; -} - -void closeDisplay() -{ - if (initialized) - { - if (display) - vaTerminate(display); - if (x11Display) - XCloseDisplay(x11Display); - display = 0; - x11Display = 0; - initialized = false; - } -} - -#endif // HAVE_VA_INTEL / HAVE_VA - } // namespace va diff --git a/samples/va_intel/va_intel_interop.cpp b/samples/va_intel/va_intel_interop.cpp index 996ac375e..8fa2c54f6 100644 --- a/samples/va_intel/va_intel_interop.cpp +++ b/samples/va_intel/va_intel_interop.cpp @@ -24,6 +24,8 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include +#include #include #include @@ -41,97 +43,85 @@ #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" #include "opencv2/core/va_intel.hpp" #include "cvconfig.h" -#define CHECK_VASTATUS(va_status,func) \ -if (va_status != VA_STATUS_SUCCESS) { \ - fprintf(stderr,"%s:%s (%d) failed(status=0x%08x),exit\n", __func__, func, __LINE__, va_status); \ - exit(1); \ -} +#define CHECK_VASTATUS(_status,_func) \ + if (_status != VA_STATUS_SUCCESS) \ + { \ + char str[256]; \ + snprintf(str, sizeof(str)-1, "%s:%s (%d) failed(status=0x%08x),exit\n", __func__, _func, __LINE__, _status); \ + throw std::runtime_error(str); \ + } -/* Data dump of a 16x16 MPEG2 video clip,it has one I frame - */ -static unsigned char mpeg2_clip[]={ - 0x00,0x00,0x01,0xb3,0x01,0x00,0x10,0x13,0xff,0xff,0xe0,0x18,0x00,0x00,0x01,0xb5, - 0x14,0x8a,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0xb8,0x00,0x08,0x00,0x00,0x00,0x00, - 0x01,0x00,0x00,0x0f,0xff,0xf8,0x00,0x00,0x01,0xb5,0x8f,0xff,0xf3,0x41,0x80,0x00, - 0x00,0x01,0x01,0x13,0xe1,0x00,0x15,0x81,0x54,0xe0,0x2a,0x05,0x43,0x00,0x2d,0x60, - 0x18,0x01,0x4e,0x82,0xb9,0x58,0xb1,0x83,0x49,0xa4,0xa0,0x2e,0x05,0x80,0x4b,0x7a, - 0x00,0x01,0x38,0x20,0x80,0xe8,0x05,0xff,0x60,0x18,0xe0,0x1d,0x80,0x98,0x01,0xf8, - 0x06,0x00,0x54,0x02,0xc0,0x18,0x14,0x03,0xb2,0x92,0x80,0xc0,0x18,0x94,0x42,0x2c, - 0xb2,0x11,0x64,0xa0,0x12,0x5e,0x78,0x03,0x3c,0x01,0x80,0x0e,0x80,0x18,0x80,0x6b, - 0xca,0x4e,0x01,0x0f,0xe4,0x32,0xc9,0xbf,0x01,0x42,0x69,0x43,0x50,0x4b,0x01,0xc9, - 0x45,0x80,0x50,0x01,0x38,0x65,0xe8,0x01,0x03,0xf3,0xc0,0x76,0x00,0xe0,0x03,0x20, - 0x28,0x18,0x01,0xa9,0x34,0x04,0xc5,0xe0,0x0b,0x0b,0x04,0x20,0x06,0xc0,0x89,0xff, - 0x60,0x12,0x12,0x8a,0x2c,0x34,0x11,0xff,0xf6,0xe2,0x40,0xc0,0x30,0x1b,0x7a,0x01, - 0xa9,0x0d,0x00,0xac,0x64 +class CmdlineParser +{ +public: + enum { fnInput=0, fnOutput1, fnOutput2, _fnNumFiles }; // file name indices + CmdlineParser(int argc, char** argv): + m_argc(argc), m_argv(argv) + {} + void usage() + { + fprintf(stderr, +#if defined(HAVE_VA_INTEL) + "Usage: va_intel_interop [-f] infile outfile1 outfile2\n\n" + "Interop ON/OFF version\n\n" + "where: -f option indicates interop is off (fallback mode); interop is on by default\n" +#elif defined(HAVE_VA) + "Usage: va_intel_interop infile outfile1 outfile2\n\n" + "Interop OFF only version\n\n" + "where:\n" +#endif //HAVE_VA_INTEL / HAVE_VA + " infile is to be existing, contains input image data (bmp, jpg, png, tiff, etc)\n" + " outfile1 is to be created, contains original surface data (NV12)\n" + " outfile2 is to be created, contains processed surface data (NV12)\n"); + } + // true => go, false => usage/exit; extra args/unknown options are ignored for simplicity + bool run() + { + int n = 0; + for (int i = 0; i < _fnNumFiles; ++i) + m_files[i] = 0; +#if defined(HAVE_VA_INTEL) + m_interop = true; +#elif defined(HAVE_VA) + m_interop = false; +#endif //HAVE_VA_INTEL / HAVE_VA + for (int i = 1; i < m_argc; ++i) + { + const char *arg = m_argv[i]; + if (arg[0] == '-') // option + { +#if defined(HAVE_VA_INTEL) + if (!strcmp(arg, "-f")) + m_interop = false; +#endif //HAVE_VA_INTEL + } + else // parameter + { + if (n < _fnNumFiles) + m_files[n++] = arg; + } + } + return bool(n >= _fnNumFiles); + } + bool isInterop() const + { + return m_interop; + } + const char* getFile(int n) const + { + return ((n >= 0) && (n < _fnNumFiles)) ? m_files[n] : 0; + } +private: + int m_argc; + char** m_argv; + const char* m_files[_fnNumFiles]; + bool m_interop; }; -/* hardcoded here without a bitstream parser helper - * please see picture mpeg2-I.jpg for bitstream details - */ -static VAPictureParameterBufferMPEG2 pic_param={ - horizontal_size:16, - vertical_size:16, - forward_reference_picture:0xffffffff, - backward_reference_picture:0xffffffff, - picture_coding_type:1, - f_code:0xffff, - { - { - intra_dc_precision:0, - picture_structure:3, - top_field_first:0, - frame_pred_frame_dct:1, - concealment_motion_vectors:0, - q_scale_type:0, - intra_vlc_format:0, - alternate_scan:0, - repeat_first_field:0, - progressive_frame:1 , - is_first_field:1 - }, - } -}; - -/* see MPEG2 spec65 for the defines of matrix */ -static VAIQMatrixBufferMPEG2 iq_matrix = { - load_intra_quantiser_matrix:1, - load_non_intra_quantiser_matrix:1, - load_chroma_intra_quantiser_matrix:0, - load_chroma_non_intra_quantiser_matrix:0, - intra_quantiser_matrix:{ - 8, 16, 16, 19, 16, 19, 22, 22, - 22, 22, 22, 22, 26, 24, 26, 27, - 27, 27, 26, 26, 26, 26, 27, 27, - 27, 29, 29, 29, 34, 34, 34, 29, - 29, 29, 27, 27, 29, 29, 32, 32, - 34, 34, 37, 38, 37, 35, 35, 34, - 35, 38, 38, 40, 40, 40, 48, 48, - 46, 46, 56, 56, 58, 69, 69, 83 - }, - non_intra_quantiser_matrix:{16}, - chroma_intra_quantiser_matrix:{0}, - chroma_non_intra_quantiser_matrix:{0} -}; - -#if 1 -static VASliceParameterBufferMPEG2 slice_param={ - slice_data_size:150, - slice_data_offset:0, - slice_data_flag:0, - macroblock_offset:38, /* 4byte + 6bits=38bits */ - slice_horizontal_position:0, - slice_vertical_position:0, - quantiser_scale_code:2, - intra_slice_flag:0 -}; -#endif - -#define CLIP_WIDTH 16 -#define CLIP_HEIGHT 16 - class Timer { public: @@ -180,261 +170,109 @@ public: int m_unit_mul[3]; }; -static void dumpSurface(VADisplay display, VASurfaceID surface_id, const char* fileName, bool doInterop) -{ - VAStatus va_status; - - va_status = vaSyncSurface(display, surface_id); - CHECK_VASTATUS(va_status, "vaSyncSurface"); - - VAImage image; - va_status = vaDeriveImage(display, surface_id, &image); - CHECK_VASTATUS(va_status, "vaDeriveImage"); - - unsigned char* buffer = 0; - va_status = vaMapBuffer(display, image.buf, (void **)&buffer); - CHECK_VASTATUS(va_status, "vaMapBuffer"); - - CV_Assert(image.format.fourcc == VA_FOURCC_NV12); -/* - printf("image.format.fourcc = 0x%08x\n", image.format.fourcc); - printf("image.[width x height] = %d x %d\n", image.width, image.height); - printf("image.data_size = %d\n", image.data_size); - printf("image.num_planes = %d\n", image.num_planes); - printf("image.pitches[0..2] = 0x%08x 0x%08x 0x%08x\n", image.pitches[0], image.pitches[1], image.pitches[2]); - printf("image.offsets[0..2] = 0x%08x 0x%08x 0x%08x\n", image.offsets[0], image.offsets[1], image.offsets[2]); -*/ - std::string fn = std::string(fileName) + std::string(doInterop ? ".on" : ".off"); - FILE* out = fopen(fn.c_str(), "wb"); - if (!out) - { - perror(fileName); - exit(1); - } - fwrite(buffer, 1, image.data_size, out); - fclose(out); - - vaUnmapBuffer(display, image.buf); - CHECK_VASTATUS(va_status, "vaUnmapBuffer"); - - vaDestroyImage(display, image.image_id); - CHECK_VASTATUS(va_status, "vaDestroyImage"); -} - -static float run(const char* fn1, const char* fn2, bool doInterop) +static void checkIfAvailableYUV420() { VAEntrypoint entrypoints[5]; int num_entrypoints,vld_entrypoint; VAConfigAttrib attrib; - VAConfigID config_id; - VASurfaceID surface_id; - VAContextID context_id; - VABufferID pic_param_buf,iqmatrix_buf,slice_param_buf,slice_data_buf; - VAStatus va_status; - Timer t; + VAStatus status; - cv::va_intel::ocl::initializeContextFromVA(va::display, doInterop); + status = vaQueryConfigEntrypoints(va::display, VAProfileMPEG2Main, entrypoints, &num_entrypoints); + CHECK_VASTATUS(status, "vaQueryConfigEntrypoints"); - va_status = vaQueryConfigEntrypoints(va::display, VAProfileMPEG2Main, entrypoints, - &num_entrypoints); - CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints"); - - for (vld_entrypoint = 0; vld_entrypoint < num_entrypoints; vld_entrypoint++) { + for (vld_entrypoint = 0; vld_entrypoint < num_entrypoints; ++vld_entrypoint) + { if (entrypoints[vld_entrypoint] == VAEntrypointVLD) break; } - if (vld_entrypoint == num_entrypoints) { - /* not find VLD entry point */ - assert(0); - } + if (vld_entrypoint == num_entrypoints) + throw std::runtime_error("Failed to find VLD entry point"); - /* Assuming finding VLD, find out the format for the render target */ attrib.type = VAConfigAttribRTFormat; - vaGetConfigAttributes(va::display, VAProfileMPEG2Main, VAEntrypointVLD, - &attrib, 1); - if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) { - /* not find desired YUV420 RT format */ - assert(0); - } + vaGetConfigAttributes(va::display, VAProfileMPEG2Main, VAEntrypointVLD, &attrib, 1); + if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) + throw std::runtime_error("Desired YUV420 RT format not found"); +} - va_status = vaCreateConfig(va::display, VAProfileMPEG2Main, VAEntrypointVLD, - &attrib, 1,&config_id); - CHECK_VASTATUS(va_status, "vaCreateConfig"); +static cv::UMat readImage(const char* fileName) +{ + cv::Mat m = cv::imread(fileName); + if (m.empty()) + throw std::runtime_error("Failed to load image: " + std::string(fileName)); + return m.getUMat(cv::ACCESS_RW); +} - va_status = vaCreateSurfaces( - va::display, - VA_RT_FORMAT_YUV420, CLIP_WIDTH, CLIP_HEIGHT, - &surface_id, 1, - NULL, 0 - ); - CHECK_VASTATUS(va_status, "vaCreateSurfaces"); +static void writeImage(const cv::UMat& u, const char* fileName, bool doInterop) +{ + std::string fn = std::string(fileName) + std::string(doInterop ? ".on" : ".off") + std::string(".jpg"); + cv::imwrite(fn, u); +} - /* Create a context for this decode pipe */ - va_status = vaCreateContext(va::display, config_id, - CLIP_WIDTH, - ((CLIP_HEIGHT+15)/16)*16, - VA_PROGRESSIVE, - &surface_id, - 1, - &context_id); - CHECK_VASTATUS(va_status, "vaCreateContext"); +static float run(const char* infile, const char* outfile1, const char* outfile2, bool doInterop) +{ + VASurfaceID surface; + VAStatus status; + Timer t; - va_status = vaCreateBuffer(va::display, context_id, - VAPictureParameterBufferType, - sizeof(VAPictureParameterBufferMPEG2), - 1, &pic_param, - &pic_param_buf); - CHECK_VASTATUS(va_status, "vaCreateBuffer"); + // initialize CL context for CL/VA interop + cv::va_intel::ocl::initializeContextFromVA(va::display, doInterop); - va_status = vaCreateBuffer(va::display, context_id, - VAIQMatrixBufferType, - sizeof(VAIQMatrixBufferMPEG2), - 1, &iq_matrix, - &iqmatrix_buf ); - CHECK_VASTATUS(va_status, "vaCreateBuffer"); + // load input image + cv::UMat u1 = readImage(infile); + cv::Size size2 = u1.size(); + status = vaCreateSurfaces(va::display, VA_RT_FORMAT_YUV420, size2.width, size2.height, &surface, 1, NULL, 0); + CHECK_VASTATUS(status, "vaCreateSurfaces"); - va_status = vaCreateBuffer(va::display, context_id, - VASliceParameterBufferType, - sizeof(VASliceParameterBufferMPEG2), - 1, - &slice_param, &slice_param_buf); - CHECK_VASTATUS(va_status, "vaCreateBuffer"); + // transfer image into VA surface, make sure all CL initialization is done (kernels etc) + cv::va_intel::convertToVASurface(va::display, u1, surface, size2); + cv::va_intel::convertFromVASurface(va::display, surface, size2, u1); + cv::UMat u2; + cv::blur(u1, u2, cv::Size(7, 7), cv::Point(-3, -3)); - va_status = vaCreateBuffer(va::display, context_id, - VASliceDataBufferType, - 0xc4-0x2f+1, - 1, - mpeg2_clip+0x2f, - &slice_data_buf); - CHECK_VASTATUS(va_status, "vaCreateBuffer"); - - va_status = vaBeginPicture(va::display, context_id, surface_id); - CHECK_VASTATUS(va_status, "vaBeginPicture"); - - va_status = vaRenderPicture(va::display,context_id, &pic_param_buf, 1); - CHECK_VASTATUS(va_status, "vaRenderPicture"); - - va_status = vaRenderPicture(va::display,context_id, &iqmatrix_buf, 1); - CHECK_VASTATUS(va_status, "vaRenderPicture"); - - va_status = vaRenderPicture(va::display,context_id, &slice_param_buf, 1); - CHECK_VASTATUS(va_status, "vaRenderPicture"); - - va_status = vaRenderPicture(va::display,context_id, &slice_data_buf, 1); - CHECK_VASTATUS(va_status, "vaRenderPicture"); - - va_status = vaEndPicture(va::display,context_id); - CHECK_VASTATUS(va_status, "vaEndPicture"); - - va_status = vaSyncSurface(va::display, surface_id); - CHECK_VASTATUS(va_status, "vaSyncSurface"); - - dumpSurface(va::display, surface_id, fn1, doInterop); - - cv::Size size(CLIP_WIDTH,CLIP_HEIGHT); - cv::UMat u; - - cv::va_intel::convertFromVASurface(va::display, surface_id, size, u); - cv::blur(u, u, cv::Size(7, 7), cv::Point(-3, -3)); - cv::va_intel::convertToVASurface(va::display, u, surface_id, size); + // measure performance on some image processing + writeImage(u1, outfile1, doInterop); t.start(); - cv::va_intel::convertFromVASurface(va::display, surface_id, size, u); - cv::blur(u, u, cv::Size(7, 7), cv::Point(-3, -3)); - cv::va_intel::convertToVASurface(va::display, u, surface_id, size); + cv::va_intel::convertFromVASurface(va::display, surface, size2, u1); + cv::blur(u1, u2, cv::Size(7, 7), cv::Point(-3, -3)); + cv::va_intel::convertToVASurface(va::display, u2, surface, size2); t.stop(); + writeImage(u2, outfile2, doInterop); - dumpSurface(va::display, surface_id, fn2, doInterop); - - vaDestroySurfaces(va::display,&surface_id,1); - vaDestroyConfig(va::display,config_id); - vaDestroyContext(va::display,context_id); + vaDestroySurfaces(va::display, &surface,1); return t.time(Timer::MSEC); } -class CmdlineParser -{ -public: - CmdlineParser(int argc, char** argv): - m_argc(argc), m_argv(argv) - {} - // true => go, false => usage/exit; extra args/unknown options are ignored for simplicity - bool run() - { - int n = 0; - m_files[0] = m_files[1] = 0; -#if defined(HAVE_VA_INTEL) - m_interop = true; -#elif defined(HAVE_VA) - m_interop = false; -#endif //HAVE_VA_INTEL / HAVE_VA - for (int i = 1; i < m_argc; ++i) - { - const char *arg = m_argv[i]; - if (arg[0] == '-') // option - { -#if defined(HAVE_VA_INTEL) - if (!strcmp(arg, "-f")) - m_interop = false; -#endif //HAVE_VA_INTEL - } - else // parameter - { - if (n < 2) - m_files[n++] = arg; - } - } - return bool(n >= 2); - } - bool isInterop() const - { - return m_interop; - } - const char* getFile(int n) const - { - return ((n >= 0) && (n < 2)) ? m_files[n] : 0; - } -private: - int m_argc; - char** m_argv; - const char* m_files[2]; - bool m_interop; -}; - int main(int argc, char** argv) { - CmdlineParser cmd(argc, argv); - if (!cmd.run()) + try { - fprintf(stderr, -#if defined(HAVE_VA_INTEL) - "Usage: va_intel_interop [-f] file1 file2\n\n" - "Interop ON/OFF version\n\n" - "where: -f option indicates interop is off (fallback mode); interop is on by default\n" -#elif defined(HAVE_VA) - "Usage: va_intel_interop file1 file2\n\n" - "Interop OFF only version\n\n" - "where:\n" -#endif //HAVE_VA_INTEL / HAVE_VA - " file1 is to be created, contains original surface data (NV12)\n" - " file2 is to be created, contains processed surface data (NV12)\n"); - exit(0); - } + CmdlineParser cmd(argc, argv); + if (!cmd.run()) + { + cmd.usage(); + return 0; + } - if (!va::openDisplay()) + if (!va::openDisplay()) + throw std::runtime_error("Failed to open VA display for CL-VA interoperability"); + std::cout << "VA display opened successfully" << std::endl; + + checkIfAvailableYUV420(); + + const char* infile = cmd.getFile(CmdlineParser::fnInput); + const char* outfile1 = cmd.getFile(CmdlineParser::fnOutput1); + const char* outfile2 = cmd.getFile(CmdlineParser::fnOutput2); + bool doInterop = cmd.isInterop(); + + float time = run(infile, outfile1, outfile2, doInterop); + + std::cout << "Interop " << (doInterop ? "ON " : "OFF") << ": processing time, msec: " << time << std::endl; + } + catch (std::exception& ex) { - fprintf(stderr, "Failed to open VA display for CL-VA interoperability\n"); - exit(1); + std::cerr << "ERROR: " << ex.what() << std::endl; } - fprintf(stderr, "VA display opened successfully\n"); - - const char* file0 = cmd.getFile(0); - const char* file1 = cmd.getFile(1); - bool doInterop = cmd.isInterop(); - - float time = run(file0, file1, doInterop); - - fprintf(stderr, "Interop %s: processing time, msec: %7.3f\n", (doInterop ? "ON " : "OFF"), time); va::closeDisplay(); return 0; From db78de9c3b16a5da001803562e03de47f6a62922 Mon Sep 17 00:00:00 2001 From: robertxwu Date: Thu, 27 Aug 2015 18:14:08 -0700 Subject: [PATCH 085/156] findChessboardCorners causes crash due to out-of-bounds memory corruption. Refer to the following issue for detail: https://github.com/Itseez/opencv/issues/5145 --- modules/calib3d/src/calibinit.cpp | 35 ++++++++++++++++++------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/modules/calib3d/src/calibinit.cpp b/modules/calib3d/src/calibinit.cpp index c9dde993f..d2641fe87 100644 --- a/modules/calib3d/src/calibinit.cpp +++ b/modules/calib3d/src/calibinit.cpp @@ -154,7 +154,7 @@ struct CvCBQuad //static CvMat* debug_img = 0; static int icvGenerateQuads( CvCBQuad **quads, CvCBCorner **corners, - CvMemStorage *storage, CvMat *image, int flags ); + CvMemStorage *storage, CvMat *image, int flags, int *max_quad_buf_size); /*static int icvGenerateQuadsEx( CvCBQuad **out_quads, CvCBCorner **out_corners, @@ -174,7 +174,7 @@ static int icvCleanFoundConnectedQuads( int quad_count, static int icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, int *all_count, CvCBQuad **all_quads, CvCBCorner **corners, - CvSize pattern_size, CvMemStorage* storage ); + CvSize pattern_size, int max_quad_buf_size, CvMemStorage* storage ); static void icvOrderQuad(CvCBQuad *quad, CvCBCorner *corner, int common); @@ -185,7 +185,7 @@ static int icvTrimRow(CvCBQuad **quads, int count, int row, int dir); #endif static int icvAddOuterQuad(CvCBQuad *quad, CvCBQuad **quads, int quad_count, - CvCBQuad **all_quads, int all_count, CvCBCorner **corners); + CvCBQuad **all_quads, int all_count, CvCBCorner **corners, int max_quad_buf_size); static void icvRemoveQuadFromGroup(CvCBQuad **quads, int count, CvCBQuad *q0); @@ -314,6 +314,7 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, // making it difficult to detect smaller squares. for( k = 0; k < 6; k++ ) { + int max_quad_buf_size = 0; for( dilations = min_dilations; dilations <= max_dilations; dilations++ ) { if (found) @@ -369,7 +370,7 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, cvRectangle( thresh_img, cvPoint(0,0), cvPoint(thresh_img->cols-1, thresh_img->rows-1), CV_RGB(255,255,255), 3, 8); - quad_count = icvGenerateQuads( &quads, &corners, storage, thresh_img, flags ); + quad_count = icvGenerateQuads( &quads, &corners, storage, thresh_img, flags, &max_quad_buf_size); PRINTF("Quad count: %d/%d\n", quad_count, expected_corners_num); } @@ -409,8 +410,8 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, // allocate extra for adding in icvOrderFoundQuads cvFree(&quad_group); cvFree(&corner_group); - quad_group = (CvCBQuad**)cvAlloc( sizeof(quad_group[0]) * (quad_count+quad_count / 2)); - corner_group = (CvCBCorner**)cvAlloc( sizeof(corner_group[0]) * (quad_count+quad_count / 2)*4 ); + quad_group = (CvCBQuad**)cvAlloc( sizeof(quad_group[0]) * max_quad_buf_size); + corner_group = (CvCBCorner**)cvAlloc( sizeof(corner_group[0]) * max_quad_buf_size * 4 ); for( group_idx = 0; ; group_idx++ ) { @@ -425,7 +426,7 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, // maybe delete or add some PRINTF("Starting ordering of inner quads\n"); count = icvOrderFoundConnectedQuads(count, quad_group, &quad_count, &quads, &corners, - pattern_size, storage ); + pattern_size, max_quad_buf_size, storage ); PRINTF("Orig count: %d After ordering: %d\n", icount, count); @@ -624,7 +625,7 @@ icvCheckBoardMonotony( CvPoint2D32f* corners, CvSize pattern_size ) static int icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, int *all_count, CvCBQuad **all_quads, CvCBCorner **corners, - CvSize pattern_size, CvMemStorage* storage ) + CvSize pattern_size, int max_quad_buf_size, CvMemStorage* storage ) { cv::Ptr temp_storage(cvCreateChildMemStorage( storage )); CvSeq* stack = cvCreateSeq( 0, sizeof(*stack), sizeof(void*), temp_storage ); @@ -804,15 +805,18 @@ icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, if (found > 0) { PRINTF("Found %d inner quads not connected to outer quads, repairing\n", found); - for (int i=0; icount < 4 && quads[i]->ordered) { - int added = icvAddOuterQuad(quads[i],quads,quad_count,all_quads,*all_count,corners); + int added = icvAddOuterQuad(quads[i],quads,quad_count,all_quads,*all_count,corners, max_quad_buf_size); *all_count += added; quad_count += added; } } + + if (*all_count >= max_quad_buf_size) + return 0; } @@ -855,11 +859,11 @@ icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, static int icvAddOuterQuad( CvCBQuad *quad, CvCBQuad **quads, int quad_count, - CvCBQuad **all_quads, int all_count, CvCBCorner **corners ) + CvCBQuad **all_quads, int all_count, CvCBCorner **corners, int max_quad_buf_size ) { int added = 0; - for (int i=0; i<4; i++) // find no-neighbor corners + for (int i=0; i<4 && all_count < max_quad_buf_size; i++) // find no-neighbor corners { if (!quad->neighbors[i]) // ok, create and add neighbor { @@ -1649,7 +1653,7 @@ static void icvFindQuadNeighbors( CvCBQuad *quads, int quad_count ) static int icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners, - CvMemStorage *storage, CvMat *image, int flags ) + CvMemStorage *storage, CvMat *image, int flags, int *max_quad_buf_size ) { int quad_count = 0; cv::Ptr temp_storage; @@ -1754,8 +1758,9 @@ icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners, cvEndFindContours( &scanner ); // allocate quad & corner buffers - *out_quads = (CvCBQuad*)cvAlloc((root->total+root->total / 2) * sizeof((*out_quads)[0])); - *out_corners = (CvCBCorner*)cvAlloc((root->total+root->total / 2) * 4 * sizeof((*out_corners)[0])); + *max_quad_buf_size = MAX(1, (root->total+root->total / 2)) * 2; + *out_quads = (CvCBQuad*)cvAlloc(*max_quad_buf_size * sizeof((*out_quads)[0])); + *out_corners = (CvCBCorner*)cvAlloc(*max_quad_buf_size * 4 * sizeof((*out_corners)[0])); // Create array of quads structures for( idx = 0; idx < root->total; idx++ ) From f52cac9d47ef8561f57726dff7f8770e998e2ec5 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 24 Sep 2015 15:56:47 +0300 Subject: [PATCH 086/156] fix #5264 --- cmake/OpenCVModule.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index 5e7a03d5b..85beca606 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -473,7 +473,6 @@ function(__ocv_resolve_dependencies) # reorder dependencies foreach(m ${OPENCV_MODULES_BUILD}) __ocv_sort_modules_by_deps(OPENCV_MODULE_${m}_DEPS) - ocv_list_sort(OPENCV_MODULE_${m}_DEPS_EXT) set(LINK_DEPS ${OPENCV_MODULE_${m}_DEPS}) From 46ada3886fa490e279274182aa8f5fc65740fc21 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Wed, 23 Sep 2015 16:20:07 +0200 Subject: [PATCH 087/156] fix wrong parsing of values containing '=' fixes #5074 --- modules/core/src/command_line_parser.cpp | 28 ++++++++++-------------- modules/core/test/test_utils.cpp | 15 +++++++++++++ 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/modules/core/src/command_line_parser.cpp b/modules/core/src/command_line_parser.cpp index 658c3c700..542b231ff 100644 --- a/modules/core/src/command_line_parser.cpp +++ b/modules/core/src/command_line_parser.cpp @@ -234,25 +234,21 @@ CommandLineParser::CommandLineParser(int argc, const char* const argv[], const S jj = 0; for (int i = 1; i < argc; i++) { - String s = String(argv[i]); + String s(argv[i]); + bool hasSingleDash = s.length() > 1 && s[0] == '-'; - if (s.find('=') != String::npos && s.find('=') < s.length()) + if (hasSingleDash) { - std::vector k_v = impl->split_string(s, '=', true); - for (int h = 0; h < 2; h++) - { - if (k_v[0][0] == '-') - k_v[0] = k_v[0].substr(1, k_v[0].length() -1); + bool hasDoubleDash = s.length() > 2 && s[1] == '-'; + String key = s.substr(hasDoubleDash ? 2 : 1); + String value = "true"; + size_t equalsPos = key.find('='); + + if(equalsPos != String::npos) { + value = key.substr(equalsPos + 1); + key = key.substr(0, equalsPos); } - impl->apply_params(k_v[0], k_v[1]); - } - else if (s.length() > 2 && s[0] == '-' && s[1] == '-') - { - impl->apply_params(s.substr(2), "true"); - } - else if (s.length() > 1 && s[0] == '-') - { - impl->apply_params(s.substr(1), "true"); + impl->apply_params(key, value); } else { diff --git a/modules/core/test/test_utils.cpp b/modules/core/test/test_utils.cpp index 0f1188de0..18b0a5a7e 100644 --- a/modules/core/test/test_utils.cpp +++ b/modules/core/test/test_utils.cpp @@ -203,4 +203,19 @@ TEST(CommandLineParser, testEmptyStringValue) EXPECT_FALSE(parser.check()); } +TEST(CommandLineParser, positional_regression_5074_equal_sign) +{ + static const char * const keys3 = + "{ @eq0 | | }" + "{ eq1 | | }"; + + const char* argv[] = {"", "1=0", "--eq1=1=0"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys3); + EXPECT_EQ("1=0", parser.get("@eq0")); + EXPECT_EQ("1=0", parser.get(0)); + EXPECT_EQ("1=0", parser.get("eq1")); + EXPECT_TRUE(parser.check()); +} + } // namespace From 750162acb3d0352ee09f911f1e31080971f83ba2 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 25 Sep 2015 16:50:50 +0300 Subject: [PATCH 088/156] move IPPICV binaries to GitHub opencv_3rdparty repository --- 3rdparty/ippicv/downloader.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/3rdparty/ippicv/downloader.cmake b/3rdparty/ippicv/downloader.cmake index debb6070d..0a3a4119c 100644 --- a/3rdparty/ippicv/downloader.cmake +++ b/3rdparty/ippicv/downloader.cmake @@ -6,6 +6,8 @@ # function(_icv_downloader) + # Commit SHA in the opencv_3rdparty repo + set(IPPICV_BINARIES_COMMIT "3d41df448b589aa076d9d27ace344d3ef709e4b9") # Define actual ICV versions if(APPLE) set(OPENCV_ICV_PACKAGE_NAME "ippicv_macosx_20141027.tgz") @@ -62,7 +64,7 @@ function(_icv_downloader) if(DEFINED ENV{OPENCV_ICV_URL}) set(OPENCV_ICV_URL $ENV{OPENCV_ICV_URL}) else() - set(OPENCV_ICV_URL "http://sourceforge.net/projects/opencvlibrary/files/3rdparty/ippicv") + set(OPENCV_ICV_URL "https://raw.githubusercontent.com/Itseez/opencv_3rdparty/${IPPICV_BINARIES_COMMIT}/ippicv") endif() endif() From 2177c7c5a8aaf71e3120ba24286b517a58bf946c Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Fri, 25 Sep 2015 17:13:11 +0300 Subject: [PATCH 089/156] Some IPP functions were encapsulated; Minor changes to IPP implementations; --- modules/calib3d/src/stereosgbm.cpp | 71 +++++---- modules/core/src/dxt.cpp | 16 +- modules/core/src/matrix.cpp | 124 +++++++-------- modules/core/src/stat.cpp | 181 +++++++++++----------- modules/imgproc/src/canny.cpp | 25 +-- modules/imgproc/src/corner.cpp | 6 +- modules/imgproc/src/deriv.cpp | 235 +++++++---------------------- modules/imgproc/src/histogram.cpp | 2 - modules/imgproc/src/pyramids.cpp | 9 +- modules/imgproc/src/smooth.cpp | 11 +- 10 files changed, 269 insertions(+), 411 deletions(-) diff --git a/modules/calib3d/src/stereosgbm.cpp b/modules/calib3d/src/stereosgbm.cpp index ef71a3f7f..7ea6ad54e 100644 --- a/modules/calib3d/src/stereosgbm.cpp +++ b/modules/calib3d/src/stereosgbm.cpp @@ -1688,6 +1688,45 @@ void filterSpecklesImpl(cv::Mat& img, int newVal, int maxSpeckleSize, int maxDif } } +#ifdef HAVE_IPP +static bool ipp_filterSpeckles(Mat &img, int maxSpeckleSize, int newVal, int maxDiff) +{ +#if IPP_VERSION_X100 >= 801 + int type = img.type(); + Ipp32s bufsize = 0; + IppiSize roisize = { img.cols, img.rows }; + IppDataType datatype = type == CV_8UC1 ? ipp8u : ipp16s; + Ipp8u *pBuffer = NULL; + IppStatus status = ippStsNoErr; + + if(ippiMarkSpecklesGetBufferSize(roisize, datatype, CV_MAT_CN(type), &bufsize) < 0) + return false; + + pBuffer = (Ipp8u*)ippMalloc(bufsize); + if(!pBuffer && bufsize) + return false; + + if (type == CV_8UC1) + { + status = ippiMarkSpeckles_8u_C1IR(img.ptr(), (int)img.step, roisize, + (Ipp8u)newVal, maxSpeckleSize, (Ipp8u)maxDiff, ippiNormL1, pBuffer); + } + else + { + status = ippiMarkSpeckles_16s_C1IR(img.ptr(), (int)img.step, roisize, + (Ipp16s)newVal, maxSpeckleSize, (Ipp16s)maxDiff, ippiNormL1, pBuffer); + } + if(pBuffer) ippFree(pBuffer); + + if (status >= 0) + return true; +#else + CV_UNUSED(img); CV_UNUSED(maxSpeckleSize); CV_UNUSED(newVal); CV_UNUSED(maxDiff); +#endif + return false; +} +#endif + } void cv::filterSpeckles( InputOutputArray _img, double _newval, int maxSpeckleSize, @@ -1700,37 +1739,7 @@ void cv::filterSpeckles( InputOutputArray _img, double _newval, int maxSpeckleSi int newVal = cvRound(_newval), maxDiff = cvRound(_maxDiff); -#if IPP_VERSION_X100 >= 801 - CV_IPP_CHECK() - { - Ipp32s bufsize = 0; - IppiSize roisize = { img.cols, img.rows }; - IppDataType datatype = type == CV_8UC1 ? ipp8u : ipp16s; - - if (!__buf.needed() && (type == CV_8UC1 || type == CV_16SC1)) - { - IppStatus status = ippiMarkSpecklesGetBufferSize(roisize, datatype, CV_MAT_CN(type), &bufsize); - Ipp8u * buffer = ippsMalloc_8u(bufsize); - - if ((int)status >= 0) - { - if (type == CV_8UC1) - status = ippiMarkSpeckles_8u_C1IR(img.ptr(), (int)img.step, roisize, - (Ipp8u)newVal, maxSpeckleSize, (Ipp8u)maxDiff, ippiNormL1, buffer); - else - status = ippiMarkSpeckles_16s_C1IR(img.ptr(), (int)img.step, roisize, - (Ipp16s)newVal, maxSpeckleSize, (Ipp16s)maxDiff, ippiNormL1, buffer); - } - - if (status >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - } - } -#endif + CV_IPP_RUN(IPP_VERSION_X100 >= 801 && !__buf.needed() && (type == CV_8UC1 || type == CV_16SC1), ipp_filterSpeckles(img, maxSpeckleSize, newVal, maxDiff)); if (type == CV_8UC1) filterSpecklesImpl(img, newVal, maxSpeckleSize, maxDiff, _buf); diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index ef01c2139..315ab5b36 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -3473,21 +3473,7 @@ void cv::dct( InputArray _src0, OutputArray _dst, int flags ) _dst.create( src.rows, src.cols, type ); Mat dst = _dst.getMat(); -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - CV_IPP_CHECK() - { - bool row = (flags & DCT_ROWS) != 0; - if (src.type() == CV_32F) - { - if(ippi_DCT_32f(src,dst,inv, row)) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - } - } -#endif + CV_IPP_RUN(IPP_VERSION_X100 >= 700 && src.type() == CV_32F, ippi_DCT_32f(src, dst, inv, ((flags & DCT_ROWS) != 0))) DCTFunc dct_func = dct_tbl[(int)inv + (depth == CV_64F)*2]; diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 9d9dda329..cb3675e2c 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -3367,22 +3367,20 @@ typedef void (*ReduceFunc)( const Mat& src, Mat& dst ); #define reduceMinR32f reduceR_ > #define reduceMinR64f reduceR_ > -#if IPP_VERSION_X100 > 0 - -static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& dstmat) +#ifdef HAVE_IPP +static inline bool ipp_reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& dstmat) { - cv::Size size = srcmat.size(); - IppiSize roisize = { size.width, 1 }; int sstep = (int)srcmat.step, stype = srcmat.type(), - sdepth = CV_MAT_DEPTH(stype), ddepth = dstmat.depth(); + ddepth = dstmat.depth(); + + IppiSize roisize = { srcmat.size().width, 1 }; typedef IppStatus (CV_STDCALL * ippiSum)(const void * pSrc, int srcStep, IppiSize roiSize, Ipp64f* pSum); typedef IppStatus (CV_STDCALL * ippiSumHint)(const void * pSrc, int srcStep, IppiSize roiSize, Ipp64f* pSum, IppHintAlgorithm hint); ippiSum ippFunc = 0; ippiSumHint ippFuncHint = 0; - cv::ReduceFunc func = 0; - if (ddepth == CV_64F) + if(ddepth == CV_64F) { ippFunc = stype == CV_8UC1 ? (ippiSum)ippiSum_8u_C1R : @@ -3398,41 +3396,46 @@ static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& ds stype == CV_32FC1 ? (ippiSumHint)ippiSum_32f_C1R : stype == CV_32FC3 ? (ippiSumHint)ippiSum_32f_C3R : stype == CV_32FC4 ? (ippiSumHint)ippiSum_32f_C4R : 0; + } + + if(ippFunc) + { + for(int y = 0; y < srcmat.size().height; y++) + { + if(ippFunc(srcmat.ptr(y), sstep, roisize, dstmat.ptr(y)) < 0) + return false; + } + return true; + } + else if(ippFuncHint) + { + for(int y = 0; y < srcmat.size().height; y++) + { + if(ippFuncHint(srcmat.ptr(y), sstep, roisize, dstmat.ptr(y), ippAlgHintAccurate) < 0) + return false; + } + return true; + } + + return false; +} + +static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& dstmat) +{ + CV_IPP_RUN(true, ipp_reduceSumC_8u16u16s32f_64f(srcmat, dstmat)); + + cv::ReduceFunc func = 0; + + if(dstmat.depth() == CV_64F) + { + int sdepth = CV_MAT_DEPTH(srcmat.type()); func = sdepth == CV_8U ? (cv::ReduceFunc)cv::reduceC_ > : sdepth == CV_16U ? (cv::ReduceFunc)cv::reduceC_ > : sdepth == CV_16S ? (cv::ReduceFunc)cv::reduceC_ > : sdepth == CV_32F ? (cv::ReduceFunc)cv::reduceC_ > : 0; } - CV_Assert(!(ippFunc && ippFuncHint) && func); - - CV_IPP_CHECK() - { - if (ippFunc) - { - for (int y = 0; y < size.height; ++y) - if (ippFunc(srcmat.ptr(y), sstep, roisize, dstmat.ptr(y)) < 0) - { - setIppErrorStatus(); - cv::Mat dstroi = dstmat.rowRange(y, y + 1); - func(srcmat.rowRange(y, y + 1), dstroi); - } - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - else if (ippFuncHint) - { - for (int y = 0; y < size.height; ++y) - if (ippFuncHint(srcmat.ptr(y), sstep, roisize, dstmat.ptr(y), ippAlgHintAccurate) < 0) - { - setIppErrorStatus(); - cv::Mat dstroi = dstmat.rowRange(y, y + 1); - func(srcmat.rowRange(y, y + 1), dstroi); - } - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - } + CV_Assert(func); func(srcmat, dstmat); } @@ -3446,7 +3449,7 @@ static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& ds #define reduceSumC32f32f reduceC_ > #define reduceSumC64f64f reduceC_ > -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP #define reduceSumC8u64f reduceSumC_8u16u16s32f_64f #define reduceSumC16u64f reduceSumC_8u16u16s32f_64f #define reduceSumC16s64f reduceSumC_8u16u16s32f_64f @@ -3458,35 +3461,32 @@ static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& ds #define reduceSumC32f64f reduceC_ > #endif -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP #define REDUCE_OP(favor, optype, type1, type2) \ +static inline bool ipp_reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& dstmat) \ +{ \ + if((srcmat.channels() == 1)) \ + { \ + int sstep = (int)srcmat.step; \ + typedef Ipp##favor IppType; \ + IppiSize roisize = ippiSize(srcmat.size().width, 1);\ + for(int y = 0; y < srcmat.size().height; y++)\ + {\ + if(ippi##optype##_##favor##_C1R(srcmat.ptr(y), sstep, roisize, dstmat.ptr(y)) < 0)\ + return false;\ + }\ + return true;\ + }\ + return false; \ +} \ static inline void reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& dstmat) \ { \ - typedef Ipp##favor IppType; \ - cv::Size size = srcmat.size(); \ - IppiSize roisize = ippiSize(size.width, 1);\ - int sstep = (int)srcmat.step; \ - \ - if (CV_IPP_CHECK_COND && (srcmat.channels() == 1)) \ - { \ - for (int y = 0; y < size.height; ++y) \ - if (ippi##optype##_##favor##_C1R(srcmat.ptr(y), sstep, roisize, dstmat.ptr(y)) < 0) \ - { \ - setIppErrorStatus(); \ - cv::Mat dstroi = dstmat.rowRange(y, y + 1); \ - cv::reduceC_ < type1, type2, cv::Op##optype < type2 > >(srcmat.rowRange(y, y + 1), dstroi); \ - } \ - else \ - { \ - CV_IMPL_ADD(CV_IMPL_IPP);\ - } \ - return; \ - } \ + CV_IPP_RUN(true, ipp_reduce##optype##C##favor(srcmat, dstmat)); \ cv::reduceC_ < type1, type2, cv::Op##optype < type2 > >(srcmat, dstmat); \ } #endif -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP REDUCE_OP(8u, Max, uchar, uchar) REDUCE_OP(16u, Max, ushort, ushort) REDUCE_OP(16s, Max, short, short) @@ -3499,7 +3499,7 @@ REDUCE_OP(32f, Max, float, float) #endif #define reduceMaxC64f reduceC_ > -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP REDUCE_OP(8u, Min, uchar, uchar) REDUCE_OP(16u, Min, ushort, ushort) REDUCE_OP(16s, Min, short, short) @@ -3772,7 +3772,7 @@ void cv::reduce(InputArray _src, OutputArray _dst, int dim, int op, int dtype) namespace cv { -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP #define USE_IPP_SORT typedef IppStatus (CV_STDCALL * IppSortFunc)(void *, int); diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index ebb845a14..3fce01d58 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -1368,100 +1368,106 @@ int cv::countNonZero( InputArray _src ) return nz; } +#if defined HAVE_IPP +namespace cv +{ +static bool ipp_mean( Mat &src, Mat &mask, Scalar &ret ) +{ +#if IPP_VERSION_X100 >= 700 + size_t total_size = src.total(); + int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0; + if( src.dims == 2 || (src.isContinuous() && mask.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) ) + { + IppiSize sz = { cols, rows }; + int type = src.type(); + if( !mask.empty() ) + { + typedef IppStatus (CV_STDCALL* ippiMaskMeanFuncC1)(const void *, int, const void *, int, IppiSize, Ipp64f *); + ippiMaskMeanFuncC1 ippFuncC1 = + type == CV_8UC1 ? (ippiMaskMeanFuncC1)ippiMean_8u_C1MR : + type == CV_16UC1 ? (ippiMaskMeanFuncC1)ippiMean_16u_C1MR : + type == CV_32FC1 ? (ippiMaskMeanFuncC1)ippiMean_32f_C1MR : + 0; + if( ippFuncC1 ) + { + Ipp64f res; + if( ippFuncC1(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, &res) >= 0 ) + { + ret = Scalar(res); + return true; + } + } + typedef IppStatus (CV_STDCALL* ippiMaskMeanFuncC3)(const void *, int, const void *, int, IppiSize, int, Ipp64f *); + ippiMaskMeanFuncC3 ippFuncC3 = + type == CV_8UC3 ? (ippiMaskMeanFuncC3)ippiMean_8u_C3CMR : + type == CV_16UC3 ? (ippiMaskMeanFuncC3)ippiMean_16u_C3CMR : + type == CV_32FC3 ? (ippiMaskMeanFuncC3)ippiMean_32f_C3CMR : + 0; + if( ippFuncC3 ) + { + Ipp64f res1, res2, res3; + if( ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 1, &res1) >= 0 && + ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 2, &res2) >= 0 && + ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 3, &res3) >= 0 ) + { + ret = Scalar(res1, res2, res3); + return true; + } + } + } + else + { + typedef IppStatus (CV_STDCALL* ippiMeanFuncHint)(const void*, int, IppiSize, double *, IppHintAlgorithm); + typedef IppStatus (CV_STDCALL* ippiMeanFuncNoHint)(const void*, int, IppiSize, double *); + ippiMeanFuncHint ippFuncHint = + type == CV_32FC1 ? (ippiMeanFuncHint)ippiMean_32f_C1R : + type == CV_32FC3 ? (ippiMeanFuncHint)ippiMean_32f_C3R : + type == CV_32FC4 ? (ippiMeanFuncHint)ippiMean_32f_C4R : + 0; + ippiMeanFuncNoHint ippFuncNoHint = + type == CV_8UC1 ? (ippiMeanFuncNoHint)ippiMean_8u_C1R : + type == CV_8UC3 ? (ippiMeanFuncNoHint)ippiMean_8u_C3R : + type == CV_8UC4 ? (ippiMeanFuncNoHint)ippiMean_8u_C4R : + type == CV_16UC1 ? (ippiMeanFuncNoHint)ippiMean_16u_C1R : + type == CV_16UC3 ? (ippiMeanFuncNoHint)ippiMean_16u_C3R : + type == CV_16UC4 ? (ippiMeanFuncNoHint)ippiMean_16u_C4R : + type == CV_16SC1 ? (ippiMeanFuncNoHint)ippiMean_16s_C1R : + type == CV_16SC3 ? (ippiMeanFuncNoHint)ippiMean_16s_C3R : + type == CV_16SC4 ? (ippiMeanFuncNoHint)ippiMean_16s_C4R : + 0; + // Make sure only zero or one version of the function pointer is valid + CV_Assert(!ippFuncHint || !ippFuncNoHint); + if( ippFuncHint || ippFuncNoHint ) + { + Ipp64f res[4]; + IppStatus status = ippFuncHint ? ippFuncHint(src.ptr(), (int)src.step[0], sz, res, ippAlgHintAccurate) : + ippFuncNoHint(src.ptr(), (int)src.step[0], sz, res); + if( status >= 0 ) + { + for( int i = 0; i < src.channels(); i++ ) + ret[i] = res[i]; + return true; + } + } + } + } + return false; +#else + return false; +#endif +} +} +#endif + cv::Scalar cv::mean( InputArray _src, InputArray _mask ) { Mat src = _src.getMat(), mask = _mask.getMat(); CV_Assert( mask.empty() || mask.type() == CV_8U ); int k, cn = src.channels(), depth = src.depth(); + Scalar s; -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - CV_IPP_CHECK() - { - size_t total_size = src.total(); - int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0; - if( src.dims == 2 || (src.isContinuous() && mask.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) ) - { - IppiSize sz = { cols, rows }; - int type = src.type(); - if( !mask.empty() ) - { - typedef IppStatus (CV_STDCALL* ippiMaskMeanFuncC1)(const void *, int, const void *, int, IppiSize, Ipp64f *); - ippiMaskMeanFuncC1 ippFuncC1 = - type == CV_8UC1 ? (ippiMaskMeanFuncC1)ippiMean_8u_C1MR : - type == CV_16UC1 ? (ippiMaskMeanFuncC1)ippiMean_16u_C1MR : - type == CV_32FC1 ? (ippiMaskMeanFuncC1)ippiMean_32f_C1MR : - 0; - if( ippFuncC1 ) - { - Ipp64f res; - if( ippFuncC1(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, &res) >= 0 ) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return Scalar(res); - } - setIppErrorStatus(); - } - typedef IppStatus (CV_STDCALL* ippiMaskMeanFuncC3)(const void *, int, const void *, int, IppiSize, int, Ipp64f *); - ippiMaskMeanFuncC3 ippFuncC3 = - type == CV_8UC3 ? (ippiMaskMeanFuncC3)ippiMean_8u_C3CMR : - type == CV_16UC3 ? (ippiMaskMeanFuncC3)ippiMean_16u_C3CMR : - type == CV_32FC3 ? (ippiMaskMeanFuncC3)ippiMean_32f_C3CMR : - 0; - if( ippFuncC3 ) - { - Ipp64f res1, res2, res3; - if( ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 1, &res1) >= 0 && - ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 2, &res2) >= 0 && - ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 3, &res3) >= 0 ) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return Scalar(res1, res2, res3); - } - setIppErrorStatus(); - } - } - else - { - typedef IppStatus (CV_STDCALL* ippiMeanFuncHint)(const void*, int, IppiSize, double *, IppHintAlgorithm); - typedef IppStatus (CV_STDCALL* ippiMeanFuncNoHint)(const void*, int, IppiSize, double *); - ippiMeanFuncHint ippFuncHint = - type == CV_32FC1 ? (ippiMeanFuncHint)ippiMean_32f_C1R : - type == CV_32FC3 ? (ippiMeanFuncHint)ippiMean_32f_C3R : - type == CV_32FC4 ? (ippiMeanFuncHint)ippiMean_32f_C4R : - 0; - ippiMeanFuncNoHint ippFuncNoHint = - type == CV_8UC1 ? (ippiMeanFuncNoHint)ippiMean_8u_C1R : - type == CV_8UC3 ? (ippiMeanFuncNoHint)ippiMean_8u_C3R : - type == CV_8UC4 ? (ippiMeanFuncNoHint)ippiMean_8u_C4R : - type == CV_16UC1 ? (ippiMeanFuncNoHint)ippiMean_16u_C1R : - type == CV_16UC3 ? (ippiMeanFuncNoHint)ippiMean_16u_C3R : - type == CV_16UC4 ? (ippiMeanFuncNoHint)ippiMean_16u_C4R : - type == CV_16SC1 ? (ippiMeanFuncNoHint)ippiMean_16s_C1R : - type == CV_16SC3 ? (ippiMeanFuncNoHint)ippiMean_16s_C3R : - type == CV_16SC4 ? (ippiMeanFuncNoHint)ippiMean_16s_C4R : - 0; - // Make sure only zero or one version of the function pointer is valid - CV_Assert(!ippFuncHint || !ippFuncNoHint); - if( ippFuncHint || ippFuncNoHint ) - { - Ipp64f res[4]; - IppStatus ret = ippFuncHint ? ippFuncHint(src.ptr(), (int)src.step[0], sz, res, ippAlgHintAccurate) : - ippFuncNoHint(src.ptr(), (int)src.step[0], sz, res); - if( ret >= 0 ) - { - Scalar sc; - for( int i = 0; i < cn; i++ ) - sc[i] = res[i]; - CV_IMPL_ADD(CV_IMPL_IPP); - return sc; - } - setIppErrorStatus(); - } - } - } - } -#endif + CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_mean(src, mask, s), s) SumFunc func = getSumFunc(depth); @@ -1470,7 +1476,6 @@ cv::Scalar cv::mean( InputArray _src, InputArray _mask ) const Mat* arrays[] = {&src, &mask, 0}; uchar* ptrs[2]; NAryMatIterator it(arrays, ptrs); - Scalar s; int total = (int)it.size, blockSize = total, intSumBlockSize = 0; int j, count = 0; AutoBuffer _buf; diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index d51711e0a..77aeb1ef3 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -47,16 +47,16 @@ #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) #define USE_IPP_CANNY 1 #else -#undef USE_IPP_CANNY +#define USE_IPP_CANNY 0 #endif namespace cv { - -#ifdef USE_IPP_CANNY +#ifdef HAVE_IPP static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high) { +#if USE_IPP_CANNY int size = 0, size1 = 0; IppiSize roi = { _src.cols, _src.rows }; @@ -90,6 +90,10 @@ static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high) _dst.ptr(), (int)_dst.step, roi, low, high, buffer) < 0 ) return false; return true; +#else + CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(low); CV_UNUSED(high); + return false; +#endif } #endif @@ -610,20 +614,7 @@ void cv::Canny( InputArray _src, OutputArray _dst, return; #endif -#ifdef USE_IPP_CANNY - CV_IPP_CHECK() - { - if( aperture_size == 3 && !L2gradient && 1 == cn ) - { - if (ippCanny(src, dst, (float)low_thresh, (float)high_thresh)) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - } - } -#endif + CV_IPP_RUN(USE_IPP_CANNY && (aperture_size == 3 && !L2gradient && 1 == cn), ippCanny(src, dst, (float)low_thresh, (float)high_thresh)) #ifdef HAVE_TBB diff --git a/modules/imgproc/src/corner.cpp b/modules/imgproc/src/corner.cpp index d9b3d943e..9dba9b4c6 100644 --- a/modules/imgproc/src/corner.cpp +++ b/modules/imgproc/src/corner.cpp @@ -603,11 +603,7 @@ void cv::cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, in ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, 0.0, borderType, MINEIGENVAL)) #ifdef HAVE_IPP - int kerSize = ksize; - if (ksize < 0) - { - kerSize = 3; - } + int kerSize = (ksize < 0)?3:ksize; bool isolated = (borderType & BORDER_ISOLATED) != 0; int borderTypeNI = borderType & ~BORDER_ISOLATED; #endif diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index 482f4d365..0807fe6d2 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -183,15 +183,12 @@ cv::Ptr cv::createDerivFilter(int srcType, int dstType, kx, ky, Point(-1,-1), 0, borderType ); } -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - -#define IPP_RETURN_ERROR {setIppErrorStatus(); return false;} - +#ifdef HAVE_IPP namespace cv { -#if IPP_VERSION_X100 >= 801 static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, double scale, double delta, int borderType) { +#if IPP_VERSION_X100 >= 801 if ((0 > dx) || (0 > dy) || (1 != dx + dy)) return false; if (fabs(delta) > FLT_EPSILON) @@ -233,19 +230,19 @@ static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx if (horz) { if (0 > ippiFilterScharrHorizMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp8u, ipp16s, 1, &bufferSize)) - IPP_RETURN_ERROR + return false; pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) - IPP_RETURN_ERROR + return false; sts = ippiFilterScharrHorizMaskBorder_8u16s_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } else { if (0 > ippiFilterScharrVertMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp8u, ipp16s, 1, &bufferSize)) - IPP_RETURN_ERROR + return false; pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) - IPP_RETURN_ERROR + return false; sts = ippiFilterScharrVertMaskBorder_8u16s_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } ippsFree(pBuffer); @@ -256,19 +253,19 @@ static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx if (horz) { if (0 > ippiFilterScharrHorizMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp16s, ipp16s, 1, &bufferSize)) - IPP_RETURN_ERROR + return false; pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) - IPP_RETURN_ERROR + return false; sts = ippiFilterScharrHorizMaskBorder_16s_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } else { if (0 > ippiFilterScharrVertMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp16s, ipp16s, 1, &bufferSize)) - IPP_RETURN_ERROR + return false; pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) - IPP_RETURN_ERROR + return false; sts = ippiFilterScharrVertMaskBorder_16s_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } ippsFree(pBuffer); @@ -279,134 +276,34 @@ static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx if (horz) { if (0 > ippiFilterScharrHorizMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp32f, ipp32f, 1, &bufferSize)) - IPP_RETURN_ERROR + return false; pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) - IPP_RETURN_ERROR + return false; sts = ippiFilterScharrHorizMaskBorder_32f_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } else { if (0 > ippiFilterScharrVertMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp32f, ipp32f, 1, &bufferSize)) - IPP_RETURN_ERROR + return false; pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) - IPP_RETURN_ERROR + return false; sts = ippiFilterScharrVertMaskBorder_32f_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } ippsFree(pBuffer); if (sts < 0) - IPP_RETURN_ERROR; + return false;; if (FLT_EPSILON < fabs(scale - 1.0)) sts = ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, roiSize); } return (0 <= sts); -} -#elif IPP_VERSION_X100 >= 700 -static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, double scale, double delta, int borderType) -{ - if (BORDER_REPLICATE != borderType) - return false; - if ((0 > dx) || (0 > dy) || (1 != dx + dy)) - return false; - if (fabs(delta) > FLT_EPSILON) - return false; - - Mat src = _src.getMat(), dst = _dst.getMat(); - - int bufSize = 0; - cv::AutoBuffer buffer; - IppiSize roi = ippiSize(src.cols, src.rows); - - if( ddepth < 0 ) - ddepth = src.depth(); - - dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); - - switch(src.type()) - { - case CV_8UC1: - { - if(scale != 1) - return false; - - switch(dst.type()) - { - case CV_16S: - { - if ((dx == 1) && (dy == 0)) - { - if (0 > ippiFilterScharrVertGetBufferSize_8u16s_C1R(roi,&bufSize)) - return false; - buffer.allocate(bufSize); - return (0 <= ippiFilterScharrVertBorder_8u16s_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, roi, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)); - } - if ((dx == 0) && (dy == 1)) - { - if (0 > ippiFilterScharrHorizGetBufferSize_8u16s_C1R(roi,&bufSize)) - return false; - buffer.allocate(bufSize); - return (0 <= ippiFilterScharrHorizBorder_8u16s_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, roi, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)); - } - return false; - } - default: - return false; - } - } - case CV_32FC1: - { - switch(dst.type()) - { - case CV_32FC1: - { - if ((dx == 1) && (dy == 0)) - { - if (0 > ippiFilterScharrVertGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows),&bufSize)) - return false; - buffer.allocate(bufSize); - - if (0 > ippiFilterScharrVertBorder_32f_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), - ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - { - return false; - } - - if (scale != 1) - /* IPP is fast, so MulC produce very little perf degradation.*/ - //ippiMulC_32f_C1IR((Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); - ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); - return true; - } - if ((dx == 0) && (dy == 1)) - { - if (0 > ippiFilterScharrHorizGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows),&bufSize)) - return false; - buffer.allocate(bufSize); - - if (0 > ippiFilterScharrHorizBorder_32f_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), - ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - return false; - - if (scale != 1) - ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); - return true; - } - } - default: - return false; - } - } - default: - return false; - } -} +#else + CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(ddepth); CV_UNUSED(dx); CV_UNUSED(dy); CV_UNUSED(scale); CV_UNUSED(delta); CV_UNUSED(borderType); + return false; #endif +} static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType) { @@ -423,58 +320,61 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, if ( ddepth < 0 ) ddepth = src.depth(); + IppiSize roi = {src.cols, src.rows}; + IppiMaskSize kernel = (IppiMaskSize)(ksize*10+ksize); + if (src.type() == CV_8U && dst.type() == CV_16S && scale == 1) { if ((dx == 1) && (dy == 0)) { - if (0 > ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize)) - IPP_RETURN_ERROR + if (0 > ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) + return false; buffer.allocate(bufSize); if (0 > ippiFilterSobelNegVertBorder_8u16s_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - IPP_RETURN_ERROR + return false; return true; } if ((dx == 0) && (dy == 1)) { - if (0 > ippiFilterSobelHorizGetBufferSize_8u16s_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize)) - IPP_RETURN_ERROR + if (0 > ippiFilterSobelHorizGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) + return false; buffer.allocate(bufSize); if (0 > ippiFilterSobelHorizBorder_8u16s_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - IPP_RETURN_ERROR + return false; return true; } #if !defined(HAVE_IPP_ICV_ONLY) if ((dx == 2) && (dy == 0)) { - if (0 > ippiFilterSobelVertSecondGetBufferSize_8u16s_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize)) - IPP_RETURN_ERROR + if (0 > ippiFilterSobelVertSecondGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) + return false; buffer.allocate(bufSize); if (0 > ippiFilterSobelVertSecondBorder_8u16s_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - IPP_RETURN_ERROR + return false; return true; } if ((dx == 0) && (dy == 2)) { - if (0 > ippiFilterSobelHorizSecondGetBufferSize_8u16s_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize)) - IPP_RETURN_ERROR + if (0 > ippiFilterSobelHorizSecondGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) + return false; buffer.allocate(bufSize); if (0 > ippiFilterSobelHorizSecondBorder_8u16s_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - IPP_RETURN_ERROR + return false; return true; } #endif @@ -485,14 +385,14 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, #if 0 if ((dx == 1) && (dy == 0)) { - if (0 > ippiFilterSobelNegVertGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), &bufSize)) - IPP_RETURN_ERROR + if (0 > ippiFilterSobelNegVertGetBufferSize_32f_C1R(roi, kernel, &bufSize)) + return false; buffer.allocate(bufSize); if (0 > ippiFilterSobelNegVertBorder_32f_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - IPP_RETURN_ERROR + return false; if(scale != 1) ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); return true; @@ -500,13 +400,13 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, if ((dx == 0) && (dy == 1)) { - if (0 > ippiFilterSobelHorizGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize)) - IPP_RETURN_ERROR + if (0 > ippiFilterSobelHorizGetBufferSize_32f_C1R(roi, kernel,&bufSize)) + return false; buffer.allocate(bufSize); if (0 > ippiFilterSobelHorizBorder_32f_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - IPP_RETURN_ERROR + return false; if(scale != 1) ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); return true; @@ -515,14 +415,14 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, #if !defined(HAVE_IPP_ICV_ONLY) if((dx == 2) && (dy == 0)) { - if (0 > ippiFilterSobelVertSecondGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize)) - IPP_RETURN_ERROR + if (0 > ippiFilterSobelVertSecondGetBufferSize_32f_C1R(roi, kernel,&bufSize)) + return false; buffer.allocate(bufSize); if (0 > ippiFilterSobelVertSecondBorder_32f_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - IPP_RETURN_ERROR + return false; if(scale != 1) ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); return true; @@ -530,14 +430,14 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, if((dx == 0) && (dy == 2)) { - if (0 > ippiFilterSobelHorizSecondGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize)) - IPP_RETURN_ERROR + if (0 > ippiFilterSobelHorizSecondGetBufferSize_32f_C1R(roi, kernel,&bufSize)) + return false; buffer.allocate(bufSize); if (0 > ippiFilterSobelHorizSecondBorder_32f_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - IPP_RETURN_ERROR + return false; if(scale != 1) ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); @@ -547,41 +447,22 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, } return false; } -#ifdef HAVE_IPP + static bool ipp_sobel(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType) { if (ksize < 0) { if (IPPDerivScharr(_src, _dst, ddepth, dx, dy, scale, delta, borderType)) - { - CV_IMPL_ADD(CV_IMPL_IPP); return true; - } } else if (0 < ksize) { if (IPPDerivSobel(_src, _dst, ddepth, dx, dy, ksize, scale, delta, borderType)) - { - CV_IMPL_ADD(CV_IMPL_IPP); return true; - } } return false; } -static bool ipp_scharr(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, double scale, double delta, int borderType) -{ -#if IPP_VERSION_MAJOR >= 7 - if (IPPDerivScharr(_src, _dst, ddepth, dx, dy, scale, delta, borderType)) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return true; - } -#endif - return false; } -#endif -} - #endif void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, @@ -604,10 +485,8 @@ void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, } #endif - CV_IPP_RUN(true, ipp_sobel(_src, _dst, ddepth, dx, dy, ksize, scale, delta, borderType)); - int ktype = std::max(CV_32F, std::max(ddepth, sdepth)); Mat kx, ky; @@ -643,9 +522,7 @@ void cv::Scharr( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, } #endif - - CV_IPP_RUN(true, ipp_scharr(_src, _dst, ddepth, dx, dy, scale, delta, borderType)); - + CV_IPP_RUN(true, IPPDerivScharr(_src, _dst, ddepth, dx, dy, scale, delta, borderType)); int ktype = std::max(CV_32F, std::max(ddepth, sdepth)); diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index d9c5edfd4..4ae4a4d9d 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -1200,7 +1200,6 @@ public: *ok = false; return; } - CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); for (int i = 0; i < histSize; ++i) CV_XADD((int *)(hist->data + i * hist->step), *(int *)(phist.data + i * phist.step)); @@ -1256,7 +1255,6 @@ static bool ipp_calchist(const Mat* images, int nimages, const int* channels, if (ok) { ihist.convertTo(hist, CV_32F); - CV_IMPL_ADD(CV_IMPL_IPP); return true; } } diff --git a/modules/imgproc/src/pyramids.cpp b/modules/imgproc/src/pyramids.cpp index 1d8c94333..a0d2d51c5 100644 --- a/modules/imgproc/src/pyramids.cpp +++ b/modules/imgproc/src/pyramids.cpp @@ -1375,7 +1375,7 @@ void cv::pyrUp( InputArray _src, OutputArray _dst, const Size& _dsz, int borderT } -#if 0 //#ifdef HAVE_IPP +#ifdef HAVE_IPP namespace cv { static bool ipp_buildpyramid( InputArray _src, OutputArrayOfArrays _dst, int maxlevel, int borderType ) @@ -1508,13 +1508,8 @@ void cv::buildPyramid( InputArray _src, OutputArrayOfArrays _dst, int maxlevel, int i=1; -#if (IPP_VERSION_X100 >= 801 && 0) - bool isolated = (borderType & BORDER_ISOLATED) != 0; - int borderTypeNI = borderType & ~BORDER_ISOLATED; - CV_IPP_RUN(((IPP_VERSION_X100 >= 801 && 0) && (borderTypeNI == BORDER_DEFAULT && (!_src.isSubmatrix() || isolated))), + CV_IPP_RUN(((IPP_VERSION_X100 >= 801 && 0) && ((borderType & ~BORDER_ISOLATED) == BORDER_DEFAULT && (!_src.isSubmatrix() || ((borderType & BORDER_ISOLATED) != 0)))), ipp_buildpyramid( _src, _dst, maxlevel, borderType)); -#endif - for( ; i <= maxlevel; i++ ) pyrDown( _dst.getMatRef(i-1), _dst.getMatRef(i), Size(), borderType ); diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 012b90418..104228b47 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -1668,6 +1668,7 @@ static bool ipp_GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, double sigma1, double sigma2, int borderType ) { +#if IPP_VERSION_X100 >= 801 int type = _src.type(); Size size = _src.size(); @@ -1742,10 +1743,7 @@ static bool ipp_GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, ippFree(pBuffer); if(status >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); return true; - } #undef IPP_FILTER_GAUSS_C1 #undef IPP_FILTER_GAUSS_CN @@ -1753,6 +1751,9 @@ static bool ipp_GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, } } } +#else + CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(ksize); CV_UNUSED(sigma1); CV_UNUSED(sigma2); CV_UNUSED(borderType); +#endif return false; } } @@ -1788,10 +1789,8 @@ void cv::GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, return; #endif - CV_IPP_RUN(true, ipp_GaussianBlur( _src, _dst, ksize, sigma1, sigma2, borderType)); - Mat kx, ky; createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2); sepFilter2D(_src, _dst, CV_MAT_DEPTH(type), kx, ky, Point(-1,-1), 0, borderType ); @@ -2754,6 +2753,8 @@ static bool ipp_medianFilter( InputArray _src0, OutputArray _dst, int ksize ) IPP_FILTER_MEDIAN_BORDER(Ipp32f, ipp32f, 32f_C1R); } #undef IPP_FILTER_MEDIAN_BORDER +#else + CV_UNUSED(_src0); CV_UNUSED(_dst); CV_UNUSED(ksize); #endif return false; } From 14b006e808f4b74e3cba39a4f4b196dc1228bc65 Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Fri, 25 Sep 2015 17:50:15 +0300 Subject: [PATCH 090/156] IPP_VERSION_X100 was changed to: IPP_VERSION_MAJOR * 100 + IPP_VERSION_MINOR*10 + IPP_VERSION_UPDATE to manage changes between updates more easily. IPP_DISABLE_BLOCK was added to ease tracking of disabled IPP functions; --- modules/calib3d/src/stereosgbm.cpp | 4 +-- modules/core/include/opencv2/core/private.hpp | 13 +++++-- modules/core/src/convert.cpp | 4 +-- modules/core/src/copy.cpp | 4 +-- modules/core/src/dxt.cpp | 2 +- modules/core/src/matmul.cpp | 2 +- modules/core/src/matrix.cpp | 30 +++++++++------- modules/core/src/precomp.hpp | 2 +- modules/core/src/stat.cpp | 34 ++++++++++--------- modules/imgproc/perf/perf_houghLines.cpp | 2 +- modules/imgproc/src/canny.cpp | 2 +- modules/imgproc/src/color.cpp | 34 +++++++++---------- modules/imgproc/src/corner.cpp | 8 ++--- modules/imgproc/src/deriv.cpp | 4 +-- modules/imgproc/src/distransform.cpp | 4 +-- modules/imgproc/src/filter.cpp | 8 ++--- modules/imgproc/src/histogram.cpp | 1 - modules/imgproc/src/hough.cpp | 4 +-- modules/imgproc/src/imgwarp.cpp | 24 ++++++------- modules/imgproc/src/moments.cpp | 2 +- modules/imgproc/src/morph.cpp | 4 +-- modules/imgproc/src/pyramids.cpp | 8 ++--- modules/imgproc/src/samplers.cpp | 2 +- modules/imgproc/src/smooth.cpp | 10 +++--- modules/imgproc/src/thresh.cpp | 4 +-- modules/imgproc/test/ocl/test_color.cpp | 8 ++--- modules/imgproc/test/test_houghLines.cpp | 2 +- 27 files changed, 120 insertions(+), 106 deletions(-) diff --git a/modules/calib3d/src/stereosgbm.cpp b/modules/calib3d/src/stereosgbm.cpp index 7ea6ad54e..15b35fcf1 100644 --- a/modules/calib3d/src/stereosgbm.cpp +++ b/modules/calib3d/src/stereosgbm.cpp @@ -1691,7 +1691,7 @@ void filterSpecklesImpl(cv::Mat& img, int newVal, int maxSpeckleSize, int maxDif #ifdef HAVE_IPP static bool ipp_filterSpeckles(Mat &img, int maxSpeckleSize, int newVal, int maxDiff) { -#if IPP_VERSION_X100 >= 801 +#if IPP_VERSION_X100 >= 810 int type = img.type(); Ipp32s bufsize = 0; IppiSize roisize = { img.cols, img.rows }; @@ -1739,7 +1739,7 @@ void cv::filterSpeckles( InputOutputArray _img, double _newval, int maxSpeckleSi int newVal = cvRound(_newval), maxDiff = cvRound(_maxDiff); - CV_IPP_RUN(IPP_VERSION_X100 >= 801 && !__buf.needed() && (type == CV_8UC1 || type == CV_16SC1), ipp_filterSpeckles(img, maxSpeckleSize, newVal, maxDiff)); + CV_IPP_RUN(IPP_VERSION_X100 >= 810 && !__buf.needed() && (type == CV_8UC1 || type == CV_16SC1), ipp_filterSpeckles(img, maxSpeckleSize, newVal, maxDiff)); if (type == CV_8UC1) filterSpecklesImpl(img, newVal, maxSpeckleSize, maxDiff, _buf); diff --git a/modules/core/include/opencv2/core/private.hpp b/modules/core/include/opencv2/core/private.hpp index 0e8765be1..9f0f5701f 100644 --- a/modules/core/include/opencv2/core/private.hpp +++ b/modules/core/include/opencv2/core/private.hpp @@ -191,9 +191,16 @@ CV_EXPORTS void scalarToRawData(const cv::Scalar& s, void* buf, int type, int un \****************************************************************************************/ #ifdef HAVE_IPP -# include "ipp.h" +#include "ipp.h" -# define IPP_VERSION_X100 (IPP_VERSION_MAJOR * 100 + IPP_VERSION_MINOR) +#ifndef IPP_VERSION_UPDATE // prior to 7.1 +#define IPP_VERSION_UPDATE 0 +#endif + +#define IPP_VERSION_X100 (IPP_VERSION_MAJOR * 100 + IPP_VERSION_MINOR*10 + IPP_VERSION_UPDATE) + +// General define for ipp function disabling +#define IPP_DISABLE_BLOCK 0 #ifdef CV_MALLOC_ALIGN #undef CV_MALLOC_ALIGN @@ -235,7 +242,7 @@ static inline IppDataType ippiGetDataType(int depth) } #else -# define IPP_VERSION_X100 0 +#define IPP_VERSION_X100 0 #endif #ifdef HAVE_IPP_ICV_ONLY diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index fd07a7fc5..1070bd546 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -5682,7 +5682,7 @@ static bool ocl_LUT(InputArray _src, InputArray _lut, OutputArray _dst) #if defined(HAVE_IPP) namespace ipp { -#if 0 // there are no performance benefits (PR #2653) +#if IPP_DISABLE_BLOCK // there are no performance benefits (PR #2653) class IppLUTParallelBody_LUTC1 : public ParallelLoopBody { public: @@ -5850,7 +5850,7 @@ static bool ipp_lut(Mat &src, Mat &lut, Mat &dst) Ptr body; size_t elemSize1 = CV_ELEM_SIZE1(dst.depth()); -#if 0 // there are no performance benefits (PR #2653) +#if IPP_DISABLE_BLOCK // there are no performance benefits (PR #2653) if (lutcn == 1) { ParallelLoopBody* p = new ipp::IppLUTParallelBody_LUTC1(src, lut, dst, &ok); diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index 22b18710d..c463b70d4 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -377,7 +377,7 @@ Mat& Mat::operator = (const Scalar& s) if( is[0] == 0 && is[1] == 0 && is[2] == 0 && is[3] == 0 ) { -#if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY && 0 +#if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY && IPP_DISABLE_BLOCK CV_IPP_CHECK() { if (dims <= 2 || isContinuous()) @@ -1157,7 +1157,7 @@ void cv::copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom, borderType &= ~BORDER_ISOLATED; -#if defined HAVE_IPP && 0 +#if defined HAVE_IPP && IPP_DISABLE_BLOCK CV_IPP_CHECK() { typedef IppStatus (CV_STDCALL * ippiCopyMakeBorder)(const void * pSrc, int srcStep, IppiSize srcRoiSize, void * pDst, diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index 315ab5b36..f6709e943 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -54,7 +54,7 @@ namespace cv # pragma warning(disable: 4748) #endif -#if IPP_VERSION_X100 >= 701 +#if IPP_VERSION_X100 >= 710 #define USE_IPP_DFT 1 #else #undef USE_IPP_DFT diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.cpp index c1eacfd21..cb639462f 100644 --- a/modules/core/src/matmul.cpp +++ b/modules/core/src/matmul.cpp @@ -2916,7 +2916,7 @@ dotProd_(const T* src1, const T* src2, int len) static double dotProd_8u(const uchar* src1, const uchar* src2, int len) { double r = 0; -#if ARITHM_USE_IPP && 0 +#if ARITHM_USE_IPP && IPP_DISABLE_BLOCK CV_IPP_CHECK() { if (0 <= ippiDotProd_8u64f_C1R(src1, (int)(len*sizeof(src1[0])), diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index cb3675e2c..9c05260e1 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -3782,18 +3782,24 @@ static IppSortFunc getSortFunc(int depth, bool sortDescending) { if (!sortDescending) return depth == CV_8U ? (IppSortFunc)ippsSortAscend_8u_I : - /*depth == CV_16U ? (IppSortFunc)ippsSortAscend_16u_I : +#if IPP_DISABLE_BLOCK + depth == CV_16U ? (IppSortFunc)ippsSortAscend_16u_I : depth == CV_16S ? (IppSortFunc)ippsSortAscend_16s_I : depth == CV_32S ? (IppSortFunc)ippsSortAscend_32s_I : depth == CV_32F ? (IppSortFunc)ippsSortAscend_32f_I : - depth == CV_64F ? (IppSortFunc)ippsSortAscend_64f_I :*/ 0; + depth == CV_64F ? (IppSortFunc)ippsSortAscend_64f_I : +#endif + 0; else return depth == CV_8U ? (IppSortFunc)ippsSortDescend_8u_I : - /*depth == CV_16U ? (IppSortFunc)ippsSortDescend_16u_I : +#if IPP_DISABLE_BLOCK + depth == CV_16U ? (IppSortFunc)ippsSortDescend_16u_I : depth == CV_16S ? (IppSortFunc)ippsSortDescend_16s_I : depth == CV_32S ? (IppSortFunc)ippsSortDescend_32s_I : depth == CV_32F ? (IppSortFunc)ippsSortDescend_32f_I : - depth == CV_64F ? (IppSortFunc)ippsSortDescend_64f_I :*/ 0; + depth == CV_64F ? (IppSortFunc)ippsSortDescend_64f_I : +#endif + 0; } static IppFlipFunc getFlipFunc(int depth) @@ -3908,7 +3914,7 @@ public: const _Tp* arr; }; -#if defined USE_IPP_SORT && 0 +#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK typedef IppStatus (CV_STDCALL *IppSortIndexFunc)(void *, int *, int); @@ -3955,7 +3961,7 @@ template static void sortIdx_( const Mat& src, Mat& dst, int flags ) bptr = (T*)buf; _iptr = (int*)ibuf; -#if defined USE_IPP_SORT && 0 +#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK int depth = src.depth(); IppSortIndexFunc ippFunc = 0; IppFlipFunc ippFlipFunc = 0; @@ -3984,27 +3990,27 @@ template static void sortIdx_( const Mat& src, Mat& dst, int flags ) for( j = 0; j < len; j++ ) iptr[j] = j; -#if defined USE_IPP_SORT && 0 +#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK if (sortRows || !ippFunc || ippFunc(ptr, iptr, len) < 0) #endif { -#if defined USE_IPP_SORT && 0 +#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK setIppErrorStatus(); #endif std::sort( iptr, iptr + len, LessThanIdx(ptr) ); if( sortDescending ) { -#if defined USE_IPP_SORT && 0 +#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK if (!ippFlipFunc || ippFlipFunc(iptr, len) < 0) #endif { -#if defined USE_IPP_SORT && 0 +#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK setIppErrorStatus(); #endif for( j = 0; j < len/2; j++ ) std::swap(iptr[j], iptr[len-1-j]); } -#if defined USE_IPP_SORT && 0 +#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK else { CV_IMPL_ADD(CV_IMPL_IPP); @@ -4012,7 +4018,7 @@ template static void sortIdx_( const Mat& src, Mat& dst, int flags ) #endif } } -#if defined USE_IPP_SORT && 0 +#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK else { CV_IMPL_ADD(CV_IMPL_IPP); diff --git a/modules/core/src/precomp.hpp b/modules/core/src/precomp.hpp index 88064c85b..6123d3f3d 100644 --- a/modules/core/src/precomp.hpp +++ b/modules/core/src/precomp.hpp @@ -206,7 +206,7 @@ extern volatile bool USE_AVX2; enum { BLOCK_SIZE = 1024 }; -#if defined HAVE_IPP && (IPP_VERSION_MAJOR >= 7) +#if defined HAVE_IPP && (IPP_VERSION_X100 >= 700) #define ARITHM_USE_IPP 1 #else #define ARITHM_USE_IPP 0 diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 3fce01d58..999640d94 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -1141,7 +1141,7 @@ static bool ocl_sum( InputArray _src, Scalar & res, int sum_op, InputArray _mask #ifdef HAVE_IPP static bool ipp_sum(Mat &src, Scalar &_res) { -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 int cn = src.channels(); size_t total_size = src.total(); int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0; @@ -1203,7 +1203,7 @@ cv::Scalar cv::sum( InputArray _src ) #endif Mat src = _src.getMat(); - CV_IPP_RUN(IPP_VERSION_MAJOR >= 7, ipp_sum(src, _res), _res); + CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_sum(src, _res), _res); int k, cn = src.channels(), depth = src.depth(); SumFunc func = getSumFunc(depth); @@ -1645,7 +1645,7 @@ namespace cv { static bool ipp_meanStdDev(Mat& src, OutputArray _mean, OutputArray _sdv, Mat& mask) { -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 int cn = src.channels(); size_t total_size = src.total(); int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0; @@ -1717,7 +1717,7 @@ static bool ipp_meanStdDev(Mat& src, OutputArray _mean, OutputArray _sdv, Mat& m ippiMeanStdDevFuncC1 ippFuncC1 = type == CV_8UC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_8u_C1R : type == CV_16UC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_16u_C1R : -#if (IPP_VERSION_X100 >= 801) +#if (IPP_VERSION_X100 >= 810) type == CV_32FC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_32f_C1R ://Aug 2013: bug in IPP 7.1, 8.0 #endif 0; @@ -1761,7 +1761,7 @@ void cv::meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv, Input Mat src = _src.getMat(), mask = _mask.getMat(); CV_Assert( mask.empty() || mask.type() == CV_8UC1 ); - CV_IPP_RUN(IPP_VERSION_MAJOR >= 7, ipp_meanStdDev(src, _mean, _sdv, mask)); + CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_meanStdDev(src, _mean, _sdv, mask)); int k, cn = src.channels(), depth = src.depth(); @@ -2217,7 +2217,7 @@ static bool ocl_minMaxIdx( InputArray _src, double* minVal, double* maxVal, int* #ifdef HAVE_IPP static bool ipp_minMaxIdx( Mat &src, double* minVal, double* maxVal, int* minIdx, int* maxIdx, Mat &mask) { -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 int type = src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); size_t total_size = src.total(); int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0; @@ -2325,7 +2325,7 @@ void cv::minMaxIdx(InputArray _src, double* minVal, ocl_minMaxIdx(_src, minVal, maxVal, minIdx, maxIdx, _mask)) Mat src = _src.getMat(), mask = _mask.getMat(); - CV_IPP_RUN(IPP_VERSION_MAJOR >= 7, ipp_minMaxIdx(src, minVal, maxVal, minIdx, maxIdx, mask)) + CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_minMaxIdx(src, minVal, maxVal, minIdx, maxIdx, mask)) MinMaxIdxFunc func = getMinmaxTab(depth); CV_Assert( func != 0 ); @@ -2658,7 +2658,7 @@ static bool ocl_norm( InputArray _src, int normType, InputArray _mask, double & #ifdef HAVE_IPP static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) { -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 int cn = src.channels(); size_t total_size = src.total(); int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0; @@ -2701,7 +2701,8 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) return true; } } - /*typedef IppStatus (CV_STDCALL* ippiMaskNormFuncC3)(const void *, int, const void *, int, IppiSize, int, Ipp64f *); +#if IPP_DISABLED_BLOCK + typedef IppStatus (CV_STDCALL* ippiMaskNormFuncC3)(const void *, int, const void *, int, IppiSize, int, Ipp64f *); ippiMaskNormFuncC3 ippFuncC3 = normType == NORM_INF ? (type == CV_8UC3 ? (ippiMaskNormFuncC3)ippiNorm_Inf_8u_C3CMR : @@ -2736,7 +2737,8 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) result = (normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm); return true; } - }*/ + } +#endif } else { @@ -2762,7 +2764,7 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) type == CV_16UC3 ? (ippiNormFuncNoHint)ippiNorm_Inf_16u_C3R : type == CV_16UC4 ? (ippiNormFuncNoHint)ippiNorm_Inf_16u_C4R : type == CV_16SC1 ? (ippiNormFuncNoHint)ippiNorm_Inf_16s_C1R : -#if (IPP_VERSION_X100 >= 801) +#if (IPP_VERSION_X100 >= 810) type == CV_16SC3 ? (ippiNormFuncNoHint)ippiNorm_Inf_16s_C3R : //Aug 2013: problem in IPP 7.1, 8.0 : -32768 type == CV_16SC4 ? (ippiNormFuncNoHint)ippiNorm_Inf_16s_C4R : //Aug 2013: problem in IPP 7.1, 8.0 : -32768 #endif @@ -2842,7 +2844,7 @@ double cv::norm( InputArray _src, int normType, InputArray _mask ) #endif Mat src = _src.getMat(), mask = _mask.getMat(); - CV_IPP_RUN(IPP_VERSION_MAJOR >= 7, ipp_norm(src, normType, mask, _result), _result); + CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_norm(src, normType, mask, _result), _result); int depth = src.depth(), cn = src.channels(); if( src.isContinuous() && mask.empty() ) @@ -3046,7 +3048,7 @@ namespace cv { static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArray _mask, double &result) { -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat(); if( normType & CV_RELATIVE ) @@ -3260,7 +3262,7 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra type == CV_16UC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16u_C3R : type == CV_16UC4 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16u_C4R : type == CV_16SC1 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16s_C1R : -#if (IPP_VERSION_X100 >= 801) +#if (IPP_VERSION_X100 >= 810) type == CV_16SC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16s_C3R : //Aug 2013: problem in IPP 7.1, 8.0 : -32768 type == CV_16SC4 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16s_C4R : //Aug 2013: problem in IPP 7.1, 8.0 : -32768 #endif @@ -3275,7 +3277,7 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra type == CV_16UC1 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16u_C1R : type == CV_16UC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16u_C3R : type == CV_16UC4 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16u_C4R : -#if !(IPP_VERSION_X100 == 802 && (!defined(IPP_VERSION_UPDATE) || IPP_VERSION_UPDATE <= 1)) // Oct 2014: Accuracy issue with IPP 8.2 / 8.2.1 +#if !(IPP_VERSION_X100 == 820 || IPP_VERSION_X100 == 821) // Oct 2014: Accuracy issue with IPP 8.2 / 8.2.1 type == CV_16SC1 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16s_C1R : #endif type == CV_16SC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16s_C3R : @@ -3339,7 +3341,7 @@ double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _m _result) #endif - CV_IPP_RUN(IPP_VERSION_MAJOR >= 7, ipp_norm(_src1, _src2, normType, _mask, _result), _result); + CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_norm(_src1, _src2, normType, _mask, _result), _result); if( normType & CV_RELATIVE ) { diff --git a/modules/imgproc/perf/perf_houghLines.cpp b/modules/imgproc/perf/perf_houghLines.cpp index a6e7e7340..6dfaa56aa 100644 --- a/modules/imgproc/perf/perf_houghLines.cpp +++ b/modules/imgproc/perf/perf_houghLines.cpp @@ -37,7 +37,7 @@ PERF_TEST_P(Image_RhoStep_ThetaStep_Threshold, HoughLines, TEST_CYCLE() HoughLines(image, lines, rhoStep, thetaStep, threshold); transpose(lines, lines); -#if (0 && defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 801) +#if (0 && defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 810) SANITY_CHECK_NOTHING(); #else SANITY_CHECK(lines); diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index 77aeb1ef3..670d1486c 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -44,7 +44,7 @@ #include "opencl_kernels_imgproc.hpp" -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) #define USE_IPP_CANNY 1 #else #define USE_IPP_CANNY 0 diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 3c3e51255..6020eaf77 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -96,7 +96,7 @@ #define CV_DESCALE(x,n) (((x) + (1 << ((n)-1))) >> (n)) -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) #define MAX_IPP8u 255 #define MAX_IPP16u 65535 #define MAX_IPP32f 1.0 @@ -200,7 +200,7 @@ void CvtColorLoop(const Mat& src, Mat& dst, const Cvt& cvt) parallel_for_(Range(0, src.rows), CvtColorLoop_Invoker(src, dst, cvt), src.total()/(double)(1<<16) ); } -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) typedef IppStatus (CV_STDCALL* ippiReorderFunc)(const void *, int, void *, int, IppiSize, const int *); typedef IppStatus (CV_STDCALL* ippiGeneralFunc)(const void *, int, void *, int, IppiSize); @@ -305,7 +305,7 @@ static ippiReorderFunc ippiSwapChannelsC3RTab[] = 0, (ippiReorderFunc)ippiSwapChannels_32f_C3R, 0, 0 }; -#if IPP_VERSION_X100 >= 801 +#if IPP_VERSION_X100 >= 810 static ippiReorderFunc ippiSwapChannelsC4RTab[] = { (ippiReorderFunc)ippiSwapChannels_8u_C4R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4R, 0, @@ -379,7 +379,7 @@ static ippiGeneralFunc ippiHLS2RGBTab[] = 0, (ippiGeneralFunc)ippiHLSToRGB_32f_C3R, 0, 0 }; -#if !defined(HAVE_IPP_ICV_ONLY) && 0 +#if !defined(HAVE_IPP_ICV_ONLY) && IPP_DISABLE_BLOCK static ippiGeneralFunc ippiRGBToLUVTab[] = { (ippiGeneralFunc)ippiRGBToLUV_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToLUV_16u_C3R, 0, @@ -7336,7 +7336,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) switch( code ) { -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 case CV_BGR2BGRA: case CV_RGB2BGRA: case CV_BGRA2BGR: case CV_RGBA2BGR: case CV_RGB2BGR: case CV_BGRA2RGBA: CV_Assert( scn == 3 || scn == 4 ); @@ -7369,7 +7369,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) if( CvtColorIPPLoopCopy(src, dst, IPPReorderFunctor(ippiSwapChannelsC3RTab[depth], 2, 1, 0)) ) return true; } -#if IPP_VERSION_X100 >= 801 +#if IPP_VERSION_X100 >= 810 else if( code == CV_RGBA2BGRA ) { if( CvtColorIPPLoopCopy(src, dst, IPPReorderFunctor(ippiSwapChannelsC4RTab[depth], 2, 1, 0)) ) @@ -7379,7 +7379,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) return false; #endif -#if 0 // breaks OCL accuracy tests +#if IPP_DISABLE_BLOCK // breaks OCL accuracy tests case CV_BGR2BGR565: case CV_BGR2BGR555: case CV_RGB2BGR565: case CV_RGB2BGR555: case CV_BGRA2BGR565: case CV_BGRA2BGR555: case CV_RGBA2BGR565: case CV_RGBA2BGR555: CV_Assert( (scn == 3 || scn == 4) && depth == CV_8U ); @@ -7450,7 +7450,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) CV_SUPPRESS_DEPRECATED_END return false; -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 case CV_BGR2GRAY: case CV_BGRA2GRAY: case CV_RGB2GRAY: case CV_RGBA2GRAY: CV_Assert( scn == 3 || scn == 4 ); _dst.create(sz, CV_MAKETYPE(depth, 1)); @@ -7497,7 +7497,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) return false; #endif -#if 0 +#if IPP_DISABLE_BLOCK case CV_BGR2YCrCb: case CV_RGB2YCrCb: case CV_BGR2YUV: case CV_RGB2YUV: { @@ -7537,7 +7537,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) } #endif -#if 0 +#if IPP_DISABLE_BLOCK case CV_YCrCb2BGR: case CV_YCrCb2RGB: case CV_YUV2BGR: case CV_YUV2RGB: { @@ -7578,7 +7578,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) } #endif -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 case CV_BGR2XYZ: case CV_RGB2XYZ: CV_Assert( scn == 3 || scn == 4 ); _dst.create(sz, CV_MAKETYPE(depth, 3)); @@ -7607,7 +7607,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) return false; #endif -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 case CV_XYZ2BGR: case CV_XYZ2RGB: if( dcn <= 0 ) dcn = 3; CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) ); @@ -7638,7 +7638,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) return false; #endif -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 case CV_BGR2HSV: case CV_RGB2HSV: case CV_BGR2HSV_FULL: case CV_RGB2HSV_FULL: case CV_BGR2HLS: case CV_RGB2HLS: case CV_BGR2HLS_FULL: case CV_RGB2HLS_FULL: { @@ -7648,7 +7648,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) if( depth == CV_8U || depth == CV_16U ) { -#if 0 // breaks OCL accuracy tests +#if IPP_DISABLE_BLOCK // breaks OCL accuracy tests if( code == CV_BGR2HSV_FULL && scn == 3 ) { if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) ) @@ -7695,7 +7695,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) } #endif -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 case CV_HSV2BGR: case CV_HSV2RGB: case CV_HSV2BGR_FULL: case CV_HSV2RGB_FULL: case CV_HLS2BGR: case CV_HLS2RGB: case CV_HLS2BGR_FULL: case CV_HLS2RGB_FULL: { @@ -7751,7 +7751,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) } #endif -#if 0 +#if IPP_DISABLE_BLOCK case CV_BGR2Lab: case CV_RGB2Lab: case CV_LBGR2Lab: case CV_LRGB2Lab: case CV_BGR2Luv: case CV_RGB2Luv: case CV_LBGR2Luv: case CV_LRGB2Luv: { @@ -7813,7 +7813,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) } #endif -#if 0 +#if IPP_DISABLE_BLOCK case CV_Lab2BGR: case CV_Lab2RGB: case CV_Lab2LBGR: case CV_Lab2LRGB: case CV_Luv2BGR: case CV_Luv2RGB: case CV_Luv2LBGR: case CV_Luv2LRGB: { diff --git a/modules/imgproc/src/corner.cpp b/modules/imgproc/src/corner.cpp index 9dba9b4c6..f4b6854b7 100644 --- a/modules/imgproc/src/corner.cpp +++ b/modules/imgproc/src/corner.cpp @@ -528,7 +528,7 @@ namespace cv { static bool ipp_cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType ) { -#if IPP_VERSION_MAJOR >= 8 +#if IPP_VERSION_X100 >= 800 Mat src = _src.getMat(); _dst.create( src.size(), CV_32FC1 ); Mat dst = _dst.getMat(); @@ -608,7 +608,7 @@ void cv::cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, in int borderTypeNI = borderType & ~BORDER_ISOLATED; #endif CV_IPP_RUN(((borderTypeNI == BORDER_REPLICATE && (!_src.isSubmatrix() || isolated)) && - (kerSize == 3 || kerSize == 5) && (blockSize == 3 || blockSize == 5)) && IPP_VERSION_MAJOR >= 8, + (kerSize == 3 || kerSize == 5) && (blockSize == 3 || blockSize == 5)) && IPP_VERSION_X100 >= 800, ipp_cornerMinEigenVal( _src, _dst, blockSize, ksize, borderType )); @@ -625,7 +625,7 @@ namespace cv { static bool ipp_cornerHarris( InputArray _src, OutputArray _dst, int blockSize, int ksize, double k, int borderType ) { -#if IPP_VERSION_X100 >= 801 && 0 +#if IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK Mat src = _src.getMat(); _dst.create( src.size(), CV_32FC1 ); Mat dst = _dst.getMat(); @@ -692,7 +692,7 @@ void cv::cornerHarris( InputArray _src, OutputArray _dst, int blockSize, int ksi #endif CV_IPP_RUN(((ksize == 3 || ksize == 5) && (_src.type() == CV_8UC1 || _src.type() == CV_32FC1) && (borderTypeNI == BORDER_CONSTANT || borderTypeNI == BORDER_REPLICATE) && CV_MAT_CN(_src.type()) == 1 && - (!_src.isSubmatrix() || isolated)) && IPP_VERSION_X100 >= 801 && 0, ipp_cornerHarris( _src, _dst, blockSize, ksize, k, borderType )); + (!_src.isSubmatrix() || isolated)) && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK, ipp_cornerHarris( _src, _dst, blockSize, ksize, k, borderType )); Mat src = _src.getMat(); diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index 0807fe6d2..c263b6914 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -188,7 +188,7 @@ namespace cv { static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, double scale, double delta, int borderType) { -#if IPP_VERSION_X100 >= 801 +#if IPP_VERSION_X100 >= 810 if ((0 > dx) || (0 > dy) || (1 != dx + dy)) return false; if (fabs(delta) > FLT_EPSILON) @@ -382,7 +382,7 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, if (src.type() == CV_32F && dst.type() == CV_32F) { -#if 0 +#if IPP_DISABLE_BLOCK if ((dx == 1) && (dy == 0)) { if (0 > ippiFilterSobelNegVertGetBufferSize_32f_C1R(roi, kernel, &bufSize)) diff --git a/modules/imgproc/src/distransform.cpp b/modules/imgproc/src/distransform.cpp index a6491086e..cde6ec4eb 100644 --- a/modules/imgproc/src/distransform.cpp +++ b/modules/imgproc/src/distransform.cpp @@ -785,7 +785,7 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe { if( maskSize == CV_DIST_MASK_3 ) { -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) CV_IPP_CHECK() { IppiSize roi = { src.cols, src.rows }; @@ -802,7 +802,7 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe } else { -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) CV_IPP_CHECK() { IppiSize roi = { src.cols, src.rows }; diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 10c8240a9..587c50ba3 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -47,7 +47,7 @@ Base Image Filter \****************************************************************************************/ -#if IPP_VERSION_X100 >= 701 +#if IPP_VERSION_X100 >= 710 #define USE_IPP_SEP_FILTERS 1 #else #undef USE_IPP_SEP_FILTERS @@ -1415,14 +1415,14 @@ struct RowVec_32f { kernel = _kernel; haveSSE = checkHardwareSupport(CV_CPU_SSE); -#if defined USE_IPP_SEP_FILTERS && 0 +#if defined USE_IPP_SEP_FILTERS && IPP_DISABLE_BLOCK bufsz = -1; #endif } int operator()(const uchar* _src, uchar* _dst, int width, int cn) const { -#if defined USE_IPP_SEP_FILTERS && 0 +#if defined USE_IPP_SEP_FILTERS && IPP_DISABLE_BLOCK CV_IPP_CHECK() { int ret = ippiOperator(_src, _dst, width, cn); @@ -1463,7 +1463,7 @@ struct RowVec_32f Mat kernel; bool haveSSE; -#if defined USE_IPP_SEP_FILTERS && 0 +#if defined USE_IPP_SEP_FILTERS && IPP_DISABLE_BLOCK private: mutable int bufsz; int ippiOperator(const uchar* _src, uchar* _dst, int width, int cn) const diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index 4ae4a4d9d..1bb9ec5e5 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -1176,7 +1176,6 @@ calcHist_8u( std::vector& _ptrs, const std::vector& _deltas, } #ifdef HAVE_IPP - class IPPCalcHistInvoker : public ParallelLoopBody { diff --git a/modules/imgproc/src/hough.cpp b/modules/imgproc/src/hough.cpp index c5bb2e20e..18a030841 100644 --- a/modules/imgproc/src/hough.cpp +++ b/modules/imgproc/src/hough.cpp @@ -96,7 +96,7 @@ HoughLinesStandard( const Mat& img, float rho, float theta, int numangle = cvRound((max_theta - min_theta) / theta); int numrho = cvRound(((width + height) * 2 + 1) / rho); -#if (0 && defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 801) +#if defined HAVE_IPP && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 810 && IPP_DISABLED_BLOCK CV_IPP_CHECK() { IppiSize srcSize = { width, height }; @@ -429,7 +429,7 @@ HoughLinesProbabilistic( Mat& image, int numangle = cvRound(CV_PI / theta); int numrho = cvRound(((width + height) * 2 + 1) / rho); -#if (0 && defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 801) +#if defined HAVE_IPP && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 810 && IPP_DISABLED_BLOCK CV_IPP_CHECK() { IppiSize srcSize = { width, height }; diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index 433e38f70..9c16f91a2 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -56,13 +56,13 @@ static IppStatus sts = ippInit(); namespace cv { -#if IPP_VERSION_X100 >= 701 +#if IPP_VERSION_X100 >= 710 typedef IppStatus (CV_STDCALL* ippiResizeFunc)(const void*, int, const void*, int, IppiPoint, IppiSize, IppiBorderType, void*, void*, Ipp8u*); typedef IppStatus (CV_STDCALL* ippiResizeGetBufferSize)(void*, IppiSize, Ipp32u, int*); typedef IppStatus (CV_STDCALL* ippiResizeGetSrcOffset)(void*, IppiPoint, IppiPoint*); #endif -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) && 0 +#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) && IPP_DISABLE_BLOCK typedef IppStatus (CV_STDCALL* ippiSetFunc)(const void*, void *, int, IppiSize); typedef IppStatus (CV_STDCALL* ippiWarpPerspectiveFunc)(const void*, IppiSize, int, IppiRect, void *, int, IppiRect, double [3][3], int); typedef IppStatus (CV_STDCALL* ippiWarpAffineBackFunc)(const void*, IppiSize, int, IppiRect, void *, int, IppiRect, double [2][3], int); @@ -2745,7 +2745,7 @@ static int computeResizeAreaTab( int ssize, int dsize, int cn, double scale, Dec getBufferSizeFunc = (ippiResizeGetBufferSize)ippiResizeGetBufferSize_##TYPE; \ getSrcOffsetFunc = (ippiResizeGetSrcOffset)ippiResizeGetSrcOffset_##TYPE; -#if IPP_VERSION_X100 >= 701 +#if IPP_VERSION_X100 >= 710 class IPPresizeInvoker : public ParallelLoopBody { @@ -2765,7 +2765,7 @@ public: switch (type) { -#if 0 // disabled since it breaks tests for CascadeClassifier +#if IPP_DISABLE_BLOCK // disabled since it breaks tests for CascadeClassifier case CV_8UC1: SET_IPP_RESIZE_PTR(8u,C1); break; case CV_8UC3: SET_IPP_RESIZE_PTR(8u,C3); break; case CV_8UC4: SET_IPP_RESIZE_PTR(8u,C4); break; @@ -3092,7 +3092,7 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize, #endif -#if IPP_VERSION_X100 >= 701 +#if IPP_VERSION_X100 >= 710 static bool ipp_resize_mt( Mat src, Mat dst, double inv_scale_x, double inv_scale_y, int interpolation) { @@ -3278,7 +3278,7 @@ void cv::resize( InputArray _src, OutputArray _dst, Size dsize, double ex = fabs((double)dsize.width / _src.cols() - inv_scale_x) / inv_scale_x; double ey = fabs((double)dsize.height / _src.rows() - inv_scale_y) / inv_scale_y; #endif - CV_IPP_RUN(IPP_VERSION_X100 >= 701 && ((ex < IPP_RESIZE_EPS && ey < IPP_RESIZE_EPS && depth != CV_64F) || (ex == 0 && ey == 0 && depth == CV_64F)) && + CV_IPP_RUN(IPP_VERSION_X100 >= 710 && ((ex < IPP_RESIZE_EPS && ey < IPP_RESIZE_EPS && depth != CV_64F) || (ex == 0 && ey == 0 && depth == CV_64F)) && (interpolation == INTER_LINEAR || interpolation == INTER_CUBIC) && !(interpolation == INTER_LINEAR && is_area_fast && iscale_x == 2 && iscale_y == 2 && depth == CV_8U) && mode >= 0 && (cn == 1 || cn == 3 || cn == 4) && (depth == CV_16U || depth == CV_16S || depth == CV_32F || @@ -4576,7 +4576,7 @@ static bool ocl_remap(InputArray _src, OutputArray _dst, InputArray _map1, Input #endif -#if IPP_VERSION_X100 >= 0 && !defined HAVE_IPP_ICV_ONLY && 0 +#if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY && IPP_DISABLE_BLOCK typedef IppStatus (CV_STDCALL * ippiRemap)(const void * pSrc, IppiSize srcSize, int srcStep, IppiRect srcRoi, const Ipp32f* pxMap, int xMapStep, const Ipp32f* pyMap, int yMapStep, @@ -4684,7 +4684,7 @@ void cv::remap( InputArray _src, OutputArray _dst, int type = src.type(), depth = CV_MAT_DEPTH(type); -#if IPP_VERSION_X100 >= 0 && !defined HAVE_IPP_ICV_ONLY && 0 +#if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY && IPP_DISABLE_BLOCK CV_IPP_CHECK() { if ((interpolation == INTER_LINEAR || interpolation == INTER_CUBIC || interpolation == INTER_NEAREST) && @@ -5410,7 +5410,7 @@ private: }; -#if defined (HAVE_IPP) && IPP_VERSION_MAJOR * 100 + IPP_VERSION_MINOR >= 801 && 0 +#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK class IPPWarpAffineInvoker : public ParallelLoopBody { @@ -5615,7 +5615,7 @@ void cv::warpAffine( InputArray _src, OutputArray _dst, const int AB_BITS = MAX(10, (int)INTER_BITS); const int AB_SCALE = 1 << AB_BITS; -#if defined (HAVE_IPP) && IPP_VERSION_MAJOR * 100 + IPP_VERSION_MINOR >= 801 && 0 +#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK CV_IPP_CHECK() { int type = src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); @@ -6039,7 +6039,7 @@ private: }; -#if defined (HAVE_IPP) && IPP_VERSION_MAJOR * 100 + IPP_VERSION_MINOR >= 801 && 0 +#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK class IPPWarpPerspectiveInvoker : public ParallelLoopBody { @@ -6124,7 +6124,7 @@ void cv::warpPerspective( InputArray _src, OutputArray _dst, InputArray _M0, #endif -#if defined (HAVE_IPP) && IPP_VERSION_MAJOR * 100 + IPP_VERSION_MINOR >= 801 && 0 +#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK CV_IPP_CHECK() { int type = src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); diff --git a/modules/imgproc/src/moments.cpp b/modules/imgproc/src/moments.cpp index 3b86be234..31da20110 100644 --- a/modules/imgproc/src/moments.cpp +++ b/modules/imgproc/src/moments.cpp @@ -577,7 +577,7 @@ cv::Moments cv::moments( InputArray _src, bool binary ) if( cn > 1 ) CV_Error( CV_StsBadArg, "Invalid image type (must be single-channel)" ); -#if IPP_VERSION_X100 >= 801 && 0 +#if IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK CV_IPP_CHECK() { if (!binary) diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index 822df8e47..dfb9d4755 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1140,7 +1140,7 @@ private: static bool ipp_MorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kernel, const Size& ksize, const Point &anchor, bool rectKernel) { -#if IPP_VERSION_X100 >= 801 +#if IPP_VERSION_X100 >= 810 int type = src.type(); const Mat* _src = &src; Mat temp; @@ -1715,7 +1715,7 @@ static void morphOp( int op, InputArray _src, OutputArray _dst, iterations = 1; } - CV_IPP_RUN(IPP_VERSION_X100 >= 801, ipp_MorphOp(op, _src, _dst, kernel, anchor, iterations, borderType, borderValue)) + CV_IPP_RUN(IPP_VERSION_X100 >= 810, ipp_MorphOp(op, _src, _dst, kernel, anchor, iterations, borderType, borderValue)) Mat src = _src.getMat(); _dst.create( src.size(), src.type() ); diff --git a/modules/imgproc/src/pyramids.cpp b/modules/imgproc/src/pyramids.cpp index a0d2d51c5..d9395e0b5 100644 --- a/modules/imgproc/src/pyramids.cpp +++ b/modules/imgproc/src/pyramids.cpp @@ -1171,7 +1171,7 @@ namespace cv { static bool ipp_pyrdown( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType ) { -#if IPP_VERSION_X100 >= 801 && 0 +#if IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK Size dsz = _dsz.area() == 0 ? Size((_src.cols() + 1)/2, (_src.rows() + 1)/2) : _dsz; bool isolated = (borderType & BORDER_ISOLATED) != 0; int borderTypeNI = borderType & ~BORDER_ISOLATED; @@ -1276,7 +1276,7 @@ namespace cv { static bool ipp_pyrup( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType ) { -#if IPP_VERSION_X100 >= 801 && 0 +#if IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK Size sz = _src.dims() <= 2 ? _src.size() : Size(); Size dsz = _dsz.area() == 0 ? Size(_src.cols()*2, _src.rows()*2) : _dsz; @@ -1380,7 +1380,7 @@ namespace cv { static bool ipp_buildpyramid( InputArray _src, OutputArrayOfArrays _dst, int maxlevel, int borderType ) { -#if IPP_VERSION_X100 >= 801 && 0 +#if IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK Mat src = _src.getMat(); _dst.create( maxlevel + 1, 1, 0 ); _dst.getMatRef(0) = src; @@ -1508,7 +1508,7 @@ void cv::buildPyramid( InputArray _src, OutputArrayOfArrays _dst, int maxlevel, int i=1; - CV_IPP_RUN(((IPP_VERSION_X100 >= 801 && 0) && ((borderType & ~BORDER_ISOLATED) == BORDER_DEFAULT && (!_src.isSubmatrix() || ((borderType & BORDER_ISOLATED) != 0)))), + CV_IPP_RUN(((IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK) && ((borderType & ~BORDER_ISOLATED) == BORDER_DEFAULT && (!_src.isSubmatrix() || ((borderType & BORDER_ISOLATED) != 0)))), ipp_buildpyramid( _src, _dst, maxlevel, borderType)); for( ; i <= maxlevel; i++ ) diff --git a/modules/imgproc/src/samplers.cpp b/modules/imgproc/src/samplers.cpp index c592138ea..c89bd32e0 100644 --- a/modules/imgproc/src/samplers.cpp +++ b/modules/imgproc/src/samplers.cpp @@ -374,7 +374,7 @@ void cv::getRectSubPix( InputArray _image, Size patchSize, Point2f center, _patch.create(patchSize, CV_MAKETYPE(ddepth, cn)); Mat patch = _patch.getMat(); -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) CV_IPP_CHECK() { typedef IppStatus (CV_STDCALL *ippiGetRectSubPixFunc)( const void* src, int src_step, diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 104228b47..19b0bf2d2 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -1668,7 +1668,7 @@ static bool ipp_GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, double sigma1, double sigma2, int borderType ) { -#if IPP_VERSION_X100 >= 801 +#if IPP_VERSION_X100 >= 810 int type = _src.type(); Size size = _src.size(); @@ -2707,7 +2707,7 @@ namespace cv { static bool ipp_medianFilter( InputArray _src0, OutputArray _dst, int ksize ) { -#if IPP_VERSION_X100 >= 801 +#if IPP_VERSION_X100 >= 810 Mat src0 = _src0.getMat(); _dst.create( src0.size(), src0.type() ); Mat dst = _dst.getMat(); @@ -2778,7 +2778,7 @@ void cv::medianBlur( InputArray _src0, OutputArray _dst, int ksize ) _dst.create( src0.size(), src0.type() ); Mat dst = _dst.getMat(); - CV_IPP_RUN(IPP_VERSION_X100 >= 801 && ksize <= 5, ipp_medianFilter(_src0,_dst, ksize)); + CV_IPP_RUN(IPP_VERSION_X100 >= 810 && ksize <= 5, ipp_medianFilter(_src0,_dst, ksize)); #ifdef HAVE_TEGRA_OPTIMIZATION if (tegra::useTegra() && tegra::medianBlur(src0, dst, ksize)) @@ -2996,7 +2996,7 @@ private: float *space_weight, *color_weight; }; -#if defined (HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && 0 +#if defined (HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_DISABLE_BLOCK class IPPBilateralFilter_8u_Invoker : public ParallelLoopBody { @@ -3166,7 +3166,7 @@ bilateralFilter_8u( const Mat& src, Mat& dst, int d, Mat temp; copyMakeBorder( src, temp, radius, radius, radius, radius, borderType ); -#if defined HAVE_IPP && (IPP_VERSION_MAJOR >= 7) && 0 +#if defined HAVE_IPP && (IPP_VERSION_X100 >= 700) && IPP_DISABLE_BLOCK CV_IPP_CHECK() { if( cn == 1 ) diff --git a/modules/imgproc/src/thresh.cpp b/modules/imgproc/src/thresh.cpp index 66665f978..3aaf38bd1 100644 --- a/modules/imgproc/src/thresh.cpp +++ b/modules/imgproc/src/thresh.cpp @@ -907,7 +907,7 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type ) #ifdef HAVE_IPP static bool ipp_getThreshVal_Otsu_8u( const unsigned char* _src, int step, Size size, unsigned char &thresh) { -#if IPP_VERSION_X100 >= 801 && !HAVE_ICV +#if IPP_VERSION_X100 >= 810 && !HAVE_ICV int ippStatus = -1; IppiSize srcSize = { size.width, size.height }; CV_SUPPRESS_DEPRECATED_START @@ -937,7 +937,7 @@ getThreshVal_Otsu_8u( const Mat& _src ) #ifdef HAVE_IPP unsigned char thresh; - CV_IPP_RUN(IPP_VERSION_X100 >= 801 && !HAVE_ICV, ipp_getThreshVal_Otsu_8u(_src.ptr(), step, size, thresh), thresh); + CV_IPP_RUN(IPP_VERSION_X100 >= 810 && !HAVE_ICV, ipp_getThreshVal_Otsu_8u(_src.ptr(), step, size, thresh), thresh); #endif const int N = 256; diff --git a/modules/imgproc/test/ocl/test_color.cpp b/modules/imgproc/test/ocl/test_color.cpp index 6e117cdd5..160c03534 100644 --- a/modules/imgproc/test/ocl/test_color.cpp +++ b/modules/imgproc/test/ocl/test_color.cpp @@ -155,7 +155,7 @@ OCL_TEST_P(CvtColor, YCrCb2BGRA) { performTest(3, 4, CVTCODE(YCrCb2BGR)); } // RGB <-> XYZ -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP #define IPP_EPS depth <= CV_32S ? 1 : 5e-5 #else #define IPP_EPS 1e-3 @@ -175,7 +175,7 @@ OCL_TEST_P(CvtColor, XYZ2BGRA) { performTest(3, 4, CVTCODE(XYZ2BGR), IPP_EPS); } // RGB <-> HSV -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP #define IPP_EPS depth <= CV_32S ? 1 : 4e-5 #else #define IPP_EPS 1e-3 @@ -207,7 +207,7 @@ OCL_TEST_P(CvtColor8u32f, HSV2BGRA_FULL) { performTest(3, 4, CVTCODE(HSV2BGR_FUL // RGB <-> HLS -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP #define IPP_EPS depth == CV_8U ? 2 : 1e-3 #else #define IPP_EPS depth == CV_8U ? 1 : 1e-3 @@ -269,7 +269,7 @@ OCL_TEST_P(CvtColor8u, GRAY2BGR555) { performTest(1, 2, CVTCODE(GRAY2BGR555)); } // RGBA <-> mRGBA -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP #define IPP_EPS depth <= CV_32S ? 1 : 1e-3 #else #define IPP_EPS 1e-3 diff --git a/modules/imgproc/test/test_houghLines.cpp b/modules/imgproc/test/test_houghLines.cpp index fd9783b31..cf6dc87d9 100644 --- a/modules/imgproc/test/test_houghLines.cpp +++ b/modules/imgproc/test/test_houghLines.cpp @@ -189,7 +189,7 @@ void BaseHoughLineTest::run_test(int type) else if (type == PROBABILISTIC) count = countMatIntersection(exp_lines, lines, 1e-4f, 0.f); -#if (0 && defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 801) +#if defined HAVE_IPP && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 810 && IPP_DISABLED_BLOCK EXPECT_GE( count, (int) (exp_lines.total() * 0.8) ); #else EXPECT_EQ( count, (int) exp_lines.total()); From fdbed4a4731e1e089ce6a4d9ea957a5a4718b96f Mon Sep 17 00:00:00 2001 From: Balint Cristian Date: Sat, 26 Sep 2015 04:43:07 +0300 Subject: [PATCH 091/156] Speedup AGAST nonmax-suppression. --- modules/features2d/src/agast.cpp | 50 ++++++++++++++++---------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/modules/features2d/src/agast.cpp b/modules/features2d/src/agast.cpp index cd58ac278..95c74fbee 100644 --- a/modules/features2d/src/agast.cpp +++ b/modules/features2d/src/agast.cpp @@ -7511,19 +7511,22 @@ Ptr AgastFeatureDetector::create( int threshold, bool nonm void AGAST(InputArray _img, std::vector& keypoints, int threshold, bool nonmax_suppression, int type) { + + std::vector kpts; + // detect switch(type) { case AgastFeatureDetector::AGAST_5_8: - AGAST_5_8(_img, keypoints, threshold); + AGAST_5_8(_img, kpts, threshold); break; case AgastFeatureDetector::AGAST_7_12d: - AGAST_7_12d(_img, keypoints, threshold); + AGAST_7_12d(_img, kpts, threshold); break; case AgastFeatureDetector::AGAST_7_12s: - AGAST_7_12s(_img, keypoints, threshold); + AGAST_7_12s(_img, kpts, threshold); break; case AgastFeatureDetector::OAST_9_16: - OAST_9_16(_img, keypoints, threshold); + OAST_9_16(_img, kpts, threshold); break; } @@ -7534,7 +7537,7 @@ void AGAST(InputArray _img, std::vector& keypoints, int threshold, boo makeAgastOffsets(pixel_, (int)img.step, type); std::vector::iterator kpt; - for(kpt = keypoints.begin(); kpt != keypoints.end(); kpt++) + for(kpt = kpts.begin(); kpt != kpts.end(); kpt++) { switch(type) { case AgastFeatureDetector::AGAST_5_8: @@ -7555,20 +7558,21 @@ void AGAST(InputArray _img, std::vector& keypoints, int threshold, boo break; } } + // suppression if(nonmax_suppression) { size_t j; size_t curr_idx; size_t lastRow = 0, next_lastRow = 0; - size_t num_Corners = keypoints.size(); + size_t num_Corners = kpts.size(); size_t lastRowCorner_ind = 0, next_lastRowCorner_ind = 0; std::vector nmsFlags; std::vector::iterator currCorner_nms; std::vector::const_iterator currCorner; - currCorner = keypoints.begin(); + currCorner = kpts.begin(); nmsFlags.resize((int)num_Corners); @@ -7593,11 +7597,11 @@ void AGAST(InputArray _img, std::vector& keypoints, int threshold, boo if(lastRow + 1 == currCorner->pt.y) { // find the corner above the current one - while( (keypoints[lastRowCorner_ind].pt.x < currCorner->pt.x) - && (keypoints[lastRowCorner_ind].pt.y == lastRow) ) + while( (kpts[lastRowCorner_ind].pt.x < currCorner->pt.x) + && (kpts[lastRowCorner_ind].pt.y == lastRow) ) lastRowCorner_ind++; - if( (keypoints[lastRowCorner_ind].pt.x == currCorner->pt.x) + if( (kpts[lastRowCorner_ind].pt.x == currCorner->pt.x) && (lastRowCorner_ind != curr_idx) ) { size_t w = lastRowCorner_ind; @@ -7605,7 +7609,7 @@ void AGAST(InputArray _img, std::vector& keypoints, int threshold, boo while(nmsFlags[w] != -1) w = nmsFlags[w]; - if(keypoints[curr_idx].response < keypoints[w].response) + if(kpts[curr_idx].response < kpts[w].response) nmsFlags[curr_idx] = (int)w; else nmsFlags[w] = (int)curr_idx; @@ -7614,8 +7618,8 @@ void AGAST(InputArray _img, std::vector& keypoints, int threshold, boo // check left t = (int)curr_idx - 1; - if( (curr_idx != 0) && (keypoints[t].pt.y == currCorner->pt.y) - && (keypoints[t].pt.x + 1 == currCorner->pt.x) ) + if( (curr_idx != 0) && (kpts[t].pt.y == currCorner->pt.y) + && (kpts[t].pt.x + 1 == currCorner->pt.x) ) { int currCornerMaxAbove_ind = nmsFlags[curr_idx]; // find the maximum in that area @@ -7626,7 +7630,7 @@ void AGAST(InputArray _img, std::vector& keypoints, int threshold, boo { if((size_t)t != curr_idx) { - if ( keypoints[curr_idx].response < keypoints[t].response ) + if ( kpts[curr_idx].response < kpts[t].response ) nmsFlags[curr_idx] = t; else nmsFlags[t] = (int)curr_idx; @@ -7636,7 +7640,7 @@ void AGAST(InputArray _img, std::vector& keypoints, int threshold, boo { if(t != currCornerMaxAbove_ind) { - if(keypoints[currCornerMaxAbove_ind].response < keypoints[t].response) + if(kpts[currCornerMaxAbove_ind].response < kpts[t].response) { nmsFlags[currCornerMaxAbove_ind] = t; nmsFlags[curr_idx] = t; @@ -7652,19 +7656,15 @@ void AGAST(InputArray _img, std::vector& keypoints, int threshold, boo currCorner++; } - // marks non-maximum corners + // collecting maximum corners for(curr_idx = 0; curr_idx < num_Corners; curr_idx++) { - if (nmsFlags[curr_idx] != -1) - keypoints[curr_idx].response = -1; - } - - // erase non-maximum corners - for (j = keypoints.size(); j > 0; j--) - { - if (keypoints[j - 1].response == -1) - keypoints.erase(keypoints.begin() + j - 1 ); + if (nmsFlags[curr_idx] == -1) + keypoints.push_back(kpts[curr_idx]); } + } else + { + keypoints = kpts; } } From 1bd18836d72d4e15882c36bfa0a36ad3dbc2ab5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kau=C3=AA=20de=20Moraes=20Vestena?= Date: Sun, 27 Sep 2015 15:53:30 -0300 Subject: [PATCH 092/156] little fixes and correction of a conceptual error Previously, there's no way to the user see the found corners, i've changed that. In a cout, are write that: "average reprojection err = " But it isn't a "reprojection error" at all, it is a mean of each EPIPOLAR error, wich occur when the product x' * F * x is not equal to zero. (x and x' are the same points in the right and left scene) (the RMS that explain the average absolute reprojection error is given by the return of the stereoCalibrate() function) At least, i think it's interesting to initialize the camera matrices before. Thank you all for this amazing code. Apologize my weak english. --- samples/cpp/stereo_calib.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/cpp/stereo_calib.cpp b/samples/cpp/stereo_calib.cpp index f25a3e139..12ed3ef1e 100644 --- a/samples/cpp/stereo_calib.cpp +++ b/samples/cpp/stereo_calib.cpp @@ -56,7 +56,7 @@ static int print_help() static void -StereoCalib(const vector& imagelist, Size boardSize, bool useCalibrated=true, bool showRectified=true) +StereoCalib(const vector& imagelist, Size boardSize,bool displayCorners = false, bool useCalibrated=true, bool showRectified=true) { if( imagelist.size() % 2 != 0 ) { @@ -64,7 +64,6 @@ StereoCalib(const vector& imagelist, Size boardSize, bool useCalibrated= return; } - bool displayCorners = false;//true; const int maxScale = 2; const float squareSize = 1.f; // Set this to your actual square size // ARRAY AND VECTOR STORAGE: @@ -165,8 +164,8 @@ StereoCalib(const vector& imagelist, Size boardSize, bool useCalibrated= cout << "Running stereo calibration ...\n"; Mat cameraMatrix[2], distCoeffs[2]; - cameraMatrix[0] = Mat::eye(3, 3, CV_64F); - cameraMatrix[1] = Mat::eye(3, 3, CV_64F); + cameraMatrix[0] = initCameraMatrix2D(objectPoints,imagePoints[0],imageSize,0); + cameraMatrix[1] = initCameraMatrix2D(objectPoints,imagePoints[1],imageSize,0); Mat R, T, E, F; double rms = stereoCalibrate(objectPoints, imagePoints[0], imagePoints[1], @@ -175,6 +174,7 @@ StereoCalib(const vector& imagelist, Size boardSize, bool useCalibrated= imageSize, R, T, E, F, CALIB_FIX_ASPECT_RATIO + CALIB_ZERO_TANGENT_DIST + + CALIB_USE_INTRINSIC_GUESS + CALIB_SAME_FOCAL_LENGTH + CALIB_RATIONAL_MODEL + CALIB_FIX_K3 + CALIB_FIX_K4 + CALIB_FIX_K5, @@ -209,7 +209,7 @@ StereoCalib(const vector& imagelist, Size boardSize, bool useCalibrated= } npoints += npt; } - cout << "average reprojection err = " << err/npoints << endl; + cout << "average epipolar err = " << err/npoints << endl; // save intrinsic parameters FileStorage fs("../data/intrinsics.yml", FileStorage::WRITE); @@ -399,6 +399,6 @@ int main(int argc, char** argv) return print_help(); } - StereoCalib(imagelist, boardSize, true, showRectified); + StereoCalib(imagelist, boardSize,false, true, showRectified); return 0; } From 7c226ed7a298efeff33d66822046f817551a6dd3 Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Thu, 24 Sep 2015 22:51:11 +0300 Subject: [PATCH 093/156] adding new flags to imread to load image reduced --- .../imgcodecs/include/opencv2/imgcodecs.hpp | 26 +++++----- modules/imgcodecs/src/loadsave.cpp | 47 +++++++------------ 2 files changed, 30 insertions(+), 43 deletions(-) diff --git a/modules/imgcodecs/include/opencv2/imgcodecs.hpp b/modules/imgcodecs/include/opencv2/imgcodecs.hpp index e21db8e1e..678861bfe 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs.hpp +++ b/modules/imgcodecs/include/opencv2/imgcodecs.hpp @@ -62,12 +62,18 @@ namespace cv //! Imread flags enum ImreadModes { - IMREAD_UNCHANGED = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped). - IMREAD_GRAYSCALE = 0, //!< If set, always convert image to the single channel grayscale image. - IMREAD_COLOR = 1, //!< If set, always convert image to the 3 channel BGR color image. - IMREAD_ANYDEPTH = 2, //!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit. - IMREAD_ANYCOLOR = 4, //!< If set, the image is read in any possible color format. - IMREAD_LOAD_GDAL = 8 //!< If set, use the gdal driver for loading the image. + IMREAD_UNCHANGED = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped). + IMREAD_GRAYSCALE = 0, //!< If set, always convert image to the single channel grayscale image. + IMREAD_COLOR = 1, //!< If set, always convert image to the 3 channel BGR color image. + IMREAD_ANYDEPTH = 2, //!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit. + IMREAD_ANYCOLOR = 4, //!< If set, the image is read in any possible color format. + IMREAD_LOAD_GDAL = 8, //!< If set, use the gdal driver for loading the image. + IMREAD_GRAYSCALE_REDUCED_2 = 16, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/2. + IMREAD_COLOR_REDUCED_2 = 17, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/2. + IMREAD_GRAYSCALE_REDUCED_4 = 32, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/4. + IMREAD_COLOR_REDUCED_4 = 33, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4. + IMREAD_GRAYSCALE_REDUCED_8 = 64, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/8. + IMREAD_COLOR_REDUCED_8 = 65 //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8. }; //! Imwrite flags @@ -133,14 +139,6 @@ returns an empty matrix ( Mat::data==NULL ). Currently, the following file forma */ CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR ); -/** @brief Loads and resizes down an image from a file. -@anchor imread_reduced -@param filename Name of file to be loaded. -@param flags Flag that can take values of @ref cv::ImreadModes -@param scale_denom - */ -CV_EXPORTS_W Mat imread_reduced( const String& filename, int flags = IMREAD_COLOR, int scale_denom=1 ); - /** @brief Loads a multi-page image from a file. (see imread for details.) @param filename Name of file to be loaded. diff --git a/modules/imgcodecs/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp index a7bf46f42..336777aee 100644 --- a/modules/imgcodecs/src/loadsave.cpp +++ b/modules/imgcodecs/src/loadsave.cpp @@ -238,7 +238,7 @@ enum { LOAD_CVMAT=0, LOAD_IMAGE=1, LOAD_MAT=2 }; * */ static void* -imread_( const String& filename, int flags, int hdrtype, Mat* mat=0, int scale_denom=1 ) +imread_( const String& filename, int flags, int hdrtype, Mat* mat=0 ) { IplImage* image = 0; CvMat *matrix = 0; @@ -252,7 +252,7 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0, int scale_d decoder = GdalDecoder().newDecoder(); }else{ #endif - decoder = findDecoder(filename); + decoder = findDecoder( filename ); #ifdef HAVE_GDAL } #endif @@ -262,11 +262,22 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0, int scale_d return 0; } + int scale_denom = 1; + if( flags > IMREAD_LOAD_GDAL ) + { + if( flags & IMREAD_GRAYSCALE_REDUCED_2 ) + scale_denom = 2; + else if( flags & IMREAD_GRAYSCALE_REDUCED_4 ) + scale_denom = 4; + else if( flags & IMREAD_GRAYSCALE_REDUCED_8 ) + scale_denom = 8; + } + /// set the scale_denom in the driver decoder->setScale( scale_denom ); /// set the filename in the driver - decoder->setSource(filename); + decoder->setSource( filename ); // read the header to make sure it succeeds if( !decoder->readHeader() ) @@ -296,7 +307,7 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0, int scale_d if( hdrtype == LOAD_CVMAT ) { matrix = cvCreateMat( size.height, size.width, type ); - temp = cvarrToMat(matrix); + temp = cvarrToMat( matrix ); } else { @@ -307,7 +318,7 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0, int scale_d else { image = cvCreateImage( size, cvIplDepth(type), CV_MAT_CN(type) ); - temp = cvarrToMat(image); + temp = cvarrToMat( image ); } // read the image data @@ -320,10 +331,9 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0, int scale_d return 0; } - int testdecoder = decoder->setScale( scale_denom ); // if decoder is JpegDecoder then testdecoder will be 1 - if( (scale_denom > 1 ) & ( testdecoder > 1 ) ) + if( decoder->setScale( scale_denom ) > 1 ) // if decoder is JpegDecoder then decoder->setScale always returns 1 { - resize(*mat,*mat,Size(size.width/scale_denom,size.height/scale_denom)); + resize( *mat, *mat, Size( size.width / scale_denom, size.height / scale_denom ) ); } return hdrtype == LOAD_CVMAT ? (void*)matrix : @@ -421,27 +431,6 @@ Mat imread( const String& filename, int flags ) return img; } -/** - * Read an image and resize it - * - * This function merely calls the actual implementation above and returns itself. - * - * @param[in] filename File to load - * @param[in] flags Flags you wish to set. - * @param[in] scale_denom Scale value -*/ -Mat imread_reduced( const String& filename, int flags, int scale_denom ) -{ - /// create the basic container - Mat img; - - /// load the data - imread_( filename, flags, LOAD_MAT, &img, scale_denom ); - - /// return a reference to the data - return img; -} - /** * Read a multi-page image * From 75c7917643b31e6ce10d22a3fa84299247c4e735 Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Tue, 29 Sep 2015 17:24:18 +0300 Subject: [PATCH 094/156] IPP_VERSION_X100 was changed to: IPP_VERSION_MAJOR * 100 + IPP_VERSION_MINOR*10 + IPP_VERSION_UPDATE to manage changes between updates more easily. IPP_DISABLE_BLOCK was added to ease tracking of disabled IPP functions; --- modules/core/src/stat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 999640d94..a1ceb5702 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -2701,7 +2701,7 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) return true; } } -#if IPP_DISABLED_BLOCK +#if IPP_DISABLE_BLOCK typedef IppStatus (CV_STDCALL* ippiMaskNormFuncC3)(const void *, int, const void *, int, IppiSize, int, Ipp64f *); ippiMaskNormFuncC3 ippFuncC3 = normType == NORM_INF ? From 62854dcc0d8b6cdc5650d00c3f3df5f5c541e616 Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Fri, 25 Sep 2015 17:56:19 +0300 Subject: [PATCH 095/156] Enables support of IPP 9.0.0; HAVE_IPP_ICV_ONLY will be undefined if OpenCV was linked against ICV packet from IPP9 or greater. ICV9+ packets will be aligned with IPP in OpenCV APIs This will ease code management between IPP and ICV --- modules/core/include/opencv2/core/private.hpp | 5 + modules/core/src/dxt.cpp | 189 +++++++++++++++--- modules/core/src/stat.cpp | 32 ++- modules/imgproc/src/canny.cpp | 6 + modules/imgproc/src/color.cpp | 2 + modules/imgproc/src/deriv.cpp | 29 +++ modules/imgproc/src/histogram.cpp | 61 +++++- modules/imgproc/src/morph.cpp | 93 ++++++--- modules/objdetect/src/haar.cpp | 4 + 9 files changed, 352 insertions(+), 69 deletions(-) diff --git a/modules/core/include/opencv2/core/private.hpp b/modules/core/include/opencv2/core/private.hpp index 9f0f5701f..28f21d4d8 100644 --- a/modules/core/include/opencv2/core/private.hpp +++ b/modules/core/include/opencv2/core/private.hpp @@ -245,6 +245,11 @@ static inline IppDataType ippiGetDataType(int depth) #define IPP_VERSION_X100 0 #endif +// There shoud be no API difference in OpenCV between ICV and IPP since 9.0 +#if (defined HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 900 +#undef HAVE_IPP_ICV_ONLY +#endif + #ifdef HAVE_IPP_ICV_ONLY #define HAVE_ICV 1 #else diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index f6709e943..720898c43 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -3318,28 +3318,102 @@ static void IDCT_64f(const double* src, int src_step, double* dft_src, double* d } +#ifdef HAVE_IPP namespace cv { -#if defined HAVE_IPP && IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 900 +typedef IppStatus (CV_STDCALL * ippiDCTFunc)(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep, const void* pDCTSpec, Ipp8u* pBuffer); +typedef IppStatus (CV_STDCALL * ippiDCTInit)(void* pDCTSpec, IppiSize roiSize, Ipp8u* pMemInit ); +typedef IppStatus (CV_STDCALL * ippiDCTGetSize)(IppiSize roiSize, int* pSizeSpec, int* pSizeInit, int* pSizeBuf); +#elif IPP_VERSION_X100 >= 700 typedef IppStatus (CV_STDCALL * ippiDCTFunc)(const Ipp32f*, int, Ipp32f*, int, const void*, Ipp8u*); typedef IppStatus (CV_STDCALL * ippiDCTInitAlloc)(void**, IppiSize, IppHintAlgorithm); typedef IppStatus (CV_STDCALL * ippiDCTFree)(void* pDCTSpec); typedef IppStatus (CV_STDCALL * ippiDCTGetBufSize)(const void*, int*); +#endif -template class DctIPPLoop_Invoker : public ParallelLoopBody { public: - - DctIPPLoop_Invoker(const Mat& _src, Mat& _dst, const Dct* _ippidct, bool _inv, bool *_ok) : - ParallelLoopBody(), src(&_src), dst(&_dst), ippidct(_ippidct), inv(_inv), ok(_ok) + DctIPPLoop_Invoker(const Mat& _src, Mat& _dst, bool _inv, bool *_ok) : + ParallelLoopBody(), src(&_src), dst(&_dst), inv(_inv), ok(_ok) { *ok = true; } virtual void operator()(const Range& range) const { + if(*ok == false) + return; + +#if IPP_VERSION_X100 >= 900 + IppiSize srcRoiSize = {src->cols, 1}; + + int specSize = 0; + int initSize = 0; + int bufferSize = 0; + + Ipp8u* pDCTSpec = NULL; + Ipp8u* pBuffer = NULL; + Ipp8u* pInitBuf = NULL; + + #define IPP_RETURN \ + if(pDCTSpec) \ + ippFree(pDCTSpec); \ + if(pBuffer) \ + ippFree(pBuffer); \ + if(pInitBuf) \ + ippFree(pInitBuf); \ + return; + + ippiDCTFunc ippDctFun = inv ? (ippiDCTFunc)ippiDCTInv_32f_C1R : (ippiDCTFunc)ippiDCTFwd_32f_C1R; + ippiDCTInit ippDctInit = inv ? (ippiDCTInit)ippiDCTInvInit_32f : (ippiDCTInit)ippiDCTFwdInit_32f; + ippiDCTGetSize ippDctGetSize = inv ? (ippiDCTGetSize)ippiDCTInvGetSize_32f : (ippiDCTGetSize)ippiDCTFwdGetSize_32f; + + if(ippDctGetSize(srcRoiSize, &specSize, &initSize, &bufferSize) < 0) + { + *ok = false; + return; + } + + pDCTSpec = (Ipp8u*)ippMalloc(specSize); + if(!pDCTSpec && specSize) + { + *ok = false; + return; + } + + pBuffer = (Ipp8u*)ippMalloc(bufferSize); + if(!pBuffer && bufferSize) + { + *ok = false; + IPP_RETURN + } + pInitBuf = (Ipp8u*)ippMalloc(initSize); + if(!pInitBuf && initSize) + { + *ok = false; + IPP_RETURN + } + + if(ippDctInit(pDCTSpec, srcRoiSize, pInitBuf) < 0) + { + *ok = false; + IPP_RETURN + } + + for(int i = range.start; i < range.end; ++i) + { + if(ippDctFun(src->ptr(i), (int)src->step,dst->ptr(i), (int)dst->step, pDCTSpec, pBuffer) < 0) + { + *ok = false; + IPP_RETURN + } + } + IPP_RETURN +#undef IPP_RETURN +#elif IPP_VERSION_X100 >= 700 void* pDCTSpec; AutoBuffer buf; uchar* pBuffer = 0; @@ -3349,6 +3423,7 @@ public: CV_SUPPRESS_DEPRECATED_START + ippiDCTFunc ippDctFun = inv ? (ippiDCTFunc)ippiDCTInv_32f_C1R : (ippiDCTFunc)ippiDCTFwd_32f_C1R; ippiDCTInitAlloc ippInitAlloc = inv ? (ippiDCTInitAlloc)ippiDCTInvInitAlloc_32f : (ippiDCTInitAlloc)ippiDCTFwdInitAlloc_32f; ippiDCTFree ippFree = inv ? (ippiDCTFree)ippiDCTInvFree_32f : (ippiDCTFree)ippiDCTFwdFree_32f; ippiDCTGetBufSize ippGetBufSize = inv ? (ippiDCTGetBufSize)ippiDCTInvGetBufSize_32f : (ippiDCTGetBufSize)ippiDCTFwdGetBufSize_32f; @@ -3359,8 +3434,13 @@ public: pBuffer = (uchar*)buf; for( int i = range.start; i < range.end; ++i) - if(!(*ippidct)(src->ptr(i), (int)src->step,dst->ptr(i), (int)dst->step, pDCTSpec, (Ipp8u*)pBuffer)) + { + if(ippDctFun(src->ptr(i), (int)src->step,dst->ptr(i), (int)dst->step, pDCTSpec, (Ipp8u*)pBuffer) < 0) + { *ok = false; + break; + } + } } else *ok = false; @@ -3369,44 +3449,91 @@ public: ippFree(pDCTSpec); CV_SUPPRESS_DEPRECATED_END +#else + CV_UNUSED(range); + *ok = false; +#endif } private: const Mat* src; Mat* dst; - const Dct* ippidct; bool inv; bool *ok; }; -template -bool DctIPPLoop(const Mat& src, Mat& dst, const Dct& ippidct, bool inv) +static bool DctIPPLoop(const Mat& src, Mat& dst, bool inv) { bool ok; - parallel_for_(Range(0, src.rows), DctIPPLoop_Invoker(src, dst, &ippidct, inv, &ok), src.rows/(double)(1<<4) ); + parallel_for_(Range(0, src.rows), DctIPPLoop_Invoker(src, dst, inv, &ok), src.rows/(double)(1<<4) ); return ok; } -struct IPPDCTFunctor -{ - IPPDCTFunctor(ippiDCTFunc _func) : func(_func){} - - bool operator()(const Ipp32f* src, int srcStep, Ipp32f* dst, int dstStep, const void* pDCTSpec, Ipp8u* pBuffer) const - { - return func ? func(src, srcStep, dst, dstStep, pDCTSpec, pBuffer) >= 0 : false; - } -private: - ippiDCTFunc func; -}; - static bool ippi_DCT_32f(const Mat& src, Mat& dst, bool inv, bool row) { - ippiDCTFunc ippFunc = inv ? (ippiDCTFunc)ippiDCTInv_32f_C1R : (ippiDCTFunc)ippiDCTFwd_32f_C1R ; - - if (row) - return(DctIPPLoop(src,dst,IPPDCTFunctor(ippFunc),inv)); + if(row) + return DctIPPLoop(src, dst, inv); else { +#if IPP_VERSION_X100 >= 900 + IppiSize srcRoiSize = {src.cols, src.rows}; + + int specSize = 0; + int initSize = 0; + int bufferSize = 0; + + Ipp8u* pDCTSpec = NULL; + Ipp8u* pBuffer = NULL; + Ipp8u* pInitBuf = NULL; + + #define IPP_RELEASE \ + if(pDCTSpec) \ + ippFree(pDCTSpec); \ + if(pBuffer) \ + ippFree(pBuffer); \ + if(pInitBuf) \ + ippFree(pInitBuf); \ + + ippiDCTFunc ippDctFun = inv ? (ippiDCTFunc)ippiDCTInv_32f_C1R : (ippiDCTFunc)ippiDCTFwd_32f_C1R; + ippiDCTInit ippDctInit = inv ? (ippiDCTInit)ippiDCTInvInit_32f : (ippiDCTInit)ippiDCTFwdInit_32f; + ippiDCTGetSize ippDctGetSize = inv ? (ippiDCTGetSize)ippiDCTInvGetSize_32f : (ippiDCTGetSize)ippiDCTFwdGetSize_32f; + + if(ippDctGetSize(srcRoiSize, &specSize, &initSize, &bufferSize) < 0) + return false; + + pDCTSpec = (Ipp8u*)ippMalloc(specSize); + if(!pDCTSpec && specSize) + return false; + + pBuffer = (Ipp8u*)ippMalloc(bufferSize); + if(!pBuffer && bufferSize) + { + IPP_RELEASE + return false; + } + pInitBuf = (Ipp8u*)ippMalloc(initSize); + if(!pInitBuf && initSize) + { + IPP_RELEASE + return false; + } + + if(ippDctInit(pDCTSpec, srcRoiSize, pInitBuf) < 0) + { + IPP_RELEASE + return false; + } + + if(ippDctFun(src.ptr(), (int)src.step,dst.ptr(), (int)dst.step, pDCTSpec, pBuffer) < 0) + { + IPP_RELEASE + return false; + } + + IPP_RELEASE + return true; +#undef IPP_RELEASE +#elif IPP_VERSION_X100 >= 700 IppStatus status; void* pDCTSpec; AutoBuffer buf; @@ -3417,6 +3544,7 @@ static bool ippi_DCT_32f(const Mat& src, Mat& dst, bool inv, bool row) CV_SUPPRESS_DEPRECATED_START + ippiDCTFunc ippDctFun = inv ? (ippiDCTFunc)ippiDCTInv_32f_C1R : (ippiDCTFunc)ippiDCTFwd_32f_C1R; ippiDCTInitAlloc ippInitAlloc = inv ? (ippiDCTInitAlloc)ippiDCTInvInitAlloc_32f : (ippiDCTInitAlloc)ippiDCTFwdInitAlloc_32f; ippiDCTFree ippFree = inv ? (ippiDCTFree)ippiDCTInvFree_32f : (ippiDCTFree)ippiDCTFwdFree_32f; ippiDCTGetBufSize ippGetBufSize = inv ? (ippiDCTGetBufSize)ippiDCTInvGetBufSize_32f : (ippiDCTGetBufSize)ippiDCTFwdGetBufSize_32f; @@ -3428,7 +3556,7 @@ static bool ippi_DCT_32f(const Mat& src, Mat& dst, bool inv, bool row) buf.allocate( bufSize ); pBuffer = (uchar*)buf; - status = ippFunc(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, pDCTSpec, (Ipp8u*)pBuffer); + status = ippDctFun(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, pDCTSpec, (Ipp8u*)pBuffer); } if (pDCTSpec) @@ -3437,11 +3565,14 @@ static bool ippi_DCT_32f(const Mat& src, Mat& dst, bool inv, bool row) CV_SUPPRESS_DEPRECATED_END return status >= 0; +#else + CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(inv); CV_UNUSED(row); + return false; +#endif } } - -#endif } +#endif void cv::dct( InputArray _src0, OutputArray _dst, int flags ) { diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 999640d94..4e60dbe4f 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -2233,7 +2233,9 @@ static bool ipp_minMaxIdx( Mat &src, double* minVal, double* maxVal, int* minIdx CV_SUPPRESS_DEPRECATED_START ippiMaskMinMaxIndxFuncC1 ippFuncC1 = type == CV_8UC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_8u_C1MR : +#if IPP_VERSION_X100 < 900 type == CV_8SC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_8s_C1MR : +#endif type == CV_16UC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_16u_C1MR : type == CV_32FC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_32f_C1MR : 0; CV_SUPPRESS_DEPRECATED_END @@ -2270,8 +2272,12 @@ static bool ipp_minMaxIdx( Mat &src, double* minVal, double* maxVal, int* minIdx CV_SUPPRESS_DEPRECATED_START ippiMinMaxIndxFuncC1 ippFuncC1 = +#if IPP_VERSION_X100 != 900 // bug in 9.0.0 avx2 optimization depth == CV_8U ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_8u_C1R : +#endif +#if IPP_VERSION_X100 < 900 depth == CV_8S ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_8s_C1R : +#endif depth == CV_16U ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_16u_C1R : #if !((defined _MSC_VER && defined _M_IX86) || defined __i386__) depth == CV_32F ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_32f_C1R : @@ -2676,19 +2682,25 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) ippiMaskNormFuncC1 ippFuncC1 = normType == NORM_INF ? (type == CV_8UC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_8u_C1MR : +#if IPP_VERSION_X100 < 900 type == CV_8SC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_8s_C1MR : +#endif // type == CV_16UC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_32f_C1MR : 0) : normType == NORM_L1 ? (type == CV_8UC1 ? (ippiMaskNormFuncC1)ippiNorm_L1_8u_C1MR : +#if IPP_VERSION_X100 < 900 type == CV_8SC1 ? (ippiMaskNormFuncC1)ippiNorm_L1_8s_C1MR : +#endif type == CV_16UC1 ? (ippiMaskNormFuncC1)ippiNorm_L1_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormFuncC1)ippiNorm_L1_32f_C1MR : 0) : normType == NORM_L2 || normType == NORM_L2SQR ? (type == CV_8UC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_8u_C1MR : +#if IPP_VERSION_X100 < 900 type == CV_8SC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_8s_C1MR : +#endif type == CV_16UC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_32f_C1MR : 0) : 0; @@ -2701,7 +2713,7 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) return true; } } -#if IPP_DISABLED_BLOCK +#if IPP_DISABLE_BLOCK typedef IppStatus (CV_STDCALL* ippiMaskNormFuncC3)(const void *, int, const void *, int, IppiSize, int, Ipp64f *); ippiMaskNormFuncC3 ippFuncC3 = normType == NORM_INF ? @@ -3071,23 +3083,29 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra ippiMaskNormRelFuncC1 ippFuncC1 = normType == NORM_INF ? (type == CV_8UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_Inf_8u_C1MR : +#if IPP_VERSION_X100 < 900 #ifndef __APPLE__ type == CV_8SC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_Inf_8s_C1MR : +#endif #endif type == CV_16UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_Inf_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_Inf_32f_C1MR : 0) : normType == NORM_L1 ? (type == CV_8UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L1_8u_C1MR : +#if IPP_VERSION_X100 < 900 #ifndef __APPLE__ type == CV_8SC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L1_8s_C1MR : +#endif #endif type == CV_16UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L1_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L1_32f_C1MR : 0) : normType == NORM_L2 || normType == NORM_L2SQR ? (type == CV_8UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L2_8u_C1MR : +#if IPP_VERSION_X100 < 900 type == CV_8SC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L2_8s_C1MR : +#endif type == CV_16UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L2_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L2_32f_C1MR : 0) : 0; @@ -3172,21 +3190,27 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra ippiMaskNormDiffFuncC1 ippFuncC1 = normType == NORM_INF ? (type == CV_8UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_8u_C1MR : +#if IPP_VERSION_X100 < 900 type == CV_8SC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_8s_C1MR : +#endif type == CV_16UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_32f_C1MR : 0) : normType == NORM_L1 ? (type == CV_8UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L1_8u_C1MR : +#if IPP_VERSION_X100 < 900 #ifndef __APPLE__ type == CV_8SC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L1_8s_C1MR : +#endif #endif type == CV_16UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L1_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L1_32f_C1MR : 0) : normType == NORM_L2 || normType == NORM_L2SQR ? (type == CV_8UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_8u_C1MR : +#if IPP_VERSION_X100 < 900 type == CV_8SC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_8s_C1MR : +#endif type == CV_16UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_32f_C1MR : 0) : 0; @@ -3204,19 +3228,25 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra ippiMaskNormDiffFuncC3 ippFuncC3 = normType == NORM_INF ? (type == CV_8UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_8u_C3CMR : +#if IPP_VERSION_X100 < 900 type == CV_8SC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_8s_C3CMR : +#endif type == CV_16UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_16u_C3CMR : type == CV_32FC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_32f_C3CMR : 0) : normType == NORM_L1 ? (type == CV_8UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L1_8u_C3CMR : +#if IPP_VERSION_X100 < 900 type == CV_8SC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L1_8s_C3CMR : +#endif type == CV_16UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L1_16u_C3CMR : type == CV_32FC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L1_32f_C3CMR : 0) : normType == NORM_L2 || normType == NORM_L2SQR ? (type == CV_8UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_8u_C3CMR : +#if IPP_VERSION_X100 < 900 type == CV_8SC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_8s_C3CMR : +#endif type == CV_16UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_16u_C3CMR : type == CV_32FC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_32f_C3CMR : 0) : 0; diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index 670d1486c..a4c0c6cfd 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -60,10 +60,16 @@ static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high) int size = 0, size1 = 0; IppiSize roi = { _src.cols, _src.rows }; +#if IPP_VERSION_X100 < 900 if (ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(roi, ippMskSize3x3, &size) < 0) return false; if (ippiFilterSobelHorizGetBufferSize_8u16s_C1R(roi, ippMskSize3x3, &size1) < 0) return false; +#else + if(ippiFilterSobelGetBufferSize(roi, ippMskSize3x3, ippNormL2, ipp8u, ipp16s, 1, &size) < 0) + return false; +#endif + size = std::max(size, size1); if (ippiCannyGetSize(roi, &size1) < 0) diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 6020eaf77..df6a59d87 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -7416,6 +7416,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) return false; #endif +#if IPP_VERSION_X100 < 900 case CV_BGR5652BGR: case CV_BGR5552BGR: case CV_BGR5652RGB: case CV_BGR5552RGB: case CV_BGR5652BGRA: case CV_BGR5552BGRA: case CV_BGR5652RGBA: case CV_BGR5552RGBA: if(dcn <= 0) dcn = (code==CV_BGR5652BGRA || code==CV_BGR5552BGRA || code==CV_BGR5652RGBA || code==CV_BGR5552RGBA) ? 4 : 3; @@ -7449,6 +7450,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) } CV_SUPPRESS_DEPRECATED_END return false; +#endif #if IPP_VERSION_X100 >= 700 case CV_BGR2GRAY: case CV_BGRA2GRAY: case CV_RGB2GRAY: case CV_RGBA2GRAY: diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index c263b6914..b2f2bd497 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -325,11 +325,19 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, if (src.type() == CV_8U && dst.type() == CV_16S && scale == 1) { +#if IPP_VERSION_X100 >= 900 + if(ippiFilterSobelGetBufferSize(roi, kernel, ippNormL2, ipp8u, ipp16s, 1, &bufSize) < 0) + return false; + buffer.allocate(bufSize); +#endif + if ((dx == 1) && (dy == 0)) { +#if IPP_VERSION_X100 < 900 if (0 > ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) return false; buffer.allocate(bufSize); +#endif if (0 > ippiFilterSobelNegVertBorder_8u16s_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, kernel, @@ -340,9 +348,11 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, if ((dx == 0) && (dy == 1)) { +#if IPP_VERSION_X100 < 900 if (0 > ippiFilterSobelHorizGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) return false; buffer.allocate(bufSize); +#endif if (0 > ippiFilterSobelHorizBorder_8u16s_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, kernel, @@ -354,9 +364,11 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, #if !defined(HAVE_IPP_ICV_ONLY) if ((dx == 2) && (dy == 0)) { +#if IPP_VERSION_X100 < 900 if (0 > ippiFilterSobelVertSecondGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) return false; buffer.allocate(bufSize); +#endif if (0 > ippiFilterSobelVertSecondBorder_8u16s_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, kernel, @@ -367,9 +379,11 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, if ((dx == 0) && (dy == 2)) { +#if IPP_VERSION_X100 < 900 if (0 > ippiFilterSobelHorizSecondGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) return false; buffer.allocate(bufSize); +#endif if (0 > ippiFilterSobelHorizSecondBorder_8u16s_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, kernel, @@ -382,12 +396,20 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, if (src.type() == CV_32F && dst.type() == CV_32F) { +#if IPP_VERSION_X100 >= 900 + if(ippiFilterSobelGetBufferSize(roi, kernel, ippNormL2, ipp32f, ipp32f, 1, &bufSize) < 0) + return false; + buffer.allocate(bufSize); +#endif + #if IPP_DISABLE_BLOCK if ((dx == 1) && (dy == 0)) { +#if IPP_VERSION_X100 < 900 if (0 > ippiFilterSobelNegVertGetBufferSize_32f_C1R(roi, kernel, &bufSize)) return false; buffer.allocate(bufSize); +#endif if (0 > ippiFilterSobelNegVertBorder_32f_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, kernel, @@ -400,9 +422,12 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, if ((dx == 0) && (dy == 1)) { +#if IPP_VERSION_X100 < 900 if (0 > ippiFilterSobelHorizGetBufferSize_32f_C1R(roi, kernel,&bufSize)) return false; buffer.allocate(bufSize); +#endif + if (0 > ippiFilterSobelHorizBorder_32f_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) @@ -415,9 +440,11 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, #if !defined(HAVE_IPP_ICV_ONLY) if((dx == 2) && (dy == 0)) { +#if IPP_VERSION_X100 < 900 if (0 > ippiFilterSobelVertSecondGetBufferSize_32f_C1R(roi, kernel,&bufSize)) return false; buffer.allocate(bufSize); +#endif if (0 > ippiFilterSobelVertSecondBorder_32f_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, kernel, @@ -430,9 +457,11 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, if((dx == 0) && (dy == 2)) { +#if IPP_VERSION_X100 < 900 if (0 > ippiFilterSobelHorizSecondGetBufferSize_32f_C1R(roi, kernel,&bufSize)) return false; buffer.allocate(bufSize); +#endif if (0 > ippiFilterSobelHorizSecondBorder_32f_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, kernel, diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index 1bb9ec5e5..00fce77ea 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -1180,7 +1180,7 @@ class IPPCalcHistInvoker : public ParallelLoopBody { public: - IPPCalcHistInvoker(const Mat & _src, Mat & _hist, AutoBuffer & _levels, Ipp32s _histSize, Ipp32s _low, Ipp32s _high, bool * _ok) : + IPPCalcHistInvoker(const Mat & _src, Mat & _hist, AutoBuffer & _levels, Ipp32s _histSize, Ipp32f _low, Ipp32f _high, bool * _ok) : ParallelLoopBody(), src(&_src), hist(&_hist), levels(&_levels), histSize(_histSize), low(_low), high(_high), ok(_ok) { *ok = true; @@ -1189,12 +1189,54 @@ public: virtual void operator() (const Range & range) const { Mat phist(hist->size(), hist->type(), Scalar::all(0)); +#if IPP_VERSION_X100 >= 900 + IppiSize roi = {src->cols, range.end - range.start}; + int bufferSize = 0; + int specSize = 0; + IppiHistogramSpec *pSpec = NULL; + Ipp8u *pBuffer = NULL; - IppStatus status = ippiHistogramEven_8u_C1R( - src->ptr(range.start), (int)src->step, ippiSize(src->cols, range.end - range.start), - phist.ptr(), (Ipp32s *)*levels, histSize, low, high); + if(ippiHistogramGetBufferSize(ipp8u, roi, &histSize, 1, 1, &specSize, &bufferSize) < 0) + { + *ok = false; + return; + } - if (status < 0) + pBuffer = (Ipp8u*)ippMalloc(bufferSize); + if(!pBuffer && bufferSize) + { + *ok = false; + return; + } + + pSpec = (IppiHistogramSpec*)ippMalloc(specSize); + if(!pSpec && specSize) + { + if(pBuffer) ippFree(pBuffer); + *ok = false; + return; + } + + if(ippiHistogramUniformInit(ipp8u, (Ipp32f*)&low, (Ipp32f*)&high, (Ipp32s*)&histSize, 1, pSpec) < 0) + { + if(pSpec) ippFree(pSpec); + if(pBuffer) ippFree(pBuffer); + *ok = false; + return; + } + + IppStatus status = ippiHistogram_8u_C1R(src->ptr(range.start), (int)src->step, ippiSize(src->cols, range.end - range.start), + phist.ptr(), pSpec, pBuffer); + + if(pSpec) ippFree(pSpec); + if(pBuffer) ippFree(pBuffer); +#else + CV_SUPPRESS_DEPRECATED_START + IppStatus status = ippiHistogramEven_8u_C1R(src->ptr(range.start), (int)src->step, ippiSize(src->cols, range.end - range.start), + phist.ptr(), (Ipp32s*)(Ipp32f*)*levels, histSize, (Ipp32s)low, (Ipp32s)high); + CV_SUPPRESS_DEPRECATED_END +#endif + if(status < 0) { *ok = false; return; @@ -1207,8 +1249,9 @@ public: private: const Mat * src; Mat * hist; - AutoBuffer * levels; - Ipp32s histSize, low, high; + AutoBuffer * levels; + Ipp32s histSize; + Ipp32f low, high; bool * ok; const IPPCalcHistInvoker & operator = (const IPPCalcHistInvoker & ); @@ -1239,7 +1282,7 @@ static bool ipp_calchist(const Mat* images, int nimages, const int* channels, !accumulate && uniform) { ihist.setTo(Scalar::all(0)); - AutoBuffer levels(histSize[0] + 1); + AutoBuffer levels(histSize[0] + 1); bool ok = true; const Mat & src = images[0]; @@ -1247,7 +1290,7 @@ static bool ipp_calchist(const Mat* images, int nimages, const int* channels, #ifdef HAVE_CONCURRENCY nstripes = 1; #endif - IPPCalcHistInvoker invoker(src, ihist, levels, histSize[0] + 1, (Ipp32s)ranges[0][0], (Ipp32s)ranges[0][1], &ok); + IPPCalcHistInvoker invoker(src, ihist, levels, histSize[0] + 1, ranges[0][0], ranges[0][1], &ok); Range range(0, src.rows); parallel_for_(range, invoker, nstripes); diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index dfb9d4755..1ec1d25bf 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1155,7 +1155,36 @@ static bool ipp_MorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kern if (!rectKernel) { -#if 1 +#if IPP_VERSION_X100 >= 900 + if (((kernel.cols - 1) / 2 != anchor.x) || ((kernel.rows - 1) / 2 != anchor.y)) + return false; + #define IPP_MORPH_CASE(cvtype, flavor, data_type) \ + case cvtype: \ + {\ + int specSize = 0, bufferSize = 0;\ + if (0 > ippiMorphologyBorderGetSize_##flavor(roiSize, kernelSize, &specSize, &bufferSize))\ + return false;\ + IppiMorphState *pSpec = (IppiMorphState*)ippMalloc(specSize);\ + Ipp8u *pBuffer = (Ipp8u*)ippMalloc(bufferSize);\ + if (0 > ippiMorphologyBorderInit_##flavor(roiSize, kernel.ptr(), kernelSize, pSpec, pBuffer))\ + {\ + ippFree(pBuffer);\ + ippFree(pSpec);\ + return false;\ + }\ + bool ok = false;\ + if (op == MORPH_ERODE)\ + ok = (0 <= ippiErodeBorder_##flavor(_src->ptr(), (int)_src->step[0], dst.ptr(), (int)dst.step[0],\ + roiSize, ippBorderRepl, 0, pSpec, pBuffer));\ + else\ + ok = (0 <= ippiDilateBorder_##flavor(_src->ptr(), (int)_src->step[0], dst.ptr(), (int)dst.step[0],\ + roiSize, ippBorderRepl, 0, pSpec, pBuffer));\ + ippFree(pBuffer);\ + ippFree(pSpec);\ + return ok;\ + }\ + break; +#else if (((kernel.cols - 1) / 2 != anchor.x) || ((kernel.rows - 1) / 2 != anchor.y)) return false; #define IPP_MORPH_CASE(cvtype, flavor, data_type) \ @@ -1184,35 +1213,8 @@ static bool ipp_MorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kern return ok;\ }\ break; -#else - IppiPoint point = {anchor.x, anchor.y}; - // this is case, which can be used with the anchor not in center of the kernel, but - // ippiMorphologyBorderGetSize_, ippiErodeBorderReplicate_ and ippiDilateBorderReplicate_ are deprecated. - #define IPP_MORPH_CASE(cvtype, flavor, data_type) \ - case cvtype: \ - {\ - int specSize = 0;\ - int bufferSize = 0;\ - if (0 > ippiMorphologyGetSize_##flavor( roiSize.width, kernel.ptr() kernelSize, &specSize))\ - return false;\ - bool ok = false;\ - IppiMorphState* pState = (IppiMorphState*)ippMalloc(specSize);\ - if (ippiMorphologyInit_##flavor(roiSize.width, kernel.ptr(), kernelSize, point, pState) >= 0)\ - {\ - if (op == MORPH_ERODE)\ - ok = ippiErodeBorderReplicate_##flavor(_src->ptr(), (int)_src->step[0],\ - dst.ptr(), (int)dst.step[0],\ - roiSize, ippBorderRepl, pState ) >= 0;\ - else\ - ok = ippiDilateBorderReplicate_##flavor(_src->ptr(), (int)_src->step[0],\ - dst.ptr(), (int)dst.step[0],\ - roiSize, ippBorderRepl, pState ) >= 0;\ - }\ - ippFree(pState);\ - return ok;\ - }\ - break; #endif + CV_SUPPRESS_DEPRECATED_START switch (type) { IPP_MORPH_CASE(CV_8UC1, 8u_C1R, 8u); @@ -1224,11 +1226,39 @@ static bool ipp_MorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kern default: ; } - + CV_SUPPRESS_DEPRECATED_END #undef IPP_MORPH_CASE } else { +#if IPP_VERSION_X100 >= 900 + if (((kernel.cols - 1) / 2 != anchor.x) || ((kernel.rows - 1) / 2 != anchor.y)) // Arbitrary anchor is no longer supporeted since IPP 9.0.0 + return false; + + #define IPP_MORPH_CASE(cvtype, flavor, data_type) \ + case cvtype: \ + {\ + if (op == MORPH_ERODE)\ + {\ + int bufSize = 0;\ + if (0 > ippiFilterMinBorderGetBufferSize(roiSize, kernelSize, ipp##data_type, 1, &bufSize))\ + return false;\ + AutoBuffer buf(bufSize + 64);\ + uchar* buffer = alignPtr((uchar*)buf, 32);\ + return (0 <= ippiFilterMinBorder_##flavor(_src->ptr(), (int)_src->step[0], dst.ptr(), (int)dst.step[0], roiSize, kernelSize, ippBorderRepl, 0, buffer));\ + }\ + else\ + {\ + int bufSize = 0;\ + if (0 > ippiFilterMaxBorderGetBufferSize(roiSize, kernelSize, ipp##data_type, 1, &bufSize))\ + return false;\ + AutoBuffer buf(bufSize + 64);\ + uchar* buffer = alignPtr((uchar*)buf, 32);\ + return (0 <= ippiFilterMaxBorder_##flavor(_src->ptr(), (int)_src->step[0], dst.ptr(), (int)dst.step[0], roiSize, kernelSize, ippBorderRepl, 0, buffer));\ + }\ + }\ + break; +#else IppiPoint point = {anchor.x, anchor.y}; #define IPP_MORPH_CASE(cvtype, flavor, data_type) \ @@ -1244,7 +1274,9 @@ static bool ipp_MorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kern return (0 <= ippiFilterMaxBorderReplicate_##flavor(_src->ptr(), (int)_src->step[0], dst.ptr(), (int)dst.step[0], roiSize, kernelSize, point, buffer));\ }\ break; +#endif + CV_SUPPRESS_DEPRECATED_START switch (type) { IPP_MORPH_CASE(CV_8UC1, 8u_C1R, 8u); @@ -1256,6 +1288,7 @@ static bool ipp_MorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kern default: ; } + CV_SUPPRESS_DEPRECATED_END #undef IPP_MORPH_CASE } #else diff --git a/modules/objdetect/src/haar.cpp b/modules/objdetect/src/haar.cpp index 09928264a..66ea517c3 100644 --- a/modules/objdetect/src/haar.cpp +++ b/modules/objdetect/src/haar.cpp @@ -165,7 +165,11 @@ icvReleaseHidHaarClassifierCascade( CvHidHaarClassifierCascade** _cascade ) for( i = 0; i < cascade->count; i++ ) { if( cascade->ipp_stages[i] ) +#if IPP_VERSION_X100 < 900 ippiHaarClassifierFree_32f( (IppiHaarClassifier_32f*)cascade->ipp_stages[i] ); +#else + cvFree(&cascade->ipp_stages[i]); +#endif } } cvFree( &cascade->ipp_stages ); From e837d69f8fa3b465d7a5185900c84c8ce85f00c0 Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Fri, 25 Sep 2015 18:00:53 +0300 Subject: [PATCH 096/156] IPPInitSingelton was added to contain IPP related global variables; OPENCV_IPP env var now allows to select IPP architecture level for IPP9+; IPP initialization logic was unified across modules; --- modules/calib3d/src/main.cpp | 52 +++++++++ modules/core/include/opencv2/core/base.hpp | 1 + modules/core/include/opencv2/core/private.hpp | 36 +++++++ modules/core/src/system.cpp | 102 +++++++++++++----- modules/features2d/src/main.cpp | 52 +++++++++ modules/imgproc/src/color.cpp | 1 - modules/imgproc/src/deriv.cpp | 4 - modules/imgproc/src/imgwarp.cpp | 4 - modules/imgproc/src/main.cpp | 52 +++++++++ modules/imgproc/src/sumpixels.cpp | 4 - modules/objdetect/src/main.cpp | 52 +++++++++ 11 files changed, 318 insertions(+), 42 deletions(-) create mode 100644 modules/calib3d/src/main.cpp create mode 100644 modules/features2d/src/main.cpp create mode 100644 modules/imgproc/src/main.cpp create mode 100644 modules/objdetect/src/main.cpp diff --git a/modules/calib3d/src/main.cpp b/modules/calib3d/src/main.cpp new file mode 100644 index 000000000..127f86b26 --- /dev/null +++ b/modules/calib3d/src/main.cpp @@ -0,0 +1,52 @@ +/*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) 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*/ + +// +// Library initialization file +// + +#include "precomp.hpp" + +IPP_INITIALIZER_AUTO + +/* End of file. */ diff --git a/modules/core/include/opencv2/core/base.hpp b/modules/core/include/opencv2/core/base.hpp index 95142c513..3ab0982ce 100644 --- a/modules/core/include/opencv2/core/base.hpp +++ b/modules/core/include/opencv2/core/base.hpp @@ -645,6 +645,7 @@ namespace cudev namespace ipp { +CV_EXPORTS int getIppFeatures(); CV_EXPORTS void setIppStatus(int status, const char * const funcname = NULL, const char * const filename = NULL, int line = 0); CV_EXPORTS int getIppStatus(); diff --git a/modules/core/include/opencv2/core/private.hpp b/modules/core/include/opencv2/core/private.hpp index 28f21d4d8..363c76f0d 100644 --- a/modules/core/include/opencv2/core/private.hpp +++ b/modules/core/include/opencv2/core/private.hpp @@ -256,6 +256,42 @@ static inline IppDataType ippiGetDataType(int depth) #define HAVE_ICV 0 #endif +#if defined HAVE_IPP +#if IPP_VERSION_X100 >= 900 +#define IPP_INITIALIZER(FEAT) \ +{ \ + if(FEAT) \ + ippSetCpuFeatures(FEAT); \ + else \ + ippInit(); \ +} +#elif IPP_VERSION_X100 >= 800 +#define IPP_INITIALIZER(FEAT) \ +{ \ + ippInit(); \ +} +#else +#define IPP_INITIALIZER(FEAT) \ +{ \ + ippStaticInit(); \ +} +#endif + +#ifdef CVAPI_EXPORTS +#define IPP_INITIALIZER_AUTO \ +struct __IppInitializer__ \ +{ \ + __IppInitializer__() \ + {IPP_INITIALIZER(cv::ipp::getIppFeatures())} \ +}; \ +static struct __IppInitializer__ __ipp_initializer__; +#else +#define IPP_INITIALIZER_AUTO +#endif +#else +#define IPP_INITIALIZER +#define IPP_INITIALIZER_AUTO +#endif #define CV_IPP_CHECK_COND (cv::ipp::useIPP()) #define CV_IPP_CHECK() if(CV_IPP_CHECK_COND) diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index 337414918..623280b32 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -42,6 +42,7 @@ //M*/ #include "precomp.hpp" +#include namespace cv { @@ -377,21 +378,6 @@ bool checkHardwareSupport(int feature) volatile bool useOptimizedFlag = true; -#ifdef HAVE_IPP -struct IPPInitializer -{ - IPPInitializer(void) - { -#if IPP_VERSION_MAJOR >= 8 - ippInit(); -#else - ippStaticInit(); -#endif - } -}; - -IPPInitializer ippInitializer; -#endif volatile bool USE_SSE2 = featuresEnabled.have[CV_CPU_SSE2]; volatile bool USE_SSE4_2 = featuresEnabled.have[CV_CPU_SSE4_2]; @@ -1305,26 +1291,88 @@ void setUseCollection(bool flag) namespace ipp { -static int ippStatus = 0; // 0 - all is ok, -1 - IPP functions failed -static const char * funcname = NULL, * filename = NULL; -static int linen = 0; +struct IPPInitSingelton +{ +public: + IPPInitSingelton() + { + useIPP = true; + ippStatus = 0; + funcname = NULL; + filename = NULL; + linen = 0; + ippFeatures = 0; + +#ifdef HAVE_IPP + const char* pIppEnv = getenv("OPENCV_IPP"); + cv::String env = pIppEnv; + if(env.size()) + { + if(env == "disabled") + { + std::cerr << "WARNING: IPP was disabled by OPENCV_IPP environment variable" << std::endl; + useIPP = false; + } +#if IPP_VERSION_X100 >= 900 + else if(env == "sse") + ippFeatures = ippCPUID_SSE; + else if(env == "sse2") + ippFeatures = ippCPUID_SSE2; + else if(env == "sse42") + ippFeatures = ippCPUID_SSE42; + else if(env == "avx") + ippFeatures = ippCPUID_AVX; + else if(env == "avx2") + ippFeatures = ippCPUID_AVX2; +#endif + else + std::cerr << "ERROR: Improper value of OPENCV_IPP: " << env.c_str() << std::endl; + } + + IPP_INITIALIZER(ippFeatures) +#endif + } + + bool useIPP; + + int ippStatus; // 0 - all is ok, -1 - IPP functions failed + const char *funcname; + const char *filename; + int linen; + int ippFeatures; +}; + +static IPPInitSingelton& getIPPSingelton() +{ + static IPPInitSingelton sing; + return sing; +} + +int getIppFeatures() +{ +#ifdef HAVE_IPP + return getIPPSingelton().ippFeatures; +#else + return 0; +#endif +} void setIppStatus(int status, const char * const _funcname, const char * const _filename, int _line) { - ippStatus = status; - funcname = _funcname; - filename = _filename; - linen = _line; + getIPPSingelton().ippStatus = status; + getIPPSingelton().funcname = _funcname; + getIPPSingelton().filename = _filename; + getIPPSingelton().linen = _line; } int getIppStatus() { - return ippStatus; + return getIPPSingelton().ippStatus; } String getIppErrorLocation() { - return format("%s:%d %s", filename ? filename : "", linen, funcname ? funcname : ""); + return format("%s:%d %s", getIPPSingelton().filename ? getIPPSingelton().filename : "", getIPPSingelton().linen, getIPPSingelton().funcname ? getIPPSingelton().funcname : ""); } bool useIPP() @@ -1333,11 +1381,7 @@ bool useIPP() CoreTLSData* data = getCoreTlsData().get(); if(data->useIPP < 0) { - const char* pIppEnv = getenv("OPENCV_IPP"); - if(pIppEnv && (cv::String(pIppEnv) == "disabled")) - data->useIPP = false; - else - data->useIPP = true; + data->useIPP = getIPPSingelton().useIPP; } return (data->useIPP > 0); #else diff --git a/modules/features2d/src/main.cpp b/modules/features2d/src/main.cpp new file mode 100644 index 000000000..127f86b26 --- /dev/null +++ b/modules/features2d/src/main.cpp @@ -0,0 +1,52 @@ +/*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) 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*/ + +// +// Library initialization file +// + +#include "precomp.hpp" + +IPP_INITIALIZER_AUTO + +/* End of file. */ diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index df6a59d87..27d602e0d 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -100,7 +100,6 @@ #define MAX_IPP8u 255 #define MAX_IPP16u 65535 #define MAX_IPP32f 1.0 -static IppStatus sts = ippInit(); #endif namespace cv diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index b2f2bd497..2fcdabeaa 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -43,10 +43,6 @@ #include "precomp.hpp" #include "opencl_kernels_imgproc.hpp" -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) -static IppStatus sts = ippInit(); -#endif - /****************************************************************************************\ Sobel & Scharr Derivative Filters \****************************************************************************************/ diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index 9c16f91a2..e7ee0c677 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -50,10 +50,6 @@ #include "precomp.hpp" #include "opencl_kernels_imgproc.hpp" -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) -static IppStatus sts = ippInit(); -#endif - namespace cv { #if IPP_VERSION_X100 >= 710 diff --git a/modules/imgproc/src/main.cpp b/modules/imgproc/src/main.cpp new file mode 100644 index 000000000..127f86b26 --- /dev/null +++ b/modules/imgproc/src/main.cpp @@ -0,0 +1,52 @@ +/*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) 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*/ + +// +// Library initialization file +// + +#include "precomp.hpp" + +IPP_INITIALIZER_AUTO + +/* End of file. */ diff --git a/modules/imgproc/src/sumpixels.cpp b/modules/imgproc/src/sumpixels.cpp index a6e86f6c0..8a667d291 100755 --- a/modules/imgproc/src/sumpixels.cpp +++ b/modules/imgproc/src/sumpixels.cpp @@ -44,10 +44,6 @@ #include "precomp.hpp" #include "opencl_kernels_imgproc.hpp" -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) -static IppStatus sts = ippInit(); -#endif - namespace cv { diff --git a/modules/objdetect/src/main.cpp b/modules/objdetect/src/main.cpp new file mode 100644 index 000000000..127f86b26 --- /dev/null +++ b/modules/objdetect/src/main.cpp @@ -0,0 +1,52 @@ +/*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) 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*/ + +// +// Library initialization file +// + +#include "precomp.hpp" + +IPP_INITIALIZER_AUTO + +/* End of file. */ From 05846438e33282ffff8af54030b422a4fc639dc8 Mon Sep 17 00:00:00 2001 From: Philipp Hasper Date: Thu, 1 Oct 2015 15:09:14 +0200 Subject: [PATCH 097/156] Typo in CameraBridgeViewBase.java Corrected typo and unused imports --- .../java/generator/src/java/android+CameraBridgeViewBase.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/java/generator/src/java/android+CameraBridgeViewBase.java b/modules/java/generator/src/java/android+CameraBridgeViewBase.java index da939017c..14e041146 100644 --- a/modules/java/generator/src/java/android+CameraBridgeViewBase.java +++ b/modules/java/generator/src/java/android+CameraBridgeViewBase.java @@ -3,10 +3,8 @@ package org.opencv.android; import java.util.List; import org.opencv.R; -import org.opencv.android.Utils; import org.opencv.core.Mat; import org.opencv.core.Size; -import org.opencv.videoio.Videoio; import android.app.Activity; import android.app.AlertDialog; @@ -451,7 +449,7 @@ public abstract class CameraBridgeViewBase extends SurfaceView implements Surfac */ protected abstract void disconnectCamera(); - // NOTE: On Android 4.1.x the function must be called before SurfaceTextre constructor! + // NOTE: On Android 4.1.x the function must be called before SurfaceTexture constructor! protected void AllocateCache() { mCacheBitmap = Bitmap.createBitmap(mFrameWidth, mFrameHeight, Bitmap.Config.ARGB_8888); From b71a27b96c1d05329741206ccbc97f3696e52533 Mon Sep 17 00:00:00 2001 From: Miguel Algaba Date: Thu, 1 Oct 2015 16:45:59 +0200 Subject: [PATCH 098/156] Assert fix: allow one cluster as valid parameter --- modules/ml/src/em.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ml/src/em.cpp b/modules/ml/src/em.cpp index c837b0d63..0ee3c4a71 100644 --- a/modules/ml/src/em.cpp +++ b/modules/ml/src/em.cpp @@ -61,7 +61,7 @@ public: void setClustersNumber(int val) { nclusters = val; - CV_Assert(nclusters > 1); + CV_Assert(nclusters >= 1); } int getClustersNumber() const From 6a0d3b06f2933472109e43ba4b887012b0822c56 Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Thu, 1 Oct 2015 17:48:49 +0300 Subject: [PATCH 099/156] IPPInitSingelton initialization guards; --- modules/core/src/system.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index 623280b32..81d555d81 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -1344,8 +1344,7 @@ public: static IPPInitSingelton& getIPPSingelton() { - static IPPInitSingelton sing; - return sing; + CV_SINGLETON_LAZY_INIT_REF(IPPInitSingelton, new IPPInitSingelton()) } int getIppFeatures() From 1bf811c3f187f5aea08eeb868bca2ee0cf8ad532 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Fri, 2 Oct 2015 11:41:01 +0300 Subject: [PATCH 100/156] fix cuda::normalize (dtype < 0) case --- modules/cudaarithm/src/cuda/normalize.cu | 4 ++++ modules/cudaarithm/test/test_reductions.cpp | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/cudaarithm/src/cuda/normalize.cu b/modules/cudaarithm/src/cuda/normalize.cu index efbc94ecc..c83f2c0df 100644 --- a/modules/cudaarithm/src/cuda/normalize.cu +++ b/modules/cudaarithm/src/cuda/normalize.cu @@ -249,6 +249,10 @@ void cv::cuda::normalize(InputArray _src, OutputArray _dst, double a, double b, CV_Assert( src.channels() == 1 ); CV_Assert( mask.empty() || (mask.size() == src.size() && mask.type() == CV_8U) ); + if (dtype < 0) + { + dtype = _dst.fixedType() ? _dst.type() : src.type(); + } dtype = CV_MAT_DEPTH(dtype); const int src_depth = src.depth(); diff --git a/modules/cudaarithm/test/test_reductions.cpp b/modules/cudaarithm/test/test_reductions.cpp index 9a8854939..a0ff0dfa4 100644 --- a/modules/cudaarithm/test/test_reductions.cpp +++ b/modules/cudaarithm/test/test_reductions.cpp @@ -951,11 +951,11 @@ CUDA_TEST_P(Normalize, WithMask) cv::cuda::GpuMat dst = createMat(size, type, useRoi); dst.setTo(cv::Scalar::all(0)); - cv::cuda::normalize(loadMat(src, useRoi), dst, alpha, beta, norm_type, type, loadMat(mask, useRoi)); + cv::cuda::normalize(loadMat(src, useRoi), dst, alpha, beta, norm_type, -1, loadMat(mask, useRoi)); cv::Mat dst_gold(size, type); dst_gold.setTo(cv::Scalar::all(0)); - cv::normalize(src, dst_gold, alpha, beta, norm_type, type, mask); + cv::normalize(src, dst_gold, alpha, beta, norm_type, -1, mask); EXPECT_MAT_NEAR(dst_gold, dst, type < CV_32F ? 1.0 : 1e-4); } From 21c0acff241e7655cf326b200dcbc0ea2d5cd69e Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Thu, 1 Oct 2015 17:25:18 +0300 Subject: [PATCH 101/156] Update imgcodecs.hpp --- .../imgcodecs/include/opencv2/imgcodecs.hpp | 110 +++++++++--------- modules/imgcodecs/src/loadsave.cpp | 6 +- 2 files changed, 61 insertions(+), 55 deletions(-) diff --git a/modules/imgcodecs/include/opencv2/imgcodecs.hpp b/modules/imgcodecs/include/opencv2/imgcodecs.hpp index 678861bfe..699bc163c 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs.hpp +++ b/modules/imgcodecs/include/opencv2/imgcodecs.hpp @@ -68,12 +68,12 @@ enum ImreadModes { IMREAD_ANYDEPTH = 2, //!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit. IMREAD_ANYCOLOR = 4, //!< If set, the image is read in any possible color format. IMREAD_LOAD_GDAL = 8, //!< If set, use the gdal driver for loading the image. - IMREAD_GRAYSCALE_REDUCED_2 = 16, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/2. - IMREAD_COLOR_REDUCED_2 = 17, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/2. - IMREAD_GRAYSCALE_REDUCED_4 = 32, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/4. - IMREAD_COLOR_REDUCED_4 = 33, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4. - IMREAD_GRAYSCALE_REDUCED_8 = 64, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/8. - IMREAD_COLOR_REDUCED_8 = 65 //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8. + IMREAD_REDUCED_GRAYSCALE_2 = 16, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/2. + IMREAD_REDUCED_COLOR_2 = 17, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/2. + IMREAD_REDUCED_GRAYSCALE_4 = 32, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/4. + IMREAD_REDUCED_COLOR_4 = 33, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4. + IMREAD_REDUCED_GRAYSCALE_8 = 64, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/8. + IMREAD_REDUCED_COLOR_8 = 65 //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8. }; //! Imwrite flags @@ -91,25 +91,31 @@ enum ImwriteFlags { IMWRITE_WEBP_QUALITY = 64 //!< For WEBP, it can be a quality from 1 to 100 (the higher is the better). By default (without any parameter) and for quality above 100 the lossless compression is used. }; -//! Imwrite PNG specific flags +//! Imwrite PNG specific flags used to tune the compression algorithm. +/** These flags will be modify the way of PNG image compression and will be passed to the underlying zlib processing stage. + +- The effect of IMWRITE_PNG_STRATEGY_FILTERED is to force more Huffman coding and less string matching; it is somewhat intermediate between IMWRITE_PNG_STRATEGY_DEFAULT and IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY. +- IMWRITE_PNG_STRATEGY_RLE is designed to be almost as fast as IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY, but give better compression for PNG image data. +- The strategy parameter only affects the compression ratio but not the correctness of the compressed output even if it is not set appropriately. +- IMWRITE_PNG_STRATEGY_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. +*/ enum ImwritePNGFlags { - IMWRITE_PNG_STRATEGY_DEFAULT = 0, - IMWRITE_PNG_STRATEGY_FILTERED = 1, - IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY = 2, - IMWRITE_PNG_STRATEGY_RLE = 3, - IMWRITE_PNG_STRATEGY_FIXED = 4 + IMWRITE_PNG_STRATEGY_DEFAULT = 0, //!< Use this value for normal data. + IMWRITE_PNG_STRATEGY_FILTERED = 1, //!< Use this value for data produced by a filter (or predictor).Filtered data consists mostly of small values with a somewhat random distribution. In this case, the compression algorithm is tuned to compress them better. + IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY = 2, //!< Use this value to force Huffman encoding only (no string match). + IMWRITE_PNG_STRATEGY_RLE = 3, //!< Use this value to limit match distances to one (run-length encoding). + IMWRITE_PNG_STRATEGY_FIXED = 4 //!< Using this value prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. }; /** @brief Loads an image from a file. @anchor imread -@param filename Name of file to be loaded. -@param flags Flag that can take values of @ref cv::ImreadModes - The function imread loads an image from the specified file and returns it. If the image cannot be read (because of missing file, improper permissions, unsupported or invalid format), the function -returns an empty matrix ( Mat::data==NULL ). Currently, the following file formats are supported: +returns an empty matrix ( Mat::data==NULL ). + +Currently, the following file formats are supported: - Windows bitmaps - \*.bmp, \*.dib (always supported) - JPEG files - \*.jpeg, \*.jpg, \*.jpe (see the *Notes* section) @@ -125,6 +131,7 @@ returns an empty matrix ( Mat::data==NULL ). Currently, the following file forma @note - The function determines the type of an image by the content, not by the file extension. +- In the case of color images, the decoded images will have the channels stored in **B G R** order. - On Microsoft Windows\* OS and MacOSX\*, the codecs shipped with an OpenCV image (libjpeg, libpng, libtiff, and libjasper) are used by default. So, OpenCV can always read JPEGs, PNGs, and TIFFs. On MacOSX, there is also an option to use native MacOSX image readers. But beware @@ -134,38 +141,35 @@ returns an empty matrix ( Mat::data==NULL ). Currently, the following file forma codecs supplied with an OS image. Install the relevant packages (do not forget the development files, for example, "libjpeg-dev", in Debian\* and Ubuntu\*) to get the codec support or turn on the OPENCV_BUILD_3RDPARTY_LIBS flag in CMake. - -@note In the case of color images, the decoded images will have the channels stored in B G R order. - */ +@param filename Name of file to be loaded. +@param flags Flag that can take values of cv::ImreadModes +*/ CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR ); -/** @brief Loads a multi-page image from a file. (see imread for details.) +/** @brief Loads a multi-page image from a file. +The function imreadmulti loads a multi-page image from the specified file into a vector of Mat objects. @param filename Name of file to be loaded. -@param flags Flag that can take values of @ref cv::ImreadModes, default with IMREAD_ANYCOLOR. +@param flags Flag that can take values of cv::ImreadModes, default with cv::IMREAD_ANYCOLOR. @param mats A vector of Mat objects holding each page, if more than one. - +@sa cv::imread */ CV_EXPORTS_W bool imreadmulti(const String& filename, std::vector& mats, int flags = IMREAD_ANYCOLOR); /** @brief Saves an image to a specified file. -@param filename Name of the file. -@param img Image to be saved. -@param params Format-specific save parameters encoded as pairs, see @ref cv::ImwriteFlags -paramId_1, paramValue_1, paramId_2, paramValue_2, ... . - The function imwrite saves the image to the specified file. The image format is chosen based on the -filename extension (see imread for the list of extensions). Only 8-bit (or 16-bit unsigned (CV_16U) +filename extension (see cv::imread for the list of extensions). Only 8-bit (or 16-bit unsigned (CV_16U) in case of PNG, JPEG 2000, and TIFF) single-channel or 3-channel (with 'BGR' channel order) images can be saved using this function. If the format, depth or channel order is different, use -Mat::convertTo , and cvtColor to convert it before saving. Or, use the universal FileStorage I/O +Mat::convertTo , and cv::cvtColor to convert it before saving. Or, use the universal FileStorage I/O functions to save the image to XML or YAML format. It is possible to store PNG images with an alpha channel using this function. To do this, create 8-bit (or 16-bit) 4-channel image BGRA, where the alpha channel goes last. Fully transparent pixels -should have alpha set to 0, fully opaque pixels should have alpha set to 255/65535. The sample below -shows how to create such a BGRA image and store to PNG file. It also demonstrates how to set custom +should have alpha set to 0, fully opaque pixels should have alpha set to 255/65535. + +The sample below shows how to create such a BGRA image and store to PNG file. It also demonstrates how to set custom compression parameters : @code #include @@ -211,42 +215,44 @@ compression parameters : return 0; } @endcode - */ +@param filename Name of the file. +@param img Image to be saved. +@param params Format-specific parameters encoded as pairs (paramId_1, paramValue_1, paramId_2, paramValue_2, ... .) see cv::ImwriteFlags +*/ CV_EXPORTS_W bool imwrite( const String& filename, InputArray img, const std::vector& params = std::vector()); -/** @overload */ -CV_EXPORTS_W Mat imdecode( InputArray buf, int flags ); - /** @brief Reads an image from a buffer in memory. +The function imdecode reads an image from the specified buffer in the memory. If the buffer is too short or +contains invalid data, the function returns an empty matrix ( Mat::data==NULL ). + +See cv::imread for the list of supported formats and flags description. + +@note In the case of color images, the decoded images will have the channels stored in **B G R** order. @param buf Input array or vector of bytes. -@param flags The same flags as in imread, see @ref cv::ImreadModes. +@param flags The same flags as in cv::imread, see cv::ImreadModes. +*/ +CV_EXPORTS_W Mat imdecode( InputArray buf, int flags ); + +/** @overload +@param buf +@param flags @param dst The optional output placeholder for the decoded matrix. It can save the image reallocations when the function is called repeatedly for images of the same size. - -The function reads an image from the specified buffer in the memory. If the buffer is too short or -contains invalid data, the empty matrix/image is returned. - -See imread for the list of supported formats and flags description. - -@note In the case of color images, the decoded images will have the channels stored in B G R order. - */ +*/ CV_EXPORTS Mat imdecode( InputArray buf, int flags, Mat* dst); /** @brief Encodes an image into a memory buffer. +The function imencode compresses the image and stores it in the memory buffer that is resized to fit the +result. See cv::imwrite for the list of supported formats and flags description. + @param ext File extension that defines the output format. @param img Image to be written. @param buf Output buffer resized to fit the compressed image. -@param params Format-specific parameters. See imwrite and @ref cv::ImwriteFlags. - -The function compresses the image and stores it in the memory buffer that is resized to fit the -result. See imwrite for the list of supported formats and flags description. - -@note cvEncodeImage returns single-row matrix of type CV_8UC1 that contains encoded image as array -of bytes. - */ +@param params Format-specific parameters. See cv::imwrite and cv::ImwriteFlags. +*/ CV_EXPORTS_W bool imencode( const String& ext, InputArray img, CV_OUT std::vector& buf, const std::vector& params = std::vector()); diff --git a/modules/imgcodecs/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp index 336777aee..385bab1e1 100644 --- a/modules/imgcodecs/src/loadsave.cpp +++ b/modules/imgcodecs/src/loadsave.cpp @@ -265,11 +265,11 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0 ) int scale_denom = 1; if( flags > IMREAD_LOAD_GDAL ) { - if( flags & IMREAD_GRAYSCALE_REDUCED_2 ) + if( flags & IMREAD_REDUCED_GRAYSCALE_2 ) scale_denom = 2; - else if( flags & IMREAD_GRAYSCALE_REDUCED_4 ) + else if( flags & IMREAD_REDUCED_GRAYSCALE_4 ) scale_denom = 4; - else if( flags & IMREAD_GRAYSCALE_REDUCED_8 ) + else if( flags & IMREAD_REDUCED_GRAYSCALE_8 ) scale_denom = 8; } From 50a0a167f07fca8a0b7ee324eac7708a67154650 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 2 Oct 2015 18:27:18 +0300 Subject: [PATCH 102/156] fix ffmpeg frame creation (fix #5439) --- modules/videoio/src/cap_ffmpeg_impl.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index 4f743ec76..e869f1b1e 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -1130,6 +1130,11 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo #endif if (!picture) return NULL; + + picture->format = pix_fmt; + picture->width = width; + picture->height = height; + size = avpicture_get_size( (AVPixelFormat) pix_fmt, width, height); if(alloc){ picture_buf = (uint8_t *) malloc(size); From 345cd1242fb22f872a5b1c3f0144762f12f8fe63 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Mon, 5 Oct 2015 12:28:47 +0200 Subject: [PATCH 103/156] do not leak GstMapInfo it is new'ed but never deleted. However it does not need to be global or heap allocated in the first place. --- modules/videoio/src/cap_gstreamer.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/modules/videoio/src/cap_gstreamer.cpp b/modules/videoio/src/cap_gstreamer.cpp index 9d74df6ea..62a18b5a7 100644 --- a/modules/videoio/src/cap_gstreamer.cpp +++ b/modules/videoio/src/cap_gstreamer.cpp @@ -146,7 +146,6 @@ protected: GstElement* sink; #if GST_VERSION_MAJOR > 0 GstSample* sample; - GstMapInfo* info; #endif GstBuffer* buffer; GstCaps* caps; @@ -169,7 +168,6 @@ void CvCapture_GStreamer::init() sink = NULL; #if GST_VERSION_MAJOR > 0 sample = NULL; - info = new GstMapInfo; #endif buffer = NULL; caps = NULL; @@ -318,17 +316,16 @@ IplImage * CvCapture_GStreamer::retrieveFrame(int) #if GST_VERSION_MAJOR == 0 frame->imageData = (char *)GST_BUFFER_DATA(buffer); #else - // the data ptr in GstMapInfo is only valid throughout the mapifo objects life. - // TODO: check if reusing the mapinfo object is ok. - - gboolean success = gst_buffer_map(buffer,info, (GstMapFlags)GST_MAP_READ); + // info.data ptr is valid until next grabFrame where the associated sample is unref'd + GstMapInfo info = GstMapInfo(); + gboolean success = gst_buffer_map(buffer,&info, (GstMapFlags)GST_MAP_READ); if (!success){ //something weird went wrong here. abort. abort. //fprintf(stderr,"GStreamer: unable to map buffer"); return 0; } - frame->imageData = (char*)info->data; - gst_buffer_unmap(buffer,info); + frame->imageData = (char*)info.data; + gst_buffer_unmap(buffer,&info); #endif return frame; From 4760d329374cfbe9d37e01fd1a59718629b04d98 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 5 Oct 2015 19:28:35 +0300 Subject: [PATCH 104/156] ffmpeg: fix invalid NULL pointer access Catched on Ubuntu 12.04 with FFMPEG: codec: YES (ver 53.35.0) format: YES (ver 53.21.1) util: YES (ver 51.22.3) swscale: YES (ver 2.1.0) resample: NO gentoo-style: YES --- modules/videoio/src/cap_ffmpeg_impl.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index 4f743ec76..50ac0a422 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -1269,7 +1269,8 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc, c->gop_size = -1; c->qmin = -1; c->bit_rate = 0; - av_opt_set(c->priv_data,"crf","23", 0); + if (c->priv_data) + av_opt_set(c->priv_data,"crf","23", 0); } #endif From 9da4fe4b0203030940551cd8cc7421dbd77879f3 Mon Sep 17 00:00:00 2001 From: Sergiu Dotenco Date: Tue, 6 Oct 2015 15:09:31 +0200 Subject: [PATCH 105/156] videoio: fixed segmentation fault at frame size change --- modules/videoio/src/cap_ffmpeg_impl.hpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index 4f743ec76..8f2efd5a6 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -750,9 +750,6 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* if( !video_st || !picture->data[0] ) return false; - avpicture_fill((AVPicture*)&rgb_picture, rgb_picture.data[0], AV_PIX_FMT_RGB24, - video_st->codec->width, video_st->codec->height); - if( img_convert_ctx == NULL || frame.width != video_st->codec->width || frame.height != video_st->codec->height ) @@ -775,8 +772,17 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* if (img_convert_ctx == NULL) return false;//CV_Error(0, "Cannot initialize the conversion context!"); + + rgb_picture.data[0] = (uint8_t*)realloc(rgb_picture.data[0], + avpicture_get_size( AV_PIX_FMT_BGR24, + video_st->codec->width, video_st->codec->height )); + frame.data = rgb_picture.data[0]; } + avpicture_fill((AVPicture*)&rgb_picture, rgb_picture.data[0], AV_PIX_FMT_RGB24, + video_st->codec->width, video_st->codec->height); + frame.step = rgb_picture.linesize[0]; + sws_scale( img_convert_ctx, picture->data, From dff7037156779920c3094cad64e828a66b8b9873 Mon Sep 17 00:00:00 2001 From: Aman Verma Date: Tue, 6 Oct 2015 14:23:27 +0000 Subject: [PATCH 106/156] Adding fix for issue 5451 "putText fails with empty std::string" --- modules/imgproc/src/drawing.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/imgproc/src/drawing.cpp b/modules/imgproc/src/drawing.cpp index d2a7c03cd..a968943f4 100644 --- a/modules/imgproc/src/drawing.cpp +++ b/modules/imgproc/src/drawing.cpp @@ -2090,6 +2090,10 @@ void putText( InputOutputArray _img, const String& text, Point org, int thickness, int line_type, bool bottomLeftOrigin ) { + if ( text.empty() ) + { + return; + } Mat img = _img.getMat(); const int* ascii = getFontData(fontFace); From 514b202d7b6f09f38c5cb9c5a7c8a8469477880b Mon Sep 17 00:00:00 2001 From: Sergiu Dotenco Date: Tue, 6 Oct 2015 17:01:28 +0200 Subject: [PATCH 107/156] highgui: CV_WINDOW_AUTOSIZE does not resize with GTK3 --- modules/highgui/src/window_gtk.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index 3d913fa2e..deae665ff 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -246,7 +246,7 @@ cvImageWidget_get_preferred_width (GtkWidget *widget, gint *minimal_width, gint CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget ); if(image_widget->original_image != NULL) { - *minimal_width = image_widget->flags & CV_WINDOW_AUTOSIZE ? + *minimal_width = (image_widget->flags & CV_WINDOW_AUTOSIZE) != CV_WINDOW_AUTOSIZE ? gdk_window_get_width(gtk_widget_get_window(widget)) : image_widget->original_image->cols; } else { @@ -270,7 +270,7 @@ cvImageWidget_get_preferred_height (GtkWidget *widget, gint *minimal_height, gin CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget ); if(image_widget->original_image != NULL) { - *minimal_height = image_widget->flags & CV_WINDOW_AUTOSIZE ? + *minimal_height = (image_widget->flags & CV_WINDOW_AUTOSIZE) != CV_WINDOW_AUTOSIZE ? gdk_window_get_height(gtk_widget_get_window(widget)) : image_widget->original_image->rows; } else { From f2decec3e887dd1539e9613a6eaafe4980e25252 Mon Sep 17 00:00:00 2001 From: berak Date: Tue, 6 Oct 2015 16:14:15 +0200 Subject: [PATCH 108/156] fix zero length std::string in putText() --- modules/imgproc/src/drawing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/src/drawing.cpp b/modules/imgproc/src/drawing.cpp index d2a7c03cd..c422b1d10 100644 --- a/modules/imgproc/src/drawing.cpp +++ b/modules/imgproc/src/drawing.cpp @@ -2111,7 +2111,7 @@ void putText( InputOutputArray _img, const String& text, Point org, pts.reserve(1 << 10); const char **faces = cv::g_HersheyGlyphs; - for( int i = 0; text[i] != '\0'; i++ ) + for( int i = 0; i < (int)text.size(); i++ ) { int c = (uchar)text[i]; Point p; @@ -2158,7 +2158,7 @@ Size getTextSize( const String& text, int fontFace, double fontScale, int thickn int cap_line = (ascii[0] >> 4) & 15; size.height = cvRound((cap_line + base_line)*fontScale + (thickness+1)/2); - for( int i = 0; text[i] != '\0'; i++ ) + for( int i = 0; i < (int)text.size(); i++ ) { int c = (uchar)text[i]; Point p; From fe006897572de0fa9a9efc1d5937837d110f4da8 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 6 Oct 2015 20:42:21 +0300 Subject: [PATCH 109/156] workaround for 32-bit OS on 64-bit x86 CPU --- cmake/OpenCVDetectCXXCompiler.cmake | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmake/OpenCVDetectCXXCompiler.cmake b/cmake/OpenCVDetectCXXCompiler.cmake index 360a08fec..bd3cf49d0 100644 --- a/cmake/OpenCVDetectCXXCompiler.cmake +++ b/cmake/OpenCVDetectCXXCompiler.cmake @@ -116,6 +116,12 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*)") set(AARCH64 1) endif() +# Workaround for 32-bit operating systems on 64-bit x86_64 processor +if(X86_64 AND CMAKE_SIZEOF_VOID_P EQUAL 4 AND NOT FORCE_X86_64) + message(STATUS "sizeof(void) = 4 on x86 / x86_64 processor. Assume 32-bit compilation mode (X86=1)") + unset(X86_64) + set(X86 1) +endif() # Similar code exists in OpenCVConfig.cmake if(NOT DEFINED OpenCV_STATIC) From 15db8243efd24ea35ed8151425a399a9ad1a712a Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Wed, 7 Oct 2015 11:28:57 +0300 Subject: [PATCH 110/156] refactored; added Camera2, notify callbacks, front/back maxCamera sizes; disable new stuff if target API < 21 --- modules/java/CMakeLists.txt | 11 + .../src/java/android+Camera2Renderer.java | 302 +++++++++++++ .../java/android+CameraGLRendererBase.java | 424 ++++++++++++++++++ .../src/java/android+CameraGLSurfaceView.java | 55 ++- .../src/java/android+CameraRenderer.java | 401 +++++------------ 5 files changed, 882 insertions(+), 311 deletions(-) create mode 100644 modules/java/generator/src/java/android+Camera2Renderer.java create mode 100644 modules/java/generator/src/java/android+CameraGLRendererBase.java diff --git a/modules/java/CMakeLists.txt b/modules/java/CMakeLists.txt index 17d190781..3906040df 100644 --- a/modules/java/CMakeLists.txt +++ b/modules/java/CMakeLists.txt @@ -181,6 +181,17 @@ else() list(REMOVE_ITEM handwrittren_lib_project_files_rel "${ANDROID_MANIFEST_FILE}") endif() +# Calc default SDK Target +android_get_compatible_target(android_sdk_target ${ANDROID_NATIVE_API_LEVEL} ${ANDROID_SDK_TARGET} 11) +string(REGEX REPLACE "android-" "" android_sdk_target_num ${android_sdk_target}) + +if( (ANDROID_SDK_TARGET AND ANDROID_SDK_TARGET LESS 21) OR (android_sdk_target_num LESS 21) ) + message(STATUS "[OpenCV for Android SDK]: A new OpenGL Camera Bridge (CameraGLSurfaceView, CameraGLRendererBase, CameraRenderer, Camera2Renderer) is disabled, because ANDROID_SDK_TARGET (${android_sdk_target_num}) < 21") + ocv_list_filterout(handwritten_java_sources "android\\\\+CameraGL") + ocv_list_filterout(handwritten_java_sources "android\\\\+Camera.?Renderer") +endif() + + # IMPORTANT: add dependencies to cmake (we should rerun cmake if any of these files is modified) add_cmake_dependencies(${scripts_gen_java} ${scripts_hdr_parser} ${opencv_public_headers}) diff --git a/modules/java/generator/src/java/android+Camera2Renderer.java b/modules/java/generator/src/java/android+Camera2Renderer.java new file mode 100644 index 000000000..408214057 --- /dev/null +++ b/modules/java/generator/src/java/android+Camera2Renderer.java @@ -0,0 +1,302 @@ +package org.opencv.android; + +import java.util.Arrays; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.SurfaceTexture; +import android.hardware.camera2.CameraAccessException; +import android.hardware.camera2.CameraCaptureSession; +import android.hardware.camera2.CameraCharacteristics; +import android.hardware.camera2.CameraDevice; +import android.hardware.camera2.CameraManager; +import android.hardware.camera2.CaptureRequest; +import android.hardware.camera2.params.StreamConfigurationMap; +import android.os.Handler; +import android.os.HandlerThread; +import android.util.Log; +import android.util.Size; +import android.view.Surface; + +@TargetApi(21) +public class Camera2Renderer extends CameraGLRendererBase { + + protected final String LOGTAG = "Camera2Renderer"; + private CameraDevice mCameraDevice; + private CameraCaptureSession mCaptureSession; + private CaptureRequest.Builder mPreviewRequestBuilder; + private String mCameraID; + private Size mPreviewSize = new Size(-1, -1); + + private HandlerThread mBackgroundThread; + private Handler mBackgroundHandler; + private Semaphore mCameraOpenCloseLock = new Semaphore(1); + + Camera2Renderer(CameraGLSurfaceView view) { + super(view); + } + + @Override + protected void doStart() { + Log.d(LOGTAG, "doStart"); + startBackgroundThread(); + super.doStart(); + } + + + @Override + protected void doStop() { + Log.d(LOGTAG, "doStop"); + super.doStop(); + stopBackgroundThread(); + } + + boolean cacPreviewSize(final int width, final int height) { + Log.i(LOGTAG, "cacPreviewSize: "+width+"x"+height); + if(mCameraID == null) { + Log.e(LOGTAG, "Camera isn't initialized!"); + return false; + } + CameraManager manager = (CameraManager) mView.getContext() + .getSystemService(Context.CAMERA_SERVICE); + try { + CameraCharacteristics characteristics = manager + .getCameraCharacteristics(mCameraID); + StreamConfigurationMap map = characteristics + .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); + int bestWidth = 0, bestHeight = 0; + float aspect = (float)width / height; + for (Size psize : map.getOutputSizes(SurfaceTexture.class)) { + int w = psize.getWidth(), h = psize.getHeight(); + Log.d(LOGTAG, "trying size: "+w+"x"+h); + if ( width >= w && height >= h && + bestWidth <= w && bestHeight <= h && + Math.abs(aspect - (float)w/h) < 0.2 ) { + bestWidth = w; + bestHeight = h; + } + } + Log.i(LOGTAG, "best size: "+bestWidth+"x"+bestHeight); + if( bestWidth == 0 || bestHeight == 0 || + mPreviewSize.getWidth() == bestWidth && + mPreviewSize.getHeight() == bestHeight ) + return false; + else { + mPreviewSize = new Size(bestWidth, bestHeight); + return true; + } + } catch (CameraAccessException e) { + Log.e(LOGTAG, "cacPreviewSize - Camera Access Exception"); + } catch (IllegalArgumentException e) { + Log.e(LOGTAG, "cacPreviewSize - Illegal Argument Exception"); + } catch (SecurityException e) { + Log.e(LOGTAG, "cacPreviewSize - Security Exception"); + } + return false; + } + + @Override + protected void openCamera(int id) { + Log.i(LOGTAG, "openCamera"); + CameraManager manager = (CameraManager) mView.getContext().getSystemService(Context.CAMERA_SERVICE); + try { + String camList[] = manager.getCameraIdList(); + if(camList.length == 0) { + Log.e(LOGTAG, "Error: camera isn't detected."); + return; + } + if(id == CameraBridgeViewBase.CAMERA_ID_ANY) { + mCameraID = camList[0]; + } else { + for (String cameraID : camList) { + CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraID); + if( id == CameraBridgeViewBase.CAMERA_ID_BACK && + characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK || + id == CameraBridgeViewBase.CAMERA_ID_FRONT && + characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) { + mCameraID = cameraID; + break; + } + } + } + if(mCameraID != null) { + if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) { + throw new RuntimeException( + "Time out waiting to lock camera opening."); + } + Log.i(LOGTAG, "Opening camera: " + mCameraID); + manager.openCamera(mCameraID, mStateCallback, mBackgroundHandler); + } + } catch (CameraAccessException e) { + Log.e(LOGTAG, "OpenCamera - Camera Access Exception"); + } catch (IllegalArgumentException e) { + Log.e(LOGTAG, "OpenCamera - Illegal Argument Exception"); + } catch (SecurityException e) { + Log.e(LOGTAG, "OpenCamera - Security Exception"); + } catch (InterruptedException e) { + Log.e(LOGTAG, "OpenCamera - Interrupted Exception"); + } + } + + @Override + protected void closeCamera() { + Log.i(LOGTAG, "closeCamera"); + try { + mCameraOpenCloseLock.acquire(); + if (null != mCaptureSession) { + mCaptureSession.close(); + mCaptureSession = null; + } + if (null != mCameraDevice) { + mCameraDevice.close(); + mCameraDevice = null; + } + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted while trying to lock camera closing.", e); + } finally { + mCameraOpenCloseLock.release(); + } + } + + private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { + + @Override + public void onOpened(CameraDevice cameraDevice) { + mCameraDevice = cameraDevice; + mCameraOpenCloseLock.release(); + createCameraPreviewSession(); + } + + @Override + public void onDisconnected(CameraDevice cameraDevice) { + cameraDevice.close(); + mCameraDevice = null; + mCameraOpenCloseLock.release(); + } + + @Override + public void onError(CameraDevice cameraDevice, int error) { + cameraDevice.close(); + mCameraDevice = null; + mCameraOpenCloseLock.release(); + } + + }; + + private void createCameraPreviewSession() { + int w=mPreviewSize.getWidth(), h=mPreviewSize.getHeight(); + Log.i(LOGTAG, "createCameraPreviewSession("+w+"x"+h+")"); + if(w<0 || h<0) + return; + try { + mCameraOpenCloseLock.acquire(); + if (null == mCameraDevice) { + mCameraOpenCloseLock.release(); + Log.e(LOGTAG, "createCameraPreviewSession: camera isn't opened"); + return; + } + if (null != mCaptureSession) { + mCameraOpenCloseLock.release(); + Log.e(LOGTAG, "createCameraPreviewSession: mCaptureSession is already started"); + return; + } + if(null == mSTexture) { + mCameraOpenCloseLock.release(); + Log.e(LOGTAG, "createCameraPreviewSession: preview SurfaceTexture is null"); + return; + } + mSTexture.setDefaultBufferSize(w, h); + + Surface surface = new Surface(mSTexture); + + mPreviewRequestBuilder = mCameraDevice + .createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); + mPreviewRequestBuilder.addTarget(surface); + + mCameraDevice.createCaptureSession(Arrays.asList(surface), + new CameraCaptureSession.StateCallback() { + @Override + public void onConfigured( CameraCaptureSession cameraCaptureSession) { + mCaptureSession = cameraCaptureSession; + try { + mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); + mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); + + mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), null, mBackgroundHandler); + Log.i(LOGTAG, "CameraPreviewSession has been started"); + } catch (CameraAccessException e) { + Log.e(LOGTAG, "createCaptureSession failed"); + } + mCameraOpenCloseLock.release(); + } + + @Override + public void onConfigureFailed( + CameraCaptureSession cameraCaptureSession) { + Log.e(LOGTAG, "createCameraPreviewSession failed"); + mCameraOpenCloseLock.release(); + } + }, mBackgroundHandler); + } catch (CameraAccessException e) { + Log.e(LOGTAG, "createCameraPreviewSession"); + } catch (InterruptedException e) { + throw new RuntimeException( + "Interrupted while createCameraPreviewSession", e); + } + finally { + //mCameraOpenCloseLock.release(); + } + } + + private void startBackgroundThread() { + Log.i(LOGTAG, "startBackgroundThread"); + stopBackgroundThread(); + mBackgroundThread = new HandlerThread("CameraBackground"); + mBackgroundThread.start(); + mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); + } + + private void stopBackgroundThread() { + Log.i(LOGTAG, "stopBackgroundThread"); + if(mBackgroundThread == null) + return; + mBackgroundThread.quitSafely(); + try { + mBackgroundThread.join(); + mBackgroundThread = null; + mBackgroundHandler = null; + } catch (InterruptedException e) { + Log.e(LOGTAG, "stopBackgroundThread"); + } + } + + @Override + protected void setCameraPreviewSize(int width, int height) { + Log.i(LOGTAG, "setCameraPreviewSize("+width+"x"+height+")"); + if(mMaxCameraWidth > 0 && mMaxCameraWidth < width) width = mMaxCameraWidth; + if(mMaxCameraHeight > 0 && mMaxCameraHeight < height) height = mMaxCameraHeight; + try { + mCameraOpenCloseLock.acquire(); + + boolean needReconfig = cacPreviewSize(width, height); + mCameraWidth = mPreviewSize.getWidth(); + mCameraHeight = mPreviewSize.getHeight(); + + if( !needReconfig ) { + mCameraOpenCloseLock.release(); + return; + } + if (null != mCaptureSession) { + Log.d(LOGTAG, "closing existing previewSession"); + mCaptureSession.close(); + mCaptureSession = null; + } + mCameraOpenCloseLock.release(); + createCameraPreviewSession(); + } catch (InterruptedException e) { + mCameraOpenCloseLock.release(); + throw new RuntimeException("Interrupted while setCameraPreviewSize.", e); + } + } +} diff --git a/modules/java/generator/src/java/android+CameraGLRendererBase.java b/modules/java/generator/src/java/android+CameraGLRendererBase.java new file mode 100644 index 000000000..3971d0cb4 --- /dev/null +++ b/modules/java/generator/src/java/android+CameraGLRendererBase.java @@ -0,0 +1,424 @@ +package org.opencv.android; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import org.opencv.android.CameraGLSurfaceView.CameraTextureListener; + +import android.annotation.TargetApi; +import android.graphics.SurfaceTexture; +import android.opengl.GLES11Ext; +import android.opengl.GLES20; +import android.opengl.GLSurfaceView; +import android.util.Log; +import android.view.View; + +@TargetApi(15) +public abstract class CameraGLRendererBase implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener { + + protected final String LOGTAG = "CameraGLRendererBase"; + + // shaders + private final String vss = "" + + "attribute vec2 vPosition;\n" + + "attribute vec2 vTexCoord;\n" + "varying vec2 texCoord;\n" + + "void main() {\n" + " texCoord = vTexCoord;\n" + + " gl_Position = vec4 ( vPosition.x, vPosition.y, 0.0, 1.0 );\n" + + "}"; + + private final String fssOES = "" + + "#extension GL_OES_EGL_image_external : require\n" + + "precision mediump float;\n" + + "uniform samplerExternalOES sTexture;\n" + + "varying vec2 texCoord;\n" + + "void main() {\n" + + " gl_FragColor = texture2D(sTexture,texCoord);\n" + "}"; + + private final String fss2D = "" + + "precision mediump float;\n" + + "uniform sampler2D sTexture;\n" + + "varying vec2 texCoord;\n" + + "void main() {\n" + + " gl_FragColor = texture2D(sTexture,texCoord);\n" + "}"; + + // coord-s + private final float vertices[] = { + -1, -1, + -1, 1, + 1, -1, + 1, 1 }; + private final float texCoordOES[] = { + 0, 1, + 0, 0, + 1, 1, + 1, 0 }; + private final float texCoord2D[] = { + 0, 0, + 0, 1, + 1, 0, + 1, 1 }; + + private int[] texCamera = {0}, texFBO = {0}, texDraw = {0}; + private int[] FBO = {0}; + private int progOES = -1, prog2D = -1; + private int vPosOES, vTCOES, vPos2D, vTC2D; + + private FloatBuffer vert, texOES, tex2D; + + protected int mCameraWidth = -1, mCameraHeight = -1; + protected int mFBOWidth = -1, mFBOHeight = -1; + protected int mMaxCameraWidth = -1, mMaxCameraHeight = -1; + protected int mCameraIndex = CameraBridgeViewBase.CAMERA_ID_ANY; + + protected SurfaceTexture mSTexture; + + protected boolean mHaveSurface = false; + protected boolean mHaveFBO = false; + protected boolean mUpdateST = false; + protected boolean mEnabled = true; + protected boolean mIsStarted = false; + + protected CameraGLSurfaceView mView; + + protected abstract void openCamera(int id); + protected abstract void closeCamera(); + protected abstract void setCameraPreviewSize(int width, int height); // updates mCameraWidth & mCameraHeight + + public CameraGLRendererBase(CameraGLSurfaceView view) { + mView = view; + int bytes = vertices.length * Float.SIZE / Byte.SIZE; + vert = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer(); + texOES = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer(); + tex2D = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer(); + vert.put(vertices).position(0); + texOES.put(texCoordOES).position(0); + tex2D.put(texCoord2D).position(0); + } + + @Override + public synchronized void onFrameAvailable(SurfaceTexture surfaceTexture) { + //Log.i(LOGTAG, "onFrameAvailable"); + mUpdateST = true; + mView.requestRender(); + } + + @Override + public void onDrawFrame(GL10 gl) { + //Log.i(LOGTAG, "onDrawFrame start"); + + if (!mHaveFBO) + return; + + synchronized(this) { + if (mUpdateST) { + mSTexture.updateTexImage(); + mUpdateST = false; + } + + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); + + CameraTextureListener texListener = mView.getCameraTextureListener(); + if(texListener != null) { + //Log.d(LOGTAG, "haveUserCallback"); + // texCamera(OES) -> texFBO + drawTex(texCamera[0], true, FBO[0]); + + // call user code (texFBO -> texDraw) + boolean modified = texListener.onCameraTexture(texFBO[0], texDraw[0], mCameraWidth, mCameraHeight); + + if(modified) { + // texDraw -> screen + drawTex(texDraw[0], false, 0); + } else { + // texFBO -> screen + drawTex(texFBO[0], false, 0); + } + } else { + Log.d(LOGTAG, "texCamera(OES) -> screen"); + // texCamera(OES) -> screen + drawTex(texCamera[0], true, 0); + } + //Log.i(LOGTAG, "onDrawFrame end"); + } + } + + @Override + public void onSurfaceChanged(GL10 gl, int surfaceWidth, int surfaceHeight) { + Log.i(LOGTAG, "onSurfaceChanged("+surfaceWidth+"x"+surfaceHeight+")"); + mHaveSurface = true; + updateState(); + setPreviewSize(surfaceWidth, surfaceHeight); + } + + @Override + public void onSurfaceCreated(GL10 gl, EGLConfig config) { + Log.i(LOGTAG, "onSurfaceCreated"); + initShaders(); + } + + private void initShaders() { + String strGLVersion = GLES20.glGetString(GLES20.GL_VERSION); + if (strGLVersion != null) + Log.i(LOGTAG, "OpenGL ES version: " + strGLVersion); + + GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + + progOES = loadShader(vss, fssOES); + vPosOES = GLES20.glGetAttribLocation(progOES, "vPosition"); + vTCOES = GLES20.glGetAttribLocation(progOES, "vTexCoord"); + GLES20.glEnableVertexAttribArray(vPosOES); + GLES20.glEnableVertexAttribArray(vTCOES); + + prog2D = loadShader(vss, fss2D); + vPos2D = GLES20.glGetAttribLocation(prog2D, "vPosition"); + vTC2D = GLES20.glGetAttribLocation(prog2D, "vTexCoord"); + GLES20.glEnableVertexAttribArray(vPos2D); + GLES20.glEnableVertexAttribArray(vTC2D); + } + + private void initSurfaceTexture() { + Log.d(LOGTAG, "initSurfaceTexture"); + deleteSurfaceTexture(); + initTexOES(texCamera); + mSTexture = new SurfaceTexture(texCamera[0]); + mSTexture.setOnFrameAvailableListener(this); + } + + private void deleteSurfaceTexture() { + Log.d(LOGTAG, "deleteSurfaceTexture"); + if(mSTexture != null) { + mSTexture.release(); + mSTexture = null; + deleteTex(texCamera); + } + } + + private void initTexOES(int[] tex) { + if(tex.length == 1) { + GLES20.glGenTextures(1, tex, 0); + GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0]); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); + } + } + + private static void deleteTex(int[] tex) { + if(tex.length == 1) { + GLES20.glDeleteTextures(1, tex, 0); + } + } + + private static int loadShader(String vss, String fss) { + Log.d("CameraGLRendererBase", "loadShader"); + int vshader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); + GLES20.glShaderSource(vshader, vss); + GLES20.glCompileShader(vshader); + int[] compiled = new int[1]; + GLES20.glGetShaderiv(vshader, GLES20.GL_COMPILE_STATUS, compiled, 0); + if (compiled[0] == 0) { + Log.e("CameraGLRendererBase", "Could not compile vertex shader: "+GLES20.glGetShaderInfoLog(vshader)); + GLES20.glDeleteShader(vshader); + vshader = 0; + return 0; + } + + int fshader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); + GLES20.glShaderSource(fshader, fss); + GLES20.glCompileShader(fshader); + GLES20.glGetShaderiv(fshader, GLES20.GL_COMPILE_STATUS, compiled, 0); + if (compiled[0] == 0) { + Log.e("CameraGLRendererBase", "Could not compile fragment shader:"+GLES20.glGetShaderInfoLog(fshader)); + GLES20.glDeleteShader(vshader); + GLES20.glDeleteShader(fshader); + fshader = 0; + return 0; + } + + int program = GLES20.glCreateProgram(); + GLES20.glAttachShader(program, vshader); + GLES20.glAttachShader(program, fshader); + GLES20.glLinkProgram(program); + Log.d("CameraGLRendererBase", "shaders were compiled OK"); + GLES20.glDeleteShader(vshader); + GLES20.glDeleteShader(fshader); + + return program; + } + + private void deleteFBO() + { + Log.d(LOGTAG, "deleteFBO("+mFBOWidth+"x"+mFBOHeight+")"); + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); + GLES20.glDeleteFramebuffers(1, FBO, 0); + + deleteTex(texFBO); + deleteTex(texDraw); + mFBOWidth = mFBOHeight = 0; + } + + private void initFBO(int width, int height) + { + Log.d(LOGTAG, "initFBO("+width+"x"+height+")"); + + deleteFBO(); + + GLES20.glGenTextures(1, texDraw, 0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texDraw[0]); + GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); + + GLES20.glGenTextures(1, texFBO, 0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texFBO[0]); + GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); + + //int hFBO; + GLES20.glGenFramebuffers(1, FBO, 0); + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, FBO[0]); + GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, texFBO[0], 0); + Log.d(LOGTAG, "initFBO error status: " + GLES20.glGetError()); + + int FBOstatus = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER); + if (FBOstatus != GLES20.GL_FRAMEBUFFER_COMPLETE) + Log.e(LOGTAG, "initFBO failed, status: " + FBOstatus); + + mFBOWidth = width; + mFBOHeight = height; + } + + // draw texture to FBO or to screen if fbo == 0 + private void drawTex(int tex, boolean isOES, int fbo) + { + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbo); + + if(fbo == 0) + GLES20.glViewport(0, 0, mView.getWidth(), mView.getHeight()); + else + GLES20.glViewport(0, 0, mFBOWidth, mFBOHeight); + + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); + + if(isOES) { + GLES20.glUseProgram(progOES); + GLES20.glVertexAttribPointer(vPosOES, 2, GLES20.GL_FLOAT, false, 4*2, vert); + GLES20.glVertexAttribPointer(vTCOES, 2, GLES20.GL_FLOAT, false, 4*2, texOES); + } else { + GLES20.glUseProgram(prog2D); + GLES20.glVertexAttribPointer(vPos2D, 2, GLES20.GL_FLOAT, false, 4*2, vert); + GLES20.glVertexAttribPointer(vTC2D, 2, GLES20.GL_FLOAT, false, 4*2, tex2D); + } + + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + + if(isOES) { + GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex); + GLES20.glUniform1i(GLES20.glGetUniformLocation(progOES, "sTexture"), 0); + } else { + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex); + GLES20.glUniform1i(GLES20.glGetUniformLocation(prog2D, "sTexture"), 0); + } + + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); + GLES20.glFlush(); + } + + public synchronized void enableView() { + Log.d(LOGTAG, "enableView"); + mEnabled = true; + updateState(); + } + + public synchronized void disableView() { + Log.d(LOGTAG, "disableView"); + mEnabled = false; + updateState(); + } + + protected void updateState() { + Log.d(LOGTAG, "updateState"); + Log.d(LOGTAG, "mEnabled="+mEnabled+", mHaveSurface="+mHaveSurface); + boolean willStart = mEnabled && mHaveSurface && mView.getVisibility() == View.VISIBLE; + if (willStart != mIsStarted) { + if(willStart) doStart(); + else doStop(); + } else { + Log.d(LOGTAG, "keeping State unchanged"); + } + Log.d(LOGTAG, "updateState end"); + } + + protected synchronized void doStart() { + Log.d(LOGTAG, "doStart"); + initSurfaceTexture(); + openCamera(mCameraIndex); + mIsStarted = true; + if(mCameraWidth>0 && mCameraHeight>0) + setPreviewSize(mCameraWidth, mCameraHeight); // start preview and call listener.onCameraViewStarted() + } + + + protected void doStop() { + Log.d(LOGTAG, "doStop"); + synchronized(this) { + mUpdateST = false; + mIsStarted = false; + mHaveFBO = false; + closeCamera(); + deleteSurfaceTexture(); + } + CameraTextureListener listener = mView.getCameraTextureListener(); + if(listener != null) listener.onCameraViewStopped(); + + } + + protected void setPreviewSize(int width, int height) { + synchronized(this) { + mHaveFBO = false; + mCameraWidth = width; + mCameraHeight = height; + setCameraPreviewSize(width, height); // can change mCameraWidth & mCameraHeight + initFBO(mCameraWidth, mCameraHeight); + mHaveFBO = true; + } + + CameraTextureListener listener = mView.getCameraTextureListener(); + if(listener != null) listener.onCameraViewStarted(mCameraWidth, mCameraHeight); + } + + public void setCameraIndex(int cameraIndex) { + disableView(); + mCameraIndex = cameraIndex; + enableView(); + } + + public void setMaxCameraPreviewSize(int maxWidth, int maxHeight) { + disableView(); + mMaxCameraWidth = maxWidth; + mMaxCameraHeight = maxHeight; + enableView(); + } + + public void onResume() { + Log.i(LOGTAG, "onResume"); + } + + public void onPause() { + Log.i(LOGTAG, "onPause"); + mHaveSurface = false; + updateState(); + mCameraWidth = mCameraHeight = -1; + } + +} diff --git a/modules/java/generator/src/java/android+CameraGLSurfaceView.java b/modules/java/generator/src/java/android+CameraGLSurfaceView.java index 45212081e..05f950b47 100644 --- a/modules/java/generator/src/java/android+CameraGLSurfaceView.java +++ b/modules/java/generator/src/java/android+CameraGLSurfaceView.java @@ -1,18 +1,18 @@ package org.opencv.android; -import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame; -import org.opencv.core.Mat; +import org.opencv.R; -import android.app.Activity; import android.content.Context; +import android.content.res.TypedArray; import android.opengl.GLSurfaceView; import android.util.AttributeSet; -import android.view.MotionEvent; +import android.util.Log; import android.view.SurfaceHolder; -import android.widget.TextView; public class CameraGLSurfaceView extends GLSurfaceView { + private static final String LOGTAG = "CameraGLSurfaceView"; + public interface CameraTextureListener { /** * This method is invoked when camera preview has started. After this method is invoked @@ -29,24 +29,33 @@ public class CameraGLSurfaceView extends GLSurfaceView { public void onCameraViewStopped(); /** - * This method is invoked when delivery of the frame needs to be done. - * The returned values - is a modified frame which needs to be displayed on the screen. - * TODO: pass the parameters specifying the format of the frame (BPP, YUV or RGB and etc) + * This method is invoked when a new preview frame from Camera is ready. + * @param texIn - the OpenGL texture ID that contains frame in RGBA format + * @param texOut - the OpenGL texture ID that can be used to store modified frame image t display + * @param width - the width of the frame + * @param height - the height of the frame + * @return `true` if `texOut` should be displayed, `false` - to show `texIn` */ - public boolean onCameraFrame(int texIn, int texOut, int width, int height); + public boolean onCameraTexture(int texIn, int texOut, int width, int height); }; private CameraTextureListener mTexListener; - private CameraRenderer mRenderer; + private CameraGLRendererBase mRenderer; public CameraGLSurfaceView(Context context, AttributeSet attrs) { super(context, attrs); - /*if(android.os.Build.VERSION.SDK_INT >= 21) + TypedArray styledAttrs = getContext().obtainStyledAttributes(attrs, R.styleable.CameraBridgeViewBase); + int cameraIndex = styledAttrs.getInt(R.styleable.CameraBridgeViewBase_camera_id, -1); + styledAttrs.recycle(); + + if(android.os.Build.VERSION.SDK_INT >= 21) mRenderer = new Camera2Renderer(this); - else*/ + else mRenderer = new CameraRenderer(this); + setCameraIndex(cameraIndex); + setEGLContextClientVersion(2); setRenderer(mRenderer); setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); @@ -62,6 +71,14 @@ public class CameraGLSurfaceView extends GLSurfaceView { return mTexListener; } + public void setCameraIndex(int cameraIndex) { + mRenderer.setCameraIndex(cameraIndex); + } + + public void setMaxCameraPreviewSize(int maxWidth, int maxHeight) { + mRenderer.setMaxCameraPreviewSize(maxWidth, maxHeight); + } + @Override public void surfaceCreated(SurfaceHolder holder) { super.surfaceCreated(holder); @@ -69,6 +86,7 @@ public class CameraGLSurfaceView extends GLSurfaceView { @Override public void surfaceDestroyed(SurfaceHolder holder) { + mRenderer.mHaveSurface = false; super.surfaceDestroyed(holder); } @@ -79,20 +97,23 @@ public class CameraGLSurfaceView extends GLSurfaceView { @Override public void onResume() { + Log.i(LOGTAG, "onResume"); super.onResume(); mRenderer.onResume(); } @Override public void onPause() { + Log.i(LOGTAG, "onPause"); mRenderer.onPause(); super.onPause(); } - @Override - public boolean onTouchEvent(MotionEvent e) { - if(e.getAction() == MotionEvent.ACTION_DOWN) - ((Activity)getContext()).openOptionsMenu(); - return true; + public void enableView() { + mRenderer.enableView(); + } + + public void disableView() { + mRenderer.disableView(); } } diff --git a/modules/java/generator/src/java/android+CameraRenderer.java b/modules/java/generator/src/java/android+CameraRenderer.java index ae8edda01..2d668ffa6 100644 --- a/modules/java/generator/src/java/android+CameraRenderer.java +++ b/modules/java/generator/src/java/android+CameraRenderer.java @@ -1,197 +1,132 @@ package org.opencv.android; import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.FloatBuffer; -import java.nio.IntBuffer; import java.util.List; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; - -import org.opencv.android.CameraGLSurfaceView.CameraTextureListener; - -import android.opengl.GLES11Ext; -import android.opengl.GLES20; -import android.opengl.GLSurfaceView; -import android.os.Build; -import android.util.Log; import android.annotation.TargetApi; -import android.graphics.SurfaceTexture; import android.hardware.Camera; import android.hardware.Camera.Size; +import android.os.Build; +import android.util.Log; @TargetApi(15) -public class CameraRenderer implements GLSurfaceView.Renderer, - SurfaceTexture.OnFrameAvailableListener { +@SuppressWarnings("deprecation") +public class CameraRenderer extends CameraGLRendererBase { public static final String LOGTAG = "CameraRenderer"; - // shaders - private final String vss = "" - + "attribute vec2 vPosition;\n" - + "attribute vec2 vTexCoord;\n" + "varying vec2 texCoord;\n" - + "void main() {\n" + " texCoord = vTexCoord;\n" - + " gl_Position = vec4 ( vPosition.x, vPosition.y, 0.0, 1.0 );\n" - + "}"; - - private final String fssOES = "" - + "#extension GL_OES_EGL_image_external : require\n" - + "precision mediump float;\n" - + "uniform samplerExternalOES sTexture;\n" - + "varying vec2 texCoord;\n" - + "void main() {\n" - + " gl_FragColor = texture2D(sTexture,texCoord);\n" + "}"; - - private final String fss2D = "" - + "precision mediump float;\n" - + "uniform sampler2D sTexture;\n" - + "varying vec2 texCoord;\n" - + "void main() {\n" - + " gl_FragColor = texture2D(sTexture,texCoord);\n" + "}"; - - // coord-s - private final float vertices[] = { - -1, -1, - -1, 1, - 1, -1, - 1, 1 }; - private final float texCoordOES[] = { - 0, 1, - 0, 0, - 1, 1, - 1, 0 }; - private final float texCoord2D[] = { - 0, 0, - 0, 1, - 1, 0, - 1, 1 }; - - private int[] texCamera = {0}, texFBO = {0}, texDraw = {0}; - private int[] FBO = {0}; - private int progOES, prog2D; - private int vPosOES, vTCOES, vPos2D, vTC2D; - - private FloatBuffer vert, texOES, tex2D; - private Camera mCamera; private boolean mPreviewStarted = false; - private int mPreviewWidth, mPreviewHeight; - - private SurfaceTexture mSTexture; - - private boolean mGLInit = false; - private boolean mUpdateST = false; - - private CameraGLSurfaceView mView; CameraRenderer(CameraGLSurfaceView view) { - mView = view; - int bytes = vertices.length * Float.SIZE / Byte.SIZE; - vert = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer(); - texOES = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer(); - tex2D = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer(); - vert.put(vertices).position(0); - texOES.put(texCoordOES).position(0); - tex2D.put(texCoord2D).position(0); + super(view); } - public void onResume() { - //nothing - Log.i(LOGTAG, "onResume"); - } - - public void onPause() { - Log.i(LOGTAG, "onPause"); - mGLInit = false; - mUpdateST = false; - + @Override + protected synchronized void closeCamera() { + Log.i(LOGTAG, "closeCamera"); if(mCamera != null) { mCamera.stopPreview(); + mPreviewStarted = false; mCamera.release(); mCamera = null; } - - if(mSTexture != null) { - mSTexture.release(); - mSTexture = null; - deleteTex(texCamera); - } } - public void onSurfaceCreated(GL10 unused, EGLConfig config) { - GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + @Override + protected synchronized void openCamera(int id) { + Log.i(LOGTAG, "openCamera"); + closeCamera(); + if (id == CameraBridgeViewBase.CAMERA_ID_ANY) { + Log.d(LOGTAG, "Trying to open camera with old open()"); + try { + mCamera = Camera.open(); + } + catch (Exception e){ + Log.e(LOGTAG, "Camera is not available (in use or does not exist): " + e.getLocalizedMessage()); + } - progOES = loadShader(vss, fssOES); - vPosOES = GLES20.glGetAttribLocation(progOES, "vPosition"); - vTCOES = GLES20.glGetAttribLocation(progOES, "vTexCoord"); - GLES20.glEnableVertexAttribArray(vPosOES); - GLES20.glEnableVertexAttribArray(vTCOES); + if(mCamera == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { + boolean connected = false; + for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) { + Log.d(LOGTAG, "Trying to open camera with new open(" + camIdx + ")"); + try { + mCamera = Camera.open(camIdx); + connected = true; + } catch (RuntimeException e) { + Log.e(LOGTAG, "Camera #" + camIdx + "failed to open: " + e.getLocalizedMessage()); + } + if (connected) break; + } + } + } else { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { + int localCameraIndex = mCameraIndex; + if (mCameraIndex == CameraBridgeViewBase.CAMERA_ID_BACK) { + Log.i(LOGTAG, "Trying to open BACK camera"); + Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); + for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) { + Camera.getCameraInfo( camIdx, cameraInfo ); + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { + localCameraIndex = camIdx; + break; + } + } + } else if (mCameraIndex == CameraBridgeViewBase.CAMERA_ID_FRONT) { + Log.i(LOGTAG, "Trying to open FRONT camera"); + Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); + for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) { + Camera.getCameraInfo( camIdx, cameraInfo ); + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { + localCameraIndex = camIdx; + break; + } + } + } + if (localCameraIndex == CameraBridgeViewBase.CAMERA_ID_BACK) { + Log.e(LOGTAG, "Back camera not found!"); + } else if (localCameraIndex == CameraBridgeViewBase.CAMERA_ID_FRONT) { + Log.e(LOGTAG, "Front camera not found!"); + } else { + Log.d(LOGTAG, "Trying to open camera with new open(" + localCameraIndex + ")"); + try { + mCamera = Camera.open(localCameraIndex); + } catch (RuntimeException e) { + Log.e(LOGTAG, "Camera #" + localCameraIndex + "failed to open: " + e.getLocalizedMessage()); + } + } + } + } + if(mCamera == null) { + Log.e(LOGTAG, "Error: can't open camera"); + return; + } + Camera.Parameters params = mCamera.getParameters(); + List FocusModes = params.getSupportedFocusModes(); + if (FocusModes != null && FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) + { + params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); + } + mCamera.setParameters(params); - prog2D = loadShader(vss, fss2D); - vPos2D = GLES20.glGetAttribLocation(prog2D, "vPosition"); - vTC2D = GLES20.glGetAttribLocation(prog2D, "vTexCoord"); - GLES20.glEnableVertexAttribArray(vPos2D); - GLES20.glEnableVertexAttribArray(vTC2D); - - initTexOES(texCamera); - mSTexture = new SurfaceTexture(texCamera[0]); - mSTexture.setOnFrameAvailableListener(this); - - mCamera = Camera.open(); try { mCamera.setPreviewTexture(mSTexture); } catch (IOException ioe) { - } - - mGLInit = true; - } - - public void onDrawFrame(GL10 unused) { - if (!mGLInit) - return; - GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); - - synchronized (this) { - if (mUpdateST) { - mSTexture.updateTexImage(); - mUpdateST = false; - } - } - - CameraTextureListener texListener = mView.getCameraTextureListener(); - if(texListener != null) { - Log.d(LOGTAG, "haveUserCallback"); - // texCamera(OES) -> texFBO - drawTex(texCamera[0], true, FBO[0]); - - // call user code (texFBO -> texDraw) - boolean modified = texListener.onCameraFrame(texFBO[0], texDraw[0], mPreviewWidth, mPreviewHeight); - - if(modified) { - // texDraw -> screen - drawTex(texDraw[0], false, 0); - } else { - // texFBO -> screen - drawTex(texFBO[0], false, 0); - } - } else { - // texCamera(OES) -> screen - drawTex(texCamera[0], true, 0); + Log.e(LOGTAG, "setPreviewTexture() failed: " + ioe.getMessage()); } } - public void onSurfaceChanged(GL10 unused, int width, int height) { - Log.i(LOGTAG, "onSurfaceChanged("+width+"x"+height+")"); - - if(mCamera == null) + @Override + public synchronized void setCameraPreviewSize(int width, int height) { + Log.i(LOGTAG, "setCameraPreviewSize: "+width+"x"+height); + if(mCamera == null) { + Log.e(LOGTAG, "Camera isn't initialized!"); return; - if(mPreviewStarted) { - mCamera.stopPreview(); - mPreviewStarted = false; } + if(mMaxCameraWidth > 0 && mMaxCameraWidth < width) width = mMaxCameraWidth; + if(mMaxCameraHeight > 0 && mMaxCameraHeight < height) height = mMaxCameraHeight; + Camera.Parameters param = mCamera.getParameters(); List psize = param.getSupportedPreviewSizes(); int bestWidth = 0, bestHeight = 0; @@ -207,147 +142,25 @@ public class CameraRenderer implements GLSurfaceView.Renderer, bestHeight = h; } } - if(bestWidth > 0 && bestHeight > 0) { - param.setPreviewSize(bestWidth, bestHeight); - Log.i(LOGTAG, "selected size: "+bestWidth+" x "+bestHeight); - - GLES20.glViewport(0, 0, bestWidth, bestWidth); - initFBO(bestWidth, bestHeight); - mPreviewWidth = bestWidth; - mPreviewHeight = bestHeight; + if(bestWidth <= 0 || bestHeight <= 0) { + bestWidth = psize.get(0).width; + bestHeight = psize.get(0).height; + Log.e(LOGTAG, "Error: best size was not selected, using "+bestWidth+" x "+bestHeight); + } else { + Log.i(LOGTAG, "Selected best size: "+bestWidth+" x "+bestHeight); } + + if(mPreviewStarted) { + mCamera.stopPreview(); + mPreviewStarted = false; + } + mCameraWidth = bestWidth; + mCameraHeight = bestHeight; + param.setPreviewSize(bestWidth, bestHeight); } - //param.set("orientation", "landscape"); + param.set("orientation", "landscape"); mCamera.setParameters(param); mCamera.startPreview(); mPreviewStarted = true; } - - public synchronized void onFrameAvailable(SurfaceTexture st) { - mUpdateST = true; - mView.requestRender(); - } - - private void initTexOES(int[] tex) { - if(tex.length == 1) { - GLES20.glGenTextures(1, tex, 0); - GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0]); - GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); - GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); - GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); - GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); - } - } - - private void deleteTex(int[] tex) { - if(tex.length == 1) { - GLES20.glDeleteTextures(1, tex, 0); - } - } - - private static int loadShader(String vss, String fss) { - int vshader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); - GLES20.glShaderSource(vshader, vss); - GLES20.glCompileShader(vshader); - int[] compiled = new int[1]; - GLES20.glGetShaderiv(vshader, GLES20.GL_COMPILE_STATUS, compiled, 0); - if (compiled[0] == 0) { - Log.e(LOGTAG, "Could not compile vertex shader"); - Log.v(LOGTAG, "Could not compile vertex shader:"+GLES20.glGetShaderInfoLog(vshader)); - GLES20.glDeleteShader(vshader); - vshader = 0; - } - - int fshader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); - GLES20.glShaderSource(fshader, fss); - GLES20.glCompileShader(fshader); - GLES20.glGetShaderiv(fshader, GLES20.GL_COMPILE_STATUS, compiled, 0); - if (compiled[0] == 0) { - Log.e("Renderer", "Could not compile fragment shader"); - Log.v("Renderer", "Could not compile fragment shader:"+GLES20.glGetShaderInfoLog(fshader)); - GLES20.glDeleteShader(fshader); - fshader = 0; - } - - int program = GLES20.glCreateProgram(); - GLES20.glAttachShader(program, vshader); - GLES20.glAttachShader(program, fshader); - GLES20.glLinkProgram(program); - - return program; - } - - private void releaseFBO() - { - - GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); - GLES20.glDeleteFramebuffers(1, FBO, 0); - - deleteTex(texFBO); - deleteTex(texDraw); - } - - private void initFBO(int width, int height) - { - Log.d(LOGTAG, "initFBO("+width+"x"+height+")"); - releaseFBO(); - - GLES20.glGenTextures(1, texDraw, 0); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texDraw[0]); - GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); - GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); - GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); - GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); - GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); - - GLES20.glGenTextures(1, texFBO, 0); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texFBO[0]); - GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); - GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); - GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); - GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); - GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); - - //int hFBO; - GLES20.glGenFramebuffers(1, FBO, 0); - GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, FBO[0]); - GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, texFBO[0], 0); - Log.d(LOGTAG, "initFBO status: " + GLES20.glGetError()); - - if (GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER) != GLES20.GL_FRAMEBUFFER_COMPLETE) - Log.e(LOGTAG, "initFBO failed: " + GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER)); - - //GLES20.glViewport(0, 0, width, height); - } - - // draw texture to FBO or to screen if fbo == 0 - private void drawTex(int tex, boolean isOES, int fbo) - { - GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbo); - GLES20.glViewport(0, 0, mPreviewWidth, mPreviewHeight); - GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); - - if(isOES) { - GLES20.glUseProgram(progOES); - GLES20.glVertexAttribPointer(vPosOES, 2, GLES20.GL_FLOAT, false, 4*2, vert); - GLES20.glVertexAttribPointer(vTCOES, 2, GLES20.GL_FLOAT, false, 4*2, texOES); - } else { - GLES20.glUseProgram(prog2D); - GLES20.glVertexAttribPointer(vPos2D, 2, GLES20.GL_FLOAT, false, 4*2, vert); - GLES20.glVertexAttribPointer(vTC2D, 2, GLES20.GL_FLOAT, false, 4*2, tex2D); - } - - GLES20.glActiveTexture(GLES20.GL_TEXTURE0); - - if(isOES) { - GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex); - GLES20.glUniform1i(GLES20.glGetUniformLocation(progOES, "sTexture"), 0); - } else { - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex); - GLES20.glUniform1i(GLES20.glGetUniformLocation(prog2D, "sTexture"), 0); - } - - GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); - GLES20.glFlush(); - } } \ No newline at end of file From a0411054919432b30e70aadba3bc647654ca570d Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Wed, 7 Oct 2015 18:59:43 +0300 Subject: [PATCH 111/156] refactoring Tutorial-4 using new OpenCV CameraGLSurfaceView --- samples/android/tutorial-4-opencl/.cproject | 4 +- .../android/tutorial-4-opencl/jni/Android.mk | 4 +- .../tutorial-4-opencl/jni/CLprocessor.cpp | 76 +++- .../tutorial-4-opencl/jni/GLrender.cpp | 375 ------------------ .../android/tutorial-4-opencl/jni/common.hpp | 2 +- samples/android/tutorial-4-opencl/jni/jni.c | 30 +- .../samples/tutorial4/Camera2Renderer.java | 281 ------------- .../samples/tutorial4/CameraRenderer.java | 75 ---- .../samples/tutorial4/MyGLRendererBase.java | 117 ------ .../samples/tutorial4/MyGLSurfaceView.java | 133 +++++-- ...{NativeGLRenderer.java => NativePart.java} | 12 +- .../samples/tutorial4/Tutorial4Activity.java | 13 +- 12 files changed, 188 insertions(+), 934 deletions(-) delete mode 100644 samples/android/tutorial-4-opencl/jni/GLrender.cpp delete mode 100644 samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/Camera2Renderer.java delete mode 100644 samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/CameraRenderer.java delete mode 100644 samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/MyGLRendererBase.java rename samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/{NativeGLRenderer.java => NativePart.java} (51%) diff --git a/samples/android/tutorial-4-opencl/.cproject b/samples/android/tutorial-4-opencl/.cproject index 9f3b5fd84..90fc6c97f 100644 --- a/samples/android/tutorial-4-opencl/.cproject +++ b/samples/android/tutorial-4-opencl/.cproject @@ -5,6 +5,7 @@ + @@ -12,7 +13,6 @@ - @@ -28,7 +28,7 @@ diff --git a/samples/android/tutorial-4-opencl/jni/Android.mk b/samples/android/tutorial-4-opencl/jni/Android.mk index fa44bf8c5..dacd0f665 100644 --- a/samples/android/tutorial-4-opencl/jni/Android.mk +++ b/samples/android/tutorial-4-opencl/jni/Android.mk @@ -21,7 +21,7 @@ endif LOCAL_C_INCLUDES += $(OPENCL_SDK)/include LOCAL_LDLIBS += -L$(OPENCL_SDK)/lib/$(TARGET_ARCH_ABI) -lOpenCL -LOCAL_MODULE := JNIrender -LOCAL_SRC_FILES := jni.c GLrender.cpp CLprocessor.cpp +LOCAL_MODULE := JNIpart +LOCAL_SRC_FILES := jni.c CLprocessor.cpp LOCAL_LDLIBS += -llog -lGLESv2 -lEGL include $(BUILD_SHARED_LIBRARY) \ No newline at end of file diff --git a/samples/android/tutorial-4-opencl/jni/CLprocessor.cpp b/samples/android/tutorial-4-opencl/jni/CLprocessor.cpp index a46cac424..b7bf530b9 100644 --- a/samples/android/tutorial-4-opencl/jni/CLprocessor.cpp +++ b/samples/android/tutorial-4-opencl/jni/CLprocessor.cpp @@ -2,6 +2,7 @@ #define CL_USE_DEPRECATED_OPENCL_1_1_APIS /*let's give a chance for OpenCL 1.1 devices*/ #include +#include #include #include @@ -82,7 +83,7 @@ cl::CommandQueue theQueue; cl::Program theProgB2B, theProgI2B, theProgI2I; bool haveOpenCL = false; -void initCL() +extern "C" void initCL() { dumpCLinfo(); @@ -144,14 +145,19 @@ void initCL() LOGD("initCL completed"); } -void closeCL() +extern "C" void closeCL() { } #define GL_TEXTURE_2D 0x0DE1 void procOCL_I2I(int texIn, int texOut, int w, int h) { - if(!haveOpenCL) return; + LOGD("Processing OpenCL Direct (image2d)"); + if(!haveOpenCL) + { + LOGE("OpenCL isn't initialized"); + return; + } LOGD("procOCL_I2I(%d, %d, %d, %d)", texIn, texOut, w, h); cl::ImageGL imgIn (theContext, CL_MEM_READ_ONLY, GL_TEXTURE_2D, 0, texIn); @@ -185,7 +191,12 @@ void procOCL_I2I(int texIn, int texOut, int w, int h) void procOCL_OCV(int texIn, int texOut, int w, int h) { - if(!haveOpenCL) return; + LOGD("Processing OpenCL via OpenCV"); + if(!haveOpenCL) + { + LOGE("OpenCL isn't initialized"); + return; + } int64_t t = getTimeMs(); cl::ImageGL imgIn (theContext, CL_MEM_READ_ONLY, GL_TEXTURE_2D, 0, texIn); @@ -219,3 +230,60 @@ void procOCL_OCV(int texIn, int texOut, int w, int h) cv::ocl::finish(); LOGD("uploading results to texture costs %d ms", getTimeInterval(t)); } + +void drawFrameProcCPU(int w, int h, int texOut) +{ + LOGD("Processing on CPU"); + int64_t t; + + // let's modify pixels in FBO texture in C++ code (on CPU) + const int BUFF_SIZE = 1<<24;//2k*2k*4; + static char tmpBuff[BUFF_SIZE]; + if(w*h > BUFF_SIZE) + { + LOGE("Internal temp buffer is too small, can't make CPU frame processing"); + return; + } + + // read + t = getTimeMs(); + // expecting FBO to be bound + glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, tmpBuff); + LOGD("glReadPixels() costs %d ms", getTimeInterval(t)); + + // modify + t = getTimeMs(); + cv::Mat m(h, w, CV_8UC4, tmpBuff); + cv::Laplacian(m, m, CV_8U); + m *= 10; + LOGD("Laplacian() costs %d ms", getTimeInterval(t)); + + // write back + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texOut); + t = getTimeMs(); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, tmpBuff); + LOGD("glTexSubImage2D() costs %d ms", getTimeInterval(t)); +} + + +enum ProcMode {PROC_MODE_NO_PROC=0, PROC_MODE_CPU=1, PROC_MODE_OCL_DIRECT=2, PROC_MODE_OCL_OCV=3}; + +extern "C" void processFrame(int tex1, int tex2, int w, int h, int mode) +{ + switch(mode) + { + //case PROC_MODE_NO_PROC: + case PROC_MODE_CPU: + drawFrameProcCPU(w, h, tex2); + break; + case PROC_MODE_OCL_DIRECT: + procOCL_I2I(tex1, tex2, w, h); + break; + case PROC_MODE_OCL_OCV: + procOCL_OCV(tex1, tex2, w, h); + break; + default: + LOGE("Unexpected processing mode: %d", mode); + } +} diff --git a/samples/android/tutorial-4-opencl/jni/GLrender.cpp b/samples/android/tutorial-4-opencl/jni/GLrender.cpp deleted file mode 100644 index 5c2862026..000000000 --- a/samples/android/tutorial-4-opencl/jni/GLrender.cpp +++ /dev/null @@ -1,375 +0,0 @@ -#include -#include - -#include -#include - -#include "common.hpp" - -float vertices[] = { - -1.0f, -1.0f, - -1.0f, 1.0f, - 1.0f, -1.0f, - 1.0f, 1.0f -}; -float texCoordOES[] = { - 0.0f, 1.0f, - 0.0f, 0.0f, - 1.0f, 1.0f, - 1.0f, 0.0f -}; -float texCoord2D[] = { - 0.0f, 0.0f, - 0.0f, 1.0f, - 1.0f, 0.0f, - 1.0f, 1.0f -}; - -const char vss[] = \ - "attribute vec2 vPosition;\n" \ - "attribute vec2 vTexCoord;\n" \ - "varying vec2 texCoord;\n" \ - "void main() {\n" \ - " texCoord = vTexCoord;\n" \ - " gl_Position = vec4 ( vPosition, 0.0, 1.0 );\n" \ - "}"; - -const char fssOES[] = \ - "#extension GL_OES_EGL_image_external : require\n" \ - "precision mediump float;\n" \ - "uniform samplerExternalOES sTexture;\n" \ - "varying vec2 texCoord;\n" \ - "void main() {\n" \ - " gl_FragColor = texture2D(sTexture,texCoord);\n" \ - "}"; - -const char fss2D[] = \ - "precision mediump float;\n" \ - "uniform sampler2D sTexture;\n" \ - "varying vec2 texCoord;\n" \ - "void main() {\n" \ - " gl_FragColor = texture2D(sTexture,texCoord);\n" \ - "}"; - -GLuint progOES = 0; -GLuint prog2D = 0; - -GLint vPosOES, vTCOES; -GLint vPos2D, vTC2D; - -GLuint FBOtex = 0, FBOtex2 = 0; -GLuint FBO = 0; - -GLuint texOES = 0; -int texWidth = 0, texHeight = 0; - -enum ProcMode {PROC_MODE_NO_PROC=0, PROC_MODE_CPU=1, PROC_MODE_OCL_DIRECT=2, PROC_MODE_OCL_OCV=3}; - -ProcMode procMode = PROC_MODE_NO_PROC; - -static inline void deleteTex(GLuint* tex) -{ - if(tex && *tex) - { - glDeleteTextures(1, tex); - *tex = 0; - } -} - -static void releaseFBO() -{ - if (FBO != 0) - { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &FBO); - FBO = 0; - } - deleteTex(&FBOtex); - deleteTex(&FBOtex2); - glDeleteProgram(prog2D); - prog2D = 0; -} - -static inline void logShaderCompileError(GLuint shader, bool isProgram = false) -{ - GLchar msg[512]; - msg[0] = 0; - GLsizei len; - if(isProgram) - glGetProgramInfoLog(shader, sizeof(msg)-1, &len, msg); - else - glGetShaderInfoLog(shader, sizeof(msg)-1, &len, msg); - LOGE("Could not compile shader/program: %s", msg); -} - -static int makeShaderProg(const char* vss, const char* fss) -{ - LOGD("makeShaderProg: setup GL_VERTEX_SHADER"); - GLuint vshader = glCreateShader(GL_VERTEX_SHADER); - const GLchar* text = vss; - glShaderSource(vshader, 1, &text, 0); - glCompileShader(vshader); - GLint compiled; - glGetShaderiv(vshader, GL_COMPILE_STATUS, &compiled); - if (!compiled) { - logShaderCompileError(vshader); - glDeleteShader(vshader); - vshader = 0; - } - - LOGD("makeShaderProg: setup GL_FRAGMENT_SHADER"); - GLuint fshader = glCreateShader(GL_FRAGMENT_SHADER); - text = fss; - glShaderSource(fshader, 1, &text, 0); - glCompileShader(fshader); - glGetShaderiv(fshader, GL_COMPILE_STATUS, &compiled); - if (!compiled) { - logShaderCompileError(fshader); - glDeleteShader(fshader); - fshader = 0; - } - - LOGD("makeShaderProg: glCreateProgram"); - GLuint program = glCreateProgram(); - glAttachShader(program, vshader); - glAttachShader(program, fshader); - glLinkProgram(program); - GLint linked; - glGetProgramiv(program, GL_LINK_STATUS, &linked); - if (!linked) - { - logShaderCompileError(program, true); - glDeleteProgram(program); - program = 0; - } - glValidateProgram(program); - GLint validated; - glGetProgramiv(program, GL_VALIDATE_STATUS, &validated); - if (!validated) - { - logShaderCompileError(program, true); - glDeleteProgram(program); - program = 0; - } - - if(vshader) glDeleteShader(vshader); - if(fshader) glDeleteShader(fshader); - - return program; -} - - -static void initFBO(int width, int height) -{ - LOGD("initFBO(%d, %d)", width, height); - releaseFBO(); - - glGenTextures(1, &FBOtex2); - glBindTexture(GL_TEXTURE_2D, FBOtex2); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glGenTextures(1, &FBOtex); - glBindTexture(GL_TEXTURE_2D, FBOtex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - //int hFBO; - glGenFramebuffers(1, &FBO); - glBindFramebuffer(GL_FRAMEBUFFER, FBO); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FBOtex, 0); - LOGD("initFBO status: %d", glGetError()); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - LOGE("initFBO failed: %d", glCheckFramebufferStatus(GL_FRAMEBUFFER)); - - prog2D = makeShaderProg(vss, fss2D); - vPos2D = glGetAttribLocation(prog2D, "vPosition"); - vTC2D = glGetAttribLocation(prog2D, "vTexCoord"); - glEnableVertexAttribArray(vPos2D); - glEnableVertexAttribArray(vTC2D); -} - -void drawTex(int tex, GLenum texType, GLuint fbo) -{ - int64_t t = getTimeMs(); - //draw texture to FBO or to screen - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glViewport(0, 0, texWidth, texHeight); - - glClear(GL_COLOR_BUFFER_BIT); - - GLuint prog = texType == GL_TEXTURE_EXTERNAL_OES ? progOES : prog2D; - GLint vPos = texType == GL_TEXTURE_EXTERNAL_OES ? vPosOES : vPos2D; - GLint vTC = texType == GL_TEXTURE_EXTERNAL_OES ? vTCOES : vTC2D; - float* texCoord = texType == GL_TEXTURE_EXTERNAL_OES ? texCoordOES : texCoord2D; - glUseProgram(prog); - glVertexAttribPointer(vPos, 2, GL_FLOAT, false, 4*2, vertices); - glVertexAttribPointer(vTC, 2, GL_FLOAT, false, 4*2, texCoord); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texType, tex); - glUniform1i(glGetUniformLocation(prog, "sTexture"), 0); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glFlush(); - LOGD("drawTex(%u) costs %d ms", tex, getTimeInterval(t)); -} - -void drawFrameOrig() -{ - drawTex(texOES, GL_TEXTURE_EXTERNAL_OES, 0); -} - -void procCPU(char* buff, int w, int h) -{ - int64_t t = getTimeMs(); - cv::Mat m(h, w, CV_8UC4, buff); - cv::Laplacian(m, m, CV_8U); - m *= 10; - LOGD("procCPU() costs %d ms", getTimeInterval(t)); -} - -void drawFrameProcCPU() -{ - int64_t t; - drawTex(texOES, GL_TEXTURE_EXTERNAL_OES, FBO); - - // let's modify pixels in FBO texture in C++ code (on CPU) - const int BUFF_SIZE = 1<<24;//2k*2k*4; - static char tmpBuff[BUFF_SIZE]; - if(texWidth*texHeight > BUFF_SIZE) - { - LOGE("Internal temp buffer is too small, can't make CPU frame processing"); - return; - } - - // read - t = getTimeMs(); - glReadPixels(0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_BYTE, tmpBuff); - LOGD("glReadPixels() costs %d ms", getTimeInterval(t)); - - // modify - procCPU(tmpBuff, texWidth, texHeight); - - // write back - t = getTimeMs(); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_BYTE, tmpBuff); - LOGD("glTexSubImage2D() costs %d ms", getTimeInterval(t)); - - // render to screen - drawTex(FBOtex, GL_TEXTURE_2D, 0); -} - -void procOCL_I2I(int texIn, int texOut, int w, int h); -void procOCL_OCV(int texIn, int texOut, int w, int h); -void drawFrameProcOCL() -{ - drawTex(texOES, GL_TEXTURE_EXTERNAL_OES, FBO); - - // modify pixels in FBO texture using OpenCL and CL-GL interop - procOCL_I2I(FBOtex, FBOtex2, texWidth, texHeight); - - // render to screen - drawTex(FBOtex2, GL_TEXTURE_2D, 0); -} - -void drawFrameProcOCLOCV() -{ - drawTex(texOES, GL_TEXTURE_EXTERNAL_OES, FBO); - - // modify pixels in FBO texture using OpenCL and CL-GL interop - procOCL_OCV(FBOtex, FBOtex2, texWidth, texHeight); - - // render to screen - drawTex(FBOtex2, GL_TEXTURE_2D, 0); -} - -extern "C" void drawFrame() -{ - LOGD("*** drawFrame() ***"); - int64_t t = getTimeMs(); - - switch(procMode) - { - case PROC_MODE_NO_PROC: drawFrameOrig(); break; - case PROC_MODE_CPU: drawFrameProcCPU(); break; - case PROC_MODE_OCL_DIRECT: drawFrameProcOCL(); break; - case PROC_MODE_OCL_OCV: drawFrameProcOCLOCV(); break; - default: drawFrameOrig(); - } - - glFinish(); - LOGD("*** drawFrame() costs %d ms ***", getTimeInterval(t)); -} - -void closeCL(); -extern "C" void closeGL() -{ - closeCL(); - LOGD("closeGL"); - deleteTex(&texOES); - - glUseProgram(0); - glDeleteProgram(progOES); - progOES = 0; - - releaseFBO(); -} - -void initCL(); -extern "C" int initGL() -{ - LOGD("initGL"); - - closeGL(); - - const char* vs = (const char*)glGetString(GL_VERSION); - LOGD("GL_VERSION = %s", vs); - - progOES = makeShaderProg(vss, fssOES); - vPosOES = glGetAttribLocation(progOES, "vPosition"); - vTCOES = glGetAttribLocation(progOES, "vTexCoord"); - glEnableVertexAttribArray(vPosOES); - glEnableVertexAttribArray(vTCOES); - - glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - - texOES = 0; - glGenTextures(1, &texOES); - glBindTexture(GL_TEXTURE_EXTERNAL_OES, texOES); - glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - initCL(); - - return texOES; -} - -extern "C" void changeSize(int width, int height) -{ - const int MAX_W=1<<11, MAX_H=1<<11; - LOGD("changeSize: %dx%d", width, height); - texWidth = width <= MAX_W ? width : MAX_W; - texHeight = height <= MAX_H ? height : MAX_H; - initFBO(texWidth, texHeight); -} - -extern "C" void setProcessingMode(int mode) -{ - switch(mode) - { - case PROC_MODE_NO_PROC: procMode = PROC_MODE_NO_PROC; break; - case PROC_MODE_CPU: procMode = PROC_MODE_CPU; break; - case PROC_MODE_OCL_DIRECT: procMode = PROC_MODE_OCL_DIRECT; break; - case PROC_MODE_OCL_OCV: procMode = PROC_MODE_OCL_OCV; break; - } -} diff --git a/samples/android/tutorial-4-opencl/jni/common.hpp b/samples/android/tutorial-4-opencl/jni/common.hpp index 20b882a9f..2923803f2 100644 --- a/samples/android/tutorial-4-opencl/jni/common.hpp +++ b/samples/android/tutorial-4-opencl/jni/common.hpp @@ -1,5 +1,5 @@ #include -#define LOG_TAG "JNIRenderer" +#define LOG_TAG "JNIpart" //#define LOGD(...) #define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) diff --git a/samples/android/tutorial-4-opencl/jni/jni.c b/samples/android/tutorial-4-opencl/jni/jni.c index 7be35a000..0c48ab606 100644 --- a/samples/android/tutorial-4-opencl/jni/jni.c +++ b/samples/android/tutorial-4-opencl/jni/jni.c @@ -1,32 +1,20 @@ #include -int initGL(); -void closeGL(); -void changeSize(int width, int height); -void drawFrame(); -void setProcessingMode(int mode); +int initCL(); +void closeCL(); +void processFrame(int tex1, int tex2, int w, int h, int mode); -JNIEXPORT jint JNICALL Java_org_opencv_samples_tutorial4_NativeGLRenderer_initGL(JNIEnv * env, jclass cls) +JNIEXPORT jint JNICALL Java_org_opencv_samples_tutorial4_NativePart_initCL(JNIEnv * env, jclass cls) { - return initGL(); + return initCL(); } -JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativeGLRenderer_closeGL(JNIEnv * env, jclass cls) +JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativePart_closeCL(JNIEnv * env, jclass cls) { - closeGL(); + closeCL(); } -JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativeGLRenderer_changeSize(JNIEnv * env, jclass cls, jint width, jint height) +JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativePart_processFrame(JNIEnv * env, jclass cls, jint tex1, jint tex2, jint w, jint h, jint mode) { - changeSize(width, height); -} - -JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativeGLRenderer_drawFrame(JNIEnv * env, jclass cls) -{ - drawFrame(); -} - -JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativeGLRenderer_setProcessingMode(JNIEnv * env, jclass cls, jint mode) -{ - setProcessingMode(mode); + processFrame(tex1, tex2, w, h, mode); } diff --git a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/Camera2Renderer.java b/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/Camera2Renderer.java deleted file mode 100644 index 217268a78..000000000 --- a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/Camera2Renderer.java +++ /dev/null @@ -1,281 +0,0 @@ -package org.opencv.samples.tutorial4; - -import java.util.Arrays; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.graphics.SurfaceTexture; -import android.hardware.camera2.CameraAccessException; -import android.hardware.camera2.CameraCaptureSession; -import android.hardware.camera2.CameraCharacteristics; -import android.hardware.camera2.CameraDevice; -import android.hardware.camera2.CameraManager; -import android.hardware.camera2.CaptureRequest; -import android.hardware.camera2.params.StreamConfigurationMap; -import android.os.Handler; -import android.os.HandlerThread; -import android.util.Log; -import android.util.Size; -import android.view.Surface; - -@SuppressLint("NewApi") public class Camera2Renderer extends MyGLRendererBase { - - protected final String LOGTAG = "Camera2Renderer"; - private CameraDevice mCameraDevice; - private CameraCaptureSession mCaptureSession; - private CaptureRequest.Builder mPreviewRequestBuilder; - private String mCameraID; - private Size mPreviewSize = new Size(1280, 720); - - private HandlerThread mBackgroundThread; - private Handler mBackgroundHandler; - private Semaphore mCameraOpenCloseLock = new Semaphore(1); - - Camera2Renderer(MyGLSurfaceView view) { - super(view); - } - - public void onResume() { - stopBackgroundThread(); - super.onResume(); - startBackgroundThread(); - } - - public void onPause() { - super.onPause(); - stopBackgroundThread(); - } - - boolean cacPreviewSize(final int width, final int height) { - Log.i(LOGTAG, "cacPreviewSize: "+width+"x"+height); - if(mCameraID == null) - return false; - CameraManager manager = (CameraManager) mView.getContext() - .getSystemService(Context.CAMERA_SERVICE); - try { - CameraCharacteristics characteristics = manager - .getCameraCharacteristics(mCameraID); - StreamConfigurationMap map = characteristics - .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); - int bestWidth = 0, bestHeight = 0; - float aspect = (float)width / height; - for (Size psize : map.getOutputSizes(SurfaceTexture.class)) { - int w = psize.getWidth(), h = psize.getHeight(); - Log.d(LOGTAG, "trying size: "+w+"x"+h); - if ( width >= w && height >= h && - bestWidth <= w && bestHeight <= h && - Math.abs(aspect - (float)w/h) < 0.2 ) { - bestWidth = w; - bestHeight = h; - } - } - Log.i(LOGTAG, "best size: "+bestWidth+"x"+bestHeight); - if( mPreviewSize.getWidth() == bestWidth && - mPreviewSize.getHeight() == bestHeight ) - return false; - else { - mPreviewSize = new Size(bestWidth, bestHeight); - return true; - } - } catch (CameraAccessException e) { - Log.e(LOGTAG, "cacPreviewSize - Camera Access Exception"); - } catch (IllegalArgumentException e) { - Log.e(LOGTAG, "cacPreviewSize - Illegal Argument Exception"); - } catch (SecurityException e) { - Log.e(LOGTAG, "cacPreviewSize - Security Exception"); - } - return false; - } - - protected void openCamera() { - Log.i(LOGTAG, "openCamera"); - //closeCamera(); - CameraManager manager = (CameraManager) mView.getContext() - .getSystemService(Context.CAMERA_SERVICE); - try { - for (String cameraID : manager.getCameraIdList()) { - CameraCharacteristics characteristics = manager - .getCameraCharacteristics(cameraID); - if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) - continue; - - mCameraID = cameraID; - break; - } - if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) { - throw new RuntimeException( - "Time out waiting to lock camera opening."); - } - manager.openCamera(mCameraID, mStateCallback, mBackgroundHandler); - } catch (CameraAccessException e) { - Log.e(LOGTAG, "OpenCamera - Camera Access Exception"); - } catch (IllegalArgumentException e) { - Log.e(LOGTAG, "OpenCamera - Illegal Argument Exception"); - } catch (SecurityException e) { - Log.e(LOGTAG, "OpenCamera - Security Exception"); - } catch (InterruptedException e) { - Log.e(LOGTAG, "OpenCamera - Interrupted Exception"); - } - } - - protected void closeCamera() { - Log.i(LOGTAG, "closeCamera"); - try { - mCameraOpenCloseLock.acquire(); - if (null != mCaptureSession) { - mCaptureSession.close(); - mCaptureSession = null; - } - if (null != mCameraDevice) { - mCameraDevice.close(); - mCameraDevice = null; - } - } catch (InterruptedException e) { - throw new RuntimeException( - "Interrupted while trying to lock camera closing.", e); - } finally { - mCameraOpenCloseLock.release(); - } - } - - private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { - - @Override - public void onOpened(CameraDevice cameraDevice) { - mCameraDevice = cameraDevice; - mCameraOpenCloseLock.release(); - createCameraPreviewSession(); - } - - @Override - public void onDisconnected(CameraDevice cameraDevice) { - cameraDevice.close(); - mCameraDevice = null; - mCameraOpenCloseLock.release(); - } - - @Override - public void onError(CameraDevice cameraDevice, int error) { - cameraDevice.close(); - mCameraDevice = null; - mCameraOpenCloseLock.release(); - } - - }; - - private void createCameraPreviewSession() { - Log.i(LOGTAG, "createCameraPreviewSession"); - try { - mCameraOpenCloseLock.acquire(); - if (null == mCameraDevice) { - mCameraOpenCloseLock.release(); - Log.e(LOGTAG, "createCameraPreviewSession: camera isn't opened"); - return; - } - if (null != mCaptureSession) { - mCameraOpenCloseLock.release(); - Log.e(LOGTAG, "createCameraPreviewSession: mCaptureSession is already started"); - return; - } - if(null == mSTex) { - mCameraOpenCloseLock.release(); - Log.e(LOGTAG, "createCameraPreviewSession: preview SurfaceTexture is null"); - return; - } - Log.d(LOGTAG, "starting preview "+mPreviewSize.getWidth()+"x"+mPreviewSize.getHeight()); - mSTex.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); - - Surface surface = new Surface(mSTex); - - mPreviewRequestBuilder = mCameraDevice - .createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); - mPreviewRequestBuilder.addTarget(surface); - - mCameraDevice.createCaptureSession(Arrays.asList(surface), - new CameraCaptureSession.StateCallback() { - @Override - public void onConfigured( - CameraCaptureSession cameraCaptureSession) { - mCaptureSession = cameraCaptureSession; - try { - mPreviewRequestBuilder - .set(CaptureRequest.CONTROL_AF_MODE, - CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); - mPreviewRequestBuilder - .set(CaptureRequest.CONTROL_AE_MODE, - CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); - - mCaptureSession.setRepeatingRequest( - mPreviewRequestBuilder.build(), null, - mBackgroundHandler); - Log.i(LOGTAG, "CameraPreviewSession has been started"); - } catch (CameraAccessException e) { - Log.e(LOGTAG, "createCaptureSession failed"); - } - mCameraOpenCloseLock.release(); - } - - @Override - public void onConfigureFailed( - CameraCaptureSession cameraCaptureSession) { - Log.e(LOGTAG, "createCameraPreviewSession failed"); - mCameraOpenCloseLock.release(); - } - }, mBackgroundHandler); - } catch (CameraAccessException e) { - Log.e(LOGTAG, "createCameraPreviewSession"); - } catch (InterruptedException e) { - throw new RuntimeException( - "Interrupted while createCameraPreviewSession", e); - } - finally { - //mCameraOpenCloseLock.release(); - } - } - - private void startBackgroundThread() { - Log.i(LOGTAG, "startBackgroundThread"); - mBackgroundThread = new HandlerThread("CameraBackground"); - mBackgroundThread.start(); - mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); - } - - private void stopBackgroundThread() { - Log.i(LOGTAG, "stopBackgroundThread"); - if(mBackgroundThread == null) - return; - mBackgroundThread.quitSafely(); - try { - mBackgroundThread.join(); - mBackgroundThread = null; - mBackgroundHandler = null; - } catch (InterruptedException e) { - Log.e(LOGTAG, "stopBackgroundThread"); - } - } - - @Override - protected void setCameraPreviewSize(int width, int height) { - Log.i(LOGTAG, "setCameraPreviewSize("+width+"x"+height+")"); - try { - mCameraOpenCloseLock.acquire(); - if( !cacPreviewSize(width, height) ) { - mCameraOpenCloseLock.release(); - return; - } - if (null != mCaptureSession) { - Log.d(LOGTAG, "closing existing previewSession"); - mCaptureSession.close(); - mCaptureSession = null; - } - mCameraOpenCloseLock.release(); - createCameraPreviewSession(); - } catch (InterruptedException e) { - mCameraOpenCloseLock.release(); - throw new RuntimeException( - "Interrupted while setCameraPreviewSize.", e); - } - } -} diff --git a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/CameraRenderer.java b/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/CameraRenderer.java deleted file mode 100644 index 692ab9884..000000000 --- a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/CameraRenderer.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.opencv.samples.tutorial4; - -import java.io.IOException; -import java.util.List; - -import android.hardware.Camera; -import android.hardware.Camera.Size; -import android.util.Log; - -@SuppressWarnings("deprecation") -public class CameraRenderer extends MyGLRendererBase { - - protected final String LOGTAG = "CameraRenderer"; - private Camera mCamera; - boolean mPreviewStarted = false; - - CameraRenderer(MyGLSurfaceView view) { - super(view); - } - - protected void closeCamera() { - Log.i(LOGTAG, "closeCamera"); - if(mCamera != null) { - mCamera.stopPreview(); - mPreviewStarted = false; - mCamera.release(); - mCamera = null; - } - } - - protected void openCamera() { - Log.i(LOGTAG, "openCamera"); - closeCamera(); - mCamera = Camera.open(); - try { - mCamera.setPreviewTexture(mSTex); - } catch (IOException ioe) { - Log.e(LOGTAG, "setPreviewTexture() failed: " + ioe.getMessage()); - } - } - - public void setCameraPreviewSize(int width, int height) { - Log.i(LOGTAG, "setCameraPreviewSize: "+width+"x"+height); - if(mCamera == null) - return; - if(mPreviewStarted) { - mCamera.stopPreview(); - mPreviewStarted = false; - } - Camera.Parameters param = mCamera.getParameters(); - List psize = param.getSupportedPreviewSizes(); - int bestWidth = 0, bestHeight = 0; - if (psize.size() > 0) { - float aspect = (float)width / height; - for (Size size : psize) { - int w = size.width, h = size.height; - Log.d("Renderer", "checking camera preview size: "+w+"x"+h); - if ( w <= width && h <= height && - w >= bestWidth && h >= bestHeight && - Math.abs(aspect - (float)w/h) < 0.2 ) { - bestWidth = w; - bestHeight = h; - } - } - if(bestWidth > 0 && bestHeight > 0) { - param.setPreviewSize(bestWidth, bestHeight); - Log.i(LOGTAG, "size: "+bestWidth+" x "+bestHeight); - } - } - param.set("orientation", "landscape"); - mCamera.setParameters(param); - mCamera.startPreview(); - mPreviewStarted = true; - } -} diff --git a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/MyGLRendererBase.java b/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/MyGLRendererBase.java deleted file mode 100644 index f3abe87b3..000000000 --- a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/MyGLRendererBase.java +++ /dev/null @@ -1,117 +0,0 @@ -package org.opencv.samples.tutorial4; - -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; - -import android.graphics.SurfaceTexture; -import android.opengl.GLES20; -import android.opengl.GLSurfaceView; -import android.os.Handler; -import android.os.Looper; -import android.util.Log; -import android.widget.TextView; - -public abstract class MyGLRendererBase implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener { - protected final String LOGTAG = "MyGLRendererBase"; - protected int frameCounter; - protected long lastNanoTime; - - protected SurfaceTexture mSTex; - protected MyGLSurfaceView mView; - protected TextView mFpsText; - - protected boolean mGLInit = false; - protected boolean mTexUpdate = false; - - MyGLRendererBase(MyGLSurfaceView view) { - mView = view; - } - - protected abstract void openCamera(); - protected abstract void closeCamera(); - protected abstract void setCameraPreviewSize(int width, int height); - - public void setFpsTextView(TextView fpsTV) - { - mFpsText = fpsTV; - } - - public void onResume() { - Log.i(LOGTAG, "onResume"); - frameCounter = 0; - lastNanoTime = System.nanoTime(); - } - - public void onPause() { - Log.i(LOGTAG, "onPause"); - mGLInit = false; - mTexUpdate = false; - closeCamera(); - if(mSTex != null) { - mSTex.release(); - mSTex = null; - NativeGLRenderer.closeGL(); - } - } - - @Override - public synchronized void onFrameAvailable(SurfaceTexture surfaceTexture) { - //Log.i(LOGTAG, "onFrameAvailable"); - mTexUpdate = true; - mView.requestRender(); - } - - @Override - public void onDrawFrame(GL10 gl) { - //Log.i(LOGTAG, "onDrawFrame"); - if (!mGLInit) - return; - - synchronized (this) { - if (mTexUpdate) { - mSTex.updateTexImage(); - mTexUpdate = false; - } - } - NativeGLRenderer.drawFrame(); - - // log FPS - frameCounter++; - if(frameCounter >= 10) - { - final int fps = (int) (frameCounter * 1e9 / (System.nanoTime() - lastNanoTime)); - Log.i(LOGTAG, "drawFrame() FPS: "+fps); - if(mFpsText != null) { - Runnable fpsUpdater = new Runnable() { - public void run() { - mFpsText.setText("FPS: " + fps); - } - }; - new Handler(Looper.getMainLooper()).post(fpsUpdater); - } - frameCounter = 0; - lastNanoTime = System.nanoTime(); - } - } - - @Override - public void onSurfaceChanged(GL10 gl, int surfaceWidth, int surfaceHeight) { - Log.i(LOGTAG, "onSurfaceChanged("+surfaceWidth+"x"+surfaceHeight+")"); - NativeGLRenderer.changeSize(surfaceWidth, surfaceHeight); - setCameraPreviewSize(surfaceWidth, surfaceHeight); - } - - @Override - public void onSurfaceCreated(GL10 gl, EGLConfig config) { - Log.i(LOGTAG, "onSurfaceCreated"); - String strGLVersion = GLES20.glGetString(GLES20.GL_VERSION); - if (strGLVersion != null) - Log.i(LOGTAG, "OpenGL ES version: " + strGLVersion); - - int hTex = NativeGLRenderer.initGL(); - mSTex = new SurfaceTexture(hTex); - mSTex.setOnFrameAvailableListener(this); - openCamera(); - mGLInit = true; - } -} diff --git a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/MyGLSurfaceView.java b/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/MyGLSurfaceView.java index 8556b4181..edaf34631 100644 --- a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/MyGLSurfaceView.java +++ b/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/MyGLSurfaceView.java @@ -1,59 +1,29 @@ package org.opencv.samples.tutorial4; +import org.opencv.android.CameraGLSurfaceView; + import android.app.Activity; import android.content.Context; -import android.opengl.GLSurfaceView; +import android.os.Handler; +import android.os.Looper; import android.util.AttributeSet; +import android.util.Log; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.widget.TextView; +import android.widget.Toast; -public class MyGLSurfaceView extends GLSurfaceView { +public class MyGLSurfaceView extends CameraGLSurfaceView implements CameraGLSurfaceView.CameraTextureListener { - MyGLRendererBase mRenderer; + static final String LOGTAG = "MyGLSurfaceView"; + protected int procMode = NativePart.PROCESSING_MODE_NO_PROCESSING; + static final String[] procModeName = new String[] {"No Processing", "CPU", "OpenCL Direct", "OpenCL via OpenCV"}; + protected int frameCounter; + protected long lastNanoTime; + TextView mFpsText = null; public MyGLSurfaceView(Context context, AttributeSet attrs) { super(context, attrs); - - if(android.os.Build.VERSION.SDK_INT >= 21) - mRenderer = new Camera2Renderer(this); - else - mRenderer = new CameraRenderer(this); - - setEGLContextClientVersion(2); - setRenderer(mRenderer); - setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); - } - - public void setFpsTextView(TextView tv) { - mRenderer.setFpsTextView(tv); - } - - @Override - public void surfaceCreated(SurfaceHolder holder) { - super.surfaceCreated(holder); - } - - @Override - public void surfaceDestroyed(SurfaceHolder holder) { - super.surfaceDestroyed(holder); - } - - @Override - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { - super.surfaceChanged(holder, format, w, h); - } - - @Override - public void onResume() { - super.onResume(); - mRenderer.onResume(); - } - - @Override - public void onPause() { - mRenderer.onPause(); - super.onPause(); } @Override @@ -62,4 +32,81 @@ public class MyGLSurfaceView extends GLSurfaceView { ((Activity)getContext()).openOptionsMenu(); return true; } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + super.surfaceCreated(holder); + //NativePart.initCL(); + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + //NativePart.closeCL(); + super.surfaceDestroyed(holder); + } + + public void setProcessingMode(int newMode) { + if(newMode>=0 && newMode= 30) + { + final int fps = (int) (frameCounter * 1e9 / (System.nanoTime() - lastNanoTime)); + Log.i(LOGTAG, "drawFrame() FPS: "+fps); + if(mFpsText != null) { + Runnable fpsUpdater = new Runnable() { + public void run() { + mFpsText.setText("FPS: " + fps); + } + }; + new Handler(Looper.getMainLooper()).post(fpsUpdater); + } else { + Log.d(LOGTAG, "mFpsText == null"); + mFpsText = (TextView)((Activity) getContext()).findViewById(R.id.fps_text_view); + } + frameCounter = 0; + lastNanoTime = System.nanoTime(); + } + + + if(procMode == NativePart.PROCESSING_MODE_NO_PROCESSING) + return false; + + NativePart.processFrame(texIn, texOut, width, height, procMode); + return true; + } } diff --git a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/NativeGLRenderer.java b/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/NativePart.java similarity index 51% rename from samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/NativeGLRenderer.java rename to samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/NativePart.java index 8d9216c97..e5f11ba3a 100644 --- a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/NativeGLRenderer.java +++ b/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/NativePart.java @@ -1,10 +1,10 @@ package org.opencv.samples.tutorial4; -public class NativeGLRenderer { +public class NativePart { static { System.loadLibrary("opencv_java3"); - System.loadLibrary("JNIrender"); + System.loadLibrary("JNIpart"); } public static final int PROCESSING_MODE_NO_PROCESSING = 0; @@ -12,9 +12,7 @@ public class NativeGLRenderer { public static final int PROCESSING_MODE_OCL_DIRECT = 2; public static final int PROCESSING_MODE_OCL_OCV = 3; - public static native int initGL(); - public static native void closeGL(); - public static native void drawFrame(); - public static native void changeSize(int width, int height); - public static native void setProcessingMode(int mode); + public static native int initCL(); + public static native void closeCL(); + public static native void processFrame(int tex1, int tex2, int w, int h, int mode); } diff --git a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/Tutorial4Activity.java b/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/Tutorial4Activity.java index 56b416c80..0be55df65 100644 --- a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/Tutorial4Activity.java +++ b/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/Tutorial4Activity.java @@ -29,8 +29,8 @@ public class Tutorial4Activity extends Activity { //setContentView(mView); setContentView(R.layout.activity); mView = (MyGLSurfaceView) findViewById(R.id.my_gl_surface_view); + mView.setCameraTextureListener(mView); TextView tv = (TextView)findViewById(R.id.fps_text_view); - mView.setFpsTextView(tv); mProcMode = (TextView)findViewById(R.id.proc_mode_text_view); runOnUiThread(new Runnable() { public void run() { @@ -38,7 +38,8 @@ public class Tutorial4Activity extends Activity { } }); - NativeGLRenderer.setProcessingMode(NativeGLRenderer.PROCESSING_MODE_NO_PROCESSING); } + mView.setProcessingMode(NativePart.PROCESSING_MODE_NO_PROCESSING); + } @Override protected void onPause() { @@ -68,7 +69,7 @@ public class Tutorial4Activity extends Activity { mProcMode.setText("Processing mode: No Processing"); } }); - NativeGLRenderer.setProcessingMode(NativeGLRenderer.PROCESSING_MODE_NO_PROCESSING); + mView.setProcessingMode(NativePart.PROCESSING_MODE_NO_PROCESSING); return true; case R.id.cpu: runOnUiThread(new Runnable() { @@ -76,7 +77,7 @@ public class Tutorial4Activity extends Activity { mProcMode.setText("Processing mode: CPU"); } }); - NativeGLRenderer.setProcessingMode(NativeGLRenderer.PROCESSING_MODE_CPU); + mView.setProcessingMode(NativePart.PROCESSING_MODE_CPU); return true; case R.id.ocl_direct: runOnUiThread(new Runnable() { @@ -84,7 +85,7 @@ public class Tutorial4Activity extends Activity { mProcMode.setText("Processing mode: OpenCL direct"); } }); - NativeGLRenderer.setProcessingMode(NativeGLRenderer.PROCESSING_MODE_OCL_DIRECT); + mView.setProcessingMode(NativePart.PROCESSING_MODE_OCL_DIRECT); return true; case R.id.ocl_ocv: runOnUiThread(new Runnable() { @@ -92,7 +93,7 @@ public class Tutorial4Activity extends Activity { mProcMode.setText("Processing mode: OpenCL via OpenCV (TAPI)"); } }); - NativeGLRenderer.setProcessingMode(NativeGLRenderer.PROCESSING_MODE_OCL_OCV); + mView.setProcessingMode(NativePart.PROCESSING_MODE_OCL_OCV); return true; default: return false; From 23fea91e840960e666f00521b7ed77f847953d8a Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Thu, 8 Oct 2015 12:21:05 +0300 Subject: [PATCH 112/156] minor fixes --- modules/java/CMakeLists.txt | 21 +++++++------- .../java/android+CameraGLRendererBase.java | 28 +++++++++++++++---- .../tutorial-4-opencl/jni/CLprocessor.cpp | 14 +++------- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/modules/java/CMakeLists.txt b/modules/java/CMakeLists.txt index 3906040df..1a1512d36 100644 --- a/modules/java/CMakeLists.txt +++ b/modules/java/CMakeLists.txt @@ -179,19 +179,18 @@ if(NOT ANDROID) else() file(GLOB_RECURSE handwrittren_lib_project_files_rel RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/android_lib/" "${CMAKE_CURRENT_SOURCE_DIR}/android_lib/*") list(REMOVE_ITEM handwrittren_lib_project_files_rel "${ANDROID_MANIFEST_FILE}") + + # calc default SDK Target + android_get_compatible_target(android_sdk_target ${ANDROID_NATIVE_API_LEVEL} ${ANDROID_SDK_TARGET} 11) + string(REGEX REPLACE "android-" "" android_sdk_target_num ${android_sdk_target}) + # filter out + if( (ANDROID_SDK_TARGET AND ANDROID_SDK_TARGET LESS 21) OR (android_sdk_target_num LESS 21) ) + message(STATUS "[OpenCV for Android SDK]: A new OpenGL Camera Bridge (CameraGLSurfaceView, CameraGLRendererBase, CameraRenderer, Camera2Renderer) is disabled, because ANDROID_SDK_TARGET (${android_sdk_target_num}) < 21") + ocv_list_filterout(handwritten_java_sources "android\\\\+CameraGL") + ocv_list_filterout(handwritten_java_sources "android\\\\+Camera.?Renderer") + endif() endif() -# Calc default SDK Target -android_get_compatible_target(android_sdk_target ${ANDROID_NATIVE_API_LEVEL} ${ANDROID_SDK_TARGET} 11) -string(REGEX REPLACE "android-" "" android_sdk_target_num ${android_sdk_target}) - -if( (ANDROID_SDK_TARGET AND ANDROID_SDK_TARGET LESS 21) OR (android_sdk_target_num LESS 21) ) - message(STATUS "[OpenCV for Android SDK]: A new OpenGL Camera Bridge (CameraGLSurfaceView, CameraGLRendererBase, CameraRenderer, Camera2Renderer) is disabled, because ANDROID_SDK_TARGET (${android_sdk_target_num}) < 21") - ocv_list_filterout(handwritten_java_sources "android\\\\+CameraGL") - ocv_list_filterout(handwritten_java_sources "android\\\\+Camera.?Renderer") -endif() - - # IMPORTANT: add dependencies to cmake (we should rerun cmake if any of these files is modified) add_cmake_dependencies(${scripts_gen_java} ${scripts_hdr_parser} ${opencv_public_headers}) diff --git a/modules/java/generator/src/java/android+CameraGLRendererBase.java b/modules/java/generator/src/java/android+CameraGLRendererBase.java index 3971d0cb4..60c37c304 100644 --- a/modules/java/generator/src/java/android+CameraGLRendererBase.java +++ b/modules/java/generator/src/java/android+CameraGLRendererBase.java @@ -219,9 +219,9 @@ public abstract class CameraGLRendererBase implements GLSurfaceView.Renderer, Su int vshader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); GLES20.glShaderSource(vshader, vss); GLES20.glCompileShader(vshader); - int[] compiled = new int[1]; - GLES20.glGetShaderiv(vshader, GLES20.GL_COMPILE_STATUS, compiled, 0); - if (compiled[0] == 0) { + int[] status = new int[1]; + GLES20.glGetShaderiv(vshader, GLES20.GL_COMPILE_STATUS, status, 0); + if (status[0] == 0) { Log.e("CameraGLRendererBase", "Could not compile vertex shader: "+GLES20.glGetShaderInfoLog(vshader)); GLES20.glDeleteShader(vshader); vshader = 0; @@ -231,8 +231,8 @@ public abstract class CameraGLRendererBase implements GLSurfaceView.Renderer, Su int fshader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); GLES20.glShaderSource(fshader, fss); GLES20.glCompileShader(fshader); - GLES20.glGetShaderiv(fshader, GLES20.GL_COMPILE_STATUS, compiled, 0); - if (compiled[0] == 0) { + GLES20.glGetShaderiv(fshader, GLES20.GL_COMPILE_STATUS, status, 0); + if (status[0] == 0) { Log.e("CameraGLRendererBase", "Could not compile fragment shader:"+GLES20.glGetShaderInfoLog(fshader)); GLES20.glDeleteShader(vshader); GLES20.glDeleteShader(fshader); @@ -244,9 +244,25 @@ public abstract class CameraGLRendererBase implements GLSurfaceView.Renderer, Su GLES20.glAttachShader(program, vshader); GLES20.glAttachShader(program, fshader); GLES20.glLinkProgram(program); - Log.d("CameraGLRendererBase", "shaders were compiled OK"); GLES20.glDeleteShader(vshader); GLES20.glDeleteShader(fshader); + GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, status, 0); + if (status[0] == 0) { + Log.e("CameraGLRendererBase", "Could not link shader program: "+GLES20.glGetProgramInfoLog(program)); + program = 0; + return 0; + } + GLES20.glValidateProgram(program); + GLES20.glGetProgramiv(program, GLES20.GL_VALIDATE_STATUS, status, 0); + if (status[0] == 0) + { + Log.e("CameraGLRendererBase", "Shader program validation error: "+GLES20.glGetProgramInfoLog(program)); + GLES20.glDeleteProgram(program); + program = 0; + return 0; + } + + Log.d("CameraGLRendererBase", "Shader program is built OK"); return program; } diff --git a/samples/android/tutorial-4-opencl/jni/CLprocessor.cpp b/samples/android/tutorial-4-opencl/jni/CLprocessor.cpp index b7bf530b9..b71dc1018 100644 --- a/samples/android/tutorial-4-opencl/jni/CLprocessor.cpp +++ b/samples/android/tutorial-4-opencl/jni/CLprocessor.cpp @@ -237,23 +237,17 @@ void drawFrameProcCPU(int w, int h, int texOut) int64_t t; // let's modify pixels in FBO texture in C++ code (on CPU) - const int BUFF_SIZE = 1<<24;//2k*2k*4; - static char tmpBuff[BUFF_SIZE]; - if(w*h > BUFF_SIZE) - { - LOGE("Internal temp buffer is too small, can't make CPU frame processing"); - return; - } + static cv::Mat m; + m.create(h, w, CV_8UC4); // read t = getTimeMs(); // expecting FBO to be bound - glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, tmpBuff); + glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, m.data); LOGD("glReadPixels() costs %d ms", getTimeInterval(t)); // modify t = getTimeMs(); - cv::Mat m(h, w, CV_8UC4, tmpBuff); cv::Laplacian(m, m, CV_8U); m *= 10; LOGD("Laplacian() costs %d ms", getTimeInterval(t)); @@ -262,7 +256,7 @@ void drawFrameProcCPU(int w, int h, int texOut) glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texOut); t = getTimeMs(); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, tmpBuff); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, m.data); LOGD("glTexSubImage2D() costs %d ms", getTimeInterval(t)); } From 913c266b4aa102c3c9d0507c794137de76f42bf6 Mon Sep 17 00:00:00 2001 From: StevenPuttemans Date: Thu, 8 Oct 2015 11:03:30 +0200 Subject: [PATCH 113/156] adding missing images from python tutorials, like chessboard.png, simple.jpg, home.jpg, fly.png, ... --- .../py_features_harris.markdown | 2 +- .../py_shi_tomasi/py_shi_tomasi.markdown | 2 +- samples/data/blox.jpg | Bin 0 -> 7705 bytes samples/data/butterfly.jpg | Bin 0 -> 44746 bytes samples/data/chessboard.png | Bin 0 -> 62550 bytes samples/data/home.jpg | Bin 0 -> 32197 bytes samples/data/left.jpg | Bin 0 -> 24056 bytes samples/data/messi5.jpg | Bin 0 -> 72937 bytes samples/data/right.jpg | Bin 0 -> 23826 bytes 9 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 samples/data/blox.jpg create mode 100644 samples/data/butterfly.jpg create mode 100644 samples/data/chessboard.png create mode 100644 samples/data/home.jpg create mode 100644 samples/data/left.jpg create mode 100644 samples/data/messi5.jpg create mode 100644 samples/data/right.jpg diff --git a/doc/py_tutorials/py_feature2d/py_features_harris/py_features_harris.markdown b/doc/py_tutorials/py_feature2d/py_features_harris/py_features_harris.markdown index 4cb01e32a..7297eb403 100644 --- a/doc/py_tutorials/py_feature2d/py_features_harris/py_features_harris.markdown +++ b/doc/py_tutorials/py_feature2d/py_features_harris/py_features_harris.markdown @@ -77,7 +77,7 @@ See the example below: import cv2 import numpy as np -filename = 'chessboard.jpg' +filename = 'chessboard.png' img = cv2.imread(filename) gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) diff --git a/doc/py_tutorials/py_feature2d/py_shi_tomasi/py_shi_tomasi.markdown b/doc/py_tutorials/py_feature2d/py_shi_tomasi/py_shi_tomasi.markdown index d42b10ba2..5731e2157 100644 --- a/doc/py_tutorials/py_feature2d/py_shi_tomasi/py_shi_tomasi.markdown +++ b/doc/py_tutorials/py_feature2d/py_shi_tomasi/py_shi_tomasi.markdown @@ -50,7 +50,7 @@ import numpy as np import cv2 from matplotlib import pyplot as plt -img = cv2.imread('simple.jpg') +img = cv2.imread('blox.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) corners = cv2.goodFeaturesToTrack(gray,25,0.01,10) diff --git a/samples/data/blox.jpg b/samples/data/blox.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b682b2c0aa3a25890569ca3e63b681c4a7a38604 GIT binary patch literal 7705 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 literal 0 HcmV?d00001 diff --git a/samples/data/butterfly.jpg b/samples/data/butterfly.jpg new file mode 100644 index 0000000000000000000000000000000000000000..67d60f05552615d6abef100ca1010409a3d13fa0 GIT binary patch literal 44746 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 Qm&9J+yLj%w*}>`m2JU)0G5`Po literal 0 HcmV?d00001 diff --git a/samples/data/home.jpg b/samples/data/home.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7528a7d77602dc9246f855fe452ac1238e58db68 GIT binary patch literal 32197 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 az~J}k!KoPTGAWPuv*}Lbtucr+2>;nA`L`GV literal 0 HcmV?d00001 diff --git a/samples/data/left.jpg b/samples/data/left.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f4c26303a2591eec80c08ce134baf7bc329d42fb GIT binary patch literal 24056 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 Hi^c!hHrSC# literal 0 HcmV?d00001 diff --git a/samples/data/messi5.jpg b/samples/data/messi5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cd437610fe392d3ca892f62e26c33521f5147295 GIT binary patch literal 72937 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�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%0DdO~R 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 literal 0 HcmV?d00001 From 24ca6aaadab50aeab8cbe5e4a19a17ae75bd7a38 Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Thu, 8 Oct 2015 13:48:46 +0300 Subject: [PATCH 114/156] fix build with CMake now it builds by the command: `cmake.exe -Wno-dev -GNinja -DCMAKE_MAKE_PROGRAM="path\to\ninja\ninja.exe" -DCMAKE_TOOLCHAIN_FILE=../opencv3/platforms/android/android.toolchain.cmake -DANDROID_ABI="armeabi-v7a with NEON" -DANDROID_SDK_TARGET=21 -DANDROID_NATIVE_API_LEVEL=14 -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON -DBUILD_ANDROID_EXAMPLES=ON -DINSTALL_ANDROID_EXAMPLES=ON -DWITH_OPENCL=YES -DANDROID_OPENCL_SDK=path\to\OpenCL ../opencv` --- samples/android/tutorial-4-opencl/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/samples/android/tutorial-4-opencl/CMakeLists.txt b/samples/android/tutorial-4-opencl/CMakeLists.txt index 96bacdeb4..e8036cfbd 100644 --- a/samples/android/tutorial-4-opencl/CMakeLists.txt +++ b/samples/android/tutorial-4-opencl/CMakeLists.txt @@ -15,11 +15,12 @@ else() endif() include_directories(${ANDROID_OPENCL_SDK}/include) -link_directories(${ANDROID_OPENCL_SDK}/lib/${ANDROID_ABI}) +link_directories(${ANDROID_OPENCL_SDK}/lib/${ANDROID_NDK_ABI_NAME}) add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}" LIBRARY_DEPS ${OpenCV_BINARY_DIR} SDK_TARGET 21 ${ANDROID_SDK_TARGET} NATIVE_DEPS ${native_deps} -lGLESv2 -lEGL -lOpenCL + COPY_LIBS YES ) if(TARGET ${sample}) add_dependencies(opencv_android_examples ${sample}) From bbe007159ad6b99e15f47171b7b6be7c892ca9fa Mon Sep 17 00:00:00 2001 From: "Anton V. Shokurov" Date: Wed, 7 Oct 2015 15:16:24 -0400 Subject: [PATCH 115/156] The latest version (5.1.1) of the gnu compiler returns just its major version ("5") when given the "-dumpversion" argument. Gnu compiler developers don't consider this to be an error. A workaround for this case has been made. --- cmake/OpenCVDetectCXXCompiler.cmake | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/cmake/OpenCVDetectCXXCompiler.cmake b/cmake/OpenCVDetectCXXCompiler.cmake index bd3cf49d0..5cf4c856b 100644 --- a/cmake/OpenCVDetectCXXCompiler.cmake +++ b/cmake/OpenCVDetectCXXCompiler.cmake @@ -76,17 +76,27 @@ elseif(CMAKE_COMPILER_IS_GNUCXX) OUTPUT_STRIP_TRAILING_WHITESPACE) # Typical output in CMAKE_OPENCV_GCC_VERSION_FULL: "c+//0 (whatever) 4.2.3 (...)" - # Look for the version number + # Look for the version number, major.minor.build string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" CMAKE_GCC_REGEX_VERSION "${CMAKE_OPENCV_GCC_VERSION_FULL}") - if(NOT CMAKE_GCC_REGEX_VERSION) + if(NOT CMAKE_GCC_REGEX_VERSION)#major.minor string(REGEX MATCH "[0-9]+\\.[0-9]+" CMAKE_GCC_REGEX_VERSION "${CMAKE_OPENCV_GCC_VERSION_FULL}") endif() - # Split the three parts: - string(REGEX MATCHALL "[0-9]+" CMAKE_OPENCV_GCC_VERSIONS "${CMAKE_GCC_REGEX_VERSION}") + if(CMAKE_GCC_REGEX_VERSION) + # Split the parts: + string(REGEX MATCHALL "[0-9]+" CMAKE_OPENCV_GCC_VERSIONS "${CMAKE_GCC_REGEX_VERSION}") - list(GET CMAKE_OPENCV_GCC_VERSIONS 0 CMAKE_OPENCV_GCC_VERSION_MAJOR) - list(GET CMAKE_OPENCV_GCC_VERSIONS 1 CMAKE_OPENCV_GCC_VERSION_MINOR) + list(GET CMAKE_OPENCV_GCC_VERSIONS 0 CMAKE_OPENCV_GCC_VERSION_MAJOR) + list(GET CMAKE_OPENCV_GCC_VERSIONS 1 CMAKE_OPENCV_GCC_VERSION_MINOR) + else()#compiler returned just the major version number + string(REGEX MATCH "[0-9]+" CMAKE_GCC_REGEX_VERSION "${CMAKE_OPENCV_GCC_VERSION_FULL}") + if(NOT CMAKE_GCC_REGEX_VERSION)#compiler did not return anything reasonable + set(CMAKE_GCC_REGEX_VERSION "0") + message(WARNING "GCC version not detected!") + endif() + set(CMAKE_OPENCV_GCC_VERSION_MAJOR ${CMAKE_GCC_REGEX_VERSION}) + set(CMAKE_OPENCV_GCC_VERSION_MINOR 0) + endif() set(CMAKE_OPENCV_GCC_VERSION ${CMAKE_OPENCV_GCC_VERSION_MAJOR}${CMAKE_OPENCV_GCC_VERSION_MINOR}) math(EXPR CMAKE_OPENCV_GCC_VERSION_NUM "${CMAKE_OPENCV_GCC_VERSION_MAJOR}*100 + ${CMAKE_OPENCV_GCC_VERSION_MINOR}") From dbcc55a196cd0d1cab7053b339d937c5a614eb8e Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 9 Oct 2015 17:06:01 +0300 Subject: [PATCH 116/156] cleanup /src|gen folders to remove stalled/unused Java files --- modules/java/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/java/CMakeLists.txt b/modules/java/CMakeLists.txt index 1a1512d36..68d3ff9ca 100644 --- a/modules/java/CMakeLists.txt +++ b/modules/java/CMakeLists.txt @@ -7,6 +7,13 @@ if(IOS OR WINRT OR NOT PYTHON_DEFAULT_AVAILABLE OR NOT ANT_EXECUTABLE OR NOT (JN ocv_module_disable(java) endif() +if(EXISTS ${CMAKE_BINARY_DIR}/src) + execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}/src") +endif() +if(EXISTS ${CMAKE_BINARY_DIR}/gen) + execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}/gen") +endif() + set(the_description "The java bindings") ocv_add_module(java BINDINGS opencv_core opencv_imgproc) ocv_module_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/generator/src/cpp") From 13a0a37e6346c6fe45de474208f63283d6d4e729 Mon Sep 17 00:00:00 2001 From: Amro Date: Sun, 11 Oct 2015 01:54:11 +0300 Subject: [PATCH 117/156] fix randMVNormal in ML (#5469) Fix the failed assertion by replacing the GEMM call. Also random numbers are generated from normal distribution ~N(0,1), instead of uniform distribution ~U(0,1). --- modules/ml/src/inner_functions.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/modules/ml/src/inner_functions.cpp b/modules/ml/src/inner_functions.cpp index 52f368874..b39d40343 100644 --- a/modules/ml/src/inner_functions.cpp +++ b/modules/ml/src/inner_functions.cpp @@ -151,21 +151,28 @@ static void Cholesky( const Mat& A, Mat& S ) average row vector, - symmetric covariation matrix */ void randMVNormal( InputArray _mean, InputArray _cov, int nsamples, OutputArray _samples ) { + // check mean vector and covariance matrix Mat mean = _mean.getMat(), cov = _cov.getMat(); - int dim = (int)mean.total(); + int dim = (int)mean.total(); // dimensionality + CV_Assert(mean.rows == 1 || mean.cols == 1); + CV_Assert(cov.rows == dim && cov.cols == dim); + mean = mean.reshape(1,1); // ensure a row vector + // generate n-samples of the same dimension, from ~N(0,1) _samples.create(nsamples, dim, CV_32F); Mat samples = _samples.getMat(); - randu(samples, 0., 1.); + randn(samples, Scalar::all(0), Scalar::all(1)); + // decompose covariance using Cholesky: cov = U'*U + // (cov must be square, symmetric, and positive semi-definite matrix) Mat utmat; Cholesky(cov, utmat); - int flags = mean.cols == 1 ? 0 : GEMM_3_T; + // transform random numbers using specified mean and covariance for( int i = 0; i < nsamples; i++ ) { Mat sample = samples.row(i); - gemm(sample, utmat, 1, mean, 1, sample, flags); + sample = sample * utmat + mean; } } From 89eee6ca990ed44439a166de55c973798f5b86c3 Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Mon, 12 Oct 2015 10:51:28 +0300 Subject: [PATCH 118/156] Fixes for IPP integration: dotProd_16s - disabled for IPP 9.0.0; filter2D - fixed kernel preparation; morphology - conditions fix and disabled FilterMin and FilterMax for IPP 9.0.0; GaussianBlur - disabled for CV_8UC1 due to buffer overflow; integral - disabled for IPP 9.0.0; IppAutoBuffer class was added; --- modules/core/include/opencv2/core/private.hpp | 20 +++++++ modules/core/src/matmul.cpp | 2 +- modules/core/src/system.cpp | 6 +++ modules/imgproc/src/filter.cpp | 54 +++++++++++++------ modules/imgproc/src/morph.cpp | 24 +++++---- modules/imgproc/src/smooth.cpp | 30 +++++------ modules/imgproc/src/sumpixels.cpp | 2 +- 7 files changed, 93 insertions(+), 45 deletions(-) diff --git a/modules/core/include/opencv2/core/private.hpp b/modules/core/include/opencv2/core/private.hpp index 363c76f0d..c71ec626e 100644 --- a/modules/core/include/opencv2/core/private.hpp +++ b/modules/core/include/opencv2/core/private.hpp @@ -241,6 +241,26 @@ static inline IppDataType ippiGetDataType(int depth) depth == CV_64F ? ipp64f : (IppDataType)-1; } +// IPP temporary buffer hepler +template +class IppAutoBuffer +{ +public: + IppAutoBuffer() { m_pBuffer = NULL; } + IppAutoBuffer(int size) { Alloc(size); } + ~IppAutoBuffer() { Release(); } + T* Alloc(int size) { m_pBuffer = (T*)ippMalloc(size); return m_pBuffer; } + void Release() { if(m_pBuffer) ippFree(m_pBuffer); } + inline operator T* () { return (T*)m_pBuffer;} + inline operator const T* () const { return (const T*)m_pBuffer;} +private: + // Disable copy operations + IppAutoBuffer(IppAutoBuffer &) {}; + IppAutoBuffer& operator =(const IppAutoBuffer &) {return *this;}; + + T* m_pBuffer; +}; + #else #define IPP_VERSION_X100 0 #endif diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.cpp index cb639462f..99f6bf95e 100644 --- a/modules/core/src/matmul.cpp +++ b/modules/core/src/matmul.cpp @@ -3131,7 +3131,7 @@ static double dotProd_16u(const ushort* src1, const ushort* src2, int len) static double dotProd_16s(const short* src1, const short* src2, int len) { -#if (ARITHM_USE_IPP == 1) +#if (ARITHM_USE_IPP == 1) && (IPP_VERSION_X100 != 900) // bug in IPP 9.0.0 CV_IPP_CHECK() { double r = 0; diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index 81d555d81..8c0072aed 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -1318,6 +1318,12 @@ public: ippFeatures = ippCPUID_SSE; else if(env == "sse2") ippFeatures = ippCPUID_SSE2; + else if(env == "sse3") + ippFeatures = ippCPUID_SSE3; + else if(env == "ssse3") + ippFeatures = ippCPUID_SSSE3; + else if(env == "sse41") + ippFeatures = ippCPUID_SSE41; else if(env == "sse42") ippFeatures = ippCPUID_SSE42; else if(env == "avx") diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 587c50ba3..42a1130a3 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -4579,7 +4579,7 @@ static bool ipp_filter2D( InputArray _src, OutputArray _dst, int ddepth, int stype = src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype), ktype = kernel.type(), kdepth = CV_MAT_DEPTH(ktype); bool isolated = (borderType & BORDER_ISOLATED) != 0; - Point ippAnchor(kernel.cols >> 1, kernel.rows >> 1); + Point ippAnchor((kernel.cols-1)/2, (kernel.rows-1)/2); int borderTypeNI = borderType & ~BORDER_ISOLATED; IppiBorderType ippBorderType = ippiGetBorderType(borderTypeNI); @@ -4610,24 +4610,48 @@ static bool ipp_filter2D( InputArray _src, OutputArray _dst, int ddepth, if ((status = ippiFilterBorderGetSize(kernelSize, dstRoiSize, dataType, kernelType, cn, &specSize, &bufsize)) >= 0) { - IppiFilterBorderSpec * spec = (IppiFilterBorderSpec *)ippMalloc(specSize); - Ipp8u * buffer = ippsMalloc_8u(bufsize); + IppAutoBuffer spec(specSize); + IppAutoBuffer buffer(bufsize); Ipp32f borderValue[4] = { 0, 0, 0, 0 }; - Mat reversedKernel; - flip(kernel, reversedKernel, -1); - - if ((kdepth == CV_32F && (status = ippiFilterBorderInit_32f((const Ipp32f *)reversedKernel.data, kernelSize, - dataType, cn, ippRndFinancial, spec)) >= 0 ) || - (kdepth == CV_16S && (status = ippiFilterBorderInit_16s((const Ipp16s *)reversedKernel.data, - kernelSize, 0, dataType, cn, ippRndFinancial, spec)) >= 0)) + if(kdepth == CV_32F) { - status = ippFunc(src.data, (int)src.step, dst.data, (int)dst.step, dstRoiSize, - ippBorderType, borderValue, spec, buffer); - } + Ipp32f *pKerBuffer = (Ipp32f*)kernel.data; + IppAutoBuffer kerTmp; + if(kernel.step != kernel.cols) + { + kerTmp.Alloc(sizeof(Ipp32f)*kernelSize.width*kernelSize.height); + if(ippiCopy_32f_C1R((Ipp32f*)kernel.data, (int)kernel.step, kerTmp, kernelSize.width*sizeof(Ipp32f), kernelSize) < 0) + return false; + pKerBuffer = kerTmp; + } - ippsFree(buffer); - ippsFree(spec); + if((status = ippiFilterBorderInit_32f(pKerBuffer, kernelSize, + dataType, cn, ippRndFinancial, spec)) >= 0 ) + { + status = ippFunc(src.data, (int)src.step, dst.data, (int)dst.step, dstRoiSize, + ippBorderType, borderValue, spec, buffer); + } + } + else if(kdepth == CV_16S) + { + Ipp16s *pKerBuffer = (Ipp16s*)kernel.data; + IppAutoBuffer kerTmp; + if(kernel.step != kernel.cols) + { + kerTmp.Alloc(sizeof(Ipp16s)*kernelSize.width*kernelSize.height); + if(ippiCopy_16s_C1R((Ipp16s*)kernel.data, (int)kernel.step, kerTmp, kernelSize.width*sizeof(Ipp16s), kernelSize) < 0) + return false; + pKerBuffer = kerTmp; + } + + if((status = ippiFilterBorderInit_16s(pKerBuffer, kernelSize, + 0, dataType, cn, ippRndFinancial, spec)) >= 0) + { + status = ippFunc(src.data, (int)src.step, dst.data, (int)dst.step, dstRoiSize, + ippBorderType, borderValue, spec, buffer); + } + } } if (status >= 0) diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index 1ec1d25bf..be55e3561 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1231,17 +1231,18 @@ static bool ipp_MorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kern } else { +#if IPP_VERSION_X100 != 900 // Problems with accuracy in 9.0.0 #if IPP_VERSION_X100 >= 900 - if (((kernel.cols - 1) / 2 != anchor.x) || ((kernel.rows - 1) / 2 != anchor.y)) // Arbitrary anchor is no longer supporeted since IPP 9.0.0 + if (((kernelSize.width - 1) / 2 != anchor.x) || ((kernelSize.height - 1) / 2 != anchor.y)) // Arbitrary anchor is no longer supporeted since IPP 9.0.0 return false; - #define IPP_MORPH_CASE(cvtype, flavor, data_type) \ + #define IPP_MORPH_CASE(cvtype, flavor, data_type, cn) \ case cvtype: \ {\ if (op == MORPH_ERODE)\ {\ int bufSize = 0;\ - if (0 > ippiFilterMinBorderGetBufferSize(roiSize, kernelSize, ipp##data_type, 1, &bufSize))\ + if (0 > ippiFilterMinBorderGetBufferSize(roiSize, kernelSize, ipp##data_type, cn, &bufSize))\ return false;\ AutoBuffer buf(bufSize + 64);\ uchar* buffer = alignPtr((uchar*)buf, 32);\ @@ -1250,7 +1251,7 @@ static bool ipp_MorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kern else\ {\ int bufSize = 0;\ - if (0 > ippiFilterMaxBorderGetBufferSize(roiSize, kernelSize, ipp##data_type, 1, &bufSize))\ + if (0 > ippiFilterMaxBorderGetBufferSize(roiSize, kernelSize, ipp##data_type, cn, &bufSize))\ return false;\ AutoBuffer buf(bufSize + 64);\ uchar* buffer = alignPtr((uchar*)buf, 32);\ @@ -1261,7 +1262,7 @@ static bool ipp_MorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kern #else IppiPoint point = {anchor.x, anchor.y}; - #define IPP_MORPH_CASE(cvtype, flavor, data_type) \ + #define IPP_MORPH_CASE(cvtype, flavor, data_type, cn) \ case cvtype: \ {\ int bufSize = 0;\ @@ -1279,17 +1280,18 @@ static bool ipp_MorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kern CV_SUPPRESS_DEPRECATED_START switch (type) { - IPP_MORPH_CASE(CV_8UC1, 8u_C1R, 8u); - IPP_MORPH_CASE(CV_8UC3, 8u_C3R, 8u); - IPP_MORPH_CASE(CV_8UC4, 8u_C4R, 8u); - IPP_MORPH_CASE(CV_32FC1, 32f_C1R, 32f); - IPP_MORPH_CASE(CV_32FC3, 32f_C3R, 32f); - IPP_MORPH_CASE(CV_32FC4, 32f_C4R, 32f); + IPP_MORPH_CASE(CV_8UC1, 8u_C1R, 8u, 1); + IPP_MORPH_CASE(CV_8UC3, 8u_C3R, 8u, 3); + IPP_MORPH_CASE(CV_8UC4, 8u_C4R, 8u, 4); + IPP_MORPH_CASE(CV_32FC1, 32f_C1R, 32f, 1); + IPP_MORPH_CASE(CV_32FC3, 32f_C3R, 32f, 3); + IPP_MORPH_CASE(CV_32FC4, 32f_C4R, 32f, 4); default: ; } CV_SUPPRESS_DEPRECATED_END #undef IPP_MORPH_CASE +#endif } #else CV_UNUSED(op); CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(kernel); CV_UNUSED(ksize); CV_UNUSED(anchor); CV_UNUSED(rectKernel); diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 19b0bf2d2..9fa92037c 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -1695,32 +1695,33 @@ static bool ipp_GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, if (ippiFilterGaussianGetBufferSize(roiSize, (Ipp32u)ksize.width, dataType, cn, &specSize, &bufferSize) >= 0) { - IppFilterGaussianSpec * pSpec = (IppFilterGaussianSpec *)ippMalloc(specSize); - Ipp8u * pBuffer = (Ipp8u*)ippMalloc(bufferSize); + IppAutoBuffer spec(specSize); + IppAutoBuffer buffer(bufferSize); - if (ippiFilterGaussianInit(roiSize, (Ipp32u)ksize.width, (Ipp32f)sigma1, ippBorder, dataType, 1, pSpec, pBuffer) >= 0) + if (ippiFilterGaussianInit(roiSize, (Ipp32u)ksize.width, (Ipp32f)sigma1, ippBorder, dataType, cn, spec, buffer) >= 0) { #define IPP_FILTER_GAUSS_C1(ippfavor) \ { \ - typedef Ipp##ippfavor ippType; \ - ippType borderValues = 0; \ - status = ippiFilterGaussianBorder_##ippfavor##_C1R(src.ptr(), (int)src.step, \ - dst.ptr(), (int)dst.step, roiSize, borderValues, pSpec, pBuffer); \ + Ipp##ippfavor borderValues = 0; \ + status = ippiFilterGaussianBorder_##ippfavor##_C1R(src.ptr(), (int)src.step, \ + dst.ptr(), (int)dst.step, roiSize, borderValues, spec, buffer); \ } #define IPP_FILTER_GAUSS_CN(ippfavor, ippcn) \ { \ - typedef Ipp##ippfavor ippType; \ - ippType borderValues[] = { 0, 0, 0 }; \ - status = ippiFilterGaussianBorder_##ippfavor##_C##ippcn##R(src.ptr(), (int)src.step, \ - dst.ptr(), (int)dst.step, roiSize, borderValues, pSpec, pBuffer); \ + Ipp##ippfavor borderValues[] = { 0, 0, 0 }; \ + status = ippiFilterGaussianBorder_##ippfavor##_C##ippcn##R(src.ptr(), (int)src.step, \ + dst.ptr(), (int)dst.step, roiSize, borderValues, spec, buffer); \ } IppStatus status = ippStsErr; #if !HAVE_ICV +#if IPP_VERSION_X100 > 901 // Buffer overflow in IPP if (type == CV_8UC1) IPP_FILTER_GAUSS_C1(8u) - else if (type == CV_8UC3) + else +#endif + if (type == CV_8UC3) IPP_FILTER_GAUSS_CN(8u, 3) else if (type == CV_16UC1) IPP_FILTER_GAUSS_C1(16u) @@ -1737,11 +1738,6 @@ static bool ipp_GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, if (type == CV_32FC1) IPP_FILTER_GAUSS_C1(32f) - if (pSpec) - ippFree(pSpec); - if (pBuffer) - ippFree(pBuffer); - if(status >= 0) return true; diff --git a/modules/imgproc/src/sumpixels.cpp b/modules/imgproc/src/sumpixels.cpp index 8a667d291..7771d2cab 100755 --- a/modules/imgproc/src/sumpixels.cpp +++ b/modules/imgproc/src/sumpixels.cpp @@ -425,7 +425,7 @@ namespace cv { static bool ipp_integral(InputArray _src, OutputArray _sum, OutputArray _sqsum, OutputArray _tilted, int sdepth, int sqdepth) { -#if !defined(HAVE_IPP_ICV_ONLY) // Disabled on ICV due invalid results +#if !defined(HAVE_IPP_ICV_ONLY) && (IPP_VERSION_X100 != 900) // Disabled on ICV due invalid results int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); if( sdepth <= 0 ) sdepth = depth == CV_8U ? CV_32S : CV_64F; From a21be6706df0266fa9c915bf94df1066478e6694 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 12 Oct 2015 14:27:05 +0300 Subject: [PATCH 119/156] android: force OpenCV library target to "android-21" --- platforms/android/build-tests/test_ant_build.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platforms/android/build-tests/test_ant_build.py b/platforms/android/build-tests/test_ant_build.py index 8ed2bdd66..73ac4d018 100644 --- a/platforms/android/build-tests/test_ant_build.py +++ b/platforms/android/build-tests/test_ant_build.py @@ -17,7 +17,7 @@ class TestAntBuild(unittest.TestCase): self.sample_dir = os.path.join(self.workdir, "project") def shortDescription(self): - return "TARGET: %s, SAMPLE: %s" % (self.target, os.path.basename(self.src_sample_dir)) + return "TARGET: %r, SAMPLE: %s" % (self.target, os.path.basename(self.src_sample_dir)) def setUp(self): if os.path.exists(self.workdir): @@ -32,7 +32,7 @@ class TestAntBuild(unittest.TestCase): shutil.rmtree(self.workdir) def runTest(self): - cmd = [os.path.join(os.environ["ANDROID_SDK"], "tools", "android"), "update", "project", "-p", self.lib_dir, "-t", self.target] + cmd = [os.path.join(os.environ["ANDROID_SDK"], "tools", "android"), "update", "project", "-p", self.lib_dir, "-t", self.target[0]] retcode = subprocess.call(cmd) self.assertEqual(retcode, 0, "android update opencv project failed") @@ -40,7 +40,7 @@ class TestAntBuild(unittest.TestCase): retcode = subprocess.call(cmd) self.assertEqual(retcode, 0, "opencv ant build failed") - cmd = [os.path.join(os.environ["ANDROID_SDK"], "tools", "android"), "update", "project", "-p", self.sample_dir, "-t", self.target, "-l", os.path.relpath(self.lib_dir, self.sample_dir)] + cmd = [os.path.join(os.environ["ANDROID_SDK"], "tools", "android"), "update", "project", "-p", self.sample_dir, "-t", self.target[1], "-l", os.path.relpath(self.lib_dir, self.sample_dir)] retcode = subprocess.call(cmd) self.assertEqual(retcode, 0, "android update sample project failed") @@ -50,7 +50,7 @@ class TestAntBuild(unittest.TestCase): def suite(workdir, opencv_lib_path, opencv_samples_path): suite = unittest.TestSuite() - for target in ["android-14", "android-17"]: + for target in [("android-21", "android-14"), ("android-21", "android-17")]: for item in os.listdir(opencv_samples_path): item = os.path.join(opencv_samples_path, item) if (os.path.exists(os.path.join(item, "AndroidManifest.xml"))): From ddd91bcebf0b6661a785be4db8540a7a1c5f2d94 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 12 Oct 2015 18:12:34 +0300 Subject: [PATCH 120/156] android: add targetSdkVersion="21" --- modules/java/android_lib/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/java/android_lib/AndroidManifest.xml b/modules/java/android_lib/AndroidManifest.xml index 1943221e9..228c6cfbb 100644 --- a/modules/java/android_lib/AndroidManifest.xml +++ b/modules/java/android_lib/AndroidManifest.xml @@ -4,5 +4,5 @@ android:versionCode="@OPENCV_VERSION_MAJOR@@OPENCV_VERSION_MINOR@@OPENCV_VERSION_PATCH@0" android:versionName="@OPENCV_VERSION@"> - + From 411be4fde8a961c63dd8fd12c19818cc06710197 Mon Sep 17 00:00:00 2001 From: Aman Verma Date: Mon, 12 Oct 2015 16:16:27 +0000 Subject: [PATCH 121/156] Fix for #5481, removing repeated/useless assignment in contours.cpp --- modules/imgproc/src/contours.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/imgproc/src/contours.cpp b/modules/imgproc/src/contours.cpp index bb21e4106..4cb3f55c4 100644 --- a/modules/imgproc/src/contours.cpp +++ b/modules/imgproc/src/contours.cpp @@ -222,7 +222,6 @@ cvStartFindContours( void* _img, CvMemStorage* storage, scanner->lnbd.x = 0; scanner->lnbd.y = 1; scanner->nbd = 2; - scanner->mode = (int) mode; scanner->frame_info.contour = &(scanner->frame); scanner->frame_info.is_hole = 1; scanner->frame_info.next = 0; From 40b2dfae096eab7693bafe3207d7c1d8406cb440 Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Tue, 13 Oct 2015 10:41:09 +0300 Subject: [PATCH 122/156] Fix for filter2D and IPP < 900 --- modules/imgproc/src/filter.cpp | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 42a1130a3..5eec45f9f 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -4579,7 +4579,11 @@ static bool ipp_filter2D( InputArray _src, OutputArray _dst, int ddepth, int stype = src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype), ktype = kernel.type(), kdepth = CV_MAT_DEPTH(ktype); bool isolated = (borderType & BORDER_ISOLATED) != 0; +#if IPP_VERSION_X100 >= 900 Point ippAnchor((kernel.cols-1)/2, (kernel.rows-1)/2); +#else + Point ippAnchor(kernel.cols >> 1, kernel.rows >> 1); +#endif int borderTypeNI = borderType & ~BORDER_ISOLATED; IppiBorderType ippBorderType = ippiGetBorderType(borderTypeNI); @@ -4618,13 +4622,21 @@ static bool ipp_filter2D( InputArray _src, OutputArray _dst, int ddepth, { Ipp32f *pKerBuffer = (Ipp32f*)kernel.data; IppAutoBuffer kerTmp; - if(kernel.step != kernel.cols) + int kerStep = sizeof(Ipp32f)*kernelSize.width; +#if IPP_VERSION_X100 >= 900 + if(kernel.step != kerStep) { - kerTmp.Alloc(sizeof(Ipp32f)*kernelSize.width*kernelSize.height); - if(ippiCopy_32f_C1R((Ipp32f*)kernel.data, (int)kernel.step, kerTmp, kernelSize.width*sizeof(Ipp32f), kernelSize) < 0) + kerTmp.Alloc(kerStep*kernelSize.height); + if(ippiCopy_32f_C1R((Ipp32f*)kernel.data, (int)kernel.step, kerTmp, kerStep, kernelSize) < 0) return false; pKerBuffer = kerTmp; } +#else + kerTmp.Alloc(kerStep*kernelSize.height); + Mat kerFlip(Size(kernelSize.width, kernelSize.height), CV_32FC1, kerTmp, kerStep); + flip(kernel, kerFlip, -1); + pKerBuffer = kerTmp; +#endif if((status = ippiFilterBorderInit_32f(pKerBuffer, kernelSize, dataType, cn, ippRndFinancial, spec)) >= 0 ) @@ -4637,13 +4649,21 @@ static bool ipp_filter2D( InputArray _src, OutputArray _dst, int ddepth, { Ipp16s *pKerBuffer = (Ipp16s*)kernel.data; IppAutoBuffer kerTmp; - if(kernel.step != kernel.cols) + int kerStep = sizeof(Ipp16s)*kernelSize.width; +#if IPP_VERSION_X100 >= 900 + if(kernel.step != kerStep) { - kerTmp.Alloc(sizeof(Ipp16s)*kernelSize.width*kernelSize.height); - if(ippiCopy_16s_C1R((Ipp16s*)kernel.data, (int)kernel.step, kerTmp, kernelSize.width*sizeof(Ipp16s), kernelSize) < 0) + kerTmp.Alloc(kerStep*kernelSize.height); + if(ippiCopy_16s_C1R((Ipp16s*)kernel.data, (int)kernel.step, kerTmp, kerStep, kernelSize) < 0) return false; pKerBuffer = kerTmp; } +#else + kerTmp.Alloc(kerStep*kernelSize.height); + Mat kerFlip(Size(kernelSize.width, kernelSize.height), CV_16SC1, kerTmp, kerStep); + flip(kernel, kerFlip, -1); + pKerBuffer = kerTmp; +#endif if((status = ippiFilterBorderInit_16s(pKerBuffer, kernelSize, 0, dataType, cn, ippRndFinancial, spec)) >= 0) From 0a708e40705e99b90eb5d7c6de922c877734222c Mon Sep 17 00:00:00 2001 From: StevenPuttemans Date: Tue, 13 Oct 2015 14:23:28 +0200 Subject: [PATCH 123/156] adding extra explanation for mask parameter --- modules/core/include/opencv2/core/mat.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index 3133876e4..caeecbf80 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -1073,6 +1073,7 @@ public: @param m Destination matrix. If it does not have a proper size or type before the operation, it is reallocated. @param mask Operation mask. Its non-zero elements indicate which matrix elements need to be copied. + The mask has to be of type CV_8U and can have 1 or multiple channels. */ void copyTo( OutputArray m, InputArray mask ) const; From 7e3d7677aeacd3e15727c0796f8943d2301960de Mon Sep 17 00:00:00 2001 From: Alexander Stohr Date: Wed, 22 Jul 2015 11:11:58 +0200 Subject: [PATCH 124/156] not only print file-not-found as a warning but also print the name of the problematic file and the uri used for the open attempt --- modules/videoio/src/cap_ffmpeg_impl.hpp | 1 + modules/videoio/src/cap_gstreamer.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index f95c5e849..2615f3a49 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -586,6 +586,7 @@ bool CvCapture_FFMPEG::open( const char* _filename ) if (err < 0) { CV_WARN("Error opening file"); + CV_WARN(_filename); goto exit_func; } err = diff --git a/modules/videoio/src/cap_gstreamer.cpp b/modules/videoio/src/cap_gstreamer.cpp index 62a18b5a7..4740126c0 100644 --- a/modules/videoio/src/cap_gstreamer.cpp +++ b/modules/videoio/src/cap_gstreamer.cpp @@ -601,6 +601,8 @@ bool CvCapture_GStreamer::open( int type, const char* filename ) else { CV_WARN("GStreamer: Error opening file\n"); + CV_WARN(filename); + CV_WARN(uri); close(); return false; } From 0098c4b571d55a63c7ebfd200f352b6d422aa159 Mon Sep 17 00:00:00 2001 From: AlexanderStohr Date: Tue, 13 Oct 2015 15:52:42 +0200 Subject: [PATCH 125/156] fix VS2010 error with type mismatch due to volatile qualifier --- modules/imgcodecs/src/grfmt_png.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/imgcodecs/src/grfmt_png.cpp b/modules/imgcodecs/src/grfmt_png.cpp index 5a5f40bb9..2f4a62bae 100644 --- a/modules/imgcodecs/src/grfmt_png.cpp +++ b/modules/imgcodecs/src/grfmt_png.cpp @@ -368,7 +368,7 @@ bool PngEncoder::write( const Mat& img, const std::vector& params ) { f = fopen( m_filename.c_str(), "wb" ); if( f ) - png_init_io( png_ptr, f ); + png_init_io( png_ptr, (png_FILE_p)f ); } int compression_level = -1; // Invalid value to allow setting 0-9 as valid @@ -437,7 +437,7 @@ bool PngEncoder::write( const Mat& img, const std::vector& params ) } png_destroy_write_struct( &png_ptr, &info_ptr ); - if(f) fclose( f ); + if(f) fclose( (FILE*)f ); return result; } From d81d51d1555f7dc55b5bc8ec7d1eccb7f5e759f8 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Tue, 9 Dec 2014 15:46:00 +0300 Subject: [PATCH 126/156] assing labels to targets and sources --- cmake/OpenCVModule.cmake | 26 ++++++++++++++++++++++++++ modules/cudev/test/CMakeLists.txt | 4 ++++ 2 files changed, 30 insertions(+) diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index 85beca606..9a330e0de 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -26,6 +26,7 @@ # To control the setup of the module you could also set: # the_description - text to be used as current module description +# the_label - label for current module # OPENCV_MODULE_TYPE - STATIC|SHARED - set to force override global settings for current module # OPENCV_MODULE_IS_PART_OF_WORLD - ON|OFF (default ON) - should the module be added to the opencv_world? # BUILD_${the_module}_INIT - ON|OFF (default ON) - initial value for BUILD_${the_module} @@ -191,6 +192,15 @@ macro(ocv_add_module _name) set(OPENCV_MODULE_${the_module}_IS_PART_OF_WORLD OFF CACHE INTERNAL "") endif() + if(NOT DEFINED the_label) + if(OPENCV_PROCESSING_EXTRA_MODULES) + set(the_label "Extra") + else() + set(the_label "Main") + endif() + endif() + set(OPENCV_MODULE_${the_module}_LABEL "${the_label};${the_module}" CACHE INTERNAL "") + if(BUILD_${the_module}) set(OPENCV_MODULES_BUILD ${OPENCV_MODULES_BUILD} "${the_module}" CACHE INTERNAL "List of OpenCV modules included into the build") else() @@ -763,6 +773,10 @@ macro(_ocv_create_module) unset(sub_links) unset(cuda_objs) + set_target_properties(${the_module} PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};Module") + set_source_files_properties(${OPENCV_MODULE_${the_module}_HEADERS} ${OPENCV_MODULE_${the_module}_SOURCES} ${${the_module}_pch} + PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};Module") + ocv_target_link_libraries(${the_module} ${OPENCV_MODULE_${the_module}_DEPS_TO_LINK}) ocv_target_link_libraries(${the_module} LINK_INTERFACE_LIBRARIES ${OPENCV_MODULE_${the_module}_DEPS_TO_LINK}) ocv_target_link_libraries(${the_module} ${OPENCV_MODULE_${the_module}_DEPS_EXT} ${OPENCV_LINKER_LIBS} ${IPP_LIBS} ${ARGN}) @@ -970,6 +984,10 @@ function(ocv_add_perf_tests) ocv_target_link_libraries(${the_target} ${perf_deps} ${OPENCV_MODULE_${the_module}_DEPS} ${OPENCV_LINKER_LIBS}) add_dependencies(opencv_perf_tests ${the_target}) + set_target_properties(${the_target} PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};PerfTest") + set_source_files_properties(${OPENCV_PERF_${the_module}_SOURCES} ${${the_target}_pch} + PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};PerfTest") + # Additional target properties set_target_properties(${the_target} PROPERTIES DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" @@ -1036,6 +1054,10 @@ function(ocv_add_accuracy_tests) ocv_target_link_libraries(${the_target} ${test_deps} ${OPENCV_MODULE_${the_module}_DEPS} ${OPENCV_LINKER_LIBS}) add_dependencies(opencv_tests ${the_target}) + set_target_properties(${the_target} PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};AccuracyTest") + set_source_files_properties(${OPENCV_TEST_${the_module}_SOURCES} ${${the_target}_pch} + PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};AccuracyTest") + # Additional target properties set_target_properties(${the_target} PROPERTIES DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" @@ -1093,6 +1115,10 @@ function(ocv_add_samples) ocv_target_link_libraries(${the_target} ${samples_deps}) set_target_properties(${the_target} PROPERTIES PROJECT_LABEL "(sample) ${name}") + set_target_properties(${the_target} PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};Sample") + set_source_files_properties("${source}" + PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};Sample") + if(ENABLE_SOLUTION_FOLDERS) set_target_properties(${the_target} PROPERTIES OUTPUT_NAME "${module_id}-example-${name}" diff --git a/modules/cudev/test/CMakeLists.txt b/modules/cudev/test/CMakeLists.txt index b3474168e..e4c753ee7 100644 --- a/modules/cudev/test/CMakeLists.txt +++ b/modules/cudev/test/CMakeLists.txt @@ -32,6 +32,10 @@ if(OCV_DEPENDENCIES_FOUND) ocv_target_link_libraries(${the_target} ${test_deps} ${OPENCV_LINKER_LIBS} ${CUDA_LIBRARIES}) add_dependencies(opencv_tests ${the_target}) + set_target_properties(${the_target} PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL}") + set_source_files_properties(${OPENCV_TEST_${the_module}_SOURCES} ${${the_target}_pch} + PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};AccuracyTest") + # Additional target properties set_target_properties(${the_target} PROPERTIES DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" From 02c48ab7d698092239b90aaebc280812d9cdf618 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Fri, 12 Dec 2014 18:21:57 +0300 Subject: [PATCH 127/156] add CTest support to build tree --- CMakeLists.txt | 2 ++ cmake/OpenCVModule.cmake | 20 ++++++++------------ cmake/OpenCVUtils.cmake | 29 +++++++++++++++++++++++++++++ modules/cudev/test/CMakeLists.txt | 4 +--- modules/ts/src/ts_func.cpp | 3 +++ 5 files changed, 43 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1482dec73..ec3d17928 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,6 +85,8 @@ if(DEFINED CMAKE_BUILD_TYPE) set_property( CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CMAKE_CONFIGURATION_TYPES} ) endif() +enable_testing() + project(OpenCV CXX C) if(MSVC) diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index 9a330e0de..92894b8b8 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -1008,6 +1008,12 @@ function(ocv_add_perf_tests) if(NOT BUILD_opencv_world) _ocv_add_precompiled_headers(${the_target}) endif() + + ocv_add_test_from_target("${the_target}" "Performance" "${the_target}") + ocv_add_test_from_target("opencv_sanity_${name}" "Sanity" "${the_target}" + "--perf_min_samples=1" + "--perf_force_samples=1" + "--perf_verify_sanity") else(OCV_DEPENDENCIES_FOUND) # TODO: warn about unsatisfied dependencies endif(OCV_DEPENDENCIES_FOUND) @@ -1068,21 +1074,11 @@ function(ocv_add_accuracy_tests) set_target_properties(${the_target} PROPERTIES FOLDER "tests accuracy") endif() - enable_testing() - get_target_property(LOC ${the_target} LOCATION) - add_test(${the_target} "${LOC}") - - if(WINRT) - # removing APPCONTAINER from tests to run from console - # look for detailed description inside of ocv_create_module macro above - add_custom_command(TARGET "opencv_test_${name}" - POST_BUILD - COMMAND link.exe /edit /APPCONTAINER:NO $(TargetPath)) - endif() - if(NOT BUILD_opencv_world) _ocv_add_precompiled_headers(${the_target}) endif() + + ocv_add_test_from_target("${the_target}" "Accuracy" "${the_target}") else(OCV_DEPENDENCIES_FOUND) # TODO: warn about unsatisfied dependencies endif(OCV_DEPENDENCIES_FOUND) diff --git a/cmake/OpenCVUtils.cmake b/cmake/OpenCVUtils.cmake index e105f8726..e4e8771bf 100644 --- a/cmake/OpenCVUtils.cmake +++ b/cmake/OpenCVUtils.cmake @@ -911,3 +911,32 @@ function(ocv_download) set(DOWNLOAD_PACKAGE_LOCATION ${DOWNLOAD_TARGET} PARENT_SCOPE) endfunction() + +function(ocv_add_test_from_target test_name test_kind the_target) + if(CMAKE_VERSION VERSION_GREATER "2.8" AND NOT CMAKE_CROSSCOMPILING) + if(NOT "${test_kind}" MATCHES "^(Accuracy|Performance|Sanity)$") + message(FATAL_ERROR "Unknown test kind : ${test_kind}") + endif() + if(NOT TARGET "${the_target}") + message(FATAL_ERROR "${the_target} is not a CMake target") + endif() + + string(TOLOWER "${test_kind}" test_kind_lower) + set(test_report_dir "${CMAKE_BINARY_DIR}/test-reports/${test_kind_lower}") + file(MAKE_DIRECTORY "${test_report_dir}") + + add_test(NAME "${test_name}" + COMMAND "${the_target}" + "--gtest_output=xml:${the_target}.xml" + ${ARGN}) + + set_tests_properties("${test_name}" PROPERTIES + LABELS "${OPENCV_MODULE_${the_module}_LABEL};${test_kind}" + WORKING_DIRECTORY "${test_report_dir}") + + if(OPENCV_TEST_DATA_PATH) + set_tests_properties("${test_name}" PROPERTIES + ENVIRONMENT "OPENCV_TEST_DATA_PATH=${OPENCV_TEST_DATA_PATH}") + endif() + endif() +endfunction() diff --git a/modules/cudev/test/CMakeLists.txt b/modules/cudev/test/CMakeLists.txt index e4c753ee7..a7bd6328b 100644 --- a/modules/cudev/test/CMakeLists.txt +++ b/modules/cudev/test/CMakeLists.txt @@ -46,9 +46,7 @@ if(OCV_DEPENDENCIES_FOUND) set_target_properties(${the_target} PROPERTIES FOLDER "tests accuracy") endif() - enable_testing() - get_target_property(LOC ${the_target} LOCATION) - add_test(${the_target} "${LOC}") + ocv_add_test_from_target("${the_target}" "Accuracy" "${the_target}") if(INSTALL_TESTS) install(TARGETS ${the_target} RUNTIME DESTINATION ${OPENCV_TEST_INSTALL_PATH} COMPONENT tests) diff --git a/modules/ts/src/ts_func.cpp b/modules/ts/src/ts_func.cpp index 202a96f36..b6409ad37 100644 --- a/modules/ts/src/ts_func.cpp +++ b/modules/ts/src/ts_func.cpp @@ -2951,6 +2951,9 @@ MatComparator::operator()(const char* expr1, const char* expr2, void printVersionInfo(bool useStdOut) { + // Tell CTest not to discard any output + if(useStdOut) std::cout << "CTEST_FULL_OUTPUT" << std::endl; + ::testing::Test::RecordProperty("cv_version", CV_VERSION); if(useStdOut) std::cout << "OpenCV version: " << CV_VERSION << std::endl; From d8e470fc303612d9874542d6b738e24bc1a1d525 Mon Sep 17 00:00:00 2001 From: Rodrigo Benenson Date: Tue, 13 Oct 2015 19:04:06 +0200 Subject: [PATCH 128/156] CommandLineParser missing gpu option As is it was not possible to use CUDA. --- samples/gpu/super_resolution.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/gpu/super_resolution.cpp b/samples/gpu/super_resolution.cpp index f106f76d3..026afd971 100644 --- a/samples/gpu/super_resolution.cpp +++ b/samples/gpu/super_resolution.cpp @@ -63,7 +63,7 @@ int main(int argc, const char* argv[]) "{ i iterations | 180 | Iteration count }" "{ t temporal | 4 | Radius of the temporal search area }" "{ f flow | farneback | Optical flow algorithm (farneback, simple, tvl1, brox, pyrlk) }" - "{ g | false | CPU as default device, cuda for CUDA }" + "{ g gpu | false | CPU as default device, cuda for CUDA }" "{ h help | false | Print help message }" ); From 066c775321debb14f82dbc6d82068af02c472394 Mon Sep 17 00:00:00 2001 From: spmallick Date: Tue, 13 Oct 2015 15:51:43 -0700 Subject: [PATCH 129/156] Update window_QT.h QPushButton was included twice. --- modules/highgui/src/window_QT.h | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/highgui/src/window_QT.h b/modules/highgui/src/window_QT.h index 20cd4142a..c0769dcc9 100644 --- a/modules/highgui/src/window_QT.h +++ b/modules/highgui/src/window_QT.h @@ -73,7 +73,6 @@ #include #include #include -#include #include #include #include From d5d16bb3b1e6e800497e4532364a205ccef3509b Mon Sep 17 00:00:00 2001 From: "paul.kim" Date: Thu, 15 Oct 2015 11:03:46 +0900 Subject: [PATCH 130/156] Fix the issue in mouse click event --- samples/python2/camshift.py | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/python2/camshift.py b/samples/python2/camshift.py index 862d5126a..867cee9b4 100755 --- a/samples/python2/camshift.py +++ b/samples/python2/camshift.py @@ -54,6 +54,7 @@ class App(object): if event == cv2.EVENT_LBUTTONDOWN: self.drag_start = (x, y) self.tracking_state = 0 + return if self.drag_start: if flags & cv2.EVENT_FLAG_LBUTTON: h, w = self.frame.shape[:2] From f260b13a6fe6a228283f48d98533619e8bd5f1dc Mon Sep 17 00:00:00 2001 From: grundman Date: Fri, 16 Oct 2015 11:19:27 -0700 Subject: [PATCH 131/156] Fix racy modification of ForThread::m_state during invocation of stop() --- modules/core/src/parallel_pthreads.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/core/src/parallel_pthreads.cpp b/modules/core/src/parallel_pthreads.cpp index df99f18bf..8bf131e14 100644 --- a/modules/core/src/parallel_pthreads.cpp +++ b/modules/core/src/parallel_pthreads.cpp @@ -304,14 +304,18 @@ void ForThread::stop() { if(m_state == eFTStarted) { + pthread_mutex_lock(&m_thread_mutex); m_state = eFTToStop; + pthread_mutex_unlock(&m_thread_mutex); run(); pthread_join(m_posix_thread, NULL); } + pthread_mutex_lock(&m_thread_mutex); m_state = eFTStoped; + pthread_mutex_unlock(&m_thread_mutex); } void ForThread::run() From f7981a8ae8b4af3e536639c16774e979ce8a45d9 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Thu, 8 Oct 2015 16:56:18 +0200 Subject: [PATCH 132/156] support setting focus and autofocus with V4L2 also refactor property range handling and opencv property to V4L2 translation. --- modules/videoio/include/opencv2/videoio.hpp | 4 +- .../include/opencv2/videoio/videoio_c.h | 1 + modules/videoio/src/cap_v4l.cpp | 452 +++++------------- 3 files changed, 131 insertions(+), 326 deletions(-) diff --git a/modules/videoio/include/opencv2/videoio.hpp b/modules/videoio/include/opencv2/videoio.hpp index f37a8036c..503fd5be6 100644 --- a/modules/videoio/include/opencv2/videoio.hpp +++ b/modules/videoio/include/opencv2/videoio.hpp @@ -133,7 +133,9 @@ enum { CAP_PROP_POS_MSEC =0, CAP_PROP_TILT =34, CAP_PROP_ROLL =35, CAP_PROP_IRIS =36, - CAP_PROP_SETTINGS =37 + CAP_PROP_SETTINGS =37, + CAP_PROP_BUFFERSIZE =38, + CAP_PROP_AUTOFOCUS =39 }; diff --git a/modules/videoio/include/opencv2/videoio/videoio_c.h b/modules/videoio/include/opencv2/videoio/videoio_c.h index 0365b9223..6d7bd640c 100644 --- a/modules/videoio/include/opencv2/videoio/videoio_c.h +++ b/modules/videoio/include/opencv2/videoio/videoio_c.h @@ -189,6 +189,7 @@ enum CV_CAP_PROP_IRIS =36, CV_CAP_PROP_SETTINGS =37, CV_CAP_PROP_BUFFERSIZE =38, + CV_CAP_PROP_AUTOFOCUS =39, CV_CAP_PROP_AUTOGRAB =1024, // property for videoio class CvCapture_Android only CV_CAP_PROP_SUPPORTED_PREVIEW_SIZES_STRING=1025, // readonly, tricky property, returns cpnst char* indeed diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index a879de7d5..f3464f52f 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -330,13 +330,30 @@ typedef struct CvCaptureCAM_V4L struct timeval timestamp; /* V4L2 control variables */ - int v4l2_brightness, v4l2_brightness_min, v4l2_brightness_max; - int v4l2_contrast, v4l2_contrast_min, v4l2_contrast_max; - int v4l2_saturation, v4l2_saturation_min, v4l2_saturation_max; - int v4l2_hue, v4l2_hue_min, v4l2_hue_max; - int v4l2_gain, v4l2_gain_min, v4l2_gain_max; - int v4l2_exposure, v4l2_exposure_min, v4l2_exposure_max; + cv::Range focus, brightness, contrast, saturation, hue, gain, exposure; + cv::Range getRange(int property_id) { + switch (property_id) { + case CV_CAP_PROP_BRIGHTNESS: + return brightness; + case CV_CAP_PROP_CONTRAST: + return contrast; + case CV_CAP_PROP_SATURATION: + return saturation; + case CV_CAP_PROP_HUE: + return hue; + case CV_CAP_PROP_GAIN: + return gain; + case CV_CAP_PROP_EXPOSURE: + return exposure; + case CV_CAP_PROP_FOCUS: + return focus; + case CV_CAP_PROP_AUTOFOCUS: + return cv::Range(0, 1); + default: + return cv::Range(0, 255); + } + } #endif /* HAVE_CAMV4L2 */ } @@ -645,158 +662,72 @@ static int autosetup_capture_mode_v4l(CvCaptureCAM_V4L* capture) #ifdef HAVE_CAMV4L2 +static void v4l2_control_range(CvCaptureCAM_V4L* cap, __u32 id) +{ + CLEAR (cap->queryctrl); + cap->queryctrl.id = id; + + if(0 != ioctl(cap->deviceHandle, VIDIOC_QUERYCTRL, &cap->queryctrl)) + { + if (errno != EINVAL) + perror ("VIDIOC_QUERYCTRL"); + return; + } + + if (cap->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) + return; + + cv::Range range(cap->queryctrl.minimum, cap->queryctrl.maximum); + + switch(cap->queryctrl.id) { + case V4L2_CID_BRIGHTNESS: + cap->brightness = range; + break; + case V4L2_CID_CONTRAST: + cap->contrast = range; + break; + case V4L2_CID_SATURATION: + cap->saturation = range; + break; + case V4L2_CID_HUE: + cap->hue = range; + break; + case V4L2_CID_GAIN: + cap->gain = range; + break; + case V4L2_CID_EXPOSURE: + cap->exposure = range; + break; + case V4L2_CID_FOCUS_ABSOLUTE: + cap->focus = range; + break; + } +} static void v4l2_scan_controls(CvCaptureCAM_V4L* capture) { __u32 ctrl_id; - for (ctrl_id = V4L2_CID_BASE; - ctrl_id < V4L2_CID_LASTP1; - ctrl_id++) + for (ctrl_id = V4L2_CID_BASE; ctrl_id < V4L2_CID_LASTP1; ctrl_id++) { - - /* set the id we will query now */ - CLEAR (capture->queryctrl); - capture->queryctrl.id = ctrl_id; - - if (0 == ioctl (capture->deviceHandle, VIDIOC_QUERYCTRL, - &capture->queryctrl)) - { - - if (capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) - continue; - - if (capture->queryctrl.id == V4L2_CID_BRIGHTNESS) - { - capture->v4l2_brightness = 1; - capture->v4l2_brightness_min = capture->queryctrl.minimum; - capture->v4l2_brightness_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_CONTRAST) - { - capture->v4l2_contrast = 1; - capture->v4l2_contrast_min = capture->queryctrl.minimum; - capture->v4l2_contrast_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_SATURATION) - { - capture->v4l2_saturation = 1; - capture->v4l2_saturation_min = capture->queryctrl.minimum; - capture->v4l2_saturation_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_HUE) - { - capture->v4l2_hue = 1; - capture->v4l2_hue_min = capture->queryctrl.minimum; - capture->v4l2_hue_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_GAIN) - { - capture->v4l2_gain = 1; - capture->v4l2_gain_min = capture->queryctrl.minimum; - capture->v4l2_gain_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_EXPOSURE) - { - capture->v4l2_exposure = 1; - capture->v4l2_exposure_min = capture->queryctrl.minimum; - capture->v4l2_exposure_max = capture->queryctrl.maximum; - } - - - } else { - - if (errno == EINVAL) - continue; - - perror ("VIDIOC_QUERYCTRL"); - - } - + v4l2_control_range(capture, ctrl_id); } for (ctrl_id = V4L2_CID_PRIVATE_BASE;;ctrl_id++) { - - /* set the id we will query now */ - CLEAR (capture->queryctrl); - capture->queryctrl.id = ctrl_id; - - if (0 == ioctl (capture->deviceHandle, VIDIOC_QUERYCTRL, - &capture->queryctrl)) - { - - if (capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) - continue; - - if (capture->queryctrl.id == V4L2_CID_BRIGHTNESS) - { - capture->v4l2_brightness = 1; - capture->v4l2_brightness_min = capture->queryctrl.minimum; - capture->v4l2_brightness_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_CONTRAST) - { - capture->v4l2_contrast = 1; - capture->v4l2_contrast_min = capture->queryctrl.minimum; - capture->v4l2_contrast_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_SATURATION) - { - capture->v4l2_saturation = 1; - capture->v4l2_saturation_min = capture->queryctrl.minimum; - capture->v4l2_saturation_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_HUE) - { - capture->v4l2_hue = 1; - capture->v4l2_hue_min = capture->queryctrl.minimum; - capture->v4l2_hue_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_GAIN) - { - capture->v4l2_gain = 1; - capture->v4l2_gain_min = capture->queryctrl.minimum; - capture->v4l2_gain_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_EXPOSURE) - { - capture->v4l2_exposure = 1; - capture->v4l2_exposure_min = capture->queryctrl.minimum; - capture->v4l2_exposure_max = capture->queryctrl.maximum; - } - - } else { + v4l2_control_range(capture, ctrl_id); if (errno == EINVAL) break; - - perror ("VIDIOC_QUERYCTRL"); - - } - } + v4l2_control_range(capture, V4L2_CID_FOCUS_ABSOLUTE); } static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) { - int detect_v4l2 = 0; - - detect_v4l2 = try_init_v4l2(capture, deviceName); - - if (detect_v4l2 != 1) { + if (try_init_v4l2(capture, deviceName) != 1) { /* init of the v4l2 device is not OK */ return -1; } @@ -804,30 +735,7 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) /* starting from here, we assume we are in V4L2 mode */ V4L2_SUPPORT = 1; - /* Init V4L2 control variables */ - capture->v4l2_brightness = 0; - capture->v4l2_contrast = 0; - capture->v4l2_saturation = 0; - capture->v4l2_hue = 0; - capture->v4l2_gain = 0; - capture->v4l2_exposure = 0; - - capture->v4l2_brightness_min = 0; - capture->v4l2_contrast_min = 0; - capture->v4l2_saturation_min = 0; - capture->v4l2_hue_min = 0; - capture->v4l2_gain_min = 0; - capture->v4l2_exposure_min = 0; - - capture->v4l2_brightness_max = 0; - capture->v4l2_contrast_max = 0; - capture->v4l2_saturation_max = 0; - capture->v4l2_hue_max = 0; - capture->v4l2_gain_max = 0; - capture->v4l2_exposure_max = 0; - - capture->timestamp.tv_sec = 0; - capture->timestamp.tv_usec = 0; + /* V4L2 control variables are zero (memset above) */ /* Scan V4L2 controls */ v4l2_scan_controls(capture); @@ -2290,6 +2198,31 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { return(&capture->frame); } +static inline __u32 capPropertyToV4L2(int prop) { + switch (prop) { +#ifdef HAVE_CAMV4L2 + case CV_CAP_PROP_BRIGHTNESS: + return V4L2_CID_BRIGHTNESS; + case CV_CAP_PROP_CONTRAST: + return V4L2_CID_CONTRAST; + case CV_CAP_PROP_SATURATION: + return V4L2_CID_SATURATION; + case CV_CAP_PROP_HUE: + return V4L2_CID_HUE; + case CV_CAP_PROP_GAIN: + return V4L2_CID_GAIN; + case CV_CAP_PROP_EXPOSURE: + return V4L2_CID_EXPOSURE; + case CV_CAP_PROP_AUTOFOCUS: + return V4L2_CID_FOCUS_AUTO; + case CV_CAP_PROP_FOCUS: + return V4L2_CID_FOCUS_ABSOLUTE; +#endif + default: + return -1; + } +} + static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, int property_id ) { @@ -2299,11 +2232,6 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, if (V4L2_SUPPORT == 1) #endif { - - /* default value for min and max */ - int v4l2_min = 0; - int v4l2_max = 255; - CLEAR (capture->form); capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) { @@ -2321,39 +2249,25 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, /* initialize the control structure */ - switch (property_id) { - case CV_CAP_PROP_POS_MSEC: + if(property_id == CV_CAP_PROP_POS_MSEC) { if (capture->FirstCapture) { return 0; } else { return 1000 * capture->timestamp.tv_sec + ((double) capture->timestamp.tv_usec) / 1000; } - break; - case CV_CAP_PROP_BRIGHTNESS: - capture->control.id = V4L2_CID_BRIGHTNESS; - break; - case CV_CAP_PROP_CONTRAST: - capture->control.id = V4L2_CID_CONTRAST; - break; - case CV_CAP_PROP_SATURATION: - capture->control.id = V4L2_CID_SATURATION; - break; - case CV_CAP_PROP_HUE: - capture->control.id = V4L2_CID_HUE; - break; - case CV_CAP_PROP_GAIN: - capture->control.id = V4L2_CID_GAIN; - break; - case CV_CAP_PROP_EXPOSURE: - capture->control.id = V4L2_CID_EXPOSURE; - break; - default: - fprintf(stderr, - "VIDEOIO ERROR: V4L2: getting property #%d is not supported\n", - property_id); - return -1; } + __u32 v4l2id = capPropertyToV4L2(property_id); + + if(v4l2id == __u32(-1)) { + fprintf(stderr, + "VIDEOIO ERROR: V4L2: getting property #%d is not supported\n", + property_id); + return -1; + } + + capture->control.id = v4l2id; + if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_CTRL, &capture->control)) { @@ -2377,43 +2291,27 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, case CV_CAP_PROP_EXPOSURE: fprintf (stderr, "Exposure"); break; + case CV_CAP_PROP_AUTOFOCUS: + fprintf (stderr, "Autofocus"); + break; + case CV_CAP_PROP_FOCUS: + fprintf (stderr, "Focus"); + break; } fprintf (stderr, " is not supported by your device\n"); return -1; } - /* get the min/max values */ - switch (property_id) { - - case CV_CAP_PROP_BRIGHTNESS: - v4l2_min = capture->v4l2_brightness_min; - v4l2_max = capture->v4l2_brightness_max; - break; - case CV_CAP_PROP_CONTRAST: - v4l2_min = capture->v4l2_contrast_min; - v4l2_max = capture->v4l2_contrast_max; - break; - case CV_CAP_PROP_SATURATION: - v4l2_min = capture->v4l2_saturation_min; - v4l2_max = capture->v4l2_saturation_max; - break; - case CV_CAP_PROP_HUE: - v4l2_min = capture->v4l2_hue_min; - v4l2_max = capture->v4l2_hue_max; - break; - case CV_CAP_PROP_GAIN: - v4l2_min = capture->v4l2_gain_min; - v4l2_max = capture->v4l2_gain_max; - break; - case CV_CAP_PROP_EXPOSURE: - v4l2_min = capture->v4l2_exposure_min; - v4l2_max = capture->v4l2_exposure_max; - break; + if(property_id == CV_CAP_PROP_AUTOFOCUS) { + return (double)capture->control.value; } + /* get the min/max values */ + cv::Range range = capture->getRange(property_id); + /* all was OK, so convert to 0.0 - 1.0 range, and return the value */ - return ((float)capture->control.value - v4l2_min + 1) / (v4l2_max - v4l2_min); + return ((float)capture->control.value - range.start + 1) / range.size(); } #endif /* HAVE_CAMV4L2 */ @@ -2603,111 +2501,24 @@ static int icvSetControl (CvCaptureCAM_V4L* capture, if (V4L2_SUPPORT == 1) { - - /* default value for min and max */ - int v4l2_min = 0; - int v4l2_max = 255; - /* initialisations */ - CLEAR (capture->control); + __u32 v4l2id = capPropertyToV4L2(property_id); - /* set which control we want to set */ - switch (property_id) { - - case CV_CAP_PROP_BRIGHTNESS: - capture->control.id = V4L2_CID_BRIGHTNESS; - break; - case CV_CAP_PROP_CONTRAST: - capture->control.id = V4L2_CID_CONTRAST; - break; - case CV_CAP_PROP_SATURATION: - capture->control.id = V4L2_CID_SATURATION; - break; - case CV_CAP_PROP_HUE: - capture->control.id = V4L2_CID_HUE; - break; - case CV_CAP_PROP_GAIN: - capture->control.id = V4L2_CID_GAIN; - break; - case CV_CAP_PROP_EXPOSURE: - capture->control.id = V4L2_CID_EXPOSURE; - break; - default: + if(v4l2id == __u32(-1)) { fprintf(stderr, "VIDEOIO ERROR: V4L2: setting property #%d is not supported\n", property_id); return -1; } - - /* get the min and max values */ - if (-1 == ioctl (capture->deviceHandle, - VIDIOC_G_CTRL, &capture->control)) { -// perror ("VIDIOC_G_CTRL for getting min/max values"); - return -1; - } + /* set which control we want to set */ + CLEAR (capture->control); + capture->control.id = v4l2id; /* get the min/max values */ - switch (property_id) { - - case CV_CAP_PROP_BRIGHTNESS: - v4l2_min = capture->v4l2_brightness_min; - v4l2_max = capture->v4l2_brightness_max; - break; - case CV_CAP_PROP_CONTRAST: - v4l2_min = capture->v4l2_contrast_min; - v4l2_max = capture->v4l2_contrast_max; - break; - case CV_CAP_PROP_SATURATION: - v4l2_min = capture->v4l2_saturation_min; - v4l2_max = capture->v4l2_saturation_max; - break; - case CV_CAP_PROP_HUE: - v4l2_min = capture->v4l2_hue_min; - v4l2_max = capture->v4l2_hue_max; - break; - case CV_CAP_PROP_GAIN: - v4l2_min = capture->v4l2_gain_min; - v4l2_max = capture->v4l2_gain_max; - break; - case CV_CAP_PROP_EXPOSURE: - v4l2_min = capture->v4l2_exposure_min; - v4l2_max = capture->v4l2_exposure_max; - break; - } - - /* initialisations */ - CLEAR (capture->control); - - /* set which control we want to set */ - switch (property_id) { - - case CV_CAP_PROP_BRIGHTNESS: - capture->control.id = V4L2_CID_BRIGHTNESS; - break; - case CV_CAP_PROP_CONTRAST: - capture->control.id = V4L2_CID_CONTRAST; - break; - case CV_CAP_PROP_SATURATION: - capture->control.id = V4L2_CID_SATURATION; - break; - case CV_CAP_PROP_HUE: - capture->control.id = V4L2_CID_HUE; - break; - case CV_CAP_PROP_GAIN: - capture->control.id = V4L2_CID_GAIN; - break; - case CV_CAP_PROP_EXPOSURE: - capture->control.id = V4L2_CID_EXPOSURE; - break; - default: - fprintf(stderr, - "VIDEOIO ERROR: V4L2: setting property #%d is not supported\n", - property_id); - return -1; - } + cv::Range range = capture->getRange(property_id); /* set the value we want to set to the scaled the value */ - capture->control.value = (int)(value * (v4l2_max - v4l2_min) + v4l2_min); + capture->control.value = (int)(value * range.size() + range.start); /* The driver may clamp the value or return ERANGE, ignored here */ if (-1 == ioctl (capture->deviceHandle, @@ -2799,18 +2610,9 @@ static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, width = height = 0; } break; - case CV_CAP_PROP_BRIGHTNESS: - case CV_CAP_PROP_CONTRAST: - case CV_CAP_PROP_SATURATION: - case CV_CAP_PROP_HUE: - case CV_CAP_PROP_GAIN: - case CV_CAP_PROP_EXPOSURE: + default: retval = icvSetControl(capture, property_id, value); break; - default: - fprintf(stderr, - "VIDEOIO ERROR: V4L: setting property #%d is not supported\n", - property_id); } /* return the the status */ From 18034a51384c4c5019508cab63d9abd67a7bb210 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Fri, 9 Oct 2015 12:05:29 +0200 Subject: [PATCH 133/156] allow icvGetPropertyCAM_V4L to return zero now icvGetPropertyCAM_V4L behaves the same as in cap_libv4l. This also fixes passing boolean values. --- modules/videoio/src/cap_v4l.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index f3464f52f..b43bed60e 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -2303,15 +2303,11 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, return -1; } - if(property_id == CV_CAP_PROP_AUTOFOCUS) { - return (double)capture->control.value; - } - /* get the min/max values */ cv::Range range = capture->getRange(property_id); /* all was OK, so convert to 0.0 - 1.0 range, and return the value */ - return ((float)capture->control.value - range.start + 1) / range.size(); + return ((float)capture->control.value - range.start) / range.size(); } #endif /* HAVE_CAMV4L2 */ From c0fe522c9df08e46dcea87fc30409df03df87256 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Fri, 9 Oct 2015 16:01:14 +0200 Subject: [PATCH 134/156] allow changing FPS and Image Size using V4L2 use logic similar to cap_libv4l: replace icvSetVideoSize by v4l2_reset as it was not used for V4L1, the actual frame format is negotiated in try_palette_v4l2 and the stream has to restarted anyway. --- modules/videoio/src/cap_v4l.cpp | 194 +++++++++++--------------------- 1 file changed, 67 insertions(+), 127 deletions(-) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index b43bed60e..3dfbe95ec 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -244,6 +244,7 @@ make & enjoy! /* Defaults - If your board can do better, set it here. Set for the most common type inputs. */ #define DEFAULT_V4L_WIDTH 640 #define DEFAULT_V4L_HEIGHT 480 +#define DEFAULT_V4L_FPS 30 #define CHANNEL_NUMBER 1 #define MAX_CAMERAS 8 @@ -315,6 +316,9 @@ typedef struct CvCaptureCAM_V4L #ifdef HAVE_CAMV4L2 enum PALETTE_TYPE palette; + int index; + int width, height; + __u32 fps; /* V4L2 variables */ buffer buffers[MAX_V4L_BUFFERS + 1]; struct v4l2_capability cap; @@ -373,8 +377,6 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int ); static double icvGetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id ); static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id, double value ); -static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h); - /*********************** Implementations ***************************************/ static int numCameras = 0; @@ -440,8 +442,8 @@ static int try_palette_v4l2(CvCaptureCAM_V4L* capture, unsigned long colorspace) capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; capture->form.fmt.pix.pixelformat = colorspace; capture->form.fmt.pix.field = V4L2_FIELD_ANY; - capture->form.fmt.pix.width = DEFAULT_V4L_WIDTH; - capture->form.fmt.pix.height = DEFAULT_V4L_HEIGHT; + capture->form.fmt.pix.width = capture->width; + capture->form.fmt.pix.height = capture->height; if (-1 == ioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form)) return -1; @@ -725,8 +727,21 @@ static void v4l2_scan_controls(CvCaptureCAM_V4L* capture) v4l2_control_range(capture, V4L2_CID_FOCUS_ABSOLUTE); } -static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) +static int v4l2_set_fps(CvCaptureCAM_V4L* capture) { + v4l2_streamparm setfps; + CLEAR(setfps); + setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + setfps.parm.capture.timeperframe.numerator = 1; + setfps.parm.capture.timeperframe.denominator = capture->fps; + return ioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps); +} + +static int _capture_V4L2 (CvCaptureCAM_V4L *capture) { + char deviceName[MAX_DEVICE_DRIVER_NAME]; + /* Print the CameraNumber at the end of the string with a width of one character */ + sprintf(deviceName, "/dev/video%1d", capture->index); + if (try_init_v4l2(capture, deviceName) != 1) { /* init of the v4l2 device is not OK */ return -1; @@ -777,14 +792,11 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) return -1; } - if (V4L2_SUPPORT == 0) - { - } - if (autosetup_capture_mode_v4l2(capture) == -1) return -1; - icvSetVideoSize(capture, DEFAULT_V4L_WIDTH, DEFAULT_V4L_HEIGHT); + /* try to set framerate */ + v4l2_set_fps(capture); unsigned int min; @@ -887,9 +899,22 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) /* Allocate space for RGBA data */ capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize); + // reinitialize buffers + capture->FirstCapture = 1; + return 1; }; /* End _capture_V4L2 */ +/** + * some properties can not be changed while the device is in streaming mode. + * this method closes and re-opens the device to re-start the stream. + * this also causes buffers to be reallocated if the frame size was changed. + */ +static int v4l2_reset( CvCaptureCAM_V4L* capture) { + icvCloseCAM_V4L(capture); + return _capture_V4L2(capture); +} + #endif /* HAVE_CAMV4L2 */ #ifdef HAVE_CAMV4L @@ -1019,8 +1044,6 @@ static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index) static int autoindex; autoindex = 0; - char deviceName[MAX_DEVICE_DRIVER_NAME]; - if (!numCameras) icvInitCapture_V4L(); /* Havent called icvInitCapture yet - do it now! */ if (!numCameras) @@ -1049,8 +1072,7 @@ static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index) index=autoindex; autoindex++;// i can recall icvOpenCAM_V4l with index=-1 for next camera } - /* Print the CameraNumber at the end of the string with a width of one character */ - sprintf(deviceName, "/dev/video%1d", index); + capture->index = index; /* w/o memset some parts arent initialized - AKA: Fill it with zeros so it is clean */ memset(capture,0,sizeof(CvCaptureCAM_V4L)); @@ -1059,19 +1081,25 @@ static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index) capture->FirstCapture = 1; #ifdef HAVE_CAMV4L2 - if (_capture_V4L2 (capture, deviceName) == -1) { + capture->width = DEFAULT_V4L_WIDTH; + capture->height = DEFAULT_V4L_HEIGHT; + capture->fps = DEFAULT_V4L_FPS; + + if (_capture_V4L2 (capture) == -1) { icvCloseCAM_V4L(capture); V4L2_SUPPORT = 0; #endif /* HAVE_CAMV4L2 */ #ifdef HAVE_CAMV4L + char deviceName[MAX_DEVICE_DRIVER_NAME]; + /* Print the CameraNumber at the end of the string with a width of one character */ + sprintf(deviceName, "/dev/video%1d", capture->index); + if (_capture_V4L (capture, deviceName) == -1) { icvCloseCAM_V4L(capture); return NULL; } #endif /* HAVE_CAMV4L */ #ifdef HAVE_CAMV4L2 - } else { - V4L2_SUPPORT = 1; } #endif /* HAVE_CAMV4L2 */ @@ -2247,6 +2275,18 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, return capture->form.fmt.pix.height; } + if(property_id == CV_CAP_PROP_FPS) { + struct v4l2_streamparm sp; + CLEAR(sp); + sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (ioctl(capture->deviceHandle, VIDIOC_G_PARM, &sp) < 0){ + fprintf(stderr, "VIDEOIO ERROR: V4L: Unable to get camera FPS\n"); + return -1; + } + + return sp.parm.capture.timeperframe.denominator / (double)sp.parm.capture.timeperframe.numerator; + } + /* initialize the control structure */ if(property_id == CV_CAP_PROP_POS_MSEC) { @@ -2376,113 +2416,6 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, }; -static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h) { - -#ifdef HAVE_CAMV4L2 - - if (V4L2_SUPPORT == 1) - { - - CLEAR (capture->cropcap); - capture->cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if (ioctl (capture->deviceHandle, VIDIOC_CROPCAP, &capture->cropcap) < 0) { - fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: VIDIOC_CROPCAP\n"); - } else { - - CLEAR (capture->crop); - capture->crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - capture->crop.c= capture->cropcap.defrect; - - /* set the crop area, but don't exit if the device don't support croping */ - if (ioctl (capture->deviceHandle, VIDIOC_S_CROP, &capture->crop) < 0) { - fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: VIDIOC_S_CROP\n"); - } - } - - CLEAR (capture->form); - capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - /* read the current setting, mainly to retreive the pixelformat information */ - ioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form); - - /* set the values we want to change */ - capture->form.fmt.pix.width = w; - capture->form.fmt.pix.height = h; - capture->form.fmt.win.chromakey = 0; - capture->form.fmt.win.field = V4L2_FIELD_ANY; - capture->form.fmt.win.clips = 0; - capture->form.fmt.win.clipcount = 0; - capture->form.fmt.pix.field = V4L2_FIELD_ANY; - - /* ask the device to change the size - * don't test if the set of the size is ok, because some device - * don't allow changing the size, and we will get the real size - * later */ - ioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form); - - /* try to set framerate to 30 fps */ - struct v4l2_streamparm setfps; - memset (&setfps, 0, sizeof(struct v4l2_streamparm)); - setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - setfps.parm.capture.timeperframe.numerator = 1; - setfps.parm.capture.timeperframe.denominator = 30; - ioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps); - - /* we need to re-initialize some things, like buffers, because the size has - * changed */ - capture->FirstCapture = 1; - - /* Get window info again, to get the real value */ - if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) - { - fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: Could not obtain specifics of capture window.\n\n"); - - icvCloseCAM_V4L(capture); - - return 0; - } - - return 0; - - } -#endif /* HAVE_CAMV4L2 */ -#if defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2) - else -#endif /* HAVE_CAMV4L && HAVE_CAMV4L2 */ -#ifdef HAVE_CAMV4L - { - - if (capture==0) return 0; - if (w>capture->capability.maxwidth) { - w=capture->capability.maxwidth; - } - if (h>capture->capability.maxheight) { - h=capture->capability.maxheight; - } - - capture->captureWindow.width=w; - capture->captureWindow.height=h; - - if (ioctl(capture->deviceHandle, VIDIOCSWIN, &capture->captureWindow) < 0) { - icvCloseCAM_V4L(capture); - return 0; - } - - if (ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) < 0) { - icvCloseCAM_V4L(capture); - return 0; - } - - capture->FirstCapture = 1; - - } -#endif /* HAVE_CAMV4L */ - - return 0; - -} - static int icvSetControl (CvCaptureCAM_V4L* capture, int property_id, double value) { @@ -2589,23 +2522,30 @@ static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, /* two subsequent calls setting WIDTH and HEIGHT will change the video size */ - /* the first one will return an error, though. */ switch (property_id) { case CV_CAP_PROP_FRAME_WIDTH: width = cvRound(value); if(width !=0 && height != 0) { - retval = icvSetVideoSize( capture, width, height); + capture->width = width; + capture->height = height; + retval = v4l2_reset( capture); width = height = 0; } break; case CV_CAP_PROP_FRAME_HEIGHT: height = cvRound(value); if(width !=0 && height != 0) { - retval = icvSetVideoSize( capture, width, height); + capture->width = width; + capture->height = height; + retval = v4l2_reset( capture); width = height = 0; } break; + case CV_CAP_PROP_FPS: + capture->fps = value; + retval = v4l2_reset( capture); + break; default: retval = icvSetControl(capture, property_id, value); break; From 5525cc4d09e24e809de8f9aea3d4c7e131ae7b79 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sat, 10 Oct 2015 12:26:08 +0200 Subject: [PATCH 135/156] implement CAP_PROP_MODE, CAP_PROP_FOURCC and CAP_PROP_FORMAT do not use a custom enum instead of the V4L2 fourcc defines for palette. This way we can easily implement CAP_PROP_FOURCC and CAP_PROP_MODE. --- modules/videoio/src/cap_v4l.cpp | 67 +++++++++++++++------------------ 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index 3dfbe95ec..5a5abfa4f 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -280,25 +280,12 @@ static unsigned int n_buffers = 0; #define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S','9','1','0') /* SN9C10x cmpr. */ #endif -#ifndef V4L2_PIX_FMT_SGBRG -#define V4L2_PIX_FMT_SGBRG v4l2_fourcc('G','B','R','G') /* bayer GBRG GBGB.. RGRG.. */ +#ifndef V4L2_PIX_FMT_SGBRG8 +#define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G','B','R','G') /* bayer GBRG GBGB.. RGRG.. */ #endif #endif /* HAVE_CAMV4L2 */ -enum PALETTE_TYPE { - PALETTE_BGR24 = 1, - PALETTE_YVU420, - PALETTE_YUV411P, - PALETTE_YUYV, - PALETTE_UYVY, - PALETTE_SBGGR8, - PALETTE_SN9C10X, - PALETTE_MJPEG, - PALETTE_SGBRG, - PALETTE_RGB24 -}; - typedef struct CvCaptureCAM_V4L { int deviceHandle; @@ -315,7 +302,7 @@ typedef struct CvCaptureCAM_V4L IplImage frame; #ifdef HAVE_CAMV4L2 - enum PALETTE_TYPE palette; + __u32 palette; int index; int width, height; __u32 fps; @@ -564,17 +551,17 @@ static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture) { if (try_palette_v4l2(capture, V4L2_PIX_FMT_BGR24) == 0) { - capture->palette = PALETTE_BGR24; + capture->palette = V4L2_PIX_FMT_BGR24; } else if (try_palette_v4l2(capture, V4L2_PIX_FMT_YVU420) == 0) { - capture->palette = PALETTE_YVU420; + capture->palette = V4L2_PIX_FMT_YVU420; } else if (try_palette_v4l2(capture, V4L2_PIX_FMT_YUV411P) == 0) { - capture->palette = PALETTE_YUV411P; + capture->palette = V4L2_PIX_FMT_YUV411P; } else @@ -582,35 +569,35 @@ static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture) if (try_palette_v4l2(capture, V4L2_PIX_FMT_MJPEG) == 0 || try_palette_v4l2(capture, V4L2_PIX_FMT_JPEG) == 0) { - capture->palette = PALETTE_MJPEG; + capture->palette = V4L2_PIX_FMT_MJPEG; } else #endif if (try_palette_v4l2(capture, V4L2_PIX_FMT_YUYV) == 0) { - capture->palette = PALETTE_YUYV; + capture->palette = V4L2_PIX_FMT_YUYV; } else if (try_palette_v4l2(capture, V4L2_PIX_FMT_UYVY) == 0) { - capture->palette = PALETTE_UYVY; + capture->palette = V4L2_PIX_FMT_UYVY; } else if (try_palette_v4l2(capture, V4L2_PIX_FMT_SN9C10X) == 0) { - capture->palette = PALETTE_SN9C10X; + capture->palette = V4L2_PIX_FMT_SN9C10X; } else if (try_palette_v4l2(capture, V4L2_PIX_FMT_SBGGR8) == 0) { - capture->palette = PALETTE_SBGGR8; + capture->palette = V4L2_PIX_FMT_SBGGR8; } else - if (try_palette_v4l2(capture, V4L2_PIX_FMT_SGBRG) == 0) + if (try_palette_v4l2(capture, V4L2_PIX_FMT_SGBRG8) == 0) { - capture->palette = PALETTE_SGBRG; + capture->palette = V4L2_PIX_FMT_SGBRG8; } else if (try_palette_v4l2(capture, V4L2_PIX_FMT_RGB24) == 0) { - capture->palette = PALETTE_RGB24; + capture->palette = V4L2_PIX_FMT_RGB24; } else { @@ -2103,27 +2090,28 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { { switch (capture->palette) { - case PALETTE_BGR24: + case V4L2_PIX_FMT_BGR24: memcpy((char *)capture->frame.imageData, (char *)capture->buffers[capture->bufferIndex].start, capture->frame.imageSize); break; - case PALETTE_YVU420: + case V4L2_PIX_FMT_YVU420: yuv420p_to_rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)(capture->buffers[capture->bufferIndex].start), (unsigned char*)capture->frame.imageData); break; - case PALETTE_YUV411P: + case V4L2_PIX_FMT_YUV411P: yuv411p_to_rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)(capture->buffers[capture->bufferIndex].start), (unsigned char*)capture->frame.imageData); break; #ifdef HAVE_JPEG - case PALETTE_MJPEG: + case V4L2_PIX_FMT_MJPEG: + case V4L2_PIX_FMT_JPEG: if (!mjpeg_to_rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)(capture->buffers[capture->bufferIndex] @@ -2134,26 +2122,26 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { break; #endif - case PALETTE_YUYV: + case V4L2_PIX_FMT_YUYV: yuyv_to_rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)(capture->buffers[capture->bufferIndex].start), (unsigned char*)capture->frame.imageData); break; - case PALETTE_UYVY: + case V4L2_PIX_FMT_UYVY: uyvy_to_rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)(capture->buffers[capture->bufferIndex].start), (unsigned char*)capture->frame.imageData); break; - case PALETTE_SBGGR8: + case V4L2_PIX_FMT_SBGGR8: bayer2rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)capture->buffers[capture->bufferIndex].start, (unsigned char*)capture->frame.imageData); break; - case PALETTE_SN9C10X: + case V4L2_PIX_FMT_SN9C10X: sonix_decompress_init(); sonix_decompress(capture->form.fmt.pix.width, capture->form.fmt.pix.height, @@ -2166,13 +2154,13 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { (unsigned char*)capture->frame.imageData); break; - case PALETTE_SGBRG: + case V4L2_PIX_FMT_SGBRG8: sgbrg2rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start, (unsigned char*)capture->frame.imageData); break; - case PALETTE_RGB24: + case V4L2_PIX_FMT_RGB24: rgb24_to_rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start, @@ -2273,6 +2261,11 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, return capture->form.fmt.pix.width; case CV_CAP_PROP_FRAME_HEIGHT: return capture->form.fmt.pix.height; + case CV_CAP_PROP_FOURCC: + case CV_CAP_PROP_MODE: + return capture->palette; + case CV_CAP_PROP_FORMAT: + return CV_8UC3; } if(property_id == CV_CAP_PROP_FPS) { From 588eba3b3726aba89a5bf3447ccaf96c9be10a01 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sat, 10 Oct 2015 12:39:37 +0200 Subject: [PATCH 136/156] simplify autosetup_capture_mode_v4l2 by using a for loop --- modules/videoio/src/cap_v4l.cpp | 91 ++++++++++----------------------- 1 file changed, 27 insertions(+), 64 deletions(-) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index 5a5abfa4f..3547f98b1 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -422,24 +422,20 @@ try_palette(int fd, #ifdef HAVE_CAMV4L2 -static int try_palette_v4l2(CvCaptureCAM_V4L* capture, unsigned long colorspace) +static bool try_palette_v4l2(CvCaptureCAM_V4L* capture) { CLEAR (capture->form); capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - capture->form.fmt.pix.pixelformat = colorspace; + capture->form.fmt.pix.pixelformat = capture->palette; capture->form.fmt.pix.field = V4L2_FIELD_ANY; capture->form.fmt.pix.width = capture->width; capture->form.fmt.pix.height = capture->height; if (-1 == ioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form)) - return -1; + return false; - - if (colorspace != capture->form.fmt.pix.pixelformat) - return -1; - else - return 0; + return capture->palette == capture->form.fmt.pix.pixelformat; } #endif /* HAVE_CAMV4L2 */ @@ -547,67 +543,34 @@ static int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName) } -static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture) -{ - if (try_palette_v4l2(capture, V4L2_PIX_FMT_BGR24) == 0) - { - capture->palette = V4L2_PIX_FMT_BGR24; - } - else - if (try_palette_v4l2(capture, V4L2_PIX_FMT_YVU420) == 0) - { - capture->palette = V4L2_PIX_FMT_YVU420; - } - else - if (try_palette_v4l2(capture, V4L2_PIX_FMT_YUV411P) == 0) - { - capture->palette = V4L2_PIX_FMT_YUV411P; - } - else - +static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture) { + __u32 try_order[] = { + V4L2_PIX_FMT_BGR24, + V4L2_PIX_FMT_YVU420, + V4L2_PIX_FMT_YUV411P, #ifdef HAVE_JPEG - if (try_palette_v4l2(capture, V4L2_PIX_FMT_MJPEG) == 0 || - try_palette_v4l2(capture, V4L2_PIX_FMT_JPEG) == 0) - { - capture->palette = V4L2_PIX_FMT_MJPEG; - } - else + V4L2_PIX_FMT_MJPEG, + V4L2_PIX_FMT_JPEG, #endif + V4L2_PIX_FMT_YUYV, + V4L2_PIX_FMT_UYVY, + V4L2_PIX_FMT_SN9C10X, + V4L2_PIX_FMT_SBGGR8, + V4L2_PIX_FMT_SGBRG8, + V4L2_PIX_FMT_RGB24 + }; - if (try_palette_v4l2(capture, V4L2_PIX_FMT_YUYV) == 0) - { - capture->palette = V4L2_PIX_FMT_YUYV; - } - else if (try_palette_v4l2(capture, V4L2_PIX_FMT_UYVY) == 0) - { - capture->palette = V4L2_PIX_FMT_UYVY; - } - else - if (try_palette_v4l2(capture, V4L2_PIX_FMT_SN9C10X) == 0) - { - capture->palette = V4L2_PIX_FMT_SN9C10X; - } else - if (try_palette_v4l2(capture, V4L2_PIX_FMT_SBGGR8) == 0) - { - capture->palette = V4L2_PIX_FMT_SBGGR8; - } else - if (try_palette_v4l2(capture, V4L2_PIX_FMT_SGBRG8) == 0) - { - capture->palette = V4L2_PIX_FMT_SGBRG8; - } - else if (try_palette_v4l2(capture, V4L2_PIX_FMT_RGB24) == 0) - { - capture->palette = V4L2_PIX_FMT_RGB24; - } - else - { - fprintf(stderr, "VIDEOIO ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n"); + for (size_t i = 0; i < sizeof(try_order) / sizeof(__u32); i++) { + capture->palette = try_order[i]; + if (try_palette_v4l2(capture)) { + return 0; + } + } + + fprintf(stderr, + "VIDEOIO ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n"); icvCloseCAM_V4L(capture); return -1; - } - - return 0; - } #endif /* HAVE_CAMV4L2 */ From 56dd7eda0d6a5ad1c5bec5ebc08739e331b7bf91 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sun, 18 Oct 2015 13:37:31 +0200 Subject: [PATCH 137/156] remove additional V4L2 pixelformat defines they are upstream since at least linux 2.6.8 (10 Years) http://lxr.oss.org.cn/ident?v=2.6.8&i=V4L2_PIX_FMT_SBGGR8 --- modules/videoio/src/cap_v4l.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index 3547f98b1..8160a0c6e 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -272,18 +272,6 @@ struct buffer static unsigned int n_buffers = 0; -/* Additional V4L2 pixelformats support for Sonix SN9C10x base webcams */ -#ifndef V4L2_PIX_FMT_SBGGR8 -#define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */ -#endif -#ifndef V4L2_PIX_FMT_SN9C10X -#define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S','9','1','0') /* SN9C10x cmpr. */ -#endif - -#ifndef V4L2_PIX_FMT_SGBRG8 -#define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G','B','R','G') /* bayer GBRG GBGB.. RGRG.. */ -#endif - #endif /* HAVE_CAMV4L2 */ typedef struct CvCaptureCAM_V4L From 80747088e3270df8c51dc540e2c25b75d3752721 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sat, 10 Oct 2015 13:14:57 +0200 Subject: [PATCH 138/156] avoid needless copies during mjpeg decoding --- modules/videoio/src/cap_v4l.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index 8160a0c6e..5ec5278f0 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -1612,15 +1612,11 @@ uyvy_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst) /* convert from mjpeg to rgb24 */ static bool -mjpeg_to_rgb24 (int width, int height, - unsigned char *src, int length, - unsigned char *dst) -{ - cv::Mat temp=cv::imdecode(cv::Mat(std::vector(src, src + length)), 1); - if( !temp.data || temp.cols != width || temp.rows != height ) - return false; - memcpy(dst, temp.data, width*height*3); - return true; +mjpeg_to_rgb24(int width, int height, unsigned char* src, int length, IplImage* dst) { + using namespace cv; + Mat temp = cvarrToMat(dst); + imdecode(Mat(1, length, CV_8U, src), IMREAD_COLOR, &temp); + return temp.data && temp.cols == width && temp.rows == height; } #endif @@ -2068,7 +2064,7 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { (unsigned char*)(capture->buffers[capture->bufferIndex] .start), capture->buffers[capture->bufferIndex].length, - (unsigned char*)capture->frame.imageData)) + &capture->frame)) return 0; break; #endif From 838947bb8ea4dbc4d8490541513453355dd6d2fc Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sat, 10 Oct 2015 13:42:26 +0200 Subject: [PATCH 139/156] replace custom yuyv_to_rgb24 implementation by cvtColor --- modules/videoio/src/cap_v4l.cpp | 47 +++------------------------------ modules/videoio/src/precomp.hpp | 1 + 2 files changed, 5 insertions(+), 43 deletions(-) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index 5ec5278f0..4f00e43d5 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -1516,49 +1516,10 @@ yuv411p_to_rgb24(int width, int height, #ifdef HAVE_CAMV4L2 static void -yuyv_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst) -{ - unsigned char *s; - unsigned char *d; - int l, c; - int r, g, b, cr, cg, cb, y1, y2; - - l = height; - s = src; - d = dst; - while (l--) { - c = width >> 1; - while (c--) { - y1 = *s++; - cb = ((*s - 128) * 454) >> 8; - cg = (*s++ - 128) * 88; - y2 = *s++; - cr = ((*s - 128) * 359) >> 8; - cg = (cg + (*s++ - 128) * 183) >> 8; - - r = y1 + cr; - b = y1 + cb; - g = y1 - cg; - SAT(r); - SAT(g); - SAT(b); - - *d++ = b; - *d++ = g; - *d++ = r; - - r = y2 + cr; - b = y2 + cb; - g = y2 - cg; - SAT(r); - SAT(g); - SAT(b); - - *d++ = b; - *d++ = g; - *d++ = r; - } - } +yuyv_to_rgb24(int width, int height, unsigned char* src, unsigned char* dst) { + using namespace cv; + cvtColor(Mat(height, width, CV_8UC2, src), Mat(height, width, CV_8UC3, dst), + COLOR_YUV2BGR_YUYV); } static void diff --git a/modules/videoio/src/precomp.hpp b/modules/videoio/src/precomp.hpp index d60b00f94..442eaa19a 100644 --- a/modules/videoio/src/precomp.hpp +++ b/modules/videoio/src/precomp.hpp @@ -49,6 +49,7 @@ #include "opencv2/imgcodecs.hpp" +#include "opencv2/imgproc.hpp" #include "opencv2/imgproc/imgproc_c.h" #include "opencv2/imgcodecs/imgcodecs_c.h" #include "opencv2/videoio/videoio_c.h" From 54e7f0876017e176955b232c3b9ebdd1817ecd52 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sun, 11 Oct 2015 18:06:02 +0200 Subject: [PATCH 140/156] add python sample to test/ showcase new cap_v4l2 features --- samples/python2/video_v4l2.py | 64 +++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 samples/python2/video_v4l2.py diff --git a/samples/python2/video_v4l2.py b/samples/python2/video_v4l2.py new file mode 100644 index 000000000..0f03e6bf0 --- /dev/null +++ b/samples/python2/video_v4l2.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python + +''' +VideoCapture sample showcasing some features of the Video4Linux2 backend + +Sample shows how VideoCapture class can be used to control parameters +of a webcam such as focus or framerate. +Also the sample provides an example how to access raw images delivered +by the hardware to get a grayscale image in a very efficient fashion. + +Keys: + ESC - exit + g - toggle optimized grayscale conversion + +''' + +import cv2 + +def decode_fourcc(v): + v = int(v) + return "".join([chr((v >> 8 * i) & 0xFF) for i in range(4)]) + +font = cv2.FONT_HERSHEY_SIMPLEX +color = (0, 255, 0) + +cap = cv2.VideoCapture(0) +cap.set(cv2.CAP_PROP_AUTOFOCUS, False) + +cv2.namedWindow("Video") + +convert_rgb = True +fps = int(cap.get(cv2.CAP_PROP_FPS)) +focus = int(cap.get(cv2.CAP_PROP_FOCUS)) * 100 + +cv2.createTrackbar("FPS", "Video", fps, 30, lambda v: cap.set(cv2.CAP_PROP_FPS, v)) +cv2.createTrackbar("Focus", "Video", focus, 100, lambda v: cap.set(cv2.CAP_PROP_FOCUS, v / 100)) + +while True: + status, img = cap.read() + + fourcc = decode_fourcc(cap.get(cv2.CAP_PROP_FOURCC)) + + fps = cap.get(cv2.CAP_PROP_FPS) + + if not bool(cap.get(cv2.CAP_PROP_CONVERT_RGB)): + if fourcc == "MJPG": + img = cv2.imdecode(img, cv2.IMREAD_GRAYSCALE) + elif fourcc == "YUYV": + img = cv2.cvtColor(img, cv2.COLOR_YUV2GRAY_YUYV) + else: + print("unsupported format") + break + + cv2.putText(img, "Mode: {}".format(fourcc), (15, 40), font, 1.0, color) + cv2.putText(img, "FPS: {}".format(fps), (15, 80), font, 1.0, color) + cv2.imshow("Video", img) + + k = cv2.waitKey(1) + + if k == 27: + break + elif k == ord("g"): + convert_rgb = not convert_rgb + cap.set(cv2.CAP_PROP_CONVERT_RGB, convert_rgb) From 5e62e71b13f29c227727a145765f2e625b4da30b Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sun, 11 Oct 2015 16:28:01 +0200 Subject: [PATCH 141/156] fix wrong ifdef bracketing in the case of HAVE_CAMV4L2 && !HAVE_CAMV4L there was no body for the if statement. --- modules/videoio/src/cap_v4l.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index 4f00e43d5..297d619f8 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -1939,18 +1939,16 @@ static int sonix_decompress(int width, int height, unsigned char *inp, unsigned static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { #ifdef HAVE_CAMV4L2 - if (V4L2_SUPPORT == 0) -#endif /* HAVE_CAMV4L2 */ #ifdef HAVE_CAMV4L + if (V4L2_SUPPORT == 0) { - /* [FD] this really belongs here */ if (ioctl(capture->deviceHandle, VIDIOCSYNC, &capture->mmaps[capture->bufferIndex].frame) == -1) { fprintf( stderr, "VIDEOIO ERROR: V4L: Could not SYNC to video stream. %s\n", strerror(errno)); } - } #endif /* HAVE_CAMV4L */ +#endif /* HAVE_CAMV4L2 */ /* Now get what has already been captured as a IplImage return */ From eac5cab5cb18aa5014c66c79bea5b465df98ef7f Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Sun, 11 Oct 2015 15:23:47 +0200 Subject: [PATCH 142/156] cap_v4l: implement PROP_CONVERT_RGB allows disabling automatic conversion to RGB for certain formats. If conversion is disabled the returned image just points to the underlying buffer, so no memcpy is performed. Note that we do not check image size in retrieve frame any more as it can not possibly while the device is streaming. Furthermore this code was disabled altogether by the wrong ifdef in the previous commit. --- modules/videoio/src/cap_v4l.cpp | 88 ++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 19 deletions(-) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index 297d619f8..fc9f6e06a 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -294,6 +294,9 @@ typedef struct CvCaptureCAM_V4L int index; int width, height; __u32 fps; + bool convert_rgb; + bool frame_allocated; + /* V4L2 variables */ buffer buffers[MAX_V4L_BUFFERS + 1]; struct v4l2_capability cap; @@ -674,6 +677,43 @@ static int v4l2_set_fps(CvCaptureCAM_V4L* capture) { return ioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps); } +static int v4l2_num_channels(__u32 palette) { + switch(palette) { + case V4L2_PIX_FMT_MJPEG: + case V4L2_PIX_FMT_JPEG: + return 1; + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + return 2; + default: + return 0; + } +} + +static void v4l2_create_frame(CvCaptureCAM_V4L *capture) { + CvSize size(capture->form.fmt.pix.width, capture->form.fmt.pix.height); + int channels = 3; + + if (!capture->convert_rgb) { + if (capture->palette == V4L2_PIX_FMT_MJPEG || capture->palette == V4L2_PIX_FMT_JPEG) { + size = CvSize(capture->buffers[capture->bufferIndex].length, 1); + } + channels = v4l2_num_channels(capture->palette); + } + + /* Set up Image data */ + cvInitImageHeader(&capture->frame, size, IPL_DEPTH_8U, channels); + + /* Allocate space for pixelformat we convert to. + * If we do not convert frame is just points to the buffer + */ + if(capture->convert_rgb) { + capture->frame.imageData = (char*)cvAlloc(capture->frame.imageSize); + } + + capture->frame_allocated = capture->convert_rgb; +} + static int _capture_V4L2 (CvCaptureCAM_V4L *capture) { char deviceName[MAX_DEVICE_DRIVER_NAME]; @@ -829,13 +869,7 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture) } } - /* Set up Image data */ - cvInitImageHeader( &capture->frame, - cvSize( capture->form.fmt.pix.width, - capture->form.fmt.pix.height ), - IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 ); - /* Allocate space for RGBA data */ - capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize); + v4l2_create_frame(capture); // reinitialize buffers capture->FirstCapture = 1; @@ -1022,6 +1056,7 @@ static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index) capture->width = DEFAULT_V4L_WIDTH; capture->height = DEFAULT_V4L_HEIGHT; capture->fps = DEFAULT_V4L_FPS; + capture->convert_rgb = true; if (_capture_V4L2 (capture) == -1) { icvCloseCAM_V4L(capture); @@ -1958,15 +1993,19 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { if (V4L2_SUPPORT == 1) { + // we need memory iff convert_rgb is true + bool recreate_frame = capture->frame_allocated != capture->convert_rgb; - if(((unsigned long)capture->frame.width != capture->form.fmt.pix.width) - || ((unsigned long)capture->frame.height != capture->form.fmt.pix.height)) { - cvFree(&capture->frame.imageData); - cvInitImageHeader( &capture->frame, - cvSize( capture->form.fmt.pix.width, - capture->form.fmt.pix.height ), - IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 ); - capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize); + if (!capture->convert_rgb) { + // for mjpeg streams the size might change in between, so we have to change the header + recreate_frame += capture->frame.imageSize != (int)capture->buffers[capture->bufferIndex].length; + } + + if(recreate_frame) { + // printf("realloc %d %zu\n", capture->frame.imageSize, capture->buffers[capture->bufferIndex].length); + if(capture->frame_allocated) + cvFree(&capture->frame.imageData); + v4l2_create_frame(capture); } } @@ -1994,6 +2033,11 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { if (V4L2_SUPPORT == 1) { + if(!capture->convert_rgb) { + capture->frame.imageData = (char*)capture->buffers[capture->bufferIndex].start; + return &capture->frame; + } + switch (capture->palette) { case V4L2_PIX_FMT_BGR24: @@ -2172,6 +2216,8 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, return capture->palette; case CV_CAP_PROP_FORMAT: return CV_8UC3; + case CV_CAP_PROP_CONVERT_RGB: + return capture->convert_rgb; } if(property_id == CV_CAP_PROP_FPS) { @@ -2414,10 +2460,8 @@ static int icvSetControl (CvCaptureCAM_V4L* capture, static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id, double value ){ static int width = 0, height = 0; - int retval; - - /* initialization */ - retval = 0; + int retval = 0; + bool possible; /* two subsequent calls setting WIDTH and HEIGHT will change the video size */ @@ -2445,6 +2489,12 @@ static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, capture->fps = value; retval = v4l2_reset( capture); break; + case CV_CAP_PROP_CONVERT_RGB: + // returns "0" for formats we do not know how to map to IplImage + possible = v4l2_num_channels(capture->palette); + capture->convert_rgb = bool(value) && possible; + retval = !possible && bool(value) ? -1 : 0; + break; default: retval = icvSetControl(capture, property_id, value); break; From 51e687f7a9c3598249adfdcb5d19aab26431249b Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Sun, 18 Oct 2015 14:50:39 +0300 Subject: [PATCH 143/156] Update imgproc.hpp --- modules/imgproc/include/opencv2/imgproc.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index d8ded742c..d440254e7 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -1922,7 +1922,7 @@ CV_EXPORTS_W void dilate( InputArray src, OutputArray dst, InputArray kernel, /** @brief Performs advanced morphological transformations. -The function can perform advanced morphological transformations using an erosion and dilation as +The function morphologyEx can perform advanced morphological transformations using an erosion and dilation as basic operations. Any of the operations can be done in-place. In case of multi-channel images, each channel is @@ -1930,11 +1930,11 @@ processed independently. @param src Source image. The number of channels can be arbitrary. The depth should be one of CV_8U, CV_16U, CV_16S, CV_32F or CV_64F. -@param dst Destination image of the same size and type as src\` . -@param kernel Structuring element. It can be created using getStructuringElement. +@param dst Destination image of the same size and type as source image. +@param op Type of a morphological operation, see cv::MorphTypes +@param kernel Structuring element. It can be created using cv::getStructuringElement. @param anchor Anchor position with the kernel. Negative values mean that the anchor is at the kernel center. -@param op Type of a morphological operation, see cv::MorphTypes @param iterations Number of times erosion and dilation are applied. @param borderType Pixel extrapolation method, see cv::BorderTypes @param borderValue Border value in case of a constant border. The default value has a special From f5b98bea41befeb41acf6e972e53e054eb86b336 Mon Sep 17 00:00:00 2001 From: Renato Florentino Garcia Date: Sun, 18 Oct 2015 23:16:21 -0200 Subject: [PATCH 144/156] Fix behavior of Matx 12 and 16 args constructors. The 12 and 16 arguments Matx constructors differs from all others, leaving values initialized and requiring the argument number to be equal to the channels number. --- modules/core/include/opencv2/core/matx.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/core/include/opencv2/core/matx.hpp b/modules/core/include/opencv2/core/matx.hpp index 9bbcc37a7..9e0fb8118 100644 --- a/modules/core/include/opencv2/core/matx.hpp +++ b/modules/core/include/opencv2/core/matx.hpp @@ -574,20 +574,22 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _T template inline Matx<_Tp,m,n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9, _Tp v10, _Tp v11) { - CV_StaticAssert(channels == 12, "Matx should have at least 12 elements."); + CV_StaticAssert(channels >= 12, "Matx should have at least 12 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7; val[8] = v8; val[9] = v9; val[10] = v10; val[11] = v11; + for(int i = 12; i < channels; i++) val[i] = _Tp(0); } template inline Matx<_Tp,m,n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9, _Tp v10, _Tp v11, _Tp v12, _Tp v13, _Tp v14, _Tp v15) { - CV_StaticAssert(channels == 16, "Matx should have at least 16 elements."); + CV_StaticAssert(channels >= 16, "Matx should have at least 16 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7; val[8] = v8; val[9] = v9; val[10] = v10; val[11] = v11; val[12] = v12; val[13] = v13; val[14] = v14; val[15] = v15; + for(int i = 16; i < channels; i++) val[i] = _Tp(0); } template inline From b0209ad7f742ecc22de2944cd12c2c9fed036f2f Mon Sep 17 00:00:00 2001 From: Aman Verma Date: Mon, 19 Oct 2015 08:44:06 +0000 Subject: [PATCH 145/156] Fix for #5495 : add setTrackbarMin --- modules/highgui/include/opencv2/highgui.hpp | 15 +++++++ .../include/opencv2/highgui/highgui_c.h | 1 + modules/highgui/src/window.cpp | 10 +++++ modules/highgui/src/window_QT.cpp | 17 ++++++++ modules/highgui/src/window_cocoa.mm | 35 +++++++++++++++- modules/highgui/src/window_gtk.cpp | 40 ++++++++++++++++++- modules/highgui/src/window_w32.cpp | 34 +++++++++++++++- modules/highgui/src/window_winrt.cpp | 16 ++++++++ modules/highgui/src/window_winrt_bridge.cpp | 20 +++++++++- modules/highgui/src/window_winrt_bridge.hpp | 2 + 10 files changed, 184 insertions(+), 6 deletions(-) diff --git a/modules/highgui/include/opencv2/highgui.hpp b/modules/highgui/include/opencv2/highgui.hpp index 006059566..41bd8aff8 100644 --- a/modules/highgui/include/opencv2/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui.hpp @@ -526,6 +526,21 @@ panel. */ CV_EXPORTS_W void setTrackbarMax(const String& trackbarname, const String& winname, int maxval); +/** @brief Sets the trackbar minimum position. + +The function sets the minimum position of the specified trackbar in the specified window. + +@note + +[__Qt Backend Only__] winname can be empty (or NULL) if the trackbar is attached to the control +panel. + +@param trackbarname Name of the trackbar. +@param winname Name of the window that is the parent of trackbar. +@param minval New maximum position. + */ +CV_EXPORTS_W void setTrackbarMin(const String& trackbarname, const String& winname, int minval); + //! @addtogroup highgui_opengl OpenGL support //! @{ diff --git a/modules/highgui/include/opencv2/highgui/highgui_c.h b/modules/highgui/include/opencv2/highgui/highgui_c.h index 46d4c9549..47fdb84a4 100644 --- a/modules/highgui/include/opencv2/highgui/highgui_c.h +++ b/modules/highgui/include/opencv2/highgui/highgui_c.h @@ -166,6 +166,7 @@ CVAPI(int) cvCreateTrackbar2( const char* trackbar_name, const char* window_name CVAPI(int) cvGetTrackbarPos( const char* trackbar_name, const char* window_name ); CVAPI(void) cvSetTrackbarPos( const char* trackbar_name, const char* window_name, int pos ); CVAPI(void) cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval); +CVAPI(void) cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval); enum { diff --git a/modules/highgui/src/window.cpp b/modules/highgui/src/window.cpp index 03d446dd0..c879c4130 100644 --- a/modules/highgui/src/window.cpp +++ b/modules/highgui/src/window.cpp @@ -216,6 +216,11 @@ void cv::setTrackbarMax(const String& trackbarName, const String& winName, int m cvSetTrackbarMax(trackbarName.c_str(), winName.c_str(), maxval); } +void cv::setTrackbarMin(const String& trackbarName, const String& winName, int minval) +{ + cvSetTrackbarMin(trackbarName.c_str(), winName.c_str(), minval); +} + int cv::getTrackbarPos( const String& trackbarName, const String& winName ) { return cvGetTrackbarPos(trackbarName.c_str(), winName.c_str()); @@ -589,6 +594,11 @@ CV_IMPL void cvSetTrackbarMax(const char*, const char*, int) CV_NO_GUI_ERROR( "cvSetTrackbarMax" ); } +CV_IMPL void cvSetTrackbarMin(const char*, const char*, int) +{ + CV_NO_GUI_ERROR( "cvSetTrackbarMin" ); +} + CV_IMPL void* cvGetWindowHandle( const char* ) { CV_NO_GUI_ERROR( "cvGetWindowHandle" ); diff --git a/modules/highgui/src/window_QT.cpp b/modules/highgui/src/window_QT.cpp index a01dcd342..9d9877815 100644 --- a/modules/highgui/src/window_QT.cpp +++ b/modules/highgui/src/window_QT.cpp @@ -664,12 +664,29 @@ CV_IMPL void cvSetTrackbarMax(const char* name_bar, const char* window_name, int QPointer t = icvFindTrackBarByName(name_bar, window_name); if (t) { + int minval = t->slider->getMinimum(); + maxval = (maxval>minval)?maxval:minval; t->slider->setMaximum(maxval); } } } +CV_IMPL void cvSetTrackbarMin(const char* name_bar, const char* window_name, int minval) +{ + if (minval >= 0) + { + QPointer t = icvFindTrackBarByName(name_bar, window_name); + if (t) + { + int maxval = t->slider->getMaximum(); + minval = (maxvalslider->setMinimum(minval); + } + } +} + + /* assign callback for mouse events */ CV_IMPL void cvSetMouseCallback(const char* window_name, CvMouseCallback on_mouse, void* param) { diff --git a/modules/highgui/src/window_cocoa.mm b/modules/highgui/src/window_cocoa.mm index 56baded39..f8c48fc4c 100644 --- a/modules/highgui/src/window_cocoa.mm +++ b/modules/highgui/src/window_cocoa.mm @@ -62,6 +62,7 @@ CV_IMPL void cvSetMouseCallback( const char* name, CvMouseCallback function, voi CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name ) {return 0;} CV_IMPL void cvSetTrackbarPos(const char* trackbar_name, const char* window_name, int pos) {} CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval) {} +CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval) {} CV_IMPL void* cvGetWindowHandle( const char* name ) {return NULL;} CV_IMPL const char* cvGetWindowName( void* window_handle ) {return NULL;} CV_IMPL int cvNamedWindow( const char* name, int flags ) {return 0; } @@ -426,7 +427,7 @@ CV_IMPL void cvSetTrackbarPos(const char* trackbar_name, const char* window_name CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval) { - CV_FUNCNAME("cvSetTrackbarPos"); + CV_FUNCNAME("cvSetTrackbarMax"); CVWindow *window = nil; CVSlider *slider = nil; @@ -454,7 +455,37 @@ CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name __END__; } -CV_IMPL void* cvGetWindowHandle( const char* name ) +CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval) +{ + CV_FUNCNAME("cvSetTrackbarMin"); + + CVWindow *window = nil; + CVSlider *slider = nil; + NSAutoreleasePool* localpool5 = nil; + + __BEGIN__; + //cout << "cvSetTrackbarPos" << endl; + if(trackbar_name == NULL || window_name == NULL) + CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" ); + + if (localpool5 != nil) [localpool5 drain]; + localpool5 = [[NSAutoreleasePool alloc] init]; + + window = cvGetWindow(window_name); + if(window) { + slider = [[window sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]]; + if(slider) { + if(minval >= 0) { + [[slider slider] setMinValue:minval]; + } + } + } + [localpool5 drain]; + + __END__; +} + +CV_IMPL void* cvGetWindowHandle( const char* name )k { //cout << "cvGetWindowHandle" << endl; return cvGetWindow(name); diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index deae665ff..c72216510 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -508,6 +508,7 @@ typedef struct CvTrackbar int* data; int pos; int maxval; + int minval; CvTrackbarCallback notify; CvTrackbarCallback2 notify2; void* userdata; @@ -1607,7 +1608,7 @@ CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name trackbar = icvFindTrackbarByName(window, trackbar_name); if (trackbar) { - trackbar->maxval = maxval; + trackbar->maxval = (trackbar->minval>maxval)?trackbar->minval:maxval; CV_LOCK_MUTEX(); @@ -1622,6 +1623,43 @@ CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name } +CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval) +{ + CV_FUNCNAME("cvSetTrackbarMin"); + + __BEGIN__; + + if (minval >= 0) + { + CvWindow* window = 0; + CvTrackbar* trackbar = 0; + + if (trackbar_name == 0 || window_name == 0) + { + CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name"); + } + + window = icvFindWindowByName( window_name ); + if (window) + { + trackbar = icvFindTrackbarByName(window, trackbar_name); + if (trackbar) + { + trackbar->minval = (minvalmaxval)?minval:trackbar->maxval; + + CV_LOCK_MUTEX(); + + gtk_range_set_range(GTK_RANGE(trackbar->widget), minval, trackbar->maxval); + + CV_UNLOCK_MUTEX(); + } + } + } + + __END__; +} + + CV_IMPL void* cvGetWindowHandle( const char* window_name ) { void* widget = 0; diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index 988aedaf6..395c46dcf 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -2325,7 +2325,7 @@ CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name if (trackbar) { // The position will be min(pos, maxval). - trackbar->maxval = maxval; + trackbar->maxval = (trackbar->minval>maxval)?trackbar->minval:maxval; SendMessage(trackbar->hwnd, TBM_SETRANGEMAX, (WPARAM)TRUE, (LPARAM)maxval); } } @@ -2335,6 +2335,38 @@ CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name } +CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval) +{ + CV_FUNCNAME( "cvSetTrackbarMin" ); + + __BEGIN__; + + if (maxval >= 0) + { + CvWindow* window = 0; + CvTrackbar* trackbar = 0; + if (trackbar_name == 0 || window_name == 0) + { + CV_ERROR(CV_StsNullPtr, "NULL trackbar or window name"); + } + + window = icvFindWindowByName(window_name); + if (window) + { + trackbar = icvFindTrackbarByName(window, trackbar_name); + if (trackbar) + { + // The position will be min(pos, maxval). + trackbar->minval = (minvalmaxval)?minval:trackbar->maxval; + SendMessage(trackbar->hwnd, TBM_SETRANGEMIN, (WPARAM)TRUE, (LPARAM)minval); + } + } + } + + __END__; +} + + CV_IMPL void* cvGetWindowHandle( const char* window_name ) { void* hwnd = 0; diff --git a/modules/highgui/src/window_winrt.cpp b/modules/highgui/src/window_winrt.cpp index ba81b51c6..4bd3e1ab2 100644 --- a/modules/highgui/src/window_winrt.cpp +++ b/modules/highgui/src/window_winrt.cpp @@ -170,6 +170,22 @@ CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name } } +CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval) +{ + CV_FUNCNAME("cvSetTrackbarMin"); + + if (minval >= 0) + { + if (trackbar_name == 0 || window_name == 0) + CV_ERROR(CV_StsNullPtr, "NULL trackbar or window name"); + + CvTrackbar* trackbar = HighguiBridge::getInstance().findTrackbarByName(trackbar_name, window_name); + + if (trackbar) + trackbar->setMinPosition(minval); + } +} + CV_IMPL int cvGetTrackbarPos(const char* trackbar_name, const char* window_name) { int pos = -1; diff --git a/modules/highgui/src/window_winrt_bridge.cpp b/modules/highgui/src/window_winrt_bridge.cpp index 60421d681..e0818eafb 100644 --- a/modules/highgui/src/window_winrt_bridge.cpp +++ b/modules/highgui/src/window_winrt_bridge.cpp @@ -171,12 +171,23 @@ void CvTrackbar::setPosition(double pos) void CvTrackbar::setMaxPosition(double pos) { - if (pos < 0) - pos = 0; + //slider->Minimum is initialized with 0 + if (pos < slider->Minimum) + pos = slider->Minimum; slider->Maximum = pos; } +void CvTrackbar::setMinPosition(double pos) +{ + if (pos < 0) + pos = 0; + //Min is always less than Max. + if ((pos > slider->Maximum) + pos = slider->Maximum; + slider->Minimum = pos; +} + void CvTrackbar::setSlider(Slider^ slider) { if (slider) this->slider = slider; @@ -192,6 +203,11 @@ double CvTrackbar::getMaxPosition() return slider->Maximum; } +double CvTrackbar::getMinPosition() +{ + return slider->Minimum; +} + Slider^ CvTrackbar::getSlider() { return slider; diff --git a/modules/highgui/src/window_winrt_bridge.hpp b/modules/highgui/src/window_winrt_bridge.hpp index d19dd29c8..25f4aef8e 100644 --- a/modules/highgui/src/window_winrt_bridge.hpp +++ b/modules/highgui/src/window_winrt_bridge.hpp @@ -151,6 +151,8 @@ public: void setPosition(double pos); double getMaxPosition(); void setMaxPosition(double pos); + double getMinPosition(); + void setMinPosition(double pos); Slider^ getSlider(); void setSlider(Slider^ pos); From d5e314e72800266657c0455e9cc4f82228b6795b Mon Sep 17 00:00:00 2001 From: Aman Verma Date: Mon, 19 Oct 2015 10:58:43 +0000 Subject: [PATCH 146/156] Fixing compilation errors in windows and mac --- modules/highgui/src/window_cocoa.mm | 7 +++++-- modules/highgui/src/window_w32.cpp | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/highgui/src/window_cocoa.mm b/modules/highgui/src/window_cocoa.mm index f8c48fc4c..4ab1e360e 100644 --- a/modules/highgui/src/window_cocoa.mm +++ b/modules/highgui/src/window_cocoa.mm @@ -446,6 +446,8 @@ CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name slider = [[window sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]]; if(slider) { if(maxval >= 0) { + int minval = [[slider slider] minValue]; + maxval = (minval>maxval)?minval:maxval; [[slider slider] setMaxValue:maxval]; } } @@ -464,7 +466,6 @@ CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name NSAutoreleasePool* localpool5 = nil; __BEGIN__; - //cout << "cvSetTrackbarPos" << endl; if(trackbar_name == NULL || window_name == NULL) CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" ); @@ -476,6 +477,8 @@ CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name slider = [[window sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]]; if(slider) { if(minval >= 0) { + int maxval = [[slider slider] maxValue]; + minval = (minval= 0) + if (minval >= 0) { CvWindow* window = 0; CvTrackbar* trackbar = 0; From 6e9d0d9a0cc382c1fd2ac89c4785a1895649a1a3 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Fri, 16 Oct 2015 17:10:00 +0300 Subject: [PATCH 147/156] Visual Studio 2015 warning and test fixes --- 3rdparty/libtiff/CMakeLists.txt | 1 + 3rdparty/openexr/CMakeLists.txt | 1 + cmake/OpenCVCompilerOptions.cmake | 2 + modules/calib3d/src/stereobm.cpp | 8 +- modules/calib3d/test/test_fisheye.cpp | 106 +++++++++--------- modules/core/src/arithm.cpp | 8 +- modules/core/src/convert.cpp | 12 +- modules/core/src/copy.cpp | 6 +- modules/core/src/directx.cpp | 16 +-- modules/core/src/dxt.cpp | 2 +- modules/core/src/mathfuncs.cpp | 14 +-- modules/core/src/matmul.cpp | 6 +- modules/core/src/matop.cpp | 4 +- modules/core/src/matrix.cpp | 8 +- modules/core/src/umatrix.cpp | 6 +- modules/core/src/va_intel.cpp | 4 +- modules/core/test/test_umat.cpp | 6 +- modules/features2d/src/fast.cpp | 4 +- modules/features2d/src/matchers.cpp | 12 +- modules/features2d/src/orb.cpp | 6 +- modules/imgproc/perf/perf_cvt_color.cpp | 5 + modules/imgproc/src/accum.cpp | 2 +- modules/imgproc/src/blend.cpp | 2 +- modules/imgproc/src/canny.cpp | 10 +- modules/imgproc/src/clahe.cpp | 2 +- modules/imgproc/src/color.cpp | 2 +- modules/imgproc/src/colormap.cpp | 70 ++++++------ modules/imgproc/src/corner.cpp | 4 +- modules/imgproc/src/deriv.cpp | 2 +- modules/imgproc/src/featureselect.cpp | 2 +- modules/imgproc/src/filter.cpp | 2 +- modules/imgproc/src/histogram.cpp | 4 +- modules/imgproc/src/hough.cpp | 8 +- modules/imgproc/src/imgwarp.cpp | 6 +- modules/imgproc/src/moments.cpp | 2 +- modules/imgproc/src/morph.cpp | 4 +- modules/imgproc/src/pyramids.cpp | 8 +- modules/imgproc/src/smooth.cpp | 4 +- modules/imgproc/src/templmatch.cpp | 16 +-- modules/imgproc/src/thresh.cpp | 2 +- modules/java/generator/gen_java.py | 4 +- modules/java/generator/src/cpp/Mat.cpp | 4 +- modules/objdetect/src/cascadedetect.cpp | 2 +- modules/objdetect/src/hog.cpp | 12 +- .../src/fast_nlmeans_denoising_opencl.hpp | 4 +- modules/python/src2/cv2.cpp | 2 +- modules/stitching/src/blenders.cpp | 4 +- modules/stitching/src/warpers.cpp | 6 +- modules/superres/src/btv_l1.cpp | 8 +- modules/superres/src/input_array_utility.cpp | 10 +- modules/video/src/bgfg_gaussmix2.cpp | 4 +- modules/video/src/lkpyramid.cpp | 2 +- modules/video/src/optflowgf.cpp | 12 +- modules/video/src/tvl1flow.cpp | 8 +- 54 files changed, 242 insertions(+), 229 deletions(-) diff --git a/3rdparty/libtiff/CMakeLists.txt b/3rdparty/libtiff/CMakeLists.txt index a06296e41..13971f16a 100644 --- a/3rdparty/libtiff/CMakeLists.txt +++ b/3rdparty/libtiff/CMakeLists.txt @@ -93,6 +93,7 @@ ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4018 /wd4100 /wd4127 /wd4311 /wd4701 /wd ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4244) # vs2008 ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4267 /wd4305 /wd4306) # vs2008 Win64 ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4703) # vs2012 +ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4456 /wd4457 /wd4312) # vs2015 ocv_warnings_disable(CMAKE_C_FLAGS /wd4267 /wd4244 /wd4018) diff --git a/3rdparty/openexr/CMakeLists.txt b/3rdparty/openexr/CMakeLists.txt index e01d8f500..4efab827e 100644 --- a/3rdparty/openexr/CMakeLists.txt +++ b/3rdparty/openexr/CMakeLists.txt @@ -44,6 +44,7 @@ ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4018 /wd4099 /wd4100 /wd4101 /wd4127 /wd ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4334) # vs2005 Win64 ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4244) # vs2008 ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4267) # vs2008 Win64 +ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4456) # vs2015 if(UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR CV_ICC)) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") diff --git a/cmake/OpenCVCompilerOptions.cmake b/cmake/OpenCVCompilerOptions.cmake index fe3de3fed..0dcf7ed26 100644 --- a/cmake/OpenCVCompilerOptions.cmake +++ b/cmake/OpenCVCompilerOptions.cmake @@ -362,5 +362,7 @@ if(MSVC) if(NOT ENABLE_NOISY_WARNINGS) ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4251) # class 'std::XXX' needs to have dll-interface to be used by clients of YYY ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4324) # 'struct_name' : structure was padded due to __declspec(align()) + ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4275) # non dll-interface class 'std::exception' used as base for dll-interface class 'cv::Exception' + ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4589) # Constructor of abstract class 'cv::ORB' ignores initializer for virtual base class 'cv::Algorithm' endif() endif() diff --git a/modules/calib3d/src/stereobm.cpp b/modules/calib3d/src/stereobm.cpp index 760abefa8..ed83c0cb3 100644 --- a/modules/calib3d/src/stereobm.cpp +++ b/modules/calib3d/src/stereobm.cpp @@ -99,7 +99,7 @@ static bool ocl_prefilter_norm(InputArray _input, OutputArray _output, int winsi _output.create(input.size(), input.type()); output = _output.getUMat(); - size_t globalThreads[3] = { input.cols, input.rows, 1 }; + size_t globalThreads[3] = { (size_t)input.cols, (size_t)input.rows, 1 }; k.args(ocl::KernelArg::PtrReadOnly(input), ocl::KernelArg::PtrWriteOnly(output), input.rows, input.cols, prefilterCap, scale_g, scale_s); @@ -180,7 +180,7 @@ static bool ocl_prefilter_xsobel(InputArray _input, OutputArray _output, int pre _output.create(input.size(), input.type()); output = _output.getUMat(); - size_t globalThreads[3] = { input.cols, input.rows, 1 }; + size_t globalThreads[3] = { (size_t)input.cols, (size_t)input.rows, 1 }; k.args(ocl::KernelArg::PtrReadOnly(input), ocl::KernelArg::PtrWriteOnly(output), input.rows, input.cols, prefilterCap); @@ -927,8 +927,8 @@ static bool ocl_stereobm( InputArray _left, InputArray _right, int globalX = (disp.cols + sizeX - 1) / sizeX, globalY = (disp.rows + sizeY - 1) / sizeY; - size_t globalThreads[3] = {N, globalX, globalY}; - size_t localThreads[3] = {N, 1, 1}; + size_t globalThreads[3] = {(size_t)N, (size_t)globalX, (size_t)globalY}; + size_t localThreads[3] = {(size_t)N, 1, 1}; int idx = 0; idx = k.set(idx, ocl::KernelArg::PtrReadOnly(left)); diff --git a/modules/calib3d/test/test_fisheye.cpp b/modules/calib3d/test/test_fisheye.cpp index 4e7bf5363..32b77c654 100644 --- a/modules/calib3d/test/test_fisheye.cpp +++ b/modules/calib3d/test/test_fisheye.cpp @@ -101,15 +101,15 @@ TEST_F(fisheyeTest, projectPoints) TEST_F(fisheyeTest, DISABLED_undistortImage) { - cv::Matx33d K = this->K; - cv::Mat D = cv::Mat(this->D); + cv::Matx33d theK = this->K; + cv::Mat theD = cv::Mat(this->D); std::string file = combine(datasets_repository_path, "/calib-3_stereo_from_JY/left/stereo_pair_014.jpg"); - cv::Matx33d newK = K; + cv::Matx33d newK = theK; cv::Mat distorted = cv::imread(file), undistorted; { newK(0, 0) = 100; newK(1, 1) = 100; - cv::fisheye::undistortImage(distorted, undistorted, K, D, newK); + cv::fisheye::undistortImage(distorted, undistorted, theK, theD, newK); cv::Mat correct = cv::imread(combine(datasets_repository_path, "new_f_100.png")); if (correct.empty()) CV_Assert(cv::imwrite(combine(datasets_repository_path, "new_f_100.png"), undistorted)); @@ -118,8 +118,8 @@ TEST_F(fisheyeTest, DISABLED_undistortImage) } { double balance = 1.0; - cv::fisheye::estimateNewCameraMatrixForUndistortRectify(K, D, distorted.size(), cv::noArray(), newK, balance); - cv::fisheye::undistortImage(distorted, undistorted, K, D, newK); + cv::fisheye::estimateNewCameraMatrixForUndistortRectify(theK, theD, distorted.size(), cv::noArray(), newK, balance); + cv::fisheye::undistortImage(distorted, undistorted, theK, theD, newK); cv::Mat correct = cv::imread(combine(datasets_repository_path, "balance_1.0.png")); if (correct.empty()) CV_Assert(cv::imwrite(combine(datasets_repository_path, "balance_1.0.png"), undistorted)); @@ -129,8 +129,8 @@ TEST_F(fisheyeTest, DISABLED_undistortImage) { double balance = 0.0; - cv::fisheye::estimateNewCameraMatrixForUndistortRectify(K, D, distorted.size(), cv::noArray(), newK, balance); - cv::fisheye::undistortImage(distorted, undistorted, K, D, newK); + cv::fisheye::estimateNewCameraMatrixForUndistortRectify(theK, theD, distorted.size(), cv::noArray(), newK, balance); + cv::fisheye::undistortImage(distorted, undistorted, theK, theD, newK); cv::Mat correct = cv::imread(combine(datasets_repository_path, "balance_0.0.png")); if (correct.empty()) CV_Assert(cv::imwrite(combine(datasets_repository_path, "balance_0.0.png"), undistorted)); @@ -143,7 +143,7 @@ TEST_F(fisheyeTest, jacobians) { int n = 10; cv::Mat X(1, n, CV_64FC3); - cv::Mat om(3, 1, CV_64F), T(3, 1, CV_64F); + cv::Mat om(3, 1, CV_64F), theT(3, 1, CV_64F); cv::Mat f(2, 1, CV_64F), c(2, 1, CV_64F); cv::Mat k(4, 1, CV_64F); double alpha; @@ -156,8 +156,8 @@ TEST_F(fisheyeTest, jacobians) r.fill(om, cv::RNG::NORMAL, 0, 1); om = cv::abs(om); - r.fill(T, cv::RNG::NORMAL, 0, 1); - T = cv::abs(T); T.at(2) = 4; T *= 10; + r.fill(theT, cv::RNG::NORMAL, 0, 1); + theT = cv::abs(theT); theT.at(2) = 4; theT *= 10; r.fill(f, cv::RNG::NORMAL, 0, 1); f = cv::abs(f) * 1000; @@ -171,19 +171,19 @@ TEST_F(fisheyeTest, jacobians) alpha = 0.01*r.gaussian(1); cv::Mat x1, x2, xpred; - cv::Matx33d K(f.at(0), alpha * f.at(0), c.at(0), + cv::Matx33d theK(f.at(0), alpha * f.at(0), c.at(0), 0, f.at(1), c.at(1), 0, 0, 1); cv::Mat jacobians; - cv::fisheye::projectPoints(X, x1, om, T, K, k, alpha, jacobians); + cv::fisheye::projectPoints(X, x1, om, theT, theK, k, alpha, jacobians); //test on T: cv::Mat dT(3, 1, CV_64FC1); r.fill(dT, cv::RNG::NORMAL, 0, 1); - dT *= 1e-9*cv::norm(T); - cv::Mat T2 = T + dT; - cv::fisheye::projectPoints(X, x2, om, T2, K, k, alpha, cv::noArray()); + dT *= 1e-9*cv::norm(theT); + cv::Mat T2 = theT + dT; + cv::fisheye::projectPoints(X, x2, om, T2, theK, k, alpha, cv::noArray()); xpred = x1 + cv::Mat(jacobians.colRange(11,14) * dT).reshape(2, 1); CV_Assert (cv::norm(x2 - xpred) < 1e-10); @@ -192,7 +192,7 @@ TEST_F(fisheyeTest, jacobians) r.fill(dom, cv::RNG::NORMAL, 0, 1); dom *= 1e-9*cv::norm(om); cv::Mat om2 = om + dom; - cv::fisheye::projectPoints(X, x2, om2, T, K, k, alpha, cv::noArray()); + cv::fisheye::projectPoints(X, x2, om2, theT, theK, k, alpha, cv::noArray()); xpred = x1 + cv::Mat(jacobians.colRange(8,11) * dom).reshape(2, 1); CV_Assert (cv::norm(x2 - xpred) < 1e-10); @@ -200,8 +200,8 @@ TEST_F(fisheyeTest, jacobians) cv::Mat df(2, 1, CV_64FC1); r.fill(df, cv::RNG::NORMAL, 0, 1); df *= 1e-9*cv::norm(f); - cv::Matx33d K2 = K + cv::Matx33d(df.at(0), df.at(0) * alpha, 0, 0, df.at(1), 0, 0, 0, 0); - cv::fisheye::projectPoints(X, x2, om, T, K2, k, alpha, cv::noArray()); + cv::Matx33d K2 = theK + cv::Matx33d(df.at(0), df.at(0) * alpha, 0, 0, df.at(1), 0, 0, 0, 0); + cv::fisheye::projectPoints(X, x2, om, theT, K2, k, alpha, cv::noArray()); xpred = x1 + cv::Mat(jacobians.colRange(0,2) * df).reshape(2, 1); CV_Assert (cv::norm(x2 - xpred) < 1e-10); @@ -209,8 +209,8 @@ TEST_F(fisheyeTest, jacobians) cv::Mat dc(2, 1, CV_64FC1); r.fill(dc, cv::RNG::NORMAL, 0, 1); dc *= 1e-9*cv::norm(c); - K2 = K + cv::Matx33d(0, 0, dc.at(0), 0, 0, dc.at(1), 0, 0, 0); - cv::fisheye::projectPoints(X, x2, om, T, K2, k, alpha, cv::noArray()); + K2 = theK + cv::Matx33d(0, 0, dc.at(0), 0, 0, dc.at(1), 0, 0, 0); + cv::fisheye::projectPoints(X, x2, om, theT, K2, k, alpha, cv::noArray()); xpred = x1 + cv::Mat(jacobians.colRange(2,4) * dc).reshape(2, 1); CV_Assert (cv::norm(x2 - xpred) < 1e-10); @@ -219,7 +219,7 @@ TEST_F(fisheyeTest, jacobians) r.fill(dk, cv::RNG::NORMAL, 0, 1); dk *= 1e-9*cv::norm(k); cv::Mat k2 = k + dk; - cv::fisheye::projectPoints(X, x2, om, T, K, k2, alpha, cv::noArray()); + cv::fisheye::projectPoints(X, x2, om, theT, theK, k2, alpha, cv::noArray()); xpred = x1 + cv::Mat(jacobians.colRange(4,8) * dk).reshape(2, 1); CV_Assert (cv::norm(x2 - xpred) < 1e-10); @@ -228,8 +228,8 @@ TEST_F(fisheyeTest, jacobians) r.fill(dalpha, cv::RNG::NORMAL, 0, 1); dalpha *= 1e-9*cv::norm(f); double alpha2 = alpha + dalpha.at(0); - K2 = K + cv::Matx33d(0, f.at(0) * dalpha.at(0), 0, 0, 0, 0, 0, 0, 0); - cv::fisheye::projectPoints(X, x2, om, T, K, k, alpha2, cv::noArray()); + K2 = theK + cv::Matx33d(0, f.at(0) * dalpha.at(0), 0, 0, 0, 0, 0, 0, 0); + cv::fisheye::projectPoints(X, x2, om, theT, theK, k, alpha2, cv::noArray()); xpred = x1 + cv::Mat(jacobians.col(14) * dalpha).reshape(2, 1); CV_Assert (cv::norm(x2 - xpred) < 1e-10); } @@ -259,14 +259,14 @@ TEST_F(fisheyeTest, Calibration) flag |= cv::fisheye::CALIB_CHECK_COND; flag |= cv::fisheye::CALIB_FIX_SKEW; - cv::Matx33d K; - cv::Vec4d D; + cv::Matx33d theK; + cv::Vec4d theD; - cv::fisheye::calibrate(objectPoints, imagePoints, imageSize, K, D, + cv::fisheye::calibrate(objectPoints, imagePoints, imageSize, theK, theD, cv::noArray(), cv::noArray(), flag, cv::TermCriteria(3, 20, 1e-6)); - EXPECT_MAT_NEAR(K, this->K, 1e-10); - EXPECT_MAT_NEAR(D, this->D, 1e-10); + EXPECT_MAT_NEAR(theK, this->K, 1e-10); + EXPECT_MAT_NEAR(theD, this->D, 1e-10); } TEST_F(fisheyeTest, Homography) @@ -303,15 +303,15 @@ TEST_F(fisheyeTest, Homography) int Np = imagePointsNormalized.cols; cv::calcCovarMatrix(_objectPoints, covObjectPoints, objectPointsMean, cv::COVAR_NORMAL | cv::COVAR_COLS); cv::SVD svd(covObjectPoints); - cv::Mat R(svd.vt); + cv::Mat theR(svd.vt); - if (cv::norm(R(cv::Rect(2, 0, 1, 2))) < 1e-6) - R = cv::Mat::eye(3,3, CV_64FC1); - if (cv::determinant(R) < 0) - R = -R; + if (cv::norm(theR(cv::Rect(2, 0, 1, 2))) < 1e-6) + theR = cv::Mat::eye(3,3, CV_64FC1); + if (cv::determinant(theR) < 0) + theR = -theR; - cv::Mat T = -R * objectPointsMean; - cv::Mat X_new = R * _objectPoints + T * cv::Mat::ones(1, Np, CV_64FC1); + cv::Mat theT = -theR * objectPointsMean; + cv::Mat X_new = theR * _objectPoints + theT * cv::Mat::ones(1, Np, CV_64FC1); cv::Mat H = cv::internal::ComputeHomography(imagePointsNormalized, X_new.rowRange(0, 2)); cv::Mat M = cv::Mat::ones(3, X_new.cols, CV_64FC1); @@ -355,19 +355,19 @@ TEST_F(fisheyeTest, EtimateUncertainties) flag |= cv::fisheye::CALIB_CHECK_COND; flag |= cv::fisheye::CALIB_FIX_SKEW; - cv::Matx33d K; - cv::Vec4d D; + cv::Matx33d theK; + cv::Vec4d theD; std::vector rvec; std::vector tvec; - cv::fisheye::calibrate(objectPoints, imagePoints, imageSize, K, D, + cv::fisheye::calibrate(objectPoints, imagePoints, imageSize, theK, theD, rvec, tvec, flag, cv::TermCriteria(3, 20, 1e-6)); cv::internal::IntrinsicParams param, errors; cv::Vec2d err_std; double thresh_cond = 1e6; int check_cond = 1; - param.Init(cv::Vec2d(K(0,0), K(1,1)), cv::Vec2d(K(0,2), K(1, 2)), D); + param.Init(cv::Vec2d(theK(0,0), theK(1,1)), cv::Vec2d(theK(0,2), theK(1, 2)), theD); param.isEstimate = std::vector(9, 1); param.isEstimate[4] = 0; @@ -399,12 +399,12 @@ TEST_F(fisheyeTest, rectify) cv::Matx33d K1 = this->K, K2 = K1; cv::Mat D1 = cv::Mat(this->D), D2 = D1; - cv::Vec3d T = this->T; - cv::Matx33d R = this->R; + cv::Vec3d theT = this->T; + cv::Matx33d theR = this->R; double balance = 0.0, fov_scale = 1.1; cv::Mat R1, R2, P1, P2, Q; - cv::fisheye::stereoRectify(K1, D1, K2, D2, calibration_size, R, T, R1, R2, P1, P2, Q, + cv::fisheye::stereoRectify(K1, D1, K2, D2, calibration_size, theR, theT, R1, R2, P1, P2, Q, cv::CALIB_ZERO_DISPARITY, requested_size, balance, fov_scale); cv::Mat lmapx, lmapy, rmapx, rmapy; @@ -468,8 +468,8 @@ TEST_F(fisheyeTest, stereoCalibrate) fs_object[cv::format("image_%d", i )] >> objectPoints[i]; fs_object.release(); - cv::Matx33d K1, K2, R; - cv::Vec3d T; + cv::Matx33d K1, K2, theR; + cv::Vec3d theT; cv::Vec4d D1, D2; int flag = 0; @@ -479,7 +479,7 @@ TEST_F(fisheyeTest, stereoCalibrate) // flag |= cv::fisheye::CALIB_FIX_INTRINSIC; cv::fisheye::stereoCalibrate(objectPoints, leftPoints, rightPoints, - K1, D1, K2, D2, imageSize, R, T, flag, + K1, D1, K2, D2, imageSize, theR, theT, flag, cv::TermCriteria(3, 12, 0)); cv::Matx33d R_correct( 0.9975587205950972, 0.06953016383322372, 0.006492709911733523, @@ -497,8 +497,8 @@ TEST_F(fisheyeTest, stereoCalibrate) cv::Vec4d D1_correct (-7.44253716539556e-05, -0.00702662033932424, 0.00737569823650885, -0.00342230256441771); cv::Vec4d D2_correct (-0.0130785435677431, 0.0284434505383497, -0.0360333869900506, 0.0144724062347222); - EXPECT_MAT_NEAR(R, R_correct, 1e-10); - EXPECT_MAT_NEAR(T, T_correct, 1e-10); + EXPECT_MAT_NEAR(theR, R_correct, 1e-10); + EXPECT_MAT_NEAR(theT, T_correct, 1e-10); EXPECT_MAT_NEAR(K1, K1_correct, 1e-10); EXPECT_MAT_NEAR(K2, K2_correct, 1e-10); @@ -536,8 +536,8 @@ TEST_F(fisheyeTest, stereoCalibrateFixIntrinsic) fs_object[cv::format("image_%d", i )] >> objectPoints[i]; fs_object.release(); - cv::Matx33d R; - cv::Vec3d T; + cv::Matx33d theR; + cv::Vec3d theT; int flag = 0; flag |= cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC; @@ -557,7 +557,7 @@ TEST_F(fisheyeTest, stereoCalibrateFixIntrinsic) cv::Vec4d D2 (-0.0130785435677431, 0.0284434505383497, -0.0360333869900506, 0.0144724062347222); cv::fisheye::stereoCalibrate(objectPoints, leftPoints, rightPoints, - K1, D1, K2, D2, imageSize, R, T, flag, + K1, D1, K2, D2, imageSize, theR, theT, flag, cv::TermCriteria(3, 12, 0)); cv::Matx33d R_correct( 0.9975587205950972, 0.06953016383322372, 0.006492709911733523, @@ -566,8 +566,8 @@ TEST_F(fisheyeTest, stereoCalibrateFixIntrinsic) cv::Vec3d T_correct(-0.099402724724121, 0.00270812139265413, 0.00129330292472699); - EXPECT_MAT_NEAR(R, R_correct, 1e-10); - EXPECT_MAT_NEAR(T, T_correct, 1e-10); + EXPECT_MAT_NEAR(theR, R_correct, 1e-10); + EXPECT_MAT_NEAR(theT, T_correct, 1e-10); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index a9240f8d4..6ad72461d 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -1504,7 +1504,7 @@ static bool ocl_binary_op(InputArray _src1, InputArray _src2, OutputArray _dst, k.args(src1arg, src2arg, maskarg, dstarg); } - size_t globalsize[] = { src1.cols * cn / kercn, (src1.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[] = { (size_t)src1.cols * cn / kercn, ((size_t)src1.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, 0, false); } @@ -1917,7 +1917,7 @@ static bool ocl_arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, k.args(src1arg, src2arg, maskarg, dstarg); } - size_t globalsize[] = { src1.cols * cn / kercn, (src1.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[] = { (size_t)src1.cols * cn / kercn, ((size_t)src1.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -4974,7 +4974,7 @@ static bool ocl_compare(InputArray _src1, InputArray _src2, OutputArray _dst, in ocl::KernelArg::WriteOnly(dst, cn, kercn)); } - size_t globalsize[2] = { dst.cols * cn / kercn, (dst.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dst.cols * cn / kercn, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -5668,7 +5668,7 @@ static bool ocl_inRange( InputArray _src, InputArray _lowerb, ker.args(srcarg, dstarg, ocl::KernelArg::ReadOnlyNoSize(lscalaru), ocl::KernelArg::ReadOnlyNoSize(uscalaru), rowsPerWI); - size_t globalsize[2] = { ssize.width / colsPerWI, (ssize.height + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)ssize.width / colsPerWI, ((size_t)ssize.height + rowsPerWI - 1) / rowsPerWI }; return ker.run(2, globalsize, NULL, false); } diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 1070bd546..1e9d832f3 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -902,7 +902,7 @@ static bool ocl_split( InputArray _m, OutputArrayOfArrays _mv ) argidx = k.set(argidx, ocl::KernelArg::WriteOnlyNoSize(dst[i])); k.set(argidx, rowsPerWI); - size_t globalsize[2] = { size.width, (size.height + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)size.width, ((size_t)size.height + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -1069,7 +1069,7 @@ static bool ocl_merge( InputArrayOfArrays _mv, OutputArray _dst ) argidx = k.set(argidx, ocl::KernelArg::WriteOnly(dst)); k.set(argidx, rowsPerWI); - size_t globalsize[2] = { dst.cols, (dst.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dst.cols, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -1338,7 +1338,7 @@ static bool ocl_mixChannels(InputArrayOfArrays _src, InputOutputArrayOfArrays _d argindex = k.set(argindex, size.width); k.set(argindex, rowsPerWI); - size_t globalsize[2] = { size.width, (size.height + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)size.width, ((size_t)size.height + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -5505,7 +5505,7 @@ static bool ocl_convertScaleAbs( InputArray _src, OutputArray _dst, double alpha else if (wdepth == CV_64F) k.args(srcarg, dstarg, alpha, beta); - size_t globalsize[2] = { src.cols * cn / kercn, (src.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)src.cols * cn / kercn, ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -5673,7 +5673,7 @@ static bool ocl_LUT(InputArray _src, InputArray _lut, OutputArray _dst) k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::ReadOnlyNoSize(lut), ocl::KernelArg::WriteOnly(dst, dcn, kercn)); - size_t globalSize[2] = { dst.cols * dcn / kercn, (dst.rows + 3) / 4 }; + size_t globalSize[2] = { (size_t)dst.cols * dcn / kercn, ((size_t)dst.rows + 3) / 4 }; return k.run(2, globalSize, NULL, false); } @@ -6053,7 +6053,7 @@ static bool ocl_normalize( InputArray _src, InputOutputArray _dst, InputArray _m k.args(srcarg, maskarg, dstarg); } - size_t globalsize[2] = { src.cols, (src.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)src.cols, ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } else diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index c463b70d4..b2ef33cad 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -692,7 +692,7 @@ static bool ocl_flip(InputArray _src, OutputArray _dst, int flipCode ) size_t maxWorkGroupSize = dev.maxWorkGroupSize(); CV_Assert(maxWorkGroupSize % 4 == 0); - size_t globalsize[2] = { cols, (rows + pxPerWIy - 1) / pxPerWIy }, + size_t globalsize[2] = { (size_t)cols, ((size_t)rows + pxPerWIy - 1) / pxPerWIy }, localsize[2] = { maxWorkGroupSize / 4, 4 }; return k.run(2, globalsize, (flipType == FLIP_COLS) && !dev.isIntel() ? localsize : NULL, false); } @@ -833,7 +833,7 @@ static bool ocl_repeat(InputArray _src, int ny, int nx, OutputArray _dst) UMat src = _src.getUMat(), dst = _dst.getUMat(); k.args(ocl::KernelArg::ReadOnly(src, cn, kercn), ocl::KernelArg::WriteOnlyNoSize(dst)); - size_t globalsize[] = { src.cols * cn / kercn, (src.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[] = { (size_t)src.cols * cn / kercn, ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -1110,7 +1110,7 @@ static bool ocl_copyMakeBorder( InputArray _src, OutputArray _dst, int top, int k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst), top, left, ocl::KernelArg::Constant(Mat(1, 1, sctype, value))); - size_t globalsize[2] = { dst.cols, (dst.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dst.cols, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/core/src/directx.cpp b/modules/core/src/directx.cpp index 46f353240..23a7b94c6 100644 --- a/modules/core/src/directx.cpp +++ b/modules/core/src/directx.cpp @@ -729,7 +729,7 @@ bool ocl_convert_nv12_to_bgr( k.args(clImageY, clImageUV, clBuffer, step, cols, rows); - size_t globalsize[] = { cols, rows }; + size_t globalsize[] = { (size_t)cols, (size_t)rows }; return k.run(2, globalsize, 0, false); } @@ -750,7 +750,7 @@ bool ocl_convert_bgr_to_nv12( k.args(clBuffer, step, cols, rows, clImageY, clImageUV); - size_t globalsize[] = { cols, rows }; + size_t globalsize[] = { (size_t)cols, (size_t)rows }; return k.run(2, globalsize, 0, false); } @@ -834,7 +834,7 @@ void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D) { size_t offset = 0; // TODO size_t origin[3] = { 0, 0, 0 }; - size_t region[3] = { u.cols, u.rows, 1 }; + size_t region[3] = { (size_t)u.cols, (size_t)u.rows, 1 }; status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, origin, region, 0, NULL, NULL); if (status != CL_SUCCESS) @@ -939,7 +939,7 @@ void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst { size_t offset = 0; // TODO size_t origin[3] = { 0, 0, 0 }; - size_t region[3] = { u.cols, u.rows, 1 }; + size_t region[3] = { (size_t)u.cols, (size_t)u.rows, 1 }; status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, origin, region, offset, 0, NULL, NULL); if (status != CL_SUCCESS) @@ -1041,7 +1041,7 @@ void convertToD3D10Texture2D(InputArray src, ID3D10Texture2D* pD3D10Texture2D) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D10ObjectsKHR failed"); size_t offset = 0; // TODO size_t dst_origin[3] = {0, 0, 0}; - size_t region[3] = {u.cols, u.rows, 1}; + size_t region[3] = {(size_t)u.cols, (size_t)u.rows, 1}; status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, dst_origin, region, 0, NULL, NULL); if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyBufferToImage failed"); @@ -1100,7 +1100,7 @@ void convertFromD3D10Texture2D(ID3D10Texture2D* pD3D10Texture2D, OutputArray dst CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D10ObjectsKHR failed"); size_t offset = 0; // TODO size_t src_origin[3] = {0, 0, 0}; - size_t region[3] = {u.cols, u.rows, 1}; + size_t region[3] = {(size_t)u.cols, (size_t)u.rows, 1}; status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, src_origin, region, offset, 0, NULL, NULL); if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyImageToBuffer failed"); @@ -1195,7 +1195,7 @@ void convertToDirect3DSurface9(InputArray src, IDirect3DSurface9* pDirect3DSurfa CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireDX9MediaSurfacesKHR failed"); size_t offset = 0; // TODO size_t dst_origin[3] = {0, 0, 0}; - size_t region[3] = {u.cols, u.rows, 1}; + size_t region[3] = {(size_t)u.cols, (size_t)u.rows, 1}; status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, dst_origin, region, 0, NULL, NULL); if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyBufferToImage failed"); @@ -1261,7 +1261,7 @@ void convertFromDirect3DSurface9(IDirect3DSurface9* pDirect3DSurface9, OutputArr CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireDX9MediaSurfacesKHR failed"); size_t offset = 0; // TODO size_t src_origin[3] = {0, 0, 0}; - size_t region[3] = {u.cols, u.rows, 1}; + size_t region[3] = {(size_t)u.cols, (size_t)u.rows, 1}; status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, src_origin, region, offset, 0, NULL, NULL); if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyImageToBuffer failed"); diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index 720898c43..5576a347a 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -2934,7 +2934,7 @@ static bool ocl_mulSpectrums( InputArray _srcA, InputArray _srcB, k.args(ocl::KernelArg::ReadOnlyNoSize(A), ocl::KernelArg::ReadOnlyNoSize(B), ocl::KernelArg::WriteOnly(dst), rowsPerWI); - size_t globalsize[2] = { asize.width, (asize.height + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)asize.width, ((size_t)asize.height + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/core/src/mathfuncs.cpp b/modules/core/src/mathfuncs.cpp index 97f36299d..2859b2d5d 100644 --- a/modules/core/src/mathfuncs.cpp +++ b/modules/core/src/mathfuncs.cpp @@ -93,7 +93,7 @@ static bool ocl_math_op(InputArray _src1, InputArray _src2, OutputArray _dst, in else k.args(src1arg, src2arg, dstarg); - size_t globalsize[] = { src1.cols * cn / kercn, (src1.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[] = { (size_t)src1.cols * cn / kercn, ((size_t)src1.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, 0, false); } @@ -330,7 +330,7 @@ static bool ocl_cartToPolar( InputArray _src1, InputArray _src2, ocl::KernelArg::WriteOnly(dst1, cn), ocl::KernelArg::WriteOnlyNoSize(dst2)); - size_t globalsize[2] = { dst1.cols * cn, (dst1.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dst1.cols * cn, ((size_t)dst1.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -612,7 +612,7 @@ static bool ocl_polarToCart( InputArray _mag, InputArray _angle, k.args(ocl::KernelArg::ReadOnlyNoSize(mag), ocl::KernelArg::ReadOnlyNoSize(angle), ocl::KernelArg::WriteOnly(dst1, cn), ocl::KernelArg::WriteOnlyNoSize(dst2)); - size_t globalsize[2] = { dst1.cols * cn, (dst1.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dst1.cols * cn, ((size_t)dst1.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -1181,8 +1181,8 @@ iPow_i( const T* src, T* dst, int len, int power ) { T tab[5] = { - power == -1 ? saturate_cast(-1) : 0, (power & 1) ? -1 : 1, - std::numeric_limits::max(), 1, power == -1 ? 1 : 0 + saturate_cast(power == -1 ? -1 : 0), saturate_cast((power & 1) ? -1 : 1), + std::numeric_limits::max(), 1, saturate_cast(power == -1 ? 1 : 0) }; for( int i = 0; i < len; i++ ) { @@ -1349,7 +1349,7 @@ static bool ocl_pow(InputArray _src, double power, OutputArray _dst, k.args(srcarg, dstarg, power); } - size_t globalsize[2] = { dst.cols * cn, (dst.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dst.cols * cn, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -1734,7 +1734,7 @@ static bool ocl_patchNaNs( InputOutputArray _a, float value ) k.args(ocl::KernelArg::ReadOnlyNoSize(a), ocl::KernelArg::WriteOnly(a, cn), (float)value); - size_t globalsize[2] = { a.cols * cn, (a.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)a.cols * cn, ((size_t)a.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.cpp index 99f6bf95e..bf58dd0f3 100644 --- a/modules/core/src/matmul.cpp +++ b/modules/core/src/matmul.cpp @@ -859,8 +859,8 @@ static bool ocl_gemm( InputArray matA, InputArray matB, double alpha, ocl::KernelArg::ReadWrite(D, cn, kercn), sizeA.width, (float)alpha, (float)beta); - size_t globalsize[2] = { sizeD.width * cn / kercn, sizeD.height}; - size_t localsize[2] = { block_size, block_size}; + size_t globalsize[2] = { (size_t)sizeD.width * cn / kercn, (size_t)sizeD.height}; + size_t localsize[2] = { (size_t)block_size, (size_t)block_size}; return k.run(2, globalsize, block_size!=1 ? localsize : NULL, false); } #endif @@ -2304,7 +2304,7 @@ static bool ocl_scaleAdd( InputArray _src1, double alpha, InputArray _src2, Outp else k.args(src1arg, src2arg, dstarg, alpha); - size_t globalsize[2] = { dst.cols * cn / kercn, (dst.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dst.cols * cn / kercn, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/core/src/matop.cpp b/modules/core/src/matop.cpp index 30933e08a..2a6ec2635 100644 --- a/modules/core/src/matop.cpp +++ b/modules/core/src/matop.cpp @@ -1583,12 +1583,12 @@ void MatOp_Initializer::multiply(const MatExpr& e, double s, MatExpr& res) const inline void MatOp_Initializer::makeExpr(MatExpr& res, int method, Size sz, int type, double alpha) { - res = MatExpr(getGlobalMatOpInitializer(), method, Mat(sz, type, (void*)0xEEEEEEEE), Mat(), Mat(), alpha, 0); + res = MatExpr(getGlobalMatOpInitializer(), method, Mat(sz, type, (void*)(size_t)0xEEEEEEEE), Mat(), Mat(), alpha, 0); } inline void MatOp_Initializer::makeExpr(MatExpr& res, int method, int ndims, const int* sizes, int type, double alpha) { - res = MatExpr(getGlobalMatOpInitializer(), method, Mat(ndims, sizes, type, (void*)0xEEEEEEEE), Mat(), Mat(), alpha, 0); + res = MatExpr(getGlobalMatOpInitializer(), method, Mat(ndims, sizes, type, (void*)(size_t)0xEEEEEEEE), Mat(), Mat(), alpha, 0); } /////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 9c05260e1..8c391aa0d 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -2831,7 +2831,7 @@ static bool ocl_setIdentity( InputOutputArray _m, const Scalar& s ) k.args(ocl::KernelArg::WriteOnly(m, cn, kercn), ocl::KernelArg::Constant(Mat(1, 1, sctype, s))); - size_t globalsize[2] = { m.cols * cn / kercn, (m.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)m.cols * cn / kercn, ((size_t)m.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -3071,7 +3071,7 @@ static bool ocl_transpose( InputArray _src, OutputArray _dst ) ocl::KernelArg::WriteOnlyNoSize(dst)); size_t localsize[2] = { TILE_DIM, BLOCK_ROWS }; - size_t globalsize[2] = { src.cols, inplace ? (src.rows + rowsPerWI - 1) / rowsPerWI : (divUp(src.rows, TILE_DIM) * BLOCK_ROWS) }; + size_t globalsize[2] = { (size_t)src.cols, inplace ? ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI : (divUp((size_t)src.rows, TILE_DIM) * BLOCK_ROWS) }; if (inplace && dev.isIntel()) { @@ -3576,8 +3576,8 @@ static bool ocl_reduce(InputArray _src, OutputArray _dst, k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnlyNoSize(dst)); - size_t localSize[2] = { buf_cols, tileHeight}; - size_t globalSize[2] = { buf_cols, src.rows }; + size_t localSize[2] = { (size_t)buf_cols, (size_t)tileHeight}; + size_t globalSize[2] = { (size_t)buf_cols, (size_t)src.rows }; return k.run(2, globalSize, localSize, false); } else diff --git a/modules/core/src/umatrix.cpp b/modules/core/src/umatrix.cpp index 7bfeff1df..999a5cc18 100644 --- a/modules/core/src/umatrix.cpp +++ b/modules/core/src/umatrix.cpp @@ -840,7 +840,7 @@ void UMat::copyTo(OutputArray _dst, InputArray _mask) const haveDstUninit ? ocl::KernelArg::WriteOnly(dst) : ocl::KernelArg::ReadWrite(dst)); - size_t globalsize[2] = { cols, rows }; + size_t globalsize[2] = { (size_t)cols, (size_t)rows }; if (k.run(2, globalsize, NULL, false)) { CV_IMPL_ADD(CV_IMPL_OCL); @@ -901,7 +901,7 @@ void UMat::convertTo(OutputArray _dst, int _type, double alpha, double beta) con else k.args(srcarg, dstarg, alpha, beta, rowsPerWI); - size_t globalsize[2] = { dst.cols * cn, (dst.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dst.cols * cn, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; if (k.run(2, globalsize, NULL, false)) { CV_IMPL_ADD(CV_IMPL_OCL); @@ -957,7 +957,7 @@ UMat& UMat::setTo(InputArray _value, InputArray _mask) setK.args(dstarg, scalararg); } - size_t globalsize[] = { cols * cn / kercn, (rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[] = { (size_t)cols * cn / kercn, ((size_t)rows + rowsPerWI - 1) / rowsPerWI }; if( setK.run(2, globalsize, NULL, false) ) { CV_IMPL_ADD(CV_IMPL_OCL); diff --git a/modules/core/src/va_intel.cpp b/modules/core/src/va_intel.cpp index 32fbb2dfd..5cdd6e8f3 100644 --- a/modules/core/src/va_intel.cpp +++ b/modules/core/src/va_intel.cpp @@ -158,7 +158,7 @@ static bool ocl_convert_nv12_to_bgr(cl_mem clImageY, cl_mem clImageUV, cl_mem cl k.args(clImageY, clImageUV, clBuffer, step, cols, rows); - size_t globalsize[] = { cols, rows }; + size_t globalsize[] = { (size_t)cols, (size_t)rows }; return k.run(2, globalsize, 0, false); } @@ -171,7 +171,7 @@ static bool ocl_convert_bgr_to_nv12(cl_mem clBuffer, int step, int cols, int row k.args(clBuffer, step, cols, rows, clImageY, clImageUV); - size_t globalsize[] = { cols, rows }; + size_t globalsize[] = { (size_t)cols, (size_t)rows }; return k.run(2, globalsize, 0, false); } #endif // HAVE_VA_INTEL && HAVE_OPENCL diff --git a/modules/core/test/test_umat.cpp b/modules/core/test/test_umat.cpp index bdd38a0a1..fe64d2f94 100644 --- a/modules/core/test/test_umat.cpp +++ b/modules/core/test/test_umat.cpp @@ -1298,7 +1298,11 @@ TEST(UMat, testTempObjects_UMat) ASSERT_EQ(0, countNonZero(uDiff)); } -TEST(UMat, testTempObjects_Mat) +// Disabled due to failure in VS 2015: +// C++11 is enabled by default ==> +// destructors have implicit 'noexcept(true)' specifier ==> +// throwing exception from destructor is not handled correctly +TEST(UMat, DISABLED_testTempObjects_Mat) { Mat m(10, 10, CV_8UC1, Scalar(1)); { diff --git a/modules/features2d/src/fast.cpp b/modules/features2d/src/fast.cpp index 11c039a0c..c70a29ae1 100644 --- a/modules/features2d/src/fast.cpp +++ b/modules/features2d/src/fast.cpp @@ -262,7 +262,7 @@ static bool ocl_FAST( InputArray _img, std::vector& keypoints, UMat img = _img.getUMat(); if( img.cols < 7 || img.rows < 7 ) return false; - size_t globalsize[] = { img.cols-6, img.rows-6 }; + size_t globalsize[] = { (size_t)img.cols-6, (size_t)img.rows-6 }; ocl::Kernel fastKptKernel("FAST_findKeypoints", ocl::features2d::fast_oclsrc); if (fastKptKernel.empty()) @@ -306,7 +306,7 @@ static bool ocl_FAST( InputArray _img, std::vector& keypoints, if (fastNMSKernel.empty()) return false; - size_t globalsize_nms[] = { counter }; + size_t globalsize_nms[] = { (size_t)counter }; if( !fastNMSKernel.args(ocl::KernelArg::PtrReadOnly(kp1), ocl::KernelArg::PtrReadWrite(kp2), ocl::KernelArg::ReadOnly(img), diff --git a/modules/features2d/src/matchers.cpp b/modules/features2d/src/matchers.cpp index 8d2f69ec8..ea0fdaa0b 100644 --- a/modules/features2d/src/matchers.cpp +++ b/modules/features2d/src/matchers.cpp @@ -97,8 +97,8 @@ static bool ocl_matchSingle(InputArray query, InputArray train, if(k.empty()) return false; - size_t globalSize[] = {(query.size().height + block_size - 1) / block_size * block_size, block_size}; - size_t localSize[] = {block_size, block_size}; + size_t globalSize[] = {((size_t)query.size().height + block_size - 1) / block_size * block_size, (size_t)block_size}; + size_t localSize[] = {(size_t)block_size, (size_t)block_size}; int idx = 0; idx = k.set(idx, ocl::KernelArg::PtrReadOnly(uquery)); @@ -197,8 +197,8 @@ static bool ocl_knnMatchSingle(InputArray query, InputArray train, UMat &trainId if(k.empty()) return false; - size_t globalSize[] = {(query_rows + block_size - 1) / block_size * block_size, block_size}; - size_t localSize[] = {block_size, block_size}; + size_t globalSize[] = {((size_t)query_rows + block_size - 1) / block_size * block_size, (size_t)block_size}; + size_t localSize[] = {(size_t)block_size, (size_t)block_size}; int idx = 0; idx = k.set(idx, ocl::KernelArg::PtrReadOnly(uquery)); @@ -306,8 +306,8 @@ static bool ocl_radiusMatchSingle(InputArray query, InputArray train, if (k.empty()) return false; - size_t globalSize[] = {(train_rows + block_size - 1) / block_size * block_size, (query_rows + block_size - 1) / block_size * block_size}; - size_t localSize[] = {block_size, block_size}; + size_t globalSize[] = {((size_t)train_rows + block_size - 1) / block_size * block_size, ((size_t)query_rows + block_size - 1) / block_size * block_size}; + size_t localSize[] = {(size_t)block_size, (size_t)block_size}; int idx = 0; idx = k.set(idx, ocl::KernelArg::PtrReadOnly(uquery)); diff --git a/modules/features2d/src/orb.cpp b/modules/features2d/src/orb.cpp index a1a245339..c9827e2c0 100644 --- a/modules/features2d/src/orb.cpp +++ b/modules/features2d/src/orb.cpp @@ -64,7 +64,7 @@ ocl_HarrisResponses(const UMat& imgbuf, UMat& responses, int nkeypoints, int blockSize, float harris_k) { - size_t globalSize[] = {nkeypoints}; + size_t globalSize[] = {(size_t)nkeypoints}; float scale = 1.f/((1 << 2) * blockSize * 255.f); float scale_sq_sq = scale * scale * scale * scale; @@ -86,7 +86,7 @@ ocl_ICAngles(const UMat& imgbuf, const UMat& layerinfo, const UMat& keypoints, UMat& responses, const UMat& umax, int nkeypoints, int half_k) { - size_t globalSize[] = {nkeypoints}; + size_t globalSize[] = {(size_t)nkeypoints}; ocl::Kernel icangle_ker("ORB_ICAngle", ocl::features2d::orb_oclsrc, "-D ORB_ANGLES"); if( icangle_ker.empty() ) @@ -106,7 +106,7 @@ ocl_computeOrbDescriptors(const UMat& imgbuf, const UMat& layerInfo, const UMat& keypoints, UMat& desc, const UMat& pattern, int nkeypoints, int dsize, int wta_k) { - size_t globalSize[] = {nkeypoints}; + size_t globalSize[] = {(size_t)nkeypoints}; ocl::Kernel desc_ker("ORB_computeDescriptor", ocl::features2d::orb_oclsrc, format("-D ORB_DESCRIPTORS -D WTA_K=%d", wta_k)); diff --git a/modules/imgproc/perf/perf_cvt_color.cpp b/modules/imgproc/perf/perf_cvt_color.cpp index 02622ea80..fc9a2cd8e 100644 --- a/modules/imgproc/perf/perf_cvt_color.cpp +++ b/modules/imgproc/perf/perf_cvt_color.cpp @@ -263,6 +263,11 @@ PERF_TEST_P(Size_CvtMode, cvtColor8u, #if defined(__APPLE__) && defined(HAVE_IPP) SANITY_CHECK(dst, _mode == CX_BGRA2HLS_FULL ? 2 : 1); +#elif defined(_MSC_VER) && _MSC_VER >= 1900 /* MSVC 14 */ + if (_mode == CX_Luv2BGRA) + SANITY_CHECK_NOTHING(); + else + SANITY_CHECK(dst, 1); #else SANITY_CHECK(dst, 1); #endif diff --git a/modules/imgproc/src/accum.cpp b/modules/imgproc/src/accum.cpp index 8792e85d0..c7cbc40f3 100644 --- a/modules/imgproc/src/accum.cpp +++ b/modules/imgproc/src/accum.cpp @@ -835,7 +835,7 @@ static bool ocl_accumulate( InputArray _src, InputArray _src2, InputOutputArray if (haveMask) k.set(argidx, maskarg); - size_t globalsize[2] = { src.cols * cn / kercn, (src.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)src.cols * cn / kercn, ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/imgproc/src/blend.cpp b/modules/imgproc/src/blend.cpp index 7a2e57d52..2393f26db 100644 --- a/modules/imgproc/src/blend.cpp +++ b/modules/imgproc/src/blend.cpp @@ -111,7 +111,7 @@ static bool ocl_blendLinear( InputArray _src1, InputArray _src2, InputArray _wei ocl::KernelArg::ReadOnlyNoSize(weights1), ocl::KernelArg::ReadOnlyNoSize(weights2), ocl::KernelArg::WriteOnly(dst)); - size_t globalsize[2] = { dst.cols, dst.rows }; + size_t globalsize[2] = { (size_t)dst.cols, (size_t)dst.rows }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index a4c0c6cfd..815b03b70 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -164,8 +164,8 @@ static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float ocl::KernelArg::WriteOnlyNoSize(map), (float) low, (float) high); - size_t globalsize[2] = { size.width, size.height }, - localsize[2] = { lSizeX, lSizeY }; + size_t globalsize[2] = { (size_t)size.width, (size_t)size.height }, + localsize[2] = { (size_t)lSizeX, (size_t)lSizeY }; if (!with_sobel.run(2, globalsize, localsize, false)) return false; @@ -193,8 +193,8 @@ static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float ocl::KernelArg::WriteOnly(map), low, high); - size_t globalsize[2] = { size.width, size.height }, - localsize[2] = { lSizeX, lSizeY }; + size_t globalsize[2] = { (size_t)size.width, (size_t)size.height }, + localsize[2] = { (size_t)lSizeX, (size_t)lSizeY }; if (!without_sobel.run(2, globalsize, localsize, false)) return false; @@ -210,7 +210,7 @@ static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float if (sizey == 0) sizey = 1; - size_t globalsize[2] = { size.width, (size.height + PIX_PER_WI - 1) / PIX_PER_WI }, localsize[2] = { lSizeX, sizey }; + size_t globalsize[2] = { (size_t)size.width, ((size_t)size.height + PIX_PER_WI - 1) / PIX_PER_WI }, localsize[2] = { (size_t)lSizeX, (size_t)sizey }; ocl::Kernel edgesHysteresis("stage2_hysteresis", ocl::imgproc::canny_oclsrc, format("-D STAGE2 -D PIX_PER_WI=%d -D LOCAL_X=%d -D LOCAL_Y=%d", diff --git a/modules/imgproc/src/clahe.cpp b/modules/imgproc/src/clahe.cpp index 75edd18e4..fcd6c21a3 100644 --- a/modules/imgproc/src/clahe.cpp +++ b/modules/imgproc/src/clahe.cpp @@ -107,7 +107,7 @@ namespace clahe cv::UMat lut = _lut.getUMat(); size_t localThreads[3] = { 32, 8, 1 }; - size_t globalThreads[3] = { src.cols, src.rows, 1 }; + size_t globalThreads[3] = { (size_t)src.cols, (size_t)src.rows, 1 }; int idx = 0; idx = k.set(idx, cv::ocl::KernelArg::ReadOnlyNoSize(src)); diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 27d602e0d..95197ec03 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -6692,7 +6692,7 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) int pxPerWIy = dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU) ? 4 : 1; int pxPerWIx = 1; - size_t globalsize[] = { src.cols, (src.rows + pxPerWIy - 1) / pxPerWIy }; + size_t globalsize[] = { (size_t)src.cols, ((size_t)src.rows + pxPerWIy - 1) / pxPerWIy }; cv::String opts = format("-D depth=%d -D scn=%d -D PIX_PER_WI_Y=%d ", depth, scn, pxPerWIy); diff --git a/modules/imgproc/src/colormap.cpp b/modules/imgproc/src/colormap.cpp index 8e5236ce4..6d03d7b5f 100644 --- a/modules/imgproc/src/colormap.cpp +++ b/modules/imgproc/src/colormap.cpp @@ -188,7 +188,7 @@ namespace colormap void init(int n) { float r[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - float g[] = { 0, 0.01587301587301587, 0.03174603174603174, 0.04761904761904762, 0.06349206349206349, 0.07936507936507936, 0.09523809523809523, 0.1111111111111111, 0.126984126984127, 0.1428571428571428, 0.1587301587301587, 0.1746031746031746, 0.1904761904761905, 0.2063492063492063, 0.2222222222222222, 0.2380952380952381, 0.253968253968254, 0.2698412698412698, 0.2857142857142857, 0.3015873015873016, 0.3174603174603174, 0.3333333333333333, 0.3492063492063492, 0.3650793650793651, 0.3809523809523809, 0.3968253968253968, 0.4126984126984127, 0.4285714285714285, 0.4444444444444444, 0.4603174603174603, 0.4761904761904762, 0.492063492063492, 0.5079365079365079, 0.5238095238095238, 0.5396825396825397, 0.5555555555555556, 0.5714285714285714, 0.5873015873015873, 0.6031746031746031, 0.6190476190476191, 0.6349206349206349, 0.6507936507936508, 0.6666666666666666, 0.6825396825396826, 0.6984126984126984, 0.7142857142857143, 0.7301587301587301, 0.746031746031746, 0.7619047619047619, 0.7777777777777778, 0.7936507936507936, 0.8095238095238095, 0.8253968253968254, 0.8412698412698413, 0.8571428571428571, 0.873015873015873, 0.8888888888888888, 0.9047619047619048, 0.9206349206349206, 0.9365079365079365, 0.9523809523809523, 0.9682539682539683, 0.9841269841269841, 1}; + float g[] = { 0, 0.01587301587301587f, 0.03174603174603174f, 0.04761904761904762f, 0.06349206349206349f, 0.07936507936507936f, 0.09523809523809523f, 0.1111111111111111f, 0.126984126984127f, 0.1428571428571428f, 0.1587301587301587f, 0.1746031746031746f, 0.1904761904761905f, 0.2063492063492063f, 0.2222222222222222f, 0.2380952380952381f, 0.253968253968254f, 0.2698412698412698f, 0.2857142857142857f, 0.3015873015873016f, 0.3174603174603174f, 0.3333333333333333f, 0.3492063492063492f, 0.3650793650793651f, 0.3809523809523809f, 0.3968253968253968f, 0.4126984126984127f, 0.4285714285714285f, 0.4444444444444444f, 0.4603174603174603f, 0.4761904761904762f, 0.492063492063492f, 0.5079365079365079f, 0.5238095238095238f, 0.5396825396825397f, 0.5555555555555556f, 0.5714285714285714f, 0.5873015873015873f, 0.6031746031746031f, 0.6190476190476191f, 0.6349206349206349f, 0.6507936507936508f, 0.6666666666666666f, 0.6825396825396826f, 0.6984126984126984f, 0.7142857142857143f, 0.7301587301587301f, 0.746031746031746f, 0.7619047619047619f, 0.7777777777777778f, 0.7936507936507936f, 0.8095238095238095f, 0.8253968253968254f, 0.8412698412698413f, 0.8571428571428571f, 0.873015873015873f, 0.8888888888888888f, 0.9047619047619048f, 0.9206349206349206f, 0.9365079365079365f, 0.9523809523809523f, 0.9682539682539683f, 0.9841269841269841f, 1}; float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, @@ -211,9 +211,9 @@ namespace colormap } void init(int n) { - float r[] = { 0, 0.01388888888888889, 0.02777777777777778, 0.04166666666666666, 0.05555555555555555, 0.06944444444444445, 0.08333333333333333, 0.09722222222222221, 0.1111111111111111, 0.125, 0.1388888888888889, 0.1527777777777778, 0.1666666666666667, 0.1805555555555556, 0.1944444444444444, 0.2083333333333333, 0.2222222222222222, 0.2361111111111111, 0.25, 0.2638888888888889, 0.2777777777777778, 0.2916666666666666, 0.3055555555555555, 0.3194444444444444, 0.3333333333333333, 0.3472222222222222, 0.3611111111111111, 0.375, 0.3888888888888888, 0.4027777777777777, 0.4166666666666666, 0.4305555555555555, 0.4444444444444444, 0.4583333333333333, 0.4722222222222222, 0.4861111111111112, 0.5, 0.5138888888888888, 0.5277777777777778, 0.5416666666666667, 0.5555555555555556, 0.5694444444444444, 0.5833333333333333, 0.5972222222222222, 0.611111111111111, 0.6249999999999999, 0.6388888888888888, 0.6527777777777778, 0.6726190476190474, 0.6944444444444442, 0.7162698412698412, 0.7380952380952381, 0.7599206349206349, 0.7817460317460316, 0.8035714285714286, 0.8253968253968254, 0.8472222222222221, 0.8690476190476188, 0.8908730158730158, 0.9126984126984128, 0.9345238095238095, 0.9563492063492063, 0.978174603174603, 1}; - float g[] = { 0, 0.01388888888888889, 0.02777777777777778, 0.04166666666666666, 0.05555555555555555, 0.06944444444444445, 0.08333333333333333, 0.09722222222222221, 0.1111111111111111, 0.125, 0.1388888888888889, 0.1527777777777778, 0.1666666666666667, 0.1805555555555556, 0.1944444444444444, 0.2083333333333333, 0.2222222222222222, 0.2361111111111111, 0.25, 0.2638888888888889, 0.2777777777777778, 0.2916666666666666, 0.3055555555555555, 0.3194444444444444, 0.3353174603174602, 0.3544973544973544, 0.3736772486772486, 0.3928571428571428, 0.412037037037037, 0.4312169312169312, 0.4503968253968254, 0.4695767195767195, 0.4887566137566137, 0.5079365079365078, 0.5271164021164021, 0.5462962962962963, 0.5654761904761904, 0.5846560846560845, 0.6038359788359787, 0.623015873015873, 0.6421957671957671, 0.6613756613756612, 0.6805555555555555, 0.6997354497354497, 0.7189153439153438, 0.7380952380952379, 0.7572751322751322, 0.7764550264550264, 0.7916666666666666, 0.8055555555555555, 0.8194444444444444, 0.8333333333333334, 0.8472222222222222, 0.861111111111111, 0.875, 0.8888888888888888, 0.9027777777777777, 0.9166666666666665, 0.9305555555555555, 0.9444444444444444, 0.9583333333333333, 0.9722222222222221, 0.986111111111111, 1}; - float b[] = { 0, 0.01917989417989418, 0.03835978835978836, 0.05753968253968253, 0.07671957671957672, 0.09589947089947089, 0.1150793650793651, 0.1342592592592592, 0.1534391534391534, 0.1726190476190476, 0.1917989417989418, 0.210978835978836, 0.2301587301587301, 0.2493386243386243, 0.2685185185185185, 0.2876984126984127, 0.3068783068783069, 0.326058201058201, 0.3452380952380952, 0.3644179894179894, 0.3835978835978835, 0.4027777777777777, 0.4219576719576719, 0.4411375661375661, 0.4583333333333333, 0.4722222222222222, 0.4861111111111111, 0.5, 0.5138888888888888, 0.5277777777777777, 0.5416666666666666, 0.5555555555555556, 0.5694444444444444, 0.5833333333333333, 0.5972222222222222, 0.6111111111111112, 0.625, 0.6388888888888888, 0.6527777777777778, 0.6666666666666667, 0.6805555555555556, 0.6944444444444444, 0.7083333333333333, 0.7222222222222222, 0.736111111111111, 0.7499999999999999, 0.7638888888888888, 0.7777777777777778, 0.7916666666666666, 0.8055555555555555, 0.8194444444444444, 0.8333333333333334, 0.8472222222222222, 0.861111111111111, 0.875, 0.8888888888888888, 0.9027777777777777, 0.9166666666666665, 0.9305555555555555, 0.9444444444444444, 0.9583333333333333, 0.9722222222222221, 0.986111111111111, 1}; + float r[] = { 0, 0.01388888888888889f, 0.02777777777777778f, 0.04166666666666666f, 0.05555555555555555f, 0.06944444444444445f, 0.08333333333333333f, 0.09722222222222221f, 0.1111111111111111f, 0.125f, 0.1388888888888889f, 0.1527777777777778f, 0.1666666666666667f, 0.1805555555555556f, 0.1944444444444444f, 0.2083333333333333f, 0.2222222222222222f, 0.2361111111111111f, 0.25f, 0.2638888888888889f, 0.2777777777777778f, 0.2916666666666666f, 0.3055555555555555f, 0.3194444444444444f, 0.3333333333333333f, 0.3472222222222222f, 0.3611111111111111f, 0.375f, 0.3888888888888888f, 0.4027777777777777f, 0.4166666666666666f, 0.4305555555555555f, 0.4444444444444444f, 0.4583333333333333f, 0.4722222222222222f, 0.4861111111111112f, 0.5f, 0.5138888888888888f, 0.5277777777777778f, 0.5416666666666667f, 0.5555555555555556f, 0.5694444444444444f, 0.5833333333333333f, 0.5972222222222222f, 0.611111111111111f, 0.6249999999999999f, 0.6388888888888888f, 0.6527777777777778f, 0.6726190476190474f, 0.6944444444444442f, 0.7162698412698412f, 0.7380952380952381f, 0.7599206349206349f, 0.7817460317460316f, 0.8035714285714286f, 0.8253968253968254f, 0.8472222222222221f, 0.8690476190476188f, 0.8908730158730158f, 0.9126984126984128f, 0.9345238095238095f, 0.9563492063492063f, 0.978174603174603f, 1}; + float g[] = { 0, 0.01388888888888889f, 0.02777777777777778f, 0.04166666666666666f, 0.05555555555555555f, 0.06944444444444445f, 0.08333333333333333f, 0.09722222222222221f, 0.1111111111111111f, 0.125f, 0.1388888888888889f, 0.1527777777777778f, 0.1666666666666667f, 0.1805555555555556f, 0.1944444444444444f, 0.2083333333333333f, 0.2222222222222222f, 0.2361111111111111f, 0.25f, 0.2638888888888889f, 0.2777777777777778f, 0.2916666666666666f, 0.3055555555555555f, 0.3194444444444444f, 0.3353174603174602f, 0.3544973544973544f, 0.3736772486772486f, 0.3928571428571428f, 0.412037037037037f, 0.4312169312169312f, 0.4503968253968254f, 0.4695767195767195f, 0.4887566137566137f, 0.5079365079365078f, 0.5271164021164021f, 0.5462962962962963f, 0.5654761904761904f, 0.5846560846560845f, 0.6038359788359787f, 0.623015873015873f, 0.6421957671957671f, 0.6613756613756612f, 0.6805555555555555f, 0.6997354497354497f, 0.7189153439153438f, 0.7380952380952379f, 0.7572751322751322f, 0.7764550264550264f, 0.7916666666666666f, 0.8055555555555555f, 0.8194444444444444f, 0.8333333333333334f, 0.8472222222222222f, 0.861111111111111f, 0.875f, 0.8888888888888888f, 0.9027777777777777f, 0.9166666666666665f, 0.9305555555555555f, 0.9444444444444444f, 0.9583333333333333f, 0.9722222222222221f, 0.986111111111111f, 1}; + float b[] = { 0, 0.01917989417989418f, 0.03835978835978836f, 0.05753968253968253f, 0.07671957671957672f, 0.09589947089947089f, 0.1150793650793651f, 0.1342592592592592f, 0.1534391534391534f, 0.1726190476190476f, 0.1917989417989418f, 0.210978835978836f, 0.2301587301587301f, 0.2493386243386243f, 0.2685185185185185f, 0.2876984126984127f, 0.3068783068783069f, 0.326058201058201f, 0.3452380952380952f, 0.3644179894179894f, 0.3835978835978835f, 0.4027777777777777f, 0.4219576719576719f, 0.4411375661375661f, 0.4583333333333333f, 0.4722222222222222f, 0.4861111111111111f, 0.5f, 0.5138888888888888f, 0.5277777777777777f, 0.5416666666666666f, 0.5555555555555556f, 0.5694444444444444f, 0.5833333333333333f, 0.5972222222222222f, 0.6111111111111112f, 0.625f, 0.6388888888888888f, 0.6527777777777778f, 0.6666666666666667f, 0.6805555555555556f, 0.6944444444444444f, 0.7083333333333333f, 0.7222222222222222f, 0.736111111111111f, 0.7499999999999999f, 0.7638888888888888f, 0.7777777777777778f, 0.7916666666666666f, 0.8055555555555555f, 0.8194444444444444f, 0.8333333333333334f, 0.8472222222222222f, 0.861111111111111f, 0.875f, 0.8888888888888888f, 0.9027777777777777f, 0.9166666666666665f, 0.9305555555555555f, 0.9444444444444444f, 0.9583333333333333f, 0.9722222222222221f, 0.986111111111111f, 1}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, Mat(64,1, CV_32FC1, r).clone(), // red @@ -241,9 +241,9 @@ namespace colormap // breakpoints Mat X = linspace(0,1,256); // define the basemap - float r[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00588235294117645,0.02156862745098032,0.03725490196078418,0.05294117647058827,0.06862745098039214,0.084313725490196,0.1000000000000001,0.115686274509804,0.1313725490196078,0.1470588235294117,0.1627450980392156,0.1784313725490196,0.1941176470588235,0.2098039215686274,0.2254901960784315,0.2411764705882353,0.2568627450980392,0.2725490196078431,0.2882352941176469,0.303921568627451,0.3196078431372549,0.3352941176470587,0.3509803921568628,0.3666666666666667,0.3823529411764706,0.3980392156862744,0.4137254901960783,0.4294117647058824,0.4450980392156862,0.4607843137254901,0.4764705882352942,0.4921568627450981,0.5078431372549019,0.5235294117647058,0.5392156862745097,0.5549019607843135,0.5705882352941174,0.5862745098039217,0.6019607843137256,0.6176470588235294,0.6333333333333333,0.6490196078431372,0.664705882352941,0.6803921568627449,0.6960784313725492,0.7117647058823531,0.7274509803921569,0.7431372549019608,0.7588235294117647,0.7745098039215685,0.7901960784313724,0.8058823529411763,0.8215686274509801,0.8372549019607844,0.8529411764705883,0.8686274509803922,0.884313725490196,0.8999999999999999,0.9156862745098038,0.9313725490196076,0.947058823529412,0.9627450980392158,0.9784313725490197,0.9941176470588236,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.9862745098039216,0.9705882352941178,0.9549019607843139,0.93921568627451,0.9235294117647062,0.9078431372549018,0.892156862745098,0.8764705882352941,0.8607843137254902,0.8450980392156864,0.8294117647058825,0.8137254901960786,0.7980392156862743,0.7823529411764705,0.7666666666666666,0.7509803921568627,0.7352941176470589,0.719607843137255,0.7039215686274511,0.6882352941176473,0.6725490196078434,0.6568627450980391,0.6411764705882352,0.6254901960784314,0.6098039215686275,0.5941176470588236,0.5784313725490198,0.5627450980392159,0.5470588235294116,0.5313725490196077,0.5156862745098039,0.5}; - float g[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001960784313725483,0.01764705882352935,0.03333333333333333,0.0490196078431373,0.06470588235294117,0.08039215686274503,0.09607843137254901,0.111764705882353,0.1274509803921569,0.1431372549019607,0.1588235294117647,0.1745098039215687,0.1901960784313725,0.2058823529411764,0.2215686274509804,0.2372549019607844,0.2529411764705882,0.2686274509803921,0.2843137254901961,0.3,0.3156862745098039,0.3313725490196078,0.3470588235294118,0.3627450980392157,0.3784313725490196,0.3941176470588235,0.4098039215686274,0.4254901960784314,0.4411764705882353,0.4568627450980391,0.4725490196078431,0.4882352941176471,0.503921568627451,0.5196078431372548,0.5352941176470587,0.5509803921568628,0.5666666666666667,0.5823529411764705,0.5980392156862746,0.6137254901960785,0.6294117647058823,0.6450980392156862,0.6607843137254901,0.6764705882352942,0.692156862745098,0.7078431372549019,0.723529411764706,0.7392156862745098,0.7549019607843137,0.7705882352941176,0.7862745098039214,0.8019607843137255,0.8176470588235294,0.8333333333333333,0.8490196078431373,0.8647058823529412,0.8803921568627451,0.8960784313725489,0.9117647058823528,0.9274509803921569,0.9431372549019608,0.9588235294117646,0.9745098039215687,0.9901960784313726,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.9901960784313726,0.9745098039215687,0.9588235294117649,0.943137254901961,0.9274509803921571,0.9117647058823528,0.8960784313725489,0.8803921568627451,0.8647058823529412,0.8490196078431373,0.8333333333333335,0.8176470588235296,0.8019607843137253,0.7862745098039214,0.7705882352941176,0.7549019607843137,0.7392156862745098,0.723529411764706,0.7078431372549021,0.6921568627450982,0.6764705882352944,0.6607843137254901,0.6450980392156862,0.6294117647058823,0.6137254901960785,0.5980392156862746,0.5823529411764707,0.5666666666666669,0.5509803921568626,0.5352941176470587,0.5196078431372548,0.503921568627451,0.4882352941176471,0.4725490196078432,0.4568627450980394,0.4411764705882355,0.4254901960784316,0.4098039215686273,0.3941176470588235,0.3784313725490196,0.3627450980392157,0.3470588235294119,0.331372549019608,0.3156862745098041,0.2999999999999998,0.284313725490196,0.2686274509803921,0.2529411764705882,0.2372549019607844,0.2215686274509805,0.2058823529411766,0.1901960784313728,0.1745098039215689,0.1588235294117646,0.1431372549019607,0.1274509803921569,0.111764705882353,0.09607843137254912,0.08039215686274526,0.06470588235294139,0.04901960784313708,0.03333333333333321,0.01764705882352935,0.001960784313725483,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - float b[] = {0.5,0.5156862745098039,0.5313725490196078,0.5470588235294118,0.5627450980392157,0.5784313725490196,0.5941176470588235,0.6098039215686275,0.6254901960784314,0.6411764705882352,0.6568627450980392,0.6725490196078432,0.6882352941176471,0.7039215686274509,0.7196078431372549,0.7352941176470589,0.7509803921568627,0.7666666666666666,0.7823529411764706,0.7980392156862746,0.8137254901960784,0.8294117647058823,0.8450980392156863,0.8607843137254902,0.8764705882352941,0.892156862745098,0.907843137254902,0.9235294117647059,0.9392156862745098,0.9549019607843137,0.9705882352941176,0.9862745098039216,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.9941176470588236,0.9784313725490197,0.9627450980392158,0.9470588235294117,0.9313725490196079,0.915686274509804,0.8999999999999999,0.884313725490196,0.8686274509803922,0.8529411764705883,0.8372549019607844,0.8215686274509804,0.8058823529411765,0.7901960784313726,0.7745098039215685,0.7588235294117647,0.7431372549019608,0.7274509803921569,0.7117647058823531,0.696078431372549,0.6803921568627451,0.6647058823529413,0.6490196078431372,0.6333333333333333,0.6176470588235294,0.6019607843137256,0.5862745098039217,0.5705882352941176,0.5549019607843138,0.5392156862745099,0.5235294117647058,0.5078431372549019,0.4921568627450981,0.4764705882352942,0.4607843137254903,0.4450980392156865,0.4294117647058826,0.4137254901960783,0.3980392156862744,0.3823529411764706,0.3666666666666667,0.3509803921568628,0.335294117647059,0.3196078431372551,0.3039215686274508,0.2882352941176469,0.2725490196078431,0.2568627450980392,0.2411764705882353,0.2254901960784315,0.2098039215686276,0.1941176470588237,0.1784313725490199,0.1627450980392156,0.1470588235294117,0.1313725490196078,0.115686274509804,0.1000000000000001,0.08431372549019622,0.06862745098039236,0.05294117647058805,0.03725490196078418,0.02156862745098032,0.00588235294117645,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + float r[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00588235294117645f,0.02156862745098032f,0.03725490196078418f,0.05294117647058827f,0.06862745098039214f,0.084313725490196f,0.1000000000000001f,0.115686274509804f,0.1313725490196078f,0.1470588235294117f,0.1627450980392156f,0.1784313725490196f,0.1941176470588235f,0.2098039215686274f,0.2254901960784315f,0.2411764705882353f,0.2568627450980392f,0.2725490196078431f,0.2882352941176469f,0.303921568627451f,0.3196078431372549f,0.3352941176470587f,0.3509803921568628f,0.3666666666666667f,0.3823529411764706f,0.3980392156862744f,0.4137254901960783f,0.4294117647058824f,0.4450980392156862f,0.4607843137254901f,0.4764705882352942f,0.4921568627450981f,0.5078431372549019f,0.5235294117647058f,0.5392156862745097f,0.5549019607843135f,0.5705882352941174f,0.5862745098039217f,0.6019607843137256f,0.6176470588235294f,0.6333333333333333f,0.6490196078431372f,0.664705882352941f,0.6803921568627449f,0.6960784313725492f,0.7117647058823531f,0.7274509803921569f,0.7431372549019608f,0.7588235294117647f,0.7745098039215685f,0.7901960784313724f,0.8058823529411763f,0.8215686274509801f,0.8372549019607844f,0.8529411764705883f,0.8686274509803922f,0.884313725490196f,0.8999999999999999f,0.9156862745098038f,0.9313725490196076f,0.947058823529412f,0.9627450980392158f,0.9784313725490197f,0.9941176470588236f,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.9862745098039216f,0.9705882352941178f,0.9549019607843139f,0.93921568627451f,0.9235294117647062f,0.9078431372549018f,0.892156862745098f,0.8764705882352941f,0.8607843137254902f,0.8450980392156864f,0.8294117647058825f,0.8137254901960786f,0.7980392156862743f,0.7823529411764705f,0.7666666666666666f,0.7509803921568627f,0.7352941176470589f,0.719607843137255f,0.7039215686274511f,0.6882352941176473f,0.6725490196078434f,0.6568627450980391f,0.6411764705882352f,0.6254901960784314f,0.6098039215686275f,0.5941176470588236f,0.5784313725490198f,0.5627450980392159f,0.5470588235294116f,0.5313725490196077f,0.5156862745098039f,0.5f}; + float g[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001960784313725483f,0.01764705882352935f,0.03333333333333333f,0.0490196078431373f,0.06470588235294117f,0.08039215686274503f,0.09607843137254901f,0.111764705882353f,0.1274509803921569f,0.1431372549019607f,0.1588235294117647f,0.1745098039215687f,0.1901960784313725f,0.2058823529411764f,0.2215686274509804f,0.2372549019607844f,0.2529411764705882f,0.2686274509803921f,0.2843137254901961f,0.3f,0.3156862745098039f,0.3313725490196078f,0.3470588235294118f,0.3627450980392157f,0.3784313725490196f,0.3941176470588235f,0.4098039215686274f,0.4254901960784314f,0.4411764705882353f,0.4568627450980391f,0.4725490196078431f,0.4882352941176471f,0.503921568627451f,0.5196078431372548f,0.5352941176470587f,0.5509803921568628f,0.5666666666666667f,0.5823529411764705f,0.5980392156862746f,0.6137254901960785f,0.6294117647058823f,0.6450980392156862f,0.6607843137254901f,0.6764705882352942f,0.692156862745098f,0.7078431372549019f,0.723529411764706f,0.7392156862745098f,0.7549019607843137f,0.7705882352941176f,0.7862745098039214f,0.8019607843137255f,0.8176470588235294f,0.8333333333333333f,0.8490196078431373f,0.8647058823529412f,0.8803921568627451f,0.8960784313725489f,0.9117647058823528f,0.9274509803921569f,0.9431372549019608f,0.9588235294117646f,0.9745098039215687f,0.9901960784313726f,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.9901960784313726f,0.9745098039215687f,0.9588235294117649f,0.943137254901961f,0.9274509803921571f,0.9117647058823528f,0.8960784313725489f,0.8803921568627451f,0.8647058823529412f,0.8490196078431373f,0.8333333333333335f,0.8176470588235296f,0.8019607843137253f,0.7862745098039214f,0.7705882352941176f,0.7549019607843137f,0.7392156862745098f,0.723529411764706f,0.7078431372549021f,0.6921568627450982f,0.6764705882352944f,0.6607843137254901f,0.6450980392156862f,0.6294117647058823f,0.6137254901960785f,0.5980392156862746f,0.5823529411764707f,0.5666666666666669f,0.5509803921568626f,0.5352941176470587f,0.5196078431372548f,0.503921568627451f,0.4882352941176471f,0.4725490196078432f,0.4568627450980394f,0.4411764705882355f,0.4254901960784316f,0.4098039215686273f,0.3941176470588235f,0.3784313725490196f,0.3627450980392157f,0.3470588235294119f,0.331372549019608f,0.3156862745098041f,0.2999999999999998f,0.284313725490196f,0.2686274509803921f,0.2529411764705882f,0.2372549019607844f,0.2215686274509805f,0.2058823529411766f,0.1901960784313728f,0.1745098039215689f,0.1588235294117646f,0.1431372549019607f,0.1274509803921569f,0.111764705882353f,0.09607843137254912f,0.08039215686274526f,0.06470588235294139f,0.04901960784313708f,0.03333333333333321f,0.01764705882352935f,0.001960784313725483f,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + float b[] = {0.5f,0.5156862745098039f,0.5313725490196078f,0.5470588235294118f,0.5627450980392157f,0.5784313725490196f,0.5941176470588235f,0.6098039215686275f,0.6254901960784314f,0.6411764705882352f,0.6568627450980392f,0.6725490196078432f,0.6882352941176471f,0.7039215686274509f,0.7196078431372549f,0.7352941176470589f,0.7509803921568627f,0.7666666666666666f,0.7823529411764706f,0.7980392156862746f,0.8137254901960784f,0.8294117647058823f,0.8450980392156863f,0.8607843137254902f,0.8764705882352941f,0.892156862745098f,0.907843137254902f,0.9235294117647059f,0.9392156862745098f,0.9549019607843137f,0.9705882352941176f,0.9862745098039216f,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.9941176470588236f,0.9784313725490197f,0.9627450980392158f,0.9470588235294117f,0.9313725490196079f,0.915686274509804f,0.8999999999999999f,0.884313725490196f,0.8686274509803922f,0.8529411764705883f,0.8372549019607844f,0.8215686274509804f,0.8058823529411765f,0.7901960784313726f,0.7745098039215685f,0.7588235294117647f,0.7431372549019608f,0.7274509803921569f,0.7117647058823531f,0.696078431372549f,0.6803921568627451f,0.6647058823529413f,0.6490196078431372f,0.6333333333333333f,0.6176470588235294f,0.6019607843137256f,0.5862745098039217f,0.5705882352941176f,0.5549019607843138f,0.5392156862745099f,0.5235294117647058f,0.5078431372549019f,0.4921568627450981f,0.4764705882352942f,0.4607843137254903f,0.4450980392156865f,0.4294117647058826f,0.4137254901960783f,0.3980392156862744f,0.3823529411764706f,0.3666666666666667f,0.3509803921568628f,0.335294117647059f,0.3196078431372551f,0.3039215686274508f,0.2882352941176469f,0.2725490196078431f,0.2568627450980392f,0.2411764705882353f,0.2254901960784315f,0.2098039215686276f,0.1941176470588237f,0.1784313725490199f,0.1627450980392156f,0.1470588235294117f,0.1313725490196078f,0.115686274509804f,0.1000000000000001f,0.08431372549019622f,0.06862745098039236f,0.05294117647058805f,0.03725490196078418f,0.02156862745098032f,0.00588235294117645f,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // now build lookup table this->_lut = ColorMap::linear_colormap(X, Mat(256,1, CV_32FC1, r).clone(), // red @@ -265,9 +265,9 @@ namespace colormap } void init(int n) { - float r[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; - float g[] = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}; - float b[] = {1.0, 0.95, 0.9, 0.85, 0.8, 0.75, 0.7, 0.65, 0.6, 0.55, 0.5}; + float r[] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; + float g[] = {0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f,}; + float b[] = {1.0, 0.95f, 0.9f, 0.85f, 0.8f, 0.75f, 0.7f, 0.65f, 0.6f, 0.55f, 0.5f}; Mat X = linspace(0,1,11); this->_lut = ColorMap::linear_colormap(X, Mat(11,1, CV_32FC1, r).clone(), // red @@ -289,9 +289,9 @@ namespace colormap } void init(int n) { - float r[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9365079365079367, 0.8571428571428572, 0.7777777777777777, 0.6984126984126986, 0.6190476190476191, 0.53968253968254, 0.4603174603174605, 0.3809523809523814, 0.3015873015873018, 0.2222222222222223, 0.1428571428571432, 0.06349206349206415, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.03174603174603208, 0.08465608465608465, 0.1375661375661377, 0.1904761904761907, 0.2433862433862437, 0.2962962962962963, 0.3492063492063493, 0.4021164021164023, 0.4550264550264553, 0.5079365079365079, 0.5608465608465609, 0.6137566137566139, 0.666666666666667}; - float g[] = { 0, 0.03968253968253968, 0.07936507936507936, 0.119047619047619, 0.1587301587301587, 0.1984126984126984, 0.2380952380952381, 0.2777777777777778, 0.3174603174603174, 0.3571428571428571, 0.3968253968253968, 0.4365079365079365, 0.4761904761904762, 0.5158730158730158, 0.5555555555555556, 0.5952380952380952, 0.6349206349206349, 0.6746031746031745, 0.7142857142857142, 0.753968253968254, 0.7936507936507936, 0.8333333333333333, 0.873015873015873, 0.9126984126984127, 0.9523809523809523, 0.992063492063492, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9841269841269842, 0.9047619047619047, 0.8253968253968256, 0.7460317460317465, 0.666666666666667, 0.587301587301587, 0.5079365079365079, 0.4285714285714288, 0.3492063492063493, 0.2698412698412698, 0.1904761904761907, 0.1111111111111116, 0.03174603174603208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.01587301587301582, 0.09523809523809534, 0.1746031746031744, 0.2539682539682535, 0.333333333333333, 0.412698412698413, 0.4920634920634921, 0.5714285714285712, 0.6507936507936507, 0.7301587301587302, 0.8095238095238093, 0.8888888888888884, 0.9682539682539679, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + float r[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9365079365079367f, 0.8571428571428572f, 0.7777777777777777f, 0.6984126984126986f, 0.6190476190476191f, 0.53968253968254f, 0.4603174603174605f, 0.3809523809523814f, 0.3015873015873018f, 0.2222222222222223f, 0.1428571428571432f, 0.06349206349206415f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.03174603174603208f, 0.08465608465608465f, 0.1375661375661377f, 0.1904761904761907f, 0.2433862433862437f, 0.2962962962962963f, 0.3492063492063493f, 0.4021164021164023f, 0.4550264550264553f, 0.5079365079365079f, 0.5608465608465609f, 0.6137566137566139f, 0.666666666666667f}; + float g[] = { 0, 0.03968253968253968f, 0.07936507936507936f, 0.119047619047619f, 0.1587301587301587f, 0.1984126984126984f, 0.2380952380952381f, 0.2777777777777778f, 0.3174603174603174f, 0.3571428571428571f, 0.3968253968253968f, 0.4365079365079365f, 0.4761904761904762f, 0.5158730158730158f, 0.5555555555555556f, 0.5952380952380952f, 0.6349206349206349f, 0.6746031746031745f, 0.7142857142857142f, 0.753968253968254f, 0.7936507936507936f, 0.8333333333333333f, 0.873015873015873f, 0.9126984126984127f, 0.9523809523809523f, 0.992063492063492f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9841269841269842f, 0.9047619047619047f, 0.8253968253968256f, 0.7460317460317465f, 0.666666666666667f, 0.587301587301587f, 0.5079365079365079f, 0.4285714285714288f, 0.3492063492063493f, 0.2698412698412698f, 0.1904761904761907f, 0.1111111111111116f, 0.03174603174603208f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.01587301587301582f, 0.09523809523809534f, 0.1746031746031744f, 0.2539682539682535f, 0.333333333333333f, 0.412698412698413f, 0.4920634920634921f, 0.5714285714285712f, 0.6507936507936507f, 0.7301587301587302f, 0.8095238095238093f, 0.8888888888888884f, 0.9682539682539679f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, Mat(64,1, CV_32FC1, r).clone(), // red @@ -313,9 +313,9 @@ namespace colormap } void init(int n) { - float r[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.04761904761904762, 0.09523809523809523, 0.1428571428571428, 0.1904761904761905, 0.2380952380952381, 0.2857142857142857, 0.3333333333333333, 0.3809523809523809, 0.4285714285714285, 0.4761904761904762, 0.5238095238095238, 0.5714285714285714, 0.6190476190476191, 0.6666666666666666, 0.7142857142857143, 0.7619047619047619, 0.8095238095238095, 0.8571428571428571, 0.9047619047619048, 0.9523809523809523, 1}; - float g[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.02380952380952381, 0.04761904761904762, 0.07142857142857142, 0.09523809523809523, 0.119047619047619, 0.1428571428571428, 0.1666666666666667, 0.1904761904761905, 0.2142857142857143, 0.2380952380952381, 0.2619047619047619, 0.2857142857142857, 0.3095238095238095, 0.3333333333333333, 0.3571428571428572, 0.3809523809523809, 0.4047619047619048, 0.4285714285714285, 0.4523809523809524, 0.4761904761904762, 0.5, 0.5238095238095238, 0.5476190476190477, 0.5714285714285714, 0.5952380952380952, 0.6190476190476191, 0.6428571428571429, 0.6666666666666666, 0.6904761904761905, 0.7142857142857143, 0.7380952380952381, 0.7619047619047619, 0.7857142857142857, 0.8095238095238095, 0.8333333333333334, 0.8571428571428571, 0.8809523809523809, 0.9047619047619048, 0.9285714285714286, 0.9523809523809523, 0.9761904761904762, 1}; - float b[] = { 0, 0.01587301587301587, 0.03174603174603174, 0.04761904761904762, 0.06349206349206349, 0.07936507936507936, 0.09523809523809523, 0.1111111111111111, 0.126984126984127, 0.1428571428571428, 0.1587301587301587, 0.1746031746031746, 0.1904761904761905, 0.2063492063492063, 0.2222222222222222, 0.2380952380952381, 0.253968253968254, 0.2698412698412698, 0.2857142857142857, 0.3015873015873016, 0.3174603174603174, 0.3333333333333333, 0.3492063492063492, 0.3650793650793651, 0.3809523809523809, 0.3968253968253968, 0.4126984126984127, 0.4285714285714285, 0.4444444444444444, 0.4603174603174603, 0.4761904761904762, 0.492063492063492, 0.5079365079365079, 0.5238095238095238, 0.5396825396825397, 0.5555555555555556, 0.5714285714285714, 0.5873015873015873, 0.6031746031746031, 0.6190476190476191, 0.6349206349206349, 0.6507936507936508, 0.6666666666666666, 0.6825396825396826, 0.6984126984126984, 0.7142857142857143, 0.7301587301587301, 0.746031746031746, 0.7619047619047619, 0.7777777777777778, 0.7936507936507936, 0.8095238095238095, 0.8253968253968254, 0.8412698412698413, 0.8571428571428571, 0.873015873015873, 0.8888888888888888, 0.9047619047619048, 0.9206349206349206, 0.9365079365079365, 0.9523809523809523, 0.9682539682539683, 0.9841269841269841, 1}; + float r[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.04761904761904762f, 0.09523809523809523f, 0.1428571428571428f, 0.1904761904761905f, 0.2380952380952381f, 0.2857142857142857f, 0.3333333333333333f, 0.3809523809523809f, 0.4285714285714285f, 0.4761904761904762f, 0.5238095238095238f, 0.5714285714285714f, 0.6190476190476191f, 0.6666666666666666f, 0.7142857142857143f, 0.7619047619047619f, 0.8095238095238095f, 0.8571428571428571f, 0.9047619047619048f, 0.9523809523809523f, 1}; + float g[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.02380952380952381f, 0.04761904761904762f, 0.07142857142857142f, 0.09523809523809523f, 0.119047619047619f, 0.1428571428571428f, 0.1666666666666667f, 0.1904761904761905f, 0.2142857142857143f, 0.2380952380952381f, 0.2619047619047619f, 0.2857142857142857f, 0.3095238095238095f, 0.3333333333333333f, 0.3571428571428572f, 0.3809523809523809f, 0.4047619047619048f, 0.4285714285714285f, 0.4523809523809524f, 0.4761904761904762f, 0.5f, 0.5238095238095238f, 0.5476190476190477f, 0.5714285714285714f, 0.5952380952380952f, 0.6190476190476191f, 0.6428571428571429f, 0.6666666666666666f, 0.6904761904761905f, 0.7142857142857143f, 0.7380952380952381f, 0.7619047619047619f, 0.7857142857142857f, 0.8095238095238095f, 0.8333333333333334f, 0.8571428571428571f, 0.8809523809523809f, 0.9047619047619048f, 0.9285714285714286f, 0.9523809523809523f, 0.9761904761904762f, 1}; + float b[] = { 0, 0.01587301587301587f, 0.03174603174603174f, 0.04761904761904762f, 0.06349206349206349f, 0.07936507936507936f, 0.09523809523809523f, 0.1111111111111111f, 0.126984126984127f, 0.1428571428571428f, 0.1587301587301587f, 0.1746031746031746f, 0.1904761904761905f, 0.2063492063492063f, 0.2222222222222222f, 0.2380952380952381f, 0.253968253968254f, 0.2698412698412698f, 0.2857142857142857f, 0.3015873015873016f, 0.3174603174603174f, 0.3333333333333333f, 0.3492063492063492f, 0.3650793650793651f, 0.3809523809523809f, 0.3968253968253968f, 0.4126984126984127f, 0.4285714285714285f, 0.4444444444444444f, 0.4603174603174603f, 0.4761904761904762f, 0.492063492063492f, 0.5079365079365079f, 0.5238095238095238f, 0.5396825396825397f, 0.5555555555555556f, 0.5714285714285714f, 0.5873015873015873f, 0.6031746031746031f, 0.6190476190476191f, 0.6349206349206349f, 0.6507936507936508f, 0.6666666666666666f, 0.6825396825396826f, 0.6984126984126984f, 0.7142857142857143f, 0.7301587301587301f, 0.746031746031746f, 0.7619047619047619f, 0.7777777777777778f, 0.7936507936507936f, 0.8095238095238095f, 0.8253968253968254f, 0.8412698412698413f, 0.8571428571428571f, 0.873015873015873f, 0.8888888888888888f, 0.9047619047619048f, 0.9206349206349206f, 0.9365079365079365f, 0.9523809523809523f, 0.9682539682539683f, 0.9841269841269841f, 1}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, Mat(64,1, CV_32FC1, r).clone(), // red @@ -337,9 +337,9 @@ namespace colormap } void init(int n) { - float r[] = { 0, 0.01587301587301587, 0.03174603174603174, 0.04761904761904762, 0.06349206349206349, 0.07936507936507936, 0.09523809523809523, 0.1111111111111111, 0.126984126984127, 0.1428571428571428, 0.1587301587301587, 0.1746031746031746, 0.1904761904761905, 0.2063492063492063, 0.2222222222222222, 0.2380952380952381, 0.253968253968254, 0.2698412698412698, 0.2857142857142857, 0.3015873015873016, 0.3174603174603174, 0.3333333333333333, 0.3492063492063492, 0.3650793650793651, 0.3809523809523809, 0.3968253968253968, 0.4126984126984127, 0.4285714285714285, 0.4444444444444444, 0.4603174603174603, 0.4761904761904762, 0.492063492063492, 0.5079365079365079, 0.5238095238095238, 0.5396825396825397, 0.5555555555555556, 0.5714285714285714, 0.5873015873015873, 0.6031746031746031, 0.6190476190476191, 0.6349206349206349, 0.6507936507936508, 0.6666666666666666, 0.6825396825396826, 0.6984126984126984, 0.7142857142857143, 0.7301587301587301, 0.746031746031746, 0.7619047619047619, 0.7777777777777778, 0.7936507936507936, 0.8095238095238095, 0.8253968253968254, 0.8412698412698413, 0.8571428571428571, 0.873015873015873, 0.8888888888888888, 0.9047619047619048, 0.9206349206349206, 0.9365079365079365, 0.9523809523809523, 0.9682539682539683, 0.9841269841269841, 1}; - float g[] = { 0.5, 0.5079365079365079, 0.5158730158730158, 0.5238095238095238, 0.5317460317460317, 0.5396825396825397, 0.5476190476190477, 0.5555555555555556, 0.5634920634920635, 0.5714285714285714, 0.5793650793650793, 0.5873015873015873, 0.5952380952380952, 0.6031746031746031, 0.6111111111111112, 0.6190476190476191, 0.626984126984127, 0.6349206349206349, 0.6428571428571428, 0.6507936507936508, 0.6587301587301587, 0.6666666666666666, 0.6746031746031746, 0.6825396825396826, 0.6904761904761905, 0.6984126984126984, 0.7063492063492063, 0.7142857142857143, 0.7222222222222222, 0.7301587301587301, 0.7380952380952381, 0.746031746031746, 0.753968253968254, 0.7619047619047619, 0.7698412698412698, 0.7777777777777778, 0.7857142857142857, 0.7936507936507937, 0.8015873015873016, 0.8095238095238095, 0.8174603174603174, 0.8253968253968254, 0.8333333333333333, 0.8412698412698413, 0.8492063492063492, 0.8571428571428572, 0.8650793650793651, 0.873015873015873, 0.8809523809523809, 0.8888888888888888, 0.8968253968253967, 0.9047619047619048, 0.9126984126984127, 0.9206349206349207, 0.9285714285714286, 0.9365079365079365, 0.9444444444444444, 0.9523809523809523, 0.9603174603174602, 0.9682539682539683, 0.9761904761904762, 0.9841269841269842, 0.9920634920634921, 1}; - float b[] = { 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4}; + float r[] = { 0, 0.01587301587301587f, 0.03174603174603174f, 0.04761904761904762f, 0.06349206349206349f, 0.07936507936507936f, 0.09523809523809523f, 0.1111111111111111f, 0.126984126984127f, 0.1428571428571428f, 0.1587301587301587f, 0.1746031746031746f, 0.1904761904761905f, 0.2063492063492063f, 0.2222222222222222f, 0.2380952380952381f, 0.253968253968254f, 0.2698412698412698f, 0.2857142857142857f, 0.3015873015873016f, 0.3174603174603174f, 0.3333333333333333f, 0.3492063492063492f, 0.3650793650793651f, 0.3809523809523809f, 0.3968253968253968f, 0.4126984126984127f, 0.4285714285714285f, 0.4444444444444444f, 0.4603174603174603f, 0.4761904761904762f, 0.492063492063492f, 0.5079365079365079f, 0.5238095238095238f, 0.5396825396825397f, 0.5555555555555556f, 0.5714285714285714f, 0.5873015873015873f, 0.6031746031746031f, 0.6190476190476191f, 0.6349206349206349f, 0.6507936507936508f, 0.6666666666666666f, 0.6825396825396826f, 0.6984126984126984f, 0.7142857142857143f, 0.7301587301587301f, 0.746031746031746f, 0.7619047619047619f, 0.7777777777777778f, 0.7936507936507936f, 0.8095238095238095f, 0.8253968253968254f, 0.8412698412698413f, 0.8571428571428571f, 0.873015873015873f, 0.8888888888888888f, 0.9047619047619048f, 0.9206349206349206f, 0.9365079365079365f, 0.9523809523809523f, 0.9682539682539683f, 0.9841269841269841f, 1}; + float g[] = { 0.5f, 0.5079365079365079f, 0.5158730158730158f, 0.5238095238095238f, 0.5317460317460317f, 0.5396825396825397f, 0.5476190476190477f, 0.5555555555555556f, 0.5634920634920635f, 0.5714285714285714f, 0.5793650793650793f, 0.5873015873015873f, 0.5952380952380952f, 0.6031746031746031f, 0.6111111111111112f, 0.6190476190476191f, 0.626984126984127f, 0.6349206349206349f, 0.6428571428571428f, 0.6507936507936508f, 0.6587301587301587f, 0.6666666666666666f, 0.6746031746031746f, 0.6825396825396826f, 0.6904761904761905f, 0.6984126984126984f, 0.7063492063492063f, 0.7142857142857143f, 0.7222222222222222f, 0.7301587301587301f, 0.7380952380952381f, 0.746031746031746f, 0.753968253968254f, 0.7619047619047619f, 0.7698412698412698f, 0.7777777777777778f, 0.7857142857142857f, 0.7936507936507937f, 0.8015873015873016f, 0.8095238095238095f, 0.8174603174603174f, 0.8253968253968254f, 0.8333333333333333f, 0.8412698412698413f, 0.8492063492063492f, 0.8571428571428572f, 0.8650793650793651f, 0.873015873015873f, 0.8809523809523809f, 0.8888888888888888f, 0.8968253968253967f, 0.9047619047619048f, 0.9126984126984127f, 0.9206349206349207f, 0.9285714285714286f, 0.9365079365079365f, 0.9444444444444444f, 0.9523809523809523f, 0.9603174603174602f, 0.9682539682539683f, 0.9761904761904762f, 0.9841269841269842f, 0.9920634920634921f, 1}; + float b[] = { 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, Mat(64,1, CV_32FC1, r).clone(), // red @@ -362,8 +362,8 @@ namespace colormap void init(int n) { float r[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - float g[] = { 0, 0.01587301587301587, 0.03174603174603174, 0.04761904761904762, 0.06349206349206349, 0.07936507936507936, 0.09523809523809523, 0.1111111111111111, 0.126984126984127, 0.1428571428571428, 0.1587301587301587, 0.1746031746031746, 0.1904761904761905, 0.2063492063492063, 0.2222222222222222, 0.2380952380952381, 0.253968253968254, 0.2698412698412698, 0.2857142857142857, 0.3015873015873016, 0.3174603174603174, 0.3333333333333333, 0.3492063492063492, 0.3650793650793651, 0.3809523809523809, 0.3968253968253968, 0.4126984126984127, 0.4285714285714285, 0.4444444444444444, 0.4603174603174603, 0.4761904761904762, 0.492063492063492, 0.5079365079365079, 0.5238095238095238, 0.5396825396825397, 0.5555555555555556, 0.5714285714285714, 0.5873015873015873, 0.6031746031746031, 0.6190476190476191, 0.6349206349206349, 0.6507936507936508, 0.6666666666666666, 0.6825396825396826, 0.6984126984126984, 0.7142857142857143, 0.7301587301587301, 0.746031746031746, 0.7619047619047619, 0.7777777777777778, 0.7936507936507936, 0.8095238095238095, 0.8253968253968254, 0.8412698412698413, 0.8571428571428571, 0.873015873015873, 0.8888888888888888, 0.9047619047619048, 0.9206349206349206, 0.9365079365079365, 0.9523809523809523, 0.9682539682539683, 0.9841269841269841, 1}; - float b[] = { 1, 0.9841269841269842, 0.9682539682539683, 0.9523809523809523, 0.9365079365079365, 0.9206349206349207, 0.9047619047619048, 0.8888888888888888, 0.873015873015873, 0.8571428571428572, 0.8412698412698413, 0.8253968253968254, 0.8095238095238095, 0.7936507936507937, 0.7777777777777778, 0.7619047619047619, 0.746031746031746, 0.7301587301587302, 0.7142857142857143, 0.6984126984126984, 0.6825396825396826, 0.6666666666666667, 0.6507936507936508, 0.6349206349206349, 0.6190476190476191, 0.6031746031746033, 0.5873015873015873, 0.5714285714285714, 0.5555555555555556, 0.5396825396825398, 0.5238095238095238, 0.5079365079365079, 0.4920634920634921, 0.4761904761904762, 0.4603174603174603, 0.4444444444444444, 0.4285714285714286, 0.4126984126984127, 0.3968253968253969, 0.3809523809523809, 0.3650793650793651, 0.3492063492063492, 0.3333333333333334, 0.3174603174603174, 0.3015873015873016, 0.2857142857142857, 0.2698412698412699, 0.253968253968254, 0.2380952380952381, 0.2222222222222222, 0.2063492063492064, 0.1904761904761905, 0.1746031746031746, 0.1587301587301587, 0.1428571428571429, 0.126984126984127, 0.1111111111111112, 0.09523809523809523, 0.07936507936507942, 0.06349206349206349, 0.04761904761904767, 0.03174603174603174, 0.01587301587301593, 0}; + float g[] = { 0, 0.01587301587301587f, 0.03174603174603174f, 0.04761904761904762f, 0.06349206349206349f, 0.07936507936507936f, 0.09523809523809523f, 0.1111111111111111f, 0.126984126984127f, 0.1428571428571428f, 0.1587301587301587f, 0.1746031746031746f, 0.1904761904761905f, 0.2063492063492063f, 0.2222222222222222f, 0.2380952380952381f, 0.253968253968254f, 0.2698412698412698f, 0.2857142857142857f, 0.3015873015873016f, 0.3174603174603174f, 0.3333333333333333f, 0.3492063492063492f, 0.3650793650793651f, 0.3809523809523809f, 0.3968253968253968f, 0.4126984126984127f, 0.4285714285714285f, 0.4444444444444444f, 0.4603174603174603f, 0.4761904761904762f, 0.492063492063492f, 0.5079365079365079f, 0.5238095238095238f, 0.5396825396825397f, 0.5555555555555556f, 0.5714285714285714f, 0.5873015873015873f, 0.6031746031746031f, 0.6190476190476191f, 0.6349206349206349f, 0.6507936507936508f, 0.6666666666666666f, 0.6825396825396826f, 0.6984126984126984f, 0.7142857142857143f, 0.7301587301587301f, 0.746031746031746f, 0.7619047619047619f, 0.7777777777777778f, 0.7936507936507936f, 0.8095238095238095f, 0.8253968253968254f, 0.8412698412698413f, 0.8571428571428571f, 0.873015873015873f, 0.8888888888888888f, 0.9047619047619048f, 0.9206349206349206f, 0.9365079365079365f, 0.9523809523809523f, 0.9682539682539683f, 0.9841269841269841f, 1}; + float b[] = { 1, 0.9841269841269842f, 0.9682539682539683f, 0.9523809523809523f, 0.9365079365079365f, 0.9206349206349207f, 0.9047619047619048f, 0.8888888888888888f, 0.873015873015873f, 0.8571428571428572f, 0.8412698412698413f, 0.8253968253968254f, 0.8095238095238095f, 0.7936507936507937f, 0.7777777777777778f, 0.7619047619047619f, 0.746031746031746f, 0.7301587301587302f, 0.7142857142857143f, 0.6984126984126984f, 0.6825396825396826f, 0.6666666666666667f, 0.6507936507936508f, 0.6349206349206349f, 0.6190476190476191f, 0.6031746031746033f, 0.5873015873015873f, 0.5714285714285714f, 0.5555555555555556f, 0.5396825396825398f, 0.5238095238095238f, 0.5079365079365079f, 0.4920634920634921f, 0.4761904761904762f, 0.4603174603174603f, 0.4444444444444444f, 0.4285714285714286f, 0.4126984126984127f, 0.3968253968253969f, 0.3809523809523809f, 0.3650793650793651f, 0.3492063492063492f, 0.3333333333333334f, 0.3174603174603174f, 0.3015873015873016f, 0.2857142857142857f, 0.2698412698412699f, 0.253968253968254f, 0.2380952380952381f, 0.2222222222222222f, 0.2063492063492064f, 0.1904761904761905f, 0.1746031746031746f, 0.1587301587301587f, 0.1428571428571429f, 0.126984126984127f, 0.1111111111111112f, 0.09523809523809523f, 0.07936507936507942f, 0.06349206349206349f, 0.04761904761904767f, 0.03174603174603174f, 0.01587301587301593f, 0}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, Mat(64,1, CV_32FC1, r).clone(), // red @@ -385,8 +385,8 @@ namespace colormap } void init(int n) { - float r[] = { 0, 0.01587301587301587, 0.03174603174603174, 0.04761904761904762, 0.06349206349206349, 0.07936507936507936, 0.09523809523809523, 0.1111111111111111, 0.126984126984127, 0.1428571428571428, 0.1587301587301587, 0.1746031746031746, 0.1904761904761905, 0.2063492063492063, 0.2222222222222222, 0.2380952380952381, 0.253968253968254, 0.2698412698412698, 0.2857142857142857, 0.3015873015873016, 0.3174603174603174, 0.3333333333333333, 0.3492063492063492, 0.3650793650793651, 0.3809523809523809, 0.3968253968253968, 0.4126984126984127, 0.4285714285714285, 0.4444444444444444, 0.4603174603174603, 0.4761904761904762, 0.492063492063492, 0.5079365079365079, 0.5238095238095238, 0.5396825396825397, 0.5555555555555556, 0.5714285714285714, 0.5873015873015873, 0.6031746031746031, 0.6190476190476191, 0.6349206349206349, 0.6507936507936508, 0.6666666666666666, 0.6825396825396826, 0.6984126984126984, 0.7142857142857143, 0.7301587301587301, 0.746031746031746, 0.7619047619047619, 0.7777777777777778, 0.7936507936507936, 0.8095238095238095, 0.8253968253968254, 0.8412698412698413, 0.8571428571428571, 0.873015873015873, 0.8888888888888888, 0.9047619047619048, 0.9206349206349206, 0.9365079365079365, 0.9523809523809523, 0.9682539682539683, 0.9841269841269841, 1}; - float g[] = { 1, 0.9841269841269842, 0.9682539682539683, 0.9523809523809523, 0.9365079365079365, 0.9206349206349207, 0.9047619047619048, 0.8888888888888888, 0.873015873015873, 0.8571428571428572, 0.8412698412698413, 0.8253968253968254, 0.8095238095238095, 0.7936507936507937, 0.7777777777777778, 0.7619047619047619, 0.746031746031746, 0.7301587301587302, 0.7142857142857143, 0.6984126984126984, 0.6825396825396826, 0.6666666666666667, 0.6507936507936508, 0.6349206349206349, 0.6190476190476191, 0.6031746031746033, 0.5873015873015873, 0.5714285714285714, 0.5555555555555556, 0.5396825396825398, 0.5238095238095238, 0.5079365079365079, 0.4920634920634921, 0.4761904761904762, 0.4603174603174603, 0.4444444444444444, 0.4285714285714286, 0.4126984126984127, 0.3968253968253969, 0.3809523809523809, 0.3650793650793651, 0.3492063492063492, 0.3333333333333334, 0.3174603174603174, 0.3015873015873016, 0.2857142857142857, 0.2698412698412699, 0.253968253968254, 0.2380952380952381, 0.2222222222222222, 0.2063492063492064, 0.1904761904761905, 0.1746031746031746, 0.1587301587301587, 0.1428571428571429, 0.126984126984127, 0.1111111111111112, 0.09523809523809523, 0.07936507936507942, 0.06349206349206349, 0.04761904761904767, 0.03174603174603174, 0.01587301587301593, 0}; + float r[] = { 0, 0.01587301587301587f, 0.03174603174603174f, 0.04761904761904762f, 0.06349206349206349f, 0.07936507936507936f, 0.09523809523809523f, 0.1111111111111111f, 0.126984126984127f, 0.1428571428571428f, 0.1587301587301587f, 0.1746031746031746f, 0.1904761904761905f, 0.2063492063492063f, 0.2222222222222222f, 0.2380952380952381f, 0.253968253968254f, 0.2698412698412698f, 0.2857142857142857f, 0.3015873015873016f, 0.3174603174603174f, 0.3333333333333333f, 0.3492063492063492f, 0.3650793650793651f, 0.3809523809523809f, 0.3968253968253968f, 0.4126984126984127f, 0.4285714285714285f, 0.4444444444444444f, 0.4603174603174603f, 0.4761904761904762f, 0.492063492063492f, 0.5079365079365079f, 0.5238095238095238f, 0.5396825396825397f, 0.5555555555555556f, 0.5714285714285714f, 0.5873015873015873f, 0.6031746031746031f, 0.6190476190476191f, 0.6349206349206349f, 0.6507936507936508f, 0.6666666666666666f, 0.6825396825396826f, 0.6984126984126984f, 0.7142857142857143f, 0.7301587301587301f, 0.746031746031746f, 0.7619047619047619f, 0.7777777777777778f, 0.7936507936507936f, 0.8095238095238095f, 0.8253968253968254f, 0.8412698412698413f, 0.8571428571428571f, 0.873015873015873f, 0.8888888888888888f, 0.9047619047619048f, 0.9206349206349206f, 0.9365079365079365f, 0.9523809523809523f, 0.9682539682539683f, 0.9841269841269841f, 1}; + float g[] = { 1, 0.9841269841269842f, 0.9682539682539683f, 0.9523809523809523f, 0.9365079365079365f, 0.9206349206349207f, 0.9047619047619048f, 0.8888888888888888f, 0.873015873015873f, 0.8571428571428572f, 0.8412698412698413f, 0.8253968253968254f, 0.8095238095238095f, 0.7936507936507937f, 0.7777777777777778f, 0.7619047619047619f, 0.746031746031746f, 0.7301587301587302f, 0.7142857142857143f, 0.6984126984126984f, 0.6825396825396826f, 0.6666666666666667f, 0.6507936507936508f, 0.6349206349206349f, 0.6190476190476191f, 0.6031746031746033f, 0.5873015873015873f, 0.5714285714285714f, 0.5555555555555556f, 0.5396825396825398f, 0.5238095238095238f, 0.5079365079365079f, 0.4920634920634921f, 0.4761904761904762f, 0.4603174603174603f, 0.4444444444444444f, 0.4285714285714286f, 0.4126984126984127f, 0.3968253968253969f, 0.3809523809523809f, 0.3650793650793651f, 0.3492063492063492f, 0.3333333333333334f, 0.3174603174603174f, 0.3015873015873016f, 0.2857142857142857f, 0.2698412698412699f, 0.253968253968254f, 0.2380952380952381f, 0.2222222222222222f, 0.2063492063492064f, 0.1904761904761905f, 0.1746031746031746f, 0.1587301587301587f, 0.1428571428571429f, 0.126984126984127f, 0.1111111111111112f, 0.09523809523809523f, 0.07936507936507942f, 0.06349206349206349f, 0.04761904761904767f, 0.03174603174603174f, 0.01587301587301593f, 0}; float b[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, @@ -409,9 +409,9 @@ namespace colormap } void init(int n) { - float r[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9523809523809526, 0.8571428571428568, 0.7619047619047614, 0.6666666666666665, 0.5714285714285716, 0.4761904761904763, 0.3809523809523805, 0.2857142857142856, 0.1904761904761907, 0.0952380952380949, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.09523809523809557, 0.1904761904761905, 0.2857142857142854, 0.3809523809523809, 0.4761904761904765, 0.5714285714285714, 0.6666666666666663, 0.7619047619047619, 0.8571428571428574, 0.9523809523809523, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - float g[] = { 0, 0.09523809523809523, 0.1904761904761905, 0.2857142857142857, 0.3809523809523809, 0.4761904761904762, 0.5714285714285714, 0.6666666666666666, 0.7619047619047619, 0.8571428571428571, 0.9523809523809523, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9523809523809526, 0.8571428571428577, 0.7619047619047619, 0.6666666666666665, 0.5714285714285716, 0.4761904761904767, 0.3809523809523814, 0.2857142857142856, 0.1904761904761907, 0.09523809523809579, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.09523809523809523, 0.1904761904761905, 0.2857142857142857, 0.3809523809523809, 0.4761904761904762, 0.5714285714285714, 0.6666666666666666, 0.7619047619047619, 0.8571428571428571, 0.9523809523809523, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9523809523809526, 0.8571428571428577, 0.7619047619047614, 0.6666666666666665, 0.5714285714285716, 0.4761904761904767, 0.3809523809523805, 0.2857142857142856, 0.1904761904761907, 0.09523809523809579, 0}; + float r[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9523809523809526f, 0.8571428571428568f, 0.7619047619047614f, 0.6666666666666665f, 0.5714285714285716f, 0.4761904761904763f, 0.3809523809523805f, 0.2857142857142856f, 0.1904761904761907f, 0.0952380952380949f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.09523809523809557f, 0.1904761904761905f, 0.2857142857142854f, 0.3809523809523809f, 0.4761904761904765f, 0.5714285714285714f, 0.6666666666666663f, 0.7619047619047619f, 0.8571428571428574f, 0.9523809523809523f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + float g[] = { 0, 0.09523809523809523f, 0.1904761904761905f, 0.2857142857142857f, 0.3809523809523809f, 0.4761904761904762f, 0.5714285714285714f, 0.6666666666666666f, 0.7619047619047619f, 0.8571428571428571f, 0.9523809523809523f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9523809523809526f, 0.8571428571428577f, 0.7619047619047619f, 0.6666666666666665f, 0.5714285714285716f, 0.4761904761904767f, 0.3809523809523814f, 0.2857142857142856f, 0.1904761904761907f, 0.09523809523809579f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.09523809523809523f, 0.1904761904761905f, 0.2857142857142857f, 0.3809523809523809f, 0.4761904761904762f, 0.5714285714285714f, 0.6666666666666666f, 0.7619047619047619f, 0.8571428571428571f, 0.9523809523809523f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9523809523809526f, 0.8571428571428577f, 0.7619047619047614f, 0.6666666666666665f, 0.5714285714285716f, 0.4761904761904767f, 0.3809523809523805f, 0.2857142857142856f, 0.1904761904761907f, 0.09523809523809579f, 0}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, Mat(64,1, CV_32FC1, r).clone(), // red @@ -433,9 +433,9 @@ namespace colormap } void init(int n) { - float r[] = { 0, 0.1571348402636772, 0.2222222222222222, 0.2721655269759087, 0.3142696805273544, 0.3513641844631533, 0.3849001794597505, 0.415739709641549, 0.4444444444444444, 0.4714045207910317, 0.4969039949999532, 0.5211573066470477, 0.5443310539518174, 0.5665577237325317, 0.5879447357921312, 0.6085806194501846, 0.6285393610547089, 0.6478835438717, 0.6666666666666666, 0.6849348892187751, 0.7027283689263065, 0.7200822998230956, 0.7370277311900888, 0.753592220347252, 0.7663560447348133, 0.7732293307186413, 0.7800420555749596, 0.7867957924694432, 0.7934920476158722, 0.8001322641986387, 0.8067178260046388, 0.8132500607904444, 0.8197302434079591, 0.8261595987094034, 0.8325393042503717, 0.8388704928078611, 0.8451542547285166, 0.8513916401208816, 0.8575836609041332, 0.8637312927246217, 0.8698354767504924, 0.8758971213537393, 0.8819171036881968, 0.8878962711712378, 0.8938354428762595, 0.8997354108424372, 0.9055969413076769, 0.9114207758701963, 0.9172076325837248, 0.9229582069908971, 0.9286731730990523, 0.9343531843023135, 0.9399988742535192, 0.9456108576893002, 0.9511897312113418, 0.9567360740266436, 0.9622504486493763, 0.9677334015667416, 0.9731854638710686, 0.9786071518602129, 0.9839989676081821, 0.9893613995077727, 0.9946949227868761, 1}; - float g[] = { 0, 0.1028688999747279, 0.1454785934906616, 0.1781741612749496, 0.2057377999494559, 0.2300218531141181, 0.2519763153394848, 0.2721655269759087, 0.2909571869813232, 0.3086066999241838, 0.3253000243161777, 0.3411775438127727, 0.3563483225498992, 0.3708990935094579, 0.3849001794597505, 0.3984095364447979, 0.4114755998989117, 0.4241393401869012, 0.4364357804719847, 0.4483951394230328, 0.4600437062282361, 0.4714045207910317, 0.4824979096371639, 0.4933419132673033, 0.5091750772173156, 0.5328701692569688, 0.5555555555555556, 0.5773502691896257, 0.5983516452371671, 0.6186404847588913, 0.6382847385042254, 0.6573421981221795, 0.6758625033664688, 0.6938886664887108, 0.7114582486036499, 0.7286042804780002, 0.7453559924999299, 0.7617394000445604, 0.7777777777777778, 0.7934920476158723, 0.8089010988089465, 0.8240220541217402, 0.8388704928078611, 0.8534606386520677, 0.8678055195451838, 0.8819171036881968, 0.8958064164776166, 0.9094836413191612, 0.9172076325837248, 0.9229582069908971, 0.9286731730990523, 0.9343531843023135, 0.9399988742535192, 0.9456108576893002, 0.9511897312113418, 0.9567360740266436, 0.9622504486493763, 0.9677334015667416, 0.9731854638710686, 0.9786071518602129, 0.9839989676081821, 0.9893613995077727, 0.9946949227868761, 1}; - float b[] = { 0, 0.1028688999747279, 0.1454785934906616, 0.1781741612749496, 0.2057377999494559, 0.2300218531141181, 0.2519763153394848, 0.2721655269759087, 0.2909571869813232, 0.3086066999241838, 0.3253000243161777, 0.3411775438127727, 0.3563483225498992, 0.3708990935094579, 0.3849001794597505, 0.3984095364447979, 0.4114755998989117, 0.4241393401869012, 0.4364357804719847, 0.4483951394230328, 0.4600437062282361, 0.4714045207910317, 0.4824979096371639, 0.4933419132673033, 0.5039526306789697, 0.5143444998736397, 0.5245305283129621, 0.5345224838248488, 0.5443310539518174, 0.5539659798925444, 0.563436169819011, 0.5727497953228163, 0.5819143739626463, 0.5909368402852788, 0.5998236072282915, 0.6085806194501846, 0.6172133998483676, 0.6257270902992705, 0.6341264874742278, 0.642416074439621, 0.6506000486323554, 0.6586823467062358, 0.6666666666666666, 0.6745564876468501, 0.6823550876255453, 0.6900655593423541, 0.6976908246297114, 0.7052336473499384, 0.7237468644557459, 0.7453559924999298, 0.7663560447348133, 0.7867957924694432, 0.8067178260046388, 0.8261595987094034, 0.8451542547285166, 0.8637312927246217, 0.8819171036881968, 0.8997354108424372, 0.9172076325837248, 0.9343531843023135, 0.9511897312113418, 0.9677334015667416, 0.9839989676081821, 1}; + float r[] = { 0, 0.1571348402636772f, 0.2222222222222222f, 0.2721655269759087f, 0.3142696805273544f, 0.3513641844631533f, 0.3849001794597505f, 0.415739709641549f, 0.4444444444444444f, 0.4714045207910317f, 0.4969039949999532f, 0.5211573066470477f, 0.5443310539518174f, 0.5665577237325317f, 0.5879447357921312f, 0.6085806194501846f, 0.6285393610547089f, 0.6478835438717f, 0.6666666666666666f, 0.6849348892187751f, 0.7027283689263065f, 0.7200822998230956f, 0.7370277311900888f, 0.753592220347252f, 0.7663560447348133f, 0.7732293307186413f, 0.7800420555749596f, 0.7867957924694432f, 0.7934920476158722f, 0.8001322641986387f, 0.8067178260046388f, 0.8132500607904444f, 0.8197302434079591f, 0.8261595987094034f, 0.8325393042503717f, 0.8388704928078611f, 0.8451542547285166f, 0.8513916401208816f, 0.8575836609041332f, 0.8637312927246217f, 0.8698354767504924f, 0.8758971213537393f, 0.8819171036881968f, 0.8878962711712378f, 0.8938354428762595f, 0.8997354108424372f, 0.9055969413076769f, 0.9114207758701963f, 0.9172076325837248f, 0.9229582069908971f, 0.9286731730990523f, 0.9343531843023135f, 0.9399988742535192f, 0.9456108576893002f, 0.9511897312113418f, 0.9567360740266436f, 0.9622504486493763f, 0.9677334015667416f, 0.9731854638710686f, 0.9786071518602129f, 0.9839989676081821f, 0.9893613995077727f, 0.9946949227868761f, 1}; + float g[] = { 0, 0.1028688999747279f, 0.1454785934906616f, 0.1781741612749496f, 0.2057377999494559f, 0.2300218531141181f, 0.2519763153394848f, 0.2721655269759087f, 0.2909571869813232f, 0.3086066999241838f, 0.3253000243161777f, 0.3411775438127727f, 0.3563483225498992f, 0.3708990935094579f, 0.3849001794597505f, 0.3984095364447979f, 0.4114755998989117f, 0.4241393401869012f, 0.4364357804719847f, 0.4483951394230328f, 0.4600437062282361f, 0.4714045207910317f, 0.4824979096371639f, 0.4933419132673033f, 0.5091750772173156f, 0.5328701692569688f, 0.5555555555555556f, 0.5773502691896257f, 0.5983516452371671f, 0.6186404847588913f, 0.6382847385042254f, 0.6573421981221795f, 0.6758625033664688f, 0.6938886664887108f, 0.7114582486036499f, 0.7286042804780002f, 0.7453559924999299f, 0.7617394000445604f, 0.7777777777777778f, 0.7934920476158723f, 0.8089010988089465f, 0.8240220541217402f, 0.8388704928078611f, 0.8534606386520677f, 0.8678055195451838f, 0.8819171036881968f, 0.8958064164776166f, 0.9094836413191612f, 0.9172076325837248f, 0.9229582069908971f, 0.9286731730990523f, 0.9343531843023135f, 0.9399988742535192f, 0.9456108576893002f, 0.9511897312113418f, 0.9567360740266436f, 0.9622504486493763f, 0.9677334015667416f, 0.9731854638710686f, 0.9786071518602129f, 0.9839989676081821f, 0.9893613995077727f, 0.9946949227868761f, 1}; + float b[] = { 0, 0.1028688999747279f, 0.1454785934906616f, 0.1781741612749496f, 0.2057377999494559f, 0.2300218531141181f, 0.2519763153394848f, 0.2721655269759087f, 0.2909571869813232f, 0.3086066999241838f, 0.3253000243161777f, 0.3411775438127727f, 0.3563483225498992f, 0.3708990935094579f, 0.3849001794597505f, 0.3984095364447979f, 0.4114755998989117f, 0.4241393401869012f, 0.4364357804719847f, 0.4483951394230328f, 0.4600437062282361f, 0.4714045207910317f, 0.4824979096371639f, 0.4933419132673033f, 0.5039526306789697f, 0.5143444998736397f, 0.5245305283129621f, 0.5345224838248488f, 0.5443310539518174f, 0.5539659798925444f, 0.563436169819011f, 0.5727497953228163f, 0.5819143739626463f, 0.5909368402852788f, 0.5998236072282915f, 0.6085806194501846f, 0.6172133998483676f, 0.6257270902992705f, 0.6341264874742278f, 0.642416074439621f, 0.6506000486323554f, 0.6586823467062358f, 0.6666666666666666f, 0.6745564876468501f, 0.6823550876255453f, 0.6900655593423541f, 0.6976908246297114f, 0.7052336473499384f, 0.7237468644557459f, 0.7453559924999298f, 0.7663560447348133f, 0.7867957924694432f, 0.8067178260046388f, 0.8261595987094034f, 0.8451542547285166f, 0.8637312927246217f, 0.8819171036881968f, 0.8997354108424372f, 0.9172076325837248f, 0.9343531843023135f, 0.9511897312113418f, 0.9677334015667416f, 0.9839989676081821f, 1}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, Mat(64,1, CV_32FC1, r).clone(), // red @@ -457,9 +457,9 @@ namespace colormap } void init(int n) { - float r[] = { 0, 0.03968253968253968, 0.07936507936507936, 0.119047619047619, 0.1587301587301587, 0.1984126984126984, 0.2380952380952381, 0.2777777777777778, 0.3174603174603174, 0.3571428571428571, 0.3968253968253968, 0.4365079365079365, 0.4761904761904762, 0.5158730158730158, 0.5555555555555556, 0.5952380952380952, 0.6349206349206349, 0.6746031746031745, 0.7142857142857142, 0.753968253968254, 0.7936507936507936, 0.8333333333333333, 0.873015873015873, 0.9126984126984127, 0.9523809523809523, 0.992063492063492, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - float g[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.03174603174603163, 0.0714285714285714, 0.1111111111111112, 0.1507936507936507, 0.1904761904761905, 0.23015873015873, 0.2698412698412698, 0.3095238095238093, 0.3492063492063491, 0.3888888888888888, 0.4285714285714284, 0.4682539682539679, 0.5079365079365079, 0.5476190476190477, 0.5873015873015872, 0.6269841269841268, 0.6666666666666665, 0.7063492063492065, 0.746031746031746, 0.7857142857142856, 0.8253968253968254, 0.8650793650793651, 0.9047619047619047, 0.9444444444444442, 0.984126984126984, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.04761904761904745, 0.1269841269841265, 0.2063492063492056, 0.2857142857142856, 0.3650793650793656, 0.4444444444444446, 0.5238095238095237, 0.6031746031746028, 0.6825396825396828, 0.7619047619047619, 0.8412698412698409, 0.92063492063492, 1}; + float r[] = { 0, 0.03968253968253968f, 0.07936507936507936f, 0.119047619047619f, 0.1587301587301587f, 0.1984126984126984f, 0.2380952380952381f, 0.2777777777777778f, 0.3174603174603174f, 0.3571428571428571f, 0.3968253968253968f, 0.4365079365079365f, 0.4761904761904762f, 0.5158730158730158f, 0.5555555555555556f, 0.5952380952380952f, 0.6349206349206349f, 0.6746031746031745f, 0.7142857142857142f, 0.753968253968254f, 0.7936507936507936f, 0.8333333333333333f, 0.873015873015873f, 0.9126984126984127f, 0.9523809523809523f, 0.992063492063492f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + float g[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.03174603174603163f, 0.0714285714285714f, 0.1111111111111112f, 0.1507936507936507f, 0.1904761904761905f, 0.23015873015873f, 0.2698412698412698f, 0.3095238095238093f, 0.3492063492063491f, 0.3888888888888888f, 0.4285714285714284f, 0.4682539682539679f, 0.5079365079365079f, 0.5476190476190477f, 0.5873015873015872f, 0.6269841269841268f, 0.6666666666666665f, 0.7063492063492065f, 0.746031746031746f, 0.7857142857142856f, 0.8253968253968254f, 0.8650793650793651f, 0.9047619047619047f, 0.9444444444444442f, 0.984126984126984f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.04761904761904745f, 0.1269841269841265f, 0.2063492063492056f, 0.2857142857142856f, 0.3650793650793656f, 0.4444444444444446f, 0.5238095238095237f, 0.6031746031746028f, 0.6825396825396828f, 0.7619047619047619f, 0.8412698412698409f, 0.92063492063492f, 1}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, Mat(64,1, CV_32FC1, r).clone(), // red @@ -481,9 +481,9 @@ namespace colormap } void init(int n) { - float r[] = { 0.2078, 0.0118, 0.0784, 0.0235, 0.2196, 0.5725, 0.8510, 0.9882, 0.9765 }; - float g[] = { 0.1647, 0.3882, 0.5216, 0.6549, 0.7255, 0.7490, 0.7294, 0.8078, 0.9843 }; - float b[] = { 0.5294, 0.8824, 0.8314, 0.7765, 0.6196, 0.4510, 0.3373, 0.1804, 0.0549 }; + float r[] = { 0.2078f, 0.0118f, 0.0784f, 0.0235f, 0.2196f, 0.5725f, 0.8510f, 0.9882f, 0.9765f }; + float g[] = { 0.1647f, 0.3882f, 0.5216f, 0.6549f, 0.7255f, 0.7490f, 0.7294f, 0.8078f, 0.9843f }; + float b[] = { 0.5294f, 0.8824f, 0.8314f, 0.7765f, 0.6196f, 0.4510f, 0.3373f, 0.1804f, 0.0549f }; Mat X = linspace(0, 1, 9); this->_lut = ColorMap::linear_colormap(X, Mat(9, 1, CV_32FC1, r).clone(), // red diff --git a/modules/imgproc/src/corner.cpp b/modules/imgproc/src/corner.cpp index f4b6854b7..946625eb0 100644 --- a/modules/imgproc/src/corner.cpp +++ b/modules/imgproc/src/corner.cpp @@ -394,7 +394,7 @@ static bool extractCovData(InputArray _src, UMat & Dx, UMat & Dy, int depth, Dx.create(src.size(), CV_32FC1); Dy.create(src.size(), CV_32FC1); - size_t localsize[2] = { sobel_lsz, sobel_lsz }; + size_t localsize[2] = { (size_t)sobel_lsz, (size_t)sobel_lsz }; size_t globalsize[2] = { localsize[0] * (1 + (src.cols - 1) / localsize[0]), localsize[1] * (1 + (src.rows - 1) / localsize[1]) }; @@ -515,7 +515,7 @@ static bool ocl_preCornerDetect( InputArray _src, OutputArray _dst, int ksize, i ocl::KernelArg::ReadOnlyNoSize(D2x), ocl::KernelArg::ReadOnlyNoSize(D2y), ocl::KernelArg::ReadOnlyNoSize(Dxy), ocl::KernelArg::WriteOnly(dst), (float)factor); - size_t globalsize[2] = { dst.cols, dst.rows }; + size_t globalsize[2] = { (size_t)dst.cols, (size_t)dst.rows }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index 2fcdabeaa..d41b8ae53 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -702,7 +702,7 @@ static bool ocl_Laplacian5(InputArray _src, OutputArray _dst, else k.args(d2xarg, d2yarg, dstarg, iscale, idelta); - size_t globalsize[] = { dst.cols * cn / kercn, dst.rows }; + size_t globalsize[] = { (size_t)dst.cols * cn / kercn, (size_t)dst.rows }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/imgproc/src/featureselect.cpp b/modules/imgproc/src/featureselect.cpp index e51859e01..3d5af6330 100644 --- a/modules/imgproc/src/featureselect.cpp +++ b/modules/imgproc/src/featureselect.cpp @@ -156,7 +156,7 @@ static bool ocl_goodFeaturesToTrack( InputArray _image, OutputArray _corners, thresholdarg, (int)possibleCornersCount); } - size_t globalsize[2] = { eig.cols - 2, eig.rows - 2 }; + size_t globalsize[2] = { (size_t)eig.cols - 2, (size_t)eig.rows - 2 }; if (!k.run(2, globalsize, NULL, false)) return false; diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 5eec45f9f..f78296ced 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -4031,7 +4031,7 @@ static bool ocl_filter2D( InputArray _src, OutputArray _dst, int ddepth, cv::Mat kernelMat = _kernel.getMat(); cv::Size sz = _src.size(), wholeSize; - size_t globalsize[2] = { sz.width, sz.height }; + size_t globalsize[2] = { (size_t)sz.width, (size_t)sz.height }; size_t localsize_general[2] = {0, 1}; size_t* localsize = NULL; diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index 00fce77ea..7e181684c 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -2220,7 +2220,7 @@ static bool ocl_calcBackProject( InputArrayOfArrays _images, std::vector ch mapk.args(ocl::KernelArg::ReadOnlyNoSize(im), ocl::KernelArg::PtrReadOnly(lut), ocl::KernelArg::WriteOnly(dst)); - size_t globalsize[2] = { size.width, size.height }; + size_t globalsize[2] = { (size_t)size.width, (size_t)size.height }; return mapk.run(2, globalsize, NULL, false); } else if (histdims == 2) @@ -2267,7 +2267,7 @@ static bool ocl_calcBackProject( InputArrayOfArrays _images, std::vector ch mapk.args(ocl::KernelArg::ReadOnlyNoSize(im0), ocl::KernelArg::ReadOnlyNoSize(im1), ocl::KernelArg::ReadOnlyNoSize(hist), ocl::KernelArg::PtrReadOnly(lut), scale, ocl::KernelArg::WriteOnly(dst)); - size_t globalsize[2] = { size.width, size.height }; + size_t globalsize[2] = { (size_t)size.width, (size_t)size.height }; return mapk.run(2, globalsize, NULL, false); } return false; diff --git a/modules/imgproc/src/hough.cpp b/modules/imgproc/src/hough.cpp index 18a030841..ae3eef946 100644 --- a/modules/imgproc/src/hough.cpp +++ b/modules/imgproc/src/hough.cpp @@ -680,8 +680,8 @@ static bool ocl_makePointsList(InputArray _src, OutputArray _pointsList, InputOu pointListKernel.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnlyNoSize(pointsList), ocl::KernelArg::PtrWriteOnly(counters)); - size_t localThreads[2] = { workgroup_size, 1 }; - size_t globalThreads[2] = { workgroup_size, src.rows }; + size_t localThreads[2] = { (size_t)workgroup_size, 1 }; + size_t globalThreads[2] = { (size_t)workgroup_size, (size_t)src.rows }; return pointListKernel.run(2, globalThreads, localThreads, false); } @@ -775,7 +775,7 @@ static bool ocl_HoughLines(InputArray _src, OutputArray _lines, double rho, doub getLinesKernel.args(ocl::KernelArg::ReadOnly(accum), ocl::KernelArg::WriteOnlyNoSize(lines), ocl::KernelArg::PtrWriteOnly(counters), linesMax, threshold, (float) rho, (float) theta); - size_t globalThreads[2] = { (numrho + pixPerWI - 1)/pixPerWI, numangle }; + size_t globalThreads[2] = { ((size_t)numrho + pixPerWI - 1)/pixPerWI, (size_t)numangle }; if (!getLinesKernel.run(2, globalThreads, NULL, false)) return false; @@ -829,7 +829,7 @@ static bool ocl_HoughLinesP(InputArray _src, OutputArray _lines, double rho, dou ocl::KernelArg::WriteOnlyNoSize(lines), ocl::KernelArg::PtrWriteOnly(counters), linesMax, threshold, (int) minLineLength, (int) maxGap, (float) rho, (float) theta); - size_t globalThreads[2] = { numrho, numangle }; + size_t globalThreads[2] = { (size_t)numrho, (size_t)numangle }; if (!getLinesKernel.run(2, globalThreads, NULL, false)) return false; diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index e7ee0c677..585d3a6e9 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -2900,7 +2900,7 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize, Size ssize = src.size(); ocl::Kernel k; - size_t globalsize[] = { dst.cols, dst.rows }; + size_t globalsize[] = { (size_t)dst.cols, (size_t)dst.rows }; ocl::Image2D srcImage; @@ -4566,7 +4566,7 @@ static bool ocl_remap(InputArray _src, OutputArray _dst, InputArray _map1, Input else k.args(srcarg, dstarg, map1arg, ocl::KernelArg::ReadOnlyNoSize(map2), scalararg); - size_t globalThreads[2] = { dst.cols, (dst.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalThreads[2] = { (size_t)dst.cols, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalThreads, NULL, false); } @@ -5555,7 +5555,7 @@ static bool ocl_warpTransform(InputArray _src, OutputArray _dst, InputArray _M0, k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst), ocl::KernelArg::PtrReadOnly(M0), ocl::KernelArg(0, 0, 0, 0, borderBuf, CV_ELEM_SIZE(sctype))); - size_t globalThreads[2] = { dst.cols, (dst.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalThreads[2] = { (size_t)dst.cols, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalThreads, NULL, false); } diff --git a/modules/imgproc/src/moments.cpp b/modules/imgproc/src/moments.cpp index 31da20110..15c4a6103 100644 --- a/modules/imgproc/src/moments.cpp +++ b/modules/imgproc/src/moments.cpp @@ -499,7 +499,7 @@ static bool ocl_moments( InputArray _src, Moments& m, bool binary) int ntiles = xtiles*ytiles; UMat umbuf(1, ntiles*K, CV_32S); - size_t globalsize[] = {xtiles, sz.height}, localsize[] = {1, TILE_SIZE}; + size_t globalsize[] = {(size_t)xtiles, (size_t)sz.height}, localsize[] = {1, TILE_SIZE}; bool ok = k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::PtrWriteOnly(umbuf), xtiles).run(2, globalsize, localsize, true); diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index be55e3561..ee3cdc04b 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1411,7 +1411,7 @@ static bool ocl_morphSmall( InputArray _src, OutputArray _dst, InputArray _kerne const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", 0, "BORDER_REFLECT_101" }; - size_t globalsize[2] = { size.width, size.height }; + size_t globalsize[2] = { (size_t)size.width, (size_t)size.height }; UMat src = _src.getUMat(); if (!isolated) @@ -1592,7 +1592,7 @@ static bool ocl_morphOp(InputArray _src, OutputArray _dst, InputArray _kernel, #else size_t localThreads[2] = { 16, 16 }; #endif - size_t globalThreads[2] = { ssize.width, ssize.height }; + size_t globalThreads[2] = { (size_t)ssize.width, (size_t)ssize.height }; #ifdef __APPLE__ if( actual_op != MORPH_ERODE && actual_op != MORPH_DILATE ) diff --git a/modules/imgproc/src/pyramids.cpp b/modules/imgproc/src/pyramids.cpp index d9395e0b5..0d311e22f 100644 --- a/modules/imgproc/src/pyramids.cpp +++ b/modules/imgproc/src/pyramids.cpp @@ -1107,8 +1107,8 @@ static bool ocl_pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, in k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst)); - size_t localThreads[2] = { local_size/kercn, 1 }; - size_t globalThreads[2] = { (src.cols + (kercn-1))/kercn, (dst.rows + 1) / 2 }; + size_t localThreads[2] = { (size_t)local_size/kercn, 1 }; + size_t globalThreads[2] = { ((size_t)src.cols + (kercn-1))/kercn, ((size_t)dst.rows + 1) / 2 }; return k.run(2, globalThreads, localThreads, false); } @@ -1144,8 +1144,8 @@ static bool ocl_pyrUp( InputArray _src, OutputArray _dst, const Size& _dsz, int doubleSupport ? " -D DOUBLE_SUPPORT" : "", ocl::typeToStr(depth), channels, local_size ); - size_t globalThreads[2] = { dst.cols, dst.rows }; - size_t localThreads[2] = { local_size, local_size }; + size_t globalThreads[2] = { (size_t)dst.cols, (size_t)dst.rows }; + size_t localThreads[2] = { (size_t)local_size, (size_t)local_size }; ocl::Kernel k; if (ocl::Device::getDefault().isIntel() && channels == 1) { diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 9fa92037c..855c43283 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -1057,7 +1057,7 @@ static bool ocl_boxFilter( InputArray _src, OutputArray _dst, int ddepth, wtype = CV_MAKE_TYPE(wdepth, cn), dtype = CV_MAKE_TYPE(ddepth, cn); const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", 0, "BORDER_REFLECT_101" }; - size_t globalsize[2] = { size.width, size.height }; + size_t globalsize[2] = { (size_t)size.width, (size_t)size.height }; size_t localsize_general[2] = { 0, 1 }, * localsize = NULL; UMat src = _src.getUMat(); @@ -3128,7 +3128,7 @@ static bool ocl_bilateralFilter_8u(InputArray _src, OutputArray _dst, int d, ocl::KernelArg::PtrReadOnly(uspace_weight), ocl::KernelArg::PtrReadOnly(uspace_ofs)); - size_t globalsize[2] = { dst.cols / sizeDiv, dst.rows }; + size_t globalsize[2] = { (size_t)dst.cols / sizeDiv, (size_t)dst.rows }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/imgproc/src/templmatch.cpp b/modules/imgproc/src/templmatch.cpp index e5f4986cf..59b07032b 100644 --- a/modules/imgproc/src/templmatch.cpp +++ b/modules/imgproc/src/templmatch.cpp @@ -72,7 +72,7 @@ static bool extractFirstChannel_32F(InputArray _image, OutputArray _result, int UMat result = _result.getUMat(); - size_t globalsize[2] = {result.cols, (result.rows+pxPerWIy-1)/pxPerWIy}; + size_t globalsize[2] = {(size_t)result.cols, ((size_t)result.rows+pxPerWIy-1)/pxPerWIy}; return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::WriteOnly(result)).run( 2, globalsize, NULL, false); } @@ -286,7 +286,7 @@ static bool matchTemplateNaive_CCORR(InputArray _image, InputArray _templ, Outpu k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)); - size_t globalsize[2] = { (result.cols+pxPerWIx-1)/pxPerWIx, result.rows}; + size_t globalsize[2] = { ((size_t)result.cols+pxPerWIx-1)/pxPerWIx, (size_t)result.rows}; return k.run(2, globalsize, NULL, false); } @@ -338,7 +338,7 @@ static bool matchTemplate_CCORR_NORMED(InputArray _image, InputArray _templ, Out k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols, ocl::KernelArg::PtrReadOnly(templ_sqsum)); - size_t globalsize[2] = { result.cols, result.rows }; + size_t globalsize[2] = { (size_t)result.cols, (size_t)result.rows }; return k.run(2, globalsize, NULL, false); } @@ -363,7 +363,7 @@ static bool matchTemplateNaive_SQDIFF(InputArray _image, InputArray _templ, Outp k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)); - size_t globalsize[2] = { result.cols, result.rows }; + size_t globalsize[2] = { (size_t)result.cols, (size_t)result.rows }; return k.run(2, globalsize, NULL, false); } @@ -396,7 +396,7 @@ static bool matchTemplate_SQDIFF(InputArray _image, InputArray _templ, OutputArr k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols, ocl::KernelArg::PtrReadOnly(templ_sqsum)); - size_t globalsize[2] = { result.cols, result.rows }; + size_t globalsize[2] = { (size_t)result.cols, (size_t)result.rows }; return k.run(2, globalsize, NULL, false); } @@ -427,7 +427,7 @@ static bool matchTemplate_SQDIFF_NORMED(InputArray _image, InputArray _templ, Ou k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols, ocl::KernelArg::PtrReadOnly(templ_sqsum)); - size_t globalsize[2] = { result.cols, result.rows }; + size_t globalsize[2] = { (size_t)result.cols, (size_t)result.rows }; return k.run(2, globalsize, NULL, false); } @@ -465,7 +465,7 @@ static bool matchTemplate_CCOEFF(InputArray _image, InputArray _templ, OutputArr k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols, templ_sum); } - size_t globalsize[2] = { result.cols, result.rows }; + size_t globalsize[2] = { (size_t)result.cols, (size_t)result.rows }; return k.run(2, globalsize, NULL, false); } @@ -533,7 +533,7 @@ static bool matchTemplate_CCOEFF_NORMED(InputArray _image, InputArray _templ, Ou ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols, scale, templ_sum, templ_sqsum_sum); } - size_t globalsize[2] = { result.cols, result.rows }; + size_t globalsize[2] = { (size_t)result.cols, (size_t)result.rows }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/imgproc/src/thresh.cpp b/modules/imgproc/src/thresh.cpp index 3aaf38bd1..0b61347fd 100644 --- a/modules/imgproc/src/thresh.cpp +++ b/modules/imgproc/src/thresh.cpp @@ -1180,7 +1180,7 @@ static bool ocl_threshold( InputArray _src, OutputArray _dst, double & thresh, d ocl::KernelArg::Constant(Mat(1, 1, depth, Scalar::all(maxval))), ocl::KernelArg::Constant(Mat(1, 1, depth, Scalar::all(min_val)))); - size_t globalsize[2] = { dst.cols * cn / kercn, dst.rows }; + size_t globalsize[2] = { (size_t)dst.cols * cn / kercn, (size_t)dst.rows }; globalsize[1] = (globalsize[1] + stride_size - 1) / stride_size; return k.run(2, globalsize, NULL, false); } diff --git a/modules/java/generator/gen_java.py b/modules/java/generator/gen_java.py index d146eba96..a51bef170 100755 --- a/modules/java/generator/gen_java.py +++ b/modules/java/generator/gen_java.py @@ -1161,7 +1161,7 @@ class JavaWrapperGenerator(object): ("jdoubleArray _da_retval_ = env->NewDoubleArray(%(cnt)i); " + "jdouble _tmp_retval_[%(cnt)i] = {%(args)s}; " + "env->SetDoubleArrayRegion(_da_retval_, 0, %(cnt)i, _tmp_retval_);") % - { "cnt" : len(fields), "args" : ", ".join(["_retval_" + f[1] for f in fields]) } ) + { "cnt" : len(fields), "args" : ", ".join(["(jdouble)_retval_" + f[1] for f in fields]) } ) if fi.classname and fi.ctype and not fi.static: # non-static class method except c-tor # adding 'self' jn_args.append ( ArgInfo([ "__int64", "nativeObj", "", [], "" ]) ) @@ -1208,7 +1208,7 @@ class JavaWrapperGenerator(object): j_prologue.append( "double[] %s_out = new double[%i];" % (a.name, len(fields)) ) c_epilogue.append( \ "jdouble tmp_%(n)s[%(cnt)i] = {%(args)s}; env->SetDoubleArrayRegion(%(n)s_out, 0, %(cnt)i, tmp_%(n)s);" % - { "n" : a.name, "cnt" : len(fields), "args" : ", ".join([a.name + f[1] for f in fields]) } ) + { "n" : a.name, "cnt" : len(fields), "args" : ", ".join(["(jdouble)" + a.name + f[1] for f in fields]) } ) if a.ctype in ('bool', 'int', 'long', 'float', 'double'): j_epilogue.append('if(%(n)s!=null) %(n)s[0] = (%(t)s)%(n)s_out[0];' % {'n':a.name,'t':a.ctype}) else: diff --git a/modules/java/generator/src/cpp/Mat.cpp b/modules/java/generator/src/cpp/Mat.cpp index 185cb2de9..d8483cd02 100644 --- a/modules/java/generator/src/cpp/Mat.cpp +++ b/modules/java/generator/src/cpp/Mat.cpp @@ -1070,7 +1070,7 @@ JNIEXPORT void JNICALL Java_org_opencv_core_Mat_locateROI_10 Size wholeSize; Point ofs; me->locateROI( wholeSize, ofs ); - jdouble tmp_wholeSize[2] = {wholeSize.width, wholeSize.height}; env->SetDoubleArrayRegion(wholeSize_out, 0, 2, tmp_wholeSize); jdouble tmp_ofs[2] = {ofs.x, ofs.y}; env->SetDoubleArrayRegion(ofs_out, 0, 2, tmp_ofs); + jdouble tmp_wholeSize[2] = {(jdouble)wholeSize.width, (jdouble)wholeSize.height}; env->SetDoubleArrayRegion(wholeSize_out, 0, 2, tmp_wholeSize); jdouble tmp_ofs[2] = {(jdouble)ofs.x, (jdouble)ofs.y}; env->SetDoubleArrayRegion(ofs_out, 0, 2, tmp_ofs); } catch(const std::exception &e) { throwJavaException(env, &e, method_name); } catch (...) { @@ -1489,7 +1489,7 @@ JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Mat_n_1size Mat* me = (Mat*) self; //TODO: check for NULL Size _retval_ = me->size( ); jdoubleArray _da_retval_ = env->NewDoubleArray(2); - jdouble _tmp_retval_[2] = {_retval_.width, _retval_.height}; + jdouble _tmp_retval_[2] = {(jdouble)_retval_.width, (jdouble)_retval_.height}; env->SetDoubleArrayRegion(_da_retval_, 0, 2, _tmp_retval_); return _da_retval_; } catch(const std::exception &e) { diff --git a/modules/objdetect/src/cascadedetect.cpp b/modules/objdetect/src/cascadedetect.cpp index 20800ae52..9d7ccfed1 100644 --- a/modules/objdetect/src/cascadedetect.cpp +++ b/modules/objdetect/src/cascadedetect.cpp @@ -1051,7 +1051,7 @@ bool CascadeClassifierImpl::ocl_detectMultiScaleNoGrouping( const std::vectorgetLocalBufSize(); - size_t localsize[] = { localsz.width, localsz.height }; + size_t localsize[] = { (size_t)localsz.width, (size_t)localsz.height }; const int grp_per_CU = 12; size_t globalsize[] = { grp_per_CU*ocl::Device::getDefault().maxComputeUnits()*localsize[0], localsize[1] }; bool ok = false; diff --git a/modules/objdetect/src/hog.cpp b/modules/objdetect/src/hog.cpp index 057387b3e..a6ff7e2ce 100644 --- a/modules/objdetect/src/hog.cpp +++ b/modules/objdetect/src/hog.cpp @@ -1092,7 +1092,7 @@ static bool ocl_compute_gradients_8UC1(int height, int width, InputArray _img, f UMat img = _img.getUMat(); size_t localThreads[3] = { NTHREADS, 1, 1 }; - size_t globalThreads[3] = { width, height, 1 }; + size_t globalThreads[3] = { (size_t)width, (size_t)height, 1 }; char correctGamma = (correct_gamma) ? 1 : 0; int grad_quadstep = (int)grad.step >> 3; int qangle_elem_size = CV_ELEM_SIZE1(qangle.type()); @@ -1152,7 +1152,7 @@ static bool ocl_compute_hists(int nbins, int block_stride_x, int block_stride_y, int qangle_step = (int)qangle.step / qangle_elem_size; int blocks_in_group = 4; - size_t localThreads[3] = { blocks_in_group * 24, 2, 1 }; + size_t localThreads[3] = { (size_t)blocks_in_group * 24, 2, 1 }; size_t globalThreads[3] = {((img_block_width * img_block_height + blocks_in_group - 1)/blocks_in_group) * localThreads[0], 2, 1 }; int hists_size = (nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y * 12) * sizeof(float); @@ -1271,7 +1271,7 @@ static bool ocl_extract_descrs_by_rows(int win_height, int win_width, int block_ int descriptors_quadstep = (int)descriptors.step >> 2; - size_t globalThreads[3] = { img_win_width * NTHREADS, img_win_height, 1 }; + size_t globalThreads[3] = { (size_t)img_win_width * NTHREADS, (size_t)img_win_height, 1 }; size_t localThreads[3] = { NTHREADS, 1, 1 }; int idx = 0; @@ -1305,7 +1305,7 @@ static bool ocl_extract_descrs_by_cols(int win_height, int win_width, int block_ int descriptors_quadstep = (int)descriptors.step >> 2; - size_t globalThreads[3] = { img_win_width * NTHREADS, img_win_height, 1 }; + size_t globalThreads[3] = { (size_t)img_win_width * NTHREADS, (size_t)img_win_height, 1 }; size_t localThreads[3] = { NTHREADS, 1, 1 }; int idx = 0; @@ -1704,8 +1704,8 @@ static bool ocl_classify_hists(int win_height, int win_width, int block_stride_y int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) / block_stride_x; - size_t globalThreads[3] = { img_win_width * nthreads, img_win_height, 1 }; - size_t localThreads[3] = { nthreads, 1, 1 }; + size_t globalThreads[3] = { (size_t)img_win_width * nthreads, (size_t)img_win_height, 1 }; + size_t localThreads[3] = { (size_t)nthreads, 1, 1 }; idx = k.set(idx, block_hist_size); idx = k.set(idx, img_win_width); diff --git a/modules/photo/src/fast_nlmeans_denoising_opencl.hpp b/modules/photo/src/fast_nlmeans_denoising_opencl.hpp index 1c511f37b..f012de507 100644 --- a/modules/photo/src/fast_nlmeans_denoising_opencl.hpp +++ b/modules/photo/src/fast_nlmeans_denoising_opencl.hpp @@ -77,7 +77,7 @@ static bool ocl_calcAlmostDist2Weight(UMat & almostDist2Weight, almostDist2ActualDistMultiplier, fixedPointMult, ocl::KernelArg::Constant(den, (hn == 3 ? 4 : hn)*sizeof(FT)), WEIGHT_THRESHOLD); - size_t globalsize[1] = { almostMaxDist }; + size_t globalsize[1] = { (size_t)almostMaxDist }; return k.run(1, globalsize, NULL, false); } @@ -172,7 +172,7 @@ static bool ocl_fastNlMeansDenoising(InputArray _src, OutputArray _dst, const fl ocl::KernelArg::PtrReadOnly(almostDist2Weight), ocl::KernelArg::PtrReadOnly(buffer), almostTemplateWindowSizeSqBinShift); - size_t globalsize[2] = { nblocksx * ctaSize, nblocksy }, localsize[2] = { ctaSize, 1 }; + size_t globalsize[2] = { (size_t)nblocksx * ctaSize, (size_t)nblocksy }, localsize[2] = { (size_t)ctaSize, 1 }; if (!k.run(2, globalsize, localsize, false)) return false; if (cn == 3) { diff --git a/modules/python/src2/cv2.cpp b/modules/python/src2/cv2.cpp index 82f1c8b9f..cbe285222 100644 --- a/modules/python/src2/cv2.cpp +++ b/modules/python/src2/cv2.cpp @@ -1,6 +1,6 @@ #if defined(_MSC_VER) && (_MSC_VER >= 1800) // eliminating duplicated round() declaration -#define HAVE_ROUND +#define HAVE_ROUND 1 #endif #include diff --git a/modules/stitching/src/blenders.cpp b/modules/stitching/src/blenders.cpp index 82e65fa38..1d2fe9e59 100644 --- a/modules/stitching/src/blenders.cpp +++ b/modules/stitching/src/blenders.cpp @@ -267,7 +267,7 @@ static bool ocl_MultiBandBlender_feed(InputArray _src, InputArray _weight, ocl::KernelArg::ReadWrite(_dst_weight.getUMat()) ); - size_t globalsize[2] = {src.cols, src.rows }; + size_t globalsize[2] = {(size_t)src.cols, (size_t)src.rows }; return k.run(2, globalsize, NULL, false); } #endif @@ -469,7 +469,7 @@ static bool ocl_normalizeUsingWeightMap(InputArray _weight, InputOutputArray _ma ocl::KernelArg::ReadOnly(_weight.getUMat()) ); - size_t globalsize[2] = {mat.cols, mat.rows }; + size_t globalsize[2] = {(size_t)mat.cols, (size_t)mat.rows }; return k.run(2, globalsize, NULL, false); } #endif diff --git a/modules/stitching/src/warpers.cpp b/modules/stitching/src/warpers.cpp index 141fdec35..e69f8d25d 100644 --- a/modules/stitching/src/warpers.cpp +++ b/modules/stitching/src/warpers.cpp @@ -124,7 +124,7 @@ Rect PlaneWarper::buildMaps(Size src_size, InputArray K, InputArray R, InputArra ocl::KernelArg::PtrReadOnly(uk_rinv), ocl::KernelArg::PtrReadOnly(ut), dst_tl.x, dst_tl.y, 1/projector_.scale, rowsPerWI); - size_t globalsize[2] = { dsize.width, (dsize.height + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dsize.width, ((size_t)dsize.height + rowsPerWI - 1) / rowsPerWI }; if (k.run(2, globalsize, NULL, true)) { CV_IMPL_ADD(CV_IMPL_OCL); @@ -331,7 +331,7 @@ Rect SphericalWarper::buildMaps(Size src_size, InputArray K, InputArray R, Outpu k.args(ocl::KernelArg::WriteOnlyNoSize(uxmap), ocl::KernelArg::WriteOnly(uymap), ocl::KernelArg::PtrReadOnly(uk_rinv), dst_tl.x, dst_tl.y, 1/projector_.scale, rowsPerWI); - size_t globalsize[2] = { dsize.width, (dsize.height + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dsize.width, ((size_t)dsize.height + rowsPerWI - 1) / rowsPerWI }; if (k.run(2, globalsize, NULL, true)) { CV_IMPL_ADD(CV_IMPL_OCL); @@ -380,7 +380,7 @@ Rect CylindricalWarper::buildMaps(Size src_size, InputArray K, InputArray R, Out ocl::KernelArg::PtrReadOnly(uk_rinv), dst_tl.x, dst_tl.y, 1/projector_.scale, rowsPerWI); - size_t globalsize[2] = { dsize.width, (dsize.height + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dsize.width, ((size_t)dsize.height + rowsPerWI - 1) / rowsPerWI }; if (k.run(2, globalsize, NULL, true)) { CV_IMPL_ADD(CV_IMPL_OCL); diff --git a/modules/superres/src/btv_l1.cpp b/modules/superres/src/btv_l1.cpp index 291fa1bcb..d47453f0d 100644 --- a/modules/superres/src/btv_l1.cpp +++ b/modules/superres/src/btv_l1.cpp @@ -185,7 +185,7 @@ namespace ocl::KernelArg::WriteOnlyNoSize(forwardMap), ocl::KernelArg::WriteOnly(backwardMap)); - size_t globalsize[2] = { size.width, size.height }; + size_t globalsize[2] = { (size_t)size.width, (size_t)size.height }; return k.run(2, globalsize, NULL, false); } @@ -258,7 +258,7 @@ namespace k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::ReadWriteNoSize(dst), scale); - size_t globalsize[2] = { src.cols, src.rows }; + size_t globalsize[2] = { (size_t)src.cols, (size_t)src.rows }; return k.run(2, globalsize, NULL, false); } @@ -316,7 +316,7 @@ namespace ocl::KernelArg::ReadOnlyNoSize(src2), ocl::KernelArg::WriteOnly(dst, cn)); - size_t globalsize[2] = { src1.cols * cn, src1.rows }; + size_t globalsize[2] = { (size_t)src1.cols * cn, (size_t)src1.rows }; return k.run(2, globalsize, NULL, false); } @@ -436,7 +436,7 @@ namespace k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst), ksize, ocl::KernelArg::PtrReadOnly(ubtvWeights)); - size_t globalsize[2] = { src.cols, src.rows }; + size_t globalsize[2] = { (size_t)src.cols, (size_t)src.rows }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/superres/src/input_array_utility.cpp b/modules/superres/src/input_array_utility.cpp index ec20673b4..a823e43cd 100644 --- a/modules/superres/src/input_array_utility.cpp +++ b/modules/superres/src/input_array_utility.cpp @@ -205,11 +205,11 @@ namespace static const double maxVals[] = { - std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::max(), + (double)std::numeric_limits::max(), + (double)std::numeric_limits::max(), + (double)std::numeric_limits::max(), + (double)std::numeric_limits::max(), + (double)std::numeric_limits::max(), 1.0, 1.0, }; diff --git a/modules/video/src/bgfg_gaussmix2.cpp b/modules/video/src/bgfg_gaussmix2.cpp index 226af9dc0..5932d9c9e 100644 --- a/modules/video/src/bgfg_gaussmix2.cpp +++ b/modules/video/src/bgfg_gaussmix2.cpp @@ -787,7 +787,7 @@ bool BackgroundSubtractorMOG2Impl::ocl_apply(InputArray _image, OutputArray _fgm if (bShadowDetection) kernel_apply.set(idxArg, nShadowDetection); - size_t globalsize[] = {frame.cols, frame.rows, 1}; + size_t globalsize[] = {(size_t)frame.cols, (size_t)frame.rows, 1}; return kernel_apply.run(2, globalsize, NULL, true); } @@ -805,7 +805,7 @@ bool BackgroundSubtractorMOG2Impl::ocl_getBackgroundImage(OutputArray _backgroun idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::WriteOnly(dst)); kernel_getBg.set(idxArg, backgroundRatio); - size_t globalsize[2] = {u_bgmodelUsedModes.cols, u_bgmodelUsedModes.rows}; + size_t globalsize[2] = {(size_t)u_bgmodelUsedModes.cols, (size_t)u_bgmodelUsedModes.rows}; return kernel_getBg.run(2, globalsize, NULL, false); } diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index a34e73d51..ccbedc534 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -976,7 +976,7 @@ namespace cv int ptcount, int level) { size_t localThreads[3] = { 8, 8}; - size_t globalThreads[3] = { 8 * ptcount, 8}; + size_t globalThreads[3] = { 8 * (size_t)ptcount, 8}; char calcErr = (0 == level) ? 1 : 0; cv::String build_options; diff --git a/modules/video/src/optflowgf.cpp b/modules/video/src/optflowgf.cpp index 1d6524e30..740894619 100644 --- a/modules/video/src/optflowgf.cpp +++ b/modules/video/src/optflowgf.cpp @@ -845,7 +845,7 @@ private: #else size_t localsize[2] = { 256, 1}; #endif - size_t globalsize[2] = { src.cols, src.rows}; + size_t globalsize[2] = { (size_t)src.cols, (size_t)src.rows}; int smem_size = (int)((localsize[0] + 2*ksizeHalf) * sizeof(float)); ocl::Kernel kernel; if (!kernel.create("gaussianBlur", cv::ocl::video::optical_flow_farneback_oclsrc, "")) @@ -872,7 +872,7 @@ private: #else size_t localsize[2] = { 256, 1}; #endif - size_t globalsize[2] = { src.cols, height}; + size_t globalsize[2] = { (size_t)src.cols, (size_t)height}; int smem_size = (int)((localsize[0] + 2*ksizeHalf) * 5 * sizeof(float)); ocl::Kernel kernel; if (!kernel.create("gaussianBlur5", cv::ocl::video::optical_flow_farneback_oclsrc, "")) @@ -897,7 +897,7 @@ private: #else size_t localsize[2] = { 256, 1}; #endif - size_t globalsize[2] = { DIVUP(src.cols, localsize[0] - 2*polyN) * localsize[0], src.rows}; + size_t globalsize[2] = { DIVUP((size_t)src.cols, localsize[0] - 2*polyN) * localsize[0], (size_t)src.rows}; #if 0 const cv::ocl::Device &device = cv::ocl::Device::getDefault(); @@ -934,7 +934,7 @@ private: #else size_t localsize[2] = { 256, 1}; #endif - size_t globalsize[2] = { src.cols, height}; + size_t globalsize[2] = { (size_t)src.cols, (size_t)height}; ocl::Kernel kernel; if (!kernel.create("boxFilter5", cv::ocl::video::optical_flow_farneback_oclsrc, "")) @@ -961,7 +961,7 @@ private: #else size_t localsize[2] = { 32, 8}; #endif - size_t globalsize[2] = { flowx.cols, flowx.rows}; + size_t globalsize[2] = { (size_t)flowx.cols, (size_t)flowx.rows}; ocl::Kernel kernel; if (!kernel.create("updateFlow", cv::ocl::video::optical_flow_farneback_oclsrc, "")) @@ -985,7 +985,7 @@ private: #else size_t localsize[2] = { 32, 8}; #endif - size_t globalsize[2] = { flowx.cols, flowx.rows}; + size_t globalsize[2] = { (size_t)flowx.cols, (size_t)flowx.rows}; ocl::Kernel kernel; if (!kernel.create("updateMatrices", cv::ocl::video::optical_flow_farneback_oclsrc, "")) diff --git a/modules/video/src/tvl1flow.cpp b/modules/video/src/tvl1flow.cpp index 90fe48f47..1bbc12f0b 100644 --- a/modules/video/src/tvl1flow.cpp +++ b/modules/video/src/tvl1flow.cpp @@ -216,7 +216,7 @@ namespace cv_ocl_tvl1flow bool cv_ocl_tvl1flow::centeredGradient(const UMat &src, UMat &dx, UMat &dy) { - size_t globalsize[2] = { src.cols, src.rows }; + size_t globalsize[2] = { (size_t)src.cols, (size_t)src.rows }; ocl::Kernel kernel; if (!kernel.create("centeredGradientKernel", cv::ocl::video::optical_flow_tvl1_oclsrc, "")) @@ -237,7 +237,7 @@ bool cv_ocl_tvl1flow::warpBackward(const UMat &I0, const UMat &I1, UMat &I1x, UM UMat &u1, UMat &u2, UMat &I1w, UMat &I1wx, UMat &I1wy, UMat &grad, UMat &rho) { - size_t globalsize[2] = { I0.cols, I0.rows }; + size_t globalsize[2] = { (size_t)I0.cols, (size_t)I0.rows }; ocl::Kernel kernel; if (!kernel.create("warpBackwardKernel", cv::ocl::video::optical_flow_tvl1_oclsrc, "")) @@ -281,7 +281,7 @@ bool cv_ocl_tvl1flow::estimateU(UMat &I1wx, UMat &I1wy, UMat &grad, UMat &p21, UMat &p22, UMat &u1, UMat &u2, UMat &error, float l_t, float theta, char calc_error) { - size_t globalsize[2] = { I1wx.cols, I1wx.rows }; + size_t globalsize[2] = { (size_t)I1wx.cols, (size_t)I1wx.rows }; ocl::Kernel kernel; if (!kernel.create("estimateUKernel", cv::ocl::video::optical_flow_tvl1_oclsrc, "")) @@ -322,7 +322,7 @@ bool cv_ocl_tvl1flow::estimateU(UMat &I1wx, UMat &I1wy, UMat &grad, bool cv_ocl_tvl1flow::estimateDualVariables(UMat &u1, UMat &u2, UMat &p11, UMat &p12, UMat &p21, UMat &p22, float taut) { - size_t globalsize[2] = { u1.cols, u1.rows }; + size_t globalsize[2] = { (size_t)u1.cols, (size_t)u1.rows }; ocl::Kernel kernel; if (!kernel.create("estimateDualVariablesKernel", cv::ocl::video::optical_flow_tvl1_oclsrc, "")) From fd4761ba313926b32f1efff5bae75b53170ddc02 Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Fri, 18 Sep 2015 11:39:39 +0300 Subject: [PATCH 148/156] Update face detection samples --- samples/cpp/facedetect.cpp | 117 +++++++++++--------------- samples/cpp/smiledetect.cpp | 110 ++++++++++-------------- samples/{cpp => tapi}/ufacedetect.cpp | 86 +++++++++---------- 3 files changed, 134 insertions(+), 179 deletions(-) rename samples/{cpp => tapi}/ufacedetect.cpp (80%) diff --git a/samples/cpp/facedetect.cpp b/samples/cpp/facedetect.cpp index 1206245ef..2be4e17e4 100644 --- a/samples/cpp/facedetect.cpp +++ b/samples/cpp/facedetect.cpp @@ -1,17 +1,7 @@ #include "opencv2/objdetect.hpp" -#include "opencv2/imgcodecs.hpp" -#include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/core/utility.hpp" - -#include "opencv2/videoio/videoio_c.h" -#include "opencv2/highgui/highgui_c.h" - -#include #include -#include -#include using namespace std; using namespace cv; @@ -28,7 +18,7 @@ static void help() " [--try-flip]\n" " [filename|camera_index]\n\n" "see facedetect.cmd for one call:\n" - "./facedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"../../data/haarcascades/haarcascade_eye.xml\" --scale=1.3\n\n" + "./facedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml\" --scale=1.3\n\n" "During execution:\n\tHit any key to quit.\n" "\tUsing OpenCV version " << CV_VERSION << "\n" << endl; } @@ -42,8 +32,8 @@ string nestedCascadeName = "../../data/haarcascades/haarcascade_eye_tree_eyeglas int main( int argc, const char** argv ) { - CvCapture* capture = 0; - Mat frame, frameCopy, image; + VideoCapture capture; + Mat frame, image; const string scaleOpt = "--scale="; size_t scaleOptLen = scaleOpt.length(); const string cascadeOpt = "--cascade="; @@ -103,17 +93,17 @@ int main( int argc, const char** argv ) if( inputName.empty() || (isdigit(inputName.c_str()[0]) && inputName.c_str()[1] == '\0') ) { - capture = cvCaptureFromCAM( inputName.empty() ? 0 : inputName.c_str()[0] - '0' ); int c = inputName.empty() ? 0 : inputName.c_str()[0] - '0' ; - if(!capture) cout << "Capture from CAM " << c << " didn't work" << endl; + if(!capture.open(c)) + cout << "Capture from camera #" << c << " didn't work" << endl; } else if( inputName.size() ) { image = imread( inputName, 1 ); if( image.empty() ) { - capture = cvCaptureFromAVI( inputName.c_str() ); - if(!capture) cout << "Capture from AVI didn't work" << endl; + if(!capture.open( inputName )) + cout << "Could not read " << inputName << endl; } } else @@ -122,36 +112,27 @@ int main( int argc, const char** argv ) if(image.empty()) cout << "Couldn't read ../data/lena.jpg" << endl; } - cvNamedWindow( "result", 1 ); - - if( capture ) + if( capture.isOpened() ) { - cout << "In capture ..." << endl; + cout << "Video capturing has been started ..." << endl; + for(;;) { - IplImage* iplImg = cvQueryFrame( capture ); - frame = cv::cvarrToMat(iplImg); + capture >> frame; if( frame.empty() ) break; - if( iplImg->origin == IPL_ORIGIN_TL ) - frame.copyTo( frameCopy ); - else - flip( frame, frameCopy, 0 ); - detectAndDraw( frameCopy, cascade, nestedCascade, scale, tryflip ); + Mat frame1 = frame.clone(); + detectAndDraw( frame1, cascade, nestedCascade, scale, tryflip ); - if( waitKey( 10 ) >= 0 ) - goto _cleanup_; + int c = waitKey(10); + if( c == 27 || c == 'q' || c == 'Q' ) + break; } - - waitKey(0); - -_cleanup_: - cvReleaseCapture( &capture ); } else { - cout << "In image read" << endl; + cout << "Detecting face(s) in " << inputName << endl; if( !image.empty() ) { detectAndDraw( image, cascade, nestedCascade, scale, tryflip ); @@ -190,8 +171,6 @@ _cleanup_: } } - cvDestroyWindow("result"); - return 0; } @@ -199,21 +178,24 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, CascadeClassifier& nestedCascade, double scale, bool tryflip ) { - int i = 0; double t = 0; vector faces, faces2; - const static Scalar colors[] = { CV_RGB(0,0,255), - CV_RGB(0,128,255), - CV_RGB(0,255,255), - CV_RGB(0,255,0), - CV_RGB(255,128,0), - CV_RGB(255,255,0), - CV_RGB(255,0,0), - CV_RGB(255,0,255)} ; - Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 ); + const static Scalar colors[] = + { + Scalar(255,0,0), + Scalar(255,128,0), + Scalar(255,255,0), + Scalar(0,255,0), + Scalar(0,128,255), + Scalar(0,255,255), + Scalar(0,0,255), + Scalar(255,0,255) + }; + Mat gray, smallImg; cvtColor( img, gray, COLOR_BGR2GRAY ); - resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR ); + double fx = 1 / scale; + resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR ); equalizeHist( smallImg, smallImg ); t = (double)cvGetTickCount(); @@ -221,8 +203,7 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); if( tryflip ) { @@ -231,8 +212,7 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); for( vector::const_iterator r = faces2.begin(); r != faces2.end(); r++ ) { @@ -241,44 +221,45 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, } t = (double)cvGetTickCount() - t; printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) ); - for( vector::const_iterator r = faces.begin(); r != faces.end(); r++, i++ ) + for ( size_t i = 0; i < faces.size(); i++ ) { + Rect r = faces[i]; Mat smallImgROI; vector nestedObjects; Point center; Scalar color = colors[i%8]; int radius; - double aspect_ratio = (double)r->width/r->height; + double aspect_ratio = (double)r.width/r.height; if( 0.75 < aspect_ratio && aspect_ratio < 1.3 ) { - center.x = cvRound((r->x + r->width*0.5)*scale); - center.y = cvRound((r->y + r->height*0.5)*scale); - radius = cvRound((r->width + r->height)*0.25*scale); + center.x = cvRound((r.x + r.width*0.5)*scale); + center.y = cvRound((r.y + r.height*0.5)*scale); + radius = cvRound((r.width + r.height)*0.25*scale); circle( img, center, radius, color, 3, 8, 0 ); } else - rectangle( img, cvPoint(cvRound(r->x*scale), cvRound(r->y*scale)), - cvPoint(cvRound((r->x + r->width-1)*scale), cvRound((r->y + r->height-1)*scale)), + rectangle( img, cvPoint(cvRound(r.x*scale), cvRound(r.y*scale)), + cvPoint(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)), color, 3, 8, 0); if( nestedCascade.empty() ) continue; - smallImgROI = smallImg(*r); + smallImgROI = smallImg( r ); nestedCascade.detectMultiScale( smallImgROI, nestedObjects, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH //|CASCADE_DO_CANNY_PRUNING - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); - for( vector::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++ ) + for ( size_t j = 0; j < nestedObjects.size(); j++ ) { - center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale); - center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale); - radius = cvRound((nr->width + nr->height)*0.25*scale); + Rect nr = nestedObjects[j]; + center.x = cvRound((r.x + nr.x + nr.width*0.5)*scale); + center.y = cvRound((r.y + nr.y + nr.height*0.5)*scale); + radius = cvRound((nr.width + nr.height)*0.25*scale); circle( img, center, radius, color, 3, 8, 0 ); } } - cv::imshow( "result", img ); + imshow( "result", img ); } diff --git a/samples/cpp/smiledetect.cpp b/samples/cpp/smiledetect.cpp index 305cdad8d..d15183fb0 100644 --- a/samples/cpp/smiledetect.cpp +++ b/samples/cpp/smiledetect.cpp @@ -1,15 +1,7 @@ #include "opencv2/objdetect.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/core/utility.hpp" - -#include "opencv2/videoio/videoio_c.h" -#include "opencv2/highgui/highgui_c.h" - -#include #include -#include -#include using namespace std; using namespace cv; @@ -36,11 +28,10 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, string cascadeName = "../../data/haarcascades/haarcascade_frontalface_alt.xml"; string nestedCascadeName = "../../data/haarcascades/haarcascade_smile.xml"; - int main( int argc, const char** argv ) { - CvCapture* capture = 0; - Mat frame, frameCopy, image; + VideoCapture capture; + Mat frame, image; const string scaleOpt = "--scale="; size_t scaleOptLen = scaleOpt.length(); const string cascadeOpt = "--cascade="; @@ -104,44 +95,34 @@ int main( int argc, const char** argv ) if( inputName.empty() || (isdigit(inputName.c_str()[0]) && inputName.c_str()[1] == '\0') ) { - capture = cvCaptureFromCAM( inputName.empty() ? 0 : inputName.c_str()[0] - '0' ); int c = inputName.empty() ? 0 : inputName.c_str()[0] - '0' ; - if(!capture) cout << "Capture from CAM " << c << " didn't work" << endl; + if(!capture.open(c)) + cout << "Capture from camera #" << c << " didn't work" << endl; } else if( inputName.size() ) { - capture = cvCaptureFromAVI( inputName.c_str() ); - if(!capture) cout << "Capture from AVI didn't work" << endl; + if(!capture.open( inputName )) + cout << "Could not read " << inputName << endl; } - cvNamedWindow( "result", 1 ); - - if( capture ) + if( capture.isOpened() ) { - cout << "In capture ..." << endl; + cout << "Video capturing has been started ..." << endl; cout << endl << "NOTE: Smile intensity will only be valid after a first smile has been detected" << endl; for(;;) { - IplImage* iplImg = cvQueryFrame( capture ); - frame = cv::cvarrToMat(iplImg); + capture >> frame; if( frame.empty() ) break; - if( iplImg->origin == IPL_ORIGIN_TL ) - frame.copyTo( frameCopy ); - else - flip( frame, frameCopy, 0 ); - detectAndDraw( frameCopy, cascade, nestedCascade, scale, tryflip ); + Mat frame1 = frame.clone(); + detectAndDraw( frame1, cascade, nestedCascade, scale, tryflip ); - if( waitKey( 10 ) >= 0 ) - goto _cleanup_; + int c = waitKey(10); + if( c == 27 || c == 'q' || c == 'Q' ) + break; } - - waitKey(0); - -_cleanup_: - cvReleaseCapture( &capture ); } else { @@ -150,7 +131,6 @@ _cleanup_: return -1; } - cvDestroyWindow("result"); return 0; } @@ -158,28 +138,31 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, CascadeClassifier& nestedCascade, double scale, bool tryflip) { - int i = 0; vector faces, faces2; - const static Scalar colors[] = { CV_RGB(0,0,255), - CV_RGB(0,128,255), - CV_RGB(0,255,255), - CV_RGB(0,255,0), - CV_RGB(255,128,0), - CV_RGB(255,255,0), - CV_RGB(255,0,0), - CV_RGB(255,0,255)} ; - Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 ); + const static Scalar colors[] = + { + Scalar(255,0,0), + Scalar(255,128,0), + Scalar(255,255,0), + Scalar(0,255,0), + Scalar(0,128,255), + Scalar(0,255,255), + Scalar(0,0,255), + Scalar(255,0,255) + }; + Mat gray, smallImg; cvtColor( img, gray, COLOR_BGR2GRAY ); - resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR ); + + double fx = 1 / scale; + resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR ); equalizeHist( smallImg, smallImg ); cascade.detectMultiScale( smallImg, faces, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); if( tryflip ) { @@ -188,8 +171,7 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); for( vector::const_iterator r = faces2.begin(); r != faces2.end(); r++ ) { @@ -197,38 +179,38 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, } } - for( vector::iterator r = faces.begin(); r != faces.end(); r++, i++ ) + for ( size_t i = 0; i < faces.size(); i++ ) { + Rect r = faces[i]; Mat smallImgROI; vector nestedObjects; Point center; Scalar color = colors[i%8]; int radius; - double aspect_ratio = (double)r->width/r->height; + double aspect_ratio = (double)r.width/r.height; if( 0.75 < aspect_ratio && aspect_ratio < 1.3 ) { - center.x = cvRound((r->x + r->width*0.5)*scale); - center.y = cvRound((r->y + r->height*0.5)*scale); - radius = cvRound((r->width + r->height)*0.25*scale); + center.x = cvRound((r.x + r.width*0.5)*scale); + center.y = cvRound((r.y + r.height*0.5)*scale); + radius = cvRound((r.width + r.height)*0.25*scale); circle( img, center, radius, color, 3, 8, 0 ); } else - rectangle( img, cvPoint(cvRound(r->x*scale), cvRound(r->y*scale)), - cvPoint(cvRound((r->x + r->width-1)*scale), cvRound((r->y + r->height-1)*scale)), + rectangle( img, cvPoint(cvRound(r.x*scale), cvRound(r.y*scale)), + cvPoint(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)), color, 3, 8, 0); - const int half_height=cvRound((float)r->height/2); - r->y=r->y + half_height; - r->height = half_height; - smallImgROI = smallImg(*r); + const int half_height=cvRound((float)r.height/2); + r.y=r.y + half_height; + r.height = half_height-1; + smallImgROI = smallImg( r ); nestedCascade.detectMultiScale( smallImgROI, nestedObjects, 1.1, 0, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH //|CASCADE_DO_CANNY_PRUNING - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); // The number of detected neighbors depends on image size (and also illumination, etc.). The @@ -243,9 +225,9 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, // Draw rectangle on the left side of the image reflecting smile intensity float intensityZeroOne = ((float)smile_neighbors - min_neighbors) / (max_neighbors - min_neighbors + 1); int rect_height = cvRound((float)img.rows * intensityZeroOne); - CvScalar col = CV_RGB((float)255 * intensityZeroOne, 0, 0); + Scalar col = Scalar((float)255 * intensityZeroOne, 0, 0); rectangle(img, cvPoint(0, img.rows), cvPoint(img.cols/10, img.rows - rect_height), col, -1); } - cv::imshow( "result", img ); + imshow( "result", img ); } diff --git a/samples/cpp/ufacedetect.cpp b/samples/tapi/ufacedetect.cpp similarity index 80% rename from samples/cpp/ufacedetect.cpp rename to samples/tapi/ufacedetect.cpp index 1e08b3e71..e3c82a2c6 100644 --- a/samples/cpp/ufacedetect.cpp +++ b/samples/tapi/ufacedetect.cpp @@ -1,15 +1,8 @@ #include "opencv2/objdetect.hpp" -#include "opencv2/imgcodecs.hpp" -#include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/core/utility.hpp" #include "opencv2/core/ocl.hpp" - -#include #include -#include -#include using namespace std; using namespace cv; @@ -20,13 +13,13 @@ static void help() "This classifier can recognize many kinds of rigid objects, once the appropriate classifier is trained.\n" "It's most known use is for faces.\n" "Usage:\n" - "./facedetect [--cascade= this is the primary trained classifier such as frontal face]\n" + "./ufacedetect [--cascade= this is the primary trained classifier such as frontal face]\n" " [--nested-cascade[=nested_cascade_path this an optional secondary classifier such as eyes]]\n" " [--scale=]\n" " [--try-flip]\n" " [filename|camera_index]\n\n" "see facedetect.cmd for one call:\n" - "./facedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"../../data/haarcascades/haarcascade_eye.xml\" --scale=1.3\n\n" + "./ufacedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml\" --scale=1.3\n\n" "During execution:\n\tHit any key to quit.\n" "\tUsing OpenCV version " << CV_VERSION << "\n" << endl; } @@ -76,7 +69,7 @@ int main( int argc, const char** argv ) } else if( scaleOpt.compare( 0, scaleOptLen, argv[i], scaleOptLen ) == 0 ) { - if( !sscanf( argv[i] + scaleOpt.length(), "%lf", &scale ) || scale > 1 ) + if( !sscanf( argv[i] + scaleOpt.length(), "%lf", &scale ) ) scale = 1; cout << " from which we read scale = " << scale << endl; } @@ -87,7 +80,7 @@ int main( int argc, const char** argv ) } else if( argv[i][0] == '-' ) { - cerr << "WARNING: Unknown option %s" << argv[i] << endl; + cerr << "WARNING: Unknown option " << argv[i] << endl; } else inputName = argv[i]; @@ -120,8 +113,6 @@ int main( int argc, const char** argv ) } } - namedWindow( "result", 1 ); - if( capture.isOpened() ) { cout << "Video capturing has been started ..." << endl; @@ -133,7 +124,8 @@ int main( int argc, const char** argv ) detectAndDraw( frame, canvas, cascade, nestedCascade, scale, tryflip ); - if( waitKey( 10 ) >= 0 ) + int c = waitKey(10); + if( c == 27 || c == 'q' || c == 'Q' ) break; } } @@ -183,46 +175,44 @@ int main( int argc, const char** argv ) void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade, CascadeClassifier& nestedCascade, - double scale0, bool tryflip ) + double scale, bool tryflip ) { - int i = 0; - double t = 0, scale=1; + double t = 0; vector faces, faces2; const static Scalar colors[] = { - Scalar(0,0,255), - Scalar(0,128,255), - Scalar(0,255,255), - Scalar(0,255,0), + Scalar(255,0,0), Scalar(255,128,0), Scalar(255,255,0), - Scalar(255,0,0), + Scalar(0,255,0), + Scalar(0,128,255), + Scalar(0,255,255), + Scalar(0,0,255), Scalar(255,0,255) }; static UMat gray, smallImg; t = (double)getTickCount(); - resize( img, smallImg, Size(), scale0, scale0, INTER_LINEAR ); - cvtColor( smallImg, gray, COLOR_BGR2GRAY ); - equalizeHist( gray, gray ); + cvtColor( img, gray, COLOR_BGR2GRAY ); + double fx = 1 / scale; + resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR ); + equalizeHist( smallImg, smallImg ); - cascade.detectMultiScale( gray, faces, + cascade.detectMultiScale( smallImg, faces, 1.1, 3, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); if( tryflip ) { - flip(gray, gray, 1); - cascade.detectMultiScale( gray, faces2, + flip(smallImg, smallImg, 1); + cascade.detectMultiScale( smallImg, faces2, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); for( vector::const_iterator r = faces2.begin(); r != faces2.end(); r++ ) { @@ -230,7 +220,7 @@ void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade, } } t = (double)getTickCount() - t; - smallImg.copyTo(canvas); + img.copyTo(canvas); double fps = getTickFrequency()/t; static double avgfps = 0; @@ -242,41 +232,43 @@ void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade, putText(canvas, format("OpenCL: %s, fps: %.1f", ocl::useOpenCL() ? "ON" : "OFF", avgfps), Point(50, 30), FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0,255,0), 2); - for( vector::const_iterator r = faces.begin(); r != faces.end(); r++, i++ ) + for ( size_t i = 0; i < faces.size(); i++ ) { + Rect r = faces[i]; vector nestedObjects; Point center; Scalar color = colors[i%8]; int radius; - double aspect_ratio = (double)r->width/r->height; + double aspect_ratio = (double)r.width/r.height; if( 0.75 < aspect_ratio && aspect_ratio < 1.3 ) { - center.x = cvRound((r->x + r->width*0.5)*scale); - center.y = cvRound((r->y + r->height*0.5)*scale); - radius = cvRound((r->width + r->height)*0.25*scale); + center.x = cvRound((r.x + r.width*0.5)*scale); + center.y = cvRound((r.y + r.height*0.5)*scale); + radius = cvRound((r.width + r.height)*0.25*scale); circle( canvas, center, radius, color, 3, 8, 0 ); } else - rectangle( canvas, Point(cvRound(r->x*scale), cvRound(r->y*scale)), - Point(cvRound((r->x + r->width-1)*scale), cvRound((r->y + r->height-1)*scale)), + rectangle( canvas, Point(cvRound(r.x*scale), cvRound(r.y*scale)), + Point(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)), color, 3, 8, 0); if( nestedCascade.empty() ) continue; - UMat smallImgROI = gray(*r); + UMat smallImgROI = smallImg(r); nestedCascade.detectMultiScale( smallImgROI, nestedObjects, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH //|CASCADE_DO_CANNY_PRUNING - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); - for( vector::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++ ) + + for ( size_t j = 0; j < nestedObjects.size(); j++ ) { - center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale); - center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale); - radius = cvRound((nr->width + nr->height)*0.25*scale); + Rect nr = nestedObjects[j]; + center.x = cvRound((r.x + nr.x + nr.width*0.5)*scale); + center.y = cvRound((r.y + nr.y + nr.height*0.5)*scale); + radius = cvRound((nr.width + nr.height)*0.25*scale); circle( canvas, center, radius, color, 3, 8, 0 ); } } From 781931a67152767224789b52f447bc598ba6530b Mon Sep 17 00:00:00 2001 From: berak Date: Tue, 20 Oct 2015 11:57:29 +0200 Subject: [PATCH 149/156] update python features2d tutorials --- .../py_feature2d/py_brief/py_brief.markdown | 8 +++++--- .../py_feature2d/py_fast/py_fast.markdown | 2 +- .../py_feature_homography.markdown | 4 ++-- doc/py_tutorials/py_feature2d/py_orb/py_orb.markdown | 4 ++-- .../py_sift_intro/py_sift_intro.markdown | 6 +++--- .../py_surf_intro/py_surf_intro.markdown | 12 ++++++------ 6 files changed, 19 insertions(+), 17 deletions(-) diff --git a/doc/py_tutorials/py_feature2d/py_brief/py_brief.markdown b/doc/py_tutorials/py_feature2d/py_brief/py_brief.markdown index f1fc1e0ec..e2c0ed428 100644 --- a/doc/py_tutorials/py_feature2d/py_brief/py_brief.markdown +++ b/doc/py_tutorials/py_feature2d/py_brief/py_brief.markdown @@ -48,6 +48,8 @@ BRIEF in OpenCV Below code shows the computation of BRIEF descriptors with the help of CenSurE detector. (CenSurE detector is called STAR detector in OpenCV) + +note, that you need [opencv contrib](https://github.com/Itseez/opencv_contrib)) to use this. @code{.py} import numpy as np import cv2 @@ -55,11 +57,11 @@ from matplotlib import pyplot as plt img = cv2.imread('simple.jpg',0) -# Initiate STAR detector -star = cv2.FeatureDetector_create("STAR") +# Initiate FAST detector +star = cv2.xfeatures2d.StarDetector_create() # Initiate BRIEF extractor -brief = cv2.DescriptorExtractor_create("BRIEF") +brief = cv2.BriefDescriptorExtractor_create() # find the keypoints with STAR kp = star.detect(img,None) diff --git a/doc/py_tutorials/py_feature2d/py_fast/py_fast.markdown b/doc/py_tutorials/py_feature2d/py_fast/py_fast.markdown index aa45c325d..1534c57ac 100644 --- a/doc/py_tutorials/py_feature2d/py_fast/py_fast.markdown +++ b/doc/py_tutorials/py_feature2d/py_fast/py_fast.markdown @@ -101,7 +101,7 @@ from matplotlib import pyplot as plt img = cv2.imread('simple.jpg',0) # Initiate FAST object with default values -fast = cv2.FastFeatureDetector() +fast = cv2.FastFeatureDetector_create() # find and draw the keypoints kp = fast.detect(img,None) diff --git a/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.markdown b/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.markdown index 4f5a3234d..4f5efa4a8 100644 --- a/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.markdown +++ b/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.markdown @@ -44,7 +44,7 @@ img1 = cv2.imread('box.png',0) # queryImage img2 = cv2.imread('box_in_scene.png',0) # trainImage # Initiate SIFT detector -sift = cv2.SIFT() +sift = cv2.xfeatures2d.SIFT_create() # find the keypoints and descriptors with SIFT kp1, des1 = sift.detectAndCompute(img1,None) @@ -78,7 +78,7 @@ if len(good)>MIN_MATCH_COUNT: M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0) matchesMask = mask.ravel().tolist() - h,w = img1.shape + h,w,d = img1.shape pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2) dst = cv2.perspectiveTransform(pts,M) diff --git a/doc/py_tutorials/py_feature2d/py_orb/py_orb.markdown b/doc/py_tutorials/py_feature2d/py_orb/py_orb.markdown index 8130f39ab..c1917eb1a 100644 --- a/doc/py_tutorials/py_feature2d/py_orb/py_orb.markdown +++ b/doc/py_tutorials/py_feature2d/py_orb/py_orb.markdown @@ -69,8 +69,8 @@ from matplotlib import pyplot as plt img = cv2.imread('simple.jpg',0) -# Initiate STAR detector -orb = cv2.ORB() +# Initiate ORB detector +orb = cv2.ORB_create() # find the keypoints with ORB kp = orb.detect(img,None) diff --git a/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown b/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown index 05226d58e..b12505adc 100644 --- a/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown +++ b/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown @@ -104,7 +104,7 @@ greater than 0.8, they are rejected. It eliminaters around 90% of false matches So this is a summary of SIFT algorithm. For more details and understanding, reading the original paper is highly recommended. Remember one thing, this algorithm is patented. So this algorithm is -included in Non-free module in OpenCV. +included in [the opencv contrib repo](https://github.com/Itseez/opencv_contrib) SIFT in OpenCV -------------- @@ -119,7 +119,7 @@ import numpy as np img = cv2.imread('home.jpg') gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) -sift = cv2.SIFT() +sift = cv2.xfeatures2d.SIFT_create() kp = sift.detect(gray,None) img=cv2.drawKeypoints(gray,kp) @@ -151,7 +151,7 @@ Now to calculate the descriptor, OpenCV provides two methods. We will see the second method: @code{.py} -sift = cv2.SIFT() +sift = cv2.xfeatures2d.SIFT_create() kp, des = sift.detectAndCompute(gray,None) @endcode Here kp will be a list of keypoints and des is a numpy array of shape diff --git a/doc/py_tutorials/py_feature2d/py_surf_intro/py_surf_intro.markdown b/doc/py_tutorials/py_feature2d/py_surf_intro/py_surf_intro.markdown index 21998fede..7d5bd93fe 100644 --- a/doc/py_tutorials/py_feature2d/py_surf_intro/py_surf_intro.markdown +++ b/doc/py_tutorials/py_feature2d/py_surf_intro/py_surf_intro.markdown @@ -80,7 +80,7 @@ examples are shown in Python terminal since it is just same as SIFT only. # Create SURF object. You can specify params here or later. # Here I set Hessian Threshold to 400 ->>> surf = cv2.SURF(400) +>>> surf = cv2.xfeatures2d.SURF_create(400) # Find keypoints and descriptors directly >>> kp, des = surf.detectAndCompute(img,None) @@ -92,12 +92,12 @@ examples are shown in Python terminal since it is just same as SIFT only. While matching, we may need all those features, but not now. So we increase the Hessian Threshold. @code{.py} # Check present Hessian threshold ->>> print surf.hessianThreshold +>>> print surf.getHessianThreshold() 400.0 # We set it to some 50000. Remember, it is just for representing in picture. # In actual cases, it is better to have a value 300-500 ->>> surf.hessianThreshold = 50000 +>>> surf.setHessianThreshold(50000) # Again compute keypoints and check its number. >>> kp, des = surf.detectAndCompute(img,None) @@ -119,10 +119,10 @@ on wings of butterfly. You can test it with other images. Now I want to apply U-SURF, so that it won't find the orientation. @code{.py} # Check upright flag, if it False, set it to True ->>> print surf.upright +>>> print surf.getUpright() False ->>> surf.upright = True +>>> surf.setUpright(True) # Recompute the feature points and draw it >>> kp = surf.detect(img,None) @@ -143,7 +143,7 @@ Finally we check the descriptor size and change it to 128 if it is only 64-dim. 64 # That means flag, "extended" is False. ->>> surf.extended +>>> surf.getExtended() False # So we make it to True to get 128-dim descriptors. From 31e0d90da699344a1f3a1ce2ff4ad585a9ab4e6b Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Thu, 22 Oct 2015 12:44:03 +0300 Subject: [PATCH 150/156] Enable temp objects destruction test for VS versions less than 2015 --- modules/core/test/test_umat.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/core/test/test_umat.cpp b/modules/core/test/test_umat.cpp index fe64d2f94..6afd432cf 100644 --- a/modules/core/test/test_umat.cpp +++ b/modules/core/test/test_umat.cpp @@ -1302,7 +1302,11 @@ TEST(UMat, testTempObjects_UMat) // C++11 is enabled by default ==> // destructors have implicit 'noexcept(true)' specifier ==> // throwing exception from destructor is not handled correctly +#if defined(_MSC_VER) && _MSC_VER >= 1900 /* MSVC 14 */ TEST(UMat, DISABLED_testTempObjects_Mat) +#else +TEST(UMat, testTempObjects_Mat) +#endif { Mat m(10, 10, CV_8UC1, Scalar(1)); { From 0ef73872982fdc4080471d2612f687d00ac28a8b Mon Sep 17 00:00:00 2001 From: Rodrigo Benenson Date: Thu, 22 Oct 2015 23:27:55 +0200 Subject: [PATCH 151/156] mush -> must fixed typo --- modules/imgproc/src/grabcut.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/grabcut.cpp b/modules/imgproc/src/grabcut.cpp index c0967a1dc..36356beb4 100644 --- a/modules/imgproc/src/grabcut.cpp +++ b/modules/imgproc/src/grabcut.cpp @@ -537,7 +537,7 @@ void cv::grabCut( InputArray _img, InputOutputArray _mask, Rect rect, if( img.empty() ) CV_Error( CV_StsBadArg, "image is empty" ); if( img.type() != CV_8UC3 ) - CV_Error( CV_StsBadArg, "image mush have CV_8UC3 type" ); + CV_Error( CV_StsBadArg, "image must have CV_8UC3 type" ); GMM bgdGMM( bgdModel ), fgdGMM( fgdModel ); Mat compIdxs( img.size(), CV_32SC1 ); From 0a306f88047586356548335f5e8c9697ce43b8fc Mon Sep 17 00:00:00 2001 From: micalan Date: Sun, 11 Oct 2015 10:08:32 +0300 Subject: [PATCH 152/156] Camera orientation handling is added for jpeg files --- modules/imgcodecs/CMakeLists.txt | 2 + modules/imgcodecs/src/grfmt_jpeg.cpp | 56 +++ modules/imgcodecs/src/grfmt_jpeg.hpp | 6 + modules/imgcodecs/src/jpeg_exif.cpp | 582 ++++++++++++++++++++++++++ modules/imgcodecs/src/jpeg_exif.hpp | 251 +++++++++++ modules/imgcodecs/test/test_grfmt.cpp | 145 +++++++ 6 files changed, 1042 insertions(+) create mode 100644 modules/imgcodecs/src/jpeg_exif.cpp create mode 100644 modules/imgcodecs/src/jpeg_exif.hpp diff --git a/modules/imgcodecs/CMakeLists.txt b/modules/imgcodecs/CMakeLists.txt index 6d565217a..7b3fc0bd7 100644 --- a/modules/imgcodecs/CMakeLists.txt +++ b/modules/imgcodecs/CMakeLists.txt @@ -61,6 +61,8 @@ list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/bitstrm.hpp) list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/bitstrm.cpp) list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/rgbe.hpp) list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/rgbe.cpp) +list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/jpeg_exif.hpp) +list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/jpeg_exif.cpp) source_group("Src\\grfmts" FILES ${grfmt_hdrs} ${grfmt_srcs}) diff --git a/modules/imgcodecs/src/grfmt_jpeg.cpp b/modules/imgcodecs/src/grfmt_jpeg.cpp index 6502db941..6862a06eb 100644 --- a/modules/imgcodecs/src/grfmt_jpeg.cpp +++ b/modules/imgcodecs/src/grfmt_jpeg.cpp @@ -41,6 +41,7 @@ #include "precomp.hpp" #include "grfmt_jpeg.hpp" +#include "jpeg_exif.hpp" #ifdef HAVE_JPEG @@ -177,6 +178,7 @@ JpegDecoder::JpegDecoder() m_state = 0; m_f = 0; m_buf_supported = true; + m_orientation = JPEG_ORIENTATION_TL; } @@ -253,12 +255,64 @@ bool JpegDecoder::readHeader() } } + m_orientation = getOrientation(); + if( !result ) close(); return result; } +int JpegDecoder::getOrientation() +{ + int orientation = JPEG_ORIENTATION_TL; + + ExifReader reader( m_filename ); + if( reader.parse() ) + { + orientation = reader.getTag( ORIENTATION ).field_u16;//orientation is unsigned short, so check field_u16 + } + + return orientation; +} + +void JpegDecoder::setOrientation(Mat& img) +{ + switch( m_orientation ) + { + case JPEG_ORIENTATION_TL: //0th row == visual top, 0th column == visual left-hand side + //do nothing, the image already has proper orientation + break; + case JPEG_ORIENTATION_TR: //0th row == visual top, 0th column == visual right-hand side + flip(img, img, 1); //flip horizontally + break; + case JPEG_ORIENTATION_BR: //0th row == visual bottom, 0th column == visual right-hand side + flip(img, img, -1);//flip both horizontally and vertically + break; + case JPEG_ORIENTATION_BL: //0th row == visual bottom, 0th column == visual left-hand side + flip(img, img, 0); //flip vertically + break; + case JPEG_ORIENTATION_LT: //0th row == visual left-hand side, 0th column == visual top + transpose(img, img); + break; + case JPEG_ORIENTATION_RT: //0th row == visual right-hand side, 0th column == visual top + transpose(img, img); + flip(img, img, 1); //flip horizontally + break; + case JPEG_ORIENTATION_RB: //0th row == visual right-hand side, 0th column == visual bottom + transpose(img, img); + flip(img, img, -1); //flip both horizontally and vertically + break; + case JPEG_ORIENTATION_LB: //0th row == visual left-hand side, 0th column == visual bottom + transpose(img, img); + flip(img, img, 0); //flip vertically + break; + default: + //by default the image read has normal (JPEG_ORIENTATION_TL) orientation + break; + } +} + /*************************************************************************** * following code is for supporting MJPEG image files * based on a message of Laurent Pinchart on the video4linux mailing list @@ -472,8 +526,10 @@ bool JpegDecoder::readData( Mat& img ) icvCvt_CMYK2Gray_8u_C4C1R( buffer[0], 0, data, 0, cvSize(m_width,1) ); } } + result = true; jpeg_finish_decompress( cinfo ); + setOrientation( img ); } } diff --git a/modules/imgcodecs/src/grfmt_jpeg.hpp b/modules/imgcodecs/src/grfmt_jpeg.hpp index 8455b197b..d0a0991c5 100644 --- a/modules/imgcodecs/src/grfmt_jpeg.hpp +++ b/modules/imgcodecs/src/grfmt_jpeg.hpp @@ -70,6 +70,12 @@ protected: FILE* m_f; void* m_state; + +private: + //Support for handling exif orientation tag in Jpeg file + int m_orientation; + int getOrientation(); + void setOrientation(Mat& img); }; diff --git a/modules/imgcodecs/src/jpeg_exif.cpp b/modules/imgcodecs/src/jpeg_exif.cpp new file mode 100644 index 000000000..caade4803 --- /dev/null +++ b/modules/imgcodecs/src/jpeg_exif.cpp @@ -0,0 +1,582 @@ +/*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. +// 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 "jpeg_exif.hpp" + +namespace cv +{ + +/** + * @brief ExifReader constructor + */ +ExifReader::ExifReader(std::string filename) : m_filename(filename) +{ +} + +/** + * @brief ExifReader destructor + */ +ExifReader::~ExifReader() +{ +} + +/** + * @brief Parsing the jpeg file and prepare (internally) exif directory structure + * @return true if parsing was successful and exif information exists in JpegReader object + * false in case of unsuccessful parsing + */ +bool ExifReader::parse() +{ + m_exif = getExif(); + if( !m_exif.empty() ) + { + return true; + } + return false; +} + + +/** + * @brief Get tag value by tag number + * + * @param [in] tag The tag number + * + * @return ExifEntru_t structure. Caller has to know what tag it calls in order to extract proper field from the structure ExifEntry_t + * + */ +ExifEntry_t ExifReader::getTag(const ExifTagName tag) +{ + ExifEntry_t entry; + std::map::iterator it = m_exif.find(tag); + + if( it != m_exif.end() ) + { + entry = it->second; + } + return entry; +} + + +/** + * @brief Get exif directory structure contained in jpeg file (if any) + * This is internal function and is not exposed to client + * + * @return Map where key is tag number and value is ExifEntry_t structure + */ +std::map ExifReader::getExif() +{ + const size_t markerSize = 2; + const size_t offsetToTiffHeader = 6; //bytes from Exif size field to the first TIFF header + unsigned char appMarker[markerSize]; + m_exif.erase( m_exif.begin(), m_exif.end() ); + + size_t count; + + FILE* f = fopen( m_filename.c_str(), "rb" ); + + if( !f ) + { + return m_exif; //Until this moment the map is empty + } + + bool exifFound = false; + while( ( !feof( f ) ) && !exifFound ) + { + count = fread( appMarker, sizeof(unsigned char), markerSize, f ); + if( count < markerSize ) + { + break; + } + unsigned char marker = appMarker[1]; + size_t bytesToSkip; + size_t exifSize; + switch( marker ) + { + //For all the markers just skip bytes in file pointed by followed two bytes (field size) + case SOF0: case SOF2: case DHT: case DQT: case DRI: case SOS: + case RST0: case RST1: case RST2: case RST3: case RST4: case RST5: case RST6: case RST7: + case APP0: case APP2: case APP3: case APP4: case APP5: case APP6: case APP7: case APP8: + case APP9: case APP10: case APP11: case APP12: case APP13: case APP14: case APP15: + case COM: + bytesToSkip = getFieldSize( f ); + fseek( f, static_cast( bytesToSkip - markerSize ), SEEK_CUR ); + break; + + //SOI and EOI don't have the size field after the marker + case SOI: case EOI: + break; + + case APP1: //actual Exif Marker + exifSize = getFieldSize(f); + m_data.resize( exifSize - offsetToTiffHeader ); + fseek(f, static_cast( offsetToTiffHeader ), SEEK_CUR); + count = fread( &m_data[0], sizeof( unsigned char ), exifSize - offsetToTiffHeader, f ); + exifFound = true; + break; + + default: //No other markers are expected according to standard. May be a signal of error + break; + } + } + + fclose(f); + + if( !exifFound ) + { + return m_exif; + } + + parseExif(); + + return m_exif; +} + +/** + * @brief Get the size of exif field (required to properly ready whole exif from the file) + * This is internal function and is not exposed to client + * + * @return size of exif field in the file + */ +size_t ExifReader::getFieldSize (FILE* f) const +{ + unsigned char fieldSize[2]; + size_t count = fread ( fieldSize, sizeof( char ), 2, f ); + if (count < 2) + { + return 0; + } + return ( fieldSize[0] << 8 ) + fieldSize[1]; +} + +/** + * @brief Filling m_exif member with exif directory elements + * This is internal function and is not exposed to client + * + * @return The function doesn't return any value. In case of unsiccessful parsing + * the m_exif member is not filled up + */ +void ExifReader::parseExif() +{ + m_format = getFormat(); + + if( !checkTagMark() ) + { + return; + } + + uint32_t offset = getStartOffset(); + + size_t numEntry = getNumDirEntry(); + + offset += 2; //go to start of tag fields + + for( size_t entry = 0; entry < numEntry; entry++ ) + { + ExifEntry_t exifEntry = parseExifEntry( offset ); + m_exif.insert( std::make_pair( exifEntry.tag, exifEntry ) ); + offset += tiffFieldSize; + } +} + +/** + * @brief Get endianness of exif information + * This is internal function and is not exposed to client + * + * @return INTEL, MOTO or NONE + */ +Endianess_t ExifReader::getFormat() const +{ + if( m_data[0] != m_data[1] ) + { + return NONE; + } + + if( m_data[0] == 'I' ) + { + return INTEL; + } + + if( m_data[0] == 'M' ) + { + return MOTO; + } + + return NONE; +} + +/** + * @brief Checking whether Tag Mark (0x002A) correspond to one contained in the Jpeg file + * This is internal function and is not exposed to client + * + * @return true if tag mark equals 0x002A, false otherwise + */ +bool ExifReader::checkTagMark() const +{ + uint16_t tagMark = getU16( 2 ); + + if( tagMark != tagMarkRequired ) + { + return false; + } + return true; +} + +/** + * @brief The utility function for extracting actual offset exif IFD0 info is started from + * This is internal function and is not exposed to client + * + * @return offset of IFD0 field + */ +uint32_t ExifReader::getStartOffset() const +{ + return getU32( 4 ); +} + +/** + * @brief Get the number of Directory Entries in Jpeg file + * + * @return The number of directory entries + */ +size_t ExifReader::getNumDirEntry() const +{ + return getU16( offsetNumDir ); +} + +/** + * @brief Parsing particular entry in exif directory + * This is internal function and is not exposed to client + * + * Entries are divided into 12-bytes blocks each + * Each block corresponds the following structure: + * + * +------+-------------+-------------------+------------------------+ + * | Type | Data format | Num of components | Data or offset to data | + * +======+=============+===================+========================+ + * | TTTT | ffff | NNNNNNNN | DDDDDDDD | + * +------+-------------+-------------------+------------------------+ + * + * Details can be found here: http://www.media.mit.edu/pia/Research/deepview/exif.html + * + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return ExifEntry_t structure which corresponds to particular entry + * + */ +ExifEntry_t ExifReader::parseExifEntry(const size_t offset) +{ + ExifEntry_t entry; + uint16_t tagNum = getExifTag( offset ); + entry.tag = tagNum; + + switch( tagNum ) + { + case IMAGE_DESCRIPTION: + entry.field_str = getString( offset ); + break; + case MAKE: + entry.field_str = getString( offset ); + break; + case MODEL: + entry.field_str = getString( offset ); + break; + case ORIENTATION: + entry.field_u16 = getOrientation( offset ); + break; + case XRESOLUTION: + entry.field_u_rational = getResolution( offset ); + break; + case YRESOLUTION: + entry.field_u_rational = getResolution( offset ); + break; + case RESOLUTION_UNIT: + entry.field_u16 = getResolutionUnit( offset ); + break; + case SOFTWARE: + entry.field_str = getString( offset ); + break; + case DATE_TIME: + entry.field_str = getString( offset ); + break; + case WHITE_POINT: + entry.field_u_rational = getWhitePoint( offset ); + break; + case PRIMARY_CHROMATICIES: + entry.field_u_rational = getPrimaryChromaticies( offset ); + break; + case Y_CB_CR_COEFFICIENTS: + entry.field_u_rational = getYCbCrCoeffs( offset ); + break; + case Y_CB_CR_POSITIONING: + entry.field_u16 = getYCbCrPos( offset ); + break; + case REFERENCE_BLACK_WHITE: + entry.field_u_rational = getRefBW( offset ); + break; + case COPYRIGHT: + entry.field_str = getString( offset ); + break; + case EXIF_OFFSET: + break; + default: + entry.tag = INVALID_TAG; + break; + } + return entry; +} + +/** + * @brief Get tag number from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return tag number + */ +uint16_t ExifReader::getExifTag(const size_t offset) const +{ + return getU16( offset ); +} + +/** + * @brief Get string information from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return string value + */ +std::string ExifReader::getString(const size_t offset) const +{ + size_t size = getU32( offset + 4 ); + size_t dataOffset = 8; // position of data in the field + if( size > maxDataSize ) + { + dataOffset = getU32( offset + 8 ); + } + std::vector::const_iterator it = m_data.begin() + dataOffset; + std::string result( it, it + size ); //copy vector content into result + + return result; +} + +/** + * @brief Get unsigned short data from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return Unsigned short data + */ +uint16_t ExifReader::getU16(const size_t offset) const +{ + if( m_format == INTEL ) + { + return m_data[offset] + ( m_data[offset + 1] << 8 ); + } + return ( m_data[offset] << 8 ) + m_data[offset + 1]; +} + +/** + * @brief Get unsigned 32-bit data from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return Unsigned 32-bit data + */ +uint32_t ExifReader::getU32(const size_t offset) const +{ + if( m_format == INTEL ) + { + return m_data[offset] + + ( m_data[offset + 1] << 8 ) + + ( m_data[offset + 2] << 16 ) + + ( m_data[offset + 3] << 24 ); + } + + return ( m_data[offset] << 24 ) + + ( m_data[offset + 1] << 16 ) + + ( m_data[offset + 2] << 8 ) + + m_data[offset + 3]; +} + +/** + * @brief Get unsigned rational data from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return Unsigned rational data + * + * "rational" means a fractional value, it contains 2 signed/unsigned long integer value, + * and the first represents the numerator, the second, the denominator. + */ +u_rational_t ExifReader::getURational(const size_t offset) const +{ + u_rational_t result; + uint32_t numerator = getU32( offset ); + uint32_t denominator = getU32( offset + 4 ); + + return std::make_pair( numerator, denominator ); + +} + +/** + * @brief Get orientation information from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return orientation number + */ +uint16_t ExifReader::getOrientation(const size_t offset) const +{ + return getU16( offset + 8 ); +} + +/** + * @brief Get resolution information from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return resolution value + */ +std::vector ExifReader::getResolution(const size_t offset) const +{ + std::vector result; + uint32_t rationalOffset = getU32( offset + 8 ); + result.push_back( getURational( rationalOffset ) ); + + return result; +} + +/** + * @brief Get resolution unit from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return resolution unit value + */ +uint16_t ExifReader::getResolutionUnit(const size_t offset) const +{ + return getU16( offset + 8 ); +} + +/** + * @brief Get White Point information from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return White Point value + * + * If the image uses CIE Standard Illumination D65(known as international + * standard of 'daylight'), the values are '3127/10000,3290/10000'. + */ +std::vector ExifReader::getWhitePoint(const size_t offset) const +{ + std::vector result; + uint32_t rationalOffset = getU32( offset + 8 ); + result.push_back( getURational( rationalOffset ) ); + result.push_back( getURational( rationalOffset + 8 ) ); + + return result; +} + +/** + * @brief Get Primary Chromaticies information from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return vector with primary chromaticies values + * + */ +std::vector ExifReader::getPrimaryChromaticies(const size_t offset) const +{ + std::vector result; + uint32_t rationalOffset = getU32( offset + 8 ); + for( size_t i = 0; i < primaryChromaticiesComponents; i++ ) + { + result.push_back( getURational( rationalOffset ) ); + rationalOffset += 8; + } + return result; +} + +/** + * @brief Get YCbCr Coefficients information from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return vector with YCbCr coefficients values + * + */ +std::vector ExifReader::getYCbCrCoeffs(const size_t offset) const +{ + std::vector result; + uint32_t rationalOffset = getU32( offset + 8 ); + for( size_t i = 0; i < ycbcrCoeffs; i++ ) + { + result.push_back( getURational( rationalOffset ) ); + rationalOffset += 8; + } + return result; +} + +/** + * @brief Get YCbCr Positioning information from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return vector with YCbCr positioning value + * + */ +uint16_t ExifReader::getYCbCrPos(const size_t offset) const +{ + return getU16( offset + 8 ); +} + +/** + * @brief Get Reference Black&White point information from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return vector with reference BW points + * + * In case of YCbCr format, first 2 show black/white of Y, next 2 are Cb, + * last 2 are Cr. In case of RGB format, first 2 show black/white of R, + * next 2 are G, last 2 are B. + * + */ +std::vector ExifReader::getRefBW(const size_t offset) const +{ + const size_t rationalFieldSize = 8; + std::vector result; + uint32_t rationalOffset = getU32( offset + rationalFieldSize ); + for( size_t i = 0; i < refBWComponents; i++ ) + { + result.push_back( getURational( rationalOffset ) ); + rationalOffset += rationalFieldSize; + } + return result; +} + +} //namespace cv diff --git a/modules/imgcodecs/src/jpeg_exif.hpp b/modules/imgcodecs/src/jpeg_exif.hpp new file mode 100644 index 000000000..9ca138167 --- /dev/null +++ b/modules/imgcodecs/src/jpeg_exif.hpp @@ -0,0 +1,251 @@ +/*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. +// 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_JPEG_EXIF_HPP_ +#define _OPENCV_JPEG_EXIF_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +namespace cv +{ +/** + * @brief Jpeg markers that can encounter in Jpeg file + */ +enum AppMarkerTypes +{ + SOI = 0xD8, SOF0 = 0xC0, SOF2 = 0xC2, DHT = 0xC4, + DQT = 0xDB, DRI = 0xDD, SOS = 0xDA, + + RST0 = 0xD0, RST1 = 0xD1, RST2 = 0xD2, RST3 = 0xD3, + RST4 = 0xD4, RST5 = 0xD5, RST6 = 0xD6, RST7 = 0xD7, + + APP0 = 0xE0, APP1 = 0xE1, APP2 = 0xE2, APP3 = 0xE3, + APP4 = 0xE4, APP5 = 0xE5, APP6 = 0xE6, APP7 = 0xE7, + APP8 = 0xE8, APP9 = 0xE9, APP10 = 0xEA, APP11 = 0xEB, + APP12 = 0xEC, APP13 = 0xED, APP14 = 0xEE, APP15 = 0xEF, + + COM = 0xFE, EOI = 0xD9 +}; + +/** + * @brief Base Exif tags used by IFD0 (main image) + */ +enum ExifTagName +{ + IMAGE_DESCRIPTION = 0x010E, ///< Image Description: ASCII string + MAKE = 0x010F, ///< Description of manufacturer: ASCII string + MODEL = 0x0110, ///< Description of camera model: ASCII string + ORIENTATION = 0x0112, ///< Orientation of the image: unsigned short + XRESOLUTION = 0x011A, ///< Resolution of the image across X axis: unsigned rational + YRESOLUTION = 0x011B, ///< Resolution of the image across Y axis: unsigned rational + RESOLUTION_UNIT = 0x0128, ///< Resolution units. '1' no-unit, '2' inch, '3' centimeter + SOFTWARE = 0x0131, ///< Shows firmware(internal software of digicam) version number + DATE_TIME = 0x0132, ///< Date/Time of image was last modified + WHITE_POINT = 0x013E, ///< Chromaticity of white point of the image + PRIMARY_CHROMATICIES = 0x013F, ///< Chromaticity of the primaries of the image + Y_CB_CR_COEFFICIENTS = 0x0211, ///< constant to translate an image from YCbCr to RGB format + Y_CB_CR_POSITIONING = 0x0213, ///< Chroma sample point of subsampling pixel array + REFERENCE_BLACK_WHITE = 0x0214, ///< Reference value of black point/white point + COPYRIGHT = 0x8298, ///< Copyright information + EXIF_OFFSET = 0x8769, ///< Offset to Exif Sub IFD + INVALID_TAG = 0xFFFF ///< Shows that the tag was not recognized +}; + +enum Endianess_t +{ + INTEL = 0x49, + MOTO = 0x4D, + NONE = 0x00 +}; + +typedef std::pair u_rational_t; + +/** + * @brief Entry which contains possible values for different exif tags + */ +struct ExifEntry_t +{ + std::vector field_u_rational; ///< vector of rational fields + std::string field_str; ///< any kind of textual information + + float field_float; ///< Currently is not used + double field_double; ///< Currently is not used + + uint32_t field_u32; ///< Unsigned 32-bit value + int32_t field_s32; ///< Signed 32-bit value + + uint16_t tag; ///< Tag number + + uint16_t field_u16; ///< Unsigned 16-bit value + int16_t field_s16; ///< Signed 16-bit value + uint8_t field_u8; ///< Unsigned 8-bit value + int8_t field_s8; ///< Signed 8-bit value +}; + +/** + * @brief Picture orientation which may be taken from JPEG's EXIF + * Orientation usually matters when the picture is taken by + * smartphone or other camera with orientation sensor support + * Corresponds to EXIF 2.3 Specification + */ +enum JpegOrientation +{ + JPEG_ORIENTATION_TL = 1, ///< 0th row == visual top, 0th column == visual left-hand side + JPEG_ORIENTATION_TR = 2, ///< 0th row == visual top, 0th column == visual right-hand side + JPEG_ORIENTATION_BR = 3, ///< 0th row == visual bottom, 0th column == visual right-hand side + JPEG_ORIENTATION_BL = 4, ///< 0th row == visual bottom, 0th column == visual left-hand side + JPEG_ORIENTATION_LT = 5, ///< 0th row == visual left-hand side, 0th column == visual top + JPEG_ORIENTATION_RT = 6, ///< 0th row == visual right-hand side, 0th column == visual top + JPEG_ORIENTATION_RB = 7, ///< 0th row == visual right-hand side, 0th column == visual bottom + JPEG_ORIENTATION_LB = 8 ///< 0th row == visual left-hand side, 0th column == visual bottom +}; + +/** + * @brief Reading exif information from Jpeg file + * + * Usage example for getting the orientation of the image: + * + * @code + * ExifReader reader(fileName); + * if( reader.parse() ) + * { + * int orientation = reader.getTag(Orientation).field_u16; + * } + * @endcode + * + */ +class ExifReader +{ +public: + /** + * @brief ExifReader constructor. Constructs an object of exif reader + * + * @param [in]filename The name of file to look exif info in + */ + explicit ExifReader( std::string filename ); + ~ExifReader(); + + + /** + * @brief Parse the file with exif info + * + * @return true if parsing was successful and exif information exists in JpegReader object + */ + bool parse(); + + /** + * @brief Get tag info by tag number + * + * @param [in] tag The tag number + * @return ExifEntru_t structure. Caller has to know what tag it calls in order to extract proper field from the structure ExifEntry_t + */ + ExifEntry_t getTag( const ExifTagName tag ); + +private: + std::string m_filename; + std::vector m_data; + std::map m_exif; + Endianess_t m_format; + + void parseExif(); + bool checkTagMark() const; + + size_t getFieldSize ( FILE* f ) const; + size_t getNumDirEntry() const; + uint32_t getStartOffset() const; + uint16_t getExifTag( const size_t offset ) const; + uint16_t getU16( const size_t offset ) const; + uint32_t getU32( const size_t offset ) const; + uint16_t getOrientation( const size_t offset ) const; + uint16_t getResolutionUnit( const size_t offset ) const; + uint16_t getYCbCrPos( const size_t offset ) const; + + Endianess_t getFormat() const; + + ExifEntry_t parseExifEntry( const size_t offset ); + + u_rational_t getURational( const size_t offset ) const; + + std::map getExif(); + std::string getString( const size_t offset ) const; + std::vector getResolution( const size_t offset ) const; + std::vector getWhitePoint( const size_t offset ) const; + std::vector getPrimaryChromaticies( const size_t offset ) const; + std::vector getYCbCrCoeffs( const size_t offset ) const; + std::vector getRefBW( const size_t offset ) const; + +private: + static const uint16_t tagMarkRequired = 0x2A; + + //offset to the _number-of-directory-entry_ field + static const size_t offsetNumDir = 8; + + //max size of data in tag. + //'DDDDDDDD' contains the value of that Tag. If its size is over 4bytes, + //'DDDDDDDD' contains the offset to data stored address. + static const size_t maxDataSize = 4; + + //bytes per tag field + static const size_t tiffFieldSize = 12; + + //number of primary chromaticies components + static const size_t primaryChromaticiesComponents = 6; + + //number of YCbCr coefficients in field + static const size_t ycbcrCoeffs = 3; + + //number of Reference Black&White components + static const size_t refBWComponents = 6; +}; + + + +} + +#endif /* JPEG_EXIF_HPP_ */ diff --git a/modules/imgcodecs/test/test_grfmt.cpp b/modules/imgcodecs/test/test_grfmt.cpp index ae0b428ec..f305ca137 100644 --- a/modules/imgcodecs/test/test_grfmt.cpp +++ b/modules/imgcodecs/test/test_grfmt.cpp @@ -43,6 +43,7 @@ #include "test_precomp.hpp" #include +#include using namespace cv; using namespace std; @@ -118,6 +119,150 @@ TEST(Imgcodecs_imread, regression) } } +template +string to_string(T i) +{ + stringstream ss; + string s; + ss << i; + s = ss.str(); + + return s; +} + + +/** + * Test for check whether reading exif orientation tag was processed successfully or not + * The test info is the set of 8 images named testExifRotate_{1 to 8}.jpg + * The test image is the square 10x10 points divided by four sub-squares: + * (R corresponds to Red, G to Green, B to Blue, W to white) + * --------- --------- + * | R | G | | G | R | + * |-------| - (tag 1) |-------| - (tag 2) + * | B | W | | W | B | + * --------- --------- + * + * --------- --------- + * | W | B | | B | W | + * |-------| - (tag 3) |-------| - (tag 4) + * | G | R | | R | G | + * --------- --------- + * + * --------- --------- + * | R | B | | G | W | + * |-------| - (tag 5) |-------| - (tag 6) + * | G | W | | R | B | + * --------- --------- + * + * --------- --------- + * | W | G | | B | R | + * |-------| - (tag 7) |-------| - (tag 8) + * | B | R | | W | G | + * --------- --------- + * + * + * Every image contains exif field with orientation tag (0x112) + * After reading each image the corresponding matrix must be read as + * --------- + * | R | G | + * |-------| + * | B | W | + * --------- + * + */ +class CV_GrfmtJpegExifOrientationTest : public cvtest::BaseTest +{ +public: + void run(int) + { + try + { + for( int i = 1; i <= 8; ++i) + { + string fileName = "readwrite/testExifOrientation_" + to_string(i) + ".jpg"; + m_img = imread(string(ts->get_data_path()) + fileName); + if( !m_img.data ) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + } + ts->printf(cvtest::TS::LOG, "start reading image\t%s\n", fileName.c_str()); + if( !checkOrientation() ) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); + } + } + + } + catch(...) + { + ts->set_failed_test_info(cvtest::TS::FAIL_EXCEPTION); + } + } +private: + bool checkOrientation(); + Mat m_img; +}; + + +bool CV_GrfmtJpegExifOrientationTest::checkOrientation() +{ + Vec3b vec; + int red = 0; + int green = 0; + int blue = 0; + + const int colorThresholdHigh = 250; + const int colorThresholdLow = 5; + + //Checking the first quadrant (with supposed red) + vec = m_img.at(2, 2); //some point inside the square + red = vec.val[2]; + green = vec.val[1]; + blue = vec.val[0]; + + ts->printf(cvtest::TS::LOG, "RED QUADRANT:\n"); + ts->printf(cvtest::TS::LOG, "Red calculated:\t\t%d\n", red); + ts->printf(cvtest::TS::LOG, "Green calculated:\t%d\n", green); + ts->printf(cvtest::TS::LOG, "Blue calculated:\t%d\n", blue); + if( red < colorThresholdHigh ) return false; + if( blue > colorThresholdLow ) return false; + if( green > colorThresholdLow ) return false; + + //Checking the second quadrant (with supposed green) + vec = m_img.at(2, 7); //some point inside the square + red = vec.val[2]; + green = vec.val[1]; + blue = vec.val[0]; + ts->printf(cvtest::TS::LOG, "GREEN QUADRANT:\n"); + ts->printf(cvtest::TS::LOG, "Red calculated:\t\t%d\n", red); + ts->printf(cvtest::TS::LOG, "Green calculated:\t%d\n", green); + ts->printf(cvtest::TS::LOG, "Blue calculated:\t%d\n", blue); + if( green < colorThresholdHigh ) return false; + if( red > colorThresholdLow ) return false; + if( blue > colorThresholdLow ) return false; + + //Checking the third quadrant (with supposed blue) + vec = m_img.at(7, 2); //some point inside the square + red = vec.val[2]; + green = vec.val[1]; + blue = vec.val[0]; + ts->printf(cvtest::TS::LOG, "BLUE QUADRANT:\n"); + ts->printf(cvtest::TS::LOG, "Red calculated:\t\t%d\n", red); + ts->printf(cvtest::TS::LOG, "Green calculated:\t%d\n", green); + ts->printf(cvtest::TS::LOG, "Blue calculated:\t%d\n", blue); + if( blue < colorThresholdHigh ) return false; + if( red > colorThresholdLow ) return false; + if( green > colorThresholdLow ) return false; + + return true; +} + +TEST(Imgcodecs_jpeg_exif, setOrientation) +{ + CV_GrfmtJpegExifOrientationTest test; + test.safe_run(); +} + #ifdef HAVE_JASPER TEST(Imgcodecs_jasper, regression) { From baa21484a1c1364e56e742a7ac1a82e6229940b0 Mon Sep 17 00:00:00 2001 From: Pierre Letessier Date: Wed, 21 Oct 2015 10:32:38 +0200 Subject: [PATCH 153/156] Added CV_CAP_PROP_SAR properties to videoio module --- .../include/opencv2/videoio/videoio_c.h | 2 ++ modules/videoio/src/cap_ffmpeg_api.hpp | 4 ++- modules/videoio/src/cap_ffmpeg_impl.hpp | 27 +++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/modules/videoio/include/opencv2/videoio/videoio_c.h b/modules/videoio/include/opencv2/videoio/videoio_c.h index 6d7bd640c..ae0259fe7 100644 --- a/modules/videoio/include/opencv2/videoio/videoio_c.h +++ b/modules/videoio/include/opencv2/videoio/videoio_c.h @@ -190,6 +190,8 @@ enum CV_CAP_PROP_SETTINGS =37, CV_CAP_PROP_BUFFERSIZE =38, CV_CAP_PROP_AUTOFOCUS =39, + CV_CAP_PROP_SAR_NUM =40, + CV_CAP_PROP_SAR_DEN =41, CV_CAP_PROP_AUTOGRAB =1024, // property for videoio class CvCapture_Android only CV_CAP_PROP_SUPPORTED_PREVIEW_SIZES_STRING=1025, // readonly, tricky property, returns cpnst char* indeed diff --git a/modules/videoio/src/cap_ffmpeg_api.hpp b/modules/videoio/src/cap_ffmpeg_api.hpp index e7a956063..55defce05 100644 --- a/modules/videoio/src/cap_ffmpeg_api.hpp +++ b/modules/videoio/src/cap_ffmpeg_api.hpp @@ -23,7 +23,9 @@ enum CV_FFMPEG_CAP_PROP_FRAME_HEIGHT=4, CV_FFMPEG_CAP_PROP_FPS=5, CV_FFMPEG_CAP_PROP_FOURCC=6, - CV_FFMPEG_CAP_PROP_FRAME_COUNT=7 + CV_FFMPEG_CAP_PROP_FRAME_COUNT=7, + CV_FFMPEG_CAP_PROP_SAR_NUM=39, + CV_FFMPEG_CAP_PROP_SAR_DEN=40 }; diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index 2615f3a49..ee1447e0f 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -250,6 +250,7 @@ struct CvCapture_FFMPEG double get_duration_sec() const; double get_fps() const; int get_bitrate() const; + AVRational get_sample_aspect_ratio(AVStream *stream) const; double r2d(AVRational r) const; int64_t dts_to_frame_number(int64_t dts); @@ -836,6 +837,10 @@ double CvCapture_FFMPEG::getProperty( int property_id ) const #else return (double)video_st->codec.codec_tag; #endif + case CV_FFMPEG_CAP_PROP_SAR_NUM: + return get_sample_aspect_ratio(ic->streams[video_stream]).num; + case CV_FFMPEG_CAP_PROP_SAR_DEN: + return get_sample_aspect_ratio(ic->streams[video_stream]).den; default: break; } @@ -910,6 +915,28 @@ int64_t CvCapture_FFMPEG::dts_to_frame_number(int64_t dts) return (int64_t)(get_fps() * sec + 0.5); } +AVRational CvCapture_FFMPEG::get_sample_aspect_ratio(AVStream *stream) const +{ + AVRational undef = {0, 1}; + AVRational stream_sample_aspect_ratio = stream ? stream->sample_aspect_ratio : undef; + AVRational frame_sample_aspect_ratio = stream && stream->codec ? stream->codec->sample_aspect_ratio : undef; + + av_reduce(&stream_sample_aspect_ratio.num, &stream_sample_aspect_ratio.den, + stream_sample_aspect_ratio.num, stream_sample_aspect_ratio.den, INT_MAX); + if (stream_sample_aspect_ratio.num <= 0 || stream_sample_aspect_ratio.den <= 0) + stream_sample_aspect_ratio = undef; + + av_reduce(&frame_sample_aspect_ratio.num, &frame_sample_aspect_ratio.den, + frame_sample_aspect_ratio.num, frame_sample_aspect_ratio.den, INT_MAX); + if (frame_sample_aspect_ratio.num <= 0 || frame_sample_aspect_ratio.den <= 0) + frame_sample_aspect_ratio = undef; + + if (stream_sample_aspect_ratio.num) + return stream_sample_aspect_ratio; + else + return frame_sample_aspect_ratio; +} + double CvCapture_FFMPEG::dts_to_sec(int64_t dts) { return (double)(dts - ic->streams[video_stream]->start_time) * From cfd498a8eb86e95515295ee42e63c7ed793b0b52 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Fri, 23 Oct 2015 21:42:11 +0200 Subject: [PATCH 154/156] fix compilation with qt QSlider does not have getMinimum/Maximum getters. Probably was not compile tested. --- modules/highgui/src/window_QT.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/highgui/src/window_QT.cpp b/modules/highgui/src/window_QT.cpp index 9d9877815..925bc222d 100644 --- a/modules/highgui/src/window_QT.cpp +++ b/modules/highgui/src/window_QT.cpp @@ -664,7 +664,7 @@ CV_IMPL void cvSetTrackbarMax(const char* name_bar, const char* window_name, int QPointer t = icvFindTrackBarByName(name_bar, window_name); if (t) { - int minval = t->slider->getMinimum(); + int minval = t->slider->minimum(); maxval = (maxval>minval)?maxval:minval; t->slider->setMaximum(maxval); } @@ -679,7 +679,7 @@ CV_IMPL void cvSetTrackbarMin(const char* name_bar, const char* window_name, int QPointer t = icvFindTrackBarByName(name_bar, window_name); if (t) { - int maxval = t->slider->getMaximum(); + int maxval = t->slider->maximum(); minval = (maxvalslider->setMinimum(minval); } From e6615c5825d0b88f2985e3302d25108f3fc48846 Mon Sep 17 00:00:00 2001 From: Pierre Letessier Date: Sat, 24 Oct 2015 11:22:18 +0200 Subject: [PATCH 155/156] Changed CV_FFMPEG_CAP_PROP_SAR_* values --- modules/videoio/src/cap_ffmpeg_api.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/videoio/src/cap_ffmpeg_api.hpp b/modules/videoio/src/cap_ffmpeg_api.hpp index 55defce05..0b7f45c8b 100644 --- a/modules/videoio/src/cap_ffmpeg_api.hpp +++ b/modules/videoio/src/cap_ffmpeg_api.hpp @@ -24,8 +24,8 @@ enum CV_FFMPEG_CAP_PROP_FPS=5, CV_FFMPEG_CAP_PROP_FOURCC=6, CV_FFMPEG_CAP_PROP_FRAME_COUNT=7, - CV_FFMPEG_CAP_PROP_SAR_NUM=39, - CV_FFMPEG_CAP_PROP_SAR_DEN=40 + CV_FFMPEG_CAP_PROP_SAR_NUM=40, + CV_FFMPEG_CAP_PROP_SAR_DEN=41 }; From 90c74e3be047b484a7902483cb8e9373c9bb65f0 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Tue, 15 Sep 2015 15:14:10 +0300 Subject: [PATCH 156/156] ts: refactor run.py script --- modules/ts/misc/run.py | 1045 ++++--------------------------- modules/ts/misc/run_android.py | 197 ++++++ modules/ts/misc/run_suite.py | 164 +++++ modules/ts/misc/run_utils.py | 447 +++++++++++++ platforms/scripts/valgrind.supp | 6 + 5 files changed, 920 insertions(+), 939 deletions(-) create mode 100644 modules/ts/misc/run_android.py create mode 100644 modules/ts/misc/run_suite.py create mode 100644 modules/ts/misc/run_utils.py create mode 100644 platforms/scripts/valgrind.supp diff --git a/modules/ts/misc/run.py b/modules/ts/misc/run.py index f25922d94..a3a13145a 100755 --- a/modules/ts/misc/run.py +++ b/modules/ts/misc/run.py @@ -1,940 +1,87 @@ #!/usr/bin/env python -import sys, os, platform, xml, re, tempfile, glob, datetime, getpass, shutil -from optparse import OptionParser -from subprocess import Popen, PIPE - -hostos = os.name # 'nt', 'posix' -hostmachine = platform.machine() # 'x86', 'AMD64', 'x86_64' - -errorCode = 0 - -SIMD_DETECTION_PROGRAM=""" -#if __SSE5__ -# error SSE5 -#endif -#if __AVX2__ -# error AVX2 -#endif -#if __AVX__ -# error AVX -#endif -#if __SSE4_2__ -# error SSE4.2 -#endif -#if __SSE4_1__ -# error SSE4.1 -#endif -#if __SSSE3__ -# error SSSE3 -#endif -#if __SSE3__ -# error SSE3 -#endif -#if __AES__ -# error AES -#endif -#if __SSE2__ -# error SSE2 -#endif -#if __SSE__ -# error SSE -#endif -#if __3dNOW__ -# error 3dNOW -#endif -#if __MMX__ -# error MMX -#endif -#if __ARM_NEON__ -# error NEON -#endif -#error NOSIMD -""" - -parse_patterns = ( - {'name': "has_perf_tests", 'default': "OFF", 'pattern': re.compile("^BUILD_PERF_TESTS:BOOL=(ON)$")}, - {'name': "has_accuracy_tests", 'default': "OFF", 'pattern': re.compile("^BUILD_TESTS:BOOL=(ON)$")}, - {'name': "cmake_home", 'default': None, 'pattern': re.compile("^CMAKE_HOME_DIRECTORY:INTERNAL=(.+)$")}, - {'name': "opencv_home", 'default': None, 'pattern': re.compile("^OpenCV_SOURCE_DIR:STATIC=(.+)$")}, - {'name': "tests_dir", 'default': None, 'pattern': re.compile("^EXECUTABLE_OUTPUT_PATH:PATH=(.+)$")}, - {'name': "build_type", 'default': "Release", 'pattern': re.compile("^CMAKE_BUILD_TYPE:STRING=(.*)$")}, - {'name': "svnversion_path", 'default': None, 'pattern': re.compile("^SVNVERSION_PATH:FILEPATH=(.*)$")}, - {'name': "git_executable", 'default': None, 'pattern': re.compile("^GIT_EXECUTABLE:FILEPATH=(.*)$")}, - {'name': "cxx_flags", 'default': "", 'pattern': re.compile("^CMAKE_CXX_FLAGS:STRING=(.*)$")}, - {'name': "cxx_flags_debug", 'default': "", 'pattern': re.compile("^CMAKE_CXX_FLAGS_DEBUG:STRING=(.*)$")}, - {'name': "cxx_flags_release", 'default': "", 'pattern': re.compile("^CMAKE_CXX_FLAGS_RELEASE:STRING=(.*)$")}, - {'name': "opencv_cxx_flags", 'default': "", 'pattern': re.compile("^OPENCV_EXTRA_C_FLAGS:INTERNAL=(.*)$")}, - {'name': "opencv_cxx_flags_debug", 'default': "", 'pattern': re.compile("^OPENCV_EXTRA_C_FLAGS_DEBUG:INTERNAL=(.*)$")}, - {'name': "opencv_cxx_flags_release", 'default': "", 'pattern': re.compile("^OPENCV_EXTRA_C_FLAGS_RELEASE:INTERNAL=(.*)$")}, - {'name': "cxx_flags_android", 'default': None, 'pattern': re.compile("^ANDROID_CXX_FLAGS:INTERNAL=(.*)$")}, - {'name': "ndk_path", 'default': None, 'pattern': re.compile("^(?:ANDROID_NDK|ANDROID_STANDALONE_TOOLCHAIN)?:PATH=(.*)$")}, - {'name': "android_abi", 'default': None, 'pattern': re.compile("^ANDROID_ABI:STRING=(.*)$")}, - {'name': "android_executable", 'default': None, 'pattern': re.compile("^ANDROID_EXECUTABLE:FILEPATH=(.*android.*)$")}, - {'name': "ant_executable", 'default': None, 'pattern': re.compile("^ANT_EXECUTABLE:FILEPATH=(.*ant.*)$")}, - {'name': "java_test_binary_dir", 'default': None, 'pattern': re.compile("^opencv_test_java_BINARY_DIR:STATIC=(.*)$")}, - {'name': "is_x64", 'default': "OFF", 'pattern': re.compile("^CUDA_64_BIT_DEVICE_CODE:BOOL=(ON)$")},#ugly( - {'name': "cmake_generator", 'default': None, 'pattern': re.compile("^CMAKE_GENERATOR:INTERNAL=(.+)$")}, - {'name': "cxx_compiler", 'default': None, 'pattern': re.compile("^CMAKE_CXX_COMPILER:FILEPATH=(.+)$")}, - {'name': "cxx_compiler_arg1", 'default': None, 'pattern': re.compile("^CMAKE_CXX_COMPILER_ARG1:[A-Z]+=(.+)$")}, - {'name': "with_cuda", 'default': "OFF", 'pattern': re.compile("^WITH_CUDA:BOOL=(ON)$")}, - {'name': "cuda_library", 'default': None, 'pattern': re.compile("^CUDA_CUDA_LIBRARY:FILEPATH=(.+)$")}, - {'name': "core_dependencies", 'default': None, 'pattern': re.compile("^opencv_core_LIB_DEPENDS:STATIC=(.+)$")}, -) - -def query_yes_no(stdout, question, default="yes"): - valid = {"yes":True, "y":True, "ye":True, "no":False, "n":False} - if default == None: - prompt = " [y/n] " - elif default == "yes": - prompt = " [Y/n] " - elif default == "no": - prompt = " [y/N] " - else: - raise ValueError("invalid default answer: '%s'" % default) - - while True: - stdout.write(os.linesep + question + prompt) - choice = raw_input().lower() - if default is not None and choice == '': - return valid[default] - elif choice in valid: - return valid[choice] - else: - stdout.write("Please respond with 'yes' or 'no' "\ - "(or 'y' or 'n').\n") - -def getRunningProcessExePathByName_win32(name): - from ctypes import windll, POINTER, pointer, Structure, sizeof - from ctypes import c_long , c_int , c_uint , c_char , c_ubyte , c_char_p , c_void_p - - class PROCESSENTRY32(Structure): - _fields_ = [ ( 'dwSize' , c_uint ) , - ( 'cntUsage' , c_uint) , - ( 'th32ProcessID' , c_uint) , - ( 'th32DefaultHeapID' , c_uint) , - ( 'th32ModuleID' , c_uint) , - ( 'cntThreads' , c_uint) , - ( 'th32ParentProcessID' , c_uint) , - ( 'pcPriClassBase' , c_long) , - ( 'dwFlags' , c_uint) , - ( 'szExeFile' , c_char * 260 ) , - ( 'th32MemoryBase' , c_long) , - ( 'th32AccessKey' , c_long ) ] - - class MODULEENTRY32(Structure): - _fields_ = [ ( 'dwSize' , c_long ) , - ( 'th32ModuleID' , c_long ), - ( 'th32ProcessID' , c_long ), - ( 'GlblcntUsage' , c_long ), - ( 'ProccntUsage' , c_long ) , - ( 'modBaseAddr' , c_long ) , - ( 'modBaseSize' , c_long ) , - ( 'hModule' , c_void_p ) , - ( 'szModule' , c_char * 256 ), - ( 'szExePath' , c_char * 260 ) ] - - TH32CS_SNAPPROCESS = 2 - TH32CS_SNAPMODULE = 0x00000008 - - ## CreateToolhelp32Snapshot - CreateToolhelp32Snapshot= windll.kernel32.CreateToolhelp32Snapshot - CreateToolhelp32Snapshot.reltype = c_long - CreateToolhelp32Snapshot.argtypes = [ c_int , c_int ] - ## Process32First - Process32First = windll.kernel32.Process32First - Process32First.argtypes = [ c_void_p , POINTER( PROCESSENTRY32 ) ] - Process32First.rettype = c_int - ## Process32Next - Process32Next = windll.kernel32.Process32Next - Process32Next.argtypes = [ c_void_p , POINTER(PROCESSENTRY32) ] - Process32Next.rettype = c_int - ## CloseHandle - CloseHandle = windll.kernel32.CloseHandle - CloseHandle.argtypes = [ c_void_p ] - CloseHandle.rettype = c_int - ## Module32First - Module32First = windll.kernel32.Module32First - Module32First.argtypes = [ c_void_p , POINTER(MODULEENTRY32) ] - Module32First.rettype = c_int - - hProcessSnap = c_void_p(0) - hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS , 0 ) - - pe32 = PROCESSENTRY32() - pe32.dwSize = sizeof( PROCESSENTRY32 ) - ret = Process32First( hProcessSnap , pointer( pe32 ) ) - path = None - - while ret : - if name + ".exe" == pe32.szExeFile: - hModuleSnap = c_void_p(0) - me32 = MODULEENTRY32() - me32.dwSize = sizeof( MODULEENTRY32 ) - hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, pe32.th32ProcessID ) - - ret = Module32First( hModuleSnap, pointer(me32) ) - path = me32.szExePath - CloseHandle( hModuleSnap ) - if path: - break - ret = Process32Next( hProcessSnap, pointer(pe32) ) - CloseHandle( hProcessSnap ) - return path - -def getRunningProcessExePathByName_posix(name): - pids= [pid for pid in os.listdir('/proc') if pid.isdigit()] - for pid in pids: - try: - path = os.readlink(os.path.join('/proc', pid, 'exe')) - if path and path.endswith(name): - return path - except: - pass - -def getRunningProcessExePathByName(name): - try: - if hostos == "nt": - return getRunningProcessExePathByName_win32(name) - elif hostos == "posix": - return getRunningProcessExePathByName_posix(name) - else: - return None - except: - return None - -class TestSuite(object): - def __init__(self, options, path = None): - self.options = options - self.path = path - self.error = None - self.setUp = None - self.tearDown = None - self.adb = None - self.targetos = None - self.nameprefix = "opencv_" + self.options.mode + "_" - for p in parse_patterns: - setattr(self, p["name"], p["default"]) - - if self.path: - cachefile = open(os.path.join(self.path, "CMakeCache.txt"), "rt") - try: - for l in cachefile.readlines(): - ll = l.strip() - if not ll or ll.startswith("#"): - continue - for p in parse_patterns: - match = p["pattern"].match(ll) - if match: - value = match.groups()[0] - if value and not value.endswith("-NOTFOUND"): - setattr(self, p["name"], value) - except: - pass - cachefile.close() - - # detect target platform - if self.android_executable or self.android_abi or self.ndk_path: - self.targetos = "android" - else: - self.targetos = hostos - - self.initialize() - - def initialize(self): - # fix empty tests dir - if not self.tests_dir: - self.tests_dir = self.path - self.tests_dir = os.path.normpath(self.tests_dir) - - # compute path to adb - if self.android_executable: - self.adb = os.path.join(os.path.dirname(os.path.dirname(self.android_executable)), ("platform-tools/adb","platform-tools/adb.exe")[hostos == 'nt']) - if not os.path.isfile(self.adb) or not os.access(self.adb, os.X_OK): - self.adb = None - else: - self.adb = None - - if self.targetos == "android": - # fix adb tool location - if not self.adb: - self.adb = getRunningProcessExePathByName("adb") - if not self.adb: - self.adb = "adb" - if self.options.adb_serial: - self.adb = [self.adb, "-s", self.options.adb_serial] - else: - self.adb = [self.adb] - try: - output = Popen(self.adb + ["shell", "ls"], stdout=PIPE, stderr=PIPE).communicate() - except OSError: - self.adb = [] - # remember current device serial. Needed if another device is connected while this script runs - if self.adb and not self.options.adb_serial: - adb_res = self.runAdb("devices") - if not adb_res: - self.error = "Could not run adb command: %s (for %s)" % (self.error, self.path) - self.adb = [] - else: - # assume here that device name may consists of any characters except newline - connected_devices = re.findall(r"^[^\n]+[ \t]+device\r?$", adb_res, re.MULTILINE) - if not connected_devices: - self.error = "Android device not found" - self.adb = [] - elif len(connected_devices) != 1: - self.error = "Too many (%s) devices are connected. Please specify single device using --serial option:\n\n" % (len(connected_devices)) + adb_res - self.adb = [] - else: - self.options.adb_serial = connected_devices[0].split("\t")[0] - self.adb = self.adb + ["-s", self.options.adb_serial] - if self.adb: - # construct name for aapt tool - self.aapt = [os.path.join(os.path.dirname(self.adb[0]), ("aapt","aapt.exe")[hostos == 'nt'])] - if not os.path.isfile(self.aapt[0]): - # it's moved in SDK r22 - sdk_dir = os.path.dirname( os.path.dirname(self.adb[0]) ) - aapt_fn = ("aapt", "aapt.exe")[hostos == 'nt'] - for r, ds, fs in os.walk( os.path.join(sdk_dir, 'build-tools') ): - if aapt_fn in fs: - self.aapt = [ os.path.join(r, aapt_fn) ] - break - else: - self.error = "Can't find '%s' tool!" % aapt_fn - - # fix has_perf_tests param - self.has_perf_tests = self.has_perf_tests == "ON" - self.has_accuracy_tests = self.has_accuracy_tests == "ON" - # fix is_x64 flag - self.is_x64 = self.is_x64 == "ON" - if not self.is_x64 and ("X64" in "%s %s %s" % (self.cxx_flags, self.cxx_flags_release, self.cxx_flags_debug) or "Win64" in self.cmake_generator): - self.is_x64 = True - - # fix test path - if "Visual Studio" in self.cmake_generator: - if self.options.configuration: - self.tests_dir = os.path.join(self.tests_dir, self.options.configuration) - else: - self.tests_dir = os.path.join(self.tests_dir, self.build_type) - elif not self.is_x64 and self.cxx_compiler: - #one more attempt to detect x64 compiler - try: - compiler = [self.cxx_compiler] - if self.cxx_compiler_arg1: - compiler.append(self.cxx_compiler_arg1) - output = Popen(compiler + ["-v"], stdout=PIPE, stderr=PIPE).communicate() - if not output[0] and "x86_64" in output[1]: - self.is_x64 = True - except OSError: - pass - - # detect target arch - if self.targetos == "android": - if "armeabi-v7a" in self.android_abi: - self.targetarch = "armv7a" - elif "armeabi-v6" in self.android_abi: - self.targetarch = "armv6" - elif "armeabi" in self.android_abi: - self.targetarch = "armv5te" - elif "x86" in self.android_abi: - self.targetarch = "x86" - elif "mips" in self.android_abi: - self.targetarch = "mips" - else: - self.targetarch = "ARM" - elif self.is_x64 and hostmachine in ["AMD64", "x86_64"]: - self.targetarch = "x64" - elif hostmachine in ["x86", "AMD64", "x86_64"]: - self.targetarch = "x86" - else: - self.targetarch = "unknown" - - # fix CUDA attributes - self.with_cuda = self.with_cuda == "ON" - if self.cuda_library and self.cuda_library.endswith("-NOTFOUND"): - self.cuda_library = None - self.has_cuda = self.with_cuda and self.cuda_library and self.targetarch in ["x86", "x64"] - - self.hardware = None - - self.cmake_home_vcver = self.getVCVersion(self.cmake_home) - if self.opencv_home == self.cmake_home: - self.opencv_home_vcver = self.cmake_home_vcver - else: - self.opencv_home_vcver = self.getVCVersion(self.opencv_home) - - self.tests = self.getAvailableTestApps() - - def getVCVersion(self, root_path): - if not root_path: - return None - if os.path.isdir(os.path.join(root_path, ".svn")): - return self.getSvnVersion(root_path) - elif os.path.isdir(os.path.join(root_path, ".git")): - return self.getGitHash(root_path) - return None - - def getGitHash(self, path): - if not path or not self.git_executable: - return None - try: - output = Popen([self.git_executable, "rev-parse", "--short", "HEAD"], stdout=PIPE, stderr=PIPE, cwd = path).communicate() - if not output[1]: - return output[0].strip() - else: - return None - except OSError: - return None - - def getSvnVersion(self, path): - if not path: - val = None - elif not self.svnversion_path and hostos == 'nt': - val = self.tryGetSvnVersionWithTortoise(path) - else: - svnversion = self.svnversion_path - if not svnversion: - svnversion = "svnversion" - try: - output = Popen([svnversion, "-n", path], stdout=PIPE, stderr=PIPE).communicate() - if not output[1]: - val = output[0] - else: - val = None - except OSError: - val = None - if val: - val = val.replace(" ", "_") - return val - - def tryGetSvnVersionWithTortoise(self, path): - try: - wcrev = "SubWCRev.exe" - dir = tempfile.mkdtemp() - #print dir - tmpfilename = os.path.join(dir, "svn.tmp") - tmpfilename2 = os.path.join(dir, "svn_out.tmp") - tmpfile = open(tmpfilename, "w") - tmpfile.write("$WCRANGE$$WCMODS?M:$") - tmpfile.close(); - output = Popen([wcrev, path, tmpfilename, tmpfilename2, "-f"], stdout=PIPE, stderr=PIPE).communicate() - if "is not a working copy" in output[0]: - version = "exported" - else: - tmpfile = open(tmpfilename2, "r") - version = tmpfile.read() - tmpfile.close() - return version - except: - return None - finally: - if dir: - shutil.rmtree(dir) - - def isTest(self, fullpath): - if not os.path.isfile(fullpath): - return False - if self.targetos == "nt" and not fullpath.endswith(".exe"): - return False - if hostos == self.targetos: - return os.access(fullpath, os.X_OK) - if self.targetos == "android" and fullpath.endswith(".apk"): - return True - return True - - def getAvailableTestApps(self): - if self.tests_dir and os.path.isdir(self.tests_dir): - files = glob.glob(os.path.join(self.tests_dir, self.nameprefix + "*")) - files = [f for f in files if self.isTest(f)] - if self.ant_executable and self.java_test_binary_dir: - files.append("java") - return files - return [] - - def getLogName(self, app, timestamp): - app = os.path.basename(app) - if app.endswith(".exe"): - if app.endswith("d.exe"): - app = app[:-5] - else: - app = app[:-4] - if app.startswith(self.nameprefix): - app = app[len(self.nameprefix):] - - if self.cmake_home_vcver: - if self.cmake_home_vcver == self.opencv_home_vcver: - rev = self.cmake_home_vcver - elif self.opencv_home_vcver: - rev = self.cmake_home_vcver + "-" + self.opencv_home_vcver - else: - rev = self.cmake_home_vcver - else: - rev = None - if rev: - rev = rev.replace(":","to") - else: - rev = "" - - if self.options.useLongNames: - if not rev: - rev = "unknown" - tstamp = timestamp.strftime("%Y%m%d-%H%M%S") - - features = [] - #OS - _os = "" - if self.targetos == "android": - _os = "Android" + self.runAdb("shell", "getprop ro.build.version.release").strip() - else: - mv = platform.mac_ver() - if mv[0]: - _os = "Darwin" + mv[0] - else: - wv = platform.win32_ver() - if wv[0]: - _os = "Windows" + wv[0] - else: - lv = platform.linux_distribution() - if lv[0]: - _os = lv[0] + lv[1] - else: - _os = self.targetos - features.append(_os) - - #HW(x86, x64, ARMv7a) - if self.targetarch: - features.append(self.targetarch) - - #TBB - if ";tbb;" in self.core_dependencies: - features.append("TBB") - - #CUDA - if self.has_cuda: - #TODO: determine compute capability - features.append("CUDA") - - #SIMD - compiler_output = "" - try: - tmpfile = tempfile.mkstemp(suffix=".cpp", text = True) - fd = os.fdopen(tmpfile[0], "w+b") - fd.write(SIMD_DETECTION_PROGRAM) - fd.close(); - options = [self.cxx_compiler] - if self.cxx_compiler_arg1: - options.append(self.cxx_compiler_arg1) - cxx_flags = self.cxx_flags + " " + self.cxx_flags_release + " " + self.opencv_cxx_flags + " " + self.opencv_cxx_flags_release - if self.targetos == "android" and self.cxx_flags_android: - cxx_flags = self.cxx_flags_android + " " + cxx_flags - - prev_option = None - for opt in cxx_flags.split(" "): - if opt.count('\"') % 2 == 1: - if prev_option is None: - prev_option = opt - else: - options.append(prev_option + " " + opt) - prev_option = None - elif prev_option is None: - options.append(opt) - else: - prev_option = prev_option + " " + opt - options.append(tmpfile[1]) - output = Popen(options, stdout=PIPE, stderr=PIPE).communicate() - compiler_output = output[1] - os.remove(tmpfile[1]) - except OSError: - pass - if compiler_output: - m = re.search("#error\W+(\w+)", compiler_output) - if m: - features.append(m.group(1)) - - #fin - return "%s__%s__%s__%s.xml" % (app, rev, tstamp, "_".join(features)) - else: - if rev: - rev = rev + "_" - if self.hardware: - hw = str(self.hardware).replace(" ", "_") + "_" - elif self.has_cuda: - hw = "CUDA_" - else: - hw = "" - tstamp = timestamp.strftime("%Y%m%d-%H%M%S") - lname = "%s_%s_%s_%s%s%s.xml" % (app, self.targetos, self.targetarch, hw, rev, tstamp) - lname = str.replace(lname, '(', '_') - lname = str.replace(lname, ')', '_') - return lname - - def getTest(self, name): - # full path - if self.isTest(name): - return name - - # name only - fullname = os.path.join(self.tests_dir, name) - if self.isTest(fullname): - return fullname - - # name without extension - fullname += ".exe" - if self.isTest(fullname): - return fullname - if self.targetos == "android": - fullname += ".apk" - if self.isTest(fullname): - return fullname - - # short name for OpenCV tests - for t in self.tests: - if t == name: - return t - fname = os.path.basename(t) - if fname == name: - return t - if fname.endswith(".exe") or (self.targetos == "android" and fname.endswith(".apk")): - fname = fname[:-4] - if fname == name: - return t - if self.options.configuration == "Debug" and fname == name + 'd': - return t - if fname.startswith(self.nameprefix): - fname = fname[len(self.nameprefix):] - if fname == name: - return t - if self.options.configuration == "Debug" and fname == name + 'd': - return t - return None - - def runAdb(self, *args): - cmd = self.adb[:] - cmd.extend(args) - try: - output = Popen(cmd, stdout=PIPE, stderr=PIPE).communicate() - if not output[1]: - return output[0] - self.error = output[1] - except OSError: - pass - return None - - def isRunnable(self): - if self.error: - return False - if self.targetarch == "x64" and hostmachine == "x86": - self.error = "Target architecture is incompatible with current platform (at %s)" % self.path - return False - if self.targetos == "android": - if not self.adb: - self.error = "Could not find adb executable (for %s)" % self.path - return False - if "armeabi-v7a" in self.android_abi: - adb_res = self.runAdb("shell", "cat /proc/cpuinfo") - if not adb_res: - self.error = "Could not get info about Android platform: %s (for %s)" % (self.error, self.path) - return False - if "ARMv7" not in adb_res: - self.error = "Android device does not support ARMv7 commands, but tests are built for armeabi-v7a (for %s)" % self.path - return False - if "NEON" in self.android_abi and "neon" not in adb_res: - self.error = "Android device has no NEON, but tests are built for %s (for %s)" % (self.android_abi, self.path) - return False - hw = re.search(r"^Hardware[ \t]*:[ \t]*(.*?)$", adb_res, re.MULTILINE) - if hw: - self.hardware = hw.groups()[0].strip() - return True - - def runTest(self, path, workingDir, _stdout, _stderr, args = []): - global errorCode - - if self.error: - return - args = args[:] - timestamp = datetime.datetime.now() - logfile = self.getLogName(path, timestamp) - exe = os.path.abspath(path) - - userlog = [a for a in args if a.startswith("--gtest_output=")] - if len(userlog) == 0: - args.append("--gtest_output=xml:" + logfile) - else: - logfile = userlog[0][userlog[0].find(":")+1:] - - if self.targetos == "android" and exe.endswith(".apk"): - print "Run java tests:", exe - try: - # get package info - output = Popen(self.aapt + ["dump", "xmltree", exe, "AndroidManifest.xml"], stdout=PIPE, stderr=_stderr).communicate() - if not output[0]: - print >> _stderr, "fail to dump manifest from", exe - return - tags = re.split(r"[ ]+E: ", output[0]) - # get package name - manifest_tag = [t for t in tags if t.startswith("manifest ")] - if not manifest_tag: - print >> _stderr, "fail to read package name from", exe - return - pkg_name = re.search(r"^[ ]+A: package=\"(?P.*?)\" \(Raw: \"(?P=pkg)\"\)\r?$", manifest_tag[0], flags=re.MULTILINE).group("pkg") - # get test instrumentation info - instrumentation_tag = [t for t in tags if t.startswith("instrumentation ")] - if not instrumentation_tag: - print >> _stderr, "can not find instrumentation detials in", exe - return - pkg_runner = re.search(r"^[ ]+A: android:name\(0x[0-9a-f]{8}\)=\"(?P.*?)\" \(Raw: \"(?P=runner)\"\)\r?$", instrumentation_tag[0], flags=re.MULTILINE).group("runner") - pkg_target = re.search(r"^[ ]+A: android:targetPackage\(0x[0-9a-f]{8}\)=\"(?P.*?)\" \(Raw: \"(?P=pkg)\"\)\r?$", instrumentation_tag[0], flags=re.MULTILINE).group("pkg") - if not pkg_name or not pkg_runner or not pkg_target: - print >> _stderr, "can not find instrumentation detials in", exe - return - if self.options.junit_package: - if self.options.junit_package.startswith("."): - pkg_target += self.options.junit_package - else: - pkg_target = self.options.junit_package - # uninstall previously installed package - print >> _stderr, "Uninstalling old", pkg_name, "from device..." - Popen(self.adb + ["uninstall", pkg_name], stdout=PIPE, stderr=_stderr).communicate() - print >> _stderr, "Installing new", exe, "to device...", - output = Popen(self.adb + ["install", exe], stdout=PIPE, stderr=PIPE).communicate() - if output[0] and output[0].strip().endswith("Success"): - print >> _stderr, "Success" - else: - print >> _stderr, "Failure" - print >> _stderr, "Failed to install", exe, "to device" - return - print >> _stderr, "Running jUnit tests for ", pkg_target - if self.setUp: - self.setUp() - Popen(self.adb + ["shell", "am instrument -w -e package " + pkg_target + " " + pkg_name + "/" + pkg_runner], stdout=_stdout, stderr=_stderr).wait() - if self.tearDown: - self.tearDown() - except OSError: - pass - return - elif self.targetos == "android": - hostlogpath = "" - usercolor = [a for a in args if a.startswith("--gtest_color=")] - if len(usercolor) == 0 and _stdout.isatty() and hostos != "nt": - args.append("--gtest_color=yes") - try: - tempdir = "/data/local/tmp/" - andoidcwd = tempdir + getpass.getuser().replace(" ","") + "_" + self.options.mode +"/" - exename = os.path.basename(exe) - androidexe = andoidcwd + exename - # upload - _stderr.write("Uploading... ") - output = Popen(self.adb + ["push", exe, androidexe], stdout=_stdout, stderr=_stderr).wait() - if output != 0: - print >> _stderr, "adb finishes unexpectedly with error code", output - return - # chmod - output = Popen(self.adb + ["shell", "chmod 777 " + androidexe], stdout=_stdout, stderr=_stderr).wait() - if output != 0: - print >> _stderr, "adb finishes unexpectedly with error code", output - return - # run - if self.options.help: - command = exename + " --help" - else: - command = exename + " " + " ".join(args) - print >> _stderr, "Run command:", command - if self.setUp: - self.setUp() - env = self.options.android_env.copy() - env['OPENCV_TEST_DATA_PATH'] = self.options.test_data_path - if self.options.android_propagate_opencv_env: - for k, v in os.environ.items(): - if k.startswith('OPENCV') and not k in env: - env[k] = v - print >> _stderr, "Android environment variables: \n", '\n'.join([' %s=%s' % (k, v) for k, v in env.items()]) - commandPrefix = ''.join(['export %s=%s && ' % (k, v) for k, v in env.items()]) - Popen(self.adb + ["shell", commandPrefix + "cd " + andoidcwd + "&& ./" + command], stdout=_stdout, stderr=_stderr).wait() - if self.tearDown: - self.tearDown() - # try get log - if not self.options.help: - #_stderr.write("Pull log... ") - hostlogpath = os.path.join(workingDir, logfile) - output = Popen(self.adb + ["pull", andoidcwd + logfile, hostlogpath], stdout=_stdout, stderr=PIPE).wait() - if output != 0: - print >> _stderr, "adb finishes unexpectedly with error code", output - return - #rm log - Popen(self.adb + ["shell", "rm " + andoidcwd + logfile], stdout=PIPE, stderr=PIPE).wait() - - # clean temporary files - Popen(self.adb + ["shell", "rm " + tempdir + "__opencv_temp.*"], stdout=PIPE, stderr=PIPE).wait() - except OSError: - pass - if os.path.isfile(hostlogpath): - return hostlogpath - return None - elif path == "java": - cmd = [self.ant_executable, - "-Dopencv.build.type=" - + (self.options.configuration if self.options.configuration else self.build_type), - "buildAndTest"] - - print >> _stderr, "Run command:", " ".join(cmd) - try: - errorCode = Popen(cmd, stdout=_stdout, stderr=_stderr, cwd = self.java_test_binary_dir + "/.build").wait() - except: - print "Unexpected error:", sys.exc_info()[0] - - return None - else: - cmd = [exe] - if self.options.help: - cmd.append("--help") - else: - cmd.extend(args) - - orig_temp_path = os.environ.get('OPENCV_TEMP_PATH') - temp_path = tempfile.mkdtemp(prefix="__opencv_temp.", dir=orig_temp_path or None) - os.environ['OPENCV_TEMP_PATH'] = temp_path - - print >> _stderr, "Run command:", " ".join(cmd) - try: - errorCode = Popen(cmd, stdout=_stdout, stderr=_stderr, cwd = workingDir).wait() - except: - print "Unexpected error:", sys.exc_info()[0] - - # clean temporary files - if orig_temp_path: - os.environ['OPENCV_TEMP_PATH'] = orig_temp_path - else: - del os.environ['OPENCV_TEMP_PATH'] - - try: - shutil.rmtree(temp_path) - pass - except: - pass - - logpath = os.path.join(workingDir, logfile) - if os.path.isfile(logpath): - return logpath - return None - - def runTests(self, tests, _stdout, _stderr, workingDir, args = []): - if not self.isRunnable(): - print >> _stderr, "Error:", self.error - if self.error: - return [] - if self.adb and self.targetos == "android": - print "adb command:", " ".join(self.adb) - if not tests: - tests = self.tests - logs = [] - for test in tests: - t = self.getTest(test) - if t: - logfile = self.runTest(t, workingDir, _stdout, _stderr, args) - if logfile: - logs.append(os.path.relpath(logfile, ".")) - else: - print >> _stderr, "Error: Test \"%s\" is not found in %s" % (test, self.tests_dir) - return logs - -def getRunArgs(args): - run_args = [] - for path in args: - path = os.path.abspath(path) - while (True): - if os.path.isdir(path) and os.path.isfile(os.path.join(path, "CMakeCache.txt")): - run_args.append(path) - break - npath = os.path.dirname(path) - if npath == path: - break - path = npath - return run_args - -if hostos == "nt": - def moveTests(instance, destination): - src = os.path.dirname(instance.tests_dir) - # new binaries path - newBinPath = os.path.join(destination, "bin") - - try: - # copy binaries and CMakeCache.txt to the specified destination - shutil.copytree(src, newBinPath) - shutil.copy(os.path.join(instance.path, "CMakeCache.txt"), os.path.join(destination, "CMakeCache.txt")) - except Exception, e: - print "Copying error occurred:", str(e) - exit(e.errno) - - # pattern of CMakeCache.txt string to be replaced - replacePattern = re.compile("EXECUTABLE_OUTPUT_PATH:PATH=(.+)") - - with open(os.path.join(destination, "CMakeCache.txt"), "r") as cachefile: - try: - cachedata = cachefile.read() - if hostos == 'nt': - # fix path slashes on nt systems - newBinPath = re.sub(r"\\", r"/", newBinPath) - # replace old binaries path in CMakeCache.txt - cachedata = re.sub(re.search(replacePattern, cachedata).group(1), newBinPath, cachedata) - except Exception, e: - print "Reading error occurred:", str(e) - exit(e.errno) - - with open(os.path.join(destination, "CMakeCache.txt"), "w") as cachefile: - try: - cachefile.write(cachedata) - except Exception, e: - print "Writing error occurred:", str(e) - exit(e.errno) - exit() +import os, sys +import argparse +import logging +from run_utils import Err, CMakeCache, log, execute +from run_suite import TestSuite +from run_android import AndroidTestSuite + +epilog = ''' +NOTE: +Additional options starting with "--gtest_" and "--perf_" will be passed directly to the test executables. +''' if __name__ == "__main__": - test_args = [a for a in sys.argv if a.startswith("--perf_") or a.startswith("--gtest_")] - argv = [a for a in sys.argv if not(a.startswith("--perf_") or a.startswith("--gtest_"))] - parser = OptionParser(usage="run.py [options] [build_path]", description="Note: build_path is required if running not from CMake build directory") - parser.add_option("-t", "--tests", dest="tests", help="comma-separated list of modules to test", metavar="SUITS", default="") - if hostos == "nt": - parser.add_option("-m", "--move_tests", dest="move", help="location to move current tests build", metavar="PATH", default="") - parser.add_option("-w", "--cwd", dest="cwd", help="working directory for tests", metavar="PATH", default=".") - parser.add_option("-a", "--accuracy", dest="accuracy", help="look for accuracy tests instead of performance tests", action="store_true", default=False) - parser.add_option("-l", "--longname", dest="useLongNames", action="store_true", help="generate log files with long names", default=False) - parser.add_option("", "--android_test_data_path", dest="test_data_path", help="OPENCV_TEST_DATA_PATH for Android run", metavar="PATH", default="/sdcard/opencv_testdata/") - parser.add_option("", "--android_env", dest="android_env_array", help="Environment variable for Android run (NAME=VALUE)", action='append') - parser.add_option("", "--android_propagate_opencv_env", dest="android_propagate_opencv_env", help="Propagate OPENCV* environment variables for Android run", action="store_true", default=False) - parser.add_option("", "--configuration", dest="configuration", help="force Debug or Release configuration", metavar="CFG", default="") - parser.add_option("", "--serial", dest="adb_serial", help="Android: directs command to the USB device or emulator with the given serial number", metavar="serial number", default="") - parser.add_option("", "--package", dest="junit_package", help="Android: run jUnit tests for specified package", metavar="package", default="") - parser.add_option("", "--help-tests", dest="help", help="Show help for test executable", action="store_true", default=False) - parser.add_option("", "--check", dest="check", help="Shortcut for '--perf_min_samples=1 --perf_force_samples=1'", action="store_true", default=False) - parser.add_option("", "--list", dest="list", help="List available tests", action="store_true", default=False) + # log.basicConfig(format='[%(levelname)s] %(message)s', level = log.DEBUG) + # log.basicConfig(format='[%(levelname)s] %(message)s', level = log.INFO) - (options, args) = parser.parse_args(argv) + parser = argparse.ArgumentParser( + description='OpenCV test runner script', + epilog=epilog, + formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument("build_path", nargs = "*", default = ["."], help="Path to build directory (should contain CMakeCache.txt, default is current) or to directory with tests (all platform checks will be disabled in this case)") + parser.add_argument("-t", "--tests", metavar="MODULES", default="", help="Comma-separated list of modules to test (example: -t core,imgproc,java)") + parser.add_argument("-b", "--blacklist", metavar="MODULES", default="", help="Comma-separated list of modules to exclude from test (example: -b java)") + parser.add_argument("-a", "--accuracy", action="store_true", default=False, help="Look for accuracy tests instead of performance tests") + parser.add_argument("--check", action="store_true", default=False, help="Shortcut for '--perf_min_samples=1 --perf_force_samples=1'") + parser.add_argument("-w", "--cwd", metavar="PATH", default=".", help="Working directory for tests (default is current)") + parser.add_argument("-l", "--longname", action="store_true", default=False, help="Generate log files with long names") + parser.add_argument("--list", action="store_true", default=False, help="List available tests (executables)") + parser.add_argument("--list_short", action="store_true", default=False, help="List available tests (aliases)") + parser.add_argument("--list_short_main", action="store_true", default=False, help="List available tests (main repository, aliases)") + parser.add_argument("--configuration", metavar="CFG", default="", help="Visual Studio: force Debug or Release configuration") + parser.add_argument("-n", "--dry_run", action="store_true", help="Do not run the tests") + parser.add_argument("-v", "--verbose", action="store_true", default=False, help="Print more debug information") - if options.accuracy: - options.mode = "test" - else: - options.mode = "perf" + # Valgrind + parser.add_argument("--valgrind", action="store_true", default=False, help="Run C++ tests in valgrind") + parser.add_argument("--valgrind_supp", metavar="FILE", help="Path to valgrind suppression file (example: --valgrind_supp opencv/platforms/scripts/valgrind.supp)") + parser.add_argument("--valgrind_opt", metavar="OPT", action="append", default=[], help="Add command line option to valgrind (example: --valgrind_opt=--leak-check=full)") - run_args = getRunArgs(args[1:] or ['.']) + # Android + parser.add_argument("--android", action="store_true", default=False, help="Android: force all tests to run on device") + parser.add_argument("--android_sdk", metavar="PATH", help="Android: path to SDK to use adb and aapt tools") + parser.add_argument("--android_test_data_path", metavar="PATH", default="/sdcard/opencv_testdata/", help="Android: path to testdata on device") + parser.add_argument("--android_env", action='append', help="Android: add environment variable (NAME=VALUE)") + parser.add_argument("--android_propagate_opencv_env", action="store_true", default=False, help="Android: propagate OPENCV* environment variables") + parser.add_argument("--serial", metavar="serial number", default="", help="Android: directs command to the USB device or emulator with the given serial number") + parser.add_argument("--package", metavar="package", default="", help="Android: run jUnit tests for specified package") - if len(run_args) == 0: - print >> sys.stderr, "Usage:", os.path.basename(sys.argv[0]), "[options] [build_path]" - print >> sys.stderr, "Please specify build_path or run script from CMake build directory" + args, other_args = parser.parse_known_args() + + log.setLevel(logging.DEBUG if args.verbose else logging.INFO) + + test_args = [a for a in other_args if a.startswith("--perf_") or a.startswith("--gtest_")] + bad_args = [a for a in other_args if a not in test_args] + if len(bad_args) > 0: + log.error("Error: Bad arguments: %s", bad_args) exit(1) - options.android_env = {} - if options.android_env_array: - for entry in options.android_env_array: - k, v = entry.split("=", 1) - options.android_env[k] = v + args.mode = "test" if args.accuracy else "perf" - tests = [s.strip() for s in options.tests.split(",") if s] + android_env = [] + if args.android_env: + android_env.extend([entry.split("=", 1) for entry in args.android_env]) + if args.android_propagate_opencv_env: + android_env.extend([entry for entry in os.environ.items() if entry[0].startswith('OPENCV')]) + android_env = dict(android_env) + if args.android_test_data_path: + android_env['OPENCV_TEST_DATA_PATH'] = args.android_test_data_path - if len(tests) != 1 or len(run_args) != 1: - # remove --gtest_output from params + if args.valgrind: + try: + ver = execute(["valgrind", "--version"], silent=True) + log.debug("Using %s", ver) + except OSError as e: + log.error("Failed to run valgrind: %s", e) + exit(1) + + if len(args.build_path) != 1: test_args = [a for a in test_args if not a.startswith("--gtest_output=")] - if options.check: + if args.check: if not [a for a in test_args if a.startswith("--perf_min_samples=")] : test_args.extend(["--perf_min_samples=1"]) if not [a for a in test_args if a.startswith("--perf_force_samples=")] : @@ -942,26 +89,46 @@ if __name__ == "__main__": if not [a for a in test_args if a.startswith("--perf_verify_sanity")] : test_args.extend(["--perf_verify_sanity"]) + ret = 0 logs = [] - test_list = [] - for path in run_args: - suite = TestSuite(options, path) + for path in args.build_path: + try: + if not os.path.isdir(path): + raise Err("Not a directory (should contain CMakeCache.txt ot test executables)") + cache = CMakeCache() + fname = os.path.join(path, "CMakeCache.txt") - if hostos == "nt": - if(options.move): - moveTests(suite, options.move) - #print vars(suite),"\n" - if options.list: - test_list.extend(suite.tests) - else: - logs.extend(suite.runTests(tests, sys.stdout, sys.stderr, options.cwd, test_args)) + if os.path.isfile(fname): + log.debug("Reading cmake cache file: %s", fname) + cache.read(path, fname, args.configuration) + else: + log.debug("Assuming folder contains tests: %s", path) + cache.setDummy(path) - if options.list: - print os.linesep.join(test_list) or "No tests found" + if args.android or cache.getOS() == "android": + log.debug("Creating Android test runner") + suite = AndroidTestSuite(args, cache, android_env) + else: + log.debug("Creating native test runner") + suite = TestSuite(args, cache) + + if args.list or args.list_short or args.list_short_main: + suite.listTests(args.list_short or args.list_short_main, args.list_short_main) + else: + log.debug("Running tests in '%s', working dir: '%s'", path, args.cwd) + def parseTests(s): + return [o.strip() for o in s.split(",") if o] + l, r = suite.runTests(parseTests(args.tests), parseTests(args.blacklist), args.cwd, test_args) + logs.extend(l) + if r != 0: + ret = r + except Err as e: + log.error("ERROR: test path '%s' ==> %s", path, e.msg) + ret = -1 if logs: - print >> sys.stderr, "Collected: ", " ".join(logs) + log.warning("Collected: %s", ", ".join(logs)) - if errorCode != 0: - print "Error code: ", errorCode, (" (0x%x)" % (errorCode & 0xffffffff)) - exit(errorCode) + if ret != 0: + log.error("ERROR: some tests have failed") + exit(ret) diff --git a/modules/ts/misc/run_android.py b/modules/ts/misc/run_android.py new file mode 100644 index 000000000..d03721774 --- /dev/null +++ b/modules/ts/misc/run_android.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python + +import sys +from run_utils import * +from run_suite import TestSuite + +def exe(program): + return program + ".exe" if hostos == 'nt' else program + +class ApkInfo: + def __init__(self): + self.pkg_name = None + self.pkg_target = None + self.pkg_runner = None + + def forcePackage(self, package): + if package: + if package.startswith("."): + self.pkg_target += package + else: + self.pkg_target = package + +#============================================================================== + +class Tool: + def __init__(self): + self.cmd = [] + + def run(self, args = [], silent = False): + cmd = self.cmd[:] + cmd.extend(args) + return execute(self.cmd + args, silent) + + +#============================================================================== + +class Adb(Tool): + def __init__(self, sdk_dir): + Tool.__init__(self) + exe_path = os.path.join(sdk_dir, exe("platform-tools/adb")) + if not os.path.isfile(exe_path) or not os.access(exe_path, os.X_OK): + exe_path = None + # fix adb tool location + if not exe_path: + exe_path = getRunningProcessExePathByName("adb") + if not exe_path: + exe_path = "adb" + self.cmd = [exe_path] + self.cpuinfo = "" + + def init(self, serial): + # remember current device serial. Needed if another device is connected while this script runs + if not serial: + serial = self.detectSerial() + if serial: + self.cmd.extend(["-s", serial]) + # read device cpuinfo + self.cpuinfo = self.run(["shell", "cat /proc/cpuinfo"], silent = True) + if not self.cpuinfo: + raise Err("Can not get cpuinfo from Android device") + + def detectSerial(self): + adb_res = self.run(["devices"], silent = True) + # assume here that device name may consists of any characters except newline + connected_devices = re.findall(r"^[^\n]+[ \t]+device\r?$", adb_res, re.MULTILINE) + if not connected_devices: + raise Err("Can not find Android device") + elif len(connected_devices) != 1: + raise Err("Too many (%s) devices are connected. Please specify single device using --serial option:\n\n%s", len(connected_devices), adb_res) + else: + return connected_devices[0].split("\t")[0] + + def getOSIdentifier(self): + return "Android" + self.run(["shell", "getprop ro.build.version.release"], silent = True).strip() + + def getHardware(self): + hw = re.search(r"^Hardware[ \t]*:[ \t]*(.*?)$", self.cpuinfo, re.MULTILINE) + if hw: + return hw.group(1).strip() + + def checkArmHardware(self, expected_abi): + if expected_abi and "armeabi-v7a" in expected_abi: + if "ARMv7" not in self.cpuinfo: + raise Err("Android device does not support ARMv7 commands, but tests are built for armeabi-v7a") + if "NEON" in expected_abi and "neon" not in self.cpuinfo: + raise Err("Android device has no NEON, but tests are built for %s", expected_abi) + + +#============================================================================== + +class Aapt(Tool): + def __init__(self, sdk_dir): + Tool.__init__(self) + aapt_fn = exe("aapt") + aapt = None + for r, ds, fs in os.walk( os.path.join(sdk_dir, 'build-tools') ): + if aapt_fn in fs: + aapt = os.path.join(r, aapt_fn) + break + if not aapt: + raise Err("Can not find aapt tool: %s", aapt_fn) + self.cmd = [aapt] + + def dump(self, exe): + res = ApkInfo() + output = self.run(["dump", "xmltree", exe, "AndroidManifest.xml"], silent = True) + if not output: + raise Err("Can not dump manifest from %s", exe) + tags = re.split(r"[ ]+E: ", output) + # get package name + manifest_tag = [t for t in tags if t.startswith("manifest ")] + if not manifest_tag: + raise Err("Can not read package name from: %s", exe) + res.pkg_name = re.search(r"^[ ]+A: package=\"(?P.*?)\" \(Raw: \"(?P=pkg)\"\)\r?$", manifest_tag[0], flags=re.MULTILINE).group("pkg") + # get test instrumentation info + instrumentation_tag = [t for t in tags if t.startswith("instrumentation ")] + if not instrumentation_tag: + raise Err("Can not find instrumentation detials in: %s", exe) + res.pkg_runner = re.search(r"^[ ]+A: android:name\(0x[0-9a-f]{8}\)=\"(?P.*?)\" \(Raw: \"(?P=runner)\"\)\r?$", instrumentation_tag[0], flags=re.MULTILINE).group("runner") + res.pkg_target = re.search(r"^[ ]+A: android:targetPackage\(0x[0-9a-f]{8}\)=\"(?P.*?)\" \(Raw: \"(?P=pkg)\"\)\r?$", instrumentation_tag[0], flags=re.MULTILINE).group("pkg") + if not res.pkg_name or not res.pkg_runner or not res.pkg_target: + raise Err("Can not find instrumentation detials in: %s", exe) + return res + +#=================================================================================================== + +class AndroidTestSuite(TestSuite): + def __init__(self, options, cache, android_env = {}): + TestSuite.__init__(self, options, cache) + sdk_dir = options.android_sdk or os.environ.get("ANDROID_SDK", False) or os.path.dirname(os.path.dirname(self.cache.android_executable)) + log.debug("Detecting Android tools in directory: %s", sdk_dir) + self.adb = Adb(sdk_dir) + self.aapt = Aapt(sdk_dir) + self.env = android_env + + def isTest(self, fullpath): + if os.path.isfile(fullpath): + if fullpath.endswith(".apk") or os.access(fullpath, os.X_OK): + return True + return False + + def getOS(self): + return self.adb.getOSIdentifier() + + def getHardware(self): + return [self.adb.getHardware()] + + def checkPrerequisites(self): + self.adb.init(self.options.serial) + self.adb.checkArmHardware(self.cache.android_abi) + + def runTest(self, path, logfile, workingDir, args = []): + args = args[:] + exe = os.path.abspath(path) + + if exe.endswith(".apk"): + info = self.aapt.dump(exe) + if not info: + raise Err("Can not read info from test package: %s", exe) + info.forcePackage(self.options.package) + self.adb.run(["uninstall", info.pkg_name]) + + output = self.adb.run(["install", exe], silent = True) + if not (output and "Success" in output): + raise Err("Can not install package: %s", exe) + + params = ["-e package %s" % info.pkg_target] + ret = self.adb.run(["shell", "am instrument -w %s %s/%s" % (" ".join(params), info.pkg_name, info.pkg_runner)]) + return None, ret + else: + device_dir = getpass.getuser().replace(" ","") + "_" + self.options.mode +"/" + if isColorEnabled(args): + args.append("--gtest_color=yes") + tempdir = "/data/local/tmp/" + android_dir = tempdir + device_dir + exename = os.path.basename(exe) + android_exe = android_dir + exename + self.adb.run(["push", exe, android_exe]) + self.adb.run(["shell", "chmod 777 " + android_exe]) + env_pieces = ["export %s=%s" % (a,b) for a,b in self.env.items()] + pieces = ["cd %s" % android_dir, "./%s %s" % (exename, " ".join(args))] + log.warning("Run: %s" % " && ".join(pieces)) + ret = self.adb.run(["shell", " && ".join(env_pieces + pieces)]) + # try get log + hostlogpath = os.path.join(workingDir, logfile) + self.adb.run(["pull", android_dir + logfile, hostlogpath]) + # cleanup + self.adb.run(["shell", "rm " + android_dir + logfile]) + self.adb.run(["shell", "rm " + tempdir + "__opencv_temp.*"], silent = True) + if os.path.isfile(hostlogpath): + return hostlogpath, ret + return None, ret + +#=================================================================================================== + +if __name__ == "__main__": + log.error("This is utility file, please execute run.py script") diff --git a/modules/ts/misc/run_suite.py b/modules/ts/misc/run_suite.py new file mode 100644 index 000000000..c3d715e16 --- /dev/null +++ b/modules/ts/misc/run_suite.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python + +import datetime +from run_utils import * + +class TestSuite(object): + def __init__(self, options, cache): + self.options = options + self.cache = cache + self.nameprefix = "opencv_" + self.options.mode + "_" + self.tests = self.cache.gatherTests(self.nameprefix + "*", self.isTest) + + def getOS(self): + return getPlatformVersion() or self.cache.getOS() + + def getHardware(self): + res = [] + if self.cache.getArch() in ["x86", "x64"] and self.cache.withCuda(): + res.append("CUDA") + return res + + def getLogName(self, app, timestamp): + app = self.getAlias(app) + rev = self.cache.getGitVersion() + if isinstance(timestamp, datetime.datetime): + timestamp = timestamp.strftime("%Y%m%d-%H%M%S") + if self.options.longname: + small_pieces = [self.getOS(), self.cache.getArch()] + self.cache.getDependencies() + self.getHardware() + [self.cache.getSIMDFeatures()] + big_pieces = [app, str(rev), timestamp, "_".join([p for p in small_pieces if p])] + l = "__".join(big_pieces) + else: + pieces = [app, self.cache.getOS(), self.cache.getArch()] + self.getHardware() + [rev, timestamp] + lname = "_".join([p for p in pieces if p]) + lname = re.sub(r'[\(\)\[\]\s,]', '_', lname) + l = re.sub(r'_+', '_', lname) + return l + ".xml" + + def listTests(self, short = False, main = False): + if len(self.tests) == 0: + raise Err("No tests found") + for t in self.tests: + if short: + t = self.getAlias(t) + if not main or self.cache.isMainModule(t): + log.info("%s", t) + + def getAlias(self, fname): + return sorted(self.getAliases(fname), key = len)[0] + + def getAliases(self, fname): + # input is full path ('/home/.../bin/opencv_test_core') or 'java' + res = [fname] + fname = os.path.basename(fname) + res.append(fname) # filename (opencv_test_core.exe) + noext = re.sub(r"\.(exe|apk)$", '', fname) + res.append(noext) # filename w/o extension (opencv_test_core) + nopref = None + if fname.startswith(self.nameprefix): + nopref = fname[len(self.nameprefix):] + res.append(nopref) # filename w/o prefix (core) + if noext.startswith(self.nameprefix): + res.append(noext[len(self.nameprefix):]) + if self.options.configuration == "Debug": + res.append(re.sub(r"d$", '', noext)) # MSVC debug config, remove 'd' suffix + if nopref: + res.append(re.sub(r"d$", '', nopref)) # MSVC debug config, remove 'd' suffix + return set(res) + + def getTest(self, name): + # return stored test name by provided alias + for t in self.tests: + if name in self.getAliases(t): + return t + raise Err("Can not find test: %s", name) + + def getTestList(self, white, black): + res = [t for t in white or self.tests if self.getAlias(t) not in black] + if len(res) == 0: + raise Err("No tests found") + return set(res) + + def isTest(self, fullpath): + if fullpath == "java": + return True + if not os.path.isfile(fullpath): + return False + if self.cache.getOS() == "nt" and not fullpath.endswith(".exe"): + return False + return os.access(fullpath, os.X_OK) + + def wrapInValgrind(self, cmd = []): + if self.options.valgrind: + res = ['valgrind'] + if self.options.valgrind_supp: + res.append("--suppressions=%s" % self.options.valgrind_supp) + res.extend(self.options.valgrind_opt) + return res + cmd + return cmd + + def runTest(self, path, logfile, workingDir, args = []): + args = args[:] + exe = os.path.abspath(path) + if path == "java": + cfg = self.cache.build_type + if self.options.configuration: + cfg = self.options.configuration + cmd = [self.cache.ant_executable, "-Dopencv.build.type=%s" % cfg, "buildAndTest"] + ret = execute(cmd, cwd = self.cache.java_test_binary_dir + "/.build") + return None, ret + else: + if isColorEnabled(args): + args.append("--gtest_color=yes") + cmd = self.wrapInValgrind([exe] + args) + tempDir = TempEnvDir('OPENCV_TEMP_PATH', "__opencv_temp.") + tempDir.init() + log.warning("Run: %s" % " ".join(cmd)) + ret = execute(cmd, cwd = workingDir) + tempDir.clean() + hostlogpath = os.path.join(workingDir, logfile) + if os.path.isfile(hostlogpath): + return hostlogpath, ret + return None, ret + + def checkPrerequisites(self): + if self.cache.getArch() == "x64" and hostmachine == "x86": + raise Err("Target architecture is incompatible with current platform") + + def runTests(self, tests, black, workingDir, args = []): + self.checkPrerequisites() + args = args[:] + logs = [] + test_list = self.getTestList(tests, black) + date = datetime.datetime.now() + if len(test_list) != 1: + args = [a for a in args if not a.startswith("--gtest_output=")] + ret = 0 + for test in test_list: + more_args = [] + exe = self.getTest(test) + + userlog = [a for a in args if a.startswith("--gtest_output=")] + if len(userlog) == 0: + logname = self.getLogName(exe, date) + more_args.append("--gtest_output=xml:" + logname) + else: + logname = userlog[0][userlog[0].find(":")+1:] + + log.debug("Running the test: %s (%s) ==> %s in %s", exe, args + more_args, logname, workingDir) + if self.options.dry_run: + logfile, r = None, 0 + else: + logfile, r = self.runTest(exe, logname, workingDir, args + more_args) + log.debug("Test returned: %s ==> %s", r, logfile) + + if r != 0: + ret = r + if logfile: + logs.append(os.path.relpath(logfile, workingDir)) + return logs, ret + +#=================================================================================================== + +if __name__ == "__main__": + log.error("This is utility file, please execute run.py script") diff --git a/modules/ts/misc/run_utils.py b/modules/ts/misc/run_utils.py new file mode 100644 index 000000000..dca951d17 --- /dev/null +++ b/modules/ts/misc/run_utils.py @@ -0,0 +1,447 @@ +#!/usr/bin/env python + +import sys, os, platform, re, tempfile, glob, getpass, logging +from subprocess import check_call, check_output, CalledProcessError, STDOUT + +hostos = os.name # 'nt', 'posix' +hostmachine = platform.machine() # 'x86', 'AMD64', 'x86_64' + +def initLogger(): + l = logging.getLogger("run.py") + l.setLevel(logging.DEBUG) + ch = logging.StreamHandler(sys.stderr) + ch.setFormatter(logging.Formatter("%(message)s")) + l.addHandler(ch) + return l + +log = initLogger() + +#=================================================================================================== + +class Err(Exception): + def __init__(self, msg, *args): + self.msg = msg % args + +def execute(cmd, silent = False, cwd = "."): + try: + log.debug("Run: %s", cmd) + if silent: + return check_output(cmd, stderr = STDOUT, cwd = cwd).decode("latin-1") + else: + return check_call(cmd, cwd = cwd) + except CalledProcessError as e: + if silent: + log.debug("Process returned: %d", e.returncode) + return e.output.decode("latin-1") + else: + log.error("Process returned: %d", e.returncode) + return e.returncode + +def isColorEnabled(args): + usercolor = [a for a in args if a.startswith("--gtest_color=")] + return len(usercolor) == 0 and sys.stdout.isatty() and hostos != "nt" + +#=================================================================================================== + +def getPlatformVersion(): + mv = platform.mac_ver() + if mv[0]: + return "Darwin" + mv[0] + else: + wv = platform.win32_ver() + if wv[0]: + return "Windows" + wv[0] + else: + lv = platform.linux_distribution() + if lv[0]: + return lv[0] + lv[1] + return None + +def readGitVersion(git, path): + if not path or not git or not os.path.isdir(os.path.join(path, ".git")): + return None + try: + output = execute([git, "-C", path, "rev-parse", "--short", "HEAD"], silent = True) + return output.strip() + except OSError: + log.warning("Git version read failed") + return None + +SIMD_DETECTION_PROGRAM=""" +#if __SSE5__ +# error SSE5 +#endif +#if __AVX2__ +# error AVX2 +#endif +#if __AVX__ +# error AVX +#endif +#if __SSE4_2__ +# error SSE4.2 +#endif +#if __SSE4_1__ +# error SSE4.1 +#endif +#if __SSSE3__ +# error SSSE3 +#endif +#if __SSE3__ +# error SSE3 +#endif +#if __AES__ +# error AES +#endif +#if __SSE2__ +# error SSE2 +#endif +#if __SSE__ +# error SSE +#endif +#if __3dNOW__ +# error 3dNOW +#endif +#if __MMX__ +# error MMX +#endif +#if __ARM_NEON__ +# error NEON +#endif +#error NOSIMD +""" + +def testSIMD(compiler, cxx_flags, compiler_arg = None): + if not compiler: + return None + compiler_output = "" + try: + _, tmpfile = tempfile.mkstemp(suffix=".cpp", text = True) + with open(tmpfile, "w+") as fd: + fd.write(SIMD_DETECTION_PROGRAM) + options = [compiler] + if compiler_arg: + options.append(compiler_arg) + + prev_option = None + for opt in " ".join(cxx_flags).split(): + if opt.count('\"') % 2 == 1: + if prev_option is None: + prev_option = opt + else: + options.append(prev_option + " " + opt) + prev_option = None + elif prev_option is None: + options.append(opt) + else: + prev_option = prev_option + " " + opt + options.append(tmpfile) + compiler_output = execute(options, silent = True) + os.remove(tmpfile) + m = re.search("#error\W+(\w+)", compiler_output) + if m: + return m.group(1) + except OSError: + pass + log.debug("SIMD detection failed") + return None + +#============================================================================== + +parse_patterns = ( + {'name': "cmake_home", 'default': None, 'pattern': re.compile(r"^CMAKE_HOME_DIRECTORY:INTERNAL=(.+)$")}, + {'name': "opencv_home", 'default': None, 'pattern': re.compile(r"^OpenCV_SOURCE_DIR:STATIC=(.+)$")}, + {'name': "opencv_build", 'default': None, 'pattern': re.compile(r"^OpenCV_BINARY_DIR:STATIC=(.+)$")}, + {'name': "tests_dir", 'default': None, 'pattern': re.compile(r"^EXECUTABLE_OUTPUT_PATH:PATH=(.+)$")}, + {'name': "build_type", 'default': "Release", 'pattern': re.compile(r"^CMAKE_BUILD_TYPE:STRING=(.*)$")}, + {'name': "git_executable", 'default': None, 'pattern': re.compile(r"^GIT_EXECUTABLE:FILEPATH=(.*)$")}, + {'name': "cxx_flags", 'default': "", 'pattern': re.compile(r"^CMAKE_CXX_FLAGS:STRING=(.*)$")}, + {'name': "cxx_flags_debug", 'default': "", 'pattern': re.compile(r"^CMAKE_CXX_FLAGS_DEBUG:STRING=(.*)$")}, + {'name': "cxx_flags_release", 'default': "", 'pattern': re.compile(r"^CMAKE_CXX_FLAGS_RELEASE:STRING=(.*)$")}, + {'name': "opencv_cxx_flags", 'default': "", 'pattern': re.compile(r"^OPENCV_EXTRA_C_FLAGS:INTERNAL=(.*)$")}, + {'name': "cxx_flags_android", 'default': None, 'pattern': re.compile(r"^ANDROID_CXX_FLAGS:INTERNAL=(.*)$")}, + {'name': "android_abi", 'default': None, 'pattern': re.compile(r"^ANDROID_ABI:STRING=(.*)$")}, + {'name': "android_executable", 'default': None, 'pattern': re.compile(r"^ANDROID_EXECUTABLE:FILEPATH=(.*android.*)$")}, + {'name': "ant_executable", 'default': None, 'pattern': re.compile(r"^ANT_EXECUTABLE:FILEPATH=(.*ant.*)$")}, + {'name': "java_test_binary_dir", 'default': None, 'pattern': re.compile(r"^opencv_test_java_BINARY_DIR:STATIC=(.*)$")}, + {'name': "is_x64", 'default': "OFF", 'pattern': re.compile(r"^CUDA_64_BIT_DEVICE_CODE:BOOL=(ON)$")},#ugly( + {'name': "cmake_generator", 'default': None, 'pattern': re.compile(r"^CMAKE_GENERATOR:INTERNAL=(.+)$")}, + {'name': "cxx_compiler", 'default': None, 'pattern': re.compile(r"^CMAKE_CXX_COMPILER:\w*PATH=(.+)$")}, + {'name': "cxx_compiler_arg1", 'default': None, 'pattern': re.compile(r"^CMAKE_CXX_COMPILER_ARG1:[A-Z]+=(.+)$")}, + {'name': "with_cuda", 'default': "OFF", 'pattern': re.compile(r"^WITH_CUDA:BOOL=(ON)$")}, + {'name': "cuda_library", 'default': None, 'pattern': re.compile(r"^CUDA_CUDA_LIBRARY:FILEPATH=(.+)$")}, + {'name': "cuda_version", 'default': None, 'pattern': re.compile(r"^CUDA_VERSION:STRING=(.+)$")}, + {'name': "core_dependencies", 'default': None, 'pattern': re.compile(r"^opencv_core_LIB_DEPENDS:STATIC=(.+)$")}, +) + +class CMakeCache: + def __init__(self): + self.setDefaultAttrs() + self.cmake_home_vcver = None + self.opencv_home_vcver = None + self.featuresSIMD = None + self.main_modules = [] + + def setDummy(self, path): + self.tests_dir = os.path.normpath(path) + + def read(self, path, fname, cfg): + rx = re.compile(r'^opencv_(\w+)_SOURCE_DIR:STATIC=(.*)$') + module_paths = {} # name -> path + with open(fname, "rt") as cachefile: + for l in cachefile.readlines(): + ll = l.strip() + if not ll or ll.startswith("#"): + continue + for p in parse_patterns: + match = p["pattern"].match(ll) + if match: + value = match.groups()[0] + if value and not value.endswith("-NOTFOUND"): + setattr(self, p["name"], value) + # log.debug("cache value: %s = %s", p["name"], value) + + match = rx.search(ll) + if match: + module_paths[match.group(1)] = match.group(2) + + if not self.tests_dir: + self.tests_dir = path + else: + rel = os.path.relpath(self.tests_dir, self.opencv_build) + self.tests_dir = os.path.join(path, rel) + self.tests_dir = os.path.normpath(self.tests_dir) + + # fix VS test binary path (add Debug or Release) + if "Visual Studio" in self.cmake_generator: + if cfg: + self.tests_dir = os.path.join(self.tests_dir, self.options.configuration) + else: + self.tests_dir = os.path.join(self.tests_dir, self.build_type) + + self.cmake_home_vcver = readGitVersion(self.git_executable, self.cmake_home) + if self.opencv_home == self.cmake_home: + self.opencv_home_vcver = self.cmake_home_vcver + else: + self.opencv_home_vcver = readGitVersion(self.git_executable, self.opencv_home) + + for module,path in module_paths.items(): + rel = os.path.relpath(path, self.opencv_home) + if not ".." in rel: + self.main_modules.append(module) + + self.flags = [ + self.cxx_flags_android, + self.cxx_flags, + self.cxx_flags_release, + self.opencv_cxx_flags, + self.cxx_flags_release] + self.flags = [f for f in self.flags if f] + self.featuresSIMD = testSIMD(self.cxx_compiler, self.flags, self.cxx_compiler_arg1) + + def setDefaultAttrs(self): + for p in parse_patterns: + setattr(self, p["name"], p["default"]) + + def gatherTests(self, mask, isGood = None): + if self.tests_dir and os.path.isdir(self.tests_dir): + d = os.path.abspath(self.tests_dir) + files = glob.glob(os.path.join(d, mask)) + if not self.getOS() == "android" and self.withJava(): + files.append("java") + return [f for f in files if isGood(f)] + return [] + + def isMainModule(self, name): + return name in self.main_modules + + def withCuda(self): + return self.cuda_version and self.with_cuda == "ON" and self.cuda_library and not self.cuda_library.endswith("-NOTFOUND") + + def withJava(self): + return self.ant_executable and self.java_test_binary_dir + + def getGitVersion(self): + if self.cmake_home_vcver: + if self.cmake_home_vcver == self.opencv_home_vcver: + rev = self.cmake_home_vcver + elif self.opencv_home_vcver: + rev = self.cmake_home_vcver + "-" + self.opencv_home_vcver + else: + rev = self.cmake_home_vcver + else: + rev = None + if rev: + rev = rev.replace(":","to") + else: + rev = "" + return rev + + def getTestFullName(self, shortname): + return os.path.join(self.tests_dir, shortname) + + def getSIMDFeatures(self): + return self.featuresSIMD + + def getOS(self): + if self.android_executable: + return "android" + else: + return hostos + + def getArch(self): + arch = "unknown" + if self.getOS() == "android": + if "armeabi-v7a" in self.android_abi: + arch = "armv7a" + elif "armeabi-v6" in self.android_abi: + arch = "armv6" + elif "armeabi" in self.android_abi: + arch = "armv5te" + elif "x86" in self.android_abi: + arch = "x86" + elif "mips" in self.android_abi: + arch = "mips" + else: + arch = "ARM" + elif self.is_x64 and hostmachine in ["AMD64", "x86_64"]: + arch = "x64" + elif hostmachine in ["x86", "AMD64", "x86_64"]: + arch = "x86" + return arch + + def getDependencies(self): + if self.core_dependencies: + candidates = ["tbb", "ippicv", "ipp", "pthreads"] + return [a for a in self.core_dependencies.split(";") if a and a in candidates] + return [] + + +#============================================================================== + +def getRunningProcessExePathByName_win32(name): + from ctypes import windll, POINTER, pointer, Structure, sizeof + from ctypes import c_long , c_int , c_uint , c_char , c_ubyte , c_char_p , c_void_p + + class PROCESSENTRY32(Structure): + _fields_ = [ ( 'dwSize' , c_uint ) , + ( 'cntUsage' , c_uint) , + ( 'th32ProcessID' , c_uint) , + ( 'th32DefaultHeapID' , c_uint) , + ( 'th32ModuleID' , c_uint) , + ( 'cntThreads' , c_uint) , + ( 'th32ParentProcessID' , c_uint) , + ( 'pcPriClassBase' , c_long) , + ( 'dwFlags' , c_uint) , + ( 'szExeFile' , c_char * 260 ) , + ( 'th32MemoryBase' , c_long) , + ( 'th32AccessKey' , c_long ) ] + + class MODULEENTRY32(Structure): + _fields_ = [ ( 'dwSize' , c_long ) , + ( 'th32ModuleID' , c_long ), + ( 'th32ProcessID' , c_long ), + ( 'GlblcntUsage' , c_long ), + ( 'ProccntUsage' , c_long ) , + ( 'modBaseAddr' , c_long ) , + ( 'modBaseSize' , c_long ) , + ( 'hModule' , c_void_p ) , + ( 'szModule' , c_char * 256 ), + ( 'szExePath' , c_char * 260 ) ] + + TH32CS_SNAPPROCESS = 2 + TH32CS_SNAPMODULE = 0x00000008 + + ## CreateToolhelp32Snapshot + CreateToolhelp32Snapshot= windll.kernel32.CreateToolhelp32Snapshot + CreateToolhelp32Snapshot.reltype = c_long + CreateToolhelp32Snapshot.argtypes = [ c_int , c_int ] + ## Process32First + Process32First = windll.kernel32.Process32First + Process32First.argtypes = [ c_void_p , POINTER( PROCESSENTRY32 ) ] + Process32First.rettype = c_int + ## Process32Next + Process32Next = windll.kernel32.Process32Next + Process32Next.argtypes = [ c_void_p , POINTER(PROCESSENTRY32) ] + Process32Next.rettype = c_int + ## CloseHandle + CloseHandle = windll.kernel32.CloseHandle + CloseHandle.argtypes = [ c_void_p ] + CloseHandle.rettype = c_int + ## Module32First + Module32First = windll.kernel32.Module32First + Module32First.argtypes = [ c_void_p , POINTER(MODULEENTRY32) ] + Module32First.rettype = c_int + + hProcessSnap = c_void_p(0) + hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS , 0 ) + + pe32 = PROCESSENTRY32() + pe32.dwSize = sizeof( PROCESSENTRY32 ) + ret = Process32First( hProcessSnap , pointer( pe32 ) ) + path = None + + while ret : + if name + ".exe" == pe32.szExeFile: + hModuleSnap = c_void_p(0) + me32 = MODULEENTRY32() + me32.dwSize = sizeof( MODULEENTRY32 ) + hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, pe32.th32ProcessID ) + + ret = Module32First( hModuleSnap, pointer(me32) ) + path = me32.szExePath + CloseHandle( hModuleSnap ) + if path: + break + ret = Process32Next( hProcessSnap, pointer(pe32) ) + CloseHandle( hProcessSnap ) + return path + + +def getRunningProcessExePathByName_posix(name): + pids= [pid for pid in os.listdir('/proc') if pid.isdigit()] + for pid in pids: + try: + path = os.readlink(os.path.join('/proc', pid, 'exe')) + if path and path.endswith(name): + return path + except: + pass + +def getRunningProcessExePathByName(name): + try: + if hostos == "nt": + return getRunningProcessExePathByName_win32(name) + elif hostos == "posix": + return getRunningProcessExePathByName_posix(name) + else: + return None + except: + return None + + +class TempEnvDir: + def __init__(self, envname, prefix): + self.envname = envname + self.prefix = prefix + self.saved_name = None + self.new_name = None + + def init(self): + self.saved_name = os.environ.get(self.envname) + self.new_name = tempfile.mkdtemp(prefix=self.prefix, dir=self.saved_name or None) + os.environ[self.envname] = self.new_name + + def clean(self): + if self.saved_name: + os.environ[self.envname] = self.saved_name + else: + del os.environ[self.envname] + try: + shutil.rmtree(self.new_name) + except: + pass + +#=================================================================================================== + +if __name__ == "__main__": + log.error("This is utility file, please execute run.py script") diff --git a/platforms/scripts/valgrind.supp b/platforms/scripts/valgrind.supp new file mode 100644 index 000000000..b37ca2017 --- /dev/null +++ b/platforms/scripts/valgrind.supp @@ -0,0 +1,6 @@ +{ + IPP static init + Memcheck:Cond + fun:ippicvGetCpuFeatures + fun:ippicvStaticInit +}