diff --git a/.gitattributes b/.gitattributes index af704cdf0c..35df6ca2fc 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,42 +1,58 @@ -.git* export-ignore - * text=auto whitespace=trailing-space,space-before-tab,-indent-with-non-tab,tab-in-indent,tabwidth=4 -*.py text -*.cpp text -*.hpp text -*.cxx text -*.hxx text -*.mm text -*.c text -*.h text -*.i text -*.js text -*.java text -*.scala text -*.cu text -*.cl text -*.css_t text -*.qrc text -*.qss text -*.S text -*.rst text -*.tex text -*.sty text +.git* text export-ignore -*.aidl text -*.mk text +*.aidl text +*.appxmanifest text +*.bib text +*.c text +*.cl text +*.conf text +*.cpp text +*.css_t text +*.cu text +*.cxx text +*.def text +*.filelist text +*.h text +*.hpp text +*.htm text +*.html text +*.hxx text +*.i text +*.idl text +*.java text +*.js text +*.mk text +*.mm text +*.plist text +*.properties text +*.py text +*.qrc text +*.qss text +*.S text +*.sbt text +*.scala text +*.sty text +*.tex text +*.txt text +*.xaml text + +# reST underlines/overlines can look like conflict markers +*.rst text conflict-marker-size=80 *.cmake text whitespace=tabwidth=2 *.cmakein text whitespace=tabwidth=2 *.in text whitespace=tabwidth=2 CMakeLists.txt text whitespace=tabwidth=2 -*.png binary -*.jepg binary -*.jpg binary +*.avi binary +*.bmp binary *.exr binary *.ico binary +*.jpeg binary +*.jpg binary +*.png binary *.a binary *.so binary @@ -47,6 +63,7 @@ CMakeLists.txt text whitespace=tabwidth=2 *.pbxproj binary *.vec binary *.doc binary +*.dia binary *.xml -text whitespace=cr-at-eol *.yml -text whitespace=cr-at-eol @@ -55,9 +72,12 @@ CMakeLists.txt text whitespace=tabwidth=2 .cproject -text whitespace=cr-at-eol merge=union org.eclipse.jdt.core.prefs -text whitespace=cr-at-eol merge=union -*.vcproj text eol=crlf merge=union *.bat text eol=crlf *.cmd text eol=crlf *.cmd.tmpl text eol=crlf +*.dsp text eol=crlf -whitespace +*.sln text eol=crlf -whitespace +*.vcproj text eol=crlf -whitespace merge=union +*.vcxproj text eol=crlf -whitespace merge=union -*.sh text eol=lf \ No newline at end of file +*.sh text eol=lf diff --git a/.gitignore b/.gitignore index 0a19f3ceeb..de0707a930 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,10 @@ .DS_Store refman.rst OpenCV4Tegra/ +tegra/ *.user .sw[a-z] .*.swp tags +Thumbs.db +*.autosave diff --git a/3rdparty/.gitattributes b/3rdparty/.gitattributes new file mode 100644 index 0000000000..562b12e16e --- /dev/null +++ b/3rdparty/.gitattributes @@ -0,0 +1 @@ +* -whitespace diff --git a/3rdparty/ffmpeg/ffmpeg_version.cmake b/3rdparty/ffmpeg/ffmpeg_version.cmake index 3f27077d6a..7bb8bab3fb 100644 --- a/3rdparty/ffmpeg/ffmpeg_version.cmake +++ b/3rdparty/ffmpeg/ffmpeg_version.cmake @@ -1,4 +1,4 @@ -set(NEW_FFMPEG 1) +set(HAVE_FFMPEG 1) set(HAVE_FFMPEG_CODEC 1) set(HAVE_FFMPEG_FORMAT 1) set(HAVE_FFMPEG_UTIL 1) @@ -8,4 +8,4 @@ set(HAVE_GENTOO_FFMPEG 1) set(ALIASOF_libavcodec_VERSION 53.61.100) set(ALIASOF_libavformat_VERSION 53.32.100) set(ALIASOF_libavutil_VERSION 51.35.100) -set(ALIASOF_libswscale_VERSION 2.1.100) \ No newline at end of file +set(ALIASOF_libswscale_VERSION 2.1.100) diff --git a/3rdparty/ffmpeg/make.bat b/3rdparty/ffmpeg/make.bat index 9f11b52d63..2323af9ab8 100644 --- a/3rdparty/ffmpeg/make.bat +++ b/3rdparty/ffmpeg/make.bat @@ -1,2 +1,2 @@ set path=c:\dev\msys32\bin;%path% & gcc -Wall -shared -o opencv_ffmpeg.dll -O2 -x c++ -I../include -I../include/ffmpeg_ -I../../modules/highgui/src ffopencv.c -L../lib -lavformat -lavcodec -lavdevice -lswscale -lavutil -lwsock32 -set path=c:\dev\msys64\bin;%path% & gcc -m64 -Wall -shared -o opencv_ffmpeg_64.dll -O2 -x c++ -I../include -I../include/ffmpeg_ -I../../modules/highgui/src ffopencv.c -L../lib -lavformat64 -lavcodec64 -lavdevice64 -lswscale64 -lavutil64 -lavcore64 -lwsock32 -lws2_32 \ No newline at end of file +set path=c:\dev\msys64\bin;%path% & gcc -m64 -Wall -shared -o opencv_ffmpeg_64.dll -O2 -x c++ -I../include -I../include/ffmpeg_ -I../../modules/highgui/src ffopencv.c -L../lib -lavformat64 -lavcodec64 -lavdevice64 -lswscale64 -lavutil64 -lavcore64 -lwsock32 -lws2_32 diff --git a/3rdparty/ffmpeg/readme.txt b/3rdparty/ffmpeg/readme.txt index 1928a53039..e98b285208 100644 --- a/3rdparty/ffmpeg/readme.txt +++ b/3rdparty/ffmpeg/readme.txt @@ -40,5 +40,3 @@ How to update opencv_ffmpeg.dll and opencv_ffmpeg_64.dll when a new version of F 8. Then, go to \3rdparty\ffmpeg, edit make.bat (change paths to the actual paths to your msys32 and msys64 distributions) and then run make.bat - - diff --git a/3rdparty/lib/armeabi-v7a/libnative_camera_r2.2.0.so b/3rdparty/lib/armeabi-v7a/libnative_camera_r2.2.0.so index fb34509bd5..6f28f2c554 100755 Binary files a/3rdparty/lib/armeabi-v7a/libnative_camera_r2.2.0.so and b/3rdparty/lib/armeabi-v7a/libnative_camera_r2.2.0.so differ diff --git a/3rdparty/lib/armeabi-v7a/libnative_camera_r2.3.3.so b/3rdparty/lib/armeabi-v7a/libnative_camera_r2.3.3.so index fce58145c4..010641ed15 100755 Binary files a/3rdparty/lib/armeabi-v7a/libnative_camera_r2.3.3.so and b/3rdparty/lib/armeabi-v7a/libnative_camera_r2.3.3.so differ diff --git a/3rdparty/lib/armeabi-v7a/libnative_camera_r3.0.1.so b/3rdparty/lib/armeabi-v7a/libnative_camera_r3.0.1.so index 2498763d0f..5a145b25bd 100755 Binary files a/3rdparty/lib/armeabi-v7a/libnative_camera_r3.0.1.so and b/3rdparty/lib/armeabi-v7a/libnative_camera_r3.0.1.so differ diff --git a/3rdparty/lib/armeabi-v7a/libnative_camera_r4.0.0.so b/3rdparty/lib/armeabi-v7a/libnative_camera_r4.0.0.so index 9a7047b55d..a524b743f7 100755 Binary files a/3rdparty/lib/armeabi-v7a/libnative_camera_r4.0.0.so and b/3rdparty/lib/armeabi-v7a/libnative_camera_r4.0.0.so differ diff --git a/3rdparty/lib/armeabi-v7a/libnative_camera_r4.0.3.so b/3rdparty/lib/armeabi-v7a/libnative_camera_r4.0.3.so index 98e0d9ea08..a1802f1ff3 100755 Binary files a/3rdparty/lib/armeabi-v7a/libnative_camera_r4.0.3.so and b/3rdparty/lib/armeabi-v7a/libnative_camera_r4.0.3.so differ diff --git a/3rdparty/lib/armeabi-v7a/libnative_camera_r4.1.1.so b/3rdparty/lib/armeabi-v7a/libnative_camera_r4.1.1.so index fe147823ec..089c7e9e2f 100755 Binary files a/3rdparty/lib/armeabi-v7a/libnative_camera_r4.1.1.so and b/3rdparty/lib/armeabi-v7a/libnative_camera_r4.1.1.so differ diff --git a/3rdparty/lib/armeabi-v7a/libnative_camera_r4.2.0.so b/3rdparty/lib/armeabi-v7a/libnative_camera_r4.2.0.so index 646ae716ec..a9ffa4b0cf 100755 Binary files a/3rdparty/lib/armeabi-v7a/libnative_camera_r4.2.0.so and b/3rdparty/lib/armeabi-v7a/libnative_camera_r4.2.0.so differ diff --git a/3rdparty/lib/armeabi-v7a/libnative_camera_r4.3.0.so b/3rdparty/lib/armeabi-v7a/libnative_camera_r4.3.0.so new file mode 100755 index 0000000000..8ff7177ada Binary files /dev/null and b/3rdparty/lib/armeabi-v7a/libnative_camera_r4.3.0.so differ diff --git a/3rdparty/lib/armeabi/libnative_camera_r2.2.0.so b/3rdparty/lib/armeabi/libnative_camera_r2.2.0.so index a0db0d1997..b6ce0d5a5b 100755 Binary files a/3rdparty/lib/armeabi/libnative_camera_r2.2.0.so and b/3rdparty/lib/armeabi/libnative_camera_r2.2.0.so differ diff --git a/3rdparty/lib/armeabi/libnative_camera_r2.3.3.so b/3rdparty/lib/armeabi/libnative_camera_r2.3.3.so index 6f167cb0cb..635ce681a9 100755 Binary files a/3rdparty/lib/armeabi/libnative_camera_r2.3.3.so and b/3rdparty/lib/armeabi/libnative_camera_r2.3.3.so differ diff --git a/3rdparty/lib/armeabi/libnative_camera_r3.0.1.so b/3rdparty/lib/armeabi/libnative_camera_r3.0.1.so index 26d286a18d..caacf39d4a 100755 Binary files a/3rdparty/lib/armeabi/libnative_camera_r3.0.1.so and b/3rdparty/lib/armeabi/libnative_camera_r3.0.1.so differ diff --git a/3rdparty/lib/armeabi/libnative_camera_r4.0.0.so b/3rdparty/lib/armeabi/libnative_camera_r4.0.0.so index f29707cae3..fff4a8069b 100755 Binary files a/3rdparty/lib/armeabi/libnative_camera_r4.0.0.so and b/3rdparty/lib/armeabi/libnative_camera_r4.0.0.so differ diff --git a/3rdparty/lib/armeabi/libnative_camera_r4.0.3.so b/3rdparty/lib/armeabi/libnative_camera_r4.0.3.so index 85e0320a9c..3119265558 100755 Binary files a/3rdparty/lib/armeabi/libnative_camera_r4.0.3.so and b/3rdparty/lib/armeabi/libnative_camera_r4.0.3.so differ diff --git a/3rdparty/lib/armeabi/libnative_camera_r4.1.1.so b/3rdparty/lib/armeabi/libnative_camera_r4.1.1.so index 35c5141b9c..7c18baf01f 100755 Binary files a/3rdparty/lib/armeabi/libnative_camera_r4.1.1.so and b/3rdparty/lib/armeabi/libnative_camera_r4.1.1.so differ diff --git a/3rdparty/lib/armeabi/libnative_camera_r4.2.0.so b/3rdparty/lib/armeabi/libnative_camera_r4.2.0.so index 816669e37c..8bb093a3d0 100755 Binary files a/3rdparty/lib/armeabi/libnative_camera_r4.2.0.so and b/3rdparty/lib/armeabi/libnative_camera_r4.2.0.so differ diff --git a/3rdparty/lib/armeabi/libnative_camera_r4.3.0.so b/3rdparty/lib/armeabi/libnative_camera_r4.3.0.so new file mode 100755 index 0000000000..a05f179172 Binary files /dev/null and b/3rdparty/lib/armeabi/libnative_camera_r4.3.0.so differ diff --git a/3rdparty/lib/mips/libnative_camera_r4.0.3.so b/3rdparty/lib/mips/libnative_camera_r4.0.3.so index 616323de96..b9500441a0 100755 Binary files a/3rdparty/lib/mips/libnative_camera_r4.0.3.so and b/3rdparty/lib/mips/libnative_camera_r4.0.3.so differ diff --git a/3rdparty/lib/mips/libnative_camera_r4.1.1.so b/3rdparty/lib/mips/libnative_camera_r4.1.1.so index 7ee4f25766..d11dcf036d 100755 Binary files a/3rdparty/lib/mips/libnative_camera_r4.1.1.so and b/3rdparty/lib/mips/libnative_camera_r4.1.1.so differ diff --git a/3rdparty/lib/mips/libnative_camera_r4.2.0.so b/3rdparty/lib/mips/libnative_camera_r4.2.0.so index 33d7745ad8..b06a6819f1 100755 Binary files a/3rdparty/lib/mips/libnative_camera_r4.2.0.so and b/3rdparty/lib/mips/libnative_camera_r4.2.0.so differ diff --git a/3rdparty/lib/mips/libnative_camera_r4.3.0.so b/3rdparty/lib/mips/libnative_camera_r4.3.0.so new file mode 100755 index 0000000000..844b806b9d Binary files /dev/null and b/3rdparty/lib/mips/libnative_camera_r4.3.0.so differ diff --git a/3rdparty/lib/x86/libnative_camera_r2.3.3.so b/3rdparty/lib/x86/libnative_camera_r2.3.3.so index d40409f222..0dd8904ac9 100755 Binary files a/3rdparty/lib/x86/libnative_camera_r2.3.3.so and b/3rdparty/lib/x86/libnative_camera_r2.3.3.so differ diff --git a/3rdparty/lib/x86/libnative_camera_r3.0.1.so b/3rdparty/lib/x86/libnative_camera_r3.0.1.so index 221b833a5b..105a19d0c5 100755 Binary files a/3rdparty/lib/x86/libnative_camera_r3.0.1.so and b/3rdparty/lib/x86/libnative_camera_r3.0.1.so differ diff --git a/3rdparty/lib/x86/libnative_camera_r4.0.3.so b/3rdparty/lib/x86/libnative_camera_r4.0.3.so index 786d6dccbf..b01a4bd28c 100755 Binary files a/3rdparty/lib/x86/libnative_camera_r4.0.3.so and b/3rdparty/lib/x86/libnative_camera_r4.0.3.so differ diff --git a/3rdparty/lib/x86/libnative_camera_r4.1.1.so b/3rdparty/lib/x86/libnative_camera_r4.1.1.so index 8ec6cb74d9..a59ae39b3c 100755 Binary files a/3rdparty/lib/x86/libnative_camera_r4.1.1.so and b/3rdparty/lib/x86/libnative_camera_r4.1.1.so differ diff --git a/3rdparty/lib/x86/libnative_camera_r4.2.0.so b/3rdparty/lib/x86/libnative_camera_r4.2.0.so index 7fe74d21ab..b90b826448 100755 Binary files a/3rdparty/lib/x86/libnative_camera_r4.2.0.so and b/3rdparty/lib/x86/libnative_camera_r4.2.0.so differ diff --git a/3rdparty/lib/x86/libnative_camera_r4.3.0.so b/3rdparty/lib/x86/libnative_camera_r4.3.0.so new file mode 100755 index 0000000000..6607e5da81 Binary files /dev/null and b/3rdparty/lib/x86/libnative_camera_r4.3.0.so differ diff --git a/3rdparty/libjasper/CMakeLists.txt b/3rdparty/libjasper/CMakeLists.txt index 42855e2a6d..7a70a19cf0 100644 --- a/3rdparty/libjasper/CMakeLists.txt +++ b/3rdparty/libjasper/CMakeLists.txt @@ -23,7 +23,9 @@ if(WIN32 AND NOT MINGW) add_definitions(-DJAS_WIN_MSVC_BUILD) endif(WIN32 AND NOT MINGW) -ocv_warnings_disable(CMAKE_C_FLAGS -Wno-implicit-function-declaration -Wno-uninitialized -Wmissing-prototypes -Wmissing-declarations -Wunused -Wshadow -Wsign-compare) +ocv_warnings_disable(CMAKE_C_FLAGS -Wno-implicit-function-declaration -Wno-uninitialized -Wmissing-prototypes + -Wno-unused-but-set-parameter -Wmissing-declarations -Wunused -Wshadow + -Wsign-compare -Wstrict-overflow) ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter) # clang ocv_warnings_disable(CMAKE_C_FLAGS /wd4013 /wd4018 /wd4101 /wd4244 /wd4267 /wd4715) # vs2005 @@ -47,4 +49,3 @@ endif() if(NOT BUILD_SHARED_LIBS) install(TARGETS ${JASPER_LIBRARY} ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT main) endif() - diff --git a/3rdparty/libpng/CMakeLists.txt b/3rdparty/libpng/CMakeLists.txt index d47dd53fcd..141c9d1518 100644 --- a/3rdparty/libpng/CMakeLists.txt +++ b/3rdparty/libpng/CMakeLists.txt @@ -9,7 +9,7 @@ else() project(${PNG_LIBRARY}) endif() -ocv_include_directories("${CMAKE_CURRENT_SOURCE_DIR}" ${ZLIB_INCLUDE_DIR}) +ocv_include_directories("${CMAKE_CURRENT_SOURCE_DIR}" ${ZLIB_INCLUDE_DIRS}) file(GLOB lib_srcs *.c) file(GLOB lib_hdrs *.h) @@ -29,8 +29,12 @@ if(MSVC) add_definitions(-D_CRT_SECURE_NO_DEPRECATE) endif(MSVC) +if (HAVE_WINRT) + add_definitions(-DHAVE_WINRT) +endif() + add_library(${PNG_LIBRARY} STATIC ${lib_srcs} ${lib_hdrs}) -target_link_libraries(${PNG_LIBRARY} ${ZLIB_LIBRARY}) +target_link_libraries(${PNG_LIBRARY} ${ZLIB_LIBRARIES}) if(UNIX) if(CMAKE_COMPILER_IS_GNUCXX OR CV_ICC) diff --git a/3rdparty/libpng/opencv-libpng.patch b/3rdparty/libpng/opencv-libpng.patch new file mode 100644 index 0000000000..6ca96392a0 --- /dev/null +++ b/3rdparty/libpng/opencv-libpng.patch @@ -0,0 +1,22 @@ +diff --git a/3rdparty/libpng/pngpriv.h b/3rdparty/libpng/pngpriv.h +index 07b2b0b..e7824b8 100644 +--- a/3rdparty/libpng/pngpriv.h ++++ b/3rdparty/libpng/pngpriv.h +@@ -360,7 +360,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; + + /* Memory model/platform independent fns */ + #ifndef PNG_ABORT +-# ifdef _WINDOWS_ ++# if defined(_WINDOWS_) && !defined(HAVE_WINRT) + # define PNG_ABORT() ExitProcess(0) + # else + # define PNG_ABORT() abort() +@@ -378,7 +378,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; + # define png_memcpy _fmemcpy + # define png_memset _fmemset + #else +-# ifdef _WINDOWS_ /* Favor Windows over C runtime fns */ ++# if defined(_WINDOWS_) && !defined(HAVE_WINRT) /* Favor Windows over C runtime fns */ + # define CVT_PTR(ptr) (ptr) + # define CVT_PTR_NOCHECK(ptr) (ptr) + # define png_strlen lstrlenA diff --git a/3rdparty/libpng/pngpriv.h b/3rdparty/libpng/pngpriv.h index 07b2b0b05b..e7824b839e 100644 --- a/3rdparty/libpng/pngpriv.h +++ b/3rdparty/libpng/pngpriv.h @@ -360,7 +360,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; /* Memory model/platform independent fns */ #ifndef PNG_ABORT -# ifdef _WINDOWS_ +# if defined(_WINDOWS_) && !defined(HAVE_WINRT) # define PNG_ABORT() ExitProcess(0) # else # define PNG_ABORT() abort() @@ -378,7 +378,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; # define png_memcpy _fmemcpy # define png_memset _fmemset #else -# ifdef _WINDOWS_ /* Favor Windows over C runtime fns */ +# if defined(_WINDOWS_) && !defined(HAVE_WINRT) /* Favor Windows over C runtime fns */ # define CVT_PTR(ptr) (ptr) # define CVT_PTR_NOCHECK(ptr) (ptr) # define png_strlen lstrlenA diff --git a/3rdparty/libtiff/CMakeLists.txt b/3rdparty/libtiff/CMakeLists.txt index 46fef61c7d..cea2f906fd 100644 --- a/3rdparty/libtiff/CMakeLists.txt +++ b/3rdparty/libtiff/CMakeLists.txt @@ -17,14 +17,14 @@ check_include_file(string.h HAVE_STRING_H) check_include_file(sys/types.h HAVE_SYS_TYPES_H) check_include_file(unistd.h HAVE_UNISTD_H) -if(WIN32) +if(WIN32 AND NOT HAVE_WINRT) set(USE_WIN32_FILEIO 1) endif() configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tif_config.h.cmakein" "${CMAKE_CURRENT_BINARY_DIR}/tif_config.h" @ONLY) -ocv_include_directories("${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}" ${ZLIB_INCLUDE_DIR}) +ocv_include_directories("${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}" ${ZLIB_INCLUDE_DIRS}) set(lib_srcs tif_aux.c @@ -79,14 +79,12 @@ set(lib_srcs "${CMAKE_CURRENT_BINARY_DIR}/tif_config.h" ) -if(UNIX) +if(WIN32 AND NOT HAVE_WINRT) + list(APPEND lib_srcs tif_win32.c) +else() list(APPEND lib_srcs tif_unix.c) endif() - -if(WIN32) - list(APPEND lib_srcs tif_win32.c) -endif(WIN32) - + ocv_warnings_disable(CMAKE_C_FLAGS -Wno-unused-but-set-variable -Wmissing-prototypes -Wmissing-declarations -Wundef -Wunused -Wsign-compare -Wcast-align -Wshadow -Wno-maybe-uninitialized -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast) ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter) # clang diff --git a/3rdparty/libtiff/tif_config.h.cmakein b/3rdparty/libtiff/tif_config.h.cmakein index 1e6bc0454c..182f2833d1 100644 --- a/3rdparty/libtiff/tif_config.h.cmakein +++ b/3rdparty/libtiff/tif_config.h.cmakein @@ -168,4 +168,3 @@ /* Support Deflate compression */ #define ZIP_SUPPORT 1 - diff --git a/3rdparty/libwebp/dec/alpha.c b/3rdparty/libwebp/dec/alpha.c index 6e65de9030..b5e68919ca 100644 --- a/3rdparty/libwebp/dec/alpha.c +++ b/3rdparty/libwebp/dec/alpha.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Alpha-plane decompression. @@ -13,27 +15,17 @@ #include "./vp8i.h" #include "./vp8li.h" #include "../utils/filters.h" -#include "../utils/quant_levels.h" +#include "../utils/quant_levels_dec.h" #include "../webp/format_constants.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif -// TODO(skal): move to dsp/ ? -static void CopyPlane(const uint8_t* src, int src_stride, - uint8_t* dst, int dst_stride, int width, int height) { - while (height-- > 0) { - memcpy(dst, src, width); - src += src_stride; - dst += dst_stride; - } -} - //------------------------------------------------------------------------------ // Decodes the compressed data 'data' of size 'data_size' into the 'output'. // The 'output' buffer should be pre-allocated and must be of the same -// dimension 'height'x'stride', as that of the image. +// dimension 'height'x'width', as that of the image. // // Returns 1 on successfully decoding the compressed alpha and // 0 if either: @@ -41,17 +33,16 @@ static void CopyPlane(const uint8_t* src, int src_stride, // error returned by appropriate compression method. static int DecodeAlpha(const uint8_t* data, size_t data_size, - int width, int height, int stride, uint8_t* output) { - uint8_t* decoded_data = NULL; - const size_t decoded_size = height * width; - uint8_t* unfiltered_data = NULL; + int width, int height, uint8_t* output) { WEBP_FILTER_TYPE filter; int pre_processing; int rsrv; int ok = 0; int method; + const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN; + const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN; - assert(width > 0 && height > 0 && stride >= width); + assert(width > 0 && height > 0); assert(data != NULL && output != NULL); if (data_size <= ALPHA_HEADER_LEN) { @@ -71,44 +62,26 @@ static int DecodeAlpha(const uint8_t* data, size_t data_size, } if (method == ALPHA_NO_COMPRESSION) { - ok = (data_size >= decoded_size); - decoded_data = (uint8_t*)data + ALPHA_HEADER_LEN; + const size_t alpha_decoded_size = height * width; + ok = (alpha_data_size >= alpha_decoded_size); + if (ok) memcpy(output, alpha_data, alpha_decoded_size); } else { - decoded_data = (uint8_t*)malloc(decoded_size); - if (decoded_data == NULL) return 0; - ok = VP8LDecodeAlphaImageStream(width, height, - data + ALPHA_HEADER_LEN, - data_size - ALPHA_HEADER_LEN, - decoded_data); + ok = VP8LDecodeAlphaImageStream(width, height, alpha_data, alpha_data_size, + output); } if (ok) { - WebPFilterFunc unfilter_func = WebPUnfilters[filter]; + WebPUnfilterFunc unfilter_func = WebPUnfilters[filter]; if (unfilter_func != NULL) { - unfiltered_data = (uint8_t*)malloc(decoded_size); - if (unfiltered_data == NULL) { - ok = 0; - goto Error; - } // TODO(vikas): Implement on-the-fly decoding & filter mechanism to decode // and apply filter per image-row. - unfilter_func(decoded_data, width, height, 1, width, unfiltered_data); - // Construct raw_data (height x stride) from alpha data (height x width). - CopyPlane(unfiltered_data, width, output, stride, width, height); - free(unfiltered_data); - } else { - // Construct raw_data (height x stride) from alpha data (height x width). - CopyPlane(decoded_data, width, output, stride, width, height); + unfilter_func(width, height, width, output); } if (pre_processing == ALPHA_PREPROCESSED_LEVELS) { - ok = DequantizeLevels(decoded_data, width, height); + ok = DequantizeLevels(output, width, height); } } - Error: - if (method != ALPHA_NO_COMPRESSION) { - free(decoded_data); - } return ok; } @@ -116,23 +89,25 @@ static int DecodeAlpha(const uint8_t* data, size_t data_size, const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, int row, int num_rows) { - const int stride = dec->pic_hdr_.width_; + const int width = dec->pic_hdr_.width_; + const int height = dec->pic_hdr_.height_; - if (row < 0 || num_rows < 0 || row + num_rows > dec->pic_hdr_.height_) { + if (row < 0 || num_rows < 0 || row + num_rows > height) { return NULL; // sanity check. } if (row == 0) { // Decode everything during the first call. + assert(!dec->is_alpha_decoded_); if (!DecodeAlpha(dec->alpha_data_, (size_t)dec->alpha_data_size_, - dec->pic_hdr_.width_, dec->pic_hdr_.height_, stride, - dec->alpha_plane_)) { + width, height, dec->alpha_plane_)) { return NULL; // Error. } + dec->is_alpha_decoded_ = 1; } // Return a pointer to the current decoded row. - return dec->alpha_plane_ + row * stride; + return dec->alpha_plane_ + row * width; } #if defined(__cplusplus) || defined(c_plusplus) diff --git a/3rdparty/libwebp/dec/buffer.c b/3rdparty/libwebp/dec/buffer.c index c159f6f248..3855715239 100644 --- a/3rdparty/libwebp/dec/buffer.c +++ b/3rdparty/libwebp/dec/buffer.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Everything about WebPDecBuffer diff --git a/3rdparty/libwebp/dec/decode_vp8.h b/3rdparty/libwebp/dec/decode_vp8.h index 12c77bcbf6..acdb15aaa9 100644 --- a/3rdparty/libwebp/dec/decode_vp8.h +++ b/3rdparty/libwebp/dec/decode_vp8.h @@ -1,8 +1,10 @@ // Copyright 2010 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Low-level API for VP8 decoder diff --git a/3rdparty/libwebp/dec/frame.c b/3rdparty/libwebp/dec/frame.c index 9c91a48e17..5f6a7d9823 100644 --- a/3rdparty/libwebp/dec/frame.c +++ b/3rdparty/libwebp/dec/frame.c @@ -1,8 +1,10 @@ // Copyright 2010 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Frame-reconstruction function. Memory allocation. @@ -97,53 +99,50 @@ static void FilterRow(const VP8Decoder* const dec) { } //------------------------------------------------------------------------------ +// Precompute the filtering strength for each segment and each i4x4/i16x16 mode. -void VP8StoreBlock(VP8Decoder* const dec) { +static void PrecomputeFilterStrengths(VP8Decoder* const dec) { if (dec->filter_type_ > 0) { - VP8FInfo* const info = dec->f_info_ + dec->mb_x_; - const int skip = dec->mb_info_[dec->mb_x_].skip_; - int level = dec->filter_levels_[dec->segment_]; - if (dec->filter_hdr_.use_lf_delta_) { - // TODO(skal): only CURRENT is handled for now. - level += dec->filter_hdr_.ref_lf_delta_[0]; - if (dec->is_i4x4_) { - level += dec->filter_hdr_.mode_lf_delta_[0]; - } - } - level = (level < 0) ? 0 : (level > 63) ? 63 : level; - info->f_level_ = level; - - if (dec->filter_hdr_.sharpness_ > 0) { - if (dec->filter_hdr_.sharpness_ > 4) { - level >>= 2; + int s; + const VP8FilterHeader* const hdr = &dec->filter_hdr_; + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + int i4x4; + // First, compute the initial level + int base_level; + if (dec->segment_hdr_.use_segment_) { + base_level = dec->segment_hdr_.filter_strength_[s]; + if (!dec->segment_hdr_.absolute_delta_) { + base_level += hdr->level_; + } } else { - level >>= 1; + base_level = hdr->level_; } - if (level > 9 - dec->filter_hdr_.sharpness_) { - level = 9 - dec->filter_hdr_.sharpness_; - } - } + for (i4x4 = 0; i4x4 <= 1; ++i4x4) { + VP8FInfo* const info = &dec->fstrengths_[s][i4x4]; + int level = base_level; + if (hdr->use_lf_delta_) { + // TODO(skal): only CURRENT is handled for now. + level += hdr->ref_lf_delta_[0]; + if (i4x4) { + level += hdr->mode_lf_delta_[0]; + } + } + level = (level < 0) ? 0 : (level > 63) ? 63 : level; + info->f_level_ = level; - info->f_ilevel_ = (level < 1) ? 1 : level; - info->f_inner_ = (!skip || dec->is_i4x4_); - } - { - // Transfer samples to row cache - int y; - const int y_offset = dec->cache_id_ * 16 * dec->cache_y_stride_; - const int uv_offset = dec->cache_id_ * 8 * dec->cache_uv_stride_; - uint8_t* const ydst = dec->cache_y_ + dec->mb_x_ * 16 + y_offset; - uint8_t* const udst = dec->cache_u_ + dec->mb_x_ * 8 + uv_offset; - uint8_t* const vdst = dec->cache_v_ + dec->mb_x_ * 8 + uv_offset; - for (y = 0; y < 16; ++y) { - memcpy(ydst + y * dec->cache_y_stride_, - dec->yuv_b_ + Y_OFF + y * BPS, 16); - } - for (y = 0; y < 8; ++y) { - memcpy(udst + y * dec->cache_uv_stride_, - dec->yuv_b_ + U_OFF + y * BPS, 8); - memcpy(vdst + y * dec->cache_uv_stride_, - dec->yuv_b_ + V_OFF + y * BPS, 8); + if (hdr->sharpness_ > 0) { + if (hdr->sharpness_ > 4) { + level >>= 2; + } else { + level >>= 1; + } + if (level > 9 - hdr->sharpness_) { + level = 9 - hdr->sharpness_; + } + } + info->f_ilevel_ = (level < 1) ? 1 : level; + info->f_inner_ = 0; + } } } } @@ -339,6 +338,7 @@ VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) { dec->br_mb_y_ = dec->mb_h_; } } + PrecomputeFilterStrengths(dec); return VP8_STATUS_OK; } @@ -496,6 +496,7 @@ static int AllocateMemory(VP8Decoder* const dec) { // alpha plane dec->alpha_plane_ = alpha_size ? (uint8_t*)mem : NULL; mem += alpha_size; + assert(mem <= (uint8_t*)dec->mem_ + dec->mem_size_); // note: left-info is initialized once for all. memset(dec->mb_info_ - 1, 0, mb_info_size); @@ -551,6 +552,7 @@ static WEBP_INLINE void Copy32b(uint8_t* dst, uint8_t* src) { } void VP8ReconstructBlock(VP8Decoder* const dec) { + int j; uint8_t* const y_dst = dec->yuv_b_ + Y_OFF; uint8_t* const u_dst = dec->yuv_b_ + U_OFF; uint8_t* const v_dst = dec->yuv_b_ + V_OFF; @@ -558,7 +560,6 @@ void VP8ReconstructBlock(VP8Decoder* const dec) { // Rotate in the left samples from previously decoded block. We move four // pixels at a time for alignment reason, and because of in-loop filter. if (dec->mb_x_ > 0) { - int j; for (j = -1; j < 16; ++j) { Copy32b(&y_dst[j * BPS - 4], &y_dst[j * BPS + 12]); } @@ -567,7 +568,6 @@ void VP8ReconstructBlock(VP8Decoder* const dec) { Copy32b(&v_dst[j * BPS - 4], &v_dst[j * BPS + 4]); } } else { - int j; for (j = 0; j < 16; ++j) { y_dst[j * BPS - 1] = 129; } @@ -670,6 +670,21 @@ void VP8ReconstructBlock(VP8Decoder* const dec) { } } } + // Transfer reconstructed samples from yuv_b_ cache to final destination. + { + const int y_offset = dec->cache_id_ * 16 * dec->cache_y_stride_; + const int uv_offset = dec->cache_id_ * 8 * dec->cache_uv_stride_; + uint8_t* const y_out = dec->cache_y_ + dec->mb_x_ * 16 + y_offset; + uint8_t* const u_out = dec->cache_u_ + dec->mb_x_ * 8 + uv_offset; + uint8_t* const v_out = dec->cache_v_ + dec->mb_x_ * 8 + uv_offset; + for (j = 0; j < 16; ++j) { + memcpy(y_out + j * dec->cache_y_stride_, y_dst + j * BPS, 16); + } + for (j = 0; j < 8; ++j) { + memcpy(u_out + j * dec->cache_uv_stride_, u_dst + j * BPS, 8); + memcpy(v_out + j * dec->cache_uv_stride_, v_dst + j * BPS, 8); + } + } } //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/dec/idec.c b/3rdparty/libwebp/dec/idec.c index 7df790ced8..5fbf49aafe 100644 --- a/3rdparty/libwebp/dec/idec.c +++ b/3rdparty/libwebp/dec/idec.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Incremental decoding @@ -97,6 +99,23 @@ static WEBP_INLINE size_t MemDataSize(const MemBuffer* mem) { return (mem->end_ - mem->start_); } +// Check if we need to preserve the compressed alpha data, as it may not have +// been decoded yet. +static int NeedCompressedAlpha(const WebPIDecoder* const idec) { + if (idec->state_ == STATE_PRE_VP8) { + // We haven't parsed the headers yet, so we don't know whether the image is + // lossy or lossless. This also means that we haven't parsed the ALPH chunk. + return 0; + } + if (idec->is_lossless_) { + return 0; // ALPH chunk is not present for lossless images. + } else { + const VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + assert(dec != NULL); // Must be true as idec->state_ != STATE_PRE_VP8. + return (dec->alpha_data_ != NULL) && !dec->is_alpha_decoded_; + } +} + static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { MemBuffer* const mem = &idec->mem_; const uint8_t* const new_base = mem->buf_ + mem->start_; @@ -122,6 +141,7 @@ static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { } assert(last_part >= 0); dec->parts_[last_part].buf_end_ = mem->buf_ + mem->end_; + if (NeedCompressedAlpha(idec)) dec->alpha_data_ += offset; } else { // Resize lossless bitreader VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; VP8LBitReaderSetBuffer(&dec->br_, new_base, MemDataSize(mem)); @@ -133,8 +153,12 @@ static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { // size if required and also updates VP8BitReader's if new memory is allocated. static int AppendToMemBuffer(WebPIDecoder* const idec, const uint8_t* const data, size_t data_size) { + VP8Decoder* const dec = (VP8Decoder*)idec->dec_; MemBuffer* const mem = &idec->mem_; - const uint8_t* const old_base = mem->buf_ + mem->start_; + const int need_compressed_alpha = NeedCompressedAlpha(idec); + const uint8_t* const old_start = mem->buf_ + mem->start_; + const uint8_t* const old_base = + need_compressed_alpha ? dec->alpha_data_ : old_start; assert(mem->mode_ == MEM_MODE_APPEND); if (data_size > MAX_CHUNK_PAYLOAD) { // security safeguard: trying to allocate more than what the format @@ -143,7 +167,8 @@ static int AppendToMemBuffer(WebPIDecoder* const idec, } if (mem->end_ + data_size > mem->buf_size_) { // Need some free memory - const size_t current_size = MemDataSize(mem); + const size_t new_mem_start = old_start - old_base; + const size_t current_size = MemDataSize(mem) + new_mem_start; const uint64_t new_size = (uint64_t)current_size + data_size; const uint64_t extra_size = (new_size + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1); uint8_t* const new_buf = @@ -153,7 +178,7 @@ static int AppendToMemBuffer(WebPIDecoder* const idec, free(mem->buf_); mem->buf_ = new_buf; mem->buf_size_ = (size_t)extra_size; - mem->start_ = 0; + mem->start_ = new_mem_start; mem->end_ = current_size; } @@ -161,14 +186,15 @@ static int AppendToMemBuffer(WebPIDecoder* const idec, mem->end_ += data_size; assert(mem->end_ <= mem->buf_size_); - DoRemap(idec, mem->buf_ + mem->start_ - old_base); + DoRemap(idec, mem->buf_ + mem->start_ - old_start); return 1; } static int RemapMemBuffer(WebPIDecoder* const idec, const uint8_t* const data, size_t data_size) { MemBuffer* const mem = &idec->mem_; - const uint8_t* const old_base = mem->buf_ + mem->start_; + const uint8_t* const old_buf = mem->buf_; + const uint8_t* const old_start = old_buf + mem->start_; assert(mem->mode_ == MEM_MODE_MAP); if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer! @@ -176,7 +202,7 @@ static int RemapMemBuffer(WebPIDecoder* const idec, mem->buf_ = (uint8_t*)data; mem->end_ = mem->buf_size_ = data_size; - DoRemap(idec, mem->buf_ + mem->start_ - old_base); + DoRemap(idec, mem->buf_ + mem->start_ - old_start); return 1; } @@ -425,9 +451,8 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) { } return VP8_STATUS_SUSPENDED; } + // Reconstruct and emit samples. VP8ReconstructBlock(dec); - // Store data and save block's filtering params - VP8StoreBlock(dec); // Release buffer only if there is only one partition if (dec->num_parts_ == 1) { @@ -596,12 +621,22 @@ void WebPIDelete(WebPIDecoder* idec) { WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer, size_t output_buffer_size, int output_stride) { + const int is_external_memory = (output_buffer != NULL); WebPIDecoder* idec; + if (mode >= MODE_YUV) return NULL; + if (!is_external_memory) { // Overwrite parameters to sane values. + output_buffer_size = 0; + output_stride = 0; + } else { // A buffer was passed. Validate the other params. + if (output_stride == 0 || output_buffer_size == 0) { + return NULL; // invalid parameter. + } + } idec = WebPINewDecoder(NULL); if (idec == NULL) return NULL; idec->output_.colorspace = mode; - idec->output_.is_external_memory = 1; + idec->output_.is_external_memory = is_external_memory; idec->output_.u.RGBA.rgba = output_buffer; idec->output_.u.RGBA.stride = output_stride; idec->output_.u.RGBA.size = output_buffer_size; @@ -612,10 +647,30 @@ WebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride, uint8_t* u, size_t u_size, int u_stride, uint8_t* v, size_t v_size, int v_stride, uint8_t* a, size_t a_size, int a_stride) { - WebPIDecoder* const idec = WebPINewDecoder(NULL); + const int is_external_memory = (luma != NULL); + WebPIDecoder* idec; + WEBP_CSP_MODE colorspace; + + if (!is_external_memory) { // Overwrite parameters to sane values. + luma_size = u_size = v_size = a_size = 0; + luma_stride = u_stride = v_stride = a_stride = 0; + u = v = a = NULL; + colorspace = MODE_YUVA; + } else { // A luma buffer was passed. Validate the other parameters. + if (u == NULL || v == NULL) return NULL; + if (luma_size == 0 || u_size == 0 || v_size == 0) return NULL; + if (luma_stride == 0 || u_stride == 0 || v_stride == 0) return NULL; + if (a != NULL) { + if (a_size == 0 || a_stride == 0) return NULL; + } + colorspace = (a == NULL) ? MODE_YUV : MODE_YUVA; + } + + idec = WebPINewDecoder(NULL); if (idec == NULL) return NULL; - idec->output_.colorspace = (a == NULL) ? MODE_YUV : MODE_YUVA; - idec->output_.is_external_memory = 1; + + idec->output_.colorspace = colorspace; + idec->output_.is_external_memory = is_external_memory; idec->output_.u.YUVA.y = luma; idec->output_.u.YUVA.y_stride = luma_stride; idec->output_.u.YUVA.y_size = luma_size; diff --git a/3rdparty/libwebp/dec/io.c b/3rdparty/libwebp/dec/io.c index 594804c2e6..63810b4472 100644 --- a/3rdparty/libwebp/dec/io.c +++ b/3rdparty/libwebp/dec/io.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // functions for sample output. diff --git a/3rdparty/libwebp/dec/layer.c b/3rdparty/libwebp/dec/layer.c index a3a5bdcfe8..9a4b2d9032 100644 --- a/3rdparty/libwebp/dec/layer.c +++ b/3rdparty/libwebp/dec/layer.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Enhancement layer (for YUV444/422) diff --git a/3rdparty/libwebp/dec/quant.c b/3rdparty/libwebp/dec/quant.c index d54097af0d..a4cc693db7 100644 --- a/3rdparty/libwebp/dec/quant.c +++ b/3rdparty/libwebp/dec/quant.c @@ -1,8 +1,10 @@ // Copyright 2010 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Quantizer initialization diff --git a/3rdparty/libwebp/dec/tree.c b/3rdparty/libwebp/dec/tree.c index 82484e4c55..3f02efe43f 100644 --- a/3rdparty/libwebp/dec/tree.c +++ b/3rdparty/libwebp/dec/tree.c @@ -1,8 +1,10 @@ // Copyright 2010 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Coding trees and probas diff --git a/3rdparty/libwebp/dec/vp8.c b/3rdparty/libwebp/dec/vp8.c index b0ccfa2a06..8632e48e57 100644 --- a/3rdparty/libwebp/dec/vp8.c +++ b/3rdparty/libwebp/dec/vp8.c @@ -1,8 +1,10 @@ // Copyright 2010 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // main entry for the decoder @@ -236,20 +238,6 @@ static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) { } } dec->filter_type_ = (hdr->level_ == 0) ? 0 : hdr->simple_ ? 1 : 2; - if (dec->filter_type_ > 0) { // precompute filter levels per segment - if (dec->segment_hdr_.use_segment_) { - int s; - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - int strength = dec->segment_hdr_.filter_strength_[s]; - if (!dec->segment_hdr_.absolute_delta_) { - strength += hdr->level_; - } - dec->filter_levels_[s] = strength; - } - } else { - dec->filter_levels_[0] = hdr->level_; - } - } return !br->eof_; } @@ -458,7 +446,7 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { //------------------------------------------------------------------------------ // Residual decoding (Paragraph 13.2 / 13.3) -static const uint8_t kBands[16 + 1] = { +static const int kBands[16 + 1] = { 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 0 // extra entry as sentinel }; @@ -474,6 +462,39 @@ static const uint8_t kZigzag[16] = { }; typedef const uint8_t (*ProbaArray)[NUM_CTX][NUM_PROBAS]; // for const-casting +typedef const uint8_t (*ProbaCtxArray)[NUM_PROBAS]; + +// See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2 +static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) { + int v; + if (!VP8GetBit(br, p[3])) { + if (!VP8GetBit(br, p[4])) { + v = 2; + } else { + v = 3 + VP8GetBit(br, p[5]); + } + } else { + if (!VP8GetBit(br, p[6])) { + if (!VP8GetBit(br, p[7])) { + v = 5 + VP8GetBit(br, 159); + } else { + v = 7 + 2 * VP8GetBit(br, 165); + v += VP8GetBit(br, 145); + } + } else { + const uint8_t* tab; + const int bit1 = VP8GetBit(br, p[8]); + const int bit0 = VP8GetBit(br, p[9 + bit1]); + const int cat = 2 * bit1 + bit0; + v = 0; + for (tab = kCat3456[cat]; *tab; ++tab) { + v += v + VP8GetBit(br, *tab); + } + v += 3 + (8 << cat); + } + } + return v; +} // Returns the position of the last non-zero coeff plus one // (and 0 if there's no coeff at all) @@ -484,54 +505,26 @@ static int GetCoeffs(VP8BitReader* const br, ProbaArray prob, if (!VP8GetBit(br, p[0])) { // first EOB is more a 'CBP' bit. return 0; } - while (1) { - ++n; + for (; n < 16; ++n) { + const ProbaCtxArray p_ctx = prob[kBands[n + 1]]; if (!VP8GetBit(br, p[1])) { - p = prob[kBands[n]][0]; + p = p_ctx[0]; } else { // non zero coeff - int v, j; + int v; if (!VP8GetBit(br, p[2])) { - p = prob[kBands[n]][1]; v = 1; + p = p_ctx[1]; } else { - if (!VP8GetBit(br, p[3])) { - if (!VP8GetBit(br, p[4])) { - v = 2; - } else { - v = 3 + VP8GetBit(br, p[5]); - } - } else { - if (!VP8GetBit(br, p[6])) { - if (!VP8GetBit(br, p[7])) { - v = 5 + VP8GetBit(br, 159); - } else { - v = 7 + 2 * VP8GetBit(br, 165); - v += VP8GetBit(br, 145); - } - } else { - const uint8_t* tab; - const int bit1 = VP8GetBit(br, p[8]); - const int bit0 = VP8GetBit(br, p[9 + bit1]); - const int cat = 2 * bit1 + bit0; - v = 0; - for (tab = kCat3456[cat]; *tab; ++tab) { - v += v + VP8GetBit(br, *tab); - } - v += 3 + (8 << cat); - } - } - p = prob[kBands[n]][2]; + v = GetLargeValue(br, p); + p = p_ctx[2]; } - j = kZigzag[n - 1]; - out[j] = VP8GetSigned(br, v) * dq[j > 0]; - if (n == 16 || !VP8GetBit(br, p[0])) { // EOB - return n; + out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0]; + if (n < 15 && !VP8GetBit(br, p[0])) { // EOB + return n + 1; } } - if (n == 16) { - return 16; - } } + return 16; } // Alias-safe way of converting 4bytes to 32bits. @@ -670,6 +663,12 @@ int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) { dec->non_zero_ac_ = 0; } + if (dec->filter_type_ > 0) { // store filter info + VP8FInfo* const finfo = dec->f_info_ + dec->mb_x_; + *finfo = dec->fstrengths_[dec->segment_][dec->is_i4x4_]; + finfo->f_inner_ = (!info->skip_ || dec->is_i4x4_); + } + return (!token_br->eof_); } @@ -693,10 +692,8 @@ static int ParseFrame(VP8Decoder* const dec, VP8Io* io) { return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, "Premature end-of-file encountered."); } + // Reconstruct and emit samples. VP8ReconstructBlock(dec); - - // Store data and save block's filtering params - VP8StoreBlock(dec); } if (!VP8ProcessRow(dec, io)) { return VP8SetError(dec, VP8_STATUS_USER_ABORT, "Output aborted."); diff --git a/3rdparty/libwebp/dec/vp8i.h b/3rdparty/libwebp/dec/vp8i.h index 6e27456fe1..1d0d4077eb 100644 --- a/3rdparty/libwebp/dec/vp8i.h +++ b/3rdparty/libwebp/dec/vp8i.h @@ -1,8 +1,10 @@ // Copyright 2010 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // VP8 decoder: internal header. @@ -27,7 +29,7 @@ extern "C" { // version numbers #define DEC_MAJ_VERSION 0 -#define DEC_MIN_VERSION 2 +#define DEC_MIN_VERSION 3 #define DEC_REV_VERSION 1 #define ONLY_KEYFRAME_CODE // to remove any code related to P-Frames @@ -157,7 +159,7 @@ typedef struct { // filter specs } VP8FInfo; typedef struct { // used for syntax-parsing - unsigned int nz_; // non-zero AC/DC coeffs + unsigned int nz_:24; // non-zero AC/DC coeffs (24bit) unsigned int dc_nz_:1; // non-zero DC coeffs unsigned int skip_:1; // block type } VP8MB; @@ -269,13 +271,14 @@ struct VP8Decoder { uint32_t non_zero_ac_; // Filtering side-info - int filter_type_; // 0=off, 1=simple, 2=complex - int filter_row_; // per-row flag - uint8_t filter_levels_[NUM_MB_SEGMENTS]; // precalculated per-segment + int filter_type_; // 0=off, 1=simple, 2=complex + int filter_row_; // per-row flag + VP8FInfo fstrengths_[NUM_MB_SEGMENTS][2]; // precalculated per-segment/type // extensions const uint8_t* alpha_data_; // compressed alpha data (if present) size_t alpha_data_size_; + int is_alpha_decoded_; // true if alpha_data_ is decoded in alpha_plane_ uint8_t* alpha_plane_; // output. Persistent, contains the whole data. int layer_colorspace_; @@ -312,8 +315,6 @@ VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io); int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io); // Process the last decoded row (filtering + output) int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io); -// Store a block, along with filtering params -void VP8StoreBlock(VP8Decoder* const dec); // To be called at the start of a new scanline, to initialize predictors. void VP8InitScanline(VP8Decoder* const dec); // Decode one macroblock. Returns false if there is not enough data. diff --git a/3rdparty/libwebp/dec/vp8l.c b/3rdparty/libwebp/dec/vp8l.c index 897e4395c7..89b5b4bf6e 100644 --- a/3rdparty/libwebp/dec/vp8l.c +++ b/3rdparty/libwebp/dec/vp8l.c @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // main entry for the decoder @@ -58,18 +60,18 @@ static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = { #define CODE_TO_PLANE_CODES 120 static const uint8_t code_to_plane_lut[CODE_TO_PLANE_CODES] = { - 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a, - 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a, - 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b, - 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03, - 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c, - 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e, - 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b, - 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f, - 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b, - 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41, - 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f, - 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70 + 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a, + 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a, + 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b, + 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03, + 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c, + 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e, + 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b, + 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f, + 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b, + 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41, + 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f, + 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70 }; static int DecodeImageStream(int xsize, int ysize, @@ -149,29 +151,20 @@ static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) { //------------------------------------------------------------------------------ // Decodes the next Huffman code from bit-stream. // FillBitWindow(br) needs to be called at minimum every second call -// to ReadSymbolUnsafe. -static int ReadSymbolUnsafe(const HuffmanTree* tree, VP8LBitReader* const br) { - const HuffmanTreeNode* node = tree->root_; - assert(node != NULL); - while (!HuffmanTreeNodeIsLeaf(node)) { - node = HuffmanTreeNextNode(node, VP8LReadOneBitUnsafe(br)); - } - return node->symbol_; -} - +// to ReadSymbol, in order to pre-fetch enough bits. static WEBP_INLINE int ReadSymbol(const HuffmanTree* tree, VP8LBitReader* const br) { - const int read_safe = (br->pos_ + 8 > br->len_); - if (!read_safe) { - return ReadSymbolUnsafe(tree, br); - } else { - const HuffmanTreeNode* node = tree->root_; - assert(node != NULL); - while (!HuffmanTreeNodeIsLeaf(node)) { - node = HuffmanTreeNextNode(node, VP8LReadOneBit(br)); - } - return node->symbol_; + const HuffmanTreeNode* node = tree->root_; + int num_bits = 0; + uint32_t bits = VP8LPrefetchBits(br); + assert(node != NULL); + while (!HuffmanTreeNodeIsLeaf(node)) { + node = HuffmanTreeNextNode(node, bits & 1); + bits >>= 1; + ++num_bits; } + VP8LDiscardBits(br, num_bits); + return node->symbol_; } static int ReadHuffmanCodeLengths( @@ -327,10 +320,10 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, hdr->huffman_subsample_bits_ = huffman_precision; for (i = 0; i < huffman_pixs; ++i) { // The huffman data is stored in red and green bytes. - const int index = (huffman_image[i] >> 8) & 0xffff; - huffman_image[i] = index; - if (index >= num_htree_groups) { - num_htree_groups = index + 1; + const int group = (huffman_image[i] >> 8) & 0xffff; + huffman_image[i] = group; + if (group >= num_htree_groups) { + num_htree_groups = group + 1; } } } @@ -634,10 +627,24 @@ static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows, } } +// Special method for paletted alpha data. +static void ApplyInverseTransformsAlpha(VP8LDecoder* const dec, int num_rows, + const uint8_t* const rows) { + const int start_row = dec->last_row_; + const int end_row = start_row + num_rows; + const uint8_t* rows_in = rows; + uint8_t* rows_out = (uint8_t*)dec->io_->opaque + dec->io_->width * start_row; + VP8LTransform* const transform = &dec->transforms_[0]; + assert(dec->next_transform_ == 1); + assert(transform->type_ == COLOR_INDEXING_TRANSFORM); + VP8LColorIndexInverseTransformAlpha(transform, start_row, end_row, rows_in, + rows_out); +} + // Processes (transforms, scales & color-converts) the rows decoded after the // last call. static void ProcessRows(VP8LDecoder* const dec, int row) { - const uint32_t* const rows = dec->argb_ + dec->width_ * dec->last_row_; + const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_; const int num_rows = row - dec->last_row_; if (num_rows <= 0) return; // Nothing to be done. @@ -676,121 +683,135 @@ static void ProcessRows(VP8LDecoder* const dec, int row) { assert(dec->last_row_ <= dec->height_); } -static int DecodeImageData(VP8LDecoder* const dec, - uint32_t* const data, int width, int height, - ProcessRowsFunc process_func) { - int ok = 1; - int col = 0, row = 0; - VP8LBitReader* const br = &dec->br_; - VP8LMetadata* const hdr = &dec->hdr_; - HTreeGroup* htree_group = hdr->htree_groups_; - uint32_t* src = data; - uint32_t* last_cached = data; - uint32_t* const src_end = data + width * height; - const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; - const int color_cache_limit = len_code_limit + hdr->color_cache_size_; - VP8LColorCache* const color_cache = - (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL; - const int mask = hdr->huffman_mask_; - - assert(htree_group != NULL); - - while (!br->eos_ && src < src_end) { - int code; - // Only update when changing tile. Note we could use the following test: - // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed - // but that's actually slower and requires storing the previous col/row - if ((col & mask) == 0) { - htree_group = GetHtreeGroupForPos(hdr, col, row); - } - VP8LFillBitWindow(br); - code = ReadSymbol(&htree_group->htrees_[GREEN], br); - if (code < NUM_LITERAL_CODES) { // Literal. - int red, green, blue, alpha; - red = ReadSymbol(&htree_group->htrees_[RED], br); - green = code; - VP8LFillBitWindow(br); - blue = ReadSymbol(&htree_group->htrees_[BLUE], br); - alpha = ReadSymbol(&htree_group->htrees_[ALPHA], br); - *src = (alpha << 24) + (red << 16) + (green << 8) + blue; - AdvanceByOne: - ++src; - ++col; - if (col >= width) { - col = 0; - ++row; - if ((process_func != NULL) && (row % NUM_ARGB_CACHE_ROWS == 0)) { - process_func(dec, row); - } - if (color_cache != NULL) { - while (last_cached < src) { - VP8LColorCacheInsert(color_cache, *last_cached++); - } - } - } - } else if (code < len_code_limit) { // Backward reference - int dist_code, dist; - const int length_sym = code - NUM_LITERAL_CODES; - const int length = GetCopyLength(length_sym, br); - const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br); - VP8LFillBitWindow(br); - dist_code = GetCopyDistance(dist_symbol, br); - dist = PlaneCodeToDistance(width, dist_code); - if (src - data < dist || src_end - src < length) { - ok = 0; - goto End; - } - { - int i; - for (i = 0; i < length; ++i) src[i] = src[i - dist]; - src += length; - } - col += length; - while (col >= width) { - col -= width; - ++row; - if ((process_func != NULL) && (row % NUM_ARGB_CACHE_ROWS == 0)) { - process_func(dec, row); - } - } - if (src < src_end) { - htree_group = GetHtreeGroupForPos(hdr, col, row); - if (color_cache != NULL) { - while (last_cached < src) { - VP8LColorCacheInsert(color_cache, *last_cached++); - } - } - } - } else if (code < color_cache_limit) { // Color cache. - const int key = code - len_code_limit; - assert(color_cache != NULL); - while (last_cached < src) { - VP8LColorCacheInsert(color_cache, *last_cached++); - } - *src = VP8LColorCacheLookup(color_cache, key); - goto AdvanceByOne; - } else { // Not reached. - ok = 0; - goto End; - } - ok = !br->error_; - if (!ok) goto End; - } - // Process the remaining rows corresponding to last row-block. - if (process_func != NULL) process_func(dec, row); - - End: - if (br->error_ || !ok || (br->eos_ && src < src_end)) { - ok = 0; - dec->status_ = (!br->eos_) ? - VP8_STATUS_BITSTREAM_ERROR : VP8_STATUS_SUSPENDED; - } else if (src == src_end) { - dec->state_ = READ_DATA; - } - - return ok; +#define DECODE_DATA_FUNC(FUNC_NAME, TYPE, STORE_PIXEL) \ +static int FUNC_NAME(VP8LDecoder* const dec, TYPE* const data, int width, \ + int height, ProcessRowsFunc process_func) { \ + int ok = 1; \ + int col = 0, row = 0; \ + VP8LBitReader* const br = &dec->br_; \ + VP8LMetadata* const hdr = &dec->hdr_; \ + HTreeGroup* htree_group = hdr->htree_groups_; \ + TYPE* src = data; \ + TYPE* last_cached = data; \ + TYPE* const src_end = data + width * height; \ + const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; \ + const int color_cache_limit = len_code_limit + hdr->color_cache_size_; \ + VP8LColorCache* const color_cache = \ + (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL; \ + const int mask = hdr->huffman_mask_; \ + assert(htree_group != NULL); \ + while (!br->eos_ && src < src_end) { \ + int code; \ + /* Only update when changing tile. Note we could use this test: */ \ + /* if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed */ \ + /* but that's actually slower and needs storing the previous col/row. */ \ + if ((col & mask) == 0) { \ + htree_group = GetHtreeGroupForPos(hdr, col, row); \ + } \ + VP8LFillBitWindow(br); \ + code = ReadSymbol(&htree_group->htrees_[GREEN], br); \ + if (code < NUM_LITERAL_CODES) { /* Literal*/ \ + int red, green, blue, alpha; \ + red = ReadSymbol(&htree_group->htrees_[RED], br); \ + green = code; \ + VP8LFillBitWindow(br); \ + blue = ReadSymbol(&htree_group->htrees_[BLUE], br); \ + alpha = ReadSymbol(&htree_group->htrees_[ALPHA], br); \ + *src = STORE_PIXEL(alpha, red, green, blue); \ + AdvanceByOne: \ + ++src; \ + ++col; \ + if (col >= width) { \ + col = 0; \ + ++row; \ + if ((process_func != NULL) && (row % NUM_ARGB_CACHE_ROWS == 0)) { \ + process_func(dec, row); \ + } \ + if (color_cache != NULL) { \ + while (last_cached < src) { \ + VP8LColorCacheInsert(color_cache, *last_cached++); \ + } \ + } \ + } \ + } else if (code < len_code_limit) { /* Backward reference */ \ + int dist_code, dist; \ + const int length_sym = code - NUM_LITERAL_CODES; \ + const int length = GetCopyLength(length_sym, br); \ + const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br); \ + VP8LFillBitWindow(br); \ + dist_code = GetCopyDistance(dist_symbol, br); \ + dist = PlaneCodeToDistance(width, dist_code); \ + if (src - data < dist || src_end - src < length) { \ + ok = 0; \ + goto End; \ + } \ + { \ + int i; \ + for (i = 0; i < length; ++i) src[i] = src[i - dist]; \ + src += length; \ + } \ + col += length; \ + while (col >= width) { \ + col -= width; \ + ++row; \ + if ((process_func != NULL) && (row % NUM_ARGB_CACHE_ROWS == 0)) { \ + process_func(dec, row); \ + } \ + } \ + if (src < src_end) { \ + htree_group = GetHtreeGroupForPos(hdr, col, row); \ + if (color_cache != NULL) { \ + while (last_cached < src) { \ + VP8LColorCacheInsert(color_cache, *last_cached++); \ + } \ + } \ + } \ + } else if (code < color_cache_limit) { /* Color cache */ \ + const int key = code - len_code_limit; \ + assert(color_cache != NULL); \ + while (last_cached < src) { \ + VP8LColorCacheInsert(color_cache, *last_cached++); \ + } \ + *src = VP8LColorCacheLookup(color_cache, key); \ + goto AdvanceByOne; \ + } else { /* Not reached */ \ + ok = 0; \ + goto End; \ + } \ + ok = !br->error_; \ + if (!ok) goto End; \ + } \ + /* Process the remaining rows corresponding to last row-block. */ \ + if (process_func != NULL) process_func(dec, row); \ +End: \ + if (br->error_ || !ok || (br->eos_ && src < src_end)) { \ + ok = 0; \ + dec->status_ = \ + (!br->eos_) ? VP8_STATUS_BITSTREAM_ERROR : VP8_STATUS_SUSPENDED; \ + } else if (src == src_end) { \ + dec->state_ = READ_DATA; \ + } \ + return ok; \ } +static WEBP_INLINE uint32_t GetARGBPixel(int alpha, int red, int green, + int blue) { + return (alpha << 24) | (red << 16) | (green << 8) | blue; +} + +static WEBP_INLINE uint8_t GetAlphaPixel(int alpha, int red, int green, + int blue) { + (void)alpha; + (void)red; + (void)blue; + return green; // Alpha value is stored in green channel. +} + +DECODE_DATA_FUNC(DecodeImageData, uint32_t, GetARGBPixel) +DECODE_DATA_FUNC(DecodeAlphaData, uint8_t, GetAlphaPixel) + +#undef DECODE_DATA_FUNC + // ----------------------------------------------------------------------------- // VP8LTransform @@ -912,8 +933,8 @@ void VP8LClear(VP8LDecoder* const dec) { if (dec == NULL) return; ClearMetadata(&dec->hdr_); - free(dec->argb_); - dec->argb_ = NULL; + free(dec->pixels_); + dec->pixels_ = NULL; for (i = 0; i < dec->next_transform_; ++i) { ClearTransform(&dec->transforms_[i]); } @@ -1037,35 +1058,39 @@ static int DecodeImageStream(int xsize, int ysize, } //------------------------------------------------------------------------------ -// Allocate dec->argb_ and dec->argb_cache_ using dec->width_ and dec->height_ - -static int AllocateARGBBuffers(VP8LDecoder* const dec, int final_width) { +// Allocate internal buffers dec->pixels_ and dec->argb_cache_. +static int AllocateInternalBuffers(VP8LDecoder* const dec, int final_width, + size_t bytes_per_pixel) { + const int argb_cache_needed = (bytes_per_pixel == sizeof(uint32_t)); const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_; // Scratch buffer corresponding to top-prediction row for transforming the - // first row in the row-blocks. - const uint64_t cache_top_pixels = final_width; - // Scratch buffer for temporary BGRA storage. - const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS; + // first row in the row-blocks. Not needed for paletted alpha. + const uint64_t cache_top_pixels = + argb_cache_needed ? (uint16_t)final_width : 0ULL; + // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha. + const uint64_t cache_pixels = + argb_cache_needed ? (uint64_t)final_width * NUM_ARGB_CACHE_ROWS : 0ULL; const uint64_t total_num_pixels = num_pixels + cache_top_pixels + cache_pixels; assert(dec->width_ <= final_width); - dec->argb_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(*dec->argb_)); - if (dec->argb_ == NULL) { + dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, bytes_per_pixel); + if (dec->pixels_ == NULL) { dec->argb_cache_ = NULL; // for sanity check dec->status_ = VP8_STATUS_OUT_OF_MEMORY; return 0; } - dec->argb_cache_ = dec->argb_ + num_pixels + cache_top_pixels; + dec->argb_cache_ = + argb_cache_needed ? dec->pixels_ + num_pixels + cache_top_pixels : NULL; return 1; } //------------------------------------------------------------------------------ -// Special row-processing that only stores the alpha data. +// Special row-processing that only stores the alpha data. static void ExtractAlphaRows(VP8LDecoder* const dec, int row) { const int num_rows = row - dec->last_row_; - const uint32_t* const in = dec->argb_ + dec->width_ * dec->last_row_; + const uint32_t* const in = dec->pixels_ + dec->width_ * dec->last_row_; if (num_rows <= 0) return; // Nothing to be done. ApplyInverseTransforms(dec, num_rows, in); @@ -1079,7 +1104,17 @@ static void ExtractAlphaRows(VP8LDecoder* const dec, int row) { int i; for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff; } + dec->last_row_ = dec->last_out_row_ = row; +} +// Row-processing for the special case when alpha data contains only one +// transform: color indexing. +static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int row) { + const int num_rows = row - dec->last_row_; + const uint8_t* const in = + (uint8_t*)dec->pixels_ + dec->width_ * dec->last_row_; + if (num_rows <= 0) return; // Nothing to be done. + ApplyInverseTransformsAlpha(dec, num_rows, in); dec->last_row_ = dec->last_out_row_ = row; } @@ -1088,6 +1123,7 @@ int VP8LDecodeAlphaImageStream(int width, int height, const uint8_t* const data, VP8Io io; int ok = 0; VP8LDecoder* const dec = VP8LNew(); + size_t bytes_per_pixel = sizeof(uint32_t); // Default: BGRA mode. if (dec == NULL) return 0; dec->width_ = width; @@ -1106,13 +1142,25 @@ int VP8LDecodeAlphaImageStream(int width, int height, const uint8_t* const data, dec->action_ = READ_HDR; if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Err; - // Allocate output (note that dec->width_ may have changed here). - if (!AllocateARGBBuffers(dec, width)) goto Err; + // Special case: if alpha data uses only the color indexing transform and + // doesn't use color cache (a frequent case), we will use DecodeAlphaData() + // method that only needs allocation of 1 byte per pixel (alpha channel). + if (dec->next_transform_ == 1 && + dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM && + dec->hdr_.color_cache_size_ == 0) { + bytes_per_pixel = sizeof(uint8_t); + } + + // Allocate internal buffers (note that dec->width_ may have changed here). + if (!AllocateInternalBuffers(dec, width, bytes_per_pixel)) goto Err; // Decode (with special row processing). dec->action_ = READ_DATA; - ok = DecodeImageData(dec, dec->argb_, dec->width_, dec->height_, - ExtractAlphaRows); + ok = (bytes_per_pixel == sizeof(uint8_t)) ? + DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_, + ExtractPalettedAlphaRows) : + DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, + ExtractAlphaRows); Err: VP8LDelete(dec); @@ -1146,12 +1194,13 @@ int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) { return 1; Error: - VP8LClear(dec); - assert(dec->status_ != VP8_STATUS_OK); - return 0; + VP8LClear(dec); + assert(dec->status_ != VP8_STATUS_OK); + return 0; } int VP8LDecodeImage(VP8LDecoder* const dec) { + const size_t bytes_per_pixel = sizeof(uint32_t); VP8Io* io = NULL; WebPDecParams* params = NULL; @@ -1171,13 +1220,13 @@ int VP8LDecodeImage(VP8LDecoder* const dec) { goto Err; } - if (!AllocateARGBBuffers(dec, io->width)) goto Err; + if (!AllocateInternalBuffers(dec, io->width, bytes_per_pixel)) goto Err; if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err; // Decode. dec->action_ = READ_DATA; - if (!DecodeImageData(dec, dec->argb_, dec->width_, dec->height_, + if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, ProcessRows)) { goto Err; } diff --git a/3rdparty/libwebp/dec/vp8li.h b/3rdparty/libwebp/dec/vp8li.h index ee29eb5faf..543a767590 100644 --- a/3rdparty/libwebp/dec/vp8li.h +++ b/3rdparty/libwebp/dec/vp8li.h @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Lossless decoder: internal header. @@ -63,7 +65,8 @@ typedef struct { const WebPDecBuffer *output_; // shortcut to io->opaque->output - uint32_t *argb_; // Internal data: always in BGRA color mode. + uint32_t *pixels_; // Internal data: either uint8_t* for alpha + // or uint32_t* for BGRA. uint32_t *argb_cache_; // Scratch buffer for temporary BGRA storage. VP8LBitReader br_; diff --git a/3rdparty/libwebp/dec/webp.c b/3rdparty/libwebp/dec/webp.c index 7455da9415..97e79b64da 100644 --- a/3rdparty/libwebp/dec/webp.c +++ b/3rdparty/libwebp/dec/webp.c @@ -1,8 +1,10 @@ // Copyright 2010 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Main decoding functions for WEBP images. @@ -14,7 +16,7 @@ #include "./vp8i.h" #include "./vp8li.h" #include "./webpi.h" -#include "../webp/format_constants.h" +#include "../webp/mux_types.h" // ALPHA_FLAG #if defined(__cplusplus) || defined(c_plusplus) extern "C" { @@ -40,8 +42,8 @@ extern "C" { // 20..23 VP8X flags bit-map corresponding to the chunk-types present. // 24..26 Width of the Canvas Image. // 27..29 Height of the Canvas Image. -// There can be extra chunks after the "VP8X" chunk (ICCP, TILE, FRM, VP8, -// META ...) +// There can be extra chunks after the "VP8X" chunk (ICCP, FRGM, ANMF, VP8, +// VP8L, XMP, EXIF ...) // All sizes are in little-endian order. // Note: chunk data size must be padded to multiple of 2 when written. @@ -192,6 +194,15 @@ static VP8StatusCode ParseOptionalChunks(const uint8_t** const data, return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. } + // Start of a (possibly incomplete) VP8/VP8L chunk implies that we have + // parsed all the optional chunks. + // Note: This check must occur before the check 'buf_size < disk_chunk_size' + // below to allow incomplete VP8/VP8L chunks. + if (!memcmp(buf, "VP8 ", TAG_SIZE) || + !memcmp(buf, "VP8L", TAG_SIZE)) { + return VP8_STATUS_OK; + } + if (buf_size < disk_chunk_size) { // Insufficient data. return VP8_STATUS_NOT_ENOUGH_DATA; } @@ -199,9 +210,6 @@ static VP8StatusCode ParseOptionalChunks(const uint8_t** const data, if (!memcmp(buf, "ALPH", TAG_SIZE)) { // A valid ALPH header. *alpha_data = buf + CHUNK_HEADER_SIZE; *alpha_size = chunk_size; - } else if (!memcmp(buf, "VP8 ", TAG_SIZE) || - !memcmp(buf, "VP8L", TAG_SIZE)) { // A valid VP8/VP8L header. - return VP8_STATUS_OK; // Found. } // We have a full and valid chunk; skip it. @@ -276,6 +284,7 @@ static VP8StatusCode ParseHeadersInternal(const uint8_t* data, int* const width, int* const height, int* const has_alpha, + int* const has_animation, WebPHeaderStructure* const headers) { int found_riff = 0; int found_vp8x = 0; @@ -308,7 +317,8 @@ static VP8StatusCode ParseHeadersInternal(const uint8_t* data, // necessary to send VP8X chunk to the decoder. return VP8_STATUS_BITSTREAM_ERROR; } - if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG_BIT); + if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG); + if (has_animation != NULL) *has_animation = !!(flags & ANIMATION_FLAG); if (found_vp8x && headers == NULL) { return VP8_STATUS_OK; // Return features from VP8X header. } @@ -370,10 +380,19 @@ static VP8StatusCode ParseHeadersInternal(const uint8_t* data, } VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers) { + VP8StatusCode status; + int has_animation = 0; assert(headers != NULL); // fill out headers, ignore width/height/has_alpha. - return ParseHeadersInternal(headers->data, headers->data_size, - NULL, NULL, NULL, headers); + status = ParseHeadersInternal(headers->data, headers->data_size, + NULL, NULL, NULL, &has_animation, headers); + if (status == VP8_STATUS_OK || status == VP8_STATUS_NOT_ENOUGH_DATA) { + // TODO(jzern): full support of animation frames will require API additions. + if (has_animation) { + status = VP8_STATUS_UNSUPPORTED_FEATURE; + } + } + return status; } //------------------------------------------------------------------------------ @@ -625,10 +644,11 @@ static VP8StatusCode GetFeatures(const uint8_t* const data, size_t data_size, } DefaultFeatures(features); - // Only parse enough of the data to retrieve width/height/has_alpha. + // Only parse enough of the data to retrieve the features. return ParseHeadersInternal(data, data_size, &features->width, &features->height, - &features->has_alpha, NULL); + &features->has_alpha, &features->has_animation, + NULL); } //------------------------------------------------------------------------------ @@ -672,19 +692,13 @@ int WebPInitDecoderConfigInternal(WebPDecoderConfig* config, VP8StatusCode WebPGetFeaturesInternal(const uint8_t* data, size_t data_size, WebPBitstreamFeatures* features, int version) { - VP8StatusCode status; if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { return VP8_STATUS_INVALID_PARAM; // version mismatch } if (features == NULL) { return VP8_STATUS_INVALID_PARAM; } - - status = GetFeatures(data, data_size, features); - if (status == VP8_STATUS_NOT_ENOUGH_DATA) { - return VP8_STATUS_BITSTREAM_ERROR; // Not-enough-data treated as error. - } - return status; + return GetFeatures(data, data_size, features); } VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size, diff --git a/3rdparty/libwebp/dec/webpi.h b/3rdparty/libwebp/dec/webpi.h index 44e5744411..4ae0bfc5a0 100644 --- a/3rdparty/libwebp/dec/webpi.h +++ b/3rdparty/libwebp/dec/webpi.h @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Internal header: WebP decoding parameters and custom IO on buffer @@ -61,10 +63,10 @@ typedef struct { } WebPHeaderStructure; // Skips over all valid chunks prior to the first VP8/VP8L frame header. -// Returns VP8_STATUS_OK on success, -// VP8_STATUS_BITSTREAM_ERROR if an invalid header/chunk is found, and -// VP8_STATUS_NOT_ENOUGH_DATA if case of insufficient data. -// In 'headers', compressed_size, offset, alpha_data, alpha_size and lossless +// Returns: VP8_STATUS_OK, VP8_STATUS_BITSTREAM_ERROR (invalid header/chunk), +// VP8_STATUS_NOT_ENOUGH_DATA (partial input) or VP8_STATUS_UNSUPPORTED_FEATURE +// in the case of non-decodable features (animation for instance). +// In 'headers', compressed_size, offset, alpha_data, alpha_size, and lossless // fields are updated appropriately upon success. VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers); diff --git a/3rdparty/libwebp/mux/demux.c b/3rdparty/libwebp/demux/demux.c similarity index 67% rename from 3rdparty/libwebp/mux/demux.c rename to 3rdparty/libwebp/demux/demux.c index 4519f7d55b..bd17ff7f69 100644 --- a/3rdparty/libwebp/mux/demux.c +++ b/3rdparty/libwebp/demux/demux.c @@ -1,26 +1,35 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // WebP container demux. // -#include "../webp/mux.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include #include #include -#include "../webp/decode.h" // WebPGetInfo +#include "../utils/utils.h" +#include "../webp/decode.h" // WebPGetFeatures +#include "../webp/demux.h" #include "../webp/format_constants.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif -#define MKFOURCC(a, b, c, d) ((uint32_t)(a) | (b) << 8 | (c) << 16 | (d) << 24) +#define DMUX_MAJ_VERSION 0 +#define DMUX_MIN_VERSION 1 +#define DMUX_REV_VERSION 1 typedef struct { size_t start_; // start location of the data @@ -39,8 +48,9 @@ typedef struct Frame { int x_offset_, y_offset_; int width_, height_; int duration_; - int is_tile_; // this is an image fragment from a 'TILE'. - int frame_num_; // the referent frame number for use in assembling tiles. + WebPMuxAnimDispose dispose_method_; + int is_fragment_; // this is a frame fragment (and not a full frame). + int frame_num_; // the referent frame number for use in assembling fragments. int complete_; // img_components_ contains a full image. ChunkData img_components_[2]; // 0=VP8{,L} 1=ALPH struct Frame* next_; @@ -58,8 +68,10 @@ struct WebPDemuxer { uint32_t feature_flags_; int canvas_width_, canvas_height_; int loop_count_; + uint32_t bgcolor_; int num_frames_; Frame* frames_; + Frame** frames_tail_; Chunk* chunks_; // non-image chunks }; @@ -87,6 +99,12 @@ static const ChunkParser kMasterChunks[] = { { { '0', '0', '0', '0' }, NULL, NULL }, }; +//------------------------------------------------------------------------------ + +int WebPGetDemuxVersion(void) { + return (DMUX_MAJ_VERSION << 16) | (DMUX_MIN_VERSION << 8) | DMUX_REV_VERSION; +} + // ----------------------------------------------------------------------------- // MemBuffer @@ -127,43 +145,30 @@ static WEBP_INLINE const uint8_t* GetBuffer(MemBuffer* const mem) { return mem->buf_ + mem->start_; } -static WEBP_INLINE uint8_t GetByte(MemBuffer* const mem) { +// Read from 'mem' and skip the read bytes. +static WEBP_INLINE uint8_t ReadByte(MemBuffer* const mem) { const uint8_t byte = mem->buf_[mem->start_]; Skip(mem, 1); return byte; } -// Read 16, 24 or 32 bits stored in little-endian order. -static WEBP_INLINE int ReadLE16s(const uint8_t* const data) { - return (int)(data[0] << 0) | (data[1] << 8); -} - -static WEBP_INLINE int ReadLE24s(const uint8_t* const data) { - return ReadLE16s(data) | (data[2] << 16); -} - -static WEBP_INLINE uint32_t ReadLE32(const uint8_t* const data) { - return (uint32_t)ReadLE24s(data) | (data[3] << 24); -} - -// In addition to reading, skip the read bytes. -static WEBP_INLINE int GetLE16s(MemBuffer* const mem) { +static WEBP_INLINE int ReadLE16s(MemBuffer* const mem) { const uint8_t* const data = mem->buf_ + mem->start_; - const int val = ReadLE16s(data); + const int val = GetLE16(data); Skip(mem, 2); return val; } -static WEBP_INLINE int GetLE24s(MemBuffer* const mem) { +static WEBP_INLINE int ReadLE24s(MemBuffer* const mem) { const uint8_t* const data = mem->buf_ + mem->start_; - const int val = ReadLE24s(data); + const int val = GetLE24(data); Skip(mem, 3); return val; } -static WEBP_INLINE uint32_t GetLE32(MemBuffer* const mem) { +static WEBP_INLINE uint32_t ReadLE32(MemBuffer* const mem) { const uint8_t* const data = mem->buf_ + mem->start_; - const uint32_t val = ReadLE32(data); + const uint32_t val = GetLE32(data); Skip(mem, 4); return val; } @@ -181,32 +186,34 @@ static void AddChunk(WebPDemuxer* const dmux, Chunk* const chunk) { // Add a frame to the end of the list, ensuring the last frame is complete. // Returns true on success, false otherwise. static int AddFrame(WebPDemuxer* const dmux, Frame* const frame) { - const Frame* last_frame = NULL; - Frame** f = &dmux->frames_; - while (*f != NULL) { - last_frame = *f; - f = &(*f)->next_; - } + const Frame* const last_frame = *dmux->frames_tail_; if (last_frame != NULL && !last_frame->complete_) return 0; - *f = frame; + + *dmux->frames_tail_ = frame; frame->next_ = NULL; + dmux->frames_tail_ = &frame->next_; return 1; } // Store image bearing chunks to 'frame'. -static ParseStatus StoreFrame(int frame_num, MemBuffer* const mem, - Frame* const frame) { +// If 'has_vp8l_alpha' is not NULL, it will be set to true if the frame is a +// lossless image with alpha. +static ParseStatus StoreFrame(int frame_num, uint32_t min_size, + MemBuffer* const mem, Frame* const frame, + int* const has_vp8l_alpha) { int alpha_chunks = 0; int image_chunks = 0; - int done = (MemDataSize(mem) < CHUNK_HEADER_SIZE); + int done = (MemDataSize(mem) < min_size); ParseStatus status = PARSE_OK; + if (has_vp8l_alpha != NULL) *has_vp8l_alpha = 0; // Default. + if (done) return PARSE_NEED_MORE_DATA; do { const size_t chunk_start_offset = mem->start_; - const uint32_t fourcc = GetLE32(mem); - const uint32_t payload_size = GetLE32(mem); + const uint32_t fourcc = ReadLE32(mem); + const uint32_t payload_size = ReadLE32(mem); const uint32_t payload_size_padded = payload_size + (payload_size & 1); const size_t payload_available = (payload_size_padded > MemDataSize(mem)) ? MemDataSize(mem) : payload_size_padded; @@ -228,23 +235,30 @@ static ParseStatus StoreFrame(int frame_num, MemBuffer* const mem, goto Done; } break; - case MKFOURCC('V', 'P', '8', ' '): case MKFOURCC('V', 'P', '8', 'L'): + if (alpha_chunks > 0) return PARSE_ERROR; // VP8L has its own alpha + // fall through + case MKFOURCC('V', 'P', '8', ' '): if (image_chunks == 0) { - int width = 0, height = 0; + // Extract the bitstream features, tolerating failures when the data + // is incomplete. + WebPBitstreamFeatures features; + const VP8StatusCode vp8_status = + WebPGetFeatures(mem->buf_ + chunk_start_offset, chunk_size, + &features); + if (status == PARSE_NEED_MORE_DATA && + vp8_status == VP8_STATUS_NOT_ENOUGH_DATA) { + return PARSE_NEED_MORE_DATA; + } else if (vp8_status != VP8_STATUS_OK) { + // We have enough data, and yet WebPGetFeatures() failed. + return PARSE_ERROR; + } ++image_chunks; frame->img_components_[0].offset_ = chunk_start_offset; frame->img_components_[0].size_ = chunk_size; - // Extract the width and height from the bitstream, tolerating - // failures when the data is incomplete. - if (!WebPGetInfo(mem->buf_ + frame->img_components_[0].offset_, - frame->img_components_[0].size_, &width, &height) && - status != PARSE_NEED_MORE_DATA) { - return PARSE_ERROR; - } - - frame->width_ = width; - frame->height_ = height; + frame->width_ = features.width; + frame->height_ = features.height; + if (has_vp8l_alpha != NULL) *has_vp8l_alpha = features.has_alpha; frame->frame_num_ = frame_num; frame->complete_ = (status == PARSE_OK); Skip(mem, payload_available); @@ -275,42 +289,44 @@ static ParseStatus StoreFrame(int frame_num, MemBuffer* const mem, // Returns PARSE_OK on success with *frame pointing to the new Frame. // Returns PARSE_NEED_MORE_DATA with insufficient data, PARSE_ERROR otherwise. static ParseStatus NewFrame(const MemBuffer* const mem, - uint32_t min_size, uint32_t expected_size, - uint32_t actual_size, Frame** frame) { + uint32_t min_size, uint32_t actual_size, + Frame** frame) { if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR; - if (actual_size < expected_size) return PARSE_ERROR; + if (actual_size < min_size) return PARSE_ERROR; if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; *frame = (Frame*)calloc(1, sizeof(**frame)); return (*frame == NULL) ? PARSE_ERROR : PARSE_OK; } -// Parse a 'FRM ' chunk and any image bearing chunks that immediately follow. +// Parse a 'ANMF' chunk and any image bearing chunks that immediately follow. // 'frame_chunk_size' is the previously validated, padded chunk size. -static ParseStatus ParseFrame( +static ParseStatus ParseAnimationFrame( WebPDemuxer* const dmux, uint32_t frame_chunk_size) { const int has_frames = !!(dmux->feature_flags_ & ANIMATION_FLAG); - const uint32_t min_size = frame_chunk_size + CHUNK_HEADER_SIZE; + const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE; int added_frame = 0; MemBuffer* const mem = &dmux->mem_; Frame* frame; ParseStatus status = - NewFrame(mem, min_size, FRAME_CHUNK_SIZE, frame_chunk_size, &frame); + NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame); if (status != PARSE_OK) return status; - frame->x_offset_ = 2 * GetLE24s(mem); - frame->y_offset_ = 2 * GetLE24s(mem); - frame->width_ = 1 + GetLE24s(mem); - frame->height_ = 1 + GetLE24s(mem); - frame->duration_ = 1 + GetLE24s(mem); - Skip(mem, frame_chunk_size - FRAME_CHUNK_SIZE); // skip any trailing data. + frame->x_offset_ = 2 * ReadLE24s(mem); + frame->y_offset_ = 2 * ReadLE24s(mem); + frame->width_ = 1 + ReadLE24s(mem); + frame->height_ = 1 + ReadLE24s(mem); + frame->duration_ = ReadLE24s(mem); + frame->dispose_method_ = (WebPMuxAnimDispose)(ReadByte(mem) & 1); if (frame->width_ * (uint64_t)frame->height_ >= MAX_IMAGE_AREA) { + free(frame); return PARSE_ERROR; } - // Store a (potentially partial) frame only if the animation flag is set - // and there is some data in 'frame'. - status = StoreFrame(dmux->num_frames_ + 1, mem, frame); + // Store a frame only if the animation flag is set there is some data for + // this frame is available. + status = StoreFrame(dmux->num_frames_ + 1, anmf_payload_size, mem, frame, + NULL); if (status != PARSE_ERROR && has_frames && frame->frame_num_ > 0) { added_frame = AddFrame(dmux, frame); if (added_frame) { @@ -324,38 +340,43 @@ static ParseStatus ParseFrame( return status; } -// Parse a 'TILE' chunk and any image bearing chunks that immediately follow. -// 'tile_chunk_size' is the previously validated, padded chunk size. -static ParseStatus ParseTile(WebPDemuxer* const dmux, - uint32_t tile_chunk_size) { - const int has_tiles = !!(dmux->feature_flags_ & TILE_FLAG); - const uint32_t min_size = tile_chunk_size + CHUNK_HEADER_SIZE; - int added_tile = 0; +#ifdef WEBP_EXPERIMENTAL_FEATURES +// Parse a 'FRGM' chunk and any image bearing chunks that immediately follow. +// 'fragment_chunk_size' is the previously validated, padded chunk size. +static ParseStatus ParseFragment(WebPDemuxer* const dmux, + uint32_t fragment_chunk_size) { + const int frame_num = 1; // All fragments belong to the 1st (and only) frame. + const int has_fragments = !!(dmux->feature_flags_ & FRAGMENTS_FLAG); + const uint32_t frgm_payload_size = fragment_chunk_size - FRGM_CHUNK_SIZE; + int added_fragment = 0; MemBuffer* const mem = &dmux->mem_; Frame* frame; ParseStatus status = - NewFrame(mem, min_size, TILE_CHUNK_SIZE, tile_chunk_size, &frame); + NewFrame(mem, FRGM_CHUNK_SIZE, fragment_chunk_size, &frame); if (status != PARSE_OK) return status; - frame->is_tile_ = 1; - frame->x_offset_ = 2 * GetLE24s(mem); - frame->y_offset_ = 2 * GetLE24s(mem); - Skip(mem, tile_chunk_size - TILE_CHUNK_SIZE); // skip any trailing data. + frame->is_fragment_ = 1; + frame->x_offset_ = 2 * ReadLE24s(mem); + frame->y_offset_ = 2 * ReadLE24s(mem); - // Store a (potentially partial) tile only if the tile flag is set - // and the tile contains some data. - status = StoreFrame(dmux->num_frames_, mem, frame); - if (status != PARSE_ERROR && has_tiles && frame->frame_num_ > 0) { - // Note num_frames_ is incremented only when all tiles have been consumed. - added_tile = AddFrame(dmux, frame); - if (!added_tile) status = PARSE_ERROR; + // Store a fragment only if the fragments flag is set there is some data for + // this fragment is available. + status = StoreFrame(frame_num, frgm_payload_size, mem, frame, NULL); + if (status != PARSE_ERROR && has_fragments && frame->frame_num_ > 0) { + added_fragment = AddFrame(dmux, frame); + if (!added_fragment) { + status = PARSE_ERROR; + } else { + dmux->num_frames_ = 1; + } } - if (!added_tile) free(frame); + if (!added_fragment) free(frame); return status; } +#endif // WEBP_EXPERIMENTAL_FEATURES -// General chunk storage starting with the header at 'start_offset' allowing +// General chunk storage, starting with the header at 'start_offset', allowing // the user to request the payload via a fourcc string. 'size' includes the // header and the unpadded payload size. // Returns true on success, false otherwise. @@ -384,7 +405,7 @@ static int ReadHeader(MemBuffer* const mem) { return 0; } - riff_size = ReadLE32(GetBuffer(mem) + TAG_SIZE); + riff_size = GetLE32(GetBuffer(mem) + TAG_SIZE); if (riff_size < CHUNK_HEADER_SIZE) return 0; if (riff_size > MAX_CHUNK_PAYLOAD) return 0; @@ -403,6 +424,7 @@ static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) { MemBuffer* const mem = &dmux->mem_; Frame* frame; ParseStatus status; + int has_vp8l_alpha = 0; // Frame contains a lossless image with alpha. if (dmux->frames_ != NULL) return PARSE_ERROR; if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR; @@ -411,7 +433,10 @@ static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) { frame = (Frame*)calloc(1, sizeof(*frame)); if (frame == NULL) return PARSE_ERROR; - status = StoreFrame(1, &dmux->mem_, frame); + // For the single image case we allow parsing of a partial frame, but we need + // at least CHUNK_HEADER_SIZE for parsing. + status = StoreFrame(1, CHUNK_HEADER_SIZE, &dmux->mem_, frame, + &has_vp8l_alpha); if (status != PARSE_ERROR) { const int has_alpha = !!(dmux->feature_flags_ & ALPHA_FLAG); // Clear any alpha when the alpha flag is missing. @@ -421,10 +446,12 @@ static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) { } // Use the frame width/height as the canvas values for non-vp8x files. + // Also, set ALPHA_FLAG if this is a lossless image with alpha. if (!dmux->is_ext_format_ && frame->width_ > 0 && frame->height_ > 0) { dmux->state_ = WEBP_DEMUX_PARSED_HEADER; dmux->canvas_width_ = frame->width_; dmux->canvas_height_ = frame->height_; + dmux->feature_flags_ |= has_vp8l_alpha ? ALPHA_FLAG : 0; } AddFrame(dmux, frame); dmux->num_frames_ = 1; @@ -437,7 +464,7 @@ static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) { static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { MemBuffer* const mem = &dmux->mem_; - int loop_chunks = 0; + int anim_chunks = 0; uint32_t vp8x_size; ParseStatus status = PARSE_OK; @@ -445,17 +472,17 @@ static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { dmux->is_ext_format_ = 1; Skip(mem, TAG_SIZE); // VP8X - vp8x_size = GetLE32(mem); + vp8x_size = ReadLE32(mem); if (vp8x_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; if (vp8x_size < VP8X_CHUNK_SIZE) return PARSE_ERROR; vp8x_size += vp8x_size & 1; if (SizeIsInvalid(mem, vp8x_size)) return PARSE_ERROR; if (MemDataSize(mem) < vp8x_size) return PARSE_NEED_MORE_DATA; - dmux->feature_flags_ = GetByte(mem); + dmux->feature_flags_ = ReadByte(mem); Skip(mem, 3); // Reserved. - dmux->canvas_width_ = 1 + GetLE24s(mem); - dmux->canvas_height_ = 1 + GetLE24s(mem); + dmux->canvas_width_ = 1 + ReadLE24s(mem); + dmux->canvas_height_ = 1 + ReadLE24s(mem); if (dmux->canvas_width_ * (uint64_t)dmux->canvas_height_ >= MAX_IMAGE_AREA) { return PARSE_ERROR; // image final dimension is too large } @@ -468,8 +495,8 @@ static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { do { int store_chunk = 1; const size_t chunk_start_offset = mem->start_; - const uint32_t fourcc = GetLE32(mem); - const uint32_t chunk_size = GetLE32(mem); + const uint32_t fourcc = ReadLE32(mem); + const uint32_t chunk_size = ReadLE32(mem); const uint32_t chunk_size_padded = chunk_size + (chunk_size & 1); if (chunk_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; @@ -482,40 +509,50 @@ static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { case MKFOURCC('A', 'L', 'P', 'H'): case MKFOURCC('V', 'P', '8', ' '): case MKFOURCC('V', 'P', '8', 'L'): { + // check that this isn't an animation (all frames should be in an ANMF). + if (anim_chunks > 0) return PARSE_ERROR; + Rewind(mem, CHUNK_HEADER_SIZE); status = ParseSingleImage(dmux); break; } - case MKFOURCC('L', 'O', 'O', 'P'): { - if (chunk_size_padded < LOOP_CHUNK_SIZE) return PARSE_ERROR; + case MKFOURCC('A', 'N', 'I', 'M'): { + if (chunk_size_padded < ANIM_CHUNK_SIZE) return PARSE_ERROR; if (MemDataSize(mem) < chunk_size_padded) { status = PARSE_NEED_MORE_DATA; - } else if (loop_chunks == 0) { - ++loop_chunks; - dmux->loop_count_ = GetLE16s(mem); - Skip(mem, chunk_size_padded - LOOP_CHUNK_SIZE); + } else if (anim_chunks == 0) { + ++anim_chunks; + dmux->bgcolor_ = ReadLE32(mem); + dmux->loop_count_ = ReadLE16s(mem); + Skip(mem, chunk_size_padded - ANIM_CHUNK_SIZE); } else { store_chunk = 0; goto Skip; } break; } - case MKFOURCC('F', 'R', 'M', ' '): { - status = ParseFrame(dmux, chunk_size_padded); + case MKFOURCC('A', 'N', 'M', 'F'): { + if (anim_chunks == 0) return PARSE_ERROR; // 'ANIM' precedes frames. + status = ParseAnimationFrame(dmux, chunk_size_padded); break; } - case MKFOURCC('T', 'I', 'L', 'E'): { - if (dmux->num_frames_ == 0) dmux->num_frames_ = 1; - status = ParseTile(dmux, chunk_size_padded); +#ifdef WEBP_EXPERIMENTAL_FEATURES + case MKFOURCC('F', 'R', 'G', 'M'): { + status = ParseFragment(dmux, chunk_size_padded); break; } +#endif case MKFOURCC('I', 'C', 'C', 'P'): { store_chunk = !!(dmux->feature_flags_ & ICCP_FLAG); goto Skip; } - case MKFOURCC('M', 'E', 'T', 'A'): { - store_chunk = !!(dmux->feature_flags_ & META_FLAG); + case MKFOURCC('X', 'M', 'P', ' '): { + store_chunk = !!(dmux->feature_flags_ & XMP_FLAG); + goto Skip; + } + case MKFOURCC('E', 'X', 'I', 'F'): { + store_chunk = !!(dmux->feature_flags_ & EXIF_FLAG); goto Skip; } Skip: @@ -561,7 +598,7 @@ static int IsValidSimpleFormat(const WebPDemuxer* const dmux) { } static int IsValidExtendedFormat(const WebPDemuxer* const dmux) { - const int has_tiles = !!(dmux->feature_flags_ & TILE_FLAG); + const int has_fragments = !!(dmux->feature_flags_ & FRAGMENTS_FLAG); const int has_frames = !!(dmux->feature_flags_ & ANIMATION_FLAG); const Frame* f; @@ -573,15 +610,15 @@ static int IsValidExtendedFormat(const WebPDemuxer* const dmux) { for (f = dmux->frames_; f != NULL; f = f->next_) { const int cur_frame_set = f->frame_num_; - int frame_count = 0, tile_count = 0; + int frame_count = 0, fragment_count = 0; - // Check frame properties and if the image is composed of tiles that each - // fragment came from a 'TILE'. + // Check frame properties and if the image is composed of fragments that + // each fragment came from a fragment. for (; f != NULL && f->frame_num_ == cur_frame_set; f = f->next_) { const ChunkData* const image = f->img_components_; const ChunkData* const alpha = f->img_components_ + 1; - if (!has_tiles && f->is_tile_) return 0; + if (!has_fragments && f->is_fragment_) return 0; if (!has_frames && f->frame_num_ > 1) return 0; if (f->x_offset_ < 0 || f->y_offset_ < 0) return 0; if (f->complete_) { @@ -593,6 +630,9 @@ static int IsValidExtendedFormat(const WebPDemuxer* const dmux) { if (f->width_ <= 0 || f->height_ <= 0) return 0; } else { + // There shouldn't be a partial frame in a complete file. + if (dmux->state_ == WEBP_DEMUX_DONE) return 0; + // Ensure alpha precedes image bitstream. if (alpha->size_ > 0 && image->size_ > 0 && alpha->offset_ > image->offset_) { @@ -602,11 +642,11 @@ static int IsValidExtendedFormat(const WebPDemuxer* const dmux) { if (f->next_ != NULL) return 0; } - tile_count += f->is_tile_; + fragment_count += f->is_fragment_; ++frame_count; } - if (!has_tiles && frame_count > 1) return 0; - if (tile_count > 0 && frame_count != tile_count) return 0; + if (!has_fragments && frame_count > 1) return 0; + if (fragment_count > 0 && frame_count != fragment_count) return 0; if (f == NULL) break; } return 1; @@ -618,8 +658,10 @@ static int IsValidExtendedFormat(const WebPDemuxer* const dmux) { static void InitDemux(WebPDemuxer* const dmux, const MemBuffer* const mem) { dmux->state_ = WEBP_DEMUX_PARSING_HEADER; dmux->loop_count_ = 1; + dmux->bgcolor_ = 0xFFFFFFFF; // White background by default. dmux->canvas_width_ = -1; dmux->canvas_height_ = -1; + dmux->frames_tail_ = &dmux->frames_; dmux->mem_ = *mem; } @@ -632,9 +674,9 @@ WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial, WebPDemuxer* dmux; if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DEMUX_ABI_VERSION)) return NULL; - if (data == NULL || data->bytes_ == NULL || data->size_ == 0) return NULL; + if (data == NULL || data->bytes == NULL || data->size == 0) return NULL; - if (!InitMemBuffer(&mem, data->bytes_, data->size_)) return NULL; + if (!InitMemBuffer(&mem, data->bytes, data->size)) return NULL; if (!ReadHeader(&mem)) return NULL; partial = (mem.buf_size_ < mem.riff_end_); @@ -648,6 +690,7 @@ WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial, if (!memcmp(parser->id, GetBuffer(&dmux->mem_), TAG_SIZE)) { status = parser->parse(dmux); if (status == PARSE_OK) dmux->state_ = WEBP_DEMUX_DONE; + if (status == PARSE_NEED_MORE_DATA && !partial) status = PARSE_ERROR; if (status != PARSE_ERROR && !parser->valid(dmux)) status = PARSE_ERROR; break; } @@ -685,10 +728,12 @@ uint32_t WebPDemuxGetI(const WebPDemuxer* dmux, WebPFormatFeature feature) { if (dmux == NULL) return 0; switch (feature) { - case WEBP_FF_FORMAT_FLAGS: return dmux->feature_flags_; - case WEBP_FF_CANVAS_WIDTH: return (uint32_t)dmux->canvas_width_; - case WEBP_FF_CANVAS_HEIGHT: return (uint32_t)dmux->canvas_height_; - case WEBP_FF_LOOP_COUNT: return (uint32_t)dmux->loop_count_; + case WEBP_FF_FORMAT_FLAGS: return dmux->feature_flags_; + case WEBP_FF_CANVAS_WIDTH: return (uint32_t)dmux->canvas_width_; + case WEBP_FF_CANVAS_HEIGHT: return (uint32_t)dmux->canvas_height_; + case WEBP_FF_LOOP_COUNT: return (uint32_t)dmux->loop_count_; + case WEBP_FF_BACKGROUND_COLOR: return dmux->bgcolor_; + case WEBP_FF_FRAME_COUNT: return (uint32_t)dmux->num_frames_; } return 0; } @@ -696,7 +741,8 @@ uint32_t WebPDemuxGetI(const WebPDemuxer* dmux, WebPFormatFeature feature) { // ----------------------------------------------------------------------------- // Frame iteration -// Find the first 'frame_num' frame. There may be multiple in a tiled frame. +// Find the first 'frame_num' frame. There may be multiple such frames in a +// fragmented frame. static const Frame* GetFrame(const WebPDemuxer* const dmux, int frame_num) { const Frame* f; for (f = dmux->frames_; f != NULL; f = f->next_) { @@ -705,19 +751,19 @@ static const Frame* GetFrame(const WebPDemuxer* const dmux, int frame_num) { return f; } -// Returns tile 'tile_num' and the total count. -static const Frame* GetTile( - const Frame* const frame_set, int tile_num, int* const count) { +// Returns fragment 'fragment_num' and the total count. +static const Frame* GetFragment( + const Frame* const frame_set, int fragment_num, int* const count) { const int this_frame = frame_set->frame_num_; const Frame* f = frame_set; - const Frame* tile = NULL; + const Frame* fragment = NULL; int total; for (total = 0; f != NULL && f->frame_num_ == this_frame; f = f->next_) { - if (++total == tile_num) tile = f; + if (++total == fragment_num) fragment = f; } *count = total; - return tile; + return fragment; } static const uint8_t* GetFramePayload(const uint8_t* const mem_buf, @@ -747,27 +793,31 @@ static const uint8_t* GetFramePayload(const uint8_t* const mem_buf, // Create a whole 'frame' from VP8 (+ alpha) or lossless. static int SynthesizeFrame(const WebPDemuxer* const dmux, const Frame* const first_frame, - int tile_num, WebPIterator* const iter) { + int fragment_num, WebPIterator* const iter) { const uint8_t* const mem_buf = dmux->mem_.buf_; - int num_tiles; + int num_fragments; size_t payload_size = 0; - const Frame* const tile = GetTile(first_frame, tile_num, &num_tiles); - const uint8_t* const payload = GetFramePayload(mem_buf, tile, &payload_size); + const Frame* const fragment = + GetFragment(first_frame, fragment_num, &num_fragments); + const uint8_t* const payload = + GetFramePayload(mem_buf, fragment, &payload_size); if (payload == NULL) return 0; + assert(first_frame != NULL); - iter->frame_num_ = first_frame->frame_num_; - iter->num_frames_ = dmux->num_frames_; - iter->tile_num_ = tile_num; - iter->num_tiles_ = num_tiles; - iter->x_offset_ = tile->x_offset_; - iter->y_offset_ = tile->y_offset_; - iter->width_ = tile->width_; - iter->height_ = tile->height_; - iter->duration_ = tile->duration_; - iter->complete_ = tile->complete_; - iter->tile_.bytes_ = payload; - iter->tile_.size_ = payload_size; - // TODO(jzern): adjust offsets for 'TILE's embedded in 'FRM 's + iter->frame_num = first_frame->frame_num_; + iter->num_frames = dmux->num_frames_; + iter->fragment_num = fragment_num; + iter->num_fragments = num_fragments; + iter->x_offset = fragment->x_offset_; + iter->y_offset = fragment->y_offset_; + iter->width = fragment->width_; + iter->height = fragment->height_; + iter->duration = fragment->duration_; + iter->dispose_method = fragment->dispose_method_; + iter->complete = fragment->complete_; + iter->fragment.bytes = payload; + iter->fragment.size = payload_size; + // TODO(jzern): adjust offsets for 'FRGM's embedded in 'ANMF's return 1; } @@ -779,6 +829,8 @@ static int SetFrame(int frame_num, WebPIterator* const iter) { if (frame_num == 0) frame_num = dmux->num_frames_; frame = GetFrame(dmux, frame_num); + if (frame == NULL) return 0; + return SynthesizeFrame(dmux, frame, 1, iter); } @@ -792,22 +844,22 @@ int WebPDemuxGetFrame(const WebPDemuxer* dmux, int frame, WebPIterator* iter) { int WebPDemuxNextFrame(WebPIterator* iter) { if (iter == NULL) return 0; - return SetFrame(iter->frame_num_ + 1, iter); + return SetFrame(iter->frame_num + 1, iter); } int WebPDemuxPrevFrame(WebPIterator* iter) { if (iter == NULL) return 0; - if (iter->frame_num_ <= 1) return 0; - return SetFrame(iter->frame_num_ - 1, iter); + if (iter->frame_num <= 1) return 0; + return SetFrame(iter->frame_num - 1, iter); } -int WebPDemuxSelectTile(WebPIterator* iter, int tile) { - if (iter != NULL && iter->private_ != NULL && tile > 0) { +int WebPDemuxSelectFragment(WebPIterator* iter, int fragment_num) { + if (iter != NULL && iter->private_ != NULL && fragment_num > 0) { const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_; - const Frame* const frame = GetFrame(dmux, iter->frame_num_); + const Frame* const frame = GetFrame(dmux, iter->frame_num); if (frame == NULL) return 0; - return SynthesizeFrame(dmux, frame, tile, iter); + return SynthesizeFrame(dmux, frame, fragment_num, iter); } return 0; } @@ -856,10 +908,10 @@ static int SetChunk(const char fourcc[4], int chunk_num, if (chunk_num <= count) { const uint8_t* const mem_buf = dmux->mem_.buf_; const Chunk* const chunk = GetChunk(dmux, fourcc, chunk_num); - iter->chunk_.bytes_ = mem_buf + chunk->data_.offset_ + CHUNK_HEADER_SIZE; - iter->chunk_.size_ = chunk->data_.size_ - CHUNK_HEADER_SIZE; - iter->num_chunks_ = count; - iter->chunk_num_ = chunk_num; + iter->chunk.bytes = mem_buf + chunk->data_.offset_ + CHUNK_HEADER_SIZE; + iter->chunk.size = chunk->data_.size_ - CHUNK_HEADER_SIZE; + iter->num_chunks = count; + iter->chunk_num = chunk_num; return 1; } return 0; @@ -878,17 +930,17 @@ int WebPDemuxGetChunk(const WebPDemuxer* dmux, int WebPDemuxNextChunk(WebPChunkIterator* iter) { if (iter != NULL) { const char* const fourcc = - (const char*)iter->chunk_.bytes_ - CHUNK_HEADER_SIZE; - return SetChunk(fourcc, iter->chunk_num_ + 1, iter); + (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE; + return SetChunk(fourcc, iter->chunk_num + 1, iter); } return 0; } int WebPDemuxPrevChunk(WebPChunkIterator* iter) { - if (iter != NULL && iter->chunk_num_ > 1) { + if (iter != NULL && iter->chunk_num > 1) { const char* const fourcc = - (const char*)iter->chunk_.bytes_ - CHUNK_HEADER_SIZE; - return SetChunk(fourcc, iter->chunk_num_ - 1, iter); + (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE; + return SetChunk(fourcc, iter->chunk_num - 1, iter); } return 0; } diff --git a/3rdparty/libwebp/dsp/cpu.c b/3rdparty/libwebp/dsp/cpu.c index 0228734457..179901e100 100644 --- a/3rdparty/libwebp/dsp/cpu.c +++ b/3rdparty/libwebp/dsp/cpu.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // CPU detection diff --git a/3rdparty/libwebp/dsp/dec.c b/3rdparty/libwebp/dsp/dec.c index 9ae7b6fa76..2fbd6b1ac4 100644 --- a/3rdparty/libwebp/dsp/dec.c +++ b/3rdparty/libwebp/dsp/dec.c @@ -1,8 +1,10 @@ // Copyright 2010 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Speed-critical decoding functions. @@ -426,11 +428,16 @@ static void HE8uv(uint8_t *dst) { // horizontal } // helper for chroma-DC predictions -static WEBP_INLINE void Put8x8uv(uint64_t v, uint8_t* dst) { +static WEBP_INLINE void Put8x8uv(uint8_t value, uint8_t* dst) { int j; +#ifndef WEBP_REFERENCE_IMPLEMENTATION + const uint64_t v = (uint64_t)value * 0x0101010101010101ULL; for (j = 0; j < 8; ++j) { *(uint64_t*)(dst + j * BPS) = v; } +#else + for (j = 0; j < 8; ++j) memset(dst + j * BPS, value, 8); +#endif } static void DC8uv(uint8_t *dst) { // DC @@ -439,7 +446,7 @@ static void DC8uv(uint8_t *dst) { // DC for (i = 0; i < 8; ++i) { dc0 += dst[i - BPS] + dst[-1 + i * BPS]; } - Put8x8uv((uint64_t)((dc0 >> 4) * 0x0101010101010101ULL), dst); + Put8x8uv(dc0 >> 4, dst); } static void DC8uvNoLeft(uint8_t *dst) { // DC with no left samples @@ -448,7 +455,7 @@ static void DC8uvNoLeft(uint8_t *dst) { // DC with no left samples for (i = 0; i < 8; ++i) { dc0 += dst[i - BPS]; } - Put8x8uv((uint64_t)((dc0 >> 3) * 0x0101010101010101ULL), dst); + Put8x8uv(dc0 >> 3, dst); } static void DC8uvNoTop(uint8_t *dst) { // DC with no top samples @@ -457,11 +464,11 @@ static void DC8uvNoTop(uint8_t *dst) { // DC with no top samples for (i = 0; i < 8; ++i) { dc0 += dst[-1 + i * BPS]; } - Put8x8uv((uint64_t)((dc0 >> 3) * 0x0101010101010101ULL), dst); + Put8x8uv(dc0 >> 3, dst); } static void DC8uvNoTopLeft(uint8_t *dst) { // DC with nothing - Put8x8uv(0x8080808080808080ULL, dst); + Put8x8uv(0x80, dst); } //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/dsp/dec_neon.c b/3rdparty/libwebp/dsp/dec_neon.c index 09cafeef1c..5dcd3b7e5e 100644 --- a/3rdparty/libwebp/dsp/dec_neon.c +++ b/3rdparty/libwebp/dsp/dec_neon.c @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // ARM NEON version of dsp functions and loop filtering. @@ -79,7 +81,7 @@ extern "C" { "vld4.8 {" #c1"[6], " #c2"[6], " #c3"[6], " #c4"[6]}," #b1 "," #stride"\n" \ "vld4.8 {" #c1"[7], " #c2"[7], " #c3"[7], " #c4"[7]}," #b2 "," #stride"\n" -#define STORE8x2(c1, c2, p,stride) \ +#define STORE8x2(c1, c2, p, stride) \ "vst2.8 {" #c1"[0], " #c2"[0]}," #p "," #stride " \n" \ "vst2.8 {" #c1"[1], " #c2"[1]}," #p "," #stride " \n" \ "vst2.8 {" #c1"[2], " #c2"[2]}," #p "," #stride " \n" \ @@ -155,6 +157,9 @@ static void SimpleHFilter16iNEON(uint8_t* p, int stride, int thresh) { } } +//----------------------------------------------------------------------------- +// Inverse transforms (Paragraph 14.4) + static void TransformOneNEON(const int16_t *in, uint8_t *dst) { const int kBPS = BPS; const int16_t constants[] = {20091, 17734, 0, 0}; @@ -311,6 +316,73 @@ static void TransformTwoNEON(const int16_t* in, uint8_t* dst, int do_two) { } } +static void TransformWHT(const int16_t* in, int16_t* out) { + const int kStep = 32; // The store is only incrementing the pointer as if we + // had stored a single byte. + __asm__ volatile ( + // part 1 + // load data into q0, q1 + "vld1.16 {q0, q1}, [%[in]] \n" + + "vaddl.s16 q2, d0, d3 \n" // a0 = in[0] + in[12] + "vaddl.s16 q3, d1, d2 \n" // a1 = in[4] + in[8] + "vsubl.s16 q4, d1, d2 \n" // a2 = in[4] - in[8] + "vsubl.s16 q5, d0, d3 \n" // a3 = in[0] - in[12] + + "vadd.s32 q0, q2, q3 \n" // tmp[0] = a0 + a1 + "vsub.s32 q2, q2, q3 \n" // tmp[8] = a0 - a1 + "vadd.s32 q1, q5, q4 \n" // tmp[4] = a3 + a2 + "vsub.s32 q3, q5, q4 \n" // tmp[12] = a3 - a2 + + // Transpose + // q0 = tmp[0, 4, 8, 12], q1 = tmp[2, 6, 10, 14] + // q2 = tmp[1, 5, 9, 13], q3 = tmp[3, 7, 11, 15] + "vswp d1, d4 \n" // vtrn.64 q0, q2 + "vswp d3, d6 \n" // vtrn.64 q1, q3 + "vtrn.32 q0, q1 \n" + "vtrn.32 q2, q3 \n" + + "vmov.s32 q4, #3 \n" // dc = 3 + "vadd.s32 q0, q0, q4 \n" // dc = tmp[0] + 3 + "vadd.s32 q6, q0, q3 \n" // a0 = dc + tmp[3] + "vadd.s32 q7, q1, q2 \n" // a1 = tmp[1] + tmp[2] + "vsub.s32 q8, q1, q2 \n" // a2 = tmp[1] - tmp[2] + "vsub.s32 q9, q0, q3 \n" // a3 = dc - tmp[3] + + "vadd.s32 q0, q6, q7 \n" + "vshrn.s32 d0, q0, #3 \n" // (a0 + a1) >> 3 + "vadd.s32 q1, q9, q8 \n" + "vshrn.s32 d1, q1, #3 \n" // (a3 + a2) >> 3 + "vsub.s32 q2, q6, q7 \n" + "vshrn.s32 d2, q2, #3 \n" // (a0 - a1) >> 3 + "vsub.s32 q3, q9, q8 \n" + "vshrn.s32 d3, q3, #3 \n" // (a3 - a2) >> 3 + + // set the results to output + "vst1.16 d0[0], [%[out]], %[kStep] \n" + "vst1.16 d1[0], [%[out]], %[kStep] \n" + "vst1.16 d2[0], [%[out]], %[kStep] \n" + "vst1.16 d3[0], [%[out]], %[kStep] \n" + "vst1.16 d0[1], [%[out]], %[kStep] \n" + "vst1.16 d1[1], [%[out]], %[kStep] \n" + "vst1.16 d2[1], [%[out]], %[kStep] \n" + "vst1.16 d3[1], [%[out]], %[kStep] \n" + "vst1.16 d0[2], [%[out]], %[kStep] \n" + "vst1.16 d1[2], [%[out]], %[kStep] \n" + "vst1.16 d2[2], [%[out]], %[kStep] \n" + "vst1.16 d3[2], [%[out]], %[kStep] \n" + "vst1.16 d0[3], [%[out]], %[kStep] \n" + "vst1.16 d1[3], [%[out]], %[kStep] \n" + "vst1.16 d2[3], [%[out]], %[kStep] \n" + "vst1.16 d3[3], [%[out]], %[kStep] \n" + + : [out] "+r"(out) // modified registers + : [in] "r"(in), [kStep] "r"(kStep) // constants + : "memory", "q0", "q1", "q2", "q3", "q4", + "q5", "q6", "q7", "q8", "q9" // clobbered + ); +} + #endif // WEBP_USE_NEON //------------------------------------------------------------------------------ @@ -321,6 +393,7 @@ extern void VP8DspInitNEON(void); void VP8DspInitNEON(void) { #if defined(WEBP_USE_NEON) VP8Transform = TransformTwoNEON; + VP8TransformWHT = TransformWHT; VP8SimpleVFilter16 = SimpleVFilter16NEON; VP8SimpleHFilter16 = SimpleHFilter16NEON; diff --git a/3rdparty/libwebp/dsp/dec_sse2.c b/3rdparty/libwebp/dsp/dec_sse2.c index 2cb55d013f..6be94678ef 100644 --- a/3rdparty/libwebp/dsp/dec_sse2.c +++ b/3rdparty/libwebp/dsp/dec_sse2.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // SSE2 version of some decoding functions (idct, loop filtering). @@ -194,7 +196,7 @@ static void TransformSSE2(const int16_t* in, uint8_t* dst, int do_two) { // Add inverse transform to 'dst' and store. { - const __m128i zero = _mm_set1_epi16(0); + const __m128i zero = _mm_setzero_si128(); // Load the reference(s). __m128i dst0, dst1, dst2, dst3; if (do_two) { @@ -278,14 +280,14 @@ static void TransformSSE2(const int16_t* in, uint8_t* dst, int do_two) { #define GET_NOTHEV(p1, p0, q0, q1, hev_thresh, not_hev) { \ const __m128i zero = _mm_setzero_si128(); \ - const __m128i t1 = MM_ABS(p1, p0); \ - const __m128i t2 = MM_ABS(q1, q0); \ + const __m128i t_1 = MM_ABS(p1, p0); \ + const __m128i t_2 = MM_ABS(q1, q0); \ \ const __m128i h = _mm_set1_epi8(hev_thresh); \ - const __m128i t3 = _mm_subs_epu8(t1, h); /* abs(p1 - p0) - hev_tresh */ \ - const __m128i t4 = _mm_subs_epu8(t2, h); /* abs(q1 - q0) - hev_tresh */ \ + const __m128i t_3 = _mm_subs_epu8(t_1, h); /* abs(p1 - p0) - hev_tresh */ \ + const __m128i t_4 = _mm_subs_epu8(t_2, h); /* abs(q1 - q0) - hev_tresh */ \ \ - not_hev = _mm_or_si128(t3, t4); \ + not_hev = _mm_or_si128(t_3, t_4); \ not_hev = _mm_cmpeq_epi8(not_hev, zero); /* not_hev <= t1 && not_hev <= t2 */\ } @@ -314,13 +316,13 @@ static void TransformSSE2(const int16_t* in, uint8_t* dst, int do_two) { // Updates values of 2 pixels at MB edge during complex filtering. // Update operations: -// q = q - a and p = p + a; where a = [(a_hi >> 7), (a_lo >> 7)] +// q = q - delta and p = p + delta; where delta = [(a_hi >> 7), (a_lo >> 7)] #define UPDATE_2PIXELS(pi, qi, a_lo, a_hi) { \ const __m128i a_lo7 = _mm_srai_epi16(a_lo, 7); \ const __m128i a_hi7 = _mm_srai_epi16(a_hi, 7); \ - const __m128i a = _mm_packs_epi16(a_lo7, a_hi7); \ - pi = _mm_adds_epi8(pi, a); \ - qi = _mm_subs_epi8(qi, a); \ + const __m128i delta = _mm_packs_epi16(a_lo7, a_hi7); \ + pi = _mm_adds_epi8(pi, delta); \ + qi = _mm_subs_epi8(qi, delta); \ } static void NeedsFilter(const __m128i* p1, const __m128i* p0, const __m128i* q0, diff --git a/3rdparty/libwebp/dsp/dsp.h b/3rdparty/libwebp/dsp/dsp.h index 24d0c188c4..01a95891fe 100644 --- a/3rdparty/libwebp/dsp/dsp.h +++ b/3rdparty/libwebp/dsp/dsp.h @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Speed-critical functions. @@ -49,8 +51,6 @@ extern VP8CPUInfo VP8GetCPUInfo; //------------------------------------------------------------------------------ // Encoding -int VP8GetAlpha(const int histo[]); - // Transforms // VP8Idct: Does one of two inverse transforms. If do_two is set, the transforms // will be done for (ref, in, dst) and (ref + 4, in + 16, dst + 4). @@ -85,10 +85,11 @@ typedef int (*VP8QuantizeBlock)(int16_t in[16], int16_t out[16], int n, const struct VP8Matrix* const mtx); extern VP8QuantizeBlock VP8EncQuantizeBlock; -// Compute susceptibility based on DCT-coeff histograms: -// the higher, the "easier" the macroblock is to compress. -typedef int (*VP8CHisto)(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block); +// Collect histogram for susceptibility calculation and accumulate in histo[]. +struct VP8Histogram; +typedef void (*VP8CHisto)(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + struct VP8Histogram* const histo); extern const int VP8DspScan[16 + 4 + 4]; extern VP8CHisto VP8CollectHistogram; @@ -104,7 +105,7 @@ extern VP8DecIdct2 VP8Transform; extern VP8DecIdct VP8TransformUV; extern VP8DecIdct VP8TransformDC; extern VP8DecIdct VP8TransformDCUV; -extern void (*VP8TransformWHT)(const int16_t* in, int16_t* out); +extern VP8WHT VP8TransformWHT; // *dst is the destination block, with stride BPS. Boundary samples are // assumed accessible when needed. @@ -159,6 +160,9 @@ extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; // Initializes SSE2 version of the fancy upsamplers. void WebPInitUpsamplersSSE2(void); +// NEON version +void WebPInitUpsamplersNEON(void); + #endif // FANCY_UPSAMPLING // Point-sampling methods. @@ -200,6 +204,7 @@ extern void (*WebPApplyAlphaMultiply4444)( void WebPInitPremultiply(void); void WebPInitPremultiplySSE2(void); // should not be called directly. +void WebPInitPremultiplyNEON(void); //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/dsp/enc.c b/3rdparty/libwebp/dsp/enc.c index 02234564be..552807ad95 100644 --- a/3rdparty/libwebp/dsp/enc.c +++ b/3rdparty/libwebp/dsp/enc.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Speed-critical encoding functions. @@ -17,31 +19,18 @@ extern "C" { #endif +static WEBP_INLINE uint8_t clip_8b(int v) { + return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255; +} + +static WEBP_INLINE int clip_max(int v, int max) { + return (v > max) ? max : v; +} + //------------------------------------------------------------------------------ // Compute susceptibility based on DCT-coeff histograms: // the higher, the "easier" the macroblock is to compress. -static int ClipAlpha(int alpha) { - return alpha < 0 ? 0 : alpha > 255 ? 255 : alpha; -} - -int VP8GetAlpha(const int histo[MAX_COEFF_THRESH + 1]) { - int num = 0, den = 0, val = 0; - int k; - int alpha; - // note: changing this loop to avoid the numerous "k + 1" slows things down. - for (k = 0; k < MAX_COEFF_THRESH; ++k) { - if (histo[k + 1]) { - val += histo[k + 1]; - num += val * (k + 1); - den += (k + 1) * (k + 1); - } - } - // we scale the value to a usable [0..255] range - alpha = den ? 10 * num / den - 5 : 0; - return ClipAlpha(alpha); -} - const int VP8DspScan[16 + 4 + 4] = { // Luma 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS, @@ -53,27 +42,23 @@ const int VP8DspScan[16 + 4 + 4] = { 8 + 0 * BPS, 12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS // V }; -static int CollectHistogram(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block) { - int histo[MAX_COEFF_THRESH + 1] = { 0 }; - int16_t out[16]; - int j, k; +static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { + int j; for (j = start_block; j < end_block; ++j) { + int k; + int16_t out[16]; + VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); - // Convert coefficients to bin (within out[]). + // Convert coefficients to bin. for (k = 0; k < 16; ++k) { - const int v = abs(out[k]) >> 2; - out[k] = (v > MAX_COEFF_THRESH) ? MAX_COEFF_THRESH : v; - } - - // Use bin to update histogram. - for (k = 0; k < 16; ++k) { - histo[out[k]]++; + const int v = abs(out[k]) >> 3; // TODO(skal): add rounding? + const int clipped_value = clip_max(v, MAX_COEFF_THRESH); + histo->distribution[clipped_value]++; } } - - return VP8GetAlpha(histo); } //------------------------------------------------------------------------------ @@ -89,15 +74,12 @@ static void InitTables(void) { if (!tables_ok) { int i; for (i = -255; i <= 255 + 255; ++i) { - clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i; + clip1[255 + i] = clip_8b(i); } tables_ok = 1; } } -static WEBP_INLINE uint8_t clip_8b(int v) { - return (!(v & ~0xff)) ? v : v < 0 ? 0 : 255; -} //------------------------------------------------------------------------------ // Transforms (Paragraph 14.4) @@ -154,25 +136,25 @@ static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { int i; int tmp[16]; for (i = 0; i < 4; ++i, src += BPS, ref += BPS) { - const int d0 = src[0] - ref[0]; + const int d0 = src[0] - ref[0]; // 9bit dynamic range ([-255,255]) const int d1 = src[1] - ref[1]; const int d2 = src[2] - ref[2]; const int d3 = src[3] - ref[3]; - const int a0 = (d0 + d3) << 3; - const int a1 = (d1 + d2) << 3; - const int a2 = (d1 - d2) << 3; - const int a3 = (d0 - d3) << 3; - tmp[0 + i * 4] = (a0 + a1); - tmp[1 + i * 4] = (a2 * 2217 + a3 * 5352 + 14500) >> 12; - tmp[2 + i * 4] = (a0 - a1); - tmp[3 + i * 4] = (a3 * 2217 - a2 * 5352 + 7500) >> 12; + const int a0 = (d0 + d3); // 10b [-510,510] + const int a1 = (d1 + d2); + const int a2 = (d1 - d2); + const int a3 = (d0 - d3); + tmp[0 + i * 4] = (a0 + a1) * 8; // 14b [-8160,8160] + tmp[1 + i * 4] = (a2 * 2217 + a3 * 5352 + 1812) >> 9; // [-7536,7542] + tmp[2 + i * 4] = (a0 - a1) * 8; + tmp[3 + i * 4] = (a3 * 2217 - a2 * 5352 + 937) >> 9; } for (i = 0; i < 4; ++i) { - const int a0 = (tmp[0 + i] + tmp[12 + i]); + const int a0 = (tmp[0 + i] + tmp[12 + i]); // 15b const int a1 = (tmp[4 + i] + tmp[ 8 + i]); const int a2 = (tmp[4 + i] - tmp[ 8 + i]); const int a3 = (tmp[0 + i] - tmp[12 + i]); - out[0 + i] = (a0 + a1 + 7) >> 4; + out[0 + i] = (a0 + a1 + 7) >> 4; // 12b out[4 + i] = ((a2 * 2217 + a3 * 5352 + 12000) >> 16) + (a3 != 0); out[8 + i] = (a0 - a1 + 7) >> 4; out[12+ i] = ((a3 * 2217 - a2 * 5352 + 51000) >> 16); @@ -207,31 +189,32 @@ static void ITransformWHT(const int16_t* in, int16_t* out) { } static void FTransformWHT(const int16_t* in, int16_t* out) { - int tmp[16]; + // input is 12b signed + int16_t tmp[16]; int i; for (i = 0; i < 4; ++i, in += 64) { - const int a0 = (in[0 * 16] + in[2 * 16]) << 2; - const int a1 = (in[1 * 16] + in[3 * 16]) << 2; - const int a2 = (in[1 * 16] - in[3 * 16]) << 2; - const int a3 = (in[0 * 16] - in[2 * 16]) << 2; - tmp[0 + i * 4] = (a0 + a1) + (a0 != 0); + const int a0 = (in[0 * 16] + in[2 * 16]); // 13b + const int a1 = (in[1 * 16] + in[3 * 16]); + const int a2 = (in[1 * 16] - in[3 * 16]); + const int a3 = (in[0 * 16] - in[2 * 16]); + tmp[0 + i * 4] = a0 + a1; // 14b tmp[1 + i * 4] = a3 + a2; tmp[2 + i * 4] = a3 - a2; tmp[3 + i * 4] = a0 - a1; } for (i = 0; i < 4; ++i) { - const int a0 = (tmp[0 + i] + tmp[8 + i]); + const int a0 = (tmp[0 + i] + tmp[8 + i]); // 15b const int a1 = (tmp[4 + i] + tmp[12+ i]); const int a2 = (tmp[4 + i] - tmp[12+ i]); const int a3 = (tmp[0 + i] - tmp[8 + i]); - const int b0 = a0 + a1; + const int b0 = a0 + a1; // 16b const int b1 = a3 + a2; const int b2 = a3 - a2; const int b3 = a0 - a1; - out[ 0 + i] = (b0 + (b0 > 0) + 3) >> 3; - out[ 4 + i] = (b1 + (b1 > 0) + 3) >> 3; - out[ 8 + i] = (b2 + (b2 > 0) + 3) >> 3; - out[12 + i] = (b3 + (b3 > 0) + 3) >> 3; + out[ 0 + i] = b0 >> 1; // 15b + out[ 4 + i] = b1 >> 1; + out[ 8 + i] = b2 >> 1; + out[12 + i] = b3 >> 1; } } @@ -589,30 +572,30 @@ static int TTransform(const uint8_t* in, const uint16_t* w) { int i; // horizontal pass for (i = 0; i < 4; ++i, in += BPS) { - const int a0 = (in[0] + in[2]) << 2; - const int a1 = (in[1] + in[3]) << 2; - const int a2 = (in[1] - in[3]) << 2; - const int a3 = (in[0] - in[2]) << 2; - tmp[0 + i * 4] = a0 + a1 + (a0 != 0); + const int a0 = in[0] + in[2]; + const int a1 = in[1] + in[3]; + const int a2 = in[1] - in[3]; + const int a3 = in[0] - in[2]; + tmp[0 + i * 4] = a0 + a1; tmp[1 + i * 4] = a3 + a2; tmp[2 + i * 4] = a3 - a2; tmp[3 + i * 4] = a0 - a1; } // vertical pass for (i = 0; i < 4; ++i, ++w) { - const int a0 = (tmp[0 + i] + tmp[8 + i]); - const int a1 = (tmp[4 + i] + tmp[12+ i]); - const int a2 = (tmp[4 + i] - tmp[12+ i]); - const int a3 = (tmp[0 + i] - tmp[8 + i]); + const int a0 = tmp[0 + i] + tmp[8 + i]; + const int a1 = tmp[4 + i] + tmp[12+ i]; + const int a2 = tmp[4 + i] - tmp[12+ i]; + const int a3 = tmp[0 + i] - tmp[8 + i]; const int b0 = a0 + a1; const int b1 = a3 + a2; const int b2 = a3 - a2; const int b3 = a0 - a1; - // abs((b + (b<0) + 3) >> 3) = (abs(b) + 3) >> 3 - sum += w[ 0] * ((abs(b0) + 3) >> 3); - sum += w[ 4] * ((abs(b1) + 3) >> 3); - sum += w[ 8] * ((abs(b2) + 3) >> 3); - sum += w[12] * ((abs(b3) + 3) >> 3); + + sum += w[ 0] * abs(b0); + sum += w[ 4] * abs(b1); + sum += w[ 8] * abs(b2); + sum += w[12] * abs(b3); } return sum; } @@ -621,7 +604,7 @@ static int Disto4x4(const uint8_t* const a, const uint8_t* const b, const uint16_t* const w) { const int sum1 = TTransform(a, w); const int sum2 = TTransform(b, w); - return (abs(sum2 - sum1) + 8) >> 4; + return abs(sum2 - sum1) >> 5; } static int Disto16x16(const uint8_t* const a, const uint8_t* const b, @@ -651,13 +634,13 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16], for (; n < 16; ++n) { const int j = kZigzag[n]; const int sign = (in[j] < 0); - int coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j]; - if (coeff > 2047) coeff = 2047; + const int coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j]; if (coeff > mtx->zthresh_[j]) { const int Q = mtx->q_[j]; const int iQ = mtx->iq_[j]; const int B = mtx->bias_[j]; out[n] = QUANTDIV(coeff, iQ, B); + if (out[n] > MAX_LEVEL) out[n] = MAX_LEVEL; if (sign) out[n] = -out[n]; in[j] = out[n] * Q; if (out[n]) last = n; @@ -706,6 +689,7 @@ VP8QuantizeBlock VP8EncQuantizeBlock; VP8BlockCopy VP8Copy4x4; extern void VP8EncDspInitSSE2(void); +extern void VP8EncDspInitNEON(void); void VP8EncDspInit(void) { InitTables(); @@ -734,6 +718,10 @@ void VP8EncDspInit(void) { if (VP8GetCPUInfo(kSSE2)) { VP8EncDspInitSSE2(); } +#elif defined(WEBP_USE_NEON) + if (VP8GetCPUInfo(kNEON)) { + VP8EncDspInitNEON(); + } #endif } } diff --git a/3rdparty/libwebp/dsp/enc_neon.c b/3rdparty/libwebp/dsp/enc_neon.c new file mode 100644 index 0000000000..eb256e681d --- /dev/null +++ b/3rdparty/libwebp/dsp/enc_neon.c @@ -0,0 +1,639 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// ARM NEON version of speed-critical encoding functions. +// +// adapted from libvpx (http://www.webmproject.org/code/) + +#include "./dsp.h" + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#if defined(WEBP_USE_NEON) + +#include "../enc/vp8enci.h" + +//------------------------------------------------------------------------------ +// Transforms (Paragraph 14.4) + +// Inverse transform. +// This code is pretty much the same as TransformOneNEON in the decoder, except +// for subtraction to *ref. See the comments there for algorithmic explanations. +static void ITransformOne(const uint8_t* ref, + const int16_t* in, uint8_t* dst) { + const int kBPS = BPS; + const int16_t kC1C2[] = { 20091, 17734, 0, 0 }; // kC1 / (kC2 >> 1) / 0 / 0 + + __asm__ volatile ( + "vld1.16 {q1, q2}, [%[in]] \n" + "vld1.16 {d0}, [%[kC1C2]] \n" + + // d2: in[0] + // d3: in[8] + // d4: in[4] + // d5: in[12] + "vswp d3, d4 \n" + + // q8 = {in[4], in[12]} * kC1 * 2 >> 16 + // q9 = {in[4], in[12]} * kC2 >> 16 + "vqdmulh.s16 q8, q2, d0[0] \n" + "vqdmulh.s16 q9, q2, d0[1] \n" + + // d22 = a = in[0] + in[8] + // d23 = b = in[0] - in[8] + "vqadd.s16 d22, d2, d3 \n" + "vqsub.s16 d23, d2, d3 \n" + + // q8 = in[4]/[12] * kC1 >> 16 + "vshr.s16 q8, q8, #1 \n" + + // Add {in[4], in[12]} back after the multiplication. + "vqadd.s16 q8, q2, q8 \n" + + // d20 = c = in[4]*kC2 - in[12]*kC1 + // d21 = d = in[4]*kC1 + in[12]*kC2 + "vqsub.s16 d20, d18, d17 \n" + "vqadd.s16 d21, d19, d16 \n" + + // d2 = tmp[0] = a + d + // d3 = tmp[1] = b + c + // d4 = tmp[2] = b - c + // d5 = tmp[3] = a - d + "vqadd.s16 d2, d22, d21 \n" + "vqadd.s16 d3, d23, d20 \n" + "vqsub.s16 d4, d23, d20 \n" + "vqsub.s16 d5, d22, d21 \n" + + "vzip.16 q1, q2 \n" + "vzip.16 q1, q2 \n" + + "vswp d3, d4 \n" + + // q8 = {tmp[4], tmp[12]} * kC1 * 2 >> 16 + // q9 = {tmp[4], tmp[12]} * kC2 >> 16 + "vqdmulh.s16 q8, q2, d0[0] \n" + "vqdmulh.s16 q9, q2, d0[1] \n" + + // d22 = a = tmp[0] + tmp[8] + // d23 = b = tmp[0] - tmp[8] + "vqadd.s16 d22, d2, d3 \n" + "vqsub.s16 d23, d2, d3 \n" + + "vshr.s16 q8, q8, #1 \n" + "vqadd.s16 q8, q2, q8 \n" + + // d20 = c = in[4]*kC2 - in[12]*kC1 + // d21 = d = in[4]*kC1 + in[12]*kC2 + "vqsub.s16 d20, d18, d17 \n" + "vqadd.s16 d21, d19, d16 \n" + + // d2 = tmp[0] = a + d + // d3 = tmp[1] = b + c + // d4 = tmp[2] = b - c + // d5 = tmp[3] = a - d + "vqadd.s16 d2, d22, d21 \n" + "vqadd.s16 d3, d23, d20 \n" + "vqsub.s16 d4, d23, d20 \n" + "vqsub.s16 d5, d22, d21 \n" + + "vld1.32 d6[0], [%[ref]], %[kBPS] \n" + "vld1.32 d6[1], [%[ref]], %[kBPS] \n" + "vld1.32 d7[0], [%[ref]], %[kBPS] \n" + "vld1.32 d7[1], [%[ref]], %[kBPS] \n" + + "sub %[ref], %[ref], %[kBPS], lsl #2 \n" + + // (val) + 4 >> 3 + "vrshr.s16 d2, d2, #3 \n" + "vrshr.s16 d3, d3, #3 \n" + "vrshr.s16 d4, d4, #3 \n" + "vrshr.s16 d5, d5, #3 \n" + + "vzip.16 q1, q2 \n" + "vzip.16 q1, q2 \n" + + // Must accumulate before saturating + "vmovl.u8 q8, d6 \n" + "vmovl.u8 q9, d7 \n" + + "vqadd.s16 q1, q1, q8 \n" + "vqadd.s16 q2, q2, q9 \n" + + "vqmovun.s16 d0, q1 \n" + "vqmovun.s16 d1, q2 \n" + + "vst1.32 d0[0], [%[dst]], %[kBPS] \n" + "vst1.32 d0[1], [%[dst]], %[kBPS] \n" + "vst1.32 d1[0], [%[dst]], %[kBPS] \n" + "vst1.32 d1[1], [%[dst]] \n" + + : [in] "+r"(in), [dst] "+r"(dst) // modified registers + : [kBPS] "r"(kBPS), [kC1C2] "r"(kC1C2), [ref] "r"(ref) // constants + : "memory", "q0", "q1", "q2", "q8", "q9", "q10", "q11" // clobbered + ); +} + +static void ITransform(const uint8_t* ref, + const int16_t* in, uint8_t* dst, int do_two) { + ITransformOne(ref, in, dst); + if (do_two) { + ITransformOne(ref + 4, in + 16, dst + 4); + } +} + +// Same code as dec_neon.c +static void ITransformWHT(const int16_t* in, int16_t* out) { + const int kStep = 32; // The store is only incrementing the pointer as if we + // had stored a single byte. + __asm__ volatile ( + // part 1 + // load data into q0, q1 + "vld1.16 {q0, q1}, [%[in]] \n" + + "vaddl.s16 q2, d0, d3 \n" // a0 = in[0] + in[12] + "vaddl.s16 q3, d1, d2 \n" // a1 = in[4] + in[8] + "vsubl.s16 q4, d1, d2 \n" // a2 = in[4] - in[8] + "vsubl.s16 q5, d0, d3 \n" // a3 = in[0] - in[12] + + "vadd.s32 q0, q2, q3 \n" // tmp[0] = a0 + a1 + "vsub.s32 q2, q2, q3 \n" // tmp[8] = a0 - a1 + "vadd.s32 q1, q5, q4 \n" // tmp[4] = a3 + a2 + "vsub.s32 q3, q5, q4 \n" // tmp[12] = a3 - a2 + + // Transpose + // q0 = tmp[0, 4, 8, 12], q1 = tmp[2, 6, 10, 14] + // q2 = tmp[1, 5, 9, 13], q3 = tmp[3, 7, 11, 15] + "vswp d1, d4 \n" // vtrn.64 q0, q2 + "vswp d3, d6 \n" // vtrn.64 q1, q3 + "vtrn.32 q0, q1 \n" + "vtrn.32 q2, q3 \n" + + "vmov.s32 q4, #3 \n" // dc = 3 + "vadd.s32 q0, q0, q4 \n" // dc = tmp[0] + 3 + "vadd.s32 q6, q0, q3 \n" // a0 = dc + tmp[3] + "vadd.s32 q7, q1, q2 \n" // a1 = tmp[1] + tmp[2] + "vsub.s32 q8, q1, q2 \n" // a2 = tmp[1] - tmp[2] + "vsub.s32 q9, q0, q3 \n" // a3 = dc - tmp[3] + + "vadd.s32 q0, q6, q7 \n" + "vshrn.s32 d0, q0, #3 \n" // (a0 + a1) >> 3 + "vadd.s32 q1, q9, q8 \n" + "vshrn.s32 d1, q1, #3 \n" // (a3 + a2) >> 3 + "vsub.s32 q2, q6, q7 \n" + "vshrn.s32 d2, q2, #3 \n" // (a0 - a1) >> 3 + "vsub.s32 q3, q9, q8 \n" + "vshrn.s32 d3, q3, #3 \n" // (a3 - a2) >> 3 + + // set the results to output + "vst1.16 d0[0], [%[out]], %[kStep] \n" + "vst1.16 d1[0], [%[out]], %[kStep] \n" + "vst1.16 d2[0], [%[out]], %[kStep] \n" + "vst1.16 d3[0], [%[out]], %[kStep] \n" + "vst1.16 d0[1], [%[out]], %[kStep] \n" + "vst1.16 d1[1], [%[out]], %[kStep] \n" + "vst1.16 d2[1], [%[out]], %[kStep] \n" + "vst1.16 d3[1], [%[out]], %[kStep] \n" + "vst1.16 d0[2], [%[out]], %[kStep] \n" + "vst1.16 d1[2], [%[out]], %[kStep] \n" + "vst1.16 d2[2], [%[out]], %[kStep] \n" + "vst1.16 d3[2], [%[out]], %[kStep] \n" + "vst1.16 d0[3], [%[out]], %[kStep] \n" + "vst1.16 d1[3], [%[out]], %[kStep] \n" + "vst1.16 d2[3], [%[out]], %[kStep] \n" + "vst1.16 d3[3], [%[out]], %[kStep] \n" + + : [out] "+r"(out) // modified registers + : [in] "r"(in), [kStep] "r"(kStep) // constants + : "memory", "q0", "q1", "q2", "q3", "q4", + "q5", "q6", "q7", "q8", "q9" // clobbered + ); +} + +// Forward transform. + +// adapted from vp8/encoder/arm/neon/shortfdct_neon.asm +static const int16_t kCoeff16[] = { + 5352, 5352, 5352, 5352, 2217, 2217, 2217, 2217 +}; +static const int32_t kCoeff32[] = { + 1812, 1812, 1812, 1812, + 937, 937, 937, 937, + 12000, 12000, 12000, 12000, + 51000, 51000, 51000, 51000 +}; + +static void FTransform(const uint8_t* src, const uint8_t* ref, + int16_t* out) { + const int kBPS = BPS; + const uint8_t* src_ptr = src; + const uint8_t* ref_ptr = ref; + const int16_t* coeff16 = kCoeff16; + const int32_t* coeff32 = kCoeff32; + + __asm__ volatile ( + // load src into q4, q5 in high half + "vld1.8 {d8}, [%[src_ptr]], %[kBPS] \n" + "vld1.8 {d10}, [%[src_ptr]], %[kBPS] \n" + "vld1.8 {d9}, [%[src_ptr]], %[kBPS] \n" + "vld1.8 {d11}, [%[src_ptr]] \n" + + // load ref into q6, q7 in high half + "vld1.8 {d12}, [%[ref_ptr]], %[kBPS] \n" + "vld1.8 {d14}, [%[ref_ptr]], %[kBPS] \n" + "vld1.8 {d13}, [%[ref_ptr]], %[kBPS] \n" + "vld1.8 {d15}, [%[ref_ptr]] \n" + + // Pack the high values in to q4 and q6 + "vtrn.32 q4, q5 \n" + "vtrn.32 q6, q7 \n" + + // d[0-3] = src - ref + "vsubl.u8 q0, d8, d12 \n" + "vsubl.u8 q1, d9, d13 \n" + + // load coeff16 into q8(d16=5352, d17=2217) + "vld1.16 {q8}, [%[coeff16]] \n" + + // load coeff32 high half into q9 = 1812, q10 = 937 + "vld1.32 {q9, q10}, [%[coeff32]]! \n" + + // load coeff32 low half into q11=12000, q12=51000 + "vld1.32 {q11,q12}, [%[coeff32]] \n" + + // part 1 + // Transpose. Register dN is the same as dN in C + "vtrn.32 d0, d2 \n" + "vtrn.32 d1, d3 \n" + "vtrn.16 d0, d1 \n" + "vtrn.16 d2, d3 \n" + + "vadd.s16 d4, d0, d3 \n" // a0 = d0 + d3 + "vadd.s16 d5, d1, d2 \n" // a1 = d1 + d2 + "vsub.s16 d6, d1, d2 \n" // a2 = d1 - d2 + "vsub.s16 d7, d0, d3 \n" // a3 = d0 - d3 + + "vadd.s16 d0, d4, d5 \n" // a0 + a1 + "vshl.s16 d0, d0, #3 \n" // temp[0+i*4] = (a0+a1) << 3 + "vsub.s16 d2, d4, d5 \n" // a0 - a1 + "vshl.s16 d2, d2, #3 \n" // (temp[2+i*4] = (a0-a1) << 3 + + "vmlal.s16 q9, d7, d16 \n" // a3*5352 + 1812 + "vmlal.s16 q10, d7, d17 \n" // a3*2217 + 937 + "vmlal.s16 q9, d6, d17 \n" // a2*2217 + a3*5352 + 1812 + "vmlsl.s16 q10, d6, d16 \n" // a3*2217 + 937 - a2*5352 + + // temp[1+i*4] = (d2*2217 + d3*5352 + 1812) >> 9 + // temp[3+i*4] = (d3*2217 + 937 - d2*5352) >> 9 + "vshrn.s32 d1, q9, #9 \n" + "vshrn.s32 d3, q10, #9 \n" + + // part 2 + // transpose d0=ip[0], d1=ip[4], d2=ip[8], d3=ip[12] + "vtrn.32 d0, d2 \n" + "vtrn.32 d1, d3 \n" + "vtrn.16 d0, d1 \n" + "vtrn.16 d2, d3 \n" + + "vmov.s16 d26, #7 \n" + + "vadd.s16 d4, d0, d3 \n" // a1 = ip[0] + ip[12] + "vadd.s16 d5, d1, d2 \n" // b1 = ip[4] + ip[8] + "vsub.s16 d6, d1, d2 \n" // c1 = ip[4] - ip[8] + "vadd.s16 d4, d4, d26 \n" // a1 + 7 + "vsub.s16 d7, d0, d3 \n" // d1 = ip[0] - ip[12] + + "vadd.s16 d0, d4, d5 \n" // op[0] = a1 + b1 + 7 + "vsub.s16 d2, d4, d5 \n" // op[8] = a1 - b1 + 7 + + "vmlal.s16 q11, d7, d16 \n" // d1*5352 + 12000 + "vmlal.s16 q12, d7, d17 \n" // d1*2217 + 51000 + + "vceq.s16 d4, d7, #0 \n" + + "vshr.s16 d0, d0, #4 \n" + "vshr.s16 d2, d2, #4 \n" + + "vmlal.s16 q11, d6, d17 \n" // c1*2217 + d1*5352 + 12000 + "vmlsl.s16 q12, d6, d16 \n" // d1*2217 - c1*5352 + 51000 + + "vmvn d4, d4 \n" // !(d1 == 0) + // op[4] = (c1*2217 + d1*5352 + 12000)>>16 + "vshrn.s32 d1, q11, #16 \n" + // op[4] += (d1!=0) + "vsub.s16 d1, d1, d4 \n" + // op[12]= (d1*2217 - c1*5352 + 51000)>>16 + "vshrn.s32 d3, q12, #16 \n" + + // set result to out array + "vst1.16 {q0, q1}, [%[out]] \n" + : [src_ptr] "+r"(src_ptr), [ref_ptr] "+r"(ref_ptr), + [coeff32] "+r"(coeff32) // modified registers + : [kBPS] "r"(kBPS), [coeff16] "r"(coeff16), + [out] "r"(out) // constants + : "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", + "q10", "q11", "q12", "q13" // clobbered + ); +} + +static void FTransformWHT(const int16_t* in, int16_t* out) { + const int kStep = 32; + __asm__ volatile ( + // d0 = in[0 * 16] , d1 = in[1 * 16] + // d2 = in[2 * 16] , d3 = in[3 * 16] + "vld1.16 d0[0], [%[in]], %[kStep] \n" + "vld1.16 d1[0], [%[in]], %[kStep] \n" + "vld1.16 d2[0], [%[in]], %[kStep] \n" + "vld1.16 d3[0], [%[in]], %[kStep] \n" + "vld1.16 d0[1], [%[in]], %[kStep] \n" + "vld1.16 d1[1], [%[in]], %[kStep] \n" + "vld1.16 d2[1], [%[in]], %[kStep] \n" + "vld1.16 d3[1], [%[in]], %[kStep] \n" + "vld1.16 d0[2], [%[in]], %[kStep] \n" + "vld1.16 d1[2], [%[in]], %[kStep] \n" + "vld1.16 d2[2], [%[in]], %[kStep] \n" + "vld1.16 d3[2], [%[in]], %[kStep] \n" + "vld1.16 d0[3], [%[in]], %[kStep] \n" + "vld1.16 d1[3], [%[in]], %[kStep] \n" + "vld1.16 d2[3], [%[in]], %[kStep] \n" + "vld1.16 d3[3], [%[in]], %[kStep] \n" + + "vaddl.s16 q2, d0, d2 \n" // a0=(in[0*16]+in[2*16]) + "vaddl.s16 q3, d1, d3 \n" // a1=(in[1*16]+in[3*16]) + "vsubl.s16 q4, d1, d3 \n" // a2=(in[1*16]-in[3*16]) + "vsubl.s16 q5, d0, d2 \n" // a3=(in[0*16]-in[2*16]) + + "vqadd.s32 q6, q2, q3 \n" // a0 + a1 + "vqadd.s32 q7, q5, q4 \n" // a3 + a2 + "vqsub.s32 q8, q5, q4 \n" // a3 - a2 + "vqsub.s32 q9, q2, q3 \n" // a0 - a1 + + // Transpose + // q6 = tmp[0, 1, 2, 3] ; q7 = tmp[ 4, 5, 6, 7] + // q8 = tmp[8, 9, 10, 11] ; q9 = tmp[12, 13, 14, 15] + "vswp d13, d16 \n" // vtrn.64 q0, q2 + "vswp d15, d18 \n" // vtrn.64 q1, q3 + "vtrn.32 q6, q7 \n" + "vtrn.32 q8, q9 \n" + + "vqadd.s32 q0, q6, q8 \n" // a0 = tmp[0] + tmp[8] + "vqadd.s32 q1, q7, q9 \n" // a1 = tmp[4] + tmp[12] + "vqsub.s32 q2, q7, q9 \n" // a2 = tmp[4] - tmp[12] + "vqsub.s32 q3, q6, q8 \n" // a3 = tmp[0] - tmp[8] + + "vqadd.s32 q4, q0, q1 \n" // b0 = a0 + a1 + "vqadd.s32 q5, q3, q2 \n" // b1 = a3 + a2 + "vqsub.s32 q6, q3, q2 \n" // b2 = a3 - a2 + "vqsub.s32 q7, q0, q1 \n" // b3 = a0 - a1 + + "vshrn.s32 d18, q4, #1 \n" // b0 >> 1 + "vshrn.s32 d19, q5, #1 \n" // b1 >> 1 + "vshrn.s32 d20, q6, #1 \n" // b2 >> 1 + "vshrn.s32 d21, q7, #1 \n" // b3 >> 1 + + "vst1.16 {q9, q10}, [%[out]] \n" + + : [in] "+r"(in) + : [kStep] "r"(kStep), [out] "r"(out) + : "memory", "q0", "q1", "q2", "q3", "q4", "q5", + "q6", "q7", "q8", "q9", "q10" // clobbered + ) ; +} + +//------------------------------------------------------------------------------ +// Texture distortion +// +// We try to match the spectral content (weighted) between source and +// reconstructed samples. + +// Hadamard transform +// Returns the weighted sum of the absolute value of transformed coefficients. +// This uses a TTransform helper function in C +static int Disto4x4(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + const int kBPS = BPS; + const uint8_t* A = a; + const uint8_t* B = b; + const uint16_t* W = w; + int sum; + __asm__ volatile ( + "vld1.32 d0[0], [%[a]], %[kBPS] \n" + "vld1.32 d0[1], [%[a]], %[kBPS] \n" + "vld1.32 d2[0], [%[a]], %[kBPS] \n" + "vld1.32 d2[1], [%[a]] \n" + + "vld1.32 d1[0], [%[b]], %[kBPS] \n" + "vld1.32 d1[1], [%[b]], %[kBPS] \n" + "vld1.32 d3[0], [%[b]], %[kBPS] \n" + "vld1.32 d3[1], [%[b]] \n" + + // a d0/d2, b d1/d3 + // d0/d1: 01 01 01 01 + // d2/d3: 23 23 23 23 + // But: it goes 01 45 23 67 + // Notice the middle values are transposed + "vtrn.16 q0, q1 \n" + + // {a0, a1} = {in[0] + in[2], in[1] + in[3]} + "vaddl.u8 q2, d0, d2 \n" + "vaddl.u8 q10, d1, d3 \n" + // {a3, a2} = {in[0] - in[2], in[1] - in[3]} + "vsubl.u8 q3, d0, d2 \n" + "vsubl.u8 q11, d1, d3 \n" + + // tmp[0] = a0 + a1 + "vpaddl.s16 q0, q2 \n" + "vpaddl.s16 q8, q10 \n" + + // tmp[1] = a3 + a2 + "vpaddl.s16 q1, q3 \n" + "vpaddl.s16 q9, q11 \n" + + // No pair subtract + // q2 = {a0, a3} + // q3 = {a1, a2} + "vtrn.16 q2, q3 \n" + "vtrn.16 q10, q11 \n" + + // {tmp[3], tmp[2]} = {a0 - a1, a3 - a2} + "vsubl.s16 q12, d4, d6 \n" + "vsubl.s16 q13, d5, d7 \n" + "vsubl.s16 q14, d20, d22 \n" + "vsubl.s16 q15, d21, d23 \n" + + // separate tmp[3] and tmp[2] + // q12 = tmp[3] + // q13 = tmp[2] + "vtrn.32 q12, q13 \n" + "vtrn.32 q14, q15 \n" + + // Transpose tmp for a + "vswp d1, d26 \n" // vtrn.64 + "vswp d3, d24 \n" // vtrn.64 + "vtrn.32 q0, q1 \n" + "vtrn.32 q13, q12 \n" + + // Transpose tmp for b + "vswp d17, d30 \n" // vtrn.64 + "vswp d19, d28 \n" // vtrn.64 + "vtrn.32 q8, q9 \n" + "vtrn.32 q15, q14 \n" + + // The first Q register is a, the second b. + // q0/8 tmp[0-3] + // q13/15 tmp[4-7] + // q1/9 tmp[8-11] + // q12/14 tmp[12-15] + + // These are still in 01 45 23 67 order. We fix it easily in the addition + // case but the subtraction propegates them. + "vswp d3, d27 \n" + "vswp d19, d31 \n" + + // a0 = tmp[0] + tmp[8] + "vadd.s32 q2, q0, q1 \n" + "vadd.s32 q3, q8, q9 \n" + + // a1 = tmp[4] + tmp[12] + "vadd.s32 q10, q13, q12 \n" + "vadd.s32 q11, q15, q14 \n" + + // a2 = tmp[4] - tmp[12] + "vsub.s32 q13, q13, q12 \n" + "vsub.s32 q15, q15, q14 \n" + + // a3 = tmp[0] - tmp[8] + "vsub.s32 q0, q0, q1 \n" + "vsub.s32 q8, q8, q9 \n" + + // b0 = a0 + a1 + "vadd.s32 q1, q2, q10 \n" + "vadd.s32 q9, q3, q11 \n" + + // b1 = a3 + a2 + "vadd.s32 q12, q0, q13 \n" + "vadd.s32 q14, q8, q15 \n" + + // b2 = a3 - a2 + "vsub.s32 q0, q0, q13 \n" + "vsub.s32 q8, q8, q15 \n" + + // b3 = a0 - a1 + "vsub.s32 q2, q2, q10 \n" + "vsub.s32 q3, q3, q11 \n" + + "vld1.64 {q10, q11}, [%[w]] \n" + + // abs(b0) + "vabs.s32 q1, q1 \n" + "vabs.s32 q9, q9 \n" + // abs(b1) + "vabs.s32 q12, q12 \n" + "vabs.s32 q14, q14 \n" + // abs(b2) + "vabs.s32 q0, q0 \n" + "vabs.s32 q8, q8 \n" + // abs(b3) + "vabs.s32 q2, q2 \n" + "vabs.s32 q3, q3 \n" + + // expand w before using. + "vmovl.u16 q13, d20 \n" + "vmovl.u16 q15, d21 \n" + + // w[0] * abs(b0) + "vmul.u32 q1, q1, q13 \n" + "vmul.u32 q9, q9, q13 \n" + + // w[4] * abs(b1) + "vmla.u32 q1, q12, q15 \n" + "vmla.u32 q9, q14, q15 \n" + + // expand w before using. + "vmovl.u16 q13, d22 \n" + "vmovl.u16 q15, d23 \n" + + // w[8] * abs(b1) + "vmla.u32 q1, q0, q13 \n" + "vmla.u32 q9, q8, q13 \n" + + // w[12] * abs(b1) + "vmla.u32 q1, q2, q15 \n" + "vmla.u32 q9, q3, q15 \n" + + // Sum the arrays + "vpaddl.u32 q1, q1 \n" + "vpaddl.u32 q9, q9 \n" + "vadd.u64 d2, d3 \n" + "vadd.u64 d18, d19 \n" + + // Hadamard transform needs 4 bits of extra precision (2 bits in each + // direction) for dynamic raw. Weights w[] are 16bits at max, so the maximum + // precision for coeff is 8bit of input + 4bits of Hadamard transform + + // 16bits for w[] + 2 bits of abs() summation. + // + // This uses a maximum of 31 bits (signed). Discarding the top 32 bits is + // A-OK. + + // sum2 - sum1 + "vsub.u32 d0, d2, d18 \n" + // abs(sum2 - sum1) + "vabs.s32 d0, d0 \n" + // abs(sum2 - sum1) >> 5 + "vshr.u32 d0, #5 \n" + + // It would be better to move the value straight into r0 but I'm not + // entirely sure how this works with inline assembly. + "vmov.32 %[sum], d0[0] \n" + + : [sum] "=r"(sum), [a] "+r"(A), [b] "+r"(B), [w] "+r"(W) + : [kBPS] "r"(kBPS) + : "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", + "q10", "q11", "q12", "q13", "q14", "q15" // clobbered + ) ; + + return sum; +} + +static int Disto16x16(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + int D = 0; + int x, y; + for (y = 0; y < 16 * BPS; y += 4 * BPS) { + for (x = 0; x < 16; x += 4) { + D += Disto4x4(a + x + y, b + x + y, w); + } + } + return D; +} + +#endif // WEBP_USE_NEON + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspInitNEON(void); + +void VP8EncDspInitNEON(void) { +#if defined(WEBP_USE_NEON) + VP8ITransform = ITransform; + VP8FTransform = FTransform; + + VP8ITransformWHT = ITransformWHT; + VP8FTransformWHT = FTransformWHT; + + VP8TDisto4x4 = Disto4x4; + VP8TDisto16x16 = Disto16x16; +#endif // WEBP_USE_NEON +} + +#if defined(__cplusplus) || defined(c_plusplus) +} // extern "C" +#endif diff --git a/3rdparty/libwebp/dsp/enc_sse2.c b/3rdparty/libwebp/dsp/enc_sse2.c index 0986e82e31..032e990762 100644 --- a/3rdparty/libwebp/dsp/enc_sse2.c +++ b/3rdparty/libwebp/dsp/enc_sse2.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // SSE2 version of speed-critical encoding functions. @@ -21,17 +23,48 @@ extern "C" { #include "../enc/vp8enci.h" +//------------------------------------------------------------------------------ +// Quite useful macro for debugging. Left here for convenience. + +#if 0 +#include +static void PrintReg(const __m128i r, const char* const name, int size) { + int n; + union { + __m128i r; + uint8_t i8[16]; + uint16_t i16[8]; + uint32_t i32[4]; + uint64_t i64[2]; + } tmp; + tmp.r = r; + printf("%s\t: ", name); + if (size == 8) { + for (n = 0; n < 16; ++n) printf("%.2x ", tmp.i8[n]); + } else if (size == 16) { + for (n = 0; n < 8; ++n) printf("%.4x ", tmp.i16[n]); + } else if (size == 32) { + for (n = 0; n < 4; ++n) printf("%.8x ", tmp.i32[n]); + } else { + for (n = 0; n < 2; ++n) printf("%.16lx ", tmp.i64[n]); + } + printf("\n"); +} +#endif + //------------------------------------------------------------------------------ // Compute susceptibility based on DCT-coeff histograms: // the higher, the "easier" the macroblock is to compress. -static int CollectHistogramSSE2(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block) { - int histo[MAX_COEFF_THRESH + 1] = { 0 }; - int16_t out[16]; - int j, k; +static void CollectHistogramSSE2(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH); + int j; for (j = start_block; j < end_block; ++j) { + int16_t out[16]; + int k; + VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); // Convert coefficients to bin (within out[]). @@ -47,9 +80,9 @@ static int CollectHistogramSSE2(const uint8_t* ref, const uint8_t* pred, const __m128i xor1 = _mm_xor_si128(out1, sign1); const __m128i abs0 = _mm_sub_epi16(xor0, sign0); const __m128i abs1 = _mm_sub_epi16(xor1, sign1); - // v = abs(out) >> 2 - const __m128i v0 = _mm_srai_epi16(abs0, 2); - const __m128i v1 = _mm_srai_epi16(abs1, 2); + // v = abs(out) >> 3 + const __m128i v0 = _mm_srai_epi16(abs0, 3); + const __m128i v1 = _mm_srai_epi16(abs1, 3); // bin = min(v, MAX_COEFF_THRESH) const __m128i bin0 = _mm_min_epi16(v0, max_coeff_thresh); const __m128i bin1 = _mm_min_epi16(v1, max_coeff_thresh); @@ -58,13 +91,11 @@ static int CollectHistogramSSE2(const uint8_t* ref, const uint8_t* pred, _mm_storeu_si128((__m128i*)&out[8], bin1); } - // Use bin to update histogram. + // Convert coefficients to bin. for (k = 0; k < 16; ++k) { - histo[out[k]]++; + histo->distribution[out[k]]++; } } - - return VP8GetAlpha(histo); } //------------------------------------------------------------------------------ @@ -243,7 +274,7 @@ static void ITransformSSE2(const uint8_t* ref, const int16_t* in, uint8_t* dst, // Add inverse transform to 'ref' and store. { - const __m128i zero = _mm_set1_epi16(0); + const __m128i zero = _mm_setzero_si128(); // Load the reference(s). __m128i ref0, ref1, ref2, ref3; if (do_two) { @@ -295,17 +326,23 @@ static void FTransformSSE2(const uint8_t* src, const uint8_t* ref, int16_t* out) { const __m128i zero = _mm_setzero_si128(); const __m128i seven = _mm_set1_epi16(7); - const __m128i k7500 = _mm_set1_epi32(7500); - const __m128i k14500 = _mm_set1_epi32(14500); + const __m128i k937 = _mm_set1_epi32(937); + const __m128i k1812 = _mm_set1_epi32(1812); const __m128i k51000 = _mm_set1_epi32(51000); const __m128i k12000_plus_one = _mm_set1_epi32(12000 + (1 << 16)); const __m128i k5352_2217 = _mm_set_epi16(5352, 2217, 5352, 2217, 5352, 2217, 5352, 2217); const __m128i k2217_5352 = _mm_set_epi16(2217, -5352, 2217, -5352, 2217, -5352, 2217, -5352); - + const __m128i k88p = _mm_set_epi16(8, 8, 8, 8, 8, 8, 8, 8); + const __m128i k88m = _mm_set_epi16(-8, 8, -8, 8, -8, 8, -8, 8); + const __m128i k5352_2217p = _mm_set_epi16(2217, 5352, 2217, 5352, + 2217, 5352, 2217, 5352); + const __m128i k5352_2217m = _mm_set_epi16(-5352, 2217, -5352, 2217, + -5352, 2217, -5352, 2217); __m128i v01, v32; + // Difference between src and ref and initial transpose. { // Load src and convert to 16b. @@ -326,73 +363,52 @@ static void FTransformSSE2(const uint8_t* src, const uint8_t* ref, const __m128i ref_1 = _mm_unpacklo_epi8(ref1, zero); const __m128i ref_2 = _mm_unpacklo_epi8(ref2, zero); const __m128i ref_3 = _mm_unpacklo_epi8(ref3, zero); - // Compute difference. + // Compute difference. -> 00 01 02 03 00 00 00 00 const __m128i diff0 = _mm_sub_epi16(src_0, ref_0); const __m128i diff1 = _mm_sub_epi16(src_1, ref_1); const __m128i diff2 = _mm_sub_epi16(src_2, ref_2); const __m128i diff3 = _mm_sub_epi16(src_3, ref_3); - // Transpose. + + // Unpack and shuffle // 00 01 02 03 0 0 0 0 // 10 11 12 13 0 0 0 0 // 20 21 22 23 0 0 0 0 // 30 31 32 33 0 0 0 0 - const __m128i transpose0_0 = _mm_unpacklo_epi16(diff0, diff1); - const __m128i transpose0_1 = _mm_unpacklo_epi16(diff2, diff3); - // 00 10 01 11 02 12 03 13 - // 20 30 21 31 22 32 23 33 - const __m128i v23 = _mm_unpackhi_epi32(transpose0_0, transpose0_1); - v01 = _mm_unpacklo_epi32(transpose0_0, transpose0_1); - v32 = _mm_shuffle_epi32(v23, _MM_SHUFFLE(1, 0, 3, 2)); - // a02 a12 a22 a32 a03 a13 a23 a33 - // a00 a10 a20 a30 a01 a11 a21 a31 - // a03 a13 a23 a33 a02 a12 a22 a32 - } + const __m128i shuf01 = _mm_unpacklo_epi32(diff0, diff1); + const __m128i shuf23 = _mm_unpacklo_epi32(diff2, diff3); + // 00 01 10 11 02 03 12 13 + // 20 21 30 31 22 23 32 33 + const __m128i shuf01_p = + _mm_shufflehi_epi16(shuf01, _MM_SHUFFLE(2, 3, 0, 1)); + const __m128i shuf23_p = + _mm_shufflehi_epi16(shuf23, _MM_SHUFFLE(2, 3, 0, 1)); + // 00 01 10 11 03 02 13 12 + // 20 21 30 31 23 22 33 32 + const __m128i s01 = _mm_unpacklo_epi64(shuf01_p, shuf23_p); + const __m128i s32 = _mm_unpackhi_epi64(shuf01_p, shuf23_p); + // 00 01 10 11 20 21 30 31 + // 03 02 13 12 23 22 33 32 + const __m128i a01 = _mm_add_epi16(s01, s32); + const __m128i a32 = _mm_sub_epi16(s01, s32); + // [d0 + d3 | d1 + d2 | ...] = [a0 a1 | a0' a1' | ... ] + // [d0 - d3 | d1 - d2 | ...] = [a3 a2 | a3' a2' | ... ] - // First pass and subsequent transpose. - { - // Same operations are done on the (0,3) and (1,2) pairs. - // b0 = (a0 + a3) << 3 - // b1 = (a1 + a2) << 3 - // b3 = (a0 - a3) << 3 - // b2 = (a1 - a2) << 3 - const __m128i a01 = _mm_add_epi16(v01, v32); - const __m128i a32 = _mm_sub_epi16(v01, v32); - const __m128i b01 = _mm_slli_epi16(a01, 3); - const __m128i b32 = _mm_slli_epi16(a32, 3); - const __m128i b11 = _mm_unpackhi_epi64(b01, b01); - const __m128i b22 = _mm_unpackhi_epi64(b32, b32); - - // e0 = b0 + b1 - // e2 = b0 - b1 - const __m128i e0 = _mm_add_epi16(b01, b11); - const __m128i e2 = _mm_sub_epi16(b01, b11); - const __m128i e02 = _mm_unpacklo_epi64(e0, e2); - - // e1 = (b3 * 5352 + b2 * 2217 + 14500) >> 12 - // e3 = (b3 * 2217 - b2 * 5352 + 7500) >> 12 - const __m128i b23 = _mm_unpacklo_epi16(b22, b32); - const __m128i c1 = _mm_madd_epi16(b23, k5352_2217); - const __m128i c3 = _mm_madd_epi16(b23, k2217_5352); - const __m128i d1 = _mm_add_epi32(c1, k14500); - const __m128i d3 = _mm_add_epi32(c3, k7500); - const __m128i e1 = _mm_srai_epi32(d1, 12); - const __m128i e3 = _mm_srai_epi32(d3, 12); - const __m128i e13 = _mm_packs_epi32(e1, e3); - - // Transpose. - // 00 01 02 03 20 21 22 23 - // 10 11 12 13 30 31 32 33 - const __m128i transpose0_0 = _mm_unpacklo_epi16(e02, e13); - const __m128i transpose0_1 = _mm_unpackhi_epi16(e02, e13); - // 00 10 01 11 02 12 03 13 - // 20 30 21 31 22 32 23 33 - const __m128i v23 = _mm_unpackhi_epi32(transpose0_0, transpose0_1); - v01 = _mm_unpacklo_epi32(transpose0_0, transpose0_1); - v32 = _mm_shuffle_epi32(v23, _MM_SHUFFLE(1, 0, 3, 2)); - // 02 12 22 32 03 13 23 33 - // 00 10 20 30 01 11 21 31 - // 03 13 23 33 02 12 22 32 + const __m128i tmp0 = _mm_madd_epi16(a01, k88p); // [ (a0 + a1) << 3, ... ] + const __m128i tmp2 = _mm_madd_epi16(a01, k88m); // [ (a0 - a1) << 3, ... ] + const __m128i tmp1_1 = _mm_madd_epi16(a32, k5352_2217p); + const __m128i tmp3_1 = _mm_madd_epi16(a32, k5352_2217m); + const __m128i tmp1_2 = _mm_add_epi32(tmp1_1, k1812); + const __m128i tmp3_2 = _mm_add_epi32(tmp3_1, k937); + const __m128i tmp1 = _mm_srai_epi32(tmp1_2, 9); + const __m128i tmp3 = _mm_srai_epi32(tmp3_2, 9); + const __m128i s03 = _mm_packs_epi32(tmp0, tmp2); + const __m128i s12 = _mm_packs_epi32(tmp1, tmp3); + const __m128i s_lo = _mm_unpacklo_epi16(s03, s12); // 0 1 0 1 0 1... + const __m128i s_hi = _mm_unpackhi_epi16(s03, s12); // 2 3 2 3 2 3 + const __m128i v23 = _mm_unpackhi_epi32(s_lo, s_hi); + v01 = _mm_unpacklo_epi32(s_lo, s_hi); + v32 = _mm_shuffle_epi32(v23, _MM_SHUFFLE(1, 0, 3, 2)); // 3 2 3 2 3 2.. } // Second pass @@ -406,13 +422,12 @@ static void FTransformSSE2(const uint8_t* src, const uint8_t* ref, const __m128i a32 = _mm_sub_epi16(v01, v32); const __m128i a11 = _mm_unpackhi_epi64(a01, a01); const __m128i a22 = _mm_unpackhi_epi64(a32, a32); + const __m128i a01_plus_7 = _mm_add_epi16(a01, seven); // d0 = (a0 + a1 + 7) >> 4; // d2 = (a0 - a1 + 7) >> 4; - const __m128i b0 = _mm_add_epi16(a01, a11); - const __m128i b2 = _mm_sub_epi16(a01, a11); - const __m128i c0 = _mm_add_epi16(b0, seven); - const __m128i c2 = _mm_add_epi16(b2, seven); + const __m128i c0 = _mm_add_epi16(a01_plus_7, a11); + const __m128i c2 = _mm_sub_epi16(a01_plus_7, a11); const __m128i d0 = _mm_srai_epi16(c0, 4); const __m128i d2 = _mm_srai_epi16(c2, 4); @@ -430,6 +445,7 @@ static void FTransformSSE2(const uint8_t* src, const uint8_t* ref, // f1 = f1 + (a3 != 0); // The compare will return (0xffff, 0) for (==0, !=0). To turn that into the // desired (0, 1), we add one earlier through k12000_plus_one. + // -> f1 = f1 + 1 - (a3 == 0) const __m128i g1 = _mm_add_epi16(f1, _mm_cmpeq_epi16(a32, zero)); _mm_storel_epi64((__m128i*)&out[ 0], d0); @@ -439,13 +455,137 @@ static void FTransformSSE2(const uint8_t* src, const uint8_t* ref, } } +static void FTransformWHTSSE2(const int16_t* in, int16_t* out) { + int16_t tmp[16]; + int i; + for (i = 0; i < 4; ++i, in += 64) { + const int a0 = (in[0 * 16] + in[2 * 16]); + const int a1 = (in[1 * 16] + in[3 * 16]); + const int a2 = (in[1 * 16] - in[3 * 16]); + const int a3 = (in[0 * 16] - in[2 * 16]); + tmp[0 + i * 4] = a0 + a1; + tmp[1 + i * 4] = a3 + a2; + tmp[2 + i * 4] = a3 - a2; + tmp[3 + i * 4] = a0 - a1; + } + { + const __m128i src0 = _mm_loadl_epi64((__m128i*)&tmp[0]); + const __m128i src1 = _mm_loadl_epi64((__m128i*)&tmp[4]); + const __m128i src2 = _mm_loadl_epi64((__m128i*)&tmp[8]); + const __m128i src3 = _mm_loadl_epi64((__m128i*)&tmp[12]); + const __m128i a0 = _mm_add_epi16(src0, src2); + const __m128i a1 = _mm_add_epi16(src1, src3); + const __m128i a2 = _mm_sub_epi16(src1, src3); + const __m128i a3 = _mm_sub_epi16(src0, src2); + const __m128i b0 = _mm_srai_epi16(_mm_adds_epi16(a0, a1), 1); + const __m128i b1 = _mm_srai_epi16(_mm_adds_epi16(a3, a2), 1); + const __m128i b2 = _mm_srai_epi16(_mm_subs_epi16(a3, a2), 1); + const __m128i b3 = _mm_srai_epi16(_mm_subs_epi16(a0, a1), 1); + _mm_storel_epi64((__m128i*)&out[ 0], b0); + _mm_storel_epi64((__m128i*)&out[ 4], b1); + _mm_storel_epi64((__m128i*)&out[ 8], b2); + _mm_storel_epi64((__m128i*)&out[12], b3); + } +} + //------------------------------------------------------------------------------ // Metric -static int SSE4x4SSE2(const uint8_t* a, const uint8_t* b) { - const __m128i zero = _mm_set1_epi16(0); +static int SSE_Nx4SSE2(const uint8_t* a, const uint8_t* b, + int num_quads, int do_16) { + const __m128i zero = _mm_setzero_si128(); + __m128i sum1 = zero; + __m128i sum2 = zero; - // Load values. + while (num_quads-- > 0) { + // Note: for the !do_16 case, we read 16 pixels instead of 8 but that's ok, + // thanks to buffer over-allocation to that effect. + const __m128i a0 = _mm_loadu_si128((__m128i*)&a[BPS * 0]); + const __m128i a1 = _mm_loadu_si128((__m128i*)&a[BPS * 1]); + const __m128i a2 = _mm_loadu_si128((__m128i*)&a[BPS * 2]); + const __m128i a3 = _mm_loadu_si128((__m128i*)&a[BPS * 3]); + const __m128i b0 = _mm_loadu_si128((__m128i*)&b[BPS * 0]); + const __m128i b1 = _mm_loadu_si128((__m128i*)&b[BPS * 1]); + const __m128i b2 = _mm_loadu_si128((__m128i*)&b[BPS * 2]); + const __m128i b3 = _mm_loadu_si128((__m128i*)&b[BPS * 3]); + + // compute clip0(a-b) and clip0(b-a) + const __m128i a0p = _mm_subs_epu8(a0, b0); + const __m128i a0m = _mm_subs_epu8(b0, a0); + const __m128i a1p = _mm_subs_epu8(a1, b1); + const __m128i a1m = _mm_subs_epu8(b1, a1); + const __m128i a2p = _mm_subs_epu8(a2, b2); + const __m128i a2m = _mm_subs_epu8(b2, a2); + const __m128i a3p = _mm_subs_epu8(a3, b3); + const __m128i a3m = _mm_subs_epu8(b3, a3); + + // compute |a-b| with 8b arithmetic as clip0(a-b) | clip0(b-a) + const __m128i diff0 = _mm_or_si128(a0p, a0m); + const __m128i diff1 = _mm_or_si128(a1p, a1m); + const __m128i diff2 = _mm_or_si128(a2p, a2m); + const __m128i diff3 = _mm_or_si128(a3p, a3m); + + // unpack (only four operations, instead of eight) + const __m128i low0 = _mm_unpacklo_epi8(diff0, zero); + const __m128i low1 = _mm_unpacklo_epi8(diff1, zero); + const __m128i low2 = _mm_unpacklo_epi8(diff2, zero); + const __m128i low3 = _mm_unpacklo_epi8(diff3, zero); + + // multiply with self + const __m128i low_madd0 = _mm_madd_epi16(low0, low0); + const __m128i low_madd1 = _mm_madd_epi16(low1, low1); + const __m128i low_madd2 = _mm_madd_epi16(low2, low2); + const __m128i low_madd3 = _mm_madd_epi16(low3, low3); + + // collect in a cascading way + const __m128i low_sum0 = _mm_add_epi32(low_madd0, low_madd1); + const __m128i low_sum1 = _mm_add_epi32(low_madd2, low_madd3); + sum1 = _mm_add_epi32(sum1, low_sum0); + sum2 = _mm_add_epi32(sum2, low_sum1); + + if (do_16) { // if necessary, process the higher 8 bytes similarly + const __m128i hi0 = _mm_unpackhi_epi8(diff0, zero); + const __m128i hi1 = _mm_unpackhi_epi8(diff1, zero); + const __m128i hi2 = _mm_unpackhi_epi8(diff2, zero); + const __m128i hi3 = _mm_unpackhi_epi8(diff3, zero); + + const __m128i hi_madd0 = _mm_madd_epi16(hi0, hi0); + const __m128i hi_madd1 = _mm_madd_epi16(hi1, hi1); + const __m128i hi_madd2 = _mm_madd_epi16(hi2, hi2); + const __m128i hi_madd3 = _mm_madd_epi16(hi3, hi3); + const __m128i hi_sum0 = _mm_add_epi32(hi_madd0, hi_madd1); + const __m128i hi_sum1 = _mm_add_epi32(hi_madd2, hi_madd3); + sum1 = _mm_add_epi32(sum1, hi_sum0); + sum2 = _mm_add_epi32(sum2, hi_sum1); + } + a += 4 * BPS; + b += 4 * BPS; + } + { + int32_t tmp[4]; + const __m128i sum = _mm_add_epi32(sum1, sum2); + _mm_storeu_si128((__m128i*)tmp, sum); + return (tmp[3] + tmp[2] + tmp[1] + tmp[0]); + } +} + +static int SSE16x16SSE2(const uint8_t* a, const uint8_t* b) { + return SSE_Nx4SSE2(a, b, 4, 1); +} + +static int SSE16x8SSE2(const uint8_t* a, const uint8_t* b) { + return SSE_Nx4SSE2(a, b, 2, 1); +} + +static int SSE8x8SSE2(const uint8_t* a, const uint8_t* b) { + return SSE_Nx4SSE2(a, b, 2, 0); +} + +static int SSE4x4SSE2(const uint8_t* a, const uint8_t* b) { + const __m128i zero = _mm_setzero_si128(); + + // Load values. Note that we read 8 pixels instead of 4, + // but the a/b buffers are over-allocated to that effect. const __m128i a0 = _mm_loadl_epi64((__m128i*)&a[BPS * 0]); const __m128i a1 = _mm_loadl_epi64((__m128i*)&a[BPS * 1]); const __m128i a2 = _mm_loadl_epi64((__m128i*)&a[BPS * 2]); @@ -483,6 +623,7 @@ static int SSE4x4SSE2(const uint8_t* a, const uint8_t* b) { const __m128i sum0 = _mm_add_epi32(madd0, madd1); const __m128i sum1 = _mm_add_epi32(madd2, madd3); const __m128i sum2 = _mm_add_epi32(sum0, sum1); + int32_t tmp[4]; _mm_storeu_si128((__m128i*)tmp, sum2); return (tmp[3] + tmp[2] + tmp[1] + tmp[0]); @@ -502,8 +643,6 @@ static int TTransformSSE2(const uint8_t* inA, const uint8_t* inB, int32_t sum[4]; __m128i tmp_0, tmp_1, tmp_2, tmp_3; const __m128i zero = _mm_setzero_si128(); - const __m128i one = _mm_set1_epi16(1); - const __m128i three = _mm_set1_epi16(3); // Load, combine and tranpose inputs. { @@ -550,17 +689,14 @@ static int TTransformSSE2(const uint8_t* inA, const uint8_t* inB, // Horizontal pass and subsequent transpose. { // Calculate a and b (two 4x4 at once). - const __m128i a0 = _mm_slli_epi16(_mm_add_epi16(tmp_0, tmp_2), 2); - const __m128i a1 = _mm_slli_epi16(_mm_add_epi16(tmp_1, tmp_3), 2); - const __m128i a2 = _mm_slli_epi16(_mm_sub_epi16(tmp_1, tmp_3), 2); - const __m128i a3 = _mm_slli_epi16(_mm_sub_epi16(tmp_0, tmp_2), 2); - // b0_extra = (a0 != 0); - const __m128i b0_extra = _mm_andnot_si128(_mm_cmpeq_epi16 (a0, zero), one); - const __m128i b0_base = _mm_add_epi16(a0, a1); + const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2); + const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3); + const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3); + const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2); + const __m128i b0 = _mm_add_epi16(a0, a1); const __m128i b1 = _mm_add_epi16(a3, a2); const __m128i b2 = _mm_sub_epi16(a3, a2); const __m128i b3 = _mm_sub_epi16(a0, a1); - const __m128i b0 = _mm_add_epi16(b0_base, b0_extra); // a00 a01 a02 a03 b00 b01 b02 b03 // a10 a11 a12 a13 b10 b11 b12 b13 // a20 a21 a22 a23 b20 b21 b22 b23 @@ -635,19 +771,6 @@ static int TTransformSSE2(const uint8_t* inA, const uint8_t* inB, B_b2 = _mm_sub_epi16(B_b2, sign_B_b2); } - // b = abs(b) + 3 - A_b0 = _mm_add_epi16(A_b0, three); - A_b2 = _mm_add_epi16(A_b2, three); - B_b0 = _mm_add_epi16(B_b0, three); - B_b2 = _mm_add_epi16(B_b2, three); - - // abs((b + (b<0) + 3) >> 3) = (abs(b) + 3) >> 3 - // b = (abs(b) + 3) >> 3 - A_b0 = _mm_srai_epi16(A_b0, 3); - A_b2 = _mm_srai_epi16(A_b2, 3); - B_b0 = _mm_srai_epi16(B_b0, 3); - B_b2 = _mm_srai_epi16(B_b2, 3); - // weighted sums A_b0 = _mm_madd_epi16(A_b0, w_0); A_b2 = _mm_madd_epi16(A_b2, w_8); @@ -666,7 +789,7 @@ static int TTransformSSE2(const uint8_t* inA, const uint8_t* inB, static int Disto4x4SSE2(const uint8_t* const a, const uint8_t* const b, const uint16_t* const w) { const int diff_sum = TTransformSSE2(a, b, w); - return (abs(diff_sum) + 8) >> 4; + return abs(diff_sum) >> 5; } static int Disto16x16SSE2(const uint8_t* const a, const uint8_t* const b, @@ -681,7 +804,6 @@ static int Disto16x16SSE2(const uint8_t* const a, const uint8_t* const b, return D; } - //------------------------------------------------------------------------------ // Quantization // @@ -689,9 +811,8 @@ static int Disto16x16SSE2(const uint8_t* const a, const uint8_t* const b, // Simple quantization static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16], int n, const VP8Matrix* const mtx) { - const __m128i max_coeff_2047 = _mm_set1_epi16(2047); - const __m128i zero = _mm_set1_epi16(0); - __m128i sign0, sign8; + const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL); + const __m128i zero = _mm_setzero_si128(); __m128i coeff0, coeff8; __m128i out0, out8; __m128i packed_out; @@ -713,8 +834,8 @@ static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16], const __m128i zthresh8 = _mm_loadu_si128((__m128i*)&mtx->zthresh_[8]); // sign(in) = in >> 15 (0x0000 if positive, 0xffff if negative) - sign0 = _mm_srai_epi16(in0, 15); - sign8 = _mm_srai_epi16(in8, 15); + const __m128i sign0 = _mm_srai_epi16(in0, 15); + const __m128i sign8 = _mm_srai_epi16(in8, 15); // coeff = abs(in) = (in ^ sign) - sign coeff0 = _mm_xor_si128(in0, sign0); @@ -726,10 +847,6 @@ static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16], coeff0 = _mm_add_epi16(coeff0, sharpen0); coeff8 = _mm_add_epi16(coeff8, sharpen8); - // if (coeff > 2047) coeff = 2047 - coeff0 = _mm_min_epi16(coeff0, max_coeff_2047); - coeff8 = _mm_min_epi16(coeff8, max_coeff_2047); - // out = (coeff * iQ + B) >> QFIX; { // doing calculations with 32b precision (QFIX=17) @@ -757,9 +874,14 @@ static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16], out_04 = _mm_srai_epi32(out_04, QFIX); out_08 = _mm_srai_epi32(out_08, QFIX); out_12 = _mm_srai_epi32(out_12, QFIX); + // pack result as 16b out0 = _mm_packs_epi32(out_00, out_04); out8 = _mm_packs_epi32(out_08, out_12); + + // if (coeff > 2047) coeff = 2047 + out0 = _mm_min_epi16(out0, max_coeff_2047); + out8 = _mm_min_epi16(out8, max_coeff_2047); } // get sign back (if (sign[j]) out_n = -out_n) @@ -832,6 +954,10 @@ void VP8EncDspInitSSE2(void) { VP8EncQuantizeBlock = QuantizeBlockSSE2; VP8ITransform = ITransformSSE2; VP8FTransform = FTransformSSE2; + VP8FTransformWHT = FTransformWHTSSE2; + VP8SSE16x16 = SSE16x16SSE2; + VP8SSE16x8 = SSE16x8SSE2; + VP8SSE8x8 = SSE8x8SSE2; VP8SSE4x4 = SSE4x4SSE2; VP8TDisto4x4 = Disto4x4SSE2; VP8TDisto16x16 = Disto16x16SSE2; diff --git a/3rdparty/libwebp/dsp/lossless.c b/3rdparty/libwebp/dsp/lossless.c index 62a6b7b15a..e445924ed3 100644 --- a/3rdparty/libwebp/dsp/lossless.c +++ b/3rdparty/libwebp/dsp/lossless.c @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Image transforms and color space conversion methods for lossless decoder. @@ -11,25 +13,31 @@ // Jyrki Alakuijala (jyrki@google.com) // Urvang Joshi (urvang@google.com) +#include "./dsp.h" + +// Define the following if target arch is sure to have SSE2 +// #define WEBP_TARGET_HAS_SSE2 + #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif +#if defined(WEBP_TARGET_HAS_SSE2) +#include +#endif + #include #include #include "./lossless.h" #include "../dec/vp8li.h" -#include "../dsp/yuv.h" -#include "../dsp/dsp.h" -#include "../enc/histogram.h" +#include "./yuv.h" #define MAX_DIFF_COST (1e30f) // lookup table for small values of log2(int) #define APPROX_LOG_MAX 4096 #define LOG_2_RECIPROCAL 1.44269504088896338700465094007086 -#define LOG_LOOKUP_IDX_MAX 256 -static const float kLog2Table[LOG_LOOKUP_IDX_MAX] = { +const float kLog2Table[LOG_LOOKUP_IDX_MAX] = { 0.0000000000000000f, 0.0000000000000000f, 1.0000000000000000f, 1.5849625007211560f, 2.0000000000000000f, 2.3219280948873621f, @@ -160,16 +168,97 @@ static const float kLog2Table[LOG_LOOKUP_IDX_MAX] = { 7.9886846867721654f, 7.9943534368588577f }; -float VP8LFastLog2(int v) { - if (v < LOG_LOOKUP_IDX_MAX) { - return kLog2Table[v]; - } else if (v < APPROX_LOG_MAX) { +const float kSLog2Table[LOG_LOOKUP_IDX_MAX] = { + 0.00000000f, 0.00000000f, 2.00000000f, 4.75488750f, + 8.00000000f, 11.60964047f, 15.50977500f, 19.65148445f, + 24.00000000f, 28.52932501f, 33.21928095f, 38.05374781f, + 43.01955001f, 48.10571634f, 53.30296891f, 58.60335893f, + 64.00000000f, 69.48686830f, 75.05865003f, 80.71062276f, + 86.43856190f, 92.23866588f, 98.10749561f, 104.04192499f, + 110.03910002f, 116.09640474f, 122.21143267f, 128.38196256f, + 134.60593782f, 140.88144886f, 147.20671787f, 153.58008562f, + 160.00000000f, 166.46500594f, 172.97373660f, 179.52490559f, + 186.11730005f, 192.74977453f, 199.42124551f, 206.13068654f, + 212.87712380f, 219.65963219f, 226.47733176f, 233.32938445f, + 240.21499122f, 247.13338933f, 254.08384998f, 261.06567603f, + 268.07820003f, 275.12078236f, 282.19280949f, 289.29369244f, + 296.42286534f, 303.57978409f, 310.76392512f, 317.97478424f, + 325.21187564f, 332.47473081f, 339.76289772f, 347.07593991f, + 354.41343574f, 361.77497759f, 369.16017124f, 376.56863518f, + 384.00000000f, 391.45390785f, 398.93001188f, 406.42797576f, + 413.94747321f, 421.48818752f, 429.04981119f, 436.63204548f, + 444.23460010f, 451.85719280f, 459.49954906f, 467.16140179f, + 474.84249102f, 482.54256363f, 490.26137307f, 497.99867911f, + 505.75424759f, 513.52785023f, 521.31926438f, 529.12827280f, + 536.95466351f, 544.79822957f, 552.65876890f, 560.53608414f, + 568.42998244f, 576.34027536f, 584.26677867f, 592.20931226f, + 600.16769996f, 608.14176943f, 616.13135206f, 624.13628279f, + 632.15640007f, 640.19154569f, 648.24156472f, 656.30630539f, + 664.38561898f, 672.47935976f, 680.58738488f, 688.70955430f, + 696.84573069f, 704.99577935f, 713.15956818f, 721.33696754f, + 729.52785023f, 737.73209140f, 745.94956849f, 754.18016116f, + 762.42375127f, 770.68022275f, 778.94946161f, 787.23135586f, + 795.52579543f, 803.83267219f, 812.15187982f, 820.48331383f, + 828.82687147f, 837.18245171f, 845.54995518f, 853.92928416f, + 862.32034249f, 870.72303558f, 879.13727036f, 887.56295522f, + 896.00000000f, 904.44831595f, 912.90781569f, 921.37841320f, + 929.86002376f, 938.35256392f, 946.85595152f, 955.37010560f, + 963.89494641f, 972.43039537f, 980.97637504f, 989.53280911f, + 998.09962237f, 1006.67674069f, 1015.26409097f, 1023.86160116f, + 1032.46920021f, 1041.08681805f, 1049.71438560f, 1058.35183469f, + 1066.99909811f, 1075.65610955f, 1084.32280357f, 1092.99911564f, + 1101.68498204f, 1110.38033993f, 1119.08512727f, 1127.79928282f, + 1136.52274614f, 1145.25545758f, 1153.99735821f, 1162.74838989f, + 1171.50849518f, 1180.27761738f, 1189.05570047f, 1197.84268914f, + 1206.63852876f, 1215.44316535f, 1224.25654560f, 1233.07861684f, + 1241.90932703f, 1250.74862473f, 1259.59645914f, 1268.45278005f, + 1277.31753781f, 1286.19068338f, 1295.07216828f, 1303.96194457f, + 1312.85996488f, 1321.76618236f, 1330.68055071f, 1339.60302413f, + 1348.53355734f, 1357.47210556f, 1366.41862452f, 1375.37307041f, + 1384.33539991f, 1393.30557020f, 1402.28353887f, 1411.26926400f, + 1420.26270412f, 1429.26381818f, 1438.27256558f, 1447.28890615f, + 1456.31280014f, 1465.34420819f, 1474.38309138f, 1483.42941118f, + 1492.48312945f, 1501.54420843f, 1510.61261078f, 1519.68829949f, + 1528.77123795f, 1537.86138993f, 1546.95871952f, 1556.06319119f, + 1565.17476976f, 1574.29342040f, 1583.41910860f, 1592.55180020f, + 1601.69146137f, 1610.83805860f, 1619.99155871f, 1629.15192882f, + 1638.31913637f, 1647.49314911f, 1656.67393509f, 1665.86146266f, + 1675.05570047f, 1684.25661744f, 1693.46418280f, 1702.67836605f, + 1711.89913698f, 1721.12646563f, 1730.36032233f, 1739.60067768f, + 1748.84750254f, 1758.10076802f, 1767.36044551f, 1776.62650662f, + 1785.89892323f, 1795.17766747f, 1804.46271172f, 1813.75402857f, + 1823.05159087f, 1832.35537170f, 1841.66534438f, 1850.98148244f, + 1860.30375965f, 1869.63214999f, 1878.96662767f, 1888.30716711f, + 1897.65374295f, 1907.00633003f, 1916.36490342f, 1925.72943838f, + 1935.09991037f, 1944.47629506f, 1953.85856831f, 1963.24670620f, + 1972.64068498f, 1982.04048108f, 1991.44607117f, 2000.85743204f, + 2010.27454072f, 2019.69737440f, 2029.12591044f, 2038.56012640f +}; + +float VP8LFastSLog2Slow(int v) { + assert(v >= LOG_LOOKUP_IDX_MAX); + if (v < APPROX_LOG_MAX) { + int log_cnt = 0; + const float v_f = (float)v; + while (v >= LOG_LOOKUP_IDX_MAX) { + ++log_cnt; + v = v >> 1; + } + return v_f * (kLog2Table[v] + log_cnt); + } else { + return (float)(LOG_2_RECIPROCAL * v * log((double)v)); + } +} + +float VP8LFastLog2Slow(int v) { + assert(v >= LOG_LOOKUP_IDX_MAX); + if (v < APPROX_LOG_MAX) { int log_cnt = 0; while (v >= LOG_LOOKUP_IDX_MAX) { ++log_cnt; v = v >> 1; } - return kLog2Table[v] + (float)log_cnt; + return kLog2Table[v] + log_cnt; } else { return (float)(LOG_2_RECIPROCAL * log((double)v)); } @@ -198,6 +287,61 @@ static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, return Average2(Average2(a0, a1), Average2(a2, a3)); } +#if defined(WEBP_TARGET_HAS_SSE2) +static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1, + uint32_t c2) { + const __m128i zero = _mm_setzero_si128(); + const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c0), zero); + const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c1), zero); + const __m128i C2 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c2), zero); + const __m128i V1 = _mm_add_epi16(C0, C1); + const __m128i V2 = _mm_sub_epi16(V1, C2); + const __m128i b = _mm_packus_epi16(V2, V2); + const uint32_t output = _mm_cvtsi128_si32(b); + return output; +} + +static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1, + uint32_t c2) { + const uint32_t ave = Average2(c0, c1); + const __m128i zero = _mm_setzero_si128(); + const __m128i A0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(ave), zero); + const __m128i B0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c2), zero); + const __m128i A1 = _mm_sub_epi16(A0, B0); + const __m128i BgtA = _mm_cmpgt_epi16(B0, A0); + const __m128i A2 = _mm_sub_epi16(A1, BgtA); + const __m128i A3 = _mm_srai_epi16(A2, 1); + const __m128i A4 = _mm_add_epi16(A0, A3); + const __m128i A5 = _mm_packus_epi16(A4, A4); + const uint32_t output = _mm_cvtsi128_si32(A5); + return output; +} + +static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) { + int pa_minus_pb; + const __m128i zero = _mm_setzero_si128(); + const __m128i A0 = _mm_cvtsi32_si128(a); + const __m128i B0 = _mm_cvtsi32_si128(b); + const __m128i C0 = _mm_cvtsi32_si128(c); + const __m128i AC0 = _mm_subs_epu8(A0, C0); + const __m128i CA0 = _mm_subs_epu8(C0, A0); + const __m128i BC0 = _mm_subs_epu8(B0, C0); + const __m128i CB0 = _mm_subs_epu8(C0, B0); + const __m128i AC = _mm_or_si128(AC0, CA0); + const __m128i BC = _mm_or_si128(BC0, CB0); + const __m128i pa = _mm_unpacklo_epi8(AC, zero); // |a - c| + const __m128i pb = _mm_unpacklo_epi8(BC, zero); // |b - c| + const __m128i diff = _mm_sub_epi16(pb, pa); + { + int16_t out[8]; + _mm_storeu_si128((__m128i*)out, diff); + pa_minus_pb = out[0] + out[1] + out[2] + out[3]; + } + return (pa_minus_pb <= 0) ? a : b; +} + +#else + static WEBP_INLINE uint32_t Clip255(uint32_t a) { if (a < 256) { return a; @@ -239,9 +383,9 @@ static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1, } static WEBP_INLINE int Sub3(int a, int b, int c) { - const int pa = b - c; - const int pb = a - c; - return abs(pa) - abs(pb); + const int pb = b - c; + const int pa = a - c; + return abs(pb) - abs(pa); } static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) { @@ -250,9 +394,9 @@ static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) { Sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) + Sub3((a >> 8) & 0xff, (b >> 8) & 0xff, (c >> 8) & 0xff) + Sub3((a ) & 0xff, (b ) & 0xff, (c ) & 0xff); - return (pa_minus_pb <= 0) ? a : b; } +#endif //------------------------------------------------------------------------------ // Predictors @@ -340,35 +484,36 @@ static float PredictionCostSpatial(const int* counts, return (float)(-0.1 * bits); } -// Compute the Shanon's entropy: Sum(p*log2(p)) -static float ShannonEntropy(const int* const array, int n) { +// Compute the combined Shanon's entropy for distribution {X} and {X+Y} +static float CombinedShannonEntropy(const int* const X, + const int* const Y, int n) { int i; - float retval = 0.f; - int sum = 0; + double retval = 0.; + int sumX = 0, sumXY = 0; for (i = 0; i < n; ++i) { - if (array[i] != 0) { - sum += array[i]; - retval -= VP8LFastSLog2(array[i]); + const int x = X[i]; + const int xy = X[i] + Y[i]; + if (x != 0) { + sumX += x; + retval -= VP8LFastSLog2(x); + } + if (xy != 0) { + sumXY += xy; + retval -= VP8LFastSLog2(xy); } } - retval += VP8LFastSLog2(sum); - return retval; + retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY); + return (float)retval; } static float PredictionCostSpatialHistogram(int accumulated[4][256], int tile[4][256]) { int i; - int k; - int combo[256]; double retval = 0; for (i = 0; i < 4; ++i) { - const double exp_val = 0.94; - retval += PredictionCostSpatial(&tile[i][0], 1, exp_val); - retval += ShannonEntropy(&tile[i][0], 256); - for (k = 0; k < 256; ++k) { - combo[k] = accumulated[i][k] + tile[i][k]; - } - retval += ShannonEntropy(&combo[0], 256); + const double kExpValue = 0.94; + retval += PredictionCostSpatial(tile[i], 1, kExpValue); + retval += CombinedShannonEntropy(tile[i], accumulated[i], 256); } return (float)retval; } @@ -572,8 +717,21 @@ static void PredictorInverseTransform(const VP8LTransform* const transform, } void VP8LSubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixs) { - int i; - for (i = 0; i < num_pixs; ++i) { + int i = 0; +#if defined(WEBP_TARGET_HAS_SSE2) + const __m128i mask = _mm_set1_epi32(0x0000ff00); + for (; i + 4 < num_pixs; i += 4) { + const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); + const __m128i in_00g0 = _mm_and_si128(in, mask); // 00g0|00g0|... + const __m128i in_0g00 = _mm_slli_epi32(in_00g0, 8); // 0g00|0g00|... + const __m128i in_000g = _mm_srli_epi32(in_00g0, 8); // 000g|000g|... + const __m128i in_0g0g = _mm_or_si128(in_0g00, in_000g); + const __m128i out = _mm_sub_epi8(in, in_0g0g); + _mm_storeu_si128((__m128i*)&argb_data[i], out); + } + // fallthrough and finish off with plain-C +#endif + for (; i < num_pixs; ++i) { const uint32_t argb = argb_data[i]; const uint32_t green = (argb >> 8) & 0xff; const uint32_t new_r = (((argb >> 16) & 0xff) - green) & 0xff; @@ -588,9 +746,21 @@ static void AddGreenToBlueAndRed(const VP8LTransform* const transform, int y_start, int y_end, uint32_t* data) { const int width = transform->xsize_; const uint32_t* const data_end = data + (y_end - y_start) * width; +#if defined(WEBP_TARGET_HAS_SSE2) + const __m128i mask = _mm_set1_epi32(0x0000ff00); + for (; data + 4 < data_end; data += 4) { + const __m128i in = _mm_loadu_si128((__m128i*)data); + const __m128i in_00g0 = _mm_and_si128(in, mask); // 00g0|00g0|... + const __m128i in_0g00 = _mm_slli_epi32(in_00g0, 8); // 0g00|0g00|... + const __m128i in_000g = _mm_srli_epi32(in_00g0, 8); // 000g|000g|... + const __m128i in_0g0g = _mm_or_si128(in_0g00, in_000g); + const __m128i out = _mm_add_epi8(in, in_0g0g); + _mm_storeu_si128((__m128i*)data, out); + } + // fallthrough and finish off with plain-C +#endif while (data < data_end) { const uint32_t argb = *data; - // "* 0001001u" is equivalent to "(green << 16) + green)" const uint32_t green = ((argb >> 8) & 0xff); uint32_t red_blue = (argb & 0x00ff00ffu); red_blue += (green << 16) | green; @@ -655,6 +825,25 @@ static WEBP_INLINE uint32_t TransformColor(const Multipliers* const m, return (argb & 0xff00ff00u) | (new_red << 16) | (new_blue); } +static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red, + uint32_t argb) { + const uint32_t green = argb >> 8; + uint32_t new_red = argb >> 16; + new_red -= ColorTransformDelta(green_to_red, green); + return (new_red & 0xff); +} + +static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue, + uint8_t red_to_blue, + uint32_t argb) { + const uint32_t green = argb >> 8; + const uint32_t red = argb >> 16; + uint8_t new_blue = argb; + new_blue -= ColorTransformDelta(green_to_blue, green); + new_blue -= ColorTransformDelta(red_to_blue, red); + return (new_blue & 0xff); +} + static WEBP_INLINE int SkipRepeatedPixels(const uint32_t* const argb, int ix, int xsize) { const uint32_t v = argb[ix]; @@ -675,14 +864,10 @@ static WEBP_INLINE int SkipRepeatedPixels(const uint32_t* const argb, static float PredictionCostCrossColor(const int accumulated[256], const int counts[256]) { // Favor low entropy, locally and globally. - int i; - int combo[256]; - for (i = 0; i < 256; ++i) { - combo[i] = accumulated[i] + counts[i]; - } - return ShannonEntropy(combo, 256) + - ShannonEntropy(counts, 256) + - PredictionCostSpatial(counts, 3, 2.4); // Favor small absolute values. + // Favor small absolute values for PredictionCostSpatial + static const double kExpValue = 2.4; + return CombinedShannonEntropy(counts, accumulated, 256) + + PredictionCostSpatial(counts, 3, kExpValue); } static Multipliers GetBestColorTransformForTile( @@ -712,85 +897,75 @@ static Multipliers GetBestColorTransformForTile( if (all_y_max > ysize) { all_y_max = ysize; } + for (green_to_red = -64; green_to_red <= 64; green_to_red += halfstep) { int histo[256] = { 0 }; int all_y; - Multipliers tx; - MultipliersClear(&tx); - tx.green_to_red_ = green_to_red & 0xff; for (all_y = tile_y_offset; all_y < all_y_max; ++all_y) { - uint32_t predict; int ix = all_y * xsize + tile_x_offset; int all_x; for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) { if (SkipRepeatedPixels(argb, ix, xsize)) { continue; } - predict = TransformColor(&tx, argb[ix], 0); - ++histo[(predict >> 16) & 0xff]; // red. + ++histo[TransformColorRed(green_to_red, argb[ix])]; // red. } } cur_diff = PredictionCostCrossColor(&accumulated_red_histo[0], &histo[0]); - if (tx.green_to_red_ == prevX.green_to_red_) { + if ((uint8_t)green_to_red == prevX.green_to_red_) { cur_diff -= 3; // favor keeping the areas locally similar } - if (tx.green_to_red_ == prevY.green_to_red_) { + if ((uint8_t)green_to_red == prevY.green_to_red_) { cur_diff -= 3; // favor keeping the areas locally similar } - if (tx.green_to_red_ == 0) { + if (green_to_red == 0) { cur_diff -= 3; } if (cur_diff < best_diff) { best_diff = cur_diff; - best_tx = tx; + best_tx.green_to_red_ = green_to_red; } } best_diff = MAX_DIFF_COST; - green_to_red = best_tx.green_to_red_; for (green_to_blue = -32; green_to_blue <= 32; green_to_blue += step) { for (red_to_blue = -32; red_to_blue <= 32; red_to_blue += step) { int all_y; int histo[256] = { 0 }; - Multipliers tx; - tx.green_to_red_ = green_to_red; - tx.green_to_blue_ = green_to_blue; - tx.red_to_blue_ = red_to_blue; for (all_y = tile_y_offset; all_y < all_y_max; ++all_y) { - uint32_t predict; int all_x; int ix = all_y * xsize + tile_x_offset; for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) { if (SkipRepeatedPixels(argb, ix, xsize)) { continue; } - predict = TransformColor(&tx, argb[ix], 0); - ++histo[predict & 0xff]; // blue. + ++histo[TransformColorBlue(green_to_blue, red_to_blue, argb[ix])]; } } cur_diff = - PredictionCostCrossColor(&accumulated_blue_histo[0], &histo[0]); - if (tx.green_to_blue_ == prevX.green_to_blue_) { + PredictionCostCrossColor(&accumulated_blue_histo[0], &histo[0]); + if ((uint8_t)green_to_blue == prevX.green_to_blue_) { cur_diff -= 3; // favor keeping the areas locally similar } - if (tx.green_to_blue_ == prevY.green_to_blue_) { + if ((uint8_t)green_to_blue == prevY.green_to_blue_) { cur_diff -= 3; // favor keeping the areas locally similar } - if (tx.red_to_blue_ == prevX.red_to_blue_) { + if ((uint8_t)red_to_blue == prevX.red_to_blue_) { cur_diff -= 3; // favor keeping the areas locally similar } - if (tx.red_to_blue_ == prevY.red_to_blue_) { + if ((uint8_t)red_to_blue == prevY.red_to_blue_) { cur_diff -= 3; // favor keeping the areas locally similar } - if (tx.green_to_blue_ == 0) { + if (green_to_blue == 0) { cur_diff -= 3; } - if (tx.red_to_blue_ == 0) { + if (red_to_blue == 0) { cur_diff -= 3; } if (cur_diff < best_diff) { best_diff = cur_diff; - best_tx = tx; + best_tx.green_to_blue_ = green_to_blue; + best_tx.red_to_blue_ = red_to_blue; } } } @@ -920,39 +1095,64 @@ static void ColorSpaceInverseTransform(const VP8LTransform* const transform, } // Separate out pixels packed together using pixel-bundling. -static void ColorIndexInverseTransform( - const VP8LTransform* const transform, - int y_start, int y_end, const uint32_t* src, uint32_t* dst) { - int y; - const int bits_per_pixel = 8 >> transform->bits_; - const int width = transform->xsize_; - const uint32_t* const color_map = transform->data_; - if (bits_per_pixel < 8) { - const int pixels_per_byte = 1 << transform->bits_; - const int count_mask = pixels_per_byte - 1; - const uint32_t bit_mask = (1 << bits_per_pixel) - 1; - for (y = y_start; y < y_end; ++y) { - uint32_t packed_pixels = 0; - int x; - for (x = 0; x < width; ++x) { - // We need to load fresh 'packed_pixels' once every 'pixels_per_byte' - // increments of x. Fortunately, pixels_per_byte is a power of 2, so - // can just use a mask for that, instead of decrementing a counter. - if ((x & count_mask) == 0) packed_pixels = ((*src++) >> 8) & 0xff; - *dst++ = color_map[packed_pixels & bit_mask]; - packed_pixels >>= bits_per_pixel; - } - } - } else { - for (y = y_start; y < y_end; ++y) { - int x; - for (x = 0; x < width; ++x) { - *dst++ = color_map[((*src++) >> 8) & 0xff]; - } - } - } +// We define two methods for ARGB data (uint32_t) and alpha-only data (uint8_t). +#define COLOR_INDEX_INVERSE(FUNC_NAME, TYPE, GET_INDEX, GET_VALUE) \ +void FUNC_NAME(const VP8LTransform* const transform, \ + int y_start, int y_end, const TYPE* src, TYPE* dst) { \ + int y; \ + const int bits_per_pixel = 8 >> transform->bits_; \ + const int width = transform->xsize_; \ + const uint32_t* const color_map = transform->data_; \ + if (bits_per_pixel < 8) { \ + const int pixels_per_byte = 1 << transform->bits_; \ + const int count_mask = pixels_per_byte - 1; \ + const uint32_t bit_mask = (1 << bits_per_pixel) - 1; \ + for (y = y_start; y < y_end; ++y) { \ + uint32_t packed_pixels = 0; \ + int x; \ + for (x = 0; x < width; ++x) { \ + /* We need to load fresh 'packed_pixels' once every */ \ + /* 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte */ \ + /* is a power of 2, so can just use a mask for that, instead of */ \ + /* decrementing a counter. */ \ + if ((x & count_mask) == 0) packed_pixels = GET_INDEX(*src++); \ + *dst++ = GET_VALUE(color_map[packed_pixels & bit_mask]); \ + packed_pixels >>= bits_per_pixel; \ + } \ + } \ + } else { \ + for (y = y_start; y < y_end; ++y) { \ + int x; \ + for (x = 0; x < width; ++x) { \ + *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]); \ + } \ + } \ + } \ } +static WEBP_INLINE uint32_t GetARGBIndex(uint32_t idx) { + return (idx >> 8) & 0xff; +} + +static WEBP_INLINE uint8_t GetAlphaIndex(uint8_t idx) { + return idx; +} + +static WEBP_INLINE uint32_t GetARGBValue(uint32_t val) { + return val; +} + +static WEBP_INLINE uint8_t GetAlphaValue(uint32_t val) { + return (val >> 8) & 0xff; +} + +static COLOR_INDEX_INVERSE(ColorIndexInverseTransform, uint32_t, GetARGBIndex, + GetARGBValue) +COLOR_INDEX_INVERSE(VP8LColorIndexInverseTransformAlpha, uint8_t, GetAlphaIndex, + GetAlphaValue) + +#undef COLOR_INDEX_INVERSE + void VP8LInverseTransform(const VP8LTransform* const transform, int row_start, int row_end, const uint32_t* const in, uint32_t* const out) { @@ -1034,8 +1234,15 @@ static void ConvertBGRAToRGBA4444(const uint32_t* src, const uint32_t* const src_end = src + num_pixels; while (src < src_end) { const uint32_t argb = *src++; - *dst++ = ((argb >> 16) & 0xf0) | ((argb >> 12) & 0xf); - *dst++ = ((argb >> 0) & 0xf0) | ((argb >> 28) & 0xf); + const uint8_t rg = ((argb >> 16) & 0xf0) | ((argb >> 12) & 0xf); + const uint8_t ba = ((argb >> 0) & 0xf0) | ((argb >> 28) & 0xf); +#ifdef WEBP_SWAP_16BIT_CSP + *dst++ = ba; + *dst++ = rg; +#else + *dst++ = rg; + *dst++ = ba; +#endif } } @@ -1044,8 +1251,15 @@ static void ConvertBGRAToRGB565(const uint32_t* src, const uint32_t* const src_end = src + num_pixels; while (src < src_end) { const uint32_t argb = *src++; - *dst++ = ((argb >> 16) & 0xf8) | ((argb >> 13) & 0x7); - *dst++ = ((argb >> 5) & 0xe0) | ((argb >> 3) & 0x1f); + const uint8_t rg = ((argb >> 16) & 0xf8) | ((argb >> 13) & 0x7); + const uint8_t gb = ((argb >> 5) & 0xe0) | ((argb >> 3) & 0x1f); +#ifdef WEBP_SWAP_16BIT_CSP + *dst++ = gb; + *dst++ = rg; +#else + *dst++ = rg; + *dst++ = gb; +#endif } } @@ -1066,20 +1280,34 @@ static void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst, const uint32_t* const src_end = src + num_pixels; while (src < src_end) { uint32_t argb = *src++; -#if !defined(__BIG_ENDIAN__) && (defined(__i386__) || defined(__x86_64__)) + +#if !defined(__BIG_ENDIAN__) +#if !defined(WEBP_REFERENCE_IMPLEMENTATION) +#if defined(__i386__) || defined(__x86_64__) __asm__ volatile("bswap %0" : "=r"(argb) : "0"(argb)); *(uint32_t*)dst = argb; - dst += sizeof(argb); -#elif !defined(__BIG_ENDIAN__) && defined(_MSC_VER) +#elif defined(_MSC_VER) argb = _byteswap_ulong(argb); *(uint32_t*)dst = argb; - dst += sizeof(argb); #else - *dst++ = (argb >> 24) & 0xff; - *dst++ = (argb >> 16) & 0xff; - *dst++ = (argb >> 8) & 0xff; - *dst++ = (argb >> 0) & 0xff; + dst[0] = (argb >> 24) & 0xff; + dst[1] = (argb >> 16) & 0xff; + dst[2] = (argb >> 8) & 0xff; + dst[3] = (argb >> 0) & 0xff; #endif +#else // WEBP_REFERENCE_IMPLEMENTATION + dst[0] = (argb >> 24) & 0xff; + dst[1] = (argb >> 16) & 0xff; + dst[2] = (argb >> 8) & 0xff; + dst[3] = (argb >> 0) & 0xff; +#endif +#else // __BIG_ENDIAN__ + dst[0] = (argb >> 0) & 0xff; + dst[1] = (argb >> 8) & 0xff; + dst[2] = (argb >> 16) & 0xff; + dst[3] = (argb >> 24) & 0xff; +#endif + dst += sizeof(argb); } } else { memcpy(dst, src, num_pixels * sizeof(*src)); @@ -1131,6 +1359,27 @@ void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels, } } +// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel. +void VP8LBundleColorMap(const uint8_t* const row, int width, + int xbits, uint32_t* const dst) { + int x; + if (xbits > 0) { + const int bit_depth = 1 << (3 - xbits); + const int mask = (1 << xbits) - 1; + uint32_t code = 0xff000000; + for (x = 0; x < width; ++x) { + const int xsub = x & mask; + if (xsub == 0) { + code = 0xff000000; + } + code |= row[x] << (8 + bit_depth * xsub); + dst[x >> xbits] = code; + } + } else { + for (x = 0; x < width; ++x) dst[x] = 0xff000000 | (row[x] << 8); + } +} + //------------------------------------------------------------------------------ #if defined(__cplusplus) || defined(c_plusplus) diff --git a/3rdparty/libwebp/dsp/lossless.h b/3rdparty/libwebp/dsp/lossless.h index 992516fcdf..7490ec8efe 100644 --- a/3rdparty/libwebp/dsp/lossless.h +++ b/3rdparty/libwebp/dsp/lossless.h @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Image transforms and color space conversion methods for lossless decoder. @@ -33,6 +35,13 @@ void VP8LInverseTransform(const struct VP8LTransform* const transform, int row_start, int row_end, const uint32_t* const in, uint32_t* const out); +// Similar to the static method ColorIndexInverseTransform() that is part of +// lossless.c, but used only for alpha decoding. It takes uint8_t (rather than +// uint32_t) arguments for 'src' and 'dst'. +void VP8LColorIndexInverseTransformAlpha( + const struct VP8LTransform* const transform, int y_start, int y_end, + const uint8_t* src, uint8_t* dst); + // Subtracts green from blue and red channels. void VP8LSubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixs); @@ -59,10 +68,20 @@ static WEBP_INLINE uint32_t VP8LSubSampleSize(uint32_t size, return (size + (1 << sampling_bits) - 1) >> sampling_bits; } -// Faster logarithm for integers, with the property of log2(0) == 0. -float VP8LFastLog2(int v); +// Faster logarithm for integers. Small values use a look-up table. +#define LOG_LOOKUP_IDX_MAX 256 +extern const float kLog2Table[LOG_LOOKUP_IDX_MAX]; +extern const float kSLog2Table[LOG_LOOKUP_IDX_MAX]; +extern float VP8LFastLog2Slow(int v); +extern float VP8LFastSLog2Slow(int v); +static WEBP_INLINE float VP8LFastLog2(int v) { + return (v < LOG_LOOKUP_IDX_MAX) ? kLog2Table[v] : VP8LFastLog2Slow(v); +} // Fast calculation of v * log2(v) for integer input. -static WEBP_INLINE float VP8LFastSLog2(int v) { return VP8LFastLog2(v) * v; } +static WEBP_INLINE float VP8LFastSLog2(int v) { + return (v < LOG_LOOKUP_IDX_MAX) ? kSLog2Table[v] : VP8LFastSLog2Slow(v); +} + // In-place difference of each component with mod 256. static WEBP_INLINE uint32_t VP8LSubPixels(uint32_t a, uint32_t b) { @@ -73,6 +92,9 @@ static WEBP_INLINE uint32_t VP8LSubPixels(uint32_t a, uint32_t b) { return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); } +void VP8LBundleColorMap(const uint8_t* const row, int width, + int xbits, uint32_t* const dst); + //------------------------------------------------------------------------------ #if defined(__cplusplus) || defined(c_plusplus) diff --git a/3rdparty/libwebp/dsp/upsampling.c b/3rdparty/libwebp/dsp/upsampling.c index 4855eb1432..80ba4f8a5e 100644 --- a/3rdparty/libwebp/dsp/upsampling.c +++ b/3rdparty/libwebp/dsp/upsampling.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // YUV to RGB upsampling functions. @@ -32,7 +34,7 @@ WebPUpsampleLinePairFunc WebPUpsamplers[MODE_LAST]; // ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16 // We process u and v together stashed into 32bit (16bit each). -#define LOAD_UV(u,v) ((u) | ((v) << 16)) +#define LOAD_UV(u, v) ((u) | ((v) << 16)) #define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ @@ -327,6 +329,11 @@ void WebPInitUpsamplers(void) { if (VP8GetCPUInfo(kSSE2)) { WebPInitUpsamplersSSE2(); } +#endif +#if defined(WEBP_USE_NEON) + if (VP8GetCPUInfo(kNEON)) { + WebPInitUpsamplersNEON(); + } #endif } #endif // FANCY_UPSAMPLING @@ -347,6 +354,11 @@ void WebPInitPremultiply(void) { if (VP8GetCPUInfo(kSSE2)) { WebPInitPremultiplySSE2(); } +#endif +#if defined(WEBP_USE_NEON) + if (VP8GetCPUInfo(kNEON)) { + WebPInitPremultiplyNEON(); + } #endif } #endif // FANCY_UPSAMPLING diff --git a/3rdparty/libwebp/dsp/upsampling_neon.c b/3rdparty/libwebp/dsp/upsampling_neon.c new file mode 100644 index 0000000000..d118895909 --- /dev/null +++ b/3rdparty/libwebp/dsp/upsampling_neon.c @@ -0,0 +1,294 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// NEON version of YUV to RGB upsampling functions. +// +// Author: mans@mansr.com (Mans Rullgard) +// Based on SSE code by: somnath@google.com (Somnath Banerjee) + +#include "./dsp.h" + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#if defined(WEBP_USE_NEON) + +#include +#include +#include +#include "./yuv.h" + +#ifdef FANCY_UPSAMPLING + +// Loads 9 pixels each from rows r1 and r2 and generates 16 pixels. +#define UPSAMPLE_16PIXELS(r1, r2, out) { \ + uint8x8_t a = vld1_u8(r1); \ + uint8x8_t b = vld1_u8(r1 + 1); \ + uint8x8_t c = vld1_u8(r2); \ + uint8x8_t d = vld1_u8(r2 + 1); \ + \ + uint16x8_t al = vshll_n_u8(a, 1); \ + uint16x8_t bl = vshll_n_u8(b, 1); \ + uint16x8_t cl = vshll_n_u8(c, 1); \ + uint16x8_t dl = vshll_n_u8(d, 1); \ + \ + uint8x8_t diag1, diag2; \ + uint16x8_t sl; \ + \ + /* a + b + c + d */ \ + sl = vaddl_u8(a, b); \ + sl = vaddw_u8(sl, c); \ + sl = vaddw_u8(sl, d); \ + \ + al = vaddq_u16(sl, al); /* 3a + b + c + d */ \ + bl = vaddq_u16(sl, bl); /* a + 3b + c + d */ \ + \ + al = vaddq_u16(al, dl); /* 3a + b + c + 3d */ \ + bl = vaddq_u16(bl, cl); /* a + 3b + 3c + d */ \ + \ + diag2 = vshrn_n_u16(al, 3); \ + diag1 = vshrn_n_u16(bl, 3); \ + \ + a = vrhadd_u8(a, diag1); \ + b = vrhadd_u8(b, diag2); \ + c = vrhadd_u8(c, diag2); \ + d = vrhadd_u8(d, diag1); \ + \ + { \ + const uint8x8x2_t a_b = {{ a, b }}; \ + const uint8x8x2_t c_d = {{ c, d }}; \ + vst2_u8(out, a_b); \ + vst2_u8(out + 32, c_d); \ + } \ +} + +// Turn the macro into a function for reducing code-size when non-critical +static void Upsample16Pixels(const uint8_t *r1, const uint8_t *r2, + uint8_t *out) { + UPSAMPLE_16PIXELS(r1, r2, out); +} + +#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \ + uint8_t r1[9], r2[9]; \ + memcpy(r1, (tb), (num_pixels)); \ + memcpy(r2, (bb), (num_pixels)); \ + /* replicate last byte */ \ + memset(r1 + (num_pixels), r1[(num_pixels) - 1], 9 - (num_pixels)); \ + memset(r2 + (num_pixels), r2[(num_pixels) - 1], 9 - (num_pixels)); \ + Upsample16Pixels(r1, r2, out); \ +} + +#define CY 76283 +#define CVR 89858 +#define CUG 22014 +#define CVG 45773 +#define CUB 113618 + +static const int16_t coef[4] = { CVR / 4, CUG, CVG / 2, CUB / 4 }; + +#define CONVERT8(FMT, XSTEP, N, src_y, src_uv, out, cur_x) { \ + int i; \ + for (i = 0; i < N; i += 8) { \ + int off = ((cur_x) + i) * XSTEP; \ + uint8x8_t y = vld1_u8(src_y + (cur_x) + i); \ + uint8x8_t u = vld1_u8((src_uv) + i); \ + uint8x8_t v = vld1_u8((src_uv) + i + 16); \ + int16x8_t yy = vreinterpretq_s16_u16(vsubl_u8(y, u16)); \ + int16x8_t uu = vreinterpretq_s16_u16(vsubl_u8(u, u128)); \ + int16x8_t vv = vreinterpretq_s16_u16(vsubl_u8(v, u128)); \ + \ + int16x8_t ud = vshlq_n_s16(uu, 1); \ + int16x8_t vd = vshlq_n_s16(vv, 1); \ + \ + int32x4_t vrl = vqdmlal_lane_s16(vshll_n_s16(vget_low_s16(vv), 1), \ + vget_low_s16(vd), cf16, 0); \ + int32x4_t vrh = vqdmlal_lane_s16(vshll_n_s16(vget_high_s16(vv), 1), \ + vget_high_s16(vd), cf16, 0); \ + int16x8_t vr = vcombine_s16(vrshrn_n_s32(vrl, 16), \ + vrshrn_n_s32(vrh, 16)); \ + \ + int32x4_t vl = vmovl_s16(vget_low_s16(vv)); \ + int32x4_t vh = vmovl_s16(vget_high_s16(vv)); \ + int32x4_t ugl = vmlal_lane_s16(vl, vget_low_s16(uu), cf16, 1); \ + int32x4_t ugh = vmlal_lane_s16(vh, vget_high_s16(uu), cf16, 1); \ + int32x4_t gcl = vqdmlal_lane_s16(ugl, vget_low_s16(vv), cf16, 2); \ + int32x4_t gch = vqdmlal_lane_s16(ugh, vget_high_s16(vv), cf16, 2); \ + int16x8_t gc = vcombine_s16(vrshrn_n_s32(gcl, 16), \ + vrshrn_n_s32(gch, 16)); \ + \ + int32x4_t ubl = vqdmlal_lane_s16(vshll_n_s16(vget_low_s16(uu), 1), \ + vget_low_s16(ud), cf16, 3); \ + int32x4_t ubh = vqdmlal_lane_s16(vshll_n_s16(vget_high_s16(uu), 1), \ + vget_high_s16(ud), cf16, 3); \ + int16x8_t ub = vcombine_s16(vrshrn_n_s32(ubl, 16), \ + vrshrn_n_s32(ubh, 16)); \ + \ + int32x4_t rl = vaddl_s16(vget_low_s16(yy), vget_low_s16(vr)); \ + int32x4_t rh = vaddl_s16(vget_high_s16(yy), vget_high_s16(vr)); \ + int32x4_t gl = vsubl_s16(vget_low_s16(yy), vget_low_s16(gc)); \ + int32x4_t gh = vsubl_s16(vget_high_s16(yy), vget_high_s16(gc)); \ + int32x4_t bl = vaddl_s16(vget_low_s16(yy), vget_low_s16(ub)); \ + int32x4_t bh = vaddl_s16(vget_high_s16(yy), vget_high_s16(ub)); \ + \ + rl = vmulq_lane_s32(rl, cf32, 0); \ + rh = vmulq_lane_s32(rh, cf32, 0); \ + gl = vmulq_lane_s32(gl, cf32, 0); \ + gh = vmulq_lane_s32(gh, cf32, 0); \ + bl = vmulq_lane_s32(bl, cf32, 0); \ + bh = vmulq_lane_s32(bh, cf32, 0); \ + \ + y = vqmovun_s16(vcombine_s16(vrshrn_n_s32(rl, 16), \ + vrshrn_n_s32(rh, 16))); \ + u = vqmovun_s16(vcombine_s16(vrshrn_n_s32(gl, 16), \ + vrshrn_n_s32(gh, 16))); \ + v = vqmovun_s16(vcombine_s16(vrshrn_n_s32(bl, 16), \ + vrshrn_n_s32(bh, 16))); \ + STR_ ## FMT(out + off, y, u, v); \ + } \ +} + +#define v255 vmov_n_u8(255) + +#define STR_Rgb(out, r, g, b) do { \ + const uint8x8x3_t r_g_b = {{ r, g, b }}; \ + vst3_u8(out, r_g_b); \ +} while (0) + +#define STR_Bgr(out, r, g, b) do { \ + const uint8x8x3_t b_g_r = {{ b, g, r }}; \ + vst3_u8(out, b_g_r); \ +} while (0) + +#define STR_Rgba(out, r, g, b) do { \ + const uint8x8x4_t r_g_b_v255 = {{ r, g, b, v255 }}; \ + vst4_u8(out, r_g_b_v255); \ +} while (0) + +#define STR_Bgra(out, r, g, b) do { \ + const uint8x8x4_t b_g_r_v255 = {{ b, g, r, v255 }}; \ + vst4_u8(out, b_g_r_v255); \ +} while (0) + +#define CONVERT1(FMT, XSTEP, N, src_y, src_uv, rgb, cur_x) { \ + int i; \ + for (i = 0; i < N; i++) { \ + int off = ((cur_x) + i) * XSTEP; \ + int y = src_y[(cur_x) + i]; \ + int u = (src_uv)[i]; \ + int v = (src_uv)[i + 16]; \ + VP8YuvTo ## FMT(y, u, v, rgb + off); \ + } \ +} + +#define CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, uv, \ + top_dst, bottom_dst, cur_x, len) { \ + if (top_y) { \ + CONVERT8(FMT, XSTEP, len, top_y, uv, top_dst, cur_x) \ + } \ + if (bottom_y) { \ + CONVERT8(FMT, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x) \ + } \ +} + +#define CONVERT2RGB_1(FMT, XSTEP, top_y, bottom_y, uv, \ + top_dst, bottom_dst, cur_x, len) { \ + if (top_y) { \ + CONVERT1(FMT, XSTEP, len, top_y, uv, top_dst, cur_x); \ + } \ + if (bottom_y) { \ + CONVERT1(FMT, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x); \ + } \ +} + +#define NEON_UPSAMPLE_FUNC(FUNC_NAME, FMT, XSTEP) \ +static void FUNC_NAME(const uint8_t *top_y, const uint8_t *bottom_y, \ + const uint8_t *top_u, const uint8_t *top_v, \ + const uint8_t *cur_u, const uint8_t *cur_v, \ + uint8_t *top_dst, uint8_t *bottom_dst, int len) { \ + int block; \ + /* 16 byte aligned array to cache reconstructed u and v */ \ + uint8_t uv_buf[2 * 32 + 15]; \ + uint8_t *const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \ + const int uv_len = (len + 1) >> 1; \ + /* 9 pixels must be read-able for each block */ \ + const int num_blocks = (uv_len - 1) >> 3; \ + const int leftover = uv_len - num_blocks * 8; \ + const int last_pos = 1 + 16 * num_blocks; \ + \ + const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \ + const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \ + \ + const int16x4_t cf16 = vld1_s16(coef); \ + const int32x2_t cf32 = vmov_n_s32(CY); \ + const uint8x8_t u16 = vmov_n_u8(16); \ + const uint8x8_t u128 = vmov_n_u8(128); \ + \ + /* Treat the first pixel in regular way */ \ + if (top_y) { \ + const int u0 = (top_u[0] + u_diag) >> 1; \ + const int v0 = (top_v[0] + v_diag) >> 1; \ + VP8YuvTo ## FMT(top_y[0], u0, v0, top_dst); \ + } \ + if (bottom_y) { \ + const int u0 = (cur_u[0] + u_diag) >> 1; \ + const int v0 = (cur_v[0] + v_diag) >> 1; \ + VP8YuvTo ## FMT(bottom_y[0], u0, v0, bottom_dst); \ + } \ + \ + for (block = 0; block < num_blocks; ++block) { \ + UPSAMPLE_16PIXELS(top_u, cur_u, r_uv); \ + UPSAMPLE_16PIXELS(top_v, cur_v, r_uv + 16); \ + CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, r_uv, \ + top_dst, bottom_dst, 16 * block + 1, 16); \ + top_u += 8; \ + cur_u += 8; \ + top_v += 8; \ + cur_v += 8; \ + } \ + \ + UPSAMPLE_LAST_BLOCK(top_u, cur_u, leftover, r_uv); \ + UPSAMPLE_LAST_BLOCK(top_v, cur_v, leftover, r_uv + 16); \ + CONVERT2RGB_1(FMT, XSTEP, top_y, bottom_y, r_uv, \ + top_dst, bottom_dst, last_pos, len - last_pos); \ +} + +// NEON variants of the fancy upsampler. +NEON_UPSAMPLE_FUNC(UpsampleRgbLinePairNEON, Rgb, 3) +NEON_UPSAMPLE_FUNC(UpsampleBgrLinePairNEON, Bgr, 3) +NEON_UPSAMPLE_FUNC(UpsampleRgbaLinePairNEON, Rgba, 4) +NEON_UPSAMPLE_FUNC(UpsampleBgraLinePairNEON, Bgra, 4) + +#endif // FANCY_UPSAMPLING + +#endif // WEBP_USE_NEON + +//------------------------------------------------------------------------------ + +extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; + +void WebPInitUpsamplersNEON(void) { +#if defined(WEBP_USE_NEON) + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePairNEON; + WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePairNEON; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePairNEON; + WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePairNEON; +#endif // WEBP_USE_NEON +} + +void WebPInitPremultiplyNEON(void) { +#if defined(WEBP_USE_NEON) + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePairNEON; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePairNEON; +#endif // WEBP_USE_NEON +} + +#if defined(__cplusplus) || defined(c_plusplus) +} // extern "C" +#endif diff --git a/3rdparty/libwebp/dsp/upsampling_sse2.c b/3rdparty/libwebp/dsp/upsampling_sse2.c index 04cc0aaec3..f31d04845e 100644 --- a/3rdparty/libwebp/dsp/upsampling_sse2.c +++ b/3rdparty/libwebp/dsp/upsampling_sse2.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // SSE2 version of YUV to RGB upsampling functions. @@ -51,12 +53,12 @@ extern "C" { // pack and store two alterning pixel rows #define PACK_AND_STORE(a, b, da, db, out) do { \ - const __m128i ta = _mm_avg_epu8(a, da); /* (9a + 3b + 3c + d + 8) / 16 */ \ - const __m128i tb = _mm_avg_epu8(b, db); /* (3a + 9b + c + 3d + 8) / 16 */ \ - const __m128i t1 = _mm_unpacklo_epi8(ta, tb); \ - const __m128i t2 = _mm_unpackhi_epi8(ta, tb); \ - _mm_store_si128(((__m128i*)(out)) + 0, t1); \ - _mm_store_si128(((__m128i*)(out)) + 1, t2); \ + const __m128i t_a = _mm_avg_epu8(a, da); /* (9a + 3b + 3c + d + 8) / 16 */ \ + const __m128i t_b = _mm_avg_epu8(b, db); /* (3a + 9b + c + 3d + 8) / 16 */ \ + const __m128i t_1 = _mm_unpacklo_epi8(t_a, t_b); \ + const __m128i t_2 = _mm_unpackhi_epi8(t_a, t_b); \ + _mm_store_si128(((__m128i*)(out)) + 0, t_1); \ + _mm_store_si128(((__m128i*)(out)) + 1, t_2); \ } while (0) // Loads 17 pixels each from rows r1 and r2 and generates 32 pixels. @@ -128,7 +130,7 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ const uint8_t* top_u, const uint8_t* top_v, \ const uint8_t* cur_u, const uint8_t* cur_v, \ uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ - int b; \ + int block; \ /* 16 byte aligned array to cache reconstructed u and v */ \ uint8_t uv_buf[4 * 32 + 15]; \ uint8_t* const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \ @@ -154,11 +156,11 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ FUNC(bottom_y[0], u0, v0, bottom_dst); \ } \ \ - for (b = 0; b < num_blocks; ++b) { \ + for (block = 0; block < num_blocks; ++block) { \ UPSAMPLE_32PIXELS(top_u, cur_u, r_uv + 0 * 32); \ UPSAMPLE_32PIXELS(top_v, cur_v, r_uv + 1 * 32); \ CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, r_uv, top_dst, bottom_dst, \ - 32 * b + 1, 32) \ + 32 * block + 1, 32) \ top_u += 16; \ cur_u += 16; \ top_v += 16; \ @@ -211,3 +213,5 @@ void WebPInitPremultiplySSE2(void) { #if defined(__cplusplus) || defined(c_plusplus) } // extern "C" #endif + + diff --git a/3rdparty/libwebp/dsp/yuv.c b/3rdparty/libwebp/dsp/yuv.c index 7f05f9a3aa..1a59f7449e 100644 --- a/3rdparty/libwebp/dsp/yuv.c +++ b/3rdparty/libwebp/dsp/yuv.c @@ -1,8 +1,10 @@ // Copyright 2010 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // YUV->RGB conversion function @@ -15,7 +17,7 @@ extern "C" { #endif -enum { YUV_HALF = 1 << (YUV_FIX - 1) }; +#ifdef WEBP_YUV_USE_TABLE int16_t VP8kVToR[256], VP8kUToB[256]; int32_t VP8kVToG[256], VP8kUToG[256]; @@ -33,6 +35,7 @@ void VP8YUVInit(void) { if (done) { return; } +#ifndef USE_YUVj for (i = 0; i < 256; ++i) { VP8kVToR[i] = (89858 * (i - 128) + YUV_HALF) >> YUV_FIX; VP8kUToG[i] = -22014 * (i - 128) + YUV_HALF; @@ -44,9 +47,29 @@ void VP8YUVInit(void) { VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255); VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15); } +#else + for (i = 0; i < 256; ++i) { + VP8kVToR[i] = (91881 * (i - 128) + YUV_HALF) >> YUV_FIX; + VP8kUToG[i] = -22554 * (i - 128) + YUV_HALF; + VP8kVToG[i] = -46802 * (i - 128); + VP8kUToB[i] = (116130 * (i - 128) + YUV_HALF) >> YUV_FIX; + } + for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) { + const int k = i; + VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255); + VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15); + } +#endif + done = 1; } +#else + +void VP8YUVInit(void) {} + +#endif // WEBP_YUV_USE_TABLE + #if defined(__cplusplus) || defined(c_plusplus) } // extern "C" #endif diff --git a/3rdparty/libwebp/dsp/yuv.h b/3rdparty/libwebp/dsp/yuv.h index a569109c54..3844d8cab3 100644 --- a/3rdparty/libwebp/dsp/yuv.h +++ b/3rdparty/libwebp/dsp/yuv.h @@ -1,12 +1,34 @@ // Copyright 2010 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // inline YUV<->RGB conversion function // +// The exact naming is Y'CbCr, following the ITU-R BT.601 standard. +// More information at: http://en.wikipedia.org/wiki/YCbCr +// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16 +// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128 +// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128 +// We use 16bit fixed point operations for RGB->YUV conversion. +// +// For the Y'CbCr to RGB conversion, the BT.601 specification reads: +// R = 1.164 * (Y-16) + 1.596 * (V-128) +// G = 1.164 * (Y-16) - 0.813 * (V-128) - 0.391 * (U-128) +// B = 1.164 * (Y-16) + 2.018 * (U-128) +// where Y is in the [16,235] range, and U/V in the [16,240] range. +// In the table-lookup version (WEBP_YUV_USE_TABLE), the common factor +// "1.164 * (Y-16)" can be handled as an offset in the VP8kClip[] table. +// So in this case the formulae should be read as: +// R = 1.164 * [Y + 1.371 * (V-128) ] - 18.624 +// G = 1.164 * [Y - 0.698 * (V-128) - 0.336 * (U-128)] - 18.624 +// B = 1.164 * [Y + 1.733 * (U-128)] - 18.624 +// once factorized. Here too, 16bit fixed precision is used. +// // Author: Skal (pascal.massimino@gmail.com) #ifndef WEBP_DSP_YUV_H_ @@ -14,6 +36,19 @@ #include "../dec/decode_vp8.h" +// Define the following to use the LUT-based code: +#define WEBP_YUV_USE_TABLE + +#if defined(WEBP_EXPERIMENTAL_FEATURES) +// Do NOT activate this feature for real compression. This is only experimental! +// This flag is for comparison purpose against JPEG's "YUVj" natural colorspace. +// This colorspace is close to Rec.601's Y'CbCr model with the notable +// difference of allowing larger range for luma/chroma. +// See http://en.wikipedia.org/wiki/YCbCr#JPEG_conversion paragraph, and its +// difference with http://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion +// #define USE_YUVj +#endif + //------------------------------------------------------------------------------ // YUV -> RGB conversion @@ -22,9 +57,14 @@ extern "C" { #endif enum { YUV_FIX = 16, // fixed-point precision + YUV_HALF = 1 << (YUV_FIX - 1), + YUV_MASK = (256 << YUV_FIX) - 1, YUV_RANGE_MIN = -227, // min value of r/g/b output YUV_RANGE_MAX = 256 + 226 // max value of r/g/b output }; + +#ifdef WEBP_YUV_USE_TABLE + extern int16_t VP8kVToR[256], VP8kUToB[256]; extern int32_t VP8kVToG[256], VP8kUToG[256]; extern uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN]; @@ -40,34 +80,6 @@ static WEBP_INLINE void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v, rgb[2] = VP8kClip[y + b_off - YUV_RANGE_MIN]; } -static WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v, - uint8_t* const rgb) { - const int r_off = VP8kVToR[v]; - const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; - const int b_off = VP8kUToB[u]; - rgb[0] = ((VP8kClip[y + r_off - YUV_RANGE_MIN] & 0xf8) | - (VP8kClip[y + g_off - YUV_RANGE_MIN] >> 5)); - rgb[1] = (((VP8kClip[y + g_off - YUV_RANGE_MIN] << 3) & 0xe0) | - (VP8kClip[y + b_off - YUV_RANGE_MIN] >> 3)); -} - -static WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v, - uint8_t* const argb) { - argb[0] = 0xff; - VP8YuvToRgb(y, u, v, argb + 1); -} - -static WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v, - uint8_t* const argb) { - const int r_off = VP8kVToR[v]; - const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; - const int b_off = VP8kUToB[u]; - // Don't update alpha (last 4 bits of argb[1]) - argb[0] = ((VP8kClip4Bits[y + r_off - YUV_RANGE_MIN] << 4) | - VP8kClip4Bits[y + g_off - YUV_RANGE_MIN]); - argb[1] = 0x0f | (VP8kClip4Bits[y + b_off - YUV_RANGE_MIN] << 4); -} - static WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v, uint8_t* const bgr) { const int r_off = VP8kVToR[v]; @@ -78,6 +90,129 @@ static WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v, bgr[2] = VP8kClip[y + r_off - YUV_RANGE_MIN]; } +static WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const rgb) { + const int r_off = VP8kVToR[v]; + const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; + const int b_off = VP8kUToB[u]; + const uint8_t rg = ((VP8kClip[y + r_off - YUV_RANGE_MIN] & 0xf8) | + (VP8kClip[y + g_off - YUV_RANGE_MIN] >> 5)); + const uint8_t gb = (((VP8kClip[y + g_off - YUV_RANGE_MIN] << 3) & 0xe0) | + (VP8kClip[y + b_off - YUV_RANGE_MIN] >> 3)); +#ifdef WEBP_SWAP_16BIT_CSP + rgb[0] = gb; + rgb[1] = rg; +#else + rgb[0] = rg; + rgb[1] = gb; +#endif +} + +static WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const argb) { + const int r_off = VP8kVToR[v]; + const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; + const int b_off = VP8kUToB[u]; + const uint8_t rg = ((VP8kClip4Bits[y + r_off - YUV_RANGE_MIN] << 4) | + VP8kClip4Bits[y + g_off - YUV_RANGE_MIN]); + const uint8_t ba = (VP8kClip4Bits[y + b_off - YUV_RANGE_MIN] << 4) | 0x0f; +#ifdef WEBP_SWAP_16BIT_CSP + argb[0] = ba; + argb[1] = rg; +#else + argb[0] = rg; + argb[1] = ba; +#endif +} + +#else // Table-free version (slower on x86) + +// These constants are 16b fixed-point version of ITU-R BT.601 constants +#define kYScale 76309 // 1.164 = 255 / 219 +#define kVToR 104597 // 1.596 = 255 / 112 * 0.701 +#define kUToG 25674 // 0.391 = 255 / 112 * 0.886 * 0.114 / 0.587 +#define kVToG 53278 // 0.813 = 255 / 112 * 0.701 * 0.299 / 0.587 +#define kUToB 132201 // 2.018 = 255 / 112 * 0.886 +#define kRCst (-kYScale * 16 - kVToR * 128 + YUV_HALF) +#define kGCst (-kYScale * 16 + kUToG * 128 + kVToG * 128 + YUV_HALF) +#define kBCst (-kYScale * 16 - kUToB * 128 + YUV_HALF) + +static WEBP_INLINE uint8_t VP8Clip8(int v) { + return ((v & ~YUV_MASK) == 0) ? (uint8_t)(v >> YUV_FIX) + : (v < 0) ? 0u : 255u; +} + +static WEBP_INLINE uint8_t VP8ClipN(int v, int N) { // clip to N bits + return ((v & ~YUV_MASK) == 0) ? (uint8_t)(v >> (YUV_FIX + (8 - N))) + : (v < 0) ? 0u : (255u >> (8 - N)); +} + +static WEBP_INLINE int VP8YUVToR(int y, int v) { + return kYScale * y + kVToR * v + kRCst; +} + +static WEBP_INLINE int VP8YUVToG(int y, int u, int v) { + return kYScale * y - kUToG * u - kVToG * v + kGCst; +} + +static WEBP_INLINE int VP8YUVToB(int y, int u) { + return kYScale * y + kUToB * u + kBCst; +} + +static WEBP_INLINE void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const rgb) { + rgb[0] = VP8Clip8(VP8YUVToR(y, v)); + rgb[1] = VP8Clip8(VP8YUVToG(y, u, v)); + rgb[2] = VP8Clip8(VP8YUVToB(y, u)); +} + +static WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const bgr) { + bgr[0] = VP8Clip8(VP8YUVToB(y, u)); + bgr[1] = VP8Clip8(VP8YUVToG(y, u, v)); + bgr[2] = VP8Clip8(VP8YUVToR(y, v)); +} + +static WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const rgb) { + const int r = VP8Clip8(VP8YUVToR(y, u)); + const int g = VP8ClipN(VP8YUVToG(y, u, v), 6); + const int b = VP8ClipN(VP8YUVToB(y, v), 5); + const uint8_t rg = (r & 0xf8) | (g >> 3); + const uint8_t gb = (g << 5) | b; +#ifdef WEBP_SWAP_16BIT_CSP + rgb[0] = gb; + rgb[1] = rg; +#else + rgb[0] = rg; + rgb[1] = gb; +#endif +} + +static WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const argb) { + const int r = VP8Clip8(VP8YUVToR(y, u)); + const int g = VP8ClipN(VP8YUVToG(y, u, v), 4); + const int b = VP8Clip8(VP8YUVToB(y, v)); + const uint8_t rg = (r & 0xf0) | g; + const uint8_t ba = b | 0x0f; // overwrite the lower 4 bits +#ifdef WEBP_SWAP_16BIT_CSP + argb[0] = ba; + argb[1] = rg; +#else + argb[0] = rg; + argb[1] = ba; +#endif +} + +#endif // WEBP_YUV_USE_TABLE + +static WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const argb) { + argb[0] = 0xff; + VP8YuvToRgb(y, u, v, argb + 1); +} + static WEBP_INLINE void VP8YuvToBgra(uint8_t y, uint8_t u, uint8_t v, uint8_t* const bgra) { VP8YuvToBgr(y, u, v, bgra); @@ -95,18 +230,14 @@ void VP8YUVInit(void); //------------------------------------------------------------------------------ // RGB -> YUV conversion -// The exact naming is Y'CbCr, following the ITU-R BT.601 standard. -// More information at: http://en.wikipedia.org/wiki/YCbCr -// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16 -// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128 -// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128 -// We use 16bit fixed point operations. static WEBP_INLINE int VP8ClipUV(int v) { - v = (v + (257 << (YUV_FIX + 2 - 1))) >> (YUV_FIX + 2); - return ((v & ~0xff) == 0) ? v : (v < 0) ? 0 : 255; + v = (v + (257 << (YUV_FIX + 2 - 1))) >> (YUV_FIX + 2); + return ((v & ~0xff) == 0) ? v : (v < 0) ? 0 : 255; } +#ifndef USE_YUVj + static WEBP_INLINE int VP8RGBToY(int r, int g, int b) { const int kRound = (1 << (YUV_FIX - 1)) + (16 << YUV_FIX); const int luma = 16839 * r + 33059 * g + 6420 * b; @@ -114,13 +245,38 @@ static WEBP_INLINE int VP8RGBToY(int r, int g, int b) { } static WEBP_INLINE int VP8RGBToU(int r, int g, int b) { - return VP8ClipUV(-9719 * r - 19081 * g + 28800 * b); + const int u = -9719 * r - 19081 * g + 28800 * b; + return VP8ClipUV(u); } static WEBP_INLINE int VP8RGBToV(int r, int g, int b) { - return VP8ClipUV(+28800 * r - 24116 * g - 4684 * b); + const int v = +28800 * r - 24116 * g - 4684 * b; + return VP8ClipUV(v); } +#else + +// This JPEG-YUV colorspace, only for comparison! +// These are also 16-bit precision coefficients from Rec.601, but with full +// [0..255] output range. +static WEBP_INLINE int VP8RGBToY(int r, int g, int b) { + const int kRound = (1 << (YUV_FIX - 1)); + const int luma = 19595 * r + 38470 * g + 7471 * b; + return (luma + kRound) >> YUV_FIX; // no need to clip +} + +static WEBP_INLINE int VP8RGBToU(int r, int g, int b) { + const int u = -11058 * r - 21710 * g + 32768 * b; + return VP8ClipUV(u); +} + +static WEBP_INLINE int VP8RGBToV(int r, int g, int b) { + const int v = 32768 * r - 27439 * g - 5329 * b; + return VP8ClipUV(v); +} + +#endif // USE_YUVj + #if defined(__cplusplus) || defined(c_plusplus) } // extern "C" #endif diff --git a/3rdparty/libwebp/enc/alpha.c b/3rdparty/libwebp/enc/alpha.c index 0e519b6c66..e636c96723 100644 --- a/3rdparty/libwebp/enc/alpha.c +++ b/3rdparty/libwebp/enc/alpha.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Alpha-plane compression. @@ -79,18 +81,17 @@ static int EncodeLossless(const uint8_t* const data, int width, int height, WebPConfigInit(&config); config.lossless = 1; config.method = effort_level; // impact is very small - // Set moderate default quality setting for alpha. Higher qualities (80 and - // above) could be very slow. - config.quality = 10.f + 15.f * effort_level; - if (config.quality > 100.f) config.quality = 100.f; + // Set a moderate default quality setting for alpha. + config.quality = 10.f * effort_level; + assert(config.quality >= 0 && config.quality <= 100.f); ok = VP8LBitWriterInit(&tmp_bw, (width * height) >> 3); ok = ok && (VP8LEncodeStream(&config, &picture, &tmp_bw) == VP8_ENC_OK); WebPPictureFree(&picture); if (ok) { - const uint8_t* const data = VP8LBitWriterFinish(&tmp_bw); - const size_t data_size = VP8LBitWriterNumBytes(&tmp_bw); - VP8BitWriterAppend(bw, data, data_size); + const uint8_t* const buffer = VP8LBitWriterFinish(&tmp_bw); + const size_t buffer_size = VP8LBitWriterNumBytes(&tmp_bw); + VP8BitWriterAppend(bw, buffer, buffer_size); } VP8LBitWriterDestroy(&tmp_bw); return ok && !bw->error_; @@ -128,8 +129,8 @@ static int EncodeAlphaInternal(const uint8_t* const data, int width, int height, VP8BitWriterAppend(bw, &header, ALPHA_HEADER_LEN); filter_func = WebPFilters[filter]; - if (filter_func) { - filter_func(data, width, height, 1, width, tmp_alpha); + if (filter_func != NULL) { + filter_func(data, width, height, width, tmp_alpha); alpha_src = tmp_alpha; } else { alpha_src = data; @@ -157,6 +158,25 @@ static void CopyPlane(const uint8_t* src, int src_stride, } } +static int GetNumColors(const uint8_t* data, int width, int height, + int stride) { + int j; + int colors = 0; + uint8_t color[256] = { 0 }; + + for (j = 0; j < height; ++j) { + int i; + const uint8_t* const p = data + j * stride; + for (i = 0; i < width; ++i) { + color[p[i]] = 1; + } + } + for (j = 0; j < 256; ++j) { + if (color[j] > 0) ++colors; + } + return colors; +} + static int EncodeAlpha(VP8Encoder* const enc, int quality, int method, int filter, int effort_level, @@ -208,18 +228,32 @@ static int EncodeAlpha(VP8Encoder* const enc, VP8BitWriter bw; int test_filter; uint8_t* filtered_alpha = NULL; + int try_filter_none = (effort_level > 3); - // We always test WEBP_FILTER_NONE first. - ok = EncodeAlphaInternal(quant_alpha, width, height, - method, WEBP_FILTER_NONE, reduce_levels, - effort_level, NULL, &bw, pic->stats); - if (!ok) { - VP8BitWriterWipeOut(&bw); - goto End; + if (filter == WEBP_FILTER_FAST) { // Quick estimate of the best candidate. + const int kMinColorsForFilterNone = 16; + const int kMaxColorsForFilterNone = 192; + const int num_colors = GetNumColors(quant_alpha, width, height, width); + // For low number of colors, NONE yeilds better compression. + filter = (num_colors <= kMinColorsForFilterNone) ? WEBP_FILTER_NONE : + EstimateBestFilter(quant_alpha, width, height, width); + // For large number of colors, try FILTER_NONE in addition to the best + // filter as well. + if (num_colors > kMaxColorsForFilterNone) { + try_filter_none = 1; + } } - if (filter == WEBP_FILTER_FAST) { // Quick estimate of a second candidate? - filter = EstimateBestFilter(quant_alpha, width, height, width); + // Test for WEBP_FILTER_NONE for higher effort levels. + if (try_filter_none || filter == WEBP_FILTER_NONE) { + ok = EncodeAlphaInternal(quant_alpha, width, height, + method, WEBP_FILTER_NONE, reduce_levels, + effort_level, NULL, &bw, pic->stats); + + if (!ok) { + VP8BitWriterWipeOut(&bw); + goto End; + } } // Stop? if (filter == WEBP_FILTER_NONE) { @@ -235,11 +269,14 @@ static int EncodeAlpha(VP8Encoder* const enc, // Try the other mode(s). { WebPAuxStats best_stats; - size_t best_score = VP8BitWriterSize(&bw); + size_t best_score = try_filter_none ? + VP8BitWriterSize(&bw) : (size_t)~0U; + int wipe_tmp_bw = try_filter_none; memset(&best_stats, 0, sizeof(best_stats)); // prevent spurious warning if (pic->stats != NULL) best_stats = *pic->stats; - for (test_filter = WEBP_FILTER_HORIZONTAL; + for (test_filter = + try_filter_none ? WEBP_FILTER_HORIZONTAL : WEBP_FILTER_NONE; ok && (test_filter <= WEBP_FILTER_GRADIENT); ++test_filter) { VP8BitWriter tmp_bw; @@ -263,7 +300,10 @@ static int EncodeAlpha(VP8Encoder* const enc, } else { VP8BitWriterWipeOut(&bw); } - VP8BitWriterWipeOut(&tmp_bw); + if (wipe_tmp_bw) { + VP8BitWriterWipeOut(&tmp_bw); + } + wipe_tmp_bw = 1; // For next filter trial for WEBP_FILTER_BEST. } if (pic->stats != NULL) *pic->stats = best_stats; } @@ -287,42 +327,80 @@ static int EncodeAlpha(VP8Encoder* const enc, //------------------------------------------------------------------------------ // Main calls +static int CompressAlphaJob(VP8Encoder* const enc, void* dummy) { + const WebPConfig* config = enc->config_; + uint8_t* alpha_data = NULL; + size_t alpha_size = 0; + const int effort_level = config->method; // maps to [0..6] + const WEBP_FILTER_TYPE filter = + (config->alpha_filtering == 0) ? WEBP_FILTER_NONE : + (config->alpha_filtering == 1) ? WEBP_FILTER_FAST : + WEBP_FILTER_BEST; + if (!EncodeAlpha(enc, config->alpha_quality, config->alpha_compression, + filter, effort_level, &alpha_data, &alpha_size)) { + return 0; + } + if (alpha_size != (uint32_t)alpha_size) { // Sanity check. + free(alpha_data); + return 0; + } + enc->alpha_data_size_ = (uint32_t)alpha_size; + enc->alpha_data_ = alpha_data; + (void)dummy; + return 1; +} + void VP8EncInitAlpha(VP8Encoder* const enc) { enc->has_alpha_ = WebPPictureHasTransparency(enc->pic_); enc->alpha_data_ = NULL; enc->alpha_data_size_ = 0; + if (enc->thread_level_ > 0) { + WebPWorker* const worker = &enc->alpha_worker_; + WebPWorkerInit(worker); + worker->data1 = enc; + worker->data2 = NULL; + worker->hook = (WebPWorkerHook)CompressAlphaJob; + } +} + +int VP8EncStartAlpha(VP8Encoder* const enc) { + if (enc->has_alpha_) { + if (enc->thread_level_ > 0) { + WebPWorker* const worker = &enc->alpha_worker_; + if (!WebPWorkerReset(worker)) { // Makes sure worker is good to go. + return 0; + } + WebPWorkerLaunch(worker); + return 1; + } else { + return CompressAlphaJob(enc, NULL); // just do the job right away + } + } + return 1; } int VP8EncFinishAlpha(VP8Encoder* const enc) { if (enc->has_alpha_) { - const WebPConfig* config = enc->config_; - uint8_t* tmp_data = NULL; - size_t tmp_size = 0; - const int effort_level = config->method; // maps to [0..6] - const WEBP_FILTER_TYPE filter = - (config->alpha_filtering == 0) ? WEBP_FILTER_NONE : - (config->alpha_filtering == 1) ? WEBP_FILTER_FAST : - WEBP_FILTER_BEST; - - if (!EncodeAlpha(enc, config->alpha_quality, config->alpha_compression, - filter, effort_level, &tmp_data, &tmp_size)) { - return 0; + if (enc->thread_level_ > 0) { + WebPWorker* const worker = &enc->alpha_worker_; + if (!WebPWorkerSync(worker)) return 0; // error } - if (tmp_size != (uint32_t)tmp_size) { // Sanity check. - free(tmp_data); - return 0; - } - enc->alpha_data_size_ = (uint32_t)tmp_size; - enc->alpha_data_ = tmp_data; } return WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); } -void VP8EncDeleteAlpha(VP8Encoder* const enc) { +int VP8EncDeleteAlpha(VP8Encoder* const enc) { + int ok = 1; + if (enc->thread_level_ > 0) { + WebPWorker* const worker = &enc->alpha_worker_; + ok = WebPWorkerSync(worker); // finish anything left in flight + WebPWorkerEnd(worker); // still need to end the worker, even if !ok + } free(enc->alpha_data_); enc->alpha_data_ = NULL; enc->alpha_data_size_ = 0; enc->has_alpha_ = 0; + return ok; } #if defined(__cplusplus) || defined(c_plusplus) diff --git a/3rdparty/libwebp/enc/analysis.c b/3rdparty/libwebp/enc/analysis.c index 22cfb492e7..4ff3edd2a7 100644 --- a/3rdparty/libwebp/enc/analysis.c +++ b/3rdparty/libwebp/enc/analysis.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Macroblock analysis @@ -23,10 +25,6 @@ extern "C" { #define MAX_ITERS_K_MEANS 6 -static int ClipAlpha(int alpha) { - return alpha < 0 ? 0 : alpha > 255 ? 255 : alpha; -} - //------------------------------------------------------------------------------ // Smooth the segment map by replacing isolated block by the majority of its // neighbours. @@ -72,50 +70,10 @@ static void SmoothSegmentMap(VP8Encoder* const enc) { } //------------------------------------------------------------------------------ -// Finalize Segment probability based on the coding tree - -static int GetProba(int a, int b) { - int proba; - const int total = a + b; - if (total == 0) return 255; // that's the default probability. - proba = (255 * a + total / 2) / total; - return proba; -} - -static void SetSegmentProbas(VP8Encoder* const enc) { - int p[NUM_MB_SEGMENTS] = { 0 }; - int n; - - for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { - const VP8MBInfo* const mb = &enc->mb_info_[n]; - p[mb->segment_]++; - } - if (enc->pic_->stats) { - for (n = 0; n < NUM_MB_SEGMENTS; ++n) { - enc->pic_->stats->segment_size[n] = p[n]; - } - } - if (enc->segment_hdr_.num_segments_ > 1) { - uint8_t* const probas = enc->proba_.segments_; - probas[0] = GetProba(p[0] + p[1], p[2] + p[3]); - probas[1] = GetProba(p[0], p[1]); - probas[2] = GetProba(p[2], p[3]); - - enc->segment_hdr_.update_map_ = - (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255); - enc->segment_hdr_.size_ = - p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) + - p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) + - p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) + - p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2])); - } else { - enc->segment_hdr_.update_map_ = 0; - enc->segment_hdr_.size_ = 0; - } -} +// set segment susceptibility alpha_ / beta_ static WEBP_INLINE int clip(int v, int m, int M) { - return v < m ? m : v > M ? M : v; + return (v < m) ? m : (v > M) ? M : v; } static void SetSegmentAlphas(VP8Encoder* const enc, @@ -141,23 +99,64 @@ static void SetSegmentAlphas(VP8Encoder* const enc, } } +//------------------------------------------------------------------------------ +// Compute susceptibility based on DCT-coeff histograms: +// the higher, the "easier" the macroblock is to compress. + +#define MAX_ALPHA 255 // 8b of precision for susceptibilities. +#define ALPHA_SCALE (2 * MAX_ALPHA) // scaling factor for alpha. +#define DEFAULT_ALPHA (-1) +#define IS_BETTER_ALPHA(alpha, best_alpha) ((alpha) > (best_alpha)) + +static int FinalAlphaValue(int alpha) { + alpha = MAX_ALPHA - alpha; + return clip(alpha, 0, MAX_ALPHA); +} + +static int GetAlpha(const VP8Histogram* const histo) { + int max_value = 0, last_non_zero = 1; + int k; + int alpha; + for (k = 0; k <= MAX_COEFF_THRESH; ++k) { + const int value = histo->distribution[k]; + if (value > 0) { + if (value > max_value) max_value = value; + last_non_zero = k; + } + } + // 'alpha' will later be clipped to [0..MAX_ALPHA] range, clamping outer + // values which happen to be mostly noise. This leaves the maximum precision + // for handling the useful small values which contribute most. + alpha = (max_value > 1) ? ALPHA_SCALE * last_non_zero / max_value : 0; + return alpha; +} + +static void MergeHistograms(const VP8Histogram* const in, + VP8Histogram* const out) { + int i; + for (i = 0; i <= MAX_COEFF_THRESH; ++i) { + out->distribution[i] += in->distribution[i]; + } +} + //------------------------------------------------------------------------------ // Simplified k-Means, to assign Nb segments based on alpha-histogram -static void AssignSegments(VP8Encoder* const enc, const int alphas[256]) { +static void AssignSegments(VP8Encoder* const enc, + const int alphas[MAX_ALPHA + 1]) { const int nb = enc->segment_hdr_.num_segments_; int centers[NUM_MB_SEGMENTS]; int weighted_average = 0; - int map[256]; + int map[MAX_ALPHA + 1]; int a, n, k; - int min_a = 0, max_a = 255, range_a; + int min_a = 0, max_a = MAX_ALPHA, range_a; // 'int' type is ok for histo, and won't overflow int accum[NUM_MB_SEGMENTS], dist_accum[NUM_MB_SEGMENTS]; // bracket the input - for (n = 0; n < 256 && alphas[n] == 0; ++n) {} + for (n = 0; n <= MAX_ALPHA && alphas[n] == 0; ++n) {} min_a = n; - for (n = 255; n > min_a && alphas[n] == 0; --n) {} + for (n = MAX_ALPHA; n > min_a && alphas[n] == 0; --n) {} max_a = n; range_a = max_a - min_a; @@ -210,7 +209,7 @@ static void AssignSegments(VP8Encoder* const enc, const int alphas[256]) { VP8MBInfo* const mb = &enc->mb_info_[n]; const int alpha = mb->alpha_; mb->segment_ = map[alpha]; - mb->alpha_ = centers[map[alpha]]; // just for the record. + mb->alpha_ = centers[map[alpha]]; // for the record. } if (nb > 1) { @@ -218,7 +217,6 @@ static void AssignSegments(VP8Encoder* const enc, const int alphas[256]) { if (smooth) SmoothSegmentMap(enc); } - SetSegmentProbas(enc); // Assign final proba SetSegmentAlphas(enc, centers, weighted_average); // pick some alphas. } @@ -227,24 +225,32 @@ static void AssignSegments(VP8Encoder* const enc, const int alphas[256]) { // susceptibility and set best modes for this macroblock. // Segment assignment is done later. -// Number of modes to inspect for alpha_ evaluation. For high-quality settings, -// we don't need to test all the possible modes during the analysis phase. +// Number of modes to inspect for alpha_ evaluation. For high-quality settings +// (method >= FAST_ANALYSIS_METHOD) we don't need to test all the possible modes +// during the analysis phase. +#define FAST_ANALYSIS_METHOD 4 // method above which we do partial analysis #define MAX_INTRA16_MODE 2 #define MAX_INTRA4_MODE 2 #define MAX_UV_MODE 2 static int MBAnalyzeBestIntra16Mode(VP8EncIterator* const it) { - const int max_mode = (it->enc_->method_ >= 3) ? MAX_INTRA16_MODE : 4; + const int max_mode = + (it->enc_->method_ >= FAST_ANALYSIS_METHOD) ? MAX_INTRA16_MODE + : NUM_PRED_MODES; int mode; - int best_alpha = -1; + int best_alpha = DEFAULT_ALPHA; int best_mode = 0; VP8MakeLuma16Preds(it); for (mode = 0; mode < max_mode; ++mode) { - const int alpha = VP8CollectHistogram(it->yuv_in_ + Y_OFF, - it->yuv_p_ + VP8I16ModeOffsets[mode], - 0, 16); - if (alpha > best_alpha) { + VP8Histogram histo = { { 0 } }; + int alpha; + + VP8CollectHistogram(it->yuv_in_ + Y_OFF, + it->yuv_p_ + VP8I16ModeOffsets[mode], + 0, 16, &histo); + alpha = GetAlpha(&histo); + if (IS_BETTER_ALPHA(alpha, best_alpha)) { best_alpha = alpha; best_mode = mode; } @@ -256,46 +262,63 @@ static int MBAnalyzeBestIntra16Mode(VP8EncIterator* const it) { static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it, int best_alpha) { uint8_t modes[16]; - const int max_mode = (it->enc_->method_ >= 3) ? MAX_INTRA4_MODE : NUM_BMODES; - int i4_alpha = 0; + const int max_mode = + (it->enc_->method_ >= FAST_ANALYSIS_METHOD) ? MAX_INTRA4_MODE + : NUM_BMODES; + int i4_alpha; + VP8Histogram total_histo = { { 0 } }; + int cur_histo = 0; + VP8IteratorStartI4(it); do { int mode; - int best_mode_alpha = -1; + int best_mode_alpha = DEFAULT_ALPHA; + VP8Histogram histos[2]; const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_]; VP8MakeIntra4Preds(it); for (mode = 0; mode < max_mode; ++mode) { - const int alpha = VP8CollectHistogram(src, - it->yuv_p_ + VP8I4ModeOffsets[mode], - 0, 1); - if (alpha > best_mode_alpha) { + int alpha; + + memset(&histos[cur_histo], 0, sizeof(histos[cur_histo])); + VP8CollectHistogram(src, it->yuv_p_ + VP8I4ModeOffsets[mode], + 0, 1, &histos[cur_histo]); + alpha = GetAlpha(&histos[cur_histo]); + if (IS_BETTER_ALPHA(alpha, best_mode_alpha)) { best_mode_alpha = alpha; modes[it->i4_] = mode; + cur_histo ^= 1; // keep track of best histo so far. } } - i4_alpha += best_mode_alpha; + // accumulate best histogram + MergeHistograms(&histos[cur_histo ^ 1], &total_histo); // Note: we reuse the original samples for predictors } while (VP8IteratorRotateI4(it, it->yuv_in_ + Y_OFF)); - if (i4_alpha > best_alpha) { + i4_alpha = GetAlpha(&total_histo); + if (IS_BETTER_ALPHA(i4_alpha, best_alpha)) { VP8SetIntra4Mode(it, modes); - best_alpha = ClipAlpha(i4_alpha); + best_alpha = i4_alpha; } return best_alpha; } static int MBAnalyzeBestUVMode(VP8EncIterator* const it) { - int best_alpha = -1; + int best_alpha = DEFAULT_ALPHA; int best_mode = 0; - const int max_mode = (it->enc_->method_ >= 3) ? MAX_UV_MODE : 4; + const int max_mode = + (it->enc_->method_ >= FAST_ANALYSIS_METHOD) ? MAX_UV_MODE + : NUM_PRED_MODES; int mode; VP8MakeChroma8Preds(it); for (mode = 0; mode < max_mode; ++mode) { - const int alpha = VP8CollectHistogram(it->yuv_in_ + U_OFF, - it->yuv_p_ + VP8UVModeOffsets[mode], - 16, 16 + 4 + 4); - if (alpha > best_alpha) { + VP8Histogram histo = { { 0 } }; + int alpha; + VP8CollectHistogram(it->yuv_in_ + U_OFF, + it->yuv_p_ + VP8UVModeOffsets[mode], + 16, 16 + 4 + 4, &histo); + alpha = GetAlpha(&histo); + if (IS_BETTER_ALPHA(alpha, best_alpha)) { best_alpha = alpha; best_mode = mode; } @@ -305,7 +328,8 @@ static int MBAnalyzeBestUVMode(VP8EncIterator* const it) { } static void MBAnalyze(VP8EncIterator* const it, - int alphas[256], int* const uv_alpha) { + int alphas[MAX_ALPHA + 1], + int* const alpha, int* const uv_alpha) { const VP8Encoder* const enc = it->enc_; int best_alpha, best_uv_alpha; @@ -314,7 +338,7 @@ static void MBAnalyze(VP8EncIterator* const it, VP8SetSegment(it, 0); // default segment, spec-wise. best_alpha = MBAnalyzeBestIntra16Mode(it); - if (enc->method_ != 3) { + if (enc->method_ >= 5) { // We go and make a fast decision for intra4/intra16. // It's usually not a good and definitive pick, but helps seeding the stats // about level bit-cost. @@ -324,10 +348,22 @@ static void MBAnalyze(VP8EncIterator* const it, best_uv_alpha = MBAnalyzeBestUVMode(it); // Final susceptibility mix - best_alpha = (best_alpha + best_uv_alpha + 1) / 2; + best_alpha = (3 * best_alpha + best_uv_alpha + 2) >> 2; + best_alpha = FinalAlphaValue(best_alpha); alphas[best_alpha]++; + it->mb_->alpha_ = best_alpha; // for later remapping. + + // Accumulate for later complexity analysis. + *alpha += best_alpha; // mixed susceptibility (not just luma) *uv_alpha += best_uv_alpha; - it->mb_->alpha_ = best_alpha; // Informative only. +} + +static void DefaultMBInfo(VP8MBInfo* const mb) { + mb->type_ = 1; // I16x16 + mb->uv_mode_ = 0; + mb->skip_ = 0; // not skipped + mb->segment_ = 0; // default segment + mb->alpha_ = 0; } //------------------------------------------------------------------------------ @@ -340,22 +376,43 @@ static void MBAnalyze(VP8EncIterator* const it, // and decide intra4/intra16, but that's usually almost always a bad choice at // this stage. +static void ResetAllMBInfo(VP8Encoder* const enc) { + int n; + for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { + DefaultMBInfo(&enc->mb_info_[n]); + } + // Default susceptibilities. + enc->dqm_[0].alpha_ = 0; + enc->dqm_[0].beta_ = 0; + // Note: we can't compute this alpha_ / uv_alpha_. + WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); +} + int VP8EncAnalyze(VP8Encoder* const enc) { int ok = 1; - int alphas[256] = { 0 }; - VP8EncIterator it; - - VP8IteratorInit(enc, &it); + const int do_segments = + enc->config_->emulate_jpeg_size || // We need the complexity evaluation. + (enc->segment_hdr_.num_segments_ > 1) || + (enc->method_ == 0); // for method 0, we need preds_[] to be filled. + enc->alpha_ = 0; enc->uv_alpha_ = 0; - do { - VP8IteratorImport(&it); - MBAnalyze(&it, alphas, &enc->uv_alpha_); - ok = VP8IteratorProgress(&it, 20); - // Let's pretend we have perfect lossless reconstruction. - } while (ok && VP8IteratorNext(&it, it.yuv_in_)); - enc->uv_alpha_ /= enc->mb_w_ * enc->mb_h_; - if (ok) AssignSegments(enc, alphas); + if (do_segments) { + int alphas[MAX_ALPHA + 1] = { 0 }; + VP8EncIterator it; + VP8IteratorInit(enc, &it); + do { + VP8IteratorImport(&it); + MBAnalyze(&it, alphas, &enc->alpha_, &enc->uv_alpha_); + ok = VP8IteratorProgress(&it, 20); + // Let's pretend we have perfect lossless reconstruction. + } while (ok && VP8IteratorNext(&it, it.yuv_in_)); + enc->alpha_ /= enc->mb_w_ * enc->mb_h_; + enc->uv_alpha_ /= enc->mb_w_ * enc->mb_h_; + if (ok) AssignSegments(enc, alphas); + } else { // Use only one default segment. + ResetAllMBInfo(enc); + } return ok; } diff --git a/3rdparty/libwebp/enc/backward_references.c b/3rdparty/libwebp/enc/backward_references.c index fd30f307df..db4f430df5 100644 --- a/3rdparty/libwebp/enc/backward_references.c +++ b/3rdparty/libwebp/enc/backward_references.c @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Author: Jyrki Alakuijala (jyrki@google.com) @@ -141,74 +143,86 @@ static void HashChainInsert(HashChain* const p, p->hash_to_first_index_[hash_code] = pos; } +static void GetParamsForHashChainFindCopy(int quality, int xsize, + int cache_bits, int* window_size, + int* iter_pos, int* iter_limit) { + const int iter_mult = (quality < 27) ? 1 : 1 + ((quality - 27) >> 4); + const int iter_neg = -iter_mult * (quality >> 1); + // Limit the backward-ref window size for lower qualities. + const int max_window_size = (quality > 50) ? WINDOW_SIZE + : (quality > 25) ? (xsize << 8) + : (xsize << 4); + assert(xsize > 0); + *window_size = (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE + : max_window_size; + *iter_pos = 8 + (quality >> 3); + // For lower entropy images, the rigourous search loop in HashChainFindCopy + // can be relaxed. + *iter_limit = (cache_bits > 0) ? iter_neg : iter_neg / 2; +} + static int HashChainFindCopy(const HashChain* const p, - int quality, int index, int xsize, + int base_position, int xsize_signed, const uint32_t* const argb, int maxlen, + int window_size, int iter_pos, int iter_limit, int* const distance_ptr, int* const length_ptr) { - const uint64_t hash_code = GetPixPairHash64(&argb[index]); - int prev_length = 0; - int64_t best_val = 0; - int best_length = 0; - int best_distance = 0; - const uint32_t* const argb_start = argb + index; - const int iter_min_mult = (quality < 50) ? 2 : (quality < 75) ? 4 : 8; - const int iter_min = -quality * iter_min_mult; - int iter_cnt = 10 + (quality >> 1); - const int min_pos = (index > WINDOW_SIZE) ? index - WINDOW_SIZE : 0; + const uint32_t* const argb_start = argb + base_position; + uint64_t best_val = 0; + uint32_t best_length = 1; + uint32_t best_distance = 0; + const uint32_t xsize = (uint32_t)xsize_signed; + const int min_pos = + (base_position > window_size) ? base_position - window_size : 0; int pos; - assert(xsize > 0); - for (pos = p->hash_to_first_index_[hash_code]; + for (pos = p->hash_to_first_index_[GetPixPairHash64(argb_start)]; pos >= min_pos; pos = p->chain_[pos]) { - int64_t val; - int curr_length; - if (iter_cnt < 0) { - if (iter_cnt < iter_min || best_val >= 0xff0000) { + uint64_t val; + uint32_t curr_length; + uint32_t distance; + if (iter_pos < 0) { + if (iter_pos < iter_limit || best_val >= 0xff0000) { break; } } - --iter_cnt; - if (best_length != 0 && - argb[pos + best_length - 1] != argb_start[best_length - 1]) { + --iter_pos; + if (argb[pos + best_length - 1] != argb_start[best_length - 1]) { continue; } curr_length = FindMatchLength(argb + pos, argb_start, maxlen); - if (curr_length < prev_length) { + if (curr_length < best_length) { continue; } - val = 65536 * curr_length; + distance = (uint32_t)(base_position - pos); + val = curr_length << 16; // Favoring 2d locality here gives savings for certain images. - if (index - pos < 9 * xsize) { - const int y = (index - pos) / xsize; - int x = (index - pos) % xsize; - if (x > xsize / 2) { + if (distance < 9 * xsize) { + const uint32_t y = distance / xsize; + uint32_t x = distance % xsize; + if (x > (xsize >> 1)) { x = xsize - x; } - if (x <= 7 && x >= -8) { + if (x <= 7) { + val += 9 * 9 + 9 * 9; val -= y * y + x * x; - } else { - val -= 9 * 9 + 9 * 9; } - } else { - val -= 9 * 9 + 9 * 9; } if (best_val < val) { - prev_length = curr_length; best_val = val; best_length = curr_length; - best_distance = index - pos; + best_distance = distance; if (curr_length >= MAX_LENGTH) { break; } - if ((best_distance == 1 || best_distance == xsize) && + if ((best_distance == 1 || distance == xsize) && best_length >= 128) { break; } } } - *distance_ptr = best_distance; + *distance_ptr = (int)best_distance; *length_ptr = best_length; return (best_length >= MIN_LENGTH); } @@ -257,6 +271,9 @@ static int BackwardReferencesHashChain(int xsize, int ysize, const int pix_count = xsize * ysize; HashChain* const hash_chain = (HashChain*)malloc(sizeof(*hash_chain)); VP8LColorCache hashers; + int window_size = WINDOW_SIZE; + int iter_pos = 1; + int iter_limit = -1; if (hash_chain == NULL) return 0; if (use_color_cache) { @@ -267,6 +284,8 @@ static int BackwardReferencesHashChain(int xsize, int ysize, if (!HashChainInit(hash_chain, pix_count)) goto Error; refs->size = 0; + GetParamsForHashChainFindCopy(quality, xsize, cache_bits, + &window_size, &iter_pos, &iter_limit); for (i = 0; i < pix_count; ) { // Alternative#1: Code the pixels starting at 'i' using backward reference. int offset = 0; @@ -276,7 +295,8 @@ static int BackwardReferencesHashChain(int xsize, int ysize, if (maxlen > MAX_LENGTH) { maxlen = MAX_LENGTH; } - HashChainFindCopy(hash_chain, quality, i, xsize, argb, maxlen, + HashChainFindCopy(hash_chain, i, xsize, argb, maxlen, + window_size, iter_pos, iter_limit, &offset, &len); } if (len >= MIN_LENGTH) { @@ -291,8 +311,9 @@ static int BackwardReferencesHashChain(int xsize, int ysize, if (maxlen > MAX_LENGTH) { maxlen = MAX_LENGTH; } - HashChainFindCopy(hash_chain, quality, - i + 1, xsize, argb, maxlen, &offset2, &len2); + HashChainFindCopy(hash_chain, i + 1, xsize, argb, maxlen, + window_size, iter_pos, iter_limit, + &offset2, &len2); if (len2 > len + 1) { const uint32_t pixel = argb[i]; // Alternative#2 is a better match. So push pixel at 'i' as literal. @@ -362,7 +383,8 @@ typedef struct { static int BackwardReferencesTraceBackwards( int xsize, int ysize, int recursive_cost_model, - const uint32_t* const argb, int cache_bits, VP8LBackwardRefs* const refs); + const uint32_t* const argb, int quality, int cache_bits, + VP8LBackwardRefs* const refs); static void ConvertPopulationCountTableToBitEstimates( int num_symbols, const int population_counts[], double output[]) { @@ -387,17 +409,16 @@ static void ConvertPopulationCountTableToBitEstimates( static int CostModelBuild(CostModel* const m, int xsize, int ysize, int recursion_level, const uint32_t* const argb, - int cache_bits) { + int quality, int cache_bits) { int ok = 0; VP8LHistogram histo; VP8LBackwardRefs refs; - const int quality = 100; if (!VP8LBackwardRefsAlloc(&refs, xsize * ysize)) goto Error; if (recursion_level > 0) { if (!BackwardReferencesTraceBackwards(xsize, ysize, recursion_level - 1, - argb, cache_bits, &refs)) { + argb, quality, cache_bits, &refs)) { goto Error; } } else { @@ -452,11 +473,10 @@ static WEBP_INLINE double GetDistanceCost(const CostModel* const m, static int BackwardReferencesHashChainDistanceOnly( int xsize, int ysize, int recursive_cost_model, const uint32_t* const argb, - int cache_bits, uint32_t* const dist_array) { + int quality, int cache_bits, uint32_t* const dist_array) { int i; int ok = 0; int cc_init = 0; - const int quality = 100; const int pix_count = xsize * ysize; const int use_color_cache = (cache_bits > 0); float* const cost = @@ -466,6 +486,10 @@ static int BackwardReferencesHashChainDistanceOnly( VP8LColorCache hashers; const double mul0 = (recursive_cost_model != 0) ? 1.0 : 0.68; const double mul1 = (recursive_cost_model != 0) ? 1.0 : 0.82; + const int min_distance_code = 2; // TODO(vikasa): tune as function of quality + int window_size = WINDOW_SIZE; + int iter_pos = 1; + int iter_limit = -1; if (cost == NULL || cost_model == NULL || hash_chain == NULL) goto Error; @@ -477,7 +501,7 @@ static int BackwardReferencesHashChainDistanceOnly( } if (!CostModelBuild(cost_model, xsize, ysize, recursive_cost_model, argb, - cache_bits)) { + quality, cache_bits)) { goto Error; } @@ -486,6 +510,8 @@ static int BackwardReferencesHashChainDistanceOnly( // We loop one pixel at a time, but store all currently best points to // non-processed locations from this point. dist_array[0] = 0; + GetParamsForHashChainFindCopy(quality, xsize, cache_bits, + &window_size, &iter_pos, &iter_limit); for (i = 0; i < pix_count; ++i) { double prev_cost = 0.0; int shortmax; @@ -500,7 +526,8 @@ static int BackwardReferencesHashChainDistanceOnly( if (maxlen > pix_count - i) { maxlen = pix_count - i; } - HashChainFindCopy(hash_chain, quality, i, xsize, argb, maxlen, + HashChainFindCopy(hash_chain, i, xsize, argb, maxlen, + window_size, iter_pos, iter_limit, &offset, &len); } if (len >= MIN_LENGTH) { @@ -517,7 +544,7 @@ static int BackwardReferencesHashChainDistanceOnly( } // This if is for speedup only. It roughly doubles the speed, and // makes compression worse by .1 %. - if (len >= 128 && code < 2) { + if (len >= 128 && code <= min_distance_code) { // Long copy for short distances, let's skip the middle // lookups for better copies. // 1) insert the hashes. @@ -528,10 +555,10 @@ static int BackwardReferencesHashChainDistanceOnly( } // 2) Add to the hash_chain (but cannot add the last pixel) { - const int last = (len < pix_count - 1 - i) ? len - : pix_count - 1 - i; - for (k = 0; k < last; ++k) { - HashChainInsert(hash_chain, &argb[i + k], i + k); + const int last = (len + i < pix_count - 1) ? len + i + : pix_count - 1; + for (k = i; k < last; ++k) { + HashChainInsert(hash_chain, &argb[k], k); } } // 3) jump. @@ -571,40 +598,30 @@ Error: return ok; } -static int TraceBackwards(const uint32_t* const dist_array, - int dist_array_size, - uint32_t** const chosen_path, - int* const chosen_path_size) { - int i; - // Count how many. - int count = 0; - for (i = dist_array_size - 1; i >= 0; ) { - int k = dist_array[i]; - assert(k >= 1); - ++count; - i -= k; +// We pack the path at the end of *dist_array and return +// a pointer to this part of the array. Example: +// dist_array = [1x2xx3x2] => packed [1x2x1232], chosen_path = [1232] +static void TraceBackwards(uint32_t* const dist_array, + int dist_array_size, + uint32_t** const chosen_path, + int* const chosen_path_size) { + uint32_t* path = dist_array + dist_array_size; + uint32_t* cur = dist_array + dist_array_size - 1; + while (cur >= dist_array) { + const int k = *cur; + --path; + *path = k; + cur -= k; } - // Allocate. - *chosen_path_size = count; - *chosen_path = - (uint32_t*)WebPSafeMalloc((uint64_t)count, sizeof(**chosen_path)); - if (*chosen_path == NULL) return 0; - - // Write in reverse order. - for (i = dist_array_size - 1; i >= 0; ) { - int k = dist_array[i]; - assert(k >= 1); - (*chosen_path)[--count] = k; - i -= k; - } - return 1; + *chosen_path = path; + *chosen_path_size = (int)(dist_array + dist_array_size - path); } static int BackwardReferencesHashChainFollowChosenPath( - int xsize, int ysize, const uint32_t* const argb, int cache_bits, + int xsize, int ysize, const uint32_t* const argb, + int quality, int cache_bits, const uint32_t* const chosen_path, int chosen_path_size, VP8LBackwardRefs* const refs) { - const int quality = 100; const int pix_count = xsize * ysize; const int use_color_cache = (cache_bits > 0); int size = 0; @@ -613,6 +630,9 @@ static int BackwardReferencesHashChainFollowChosenPath( int ix; int ok = 0; int cc_init = 0; + int window_size = WINDOW_SIZE; + int iter_pos = 1; + int iter_limit = -1; HashChain* hash_chain = (HashChain*)malloc(sizeof(*hash_chain)); VP8LColorCache hashers; @@ -625,13 +645,16 @@ static int BackwardReferencesHashChainFollowChosenPath( } refs->size = 0; + GetParamsForHashChainFindCopy(quality, xsize, cache_bits, + &window_size, &iter_pos, &iter_limit); for (ix = 0; ix < chosen_path_size; ++ix, ++size) { int offset = 0; int len = 0; int maxlen = chosen_path[ix]; if (maxlen != 1) { - HashChainFindCopy(hash_chain, quality, - i, xsize, argb, maxlen, &offset, &len); + HashChainFindCopy(hash_chain, i, xsize, argb, maxlen, + window_size, iter_pos, iter_limit, + &offset, &len); assert(len == maxlen); refs->refs[size] = PixOrCopyCreateCopy(offset, len); if (use_color_cache) { @@ -674,7 +697,7 @@ Error: static int BackwardReferencesTraceBackwards(int xsize, int ysize, int recursive_cost_model, const uint32_t* const argb, - int cache_bits, + int quality, int cache_bits, VP8LBackwardRefs* const refs) { int ok = 0; const int dist_array_size = xsize * ysize; @@ -686,22 +709,18 @@ static int BackwardReferencesTraceBackwards(int xsize, int ysize, if (dist_array == NULL) goto Error; if (!BackwardReferencesHashChainDistanceOnly( - xsize, ysize, recursive_cost_model, argb, cache_bits, dist_array)) { + xsize, ysize, recursive_cost_model, argb, quality, cache_bits, + dist_array)) { goto Error; } - if (!TraceBackwards(dist_array, dist_array_size, - &chosen_path, &chosen_path_size)) { - goto Error; - } - free(dist_array); // no need to retain this memory any longer - dist_array = NULL; + TraceBackwards(dist_array, dist_array_size, &chosen_path, &chosen_path_size); if (!BackwardReferencesHashChainFollowChosenPath( - xsize, ysize, argb, cache_bits, chosen_path, chosen_path_size, refs)) { + xsize, ysize, argb, quality, cache_bits, chosen_path, chosen_path_size, + refs)) { goto Error; } ok = 1; Error: - free(chosen_path); free(dist_array); return ok; } @@ -761,18 +780,20 @@ int VP8LGetBackwardReferences(int width, int height, // Choose appropriate backward reference. if (lz77_is_useful) { - // TraceBackwards is costly. Run it for higher qualities. - const int try_lz77_trace_backwards = (quality >= 75); + // TraceBackwards is costly. Don't execute it at lower quality (q <= 10). + const int try_lz77_trace_backwards = (quality > 10); *best = refs_lz77; // default guess: lz77 is better VP8LClearBackwardRefs(&refs_rle); if (try_lz77_trace_backwards) { - const int recursion_level = (num_pix < 320 * 200) ? 1 : 0; + // Set recursion level for large images using a color cache. + const int recursion_level = + (num_pix < 320 * 200) && (cache_bits > 0) ? 1 : 0; VP8LBackwardRefs refs_trace; if (!VP8LBackwardRefsAlloc(&refs_trace, num_pix)) { goto End; } - if (BackwardReferencesTraceBackwards( - width, height, recursion_level, argb, cache_bits, &refs_trace)) { + if (BackwardReferencesTraceBackwards(width, height, recursion_level, argb, + quality, cache_bits, &refs_trace)) { VP8LClearBackwardRefs(&refs_lz77); *best = refs_trace; } diff --git a/3rdparty/libwebp/enc/backward_references.h b/3rdparty/libwebp/enc/backward_references.h index 91c03361ed..b0d18135f7 100644 --- a/3rdparty/libwebp/enc/backward_references.h +++ b/3rdparty/libwebp/enc/backward_references.h @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Author: Jyrki Alakuijala (jyrki@google.com) @@ -35,7 +37,8 @@ extern "C" { #if defined(__GNUC__) && \ ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) static WEBP_INLINE int BitsLog2Floor(uint32_t n) { - return n == 0 ? -1 : 31 ^ __builtin_clz(n); + assert(n != 0); + return 31 ^ __builtin_clz(n); } #elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) #include @@ -43,15 +46,18 @@ static WEBP_INLINE int BitsLog2Floor(uint32_t n) { static WEBP_INLINE int BitsLog2Floor(uint32_t n) { unsigned long first_set_bit; - return _BitScanReverse(&first_set_bit, n) ? first_set_bit : -1; + assert(n != 0); + _BitScanReverse(&first_set_bit, n); + return first_set_bit; } #else +// Returns (int)floor(log2(n)). n must be > 0. static WEBP_INLINE int BitsLog2Floor(uint32_t n) { int log = 0; uint32_t value = n; int i; - if (value == 0) return -1; + assert(n != 0); for (i = 4; i >= 0; --i) { const int shift = (1 << i); const uint32_t x = value >> shift; @@ -65,11 +71,11 @@ static WEBP_INLINE int BitsLog2Floor(uint32_t n) { #endif static WEBP_INLINE int VP8LBitsLog2Ceiling(uint32_t n) { - const int floor = BitsLog2Floor(n); + const int log_floor = BitsLog2Floor(n); if (n == (n & ~(n - 1))) // zero or a power of two. - return floor; + return log_floor; else - return floor + 1; + return log_floor + 1; } // Splitting of distance and length codes into prefixes and @@ -78,16 +84,17 @@ static WEBP_INLINE int VP8LBitsLog2Ceiling(uint32_t n) { static WEBP_INLINE void PrefixEncode(int distance, int* const code, int* const extra_bits_count, int* const extra_bits_value) { - // Collect the two most significant bits where the highest bit is 1. - const int highest_bit = BitsLog2Floor(--distance); - // & 0x3f is to make behavior well defined when highest_bit - // does not exist or is the least significant bit. - const int second_highest_bit = - (distance >> ((highest_bit - 1) & 0x3f)) & 1; - *extra_bits_count = (highest_bit > 0) ? (highest_bit - 1) : 0; - *extra_bits_value = distance & ((1 << *extra_bits_count) - 1); - *code = (highest_bit > 0) ? (2 * highest_bit + second_highest_bit) - : (highest_bit == 0) ? 1 : 0; + if (distance > 2) { // Collect the two most significant bits. + const int highest_bit = BitsLog2Floor(--distance); + const int second_highest_bit = (distance >> (highest_bit - 1)) & 1; + *extra_bits_count = highest_bit - 1; + *extra_bits_value = distance & ((1 << *extra_bits_count) - 1); + *code = 2 * highest_bit + second_highest_bit; + } else { + *extra_bits_count = 0; + *extra_bits_value = 0; + *code = (distance == 2) ? 1 : 0; + } } // ----------------------------------------------------------------------------- diff --git a/3rdparty/libwebp/enc/config.c b/3rdparty/libwebp/enc/config.c index 1a26113554..acf96b0f30 100644 --- a/3rdparty/libwebp/enc/config.c +++ b/3rdparty/libwebp/enc/config.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Coding tools configuration @@ -31,9 +33,9 @@ int WebPConfigInitInternal(WebPConfig* config, config->target_PSNR = 0.; config->method = 4; config->sns_strength = 50; - config->filter_strength = 20; // default: light filtering + config->filter_strength = 60; // rather high filtering, helps w/ gradients. config->filter_sharpness = 0; - config->filter_type = 0; // default: simple + config->filter_type = 1; // default: strong (so U/V is filtered too) config->partitions = 0; config->segments = 4; config->pass = 1; @@ -46,6 +48,9 @@ int WebPConfigInitInternal(WebPConfig* config, config->alpha_quality = 100; config->lossless = 0; config->image_hint = WEBP_HINT_DEFAULT; + config->emulate_jpeg_size = 0; + config->thread_level = 0; + config->low_memory = 0; // TODO(skal): tune. switch (preset) { @@ -122,6 +127,12 @@ int WebPValidateConfig(const WebPConfig* config) { return 0; if (config->image_hint >= WEBP_HINT_LAST) return 0; + if (config->emulate_jpeg_size < 0 || config->emulate_jpeg_size > 1) + return 0; + if (config->thread_level < 0 || config->thread_level > 1) + return 0; + if (config->low_memory < 0 || config->low_memory > 1) + return 0; return 1; } diff --git a/3rdparty/libwebp/enc/cost.c b/3rdparty/libwebp/enc/cost.c index 92e0cc713c..d4916d7cd2 100644 --- a/3rdparty/libwebp/enc/cost.c +++ b/3rdparty/libwebp/enc/cost.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Cost tables for level and modes @@ -75,7 +77,7 @@ const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2] = { // fixed costs for coding levels, deduce from the coding tree. // This is only the part that doesn't depend on the probability state. -const uint16_t VP8LevelFixedCosts[2048] = { +const uint16_t VP8LevelFixedCosts[MAX_LEVEL + 1] = { 0, 256, 256, 256, 256, 432, 618, 630, 731, 640, 640, 828, 901, 948, 1021, 1101, 1174, 1221, 1294, 1042, 1085, 1115, 1158, 1202, @@ -359,7 +361,7 @@ void VP8CalculateLevelCosts(VP8Proba* const proba) { for (ctype = 0; ctype < NUM_TYPES; ++ctype) { for (band = 0; band < NUM_BANDS; ++band) { - for(ctx = 0; ctx < NUM_CTX; ++ctx) { + for (ctx = 0; ctx < NUM_CTX; ++ctx) { const uint8_t* const p = proba->coeffs_[ctype][band][ctx]; uint16_t* const table = proba->level_cost_[ctype][band][ctx]; const int cost_base = VP8BitCost(1, p[1]); diff --git a/3rdparty/libwebp/enc/cost.h b/3rdparty/libwebp/enc/cost.h index 09b75b699d..7d7c2c79a2 100644 --- a/3rdparty/libwebp/enc/cost.h +++ b/3rdparty/libwebp/enc/cost.h @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Cost tables for level and modes. @@ -18,7 +20,8 @@ extern "C" { #endif -extern const uint16_t VP8LevelFixedCosts[2048]; // approximate cost per level +// approximate cost per level: +extern const uint16_t VP8LevelFixedCosts[MAX_LEVEL + 1]; extern const uint16_t VP8EntropyCost[256]; // 8bit fixed-point log(p) // Cost of coding one event with probability 'proba'. diff --git a/3rdparty/libwebp/enc/filter.c b/3rdparty/libwebp/enc/filter.c index 7fb78a3949..aae2723d16 100644 --- a/3rdparty/libwebp/enc/filter.c +++ b/3rdparty/libwebp/enc/filter.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Selecting filter level diff --git a/3rdparty/libwebp/enc/frame.c b/3rdparty/libwebp/enc/frame.c index bdd360069b..c56abed75e 100644 --- a/3rdparty/libwebp/enc/frame.c +++ b/3rdparty/libwebp/enc/frame.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // frame coding and analysis @@ -45,10 +47,10 @@ const uint8_t VP8EncBands[16 + 1] = { 0 // sentinel }; -static const uint8_t kCat3[] = { 173, 148, 140 }; -static const uint8_t kCat4[] = { 176, 155, 140, 135 }; -static const uint8_t kCat5[] = { 180, 157, 141, 134, 130 }; -static const uint8_t kCat6[] = +const uint8_t VP8Cat3[] = { 173, 148, 140 }; +const uint8_t VP8Cat4[] = { 176, 155, 140, 135 }; +const uint8_t VP8Cat5[] = { 180, 157, 141, 134, 130 }; +const uint8_t VP8Cat6[] = { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 }; //------------------------------------------------------------------------------ @@ -113,14 +115,15 @@ static int Record(int bit, proba_t* const stats) { // Note: no need to record the fixed probas. static int RecordCoeffs(int ctx, const VP8Residual* const res) { int n = res->first; - proba_t* s = res->stats[VP8EncBands[n]][ctx]; + // should be stats[VP8EncBands[n]], but it's equivalent for n=0 or 1 + proba_t* s = res->stats[n][ctx]; if (res->last < 0) { Record(0, s + 0); return 0; } while (n <= res->last) { int v; - Record(1, s + 0); + Record(1, s + 0); // order of record doesn't matter while ((v = res->coeffs[n++]) == 0) { Record(0, s + 1); s = res->stats[VP8EncBands[n]][0]; @@ -174,8 +177,7 @@ static int BranchCost(int nb, int total, int proba) { return nb * VP8BitCost(1, proba) + (total - nb) * VP8BitCost(0, proba); } -static int FinalizeTokenProbas(VP8Encoder* const enc) { - VP8Proba* const proba = &enc->proba_; +static int FinalizeTokenProbas(VP8Proba* const proba) { int has_changed = 0; int size = 0; int t, b, c, p; @@ -211,6 +213,47 @@ static int FinalizeTokenProbas(VP8Encoder* const enc) { return size; } +//------------------------------------------------------------------------------ +// Finalize Segment probability based on the coding tree + +static int GetProba(int a, int b) { + const int total = a + b; + return (total == 0) ? 255 // that's the default probability. + : (255 * a + total / 2) / total; // rounded proba +} + +static void SetSegmentProbas(VP8Encoder* const enc) { + int p[NUM_MB_SEGMENTS] = { 0 }; + int n; + + for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { + const VP8MBInfo* const mb = &enc->mb_info_[n]; + p[mb->segment_]++; + } + if (enc->pic_->stats != NULL) { + for (n = 0; n < NUM_MB_SEGMENTS; ++n) { + enc->pic_->stats->segment_size[n] = p[n]; + } + } + if (enc->segment_hdr_.num_segments_ > 1) { + uint8_t* const probas = enc->proba_.segments_; + probas[0] = GetProba(p[0] + p[1], p[2] + p[3]); + probas[1] = GetProba(p[0], p[1]); + probas[2] = GetProba(p[2], p[3]); + + enc->segment_hdr_.update_map_ = + (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255); + enc->segment_hdr_.size_ = + p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) + + p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) + + p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) + + p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2])); + } else { + enc->segment_hdr_.update_map_ = 0; + enc->segment_hdr_.size_ = 0; + } +} + //------------------------------------------------------------------------------ // helper functions for residuals struct VP8Residual. @@ -239,18 +282,19 @@ static void SetResidualCoeffs(const int16_t* const coeffs, //------------------------------------------------------------------------------ // Mode costs -static int GetResidualCost(int ctx, const VP8Residual* const res) { +static int GetResidualCost(int ctx0, const VP8Residual* const res) { int n = res->first; - int p0 = res->prob[VP8EncBands[n]][ctx][0]; - const uint16_t* t = res->cost[VP8EncBands[n]][ctx]; + // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 + int p0 = res->prob[n][ctx0][0]; + const uint16_t* t = res->cost[n][ctx0]; int cost; if (res->last < 0) { return VP8BitCost(0, p0); } cost = 0; - while (n <= res->last) { - const int v = res->coeffs[n]; + while (n < res->last) { + int v = res->coeffs[n]; const int b = VP8EncBands[n + 1]; ++n; if (v == 0) { @@ -259,19 +303,28 @@ static int GetResidualCost(int ctx, const VP8Residual* const res) { t = res->cost[b][0]; continue; } + v = abs(v); cost += VP8BitCost(1, p0); - if (2u >= (unsigned int)(v + 1)) { // v = -1 or 1 - // short-case for "VP8LevelCost(t, 1)" (256 is VP8LevelFixedCosts[1]): - cost += 256 + t[1]; - p0 = res->prob[b][1][0]; - t = res->cost[b][1]; - } else { - cost += VP8LevelCost(t, abs(v)); - p0 = res->prob[b][2][0]; - t = res->cost[b][2]; + cost += VP8LevelCost(t, v); + { + const int ctx = (v == 1) ? 1 : 2; + p0 = res->prob[b][ctx][0]; + t = res->cost[b][ctx]; + } + } + // Last coefficient is always non-zero + { + const int v = abs(res->coeffs[n]); + assert(v != 0); + cost += VP8BitCost(1, p0); + cost += VP8LevelCost(t, v); + if (n < 15) { + const int b = VP8EncBands[n + 1]; + const int ctx = (v == 1) ? 1 : 2; + const int last_p0 = res->prob[b][ctx][0]; + cost += VP8BitCost(0, last_p0); } } - if (n < 16) cost += VP8BitCost(0, p0); return cost; } @@ -342,7 +395,8 @@ int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd) { static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) { int n = res->first; - const uint8_t* p = res->prob[VP8EncBands[n]][ctx]; + // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 + const uint8_t* p = res->prob[n][ctx]; if (!VP8PutBit(bw, res->last >= 0, p[0])) { return 0; } @@ -371,30 +425,30 @@ static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) { } else { int mask; const uint8_t* tab; - if (v < 3 + (8 << 1)) { // kCat3 (3b) + if (v < 3 + (8 << 1)) { // VP8Cat3 (3b) VP8PutBit(bw, 0, p[8]); VP8PutBit(bw, 0, p[9]); v -= 3 + (8 << 0); mask = 1 << 2; - tab = kCat3; - } else if (v < 3 + (8 << 2)) { // kCat4 (4b) + tab = VP8Cat3; + } else if (v < 3 + (8 << 2)) { // VP8Cat4 (4b) VP8PutBit(bw, 0, p[8]); VP8PutBit(bw, 1, p[9]); v -= 3 + (8 << 1); mask = 1 << 3; - tab = kCat4; - } else if (v < 3 + (8 << 3)) { // kCat5 (5b) + tab = VP8Cat4; + } else if (v < 3 + (8 << 3)) { // VP8Cat5 (5b) VP8PutBit(bw, 1, p[8]); VP8PutBit(bw, 0, p[10]); v -= 3 + (8 << 2); mask = 1 << 4; - tab = kCat5; - } else { // kCat6 (11b) + tab = VP8Cat5; + } else { // VP8Cat6 (11b) VP8PutBit(bw, 1, p[8]); VP8PutBit(bw, 1, p[10]); v -= 3 + (8 << 3); mask = 1 << 10; - tab = kCat6; + tab = VP8Cat6; } while (mask) { VP8PutBit(bw, !!(v & mask), *tab++); @@ -411,8 +465,7 @@ static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) { return 1; } -static void CodeResiduals(VP8BitWriter* const bw, - VP8EncIterator* const it, +static void CodeResiduals(VP8BitWriter* const bw, VP8EncIterator* const it, const VP8ModeScore* const rd) { int x, y, ch; VP8Residual res; @@ -512,146 +565,23 @@ static void RecordResiduals(VP8EncIterator* const it, //------------------------------------------------------------------------------ // Token buffer -#ifdef USE_TOKEN_BUFFER +#if !defined(DISABLE_TOKEN_BUFFER) -void VP8TBufferInit(VP8TBuffer* const b) { - b->rows_ = NULL; - b->tokens_ = NULL; - b->last_ = &b->rows_; - b->left_ = 0; - b->error_ = 0; -} - -int VP8TBufferNewPage(VP8TBuffer* const b) { - VP8Tokens* const page = b->error_ ? NULL : (VP8Tokens*)malloc(sizeof(*page)); - if (page == NULL) { - b->error_ = 1; - return 0; - } - *b->last_ = page; - b->last_ = &page->next_; - b->left_ = MAX_NUM_TOKEN; - b->tokens_ = page->tokens_; - return 1; -} - -void VP8TBufferClear(VP8TBuffer* const b) { - if (b != NULL) { - const VP8Tokens* p = b->rows_; - while (p != NULL) { - const VP8Tokens* const next = p->next_; - free((void*)p); - p = next; - } - VP8TBufferInit(b); - } -} - -int VP8EmitTokens(const VP8TBuffer* const b, VP8BitWriter* const bw, - const uint8_t* const probas) { - VP8Tokens* p = b->rows_; - if (b->error_) return 0; - while (p != NULL) { - const int N = (p->next_ == NULL) ? b->left_ : 0; - int n = MAX_NUM_TOKEN; - while (n-- > N) { - VP8PutBit(bw, (p->tokens_[n] >> 15) & 1, probas[p->tokens_[n] & 0x7fff]); - } - p = p->next_; - } - return 1; -} - -#define TOKEN_ID(b, ctx, p) ((p) + NUM_PROBAS * ((ctx) + (b) * NUM_CTX)) - -static int RecordCoeffTokens(int ctx, const VP8Residual* const res, - VP8TBuffer* tokens) { - int n = res->first; - int b = VP8EncBands[n]; - if (!VP8AddToken(tokens, res->last >= 0, TOKEN_ID(b, ctx, 0))) { - return 0; - } - - while (n < 16) { - const int c = res->coeffs[n++]; - const int sign = c < 0; - int v = sign ? -c : c; - const int base_id = TOKEN_ID(b, ctx, 0); - if (!VP8AddToken(tokens, v != 0, base_id + 1)) { - b = VP8EncBands[n]; - ctx = 0; - continue; - } - if (!VP8AddToken(tokens, v > 1, base_id + 2)) { - b = VP8EncBands[n]; - ctx = 1; - } else { - if (!VP8AddToken(tokens, v > 4, base_id + 3)) { - if (VP8AddToken(tokens, v != 2, base_id + 4)) - VP8AddToken(tokens, v == 4, base_id + 5); - } else if (!VP8AddToken(tokens, v > 10, base_id + 6)) { - if (!VP8AddToken(tokens, v > 6, base_id + 7)) { -// VP8AddToken(tokens, v == 6, 159); - } else { -// VP8AddToken(tokens, v >= 9, 165); -// VP8AddToken(tokens, !(v & 1), 145); - } - } else { - int mask; - const uint8_t* tab; - if (v < 3 + (8 << 1)) { // kCat3 (3b) - VP8AddToken(tokens, 0, base_id + 8); - VP8AddToken(tokens, 0, base_id + 9); - v -= 3 + (8 << 0); - mask = 1 << 2; - tab = kCat3; - } else if (v < 3 + (8 << 2)) { // kCat4 (4b) - VP8AddToken(tokens, 0, base_id + 8); - VP8AddToken(tokens, 1, base_id + 9); - v -= 3 + (8 << 1); - mask = 1 << 3; - tab = kCat4; - } else if (v < 3 + (8 << 3)) { // kCat5 (5b) - VP8AddToken(tokens, 1, base_id + 8); - VP8AddToken(tokens, 0, base_id + 10); - v -= 3 + (8 << 2); - mask = 1 << 4; - tab = kCat5; - } else { // kCat6 (11b) - VP8AddToken(tokens, 1, base_id + 8); - VP8AddToken(tokens, 1, base_id + 10); - v -= 3 + (8 << 3); - mask = 1 << 10; - tab = kCat6; - } - while (mask) { - // VP8AddToken(tokens, !!(v & mask), *tab++); - mask >>= 1; - } - } - ctx = 2; - } - b = VP8EncBands[n]; - // VP8PutBitUniform(bw, sign); - if (n == 16 || !VP8AddToken(tokens, n <= res->last, TOKEN_ID(b, ctx, 0))) { - return 1; // EOB - } - } - return 1; -} - -static void RecordTokens(VP8EncIterator* const it, - const VP8ModeScore* const rd, VP8TBuffer tokens[2]) { +static void RecordTokens(VP8EncIterator* const it, const VP8ModeScore* const rd, + VP8TBuffer* const tokens) { int x, y, ch; VP8Residual res; VP8Encoder* const enc = it->enc_; VP8IteratorNzToBytes(it); if (it->mb_->type_ == 1) { // i16x16 + const int ctx = it->top_nz_[8] + it->left_nz_[8]; InitResidual(0, 1, enc, &res); SetResidualCoeffs(rd->y_dc_levels, &res); -// TODO(skal): FIX -> it->top_nz_[8] = it->left_nz_[8] = - RecordCoeffTokens(it->top_nz_[8] + it->left_nz_[8], &res, &tokens[0]); + it->top_nz_[8] = it->left_nz_[8] = + VP8RecordCoeffTokens(ctx, 1, + res.first, res.last, res.coeffs, tokens); + RecordCoeffs(ctx, &res); InitResidual(1, 0, enc, &res); } else { InitResidual(0, 3, enc, &res); @@ -663,7 +593,9 @@ static void RecordTokens(VP8EncIterator* const it, const int ctx = it->top_nz_[x] + it->left_nz_[y]; SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); it->top_nz_[x] = it->left_nz_[y] = - RecordCoeffTokens(ctx, &res, &tokens[0]); + VP8RecordCoeffTokens(ctx, res.coeff_type, + res.first, res.last, res.coeffs, tokens); + RecordCoeffs(ctx, &res); } } @@ -675,13 +607,16 @@ static void RecordTokens(VP8EncIterator* const it, const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = - RecordCoeffTokens(ctx, &res, &tokens[1]); + VP8RecordCoeffTokens(ctx, 2, + res.first, res.last, res.coeffs, tokens); + RecordCoeffs(ctx, &res); } } } + VP8IteratorBytesToNz(it); } -#endif // USE_TOKEN_BUFFER +#endif // !DISABLE_TOKEN_BUFFER //------------------------------------------------------------------------------ // ExtraInfo map / Debug function @@ -697,7 +632,10 @@ static void SetBlock(uint8_t* p, int value, int size) { #endif static void ResetSSE(VP8Encoder* const enc) { - memset(enc->sse_, 0, sizeof(enc->sse_)); + enc->sse_[0] = 0; + enc->sse_[1] = 0; + enc->sse_[2] = 0; + // Note: enc->sse_[3] is managed by alpha.c enc->sse_count_ = 0; } @@ -736,6 +674,7 @@ static void StoreSideInfo(const VP8EncIterator* const it) { const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3); *info = (b > 255) ? 255 : b; break; } + case 7: *info = mb->alpha_; break; default: *info = 0; break; }; } @@ -746,9 +685,173 @@ static void StoreSideInfo(const VP8EncIterator* const it) { #endif } +//------------------------------------------------------------------------------ +// StatLoop(): only collect statistics (number of skips, token usage, ...). +// This is used for deciding optimal probabilities. It also modifies the +// quantizer value if some target (size, PNSR) was specified. + +#define kHeaderSizeEstimate (15 + 20 + 10) // TODO: fix better + +static void SetLoopParams(VP8Encoder* const enc, float q) { + // Make sure the quality parameter is inside valid bounds + if (q < 0.) { + q = 0; + } else if (q > 100.) { + q = 100; + } + + VP8SetSegmentParams(enc, q); // setup segment quantizations and filters + SetSegmentProbas(enc); // compute segment probabilities + + ResetStats(enc); + ResetTokenStats(enc); + + ResetSSE(enc); +} + +static int OneStatPass(VP8Encoder* const enc, float q, VP8RDLevel rd_opt, + int nb_mbs, float* const PSNR, int percent_delta) { + VP8EncIterator it; + uint64_t size = 0; + uint64_t distortion = 0; + const uint64_t pixel_count = nb_mbs * 384; + + SetLoopParams(enc, q); + + VP8IteratorInit(enc, &it); + do { + VP8ModeScore info; + VP8IteratorImport(&it); + if (VP8Decimate(&it, &info, rd_opt)) { + // Just record the number of skips and act like skip_proba is not used. + enc->proba_.nb_skip_++; + } + RecordResiduals(&it, &info); + size += info.R; + distortion += info.D; + if (percent_delta && !VP8IteratorProgress(&it, percent_delta)) + return 0; + } while (VP8IteratorNext(&it, it.yuv_out_) && --nb_mbs > 0); + size += FinalizeSkipProba(enc); + size += FinalizeTokenProbas(&enc->proba_); + size += enc->segment_hdr_.size_; + size = ((size + 1024) >> 11) + kHeaderSizeEstimate; + + if (PSNR) { + *PSNR = (float)(10.* log10(255. * 255. * pixel_count / distortion)); + } + return (int)size; +} + +// successive refinement increments. +static const int dqs[] = { 20, 15, 10, 8, 6, 4, 2, 1, 0 }; + +static int StatLoop(VP8Encoder* const enc) { + const int method = enc->method_; + const int do_search = enc->do_search_; + const int fast_probe = ((method == 0 || method == 3) && !do_search); + float q = enc->config_->quality; + const int max_passes = enc->config_->pass; + const int task_percent = 20; + const int percent_per_pass = (task_percent + max_passes / 2) / max_passes; + const int final_percent = enc->percent_ + task_percent; + int pass; + int nb_mbs; + + // Fast mode: quick analysis pass over few mbs. Better than nothing. + nb_mbs = enc->mb_w_ * enc->mb_h_; + if (fast_probe) { + if (method == 3) { // we need more stats for method 3 to be reliable. + nb_mbs = (nb_mbs > 200) ? nb_mbs >> 1 : 100; + } else { + nb_mbs = (nb_mbs > 200) ? nb_mbs >> 2 : 50; + } + } + + // No target size: just do several pass without changing 'q' + if (!do_search) { + for (pass = 0; pass < max_passes; ++pass) { + const VP8RDLevel rd_opt = (method >= 3) ? RD_OPT_BASIC : RD_OPT_NONE; + if (!OneStatPass(enc, q, rd_opt, nb_mbs, NULL, percent_per_pass)) { + return 0; + } + } + } else { + // binary search for a size close to target + for (pass = 0; pass < max_passes && (dqs[pass] > 0); ++pass) { + float PSNR; + int criterion; + const int size = OneStatPass(enc, q, RD_OPT_BASIC, nb_mbs, &PSNR, + percent_per_pass); +#if DEBUG_SEARCH + printf("#%d size=%d PSNR=%.2f q=%.2f\n", pass, size, PSNR, q); +#endif + if (size == 0) return 0; + if (enc->config_->target_PSNR > 0) { + criterion = (PSNR < enc->config_->target_PSNR); + } else { + criterion = (size < enc->config_->target_size); + } + // dichotomize + if (criterion) { + q += dqs[pass]; + } else { + q -= dqs[pass]; + } + } + } + VP8CalculateLevelCosts(&enc->proba_); // finalize costs + return WebPReportProgress(enc->pic_, final_percent, &enc->percent_); +} + //------------------------------------------------------------------------------ // Main loops // + +static const int kAverageBytesPerMB[8] = { 50, 24, 16, 9, 7, 5, 3, 2 }; + +static int PreLoopInitialize(VP8Encoder* const enc) { + int p; + int ok = 1; + const int average_bytes_per_MB = kAverageBytesPerMB[enc->base_quant_ >> 4]; + const int bytes_per_parts = + enc->mb_w_ * enc->mb_h_ * average_bytes_per_MB / enc->num_parts_; + // Initialize the bit-writers + for (p = 0; ok && p < enc->num_parts_; ++p) { + ok = VP8BitWriterInit(enc->parts_ + p, bytes_per_parts); + } + if (!ok) VP8EncFreeBitWriters(enc); // malloc error occurred + return ok; +} + +static int PostLoopFinalize(VP8EncIterator* const it, int ok) { + VP8Encoder* const enc = it->enc_; + if (ok) { // Finalize the partitions, check for extra errors. + int p; + for (p = 0; p < enc->num_parts_; ++p) { + VP8BitWriterFinish(enc->parts_ + p); + ok &= !enc->parts_[p].error_; + } + } + + if (ok) { // All good. Finish up. + if (enc->pic_->stats) { // finalize byte counters... + int i, s; + for (i = 0; i <= 2; ++i) { + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + enc->residual_bytes_[i][s] = (int)((it->bit_count_[s][i] + 7) >> 3); + } + } + } + VP8AdjustFilterStrength(it); // ...and store filter stats. + } else { + // Something bad happened -> need to do some memory cleanup. + VP8EncFreeBitWriters(enc); + } + return ok; +} + +//------------------------------------------------------------------------------ // VP8EncLoop(): does the final bitstream coding. static void ResetAfterSkip(VP8EncIterator* const it) { @@ -761,27 +864,19 @@ static void ResetAfterSkip(VP8EncIterator* const it) { } int VP8EncLoop(VP8Encoder* const enc) { - int i, s, p; - int ok = 1; VP8EncIterator it; - VP8ModeScore info; - const int dont_use_skip = !enc->proba_.use_skip_proba_; - const int rd_opt = enc->rd_opt_level_; - const int kAverageBytesPerMB = 5; // TODO: have a kTable[quality/10] - const int bytes_per_parts = - enc->mb_w_ * enc->mb_h_ * kAverageBytesPerMB / enc->num_parts_; + int ok = PreLoopInitialize(enc); + if (!ok) return 0; - // Initialize the bit-writers - for (p = 0; p < enc->num_parts_; ++p) { - VP8BitWriterInit(enc->parts_ + p, bytes_per_parts); - } - - ResetStats(enc); - ResetSSE(enc); + StatLoop(enc); // stats-collection loop VP8IteratorInit(enc, &it); VP8InitFilter(&it); do { + VP8ModeScore info; + const int dont_use_skip = !enc->proba_.use_skip_proba_; + const VP8RDLevel rd_opt = enc->rd_opt_level_; + VP8IteratorImport(&it); // Warning! order is important: first call VP8Decimate() and // *then* decide how to code the skip decision if there's one. @@ -801,137 +896,82 @@ int VP8EncLoop(VP8Encoder* const enc) { ok = VP8IteratorProgress(&it, 20); } while (ok && VP8IteratorNext(&it, it.yuv_out_)); - if (ok) { // Finalize the partitions, check for extra errors. - for (p = 0; p < enc->num_parts_; ++p) { - VP8BitWriterFinish(enc->parts_ + p); - ok &= !enc->parts_[p].error_; - } - } - - if (ok) { // All good. Finish up. - if (enc->pic_->stats) { // finalize byte counters... - for (i = 0; i <= 2; ++i) { - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - enc->residual_bytes_[i][s] = (int)((it.bit_count_[s][i] + 7) >> 3); - } - } - } - VP8AdjustFilterStrength(&it); // ...and store filter stats. - } else { - // Something bad happened -> need to do some memory cleanup. - VP8EncFreeBitWriters(enc); - } - - return ok; + return PostLoopFinalize(&it, ok); } //------------------------------------------------------------------------------ -// VP8StatLoop(): only collect statistics (number of skips, token usage, ...) -// This is used for deciding optimal probabilities. It also -// modifies the quantizer value if some target (size, PNSR) -// was specified. +// Single pass using Token Buffer. -#define kHeaderSizeEstimate (15 + 20 + 10) // TODO: fix better +#if !defined(DISABLE_TOKEN_BUFFER) -static int OneStatPass(VP8Encoder* const enc, float q, int rd_opt, int nb_mbs, - float* const PSNR, int percent_delta) { +#define MIN_COUNT 96 // minimum number of macroblocks before updating stats + +int VP8EncTokenLoop(VP8Encoder* const enc) { + int ok; + // Roughly refresh the proba height times per pass + int max_count = (enc->mb_w_ * enc->mb_h_) >> 3; + int cnt; VP8EncIterator it; - uint64_t size = 0; - uint64_t distortion = 0; - const uint64_t pixel_count = nb_mbs * 384; + VP8Proba* const proba = &enc->proba_; + const VP8RDLevel rd_opt = enc->rd_opt_level_; - // Make sure the quality parameter is inside valid bounds - if (q < 0.) { - q = 0; - } else if (q > 100.) { - q = 100; - } + if (max_count < MIN_COUNT) max_count = MIN_COUNT; + cnt = max_count; - VP8SetSegmentParams(enc, q); // setup segment quantizations and filters + assert(enc->num_parts_ == 1); + assert(enc->use_tokens_); + assert(proba->use_skip_proba_ == 0); + assert(rd_opt >= RD_OPT_BASIC); // otherwise, token-buffer won't be useful + assert(!enc->do_search_); // TODO(skal): handle pass and dichotomy - ResetStats(enc); - ResetTokenStats(enc); + SetLoopParams(enc, enc->config_->quality); + + ok = PreLoopInitialize(enc); + if (!ok) return 0; VP8IteratorInit(enc, &it); + VP8InitFilter(&it); do { VP8ModeScore info; VP8IteratorImport(&it); - if (VP8Decimate(&it, &info, rd_opt)) { - // Just record the number of skips and act like skip_proba is not used. - enc->proba_.nb_skip_++; + if (--cnt < 0) { + FinalizeTokenProbas(proba); + VP8CalculateLevelCosts(proba); // refresh cost tables for rd-opt + cnt = max_count; } - RecordResiduals(&it, &info); - size += info.R; - distortion += info.D; - if (percent_delta && !VP8IteratorProgress(&it, percent_delta)) - return 0; - } while (VP8IteratorNext(&it, it.yuv_out_) && --nb_mbs > 0); - size += FinalizeSkipProba(enc); - size += FinalizeTokenProbas(enc); - size += enc->segment_hdr_.size_; - size = ((size + 1024) >> 11) + kHeaderSizeEstimate; - - if (PSNR) { - *PSNR = (float)(10.* log10(255. * 255. * pixel_count / distortion)); - } - return (int)size; -} - -// successive refinement increments. -static const int dqs[] = { 20, 15, 10, 8, 6, 4, 2, 1, 0 }; - -int VP8StatLoop(VP8Encoder* const enc) { - const int do_search = - (enc->config_->target_size > 0 || enc->config_->target_PSNR > 0); - const int fast_probe = (enc->method_ < 2 && !do_search); - float q = enc->config_->quality; - const int max_passes = enc->config_->pass; - const int task_percent = 20; - const int percent_per_pass = (task_percent + max_passes / 2) / max_passes; - const int final_percent = enc->percent_ + task_percent; - int pass; - int nb_mbs; - - // Fast mode: quick analysis pass over few mbs. Better than nothing. - nb_mbs = enc->mb_w_ * enc->mb_h_; - if (fast_probe && nb_mbs > 100) nb_mbs = 100; - - // No target size: just do several pass without changing 'q' - if (!do_search) { - for (pass = 0; pass < max_passes; ++pass) { - const int rd_opt = (enc->method_ > 2); - if (!OneStatPass(enc, q, rd_opt, nb_mbs, NULL, percent_per_pass)) { - return 0; - } + VP8Decimate(&it, &info, rd_opt); + RecordTokens(&it, &info, &enc->tokens_); +#ifdef WEBP_EXPERIMENTAL_FEATURES + if (enc->use_layer_) { + VP8EncCodeLayerBlock(&it); } - } else { - // binary search for a size close to target - for (pass = 0; pass < max_passes && (dqs[pass] > 0); ++pass) { - const int rd_opt = 1; - float PSNR; - int criterion; - const int size = OneStatPass(enc, q, rd_opt, nb_mbs, &PSNR, - percent_per_pass); -#if DEBUG_SEARCH - printf("#%d size=%d PSNR=%.2f q=%.2f\n", pass, size, PSNR, q); #endif - if (!size) return 0; - if (enc->config_->target_PSNR > 0) { - criterion = (PSNR < enc->config_->target_PSNR); - } else { - criterion = (size < enc->config_->target_size); - } - // dichotomize - if (criterion) { - q += dqs[pass]; - } else { - q -= dqs[pass]; - } - } + StoreSideInfo(&it); + VP8StoreFilterStats(&it); + VP8IteratorExport(&it); + ok = VP8IteratorProgress(&it, 20); + } while (ok && VP8IteratorNext(&it, it.yuv_out_)); + + ok = ok && WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); + + if (ok) { + FinalizeTokenProbas(proba); + ok = VP8EmitTokens(&enc->tokens_, enc->parts_ + 0, + (const uint8_t*)proba->coeffs_, 1); } - return WebPReportProgress(enc->pic_, final_percent, &enc->percent_); + + return PostLoopFinalize(&it, ok); } +#else + +int VP8EncTokenLoop(VP8Encoder* const enc) { + (void)enc; + return 0; // we shouldn't be here. +} + +#endif // DISABLE_TOKEN_BUFFER + //------------------------------------------------------------------------------ #if defined(__cplusplus) || defined(c_plusplus) diff --git a/3rdparty/libwebp/enc/histogram.c b/3rdparty/libwebp/enc/histogram.c index fb4044bfd3..787ea5d183 100644 --- a/3rdparty/libwebp/enc/histogram.c +++ b/3rdparty/libwebp/enc/histogram.c @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Author: Jyrki Alakuijala (jyrki@google.com) @@ -98,8 +100,6 @@ void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo, } } - - static double BitsEntropy(const int* const array, int n) { double retval = 0.; int sum = 0; @@ -149,25 +149,6 @@ static double BitsEntropy(const int* const array, int n) { } } -double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p) { - double retval = BitsEntropy(&p->literal_[0], VP8LHistogramNumCodes(p)) - + BitsEntropy(&p->red_[0], 256) - + BitsEntropy(&p->blue_[0], 256) - + BitsEntropy(&p->alpha_[0], 256) - + BitsEntropy(&p->distance_[0], NUM_DISTANCE_CODES); - // Compute the extra bits cost. - int i; - for (i = 2; i < NUM_LENGTH_CODES - 2; ++i) { - retval += - (i >> 1) * p->literal_[256 + i + 2]; - } - for (i = 2; i < NUM_DISTANCE_CODES - 2; ++i) { - retval += (i >> 1) * p->distance_[i + 2]; - } - return retval; -} - - // Returns the cost encode the rle-encoded entropy code. // The constants in this function are experimental. static double HuffmanCost(const int* const population, int length) { @@ -207,19 +188,150 @@ static double HuffmanCost(const int* const population, int length) { return retval; } -// Estimates the Huffman dictionary + other block overhead size. -static double HistogramEstimateBitsHeader(const VP8LHistogram* const p) { - return HuffmanCost(&p->alpha_[0], 256) + - HuffmanCost(&p->red_[0], 256) + - HuffmanCost(&p->literal_[0], VP8LHistogramNumCodes(p)) + - HuffmanCost(&p->blue_[0], 256) + - HuffmanCost(&p->distance_[0], NUM_DISTANCE_CODES); +static double PopulationCost(const int* const population, int length) { + return BitsEntropy(population, length) + HuffmanCost(population, length); } -double VP8LHistogramEstimateBits(const VP8LHistogram* const p) { - return HistogramEstimateBitsHeader(p) + VP8LHistogramEstimateBitsBulk(p); +static double ExtraCost(const int* const population, int length) { + int i; + double cost = 0.; + for (i = 2; i < length - 2; ++i) cost += (i >> 1) * population[i + 2]; + return cost; } +// Estimates the Entropy + Huffman + other block overhead size cost. +double VP8LHistogramEstimateBits(const VP8LHistogram* const p) { + return PopulationCost(p->literal_, VP8LHistogramNumCodes(p)) + + PopulationCost(p->red_, 256) + + PopulationCost(p->blue_, 256) + + PopulationCost(p->alpha_, 256) + + PopulationCost(p->distance_, NUM_DISTANCE_CODES) + + ExtraCost(p->literal_ + 256, NUM_LENGTH_CODES) + + ExtraCost(p->distance_, NUM_DISTANCE_CODES); +} + +double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p) { + return BitsEntropy(p->literal_, VP8LHistogramNumCodes(p)) + + BitsEntropy(p->red_, 256) + + BitsEntropy(p->blue_, 256) + + BitsEntropy(p->alpha_, 256) + + BitsEntropy(p->distance_, NUM_DISTANCE_CODES) + + ExtraCost(p->literal_ + 256, NUM_LENGTH_CODES) + + ExtraCost(p->distance_, NUM_DISTANCE_CODES); +} + +// ----------------------------------------------------------------------------- +// Various histogram combine/cost-eval functions + +// Adds 'in' histogram to 'out' +static void HistogramAdd(const VP8LHistogram* const in, + VP8LHistogram* const out) { + int i; + for (i = 0; i < PIX_OR_COPY_CODES_MAX; ++i) { + out->literal_[i] += in->literal_[i]; + } + for (i = 0; i < NUM_DISTANCE_CODES; ++i) { + out->distance_[i] += in->distance_[i]; + } + for (i = 0; i < 256; ++i) { + out->red_[i] += in->red_[i]; + out->blue_[i] += in->blue_[i]; + out->alpha_[i] += in->alpha_[i]; + } +} + +// Performs out = a + b, computing the cost C(a+b) - C(a) - C(b) while comparing +// to the threshold value 'cost_threshold'. The score returned is +// Score = C(a+b) - C(a) - C(b), where C(a) + C(b) is known and fixed. +// Since the previous score passed is 'cost_threshold', we only need to compare +// the partial cost against 'cost_threshold + C(a) + C(b)' to possibly bail-out +// early. +static double HistogramAddEval(const VP8LHistogram* const a, + const VP8LHistogram* const b, + VP8LHistogram* const out, + double cost_threshold) { + double cost = 0; + const double sum_cost = a->bit_cost_ + b->bit_cost_; + int i; + + cost_threshold += sum_cost; + + // palette_code_bits_ is part of the cost evaluation for literal_. + // TODO(skal): remove/simplify this palette_code_bits_? + out->palette_code_bits_ = + (a->palette_code_bits_ > b->palette_code_bits_) ? a->palette_code_bits_ : + b->palette_code_bits_; + for (i = 0; i < PIX_OR_COPY_CODES_MAX; ++i) { + out->literal_[i] = a->literal_[i] + b->literal_[i]; + } + cost += PopulationCost(out->literal_, VP8LHistogramNumCodes(out)); + cost += ExtraCost(out->literal_ + 256, NUM_LENGTH_CODES); + if (cost > cost_threshold) return cost; + + for (i = 0; i < 256; ++i) out->red_[i] = a->red_[i] + b->red_[i]; + cost += PopulationCost(out->red_, 256); + if (cost > cost_threshold) return cost; + + for (i = 0; i < 256; ++i) out->blue_[i] = a->blue_[i] + b->blue_[i]; + cost += PopulationCost(out->blue_, 256); + if (cost > cost_threshold) return cost; + + for (i = 0; i < NUM_DISTANCE_CODES; ++i) { + out->distance_[i] = a->distance_[i] + b->distance_[i]; + } + cost += PopulationCost(out->distance_, NUM_DISTANCE_CODES); + cost += ExtraCost(out->distance_, NUM_DISTANCE_CODES); + if (cost > cost_threshold) return cost; + + for (i = 0; i < 256; ++i) out->alpha_[i] = a->alpha_[i] + b->alpha_[i]; + cost += PopulationCost(out->alpha_, 256); + + out->bit_cost_ = cost; + return cost - sum_cost; +} + +// Same as HistogramAddEval(), except that the resulting histogram +// is not stored. Only the cost C(a+b) - C(a) is evaluated. We omit +// the term C(b) which is constant over all the evaluations. +static double HistogramAddThresh(const VP8LHistogram* const a, + const VP8LHistogram* const b, + double cost_threshold) { + int tmp[PIX_OR_COPY_CODES_MAX]; // <= max storage we'll need + int i; + double cost = -a->bit_cost_; + + for (i = 0; i < PIX_OR_COPY_CODES_MAX; ++i) { + tmp[i] = a->literal_[i] + b->literal_[i]; + } + // note that the tests are ordered so that the usually largest + // cost shares come first. + cost += PopulationCost(tmp, VP8LHistogramNumCodes(a)); + cost += ExtraCost(tmp + 256, NUM_LENGTH_CODES); + if (cost > cost_threshold) return cost; + + for (i = 0; i < 256; ++i) tmp[i] = a->red_[i] + b->red_[i]; + cost += PopulationCost(tmp, 256); + if (cost > cost_threshold) return cost; + + for (i = 0; i < 256; ++i) tmp[i] = a->blue_[i] + b->blue_[i]; + cost += PopulationCost(tmp, 256); + if (cost > cost_threshold) return cost; + + for (i = 0; i < NUM_DISTANCE_CODES; ++i) { + tmp[i] = a->distance_[i] + b->distance_[i]; + } + cost += PopulationCost(tmp, NUM_DISTANCE_CODES); + cost += ExtraCost(tmp, NUM_DISTANCE_CODES); + if (cost > cost_threshold) return cost; + + for (i = 0; i < 256; ++i) tmp[i] = a->alpha_[i] + b->alpha_[i]; + cost += PopulationCost(tmp, 256); + + return cost; +} + +// ----------------------------------------------------------------------------- + static void HistogramBuildImage(int xsize, int histo_bits, const VP8LBackwardRefs* const backward_refs, VP8LHistogramSet* const image) { @@ -249,14 +361,15 @@ static uint32_t MyRand(uint32_t *seed) { } static int HistogramCombine(const VP8LHistogramSet* const in, - VP8LHistogramSet* const out, int num_pairs) { + VP8LHistogramSet* const out, int iter_mult, + int num_pairs, int num_tries_no_success) { int ok = 0; int i, iter; uint32_t seed = 0; int tries_with_no_success = 0; - const int min_cluster_size = 2; int out_size = in->size; - const int outer_iters = in->size * 3; + const int outer_iters = in->size * iter_mult; + const int min_cluster_size = 2; VP8LHistogram* const histos = (VP8LHistogram*)malloc(2 * sizeof(*histos)); VP8LHistogram* cur_combo = histos + 0; // trial merged histogram VP8LHistogram* best_combo = histos + 1; // best merged histogram so far @@ -271,29 +384,26 @@ static int HistogramCombine(const VP8LHistogramSet* const in, // Collapse similar histograms in 'out'. for (iter = 0; iter < outer_iters && out_size >= min_cluster_size; ++iter) { - // We pick the best pair to be combined out of 'inner_iters' pairs. double best_cost_diff = 0.; - int best_idx1 = 0, best_idx2 = 1; + int best_idx1 = -1, best_idx2 = 1; int j; + const int num_tries = (num_pairs < out_size) ? num_pairs : out_size; seed += iter; - for (j = 0; j < num_pairs; ++j) { + for (j = 0; j < num_tries; ++j) { double curr_cost_diff; // Choose two histograms at random and try to combine them. const uint32_t idx1 = MyRand(&seed) % out_size; - const uint32_t tmp = ((j & 7) + 1) % (out_size - 1); + const uint32_t tmp = (j & 7) + 1; const uint32_t diff = (tmp < 3) ? tmp : MyRand(&seed) % (out_size - 1); const uint32_t idx2 = (idx1 + diff + 1) % out_size; if (idx1 == idx2) { continue; } - *cur_combo = *out->histograms[idx1]; - VP8LHistogramAdd(cur_combo, out->histograms[idx2]); - cur_combo->bit_cost_ = VP8LHistogramEstimateBits(cur_combo); // Calculate cost reduction on combining. - curr_cost_diff = cur_combo->bit_cost_ - - out->histograms[idx1]->bit_cost_ - - out->histograms[idx2]->bit_cost_; - if (best_cost_diff > curr_cost_diff) { // found a better pair? + curr_cost_diff = HistogramAddEval(out->histograms[idx1], + out->histograms[idx2], + cur_combo, best_cost_diff); + if (curr_cost_diff < best_cost_diff) { // found a better pair? { // swap cur/best combo histograms VP8LHistogram* const tmp_histo = cur_combo; cur_combo = best_combo; @@ -305,7 +415,7 @@ static int HistogramCombine(const VP8LHistogramSet* const in, } } - if (best_cost_diff < 0.0) { + if (best_idx1 >= 0) { *out->histograms[best_idx1] = *best_combo; // swap best_idx2 slot with last one (which is now unused) --out_size; @@ -315,7 +425,7 @@ static int HistogramCombine(const VP8LHistogramSet* const in, } tries_with_no_success = 0; } - if (++tries_with_no_success >= 50) { + if (++tries_with_no_success >= num_tries_no_success) { break; } } @@ -330,20 +440,11 @@ static int HistogramCombine(const VP8LHistogramSet* const in, // ----------------------------------------------------------------------------- // Histogram refinement -// What is the bit cost of moving square_histogram from -// cur_symbol to candidate_symbol. -// TODO(skal): we don't really need to copy the histogram and Add(). Instead -// we just need VP8LDualHistogramEstimateBits(A, B) estimation function. +// What is the bit cost of moving square_histogram from cur_symbol to candidate. static double HistogramDistance(const VP8LHistogram* const square_histogram, - const VP8LHistogram* const candidate) { - const double previous_bit_cost = candidate->bit_cost_; - double new_bit_cost; - VP8LHistogram modified_histo; - modified_histo = *candidate; - VP8LHistogramAdd(&modified_histo, square_histogram); - new_bit_cost = VP8LHistogramEstimateBits(&modified_histo); - - return new_bit_cost - previous_bit_cost; + const VP8LHistogram* const candidate, + double cost_threshold) { + return HistogramAddThresh(candidate, square_histogram, cost_threshold); } // Find the best 'out' histogram for each of the 'in' histograms. @@ -354,11 +455,12 @@ static void HistogramRemap(const VP8LHistogramSet* const in, int i; for (i = 0; i < in->size; ++i) { int best_out = 0; - double best_bits = HistogramDistance(in->histograms[i], out->histograms[0]); + double best_bits = + HistogramDistance(in->histograms[i], out->histograms[0], 1.e38); int k; for (k = 1; k < out->size; ++k) { const double cur_bits = - HistogramDistance(in->histograms[i], out->histograms[k]); + HistogramDistance(in->histograms[i], out->histograms[k], best_bits); if (cur_bits < best_bits) { best_bits = cur_bits; best_out = k; @@ -372,7 +474,7 @@ static void HistogramRemap(const VP8LHistogramSet* const in, HistogramClear(out->histograms[i]); } for (i = 0; i < in->size; ++i) { - VP8LHistogramAdd(out->histograms[symbols[i]], in->histograms[i]); + HistogramAdd(in->histograms[i], out->histograms[symbols[i]]); } } @@ -384,8 +486,13 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize, int ok = 0; const int histo_xsize = histo_bits ? VP8LSubSampleSize(xsize, histo_bits) : 1; const int histo_ysize = histo_bits ? VP8LSubSampleSize(ysize, histo_bits) : 1; - const int num_histo_pairs = 10 + quality / 2; // For HistogramCombine(). const int histo_image_raw_size = histo_xsize * histo_ysize; + + // Heuristic params for HistogramCombine(). + const int num_tries_no_success = 8 + (quality >> 1); + const int iter_mult = (quality < 27) ? 1 : 1 + ((quality - 27) >> 4); + const int num_pairs = (quality < 25) ? 10 : (5 * quality) >> 3; + VP8LHistogramSet* const image_out = VP8LAllocateHistogramSet(histo_image_raw_size, cache_bits); if (image_out == NULL) return 0; @@ -393,7 +500,8 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize, // Build histogram image. HistogramBuildImage(xsize, histo_bits, refs, image_out); // Collapse similar histograms. - if (!HistogramCombine(image_out, image_in, num_histo_pairs)) { + if (!HistogramCombine(image_out, image_in, iter_mult, num_pairs, + num_tries_no_success)) { goto Error; } // Find the optimal map from original histograms to the final ones. diff --git a/3rdparty/libwebp/enc/histogram.h b/3rdparty/libwebp/enc/histogram.h index ec573c5c85..583b5a4f80 100644 --- a/3rdparty/libwebp/enc/histogram.h +++ b/3rdparty/libwebp/enc/histogram.h @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Author: Jyrki Alakuijala (jyrki@google.com) @@ -80,22 +82,6 @@ double VP8LHistogramEstimateBits(const VP8LHistogram* const p); // represent the entropy code itself. double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p); -static WEBP_INLINE void VP8LHistogramAdd(VP8LHistogram* const p, - const VP8LHistogram* const a) { - int i; - for (i = 0; i < PIX_OR_COPY_CODES_MAX; ++i) { - p->literal_[i] += a->literal_[i]; - } - for (i = 0; i < NUM_DISTANCE_CODES; ++i) { - p->distance_[i] += a->distance_[i]; - } - for (i = 0; i < 256; ++i) { - p->red_[i] += a->red_[i]; - p->blue_[i] += a->blue_[i]; - p->alpha_[i] += a->alpha_[i]; - } -} - static WEBP_INLINE int VP8LHistogramNumCodes(const VP8LHistogram* const p) { return 256 + NUM_LENGTH_CODES + ((p->palette_code_bits_ > 0) ? (1 << p->palette_code_bits_) : 0); diff --git a/3rdparty/libwebp/enc/iterator.c b/3rdparty/libwebp/enc/iterator.c index 86e473bcf0..0746659046 100644 --- a/3rdparty/libwebp/enc/iterator.c +++ b/3rdparty/libwebp/enc/iterator.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // VP8Iterator: block iterator diff --git a/3rdparty/libwebp/enc/layer.c b/3rdparty/libwebp/enc/layer.c index 423127df63..fa89660994 100644 --- a/3rdparty/libwebp/enc/layer.c +++ b/3rdparty/libwebp/enc/layer.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Enhancement layer (for YUV444/422) diff --git a/3rdparty/libwebp/enc/picture.c b/3rdparty/libwebp/enc/picture.c index 44eed06083..5aaa385d47 100644 --- a/3rdparty/libwebp/enc/picture.c +++ b/3rdparty/libwebp/enc/picture.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // WebPPicture utils: colorspace conversion, crop, ... @@ -290,8 +292,11 @@ int WebPPictureView(const WebPPicture* src, dst->y = src->y + top * src->y_stride + left; dst->u = src->u + (top >> 1) * src->uv_stride + (left >> 1); dst->v = src->v + (top >> 1) * src->uv_stride + (left >> 1); + dst->y_stride = src->y_stride; + dst->uv_stride = src->uv_stride; if (src->a != NULL) { dst->a = src->a + top * src->a_stride + left; + dst->a_stride = src->a_stride; } #ifdef WEBP_EXPERIMENTAL_FEATURES if (src->u0 != NULL) { @@ -299,10 +304,12 @@ int WebPPictureView(const WebPPicture* src, IS_YUV_CSP(dst->colorspace, WEBP_YUV422) ? (left >> 1) : left; dst->u0 = src->u0 + top * src->uv0_stride + left_pos; dst->v0 = src->v0 + top * src->uv0_stride + left_pos; + dst->uv0_stride = src->uv0_stride; } #endif } else { dst->argb = src->argb + top * src->argb_stride + left; + dst->argb_stride = src->argb_stride; } return 1; } @@ -457,7 +464,6 @@ int WebPPictureRescale(WebPPicture* pic, int width, int height) { (uint8_t*)tmp.argb, width, height, tmp.argb_stride * 4, work, 4); - } WebPPictureFree(pic); free(work); @@ -705,7 +711,7 @@ static int Import(WebPPicture* const picture, for (y = 0; y < height; ++y) { for (x = 0; x < width; ++x) { const int offset = step * x + y * rgb_stride; - const uint32_t argb = (a_ptr[offset] << 24) | + const uint32_t argb = ((uint32_t)a_ptr[offset] << 24) | (r_ptr[offset] << 16) | (g_ptr[offset] << 8) | (b_ptr[offset]); @@ -801,11 +807,11 @@ int WebPPictureYUVAToARGB(WebPPicture* picture) { // Insert alpha values if needed, in replacement for the default 0xff ones. if (picture->colorspace & WEBP_CSP_ALPHA_BIT) { for (y = 0; y < height; ++y) { - uint32_t* const dst = picture->argb + y * picture->argb_stride; + uint32_t* const argb_dst = picture->argb + y * picture->argb_stride; const uint8_t* const src = picture->a + y * picture->a_stride; int x; for (x = 0; x < width; ++x) { - dst[x] = (dst[x] & 0x00ffffffu) | (src[x] << 24); + argb_dst[x] = (argb_dst[x] & 0x00ffffffu) | ((uint32_t)src[x] << 24); } } } @@ -906,67 +912,135 @@ void WebPCleanupTransparentArea(WebPPicture* pic) { #undef SIZE #undef SIZE2 +//------------------------------------------------------------------------------ +// local-min distortion +// +// For every pixel in the *reference* picture, we search for the local best +// match in the compressed image. This is not a symmetrical measure. + +// search radius. Shouldn't be too large. +#define RADIUS 2 + +static float AccumulateLSIM(const uint8_t* src, int src_stride, + const uint8_t* ref, int ref_stride, + int w, int h) { + int x, y; + double total_sse = 0.; + for (y = 0; y < h; ++y) { + const int y_0 = (y - RADIUS < 0) ? 0 : y - RADIUS; + const int y_1 = (y + RADIUS + 1 >= h) ? h : y + RADIUS + 1; + for (x = 0; x < w; ++x) { + const int x_0 = (x - RADIUS < 0) ? 0 : x - RADIUS; + const int x_1 = (x + RADIUS + 1 >= w) ? w : x + RADIUS + 1; + double best_sse = 255. * 255.; + const double value = (double)ref[y * ref_stride + x]; + int i, j; + for (j = y_0; j < y_1; ++j) { + const uint8_t* s = src + j * src_stride; + for (i = x_0; i < x_1; ++i) { + const double sse = (double)(s[i] - value) * (s[i] - value); + if (sse < best_sse) best_sse = sse; + } + } + total_sse += best_sse; + } + } + return (float)total_sse; +} +#undef RADIUS //------------------------------------------------------------------------------ // Distortion // Max value returned in case of exact similarity. static const double kMinDistortion_dB = 99.; +static float GetPSNR(const double v) { + return (float)((v > 0.) ? -4.3429448 * log(v / (255 * 255.)) + : kMinDistortion_dB); +} -int WebPPictureDistortion(const WebPPicture* pic1, const WebPPicture* pic2, +int WebPPictureDistortion(const WebPPicture* src, const WebPPicture* ref, int type, float result[5]) { - int c; DistoStats stats[5]; int has_alpha; + int uv_w, uv_h; - if (pic1 == NULL || pic2 == NULL || - pic1->width != pic2->width || pic1->height != pic2->height || - pic1->y == NULL || pic2->y == NULL || - pic1->u == NULL || pic2->u == NULL || - pic1->v == NULL || pic2->v == NULL || + if (src == NULL || ref == NULL || + src->width != ref->width || src->height != ref->height || + src->y == NULL || ref->y == NULL || + src->u == NULL || ref->u == NULL || + src->v == NULL || ref->v == NULL || result == NULL) { return 0; } // TODO(skal): provide distortion for ARGB too. - if (pic1->use_argb == 1 || pic1->use_argb != pic2->use_argb) { + if (src->use_argb == 1 || src->use_argb != ref->use_argb) { return 0; } - has_alpha = !!(pic1->colorspace & WEBP_CSP_ALPHA_BIT); - if (has_alpha != !!(pic2->colorspace & WEBP_CSP_ALPHA_BIT) || - (has_alpha && (pic1->a == NULL || pic2->a == NULL))) { + has_alpha = !!(src->colorspace & WEBP_CSP_ALPHA_BIT); + if (has_alpha != !!(ref->colorspace & WEBP_CSP_ALPHA_BIT) || + (has_alpha && (src->a == NULL || ref->a == NULL))) { return 0; } memset(stats, 0, sizeof(stats)); - VP8SSIMAccumulatePlane(pic1->y, pic1->y_stride, - pic2->y, pic2->y_stride, - pic1->width, pic1->height, &stats[0]); - VP8SSIMAccumulatePlane(pic1->u, pic1->uv_stride, - pic2->u, pic2->uv_stride, - (pic1->width + 1) >> 1, (pic1->height + 1) >> 1, - &stats[1]); - VP8SSIMAccumulatePlane(pic1->v, pic1->uv_stride, - pic2->v, pic2->uv_stride, - (pic1->width + 1) >> 1, (pic1->height + 1) >> 1, - &stats[2]); - if (has_alpha) { - VP8SSIMAccumulatePlane(pic1->a, pic1->a_stride, - pic2->a, pic2->a_stride, - pic1->width, pic1->height, &stats[3]); - } - for (c = 0; c <= 4; ++c) { - if (type == 1) { - const double v = VP8SSIMGet(&stats[c]); - result[c] = (float)((v < 1.) ? -10.0 * log10(1. - v) - : kMinDistortion_dB); - } else { - const double v = VP8SSIMGetSquaredError(&stats[c]); - result[c] = (float)((v > 0.) ? -4.3429448 * log(v / (255 * 255.)) - : kMinDistortion_dB); + + uv_w = HALVE(src->width); + uv_h = HALVE(src->height); + if (type >= 2) { + float sse[4]; + sse[0] = AccumulateLSIM(src->y, src->y_stride, + ref->y, ref->y_stride, src->width, src->height); + sse[1] = AccumulateLSIM(src->u, src->uv_stride, + ref->u, ref->uv_stride, uv_w, uv_h); + sse[2] = AccumulateLSIM(src->v, src->uv_stride, + ref->v, ref->uv_stride, uv_w, uv_h); + sse[3] = has_alpha ? AccumulateLSIM(src->a, src->a_stride, + ref->a, ref->a_stride, + src->width, src->height) + : 0.f; + result[0] = GetPSNR(sse[0] / (src->width * src->height)); + result[1] = GetPSNR(sse[1] / (uv_w * uv_h)); + result[2] = GetPSNR(sse[2] / (uv_w * uv_h)); + result[3] = GetPSNR(sse[3] / (src->width * src->height)); + { + double total_sse = sse[0] + sse[1] + sse[2]; + int total_pixels = src->width * src->height + 2 * uv_w * uv_h; + if (has_alpha) { + total_pixels += src->width * src->height; + total_sse += sse[3]; + } + result[4] = GetPSNR(total_sse / total_pixels); + } + } else { + int c; + VP8SSIMAccumulatePlane(src->y, src->y_stride, + ref->y, ref->y_stride, + src->width, src->height, &stats[0]); + VP8SSIMAccumulatePlane(src->u, src->uv_stride, + ref->u, ref->uv_stride, + uv_w, uv_h, &stats[1]); + VP8SSIMAccumulatePlane(src->v, src->uv_stride, + ref->v, ref->uv_stride, + uv_w, uv_h, &stats[2]); + if (has_alpha) { + VP8SSIMAccumulatePlane(src->a, src->a_stride, + ref->a, ref->a_stride, + src->width, src->height, &stats[3]); + } + for (c = 0; c <= 4; ++c) { + if (type == 1) { + const double v = VP8SSIMGet(&stats[c]); + result[c] = (float)((v < 1.) ? -10.0 * log10(1. - v) + : kMinDistortion_dB); + } else { + const double v = VP8SSIMGetSquaredError(&stats[c]); + result[c] = GetPSNR(v); + } + // Accumulate forward + if (c < 4) VP8SSIMAddStats(&stats[c], &stats[4]); } - // Accumulate forward - if (c < 4) VP8SSIMAddStats(&stats[c], &stats[4]); } return 1; } diff --git a/3rdparty/libwebp/enc/quant.c b/3rdparty/libwebp/enc/quant.c index ea153849c8..462d4e9e6e 100644 --- a/3rdparty/libwebp/enc/quant.c +++ b/3rdparty/libwebp/enc/quant.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Quantization @@ -27,6 +29,8 @@ #define SNS_TO_DQ 0.9 // Scaling constant between the sns value and the QP // power-law modulation. Must be strictly less than 1. +#define I4_PENALTY 4000 // Rate-penalty for quick i4/i16 decision + #define MULT_8B(a, b) (((a) * (b) + 128) >> 8) #if defined(__cplusplus) || defined(c_plusplus) @@ -224,28 +228,90 @@ static void SetupFilterStrength(VP8Encoder* const enc) { // We want to emulate jpeg-like behaviour where the expected "good" quality // is around q=75. Internally, our "good" middle is around c=50. So we // map accordingly using linear piece-wise function -static double QualityToCompression(double q) { - const double c = q / 100.; - return (c < 0.75) ? c * (2. / 3.) : 2. * c - 1.; +static double QualityToCompression(double c) { + const double linear_c = (c < 0.75) ? c * (2. / 3.) : 2. * c - 1.; + // The file size roughly scales as pow(quantizer, 3.). Actually, the + // exponent is somewhere between 2.8 and 3.2, but we're mostly interested + // in the mid-quant range. So we scale the compressibility inversely to + // this power-law: quant ~= compression ^ 1/3. This law holds well for + // low quant. Finer modelling for high-quant would make use of kAcTable[] + // more explicitly. + const double v = pow(linear_c, 1 / 3.); + return v; +} + +static double QualityToJPEGCompression(double c, double alpha) { + // We map the complexity 'alpha' and quality setting 'c' to a compression + // exponent empirically matched to the compression curve of libjpeg6b. + // On average, the WebP output size will be roughly similar to that of a + // JPEG file compressed with same quality factor. + const double amin = 0.30; + const double amax = 0.85; + const double exp_min = 0.4; + const double exp_max = 0.9; + const double slope = (exp_min - exp_max) / (amax - amin); + // Linearly interpolate 'expn' from exp_min to exp_max + // in the [amin, amax] range. + const double expn = (alpha > amax) ? exp_min + : (alpha < amin) ? exp_max + : exp_max + slope * (alpha - amin); + const double v = pow(c, expn); + return v; +} + +static int SegmentsAreEquivalent(const VP8SegmentInfo* const S1, + const VP8SegmentInfo* const S2) { + return (S1->quant_ == S2->quant_) && (S1->fstrength_ == S2->fstrength_); +} + +static void SimplifySegments(VP8Encoder* const enc) { + int map[NUM_MB_SEGMENTS] = { 0, 1, 2, 3 }; + const int num_segments = enc->segment_hdr_.num_segments_; + int num_final_segments = 1; + int s1, s2; + for (s1 = 1; s1 < num_segments; ++s1) { // find similar segments + const VP8SegmentInfo* const S1 = &enc->dqm_[s1]; + int found = 0; + // check if we already have similar segment + for (s2 = 0; s2 < num_final_segments; ++s2) { + const VP8SegmentInfo* const S2 = &enc->dqm_[s2]; + if (SegmentsAreEquivalent(S1, S2)) { + found = 1; + break; + } + } + map[s1] = s2; + if (!found) { + if (num_final_segments != s1) { + enc->dqm_[num_final_segments] = enc->dqm_[s1]; + } + ++num_final_segments; + } + } + if (num_final_segments < num_segments) { // Remap + int i = enc->mb_w_ * enc->mb_h_; + while (i-- > 0) enc->mb_info_[i].segment_ = map[enc->mb_info_[i].segment_]; + enc->segment_hdr_.num_segments_ = num_final_segments; + // Replicate the trailing segment infos (it's mostly cosmetics) + for (i = num_final_segments; i < num_segments; ++i) { + enc->dqm_[i] = enc->dqm_[num_final_segments - 1]; + } + } } void VP8SetSegmentParams(VP8Encoder* const enc, float quality) { int i; int dq_uv_ac, dq_uv_dc; - const int num_segments = enc->config_->segments; + const int num_segments = enc->segment_hdr_.num_segments_; const double amp = SNS_TO_DQ * enc->config_->sns_strength / 100. / 128.; - const double c_base = QualityToCompression(quality); + const double Q = quality / 100.; + const double c_base = enc->config_->emulate_jpeg_size ? + QualityToJPEGCompression(Q, enc->alpha_ / 255.) : + QualityToCompression(Q); for (i = 0; i < num_segments; ++i) { - // The file size roughly scales as pow(quantizer, 3.). Actually, the - // exponent is somewhere between 2.8 and 3.2, but we're mostly interested - // in the mid-quant range. So we scale the compressibility inversely to - // this power-law: quant ~= compression ^ 1/3. This law holds well for - // low quant. Finer modelling for high-quant would make use of kAcTable[] - // more explicitely. - // Additionally, we modulate the base exponent 1/3 to accommodate for the - // quantization susceptibility and allow denser segments to be quantized - // more. - const double expn = (1. - amp * enc->dqm_[i].alpha_) / 3.; + // We modulate the base coefficient to accommodate for the quantization + // susceptibility and allow denser segments to be quantized more. + const double expn = 1. - amp * enc->dqm_[i].alpha_; const double c = pow(c_base, expn); const int q = (int)(127. * (1. - c)); assert(expn > 0.); @@ -281,9 +347,11 @@ void VP8SetSegmentParams(VP8Encoder* const enc, float quality) { enc->dq_uv_dc_ = dq_uv_dc; enc->dq_uv_ac_ = dq_uv_ac; - SetupMatrices(enc); - SetupFilterStrength(enc); // initialize segments' filtering, eventually + + if (num_segments > 1) SimplifySegments(enc); + + SetupMatrices(enc); // finalize quantization matrices } //------------------------------------------------------------------------------ @@ -709,7 +777,7 @@ static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* const rd) { int mode; rd->mode_i16 = -1; - for (mode = 0; mode < 4; ++mode) { + for (mode = 0; mode < NUM_PRED_MODES; ++mode) { uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF; // scratch buffer int nz; @@ -838,7 +906,7 @@ static void PickBestUV(VP8EncIterator* const it, VP8ModeScore* const rd) { rd->mode_uv = -1; InitScore(&rd_best); - for (mode = 0; mode < 4; ++mode) { + for (mode = 0; mode < NUM_PRED_MODES; ++mode) { VP8ModeScore rd_uv; // Reconstruct @@ -867,10 +935,10 @@ static void PickBestUV(VP8EncIterator* const it, VP8ModeScore* const rd) { static void SimpleQuantize(VP8EncIterator* const it, VP8ModeScore* const rd) { const VP8Encoder* const enc = it->enc_; - const int i16 = (it->mb_->type_ == 1); + const int is_i16 = (it->mb_->type_ == 1); int nz = 0; - if (i16) { + if (is_i16) { nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF, it->preds_[0]); } else { VP8IteratorStartI4(it); @@ -889,11 +957,66 @@ static void SimpleQuantize(VP8EncIterator* const it, VP8ModeScore* const rd) { rd->nz = nz; } +// Refine intra16/intra4 sub-modes based on distortion only (not rate). +static void DistoRefine(VP8EncIterator* const it, int try_both_i4_i16) { + const int is_i16 = (it->mb_->type_ == 1); + score_t best_score = MAX_COST; + + if (try_both_i4_i16 || is_i16) { + int mode; + int best_mode = -1; + for (mode = 0; mode < NUM_PRED_MODES; ++mode) { + const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode]; + const uint8_t* const src = it->yuv_in_ + Y_OFF; + const score_t score = VP8SSE16x16(src, ref); + if (score < best_score) { + best_mode = mode; + best_score = score; + } + } + VP8SetIntra16Mode(it, best_mode); + } + if (try_both_i4_i16 || !is_i16) { + uint8_t modes_i4[16]; + // We don't evaluate the rate here, but just account for it through a + // constant penalty (i4 mode usually needs more bits compared to i16). + score_t score_i4 = (score_t)I4_PENALTY; + + VP8IteratorStartI4(it); + do { + int mode; + int best_sub_mode = -1; + score_t best_sub_score = MAX_COST; + const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_]; + + // TODO(skal): we don't really need the prediction pixels here, + // but just the distortion against 'src'. + VP8MakeIntra4Preds(it); + for (mode = 0; mode < NUM_BMODES; ++mode) { + const uint8_t* const ref = it->yuv_p_ + VP8I4ModeOffsets[mode]; + const score_t score = VP8SSE4x4(src, ref); + if (score < best_sub_score) { + best_sub_mode = mode; + best_sub_score = score; + } + } + modes_i4[it->i4_] = best_sub_mode; + score_i4 += best_sub_score; + if (score_i4 >= best_score) break; + } while (VP8IteratorRotateI4(it, it->yuv_in_ + Y_OFF)); + if (score_i4 < best_score) { + VP8SetIntra4Mode(it, modes_i4); + } + } +} + //------------------------------------------------------------------------------ // Entry point -int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, int rd_opt) { +int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, + VP8RDLevel rd_opt) { int is_skipped; + const int method = it->enc_->method_; InitScore(rd); @@ -902,22 +1025,21 @@ int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, int rd_opt) { VP8MakeLuma16Preds(it); VP8MakeChroma8Preds(it); - // for rd_opt = 2, we perform trellis-quant on the final decision only. - // for rd_opt > 2, we use it for every scoring (=much slower). - if (rd_opt > 0) { - it->do_trellis_ = (rd_opt > 2); + if (rd_opt > RD_OPT_NONE) { + it->do_trellis_ = (rd_opt >= RD_OPT_TRELLIS_ALL); PickBestIntra16(it, rd); - if (it->enc_->method_ >= 2) { + if (method >= 2) { PickBestIntra4(it, rd); } PickBestUV(it, rd); - if (rd_opt == 2) { + if (rd_opt == RD_OPT_TRELLIS) { // finish off with trellis-optim now it->do_trellis_ = 1; SimpleQuantize(it, rd); } } else { - // TODO: for method_ == 2, pick the best intra4/intra16 based on SSE - it->do_trellis_ = (it->enc_->method_ == 2); + // For method == 2, pick the best intra4/intra16 based on SSE (~tad slower). + // For method <= 1, we refine intra4 or intra16 (but don't re-examine mode). + DistoRefine(it, (method >= 2)); SimpleQuantize(it, rd); } is_skipped = (rd->nz == 0); diff --git a/3rdparty/libwebp/enc/syntax.c b/3rdparty/libwebp/enc/syntax.c index 7c8c7b1a84..b0f7676b48 100644 --- a/3rdparty/libwebp/enc/syntax.c +++ b/3rdparty/libwebp/enc/syntax.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Header syntax writing @@ -11,7 +13,9 @@ #include -#include "../webp/format_constants.h" +#include "../utils/utils.h" +#include "../webp/format_constants.h" // RIFF constants +#include "../webp/mux_types.h" // ALPHA_FLAG #include "./vp8enci.h" #if defined(__cplusplus) || defined(c_plusplus) @@ -21,25 +25,12 @@ extern "C" { //------------------------------------------------------------------------------ // Helper functions -// TODO(later): Move to webp/format_constants.h? -static void PutLE24(uint8_t* const data, uint32_t val) { - data[0] = (val >> 0) & 0xff; - data[1] = (val >> 8) & 0xff; - data[2] = (val >> 16) & 0xff; -} - -static void PutLE32(uint8_t* const data, uint32_t val) { - PutLE24(data, val); - data[3] = (val >> 24) & 0xff; -} - static int IsVP8XNeeded(const VP8Encoder* const enc) { return !!enc->has_alpha_; // Currently the only case when VP8X is needed. // This could change in the future. } static int PutPaddingByte(const WebPPicture* const pic) { - const uint8_t pad_byte[1] = { 0 }; return !!pic->writer(pad_byte, 1, pic); } @@ -73,14 +64,14 @@ static WebPEncodingError PutVP8XHeader(const VP8Encoder* const enc) { assert(pic->width <= MAX_CANVAS_SIZE && pic->height <= MAX_CANVAS_SIZE); if (enc->has_alpha_) { - flags |= ALPHA_FLAG_BIT; + flags |= ALPHA_FLAG; } PutLE32(vp8x + TAG_SIZE, VP8X_CHUNK_SIZE); PutLE32(vp8x + CHUNK_HEADER_SIZE, flags); PutLE24(vp8x + CHUNK_HEADER_SIZE + 4, pic->width - 1); PutLE24(vp8x + CHUNK_HEADER_SIZE + 7, pic->height - 1); - if(!pic->writer(vp8x, sizeof(vp8x), pic)) { + if (!pic->writer(vp8x, sizeof(vp8x), pic)) { return VP8_ENC_ERROR_BAD_WRITE; } return VP8_ENC_OK; @@ -327,7 +318,9 @@ static size_t GeneratePartition0(VP8Encoder* const enc) { PutSegmentHeader(bw, enc); PutFilterHeader(bw, &enc->filter_hdr_); - VP8PutValue(bw, enc->config_->partitions, 2); + VP8PutValue(bw, enc->num_parts_ == 8 ? 3 : + enc->num_parts_ == 4 ? 2 : + enc->num_parts_ == 2 ? 1 : 0, 2); PutQuant(bw, enc); VP8PutBitUniform(bw, 0); // no proba update VP8WriteProbas(bw, &enc->proba_); diff --git a/3rdparty/libwebp/enc/token.c b/3rdparty/libwebp/enc/token.c new file mode 100644 index 0000000000..6a63371f71 --- /dev/null +++ b/3rdparty/libwebp/enc/token.c @@ -0,0 +1,256 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Paginated token buffer +// +// A 'token' is a bit value associated with a probability, either fixed +// or a later-to-be-determined after statistics have been collected. +// For dynamic probability, we just record the slot id (idx) for the probability +// value in the final probability array (uint8_t* probas in VP8EmitTokens). +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include + +#include "./vp8enci.h" + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#if !defined(DISABLE_TOKEN_BUFFER) + +// we use pages to reduce the number of memcpy() +#define MAX_NUM_TOKEN 8192 // max number of token per page +#define FIXED_PROBA_BIT (1u << 14) + +struct VP8Tokens { + uint16_t tokens_[MAX_NUM_TOKEN]; // bit#15: bit + // bit #14: constant proba or idx + // bits 0..13: slot or constant proba + VP8Tokens* next_; +}; + +//------------------------------------------------------------------------------ + +void VP8TBufferInit(VP8TBuffer* const b) { + b->tokens_ = NULL; + b->pages_ = NULL; + b->last_page_ = &b->pages_; + b->left_ = 0; + b->error_ = 0; +} + +void VP8TBufferClear(VP8TBuffer* const b) { + if (b != NULL) { + const VP8Tokens* p = b->pages_; + while (p != NULL) { + const VP8Tokens* const next = p->next_; + free((void*)p); + p = next; + } + VP8TBufferInit(b); + } +} + +static int TBufferNewPage(VP8TBuffer* const b) { + VP8Tokens* const page = b->error_ ? NULL : (VP8Tokens*)malloc(sizeof(*page)); + if (page == NULL) { + b->error_ = 1; + return 0; + } + *b->last_page_ = page; + b->last_page_ = &page->next_; + b->left_ = MAX_NUM_TOKEN; + b->tokens_ = page->tokens_; + page->next_ = NULL; + return 1; +} + +//------------------------------------------------------------------------------ + +#define TOKEN_ID(t, b, ctx, p) \ + ((p) + NUM_PROBAS * ((ctx) + NUM_CTX * ((b) + NUM_BANDS * (t)))) + +static WEBP_INLINE int AddToken(VP8TBuffer* const b, + int bit, uint32_t proba_idx) { + assert(proba_idx < FIXED_PROBA_BIT); + assert(bit == 0 || bit == 1); + if (b->left_ > 0 || TBufferNewPage(b)) { + const int slot = --b->left_; + b->tokens_[slot] = (bit << 15) | proba_idx; + } + return bit; +} + +static WEBP_INLINE void AddConstantToken(VP8TBuffer* const b, + int bit, int proba) { + assert(proba < 256); + assert(bit == 0 || bit == 1); + if (b->left_ > 0 || TBufferNewPage(b)) { + const int slot = --b->left_; + b->tokens_[slot] = (bit << 15) | FIXED_PROBA_BIT | proba; + } +} + +int VP8RecordCoeffTokens(int ctx, int coeff_type, int first, int last, + const int16_t* const coeffs, + VP8TBuffer* const tokens) { + int n = first; + uint32_t base_id = TOKEN_ID(coeff_type, n, ctx, 0); + if (!AddToken(tokens, last >= 0, base_id + 0)) { + return 0; + } + + while (n < 16) { + const int c = coeffs[n++]; + const int sign = c < 0; + int v = sign ? -c : c; + if (!AddToken(tokens, v != 0, base_id + 1)) { + ctx = 0; + base_id = TOKEN_ID(coeff_type, VP8EncBands[n], ctx, 0); + continue; + } + if (!AddToken(tokens, v > 1, base_id + 2)) { + ctx = 1; + } else { + if (!AddToken(tokens, v > 4, base_id + 3)) { + if (AddToken(tokens, v != 2, base_id + 4)) + AddToken(tokens, v == 4, base_id + 5); + } else if (!AddToken(tokens, v > 10, base_id + 6)) { + if (!AddToken(tokens, v > 6, base_id + 7)) { + AddConstantToken(tokens, v == 6, 159); + } else { + AddConstantToken(tokens, v >= 9, 165); + AddConstantToken(tokens, !(v & 1), 145); + } + } else { + int mask; + const uint8_t* tab; + if (v < 3 + (8 << 1)) { // VP8Cat3 (3b) + AddToken(tokens, 0, base_id + 8); + AddToken(tokens, 0, base_id + 9); + v -= 3 + (8 << 0); + mask = 1 << 2; + tab = VP8Cat3; + } else if (v < 3 + (8 << 2)) { // VP8Cat4 (4b) + AddToken(tokens, 0, base_id + 8); + AddToken(tokens, 1, base_id + 9); + v -= 3 + (8 << 1); + mask = 1 << 3; + tab = VP8Cat4; + } else if (v < 3 + (8 << 3)) { // VP8Cat5 (5b) + AddToken(tokens, 1, base_id + 8); + AddToken(tokens, 0, base_id + 10); + v -= 3 + (8 << 2); + mask = 1 << 4; + tab = VP8Cat5; + } else { // VP8Cat6 (11b) + AddToken(tokens, 1, base_id + 8); + AddToken(tokens, 1, base_id + 10); + v -= 3 + (8 << 3); + mask = 1 << 10; + tab = VP8Cat6; + } + while (mask) { + AddConstantToken(tokens, !!(v & mask), *tab++); + mask >>= 1; + } + } + ctx = 2; + } + AddConstantToken(tokens, sign, 128); + base_id = TOKEN_ID(coeff_type, VP8EncBands[n], ctx, 0); + if (n == 16 || !AddToken(tokens, n <= last, base_id + 0)) { + return 1; // EOB + } + } + return 1; +} + +#undef TOKEN_ID + +//------------------------------------------------------------------------------ +// This function works, but isn't currently used. Saved for later. + +#if 0 + +static void Record(int bit, proba_t* const stats) { + proba_t p = *stats; + if (p >= 0xffff0000u) { // an overflow is inbound. + p = ((p + 1u) >> 1) & 0x7fff7fffu; // -> divide the stats by 2. + } + // record bit count (lower 16 bits) and increment total count (upper 16 bits). + p += 0x00010000u + bit; + *stats = p; +} + +void VP8TokenToStats(const VP8TBuffer* const b, proba_t* const stats) { + const VP8Tokens* p = b->pages_; + while (p != NULL) { + const int N = (p->next_ == NULL) ? b->left_ : 0; + int n = MAX_NUM_TOKEN; + while (n-- > N) { + const uint16_t token = p->tokens_[n]; + if (!(token & FIXED_PROBA_BIT)) { + Record((token >> 15) & 1, stats + (token & 0x3fffu)); + } + } + p = p->next_; + } +} + +#endif // 0 + +//------------------------------------------------------------------------------ +// Final coding pass, with known probabilities + +int VP8EmitTokens(VP8TBuffer* const b, VP8BitWriter* const bw, + const uint8_t* const probas, int final_pass) { + const VP8Tokens* p = b->pages_; + (void)final_pass; + if (b->error_) return 0; + while (p != NULL) { + const VP8Tokens* const next = p->next_; + const int N = (next == NULL) ? b->left_ : 0; + int n = MAX_NUM_TOKEN; + while (n-- > N) { + const uint16_t token = p->tokens_[n]; + const int bit = (token >> 15) & 1; + if (token & FIXED_PROBA_BIT) { + VP8PutBit(bw, bit, token & 0xffu); // constant proba + } else { + VP8PutBit(bw, bit, probas[token & 0x3fffu]); + } + } + if (final_pass) free((void*)p); + p = next; + } + if (final_pass) b->pages_ = NULL; + return 1; +} + +//------------------------------------------------------------------------------ + +#else // DISABLE_TOKEN_BUFFER + +void VP8TBufferInit(VP8TBuffer* const b) { + (void)b; +} +void VP8TBufferClear(VP8TBuffer* const b) { + (void)b; +} + +#endif // !DISABLE_TOKEN_BUFFER + +#if defined(__cplusplus) || defined(c_plusplus) +} // extern "C" +#endif diff --git a/3rdparty/libwebp/enc/tree.c b/3rdparty/libwebp/enc/tree.c index 8b25e5e488..ecd8fb910e 100644 --- a/3rdparty/libwebp/enc/tree.c +++ b/3rdparty/libwebp/enc/tree.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Token probabilities diff --git a/3rdparty/libwebp/enc/vp8enci.h b/3rdparty/libwebp/enc/vp8enci.h index f660eeec55..61d56be554 100644 --- a/3rdparty/libwebp/enc/vp8enci.h +++ b/3rdparty/libwebp/enc/vp8enci.h @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // WebP encoder: internal header. @@ -16,6 +18,7 @@ #include "../webp/encode.h" #include "../dsp/dsp.h" #include "../utils/bit_writer.h" +#include "../utils/thread.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { @@ -26,12 +29,9 @@ extern "C" { // version numbers #define ENC_MAJ_VERSION 0 -#define ENC_MIN_VERSION 2 +#define ENC_MIN_VERSION 3 #define ENC_REV_VERSION 1 -// size of histogram used by CollectHistogram. -#define MAX_COEFF_THRESH 64 - // intra prediction modes enum { B_DC_PRED = 0, // 4x4 modes B_TM_PRED = 1, @@ -47,7 +47,8 @@ enum { B_DC_PRED = 0, // 4x4 modes // Luma16 or UV modes DC_PRED = B_DC_PRED, V_PRED = B_VE_PRED, - H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED + H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED, + NUM_PRED_MODES = 4 }; enum { NUM_MB_SEGMENTS = 4, @@ -56,10 +57,18 @@ enum { NUM_MB_SEGMENTS = 4, NUM_BANDS = 8, NUM_CTX = 3, NUM_PROBAS = 11, - MAX_LF_LEVELS = 64, // Maximum loop filter level - MAX_VARIABLE_LEVEL = 67 // last (inclusive) level with variable cost + MAX_LF_LEVELS = 64, // Maximum loop filter level + MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost + MAX_LEVEL = 2047 // max level (note: max codable is 2047 + 67) }; +typedef enum { // Rate-distortion optimization levels + RD_OPT_NONE = 0, // no rd-opt + RD_OPT_BASIC = 1, // basic scoring (no trellis) + RD_OPT_TRELLIS = 2, // perform trellis-quant on the final decision only + RD_OPT_TRELLIS_ALL = 3 // trellis-quant for every scoring (much slower) +} VP8RDLevel; + // YUV-cache parameters. Cache is 16-pixels wide. // The original or reconstructed samples can be accessed using VP8Scan[] // The predicted blocks can be accessed using offsets to yuv_p_ and @@ -160,7 +169,17 @@ typedef int64_t score_t; // type used for scores, rate, distortion static WEBP_INLINE int QUANTDIV(int n, int iQ, int B) { return (n * iQ + B) >> QFIX; } -extern const uint8_t VP8Zigzag[16]; + +// size of histogram used by CollectHistogram. +#define MAX_COEFF_THRESH 31 +typedef struct VP8Histogram VP8Histogram; +struct VP8Histogram { + // TODO(skal): we only need to store the max_value and last_non_zero actually. + int distribution[MAX_COEFF_THRESH + 1]; +}; + +// Uncomment the following to remove token-buffer code: +// #define DISABLE_TOKEN_BUFFER //------------------------------------------------------------------------------ // Headers @@ -314,44 +333,37 @@ void VP8SetSegment(const VP8EncIterator* const it, int segment); //------------------------------------------------------------------------------ // Paginated token buffer -// WIP: #define USE_TOKEN_BUFFER - -#ifdef USE_TOKEN_BUFFER - -#define MAX_NUM_TOKEN 2048 - -typedef struct VP8Tokens VP8Tokens; -struct VP8Tokens { - uint16_t tokens_[MAX_NUM_TOKEN]; // bit#15: bit, bits 0..14: slot - int left_; - VP8Tokens* next_; -}; +typedef struct VP8Tokens VP8Tokens; // struct details in token.c typedef struct { - VP8Tokens* rows_; - uint16_t* tokens_; // set to (*last_)->tokens_ - VP8Tokens** last_; - int left_; - int error_; // true in case of malloc error +#if !defined(DISABLE_TOKEN_BUFFER) + VP8Tokens* pages_; // first page + VP8Tokens** last_page_; // last page + uint16_t* tokens_; // set to (*last_page_)->tokens_ + int left_; // how many free tokens left before the page is full. +#endif + int error_; // true in case of malloc error } VP8TBuffer; void VP8TBufferInit(VP8TBuffer* const b); // initialize an empty buffer -int VP8TBufferNewPage(VP8TBuffer* const b); // allocate a new page -void VP8TBufferClear(VP8TBuffer* const b); // de-allocate memory +void VP8TBufferClear(VP8TBuffer* const b); // de-allocate pages memory -int VP8EmitTokens(const VP8TBuffer* const b, VP8BitWriter* const bw, - const uint8_t* const probas); +#if !defined(DISABLE_TOKEN_BUFFER) -static WEBP_INLINE int VP8AddToken(VP8TBuffer* const b, - int bit, int proba_idx) { - if (b->left_ > 0 || VP8TBufferNewPage(b)) { - const int slot = --b->left_; - b->tokens_[slot] = (bit << 15) | proba_idx; - } - return bit; -} +// Finalizes bitstream when probabilities are known. +// Deletes the allocated token memory if final_pass is true. +int VP8EmitTokens(VP8TBuffer* const b, VP8BitWriter* const bw, + const uint8_t* const probas, int final_pass); -#endif // USE_TOKEN_BUFFER +// record the coding of coefficients without knowing the probabilities yet +int VP8RecordCoeffTokens(int ctx, int coeff_type, int first, int last, + const int16_t* const coeffs, + VP8TBuffer* const tokens); + +// unused for now +void VP8TokenToStats(const VP8TBuffer* const b, proba_t* const stats); + +#endif // !DISABLE_TOKEN_BUFFER //------------------------------------------------------------------------------ // VP8Encoder @@ -376,6 +388,7 @@ struct VP8Encoder { // per-partition boolean decoders. VP8BitWriter bw_; // part0 VP8BitWriter parts_[MAX_NUM_PARTITIONS]; // token partitions + VP8TBuffer tokens_; // token buffer int percent_; // for progress @@ -383,6 +396,7 @@ struct VP8Encoder { int has_alpha_; uint8_t* alpha_data_; // non-NULL if transparency is present uint32_t alpha_data_size_; + WebPWorker alpha_worker_; // enhancement layer int use_layer_; @@ -394,6 +408,7 @@ struct VP8Encoder { VP8SegmentInfo dqm_[NUM_MB_SEGMENTS]; int base_quant_; // nominal quantizer value. Only used // for relative coding of segments' quant. + int alpha_; // global susceptibility (<=> complexity) int uv_alpha_; // U/V quantization susceptibility // global offset of quantizers, shared by all segments int dq_y1_dc_; @@ -409,9 +424,12 @@ struct VP8Encoder { int block_count_[3]; // quality/speed settings - int method_; // 0=fastest, 6=best/slowest. - int rd_opt_level_; // Deduced from method_. - int max_i4_header_bits_; // partition #0 safeness factor + int method_; // 0=fastest, 6=best/slowest. + VP8RDLevel rd_opt_level_; // Deduced from method_. + int max_i4_header_bits_; // partition #0 safeness factor + int thread_level_; // derived from config->thread_level + int do_search_; // derived from config->target_XXX + int use_tokens_; // if true, use token buffer // Memory VP8MBInfo* mb_info_; // contextual macroblock infos (mb_w_ + 1) @@ -455,6 +473,11 @@ void VP8EncFreeBitWriters(VP8Encoder* const enc); // in frame.c extern const uint8_t VP8EncBands[16 + 1]; +extern const uint8_t VP8Cat3[]; +extern const uint8_t VP8Cat4[]; +extern const uint8_t VP8Cat5[]; +extern const uint8_t VP8Cat6[]; + // Form all the four Intra16x16 predictions in the yuv_p_ cache void VP8MakeLuma16Preds(const VP8EncIterator* const it); // Form all the four Chroma8x8 predictions in the yuv_p_ cache @@ -466,9 +489,9 @@ void VP8MakeIntra4Preds(const VP8EncIterator* const it); int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd); int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]); int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd); -// Main stat / coding passes +// Main coding calls int VP8EncLoop(VP8Encoder* const enc); -int VP8StatLoop(VP8Encoder* const enc); +int VP8EncTokenLoop(VP8Encoder* const enc); // in webpenc.c // Assign an error code to a picture. Return false for convenience. @@ -485,12 +508,14 @@ int VP8EncAnalyze(VP8Encoder* const enc); // Sets up segment's quantization values, base_quant_ and filter strengths. void VP8SetSegmentParams(VP8Encoder* const enc, float quality); // Pick best modes and fills the levels. Returns true if skipped. -int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, int rd_opt); +int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, + VP8RDLevel rd_opt); // in alpha.c void VP8EncInitAlpha(VP8Encoder* const enc); // initialize alpha compression +int VP8EncStartAlpha(VP8Encoder* const enc); // start alpha coding process int VP8EncFinishAlpha(VP8Encoder* const enc); // finalize compressed data -void VP8EncDeleteAlpha(VP8Encoder* const enc); // delete compressed data +int VP8EncDeleteAlpha(VP8Encoder* const enc); // delete compressed data // in layer.c void VP8EncInitLayer(VP8Encoder* const enc); // init everything diff --git a/3rdparty/libwebp/enc/vp8l.c b/3rdparty/libwebp/enc/vp8l.c index 2abc30f464..945870ca46 100644 --- a/3rdparty/libwebp/enc/vp8l.c +++ b/3rdparty/libwebp/enc/vp8l.c @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // main entry for the lossless encoder. @@ -37,7 +39,8 @@ extern "C" { static int CompareColors(const void* p1, const void* p2) { const uint32_t a = *(const uint32_t*)p1; const uint32_t b = *(const uint32_t*)p2; - return (a < b) ? -1 : (a > b) ? 1 : 0; + assert(a != b); + return (a < b) ? -1 : 1; } // If number of colors in the image is less than or equal to MAX_PALETTE_SIZE, @@ -85,7 +88,7 @@ static int AnalyzeAndCreatePalette(const WebPPicture* const pic, argb += pic->argb_stride; } - // TODO(skal): could we reuse in_use[] to speed up ApplyPalette()? + // TODO(skal): could we reuse in_use[] to speed up EncodePalette()? num_colors = 0; for (i = 0; i < (int)(sizeof(in_use) / sizeof(in_use[0])); ++i) { if (in_use[i]) { @@ -220,7 +223,7 @@ static int GetHuffBitLengthsAndCodes( } // Create Huffman trees. - for (i = 0; i < histogram_image_size; ++i) { + for (i = 0; ok && (i < histogram_image_size); ++i) { HuffmanTreeCode* const codes = &huffman_codes[5 * i]; VP8LHistogram* const histo = histogram_image->histograms[i]; ok = ok && VP8LCreateHuffmanTree(histo->literal_, 15, codes + 0); @@ -231,7 +234,11 @@ static int GetHuffBitLengthsAndCodes( } End: - if (!ok) free(mem_buf); + if (!ok) { + free(mem_buf); + // If one VP8LCreateHuffmanTree() above fails, we need to clean up behind. + memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes)); + } return ok; } @@ -406,9 +413,10 @@ static int StoreHuffmanCode(VP8LBitWriter* const bw, } static void WriteHuffmanCode(VP8LBitWriter* const bw, - const HuffmanTreeCode* const code, int index) { - const int depth = code->code_lengths[index]; - const int symbol = code->codes[index]; + const HuffmanTreeCode* const code, + int code_index) { + const int depth = code->code_lengths[code_index]; + const int symbol = code->codes[code_index]; VP8LWriteBits(bw, depth, symbol); } @@ -557,6 +565,9 @@ static int EncodeImageInternal(VP8LBitWriter* const bw, !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { goto Error; } + // Free combined histograms. + free(histogram_image); + histogram_image = NULL; // Color Cache parameters. VP8LWriteBits(bw, 1, use_color_cache); @@ -576,10 +587,10 @@ static int EncodeImageInternal(VP8LBitWriter* const bw, uint32_t i; if (histogram_argb == NULL) goto Error; for (i = 0; i < histogram_image_xysize; ++i) { - const int index = histogram_symbols[i] & 0xffff; - histogram_argb[i] = 0xff000000 | (index << 8); - if (index >= max_index) { - max_index = index + 1; + const int symbol_index = histogram_symbols[i] & 0xffff; + histogram_argb[i] = 0xff000000 | (symbol_index << 8); + if (symbol_index >= max_index) { + max_index = symbol_index + 1; } } histogram_image_size = max_index; @@ -603,9 +614,6 @@ static int EncodeImageInternal(VP8LBitWriter* const bw, ClearHuffmanTreeIfOnlyOneSymbol(codes); } } - // Free combined histograms. - free(histogram_image); - histogram_image = NULL; // Store actual literals. StoreImageToBitMask(bw, width, histogram_bits, &refs, @@ -613,7 +621,7 @@ static int EncodeImageInternal(VP8LBitWriter* const bw, ok = 1; Error: - if (!ok) free(histogram_image); + free(histogram_image); VP8LClearBackwardRefs(&refs); if (huffman_codes != NULL) { @@ -711,13 +719,6 @@ static int ApplyCrossColorFilter(const VP8LEncoder* const enc, // ----------------------------------------------------------------------------- -static void PutLE32(uint8_t* const data, uint32_t val) { - data[0] = (val >> 0) & 0xff; - data[1] = (val >> 8) & 0xff; - data[2] = (val >> 16) & 0xff; - data[3] = (val >> 24) & 0xff; -} - static WebPEncodingError WriteRiffHeader(const WebPPicture* const pic, size_t riff_size, size_t vp8l_size) { uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = { @@ -812,61 +813,94 @@ static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc, return err; } -// Bundles multiple (2, 4 or 8) pixels into a single pixel. -// Returns the new xsize. -static void BundleColorMap(const WebPPicture* const pic, - int xbits, uint32_t* bundled_argb, int xs) { - int y; - const int bit_depth = 1 << (3 - xbits); - uint32_t code = 0; - const uint32_t* argb = pic->argb; - const int width = pic->width; - const int height = pic->height; - - for (y = 0; y < height; ++y) { - int x; - for (x = 0; x < width; ++x) { - const int mask = (1 << xbits) - 1; - const int xsub = x & mask; - if (xsub == 0) { - code = 0; - } - // TODO(vikasa): simplify the bundling logic. - code |= (argb[x] & 0xff00) << (bit_depth * xsub); - bundled_argb[y * xs + (x >> xbits)] = 0xff000000 | code; +static void ApplyPalette(uint32_t* src, uint32_t* dst, + uint32_t src_stride, uint32_t dst_stride, + const uint32_t* palette, int palette_size, + int width, int height, int xbits, uint8_t* row) { + int i, x, y; + int use_LUT = 1; + for (i = 0; i < palette_size; ++i) { + if ((palette[i] & 0xffff00ffu) != 0) { + use_LUT = 0; + break; + } + } + + if (use_LUT) { + int inv_palette[MAX_PALETTE_SIZE] = { 0 }; + for (i = 0; i < palette_size; ++i) { + const int color = (palette[i] >> 8) & 0xff; + inv_palette[color] = i; + } + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + const int color = (src[x] >> 8) & 0xff; + row[x] = inv_palette[color]; + } + VP8LBundleColorMap(row, width, xbits, dst); + src += src_stride; + dst += dst_stride; + } + } else { + // Use 1 pixel cache for ARGB pixels. + uint32_t last_pix = palette[0]; + int last_idx = 0; + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + const uint32_t pix = src[x]; + if (pix != last_pix) { + for (i = 0; i < palette_size; ++i) { + if (pix == palette[i]) { + last_idx = i; + last_pix = pix; + break; + } + } + } + row[x] = last_idx; + } + VP8LBundleColorMap(row, width, xbits, dst); + src += src_stride; + dst += dst_stride; } - argb += pic->argb_stride; } } // Note: Expects "enc->palette_" to be set properly. // Also, "enc->palette_" will be modified after this call and should not be used // later. -static WebPEncodingError ApplyPalette(VP8LBitWriter* const bw, - VP8LEncoder* const enc, int quality) { +static WebPEncodingError EncodePalette(VP8LBitWriter* const bw, + VP8LEncoder* const enc, int quality) { WebPEncodingError err = VP8_ENC_OK; - int i, x, y; + int i; const WebPPicture* const pic = enc->pic_; - uint32_t* argb = pic->argb; + uint32_t* src = pic->argb; + uint32_t* dst; const int width = pic->width; const int height = pic->height; uint32_t* const palette = enc->palette_; const int palette_size = enc->palette_size_; + uint8_t* row = NULL; + int xbits; // Replace each input pixel by corresponding palette index. - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - const uint32_t pix = argb[x]; - for (i = 0; i < palette_size; ++i) { - if (pix == palette[i]) { - argb[x] = 0xff000000u | (i << 8); - break; - } - } - } - argb += pic->argb_stride; + // This is done line by line. + if (palette_size <= 4) { + xbits = (palette_size <= 2) ? 3 : 2; + } else { + xbits = (palette_size <= 16) ? 1 : 0; } + err = AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height); + if (err != VP8_ENC_OK) goto Error; + dst = enc->argb_; + + row = WebPSafeMalloc((uint64_t)width, sizeof(*row)); + if (row == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY; + + ApplyPalette(src, dst, pic->argb_stride, enc->current_width_, + palette, palette_size, width, height, xbits, row); + // Save palette to bitstream. VP8LWriteBits(bw, 1, TRANSFORM_PRESENT); VP8LWriteBits(bw, 2, COLOR_INDEXING_TRANSFORM); @@ -880,32 +914,17 @@ static WebPEncodingError ApplyPalette(VP8LBitWriter* const bw, goto Error; } - if (palette_size <= 16) { - // Image can be packed (multiple pixels per uint32_t). - int xbits = 1; - if (palette_size <= 2) { - xbits = 3; - } else if (palette_size <= 4) { - xbits = 2; - } - err = AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height); - if (err != VP8_ENC_OK) goto Error; - BundleColorMap(pic, xbits, enc->argb_, enc->current_width_); - } - Error: + free(row); return err; } // ----------------------------------------------------------------------------- -static int GetHistoBits(const WebPConfig* const config, - const WebPPicture* const pic) { - const int width = pic->width; - const int height = pic->height; +static int GetHistoBits(int method, int use_palette, int width, int height) { const uint64_t hist_size = sizeof(VP8LHistogram); // Make tile size a function of encoding method (Range: 0 to 6). - int histo_bits = 7 - config->method; + int histo_bits = (use_palette ? 9 : 7) - method; while (1) { const uint64_t huff_image_size = VP8LSubSampleSize(width, histo_bits) * VP8LSubSampleSize(height, histo_bits) * @@ -917,13 +936,14 @@ static int GetHistoBits(const WebPConfig* const config, (histo_bits > MAX_HUFFMAN_BITS) ? MAX_HUFFMAN_BITS : histo_bits; } -static void InitEncParams(VP8LEncoder* const enc) { +static void FinishEncParams(VP8LEncoder* const enc) { const WebPConfig* const config = enc->config_; - const WebPPicture* const picture = enc->pic_; + const WebPPicture* const pic = enc->pic_; const int method = config->method; const float quality = config->quality; + const int use_palette = enc->use_palette_; enc->transform_bits_ = (method < 4) ? 5 : (method > 4) ? 3 : 4; - enc->histo_bits_ = GetHistoBits(config, picture); + enc->histo_bits_ = GetHistoBits(method, use_palette, pic->width, pic->height); enc->cache_bits_ = (quality <= 25.f) ? 0 : 7; } @@ -965,8 +985,6 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, goto Error; } - InitEncParams(enc); - // --------------------------------------------------------------------------- // Analyze image (entropy, num_palettes etc) @@ -975,8 +993,10 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, goto Error; } + FinishEncParams(enc); + if (enc->use_palette_) { - err = ApplyPalette(bw, enc, quality); + err = EncodePalette(bw, enc, quality); if (err != VP8_ENC_OK) goto Error; // Color cache is disabled for palette. enc->cache_bits_ = 0; diff --git a/3rdparty/libwebp/enc/vp8li.h b/3rdparty/libwebp/enc/vp8li.h index eae90dd61f..01f01f57e5 100644 --- a/3rdparty/libwebp/enc/vp8li.h +++ b/3rdparty/libwebp/enc/vp8li.h @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Lossless encoder: internal header. diff --git a/3rdparty/libwebp/enc/webpenc.c b/3rdparty/libwebp/enc/webpenc.c index 3c275589fc..d420d063ea 100644 --- a/3rdparty/libwebp/enc/webpenc.c +++ b/3rdparty/libwebp/enc/webpenc.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // WebP encoder: main entry point @@ -93,34 +95,53 @@ static void ResetBoundaryPredictions(VP8Encoder* const enc) { enc->nz_[-1] = 0; // constant } -// Map configured quality level to coding tools used. -//-------------+---+---+---+---+---+---+ -// Quality | 0 | 1 | 2 | 3 | 4 | 5 + -//-------------+---+---+---+---+---+---+ -// dynamic prob| ~ | x | x | x | x | x | -//-------------+---+---+---+---+---+---+ -// rd-opt modes| | | x | x | x | x | -//-------------+---+---+---+---+---+---+ -// fast i4/i16 | x | x | | | | | -//-------------+---+---+---+---+---+---+ -// rd-opt i4/16| | | x | x | x | x | -//-------------+---+---+---+---+---+---+ -// Trellis | | x | | | x | x | -//-------------+---+---+---+---+---+---+ -// full-SNS | | | | | | x | -//-------------+---+---+---+---+---+---+ +// Mapping from config->method_ to coding tools used. +//-------------------+---+---+---+---+---+---+---+ +// Method | 0 | 1 | 2 | 3 |(4)| 5 | 6 | +//-------------------+---+---+---+---+---+---+---+ +// fast probe | x | | | x | | | | +//-------------------+---+---+---+---+---+---+---+ +// dynamic proba | ~ | x | x | x | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// fast mode analysis| | | | | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// basic rd-opt | | | | x | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// disto-score i4/16 | | | x | | | | | +//-------------------+---+---+---+---+---+---+---+ +// rd-opt i4/16 | | | ~ | x | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// token buffer (opt)| | | | x | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// Trellis | | | | | | x |Ful| +//-------------------+---+---+---+---+---+---+---+ +// full-SNS | | | | | x | x | x | +//-------------------+---+---+---+---+---+---+---+ static void MapConfigToTools(VP8Encoder* const enc) { - const int method = enc->config_->method; - const int limit = 100 - enc->config_->partition_limit; + const WebPConfig* const config = enc->config_; + const int method = config->method; + const int limit = 100 - config->partition_limit; enc->method_ = method; - enc->rd_opt_level_ = (method >= 6) ? 3 - : (method >= 5) ? 2 - : (method >= 3) ? 1 - : 0; + enc->rd_opt_level_ = (method >= 6) ? RD_OPT_TRELLIS_ALL + : (method >= 5) ? RD_OPT_TRELLIS + : (method >= 3) ? RD_OPT_BASIC + : RD_OPT_NONE; enc->max_i4_header_bits_ = 256 * 16 * 16 * // upper bound: up to 16bit per 4x4 block (limit * limit) / (100 * 100); // ... modulated with a quadratic curve. + + enc->thread_level_ = config->thread_level; + + enc->do_search_ = (config->target_size > 0 || config->target_PSNR > 0); + if (!config->low_memory) { +#if !defined(DISABLE_TOKEN_BUFFER) + enc->use_tokens_ = (method >= 3) && !enc->do_search_; +#endif + if (enc->use_tokens_) { + enc->num_parts_ = 1; // doesn't work with multi-partition + } + } } // Memory scaling with dimensions: @@ -259,17 +280,21 @@ static VP8Encoder* InitVP8Encoder(const WebPConfig* const config, VP8EncInitLayer(enc); #endif + VP8TBufferInit(&enc->tokens_); return enc; } -static void DeleteVP8Encoder(VP8Encoder* enc) { +static int DeleteVP8Encoder(VP8Encoder* enc) { + int ok = 1; if (enc != NULL) { - VP8EncDeleteAlpha(enc); + ok = VP8EncDeleteAlpha(enc); #ifdef WEBP_EXPERIMENTAL_FEATURES VP8EncDeleteLayer(enc); #endif + VP8TBufferClear(&enc->tokens_); free(enc); } + return ok; } //------------------------------------------------------------------------------ @@ -332,7 +357,7 @@ int WebPReportProgress(const WebPPicture* const pic, //------------------------------------------------------------------------------ int WebPEncode(const WebPConfig* config, WebPPicture* pic) { - int ok; + int ok = 0; if (pic == NULL) return 0; @@ -351,32 +376,38 @@ int WebPEncode(const WebPConfig* config, WebPPicture* pic) { if (!config->lossless) { VP8Encoder* enc = NULL; if (pic->y == NULL || pic->u == NULL || pic->v == NULL) { - if (pic->argb != NULL) { - if (!WebPPictureARGBToYUVA(pic, WEBP_YUV420)) return 0; - } else { - return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER); - } + // Make sure we have YUVA samples. + if (!WebPPictureARGBToYUVA(pic, WEBP_YUV420)) return 0; } enc = InitVP8Encoder(config, pic); if (enc == NULL) return 0; // pic->error is already set. // Note: each of the tasks below account for 20% in the progress report. - ok = VP8EncAnalyze(enc) - && VP8StatLoop(enc) - && VP8EncLoop(enc) - && VP8EncFinishAlpha(enc) + ok = VP8EncAnalyze(enc); + + // Analysis is done, proceed to actual coding. + ok = ok && VP8EncStartAlpha(enc); // possibly done in parallel + if (!enc->use_tokens_) { + ok = ok && VP8EncLoop(enc); + } else { + ok = ok && VP8EncTokenLoop(enc); + } + ok = ok && VP8EncFinishAlpha(enc); #ifdef WEBP_EXPERIMENTAL_FEATURES - && VP8EncFinishLayer(enc) + ok = ok && VP8EncFinishLayer(enc); #endif - && VP8EncWrite(enc); + + ok = ok && VP8EncWrite(enc); StoreStats(enc); if (!ok) { VP8EncFreeBitWriters(enc); } - DeleteVP8Encoder(enc); + ok &= DeleteVP8Encoder(enc); // must always be called, even if !ok } else { - if (pic->argb == NULL) - return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER); + // Make sure we have ARGB samples. + if (pic->argb == NULL && !WebPPictureYUVAToARGB(pic)) { + return 0; + } ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem. } diff --git a/3rdparty/libwebp/mux/muxedit.c b/3rdparty/libwebp/mux/muxedit.c index 08629d4ae2..2d25a14d04 100644 --- a/3rdparty/libwebp/mux/muxedit.c +++ b/3rdparty/libwebp/mux/muxedit.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Set and delete APIs for mux. @@ -12,6 +14,7 @@ #include #include "./muxi.h" +#include "../utils/utils.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { @@ -47,8 +50,9 @@ static void MuxRelease(WebPMux* const mux) { MuxImageDeleteAll(&mux->images_); DeleteAllChunks(&mux->vp8x_); DeleteAllChunks(&mux->iccp_); - DeleteAllChunks(&mux->loop_); - DeleteAllChunks(&mux->meta_); + DeleteAllChunks(&mux->anim_); + DeleteAllChunks(&mux->exif_); + DeleteAllChunks(&mux->xmp_); DeleteAllChunks(&mux->unknown_); } @@ -81,13 +85,14 @@ static WebPMuxError MuxSet(WebPMux* const mux, CHUNK_INDEX idx, uint32_t nth, ChunkInit(&chunk); SWITCH_ID_LIST(IDX_VP8X, &mux->vp8x_); SWITCH_ID_LIST(IDX_ICCP, &mux->iccp_); - SWITCH_ID_LIST(IDX_LOOP, &mux->loop_); - SWITCH_ID_LIST(IDX_META, &mux->meta_); - if (idx == IDX_UNKNOWN && data->size_ > TAG_SIZE) { + SWITCH_ID_LIST(IDX_ANIM, &mux->anim_); + SWITCH_ID_LIST(IDX_EXIF, &mux->exif_); + SWITCH_ID_LIST(IDX_XMP, &mux->xmp_); + if (idx == IDX_UNKNOWN && data->size > TAG_SIZE) { // For raw-data unknown chunk, the first four bytes should be the tag to be // used for the chunk. - const WebPData tmp = { data->bytes_ + TAG_SIZE, data->size_ - TAG_SIZE }; - err = ChunkAssignData(&chunk, &tmp, copy_data, GetLE32(data->bytes_ + 0)); + const WebPData tmp = { data->bytes + TAG_SIZE, data->size - TAG_SIZE }; + err = ChunkAssignData(&chunk, &tmp, copy_data, GetLE32(data->bytes + 0)); if (err == WEBP_MUX_OK) err = ChunkSetNth(&chunk, &mux->unknown_, nth); } @@ -106,39 +111,40 @@ static WebPMuxError MuxAddChunk(WebPMux* const mux, uint32_t nth, uint32_t tag, return MuxSet(mux, idx, nth, &chunk_data, copy_data); } -// Create data for frame/tile given image data, offsets and duration. -static WebPMuxError CreateFrameTileData(const WebPData* const image, - int x_offset, int y_offset, - int duration, int is_lossless, - int is_frame, - WebPData* const frame_tile) { +// Create data for frame/fragment given image data, offsets and duration. +static WebPMuxError CreateFrameFragmentData( + const WebPData* const image, int x_offset, int y_offset, int duration, + WebPMuxAnimDispose dispose_method, int is_lossless, int is_frame, + WebPData* const frame_frgm) { int width; int height; - uint8_t* frame_tile_bytes; - const size_t frame_tile_size = kChunks[is_frame ? IDX_FRAME : IDX_TILE].size; + uint8_t* frame_frgm_bytes; + const size_t frame_frgm_size = kChunks[is_frame ? IDX_ANMF : IDX_FRGM].size; const int ok = is_lossless ? - VP8LGetInfo(image->bytes_, image->size_, &width, &height, NULL) : - VP8GetInfo(image->bytes_, image->size_, image->size_, &width, &height); + VP8LGetInfo(image->bytes, image->size, &width, &height, NULL) : + VP8GetInfo(image->bytes, image->size, image->size, &width, &height); if (!ok) return WEBP_MUX_INVALID_ARGUMENT; - assert(width > 0 && height > 0 && duration > 0); + assert(width > 0 && height > 0 && duration >= 0); + assert(dispose_method == (dispose_method & 1)); // Note: assertion on upper bounds is done in PutLE24(). - frame_tile_bytes = (uint8_t*)malloc(frame_tile_size); - if (frame_tile_bytes == NULL) return WEBP_MUX_MEMORY_ERROR; + frame_frgm_bytes = (uint8_t*)malloc(frame_frgm_size); + if (frame_frgm_bytes == NULL) return WEBP_MUX_MEMORY_ERROR; - PutLE24(frame_tile_bytes + 0, x_offset / 2); - PutLE24(frame_tile_bytes + 3, y_offset / 2); + PutLE24(frame_frgm_bytes + 0, x_offset / 2); + PutLE24(frame_frgm_bytes + 3, y_offset / 2); if (is_frame) { - PutLE24(frame_tile_bytes + 6, width - 1); - PutLE24(frame_tile_bytes + 9, height - 1); - PutLE24(frame_tile_bytes + 12, duration - 1); + PutLE24(frame_frgm_bytes + 6, width - 1); + PutLE24(frame_frgm_bytes + 9, height - 1); + PutLE24(frame_frgm_bytes + 12, duration); + frame_frgm_bytes[15] = (dispose_method & 1); } - frame_tile->bytes_ = frame_tile_bytes; - frame_tile->size_ = frame_tile_size; + frame_frgm->bytes = frame_frgm_bytes; + frame_frgm->size = frame_frgm_size; return WEBP_MUX_OK; } @@ -149,8 +155,8 @@ static WebPMuxError GetImageData(const WebPData* const bitstream, WebPData* const image, WebPData* const alpha, int* const is_lossless) { WebPDataInit(alpha); // Default: no alpha. - if (bitstream->size_ < TAG_SIZE || - memcmp(bitstream->bytes_, "RIFF", TAG_SIZE)) { + if (bitstream->size < TAG_SIZE || + memcmp(bitstream->bytes, "RIFF", TAG_SIZE)) { // It is NOT webp file data. Return input data as is. *image = *bitstream; } else { @@ -166,7 +172,7 @@ static WebPMuxError GetImageData(const WebPData* const bitstream, } WebPMuxDelete(mux); } - *is_lossless = VP8LCheckSignature(image->bytes_, image->size_); + *is_lossless = VP8LCheckSignature(image->bytes, image->size); return WEBP_MUX_OK; } @@ -185,203 +191,96 @@ static WebPMuxError DeleteChunks(WebPChunk** chunk_list, uint32_t tag) { return err; } -static WebPMuxError MuxDeleteAllNamedData(WebPMux* const mux, CHUNK_INDEX idx) { - const WebPChunkId id = kChunks[idx].id; +static WebPMuxError MuxDeleteAllNamedData(WebPMux* const mux, uint32_t tag) { + const WebPChunkId id = ChunkGetIdFromTag(tag); WebPChunk** chunk_list; - if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; + assert(mux != NULL); if (IsWPI(id)) return WEBP_MUX_INVALID_ARGUMENT; chunk_list = MuxGetChunkListFromId(mux, id); if (chunk_list == NULL) return WEBP_MUX_INVALID_ARGUMENT; - return DeleteChunks(chunk_list, kChunks[idx].tag); -} - -static WebPMuxError DeleteLoopCount(WebPMux* const mux) { - return MuxDeleteAllNamedData(mux, IDX_LOOP); + return DeleteChunks(chunk_list, tag); } //------------------------------------------------------------------------------ // Set API(s). -WebPMuxError WebPMuxSetImage(WebPMux* mux, - const WebPData* bitstream, int copy_data) { +WebPMuxError WebPMuxSetChunk(WebPMux* mux, const char fourcc[4], + const WebPData* chunk_data, int copy_data) { + CHUNK_INDEX idx; + uint32_t tag; WebPMuxError err; - WebPChunk chunk; - WebPMuxImage wpi; - WebPData image; - WebPData alpha; - int is_lossless; - int image_tag; - - if (mux == NULL || bitstream == NULL || bitstream->bytes_ == NULL || - bitstream->size_ > MAX_CHUNK_PAYLOAD) { + if (mux == NULL || fourcc == NULL || chunk_data == NULL || + chunk_data->bytes == NULL || chunk_data->size > MAX_CHUNK_PAYLOAD) { return WEBP_MUX_INVALID_ARGUMENT; } + idx = ChunkGetIndexFromFourCC(fourcc); + tag = ChunkGetTagFromFourCC(fourcc); - // If given data is for a whole webp file, - // extract only the VP8/VP8L data from it. - err = GetImageData(bitstream, &image, &alpha, &is_lossless); - if (err != WEBP_MUX_OK) return err; - image_tag = is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag; + // Delete existing chunk(s) with the same 'fourcc'. + err = MuxDeleteAllNamedData(mux, tag); + if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; - // Delete the existing images. - MuxImageDeleteAll(&mux->images_); + // Add the given chunk. + return MuxSet(mux, idx, 1, chunk_data, copy_data); +} - MuxImageInit(&wpi); - - if (alpha.bytes_ != NULL) { // Add alpha chunk. - ChunkInit(&chunk); - err = ChunkAssignData(&chunk, &alpha, copy_data, kChunks[IDX_ALPHA].tag); - if (err != WEBP_MUX_OK) goto Err; - err = ChunkSetNth(&chunk, &wpi.alpha_, 1); - if (err != WEBP_MUX_OK) goto Err; - } - - // Add image chunk. +// Creates a chunk from given 'data' and sets it as 1st chunk in 'chunk_list'. +static WebPMuxError AddDataToChunkList( + const WebPData* const data, int copy_data, uint32_t tag, + WebPChunk** chunk_list) { + WebPChunk chunk; + WebPMuxError err; ChunkInit(&chunk); - err = ChunkAssignData(&chunk, &image, copy_data, image_tag); + err = ChunkAssignData(&chunk, data, copy_data, tag); if (err != WEBP_MUX_OK) goto Err; - err = ChunkSetNth(&chunk, &wpi.img_, 1); + err = ChunkSetNth(&chunk, chunk_list, 1); if (err != WEBP_MUX_OK) goto Err; - - // Add this image to mux. - err = MuxImagePush(&wpi, &mux->images_); - if (err != WEBP_MUX_OK) goto Err; - - // All OK. return WEBP_MUX_OK; - Err: - // Something bad happened. ChunkRelease(&chunk); - MuxImageRelease(&wpi); return err; } -WebPMuxError WebPMuxSetMetadata(WebPMux* mux, const WebPData* metadata, - int copy_data) { - WebPMuxError err; - - if (mux == NULL || metadata == NULL || metadata->bytes_ == NULL || - metadata->size_ > MAX_CHUNK_PAYLOAD) { - return WEBP_MUX_INVALID_ARGUMENT; +// Extracts image & alpha data from the given bitstream and then sets wpi.alpha_ +// and wpi.img_ appropriately. +static WebPMuxError SetAlphaAndImageChunks( + const WebPData* const bitstream, int copy_data, WebPMuxImage* const wpi) { + int is_lossless = 0; + WebPData image, alpha; + WebPMuxError err = GetImageData(bitstream, &image, &alpha, &is_lossless); + const int image_tag = + is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag; + if (err != WEBP_MUX_OK) return err; + if (alpha.bytes != NULL) { + err = AddDataToChunkList(&alpha, copy_data, kChunks[IDX_ALPHA].tag, + &wpi->alpha_); + if (err != WEBP_MUX_OK) return err; } - - // Delete the existing metadata chunk(s). - err = WebPMuxDeleteMetadata(mux); - if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; - - // Add the given metadata chunk. - return MuxSet(mux, IDX_META, 1, metadata, copy_data); + return AddDataToChunkList(&image, copy_data, image_tag, &wpi->img_); } -WebPMuxError WebPMuxSetColorProfile(WebPMux* mux, const WebPData* color_profile, - int copy_data) { - WebPMuxError err; - - if (mux == NULL || color_profile == NULL || color_profile->bytes_ == NULL || - color_profile->size_ > MAX_CHUNK_PAYLOAD) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - // Delete the existing ICCP chunk(s). - err = WebPMuxDeleteColorProfile(mux); - if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; - - // Add the given ICCP chunk. - return MuxSet(mux, IDX_ICCP, 1, color_profile, copy_data); -} - -WebPMuxError WebPMuxSetLoopCount(WebPMux* mux, int loop_count) { - WebPMuxError err; - uint8_t* data = NULL; - - if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; - if (loop_count >= MAX_LOOP_COUNT) return WEBP_MUX_INVALID_ARGUMENT; - - // Delete the existing LOOP chunk(s). - err = DeleteLoopCount(mux); - if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; - - // Add the given loop count. - data = (uint8_t*)malloc(kChunks[IDX_LOOP].size); - if (data == NULL) return WEBP_MUX_MEMORY_ERROR; - - PutLE16(data, loop_count); - err = MuxAddChunk(mux, 1, kChunks[IDX_LOOP].tag, data, - kChunks[IDX_LOOP].size, 1); - free(data); - return err; -} - -static WebPMuxError MuxPushFrameTileInternal( - WebPMux* const mux, const WebPData* const bitstream, int x_offset, - int y_offset, int duration, int copy_data, uint32_t tag) { - WebPChunk chunk; - WebPData image; - WebPData alpha; +WebPMuxError WebPMuxSetImage(WebPMux* mux, const WebPData* bitstream, + int copy_data) { WebPMuxImage wpi; WebPMuxError err; - WebPData frame_tile; - const int is_frame = (tag == kChunks[IDX_FRAME].tag) ? 1 : 0; - int is_lossless; - int image_tag; // Sanity checks. - if (mux == NULL || bitstream == NULL || bitstream->bytes_ == NULL || - bitstream->size_ > MAX_CHUNK_PAYLOAD) { - return WEBP_MUX_INVALID_ARGUMENT; - } - if (x_offset < 0 || x_offset >= MAX_POSITION_OFFSET || - y_offset < 0 || y_offset >= MAX_POSITION_OFFSET || - duration <= 0 || duration > MAX_DURATION) { + if (mux == NULL || bitstream == NULL || bitstream->bytes == NULL || + bitstream->size > MAX_CHUNK_PAYLOAD) { return WEBP_MUX_INVALID_ARGUMENT; } - // Snap offsets to even positions. - x_offset &= ~1; - y_offset &= ~1; + if (mux->images_ != NULL) { + // Only one 'simple image' can be added in mux. So, remove present images. + MuxImageDeleteAll(&mux->images_); + } - // If given data is for a whole webp file, - // extract only the VP8/VP8L data from it. - err = GetImageData(bitstream, &image, &alpha, &is_lossless); - if (err != WEBP_MUX_OK) return err; - image_tag = is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag; - - WebPDataInit(&frame_tile); - ChunkInit(&chunk); MuxImageInit(&wpi); - - if (alpha.bytes_ != NULL) { - // Add alpha chunk. - err = ChunkAssignData(&chunk, &alpha, copy_data, kChunks[IDX_ALPHA].tag); - if (err != WEBP_MUX_OK) goto Err; - err = ChunkSetNth(&chunk, &wpi.alpha_, 1); - if (err != WEBP_MUX_OK) goto Err; - ChunkInit(&chunk); // chunk owned by wpi.alpha_ now. - } - - // Add image chunk. - err = ChunkAssignData(&chunk, &image, copy_data, image_tag); + err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi); if (err != WEBP_MUX_OK) goto Err; - err = ChunkSetNth(&chunk, &wpi.img_, 1); - if (err != WEBP_MUX_OK) goto Err; - ChunkInit(&chunk); // chunk owned by wpi.img_ now. - - // Create frame/tile data. - err = CreateFrameTileData(&image, x_offset, y_offset, duration, is_lossless, - is_frame, &frame_tile); - if (err != WEBP_MUX_OK) goto Err; - - // Add frame/tile chunk (with copy_data = 1). - err = ChunkAssignData(&chunk, &frame_tile, 1, tag); - if (err != WEBP_MUX_OK) goto Err; - WebPDataClear(&frame_tile); - err = ChunkSetNth(&chunk, &wpi.header_, 1); - if (err != WEBP_MUX_OK) goto Err; - ChunkInit(&chunk); // chunk owned by wpi.header_ now. // Add this WebPMuxImage to mux. err = MuxImagePush(&wpi, &mux->images_); @@ -391,86 +290,137 @@ static WebPMuxError MuxPushFrameTileInternal( return WEBP_MUX_OK; Err: // Something bad happened. - WebPDataClear(&frame_tile); - ChunkRelease(&chunk); MuxImageRelease(&wpi); return err; } -WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPData* bitstream, - int x_offset, int y_offset, - int duration, int copy_data) { - return MuxPushFrameTileInternal(mux, bitstream, x_offset, y_offset, - duration, copy_data, kChunks[IDX_FRAME].tag); +WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* frame, + int copy_data) { + WebPMuxImage wpi; + WebPMuxError err; + int is_frame; + const WebPData* const bitstream = &frame->bitstream; + + // Sanity checks. + if (mux == NULL || frame == NULL) return WEBP_MUX_INVALID_ARGUMENT; + + is_frame = (frame->id == WEBP_CHUNK_ANMF); + if (!(is_frame || (frame->id == WEBP_CHUNK_FRGM))) { + return WEBP_MUX_INVALID_ARGUMENT; + } +#ifndef WEBP_EXPERIMENTAL_FEATURES + if (frame->id == WEBP_CHUNK_FRGM) { // disabled for now. + return WEBP_MUX_INVALID_ARGUMENT; + } +#endif + + if (bitstream->bytes == NULL || bitstream->size > MAX_CHUNK_PAYLOAD) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + if (mux->images_ != NULL) { + const WebPMuxImage* const image = mux->images_; + const uint32_t image_id = (image->header_ != NULL) ? + ChunkGetIdFromTag(image->header_->tag_) : WEBP_CHUNK_IMAGE; + if (image_id != frame->id) { + return WEBP_MUX_INVALID_ARGUMENT; // Conflicting frame types. + } + } + + MuxImageInit(&wpi); + err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi); + if (err != WEBP_MUX_OK) goto Err; + assert(wpi.img_ != NULL); // As SetAlphaAndImageChunks() was successful. + + { + const int is_lossless = (wpi.img_->tag_ == kChunks[IDX_VP8L].tag); + const int x_offset = frame->x_offset & ~1; // Snap offsets to even. + const int y_offset = frame->y_offset & ~1; + const int duration = is_frame ? frame->duration : 1 /* unused */; + const WebPMuxAnimDispose dispose_method = + is_frame ? frame->dispose_method : 0 /* unused */; + const uint32_t tag = kChunks[is_frame ? IDX_ANMF : IDX_FRGM].tag; + WebPData frame_frgm; + if (x_offset < 0 || x_offset >= MAX_POSITION_OFFSET || + y_offset < 0 || y_offset >= MAX_POSITION_OFFSET || + (duration < 0 || duration >= MAX_DURATION) || + dispose_method != (dispose_method & 1)) { + err = WEBP_MUX_INVALID_ARGUMENT; + goto Err; + } + err = CreateFrameFragmentData(&wpi.img_->data_, x_offset, y_offset, + duration, dispose_method, is_lossless, + is_frame, &frame_frgm); + if (err != WEBP_MUX_OK) goto Err; + // Add frame/fragment chunk (with copy_data = 1). + err = AddDataToChunkList(&frame_frgm, 1, tag, &wpi.header_); + WebPDataClear(&frame_frgm); // frame_frgm owned by wpi.header_ now. + if (err != WEBP_MUX_OK) goto Err; + } + + // Add this WebPMuxImage to mux. + err = MuxImagePush(&wpi, &mux->images_); + if (err != WEBP_MUX_OK) goto Err; + + // All is well. + return WEBP_MUX_OK; + + Err: // Something bad happened. + MuxImageRelease(&wpi); + return err; } -WebPMuxError WebPMuxPushTile(WebPMux* mux, const WebPData* bitstream, - int x_offset, int y_offset, - int copy_data) { - return MuxPushFrameTileInternal(mux, bitstream, x_offset, y_offset, - 1 /* unused duration */, copy_data, - kChunks[IDX_TILE].tag); +WebPMuxError WebPMuxSetAnimationParams(WebPMux* mux, + const WebPMuxAnimParams* params) { + WebPMuxError err; + uint8_t data[ANIM_CHUNK_SIZE]; + + if (mux == NULL || params == NULL) return WEBP_MUX_INVALID_ARGUMENT; + if (params->loop_count < 0 || params->loop_count >= MAX_LOOP_COUNT) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + // Delete any existing ANIM chunk(s). + err = MuxDeleteAllNamedData(mux, kChunks[IDX_ANIM].tag); + if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; + + // Set the animation parameters. + PutLE32(data, params->bgcolor); + PutLE16(data + 4, params->loop_count); + return MuxAddChunk(mux, 1, kChunks[IDX_ANIM].tag, data, sizeof(data), 1); } //------------------------------------------------------------------------------ // Delete API(s). -WebPMuxError WebPMuxDeleteImage(WebPMux* mux) { - WebPMuxError err; - - if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; - - err = MuxValidateForImage(mux); - if (err != WEBP_MUX_OK) return err; - - // All well, delete image. - MuxImageDeleteAll(&mux->images_); - return WEBP_MUX_OK; -} - -WebPMuxError WebPMuxDeleteMetadata(WebPMux* mux) { - return MuxDeleteAllNamedData(mux, IDX_META); -} - -WebPMuxError WebPMuxDeleteColorProfile(WebPMux* mux) { - return MuxDeleteAllNamedData(mux, IDX_ICCP); -} - -static WebPMuxError DeleteFrameTileInternal(WebPMux* const mux, uint32_t nth, - CHUNK_INDEX idx) { - const WebPChunkId id = kChunks[idx].id; - if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; - - assert(idx == IDX_FRAME || idx == IDX_TILE); - return MuxImageDeleteNth(&mux->images_, nth, id); +WebPMuxError WebPMuxDeleteChunk(WebPMux* mux, const char fourcc[4]) { + if (mux == NULL || fourcc == NULL) return WEBP_MUX_INVALID_ARGUMENT; + return MuxDeleteAllNamedData(mux, ChunkGetTagFromFourCC(fourcc)); } WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth) { - return DeleteFrameTileInternal(mux, nth, IDX_FRAME); -} - -WebPMuxError WebPMuxDeleteTile(WebPMux* mux, uint32_t nth) { - return DeleteFrameTileInternal(mux, nth, IDX_TILE); + if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; + return MuxImageDeleteNth(&mux->images_, nth); } //------------------------------------------------------------------------------ // Assembly of the WebP RIFF file. -static WebPMuxError GetFrameTileInfo(const WebPChunk* const frame_tile_chunk, - int* const x_offset, int* const y_offset, - int* const duration) { - const uint32_t tag = frame_tile_chunk->tag_; - const int is_frame = (tag == kChunks[IDX_FRAME].tag); - const WebPData* const data = &frame_tile_chunk->data_; +static WebPMuxError GetFrameFragmentInfo( + const WebPChunk* const frame_frgm_chunk, + int* const x_offset, int* const y_offset, int* const duration) { + const uint32_t tag = frame_frgm_chunk->tag_; + const int is_frame = (tag == kChunks[IDX_ANMF].tag); + const WebPData* const data = &frame_frgm_chunk->data_; const size_t expected_data_size = - is_frame ? FRAME_CHUNK_SIZE : TILE_CHUNK_SIZE; - assert(frame_tile_chunk != NULL); - assert(tag == kChunks[IDX_FRAME].tag || tag == kChunks[IDX_TILE].tag); - if (data->size_ != expected_data_size) return WEBP_MUX_INVALID_ARGUMENT; + is_frame ? ANMF_CHUNK_SIZE : FRGM_CHUNK_SIZE; + assert(frame_frgm_chunk != NULL); + assert(tag == kChunks[IDX_ANMF].tag || tag == kChunks[IDX_FRGM].tag); + if (data->size != expected_data_size) return WEBP_MUX_INVALID_ARGUMENT; - *x_offset = 2 * GetLE24(data->bytes_ + 0); - *y_offset = 2 * GetLE24(data->bytes_ + 3); - if (is_frame) *duration = 1 + GetLE24(data->bytes_ + 12); + *x_offset = 2 * GetLE24(data->bytes + 0); + *y_offset = 2 * GetLE24(data->bytes + 3); + if (is_frame) *duration = GetLE24(data->bytes + 12); return WEBP_MUX_OK; } @@ -483,8 +433,8 @@ WebPMuxError MuxGetImageWidthHeight(const WebPChunk* const image_chunk, assert(image_chunk != NULL); assert(tag == kChunks[IDX_VP8].tag || tag == kChunks[IDX_VP8L].tag); ok = (tag == kChunks[IDX_VP8].tag) ? - VP8GetInfo(data->bytes_, data->size_, data->size_, &w, &h) : - VP8LGetInfo(data->bytes_, data->size_, &w, &h, NULL); + VP8GetInfo(data->bytes, data->size, data->size, &w, &h) : + VP8LGetInfo(data->bytes, data->size, &w, &h, NULL); if (ok) { *width = w; *height = h; @@ -499,11 +449,11 @@ static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi, int* const duration, int* const width, int* const height) { const WebPChunk* const image_chunk = wpi->img_; - const WebPChunk* const frame_tile_chunk = wpi->header_; + const WebPChunk* const frame_frgm_chunk = wpi->header_; - // Get offsets and duration from FRM/TILE chunk. + // Get offsets and duration from ANMF/FRGM chunk. const WebPMuxError err = - GetFrameTileInfo(frame_tile_chunk, x_offset, y_offset, duration); + GetFrameFragmentInfo(frame_frgm_chunk, x_offset, y_offset, duration); if (err != WEBP_MUX_OK) return err; // Get width and height from VP8/VP8L chunk. @@ -525,9 +475,9 @@ static WebPMuxError GetImageCanvasWidthHeight( int max_x = 0; int max_y = 0; int64_t image_area = 0; - // Aggregate the bounding box for animation frames & tiled images. + // Aggregate the bounding box for animation frames & fragmented images. for (; wpi != NULL; wpi = wpi->next_) { - int x_offset, y_offset, duration, w, h; + int x_offset = 0, y_offset = 0, duration = 0, w = 0, h = 0; const WebPMuxError err = GetImageInfo(wpi, &x_offset, &y_offset, &duration, &w, &h); const int max_x_pos = x_offset + w; @@ -542,11 +492,11 @@ static WebPMuxError GetImageCanvasWidthHeight( } *width = max_x; *height = max_y; - // Crude check to validate that there are no image overlaps/holes for tile - // images. Check that the aggregated image area for individual tiles exactly - // matches the image area of the constructed canvas. However, the area-match - // is necessary but not sufficient condition. - if ((flags & TILE_FLAG) && (image_area != (max_x * max_y))) { + // Crude check to validate that there are no image overlaps/holes for + // fragmented images. Check that the aggregated image area for individual + // fragments exactly matches the image area of the constructed canvas. + // However, the area-match is necessary but not sufficient condition. + if ((flags & FRAGMENTS_FLAG) && (image_area != (max_x * max_y))) { *width = 0; *height = 0; return WEBP_MUX_INVALID_ARGUMENT; @@ -580,34 +530,34 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) { assert(mux != NULL); images = mux->images_; // First image. if (images == NULL || images->img_ == NULL || - images->img_->data_.bytes_ == NULL) { + images->img_->data_.bytes == NULL) { return WEBP_MUX_INVALID_ARGUMENT; } // If VP8X chunk(s) is(are) already present, remove them (and later add new // VP8X chunk with updated flags). - err = MuxDeleteAllNamedData(mux, IDX_VP8X); + err = MuxDeleteAllNamedData(mux, kChunks[IDX_VP8X].tag); if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; // Set flags. - if (mux->iccp_ != NULL && mux->iccp_->data_.bytes_ != NULL) { + if (mux->iccp_ != NULL && mux->iccp_->data_.bytes != NULL) { flags |= ICCP_FLAG; } - - if (mux->meta_ != NULL && mux->meta_->data_.bytes_ != NULL) { - flags |= META_FLAG; + if (mux->exif_ != NULL && mux->exif_->data_.bytes != NULL) { + flags |= EXIF_FLAG; + } + if (mux->xmp_ != NULL && mux->xmp_->data_.bytes != NULL) { + flags |= XMP_FLAG; } - if (images->header_ != NULL) { - if (images->header_->tag_ == kChunks[IDX_TILE].tag) { - // This is a tiled image. - flags |= TILE_FLAG; - } else if (images->header_->tag_ == kChunks[IDX_FRAME].tag) { + if (images->header_->tag_ == kChunks[IDX_FRGM].tag) { + // This is a fragmented image. + flags |= FRAGMENTS_FLAG; + } else if (images->header_->tag_ == kChunks[IDX_ANMF].tag) { // This is an image with animation. flags |= ANIMATION_FLAG; } } - if (MuxImageCount(images, WEBP_CHUNK_ALPHA) > 0) { flags |= ALPHA_FLAG; // Some images have an alpha channel. } @@ -643,39 +593,63 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) { return err; } +// Cleans up 'mux' by removing any unnecessary chunks. +static WebPMuxError MuxCleanup(WebPMux* const mux) { + int num_frames; + int num_fragments; + int num_anim_chunks; + + // If we have an image with single fragment or frame, convert it to a + // non-animated non-fragmented image (to avoid writing FRGM/ANMF chunk + // unnecessarily). + WebPMuxError err = WebPMuxNumChunks(mux, kChunks[IDX_ANMF].id, &num_frames); + if (err != WEBP_MUX_OK) return err; + err = WebPMuxNumChunks(mux, kChunks[IDX_FRGM].id, &num_fragments); + if (err != WEBP_MUX_OK) return err; + if (num_frames == 1 || num_fragments == 1) { + WebPMuxImage* frame_frag; + err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, &frame_frag); + assert(err == WEBP_MUX_OK); // We know that one frame/fragment does exist. + if (frame_frag->header_ != NULL) { + assert(frame_frag->header_->tag_ == kChunks[IDX_ANMF].tag || + frame_frag->header_->tag_ == kChunks[IDX_FRGM].tag); + ChunkDelete(frame_frag->header_); // Removes ANMF/FRGM chunk. + frame_frag->header_ = NULL; + } + num_frames = 0; + num_fragments = 0; + } + // Remove ANIM chunk if this is a non-animated image. + err = WebPMuxNumChunks(mux, kChunks[IDX_ANIM].id, &num_anim_chunks); + if (err != WEBP_MUX_OK) return err; + if (num_anim_chunks >= 1 && num_frames == 0) { + err = MuxDeleteAllNamedData(mux, kChunks[IDX_ANIM].tag); + if (err != WEBP_MUX_OK) return err; + } + return WEBP_MUX_OK; +} + WebPMuxError WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data) { size_t size = 0; uint8_t* data = NULL; uint8_t* dst = NULL; - int num_frames; - int num_loop_chunks; WebPMuxError err; if (mux == NULL || assembled_data == NULL) { return WEBP_MUX_INVALID_ARGUMENT; } - // Remove LOOP chunk if unnecessary. - err = WebPMuxNumChunks(mux, kChunks[IDX_LOOP].id, &num_loop_chunks); + // Finalize mux. + err = MuxCleanup(mux); if (err != WEBP_MUX_OK) return err; - if (num_loop_chunks >= 1) { - err = WebPMuxNumChunks(mux, kChunks[IDX_FRAME].id, &num_frames); - if (err != WEBP_MUX_OK) return err; - if (num_frames == 0) { - err = DeleteLoopCount(mux); - if (err != WEBP_MUX_OK) return err; - } - } - - // Create VP8X chunk. err = CreateVP8XChunk(mux); if (err != WEBP_MUX_OK) return err; // Allocate data. size = ChunksListDiskSize(mux->vp8x_) + ChunksListDiskSize(mux->iccp_) - + ChunksListDiskSize(mux->loop_) + MuxImageListDiskSize(mux->images_) - + ChunksListDiskSize(mux->meta_) + ChunksListDiskSize(mux->unknown_) - + RIFF_HEADER_SIZE; + + ChunksListDiskSize(mux->anim_) + MuxImageListDiskSize(mux->images_) + + ChunksListDiskSize(mux->exif_) + ChunksListDiskSize(mux->xmp_) + + ChunksListDiskSize(mux->unknown_) + RIFF_HEADER_SIZE; data = (uint8_t*)malloc(size); if (data == NULL) return WEBP_MUX_MEMORY_ERROR; @@ -684,9 +658,10 @@ WebPMuxError WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data) { dst = MuxEmitRiffHeader(data, size); dst = ChunkListEmit(mux->vp8x_, dst); dst = ChunkListEmit(mux->iccp_, dst); - dst = ChunkListEmit(mux->loop_, dst); + dst = ChunkListEmit(mux->anim_, dst); dst = MuxImageListEmit(mux->images_, dst); - dst = ChunkListEmit(mux->meta_, dst); + dst = ChunkListEmit(mux->exif_, dst); + dst = ChunkListEmit(mux->xmp_, dst); dst = ChunkListEmit(mux->unknown_, dst); assert(dst == data + size); @@ -698,9 +673,9 @@ WebPMuxError WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data) { size = 0; } - // Finalize. - assembled_data->bytes_ = data; - assembled_data->size_ = size; + // Finalize data. + assembled_data->bytes = data; + assembled_data->size = size; return err; } diff --git a/3rdparty/libwebp/mux/muxi.h b/3rdparty/libwebp/mux/muxi.h index edd8c368cd..eaed558b47 100644 --- a/3rdparty/libwebp/mux/muxi.h +++ b/3rdparty/libwebp/mux/muxi.h @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Internal header for mux library. @@ -15,7 +17,6 @@ #include #include "../dec/vp8i.h" #include "../dec/vp8li.h" -#include "../webp/format_constants.h" #include "../webp/mux.h" #if defined(__cplusplus) || defined(c_plusplus) @@ -25,22 +26,26 @@ extern "C" { //------------------------------------------------------------------------------ // Defines and constants. +#define MUX_MAJ_VERSION 0 +#define MUX_MIN_VERSION 1 +#define MUX_REV_VERSION 1 + // Chunk object. typedef struct WebPChunk WebPChunk; struct WebPChunk { uint32_t tag_; int owner_; // True if *data_ memory is owned internally. - // VP8X, Loop, and other internally created chunks - // like frame/tile are always owned. + // VP8X, ANIM, and other internally created chunks + // like ANMF/FRGM are always owned. WebPData data_; WebPChunk* next_; }; -// MuxImage object. Store a full webp image (including frame/tile chunk, alpha +// MuxImage object. Store a full WebP image (including ANMF/FRGM chunk, ALPH // chunk and VP8/VP8L chunk), typedef struct WebPMuxImage WebPMuxImage; struct WebPMuxImage { - WebPChunk* header_; // Corresponds to WEBP_CHUNK_FRAME/WEBP_CHUNK_TILE. + WebPChunk* header_; // Corresponds to WEBP_CHUNK_ANMF/WEBP_CHUNK_FRGM. WebPChunk* alpha_; // Corresponds to WEBP_CHUNK_ALPHA. WebPChunk* img_; // Corresponds to WEBP_CHUNK_IMAGE. int is_partial_; // True if only some of the chunks are filled. @@ -51,8 +56,9 @@ struct WebPMuxImage { struct WebPMux { WebPMuxImage* images_; WebPChunk* iccp_; - WebPChunk* meta_; - WebPChunk* loop_; + WebPChunk* exif_; + WebPChunk* xmp_; + WebPChunk* anim_; WebPChunk* vp8x_; WebPChunk* unknown_; @@ -65,13 +71,14 @@ struct WebPMux { typedef enum { IDX_VP8X = 0, IDX_ICCP, - IDX_LOOP, - IDX_FRAME, - IDX_TILE, + IDX_ANIM, + IDX_ANMF, + IDX_FRGM, IDX_ALPHA, IDX_VP8, IDX_VP8L, - IDX_META, + IDX_EXIF, + IDX_XMP, IDX_UNKNOWN, IDX_NIL, @@ -80,8 +87,6 @@ typedef enum { #define NIL_TAG 0x00000000u // To signal void chunk. -#define MKFOURCC(a, b, c, d) ((uint32_t)(a) | (b) << 8 | (c) << 16 | (d) << 24) - typedef struct { uint32_t tag; WebPChunkId id; @@ -90,44 +95,6 @@ typedef struct { extern const ChunkInfo kChunks[IDX_LAST_CHUNK]; -//------------------------------------------------------------------------------ -// Helper functions. - -// Read 16, 24 or 32 bits stored in little-endian order. -static WEBP_INLINE int GetLE16(const uint8_t* const data) { - return (int)(data[0] << 0) | (data[1] << 8); -} - -static WEBP_INLINE int GetLE24(const uint8_t* const data) { - return GetLE16(data) | (data[2] << 16); -} - -static WEBP_INLINE uint32_t GetLE32(const uint8_t* const data) { - return (uint32_t)GetLE16(data) | (GetLE16(data + 2) << 16); -} - -// Store 16, 24 or 32 bits in little-endian order. -static WEBP_INLINE void PutLE16(uint8_t* const data, int val) { - assert(val < (1 << 16)); - data[0] = (val >> 0); - data[1] = (val >> 8); -} - -static WEBP_INLINE void PutLE24(uint8_t* const data, int val) { - assert(val < (1 << 24)); - PutLE16(data, val & 0xffff); - data[2] = (val >> 16); -} - -static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) { - PutLE16(data, (int)(val & 0xffff)); - PutLE16(data + 2, (int)(val >> 16)); -} - -static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) { - return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U); -} - //------------------------------------------------------------------------------ // Chunk object management. @@ -140,6 +107,12 @@ CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag); // Get chunk id from chunk tag. Returns WEBP_CHUNK_NIL if not found. WebPChunkId ChunkGetIdFromTag(uint32_t tag); +// Convert a fourcc string to a tag. +uint32_t ChunkGetTagFromFourCC(const char fourcc[4]); + +// Get chunk index from fourcc. Returns IDX_UNKNOWN if given fourcc is unknown. +CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]); + // Search for nth chunk with given 'tag' in the chunk list. // nth = 0 means "last of the list". WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag); @@ -150,7 +123,8 @@ WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data, // Sets 'chunk' at nth position in the 'chunk_list'. // nth = 0 has the special meaning "last of the list". -WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list, +// On success ownership is transferred from 'chunk' to the 'chunk_list'. +WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list, uint32_t nth); // Releases chunk and returns chunk->next_. @@ -159,9 +133,14 @@ WebPChunk* ChunkRelease(WebPChunk* const chunk); // Deletes given chunk & returns chunk->next_. WebPChunk* ChunkDelete(WebPChunk* const chunk); +// Returns size of the chunk including chunk header and padding byte (if any). +static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) { + return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U); +} + // Size of a chunk including header and padding. static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) { - const size_t data_size = chunk->data_.size_; + const size_t data_size = chunk->data_.size; assert(data_size < MAX_CHUNK_PAYLOAD); return SizeWithPadding(data_size); } @@ -193,13 +172,14 @@ WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi); void MuxImageDeleteAll(WebPMuxImage** const wpi_list); // Count number of images matching the given tag id in the 'wpi_list'. +// If id == WEBP_CHUNK_NIL, all images will be matched. int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id); // Check if given ID corresponds to an image related chunk. static WEBP_INLINE int IsWPI(WebPChunkId id) { switch (id) { - case WEBP_CHUNK_FRAME: - case WEBP_CHUNK_TILE: + case WEBP_CHUNK_ANMF: + case WEBP_CHUNK_FRGM: case WEBP_CHUNK_ALPHA: case WEBP_CHUNK_IMAGE: return 1; default: return 0; @@ -211,8 +191,8 @@ static WEBP_INLINE WebPChunk** MuxImageGetListFromId( const WebPMuxImage* const wpi, WebPChunkId id) { assert(wpi != NULL); switch (id) { - case WEBP_CHUNK_FRAME: - case WEBP_CHUNK_TILE: return (WebPChunk**)&wpi->header_; + case WEBP_CHUNK_ANMF: + case WEBP_CHUNK_FRGM: return (WebPChunk**)&wpi->header_; case WEBP_CHUNK_ALPHA: return (WebPChunk**)&wpi->alpha_; case WEBP_CHUNK_IMAGE: return (WebPChunk**)&wpi->img_; default: return NULL; @@ -222,13 +202,12 @@ static WEBP_INLINE WebPChunk** MuxImageGetListFromId( // Pushes 'wpi' at the end of 'wpi_list'. WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list); -// Delete nth image in the image list with given tag id. -WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth, - WebPChunkId id); +// Delete nth image in the image list. +WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth); -// Get nth image in the image list with given tag id. +// Get nth image in the image list. WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, - WebPChunkId id, WebPMuxImage** wpi); + WebPMuxImage** wpi); // Total size of the given image. size_t MuxImageDiskSize(const WebPMuxImage* const wpi); diff --git a/3rdparty/libwebp/mux/muxinternal.c b/3rdparty/libwebp/mux/muxinternal.c index 6c3c4fe60a..9543c0ee5b 100644 --- a/3rdparty/libwebp/mux/muxinternal.c +++ b/3rdparty/libwebp/mux/muxinternal.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Internal objects and utils for mux. @@ -12,6 +14,7 @@ #include #include "./muxi.h" +#include "../utils/utils.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { @@ -22,18 +25,25 @@ extern "C" { const ChunkInfo kChunks[] = { { MKFOURCC('V', 'P', '8', 'X'), WEBP_CHUNK_VP8X, VP8X_CHUNK_SIZE }, { MKFOURCC('I', 'C', 'C', 'P'), WEBP_CHUNK_ICCP, UNDEFINED_CHUNK_SIZE }, - { MKFOURCC('L', 'O', 'O', 'P'), WEBP_CHUNK_LOOP, LOOP_CHUNK_SIZE }, - { MKFOURCC('F', 'R', 'M', ' '), WEBP_CHUNK_FRAME, FRAME_CHUNK_SIZE }, - { MKFOURCC('T', 'I', 'L', 'E'), WEBP_CHUNK_TILE, TILE_CHUNK_SIZE }, + { MKFOURCC('A', 'N', 'I', 'M'), WEBP_CHUNK_ANIM, ANIM_CHUNK_SIZE }, + { MKFOURCC('A', 'N', 'M', 'F'), WEBP_CHUNK_ANMF, ANMF_CHUNK_SIZE }, + { MKFOURCC('F', 'R', 'G', 'M'), WEBP_CHUNK_FRGM, FRGM_CHUNK_SIZE }, { MKFOURCC('A', 'L', 'P', 'H'), WEBP_CHUNK_ALPHA, UNDEFINED_CHUNK_SIZE }, { MKFOURCC('V', 'P', '8', ' '), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE }, { MKFOURCC('V', 'P', '8', 'L'), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE }, - { MKFOURCC('M', 'E', 'T', 'A'), WEBP_CHUNK_META, UNDEFINED_CHUNK_SIZE }, + { MKFOURCC('E', 'X', 'I', 'F'), WEBP_CHUNK_EXIF, UNDEFINED_CHUNK_SIZE }, + { MKFOURCC('X', 'M', 'P', ' '), WEBP_CHUNK_XMP, UNDEFINED_CHUNK_SIZE }, { MKFOURCC('U', 'N', 'K', 'N'), WEBP_CHUNK_UNKNOWN, UNDEFINED_CHUNK_SIZE }, - { NIL_TAG, WEBP_CHUNK_NIL, UNDEFINED_CHUNK_SIZE } + { NIL_TAG, WEBP_CHUNK_NIL, UNDEFINED_CHUNK_SIZE } }; +//------------------------------------------------------------------------------ + +int WebPGetMuxVersion(void) { + return (MUX_MAJ_VERSION << 16) | (MUX_MIN_VERSION << 8) | MUX_REV_VERSION; +} + //------------------------------------------------------------------------------ // Life of a chunk object. @@ -73,12 +83,22 @@ WebPChunkId ChunkGetIdFromTag(uint32_t tag) { return WEBP_CHUNK_NIL; } +uint32_t ChunkGetTagFromFourCC(const char fourcc[4]) { + return MKFOURCC(fourcc[0], fourcc[1], fourcc[2], fourcc[3]); +} + +CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]) { + const uint32_t tag = ChunkGetTagFromFourCC(fourcc); + const CHUNK_INDEX idx = ChunkGetIndexFromTag(tag); + return (idx == IDX_NIL) ? IDX_UNKNOWN : idx; +} + //------------------------------------------------------------------------------ // Chunk search methods. // Returns next chunk in the chunk list with the given tag. static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) { - while (chunk && chunk->tag_ != tag) { + while (chunk != NULL && chunk->tag_ != tag) { chunk = chunk->next_; } return chunk; @@ -87,7 +107,7 @@ static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) { WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) { uint32_t iter = nth; first = ChunkSearchNextInList(first, tag); - if (!first) return NULL; + if (first == NULL) return NULL; while (--iter != 0) { WebPChunk* next_chunk = ChunkSearchNextInList(first->next_, tag); @@ -99,14 +119,14 @@ WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) { // Outputs a pointer to 'prev_chunk->next_', // where 'prev_chunk' is the pointer to the chunk at position (nth - 1). -// Returns 1 if nth chunk was found, 0 otherwise. +// Returns true if nth chunk was found. static int ChunkSearchListToSet(WebPChunk** chunk_list, uint32_t nth, WebPChunk*** const location) { uint32_t count = 0; - assert(chunk_list); + assert(chunk_list != NULL); *location = chunk_list; - while (*chunk_list) { + while (*chunk_list != NULL) { WebPChunk* const cur_chunk = *chunk_list; ++count; if (count == nth) return 1; // Found. @@ -124,34 +144,25 @@ static int ChunkSearchListToSet(WebPChunk** chunk_list, uint32_t nth, WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data, int copy_data, uint32_t tag) { // For internally allocated chunks, always copy data & make it owner of data. - if (tag == kChunks[IDX_VP8X].tag || tag == kChunks[IDX_LOOP].tag) { + if (tag == kChunks[IDX_VP8X].tag || tag == kChunks[IDX_ANIM].tag) { copy_data = 1; } ChunkRelease(chunk); if (data != NULL) { - if (copy_data) { - // Copy data. - chunk->data_.bytes_ = (uint8_t*)malloc(data->size_); - if (chunk->data_.bytes_ == NULL) return WEBP_MUX_MEMORY_ERROR; - memcpy((uint8_t*)chunk->data_.bytes_, data->bytes_, data->size_); - chunk->data_.size_ = data->size_; - - // Chunk is owner of data. - chunk->owner_ = 1; - } else { - // Don't copy data. + if (copy_data) { // Copy data. + if (!WebPDataCopy(data, &chunk->data_)) return WEBP_MUX_MEMORY_ERROR; + chunk->owner_ = 1; // Chunk is owner of data. + } else { // Don't copy data. chunk->data_ = *data; } } - chunk->tag_ = tag; - return WEBP_MUX_OK; } -WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list, +WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list, uint32_t nth) { WebPChunk* new_chunk; @@ -162,6 +173,7 @@ WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list, new_chunk = (WebPChunk*)malloc(sizeof(*new_chunk)); if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR; *new_chunk = *chunk; + chunk->owner_ = 0; new_chunk->next_ = *chunk_list; *chunk_list = new_chunk; return WEBP_MUX_OK; @@ -181,7 +193,7 @@ WebPChunk* ChunkDelete(WebPChunk* const chunk) { size_t ChunksListDiskSize(const WebPChunk* chunk_list) { size_t size = 0; - while (chunk_list) { + while (chunk_list != NULL) { size += ChunkDiskSize(chunk_list); chunk_list = chunk_list->next_; } @@ -189,55 +201,26 @@ size_t ChunksListDiskSize(const WebPChunk* chunk_list) { } static uint8_t* ChunkEmit(const WebPChunk* const chunk, uint8_t* dst) { - const size_t chunk_size = chunk->data_.size_; + const size_t chunk_size = chunk->data_.size; assert(chunk); assert(chunk->tag_ != NIL_TAG); PutLE32(dst + 0, chunk->tag_); PutLE32(dst + TAG_SIZE, (uint32_t)chunk_size); assert(chunk_size == (uint32_t)chunk_size); - memcpy(dst + CHUNK_HEADER_SIZE, chunk->data_.bytes_, chunk_size); + memcpy(dst + CHUNK_HEADER_SIZE, chunk->data_.bytes, chunk_size); if (chunk_size & 1) dst[CHUNK_HEADER_SIZE + chunk_size] = 0; // Add padding. return dst + ChunkDiskSize(chunk); } uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst) { - while (chunk_list) { + while (chunk_list != NULL) { dst = ChunkEmit(chunk_list, dst); chunk_list = chunk_list->next_; } return dst; } -//------------------------------------------------------------------------------ -// Manipulation of a WebPData object. - -void WebPDataInit(WebPData* webp_data) { - if (webp_data != NULL) { - memset(webp_data, 0, sizeof(*webp_data)); - } -} - -void WebPDataClear(WebPData* webp_data) { - if (webp_data != NULL) { - free((void*)webp_data->bytes_); - WebPDataInit(webp_data); - } -} - -int WebPDataCopy(const WebPData* src, WebPData* dst) { - if (src == NULL || dst == NULL) return 0; - - WebPDataInit(dst); - if (src->bytes_ != NULL && src->size_ != 0) { - dst->bytes_ = (uint8_t*)malloc(src->size_); - if (dst->bytes_ == NULL) return 0; - memcpy((void*)dst->bytes_, src->bytes_, src->size_); - dst->size_ = src->size_; - } - return 1; -} - //------------------------------------------------------------------------------ // Life of a MuxImage object. @@ -265,10 +248,14 @@ int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id) { int count = 0; const WebPMuxImage* current; for (current = wpi_list; current != NULL; current = current->next_) { - const WebPChunk* const wpi_chunk = *MuxImageGetListFromId(current, id); - if (wpi_chunk != NULL) { - const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_); - if (wpi_chunk_id == id) ++count; + if (id == WEBP_CHUNK_NIL) { + ++count; // Special case: count all images. + } else { + const WebPChunk* const wpi_chunk = *MuxImageGetListFromId(current, id); + if (wpi_chunk != NULL) { + const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_); + if (wpi_chunk_id == id) ++count; // Count images with a matching 'id'. + } } } return count; @@ -276,34 +263,22 @@ int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id) { // Outputs a pointer to 'prev_wpi->next_', // where 'prev_wpi' is the pointer to the image at position (nth - 1). -// Returns 1 if nth image with given id was found, 0 otherwise. +// Returns true if nth image was found. static int SearchImageToGetOrDelete(WebPMuxImage** wpi_list, uint32_t nth, - WebPChunkId id, WebPMuxImage*** const location) { uint32_t count = 0; assert(wpi_list); *location = wpi_list; - // Search makes sense only for the following. - assert(id == WEBP_CHUNK_FRAME || id == WEBP_CHUNK_TILE || - id == WEBP_CHUNK_IMAGE); - assert(id != WEBP_CHUNK_IMAGE || nth == 1); - if (nth == 0) { - nth = MuxImageCount(*wpi_list, id); + nth = MuxImageCount(*wpi_list, WEBP_CHUNK_NIL); if (nth == 0) return 0; // Not found. } - while (*wpi_list) { + while (*wpi_list != NULL) { WebPMuxImage* const cur_wpi = *wpi_list; - const WebPChunk* const wpi_chunk = *MuxImageGetListFromId(cur_wpi, id); - if (wpi_chunk != NULL) { - const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_); - if (wpi_chunk_id == id) { - ++count; - if (count == nth) return 1; // Found. - } - } + ++count; + if (count == nth) return 1; // Found. wpi_list = &cur_wpi->next_; *location = wpi_list; } @@ -346,15 +321,14 @@ WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi) { } void MuxImageDeleteAll(WebPMuxImage** const wpi_list) { - while (*wpi_list) { + while (*wpi_list != NULL) { *wpi_list = MuxImageDelete(*wpi_list); } } -WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth, - WebPChunkId id) { +WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth) { assert(wpi_list); - if (!SearchImageToGetOrDelete(wpi_list, nth, id, &wpi_list)) { + if (!SearchImageToGetOrDelete(wpi_list, nth, &wpi_list)) { return WEBP_MUX_NOT_FOUND; } *wpi_list = MuxImageDelete(*wpi_list); @@ -365,10 +339,10 @@ WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth, // MuxImage reader methods. WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, - WebPChunkId id, WebPMuxImage** wpi) { + WebPMuxImage** wpi) { assert(wpi_list); assert(wpi); - if (!SearchImageToGetOrDelete((WebPMuxImage**)wpi_list, nth, id, + if (!SearchImageToGetOrDelete((WebPMuxImage**)wpi_list, nth, (WebPMuxImage***)&wpi_list)) { return WEBP_MUX_NOT_FOUND; } @@ -390,27 +364,46 @@ size_t MuxImageDiskSize(const WebPMuxImage* const wpi) { size_t MuxImageListDiskSize(const WebPMuxImage* wpi_list) { size_t size = 0; - while (wpi_list) { + while (wpi_list != NULL) { size += MuxImageDiskSize(wpi_list); wpi_list = wpi_list->next_; } return size; } +// Special case as ANMF/FRGM chunk encapsulates other image chunks. +static uint8_t* ChunkEmitSpecial(const WebPChunk* const header, + size_t total_size, uint8_t* dst) { + const size_t header_size = header->data_.size; + const size_t offset_to_next = total_size - CHUNK_HEADER_SIZE; + assert(header->tag_ == kChunks[IDX_ANMF].tag || + header->tag_ == kChunks[IDX_FRGM].tag); + PutLE32(dst + 0, header->tag_); + PutLE32(dst + TAG_SIZE, (uint32_t)offset_to_next); + assert(header_size == (uint32_t)header_size); + memcpy(dst + CHUNK_HEADER_SIZE, header->data_.bytes, header_size); + if (header_size & 1) { + dst[CHUNK_HEADER_SIZE + header_size] = 0; // Add padding. + } + return dst + ChunkDiskSize(header); +} + uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst) { // Ordering of chunks to be emitted is strictly as follows: - // 1. Frame/Tile chunk (if present). - // 2. Alpha chunk (if present). + // 1. ANMF/FRGM chunk (if present). + // 2. ALPH chunk (if present). // 3. VP8/VP8L chunk. assert(wpi); - if (wpi->header_ != NULL) dst = ChunkEmit(wpi->header_, dst); + if (wpi->header_ != NULL) { + dst = ChunkEmitSpecial(wpi->header_, MuxImageDiskSize(wpi), dst); + } if (wpi->alpha_ != NULL) dst = ChunkEmit(wpi->alpha_, dst); if (wpi->img_ != NULL) dst = ChunkEmit(wpi->img_, dst); return dst; } uint8_t* MuxImageListEmit(const WebPMuxImage* wpi_list, uint8_t* dst) { - while (wpi_list) { + while (wpi_list != NULL) { dst = MuxImageEmit(wpi_list, dst); wpi_list = wpi_list->next_; } @@ -441,11 +434,12 @@ uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size) { WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id) { assert(mux != NULL); - switch(id) { + switch (id) { case WEBP_CHUNK_VP8X: return (WebPChunk**)&mux->vp8x_; case WEBP_CHUNK_ICCP: return (WebPChunk**)&mux->iccp_; - case WEBP_CHUNK_LOOP: return (WebPChunk**)&mux->loop_; - case WEBP_CHUNK_META: return (WebPChunk**)&mux->meta_; + case WEBP_CHUNK_ANIM: return (WebPChunk**)&mux->anim_; + case WEBP_CHUNK_EXIF: return (WebPChunk**)&mux->exif_; + case WEBP_CHUNK_XMP: return (WebPChunk**)&mux->xmp_; case WEBP_CHUNK_UNKNOWN: return (WebPChunk**)&mux->unknown_; default: return NULL; } @@ -453,17 +447,17 @@ WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id) { WebPMuxError MuxValidateForImage(const WebPMux* const mux) { const int num_images = MuxImageCount(mux->images_, WEBP_CHUNK_IMAGE); - const int num_frames = MuxImageCount(mux->images_, WEBP_CHUNK_FRAME); - const int num_tiles = MuxImageCount(mux->images_, WEBP_CHUNK_TILE); + const int num_frames = MuxImageCount(mux->images_, WEBP_CHUNK_ANMF); + const int num_fragments = MuxImageCount(mux->images_, WEBP_CHUNK_FRGM); if (num_images == 0) { // No images in mux. return WEBP_MUX_NOT_FOUND; - } else if (num_images == 1 && num_frames == 0 && num_tiles == 0) { + } else if (num_images == 1 && num_frames == 0 && num_fragments == 0) { // Valid case (single image). return WEBP_MUX_OK; } else { - // Frame/Tile case OR an invalid mux. + // Frame/Fragment case OR an invalid mux. return WEBP_MUX_INVALID_ARGUMENT; } } @@ -494,10 +488,11 @@ static WebPMuxError ValidateChunk(const WebPMux* const mux, CHUNK_INDEX idx, WebPMuxError MuxValidate(const WebPMux* const mux) { int num_iccp; - int num_meta; - int num_loop_chunks; + int num_exif; + int num_xmp; + int num_anim; int num_frames; - int num_tiles; + int num_fragments; int num_vp8x; int num_images; int num_alpha; @@ -517,29 +512,33 @@ WebPMuxError MuxValidate(const WebPMux* const mux) { err = ValidateChunk(mux, IDX_ICCP, ICCP_FLAG, flags, 1, &num_iccp); if (err != WEBP_MUX_OK) return err; - // At most one XMP metadata. - err = ValidateChunk(mux, IDX_META, META_FLAG, flags, 1, &num_meta); + // At most one EXIF metadata. + err = ValidateChunk(mux, IDX_EXIF, EXIF_FLAG, flags, 1, &num_exif); if (err != WEBP_MUX_OK) return err; - // Animation: ANIMATION_FLAG, loop chunk and frame chunk(s) are consistent. - // At most one loop chunk. - err = ValidateChunk(mux, IDX_LOOP, NO_FLAG, flags, 1, &num_loop_chunks); + // At most one XMP metadata. + err = ValidateChunk(mux, IDX_XMP, XMP_FLAG, flags, 1, &num_xmp); if (err != WEBP_MUX_OK) return err; - err = ValidateChunk(mux, IDX_FRAME, NO_FLAG, flags, -1, &num_frames); + + // Animation: ANIMATION_FLAG, ANIM chunk and ANMF chunk(s) are consistent. + // At most one ANIM chunk. + err = ValidateChunk(mux, IDX_ANIM, NO_FLAG, flags, 1, &num_anim); + if (err != WEBP_MUX_OK) return err; + err = ValidateChunk(mux, IDX_ANMF, NO_FLAG, flags, -1, &num_frames); if (err != WEBP_MUX_OK) return err; { const int has_animation = !!(flags & ANIMATION_FLAG); - if (has_animation && (num_loop_chunks == 0 || num_frames == 0)) { + if (has_animation && (num_anim == 0 || num_frames == 0)) { return WEBP_MUX_INVALID_ARGUMENT; } - if (!has_animation && (num_loop_chunks == 1 || num_frames > 0)) { + if (!has_animation && (num_anim == 1 || num_frames > 0)) { return WEBP_MUX_INVALID_ARGUMENT; } } - // Tiling: TILE_FLAG and tile chunk(s) are consistent. - err = ValidateChunk(mux, IDX_TILE, TILE_FLAG, flags, -1, &num_tiles); + // Fragmentation: FRAGMENTS_FLAG and FRGM chunk(s) are consistent. + err = ValidateChunk(mux, IDX_FRGM, FRAGMENTS_FLAG, flags, -1, &num_fragments); if (err != WEBP_MUX_OK) return err; // Verify either VP8X chunk is present OR there is only one elem in @@ -551,16 +550,18 @@ WebPMuxError MuxValidate(const WebPMux* const mux) { if (num_vp8x == 0 && num_images != 1) return WEBP_MUX_INVALID_ARGUMENT; // ALPHA_FLAG & alpha chunk(s) are consistent. - if (num_vp8x > 0 && MuxHasLosslessImages(mux->images_)) { - // Special case: we have a VP8X chunk as well as some lossless images. - if (!(flags & ALPHA_FLAG)) return WEBP_MUX_INVALID_ARGUMENT; + if (MuxHasLosslessImages(mux->images_)) { + if (num_vp8x > 0) { + // Special case: we have a VP8X chunk as well as some lossless images. + if (!(flags & ALPHA_FLAG)) return WEBP_MUX_INVALID_ARGUMENT; + } } else { - err = ValidateChunk(mux, IDX_ALPHA, ALPHA_FLAG, flags, -1, &num_alpha); - if (err != WEBP_MUX_OK) return err; + err = ValidateChunk(mux, IDX_ALPHA, ALPHA_FLAG, flags, -1, &num_alpha); + if (err != WEBP_MUX_OK) return err; } - // num_tiles & num_images are consistent. - if (num_tiles > 0 && num_images != num_tiles) { + // num_fragments & num_images are consistent. + if (num_fragments > 0 && num_images != num_fragments) { return WEBP_MUX_INVALID_ARGUMENT; } diff --git a/3rdparty/libwebp/mux/muxread.c b/3rdparty/libwebp/mux/muxread.c index 21c3cfbaeb..2179ccb79e 100644 --- a/3rdparty/libwebp/mux/muxread.c +++ b/3rdparty/libwebp/mux/muxread.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Read APIs for mux. @@ -12,6 +14,7 @@ #include #include "./muxi.h" +#include "../utils/utils.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { @@ -41,8 +44,9 @@ static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx, SWITCH_ID_LIST(IDX_VP8X, mux->vp8x_); SWITCH_ID_LIST(IDX_ICCP, mux->iccp_); - SWITCH_ID_LIST(IDX_LOOP, mux->loop_); - SWITCH_ID_LIST(IDX_META, mux->meta_); + SWITCH_ID_LIST(IDX_ANIM, mux->anim_); + SWITCH_ID_LIST(IDX_EXIF, mux->exif_); + SWITCH_ID_LIST(IDX_XMP, mux->xmp_); SWITCH_ID_LIST(IDX_UNKNOWN, mux->unknown_); return WEBP_MUX_NOT_FOUND; } @@ -50,10 +54,9 @@ static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx, // Fill the chunk with the given data (includes chunk header bytes), after some // verifications. -static WebPMuxError ChunkVerifyAndAssignData(WebPChunk* chunk, - const uint8_t* data, - size_t data_size, size_t riff_size, - int copy_data) { +static WebPMuxError ChunkVerifyAndAssign(WebPChunk* chunk, + const uint8_t* data, size_t data_size, + size_t riff_size, int copy_data) { uint32_t chunk_size; WebPData chunk_data; @@ -68,11 +71,74 @@ static WebPMuxError ChunkVerifyAndAssignData(WebPChunk* chunk, } // Data assignment. - chunk_data.bytes_ = data + CHUNK_HEADER_SIZE; - chunk_data.size_ = chunk_size; + chunk_data.bytes = data + CHUNK_HEADER_SIZE; + chunk_data.size = chunk_size; return ChunkAssignData(chunk, &chunk_data, copy_data, GetLE32(data + 0)); } +static int MuxImageParse(const WebPChunk* const chunk, int copy_data, + WebPMuxImage* const wpi) { + const uint8_t* bytes = chunk->data_.bytes; + size_t size = chunk->data_.size; + const uint8_t* const last = bytes + size; + WebPChunk subchunk; + size_t subchunk_size; + ChunkInit(&subchunk); + + assert(chunk->tag_ == kChunks[IDX_ANMF].tag || + chunk->tag_ == kChunks[IDX_FRGM].tag); + assert(!wpi->is_partial_); + + // ANMF/FRGM. + { + const size_t hdr_size = (chunk->tag_ == kChunks[IDX_ANMF].tag) ? + ANMF_CHUNK_SIZE : FRGM_CHUNK_SIZE; + const WebPData temp = { bytes, hdr_size }; + // Each of ANMF and FRGM chunk contain a header at the beginning. So, its + // size should at least be 'hdr_size'. + if (size < hdr_size) goto Fail; + ChunkAssignData(&subchunk, &temp, copy_data, chunk->tag_); + } + ChunkSetNth(&subchunk, &wpi->header_, 1); + wpi->is_partial_ = 1; // Waiting for ALPH and/or VP8/VP8L chunks. + + // Rest of the chunks. + subchunk_size = ChunkDiskSize(&subchunk) - CHUNK_HEADER_SIZE; + bytes += subchunk_size; + size -= subchunk_size; + + while (bytes != last) { + ChunkInit(&subchunk); + if (ChunkVerifyAndAssign(&subchunk, bytes, size, size, + copy_data) != WEBP_MUX_OK) { + goto Fail; + } + switch (ChunkGetIdFromTag(subchunk.tag_)) { + case WEBP_CHUNK_ALPHA: + if (wpi->alpha_ != NULL) goto Fail; // Consecutive ALPH chunks. + if (ChunkSetNth(&subchunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Fail; + wpi->is_partial_ = 1; // Waiting for a VP8 chunk. + break; + case WEBP_CHUNK_IMAGE: + if (ChunkSetNth(&subchunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Fail; + wpi->is_partial_ = 0; // wpi is completely filled. + break; + default: + goto Fail; + break; + } + subchunk_size = ChunkDiskSize(&subchunk); + bytes += subchunk_size; + size -= subchunk_size; + } + if (wpi->is_partial_) goto Fail; + return 1; + + Fail: + ChunkRelease(&subchunk); + return 0; +} + //------------------------------------------------------------------------------ // Create a mux object from WebP-RIFF data. @@ -94,8 +160,8 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data, } if (bitstream == NULL) return NULL; - data = bitstream->bytes_; - size = bitstream->size_; + data = bitstream->bytes; + size = bitstream->size; if (data == NULL) return NULL; if (size < RIFF_HEADER_SIZE) return NULL; @@ -135,42 +201,48 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data, // Loop over chunks. while (data != end) { + size_t data_size; WebPChunkId id; - WebPMuxError err; - - err = ChunkVerifyAndAssignData(&chunk, data, size, riff_size, copy_data); - if (err != WEBP_MUX_OK) goto Err; - + WebPChunk** chunk_list; + if (ChunkVerifyAndAssign(&chunk, data, size, riff_size, + copy_data) != WEBP_MUX_OK) { + goto Err; + } + data_size = ChunkDiskSize(&chunk); id = ChunkGetIdFromTag(chunk.tag_); - - if (IsWPI(id)) { // An image chunk (frame/tile/alpha/vp8). - WebPChunk** wpi_chunk_ptr = - MuxImageGetListFromId(wpi, id); // Image chunk to set. - assert(wpi_chunk_ptr != NULL); - if (*wpi_chunk_ptr != NULL) goto Err; // Consecutive alpha chunks or - // consecutive frame/tile chunks. - if (ChunkSetNth(&chunk, wpi_chunk_ptr, 1) != WEBP_MUX_OK) goto Err; - if (id == WEBP_CHUNK_IMAGE) { + switch (id) { + case WEBP_CHUNK_ALPHA: + if (wpi->alpha_ != NULL) goto Err; // Consecutive ALPH chunks. + if (ChunkSetNth(&chunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Err; + wpi->is_partial_ = 1; // Waiting for a VP8 chunk. + break; + case WEBP_CHUNK_IMAGE: + if (ChunkSetNth(&chunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Err; wpi->is_partial_ = 0; // wpi is completely filled. + PushImage: // Add this to mux->images_ list. if (MuxImagePush(wpi, &mux->images_) != WEBP_MUX_OK) goto Err; MuxImageInit(wpi); // Reset for reading next image. - } else { - wpi->is_partial_ = 1; // wpi is only partially filled. - } - } else { // A non-image chunk. - WebPChunk** chunk_list; - if (wpi->is_partial_) goto Err; // Encountered a non-image chunk before - // getting all chunks of an image. - chunk_list = MuxGetChunkListFromId(mux, id); // List to add this chunk. - if (chunk_list == NULL) chunk_list = &mux->unknown_; - if (ChunkSetNth(&chunk, chunk_list, 0) != WEBP_MUX_OK) goto Err; - } - { - const size_t data_size = ChunkDiskSize(&chunk); - data += data_size; - size -= data_size; + break; + case WEBP_CHUNK_ANMF: +#ifdef WEBP_EXPERIMENTAL_FEATURES + case WEBP_CHUNK_FRGM: +#endif + if (wpi->is_partial_) goto Err; // Previous wpi is still incomplete. + if (!MuxImageParse(&chunk, copy_data, wpi)) goto Err; + ChunkRelease(&chunk); + goto PushImage; + break; + default: // A non-image chunk. + if (wpi->is_partial_) goto Err; // Encountered a non-image chunk before + // getting all chunks of an image. + chunk_list = MuxGetChunkListFromId(mux, id); // List to add this chunk. + if (chunk_list == NULL) chunk_list = &mux->unknown_; + if (ChunkSetNth(&chunk, chunk_list, 0) != WEBP_MUX_OK) goto Err; + break; } + data += data_size; + size -= data_size; ChunkInit(&chunk); } @@ -192,26 +264,30 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data, WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, uint32_t* flags) { WebPData data; - WebPMuxError err; if (mux == NULL || flags == NULL) return WEBP_MUX_INVALID_ARGUMENT; *flags = 0; // Check if VP8X chunk is present. - err = MuxGet(mux, IDX_VP8X, 1, &data); - if (err == WEBP_MUX_NOT_FOUND) { - // Check if VP8/VP8L chunk is present. - err = WebPMuxGetImage(mux, &data); - WebPDataClear(&data); - return err; - } else if (err != WEBP_MUX_OK) { - return err; + if (MuxGet(mux, IDX_VP8X, 1, &data) == WEBP_MUX_OK) { + if (data.size < CHUNK_SIZE_BYTES) return WEBP_MUX_BAD_DATA; + *flags = GetLE32(data.bytes); // All OK. Fill up flags. + } else { + WebPMuxError err = MuxValidateForImage(mux); // Check for single image. + if (err != WEBP_MUX_OK) return err; + if (MuxHasLosslessImages(mux->images_)) { + const WebPData* const vp8l_data = &mux->images_->img_->data_; + int has_alpha = 0; + if (!VP8LGetInfo(vp8l_data->bytes, vp8l_data->size, NULL, NULL, + &has_alpha)) { + return WEBP_MUX_BAD_DATA; + } + if (has_alpha) { + *flags = ALPHA_FLAG; + } + } } - if (data.size_ < CHUNK_SIZE_BYTES) return WEBP_MUX_BAD_DATA; - - // All OK. Fill up flags. - *flags = GetLE32(data.bytes_); return WEBP_MUX_OK; } @@ -230,7 +306,7 @@ static uint8_t* EmitVP8XChunk(uint8_t* const dst, int width, } // Assemble a single image WebP bitstream from 'wpi'. -static WebPMuxError SynthesizeBitstream(WebPMuxImage* const wpi, +static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi, WebPData* const bitstream) { uint8_t* dst; @@ -238,7 +314,7 @@ static WebPMuxError SynthesizeBitstream(WebPMuxImage* const wpi, const int need_vp8x = (wpi->alpha_ != NULL); const size_t vp8x_size = need_vp8x ? CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE : 0; const size_t alpha_size = need_vp8x ? ChunkDiskSize(wpi->alpha_) : 0; - // Note: No need to output FRM/TILE chunk for a single image. + // Note: No need to output ANMF/FRGM chunk for a single image. const size_t size = RIFF_HEADER_SIZE + vp8x_size + alpha_size + ChunkDiskSize(wpi->img_); uint8_t* const data = (uint8_t*)malloc(size); @@ -265,100 +341,101 @@ static WebPMuxError SynthesizeBitstream(WebPMuxImage* const wpi, assert(dst == data + size); // Output. - bitstream->bytes_ = data; - bitstream->size_ = size; + bitstream->bytes = data; + bitstream->size = size; return WEBP_MUX_OK; } -WebPMuxError WebPMuxGetImage(const WebPMux* mux, WebPData* bitstream) { - WebPMuxError err; - WebPMuxImage* wpi = NULL; - - if (mux == NULL || bitstream == NULL) { +WebPMuxError WebPMuxGetChunk(const WebPMux* mux, const char fourcc[4], + WebPData* chunk_data) { + CHUNK_INDEX idx; + if (mux == NULL || fourcc == NULL || chunk_data == NULL) { return WEBP_MUX_INVALID_ARGUMENT; } - - err = MuxValidateForImage(mux); - if (err != WEBP_MUX_OK) return err; - - // All well. Get the image. - err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, WEBP_CHUNK_IMAGE, - &wpi); - assert(err == WEBP_MUX_OK); // Already tested above. - - return SynthesizeBitstream(wpi, bitstream); + idx = ChunkGetIndexFromFourCC(fourcc); + if (IsWPI(kChunks[idx].id)) { // An image chunk. + return WEBP_MUX_INVALID_ARGUMENT; + } else if (idx != IDX_UNKNOWN) { // A known chunk type. + return MuxGet(mux, idx, 1, chunk_data); + } else { // An unknown chunk type. + const WebPChunk* const chunk = + ChunkSearchList(mux->unknown_, 1, ChunkGetTagFromFourCC(fourcc)); + if (chunk == NULL) return WEBP_MUX_NOT_FOUND; + *chunk_data = chunk->data_; + return WEBP_MUX_OK; + } } -WebPMuxError WebPMuxGetMetadata(const WebPMux* mux, WebPData* metadata) { - if (mux == NULL || metadata == NULL) return WEBP_MUX_INVALID_ARGUMENT; - return MuxGet(mux, IDX_META, 1, metadata); +static WebPMuxError MuxGetImageInternal(const WebPMuxImage* const wpi, + WebPMuxFrameInfo* const info) { + // Set some defaults for unrelated fields. + info->x_offset = 0; + info->y_offset = 0; + info->duration = 1; + // Extract data for related fields. + info->id = ChunkGetIdFromTag(wpi->img_->tag_); + return SynthesizeBitstream(wpi, &info->bitstream); } -WebPMuxError WebPMuxGetColorProfile(const WebPMux* mux, - WebPData* color_profile) { - if (mux == NULL || color_profile == NULL) return WEBP_MUX_INVALID_ARGUMENT; - return MuxGet(mux, IDX_ICCP, 1, color_profile); +static WebPMuxError MuxGetFrameFragmentInternal(const WebPMuxImage* const wpi, + WebPMuxFrameInfo* const frame) { + const int is_frame = (wpi->header_->tag_ == kChunks[IDX_ANMF].tag); + const CHUNK_INDEX idx = is_frame ? IDX_ANMF : IDX_FRGM; + const WebPData* frame_frgm_data; +#ifndef WEBP_EXPERIMENTAL_FEATURES + if (!is_frame) return WEBP_MUX_INVALID_ARGUMENT; +#endif + assert(wpi->header_ != NULL); // Already checked by WebPMuxGetFrame(). + // Get frame/fragment chunk. + frame_frgm_data = &wpi->header_->data_; + if (frame_frgm_data->size < kChunks[idx].size) return WEBP_MUX_BAD_DATA; + // Extract info. + frame->x_offset = 2 * GetLE24(frame_frgm_data->bytes + 0); + frame->y_offset = 2 * GetLE24(frame_frgm_data->bytes + 3); + frame->duration = is_frame ? GetLE24(frame_frgm_data->bytes + 12) : 1; + frame->dispose_method = + is_frame ? (WebPMuxAnimDispose)(frame_frgm_data->bytes[15] & 1) + : WEBP_MUX_DISPOSE_NONE; + frame->id = ChunkGetIdFromTag(wpi->header_->tag_); + return SynthesizeBitstream(wpi, &frame->bitstream); } -WebPMuxError WebPMuxGetLoopCount(const WebPMux* mux, int* loop_count) { - WebPData image; - WebPMuxError err; - - if (mux == NULL || loop_count == NULL) return WEBP_MUX_INVALID_ARGUMENT; - - err = MuxGet(mux, IDX_LOOP, 1, &image); - if (err != WEBP_MUX_OK) return err; - if (image.size_ < kChunks[WEBP_CHUNK_LOOP].size) return WEBP_MUX_BAD_DATA; - *loop_count = GetLE16(image.bytes_); - - return WEBP_MUX_OK; -} - -static WebPMuxError MuxGetFrameTileInternal( - const WebPMux* const mux, uint32_t nth, WebPData* const bitstream, - int* const x_offset, int* const y_offset, int* const duration, - uint32_t tag) { - const WebPData* frame_tile_data; +WebPMuxError WebPMuxGetFrame( + const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame) { WebPMuxError err; WebPMuxImage* wpi; - const int is_frame = (tag == kChunks[WEBP_CHUNK_FRAME].tag) ? 1 : 0; - const CHUNK_INDEX idx = is_frame ? IDX_FRAME : IDX_TILE; - const WebPChunkId id = kChunks[idx].id; - - if (mux == NULL || bitstream == NULL || - x_offset == NULL || y_offset == NULL || (is_frame && duration == NULL)) { + // Sanity checks. + if (mux == NULL || frame == NULL) { return WEBP_MUX_INVALID_ARGUMENT; } // Get the nth WebPMuxImage. - err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, nth, id, &wpi); + err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, nth, &wpi); if (err != WEBP_MUX_OK) return err; - // Get frame chunk. - assert(wpi->header_ != NULL); // As MuxImageGetNth() already checked header_. - frame_tile_data = &wpi->header_->data_; - - if (frame_tile_data->size_ < kChunks[idx].size) return WEBP_MUX_BAD_DATA; - *x_offset = 2 * GetLE24(frame_tile_data->bytes_ + 0); - *y_offset = 2 * GetLE24(frame_tile_data->bytes_ + 3); - if (is_frame) *duration = 1 + GetLE24(frame_tile_data->bytes_ + 12); - - return SynthesizeBitstream(wpi, bitstream); + // Get frame info. + if (wpi->header_ == NULL) { + return MuxGetImageInternal(wpi, frame); + } else { + return MuxGetFrameFragmentInternal(wpi, frame); + } } -WebPMuxError WebPMuxGetFrame(const WebPMux* mux, uint32_t nth, - WebPData* bitstream, - int* x_offset, int* y_offset, int* duration) { - return MuxGetFrameTileInternal(mux, nth, bitstream, x_offset, y_offset, - duration, kChunks[IDX_FRAME].tag); -} +WebPMuxError WebPMuxGetAnimationParams(const WebPMux* mux, + WebPMuxAnimParams* params) { + WebPData anim; + WebPMuxError err; -WebPMuxError WebPMuxGetTile(const WebPMux* mux, uint32_t nth, - WebPData* bitstream, - int* x_offset, int* y_offset) { - return MuxGetFrameTileInternal(mux, nth, bitstream, x_offset, y_offset, NULL, - kChunks[IDX_TILE].tag); + if (mux == NULL || params == NULL) return WEBP_MUX_INVALID_ARGUMENT; + + err = MuxGet(mux, IDX_ANIM, 1, &anim); + if (err != WEBP_MUX_OK) return err; + if (anim.size < kChunks[WEBP_CHUNK_ANIM].size) return WEBP_MUX_BAD_DATA; + params->bgcolor = GetLE32(anim.bytes); + params->loop_count = GetLE16(anim.bytes + 4); + + return WEBP_MUX_OK; } // Get chunk index from chunk id. Returns IDX_NIL if not found. diff --git a/3rdparty/libwebp/utils/bit_reader.c b/3rdparty/libwebp/utils/bit_reader.c index 1afb1db890..ab7a8273ea 100644 --- a/3rdparty/libwebp/utils/bit_reader.c +++ b/3rdparty/libwebp/utils/bit_reader.c @@ -1,8 +1,10 @@ // Copyright 2010 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Boolean decoder @@ -15,7 +17,11 @@ extern "C" { #endif -#define MK(X) (((bit_t)(X) << (BITS)) | (MASK)) +#ifndef USE_RIGHT_JUSTIFY +#define MK(X) (((range_t)(X) << (BITS)) | (MASK)) +#else +#define MK(X) ((range_t)(X)) +#endif //------------------------------------------------------------------------------ // VP8BitReader @@ -29,7 +35,7 @@ void VP8InitBitReader(VP8BitReader* const br, br->buf_ = start; br->buf_end_ = end; br->value_ = 0; - br->missing_ = 8; // to load the very first 8bits + br->bits_ = -8; // to load the very first 8bits br->eof_ = 0; } @@ -46,7 +52,7 @@ const uint8_t kVP8Log2Range[128] = { }; // range = (range << kVP8Log2Range[range]) + trailing 1's -const bit_t kVP8NewRange[128] = { +const range_t kVP8NewRange[128] = { MK(127), MK(127), MK(191), MK(127), MK(159), MK(191), MK(223), MK(127), MK(143), MK(159), MK(175), MK(191), MK(207), MK(223), MK(239), MK(127), MK(135), MK(143), MK(151), MK(159), MK(167), MK(175), MK(183), MK(191), @@ -71,9 +77,19 @@ void VP8LoadFinalBytes(VP8BitReader* const br) { assert(br != NULL && br->buf_ != NULL); // Only read 8bits at a time if (br->buf_ < br->buf_end_) { - br->value_ |= (bit_t)(*br->buf_++) << ((BITS) - 8 + br->missing_); - br->missing_ -= 8; - } else { +#ifndef USE_RIGHT_JUSTIFY + br->value_ |= (bit_t)(*br->buf_++) << ((BITS) - 8 - br->bits_); +#else + br->value_ = (bit_t)(*br->buf_++) | (br->value_ << 8); +#endif + br->bits_ += 8; + } else if (!br->eof_) { +#ifdef USE_RIGHT_JUSTIFY + // These are not strictly needed, but it makes the behaviour + // consistent for both USE_RIGHT_JUSTIFY and !USE_RIGHT_JUSTIFY. + br->value_ <<= 8; + br->bits_ += 8; +#endif br->eof_ = 1; } } @@ -99,6 +115,10 @@ int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) { #define MAX_NUM_BIT_READ 25 +#define LBITS 64 // Number of bits prefetched. +#define WBITS 32 // Minimum number of bytes needed after VP8LFillBitWindow. +#define LOG8_WBITS 4 // Number of bytes needed to store WBITS bits. + static const uint32_t kBitMask[MAX_NUM_BIT_READ] = { 0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287, 1048575, 2097151, 4194303, 8388607, 16777215 @@ -120,7 +140,7 @@ void VP8LInitBitReader(VP8LBitReader* const br, br->eos_ = 0; br->error_ = 0; for (i = 0; i < sizeof(br->val_) && i < br->len_; ++i) { - br->val_ |= ((uint64_t)br->buf_[br->pos_]) << (8 * i); + br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (8 * i); ++br->pos_; } } @@ -135,91 +155,56 @@ void VP8LBitReaderSetBuffer(VP8LBitReader* const br, br->len_ = len; } +// If not at EOS, reload up to LBITS byte-by-byte static void ShiftBytes(VP8LBitReader* const br) { while (br->bit_pos_ >= 8 && br->pos_ < br->len_) { br->val_ >>= 8; - br->val_ |= ((uint64_t)br->buf_[br->pos_]) << 56; + br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (LBITS - 8); ++br->pos_; br->bit_pos_ -= 8; } } void VP8LFillBitWindow(VP8LBitReader* const br) { - if (br->bit_pos_ >= 32) { -#if defined(__x86_64__) || defined(_M_X64) - if (br->pos_ + 8 < br->len_) { - br->val_ >>= 32; + if (br->bit_pos_ >= WBITS) { +#if (defined(__x86_64__) || defined(_M_X64)) + if (br->pos_ + sizeof(br->val_) < br->len_) { + br->val_ >>= WBITS; + br->bit_pos_ -= WBITS; // The expression below needs a little-endian arch to work correctly. // This gives a large speedup for decoding speed. - br->val_ |= *(const uint64_t *)(br->buf_ + br->pos_) << 32; - br->pos_ += 4; - br->bit_pos_ -= 32; - } else { - // Slow path. - ShiftBytes(br); + br->val_ |= *(const vp8l_val_t*)(br->buf_ + br->pos_) << (LBITS - WBITS); + br->pos_ += LOG8_WBITS; + return; } -#else - // Always the slow path. - ShiftBytes(br); #endif - } - if (br->pos_ == br->len_ && br->bit_pos_ == 64) { - br->eos_ = 1; - } -} - -uint32_t VP8LReadOneBit(VP8LBitReader* const br) { - const uint32_t val = (br->val_ >> br->bit_pos_) & 1; - // Flag an error at end_of_stream. - if (!br->eos_) { - ++br->bit_pos_; - if (br->bit_pos_ >= 32) { - ShiftBytes(br); - } - // After this last bit is read, check if eos needs to be flagged. - if (br->pos_ == br->len_ && br->bit_pos_ == 64) { + ShiftBytes(br); // Slow path. + if (br->pos_ == br->len_ && br->bit_pos_ == LBITS) { br->eos_ = 1; } - } else { - br->error_ = 1; } - return val; } uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) { - uint32_t val = 0; assert(n_bits >= 0); // Flag an error if end_of_stream or n_bits is more than allowed limit. if (!br->eos_ && n_bits < MAX_NUM_BIT_READ) { + const uint32_t val = + (uint32_t)(br->val_ >> br->bit_pos_) & kBitMask[n_bits]; + const int new_bits = br->bit_pos_ + n_bits; + br->bit_pos_ = new_bits; // If this read is going to cross the read buffer, set the eos flag. if (br->pos_ == br->len_) { - if ((br->bit_pos_ + n_bits) >= 64) { + if (new_bits >= LBITS) { br->eos_ = 1; - if ((br->bit_pos_ + n_bits) > 64) return val; - } - } - val = (br->val_ >> br->bit_pos_) & kBitMask[n_bits]; - br->bit_pos_ += n_bits; - if (br->bit_pos_ >= 40) { - if (br->pos_ + 5 < br->len_) { - br->val_ >>= 40; - br->val_ |= - (((uint64_t)br->buf_[br->pos_ + 0]) << 24) | - (((uint64_t)br->buf_[br->pos_ + 1]) << 32) | - (((uint64_t)br->buf_[br->pos_ + 2]) << 40) | - (((uint64_t)br->buf_[br->pos_ + 3]) << 48) | - (((uint64_t)br->buf_[br->pos_ + 4]) << 56); - br->pos_ += 5; - br->bit_pos_ -= 40; - } - if (br->bit_pos_ >= 8) { - ShiftBytes(br); } } + ShiftBytes(br); + return val; } else { br->error_ = 1; + return 0; } - return val; } //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/utils/bit_reader.h b/3rdparty/libwebp/utils/bit_reader.h index cc7aeece1e..588222b3be 100644 --- a/3rdparty/libwebp/utils/bit_reader.h +++ b/3rdparty/libwebp/utils/bit_reader.h @@ -1,8 +1,10 @@ // Copyright 2010 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Boolean decoder @@ -24,11 +26,80 @@ extern "C" { #endif -#define BITS 32 // can be 32, 16 or 8 -#define MASK ((((bit_t)1) << (BITS)) - 1) -#if (BITS == 32) -typedef uint64_t bit_t; // natural register type -typedef uint32_t lbit_t; // natural type for memory I/O +// The Boolean decoder needs to maintain infinite precision on the value_ field. +// However, since range_ is only 8bit, we only need an active window of 8 bits +// for value_. Left bits (MSB) gets zeroed and shifted away when value_ falls +// below 128, range_ is updated, and fresh bits read from the bitstream are +// brought in as LSB. +// To avoid reading the fresh bits one by one (slow), we cache a few of them +// ahead (actually, we cache BITS of them ahead. See below). There's two +// strategies regarding how to shift these looked-ahead fresh bits into the +// 8bit window of value_: either we shift them in, while keeping the position of +// the window fixed. Or we slide the window to the right while keeping the cache +// bits at a fixed, right-justified, position. +// +// Example, for BITS=16: here is the content of value_ for both strategies: +// +// !USE_RIGHT_JUSTIFY || USE_RIGHT_JUSTIFY +// || +// <- 8b -><- 8b -><- BITS bits -> || <- 8b+3b -><- 8b -><- 13 bits -> +// [unused][value_][cached bits][0] || [unused...][value_][cached bits] +// [........00vvvvvvBBBBBBBBBBBBB000]LSB || [...........00vvvvvvBBBBBBBBBBBBB] +// || +// After calling VP8Shift(), where we need to shift away two zeros: +// [........vvvvvvvvBBBBBBBBBBB00000]LSB || [.............vvvvvvvvBBBBBBBBBBB] +// || +// Just before we need to call VP8LoadNewBytes(), the situation is: +// [........vvvvvv000000000000000000]LSB || [..........................vvvvvv] +// || +// And just after calling VP8LoadNewBytes(): +// [........vvvvvvvvBBBBBBBBBBBBBBBB]LSB || [........vvvvvvvvBBBBBBBBBBBBBBBB] +// +// -> we're back to height active 'value_' bits (marked 'v') and BITS cached +// bits (marked 'B') +// +// The right-justify strategy tends to use less shifts and is often faster. + +//------------------------------------------------------------------------------ +// BITS can be any multiple of 8 from 8 to 56 (inclusive). +// Pick values that fit natural register size. + +#if !defined(WEBP_REFERENCE_IMPLEMENTATION) + +#define USE_RIGHT_JUSTIFY + +#if defined(__i386__) || defined(_M_IX86) // x86 32bit +#define BITS 16 +#elif defined(__x86_64__) || defined(_M_X64) // x86 64bit +#define BITS 56 +#elif defined(__arm__) || defined(_M_ARM) // ARM +#define BITS 24 +#else // reasonable default +#define BITS 24 +#endif + +#else // reference choices + +#define USE_RIGHT_JUSTIFY +#define BITS 8 + +#endif + +//------------------------------------------------------------------------------ +// Derived types and constants + +// bit_t = natural register type +// lbit_t = natural type for memory I/O + +#if (BITS > 32) +typedef uint64_t bit_t; +typedef uint64_t lbit_t; +#elif (BITS == 32) +typedef uint64_t bit_t; +typedef uint32_t lbit_t; +#elif (BITS == 24) +typedef uint32_t bit_t; +typedef uint32_t lbit_t; #elif (BITS == 16) typedef uint32_t bit_t; typedef uint16_t lbit_t; @@ -37,8 +108,15 @@ typedef uint32_t bit_t; typedef uint8_t lbit_t; #endif +#ifndef USE_RIGHT_JUSTIFY +typedef bit_t range_t; // type for storing range_ +#define MASK ((((bit_t)1) << (BITS)) - 1) +#else +typedef uint32_t range_t; // range_ only uses 8bits here. No need for bit_t. +#endif + //------------------------------------------------------------------------------ -// Bitreader and code-tree reader +// Bitreader typedef struct VP8BitReader VP8BitReader; struct VP8BitReader { @@ -47,9 +125,9 @@ struct VP8BitReader { int eof_; // true if input is exhausted // boolean decoder - bit_t range_; // current range minus 1. In [127, 254] interval. - bit_t value_; // current value - int missing_; // number of missing bits in value_ (8bit) + range_t range_; // current range minus 1. In [127, 254] interval. + bit_t value_; // current value + int bits_; // number of valid bits left }; // Initialize the bit reader and the boolean decoder. @@ -67,12 +145,12 @@ int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits); // Read a bit with proba 'prob'. Speed-critical function! extern const uint8_t kVP8Log2Range[128]; -extern const bit_t kVP8NewRange[128]; +extern const range_t kVP8NewRange[128]; void VP8LoadFinalBytes(VP8BitReader* const br); // special case for the tail static WEBP_INLINE void VP8LoadNewBytes(VP8BitReader* const br) { - assert(br && br->buf_); + assert(br != NULL && br->buf_ != NULL); // Read 'BITS' bits at a time if possible. if (br->buf_ + sizeof(lbit_t) <= br->buf_end_) { // convert memory type to register type (with some zero'ing!) @@ -80,70 +158,125 @@ static WEBP_INLINE void VP8LoadNewBytes(VP8BitReader* const br) { lbit_t in_bits = *(lbit_t*)br->buf_; br->buf_ += (BITS) >> 3; #if !defined(__BIG_ENDIAN__) -#if (BITS == 32) +#if (BITS > 32) +// gcc 4.3 has builtin functions for swap32/swap64 +#if defined(__GNUC__) && \ + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) + bits = (bit_t)__builtin_bswap64(in_bits); +#elif defined(_MSC_VER) + bits = (bit_t)_byteswap_uint64(in_bits); +#elif defined(__x86_64__) + __asm__ volatile("bswapq %0" : "=r"(bits) : "0"(in_bits)); +#else // generic code for swapping 64-bit values (suggested by bdb@) + bits = (bit_t)in_bits; + bits = ((bits & 0xffffffff00000000ull) >> 32) | + ((bits & 0x00000000ffffffffull) << 32); + bits = ((bits & 0xffff0000ffff0000ull) >> 16) | + ((bits & 0x0000ffff0000ffffull) << 16); + bits = ((bits & 0xff00ff00ff00ff00ull) >> 8) | + ((bits & 0x00ff00ff00ff00ffull) << 8); +#endif + bits >>= 64 - BITS; +#elif (BITS >= 24) #if defined(__i386__) || defined(__x86_64__) __asm__ volatile("bswap %k0" : "=r"(in_bits) : "0"(in_bits)); - bits = (bit_t)in_bits; // 32b -> 64b zero-extension + bits = (bit_t)in_bits; // 24b/32b -> 32b/64b zero-extension #elif defined(_MSC_VER) - bits = _byteswap_ulong(in_bits); + bits = (bit_t)_byteswap_ulong(in_bits); #else bits = (bit_t)(in_bits >> 24) | ((in_bits >> 8) & 0xff00) | ((in_bits << 8) & 0xff0000) | (in_bits << 24); #endif // x86 + bits >>= (32 - BITS); #elif (BITS == 16) // gcc will recognize a 'rorw $8, ...' here: bits = (bit_t)(in_bits >> 8) | ((in_bits & 0xff) << 8); #else // BITS == 8 bits = (bit_t)in_bits; #endif -#else // LITTLE_ENDIAN +#else // BIG_ENDIAN bits = (bit_t)in_bits; + if (BITS != 8 * sizeof(bit_t)) bits >>= (8 * sizeof(bit_t) - BITS); #endif - br->value_ |= bits << br->missing_; - br->missing_ -= (BITS); +#ifndef USE_RIGHT_JUSTIFY + br->value_ |= bits << (-br->bits_); +#else + br->value_ = bits | (br->value_ << (BITS)); +#endif + br->bits_ += (BITS); } else { VP8LoadFinalBytes(br); // no need to be inlined } } -static WEBP_INLINE int VP8BitUpdate(VP8BitReader* const br, bit_t split) { - const bit_t value_split = split | (MASK); - if (br->missing_ > 0) { // Make sure we have a least BITS bits in 'value_' +static WEBP_INLINE int VP8BitUpdate(VP8BitReader* const br, range_t split) { + if (br->bits_ < 0) { // Make sure we have a least BITS bits in 'value_' VP8LoadNewBytes(br); } - if (br->value_ > value_split) { - br->range_ -= value_split + 1; - br->value_ -= value_split + 1; +#ifndef USE_RIGHT_JUSTIFY + split |= (MASK); + if (br->value_ > split) { + br->range_ -= split + 1; + br->value_ -= split + 1; return 1; } else { - br->range_ = value_split; + br->range_ = split; return 0; } +#else + { + const int pos = br->bits_; + const range_t value = (range_t)(br->value_ >> pos); + if (value > split) { + br->range_ -= split + 1; + br->value_ -= (bit_t)(split + 1) << pos; + return 1; + } else { + br->range_ = split; + return 0; + } + } +#endif } static WEBP_INLINE void VP8Shift(VP8BitReader* const br) { +#ifndef USE_RIGHT_JUSTIFY // range_ is in [0..127] interval here. - const int idx = br->range_ >> (BITS); + const bit_t idx = br->range_ >> (BITS); const int shift = kVP8Log2Range[idx]; br->range_ = kVP8NewRange[idx]; br->value_ <<= shift; - br->missing_ += shift; + br->bits_ -= shift; +#else + const int shift = kVP8Log2Range[br->range_]; + assert(br->range_ < (range_t)128); + br->range_ = kVP8NewRange[br->range_]; + br->bits_ -= shift; +#endif } - static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) { +#ifndef USE_RIGHT_JUSTIFY // It's important to avoid generating a 64bit x 64bit multiply here. // We just need an 8b x 8b after all. - const bit_t split = - (bit_t)((uint32_t)(br->range_ >> (BITS)) * prob) << ((BITS) - 8); + const range_t split = + (range_t)((uint32_t)(br->range_ >> (BITS)) * prob) << ((BITS) - 8); const int bit = VP8BitUpdate(br, split); - if (br->range_ <= (((bit_t)0x7e << (BITS)) | (MASK))) { + if (br->range_ <= (((range_t)0x7e << (BITS)) | (MASK))) { VP8Shift(br); } return bit; +#else + const range_t split = (br->range_ * prob) >> 8; + const int bit = VP8BitUpdate(br, split); + if (br->range_ <= (range_t)0x7e) { + VP8Shift(br); + } + return bit; +#endif } static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) { - const bit_t split = (br->range_ >> 1); + const range_t split = (br->range_ >> 1); const int bit = VP8BitUpdate(br, split); VP8Shift(br); return bit ? -v : v; @@ -151,16 +284,18 @@ static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) { // ----------------------------------------------------------------------------- -// Bitreader +// Bitreader for lossless format + +typedef uint64_t vp8l_val_t; // right now, this bit-reader can only use 64bit. typedef struct { - uint64_t val_; - const uint8_t* buf_; - size_t len_; - size_t pos_; - int bit_pos_; - int eos_; - int error_; + vp8l_val_t val_; // pre-fetched bits + const uint8_t* buf_; // input byte buffer + size_t len_; // buffer length + size_t pos_; // byte position in buf_ + int bit_pos_; // current bit-reading position in val_ + int eos_; // bitstream is finished + int error_; // an error occurred (buffer overflow attempt...) } VP8LBitReader; void VP8LInitBitReader(VP8LBitReader* const br, @@ -176,17 +311,14 @@ void VP8LBitReaderSetBuffer(VP8LBitReader* const br, // Flags eos if this read attempt is going to cross the read buffer. uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits); -// Reads one bit from Read Buffer. Flags an error in case end_of_stream. -// Flags eos after reading last bit from the buffer. -uint32_t VP8LReadOneBit(VP8LBitReader* const br); +// Return the prefetched bits, so they can be looked up. +static WEBP_INLINE uint32_t VP8LPrefetchBits(VP8LBitReader* const br) { + return (uint32_t)(br->val_ >> br->bit_pos_); +} -// VP8LReadOneBitUnsafe is faster than VP8LReadOneBit, but it can be called only -// 32 times after the last VP8LFillBitWindow. Any subsequent calls -// (without VP8LFillBitWindow) will return invalid data. -static WEBP_INLINE uint32_t VP8LReadOneBitUnsafe(VP8LBitReader* const br) { - const uint32_t val = (br->val_ >> br->bit_pos_) & 1; - ++br->bit_pos_; - return val; +// Discard 'num_bits' bits from the cache. +static WEBP_INLINE void VP8LDiscardBits(VP8LBitReader* const br, int num_bits) { + br->bit_pos_ += num_bits; } // Advances the Read buffer by 4 bytes to make room for reading next 32 bits. diff --git a/3rdparty/libwebp/utils/bit_writer.c b/3rdparty/libwebp/utils/bit_writer.c index 671159cacd..3827a13ad1 100644 --- a/3rdparty/libwebp/utils/bit_writer.c +++ b/3rdparty/libwebp/utils/bit_writer.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Bit writing and boolean coder diff --git a/3rdparty/libwebp/utils/bit_writer.h b/3rdparty/libwebp/utils/bit_writer.h index f7ca08497f..cbb095c1be 100644 --- a/3rdparty/libwebp/utils/bit_writer.h +++ b/3rdparty/libwebp/utils/bit_writer.h @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Bit writing and boolean coder diff --git a/3rdparty/libwebp/utils/color_cache.c b/3rdparty/libwebp/utils/color_cache.c index 560f81db10..749db6128f 100644 --- a/3rdparty/libwebp/utils/color_cache.c +++ b/3rdparty/libwebp/utils/color_cache.c @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Color Cache for WebP Lossless diff --git a/3rdparty/libwebp/utils/color_cache.h b/3rdparty/libwebp/utils/color_cache.h index 13be629f36..e5a0bd6fd4 100644 --- a/3rdparty/libwebp/utils/color_cache.h +++ b/3rdparty/libwebp/utils/color_cache.h @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Color Cache for WebP Lossless diff --git a/3rdparty/libwebp/utils/filters.c b/3rdparty/libwebp/utils/filters.c index 08f52a3d20..eb5bb34f41 100644 --- a/3rdparty/libwebp/utils/filters.c +++ b/3rdparty/libwebp/utils/filters.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Spatial prediction using various filters @@ -26,8 +28,7 @@ extern "C" { assert(out != NULL); \ assert(width > 0); \ assert(height > 0); \ - assert(bpp > 0); \ - assert(stride >= width * bpp); + assert(stride >= width); static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred, uint8_t* dst, int length, int inverse) { @@ -43,7 +44,8 @@ static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred, // Horizontal filter. static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, - int width, int height, int bpp, int stride, int inverse, uint8_t* out) { + int width, int height, int stride, + int inverse, uint8_t* out) { int h; const uint8_t* preds = (inverse ? out : in); SANITY_CHECK(in, out); @@ -52,11 +54,11 @@ static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, for (h = 0; h < height; ++h) { // Leftmost pixel is predicted from above (except for topmost scanline). if (h == 0) { - memcpy((void*)out, (const void*)in, bpp); + out[0] = in[0]; } else { - PredictLine(in, preds - stride, out, bpp, inverse); + PredictLine(in, preds - stride, out, 1, inverse); } - PredictLine(in + bpp, preds, out + bpp, bpp * (width - 1), inverse); + PredictLine(in + 1, preds, out + 1, width - 1, inverse); preds += stride; in += stride; out += stride; @@ -64,46 +66,46 @@ static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, } static void HorizontalFilter(const uint8_t* data, int width, int height, - int bpp, int stride, uint8_t* filtered_data) { - DoHorizontalFilter(data, width, height, bpp, stride, 0, filtered_data); + int stride, uint8_t* filtered_data) { + DoHorizontalFilter(data, width, height, stride, 0, filtered_data); } -static void HorizontalUnfilter(const uint8_t* data, int width, int height, - int bpp, int stride, uint8_t* recon_data) { - DoHorizontalFilter(data, width, height, bpp, stride, 1, recon_data); +static void HorizontalUnfilter(int width, int height, int stride, + uint8_t* data) { + DoHorizontalFilter(data, width, height, stride, 1, data); } //------------------------------------------------------------------------------ // Vertical filter. static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, - int width, int height, int bpp, int stride, int inverse, uint8_t* out) { + int width, int height, int stride, + int inverse, uint8_t* out) { int h; const uint8_t* preds = (inverse ? out : in); SANITY_CHECK(in, out); // Very first top-left pixel is copied. - memcpy((void*)out, (const void*)in, bpp); + out[0] = in[0]; // Rest of top scan-line is left-predicted. - PredictLine(in + bpp, preds, out + bpp, bpp * (width - 1), inverse); + PredictLine(in + 1, preds, out + 1, width - 1, inverse); // Filter line-by-line. for (h = 1; h < height; ++h) { in += stride; out += stride; - PredictLine(in, preds, out, bpp * width, inverse); + PredictLine(in, preds, out, width, inverse); preds += stride; } } static void VerticalFilter(const uint8_t* data, int width, int height, - int bpp, int stride, uint8_t* filtered_data) { - DoVerticalFilter(data, width, height, bpp, stride, 0, filtered_data); + int stride, uint8_t* filtered_data) { + DoVerticalFilter(data, width, height, stride, 0, filtered_data); } -static void VerticalUnfilter(const uint8_t* data, int width, int height, - int bpp, int stride, uint8_t* recon_data) { - DoVerticalFilter(data, width, height, bpp, stride, 1, recon_data); +static void VerticalUnfilter(int width, int height, int stride, uint8_t* data) { + DoVerticalFilter(data, width, height, stride, 1, data); } //------------------------------------------------------------------------------ @@ -111,19 +113,19 @@ static void VerticalUnfilter(const uint8_t* data, int width, int height, static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) { const int g = a + b - c; - return (g < 0) ? 0 : (g > 255) ? 255 : g; + return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit } static WEBP_INLINE void DoGradientFilter(const uint8_t* in, int width, int height, - int bpp, int stride, int inverse, uint8_t* out) { + int stride, int inverse, uint8_t* out) { const uint8_t* preds = (inverse ? out : in); int h; SANITY_CHECK(in, out); // left prediction for top scan-line - memcpy((void*)out, (const void*)in, bpp); - PredictLine(in + bpp, preds, out + bpp, bpp * (width - 1), inverse); + out[0] = in[0]; + PredictLine(in + 1, preds, out + 1, width - 1, inverse); // Filter line-by-line. for (h = 1; h < height; ++h) { @@ -132,31 +134,29 @@ void DoGradientFilter(const uint8_t* in, int width, int height, in += stride; out += stride; // leftmost pixel: predict from above. - PredictLine(in, preds - stride, out, bpp, inverse); - for (w = bpp; w < width * bpp; ++w) { - const int pred = GradientPredictor(preds[w - bpp], + PredictLine(in, preds - stride, out, 1, inverse); + for (w = 1; w < width; ++w) { + const int pred = GradientPredictor(preds[w - 1], preds[w - stride], - preds[w - stride - bpp]); + preds[w - stride - 1]); out[w] = in[w] + (inverse ? pred : -pred); } } } static void GradientFilter(const uint8_t* data, int width, int height, - int bpp, int stride, uint8_t* filtered_data) { - DoGradientFilter(data, width, height, bpp, stride, 0, filtered_data); + int stride, uint8_t* filtered_data) { + DoGradientFilter(data, width, height, stride, 0, filtered_data); } -static void GradientUnfilter(const uint8_t* data, int width, int height, - int bpp, int stride, uint8_t* recon_data) { - DoGradientFilter(data, width, height, bpp, stride, 1, recon_data); +static void GradientUnfilter(int width, int height, int stride, uint8_t* data) { + DoGradientFilter(data, width, height, stride, 1, data); } #undef SANITY_CHECK // ----------------------------------------------------------------------------- -// Quick estimate of a potentially interesting filter mode to try, in addition -// to the default NONE. +// Quick estimate of a potentially interesting filter mode to try. #define SMAX 16 #define SDIFF(a, b) (abs((a) - (b)) >> 4) // Scoring diff, in [0..SMAX) @@ -166,6 +166,7 @@ WEBP_FILTER_TYPE EstimateBestFilter(const uint8_t* data, int i, j; int bins[WEBP_FILTER_LAST][SMAX]; memset(bins, 0, sizeof(bins)); + // We only sample every other pixels. That's enough. for (j = 2; j < height - 1; j += 2) { const uint8_t* const p = data + j * stride; @@ -215,7 +216,7 @@ const WebPFilterFunc WebPFilters[WEBP_FILTER_LAST] = { GradientFilter // WEBP_FILTER_GRADIENT }; -const WebPFilterFunc WebPUnfilters[WEBP_FILTER_LAST] = { +const WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST] = { NULL, // WEBP_FILTER_NONE HorizontalUnfilter, // WEBP_FILTER_HORIZONTAL VerticalUnfilter, // WEBP_FILTER_VERTICAL diff --git a/3rdparty/libwebp/utils/filters.h b/3rdparty/libwebp/utils/filters.h index c5cdbd6deb..1f5fa164f3 100644 --- a/3rdparty/libwebp/utils/filters.h +++ b/3rdparty/libwebp/utils/filters.h @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Spatial prediction using various filters @@ -30,18 +32,19 @@ typedef enum { } WEBP_FILTER_TYPE; typedef void (*WebPFilterFunc)(const uint8_t* in, int width, int height, - int bpp, int stride, uint8_t* out); + int stride, uint8_t* out); +typedef void (*WebPUnfilterFunc)(int width, int height, int stride, + uint8_t* data); // Filter the given data using the given predictor. // 'in' corresponds to a 2-dimensional pixel array of size (stride * height) // in raster order. -// 'bpp' is number of bytes per pixel, and // 'stride' is number of bytes per scan line (with possible padding). // 'out' should be pre-allocated. extern const WebPFilterFunc WebPFilters[WEBP_FILTER_LAST]; -// Reconstruct the original data from the given filtered data. -extern const WebPFilterFunc WebPUnfilters[WEBP_FILTER_LAST]; +// In-place reconstruct the original data from the given filtered data. +extern const WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST]; // Fast estimate of a potentially good filter. extern WEBP_FILTER_TYPE EstimateBestFilter(const uint8_t* data, diff --git a/3rdparty/libwebp/utils/huffman.c b/3rdparty/libwebp/utils/huffman.c index 41529cc9da..0ba9d05cfc 100644 --- a/3rdparty/libwebp/utils/huffman.c +++ b/3rdparty/libwebp/utils/huffman.c @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Utilities for building and looking up Huffman trees. diff --git a/3rdparty/libwebp/utils/huffman.h b/3rdparty/libwebp/utils/huffman.h index 70220a67fb..83a517ee60 100644 --- a/3rdparty/libwebp/utils/huffman.h +++ b/3rdparty/libwebp/utils/huffman.h @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Utilities for building and looking up Huffman trees. diff --git a/3rdparty/libwebp/utils/huffman_encode.c b/3rdparty/libwebp/utils/huffman_encode.c index 8ccd291d22..96086663d9 100644 --- a/3rdparty/libwebp/utils/huffman_encode.c +++ b/3rdparty/libwebp/utils/huffman_encode.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Author: Jyrki Alakuijala (jyrki@google.com) @@ -138,13 +140,8 @@ static int CompareHuffmanTrees(const void* ptr1, const void* ptr2) { } else if (t1->total_count_ < t2->total_count_) { return 1; } else { - if (t1->value_ < t2->value_) { - return -1; - } - if (t1->value_ > t2->value_) { - return 1; - } - return 0; + assert(t1->value_ != t2->value_); + return (t1->value_ < t2->value_) ? -1 : 1; } } @@ -193,6 +190,10 @@ static int GenerateOptimalTree(const int* const histogram, int histogram_size, } } + if (tree_size_orig == 0) { // pretty optimal already! + return 1; + } + // 3 * tree_size is enough to cover all the nodes representing a // population and all the inserted nodes combining two existing nodes. // The tree pool needs 2 * (tree_size_orig - 1) entities, and the @@ -234,7 +235,7 @@ static int GenerateOptimalTree(const int* const histogram, int histogram_size, tree_pool[tree_pool_size++] = tree[tree_size - 1]; tree_pool[tree_pool_size++] = tree[tree_size - 2]; count = tree_pool[tree_pool_size - 1].total_count_ + - tree_pool[tree_pool_size - 2].total_count_; + tree_pool[tree_pool_size - 2].total_count_; tree_size -= 2; { // Search for the insertion point. diff --git a/3rdparty/libwebp/utils/huffman_encode.h b/3rdparty/libwebp/utils/huffman_encode.h index cc3b38d330..0b81f470b3 100644 --- a/3rdparty/libwebp/utils/huffman_encode.h +++ b/3rdparty/libwebp/utils/huffman_encode.h @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Author: Jyrki Alakuijala (jyrki@google.com) diff --git a/3rdparty/libwebp/utils/quant_levels.c b/3rdparty/libwebp/utils/quant_levels.c index f6884392aa..42c7245d36 100644 --- a/3rdparty/libwebp/utils/quant_levels.c +++ b/3rdparty/libwebp/utils/quant_levels.c @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Quantize levels for specified number of quantization-levels ([2, 256]). @@ -140,15 +142,6 @@ int QuantizeLevels(uint8_t* const data, int width, int height, return 1; } -int DequantizeLevels(uint8_t* const data, int width, int height) { - if (data == NULL || width <= 0 || height <= 0) return 0; - // TODO(skal): implement gradient smoothing. - (void)data; - (void)width; - (void)height; - return 1; -} - #if defined(__cplusplus) || defined(c_plusplus) } // extern "C" #endif diff --git a/3rdparty/libwebp/utils/quant_levels.h b/3rdparty/libwebp/utils/quant_levels.h index 89ccafe40d..2d90828df9 100644 --- a/3rdparty/libwebp/utils/quant_levels.h +++ b/3rdparty/libwebp/utils/quant_levels.h @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Alpha plane quantization utility @@ -27,11 +29,6 @@ extern "C" { int QuantizeLevels(uint8_t* const data, int width, int height, int num_levels, uint64_t* const sse); -// Apply post-processing to input 'data' of size 'width'x'height' assuming -// that the source was quantized to a reduced number of levels. -// Returns false in case of error (data is NULL, invalid parameters, ...). -int DequantizeLevels(uint8_t* const data, int width, int height); - #if defined(__cplusplus) || defined(c_plusplus) } // extern "C" #endif diff --git a/3rdparty/libwebp/utils/quant_levels_dec.c b/3rdparty/libwebp/utils/quant_levels_dec.c new file mode 100644 index 0000000000..d93594b3ba --- /dev/null +++ b/3rdparty/libwebp/utils/quant_levels_dec.c @@ -0,0 +1,30 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// TODO(skal): implement gradient smoothing. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "./quant_levels_dec.h" + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +int DequantizeLevels(uint8_t* const data, int width, int height) { + if (data == NULL || width <= 0 || height <= 0) return 0; + (void)data; + (void)width; + (void)height; + return 1; +} + +#if defined(__cplusplus) || defined(c_plusplus) +} // extern "C" +#endif diff --git a/3rdparty/libwebp/utils/quant_levels_dec.h b/3rdparty/libwebp/utils/quant_levels_dec.h new file mode 100644 index 0000000000..5891067650 --- /dev/null +++ b/3rdparty/libwebp/utils/quant_levels_dec.h @@ -0,0 +1,32 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Alpha plane de-quantization utility +// +// Author: Vikas Arora (vikasa@google.com) + +#ifndef WEBP_UTILS_QUANT_LEVELS_DEC_H_ +#define WEBP_UTILS_QUANT_LEVELS_DEC_H_ + +#include "../webp/types.h" + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +// Apply post-processing to input 'data' of size 'width'x'height' assuming +// that the source was quantized to a reduced number of levels. +// Returns false in case of error (data is NULL, invalid parameters, ...). +int DequantizeLevels(uint8_t* const data, int width, int height); + +#if defined(__cplusplus) || defined(c_plusplus) +} // extern "C" +#endif + +#endif /* WEBP_UTILS_QUANT_LEVELS_DEC_H_ */ diff --git a/3rdparty/libwebp/utils/rescaler.c b/3rdparty/libwebp/utils/rescaler.c index 9825dcbc5f..e5ddc296ab 100644 --- a/3rdparty/libwebp/utils/rescaler.c +++ b/3rdparty/libwebp/utils/rescaler.c @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Rescaling functions @@ -20,7 +22,7 @@ extern "C" { #endif #define RFIX 30 -#define MULT_FIX(x,y) (((int64_t)(x) * (y) + (1 << (RFIX - 1))) >> RFIX) +#define MULT_FIX(x, y) (((int64_t)(x) * (y) + (1 << (RFIX - 1))) >> RFIX) void WebPRescalerInit(WebPRescaler* const wrk, int src_width, int src_height, uint8_t* const dst, int dst_width, int dst_height, diff --git a/3rdparty/libwebp/utils/rescaler.h b/3rdparty/libwebp/utils/rescaler.h index ef93d465f0..aedce46254 100644 --- a/3rdparty/libwebp/utils/rescaler.h +++ b/3rdparty/libwebp/utils/rescaler.h @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Rescaling functions diff --git a/3rdparty/libwebp/utils/thread.c b/3rdparty/libwebp/utils/thread.c index ce89cf9dc7..b1615d0fb8 100644 --- a/3rdparty/libwebp/utils/thread.c +++ b/3rdparty/libwebp/utils/thread.c @@ -1,18 +1,16 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Multi-threaded worker // // Author: Skal (pascal.massimino@gmail.com) -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include #include // for memset() #include "./thread.h" diff --git a/3rdparty/libwebp/utils/thread.h b/3rdparty/libwebp/utils/thread.h index 3191890b76..13a61a4c84 100644 --- a/3rdparty/libwebp/utils/thread.h +++ b/3rdparty/libwebp/utils/thread.h @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Multi-threaded worker @@ -12,6 +14,10 @@ #ifndef WEBP_UTILS_THREAD_H_ #define WEBP_UTILS_THREAD_H_ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif @@ -63,13 +69,13 @@ typedef struct { // Must be called first, before any other method. void WebPWorkerInit(WebPWorker* const worker); -// Must be called initialize the object and spawn the thread. Re-entrant. +// Must be called to initialize the object and spawn the thread. Re-entrant. // Will potentially launch the thread. Returns false in case of error. int WebPWorkerReset(WebPWorker* const worker); -// Make sure the previous work is finished. Returns true if worker->had_error -// was not set and not error condition was triggered by the working thread. +// Makes sure the previous work is finished. Returns true if worker->had_error +// was not set and no error condition was triggered by the working thread. int WebPWorkerSync(WebPWorker* const worker); -// Trigger the thread to call hook() with data1 and data2 argument. These +// Triggers the thread to call hook() with data1 and data2 argument. These // hook/data1/data2 can be changed at any time before calling this function, // but not be changed afterward until the next call to WebPWorkerSync(). void WebPWorkerLaunch(WebPWorker* const worker); diff --git a/3rdparty/libwebp/utils/utils.c b/3rdparty/libwebp/utils/utils.c index 673b7e284c..7eb06105b8 100644 --- a/3rdparty/libwebp/utils/utils.c +++ b/3rdparty/libwebp/utils/utils.c @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Misc. common utility functions @@ -19,7 +21,8 @@ extern "C" { //------------------------------------------------------------------------------ // Checked memory allocation -static int CheckSizeArguments(uint64_t nmemb, size_t size) { +// Returns 0 in case of overflow of nmemb * size. +static int CheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) { const uint64_t total_size = nmemb * size; if (nmemb == 0) return 1; if ((uint64_t)size > WEBP_MAX_ALLOCABLE_MEMORY / nmemb) return 0; @@ -28,12 +31,14 @@ static int CheckSizeArguments(uint64_t nmemb, size_t size) { } void* WebPSafeMalloc(uint64_t nmemb, size_t size) { - if (!CheckSizeArguments(nmemb, size)) return NULL; + if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL; + assert(nmemb * size > 0); return malloc((size_t)(nmemb * size)); } void* WebPSafeCalloc(uint64_t nmemb, size_t size) { - if (!CheckSizeArguments(nmemb, size)) return NULL; + if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL; + assert(nmemb * size > 0); return calloc((size_t)nmemb, size); } diff --git a/3rdparty/libwebp/utils/utils.h b/3rdparty/libwebp/utils/utils.h index a034762556..e10aeeb9d7 100644 --- a/3rdparty/libwebp/utils/utils.h +++ b/3rdparty/libwebp/utils/utils.h @@ -1,17 +1,22 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Misc. common utility functions // -// Author: Skal (pascal.massimino@gmail.com) +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) #ifndef WEBP_UTILS_UTILS_H_ #define WEBP_UTILS_UTILS_H_ +#include + #include "../webp/types.h" #if defined(__cplusplus) || defined(c_plusplus) @@ -35,6 +40,40 @@ void* WebPSafeMalloc(uint64_t nmemb, size_t size); // in order to favor the "calloc(num_foo, sizeof(foo))" pattern. void* WebPSafeCalloc(uint64_t nmemb, size_t size); +//------------------------------------------------------------------------------ +// Reading/writing data. + +// Read 16, 24 or 32 bits stored in little-endian order. +static WEBP_INLINE int GetLE16(const uint8_t* const data) { + return (int)(data[0] << 0) | (data[1] << 8); +} + +static WEBP_INLINE int GetLE24(const uint8_t* const data) { + return GetLE16(data) | (data[2] << 16); +} + +static WEBP_INLINE uint32_t GetLE32(const uint8_t* const data) { + return (uint32_t)GetLE16(data) | (GetLE16(data + 2) << 16); +} + +// Store 16, 24 or 32 bits in little-endian order. +static WEBP_INLINE void PutLE16(uint8_t* const data, int val) { + assert(val < (1 << 16)); + data[0] = (val >> 0); + data[1] = (val >> 8); +} + +static WEBP_INLINE void PutLE24(uint8_t* const data, int val) { + assert(val < (1 << 24)); + PutLE16(data, val & 0xffff); + data[2] = (val >> 16); +} + +static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) { + PutLE16(data, (int)(val & 0xffff)); + PutLE16(data + 2, (int)(val >> 16)); +} + //------------------------------------------------------------------------------ #if defined(__cplusplus) || defined(c_plusplus) diff --git a/3rdparty/libwebp/webp/decode.h b/3rdparty/libwebp/webp/decode.h index 43b6c58f4f..141f8618f5 100644 --- a/3rdparty/libwebp/webp/decode.h +++ b/3rdparty/libwebp/webp/decode.h @@ -1,8 +1,10 @@ // Copyright 2010 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Main decoding functions for WebP images. @@ -18,7 +20,19 @@ extern "C" { #endif -#define WEBP_DECODER_ABI_VERSION 0x0200 // MAJOR(8b) + MINOR(8b) +#define WEBP_DECODER_ABI_VERSION 0x0201 // MAJOR(8b) + MINOR(8b) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum VP8StatusCode VP8StatusCode; +// typedef enum WEBP_CSP_MODE WEBP_CSP_MODE; +typedef struct WebPRGBABuffer WebPRGBABuffer; +typedef struct WebPYUVABuffer WebPYUVABuffer; +typedef struct WebPDecBuffer WebPDecBuffer; +typedef struct WebPIDecoder WebPIDecoder; +typedef struct WebPBitstreamFeatures WebPBitstreamFeatures; +typedef struct WebPDecoderOptions WebPDecoderOptions; +typedef struct WebPDecoderConfig WebPDecoderConfig; // Return the decoder's version number, packed in hexadecimal using 8bits for // each of major/minor/revision. E.g: v2.5.7 is 0x020507. @@ -118,20 +132,28 @@ WEBP_EXTERN(uint8_t*) WebPDecodeYUVInto( // Note: the naming describes the byte-ordering of packed samples in memory. // For instance, MODE_BGRA relates to samples ordered as B,G,R,A,B,G,R,A,... // Non-capital names (e.g.:MODE_Argb) relates to pre-multiplied RGB channels. -// RGB-565 and RGBA-4444 are also endian-agnostic and byte-oriented. -typedef enum { MODE_RGB = 0, MODE_RGBA = 1, - MODE_BGR = 2, MODE_BGRA = 3, - MODE_ARGB = 4, MODE_RGBA_4444 = 5, - MODE_RGB_565 = 6, - // RGB-premultiplied transparent modes (alpha value is preserved) - MODE_rgbA = 7, - MODE_bgrA = 8, - MODE_Argb = 9, - MODE_rgbA_4444 = 10, - // YUV modes must come after RGB ones. - MODE_YUV = 11, MODE_YUVA = 12, // yuv 4:2:0 - MODE_LAST = 13 - } WEBP_CSP_MODE; +// RGBA-4444 and RGB-565 colorspaces are represented by following byte-order: +// RGBA-4444: [r3 r2 r1 r0 g3 g2 g1 g0], [b3 b2 b1 b0 a3 a2 a1 a0], ... +// RGB-565: [r4 r3 r2 r1 r0 g5 g4 g3], [g2 g1 g0 b4 b3 b2 b1 b0], ... +// In the case WEBP_SWAP_16BITS_CSP is defined, the bytes are swapped for +// these two modes: +// RGBA-4444: [b3 b2 b1 b0 a3 a2 a1 a0], [r3 r2 r1 r0 g3 g2 g1 g0], ... +// RGB-565: [g2 g1 g0 b4 b3 b2 b1 b0], [r4 r3 r2 r1 r0 g5 g4 g3], ... + +typedef enum WEBP_CSP_MODE { + MODE_RGB = 0, MODE_RGBA = 1, + MODE_BGR = 2, MODE_BGRA = 3, + MODE_ARGB = 4, MODE_RGBA_4444 = 5, + MODE_RGB_565 = 6, + // RGB-premultiplied transparent modes (alpha value is preserved) + MODE_rgbA = 7, + MODE_bgrA = 8, + MODE_Argb = 9, + MODE_rgbA_4444 = 10, + // YUV modes must come after RGB ones. + MODE_YUV = 11, MODE_YUVA = 12, // yuv 4:2:0 + MODE_LAST = 13 +} WEBP_CSP_MODE; // Some useful macros: static WEBP_INLINE int WebPIsPremultipliedMode(WEBP_CSP_MODE mode) { @@ -152,13 +174,13 @@ static WEBP_INLINE int WebPIsRGBMode(WEBP_CSP_MODE mode) { //------------------------------------------------------------------------------ // WebPDecBuffer: Generic structure for describing the output sample buffer. -typedef struct { // view as RGBA +struct WebPRGBABuffer { // view as RGBA uint8_t* rgba; // pointer to RGBA samples int stride; // stride in bytes from one scanline to the next. size_t size; // total size of the *rgba buffer. -} WebPRGBABuffer; +}; -typedef struct { // view as YUVA +struct WebPYUVABuffer { // view as YUVA uint8_t* y, *u, *v, *a; // pointer to luma, chroma U/V, alpha samples int y_stride; // luma stride int u_stride, v_stride; // chroma strides @@ -166,10 +188,10 @@ typedef struct { // view as YUVA size_t y_size; // luma plane size size_t u_size, v_size; // chroma planes size size_t a_size; // alpha-plane size -} WebPYUVABuffer; +}; // Output buffer -typedef struct { +struct WebPDecBuffer { WEBP_CSP_MODE colorspace; // Colorspace. int width, height; // Dimensions. int is_external_memory; // If true, 'internal_memory' pointer is not used. @@ -182,7 +204,7 @@ typedef struct { uint8_t* private_memory; // Internally allocated memory (only when // is_external_memory is false). Should not be used // externally, but accessed via the buffer union. -} WebPDecBuffer; +}; // Internal, version-checked, entry point WEBP_EXTERN(int) WebPInitDecBufferInternal(WebPDecBuffer*, int); @@ -200,7 +222,7 @@ WEBP_EXTERN(void) WebPFreeDecBuffer(WebPDecBuffer* buffer); //------------------------------------------------------------------------------ // Enumeration of the status codes -typedef enum { +typedef enum VP8StatusCode { VP8_STATUS_OK = 0, VP8_STATUS_OUT_OF_MEMORY, VP8_STATUS_INVALID_PARAM, @@ -237,13 +259,17 @@ typedef enum { // } // WebPIDelete(idec); -typedef struct WebPIDecoder WebPIDecoder; - // Creates a new incremental decoder with the supplied buffer parameter. // This output_buffer can be passed NULL, in which case a default output buffer // is used (with MODE_RGB). Otherwise, an internal reference to 'output_buffer' // is kept, which means that the lifespan of 'output_buffer' must be larger than // that of the returned WebPIDecoder object. +// The supplied 'output_buffer' content MUST NOT be changed between calls to +// WebPIAppend() or WebPIUpdate() unless 'output_buffer.is_external_memory' is +// set to 1. In such a case, it is allowed to modify the pointers, size and +// stride of output_buffer.u.RGBA or output_buffer.u.YUVA, provided they remain +// within valid bounds. +// All other fields of WebPDecBuffer MUST remain constant between calls. // Returns NULL if the allocation failed. WEBP_EXTERN(WebPIDecoder*) WebPINewDecoder(WebPDecBuffer* output_buffer); @@ -251,19 +277,27 @@ WEBP_EXTERN(WebPIDecoder*) WebPINewDecoder(WebPDecBuffer* output_buffer); // will output the RGB/A samples specified by 'csp' into a preallocated // buffer 'output_buffer'. The size of this buffer is at least // 'output_buffer_size' and the stride (distance in bytes between two scanlines) -// is specified by 'output_stride'. Returns NULL if the allocation failed. +// is specified by 'output_stride'. +// Additionally, output_buffer can be passed NULL in which case the output +// buffer will be allocated automatically when the decoding starts. The +// colorspace 'csp' is taken into account for allocating this buffer. All other +// parameters are ignored. +// Returns NULL if the allocation failed, or if some parameters are invalid. WEBP_EXTERN(WebPIDecoder*) WebPINewRGB( WEBP_CSP_MODE csp, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); // This function allocates and initializes an incremental-decoder object, which -// will output the raw luma/chroma samples into a preallocated planes. The luma -// plane is specified by its pointer 'luma', its size 'luma_size' and its stride -// 'luma_stride'. Similarly, the chroma-u plane is specified by the 'u', -// 'u_size' and 'u_stride' parameters, and the chroma-v plane by 'v' -// and 'v_size'. And same for the alpha-plane. The 'a' pointer can be pass -// NULL in case one is not interested in the transparency plane. -// Returns NULL if the allocation failed. +// will output the raw luma/chroma samples into a preallocated planes if +// supplied. The luma plane is specified by its pointer 'luma', its size +// 'luma_size' and its stride 'luma_stride'. Similarly, the chroma-u plane +// is specified by the 'u', 'u_size' and 'u_stride' parameters, and the chroma-v +// plane by 'v' and 'v_size'. And same for the alpha-plane. The 'a' pointer +// can be pass NULL in case one is not interested in the transparency plane. +// Conversely, 'luma' can be passed NULL if no preallocated planes are supplied. +// In this case, the output buffer will be automatically allocated (using +// MODE_YUVA) when decoding starts. All parameters are then ignored. +// Returns NULL if the allocation failed or if a parameter is invalid. WEBP_EXTERN(WebPIDecoder*) WebPINewYUVA( uint8_t* luma, size_t luma_size, int luma_stride, uint8_t* u, size_t u_size, int u_stride, @@ -344,7 +378,7 @@ WEBP_EXTERN(const WebPDecBuffer*) WebPIDecodedArea( CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK); // C) Adjust 'config', if needed - config.no_fancy = 1; + config.no_fancy_upsampling = 1; config.output.colorspace = MODE_BGRA; // etc. @@ -365,10 +399,11 @@ WEBP_EXTERN(const WebPDecBuffer*) WebPIDecodedArea( */ // Features gathered from the bitstream -typedef struct { - int width; // Width in pixels, as read from the bitstream. - int height; // Height in pixels, as read from the bitstream. - int has_alpha; // True if the bitstream contains an alpha channel. +struct WebPBitstreamFeatures { + int width; // Width in pixels, as read from the bitstream. + int height; // Height in pixels, as read from the bitstream. + int has_alpha; // True if the bitstream contains an alpha channel. + int has_animation; // True if the bitstream is an animation. // Unused for now: int bitstream_version; // should be 0 for now. TODO(later) @@ -376,8 +411,8 @@ typedef struct { // recommended. int rotate; // TODO(later) int uv_sampling; // should be 0 for now. TODO(later) - uint32_t pad[3]; // padding for later use -} WebPBitstreamFeatures; + uint32_t pad[2]; // padding for later use +}; // Internal, version-checked, entry point WEBP_EXTERN(VP8StatusCode) WebPGetFeaturesInternal( @@ -385,8 +420,9 @@ WEBP_EXTERN(VP8StatusCode) WebPGetFeaturesInternal( // Retrieve features from the bitstream. The *features structure is filled // with information gathered from the bitstream. -// Returns false in case of error or version mismatch. -// In case of error, features->bitstream_status will reflect the error code. +// Returns VP8_STATUS_OK when the features are successfully retrieved. Returns +// VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the +// features from headers. Returns error in other cases. static WEBP_INLINE VP8StatusCode WebPGetFeatures( const uint8_t* data, size_t data_size, WebPBitstreamFeatures* features) { @@ -395,7 +431,7 @@ static WEBP_INLINE VP8StatusCode WebPGetFeatures( } // Decoding options -typedef struct { +struct WebPDecoderOptions { int bypass_filtering; // if true, skip the in-loop filtering int no_fancy_upsampling; // if true, use faster pointwise upsampler int use_cropping; // if true, cropping is applied _first_ @@ -410,14 +446,14 @@ typedef struct { int force_rotation; // forced rotation (to be applied _last_) int no_enhancement; // if true, discard enhancement layer uint32_t pad[6]; // padding for later use -} WebPDecoderOptions; +}; // Main object storing the configuration for advanced decoding. -typedef struct { +struct WebPDecoderConfig { WebPBitstreamFeatures input; // Immutable bitstream features (optional) WebPDecBuffer output; // Output buffer (can point to external mem) WebPDecoderOptions options; // Decoding options -} WebPDecoderConfig; +}; // Internal, version-checked, entry point WEBP_EXTERN(int) WebPInitDecoderConfigInternal(WebPDecoderConfig*, int); diff --git a/3rdparty/libwebp/webp/demux.h b/3rdparty/libwebp/webp/demux.h new file mode 100644 index 0000000000..c7cd5d66db --- /dev/null +++ b/3rdparty/libwebp/webp/demux.h @@ -0,0 +1,214 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Demux API. +// Enables extraction of image and extended format data from WebP files. + +// Code Example: Demuxing WebP data to extract all the frames, ICC profile +// and EXIF/XMP metadata. +// +// WebPDemuxer* demux = WebPDemux(&webp_data); +// +// uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH); +// uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT); +// // ... (Get information about the features present in the WebP file). +// uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS); +// +// // ... (Iterate over all frames). +// WebPIterator iter; +// if (WebPDemuxGetFrame(demux, 1, &iter)) { +// do { +// // ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(), +// // ... and get other frame properties like width, height, offsets etc. +// // ... see 'struct WebPIterator' below for more info). +// } while (WebPDemuxNextFrame(&iter)); +// WebPDemuxReleaseIterator(&iter); +// } +// +// // ... (Extract metadata). +// WebPChunkIterator chunk_iter; +// if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter); +// // ... (Consume the ICC profile in 'chunk_iter.chunk'). +// WebPDemuxReleaseChunkIterator(&chunk_iter); +// if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter); +// // ... (Consume the EXIF metadata in 'chunk_iter.chunk'). +// WebPDemuxReleaseChunkIterator(&chunk_iter); +// if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter); +// // ... (Consume the XMP metadata in 'chunk_iter.chunk'). +// WebPDemuxReleaseChunkIterator(&chunk_iter); +// WebPDemuxDelete(demux); + +#ifndef WEBP_WEBP_DEMUX_H_ +#define WEBP_WEBP_DEMUX_H_ + +#include "./mux_types.h" + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#define WEBP_DEMUX_ABI_VERSION 0x0100 // MAJOR(8b) + MINOR(8b) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPDemuxState WebPDemuxState; +// typedef enum WebPFormatFeature WebPFormatFeature; +typedef struct WebPDemuxer WebPDemuxer; +typedef struct WebPIterator WebPIterator; +typedef struct WebPChunkIterator WebPChunkIterator; + +//------------------------------------------------------------------------------ + +// Returns the version number of the demux library, packed in hexadecimal using +// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. +WEBP_EXTERN(int) WebPGetDemuxVersion(void); + +//------------------------------------------------------------------------------ +// Life of a Demux object + +typedef enum WebPDemuxState { + WEBP_DEMUX_PARSING_HEADER, // Not enough data to parse full header. + WEBP_DEMUX_PARSED_HEADER, // Header parsing complete, data may be available. + WEBP_DEMUX_DONE // Entire file has been parsed. +} WebPDemuxState; + +// Internal, version-checked, entry point +WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal( + const WebPData*, int, WebPDemuxState*, int); + +// Parses the full WebP file given by 'data'. +// Returns a WebPDemuxer object on successful parse, NULL otherwise. +static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) { + return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION); +} + +// Parses the possibly incomplete WebP file given by 'data'. +// If 'state' is non-NULL it will be set to indicate the status of the demuxer. +// Returns a WebPDemuxer object on successful parse, NULL otherwise. +static WEBP_INLINE WebPDemuxer* WebPDemuxPartial( + const WebPData* data, WebPDemuxState* state) { + return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION); +} + +// Frees memory associated with 'dmux'. +WEBP_EXTERN(void) WebPDemuxDelete(WebPDemuxer* dmux); + +//------------------------------------------------------------------------------ +// Data/information extraction. + +typedef enum WebPFormatFeature { + WEBP_FF_FORMAT_FLAGS, // Extended format flags present in the 'VP8X' chunk. + WEBP_FF_CANVAS_WIDTH, + WEBP_FF_CANVAS_HEIGHT, + WEBP_FF_LOOP_COUNT, + WEBP_FF_BACKGROUND_COLOR, + WEBP_FF_FRAME_COUNT // Number of frames present in the demux object. + // In case of a partial demux, this is the number of + // frames seen so far, with the last frame possibly + // being partial. +} WebPFormatFeature; + +// Get the 'feature' value from the 'dmux'. +// NOTE: values are only valid if WebPDemux() was used or WebPDemuxPartial() +// returned a state > WEBP_DEMUX_PARSING_HEADER. +WEBP_EXTERN(uint32_t) WebPDemuxGetI( + const WebPDemuxer* dmux, WebPFormatFeature feature); + +//------------------------------------------------------------------------------ +// Frame iteration. + +struct WebPIterator { + int frame_num; + int num_frames; // equivalent to WEBP_FF_FRAME_COUNT. + int fragment_num; + int num_fragments; + int x_offset, y_offset; // offset relative to the canvas. + int width, height; // dimensions of this frame or fragment. + int duration; // display duration in milliseconds. + WebPMuxAnimDispose dispose_method; // dispose method for the frame. + int complete; // true if 'fragment' contains a full frame. partial images + // may still be decoded with the WebP incremental decoder. + WebPData fragment; // The frame or fragment given by 'frame_num' and + // 'fragment_num'. + + uint32_t pad[4]; // padding for later use. + void* private_; // for internal use only. +}; + +// Retrieves frame 'frame_number' from 'dmux'. +// 'iter->fragment' points to the first fragment on return from this function. +// Individual fragments may be extracted using WebPDemuxSetFragment(). +// Setting 'frame_number' equal to 0 will return the last frame of the image. +// Returns false if 'dmux' is NULL or frame 'frame_number' is not present. +// Call WebPDemuxReleaseIterator() when use of the iterator is complete. +// NOTE: 'dmux' must persist for the lifetime of 'iter'. +WEBP_EXTERN(int) WebPDemuxGetFrame( + const WebPDemuxer* dmux, int frame_number, WebPIterator* iter); + +// Sets 'iter->fragment' to point to the next ('iter->frame_num' + 1) or +// previous ('iter->frame_num' - 1) frame. These functions do not loop. +// Returns true on success, false otherwise. +WEBP_EXTERN(int) WebPDemuxNextFrame(WebPIterator* iter); +WEBP_EXTERN(int) WebPDemuxPrevFrame(WebPIterator* iter); + +// Sets 'iter->fragment' to reflect fragment number 'fragment_num'. +// Returns true if fragment 'fragment_num' is present, false otherwise. +WEBP_EXTERN(int) WebPDemuxSelectFragment(WebPIterator* iter, int fragment_num); + +// Releases any memory associated with 'iter'. +// Must be called before any subsequent calls to WebPDemuxGetChunk() on the same +// iter. Also, must be called before destroying the associated WebPDemuxer with +// WebPDemuxDelete(). +WEBP_EXTERN(void) WebPDemuxReleaseIterator(WebPIterator* iter); + +//------------------------------------------------------------------------------ +// Chunk iteration. + +struct WebPChunkIterator { + // The current and total number of chunks with the fourcc given to + // WebPDemuxGetChunk(). + int chunk_num; + int num_chunks; + WebPData chunk; // The payload of the chunk. + + uint32_t pad[6]; // padding for later use + void* private_; +}; + +// Retrieves the 'chunk_number' instance of the chunk with id 'fourcc' from +// 'dmux'. +// 'fourcc' is a character array containing the fourcc of the chunk to return, +// e.g., "ICCP", "XMP ", "EXIF", etc. +// Setting 'chunk_number' equal to 0 will return the last chunk in a set. +// Returns true if the chunk is found, false otherwise. Image related chunk +// payloads are accessed through WebPDemuxGetFrame() and related functions. +// Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete. +// NOTE: 'dmux' must persist for the lifetime of the iterator. +WEBP_EXTERN(int) WebPDemuxGetChunk(const WebPDemuxer* dmux, + const char fourcc[4], int chunk_number, + WebPChunkIterator* iter); + +// Sets 'iter->chunk' to point to the next ('iter->chunk_num' + 1) or previous +// ('iter->chunk_num' - 1) chunk. These functions do not loop. +// Returns true on success, false otherwise. +WEBP_EXTERN(int) WebPDemuxNextChunk(WebPChunkIterator* iter); +WEBP_EXTERN(int) WebPDemuxPrevChunk(WebPChunkIterator* iter); + +// Releases any memory associated with 'iter'. +// Must be called before destroying the associated WebPDemuxer with +// WebPDemuxDelete(). +WEBP_EXTERN(void) WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter); + +//------------------------------------------------------------------------------ + +#if defined(__cplusplus) || defined(c_plusplus) +} // extern "C" +#endif + +#endif /* WEBP_WEBP_DEMUX_H_ */ diff --git a/3rdparty/libwebp/webp/encode.h b/3rdparty/libwebp/webp/encode.h index 2e37cfabe7..726992f570 100644 --- a/3rdparty/libwebp/webp/encode.h +++ b/3rdparty/libwebp/webp/encode.h @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // WebP encoder: main interface @@ -18,7 +20,18 @@ extern "C" { #endif -#define WEBP_ENCODER_ABI_VERSION 0x0200 // MAJOR(8b) + MINOR(8b) +#define WEBP_ENCODER_ABI_VERSION 0x0201 // MAJOR(8b) + MINOR(8b) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPImageHint WebPImageHint; +// typedef enum WebPEncCSP WebPEncCSP; +// typedef enum WebPPreset WebPPreset; +// typedef enum WebPEncodingError WebPEncodingError; +typedef struct WebPConfig WebPConfig; +typedef struct WebPPicture WebPPicture; // main structure for I/O +typedef struct WebPAuxStats WebPAuxStats; +typedef struct WebPMemoryWriter WebPMemoryWriter; // Return the encoder's version number, packed in hexadecimal using 8bits for // each of major/minor/revision. E.g: v2.5.7 is 0x020507. @@ -66,7 +79,7 @@ WEBP_EXTERN(size_t) WebPEncodeLosslessBGRA(const uint8_t* bgra, // Coding parameters // Image characteristics hint for the underlying encoder. -typedef enum { +typedef enum WebPImageHint { WEBP_HINT_DEFAULT = 0, // default preset. WEBP_HINT_PICTURE, // digital picture, like portrait, inner shot WEBP_HINT_PHOTO, // outdoor photograph, with natural lighting @@ -74,7 +87,8 @@ typedef enum { WEBP_HINT_LAST } WebPImageHint; -typedef struct { +// Compression parameters. +struct WebPConfig { int lossless; // Lossless encoding (0=lossy(default), 1=lossless). float quality; // between 0 (smallest file) and 100 (biggest) int method; // quality/speed trade-off (0=fast, 6=slower-better) @@ -109,13 +123,19 @@ typedef struct { int partition_limit; // quality degradation allowed to fit the 512k limit // on prediction modes coding (0: no degradation, // 100: maximum possible degradation). + int emulate_jpeg_size; // If true, compression parameters will be remapped + // to better match the expected output size from + // JPEG compression. Generally, the output size will + // be similar but the degradation will be lower. + int thread_level; // If non-zero, try and use multi-threaded encoding. + int low_memory; // If set, reduce memory usage (but increase CPU use). - uint32_t pad[8]; // padding for later use -} WebPConfig; + uint32_t pad[5]; // padding for later use +}; // Enumerate some predefined settings for WebPConfig, depending on the type // of source picture. These presets are used when calling WebPConfigPreset(). -typedef enum { +typedef enum WebPPreset { WEBP_PRESET_DEFAULT = 0, // default preset. WEBP_PRESET_PICTURE, // digital picture, like portrait, inner shot WEBP_PRESET_PHOTO, // outdoor photograph, with natural lighting @@ -152,11 +172,9 @@ WEBP_EXTERN(int) WebPValidateConfig(const WebPConfig* config); //------------------------------------------------------------------------------ // Input / Output - -typedef struct WebPPicture WebPPicture; // main structure for I/O - // Structure for storing auxiliary statistics (mostly for lossy encoding). -typedef struct { + +struct WebPAuxStats { int coded_size; // final size float PSNR[5]; // peak-signal-to-noise ratio for Y/U/V/All/Alpha @@ -182,7 +200,7 @@ typedef struct { int lossless_size; // final lossless size uint32_t pad[4]; // padding for later use -} WebPAuxStats; +}; // Signature for output function. Should return true if writing was successful. // data/data_size is the segment of data to write, and 'picture' is for @@ -192,18 +210,19 @@ typedef int (*WebPWriterFunction)(const uint8_t* data, size_t data_size, // WebPMemoryWrite: a special WebPWriterFunction that writes to memory using // the following WebPMemoryWriter object (to be set as a custom_ptr). -typedef struct { +struct WebPMemoryWriter { uint8_t* mem; // final buffer (of size 'max_size', larger than 'size'). size_t size; // final size size_t max_size; // total capacity uint32_t pad[1]; // padding for later use -} WebPMemoryWriter; +}; // The following must be called first before any use. WEBP_EXTERN(void) WebPMemoryWriterInit(WebPMemoryWriter* writer); // The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon // completion, writer.mem and writer.size will hold the coded data. +// writer.mem must be freed using the call 'free(writer.mem)'. WEBP_EXTERN(int) WebPMemoryWrite(const uint8_t* data, size_t data_size, const WebPPicture* picture); @@ -212,7 +231,8 @@ WEBP_EXTERN(int) WebPMemoryWrite(const uint8_t* data, size_t data_size, // everything is OK. typedef int (*WebPProgressHook)(int percent, const WebPPicture* picture); -typedef enum { +// Color spaces. +typedef enum WebPEncCSP { // chroma sampling WEBP_YUV420 = 0, // 4:2:0 WEBP_YUV422 = 1, // 4:2:2 @@ -228,7 +248,7 @@ typedef enum { } WebPEncCSP; // Encoding error conditions. -typedef enum { +typedef enum WebPEncodingError { VP8_ENC_OK = 0, VP8_ENC_ERROR_OUT_OF_MEMORY, // memory error allocating objects VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY, // memory error while flushing bits @@ -248,7 +268,6 @@ typedef enum { // Main exchange structure (input samples, output bytes, statistics) struct WebPPicture { - // INPUT ////////////// // Main flag for encoder selecting between ARGB or YUV input. @@ -343,18 +362,19 @@ WEBP_EXTERN(int) WebPPictureAlloc(WebPPicture* picture); // preserved. WEBP_EXTERN(void) WebPPictureFree(WebPPicture* picture); -// Copy the pixels of *src into *dst, using WebPPictureAlloc. Upon return, -// *dst will fully own the copied pixels (this is not a view). +// Copy the pixels of *src into *dst, using WebPPictureAlloc. Upon return, *dst +// will fully own the copied pixels (this is not a view). The 'dst' picture need +// not be initialized as its content is overwritten. // Returns false in case of memory allocation error. WEBP_EXTERN(int) WebPPictureCopy(const WebPPicture* src, WebPPicture* dst); -// Compute PSNR or SSIM distortion between two pictures. +// Compute PSNR, SSIM or LSIM distortion metric between two pictures. // Result is in dB, stores in result[] in the Y/U/V/Alpha/All order. -// Returns false in case of error (pic1 and pic2 don't have same dimension, ...) +// Returns false in case of error (src and ref don't have same dimension, ...) // Warning: this function is rather CPU-intensive. WEBP_EXTERN(int) WebPPictureDistortion( - const WebPPicture* pic1, const WebPPicture* pic2, - int metric_type, // 0 = PSNR, 1 = SSIM + const WebPPicture* src, const WebPPicture* ref, + int metric_type, // 0 = PSNR, 1 = SSIM, 2 = LSIM float result[5]); // self-crops a picture to the rectangle defined by top/left/width/height. @@ -375,7 +395,9 @@ WEBP_EXTERN(int) WebPPictureCrop(WebPPicture* picture, // the top and left coordinates will be snapped to even values. // Picture 'src' must out-live 'dst' picture. Self-extraction of view is allowed // ('src' equal to 'dst') as a mean of fast-cropping (but note that doing so, -// the original dimension will be lost). +// the original dimension will be lost). Picture 'dst' need not be initialized +// with WebPPictureInit() if it is different from 'src', since its content will +// be overwritten. // Returns false in case of memory allocation error or invalid parameters. WEBP_EXTERN(int) WebPPictureView(const WebPPicture* src, int left, int top, int width, int height, diff --git a/3rdparty/libwebp/webp/format_constants.h b/3rdparty/libwebp/webp/format_constants.h index 7ce498f672..4c04b50c6a 100644 --- a/3rdparty/libwebp/webp/format_constants.h +++ b/3rdparty/libwebp/webp/format_constants.h @@ -1,8 +1,10 @@ // Copyright 2012 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Internal header for constants related to WebP file format. @@ -12,6 +14,9 @@ #ifndef WEBP_WEBP_FORMAT_CONSTANTS_H_ #define WEBP_WEBP_FORMAT_CONSTANTS_H_ +// Create fourcc of the chunk from the chunk tag characters. +#define MKFOURCC(a, b, c, d) ((uint32_t)(a) | (b) << 8 | (c) << 16 | (d) << 24) + // VP8 related constants. #define VP8_SIGNATURE 0x9d012a // Signature in VP8 data. #define VP8_MAX_PARTITION0_SIZE (1 << 19) // max size of mode partition @@ -65,23 +70,16 @@ typedef enum { #define CHUNK_SIZE_BYTES 4 // Size needed to store chunk's size. #define CHUNK_HEADER_SIZE 8 // Size of a chunk header. #define RIFF_HEADER_SIZE 12 // Size of the RIFF header ("RIFFnnnnWEBP"). -#define FRAME_CHUNK_SIZE 15 // Size of a FRM chunk. -#define LOOP_CHUNK_SIZE 2 // Size of a LOOP chunk. -#define TILE_CHUNK_SIZE 6 // Size of a TILE chunk. +#define ANMF_CHUNK_SIZE 16 // Size of an ANMF chunk. +#define ANIM_CHUNK_SIZE 6 // Size of an ANIM chunk. +#define FRGM_CHUNK_SIZE 6 // Size of a FRGM chunk. #define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk. -#define TILING_FLAG_BIT 0x01 // Set if tiles are possibly used. -#define ANIMATION_FLAG_BIT 0x02 // Set if some animation is expected -#define ICC_FLAG_BIT 0x04 // Whether ICC is present or not. -#define METADATA_FLAG_BIT 0x08 // Set if some META chunk is possibly present. -#define ALPHA_FLAG_BIT 0x10 // Should be same as the ALPHA_FLAG in mux.h -#define ROTATION_FLAG_BITS 0xe0 // all 3 bits for rotation + symmetry - -#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height. -#define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height. -#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count -#define MAX_DURATION (1 << 24) // maximum duration -#define MAX_POSITION_OFFSET (1 << 24) // maximum frame/tile x/y offset +#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height. +#define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height. +#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count +#define MAX_DURATION (1 << 24) // maximum duration +#define MAX_POSITION_OFFSET (1 << 24) // maximum frame/fragment x/y offset // Maximum chunk payload is such that adding the header and padding won't // overflow a uint32_t. diff --git a/3rdparty/libwebp/webp/mux.h b/3rdparty/libwebp/webp/mux.h index 5139af80fa..b8c7dc62ec 100644 --- a/3rdparty/libwebp/webp/mux.h +++ b/3rdparty/libwebp/webp/mux.h @@ -1,8 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // RIFF container manipulation for WEBP images. @@ -11,7 +13,7 @@ // Vikas (vikasa@google.com) // This API allows manipulation of WebP container images containing features -// like Color profile, XMP metadata, Animation and Tiling. +// like color profile, metadata, animation and fragmented images. // // Code Example#1: Creating a MUX with image data, color profile and XMP // metadata. @@ -21,13 +23,13 @@ // // ... (Prepare image data). // WebPMuxSetImage(mux, &image, copy_data); // // ... (Prepare ICCP color profile data). -// WebPMuxSetColorProfile(mux, &icc_profile, copy_data); +// WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data); // // ... (Prepare XMP metadata). -// WebPMuxSetMetadata(mux, &xmp, copy_data); +// WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data); // // Get data from mux in WebP RIFF format. // WebPMuxAssemble(mux, &output_data); // WebPMuxDelete(mux); -// // ... (Consume output_data; e.g. write output_data.bytes_ to file). +// // ... (Consume output_data; e.g. write output_data.bytes to file). // WebPDataClear(&output_data); // // Code Example#2: Get image and color profile data from a WebP file. @@ -35,9 +37,9 @@ // int copy_data = 0; // // ... (Read data from file). // WebPMux* mux = WebPMuxCreate(&data, copy_data); -// WebPMuxGetImage(mux, &image); +// WebPMuxGetFrame(mux, 1, &image); // // ... (Consume image; e.g. call WebPDecode() to decode the data). -// WebPMuxGetColorProfile(mux, &icc_profile); +// WebPMuxGetChunk(mux, "ICCP", &icc_profile); // // ... (Consume icc_data). // WebPMuxDelete(mux); // free(data); @@ -45,7 +47,7 @@ #ifndef WEBP_WEBP_MUX_H_ #define WEBP_WEBP_MUX_H_ -#include "./types.h" +#include "./mux_types.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { @@ -53,8 +55,16 @@ extern "C" { #define WEBP_MUX_ABI_VERSION 0x0100 // MAJOR(8b) + MINOR(8b) +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPMuxError WebPMuxError; +// typedef enum WebPChunkId WebPChunkId; +typedef struct WebPMux WebPMux; // main opaque object. +typedef struct WebPMuxFrameInfo WebPMuxFrameInfo; +typedef struct WebPMuxAnimParams WebPMuxAnimParams; + // Error codes -typedef enum { +typedef enum WebPMuxError { WEBP_MUX_OK = 1, WEBP_MUX_NOT_FOUND = 0, WEBP_MUX_INVALID_ARGUMENT = -1, @@ -63,51 +73,26 @@ typedef enum { WEBP_MUX_NOT_ENOUGH_DATA = -4 } WebPMuxError; -// Flag values for different features used in VP8X chunk. -typedef enum { - TILE_FLAG = 0x00000001, - ANIMATION_FLAG = 0x00000002, - ICCP_FLAG = 0x00000004, - META_FLAG = 0x00000008, - ALPHA_FLAG = 0x00000010 -} WebPFeatureFlags; - // IDs for different types of chunks. -typedef enum { +typedef enum WebPChunkId { WEBP_CHUNK_VP8X, // VP8X WEBP_CHUNK_ICCP, // ICCP - WEBP_CHUNK_LOOP, // LOOP - WEBP_CHUNK_FRAME, // FRM - WEBP_CHUNK_TILE, // TILE + WEBP_CHUNK_ANIM, // ANIM + WEBP_CHUNK_ANMF, // ANMF + WEBP_CHUNK_FRGM, // FRGM WEBP_CHUNK_ALPHA, // ALPH WEBP_CHUNK_IMAGE, // VP8/VP8L - WEBP_CHUNK_META, // META + WEBP_CHUNK_EXIF, // EXIF + WEBP_CHUNK_XMP, // XMP WEBP_CHUNK_UNKNOWN, // Other chunks. WEBP_CHUNK_NIL } WebPChunkId; -typedef struct WebPMux WebPMux; // main opaque object. - -// Data type used to describe 'raw' data, e.g., chunk data -// (ICC profile, metadata) and WebP compressed image data. -typedef struct { - const uint8_t* bytes_; - size_t size_; -} WebPData; - //------------------------------------------------------------------------------ -// Manipulation of a WebPData object. -// Initializes the contents of the 'webp_data' object with default values. -WEBP_EXTERN(void) WebPDataInit(WebPData* webp_data); - -// Clears the contents of the 'webp_data' object by calling free(). Does not -// deallocate the object itself. -WEBP_EXTERN(void) WebPDataClear(WebPData* webp_data); - -// Allocates necessary storage for 'dst' and copies the contents of 'src'. -// Returns true on success. -WEBP_EXTERN(int) WebPDataCopy(const WebPData* src, WebPData* dst); +// Returns the version number of the mux library, packed in hexadecimal using +// 8bits or each of major/minor/revision. E.g: v2.5.7 is 0x020507. +WEBP_EXTERN(int) WebPGetMuxVersion(void); //------------------------------------------------------------------------------ // Life of a Mux object @@ -136,8 +121,8 @@ WEBP_EXTERN(WebPMux*) WebPMuxCreateInternal(const WebPData*, int, int); // Creates a mux object from raw data given in WebP RIFF format. // Parameters: // bitstream - (in) the bitstream data in WebP RIFF format -// copy_data - (in) value 1 indicates given data WILL copied to the mux, and -// value 0 indicates data will NOT be copied. +// copy_data - (in) value 1 indicates given data WILL be copied to the mux +// and value 0 indicates data will NOT be copied. // Returns: // A pointer to the mux object created from given data - on success. // NULL - In case of invalid data or memory error. @@ -147,270 +132,175 @@ static WEBP_INLINE WebPMux* WebPMuxCreate(const WebPData* bitstream, } //------------------------------------------------------------------------------ -// Single Image. +// Non-image chunks. -// Sets the image in the mux object. Any existing images (including frame/tile) -// will be removed. +// Note: Only non-image related chunks should be managed through chunk APIs. +// (Image related chunks are: "ANMF", "FRGM", "VP8 ", "VP8L" and "ALPH"). +// To add, get and delete images, use APIs WebPMuxSetImage(), +// WebPMuxPushFrame(), WebPMuxGetFrame() and WebPMuxDeleteFrame(). + +// Adds a chunk with id 'fourcc' and data 'chunk_data' in the mux object. +// Any existing chunk(s) with the same id will be removed. +// Parameters: +// mux - (in/out) object to which the chunk is to be added +// fourcc - (in) a character array containing the fourcc of the given chunk; +// e.g., "ICCP", "XMP ", "EXIF" etc. +// chunk_data - (in) the chunk data to be added +// copy_data - (in) value 1 indicates given data WILL be copied to the mux +// and value 0 indicates data will NOT be copied. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL +// or if fourcc corresponds to an image chunk. +// WEBP_MUX_MEMORY_ERROR - on memory allocation error. +// WEBP_MUX_OK - on success. +WEBP_EXTERN(WebPMuxError) WebPMuxSetChunk( + WebPMux* mux, const char fourcc[4], const WebPData* chunk_data, + int copy_data); + +// Gets a reference to the data of the chunk with id 'fourcc' in the mux object. +// The caller should NOT free the returned data. +// Parameters: +// mux - (in) object from which the chunk data is to be fetched +// fourcc - (in) a character array containing the fourcc of the chunk; +// e.g., "ICCP", "XMP ", "EXIF" etc. +// chunk_data - (out) returned chunk data +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if either mux, fourcc or chunk_data is NULL +// or if fourcc corresponds to an image chunk. +// WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given id. +// WEBP_MUX_OK - on success. +WEBP_EXTERN(WebPMuxError) WebPMuxGetChunk( + const WebPMux* mux, const char fourcc[4], WebPData* chunk_data); + +// Deletes the chunk with the given 'fourcc' from the mux object. +// Parameters: +// mux - (in/out) object from which the chunk is to be deleted +// fourcc - (in) a character array containing the fourcc of the chunk; +// e.g., "ICCP", "XMP ", "EXIF" etc. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux or fourcc is NULL +// or if fourcc corresponds to an image chunk. +// WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given fourcc. +// WEBP_MUX_OK - on success. +WEBP_EXTERN(WebPMuxError) WebPMuxDeleteChunk( + WebPMux* mux, const char fourcc[4]); + +//------------------------------------------------------------------------------ +// Images. + +// Encapsulates data about a single frame/fragment. +struct WebPMuxFrameInfo { + WebPData bitstream; // image data: can either be a raw VP8/VP8L bitstream + // or a single-image WebP file. + int x_offset; // x-offset of the frame. + int y_offset; // y-offset of the frame. + int duration; // duration of the frame (in milliseconds). + + WebPChunkId id; // frame type: should be one of WEBP_CHUNK_ANMF, + // WEBP_CHUNK_FRGM or WEBP_CHUNK_IMAGE + WebPMuxAnimDispose dispose_method; // Disposal method for the frame. + uint32_t pad[2]; // padding for later use +}; + +// Sets the (non-animated and non-fragmented) image in the mux object. +// Note: Any existing images (including frames/fragments) will be removed. // Parameters: // mux - (in/out) object in which the image is to be set // bitstream - (in) can either be a raw VP8/VP8L bitstream or a single-image -// WebP file (non-animated and non-tiled) -// copy_data - (in) value 1 indicates given data WILL copied to the mux, and -// value 0 indicates data will NOT be copied. +// WebP file (non-animated and non-fragmented) +// copy_data - (in) value 1 indicates given data WILL be copied to the mux +// and value 0 indicates data will NOT be copied. // Returns: // WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL. // WEBP_MUX_MEMORY_ERROR - on memory allocation error. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxSetImage(WebPMux* mux, - const WebPData* bitstream, - int copy_data); +WEBP_EXTERN(WebPMuxError) WebPMuxSetImage( + WebPMux* mux, const WebPData* bitstream, int copy_data); -// Gets image data from the mux object. -// The content of 'bitstream' is allocated using malloc(), and NOT -// owned by the 'mux' object. It MUST be deallocated by the caller by calling -// WebPDataClear(). +// Adds a frame at the end of the mux object. +// Notes: (1) frame.id should be one of WEBP_CHUNK_ANMF or WEBP_CHUNK_FRGM +// (2) For setting a non-animated non-fragmented image, use +// WebPMuxSetImage() instead. +// (3) Type of frame being pushed must be same as the frames in mux. +// (4) As WebP only supports even offsets, any odd offset will be snapped +// to an even location using: offset &= ~1 // Parameters: -// mux - (in) object from which the image is to be fetched -// bitstream - (out) the image data +// mux - (in/out) object to which the frame is to be added +// frame - (in) frame data. +// copy_data - (in) value 1 indicates given data WILL be copied to the mux +// and value 0 indicates data will NOT be copied. // Returns: -// WEBP_MUX_INVALID_ARGUMENT - if either mux or bitstream is NULL -// OR mux contains animation/tiling. -// WEBP_MUX_NOT_FOUND - if image is not present in mux object. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetImage(const WebPMux* mux, - WebPData* bitstream); - -// Deletes the image in the mux object. -// Parameters: -// mux - (in/out) object from which the image is to be deleted -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL -// OR if mux contains animation/tiling. -// WEBP_MUX_NOT_FOUND - if image is not present in mux object. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxDeleteImage(WebPMux* mux); - -//------------------------------------------------------------------------------ -// XMP Metadata. - -// Sets the XMP metadata in the mux object. Any existing metadata chunk(s) will -// be removed. -// Parameters: -// mux - (in/out) object to which the XMP metadata is to be added -// metadata - (in) the XMP metadata data to be added -// copy_data - (in) value 1 indicates given data WILL copied to the mux, and -// value 0 indicates data will NOT be copied. -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux or metadata is NULL. -// WEBP_MUX_MEMORY_ERROR - on memory allocation error. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxSetMetadata(WebPMux* mux, - const WebPData* metadata, - int copy_data); - -// Gets a reference to the XMP metadata in the mux object. -// The caller should NOT free the returned data. -// Parameters: -// mux - (in) object from which the XMP metadata is to be fetched -// metadata - (out) XMP metadata -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if either mux or metadata is NULL. -// WEBP_MUX_NOT_FOUND - if metadata is not present in mux object. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetMetadata(const WebPMux* mux, - WebPData* metadata); - -// Deletes the XMP metadata in the mux object. -// Parameters: -// mux - (in/out) object from which XMP metadata is to be deleted -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL -// WEBP_MUX_NOT_FOUND - If mux does not contain metadata. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxDeleteMetadata(WebPMux* mux); - -//------------------------------------------------------------------------------ -// ICC Color Profile. - -// Sets the color profile in the mux object. Any existing color profile chunk(s) -// will be removed. -// Parameters: -// mux - (in/out) object to which the color profile is to be added -// color_profile - (in) the color profile data to be added -// copy_data - (in) value 1 indicates given data WILL copied to the mux, and -// value 0 indicates data will NOT be copied. -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux or color_profile is NULL -// WEBP_MUX_MEMORY_ERROR - on memory allocation error -// WEBP_MUX_OK - on success -WEBP_EXTERN(WebPMuxError) WebPMuxSetColorProfile(WebPMux* mux, - const WebPData* color_profile, - int copy_data); - -// Gets a reference to the color profile in the mux object. -// The caller should NOT free the returned data. -// Parameters: -// mux - (in) object from which the color profile data is to be fetched -// color_profile - (out) color profile data -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if either mux or color_profile is NULL. -// WEBP_MUX_NOT_FOUND - if color profile is not present in mux object. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetColorProfile(const WebPMux* mux, - WebPData* color_profile); - -// Deletes the color profile in the mux object. -// Parameters: -// mux - (in/out) object from which color profile is to be deleted -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL -// WEBP_MUX_NOT_FOUND - If mux does not contain color profile. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxDeleteColorProfile(WebPMux* mux); - -//------------------------------------------------------------------------------ -// Animation. - -// Adds an animation frame at the end of the mux object. -// Note: as WebP only supports even offsets, any odd offset will be snapped to -// an even location using: offset &= ~1 -// Parameters: -// mux - (in/out) object to which an animation frame is to be added -// bitstream - (in) the image data corresponding to the frame. It can either -// be a raw VP8/VP8L bitstream or a single-image WebP file -// (non-animated and non-tiled) -// x_offset - (in) x-offset of the frame to be added -// y_offset - (in) y-offset of the frame to be added -// duration - (in) duration of the frame to be added (in milliseconds) -// copy_data - (in) value 1 indicates given data WILL copied to the mux, and -// value 0 indicates data will NOT be copied. -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL +// WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL +// or if content of 'frame' is invalid. // WEBP_MUX_MEMORY_ERROR - on memory allocation error. // WEBP_MUX_OK - on success. WEBP_EXTERN(WebPMuxError) WebPMuxPushFrame( - WebPMux* mux, const WebPData* bitstream, - int x_offset, int y_offset, int duration, int copy_data); + WebPMux* mux, const WebPMuxFrameInfo* frame, int copy_data); -// TODO(urvang): Create a struct as follows to reduce argument list size: -// typedef struct { -// WebPData bitstream; -// int x_offset, y_offset; -// int duration; -// } FrameInfo; - -// Gets the nth animation frame from the mux object. -// The content of 'bitstream' is allocated using malloc(), and NOT +// Gets the nth frame from the mux object. +// The content of 'frame->bitstream' is allocated using malloc(), and NOT // owned by the 'mux' object. It MUST be deallocated by the caller by calling // WebPDataClear(). // nth=0 has a special meaning - last position. // Parameters: // mux - (in) object from which the info is to be fetched // nth - (in) index of the frame in the mux object -// bitstream - (out) the image data -// x_offset - (out) x-offset of the returned frame -// y_offset - (out) y-offset of the returned frame -// duration - (out) duration of the returned frame (in milliseconds) +// frame - (out) data of the returned frame // Returns: -// WEBP_MUX_INVALID_ARGUMENT - if either mux, bitstream, x_offset, -// y_offset, or duration is NULL +// WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL. // WEBP_MUX_NOT_FOUND - if there are less than nth frames in the mux object. // WEBP_MUX_BAD_DATA - if nth frame chunk in mux is invalid. // WEBP_MUX_OK - on success. WEBP_EXTERN(WebPMuxError) WebPMuxGetFrame( - const WebPMux* mux, uint32_t nth, WebPData* bitstream, - int* x_offset, int* y_offset, int* duration); + const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame); -// Deletes an animation frame from the mux object. +// Deletes a frame from the mux object. // nth=0 has a special meaning - last position. // Parameters: // mux - (in/out) object from which a frame is to be deleted // nth - (in) The position from which the frame is to be deleted // Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL +// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL. // WEBP_MUX_NOT_FOUND - If there are less than nth frames in the mux object // before deletion. // WEBP_MUX_OK - on success. WEBP_EXTERN(WebPMuxError) WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth); -// Sets the animation loop count in the mux object. Any existing loop count -// value(s) will be removed. -// Parameters: -// mux - (in/out) object in which loop chunk is to be set/added -// loop_count - (in) animation loop count value. -// Note that loop_count of zero denotes infinite loop. -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL -// WEBP_MUX_MEMORY_ERROR - on memory allocation error. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxSetLoopCount(WebPMux* mux, int loop_count); - -// Gets the animation loop count from the mux object. -// Parameters: -// mux - (in) object from which the loop count is to be fetched -// loop_count - (out) the loop_count value present in the LOOP chunk -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if either of mux or loop_count is NULL -// WEBP_MUX_NOT_FOUND - if loop chunk is not present in mux object. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetLoopCount(const WebPMux* mux, - int* loop_count); - //------------------------------------------------------------------------------ -// Tiling. +// Animation. -// Adds a tile at the end of the mux object. -// Note: as WebP only supports even offsets, any odd offset will be snapped to -// an even location using: offset &= ~1 +// Animation parameters. +struct WebPMuxAnimParams { + uint32_t bgcolor; // Background color of the canvas stored (in MSB order) as: + // Bits 00 to 07: Alpha. + // Bits 08 to 15: Red. + // Bits 16 to 23: Green. + // Bits 24 to 31: Blue. + int loop_count; // Number of times to repeat the animation [0 = infinite]. +}; + +// Sets the animation parameters in the mux object. Any existing ANIM chunks +// will be removed. // Parameters: -// mux - (in/out) object to which a tile is to be added. -// bitstream - (in) the image data corresponding to the frame. It can either -// be a raw VP8/VP8L bitstream or a single-image WebP file -// (non-animated and non-tiled) -// x_offset - (in) x-offset of the tile to be added -// y_offset - (in) y-offset of the tile to be added -// copy_data - (in) value 1 indicates given data WILL copied to the mux, and -// value 0 indicates data will NOT be copied. +// mux - (in/out) object in which ANIM chunk is to be set/added +// params - (in) animation parameters. // Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL +// WEBP_MUX_INVALID_ARGUMENT - if either mux or params is NULL // WEBP_MUX_MEMORY_ERROR - on memory allocation error. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxPushTile( - WebPMux* mux, const WebPData* bitstream, - int x_offset, int y_offset, int copy_data); +WEBP_EXTERN(WebPMuxError) WebPMuxSetAnimationParams( + WebPMux* mux, const WebPMuxAnimParams* params); -// Gets the nth tile from the mux object. -// The content of 'bitstream' is allocated using malloc(), and NOT -// owned by the 'mux' object. It MUST be deallocated by the caller by calling -// WebPDataClear(). -// nth=0 has a special meaning - last position. +// Gets the animation parameters from the mux object. // Parameters: -// mux - (in) object from which the info is to be fetched -// nth - (in) index of the tile in the mux object -// bitstream - (out) the image data -// x_offset - (out) x-offset of the returned tile -// y_offset - (out) y-offset of the returned tile +// mux - (in) object from which the animation parameters to be fetched +// params - (out) animation parameters extracted from the ANIM chunk // Returns: -// WEBP_MUX_INVALID_ARGUMENT - if either mux, bitstream, x_offset or -// y_offset is NULL -// WEBP_MUX_NOT_FOUND - if there are less than nth tiles in the mux object. -// WEBP_MUX_BAD_DATA - if nth tile chunk in mux is invalid. +// WEBP_MUX_INVALID_ARGUMENT - if either of mux or params is NULL +// WEBP_MUX_NOT_FOUND - if ANIM chunk is not present in mux object. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetTile( - const WebPMux* mux, uint32_t nth, WebPData* bitstream, - int* x_offset, int* y_offset); - -// Deletes a tile from the mux object. -// nth=0 has a special meaning - last position -// Parameters: -// mux - (in/out) object from which a tile is to be deleted -// nth - (in) The position from which the tile is to be deleted -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL -// WEBP_MUX_NOT_FOUND - If there are less than nth tiles in the mux object -// before deletion. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxDeleteTile(WebPMux* mux, uint32_t nth); +WEBP_EXTERN(WebPMuxError) WebPMuxGetAnimationParams( + const WebPMux* mux, WebPMuxAnimParams* params); //------------------------------------------------------------------------------ // Misc Utilities. @@ -458,143 +348,6 @@ WEBP_EXTERN(WebPMuxError) WebPMuxNumChunks(const WebPMux* mux, WEBP_EXTERN(WebPMuxError) WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data); -//------------------------------------------------------------------------------ -// Demux API. -// Enables extraction of image and extended format data from WebP files. - -#define WEBP_DEMUX_ABI_VERSION 0x0100 // MAJOR(8b) + MINOR(8b) - -typedef struct WebPDemuxer WebPDemuxer; - -typedef enum { - WEBP_DEMUX_PARSING_HEADER, // Not enough data to parse full header. - WEBP_DEMUX_PARSED_HEADER, // Header parsing complete, data may be available. - WEBP_DEMUX_DONE // Entire file has been parsed. -} WebPDemuxState; - -//------------------------------------------------------------------------------ -// Life of a Demux object - -// Internal, version-checked, entry point -WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal( - const WebPData*, int, WebPDemuxState*, int); - -// Parses the WebP file given by 'data'. -// A complete WebP file must be present in 'data' for the function to succeed. -// Returns a WebPDemuxer object on successful parse, NULL otherwise. -static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) { - return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION); -} - -// Parses the WebP file given by 'data'. -// If 'state' is non-NULL it will be set to indicate the status of the demuxer. -// Returns a WebPDemuxer object on successful parse, NULL otherwise. -static WEBP_INLINE WebPDemuxer* WebPDemuxPartial( - const WebPData* data, WebPDemuxState* state) { - return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION); -} - -// Frees memory associated with 'dmux'. -WEBP_EXTERN(void) WebPDemuxDelete(WebPDemuxer* dmux); - -//------------------------------------------------------------------------------ -// Data/information extraction. - -typedef enum { - WEBP_FF_FORMAT_FLAGS, // Extended format flags present in the 'VP8X' chunk. - WEBP_FF_CANVAS_WIDTH, - WEBP_FF_CANVAS_HEIGHT, - WEBP_FF_LOOP_COUNT -} WebPFormatFeature; - -// Get the 'feature' value from the 'dmux'. -// NOTE: values are only valid if WebPDemux() was used or WebPDemuxPartial() -// returned a state > WEBP_DEMUX_PARSING_HEADER. -WEBP_EXTERN(uint32_t) WebPDemuxGetI( - const WebPDemuxer* dmux, WebPFormatFeature feature); - -//------------------------------------------------------------------------------ -// Frame iteration. - -typedef struct { - int frame_num_; - int num_frames_; - int tile_num_; - int num_tiles_; - int x_offset_, y_offset_; // offset relative to the canvas. - int width_, height_; // dimensions of this frame or tile. - int duration_; // display duration in milliseconds. - int complete_; // true if 'tile_' contains a full frame. partial images may - // still be decoded with the WebP incremental decoder. - WebPData tile_; // The frame or tile given by 'frame_num_' and 'tile_num_'. - - uint32_t pad[4]; // padding for later use - void* private_; -} WebPIterator; - -// Retrieves frame 'frame_number' from 'dmux'. -// 'iter->tile_' points to the first tile on return from this function. -// Individual tiles may be extracted using WebPDemuxSetTile(). -// Setting 'frame_number' equal to 0 will return the last frame of the image. -// Returns false if 'dmux' is NULL or frame 'frame_number' is not present. -// Call WebPDemuxReleaseIterator() when use of the iterator is complete. -// NOTE: 'dmux' must persist for the lifetime of 'iter'. -WEBP_EXTERN(int) WebPDemuxGetFrame( - const WebPDemuxer* dmux, int frame_number, WebPIterator* iter); - -// Sets 'iter->tile_' to point to the next ('iter->frame_num_' + 1) or previous -// ('iter->frame_num_' - 1) frame. These functions do not loop. -// Returns true on success, false otherwise. -WEBP_EXTERN(int) WebPDemuxNextFrame(WebPIterator* iter); -WEBP_EXTERN(int) WebPDemuxPrevFrame(WebPIterator* iter); - -// Sets 'iter->tile_' to reflect tile number 'tile_number'. -// Returns true if tile 'tile_number' is present, false otherwise. -WEBP_EXTERN(int) WebPDemuxSelectTile(WebPIterator* iter, int tile_number); - -// Releases any memory associated with 'iter'. -// Must be called before destroying the associated WebPDemuxer with -// WebPDemuxDelete(). -WEBP_EXTERN(void) WebPDemuxReleaseIterator(WebPIterator* iter); - -//------------------------------------------------------------------------------ -// Chunk iteration. - -typedef struct { - // The current and total number of chunks with the fourcc given to - // WebPDemuxGetChunk(). - int chunk_num_; - int num_chunks_; - WebPData chunk_; // The payload of the chunk. - - uint32_t pad[6]; // padding for later use - void* private_; -} WebPChunkIterator; - -// Retrieves the 'chunk_number' instance of the chunk with id 'fourcc' from -// 'dmux'. -// 'fourcc' is a character array containing the fourcc of the chunk to return, -// e.g., "ICCP", "META", "EXIF", etc. -// Setting 'chunk_number' equal to 0 will return the last chunk in a set. -// Returns true if the chunk is found, false otherwise. Image related chunk -// payloads are accessed through WebPDemuxGetFrame() and related functions. -// Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete. -// NOTE: 'dmux' must persist for the lifetime of the iterator. -WEBP_EXTERN(int) WebPDemuxGetChunk(const WebPDemuxer* dmux, - const char fourcc[4], int chunk_number, - WebPChunkIterator* iter); - -// Sets 'iter->chunk_' to point to the next ('iter->chunk_num_' + 1) or previous -// ('iter->chunk_num_' - 1) chunk. These functions do not loop. -// Returns true on success, false otherwise. -WEBP_EXTERN(int) WebPDemuxNextChunk(WebPChunkIterator* iter); -WEBP_EXTERN(int) WebPDemuxPrevChunk(WebPChunkIterator* iter); - -// Releases any memory associated with 'iter'. -// Must be called before destroying the associated WebPDemuxer with -// WebPDemuxDelete(). -WEBP_EXTERN(void) WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter); - //------------------------------------------------------------------------------ #if defined(__cplusplus) || defined(c_plusplus) diff --git a/3rdparty/libwebp/webp/mux_types.h b/3rdparty/libwebp/webp/mux_types.h new file mode 100644 index 0000000000..b8bce363e5 --- /dev/null +++ b/3rdparty/libwebp/webp/mux_types.h @@ -0,0 +1,89 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Data-types common to the mux and demux libraries. +// +// Author: Urvang (urvang@google.com) + +#ifndef WEBP_WEBP_MUX_TYPES_H_ +#define WEBP_WEBP_MUX_TYPES_H_ + +#include // free() +#include // memset() +#include "./types.h" + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPFeatureFlags WebPFeatureFlags; +// typedef enum WebPMuxAnimDispose WebPMuxAnimDispose; +typedef struct WebPData WebPData; + +// VP8X Feature Flags. +typedef enum WebPFeatureFlags { + FRAGMENTS_FLAG = 0x00000001, + ANIMATION_FLAG = 0x00000002, + XMP_FLAG = 0x00000004, + EXIF_FLAG = 0x00000008, + ALPHA_FLAG = 0x00000010, + ICCP_FLAG = 0x00000020 +} WebPFeatureFlags; + +// Dispose method (animation only). Indicates how the area used by the current +// frame is to be treated before rendering the next frame on the canvas. +typedef enum WebPMuxAnimDispose { + WEBP_MUX_DISPOSE_NONE, // Do not dispose. + WEBP_MUX_DISPOSE_BACKGROUND // Dispose to background color. +} WebPMuxAnimDispose; + +// Data type used to describe 'raw' data, e.g., chunk data +// (ICC profile, metadata) and WebP compressed image data. +struct WebPData { + const uint8_t* bytes; + size_t size; +}; + +// Initializes the contents of the 'webp_data' object with default values. +static WEBP_INLINE void WebPDataInit(WebPData* webp_data) { + if (webp_data != NULL) { + memset(webp_data, 0, sizeof(*webp_data)); + } +} + +// Clears the contents of the 'webp_data' object by calling free(). Does not +// deallocate the object itself. +static WEBP_INLINE void WebPDataClear(WebPData* webp_data) { + if (webp_data != NULL) { + free((void*)webp_data->bytes); + WebPDataInit(webp_data); + } +} + +// Allocates necessary storage for 'dst' and copies the contents of 'src'. +// Returns true on success. +static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) { + if (src == NULL || dst == NULL) return 0; + WebPDataInit(dst); + if (src->bytes != NULL && src->size != 0) { + dst->bytes = (uint8_t*)malloc(src->size); + if (dst->bytes == NULL) return 0; + memcpy((void*)dst->bytes, src->bytes, src->size); + dst->size = src->size; + } + return 1; +} + +#if defined(__cplusplus) || defined(c_plusplus) +} // extern "C" +#endif + +#endif /* WEBP_WEBP_MUX_TYPES_H_ */ diff --git a/3rdparty/libwebp/webp/types.h b/3rdparty/libwebp/webp/types.h index 3e27190bef..568d1f263f 100644 --- a/3rdparty/libwebp/webp/types.h +++ b/3rdparty/libwebp/webp/types.h @@ -1,8 +1,10 @@ // Copyright 2010 Google Inc. All Rights Reserved. // -// This code is licensed under the same terms as WebM: -// Software License Agreement: http://www.webmproject.org/license/software/ -// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Common types diff --git a/3rdparty/openexr/CMakeLists.txt b/3rdparty/openexr/CMakeLists.txt index a77a6e1326..e10b940079 100644 --- a/3rdparty/openexr/CMakeLists.txt +++ b/3rdparty/openexr/CMakeLists.txt @@ -22,12 +22,14 @@ set(OPENEXR_INCLUDE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/Half" "${CMAKE_CURRENT_SOURCE_DIR}/Imath" "${CMAKE_CURRENT_SOURCE_DIR}/IlmImf") -ocv_include_directories("${CMAKE_CURRENT_BINARY_DIR}" ${ZLIB_INCLUDE_DIR} ${OPENEXR_INCLUDE_PATHS}) +ocv_include_directories("${CMAKE_CURRENT_BINARY_DIR}" ${ZLIB_INCLUDE_DIRS} ${OPENEXR_INCLUDE_PATHS}) file(GLOB lib_srcs Half/half.cpp Iex/*.cpp IlmThread/*.cpp Imath/*.cpp IlmImf/*.cpp) file(GLOB lib_hdrs Half/*.h Iex/Iex*.h IlmThread/IlmThread*.h Imath/Imath*.h IlmImf/*.h) list(APPEND lib_hdrs "${CMAKE_CURRENT_BINARY_DIR}/IlmBaseConfig.h" "${CMAKE_CURRENT_BINARY_DIR}/OpenEXRConfig.h") +ocv_list_filterout(lib_srcs IlmImf/b44ExpLogTable.cpp) + if(WIN32) ocv_list_filterout(lib_srcs Posix.*cpp) else() diff --git a/3rdparty/tbb/.gitignore b/3rdparty/tbb/.gitignore index 601e1b265e..69ce9ceb9c 100644 --- a/3rdparty/tbb/.gitignore +++ b/3rdparty/tbb/.gitignore @@ -1 +1 @@ -tbb*.tgz \ No newline at end of file +tbb*.tgz diff --git a/3rdparty/tbb/CMakeLists.txt b/3rdparty/tbb/CMakeLists.txt index 3c6ae98f45..4e510ffa32 100644 --- a/3rdparty/tbb/CMakeLists.txt +++ b/3rdparty/tbb/CMakeLists.txt @@ -1,12 +1,39 @@ #Cross compile TBB from source project(tbb) +if (WIN32 AND NOT ARM) + message(FATAL_ERROR "BUILD_TBB option supports Windows on ARM only!\nUse regular official TBB build instead of the BUILD_TBB option!") +endif() + +if (WIN32 AND ARM) + # 4.1 update 4 - The first release that supports Windows RT. Hangs on some Android devices + set(tbb_ver "tbb41_20130613oss") + set(tbb_url "http://threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb41_20130613oss_src.tgz") + set(tbb_md5 "108c8c1e481b0aaea61878289eb28b6a") + set(tbb_version_file "version_string.ver") + ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4702) +else() + # 4.1 update 2 - works fine + set(tbb_ver "tbb41_20130116oss") + set(tbb_url "http://threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb41_20130116oss_src.tgz") + set(tbb_md5 "3809790e1001a1b32d59c9fee590ee85") + set(tbb_version_file "version_string.ver") + ocv_warnings_disable(CMAKE_CXX_FLAGS -Wshadow) +endif() + +# 4.1 update 3 dev - Hangs on some Android devices +#set(tbb_ver "tbb41_20130401oss") +#set(tbb_url "http://threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb41_20130401oss_src.tgz") +#set(tbb_md5 "f2f591a0d2ca8f801e221ce7d9ea84bb") +#set(tbb_version_file "version_string.ver") +#ocv_warnings_disable(CMAKE_CXX_FLAGS -Wshadow) + # 4.1 update 2 - works fine -set(tbb_ver "tbb41_20130116oss") -set(tbb_url "http://threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb41_20130116oss_src.tgz") -set(tbb_md5 "3809790e1001a1b32d59c9fee590ee85") -set(tbb_version_file "version_string.ver") -ocv_warnings_disable(CMAKE_CXX_FLAGS -Wshadow) +#set(tbb_ver "tbb41_20130116oss") +#set(tbb_url "http://threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb41_20130116oss_src.tgz") +#set(tbb_md5 "3809790e1001a1b32d59c9fee590ee85") +#set(tbb_version_file "version_string.ver") +#ocv_warnings_disable(CMAKE_CXX_FLAGS -Wshadow) # 4.1 update 1 - works fine #set(tbb_ver "tbb41_20121003oss") @@ -55,24 +82,8 @@ ocv_warnings_disable(CMAKE_CXX_FLAGS -Wshadow) set(tbb_tarball "${CMAKE_CURRENT_SOURCE_DIR}/${tbb_ver}_src.tgz") set(tbb_src_dir "${CMAKE_CURRENT_BINARY_DIR}/${tbb_ver}") -macro(getMD5 filename varname) - if(CMAKE_VERSION VERSION_GREATER 2.8.6) - file(MD5 "${filename}" ${varname}) - else() - execute_process(COMMAND ${CMAKE_COMMAND} -E md5sum "${filename}" - RESULT_VARIABLE getMD5_RESULT - OUTPUT_VARIABLE getMD5_OUTPUT - OUTPUT_STRIP_TRAILING_WHITESPACE) - if(getMD5_RESULT EQUAL 0) - string(REGEX MATCH "^[a-z0-9]+" ${varname} "${getMD5_OUTPUT}") - else() - set(${varname} "invalid_md5") - endif() - endif() -endmacro() - if(EXISTS "${tbb_tarball}") - getMD5("${tbb_tarball}" tbb_local_md5) + file(MD5 "${tbb_tarball}" tbb_local_md5) if(NOT tbb_local_md5 STREQUAL tbb_md5) message(WARNING "Local copy of TBB source tarball has invalid MD5 hash: ${tbb_local_md5} (expected: ${tbb_md5})") file(REMOVE "${tbb_tarball}") @@ -88,7 +99,7 @@ if(NOT EXISTS "${tbb_tarball}") if(NOT __statvar EQUAL 0) message(FATAL_ERROR "Failed to download TBB sources: ${tbb_url}") endif() - getMD5("${tbb_tarball}" tbb_local_md5) + file(MD5 "${tbb_tarball}" tbb_local_md5) if(NOT tbb_local_md5 STREQUAL tbb_md5) file(REMOVE "${tbb_tarball}") message(FATAL_ERROR "Downloaded TBB source tarball has invalid MD5 hash: ${tbb_local_md5} (expected: ${tbb_md5})") @@ -107,7 +118,7 @@ if(NOT EXISTS "${tbb_src_dir}") RESULT_VARIABLE tbb_untar_RESULT) if(NOT tbb_untar_RESULT EQUAL 0 OR NOT EXISTS "${tbb_src_dir}") - message(FATAL_ERROR "Failed to unpack TBB sources") + message(FATAL_ERROR "Failed to unpack TBB sources from ${tbb_tarball} to ${tbb_src_dir} with error ${tbb_untar_RESULT}") endif() endif() @@ -122,15 +133,41 @@ file(GLOB lib_srcs "${tbb_src_dir}/src/tbb/*.cpp") file(GLOB lib_hdrs "${tbb_src_dir}/src/tbb/*.h") list(APPEND lib_srcs "${tbb_src_dir}/src/rml/client/rml_tbb.cpp") -add_definitions(-D__TBB_DYNAMIC_LOAD_ENABLED=0 #required - -D__TBB_BUILD=1 #required - -D__TBB_SURVIVE_THREAD_SWITCH=0 #no cilk support - -DUSE_PTHREAD #required for Unix - -DTBB_USE_GCC_BUILTINS=1 #required for ARM GCC - -DTBB_USE_DEBUG=0 #just to be sure - -DTBB_NO_LEGACY=1 #don't need backward compatibility - -DDO_ITT_NOTIFY=0 #it seems that we don't need these notifications - ) +if (WIN32) + add_definitions(/D__TBB_DYNAMIC_LOAD_ENABLED=0 + /D__TBB_BUILD=1 + /DTBB_NO_LEGACY=1 + /D_UNICODE + /DUNICODE + /DWINAPI_FAMILY=WINAPI_FAMILY_APP + /DDO_ITT_NOTIFY=0 + /DUSE_WINTHREAD + ) # defines were copied from windows.cl.inc + + if (ARM) + add_definitions(/D_WIN32_WINNT=0x0602 + /D__TBB_WIN32_USE_CL_BUILTINS + ) + endif() + +set(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} /APPCONTAINER") +else() + add_definitions(-D__TBB_DYNAMIC_LOAD_ENABLED=0 #required + -D__TBB_BUILD=1 #required + -D__TBB_SURVIVE_THREAD_SWITCH=0 #no cilk support + -DTBB_USE_DEBUG=0 #just to be sure + -DTBB_NO_LEGACY=1 #don't need backward compatibility + -DDO_ITT_NOTIFY=0 #it seems that we don't need these notifications + ) +endif() + +if (HAVE_LIBPTHREAD) + add_definitions(-DUSE_PTHREAD) #required for Unix +endif() + +if (CMAKE_COMPILER_IS_GNUCXX) + add_definitions(-DTBB_USE_GCC_BUILTINS=1) #required for ARM GCC +endif() if(ANDROID_COMPILER_IS_CLANG) add_definitions(-D__TBB_GCC_BUILTIN_ATOMICS_PRESENT=1) @@ -145,7 +182,7 @@ endif() set(TBB_SOURCE_FILES ${lib_srcs} ${lib_hdrs}) -if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm") +if (ARM AND NOT WIN32) if (NOT ANDROID) set(TBB_SOURCE_FILES ${TBB_SOURCE_FILES} "${CMAKE_CURRENT_SOURCE_DIR}/arm_linux_stub.cpp") endif() @@ -156,15 +193,38 @@ endif() set(TBB_SOURCE_FILES ${TBB_SOURCE_FILES} "${CMAKE_CURRENT_SOURCE_DIR}/${tbb_version_file}") add_library(tbb ${TBB_SOURCE_FILES}) -target_link_libraries(tbb c m dl) + +if (WIN32) + if (ARM) + set(platform_macro /D_M_ARM=1) + endif() + + add_custom_command(TARGET tbb + PRE_BUILD + COMMAND ${CMAKE_C_COMPILER} /nologo /TC /EP ${tbb_src_dir}\\src\\tbb\\win32-tbb-export.def /DTBB_NO_LEGACY=1 /D_CRT_SECURE_NO_DEPRECATE /D__TBB_BUILD=1 ${platform_macro} /I${tbb_src_dir}\\src /I${tbb_src_dir}\\include > "${tbb_src_dir}\\src\\tbb\\tbb.def" + WORKING_DIRECTORY ${tbb_src_dir}\\src\\tbb + COMMENT "Generating tbb.def file" VERBATIM + ) + + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEF:${tbb_src_dir}/src/tbb/tbb.def /DLL /MAP /fixed:no /INCREMENTAL:NO") +else() + target_link_libraries(tbb c m dl) +endif() ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef -Wmissing-declarations) string(REPLACE "-Werror=non-virtual-dtor" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") +if (WIN32) + set(tbb_debug_postfix "_debug") # to fit pragmas in _windef.h inside TBB +else() + set(tbb_debug_postfix ${OPENCV_DEBUG_POSTFIX}) +endif() + set_target_properties(tbb PROPERTIES OUTPUT_NAME tbb - DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" + DEBUG_POSTFIX "${tbb_debug_postfix}" ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH} + RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} ) if(ENABLE_SOLUTION_FOLDERS) diff --git a/3rdparty/zlib/ChangeLog b/3rdparty/zlib/ChangeLog index c2c643a1a9..f22aabaef5 100644 --- a/3rdparty/zlib/ChangeLog +++ b/3rdparty/zlib/ChangeLog @@ -1,6 +1,69 @@ ChangeLog file for zlib +Changes in 1.2.8 (28 Apr 2013) +- Update contrib/minizip/iowin32.c for Windows RT [Vollant] +- Do not force Z_CONST for C++ +- Clean up contrib/vstudio [Ro] +- Correct spelling error in zlib.h +- Fix mixed line endings in contrib/vstudio + +Changes in 1.2.7.3 (13 Apr 2013) +- Fix version numbers and DLL names in contrib/vstudio/*/zlib.rc + +Changes in 1.2.7.2 (13 Apr 2013) +- Change check for a four-byte type back to hexadecimal +- Fix typo in win32/Makefile.msc +- Add casts in gzwrite.c for pointer differences + +Changes in 1.2.7.1 (24 Mar 2013) +- Replace use of unsafe string functions with snprintf if available +- Avoid including stddef.h on Windows for Z_SOLO compile [Niessink] +- Fix gzgetc undefine when Z_PREFIX set [Turk] +- Eliminate use of mktemp in Makefile (not always available) +- Fix bug in 'F' mode for gzopen() +- Add inflateGetDictionary() function +- Correct comment in deflate.h +- Use _snprintf for snprintf in Microsoft C +- On Darwin, only use /usr/bin/libtool if libtool is not Apple +- Delete "--version" file if created by "ar --version" [Richard G.] +- Fix configure check for veracity of compiler error return codes +- Fix CMake compilation of static lib for MSVC2010 x64 +- Remove unused variable in infback9.c +- Fix argument checks in gzlog_compress() and gzlog_write() +- Clean up the usage of z_const and respect const usage within zlib +- Clean up examples/gzlog.[ch] comparisons of different types +- Avoid shift equal to bits in type (caused endless loop) +- Fix unintialized value bug in gzputc() introduced by const patches +- Fix memory allocation error in examples/zran.c [Nor] +- Fix bug where gzopen(), gzclose() would write an empty file +- Fix bug in gzclose() when gzwrite() runs out of memory +- Check for input buffer malloc failure in examples/gzappend.c +- Add note to contrib/blast to use binary mode in stdio +- Fix comparisons of differently signed integers in contrib/blast +- Check for invalid code length codes in contrib/puff +- Fix serious but very rare decompression bug in inftrees.c +- Update inflateBack() comments, since inflate() can be faster +- Use underscored I/O function names for WINAPI_FAMILY +- Add _tr_flush_bits to the external symbols prefixed by --zprefix +- Add contrib/vstudio/vc10 pre-build step for static only +- Quote --version-script argument in CMakeLists.txt +- Don't specify --version-script on Apple platforms in CMakeLists.txt +- Fix casting error in contrib/testzlib/testzlib.c +- Fix types in contrib/minizip to match result of get_crc_table() +- Simplify contrib/vstudio/vc10 with 'd' suffix +- Add TOP support to win32/Makefile.msc +- Suport i686 and amd64 assembler builds in CMakeLists.txt +- Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h +- Add vc11 and vc12 build files to contrib/vstudio +- Add gzvprintf() as an undocumented function in zlib +- Fix configure for Sun shell +- Remove runtime check in configure for four-byte integer type +- Add casts and consts to ease user conversion to C++ +- Add man pages for minizip and miniunzip +- In Makefile uninstall, don't rm if preceding cd fails +- Do not return Z_BUF_ERROR if deflateParam() has nothing to write + Changes in 1.2.7 (2 May 2012) - Replace use of memmove() with a simple copy for portability - Test for existence of strerror diff --git a/3rdparty/zlib/README b/3rdparty/zlib/README index 6f1255ffe4..5ca9d127ed 100644 --- a/3rdparty/zlib/README +++ b/3rdparty/zlib/README @@ -1,6 +1,6 @@ ZLIB DATA COMPRESSION LIBRARY -zlib 1.2.7 is a general purpose data compression library. All the code is +zlib 1.2.8 is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and @@ -31,7 +31,7 @@ Mark Nelson wrote an article about zlib for the Jan. 1997 issue of Dr. Dobb's Journal; a copy of the article is available at http://marknelson.us/1997/01/01/zlib-engine/ . -The changes made in version 1.2.7 are documented in the file ChangeLog. +The changes made in version 1.2.8 are documented in the file ChangeLog. Unsupported third party contributions are provided in directory contrib/ . @@ -84,7 +84,7 @@ Acknowledgments: Copyright notice: - (C) 1995-2012 Jean-loup Gailly and Mark Adler + (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/3rdparty/zlib/compress.c b/3rdparty/zlib/compress.c index ea4dfbe9d7..6e9762676a 100644 --- a/3rdparty/zlib/compress.c +++ b/3rdparty/zlib/compress.c @@ -29,7 +29,7 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) z_stream stream; int err; - stream.next_in = (Bytef*)source; + stream.next_in = (z_const Bytef *)source; stream.avail_in = (uInt)sourceLen; #ifdef MAXSEG_64K /* Check for source > 64K on 16-bit machine: */ diff --git a/3rdparty/zlib/deflate.c b/3rdparty/zlib/deflate.c index 9e4c2cbc8a..696957705b 100644 --- a/3rdparty/zlib/deflate.c +++ b/3rdparty/zlib/deflate.c @@ -1,5 +1,5 @@ /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler + * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -52,7 +52,7 @@ #include "deflate.h" const char deflate_copyright[] = - " deflate 1.2.7 Copyright 1995-2012 Jean-loup Gailly and Mark Adler "; + " deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -305,7 +305,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || s->pending_buf == Z_NULL) { s->status = FINISH_STATE; - strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + strm->msg = ERR_MSG(Z_MEM_ERROR); deflateEnd (strm); return Z_MEM_ERROR; } @@ -329,7 +329,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) uInt str, n; int wrap; unsigned avail; - unsigned char *next; + z_const unsigned char *next; if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) return Z_STREAM_ERROR; @@ -359,7 +359,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) avail = strm->avail_in; next = strm->next_in; strm->avail_in = dictLength; - strm->next_in = (Bytef *)dictionary; + strm->next_in = (z_const Bytef *)dictionary; fill_window(s); while (s->lookahead >= MIN_MATCH) { str = s->strstart; @@ -513,6 +513,8 @@ int ZEXPORT deflateParams(strm, level, strategy) strm->total_in != 0) { /* Flush the last buffer: */ err = deflate(strm, Z_BLOCK); + if (err == Z_BUF_ERROR && s->pending == 0) + err = Z_OK; } if (s->level != level) { s->level = level; diff --git a/3rdparty/zlib/deflate.h b/3rdparty/zlib/deflate.h index fbac44d908..ce0299edd1 100644 --- a/3rdparty/zlib/deflate.h +++ b/3rdparty/zlib/deflate.h @@ -104,7 +104,7 @@ typedef struct internal_state { int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ gz_headerp gzhead; /* gzip header information to write */ uInt gzindex; /* where in extra, name, or comment */ - Byte method; /* STORED (for zip only) or DEFLATED */ + Byte method; /* can only be DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ /* used by deflate.c: */ diff --git a/3rdparty/zlib/gzguts.h b/3rdparty/zlib/gzguts.h index ee3f281aa5..d87659d031 100644 --- a/3rdparty/zlib/gzguts.h +++ b/3rdparty/zlib/gzguts.h @@ -1,5 +1,5 @@ /* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -35,6 +35,13 @@ # include #endif +#ifdef WINAPI_FAMILY +# define open _open +# define read _read +# define write _write +# define close _close +#endif + #ifdef NO_DEFLATE /* for compatibility with old definition */ # define NO_GZCOMPRESS #endif @@ -60,7 +67,7 @@ #ifndef HAVE_VSNPRINTF # ifdef MSDOS /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), - but for now we just assume it doesn't. */ + but for now we just assume it doesn't. */ # define NO_vsnprintf # endif # ifdef __TURBOC__ @@ -88,6 +95,14 @@ # endif #endif +/* unlike snprintf (which is required in C99, yet still not supported by + Microsoft more than a decade later!), _snprintf does not guarantee null + termination of the result -- however this is only used in gzlib.c where + the result is assured to fit in the space provided */ +#ifdef _MSC_VER +# define snprintf _snprintf +#endif + #ifndef local # define local static #endif @@ -127,7 +142,8 @@ # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif -/* default i/o buffer size -- double this for output when reading */ +/* default i/o buffer size -- double this for output when reading (this and + twice this must be able to fit in an unsigned type) */ #define GZBUFSIZE 8192 /* gzip modes, also provide a little integrity check on the passed structure */ diff --git a/3rdparty/zlib/gzlib.c b/3rdparty/zlib/gzlib.c index ca55c6ea92..fae202ef89 100644 --- a/3rdparty/zlib/gzlib.c +++ b/3rdparty/zlib/gzlib.c @@ -1,5 +1,5 @@ /* gzlib.c -- zlib functions common to reading and writing gzip files - * Copyright (C) 2004, 2010, 2011, 2012 Mark Adler + * Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -108,7 +108,7 @@ local gzFile gz_open(path, fd, mode) return NULL; /* allocate gzFile structure to return */ - state = malloc(sizeof(gz_state)); + state = (gz_statep)malloc(sizeof(gz_state)); if (state == NULL) return NULL; state->size = 0; /* no buffers allocated yet */ @@ -162,8 +162,10 @@ local gzFile gz_open(path, fd, mode) break; case 'F': state->strategy = Z_FIXED; + break; case 'T': state->direct = 1; + break; default: /* could consider as an error, but just ignore */ ; } @@ -194,8 +196,8 @@ local gzFile gz_open(path, fd, mode) } else #endif - len = strlen(path); - state->path = malloc(len + 1); + len = strlen((const char *)path); + state->path = (char *)malloc(len + 1); if (state->path == NULL) { free(state); return NULL; @@ -208,7 +210,11 @@ local gzFile gz_open(path, fd, mode) *(state->path) = 0; else #endif +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(state->path, len + 1, "%s", (const char *)path); +#else strcpy(state->path, path); +#endif /* compute the flags for open() */ oflag = @@ -236,7 +242,7 @@ local gzFile gz_open(path, fd, mode) #ifdef _WIN32 fd == -2 ? _wopen(path, oflag, 0666) : #endif - open(path, oflag, 0666)); + open((const char *)path, oflag, 0666)); if (state->fd == -1) { free(state->path); free(state); @@ -282,9 +288,13 @@ gzFile ZEXPORT gzdopen(fd, mode) char *path; /* identifier for error messages */ gzFile gz; - if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL) + if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) return NULL; +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(path, 7 + 3 * sizeof(int), "", fd); /* for debugging */ +#else sprintf(path, "", fd); /* for debugging */ +#endif gz = gz_open(path, fd, mode); free(path); return gz; @@ -531,7 +541,8 @@ const char * ZEXPORT gzerror(file, errnum) /* return error information */ if (errnum != NULL) *errnum = state->err; - return state->msg == NULL ? "" : state->msg; + return state->err == Z_MEM_ERROR ? "out of memory" : + (state->msg == NULL ? "" : state->msg); } /* -- see zlib.h -- */ @@ -582,21 +593,24 @@ void ZLIB_INTERNAL gz_error(state, err, msg) if (msg == NULL) return; - /* for an out of memory error, save as static string */ - if (err == Z_MEM_ERROR) { - state->msg = (char *)msg; + /* for an out of memory error, return literal string when requested */ + if (err == Z_MEM_ERROR) return; - } /* construct error message with path */ - if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { + if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == + NULL) { state->err = Z_MEM_ERROR; - state->msg = (char *)"out of memory"; return; } +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, + "%s%s%s", state->path, ": ", msg); +#else strcpy(state->msg, state->path); strcat(state->msg, ": "); strcat(state->msg, msg); +#endif return; } diff --git a/3rdparty/zlib/gzread.c b/3rdparty/zlib/gzread.c index 3493d34d4e..bf4538eb27 100644 --- a/3rdparty/zlib/gzread.c +++ b/3rdparty/zlib/gzread.c @@ -1,5 +1,5 @@ /* gzread.c -- zlib functions for reading gzip files - * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -58,7 +58,8 @@ local int gz_avail(state) return -1; if (state->eof == 0) { if (strm->avail_in) { /* copy what's there to the start */ - unsigned char *p = state->in, *q = strm->next_in; + unsigned char *p = state->in; + unsigned const char *q = strm->next_in; unsigned n = strm->avail_in; do { *p++ = *q++; @@ -90,8 +91,8 @@ local int gz_look(state) /* allocate read buffers and inflate memory */ if (state->size == 0) { /* allocate buffers */ - state->in = malloc(state->want); - state->out = malloc(state->want << 1); + state->in = (unsigned char *)malloc(state->want); + state->out = (unsigned char *)malloc(state->want << 1); if (state->in == NULL || state->out == NULL) { if (state->out != NULL) free(state->out); @@ -352,14 +353,14 @@ int ZEXPORT gzread(file, buf, len) /* large len -- read directly into user buffer */ else if (state->how == COPY) { /* read directly */ - if (gz_load(state, buf, len, &n) == -1) + if (gz_load(state, (unsigned char *)buf, len, &n) == -1) return -1; } /* large len -- decompress directly into user buffer */ else { /* state->how == GZIP */ strm->avail_out = len; - strm->next_out = buf; + strm->next_out = (unsigned char *)buf; if (gz_decomp(state) == -1) return -1; n = state->x.have; @@ -378,7 +379,11 @@ int ZEXPORT gzread(file, buf, len) } /* -- see zlib.h -- */ -#undef gzgetc +#ifdef Z_PREFIX_SET +# undef z_gzgetc +#else +# undef gzgetc +#endif int ZEXPORT gzgetc(file) gzFile file; { @@ -518,7 +523,7 @@ char * ZEXPORT gzgets(file, buf, len) /* look for end-of-line in current output buffer */ n = state->x.have > left ? left : state->x.have; - eol = memchr(state->x.next, '\n', n); + eol = (unsigned char *)memchr(state->x.next, '\n', n); if (eol != NULL) n = (unsigned)(eol - state->x.next) + 1; diff --git a/3rdparty/zlib/gzwrite.c b/3rdparty/zlib/gzwrite.c index 27cb3428e3..aa767fbf63 100644 --- a/3rdparty/zlib/gzwrite.c +++ b/3rdparty/zlib/gzwrite.c @@ -1,5 +1,5 @@ /* gzwrite.c -- zlib functions for writing gzip files - * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -19,7 +19,7 @@ local int gz_init(state) z_streamp strm = &(state->strm); /* allocate input buffer */ - state->in = malloc(state->want); + state->in = (unsigned char *)malloc(state->want); if (state->in == NULL) { gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; @@ -28,7 +28,7 @@ local int gz_init(state) /* only need output buffer and deflate state if compressing */ if (!state->direct) { /* allocate output buffer */ - state->out = malloc(state->want); + state->out = (unsigned char *)malloc(state->want); if (state->out == NULL) { free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); @@ -168,7 +168,6 @@ int ZEXPORT gzwrite(file, buf, len) unsigned len; { unsigned put = len; - unsigned n; gz_statep state; z_streamp strm; @@ -208,16 +207,19 @@ int ZEXPORT gzwrite(file, buf, len) if (len < state->size) { /* copy to input buffer, compress when full */ do { + unsigned have, copy; + if (strm->avail_in == 0) strm->next_in = state->in; - n = state->size - strm->avail_in; - if (n > len) - n = len; - memcpy(strm->next_in + strm->avail_in, buf, n); - strm->avail_in += n; - state->x.pos += n; - buf = (char *)buf + n; - len -= n; + have = (unsigned)((strm->next_in + strm->avail_in) - state->in); + copy = state->size - have; + if (copy > len) + copy = len; + memcpy(state->in + have, buf, copy); + strm->avail_in += copy; + state->x.pos += copy; + buf = (const char *)buf + copy; + len -= copy; if (len && gz_comp(state, Z_NO_FLUSH) == -1) return 0; } while (len); @@ -229,7 +231,7 @@ int ZEXPORT gzwrite(file, buf, len) /* directly compress user buffer to file */ strm->avail_in = len; - strm->next_in = (voidp)buf; + strm->next_in = (z_const Bytef *)buf; state->x.pos += len; if (gz_comp(state, Z_NO_FLUSH) == -1) return 0; @@ -244,6 +246,7 @@ int ZEXPORT gzputc(file, c) gzFile file; int c; { + unsigned have; unsigned char buf[1]; gz_statep state; z_streamp strm; @@ -267,12 +270,16 @@ int ZEXPORT gzputc(file, c) /* try writing to input buffer for speed (state->size == 0 if buffer not initialized) */ - if (strm->avail_in < state->size) { + if (state->size) { if (strm->avail_in == 0) strm->next_in = state->in; - strm->next_in[strm->avail_in++] = c; - state->x.pos++; - return c & 0xff; + have = (unsigned)((strm->next_in + strm->avail_in) - state->in); + if (have < state->size) { + state->in[have] = c; + strm->avail_in++; + state->x.pos++; + return c & 0xff; + } } /* no room in buffer or not initialized, use gz_write() */ @@ -300,12 +307,11 @@ int ZEXPORT gzputs(file, str) #include /* -- see zlib.h -- */ -int ZEXPORTVA gzprintf (gzFile file, const char *format, ...) +int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) { int size, len; gz_statep state; z_streamp strm; - va_list va; /* get internal structure */ if (file == NULL) @@ -335,25 +341,20 @@ int ZEXPORTVA gzprintf (gzFile file, const char *format, ...) /* do the printf() into the input buffer, put length in len */ size = (int)(state->size); state->in[size - 1] = 0; - va_start(va, format); #ifdef NO_vsnprintf # ifdef HAS_vsprintf_void (void)vsprintf((char *)(state->in), format, va); - va_end(va); for (len = 0; len < size; len++) if (state->in[len] == 0) break; # else len = vsprintf((char *)(state->in), format, va); - va_end(va); # endif #else # ifdef HAS_vsnprintf_void (void)vsnprintf((char *)(state->in), size, format, va); - va_end(va); len = strlen((char *)(state->in)); # else len = vsnprintf((char *)(state->in), size, format, va); - va_end(va); # endif #endif @@ -368,6 +369,17 @@ int ZEXPORTVA gzprintf (gzFile file, const char *format, ...) return len; } +int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) +{ + va_list va; + int ret; + + va_start(va, format); + ret = gzvprintf(file, format, va); + va_end(va); + return ret; +} + #else /* !STDC && !Z_HAVE_STDARG_H */ /* -- see zlib.h -- */ @@ -547,9 +559,9 @@ int ZEXPORT gzclose_w(file) } /* flush, free memory, and close file */ + if (gz_comp(state, Z_FINISH) == -1) + ret = state->err; if (state->size) { - if (gz_comp(state, Z_FINISH) == -1) - ret = state->err; if (!state->direct) { (void)deflateEnd(&(state->strm)); free(state->out); diff --git a/3rdparty/zlib/infback.c b/3rdparty/zlib/infback.c index 981aff17c2..f3833c2e43 100644 --- a/3rdparty/zlib/infback.c +++ b/3rdparty/zlib/infback.c @@ -255,7 +255,7 @@ out_func out; void FAR *out_desc; { struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ + z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ diff --git a/3rdparty/zlib/inffast.c b/3rdparty/zlib/inffast.c index 2f1d60b43b..bda59ceb6a 100644 --- a/3rdparty/zlib/inffast.c +++ b/3rdparty/zlib/inffast.c @@ -1,5 +1,5 @@ /* inffast.c -- fast decoding - * Copyright (C) 1995-2008, 2010 Mark Adler + * Copyright (C) 1995-2008, 2010, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -69,8 +69,8 @@ z_streamp strm; unsigned start; /* inflate()'s starting value for strm->avail_out */ { struct inflate_state FAR *state; - unsigned char FAR *in; /* local strm->next_in */ - unsigned char FAR *last; /* while in < last, enough input available */ + z_const unsigned char FAR *in; /* local strm->next_in */ + z_const unsigned char FAR *last; /* have enough input while in < last */ unsigned char FAR *out; /* local strm->next_out */ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ unsigned char FAR *end; /* while out < end, enough space available */ diff --git a/3rdparty/zlib/inflate.c b/3rdparty/zlib/inflate.c index 47418a1e1e..870f89bb4d 100644 --- a/3rdparty/zlib/inflate.c +++ b/3rdparty/zlib/inflate.c @@ -93,11 +93,12 @@ /* function prototypes */ local void fixedtables OF((struct inflate_state FAR *state)); -local int updatewindow OF((z_streamp strm, unsigned out)); +local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, + unsigned copy)); #ifdef BUILDFIXED void makefixed OF((void)); #endif -local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, +local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, unsigned len)); int ZEXPORT inflateResetKeep(strm) @@ -375,12 +376,13 @@ void makefixed() output will fall in the output data, making match copies simpler and faster. The advantage may be dependent on the size of the processor's data caches. */ -local int updatewindow(strm, out) +local int updatewindow(strm, end, copy) z_streamp strm; -unsigned out; +const Bytef *end; +unsigned copy; { struct inflate_state FAR *state; - unsigned copy, dist; + unsigned dist; state = (struct inflate_state FAR *)strm->state; @@ -400,19 +402,18 @@ unsigned out; } /* copy state->wsize or less output bytes into the circular window */ - copy = out - strm->avail_out; if (copy >= state->wsize) { - zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + zmemcpy(state->window, end - state->wsize, state->wsize); state->wnext = 0; state->whave = state->wsize; } else { dist = state->wsize - state->wnext; if (dist > copy) dist = copy; - zmemcpy(state->window + state->wnext, strm->next_out - copy, dist); + zmemcpy(state->window + state->wnext, end - copy, dist); copy -= dist; if (copy) { - zmemcpy(state->window, strm->next_out - copy, copy); + zmemcpy(state->window, end - copy, copy); state->wnext = copy; state->whave = state->wsize; } @@ -606,7 +607,7 @@ z_streamp strm; int flush; { struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ + z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ @@ -920,7 +921,7 @@ int flush; while (state->have < 19) state->lens[order[state->have++]] = 0; state->next = state->codes; - state->lencode = (code const FAR *)(state->next); + state->lencode = (const code FAR *)(state->next); state->lenbits = 7; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); @@ -994,7 +995,7 @@ int flush; values here (9 and 6) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ state->next = state->codes; - state->lencode = (code const FAR *)(state->next); + state->lencode = (const code FAR *)(state->next); state->lenbits = 9; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); @@ -1003,7 +1004,7 @@ int flush; state->mode = BAD; break; } - state->distcode = (code const FAR *)(state->next); + state->distcode = (const code FAR *)(state->next); state->distbits = 6; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); @@ -1230,7 +1231,7 @@ int flush; RESTORE(); if (state->wsize || (out != strm->avail_out && state->mode < BAD && (state->mode < CHECK || flush != Z_FINISH))) - if (updatewindow(strm, out)) { + if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { state->mode = MEM; return Z_MEM_ERROR; } @@ -1264,6 +1265,29 @@ z_streamp strm; return Z_OK; } +int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) +z_streamp strm; +Bytef *dictionary; +uInt *dictLength; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* copy dictionary */ + if (state->whave && dictionary != Z_NULL) { + zmemcpy(dictionary, state->window + state->wnext, + state->whave - state->wnext); + zmemcpy(dictionary + state->whave - state->wnext, + state->window, state->wnext); + } + if (dictLength != Z_NULL) + *dictLength = state->whave; + return Z_OK; +} + int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) z_streamp strm; const Bytef *dictionary; @@ -1271,8 +1295,6 @@ uInt dictLength; { struct inflate_state FAR *state; unsigned long dictid; - unsigned char *next; - unsigned avail; int ret; /* check state */ @@ -1291,13 +1313,7 @@ uInt dictLength; /* copy dictionary to window using updatewindow(), which will amend the existing dictionary if appropriate */ - next = strm->next_out; - avail = strm->avail_out; - strm->next_out = (Bytef *)dictionary + dictLength; - strm->avail_out = 0; - ret = updatewindow(strm, dictLength); - strm->avail_out = avail; - strm->next_out = next; + ret = updatewindow(strm, dictionary + dictLength, dictLength); if (ret) { state->mode = MEM; return Z_MEM_ERROR; @@ -1337,7 +1353,7 @@ gz_headerp head; */ local unsigned syncsearch(have, buf, len) unsigned FAR *have; -unsigned char FAR *buf; +const unsigned char FAR *buf; unsigned len; { unsigned got; diff --git a/3rdparty/zlib/inftrees.c b/3rdparty/zlib/inftrees.c index abcd7c45ed..44d89cf24e 100644 --- a/3rdparty/zlib/inftrees.c +++ b/3rdparty/zlib/inftrees.c @@ -1,5 +1,5 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2012 Mark Adler + * Copyright (C) 1995-2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,7 +9,7 @@ #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.2.7 Copyright 1995-2012 Mark Adler "; + " inflate 1.2.8 Copyright 1995-2013 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -62,7 +62,7 @@ unsigned short FAR *work; 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 78, 68}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, @@ -208,8 +208,8 @@ unsigned short FAR *work; mask = used - 1; /* mask for comparing low */ /* check available table space */ - if ((type == LENS && used >= ENOUGH_LENS) || - (type == DISTS && used >= ENOUGH_DISTS)) + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) return 1; /* process all codes and make table entries */ @@ -277,8 +277,8 @@ unsigned short FAR *work; /* check for enough space */ used += 1U << curr; - if ((type == LENS && used >= ENOUGH_LENS) || - (type == DISTS && used >= ENOUGH_DISTS)) + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) return 1; /* point entry in root table to sub-table */ diff --git a/3rdparty/zlib/trees.c b/3rdparty/zlib/trees.c index 8c32b214b1..1fd7759ef0 100644 --- a/3rdparty/zlib/trees.c +++ b/3rdparty/zlib/trees.c @@ -146,8 +146,8 @@ local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); local int build_bl_tree OF((deflate_state *s)); local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, int blcodes)); -local void compress_block OF((deflate_state *s, ct_data *ltree, - ct_data *dtree)); +local void compress_block OF((deflate_state *s, const ct_data *ltree, + const ct_data *dtree)); local int detect_data_type OF((deflate_state *s)); local unsigned bi_reverse OF((unsigned value, int length)); local void bi_windup OF((deflate_state *s)); @@ -972,7 +972,8 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { #endif send_bits(s, (STATIC_TREES<<1)+last, 3); - compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); + compress_block(s, (const ct_data *)static_ltree, + (const ct_data *)static_dtree); #ifdef DEBUG s->compressed_len += 3 + s->static_len; #endif @@ -980,7 +981,8 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) send_bits(s, (DYN_TREES<<1)+last, 3); send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, max_blindex+1); - compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); + compress_block(s, (const ct_data *)s->dyn_ltree, + (const ct_data *)s->dyn_dtree); #ifdef DEBUG s->compressed_len += 3 + s->opt_len; #endif @@ -1057,8 +1059,8 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc) */ local void compress_block(s, ltree, dtree) deflate_state *s; - ct_data *ltree; /* literal tree */ - ct_data *dtree; /* distance tree */ + const ct_data *ltree; /* literal tree */ + const ct_data *dtree; /* distance tree */ { unsigned dist; /* distance of matched string */ int lc; /* match length or unmatched char (if dist == 0) */ diff --git a/3rdparty/zlib/uncompr.c b/3rdparty/zlib/uncompr.c index ad98be3a5d..242e9493df 100644 --- a/3rdparty/zlib/uncompr.c +++ b/3rdparty/zlib/uncompr.c @@ -30,7 +30,7 @@ int ZEXPORT uncompress (dest, destLen, source, sourceLen) z_stream stream; int err; - stream.next_in = (Bytef*)source; + stream.next_in = (z_const Bytef *)source; stream.avail_in = (uInt)sourceLen; /* Check for source > 64K on 16-bit machine: */ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; diff --git a/3rdparty/zlib/zconf.h.cmakein b/3rdparty/zlib/zconf.h.cmakein index 1e4e14045f..6528fb4df8 100644 --- a/3rdparty/zlib/zconf.h.cmakein +++ b/3rdparty/zlib/zconf.h.cmakein @@ -1,5 +1,5 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2012 Jean-loup Gailly. + * Copyright (C) 1995-2013 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -23,6 +23,7 @@ # define _dist_code z__dist_code # define _length_code z__length_code # define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits # define _tr_flush_block z__tr_flush_block # define _tr_init z__tr_init # define _tr_stored_block z__tr_stored_block @@ -79,6 +80,7 @@ # define gzopen_w z_gzopen_w # endif # define gzprintf z_gzprintf +# define gzvprintf z_gzvprintf # define gzputc z_gzputc # define gzputs z_gzputs # define gzread z_gzread @@ -105,6 +107,7 @@ # define inflateReset z_inflateReset # define inflateReset2 z_inflateReset2 # define inflateSetDictionary z_inflateSetDictionary +# define inflateGetDictionary z_inflateGetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine @@ -390,20 +393,14 @@ typedef uLong FAR uLongf; typedef Byte *voidp; #endif -/* ./configure may #define Z_U4 here */ - #if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) # include # if (UINT_MAX == 0xffffffffUL) # define Z_U4 unsigned -# else -# if (ULONG_MAX == 0xffffffffUL) -# define Z_U4 unsigned long -# else -# if (USHRT_MAX == 0xffffffffUL) -# define Z_U4 unsigned short -# endif -# endif +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short # endif #endif @@ -427,8 +424,16 @@ typedef uLong FAR uLongf; # endif #endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + #ifdef _WIN32 -# include /* for wchar_t */ +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif #endif /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and @@ -437,7 +442,7 @@ typedef uLong FAR uLongf; * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as * equivalently requesting no 64-bit operations */ -#if defined(LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 # undef _LARGEFILE64_SOURCE #endif @@ -445,7 +450,7 @@ typedef uLong FAR uLongf; # define Z_HAVE_UNISTD_H #endif #ifndef Z_SOLO -# if defined(Z_HAVE_UNISTD_H) || defined(LARGEFILE64_SOURCE) +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) # include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # ifdef VMS # include /* for off_t */ diff --git a/3rdparty/zlib/zlib.h b/3rdparty/zlib/zlib.h index 3edf3acdb5..3e0c7672ac 100644 --- a/3rdparty/zlib/zlib.h +++ b/3rdparty/zlib/zlib.h @@ -1,7 +1,7 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.7, May 2nd, 2012 + version 1.2.8, April 28th, 2013 - Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -37,11 +37,11 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.7" -#define ZLIB_VERNUM 0x1270 +#define ZLIB_VERSION "1.2.8" +#define ZLIB_VERNUM 0x1280 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 7 +#define ZLIB_VER_REVISION 8 #define ZLIB_VER_SUBREVISION 0 /* @@ -839,6 +839,21 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, inflate(). */ +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); /* Skips invalid compressed data until a possible full flush point (see above @@ -846,7 +861,7 @@ ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); available input is skipped. No output is provided. inflateSync searches for a 00 00 FF FF pattern in the compressed data. - All full flush points have this pattern, but not all occurences of this + All full flush points have this pattern, but not all occurrences of this pattern are full flush points. inflateSync returns Z_OK if a possible full flush point has been found, @@ -1007,7 +1022,8 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, the version of the header file. */ -typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, @@ -1015,11 +1031,12 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, out_func out, void FAR *out_desc)); /* inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is more efficient than inflate() for - file i/o applications in that it avoids copying between the output and the - sliding window by simply making the window itself the output buffer. This - function trusts the application to not change the output buffer passed by - the output function, at least until inflateBack() returns. + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. inflateBackInit() must be called first to allocate the internal state and to initialize the state with the user-provided window buffer. @@ -1736,6 +1753,13 @@ ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, const char *mode)); #endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif #ifdef __cplusplus } diff --git a/3rdparty/zlib/zutil.c b/3rdparty/zlib/zutil.c index 65e0d3b72b..23d2ebef00 100644 --- a/3rdparty/zlib/zutil.c +++ b/3rdparty/zlib/zutil.c @@ -14,7 +14,7 @@ struct internal_state {int dummy;}; /* for buggy compilers */ #endif -const char * const z_errmsg[10] = { +z_const char * const z_errmsg[10] = { "need dictionary", /* Z_NEED_DICT 2 */ "stream end", /* Z_STREAM_END 1 */ "", /* Z_OK 0 */ diff --git a/3rdparty/zlib/zutil.h b/3rdparty/zlib/zutil.h index 4e3dcc6ae9..24ab06b1cf 100644 --- a/3rdparty/zlib/zutil.h +++ b/3rdparty/zlib/zutil.h @@ -1,5 +1,5 @@ /* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2012 Jean-loup Gailly. + * Copyright (C) 1995-2013 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -44,13 +44,13 @@ typedef unsigned short ush; typedef ush FAR ushf; typedef unsigned long ulg; -extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* (size given to avoid silly warnings with Visual C++) */ #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] #define ERR_RETURN(strm,err) \ - return (strm->msg = (char*)ERR_MSG(err), (err)) + return (strm->msg = ERR_MSG(err), (err)) /* To be used only when the state is known to be valid */ /* common constants */ @@ -168,7 +168,8 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #endif /* provide prototypes for these when building zlib without LFS */ -#if !defined(_WIN32) && (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) +#if !defined(_WIN32) && \ + (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); #endif diff --git a/CMakeLists.txt b/CMakeLists.txt index 470c5520dd..c795ad3ff3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,20 +4,14 @@ # From the off-tree build directory, invoke: # $ cmake # -# -# - OCT-2008: Initial version -# # ---------------------------------------------------------------------------- -set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) +include(cmake/OpenCVMinDepVersions.cmake) -# -------------------------------------------------------------- -# Indicate CMake 2.7 and above that we don't want to mix relative -# and absolute paths in linker lib lists. -# Run "cmake --help-policy CMP0003" for more information. -# -------------------------------------------------------------- -if(COMMAND cmake_policy) - cmake_policy(SET CMP0003 NEW) +if(CMAKE_GENERATOR MATCHES Xcode AND XCODE_VERSION VERSION_GREATER 4.3) + cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR) +else() + cmake_minimum_required(VERSION "${MIN_VER_CMAKE}" FATAL_ERROR) endif() # Following block can broke build in case of cross-compilng @@ -41,20 +35,10 @@ else(NOT CMAKE_TOOLCHAIN_FILE) set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Installation Directory") endif(NOT CMAKE_TOOLCHAIN_FILE) -# -------------------------------------------------------------- -# Top level OpenCV project -# -------------------------------------------------------------- -if(CMAKE_GENERATOR MATCHES Xcode AND XCODE_VERSION VERSION_GREATER 4.3) - cmake_minimum_required(VERSION 2.8.8) -elseif(IOS) - cmake_minimum_required(VERSION 2.8.0) -else() - cmake_minimum_required(VERSION 2.6.3) -endif() # must go before the project command set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Configs" FORCE) -if(DEFINED CMAKE_BUILD_TYPE AND CMAKE_VERSION VERSION_GREATER "2.8") +if(DEFINED CMAKE_BUILD_TYPE) set_property( CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CMAKE_CONFIGURATION_TYPES} ) endif() @@ -103,6 +87,19 @@ if(UNIX AND NOT ANDROID) endif() endif() +# Add these standard paths to the search paths for FIND_PATH +# to find include files from these locations first +if(MINGW) + if(EXISTS /mingw) + list(APPEND CMAKE_INCLUDE_PATH /mingw) + endif() + if(EXISTS /mingw32) + list(APPEND CMAKE_INCLUDE_PATH /mingw32) + endif() + if(EXISTS /mingw64) + list(APPEND CMAKE_INCLUDE_PATH /mingw64) + endif() +endif() # ---------------------------------------------------------------------------- # OpenCV cmake options @@ -110,41 +107,45 @@ endif() # Optional 3rd party components # =================================================== -OCV_OPTION(WITH_1394 "Include IEEE1394 support" ON IF (UNIX AND NOT ANDROID AND NOT IOS) ) +OCV_OPTION(WITH_1394 "Include IEEE1394 support" ON IF (NOT ANDROID AND NOT IOS) ) OCV_OPTION(WITH_AVFOUNDATION "Use AVFoundation for Video I/O" ON IF IOS) OCV_OPTION(WITH_CARBON "Use Carbon for UI instead of Cocoa" OFF IF APPLE ) -OCV_OPTION(WITH_CUDA "Include NVidia Cuda Runtime support" ON IF (CMAKE_VERSION VERSION_GREATER "2.8" AND NOT ANDROID AND NOT IOS) ) -OCV_OPTION(WITH_CUFFT "Include NVidia Cuda Fast Fourier Transform (FFT) library support" ON IF (CMAKE_VERSION VERSION_GREATER "2.8" AND NOT ANDROID AND NOT IOS) ) -OCV_OPTION(WITH_CUBLAS "Include NVidia Cuda Basic Linear Algebra Subprograms (BLAS) library support" OFF IF (CMAKE_VERSION VERSION_GREATER "2.8" AND NOT ANDROID AND NOT IOS) ) -OCV_OPTION(WITH_NVCUVID "Include NVidia Video Decoding library support" OFF IF (CMAKE_VERSION VERSION_GREATER "2.8" AND NOT ANDROID AND NOT IOS AND NOT APPLE) ) +OCV_OPTION(WITH_CUDA "Include NVidia Cuda Runtime support" ON IF (NOT ANDROID AND NOT IOS) ) +OCV_OPTION(WITH_CUFFT "Include NVidia Cuda Fast Fourier Transform (FFT) library support" ON IF (NOT ANDROID AND NOT IOS) ) +OCV_OPTION(WITH_CUBLAS "Include NVidia Cuda Basic Linear Algebra Subprograms (BLAS) library support" OFF IF (NOT ANDROID AND NOT IOS) ) +OCV_OPTION(WITH_NVCUVID "Include NVidia Video Decoding library support" OFF IF (NOT ANDROID AND NOT IOS AND NOT APPLE) ) OCV_OPTION(WITH_EIGEN "Include Eigen2/Eigen3 support" ON) +OCV_OPTION(WITH_VFW "Include Video for Windows support" ON IF WIN32 ) OCV_OPTION(WITH_FFMPEG "Include FFMPEG support" ON IF (NOT ANDROID AND NOT IOS)) OCV_OPTION(WITH_GSTREAMER "Include Gstreamer support" ON IF (UNIX AND NOT APPLE AND NOT ANDROID) ) +OCV_OPTION(WITH_GSTREAMER_1_X "Include Gstreamer 1.x support" OFF) OCV_OPTION(WITH_GTK "Include GTK support" ON IF (UNIX AND NOT APPLE AND NOT ANDROID) ) OCV_OPTION(WITH_IPP "Include Intel IPP support" OFF IF (MSVC OR X86 OR X86_64) ) OCV_OPTION(WITH_JASPER "Include JPEG2K support" ON IF (NOT IOS) ) -OCV_OPTION(WITH_JPEG "Include JPEG support" ON IF (NOT IOS) ) +OCV_OPTION(WITH_JPEG "Include JPEG support" ON) OCV_OPTION(WITH_WEBP "Include WebP support" ON IF (NOT IOS) ) OCV_OPTION(WITH_OPENEXR "Include ILM support via OpenEXR" ON IF (NOT IOS) ) OCV_OPTION(WITH_OPENGL "Include OpenGL support" OFF IF (NOT ANDROID AND NOT APPLE) ) OCV_OPTION(WITH_OPENNI "Include OpenNI support" OFF IF (NOT ANDROID AND NOT IOS) ) -OCV_OPTION(WITH_PNG "Include PNG support" ON IF (NOT IOS) ) +OCV_OPTION(WITH_PNG "Include PNG support" ON) OCV_OPTION(WITH_PVAPI "Include Prosilica GigE support" ON IF (NOT ANDROID AND NOT IOS) ) OCV_OPTION(WITH_GIGEAPI "Include Smartek GigE support" ON IF (NOT ANDROID AND NOT IOS) ) OCV_OPTION(WITH_QT "Build with Qt Backend support" OFF IF (NOT ANDROID AND NOT IOS) ) +OCV_OPTION(WITH_WIN32UI "Build with Win32 UI Backend support" ON IF WIN32 ) OCV_OPTION(WITH_QUICKTIME "Use QuickTime for Video I/O insted of QTKit" OFF IF APPLE ) OCV_OPTION(WITH_TBB "Include Intel TBB support" OFF IF (NOT IOS) ) OCV_OPTION(WITH_CSTRIPES "Include C= support" OFF IF WIN32 ) 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) ) -OCV_OPTION(WITH_VIDEOINPUT "Build HighGUI with DirectShow support" ON IF WIN32 ) +OCV_OPTION(WITH_DSHOW "Build HighGUI with DirectShow support" ON IF (WIN32 AND NOT ARM) ) +OCV_OPTION(WITH_MSMF "Build HighGUI with Media Foundation support" OFF IF WIN32 ) OCV_OPTION(WITH_XIMEA "Include XIMEA cameras support" OFF IF (NOT ANDROID AND NOT APPLE) ) OCV_OPTION(WITH_XINE "Include Xine support (GPL)" OFF IF (UNIX AND NOT APPLE AND NOT ANDROID) ) OCV_OPTION(WITH_CLP "Include Clp support (EPL)" OFF) -OCV_OPTION(WITH_OPENCL "Include OpenCL Runtime support" OFF IF (NOT ANDROID AND NOT IOS) ) -OCV_OPTION(WITH_OPENCLAMDFFT "Include AMD OpenCL FFT library support" OFF IF (NOT ANDROID AND NOT IOS) ) -OCV_OPTION(WITH_OPENCLAMDBLAS "Include AMD OpenCL BLAS library support" OFF IF (NOT ANDROID AND NOT IOS) ) +OCV_OPTION(WITH_OPENCL "Include OpenCL Runtime support" ON IF (NOT ANDROID AND NOT IOS) ) +OCV_OPTION(WITH_OPENCLAMDFFT "Include AMD OpenCL FFT library support" ON IF (NOT ANDROID AND NOT IOS) ) +OCV_OPTION(WITH_OPENCLAMDBLAS "Include AMD OpenCL BLAS library support" ON IF (NOT ANDROID AND NOT IOS) ) # OpenCV build components @@ -170,7 +171,7 @@ OCV_OPTION(BUILD_JASPER "Build libjasper from source" WIN32 O OCV_OPTION(BUILD_JPEG "Build libjpeg from source" WIN32 OR ANDROID OR APPLE ) OCV_OPTION(BUILD_PNG "Build libpng from source" WIN32 OR ANDROID OR APPLE ) OCV_OPTION(BUILD_OPENEXR "Build openexr from source" WIN32 OR ANDROID OR APPLE ) -OCV_OPTION(BUILD_TBB "Download and build TBB from source" ANDROID IF CMAKE_COMPILER_IS_GNUCXX ) +OCV_OPTION(BUILD_TBB "Download and build TBB from source" ANDROID ) # OpenCV installation options # =================================================== @@ -183,7 +184,7 @@ OCV_OPTION(INSTALL_TO_MANGLED_PATHS "Enables mangled install paths, that help wi # OpenCV build options # =================================================== OCV_OPTION(ENABLE_PRECOMPILED_HEADERS "Use precompiled headers" ON IF (NOT IOS) ) -OCV_OPTION(ENABLE_SOLUTION_FOLDERS "Solution folder in Visual Studio or in other IDEs" (MSVC_IDE OR CMAKE_GENERATOR MATCHES Xcode) IF (CMAKE_VERSION VERSION_GREATER "2.8.0") ) +OCV_OPTION(ENABLE_SOLUTION_FOLDERS "Solution folder in Visual Studio or in other IDEs" (MSVC_IDE OR CMAKE_GENERATOR MATCHES Xcode) ) OCV_OPTION(ENABLE_PROFILING "Enable profiling in the GCC compiler (Add flags: -g -pg)" OFF IF CMAKE_COMPILER_IS_GNUCXX ) OCV_OPTION(ENABLE_OMIT_FRAME_POINTER "Enable -fomit-frame-pointer for GCC" ON IF CMAKE_COMPILER_IS_GNUCXX AND NOT (APPLE AND CMAKE_COMPILER_IS_CLANGCXX) ) OCV_OPTION(ENABLE_POWERPC "Enable PowerPC for GCC" ON IF (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_SYSTEM_PROCESSOR MATCHES powerpc.*) ) @@ -197,15 +198,7 @@ OCV_OPTION(ENABLE_SSE42 "Enable SSE4.2 instructions" OCV_OPTION(ENABLE_AVX "Enable AVX instructions" OFF IF ((MSVC OR CMAKE_COMPILER_IS_GNUCXX) AND (X86 OR X86_64)) ) OCV_OPTION(ENABLE_NOISY_WARNINGS "Show all warnings even if they are too noisy" OFF ) OCV_OPTION(OPENCV_WARNINGS_ARE_ERRORS "Treat warnings as errors" OFF ) - - -# uncategorized options -# =================================================== -OCV_OPTION(CMAKE_VERBOSE "Verbose mode" OFF ) - -# backward compatibility -# =================================================== -include(cmake/OpenCVLegacyOptions.cmake OPTIONAL) +OCV_OPTION(ENABLE_WINRT_MODE "Build with Windows Runtime support" OFF IF WIN32 ) # ---------------------------------------------------------------------------- @@ -272,37 +265,25 @@ if(DEFINED CMAKE_DEBUG_POSTFIX) set(OPENCV_DEBUG_POSTFIX "${CMAKE_DEBUG_POSTFIX}") endif() -if(CMAKE_VERBOSE) - set(CMAKE_VERBOSE_MAKEFILE 1) -endif() - # ---------------------------------------------------------------------------- # Path for build/platform -specific headers # ---------------------------------------------------------------------------- set(OPENCV_CONFIG_FILE_INCLUDE_DIR "${CMAKE_BINARY_DIR}/" CACHE PATH "Where to create the platform-dependant cvconfig.h") -add_definitions(-DHAVE_CVCONFIG_H) ocv_include_directories(${OPENCV_CONFIG_FILE_INCLUDE_DIR}) +# ---------------------------------------------------------------------------- +# Path for additional modules +# ---------------------------------------------------------------------------- +set(OPENCV_EXTRA_MODULES_PATH "" CACHE PATH "Where to look for additional OpenCV modules") # ---------------------------------------------------------------------------- # Autodetect if we are in a GIT repository # ---------------------------------------------------------------------------- +find_host_package(Git QUIET) -# don't use FindGit because it requires CMake 2.8.2 -set(git_names git eg) # eg = easy git -# Prefer .cmd variants on Windows unless running in a Makefile in the MSYS shell -if(CMAKE_HOST_WIN32) - if(NOT CMAKE_GENERATOR MATCHES "MSYS") - set(git_names git.cmd git eg.cmd eg) - endif() -endif() - -find_host_program(GIT_EXECUTABLE NAMES ${git_names} PATH_SUFFIXES Git/cmd Git/bin DOC "git command line client") -mark_as_advanced(GIT_EXECUTABLE) - -if(GIT_EXECUTABLE) - execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --always --dirty --match "2.[0-9].[0-9]*" +if(GIT_FOUND) + execute_process(COMMAND "${GIT_EXECUTABLE}" describe --tags --always --dirty --match "2.[0-9].[0-9]*" WORKING_DIRECTORY "${OpenCV_SOURCE_DIR}" OUTPUT_VARIABLE OPENCV_VCSVERSION RESULT_VARIABLE GIT_RESULT @@ -346,14 +327,11 @@ endif(WIN32 AND NOT MINGW) # CHECK FOR SYSTEM LIBRARIES, OPTIONS, ETC.. # ---------------------------------------------------------------------------- if(UNIX) - include(cmake/OpenCVFindPkgConfig.cmake OPTIONAL) + find_package(PkgConfig QUIET) include(CheckFunctionExists) include(CheckIncludeFile) if(NOT APPLE) - CHECK_INCLUDE_FILE(alloca.h HAVE_ALLOCA_H) - CHECK_FUNCTION_EXISTS(alloca HAVE_ALLOCA) - CHECK_INCLUDE_FILE(unistd.h HAVE_UNISTD_H) CHECK_INCLUDE_FILE(pthread.h HAVE_LIBPTHREAD) if(ANDROID) set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} dl m log) @@ -363,7 +341,7 @@ if(UNIX) set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} dl m pthread rt) endif() else() - add_definitions(-DHAVE_ALLOCA -DHAVE_ALLOCA_H -DHAVE_LIBPTHREAD -DHAVE_UNISTD_H) + set(HAVE_LIBPTHREAD YES) endif() endif() @@ -400,7 +378,7 @@ if(ANDROID) if(NOT ANDROID_TOOLS_Pkg_Revision GREATER 13) message(WARNING "OpenCV requires Android SDK tools revision 14 or newer. Otherwise tests and samples will no be compiled.") endif() -elseif(ANT_EXECUTABLE) +else() find_package(JNI) endif() @@ -413,15 +391,6 @@ endif() # --- OpenCL --- if(WITH_OPENCL) include(cmake/OpenCVDetectOpenCL.cmake) - if(OPENCL_FOUND) - set(HAVE_OPENCL 1) - endif() - if(WITH_OPENCLAMDFFT AND CLAMDFFT_INCLUDE_DIR) - set(HAVE_CLAMDFFT 1) - endif() - if(WITH_OPENCLAMDBLAS AND CLAMDBLAS_INCLUDE_DIR) - set(HAVE_CLAMDBLAS 1) - endif() endif() # ---------------------------------------------------------------------------- @@ -463,15 +432,15 @@ if(BUILD_EXAMPLES OR BUILD_ANDROID_EXAMPLES OR INSTALL_PYTHON_EXAMPLES) endif() if(ANDROID) - add_subdirectory(android/service) + add_subdirectory(platforms/android/service) endif() if(BUILD_ANDROID_PACKAGE) - add_subdirectory(android/package) + add_subdirectory(platforms/android/package) endif() if (ANDROID) - add_subdirectory(android/libinfo) + add_subdirectory(platforms/android/libinfo) endif() # ---------------------------------------------------------------------------- @@ -491,6 +460,8 @@ include(cmake/OpenCVGenAndroidMK.cmake) # Generate OpenCVСonfig.cmake and OpenCVConfig-version.cmake for cmake projects include(cmake/OpenCVGenConfig.cmake) +# Generate Info.plist for the IOS framework +include(cmake/OpenCVGenInfoPlist.cmake) # ---------------------------------------------------------------------------- # Summary: @@ -597,19 +568,32 @@ if(ANDROID) status(" Android examples:" BUILD_ANDROID_EXAMPLES AND CAN_BUILD_ANDROID_PROJECTS THEN YES ELSE NO) endif() +# ================== Windows RT features ================== +if(WIN32) +status("") + status(" Windows RT support:" HAVE_WINRT THEN YES ELSE NO) + if (ENABLE_WINRT_MODE) + status(" Windows SDK v8.0:" ${WINDOWS_SDK_PATH}) + status(" Visual Studio 2012:" ${VISUAL_STUDIO_PATH}) + endif() +endif(WIN32) + # ========================== GUI ========================== status("") status(" GUI: ") -if(HAVE_QT) +if(HAVE_QT5) + status(" QT 5.x:" HAVE_QT THEN "YES (ver ${Qt5Core_VERSION_STRING})" ELSE NO) + status(" QT OpenGL support:" HAVE_QT_OPENGL THEN "YES (${Qt5OpenGL_LIBRARIES} ${Qt5OpenGL_VERSION_STRING})" ELSE NO) +elseif(HAVE_QT) status(" QT 4.x:" HAVE_QT THEN "YES (ver ${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}.${QT_VERSION_PATCH} ${QT_EDITION})" ELSE NO) status(" QT OpenGL support:" HAVE_QT_OPENGL THEN "YES (${QT_QTOPENGL_LIBRARY})" ELSE NO) else() if(DEFINED WITH_QT) - status(" QT 4.x:" NO) + status(" QT:" NO) endif() - if(WIN32) - status(" Win32 UI:" YES) + if(DEFINED WITH_WIN32UI) + status(" Win32 UI:" HAVE_WIN32UI THEN YES ELSE NO) else() if(APPLE) if(WITH_CARBON) @@ -630,7 +614,7 @@ status(" OpenGL support:" HAVE_OPENGL THEN "YES (${OPENGL_LIBRARIES})" ELSE N # ========================== MEDIA IO ========================== status("") status(" Media I/O: ") -status(" ZLib:" BUILD_ZLIB THEN "build (ver ${ZLIB_VERSION_STRING})" ELSE "${ZLIB_LIBRARY} (ver ${ZLIB_VERSION_STRING})") +status(" ZLib:" BUILD_ZLIB THEN "build (ver ${ZLIB_VERSION_STRING})" ELSE "${ZLIB_LIBRARIES} (ver ${ZLIB_VERSION_STRING})") if(WITH_JPEG) status(" JPEG:" JPEG_FOUND THEN "${JPEG_LIBRARY} (ver ${JPEG_LIB_VERSION})" ELSE "build (ver ${JPEG_LIB_VERSION})") @@ -673,6 +657,10 @@ endif() status("") status(" Video I/O:") +if (DEFINED WITH_VFW) + status(" Video for Windows:" HAVE_VFW THEN YES ELSE NO) +endif(DEFINED WITH_VFW) + if(DEFINED WITH_1394) status(" DC1394 1.x:" HAVE_DC1394 THEN "YES (ver ${ALIASOF_libdc1394_VERSION})" ELSE NO) status(" DC1394 2.x:" HAVE_DC1394_2 THEN "YES (ver ${ALIASOF_libdc1394-2_VERSION})" ELSE NO) @@ -707,10 +695,12 @@ endif(DEFINED WITH_FFMPEG) if(DEFINED WITH_GSTREAMER) status(" GStreamer:" HAVE_GSTREAMER THEN "" ELSE NO) if(HAVE_GSTREAMER) - status(" base:" "YES (ver ${ALIASOF_gstreamer-base-0.10_VERSION})") - status(" app:" "YES (ver ${ALIASOF_gstreamer-app-0.10_VERSION})") - status(" video:" "YES (ver ${ALIASOF_gstreamer-video-0.10_VERSION})") - endif() + status(" base:" "YES (ver ${GSTREAMER_BASE_VERSION})") + status(" video:" "YES (ver ${GSTREAMER_VIDEO_VERSION})") + status(" app:" "YES (ver ${GSTREAMER_APP_VERSION})") + status(" riff:" "YES (ver ${GSTREAMER_RIFF_VERSION})") + status(" pbutils:" "YES (ver ${GSTREAMER_PBUTILS_VERSION})") + endif(HAVE_GSTREAMER) endif(DEFINED WITH_GSTREAMER) if(DEFINED WITH_OPENNI) @@ -729,8 +719,8 @@ if(DEFINED WITH_GIGEAPI) endif(DEFINED WITH_GIGEAPI) if(DEFINED WITH_QUICKTIME) - status(" QuickTime:" WITH_QUICKTIME THEN YES ELSE NO) - status(" QTKit:" WITH_QUICKTIME THEN NO ELSE YES) + status(" QuickTime:" HAVE_QUICKTIME THEN YES ELSE NO) + status(" QTKit:" HAVE_QTKIT THEN YES ELSE NO) endif(DEFINED WITH_QUICKTIME) if(DEFINED WITH_UNICAP) @@ -755,9 +745,13 @@ if(DEFINED WITH_V4L) ELSE "${HAVE_CAMV4L_STR}/${HAVE_CAMV4L2_STR}") endif(DEFINED WITH_V4L) -if(DEFINED WITH_VIDEOINPUT) - status(" DirectShow:" HAVE_VIDEOINPUT THEN YES ELSE NO) -endif(DEFINED WITH_VIDEOINPUT) +if(DEFINED WITH_DSHOW) + status(" DirectShow:" HAVE_DSHOW THEN YES ELSE NO) +endif(DEFINED WITH_DSHOW) + +if(DEFINED WITH_MSMF) + status(" Media Foundation:" HAVE_MSMF THEN YES ELSE NO) +endif(DEFINED WITH_MSMF) if(DEFINED WITH_XIMEA) status(" XIMEA:" HAVE_XIMEA THEN YES ELSE NO) @@ -799,11 +793,11 @@ if(HAVE_CUDA) status(" Use fast math:" CUDA_FAST_MATH THEN YES ELSE NO) endif() -if(HAVE_OPENCL AND BUILD_opencv_ocl) +if(HAVE_OPENCL) status("") status(" OpenCL") if(OPENCL_INCLUDE_DIR) - status(" Include:" ${OPENCL_INCLUDE_DIR}) + status(" Include path:" ${OPENCL_INCLUDE_DIRS}) endif() if(OPENCL_LIBRARIES) status(" libraries:" ${OPENCL_LIBRARIES}) @@ -815,15 +809,15 @@ endif() # ========================== python ========================== status("") status(" Python:") -status(" Interpreter:" PYTHON_EXECUTABLE THEN "${PYTHON_EXECUTABLE} (ver ${PYTHON_VERSION_FULL})" ELSE NO) +status(" Interpreter:" PYTHONINTERP_FOUND THEN "${PYTHON_EXECUTABLE} (ver ${PYTHON_VERSION_STRING})" ELSE NO) if(BUILD_opencv_python) if(PYTHONLIBS_VERSION_STRING) status(" Libraries:" HAVE_opencv_python THEN "${PYTHON_LIBRARIES} (ver ${PYTHONLIBS_VERSION_STRING})" ELSE NO) else() - status(" Libraries:" HAVE_opencv_python THEN ${PYTHON_LIBRARIES} ELSE NO) + status(" Libraries:" HAVE_opencv_python THEN "${PYTHON_LIBRARIES}" ELSE NO) endif() - status(" numpy:" PYTHON_USE_NUMPY THEN "${PYTHON_NUMPY_INCLUDE_DIR} (ver ${PYTHON_NUMPY_VERSION})" ELSE "NO (Python wrappers can not be generated)") - status(" packages path:" PYTHON_EXECUTABLE THEN "${PYTHON_PACKAGES_PATH}" ELSE "-") + status(" numpy:" PYTHON_NUMPY_INCLUDE_DIRS THEN "${PYTHON_NUMPY_INCLUDE_DIRS} (ver ${PYTHON_NUMPY_VERSION})" ELSE "NO (Python wrappers can not be generated)") + status(" packages path:" PYTHON_EXECUTABLE THEN "${PYTHON_PACKAGES_PATH}" ELSE "-") endif() # ========================== java ========================== @@ -833,7 +827,7 @@ status(" ant:" ANT_EXECUTABLE THEN "${ANT_EXECUTABLE} (ver ${A if(NOT ANDROID) status(" JNI:" JNI_INCLUDE_DIRS THEN "${JNI_INCLUDE_DIRS}" ELSE NO) endif() -status(" Java tests:" BUILD_TESTS AND (NOT ANDROID OR CAN_BUILD_ANDROID_PROJECTS) THEN YES ELSE NO) +status(" Java tests:" BUILD_TESTS AND (CAN_BUILD_ANDROID_PROJECTS OR HAVE_opencv_java) THEN YES ELSE NO) # ========================== documentation ========================== if(BUILD_DOCS) @@ -846,6 +840,7 @@ if(BUILD_DOCS) endif() status(" Sphinx:" HAVE_SPHINX THEN "${SPHINX_BUILD} (ver ${SPHINX_VERSION})" ELSE NO) status(" PdfLaTeX compiler:" PDFLATEX_COMPILER THEN "${PDFLATEX_COMPILER}" ELSE NO) + status(" PlantUML:" PLANTUML THEN "${PLANTUML}" ELSE NO) endif() # ========================== samples and tests ========================== @@ -871,4 +866,3 @@ ocv_finalize_status() if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") message(WARNING "The source directory is the same as binary directory. \"make clean\" may damage the source tree") endif() - diff --git a/README b/README deleted file mode 100644 index 9dd45a230b..0000000000 --- a/README +++ /dev/null @@ -1,6 +0,0 @@ -OpenCV: open source computer vision library - -Homepage: http://opencv.org -Online docs: http://docs.opencv.org -Q&A forum: http://answers.opencv.org -Dev zone: http://code.opencv.org diff --git a/README.md b/README.md new file mode 100644 index 0000000000..403f118eed --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +### OpenCV: Open Source Computer Vision Library + +#### Resources + +* Homepage: +* Docs: +* Q&A forum: +* Issue tracking: + +#### Contributing + +Please read before starting work on a pull request: + +Summary of guidelines: + +* One pull request per issue; +* Choose the right base branch; +* Include tests and documentation; +* Clean up "oops" commits before submitting; +* Follow the coding style guide. + +[![Donate OpenCV project](http://opencv.org/wp-content/uploads/2013/07/gittip1.png)](https://www.gittip.com/OpenCV/) +[![Donate OpenCV project](http://opencv.org/wp-content/uploads/2013/07/paypal-donate-button.png)](https://www.paypal.com/cgi-bin/webscr?item_name=Donation+to+OpenCV&cmd=_donations&business=accountant%40opencv.org) \ No newline at end of file diff --git a/android/scripts/build.cmd b/android/scripts/build.cmd deleted file mode 100644 index 3e0f1666b6..0000000000 --- a/android/scripts/build.cmd +++ /dev/null @@ -1,90 +0,0 @@ -@ECHO OFF - -:: enable command extensions -VERIFY BADVALUE 2>NUL -SETLOCAL ENABLEEXTENSIONS || (ECHO Unable to enable command extensions. & EXIT \B) - -:: build environment -SET SOURCE_DIR=%cd% -IF EXIST .\android.toolchain.cmake (SET BUILD_OPENCV=1) ELSE (SET BUILD_OPENCV=0) -IF EXIST .\jni\nul (SET BUILD_JAVA_PART=1) ELSE (SET BUILD_JAVA_PART=0) - -:: load configuration -PUSHD %~dp0 -SET SCRIPTS_DIR=%cd% -IF EXIST .\wincfg.cmd CALL .\wincfg.cmd -POPD - -:: inherit old names -IF NOT DEFINED CMAKE SET CMAKE=%CMAKE_EXE% -IF NOT DEFINED MAKE SET MAKE=%MAKE_EXE% - -:: defaults -IF NOT DEFINED BUILD_DIR SET BUILD_DIR=build -IF NOT DEFINED ANDROID_ABI SET ANDROID_ABI=armeabi-v7a -SET OPENCV_BUILD_DIR=%SCRIPTS_DIR%\..\%BUILD_DIR% - -:: check that all required variables defined -PUSHD . -IF NOT DEFINED ANDROID_NDK (ECHO. & ECHO You should set an environment variable ANDROID_NDK to the full path to your copy of Android NDK & GOTO end) -(CD "%ANDROID_NDK%") || (ECHO. & ECHO Directory "%ANDROID_NDK%" specified by ANDROID_NDK variable does not exist & GOTO end) - -IF NOT EXIST "%CMAKE%" (ECHO. & ECHO You should set an environment variable CMAKE to the full path to cmake executable & GOTO end) -IF NOT EXIST "%MAKE%" (ECHO. & ECHO You should set an environment variable MAKE to the full path to native port of make executable & GOTO end) - -IF NOT %BUILD_JAVA_PART%==1 GOTO required_variables_checked - -IF NOT DEFINED ANDROID_SDK (ECHO. & ECHO You should set an environment variable ANDROID_SDK to the full path to your copy of Android SDK & GOTO end) -(CD "%ANDROID_SDK%" 2>NUL) || (ECHO. & ECHO Directory "%ANDROID_SDK%" specified by ANDROID_SDK variable does not exist & GOTO end) - -IF NOT DEFINED ANT_DIR (ECHO. & ECHO You should set an environment variable ANT_DIR to the full path to Apache Ant root & GOTO end) -(CD "%ANT_DIR%" 2>NUL) || (ECHO. & ECHO Directory "%ANT_DIR%" specified by ANT_DIR variable does not exist & GOTO end) - -IF NOT DEFINED JAVA_HOME (ECHO. & ECHO You should set an environment variable JAVA_HOME to the full path to JDK & GOTO end) -(CD "%JAVA_HOME%" 2>NUL) || (ECHO. & ECHO Directory "%JAVA_HOME%" specified by JAVA_HOME variable does not exist & GOTO end) - -:required_variables_checked -POPD - -:: check for ninja -echo "%MAKE%"|findstr /i ninja >nul: -IF %errorlevel%==1 (SET BUILD_WITH_NINJA=0) ELSE (SET BUILD_WITH_NINJA=1) -IF %BUILD_WITH_NINJA%==1 (SET CMAKE_GENERATOR=Ninja) ELSE (SET CMAKE_GENERATOR=MinGW Makefiles) - -:: create build dir -IF DEFINED REBUILD rmdir /S /Q "%BUILD_DIR%" 2>NUL -MKDIR "%BUILD_DIR%" 2>NUL -PUSHD "%BUILD_DIR%" || (ECHO. & ECHO Directory "%BUILD_DIR%" is not found & GOTO end) - -:: run cmake -ECHO. & ECHO Runnning cmake... -ECHO ANDROID_ABI=%ANDROID_ABI% -ECHO. -IF NOT %BUILD_OPENCV%==1 GOTO other-cmake -:opencv-cmake -("%CMAKE%" -G"%CMAKE_GENERATOR%" -DANDROID_ABI="%ANDROID_ABI%" -DCMAKE_TOOLCHAIN_FILE="%SOURCE_DIR%"\android.toolchain.cmake -DCMAKE_MAKE_PROGRAM="%MAKE%" %* "%SOURCE_DIR%\..") && GOTO cmakefin -ECHO. & ECHO cmake failed & GOTO end -:other-cmake -("%CMAKE%" -G"%CMAKE_GENERATOR%" -DANDROID_ABI="%ANDROID_ABI%" -DOpenCV_DIR="%OPENCV_BUILD_DIR%" -DCMAKE_TOOLCHAIN_FILE="%OPENCV_BUILD_DIR%\..\android.toolchain.cmake" -DCMAKE_MAKE_PROGRAM="%MAKE%" %* "%SOURCE_DIR%") && GOTO cmakefin -ECHO. & ECHO cmake failed & GOTO end -:cmakefin - -:: run make -ECHO. & ECHO Building native libs... -IF %BUILD_WITH_NINJA%==0 ("%MAKE%" -j %NUMBER_OF_PROCESSORS% VERBOSE=%VERBOSE%) || (ECHO. & ECHO make failed & GOTO end) -IF %BUILD_WITH_NINJA%==1 ("%MAKE%") || (ECHO. & ECHO ninja failed & GOTO end) - -IF NOT %BUILD_JAVA_PART%==1 GOTO end -POPD && PUSHD %SOURCE_DIR% - -:: configure java part -ECHO. & ECHO Updating Android project... -(CALL "%ANDROID_SDK%\tools\android" update project --name %PROJECT_NAME% --path .) || (ECHO. & ECHO failed to update android project & GOTO end) - -:: compile java part -ECHO. & ECHO Compiling Android project... -(CALL "%ANT_DIR%\bin\ant" debug) || (ECHO. & ECHO failed to compile android project & GOTO end) - -:end -POPD -ENDLOCAL diff --git a/android/scripts/cmake_android.cmd b/android/scripts/cmake_android.cmd deleted file mode 100644 index 212c04b47e..0000000000 --- a/android/scripts/cmake_android.cmd +++ /dev/null @@ -1,5 +0,0 @@ -@ECHO OFF - -PUSHD %~dp0.. -CALL .\scripts\build.cmd %* -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON -POPD \ No newline at end of file diff --git a/android/scripts/cmake_android_armeabi.sh b/android/scripts/cmake_android_armeabi.sh deleted file mode 100755 index 9c711d8855..0000000000 --- a/android/scripts/cmake_android_armeabi.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -cd `dirname $0`/.. - -mkdir -p build_armeabi -cd build_armeabi - -cmake -DANDROID_ABI=armeabi -DCMAKE_TOOLCHAIN_FILE=../android.toolchain.cmake $@ ../.. - diff --git a/android/scripts/cmake_android_mips.sh b/android/scripts/cmake_android_mips.sh deleted file mode 100755 index 17d2ff937e..0000000000 --- a/android/scripts/cmake_android_mips.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -cd `dirname $0`/.. - -mkdir -p build_mips -cd build_mips - -cmake -DANDROID_ABI=mips -DCMAKE_TOOLCHAIN_FILE=../android.toolchain.cmake $@ ../.. - diff --git a/android/scripts/cmake_android_neon.sh b/android/scripts/cmake_android_neon.sh deleted file mode 100755 index 5e85605b56..0000000000 --- a/android/scripts/cmake_android_neon.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -cd `dirname $0`/.. - -mkdir -p build_neon -cd build_neon - -cmake -DANDROID_ABI="armeabi-v7a with NEON" -DCMAKE_TOOLCHAIN_FILE=../android.toolchain.cmake $@ ../.. - diff --git a/android/scripts/cmake_android_service.sh b/android/scripts/cmake_android_service.sh deleted file mode 100755 index 0dbd482520..0000000000 --- a/android/scripts/cmake_android_service.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -cd `dirname $0`/.. - -mkdir -p build_service -cd build_service - -cmake -DCMAKE_TOOLCHAIN_FILE=../android.toolchain.cmake -DANDROID_TOOLCHAIN_NAME="arm-linux-androideabi-4.4.3" -DANDROID_STL=stlport_static -DANDROID_STL_FORCE_FEATURES=OFF -DBUILD_ANDROID_SERVICE=ON -DANDROID_SOURCE_TREE=~/Projects/AndroidSource/ServiceStub/ $@ ../.. diff --git a/android/scripts/cmake_android_x86.sh b/android/scripts/cmake_android_x86.sh deleted file mode 100755 index a01df2e668..0000000000 --- a/android/scripts/cmake_android_x86.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -cd `dirname $0`/.. - -mkdir -p build_x86 -cd build_x86 - -cmake -DANDROID_ABI=x86 -DCMAKE_TOOLCHAIN_FILE=../android.toolchain.cmake $@ ../.. - diff --git a/android/scripts/wincfg.cmd.tmpl b/android/scripts/wincfg.cmd.tmpl deleted file mode 100644 index 166a5e7b02..0000000000 --- a/android/scripts/wincfg.cmd.tmpl +++ /dev/null @@ -1,30 +0,0 @@ -:: variables required for OpenCV build :: -:: Note: all pathes should be specified without tailing slashes! -SET ANDROID_NDK=C:\full\path\to\your\copy\of\android\NDK\android-ndk-r7b -SET CMAKE_EXE=C:\full\path\to\cmake\utility\cmake.exe -SET MAKE_EXE=%ANDROID_NDK%\prebuilt\windows\bin\make.exe - -:: variables required for android-opencv build :: -SET ANDROID_SDK=C:\full\path\to\your\copy\of\android\SDK\android-sdk-windows -SET ANT_DIR=C:\full\path\to\ant\directory\apache-ant-1.8.2 -SET JAVA_HOME=C:\full\path\to\JDK\jdk1.6.0_25 - -:: configuration options :: -:::: general ARM-V7 settings -SET ANDROID_ABI=armeabi-v7a -SET BUILD_DIR=build - -:::: uncomment following lines to compile for old emulator or old device -::SET ANDROID_ABI=armeabi -::SET BUILD_DIR=build_armeabi - -:::: uncomment following lines to compile for ARM-V7 with NEON support -::SET ANDROID_ABI=armeabi-v7a with NEON -::SET BUILD_DIR=build_neon - -:::: uncomment following lines to compile for x86 -::SET ANDROID_ABI=x86 -::SET BUILD_DIR=build_x86 - -:::: other options -::SET ANDROID_NATIVE_API_LEVEL=8 &:: android-3 is enough for native part of OpenCV but android-8 is required for Java API diff --git a/android/service/doc/Makefile b/android/service/doc/Makefile deleted file mode 100644 index b8e7bba113..0000000000 --- a/android/service/doc/Makefile +++ /dev/null @@ -1,89 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = _build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/OpenCVEngine.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/OpenCVEngine.qhc" - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ - "run these through (pdf)latex." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/android/service/engine/jni/BinderComponent/TegraDetector.cpp b/android/service/engine/jni/BinderComponent/TegraDetector.cpp deleted file mode 100644 index f7db1fa85d..0000000000 --- a/android/service/engine/jni/BinderComponent/TegraDetector.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "TegraDetector.h" -#include -#include - -#define KERNEL_CONFIG "/proc/config.gz" -#define KERNEL_CONFIG_MAX_LINE_WIDTH 512 -#define KERNEL_CONFIG_TEGRA_MAGIC "CONFIG_ARCH_TEGRA=y" -#define KERNEL_CONFIG_TEGRA2_MAGIC "CONFIG_ARCH_TEGRA_2x_SOC=y" -#define KERNEL_CONFIG_TEGRA3_MAGIC "CONFIG_ARCH_TEGRA_3x_SOC=y" -#define MAX_DATA_LEN 4096 - -int DetectTegra() -{ - int result = TEGRA_NOT_TEGRA; - gzFile kernelConfig = gzopen(KERNEL_CONFIG, "r"); - if (kernelConfig != 0) - { - char tmpbuf[KERNEL_CONFIG_MAX_LINE_WIDTH]; - const char *tegra_config = KERNEL_CONFIG_TEGRA_MAGIC; - const char *tegra2_config = KERNEL_CONFIG_TEGRA2_MAGIC; - const char *tegra3_config = KERNEL_CONFIG_TEGRA3_MAGIC; - int len = strlen(tegra_config); - int len2 = strlen(tegra2_config); - int len3 = strlen(tegra3_config); - while (0 != gzgets(kernelConfig, tmpbuf, KERNEL_CONFIG_MAX_LINE_WIDTH)) - { - if (0 == strncmp(tmpbuf, tegra_config, len)) - { - result = 1; - } - - if (0 == strncmp(tmpbuf, tegra2_config, len2)) - { - result = 2; - break; - } - - if (0 == strncmp(tmpbuf, tegra3_config, len3)) - { - result = 3; - break; - } - - } - gzclose(kernelConfig); - } - else - { - result = TEGRA_DETECTOR_ERROR; - } - - return result; -} \ No newline at end of file diff --git a/android/service/engine/jni/BinderComponent/TegraDetector.h b/android/service/engine/jni/BinderComponent/TegraDetector.h deleted file mode 100644 index 8fbdb607a1..0000000000 --- a/android/service/engine/jni/BinderComponent/TegraDetector.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __TEGRA_DETECTOR_H__ -#define __TEGRA_DETECTOR_H__ - -#define TEGRA_DETECTOR_ERROR -2 -#define TEGRA_NOT_TEGRA -1 - -int DetectTegra(); - -#endif \ No newline at end of file diff --git a/android/service/engine/src/org/opencv/engine/BinderConnector.java b/android/service/engine/src/org/opencv/engine/BinderConnector.java deleted file mode 100644 index fd23fbfe49..0000000000 --- a/android/service/engine/src/org/opencv/engine/BinderConnector.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.opencv.engine; - -import android.os.IBinder; - -public class BinderConnector -{ - public BinderConnector(MarketConnector Market) - { - Init(Market); - } - public native IBinder Connect(); - public boolean Disconnect() - { - Final(); - return true; - } - - static - { - System.loadLibrary("OpenCVEngine"); - System.loadLibrary("OpenCVEngine_jni"); - } - - private native boolean Init(MarketConnector Market); - public native void Final(); -} diff --git a/android/service/engine/src/org/opencv/engine/OpenCVEngineService.java b/android/service/engine/src/org/opencv/engine/OpenCVEngineService.java deleted file mode 100644 index df31c7fe8e..0000000000 --- a/android/service/engine/src/org/opencv/engine/OpenCVEngineService.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.opencv.engine; - -import android.app.Service; -import android.content.Intent; -import android.os.IBinder; -import android.util.Log; - - -public class OpenCVEngineService extends Service -{ - private static final String TAG = "OpenCVEngine/Service"; - private IBinder mEngineInterface; - private MarketConnector mMarket; - private BinderConnector mNativeBinder; - public void onCreate() - { - Log.i(TAG, "Service starting"); - super.onCreate(); - Log.i(TAG, "Engine binder component creating"); - mMarket = new MarketConnector(getBaseContext()); - mNativeBinder = new BinderConnector(mMarket); - mEngineInterface = mNativeBinder.Connect(); - Log.i(TAG, "Service started successfully"); - } - - public IBinder onBind(Intent intent) - { - Log.i(TAG, "Service onBind called for intent " + intent.toString()); - return mEngineInterface; - } - public boolean onUnbind(Intent intent) - { - Log.i(TAG, "Service onUnbind called for intent " + intent.toString()); - return true; - } - public void OnDestroy() - { - Log.i(TAG, "OpenCV Engine service destruction"); - mNativeBinder.Disconnect(); - } - -} diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index ad0f0daade..f5ac42a018 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -3,4 +3,3 @@ add_definitions(-D__OPENCV_BUILD=1) add_subdirectory(haartraining) add_subdirectory(traincascade) add_subdirectory(sft) - diff --git a/apps/haartraining/CMakeLists.txt b/apps/haartraining/CMakeLists.txt index 953be3b7e5..7a197db837 100644 --- a/apps/haartraining/CMakeLists.txt +++ b/apps/haartraining/CMakeLists.txt @@ -1,4 +1,4 @@ -SET(OPENCV_HAARTRAINING_DEPS opencv_core opencv_imgproc opencv_highgui opencv_objdetect opencv_calib3d opencv_video opencv_features2d opencv_flann opencv_legacy) +SET(OPENCV_HAARTRAINING_DEPS opencv_core opencv_imgproc opencv_photo opencv_ml opencv_highgui opencv_objdetect opencv_calib3d opencv_video opencv_features2d opencv_flann opencv_legacy) ocv_check_dependencies(${OPENCV_HAARTRAINING_DEPS}) if(NOT OCV_DEPENDENCIES_FOUND) @@ -79,4 +79,3 @@ if(ENABLE_SOLUTION_FOLDERS) set_target_properties(opencv_haartraining PROPERTIES FOLDER "applications") set_target_properties(opencv_haartraining_engine PROPERTIES FOLDER "applications") endif() - diff --git a/apps/haartraining/_cvcommon.h b/apps/haartraining/_cvcommon.h index 5b363f1fce..92fee8e84a 100644 --- a/apps/haartraining/_cvcommon.h +++ b/apps/haartraining/_cvcommon.h @@ -43,7 +43,6 @@ #define __CVCOMMON_H_ #include "opencv2/core.hpp" -#include "opencv2/core/internal.hpp" #include "cxcore.h" #include "cv.h" @@ -53,15 +52,6 @@ #define __END__ __CV_END__ #define EXIT __CV_EXIT__ -#define CV_DECLARE_QSORT( func_name, T, less_than ) \ -void func_name( T* array, size_t length, int aux ); - -#define less_than( a, b ) ((a) < (b)) - -CV_DECLARE_QSORT( icvSort_32f, float, less_than ) - -CV_DECLARE_QSORT( icvSort_32s, int, less_than ) - #ifndef PATH_MAX #define PATH_MAX 512 #endif /* PATH_MAX */ @@ -100,4 +90,3 @@ int icvGetIdxAt( CvMat* idx, int pos ) void icvSave( const CvArr* ptr, const char* filename, int line ); #endif /* __CVCOMMON_H_ */ - diff --git a/apps/haartraining/cvboost.cpp b/apps/haartraining/cvboost.cpp index 8dfd3dd316..4b9f24f1bc 100644 --- a/apps/haartraining/cvboost.cpp +++ b/apps/haartraining/cvboost.cpp @@ -39,9 +39,7 @@ // //M*/ -#ifdef HAVE_CVCONFIG_H - #include "cvconfig.h" -#endif +#include "cvconfig.h" #ifdef HAVE_MALLOC_H #include @@ -76,15 +74,18 @@ typedef struct CvValArray size_t step; } CvValArray; -#define CMP_VALUES( idx1, idx2 ) \ - ( *( (float*) (aux->data + ((int) (idx1)) * aux->step ) ) < \ - *( (float*) (aux->data + ((int) (idx2)) * aux->step ) ) ) - -static CV_IMPLEMENT_QSORT_EX( icvSortIndexedValArray_16s, short, CMP_VALUES, CvValArray* ) - -static CV_IMPLEMENT_QSORT_EX( icvSortIndexedValArray_32s, int, CMP_VALUES, CvValArray* ) - -static CV_IMPLEMENT_QSORT_EX( icvSortIndexedValArray_32f, float, CMP_VALUES, CvValArray* ) +template +class LessThanValArray +{ +public: + LessThanValArray( const T* _aux ) : aux(_aux) {} + bool operator()(Idx a, Idx b) const + { + return *( (float*) (aux->data + ((int) (a)) * aux->step ) ) < + *( (float*) (aux->data + ((int) (b)) * aux->step ) ); + } + const T* aux; +}; CV_BOOST_IMPL void cvGetSortedIndices( CvMat* val, CvMat* idx, int sortcols ) @@ -130,8 +131,9 @@ void cvGetSortedIndices( CvMat* val, CvMat* idx, int sortcols ) { CV_MAT_ELEM( *idx, short, i, j ) = (short) j; } - icvSortIndexedValArray_16s( (short*) (idx->data.ptr + (size_t)i * idx->step), - idx->cols, &va ); + std::sort((short*) (idx->data.ptr + (size_t)i * idx->step), + (short*) (idx->data.ptr + (size_t)i * idx->step) + idx->cols, + LessThanValArray(&va)); va.data += istep; } break; @@ -143,8 +145,9 @@ void cvGetSortedIndices( CvMat* val, CvMat* idx, int sortcols ) { CV_MAT_ELEM( *idx, int, i, j ) = j; } - icvSortIndexedValArray_32s( (int*) (idx->data.ptr + (size_t)i * idx->step), - idx->cols, &va ); + std::sort((int*) (idx->data.ptr + (size_t)i * idx->step), + (int*) (idx->data.ptr + (size_t)i * idx->step) + idx->cols, + LessThanValArray(&va)); va.data += istep; } break; @@ -156,8 +159,9 @@ void cvGetSortedIndices( CvMat* val, CvMat* idx, int sortcols ) { CV_MAT_ELEM( *idx, float, i, j ) = (float) j; } - icvSortIndexedValArray_32f( (float*) (idx->data.ptr + (size_t)i * idx->step), - idx->cols, &va ); + std::sort((float*) (idx->data.ptr + (size_t)i * idx->step), + (float*) (idx->data.ptr + (size_t)i * idx->step) + idx->cols, + LessThanValArray(&va)); va.data += istep; } break; @@ -545,7 +549,7 @@ CvClassifier* cvCreateStumpClassifier( CvMat* trainData, va.data = data + i * ((size_t) cstep); va.step = sstep; - icvSortIndexedValArray_32s( idx, l, &va ); + std::sort(idx, idx + l, LessThanValArray(&va)); if( findStumpThreshold_32s[(int) ((CvStumpTrainParams*) trainParams)->error] ( data + i * ((size_t) cstep), sstep, wdata, wstep, ydata, ystep, (uchar*) idx, sizeof( int ), l, @@ -1028,7 +1032,7 @@ CvClassifier* cvCreateMTStumpClassifier( CvMat* trainData, { va.data = t_data + ti * t_cstep; va.step = t_sstep; - icvSortIndexedValArray_32s( t_idx, l, &va ); + std::sort(t_idx, t_idx + l, LessThanValArray(&va)); if( findStumpThreshold_32s[stumperror]( t_data + ti * t_cstep, t_sstep, wdata, wstep, ydata, ystep, @@ -2096,7 +2100,7 @@ static void icvZeroApproxMed( float* approx, CvBtTrainer* trainer ) trainer->f[i] = *((float*) (trainer->ydata + idx * trainer->ystep)); } - icvSort_32f( trainer->f, trainer->numsamples, 0 ); + std::sort(trainer->f, trainer->f + trainer->numsamples); approx[0] = trainer->f[trainer->numsamples / 2]; } @@ -2341,7 +2345,7 @@ static void icvBtNext_LADREG( CvCARTClassifier** trees, CvBtTrainer* trainer ) } if( respnum > 0 ) { - icvSort_32f( resp, respnum, 0 ); + std::sort(resp, resp + respnum); val = resp[respnum / 2]; } else @@ -2394,7 +2398,7 @@ static void icvBtNext_MREG( CvCARTClassifier** trees, CvBtTrainer* trainer ) } /* delta = quantile_alpha{abs(resid_i)} */ - icvSort_32f( resp, trainer->numsamples, 0 ); + std::sort(resp, resp + trainer->numsamples); delta = resp[(int)(trainer->param[1] * (trainer->numsamples - 1))]; /* yhat_i */ @@ -2434,7 +2438,7 @@ static void icvBtNext_MREG( CvCARTClassifier** trees, CvBtTrainer* trainer ) if( respnum > 0 ) { /* rhat = median(y_i - F_(m-1)(x_i)) */ - icvSort_32f( resp, respnum, 0 ); + std::sort(resp, resp + respnum); rhat = resp[respnum / 2]; /* val = sum{sign(r_i - rhat_i) * min(delta, abs(r_i - rhat_i)} @@ -2531,7 +2535,7 @@ static void icvBtNext_L2CLASS( CvCARTClassifier** trees, CvBtTrainer* trainer ) float threshold; int count; - icvSort_32f( sorted_weights, trainer->numsamples, 0 ); + std::sort(sorted_weights, sorted_weights + trainer->numsamples); sum_weights *= (1.0F - trainer->param[1]); @@ -2693,7 +2697,7 @@ static void icvBtNext_LKCLASS( CvCARTClassifier** trees, CvBtTrainer* trainer ) float threshold; int count; - icvSort_32f( sorted_weights, trainer->numsamples, 0 ); + std::sort(sorted_weights, sorted_weights + trainer->numsamples); sum_weights *= (1.0F - trainer->param[1]); @@ -3504,7 +3508,7 @@ CvMat* cvTrimWeights( CvMat* weights, CvMat* idx, float factor ) sum_weights += sorted_weights[i]; } - icvSort_32f( sorted_weights, num, 0 ); + std::sort(sorted_weights, sorted_weights + num); sum_weights *= (1.0F - factor); diff --git a/apps/haartraining/cvclassifier.h b/apps/haartraining/cvclassifier.h index df644ed173..9a43441187 100644 --- a/apps/haartraining/cvclassifier.h +++ b/apps/haartraining/cvclassifier.h @@ -112,7 +112,9 @@ CV_INLINE float cvLogRatio( float val ) /* each trainData matrix row is a sample */ #define CV_ROW_SAMPLE 1 -#define CV_IS_ROW_SAMPLE( flags ) ( ( flags ) & CV_ROW_SAMPLE ) +#ifndef CV_IS_ROW_SAMPLE +# define CV_IS_ROW_SAMPLE( flags ) ( ( flags ) & CV_ROW_SAMPLE ) +#endif /* Classifier supports tune function */ #define CV_TUNABLE (1 << 1) diff --git a/apps/haartraining/cvcommon.cpp b/apps/haartraining/cvcommon.cpp index 013256b6d8..e23fab263b 100644 --- a/apps/haartraining/cvcommon.cpp +++ b/apps/haartraining/cvcommon.cpp @@ -50,11 +50,6 @@ #include #endif /* _WIN32 */ - -CV_IMPLEMENT_QSORT( icvSort_32f, float, less_than ) - -CV_IMPLEMENT_QSORT( icvSort_32s, int, less_than ) - int icvMkDir( const char* filename ) { char path[PATH_MAX]; diff --git a/apps/haartraining/cvhaartraining.cpp b/apps/haartraining/cvhaartraining.cpp index 661bc959be..2fcf76a4b5 100644 --- a/apps/haartraining/cvhaartraining.cpp +++ b/apps/haartraining/cvhaartraining.cpp @@ -1088,7 +1088,7 @@ CvIntHaarClassifier* icvCreateCARTStageClassifier( CvHaarTrainingData* data, numpos++; } } - icvSort_32f( eval.data.fl, numpos, 0 ); + std::sort(eval.data.fl, eval.data.fl + numpos); threshold = eval.data.fl[(int) ((1.0F - minhitrate) * numpos)]; numneg = 0; @@ -2291,7 +2291,7 @@ static CvMat* icvGetUsedValues( CvHaarTrainingData* training_data, feature_idx->data.i[total++] = cart->compidx[j]; } } - icvSort_32s( feature_idx->data.i, total, 0 ); + std::sort(feature_idx->data.i, feature_idx->data.i + total); last = 0; for( i = 1; i < total; i++ ) @@ -2676,7 +2676,7 @@ void cvCreateTreeCascadeClassifier( const char* dirname, CvSplit* curSplit; CV_CALL( curSplit = (CvSplit*) cvAlloc( sizeof( *curSplit ) ) ); - CV_ZERO_OBJ( curSplit ); + memset(curSplit, 0, sizeof(*curSplit)); if( last_split ) last_split->next = curSplit; else first_split = curSplit; diff --git a/apps/haartraining/performance.cpp b/apps/haartraining/performance.cpp index 0620f21a1b..cb8dda1c83 100644 --- a/apps/haartraining/performance.cpp +++ b/apps/haartraining/performance.cpp @@ -45,7 +45,6 @@ * Measure performance of classifier */ #include "opencv2/core.hpp" -#include "opencv2/core/internal.hpp" #include "cv.h" #include "highgui.h" @@ -376,4 +375,3 @@ int main( int argc, char* argv[] ) return 0; } - diff --git a/apps/sft/CMakeLists.txt b/apps/sft/CMakeLists.txt index 8b950225c8..05bd337c34 100644 --- a/apps/sft/CMakeLists.txt +++ b/apps/sft/CMakeLists.txt @@ -30,4 +30,4 @@ if(ENABLE_SOLUTION_FOLDERS) set_target_properties(${the_target} PROPERTIES FOLDER "applications") endif() -install(TARGETS ${the_target} RUNTIME DESTINATION bin COMPONENT main) \ No newline at end of file +install(TARGETS ${the_target} RUNTIME DESTINATION bin COMPONENT main) diff --git a/apps/sft/config.cpp b/apps/sft/config.cpp index 3cc64c7fec..9157575a1e 100644 --- a/apps/sft/config.cpp +++ b/apps/sft/config.cpp @@ -159,4 +159,4 @@ std::ostream& sft::operator<<(std::ostream& out, const Config& m) << std::setw(14) << std::left << "featureType" << m.featureType << std::endl; return out; -} \ No newline at end of file +} diff --git a/apps/sft/include/sft/common.hpp b/apps/sft/include/sft/common.hpp index 93439a48ed..5c142a749d 100644 --- a/apps/sft/include/sft/common.hpp +++ b/apps/sft/include/sft/common.hpp @@ -44,6 +44,7 @@ #define __SFT_COMMON_HPP__ #include +#include #include namespace cv {using namespace softcascade;} @@ -53,7 +54,7 @@ namespace sft using cv::Mat; struct ICF; - typedef std::string string; + typedef cv::String string; typedef std::vector Icfvector; typedef std::vector svector; @@ -70,4 +71,4 @@ namespace sft # define dprintf(format, ...) #endif -#endif \ No newline at end of file +#endif diff --git a/apps/sft/include/sft/config.hpp b/apps/sft/include/sft/config.hpp index 3d39d32722..c6e85b264c 100644 --- a/apps/sft/include/sft/config.hpp +++ b/apps/sft/include/sft/config.hpp @@ -135,4 +135,4 @@ std::ostream& operator<<(std::ostream& out, const Config& m); } -#endif \ No newline at end of file +#endif diff --git a/apps/sft/include/sft/dataset.hpp b/apps/sft/include/sft/dataset.hpp index 98d6192568..7504f4033d 100644 --- a/apps/sft/include/sft/dataset.hpp +++ b/apps/sft/include/sft/dataset.hpp @@ -64,4 +64,4 @@ private: }; } -#endif \ No newline at end of file +#endif diff --git a/apps/sft/sft.cpp b/apps/sft/sft.cpp index 7b51387638..79d41032eb 100644 --- a/apps/sft/sft.cpp +++ b/apps/sft/sft.cpp @@ -165,4 +165,4 @@ int main(int argc, char** argv) fso.release(); std::cout << "Training complete..." << std::endl; return 0; -} \ No newline at end of file +} diff --git a/apps/traincascade/CMakeLists.txt b/apps/traincascade/CMakeLists.txt index f6fa679a9a..eb0c83df5a 100644 --- a/apps/traincascade/CMakeLists.txt +++ b/apps/traincascade/CMakeLists.txt @@ -1,4 +1,4 @@ -set(OPENCV_TRAINCASCADE_DEPS opencv_core opencv_ml opencv_imgproc opencv_objdetect opencv_highgui opencv_calib3d opencv_video opencv_features2d opencv_flann opencv_legacy) +set(OPENCV_TRAINCASCADE_DEPS opencv_core opencv_ml opencv_imgproc opencv_photo opencv_objdetect opencv_highgui opencv_calib3d opencv_video opencv_features2d opencv_flann opencv_legacy) ocv_check_dependencies(${OPENCV_TRAINCASCADE_DEPS}) if(NOT OCV_DEPENDENCIES_FOUND) @@ -34,4 +34,3 @@ if(ENABLE_SOLUTION_FOLDERS) endif() install(TARGETS ${the_target} RUNTIME DESTINATION bin COMPONENT main) - diff --git a/apps/traincascade/HOGfeatures.cpp b/apps/traincascade/HOGfeatures.cpp index eaf4bd7960..132e2e62e9 100644 --- a/apps/traincascade/HOGfeatures.cpp +++ b/apps/traincascade/HOGfeatures.cpp @@ -1,5 +1,5 @@ #include "opencv2/core.hpp" -#include "opencv2/core/internal.hpp" +#include "opencv2/imgproc.hpp" #include "HOGfeatures.h" #include "cascadeclassifier.h" diff --git a/apps/traincascade/boost.cpp b/apps/traincascade/boost.cpp index 1b0f390a5b..732704a4a2 100644 --- a/apps/traincascade/boost.cpp +++ b/apps/traincascade/boost.cpp @@ -1,11 +1,52 @@ #include "opencv2/core.hpp" -#include "opencv2/core/internal.hpp" #include "boost.h" #include "cascadeclassifier.h" #include #include "cxmisc.h" +#include "cvconfig.h" +#ifdef HAVE_TBB +# include "tbb/tbb_stddef.h" +# if TBB_VERSION_MAJOR*100 + TBB_VERSION_MINOR >= 202 +# include "tbb/tbb.h" +# include "tbb/task.h" +# undef min +# undef max +# else +# undef HAVE_TBB +# endif +#endif + +#ifdef HAVE_TBB + typedef tbb::blocked_range BlockedRange; + + template static inline + void parallel_for( const BlockedRange& range, const Body& body ) + { + tbb::parallel_for(range, body); + } +#else + class BlockedRange + { + public: + BlockedRange() : _begin(0), _end(0), _grainsize(0) {} + BlockedRange(int b, int e, int g=1) : _begin(b), _end(e), _grainsize(g) {} + int begin() const { return _begin; } + int end() const { return _end; } + int grainsize() const { return _grainsize; } + + protected: + int _begin, _end, _grainsize; + }; + + template static inline + void parallel_for( const BlockedRange& range, const Body& body ) + { + body(range); + } +#endif + using namespace std; static inline double @@ -18,12 +59,20 @@ logRatio( double val ) return log( val/(1. - val) ); } -#define CV_CMP_FLT(i,j) (i < j) -static CV_IMPLEMENT_QSORT_EX( icvSortFlt, float, CV_CMP_FLT, const float* ) +template +class LessThanIdx +{ +public: + LessThanIdx( const T* _arr ) : arr(_arr) {} + bool operator()(Idx a, Idx b) const { return arr[a] < arr[b]; } + const T* arr; +}; -#define CV_CMP_NUM_IDX(i,j) (aux[i] < aux[j]) -static CV_IMPLEMENT_QSORT_EX( icvSortIntAux, int, CV_CMP_NUM_IDX, const float* ) -static CV_IMPLEMENT_QSORT_EX( icvSortUShAux, unsigned short, CV_CMP_NUM_IDX, const float* ) +static inline int cvAlign( int size, int align ) +{ + CV_DbgAssert( (align & (align-1)) == 0 && size < INT_MAX ); + return (size + align - 1) & -align; +} #define CV_THRESHOLD_EPS (0.00001F) @@ -43,7 +92,7 @@ static CvMat* cvPreprocessIndexArray( const CvMat* idx_arr, int data_arr_size, b CV_FUNCNAME( "cvPreprocessIndexArray" ); - __BEGIN__; + __CV_BEGIN__; int i, idx_total, idx_selected = 0, step, type, prev = INT_MIN, is_sorted = 1; uchar* srcb = 0; @@ -131,7 +180,7 @@ static CvMat* cvPreprocessIndexArray( const CvMat* idx_arr, int data_arr_size, b } } - __END__; + __CV_END__; if( cvGetErrStatus() < 0 ) cvReleaseMat( &idx ); @@ -722,7 +771,7 @@ void CvCascadeBoostTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* o sampleValues[i] = (*featureEvaluator)( vi, sampleIndices[i]); } } - icvSortIntAux( sortedIndicesBuf, nodeSampleCount, &sampleValues[0] ); + std::sort(sortedIndicesBuf, sortedIndicesBuf + nodeSampleCount, LessThanIdx(&sampleValues[0]) ); for( int i = 0; i < nodeSampleCount; i++ ) ordValuesBuf[i] = (&sampleValues[0])[sortedIndicesBuf[i]]; *sortedIndices = sortedIndicesBuf; @@ -766,7 +815,7 @@ float CvCascadeBoostTrainData::getVarValue( int vi, int si ) } -struct FeatureIdxOnlyPrecalc +struct FeatureIdxOnlyPrecalc : ParallelLoopBody { FeatureIdxOnlyPrecalc( const CvFeatureEvaluator* _featureEvaluator, CvMat* _buf, int _sample_count, bool _is_buf_16u ) { @@ -776,11 +825,11 @@ struct FeatureIdxOnlyPrecalc idst = _buf->data.i; is_buf_16u = _is_buf_16u; } - void operator()( const BlockedRange& range ) const + void operator()( const Range& range ) const { cv::AutoBuffer valCache(sample_count); float* valCachePtr = (float*)valCache; - for ( int fi = range.begin(); fi < range.end(); fi++) + for ( int fi = range.start; fi < range.end; fi++) { for( int si = 0; si < sample_count; si++ ) { @@ -791,9 +840,9 @@ struct FeatureIdxOnlyPrecalc *(idst + fi*sample_count + si) = si; } if ( is_buf_16u ) - icvSortUShAux( udst + fi*sample_count, sample_count, valCachePtr ); + std::sort(udst + fi*sample_count, udst + (fi + 1)*sample_count, LessThanIdx(valCachePtr) ); else - icvSortIntAux( idst + fi*sample_count, sample_count, valCachePtr ); + std::sort(idst + fi*sample_count, idst + (fi + 1)*sample_count, LessThanIdx(valCachePtr) ); } } const CvFeatureEvaluator* featureEvaluator; @@ -803,7 +852,7 @@ struct FeatureIdxOnlyPrecalc bool is_buf_16u; }; -struct FeatureValAndIdxPrecalc +struct FeatureValAndIdxPrecalc : ParallelLoopBody { FeatureValAndIdxPrecalc( const CvFeatureEvaluator* _featureEvaluator, CvMat* _buf, Mat* _valCache, int _sample_count, bool _is_buf_16u ) { @@ -814,9 +863,9 @@ struct FeatureValAndIdxPrecalc idst = _buf->data.i; is_buf_16u = _is_buf_16u; } - void operator()( const BlockedRange& range ) const + void operator()( const Range& range ) const { - for ( int fi = range.begin(); fi < range.end(); fi++) + for ( int fi = range.start; fi < range.end; fi++) { for( int si = 0; si < sample_count; si++ ) { @@ -827,9 +876,9 @@ struct FeatureValAndIdxPrecalc *(idst + fi*sample_count + si) = si; } if ( is_buf_16u ) - icvSortUShAux( udst + fi*sample_count, sample_count, valCache->ptr(fi) ); + std::sort(idst + fi*sample_count, idst + (fi + 1)*sample_count, LessThanIdx(valCache->ptr(fi)) ); else - icvSortIntAux( idst + fi*sample_count, sample_count, valCache->ptr(fi) ); + std::sort(idst + fi*sample_count, idst + (fi + 1)*sample_count, LessThanIdx(valCache->ptr(fi)) ); } } const CvFeatureEvaluator* featureEvaluator; @@ -840,7 +889,7 @@ struct FeatureValAndIdxPrecalc bool is_buf_16u; }; -struct FeatureValOnlyPrecalc +struct FeatureValOnlyPrecalc : ParallelLoopBody { FeatureValOnlyPrecalc( const CvFeatureEvaluator* _featureEvaluator, Mat* _valCache, int _sample_count ) { @@ -848,9 +897,9 @@ struct FeatureValOnlyPrecalc valCache = _valCache; sample_count = _sample_count; } - void operator()( const BlockedRange& range ) const + void operator()( const Range& range ) const { - for ( int fi = range.begin(); fi < range.end(); fi++) + for ( int fi = range.start; fi < range.end; fi++) for( int si = 0; si < sample_count; si++ ) valCache->at(fi,si) = (*featureEvaluator)( fi, si ); } @@ -864,12 +913,12 @@ void CvCascadeBoostTrainData::precalculate() int minNum = MIN( numPrecalcVal, numPrecalcIdx); double proctime = -TIME( 0 ); - parallel_for( BlockedRange(numPrecalcVal, numPrecalcIdx), - FeatureIdxOnlyPrecalc(featureEvaluator, buf, sample_count, is_buf_16u!=0) ); - parallel_for( BlockedRange(0, minNum), - FeatureValAndIdxPrecalc(featureEvaluator, buf, &valCache, sample_count, is_buf_16u!=0) ); - parallel_for( BlockedRange(minNum, numPrecalcVal), - FeatureValOnlyPrecalc(featureEvaluator, &valCache, sample_count) ); + parallel_for_( Range(numPrecalcVal, numPrecalcIdx), + FeatureIdxOnlyPrecalc(featureEvaluator, buf, sample_count, is_buf_16u!=0) ); + parallel_for_( Range(0, minNum), + FeatureValAndIdxPrecalc(featureEvaluator, buf, &valCache, sample_count, is_buf_16u!=0) ); + parallel_for_( Range(minNum, numPrecalcVal), + FeatureValOnlyPrecalc(featureEvaluator, &valCache, sample_count) ); cout << "Precalculation time: " << (proctime + TIME( 0 )) << endl; } @@ -908,7 +957,7 @@ void CvCascadeBoostTree::write( FileStorage &fs, const Mat& featureMap ) int subsetN = (maxCatCount + 31)/32; queue internalNodesQueue; int size = (int)pow( 2.f, (float)ensemble->get_params().max_depth); - Ptr leafVals = new float[size]; + std::vector leafVals(size); int leafValIdx = 0; int internalNodeIdx = 1; CvDTreeNode* tempNode; @@ -1602,7 +1651,7 @@ bool CvCascadeBoost::isErrDesired() if( ((CvCascadeBoostTrainData*)data)->featureEvaluator->getCls( i ) == 1.0F ) eval[numPos++] = predict( i, true ); - icvSortFlt( &eval[0], numPos, 0 ); + std::sort(&eval[0], &eval[0] + numPos); int thresholdIdx = (int)((1.0F - minHitRate) * numPos); diff --git a/apps/traincascade/cascadeclassifier.cpp b/apps/traincascade/cascadeclassifier.cpp index f6752da0c9..5c96b45f76 100644 --- a/apps/traincascade/cascadeclassifier.cpp +++ b/apps/traincascade/cascadeclassifier.cpp @@ -1,5 +1,4 @@ #include "opencv2/core.hpp" -#include "opencv2/core/internal.hpp" #include "cascadeclassifier.h" #include @@ -160,10 +159,10 @@ bool CvCascadeClassifier::train( const string _cascadeDirName, cascadeParams = _cascadeParams; featureParams = CvFeatureParams::create(cascadeParams.featureType); featureParams->init(_featureParams); - stageParams = new CvCascadeBoostParams; + stageParams = makePtr(); *stageParams = _stageParams; featureEvaluator = CvFeatureEvaluator::create(cascadeParams.featureType); - featureEvaluator->init( (CvFeatureParams*)featureParams, numPos + numNeg, cascadeParams.winSize ); + featureEvaluator->init( featureParams, numPos + numNeg, cascadeParams.winSize ); stageClassifiers.reserve( numStages ); } cout << "PARAMETERS:" << endl; @@ -207,10 +206,10 @@ bool CvCascadeClassifier::train( const string _cascadeDirName, break; } - CvCascadeBoost* tempStage = new CvCascadeBoost; - bool isStageTrained = tempStage->train( (CvFeatureEvaluator*)featureEvaluator, + Ptr tempStage = makePtr(); + bool isStageTrained = tempStage->train( featureEvaluator, curNumSamples, _precalcValBufSize, _precalcIdxBufSize, - *((CvCascadeBoostParams*)stageParams) ); + *stageParams ); cout << "END>" << endl; if(!isStageTrained) @@ -326,7 +325,7 @@ void CvCascadeClassifier::writeParams( FileStorage &fs ) const void CvCascadeClassifier::writeFeatures( FileStorage &fs, const Mat& featureMap ) const { - ((CvFeatureEvaluator*)((Ptr)featureEvaluator))->writeFeatures( fs, featureMap ); + featureEvaluator->writeFeatures( fs, featureMap ); } void CvCascadeClassifier::writeStages( FileStorage &fs, const Mat& featureMap ) const @@ -340,7 +339,7 @@ void CvCascadeClassifier::writeStages( FileStorage &fs, const Mat& featureMap ) sprintf( cmnt, "stage %d", i ); cvWriteComment( fs.fs, cmnt, 0 ); fs << "{"; - ((CvCascadeBoost*)((Ptr)*it))->write( fs, featureMap ); + (*it)->write( fs, featureMap ); fs << "}"; } fs << "]"; @@ -351,7 +350,7 @@ bool CvCascadeClassifier::readParams( const FileNode &node ) if ( !node.isMap() || !cascadeParams.read( node ) ) return false; - stageParams = new CvCascadeBoostParams; + stageParams = makePtr(); FileNode rnode = node[CC_STAGE_PARAMS]; if ( !stageParams->read( rnode ) ) return false; @@ -372,12 +371,9 @@ bool CvCascadeClassifier::readStages( const FileNode &node) FileNodeIterator it = rnode.begin(); for( int i = 0; i < min( (int)rnode.size(), numStages ); i++, it++ ) { - CvCascadeBoost* tempStage = new CvCascadeBoost; - if ( !tempStage->read( *it, (CvFeatureEvaluator *)featureEvaluator, *((CvCascadeBoostParams*)stageParams) ) ) - { - delete tempStage; + Ptr tempStage = makePtr(); + if ( !tempStage->read( *it, featureEvaluator, *stageParams) ) return false; - } stageClassifiers.push_back(tempStage); } return true; @@ -454,7 +450,7 @@ void CvCascadeClassifier::save( const string filename, bool baseFormat ) fs << "{"; fs << ICV_HAAR_FEATURE_NAME << "{"; - ((CvHaarEvaluator*)((CvFeatureEvaluator*)featureEvaluator))->writeFeature( fs, tempNode->split->var_idx ); + ((CvHaarEvaluator*)featureEvaluator.get())->writeFeature( fs, tempNode->split->var_idx ); fs << "}"; fs << ICV_HAAR_THRESHOLD_NAME << tempNode->split->ord.c; @@ -500,7 +496,7 @@ bool CvCascadeClassifier::load( const string cascadeDirName ) if ( !readParams( node ) ) return false; featureEvaluator = CvFeatureEvaluator::create(cascadeParams.featureType); - featureEvaluator->init( ((CvFeatureParams*)featureParams), numPos + numNeg, cascadeParams.winSize ); + featureEvaluator->init( featureParams, numPos + numNeg, cascadeParams.winSize ); fs.release(); char buf[10]; @@ -511,11 +507,10 @@ bool CvCascadeClassifier::load( const string cascadeDirName ) node = fs.getFirstTopLevelNode(); if ( !fs.isOpened() ) break; - CvCascadeBoost *tempStage = new CvCascadeBoost; + Ptr tempStage = makePtr(); - if ( !tempStage->read( node, (CvFeatureEvaluator*)featureEvaluator, *((CvCascadeBoostParams*)stageParams )) ) + if ( !tempStage->read( node, featureEvaluator, *stageParams )) { - delete tempStage; fs.release(); break; } @@ -532,7 +527,7 @@ void CvCascadeClassifier::getUsedFeaturesIdxMap( Mat& featureMap ) for( vector< Ptr >::const_iterator it = stageClassifiers.begin(); it != stageClassifiers.end(); it++ ) - ((CvCascadeBoost*)((Ptr)(*it)))->markUsedFeaturesInMap( featureMap ); + (*it)->markUsedFeaturesInMap( featureMap ); for( int fi = 0, idx = 0; fi < varCount; fi++ ) if ( featureMap.at(0, fi) >= 0 ) diff --git a/apps/traincascade/features.cpp b/apps/traincascade/features.cpp index 4aebc80940..7f0c0a7079 100644 --- a/apps/traincascade/features.cpp +++ b/apps/traincascade/features.cpp @@ -1,5 +1,4 @@ #include "opencv2/core.hpp" -#include "opencv2/core/internal.hpp" #include "traincascade_features.h" #include "cascadeclassifier.h" diff --git a/apps/traincascade/haarfeatures.cpp b/apps/traincascade/haarfeatures.cpp index 59f1fd4ca7..ceb730aafb 100644 --- a/apps/traincascade/haarfeatures.cpp +++ b/apps/traincascade/haarfeatures.cpp @@ -1,5 +1,5 @@ #include "opencv2/core.hpp" -#include "opencv2/core/internal.hpp" +#include "opencv2/imgproc.hpp" #include "haarfeatures.h" #include "cascadeclassifier.h" diff --git a/apps/traincascade/imagestorage.cpp b/apps/traincascade/imagestorage.cpp index e7922a9afc..a8426e074d 100644 --- a/apps/traincascade/imagestorage.cpp +++ b/apps/traincascade/imagestorage.cpp @@ -1,7 +1,7 @@ #include "opencv2/core.hpp" -#include "opencv2/core/internal.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" -#include "cv.h" #include "imagestorage.h" #include #include diff --git a/apps/traincascade/lbpfeatures.cpp b/apps/traincascade/lbpfeatures.cpp index 5e23d9e461..dd1659f9de 100644 --- a/apps/traincascade/lbpfeatures.cpp +++ b/apps/traincascade/lbpfeatures.cpp @@ -1,5 +1,5 @@ #include "opencv2/core.hpp" -#include "opencv2/core/internal.hpp" +#include "opencv2/imgproc.hpp" #include "lbpfeatures.h" #include "cascadeclassifier.h" diff --git a/apps/traincascade/traincascade.cpp b/apps/traincascade/traincascade.cpp index c85046e6b7..a896c216c9 100644 --- a/apps/traincascade/traincascade.cpp +++ b/apps/traincascade/traincascade.cpp @@ -1,5 +1,4 @@ #include "opencv2/core.hpp" -#include "opencv2/core/internal.hpp" #include "cv.h" #include "cascadeclassifier.h" @@ -19,9 +18,9 @@ int main( int argc, char* argv[] ) CvCascadeParams cascadeParams; CvCascadeBoostParams stageParams; - Ptr featureParams[] = { Ptr(new CvHaarFeatureParams), - Ptr(new CvLBPFeatureParams), - Ptr(new CvHOGFeatureParams) + Ptr featureParams[] = { makePtr(), + makePtr(), + makePtr() }; int fc = sizeof(featureParams)/sizeof(featureParams[0]); if( argc == 1 ) diff --git a/cmake/CMakeParseArguments.cmake b/cmake/CMakeParseArguments.cmake deleted file mode 100644 index 7ce4c49ae5..0000000000 --- a/cmake/CMakeParseArguments.cmake +++ /dev/null @@ -1,138 +0,0 @@ -# CMAKE_PARSE_ARGUMENTS( args...) -# -# CMAKE_PARSE_ARGUMENTS() is intended to be used in macros or functions for -# parsing the arguments given to that macro or function. -# It processes the arguments and defines a set of variables which hold the -# values of the respective options. -# -# The argument contains all options for the respective macro, -# i.e. keywords which can be used when calling the macro without any value -# following, like e.g. the OPTIONAL keyword of the install() command. -# -# The argument contains all keywords for this macro -# which are followed by one value, like e.g. DESTINATION keyword of the -# install() command. -# -# The argument contains all keywords for this macro -# which can be followed by more than one value, like e.g. the TARGETS or -# FILES keywords of the install() command. -# -# When done, CMAKE_PARSE_ARGUMENTS() will have defined for each of the -# keywords listed in , and -# a variable composed of the given -# followed by "_" and the name of the respective keyword. -# These variables will then hold the respective value from the argument list. -# For the keywords this will be TRUE or FALSE. -# -# All remaining arguments are collected in a variable -# _UNPARSED_ARGUMENTS, this can be checked afterwards to see whether -# your macro was called with unrecognized parameters. -# -# As an example here a my_install() macro, which takes similar arguments as the -# real install() command: -# -# function(MY_INSTALL) -# set(options OPTIONAL FAST) -# set(oneValueArgs DESTINATION RENAME) -# set(multiValueArgs TARGETS CONFIGURATIONS) -# cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) -# ... -# -# Assume my_install() has been called like this: -# my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub) -# -# After the cmake_parse_arguments() call the macro will have set the following -# variables: -# MY_INSTALL_OPTIONAL = TRUE -# MY_INSTALL_FAST = FALSE (this option was not used when calling my_install() -# MY_INSTALL_DESTINATION = "bin" -# MY_INSTALL_RENAME = "" (was not used) -# MY_INSTALL_TARGETS = "foo;bar" -# MY_INSTALL_CONFIGURATIONS = "" (was not used) -# MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (no value expected after "OPTIONAL" -# -# You can the continue and process these variables. -# -# Keywords terminate lists of values, e.g. if directly after a one_value_keyword -# another recognized keyword follows, this is interpreted as the beginning of -# the new option. -# E.g. my_install(TARGETS foo DESTINATION OPTIONAL) would result in -# MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION would -# be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefor. - -#============================================================================= -# Copyright 2010 Alexander Neundorf -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -# (To distribute this file outside of CMake, substitute the full -# License text for the above reference.) - - -if(__CMAKE_PARSE_ARGUMENTS_INCLUDED) - return() -endif() -set(__CMAKE_PARSE_ARGUMENTS_INCLUDED TRUE) - - -function(CMAKE_PARSE_ARGUMENTS prefix _optionNames _singleArgNames _multiArgNames) - # first set all result variables to empty/FALSE - foreach(arg_name ${_singleArgNames} ${_multiArgNames}) - set(${prefix}_${arg_name}) - endforeach(arg_name) - - foreach(option ${_optionNames}) - set(${prefix}_${option} FALSE) - endforeach(option) - - set(${prefix}_UNPARSED_ARGUMENTS) - - set(insideValues FALSE) - set(currentArgName) - - # now iterate over all arguments and fill the result variables - foreach(currentArg ${ARGN}) - list(FIND _optionNames "${currentArg}" optionIndex) # ... then this marks the end of the arguments belonging to this keyword - list(FIND _singleArgNames "${currentArg}" singleArgIndex) # ... then this marks the end of the arguments belonging to this keyword - list(FIND _multiArgNames "${currentArg}" multiArgIndex) # ... then this marks the end of the arguments belonging to this keyword - - if(${optionIndex} EQUAL -1 AND ${singleArgIndex} EQUAL -1 AND ${multiArgIndex} EQUAL -1) - if(insideValues) - if("${insideValues}" STREQUAL "SINGLE") - set(${prefix}_${currentArgName} ${currentArg}) - set(insideValues FALSE) - elseif("${insideValues}" STREQUAL "MULTI") - list(APPEND ${prefix}_${currentArgName} ${currentArg}) - endif() - else(insideValues) - list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${currentArg}) - endif(insideValues) - else() - if(NOT ${optionIndex} EQUAL -1) - set(${prefix}_${currentArg} TRUE) - set(insideValues FALSE) - elseif(NOT ${singleArgIndex} EQUAL -1) - set(currentArgName ${currentArg}) - set(${prefix}_${currentArgName}) - set(insideValues "SINGLE") - elseif(NOT ${multiArgIndex} EQUAL -1) - set(currentArgName ${currentArg}) - set(${prefix}_${currentArgName}) - set(insideValues "MULTI") - endif() - endif() - - endforeach(currentArg) - - # propagate the result variables to the caller: - foreach(arg_name ${_singleArgNames} ${_multiArgNames} ${_optionNames}) - set(${prefix}_${arg_name} ${${prefix}_${arg_name}} PARENT_SCOPE) - endforeach(arg_name) - set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE) - -endfunction(CMAKE_PARSE_ARGUMENTS _options _singleArgs _multiArgs) diff --git a/cmake/OpenCVCRTLinkage.cmake b/cmake/OpenCVCRTLinkage.cmake index 7514285d9f..8a297c6857 100644 --- a/cmake/OpenCVCRTLinkage.cmake +++ b/cmake/OpenCVCRTLinkage.cmake @@ -2,6 +2,45 @@ if(NOT MSVC) message(FATAL_ERROR "CRT options are available only for MSVC") endif() +#INCLUDE (CheckIncludeFiles) + +set(HAVE_WINRT FALSE) + +# search Windows Platform SDK +message(STATUS "Checking for Windows Platform SDK") +GET_FILENAME_COMPONENT(WINDOWS_SDK_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v8.0;InstallationFolder]" ABSOLUTE CACHE) +if (WINDOWS_SDK_PATH STREQUAL "") + set(HAVE_MSPDK FALSE) + message(STATUS "Windows Platform SDK 8.0 was not found") +else() + set(HAVE_MSPDK TRUE) +endif() + +#search for Visual Studio 11.0 install directory +message(STATUS "Checking for Visual Studio 2012") +GET_FILENAME_COMPONENT(VISUAL_STUDIO_PATH [HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\11.0\\Setup\\VS;ProductDir] REALPATH CACHE) +if (VISUAL_STUDIO_PATH STREQUAL "") + set(HAVE_MSVC2012 FALSE) + message(STATUS "Visual Studio 2012 was not found") +else() + set(HAVE_MSVC2012 TRUE) +endif() + +try_compile(HAVE_WINRT_SDK + "${OpenCV_BINARY_DIR}" + "${OpenCV_SOURCE_DIR}/cmake/checks/winrttest.cpp") + +if (ENABLE_WINRT_MODE AND HAVE_WINRT_SDK AND HAVE_MSVC2012 AND HAVE_MSPDK) + set(HAVE_WINRT TRUE) +endif() + +if (HAVE_WINRT) + add_definitions(/DWINVER=0x0602 /DNTDDI_VERSION=NTDDI_WIN8 /D_WIN32_WINNT=0x0602) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /appcontainer") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /appcontainer") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /appcontainer") +endif() + if(NOT BUILD_SHARED_LIBS AND BUILD_WITH_STATIC_CRT) foreach(flag_var CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE @@ -62,4 +101,3 @@ if(NOT BUILD_WITH_DEBUG_INFO AND NOT MSVC) string(REPLACE "/Zi" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") string(REPLACE "/Zi" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") endif() - diff --git a/cmake/OpenCVCompilerOptions.cmake b/cmake/OpenCVCompilerOptions.cmake index a9baa9780d..bfca6a0bc9 100644 --- a/cmake/OpenCVCompilerOptions.cmake +++ b/cmake/OpenCVCompilerOptions.cmake @@ -47,6 +47,9 @@ macro(add_extra_compiler_option option) endif() endmacro() +# OpenCV fails some tests when 'char' is 'unsigned' by default +add_extra_compiler_option(-fsigned-char) + if(MINGW) # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40838 # here we are trying to workaround the problem @@ -230,6 +233,10 @@ if(MSVC) set(OPENCV_EXTRA_FLAGS "${OPENCV_EXTRA_FLAGS} /fp:fast") # !! important - be on the same wave with x64 compilers endif() endif() + + if(OPENCV_WARNINGS_ARE_ERRORS) + set(OPENCV_EXTRA_FLAGS "${OPENCV_EXTRA_FLAGS} /WX") + endif() endif() # Extra link libs if the user selects building static libs: @@ -250,6 +257,12 @@ set(OPENCV_EXTRA_EXE_LINKER_FLAGS "${OPENCV_EXTRA_EXE_LINKER_FLAGS}" set(OPENCV_EXTRA_EXE_LINKER_FLAGS_RELEASE "${OPENCV_EXTRA_EXE_LINKER_FLAGS_RELEASE}" CACHE INTERNAL "Extra linker flags for Release build") set(OPENCV_EXTRA_EXE_LINKER_FLAGS_DEBUG "${OPENCV_EXTRA_EXE_LINKER_FLAGS_DEBUG}" CACHE INTERNAL "Extra linker flags for Debug build") +# set default visibility to hidden +if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_OPENCV_GCC_VERSION_NUM GREATER 399) + add_extra_compiler_option(-fvisibility=hidden) + add_extra_compiler_option(-fvisibility-inlines-hidden) +endif() + #combine all "extra" options set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPENCV_EXTRA_FLAGS} ${OPENCV_EXTRA_C_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OPENCV_EXTRA_FLAGS} ${OPENCV_EXTRA_CXX_FLAGS}") @@ -285,4 +298,4 @@ if(MSVC) if(NOT ENABLE_NOISY_WARNINGS) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251") #class 'std::XXX' needs to have dll-interface to be used by clients of YYY endif() -endif() \ No newline at end of file +endif() diff --git a/cmake/OpenCVConfig.cmake b/cmake/OpenCVConfig.cmake deleted file mode 100644 index 300fcd4193..0000000000 --- a/cmake/OpenCVConfig.cmake +++ /dev/null @@ -1,159 +0,0 @@ -# =================================================================================== -# The OpenCV CMake configuration file -# -# ** File generated automatically, do not modify ** -# -# Usage from an external project: -# In your CMakeLists.txt, add these lines: -# -# FIND_PACKAGE(OpenCV REQUIRED) -# TARGET_LINK_LIBRARIES(MY_TARGET_NAME ${OpenCV_LIBS}) -# -# Or you can search for specific OpenCV modules: -# -# FIND_PACKAGE(OpenCV REQUIRED core highgui) -# -# If the module is found then OPENCV__FOUND is set to TRUE. -# -# This file will define the following variables: -# - OpenCV_LIBS : The list of libraries to links against. -# - OpenCV_LIB_DIR : The directory(es) where lib files are. Calling LINK_DIRECTORIES -# with this path is NOT needed. -# - OpenCV_INCLUDE_DIRS : The OpenCV include directories. -# - OpenCV_COMPUTE_CAPABILITIES : The version of compute capability -# - OpenCV_ANDROID_NATIVE_API_LEVEL : Minimum required level of Android API -# - OpenCV_VERSION : The version of this OpenCV build. Example: "2.4.0" -# - OpenCV_VERSION_MAJOR : Major version part of OpenCV_VERSION. Example: "2" -# - OpenCV_VERSION_MINOR : Minor version part of OpenCV_VERSION. Example: "4" -# - OpenCV_VERSION_PATCH : Patch version part of OpenCV_VERSION. Example: "0" -# -# Advanced variables: -# - OpenCV_SHARED -# - OpenCV_CONFIG_PATH -# - OpenCV_LIB_COMPONENTS -# -# =================================================================================== -# -# Windows pack specific options: -# - OpenCV_STATIC -# - OpenCV_CUDA - -if(CMAKE_VERSION VERSION_GREATER 2.6) - get_property(OpenCV_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) - if(NOT ";${OpenCV_LANGUAGES};" MATCHES ";CXX;") - enable_language(CXX) - endif() -endif() - -if(NOT DEFINED OpenCV_STATIC) - # look for global setting - if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) - set(OpenCV_STATIC OFF) - else() - set(OpenCV_STATIC ON) - endif() -endif() - -if(NOT DEFINED OpenCV_CUDA) - # if user' app uses CUDA, then it probably wants CUDA-enabled OpenCV binaries - if(CUDA_FOUND) - set(OpenCV_CUDA ON) - endif() -endif() - -if(MSVC) - if(CMAKE_CL_64) - set(OpenCV_ARCH x64) - set(OpenCV_TBB_ARCH intel64) - else() - set(OpenCV_ARCH x86) - set(OpenCV_TBB_ARCH ia32) - endif() - if(MSVC_VERSION EQUAL 1400) - set(OpenCV_RUNTIME vc8) - elseif(MSVC_VERSION EQUAL 1500) - set(OpenCV_RUNTIME vc9) - elseif(MSVC_VERSION EQUAL 1600) - set(OpenCV_RUNTIME vc10) - elseif(MSVC_VERSION EQUAL 1700) - set(OpenCV_RUNTIME vc11) - endif() -elseif(MINGW) - set(OpenCV_RUNTIME mingw) - - execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpmachine - OUTPUT_VARIABLE OPENCV_GCC_TARGET_MACHINE - OUTPUT_STRIP_TRAILING_WHITESPACE) - if(CMAKE_OPENCV_GCC_TARGET_MACHINE MATCHES "64") - set(MINGW64 1) - set(OpenCV_ARCH x64) - else() - set(OpenCV_ARCH x86) - endif() -endif() - -if(CMAKE_VERSION VERSION_GREATER 2.6.2) - unset(OpenCV_CONFIG_PATH CACHE) -endif() - -get_filename_component(OpenCV_CONFIG_PATH "${CMAKE_CURRENT_LIST_FILE}" PATH CACHE) -if(OpenCV_RUNTIME AND OpenCV_ARCH) - if(OpenCV_STATIC AND EXISTS "${OpenCV_CONFIG_PATH}/${OpenCV_ARCH}/${OpenCV_RUNTIME}/staticlib/OpenCVConfig.cmake") - if(OpenCV_CUDA AND EXISTS "${OpenCV_CONFIG_PATH}/gpu/${OpenCV_ARCH}/${OpenCV_RUNTIME}/staticlib/OpenCVConfig.cmake") - set(OpenCV_LIB_PATH "${OpenCV_CONFIG_PATH}/gpu/${OpenCV_ARCH}/${OpenCV_RUNTIME}/staticlib") - else() - set(OpenCV_LIB_PATH "${OpenCV_CONFIG_PATH}/${OpenCV_ARCH}/${OpenCV_RUNTIME}/staticlib") - endif() - elseif(EXISTS "${OpenCV_CONFIG_PATH}/${OpenCV_ARCH}/${OpenCV_RUNTIME}/lib/OpenCVConfig.cmake") - if(OpenCV_CUDA AND EXISTS "${OpenCV_CONFIG_PATH}/gpu/${OpenCV_ARCH}/${OpenCV_RUNTIME}/lib/OpenCVConfig.cmake") - set(OpenCV_LIB_PATH "${OpenCV_CONFIG_PATH}/gpu/${OpenCV_ARCH}/${OpenCV_RUNTIME}/lib") - else() - set(OpenCV_LIB_PATH "${OpenCV_CONFIG_PATH}/${OpenCV_ARCH}/${OpenCV_RUNTIME}/lib") - endif() - endif() -endif() - -if(OpenCV_LIB_PATH AND EXISTS "${OpenCV_LIB_PATH}/OpenCVConfig.cmake") - set(OpenCV_LIB_DIR_OPT "${OpenCV_LIB_PATH}" CACHE PATH "Path where release OpenCV libraries are located" FORCE) - set(OpenCV_LIB_DIR_DBG "${OpenCV_LIB_PATH}" CACHE PATH "Path where debug OpenCV libraries are located" FORCE) - set(OpenCV_3RDPARTY_LIB_DIR_OPT "${OpenCV_LIB_PATH}" CACHE PATH "Path where release 3rdpaty OpenCV dependencies are located" FORCE) - set(OpenCV_3RDPARTY_LIB_DIR_DBG "${OpenCV_LIB_PATH}" CACHE PATH "Path where debug 3rdpaty OpenCV dependencies are located" FORCE) - - include("${OpenCV_LIB_PATH}/OpenCVConfig.cmake") - - if(OpenCV_CUDA) - set(_OpenCV_LIBS "") - foreach(_lib ${OpenCV_LIBS}) - string(REPLACE "${OpenCV_CONFIG_PATH}/gpu/${OpenCV_ARCH}/${OpenCV_RUNTIME}" "${OpenCV_CONFIG_PATH}/${OpenCV_ARCH}/${OpenCV_RUNTIME}" _lib2 "${_lib}") - if(NOT EXISTS "${_lib}" AND EXISTS "${_lib2}") - list(APPEND _OpenCV_LIBS "${_lib2}") - else() - list(APPEND _OpenCV_LIBS "${_lib}") - endif() - endforeach() - set(OpenCV_LIBS ${_OpenCV_LIBS}) - endif() - set(OpenCV_FOUND TRUE CACHE BOOL "" FORCE) - set(OPENCV_FOUND TRUE CACHE BOOL "" FORCE) - - if(NOT OpenCV_FIND_QUIETLY) - message(STATUS "Found OpenCV ${OpenCV_VERSION} in ${OpenCV_LIB_PATH}") - if(NOT OpenCV_LIB_PATH MATCHES "/staticlib") - get_filename_component(_OpenCV_LIB_PATH "${OpenCV_LIB_PATH}/../bin" ABSOLUTE) - file(TO_NATIVE_PATH "${_OpenCV_LIB_PATH}" _OpenCV_LIB_PATH) - message(STATUS "You might need to add ${_OpenCV_LIB_PATH} to your PATH to be able to run your applications.") - if(OpenCV_LIB_PATH MATCHES "/gpu/") - string(REPLACE "\\gpu" "" _OpenCV_LIB_PATH2 "${_OpenCV_LIB_PATH}") - message(STATUS "GPU support is enabled so you might also need ${_OpenCV_LIB_PATH2} in your PATH (it must go after the ${_OpenCV_LIB_PATH}).") - endif() - endif() - endif() -else() - if(NOT OpenCV_FIND_QUIETLY) - message(WARNING "Found OpenCV 2.4.3 Windows Super Pack but it has not binaries compatible with your configuration. - You should manually point CMake variable OpenCV_DIR to your build of OpenCV library.") - endif() - set(OpenCV_FOUND FALSE CACHE BOOL "" FORCE) - set(OPENCV_FOUND FALSE CACHE BOOL "" FORCE) -endif() - diff --git a/cmake/OpenCVDetectAndroidSDK.cmake b/cmake/OpenCVDetectAndroidSDK.cmake index 0e0240ca86..0173223d4e 100644 --- a/cmake/OpenCVDetectAndroidSDK.cmake +++ b/cmake/OpenCVDetectAndroidSDK.cmake @@ -124,7 +124,7 @@ if(ANDROID_EXECUTABLE) if(NOT ANDROID_SDK_TARGET) set(ANDROID_SDK_TARGET "" CACHE STRING "Android SDK target for the OpenCV Java API and samples") endif() - if(ANDROID_SDK_TARGETS AND CMAKE_VERSION VERSION_GREATER "2.8") + if(ANDROID_SDK_TARGETS) set_property( CACHE ANDROID_SDK_TARGET PROPERTY STRINGS ${ANDROID_SDK_TARGETS} ) endif() endif(ANDROID_EXECUTABLE) @@ -176,7 +176,8 @@ macro(android_get_compatible_target VAR) endmacro() unset(__android_project_chain CACHE) -#add_android_project(target_name ${path} NATIVE_DEPS opencv_core LIBRARY_DEPS ${OpenCV_BINARY_DIR} SDK_TARGET 11) + +# add_android_project(target_name ${path} NATIVE_DEPS opencv_core LIBRARY_DEPS ${OpenCV_BINARY_DIR} SDK_TARGET 11) macro(add_android_project target path) # parse arguments set(android_proj_arglist NATIVE_DEPS LIBRARY_DEPS SDK_TARGET IGNORE_JAVA IGNORE_MANIFEST) @@ -212,6 +213,16 @@ macro(add_android_project target path) ocv_check_dependencies(${android_proj_NATIVE_DEPS} opencv_java) endif() + if(EXISTS "${path}/jni/Android.mk" ) + # find if native_app_glue is used + file(STRINGS "${path}/jni/Android.mk" NATIVE_APP_GLUE REGEX ".*(call import-module,android/native_app_glue)" ) + if(NATIVE_APP_GLUE) + if(ANDROID_NATIVE_API_LEVEL LESS 9 OR NOT EXISTS "${ANDROID_NDK}/sources/android/native_app_glue") + set(OCV_DEPENDENCIES_FOUND FALSE) + endif() + endif() + endif() + if(OCV_DEPENDENCIES_FOUND AND android_proj_sdk_target AND ANDROID_EXECUTABLE AND ANT_EXECUTABLE AND ANDROID_TOOLS_Pkg_Revision GREATER 13 AND EXISTS "${path}/${ANDROID_MANIFEST_FILE}") project(${target}) @@ -264,6 +275,7 @@ macro(add_android_project target path) ocv_list_filterout(android_proj_jni_files "\\\\.svn") if(android_proj_jni_files AND EXISTS ${path}/jni/Android.mk AND NOT DEFINED JNI_LIB_NAME) + # find local module name in Android.mk file to build native lib file(STRINGS "${path}/jni/Android.mk" JNI_LIB_NAME REGEX "LOCAL_MODULE[ ]*:=[ ]*.*" ) string(REGEX REPLACE "LOCAL_MODULE[ ]*:=[ ]*([a-zA-Z_][a-zA-Z_0-9]*)[ ]*" "\\1" JNI_LIB_NAME "${JNI_LIB_NAME}") @@ -271,6 +283,13 @@ macro(add_android_project target path) ocv_include_modules_recurse(${android_proj_NATIVE_DEPS}) ocv_include_directories("${path}/jni") + if(NATIVE_APP_GLUE) + include_directories(${ANDROID_NDK}/sources/android/native_app_glue) + list(APPEND android_proj_jni_files ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) + ocv_warnings_disable(CMAKE_C_FLAGS -Wstrict-prototypes -Wunused-parameter -Wmissing-prototypes) + set(android_proj_NATIVE_DEPS ${android_proj_NATIVE_DEPS} android) + endif() + add_library(${JNI_LIB_NAME} MODULE ${android_proj_jni_files}) target_link_libraries(${JNI_LIB_NAME} ${OPENCV_LINKER_LIBS} ${android_proj_NATIVE_DEPS}) @@ -280,9 +299,9 @@ macro(add_android_project target path) ) get_target_property(android_proj_jni_location "${JNI_LIB_NAME}" LOCATION) - if (NOT (CMAKE_BUILD_TYPE MATCHES "debug")) - add_custom_command(TARGET ${JNI_LIB_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} --strip-unneeded "${android_proj_jni_location}") - endif() + if (NOT (CMAKE_BUILD_TYPE MATCHES "debug")) + add_custom_command(TARGET ${JNI_LIB_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} --strip-unneeded "${android_proj_jni_location}") + endif() endif() endif() diff --git a/cmake/OpenCVDetectApacheAnt.cmake b/cmake/OpenCVDetectApacheAnt.cmake index c98fc48b3e..7b7e9a6da9 100644 --- a/cmake/OpenCVDetectApacheAnt.cmake +++ b/cmake/OpenCVDetectApacheAnt.cmake @@ -16,10 +16,16 @@ find_host_program(ANT_EXECUTABLE NAMES ${ANT_NAME}) if(ANT_EXECUTABLE) execute_process(COMMAND ${ANT_EXECUTABLE} -version + RESULT_VARIABLE ANT_ERROR_LEVEL OUTPUT_VARIABLE ANT_VERSION_FULL OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REGEX MATCH "[0-9]+.[0-9]+.[0-9]+" ANT_VERSION "${ANT_VERSION_FULL}") - set(ANT_VERSION "${ANT_VERSION}" CACHE INTERNAL "Detected ant vesion") + if (ANT_ERROR_LEVEL) + unset(ANT_EXECUTABLE) + unset(ANT_EXECUTABLE CACHE) + else() + string(REGEX MATCH "[0-9]+.[0-9]+.[0-9]+" ANT_VERSION "${ANT_VERSION_FULL}") + set(ANT_VERSION "${ANT_VERSION}" CACHE INTERNAL "Detected ant vesion") - message(STATUS "Found apache ant ${ANT_VERSION}: ${ANT_EXECUTABLE}") + message(STATUS "Found apache ant ${ANT_VERSION}: ${ANT_EXECUTABLE}") + endif() endif() diff --git a/cmake/OpenCVDetectCUDA.cmake b/cmake/OpenCVDetectCUDA.cmake index e853a8d0a0..076da108f7 100644 --- a/cmake/OpenCVDetectCUDA.cmake +++ b/cmake/OpenCVDetectCUDA.cmake @@ -1,8 +1,3 @@ -if(${CMAKE_VERSION} VERSION_LESS "2.8.3") - message(STATUS "WITH_CUDA flag requires CMake 2.8.3 or newer. CUDA support is disabled.") - return() -endif() - if(WIN32 AND NOT MSVC) message(STATUS "CUDA compilation is disabled (due to only Visual Studio compiler supported on your platform).") return() @@ -26,8 +21,52 @@ if(CUDA_FOUND) set(HAVE_CUBLAS 1) endif() + if(${CUDA_VERSION} VERSION_LESS "5.5") + find_cuda_helper_libs(npp) + else() + # hack for CUDA 5.5 + if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm") + unset(CUDA_TOOLKIT_INCLUDE CACHE) + unset(CUDA_CUDART_LIBRARY CACHE) + unset(CUDA_cublas_LIBRARY CACHE) + unset(CUDA_cufft_LIBRARY CACHE) + unset(CUDA_npp_LIBRARY CACHE) + + if(SOFTFP) + set(cuda_arm_path "${CUDA_TOOLKIT_ROOT_DIR}/targets/armv7-linux-gnueabi") + else() + set(cuda_arm_path "${CUDA_TOOLKIT_ROOT_DIR}/targets/armv7-linux-gnueabihf") + endif() + + set(CUDA_TOOLKIT_INCLUDE "${cuda_arm_path}/include" CACHE PATH "include path") + set(CUDA_INCLUDE_DIRS ${CUDA_TOOLKIT_INCLUDE}) + + set(cuda_arm_library_path "${cuda_arm_path}/lib") + + set(CUDA_CUDART_LIBRARY "${cuda_arm_library_path}/libcudart.so" CACHE FILEPATH "cudart library") + set(CUDA_LIBRARIES ${CUDA_CUDART_LIBRARY}) + set(CUDA_cublas_LIBRARY "${cuda_arm_library_path}/libcublas.so" CACHE FILEPATH "cublas library") + set(CUDA_cufft_LIBRARY "${cuda_arm_library_path}/libcufft.so" CACHE FILEPATH "cufft library") + set(CUDA_nppc_LIBRARY "${cuda_arm_library_path}/libnppc.so" CACHE FILEPATH "nppc library") + set(CUDA_nppi_LIBRARY "${cuda_arm_library_path}/libnppi.so" CACHE FILEPATH "nppi library") + set(CUDA_npps_LIBRARY "${cuda_arm_library_path}/libnpps.so" CACHE FILEPATH "npps library") + set(CUDA_npp_LIBRARY "${CUDA_nppc_LIBRARY};${CUDA_nppi_LIBRARY};${CUDA_npps_LIBRARY}" CACHE STRING "npp library") + else() + unset(CUDA_npp_LIBRARY CACHE) + + find_cuda_helper_libs(nppc) + find_cuda_helper_libs(nppi) + find_cuda_helper_libs(npps) + + set(CUDA_npp_LIBRARY "${CUDA_nppc_LIBRARY};${CUDA_nppi_LIBRARY};${CUDA_npps_LIBRARY}" CACHE STRING "npp library") + endif() + endif() + if(WITH_NVCUVID) find_cuda_helper_libs(nvcuvid) + if(WIN32) + find_cuda_helper_libs(nvcuvenc) + endif() set(HAVE_NVCUVID 1) endif() @@ -55,9 +94,13 @@ if(CUDA_FOUND) if(CUDA_GENERATION STREQUAL "Fermi") set(__cuda_arch_bin "2.0 2.1(2.0)") elseif(CUDA_GENERATION STREQUAL "Kepler") - set(__cuda_arch_bin "3.0") + if(${CUDA_VERSION} VERSION_LESS "5.0") + set(__cuda_arch_bin "3.0") + else() + set(__cuda_arch_bin "3.0 3.5") + endif() elseif(CUDA_GENERATION STREQUAL "Auto") - execute_process( COMMAND "${CUDA_NVCC_EXECUTABLE}" "${OpenCV_SOURCE_DIR}/cmake/OpenCVDetectCudaArch.cu" "--run" + execute_process( COMMAND "${CUDA_NVCC_EXECUTABLE}" "${OpenCV_SOURCE_DIR}/cmake/checks/OpenCVDetectCudaArch.cu" "--run" WORKING_DIRECTORY "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/" RESULT_VARIABLE _nvcc_res OUTPUT_VARIABLE _nvcc_out ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) @@ -69,8 +112,12 @@ if(CUDA_FOUND) endif() if(NOT DEFINED __cuda_arch_bin) - set(__cuda_arch_bin "1.1 1.2 1.3 2.0 2.1(2.0) 3.0") - set(__cuda_arch_ptx "2.0 3.0") + if(${CUDA_VERSION} VERSION_LESS "5.0") + set(__cuda_arch_bin "1.1 1.2 1.3 2.0 2.1(2.0) 3.0") + else() + set(__cuda_arch_bin "1.1 1.2 1.3 2.0 2.1(2.0) 3.0 3.5") + endif() + set(__cuda_arch_ptx "3.0") endif() set(CUDA_ARCH_BIN ${__cuda_arch_bin} CACHE STRING "Specify 'real' GPU architectures to build binaries for, BIN(PTX) format is supported") @@ -136,17 +183,22 @@ if(CUDA_FOUND) mark_as_advanced(CUDA_BUILD_CUBIN CUDA_BUILD_EMULATION CUDA_VERBOSE_BUILD CUDA_SDK_ROOT_DIR) - find_cuda_helper_libs(npp) - macro(ocv_cuda_compile VAR) foreach(var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG) set(${var}_backup_in_cuda_compile_ "${${var}}") - # we reomove /EHa as it leasd warnings under windows + # we remove /EHa as it generates warnings under windows string(REPLACE "/EHa" "" ${var} "${${var}}") # we remove -ggdb3 flag as it leads to preprocessor errors when compiling CUDA files (CUDA 4.1) string(REPLACE "-ggdb3" "" ${var} "${${var}}") + + # we remove -Wsign-promo as it generates warnings under linux + string(REPLACE "-Wsign-promo" "" ${var} "${${var}}") + + # we remove -fvisibility-inlines-hidden because it's used for C++ compiler + # but NVCC uses C compiler by default + string(REPLACE "-fvisibility-inlines-hidden" "" ${var} "${${var}}") endforeach() if(BUILD_SHARED_LIBS) diff --git a/cmake/OpenCVDetectCXXCompiler.cmake b/cmake/OpenCVDetectCXXCompiler.cmake index 6e02780009..7efcba7c1e 100644 --- a/cmake/OpenCVDetectCXXCompiler.cmake +++ b/cmake/OpenCVDetectCXXCompiler.cmake @@ -27,23 +27,23 @@ endif() # the -fPIC flag should be used. # ---------------------------------------------------------------------------- if(UNIX) - if (__ICL) - set(CV_ICC __ICL) - elseif(__ICC) - set(CV_ICC __ICC) - elseif(__ECL) - set(CV_ICC __ECL) - elseif(__ECC) - set(CV_ICC __ECC) - elseif(__INTEL_COMPILER) - set(CV_ICC __INTEL_COMPILER) - elseif(CMAKE_C_COMPILER MATCHES "icc") - set(CV_ICC icc_matches_c_compiler) - endif() + if (__ICL) + set(CV_ICC __ICL) + elseif(__ICC) + set(CV_ICC __ICC) + elseif(__ECL) + set(CV_ICC __ECL) + elseif(__ECC) + set(CV_ICC __ECC) + elseif(__INTEL_COMPILER) + set(CV_ICC __INTEL_COMPILER) + elseif(CMAKE_C_COMPILER MATCHES "icc") + set(CV_ICC icc_matches_c_compiler) + endif() endif() if(MSVC AND CMAKE_C_COMPILER MATCHES "icc") - set(CV_ICC __INTEL_COMPILER_FOR_WINDOWS) + set(CV_ICC __INTEL_COMPILER_FOR_WINDOWS) endif() # ---------------------------------------------------------------------------- @@ -64,43 +64,49 @@ if(CMAKE_COMPILER_IS_CLANGCXX) string(REGEX MATCH "[0-9]+\\.[0-9]+" CMAKE_CLANG_REGEX_VERSION "${CMAKE_OPENCV_CLANG_VERSION_FULL}") elseif(CMAKE_COMPILER_IS_GNUCXX) - execute_process(COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} -dumpversion - OUTPUT_VARIABLE CMAKE_OPENCV_GCC_VERSION_FULL - OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} -dumpversion + OUTPUT_VARIABLE CMAKE_OPENCV_GCC_VERSION_FULL + OUTPUT_STRIP_TRAILING_WHITESPACE) - execute_process(COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} -v - ERROR_VARIABLE CMAKE_OPENCV_GCC_INFO_FULL - OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} -v + ERROR_VARIABLE CMAKE_OPENCV_GCC_INFO_FULL + OUTPUT_STRIP_TRAILING_WHITESPACE) - # Typical output in CMAKE_OPENCV_GCC_VERSION_FULL: "c+//0 (whatever) 4.2.3 (...)" - # Look for the version number - string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" CMAKE_GCC_REGEX_VERSION "${CMAKE_OPENCV_GCC_VERSION_FULL}") - if(NOT CMAKE_GCC_REGEX_VERSION) - 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}") - - list(GET CMAKE_OPENCV_GCC_VERSIONS 0 CMAKE_OPENCV_GCC_VERSION_MAJOR) - list(GET CMAKE_OPENCV_GCC_VERSIONS 1 CMAKE_OPENCV_GCC_VERSION_MINOR) - - 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}") - message(STATUS "Detected version of GNU GCC: ${CMAKE_OPENCV_GCC_VERSION} (${CMAKE_OPENCV_GCC_VERSION_NUM})") - - if(WIN32) - execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpmachine - OUTPUT_VARIABLE CMAKE_OPENCV_GCC_TARGET_MACHINE - OUTPUT_STRIP_TRAILING_WHITESPACE) - if(CMAKE_OPENCV_GCC_TARGET_MACHINE MATCHES "64") - set(MINGW64 1) - endif() + # Typical output in CMAKE_OPENCV_GCC_VERSION_FULL: "c+//0 (whatever) 4.2.3 (...)" + # Look for the version number + string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" CMAKE_GCC_REGEX_VERSION "${CMAKE_OPENCV_GCC_VERSION_FULL}") + if(NOT CMAKE_GCC_REGEX_VERSION) + 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}") + + list(GET CMAKE_OPENCV_GCC_VERSIONS 0 CMAKE_OPENCV_GCC_VERSION_MAJOR) + list(GET CMAKE_OPENCV_GCC_VERSIONS 1 CMAKE_OPENCV_GCC_VERSION_MINOR) + + 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}") + message(STATUS "Detected version of GNU GCC: ${CMAKE_OPENCV_GCC_VERSION} (${CMAKE_OPENCV_GCC_VERSION_NUM})") + + if(WIN32) + execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpmachine + OUTPUT_VARIABLE CMAKE_OPENCV_GCC_TARGET_MACHINE + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(CMAKE_OPENCV_GCC_TARGET_MACHINE MATCHES "amd64|x86_64|AMD64") + set(MINGW64 1) endif() + endif() endif() -if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*" OR CMAKE_GENERATOR MATCHES "Visual Studio.*Win64") - set(X86_64 1) +if(MSVC64 OR MINGW64) + set(X86_64 1) +elseif(MINGW OR (MSVC AND NOT CMAKE_CROSSCOMPILING)) + set(X86 1) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*") + set(X86_64 1) elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*|amd64.*|AMD64.*") - set(X86 1) + set(X86 1) +elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "arm.*|ARM.*") + set(ARM 1) endif() diff --git a/cmake/OpenCVDetectOpenCL.cmake b/cmake/OpenCVDetectOpenCL.cmake index 12ab9d3eae..c96df82e2b 100644 --- a/cmake/OpenCVDetectOpenCL.cmake +++ b/cmake/OpenCVDetectOpenCL.cmake @@ -1,154 +1,126 @@ if(APPLE) set(OPENCL_FOUND YES) - set(OPENCL_LIBRARIES "-framework OpenCL") -else() - find_package(OpenCL QUIET) - if(WITH_OPENCLAMDFFT) - set(CLAMDFFT_SEARCH_PATH $ENV{CLAMDFFT_PATH}) - if(NOT CLAMDFFT_SEARCH_PATH) - if(WIN32) - set( CLAMDFFT_SEARCH_PATH "C:\\Program Files (x86)\\AMD\\clAmdFft" ) - endif() - endif() - set( CLAMDFFT_INCLUDE_SEARCH_PATH ${CLAMDFFT_SEARCH_PATH}/include ) - if(UNIX) - if(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(CLAMDFFT_LIB_SEARCH_PATH /usr/lib) - else() - set(CLAMDFFT_LIB_SEARCH_PATH /usr/lib64) - endif() - else() - if(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(CLAMDFFT_LIB_SEARCH_PATH ${CLAMDFFT_SEARCH_PATH}\\lib32\\import) - else() - set(CLAMDFFT_LIB_SEARCH_PATH ${CLAMDFFT_SEARCH_PATH}\\lib64\\import) - endif() - endif() - find_path(CLAMDFFT_INCLUDE_DIR - NAMES clAmdFft.h - PATHS ${CLAMDFFT_INCLUDE_SEARCH_PATH} - PATH_SUFFIXES clAmdFft - NO_DEFAULT_PATH) - find_library(CLAMDFFT_LIBRARY - NAMES clAmdFft.Runtime - PATHS ${CLAMDFFT_LIB_SEARCH_PATH} - NO_DEFAULT_PATH) - if(CLAMDFFT_LIBRARY) - set(CLAMDFFT_LIBRARIES ${CLAMDFFT_LIBRARY}) - else() - set(CLAMDFFT_LIBRARIES "") - endif() - endif() - if(WITH_OPENCLAMDBLAS) - set(CLAMDBLAS_SEARCH_PATH $ENV{CLAMDBLAS_PATH}) - if(NOT CLAMDBLAS_SEARCH_PATH) - if(WIN32) - set( CLAMDBLAS_SEARCH_PATH "C:\\Program Files (x86)\\AMD\\clAmdBlas" ) - endif() - endif() - set( CLAMDBLAS_INCLUDE_SEARCH_PATH ${CLAMDBLAS_SEARCH_PATH}/include ) - if(UNIX) - if(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(CLAMDBLAS_LIB_SEARCH_PATH /usr/lib) - else() - set(CLAMDBLAS_LIB_SEARCH_PATH /usr/lib64) - endif() - else() - if(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(CLAMDBLAS_LIB_SEARCH_PATH ${CLAMDBLAS_SEARCH_PATH}\\lib32\\import) - else() - set(CLAMDBLAS_LIB_SEARCH_PATH ${CLAMDBLAS_SEARCH_PATH}\\lib64\\import) - endif() - endif() - find_path(CLAMDBLAS_INCLUDE_DIR - NAMES clAmdBlas.h - PATHS ${CLAMDBLAS_INCLUDE_SEARCH_PATH} - PATH_SUFFIXES clAmdBlas - NO_DEFAULT_PATH) - find_library(CLAMDBLAS_LIBRARY - NAMES clAmdBlas - PATHS ${CLAMDBLAS_LIB_SEARCH_PATH} - NO_DEFAULT_PATH) - if(CLAMDBLAS_LIBRARY) - set(CLAMDBLAS_LIBRARIES ${CLAMDBLAS_LIBRARY}) - else() - set(CLAMDBLAS_LIBRARIES "") - endif() - endif() - # Try AMD/ATI Stream SDK + set(OPENCL_LIBRARY "-framework OpenCL" CACHE STRING "OpenCL library") + set(OPENCL_INCLUDE_DIR "" CACHE STRING "OpenCL include directory") + mark_as_advanced(OPENCL_INCLUDE_DIR OPENCL_LIBRARY) +else(APPLE) + #find_package(OpenCL QUIET) + if (NOT OPENCL_FOUND) - set(ENV_AMDSTREAMSDKROOT $ENV{AMDAPPSDKROOT}) - set(ENV_AMDAPPSDKROOT $ENV{AMDAPPSDKROOT}) - set(ENV_OPENCLROOT $ENV{OPENCLROOT}) - set(ENV_CUDA_PATH $ENV{CUDA_PATH}) - set(ENV_INTELOCLSDKROOT $ENV{INTELOCLSDKROOT}) - if(ENV_AMDSTREAMSDKROOT) - set(OPENCL_INCLUDE_SEARCH_PATH ${ENV_AMDAPPSDKROOT}/include) - if(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(OPENCL_LIB_SEARCH_PATH ${OPENCL_LIB_SEARCH_PATH} ${ENV_AMDAPPSDKROOT}/lib/x86) - else() - set(OPENCL_LIB_SEARCH_PATH ${OPENCL_LIB_SEARCH_PATH} ${ENV_AMDAPPSDKROOT}/lib/x86_64) - endif() - elseif(ENV_AMDSTREAMSDKROOT) - set(OPENCL_INCLUDE_SEARCH_PATH ${ENV_AMDSTREAMSDKROOT}/include) - if(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(OPENCL_LIB_SEARCH_PATH ${OPENCL_LIB_SEARCH_PATH} ${ENV_AMDSTREAMSDKROOT}/lib/x86) - else() - set(OPENCL_LIB_SEARCH_PATH ${OPENCL_LIB_SEARCH_PATH} ${ENV_AMDSTREAMSDKROOT}/lib/x86_64) - endif() - elseif(ENV_CUDA_PATH AND WIN32) - set(OPENCL_INCLUDE_SEARCH_PATH ${ENV_CUDA_PATH}/include) - if(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(OPENCL_LIB_SEARCH_PATH ${OPENCL_LIB_SEARCH_PATH} ${ENV_CUDA_PATH}/lib/Win32) - else() - set(OPENCL_LIB_SEARCH_PATH ${OPENCL_LIB_SEARCH_PATH} ${ENV_CUDA_PATH}/lib/x64) - endif() - elseif(ENV_OPENCLROOT AND UNIX) - set(OPENCL_INCLUDE_SEARCH_PATH ${ENV_OPENCLROOT}/inc) - if(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(OPENCL_LIB_SEARCH_PATH ${OPENCL_LIB_SEARCH_PATH} /usr/lib) - else() - set(OPENCL_LIB_SEARCH_PATH ${OPENCL_LIB_SEARCH_PATH} /usr/lib64) - endif() - elseif(ENV_INTELOCLSDKROOT) - set(OPENCL_INCLUDE_SEARCH_PATH ${ENV_INTELOCLSDKROOT}/include) - if(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(OPENCL_LIB_SEARCH_PATH ${OPENCL_LIB_SEARCH_PATH} ${ENV_INTELOCLSDKROOT}/lib/x86) - else() - set(OPENCL_LIB_SEARCH_PATH ${OPENCL_LIB_SEARCH_PATH} ${ENV_INTELOCLSDKROOT}/lib/x64) - endif() - endif() + find_path(OPENCL_ROOT_DIR + NAMES OpenCL/cl.h CL/cl.h include/CL/cl.h include/nvidia-current/CL/cl.h + PATHS ENV OCLROOT ENV AMDAPPSDKROOT ENV CUDA_PATH ENV INTELOCLSDKROOT + DOC "OpenCL root directory" + NO_DEFAULT_PATH) - if(OPENCL_INCLUDE_SEARCH_PATH) - find_path(OPENCL_INCLUDE_DIR - NAMES CL/cl.h OpenCL/cl.h - PATHS ${OPENCL_INCLUDE_SEARCH_PATH} - NO_DEFAULT_PATH) + find_path(OPENCL_INCLUDE_DIR + NAMES OpenCL/cl.h CL/cl.h + HINTS ${OPENCL_ROOT_DIR} + PATH_SUFFIXES include include/nvidia-current + DOC "OpenCL include directory" + NO_DEFAULT_PATH) + + if(WIN32) + if(X86_64) + set(OPENCL_POSSIBLE_LIB_SUFFIXES lib/Win64 lib/x86_64 lib/x64) + elseif(X86) + set(OPENCL_POSSIBLE_LIB_SUFFIXES lib/Win32 lib/x86) + else() + set(OPENCL_POSSIBLE_LIB_SUFFIXES lib) + endif() + elseif(UNIX) + if(X86_64) + set(OPENCL_POSSIBLE_LIB_SUFFIXES lib64 lib) + elseif(X86) + set(OPENCL_POSSIBLE_LIB_SUFFIXES lib32 lib) + else() + set(OPENCL_POSSIBLE_LIB_SUFFIXES lib) + endif() else() - find_path(OPENCL_INCLUDE_DIR - NAMES CL/cl.h OpenCL/cl.h) + set(OPENCL_POSSIBLE_LIB_SUFFIXES lib) endif() - if(OPENCL_LIB_SEARCH_PATH) - find_library(OPENCL_LIBRARY NAMES OpenCL PATHS ${OPENCL_LIB_SEARCH_PATH} NO_DEFAULT_PATH) - else() - find_library(OPENCL_LIBRARY NAMES OpenCL) - endif() + find_library(OPENCL_LIBRARY + NAMES OpenCL + HINTS ${OPENCL_ROOT_DIR} + PATH_SUFFIXES ${OPENCL_POSSIBLE_LIB_SUFFIXES} + DOC "OpenCL library" + NO_DEFAULT_PATH) + mark_as_advanced(OPENCL_INCLUDE_DIR OPENCL_LIBRARY) include(FindPackageHandleStandardArgs) - find_package_handle_standard_args( - OPENCL - DEFAULT_MSG - OPENCL_LIBRARY OPENCL_INCLUDE_DIR - ) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(OPENCL DEFAULT_MSG OPENCL_LIBRARY OPENCL_INCLUDE_DIR ) + endif() +endif(APPLE) - if(OPENCL_FOUND) - set(OPENCL_LIBRARIES ${OPENCL_LIBRARY}) - set(HAVE_OPENCL 1) - else() - set(OPENCL_LIBRARIES) +if(OPENCL_FOUND) + set(HAVE_OPENCL 1) + set(OPENCL_INCLUDE_DIRS ${OPENCL_INCLUDE_DIR}) + set(OPENCL_LIBRARIES ${OPENCL_LIBRARY}) + + if(WIN32 AND X86_64) + set(CLAMD_POSSIBLE_LIB_SUFFIXES lib64/import) + elseif(WIN32) + set(CLAMD_POSSIBLE_LIB_SUFFIXES lib32/import) + endif() + + if(X86_64 AND UNIX) + set(CLAMD_POSSIBLE_LIB_SUFFIXES lib64) + elseif(X86 AND UNIX) + set(CLAMD_POSSIBLE_LIB_SUFFIXES lib32) + endif() + + if(WITH_OPENCLAMDFFT) + find_path(CLAMDFFT_ROOT_DIR + NAMES include/clAmdFft.h + PATHS ENV CLAMDFFT_PATH ENV ProgramFiles + PATH_SUFFIXES clAmdFft AMD/clAmdFft + DOC "AMD FFT root directory" + NO_DEFAULT_PATH) + + find_path(CLAMDFFT_INCLUDE_DIR + NAMES clAmdFft.h + HINTS ${CLAMDFFT_ROOT_DIR} + PATH_SUFFIXES include + DOC "clAmdFft include directory") + + find_library(CLAMDFFT_LIBRARY + NAMES clAmdFft.Runtime + HINTS ${CLAMDFFT_ROOT_DIR} + PATH_SUFFIXES ${CLAMD_POSSIBLE_LIB_SUFFIXES} + DOC "clAmdFft library") + + if(CLAMDFFT_LIBRARY AND CLAMDFFT_INCLUDE_DIR) + set(HAVE_CLAMDFFT 1) + list(APPEND OPENCL_INCLUDE_DIRS "${CLAMDFFT_INCLUDE_DIR}") + list(APPEND OPENCL_LIBRARIES "${CLAMDFFT_LIBRARY}") + endif() + endif() + + if(WITH_OPENCLAMDBLAS) + find_path(CLAMDBLAS_ROOT_DIR + NAMES include/clAmdBlas.h + PATHS ENV CLAMDBLAS_PATH ENV ProgramFiles + PATH_SUFFIXES clAmdBlas AMD/clAmdBlas + DOC "AMD FFT root directory" + NO_DEFAULT_PATH) + + find_path(CLAMDBLAS_INCLUDE_DIR + NAMES clAmdBlas.h + HINTS ${CLAMDBLAS_ROOT_DIR} + PATH_SUFFIXES include + DOC "clAmdFft include directory") + + find_library(CLAMDBLAS_LIBRARY + NAMES clAmdBlas + HINTS ${CLAMDBLAS_ROOT_DIR} + PATH_SUFFIXES ${CLAMD_POSSIBLE_LIB_SUFFIXES} + DOC "clAmdBlas library") + + if(CLAMDBLAS_LIBRARY AND CLAMDBLAS_INCLUDE_DIR) + set(HAVE_CLAMDBLAS 1) + list(APPEND OPENCL_INCLUDE_DIRS "${CLAMDBLAS_INCLUDE_DIR}") + list(APPEND OPENCL_LIBRARIES "${CLAMDBLAS_LIBRARY}") endif() - else() - set(HAVE_OPENCL 1) endif() endif() diff --git a/cmake/OpenCVDetectPython.cmake b/cmake/OpenCVDetectPython.cmake index 73143b7341..0ef0be9c99 100644 --- a/cmake/OpenCVDetectPython.cmake +++ b/cmake/OpenCVDetectPython.cmake @@ -2,7 +2,7 @@ if(WIN32 AND NOT PYTHON_EXECUTABLE) # search for executable with the same bitness as resulting binaries # standard FindPythonInterp always prefers executable from system path # this is really important because we are using the interpreter for numpy search and for choosing the install location - foreach(_CURRENT_VERSION ${Python_ADDITIONAL_VERSIONS} 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) + foreach(_CURRENT_VERSION ${Python_ADDITIONAL_VERSIONS} 2.7 "${MIN_VER_PYTHON}") find_host_program(PYTHON_EXECUTABLE NAMES python${_CURRENT_VERSION} python PATHS @@ -12,45 +12,20 @@ if(WIN32 AND NOT PYTHON_EXECUTABLE) ) endforeach() endif() -find_host_package(PythonInterp 2.0) +find_host_package(PythonInterp "${MIN_VER_PYTHON}") -unset(PYTHON_USE_NUMPY CACHE) unset(HAVE_SPHINX CACHE) -if(PYTHON_EXECUTABLE) - if(PYTHON_VERSION_STRING) - set(PYTHON_VERSION_MAJOR_MINOR "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}") - set(PYTHON_VERSION_FULL "${PYTHON_VERSION_STRING}") - else() - execute_process(COMMAND ${PYTHON_EXECUTABLE} --version - ERROR_VARIABLE PYTHON_VERSION_FULL - ERROR_STRIP_TRAILING_WHITESPACE) - string(REGEX MATCH "[0-9]+.[0-9]+" PYTHON_VERSION_MAJOR_MINOR "${PYTHON_VERSION_FULL}") - endif() - - if("${PYTHON_VERSION_FULL}" MATCHES "[0-9]+.[0-9]+.[0-9]+") - set(PYTHON_VERSION_FULL "${CMAKE_MATCH_0}") - elseif("${PYTHON_VERSION_FULL}" MATCHES "[0-9]+.[0-9]+") - set(PYTHON_VERSION_FULL "${CMAKE_MATCH_0}") - else() - unset(PYTHON_VERSION_FULL) - endif() +if(PYTHONINTERP_FOUND) + set(PYTHON_VERSION_MAJOR_MINOR "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}") if(NOT ANDROID AND NOT IOS) - if(CMAKE_VERSION VERSION_GREATER 2.8.8 AND PYTHON_VERSION_FULL) - find_host_package(PythonLibs ${PYTHON_VERSION_FULL} EXACT) - else() - find_host_package(PythonLibs ${PYTHON_VERSION_FULL}) - endif() - # cmake 2.4 (at least on Ubuntu 8.04 (hardy)) don't define PYTHONLIBS_FOUND - if(NOT PYTHONLIBS_FOUND AND PYTHON_INCLUDE_PATH) - set(PYTHONLIBS_FOUND ON) - endif() + find_host_package(PythonLibs "${PYTHON_VERSION_STRING}" EXACT) endif() if(NOT ANDROID AND NOT IOS) if(CMAKE_HOST_UNIX) - execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import *; print get_python_lib()" + execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import *; print(get_python_lib())" RESULT_VARIABLE PYTHON_CVPY_PROCESS OUTPUT_VARIABLE PYTHON_STD_PACKAGES_PATH OUTPUT_STRIP_TRAILING_WHITESPACE) @@ -79,46 +54,40 @@ if(PYTHON_EXECUTABLE) endif() SET(PYTHON_PACKAGES_PATH "${_PYTHON_PACKAGES_PATH}" CACHE PATH "Where to install the python packages.") - if(NOT PYTHON_NUMPY_INCLUDE_DIR) + if(NOT PYTHON_NUMPY_INCLUDE_DIRS) # Attempt to discover the NumPy include directory. If this succeeds, then build python API with NumPy - execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import os; os.environ['DISTUTILS_USE_SDK']='1'; import numpy.distutils; print numpy.distutils.misc_util.get_numpy_include_dirs()[0]" + execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c + "import os; os.environ['DISTUTILS_USE_SDK']='1'; import numpy.distutils; print(os.pathsep.join(numpy.distutils.misc_util.get_numpy_include_dirs()))" RESULT_VARIABLE PYTHON_NUMPY_PROCESS - OUTPUT_VARIABLE PYTHON_NUMPY_INCLUDE_DIR + OUTPUT_VARIABLE PYTHON_NUMPY_INCLUDE_DIRS OUTPUT_STRIP_TRAILING_WHITESPACE) if(PYTHON_NUMPY_PROCESS EQUAL 0) - file(TO_CMAKE_PATH "${PYTHON_NUMPY_INCLUDE_DIR}" _PYTHON_NUMPY_INCLUDE_DIR) - set(PYTHON_NUMPY_INCLUDE_DIR ${_PYTHON_NUMPY_INCLUDE_DIR} CACHE PATH "Path to numpy headers") + file(TO_CMAKE_PATH "${PYTHON_NUMPY_INCLUDE_DIRS}" _PYTHON_NUMPY_INCLUDE_DIRS) + set(PYTHON_NUMPY_INCLUDE_DIRS "${_PYTHON_NUMPY_INCLUDE_DIRS}" CACHE PATH "Path to numpy headers") endif() endif() - if(PYTHON_NUMPY_INCLUDE_DIR) - set(PYTHON_USE_NUMPY TRUE) - execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import numpy; print numpy.version.version" - RESULT_VARIABLE PYTHON_NUMPY_PROCESS - OUTPUT_VARIABLE PYTHON_NUMPY_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE) + if(PYTHON_NUMPY_INCLUDE_DIRS) + execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c "import numpy; print(numpy.version.version)" + OUTPUT_VARIABLE PYTHON_NUMPY_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) endif() endif(NOT ANDROID AND NOT IOS) +endif() - if(BUILD_DOCS) - find_host_program(SPHINX_BUILD sphinx-build) - if(SPHINX_BUILD) - if(UNIX) - execute_process(COMMAND sh -c "${SPHINX_BUILD} -_ 2>&1 | sed -ne 1p" - RESULT_VARIABLE SPHINX_PROCESS - OUTPUT_VARIABLE SPHINX_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE) - else() - execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import sphinx; print sphinx.__version__" - RESULT_VARIABLE SPHINX_PROCESS - OUTPUT_VARIABLE SPHINX_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE) - endif() - if(SPHINX_PROCESS EQUAL 0) - set(HAVE_SPHINX 1) - message(STATUS "Found Sphinx ${SPHINX_VERSION}: ${SPHINX_BUILD}") - endif() - endif() - endif(BUILD_DOCS) -endif(PYTHON_EXECUTABLE) +if(BUILD_DOCS) + find_host_program(SPHINX_BUILD sphinx-build) + find_host_program(PLANTUML plantuml) + if(SPHINX_BUILD) + execute_process(COMMAND "${SPHINX_BUILD}" + OUTPUT_QUIET + ERROR_VARIABLE SPHINX_OUTPUT + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(SPHINX_OUTPUT MATCHES "Sphinx v([0-9][^ \n]*)") + set(SPHINX_VERSION "${CMAKE_MATCH_1}") + set(HAVE_SPHINX 1) + message(STATUS "Found Sphinx ${SPHINX_VERSION}: ${SPHINX_BUILD}") + endif() + endif() +endif(BUILD_DOCS) diff --git a/cmake/OpenCVExtraTargets.cmake b/cmake/OpenCVExtraTargets.cmake index 936e3a2635..b4d339155a 100644 --- a/cmake/OpenCVExtraTargets.cmake +++ b/cmake/OpenCVExtraTargets.cmake @@ -13,57 +13,7 @@ endif() # ---------------------------------------------------------------------------- -# Source package, for "make package_source" -# ---------------------------------------------------------------------------- -if(BUILD_PACKAGE) - set(TARBALL_NAME "${CMAKE_PROJECT_NAME}-${OPENCV_VERSION}") - if (NOT WIN32) - if(APPLE) - set(TAR_CMD gnutar) - else() - set(TAR_CMD tar) - endif() - set(TAR_TRANSFORM "\"s,^,${TARBALL_NAME}/,\"") - add_custom_target(package_source - #TODO: maybe we should not remove dll's - COMMAND ${TAR_CMD} --transform ${TAR_TRANSFORM} -cjpf ${CMAKE_CURRENT_BINARY_DIR}/${TARBALL_NAME}.tar.bz2 --exclude=".svn" --exclude=".git" --exclude="*.pyc" --exclude="*.vcproj" --exclude="*/lib/*" --exclude="*.dll" ./ - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) - else() - add_custom_target(package_source - COMMAND zip -9 -r ${CMAKE_CURRENT_BINARY_DIR}/${TARBALL_NAME}.zip . -x '*/.svn/*' '*/.git/*' '*.vcproj' '*.pyc' - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) - endif() - if(ENABLE_SOLUTION_FOLDERS) - set_target_properties(package_source PROPERTIES FOLDER "extra") - endif() -endif() - - -# ---------------------------------------------------------------------------- -# performance tests, for "make perf" -# ---------------------------------------------------------------------------- -if(BUILD_PERF_TESTS AND PYTHON_EXECUTABLE) - if(CMAKE_VERSION VERSION_GREATER "2.8.2") - add_custom_target(perf - ${PYTHON_EXECUTABLE} "${OpenCV_SOURCE_DIR}/modules/ts/misc/run.py" --configuration $ "${CMAKE_BINARY_DIR}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - DEPENDS "${OpenCV_SOURCE_DIR}/modules/ts/misc/run.py" - ) - else() - add_custom_target(perf - ${PYTHON_EXECUTABLE} "${OpenCV_SOURCE_DIR}/modules/ts/misc/run.py" "${CMAKE_BINARY_DIR}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - DEPENDS "${OpenCV_SOURCE_DIR}/modules/ts/misc/run.py" - ) - endif() - if(ENABLE_SOLUTION_FOLDERS) - set_target_properties(perf PROPERTIES FOLDER "extra") - endif() -endif() - - -# ---------------------------------------------------------------------------- -# spefial targets to build all OpenCV modules +# target building all OpenCV modules # ---------------------------------------------------------------------------- add_custom_target(opencv_modules) if(ENABLE_SOLUTION_FOLDERS) @@ -72,7 +22,7 @@ endif() # ---------------------------------------------------------------------------- -# spefial targets to build all tests +# targets building all tests # ---------------------------------------------------------------------------- if(BUILD_TESTS) add_custom_target(opencv_tests) diff --git a/cmake/OpenCVFindIPP.cmake b/cmake/OpenCVFindIPP.cmake index d1af605653..772cae886f 100644 --- a/cmake/OpenCVFindIPP.cmake +++ b/cmake/OpenCVFindIPP.cmake @@ -136,12 +136,20 @@ endfunction() # ------------------------------------------------------------------------ # This is auxiliary function called from set_ipp_variables() -# to set IPP_LIBRARIES variable in IPP 7.x style +# to set IPP_LIBRARIES variable in IPP 7.x and 8.x style # ------------------------------------------------------------------------ -function(set_ipp_new_libraries) +function(set_ipp_new_libraries _LATEST_VERSION) set(IPP_PREFIX "ipp") - set(IPP_SUFFIX "_l") # static not threaded libs suffix - set(IPP_THRD "_t") # static threaded libs suffix + + if(${_LATEST_VERSION} VERSION_LESS "8.0") + set(IPP_SUFFIX "_l") # static not threaded libs suffix IPP 7.x + else() + if(WIN32) + set(IPP_SUFFIX "mt") # static not threaded libs suffix IPP 8.x for Windows + else() + set(IPP_SUFFIX "") # static not threaded libs suffix IPP 8.x for Linux/OS X + endif() + endif() set(IPPCORE "core") # core functionality set(IPPSP "s") # signal processing set(IPPIP "i") # image processing @@ -199,7 +207,9 @@ function(set_ipp_variables _LATEST_VERSION) # set INCLUDE and LIB folders set(IPP_INCLUDE_DIRS ${IPP_ROOT_DIR}/include PARENT_SCOPE) - if (IPP_X64) + if (APPLE) + set(IPP_LIBRARY_DIRS ${IPP_ROOT_DIR}/lib PARENT_SCOPE) + elseif (IPP_X64) if(NOT EXISTS ${IPP_ROOT_DIR}/lib/intel64) message(SEND_ERROR "IPP EM64T libraries not found") endif() @@ -211,8 +221,8 @@ function(set_ipp_variables _LATEST_VERSION) set(IPP_LIBRARY_DIRS ${IPP_ROOT_DIR}/lib/ia32 PARENT_SCOPE) endif() - # set IPP_LIBRARIES variable (7.x lib names) - set_ipp_new_libraries() + # set IPP_LIBRARIES variable (7.x or 8.x lib names) + set_ipp_new_libraries(${_LATEST_VERSION}) set(IPP_LIBRARIES ${IPP_LIBRARIES} PARENT_SCOPE) message(STATUS "IPP libs: ${IPP_LIBRARIES}") @@ -336,4 +346,4 @@ if(WIN32 AND MINGW AND NOT IPP_LATEST_VERSION_MAJOR LESS 7) # See http://code.opencv.org/issues/1906 for additional details set(MSV_NTDLL "ntdll") set(IPP_LIBRARIES ${IPP_LIBRARIES} ${MSV_NTDLL}${IPP_LIB_SUFFIX}) -endif() \ No newline at end of file +endif() diff --git a/cmake/OpenCVFindLibsGUI.cmake b/cmake/OpenCVFindLibsGUI.cmake index c883a80ced..c80beca055 100644 --- a/cmake/OpenCVFindLibsGUI.cmake +++ b/cmake/OpenCVFindLibsGUI.cmake @@ -2,13 +2,39 @@ # Detect 3rd-party GUI libraries # ---------------------------------------------------------------------------- +#--- Win32 UI --- +ocv_clear_vars(HAVE_WIN32UI) +if(WITH_WIN32UI) + try_compile(HAVE_WIN32UI + "${OpenCV_BINARY_DIR}" + "${OpenCV_SOURCE_DIR}/cmake/checks/win32uitest.cpp" + CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=user32;gdi32") +endif() + # --- QT4 --- -ocv_clear_vars(HAVE_QT) +ocv_clear_vars(HAVE_QT HAVE_QT5) if(WITH_QT) - find_package(Qt4) - if(QT4_FOUND) - set(HAVE_QT TRUE) - add_definitions(-DHAVE_QT) # We need to define the macro this way, using cvconfig.h does not work + if(NOT WITH_QT EQUAL 4) + find_package(Qt5Core) + find_package(Qt5Gui) + find_package(Qt5Widgets) + find_package(Qt5Test) + find_package(Qt5Concurrent) + if(Qt5Core_FOUND AND Qt5Gui_FOUND AND Qt5Widgets_FOUND AND Qt5Test_FOUND AND Qt5Concurrent_FOUND) + set(HAVE_QT5 ON) + set(HAVE_QT ON) + find_package(Qt5OpenGL) + if(Qt5OpenGL_FOUND) + set(QT_QTOPENGL_FOUND ON) + endif() + endif() + endif() + + if(NOT HAVE_QT) + find_package(Qt4 REQUIRED QtCore QtGui QtTest) + if(QT4_FOUND) + set(HAVE_QT TRUE) + endif() endif() endif() @@ -25,17 +51,25 @@ endif() # --- OpenGl --- ocv_clear_vars(HAVE_OPENGL HAVE_QT_OPENGL) if(WITH_OPENGL) - if(WIN32 OR QT_QTOPENGL_FOUND OR HAVE_GTKGLEXT) + if(WITH_WIN32UI OR (HAVE_QT AND QT_QTOPENGL_FOUND) OR HAVE_GTKGLEXT) find_package (OpenGL QUIET) if(OPENGL_FOUND) set(HAVE_OPENGL TRUE) list(APPEND OPENCV_LINKER_LIBS ${OPENGL_LIBRARIES}) if(QT_QTOPENGL_FOUND) set(HAVE_QT_OPENGL TRUE) - add_definitions(-DHAVE_QT_OPENGL) else() ocv_include_directories(${OPENGL_INCLUDE_DIR}) endif() endif() endif() endif(WITH_OPENGL) + +# --- Carbon & Cocoa --- +if(APPLE) + if(WITH_CARBON) + set(HAVE_CARBON YES) + elseif(NOT IOS) + set(HAVE_COCOA YES) + endif() +endif() diff --git a/cmake/OpenCVFindLibsGrfmt.cmake b/cmake/OpenCVFindLibsGrfmt.cmake index 501f8ff3e8..d8ddcfeb71 100644 --- a/cmake/OpenCVFindLibsGrfmt.cmake +++ b/cmake/OpenCVFindLibsGrfmt.cmake @@ -6,22 +6,21 @@ if(BUILD_ZLIB) ocv_clear_vars(ZLIB_FOUND) else() - include(FindZLIB) + find_package(ZLIB "${MIN_VER_ZLIB}") if(ZLIB_FOUND AND ANDROID) - if(ZLIB_LIBRARY STREQUAL "${ANDROID_SYSROOT}/usr/lib/libz.so") - set(ZLIB_LIBRARY z) + if(ZLIB_LIBRARIES STREQUAL "${ANDROID_SYSROOT}/usr/lib/libz.so") set(ZLIB_LIBRARIES z) endif() endif() endif() if(NOT ZLIB_FOUND) - ocv_clear_vars(ZLIB_LIBRARY ZLIB_LIBRARIES ZLIB_INCLUDE_DIR) + ocv_clear_vars(ZLIB_LIBRARY ZLIB_LIBRARIES ZLIB_INCLUDE_DIRS) set(ZLIB_LIBRARY zlib) - set(ZLIB_LIBRARIES ${ZLIB_LIBRARY}) add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/zlib") - set(ZLIB_INCLUDE_DIR "${${ZLIB_LIBRARY}_SOURCE_DIR}" "${${ZLIB_LIBRARY}_BINARY_DIR}") + set(ZLIB_INCLUDE_DIRS "${${ZLIB_LIBRARY}_SOURCE_DIR}" "${${ZLIB_LIBRARY}_BINARY_DIR}") + set(ZLIB_LIBRARIES ${ZLIB_LIBRARY}) ocv_parse_header2(ZLIB "${${ZLIB_LIBRARY}_SOURCE_DIR}/zlib.h" ZLIB_VERSION) endif() @@ -36,34 +35,36 @@ if(WITH_TIFF) ocv_parse_header("${TIFF_INCLUDE_DIR}/tiff.h" TIFF_VERSION_LINES TIFF_VERSION_CLASSIC TIFF_VERSION_BIG TIFF_VERSION TIFF_BIGTIFF_VERSION) endif() endif() -endif() -if(WITH_TIFF AND NOT TIFF_FOUND) - ocv_clear_vars(TIFF_LIBRARY TIFF_LIBRARIES TIFF_INCLUDE_DIR) + if(NOT TIFF_FOUND) + ocv_clear_vars(TIFF_LIBRARY TIFF_LIBRARIES TIFF_INCLUDE_DIR) - set(TIFF_LIBRARY libtiff) - set(TIFF_LIBRARIES ${TIFF_LIBRARY}) - add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/libtiff") - set(TIFF_INCLUDE_DIR "${${TIFF_LIBRARY}_SOURCE_DIR}" "${${TIFF_LIBRARY}_BINARY_DIR}") - ocv_parse_header("${${TIFF_LIBRARY}_SOURCE_DIR}/tiff.h" TIFF_VERSION_LINES TIFF_VERSION_CLASSIC TIFF_VERSION_BIG TIFF_VERSION TIFF_BIGTIFF_VERSION) -endif() - -if(TIFF_VERSION_CLASSIC AND NOT TIFF_VERSION) - set(TIFF_VERSION ${TIFF_VERSION_CLASSIC}) -endif() - -if(TIFF_BIGTIFF_VERSION AND NOT TIFF_VERSION_BIG) - set(TIFF_VERSION_BIG ${TIFF_BIGTIFF_VERSION}) -endif() - -if(NOT TIFF_VERSION_STRING AND TIFF_INCLUDE_DIR) - list(GET TIFF_INCLUDE_DIR 0 _TIFF_INCLUDE_DIR) - if(EXISTS "${_TIFF_INCLUDE_DIR}/tiffvers.h") - file(STRINGS "${_TIFF_INCLUDE_DIR}/tiffvers.h" tiff_version_str REGEX "^#define[\t ]+TIFFLIB_VERSION_STR[\t ]+\"LIBTIFF, Version .*") - string(REGEX REPLACE "^#define[\t ]+TIFFLIB_VERSION_STR[\t ]+\"LIBTIFF, Version +([^ \\n]*).*" "\\1" TIFF_VERSION_STRING "${tiff_version_str}") - unset(tiff_version_str) + set(TIFF_LIBRARY libtiff) + set(TIFF_LIBRARIES ${TIFF_LIBRARY}) + add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/libtiff") + set(TIFF_INCLUDE_DIR "${${TIFF_LIBRARY}_SOURCE_DIR}" "${${TIFF_LIBRARY}_BINARY_DIR}") + ocv_parse_header("${${TIFF_LIBRARY}_SOURCE_DIR}/tiff.h" TIFF_VERSION_LINES TIFF_VERSION_CLASSIC TIFF_VERSION_BIG TIFF_VERSION TIFF_BIGTIFF_VERSION) endif() - unset(_TIFF_INCLUDE_DIR) + + if(TIFF_VERSION_CLASSIC AND NOT TIFF_VERSION) + set(TIFF_VERSION ${TIFF_VERSION_CLASSIC}) + endif() + + if(TIFF_BIGTIFF_VERSION AND NOT TIFF_VERSION_BIG) + set(TIFF_VERSION_BIG ${TIFF_BIGTIFF_VERSION}) + endif() + + if(NOT TIFF_VERSION_STRING AND TIFF_INCLUDE_DIR) + list(GET TIFF_INCLUDE_DIR 0 _TIFF_INCLUDE_DIR) + if(EXISTS "${_TIFF_INCLUDE_DIR}/tiffvers.h") + file(STRINGS "${_TIFF_INCLUDE_DIR}/tiffvers.h" tiff_version_str REGEX "^#define[\t ]+TIFFLIB_VERSION_STR[\t ]+\"LIBTIFF, Version .*") + string(REGEX REPLACE "^#define[\t ]+TIFFLIB_VERSION_STR[\t ]+\"LIBTIFF, Version +([^ \\n]*).*" "\\1" TIFF_VERSION_STRING "${tiff_version_str}") + unset(tiff_version_str) + endif() + unset(_TIFF_INCLUDE_DIR) + endif() + + set(HAVE_TIFF YES) endif() # --- libjpeg (optional) --- @@ -73,19 +74,20 @@ if(WITH_JPEG) else() include(FindJPEG) endif() + + if(NOT JPEG_FOUND) + ocv_clear_vars(JPEG_LIBRARY JPEG_LIBRARIES JPEG_INCLUDE_DIR) + + set(JPEG_LIBRARY libjpeg) + set(JPEG_LIBRARIES ${JPEG_LIBRARY}) + add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/libjpeg") + set(JPEG_INCLUDE_DIR "${${JPEG_LIBRARY}_SOURCE_DIR}") + endif() + + ocv_parse_header("${JPEG_INCLUDE_DIR}/jpeglib.h" JPEG_VERSION_LINES JPEG_LIB_VERSION) + set(HAVE_JPEG YES) endif() -if(WITH_JPEG AND NOT JPEG_FOUND) - ocv_clear_vars(JPEG_LIBRARY JPEG_LIBRARIES JPEG_INCLUDE_DIR) - - set(JPEG_LIBRARY libjpeg) - set(JPEG_LIBRARIES ${JPEG_LIBRARY}) - add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/libjpeg") - set(JPEG_INCLUDE_DIR "${${JPEG_LIBRARY}_SOURCE_DIR}") -endif() - -ocv_parse_header("${JPEG_INCLUDE_DIR}/jpeglib.h" JPEG_VERSION_LINES JPEG_LIB_VERSION) - # --- libwebp (optional) --- if(WITH_WEBP) @@ -129,19 +131,21 @@ if(WITH_JASPER) else() include(FindJasper) endif() -endif() -if(WITH_JASPER AND NOT JASPER_FOUND) - ocv_clear_vars(JASPER_LIBRARY JASPER_LIBRARIES JASPER_INCLUDE_DIR) + if(NOT JASPER_FOUND) + ocv_clear_vars(JASPER_LIBRARY JASPER_LIBRARIES JASPER_INCLUDE_DIR) - set(JASPER_LIBRARY libjasper) - set(JASPER_LIBRARIES ${JASPER_LIBRARY}) - add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/libjasper") - set(JASPER_INCLUDE_DIR "${${JASPER_LIBRARY}_SOURCE_DIR}") -endif() + set(JASPER_LIBRARY libjasper) + set(JASPER_LIBRARIES ${JASPER_LIBRARY}) + add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/libjasper") + set(JASPER_INCLUDE_DIR "${${JASPER_LIBRARY}_SOURCE_DIR}") + endif() -if(NOT JASPER_VERSION_STRING) - ocv_parse_header2(JASPER "${JASPER_INCLUDE_DIR}/jasper/jas_config.h" JAS_VERSION "") + set(HAVE_JASPER YES) + + if(NOT JASPER_VERSION_STRING) + ocv_parse_header2(JASPER "${JASPER_INCLUDE_DIR}/jasper/jas_config.h" JAS_VERSION "") + endif() endif() # --- libpng (optional, should be searched after zlib) --- @@ -151,30 +155,31 @@ if(WITH_PNG) else() include(FindPNG) if(PNG_FOUND) - check_include_file("${PNG_PNG_INCLUDE_DIR}/png.h" HAVE_PNG_H) + include(CheckIncludeFile) check_include_file("${PNG_PNG_INCLUDE_DIR}/libpng/png.h" HAVE_LIBPNG_PNG_H) - if(HAVE_PNG_H) - ocv_parse_header("${PNG_PNG_INCLUDE_DIR}/png.h" PNG_VERSION_LINES PNG_LIBPNG_VER_MAJOR PNG_LIBPNG_VER_MINOR PNG_LIBPNG_VER_RELEASE) - elseif(HAVE_LIBPNG_PNG_H) + if(HAVE_LIBPNG_PNG_H) ocv_parse_header("${PNG_PNG_INCLUDE_DIR}/libpng/png.h" PNG_VERSION_LINES PNG_LIBPNG_VER_MAJOR PNG_LIBPNG_VER_MINOR PNG_LIBPNG_VER_RELEASE) + else() + ocv_parse_header("${PNG_PNG_INCLUDE_DIR}/png.h" PNG_VERSION_LINES PNG_LIBPNG_VER_MAJOR PNG_LIBPNG_VER_MINOR PNG_LIBPNG_VER_RELEASE) endif() endif() endif() + + if(NOT PNG_FOUND) + ocv_clear_vars(PNG_LIBRARY PNG_LIBRARIES PNG_INCLUDE_DIR PNG_PNG_INCLUDE_DIR HAVE_LIBPNG_PNG_H PNG_DEFINITIONS) + + set(PNG_LIBRARY libpng) + set(PNG_LIBRARIES ${PNG_LIBRARY}) + add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/libpng") + set(PNG_INCLUDE_DIR "${${PNG_LIBRARY}_SOURCE_DIR}") + set(PNG_DEFINITIONS "") + ocv_parse_header("${PNG_INCLUDE_DIR}/png.h" PNG_VERSION_LINES PNG_LIBPNG_VER_MAJOR PNG_LIBPNG_VER_MINOR PNG_LIBPNG_VER_RELEASE) + endif() + + set(HAVE_PNG YES) + set(PNG_VERSION "${PNG_LIBPNG_VER_MAJOR}.${PNG_LIBPNG_VER_MINOR}.${PNG_LIBPNG_VER_RELEASE}") endif() -if(WITH_PNG AND NOT PNG_FOUND) - ocv_clear_vars(PNG_LIBRARY PNG_LIBRARIES PNG_INCLUDE_DIR PNG_PNG_INCLUDE_DIR HAVE_PNG_H HAVE_LIBPNG_PNG_H PNG_DEFINITIONS) - - set(PNG_LIBRARY libpng) - set(PNG_LIBRARIES ${PNG_LIBRARY}) - add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/libpng") - set(PNG_INCLUDE_DIR "${${PNG_LIBRARY}_SOURCE_DIR}") - set(PNG_DEFINITIONS "") - ocv_parse_header("${PNG_INCLUDE_DIR}/png.h" PNG_VERSION_LINES PNG_LIBPNG_VER_MAJOR PNG_LIBPNG_VER_MINOR PNG_LIBPNG_VER_RELEASE) -endif() - -set(PNG_VERSION "${PNG_LIBPNG_VER_MAJOR}.${PNG_LIBPNG_VER_MINOR}.${PNG_LIBPNG_VER_RELEASE}") - # --- OpenEXR (optional) --- if(WITH_OPENEXR) if(BUILD_OPENEXR) @@ -182,17 +187,14 @@ if(WITH_OPENEXR) else() include("${OpenCV_SOURCE_DIR}/cmake/OpenCVFindOpenEXR.cmake") endif() -endif() -if(WITH_OPENEXR AND NOT OPENEXR_FOUND) - ocv_clear_vars(OPENEXR_INCLUDE_PATHS OPENEXR_LIBRARIES OPENEXR_ILMIMF_LIBRARY OPENEXR_VERSION) + if(NOT OPENEXR_FOUND) + ocv_clear_vars(OPENEXR_INCLUDE_PATHS OPENEXR_LIBRARIES OPENEXR_ILMIMF_LIBRARY OPENEXR_VERSION) - set(OPENEXR_LIBRARIES IlmImf) - set(OPENEXR_ILMIMF_LIBRARY IlmImf) - add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/openexr") -endif() + set(OPENEXR_LIBRARIES IlmImf) + set(OPENEXR_ILMIMF_LIBRARY IlmImf) + add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/openexr") + endif() -#cmake 2.8.2 bug - it fails to determine zlib version -if(ZLIB_FOUND) - ocv_parse_header2(ZLIB "${ZLIB_INCLUDE_DIR}/zlib.h" ZLIB_VERSION) + set(HAVE_OPENEXR YES) endif() diff --git a/cmake/OpenCVFindLibsPerf.cmake b/cmake/OpenCVFindLibsPerf.cmake index 6e497accd3..b8945c257b 100644 --- a/cmake/OpenCVFindLibsPerf.cmake +++ b/cmake/OpenCVFindLibsPerf.cmake @@ -27,7 +27,7 @@ endif(WITH_CUDA) # --- Eigen --- if(WITH_EIGEN) find_path(EIGEN_INCLUDE_PATH "Eigen/Core" - PATHS /usr/local /opt /usr $ENV{EIGEN_ROOT}/include ENV ProgramFiles ENV ProgramW6432 + PATHS /usr/local /opt /usr $ENV{EIGEN_ROOT}/include ENV ProgramFiles ENV ProgramW6432 PATH_SUFFIXES include/eigen3 include/eigen2 Eigen/include/eigen3 Eigen/include/eigen2 DOC "The path to Eigen3/Eigen2 headers" CMAKE_FIND_ROOT_PATH_BOTH) @@ -88,8 +88,9 @@ endif() # --- OpenMP --- if(NOT HAVE_TBB AND NOT HAVE_CSTRIPES) set(_fname "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/omptest.cpp") - FILE(WRITE "${_fname}" "#ifndef _OPENMP\n#error\n#endif\nint main() { return 0; }\n") - TRY_COMPILE(HAVE_OPENMP "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp" "${_fname}") + file(WRITE "${_fname}" "#ifndef _OPENMP\n#error\n#endif\nint main() { return 0; }\n") + try_compile(HAVE_OPENMP "${CMAKE_BINARY_DIR}" "${_fname}") + file(REMOVE "${_fname}") else() set(HAVE_OPENMP 0) endif() @@ -104,8 +105,9 @@ endif() # --- Concurrency --- if(MSVC AND NOT HAVE_TBB AND NOT HAVE_CSTRIPES AND NOT HAVE_OPENMP) set(_fname "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/concurrencytest.cpp") - FILE(WRITE "${_fname}" "#if _MSC_VER < 1600\n#error\n#endif\nint main() { return 0; }\n") - TRY_COMPILE(HAVE_CONCURRENCY "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp" "${_fname}") + file(WRITE "${_fname}" "#if _MSC_VER < 1600\n#error\n#endif\nint main() { return 0; }\n") + try_compile(HAVE_CONCURRENCY "${CMAKE_BINARY_DIR}" "${_fname}") + file(REMOVE "${_fname}") else() set(HAVE_CONCURRENCY 0) endif() diff --git a/cmake/OpenCVFindLibsVideo.cmake b/cmake/OpenCVFindLibsVideo.cmake index 414918527b..eba6fa988c 100644 --- a/cmake/OpenCVFindLibsVideo.cmake +++ b/cmake/OpenCVFindLibsVideo.cmake @@ -2,17 +2,54 @@ # Detect 3rd-party video IO libraries # ---------------------------------------------------------------------------- +ocv_clear_vars(HAVE_VFW) +if(WITH_VFW) + try_compile(HAVE_VFW + "${OpenCV_BINARY_DIR}" + "${OpenCV_SOURCE_DIR}/cmake/checks/vfwtest.cpp" + CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=vfw32") +endif(WITH_VFW) + # --- GStreamer --- ocv_clear_vars(HAVE_GSTREAMER) -if(WITH_GSTREAMER) - CHECK_MODULE(gstreamer-base-0.10 HAVE_GSTREAMER) - if(HAVE_GSTREAMER) - CHECK_MODULE(gstreamer-app-0.10 HAVE_GSTREAMER) +# try to find gstreamer 0.10 first +if(WITH_GSTREAMER AND NOT WITH_GSTREAMER_1_X) + CHECK_MODULE(gstreamer-base-0.10 HAVE_GSTREAMER_BASE) + CHECK_MODULE(gstreamer-video-0.10 HAVE_GSTREAMER_VIDEO) + CHECK_MODULE(gstreamer-app-0.10 HAVE_GSTREAMER_APP) + CHECK_MODULE(gstreamer-riff-0.10 HAVE_GSTREAMER_RIFF) + CHECK_MODULE(gstreamer-pbutils-0.10 HAVE_GSTREAMER_PBUTILS) + + if(HAVE_GSTREAMER_BASE AND HAVE_GSTREAMER_VIDEO AND HAVE_GSTREAMER_APP AND HAVE_GSTREAMER_RIFF AND HAVE_GSTREAMER_PBUTILS) + set(HAVE_GSTREAMER TRUE) + set(GSTREAMER_BASE_VERSION ${ALIASOF_gstreamer-base-0.10_VERSION}) + set(GSTREAMER_VIDEO_VERSION ${ALIASOF_gstreamer-video-0.10_VERSION}) + set(GSTREAMER_APP_VERSION ${ALIASOF_gstreamer-app-0.10_VERSION}) + set(GSTREAMER_RIFF_VERSION ${ALIASOF_gstreamer-riff-0.10_VERSION}) + set(GSTREAMER_PBUTILS_VERSION ${ALIASOF_gstreamer-pbutils-0.10_VERSION}) endif() - if(HAVE_GSTREAMER) - CHECK_MODULE(gstreamer-video-0.10 HAVE_GSTREAMER) + +endif(WITH_GSTREAMER AND NOT WITH_GSTREAMER_1_X) + +# if gstreamer 0.10 was not found, or we specified we wanted 1.x, try to find it +if(WITH_GSTREAMER_1_X OR NOT HAVE_GSTREAMER) + #check for 1.x + CHECK_MODULE(gstreamer-base-1.0 HAVE_GSTREAMER_BASE) + CHECK_MODULE(gstreamer-video-1.0 HAVE_GSTREAMER_VIDEO) + CHECK_MODULE(gstreamer-app-1.0 HAVE_GSTREAMER_APP) + CHECK_MODULE(gstreamer-riff-1.0 HAVE_GSTREAMER_RIFF) + CHECK_MODULE(gstreamer-pbutils-1.0 HAVE_GSTREAMER_PBUTILS) + + if(HAVE_GSTREAMER_BASE AND HAVE_GSTREAMER_VIDEO AND HAVE_GSTREAMER_APP AND HAVE_GSTREAMER_RIFF AND HAVE_GSTREAMER_PBUTILS) + set(HAVE_GSTREAMER TRUE) + set(GSTREAMER_BASE_VERSION ${ALIASOF_gstreamer-base-1.0_VERSION}) + set(GSTREAMER_VIDEO_VERSION ${ALIASOF_gstreamer-video-1.0_VERSION}) + set(GSTREAMER_APP_VERSION ${ALIASOF_gstreamer-app-1.0_VERSION}) + set(GSTREAMER_RIFF_VERSION ${ALIASOF_gstreamer-riff-1.0_VERSION}) + set(GSTREAMER_PBUTILS_VERSION ${ALIASOF_gstreamer-pbutils-1.0_VERSION}) endif() -endif(WITH_GSTREAMER) + +endif(WITH_GSTREAMER_1_X OR NOT HAVE_GSTREAMER) # --- unicap --- ocv_clear_vars(HAVE_UNICAP) @@ -37,7 +74,7 @@ if(WITH_PVAPI) set(PVAPI_SDK_SUBDIR x86) elseif(X86_64) set(PVAPI_SDK_SUBDIR x64) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES arm) + elseif(ARM) set(PVAPI_SDK_SUBDIR arm) endif() @@ -49,7 +86,14 @@ if(WITH_PVAPI) set(_PVAPI_LIBRARY "${_PVAPI_LIBRARY}/${CMAKE_OPENCV_GCC_VERSION_MAJOR}.${CMAKE_OPENCV_GCC_VERSION_MINOR}") endif() - set(PVAPI_LIBRARY "${_PVAPI_LIBRARY}/${CMAKE_STATIC_LIBRARY_PREFIX}PvAPI${CMAKE_STATIC_LIBRARY_SUFFIX}" CACHE PATH "The PvAPI library") + if(WIN32) + if(MINGW) + set(PVAPI_DEFINITIONS "-DPVDECL=__stdcall") + endif(MINGW) + set(PVAPI_LIBRARY "${_PVAPI_LIBRARY}/PvAPI.lib" CACHE PATH "The PvAPI library") + else(WIN32) + set(PVAPI_LIBRARY "${_PVAPI_LIBRARY}/${CMAKE_STATIC_LIBRARY_PREFIX}PvAPI${CMAKE_STATIC_LIBRARY_SUFFIX}" CACHE PATH "The PvAPI library") + endif(WIN32) if(EXISTS "${PVAPI_LIBRARY}") set(HAVE_PVAPI TRUE) endif() @@ -72,10 +116,33 @@ endif(WITH_GIGEAPI) # --- Dc1394 --- ocv_clear_vars(HAVE_DC1394 HAVE_DC1394_2) if(WITH_1394) - CHECK_MODULE(libdc1394-2 HAVE_DC1394_2) - if(NOT HAVE_DC1394_2) - CHECK_MODULE(libdc1394 HAVE_DC1394) - endif() + if(WIN32 AND MINGW) + find_path(CMU1394_INCLUDE_PATH "/1394common.h" + PATH_SUFFIXES include + DOC "The path to cmu1394 headers") + find_path(DC1394_2_INCLUDE_PATH "/dc1394/dc1394.h" + PATH_SUFFIXES include + DOC "The path to DC1394 2.x headers") + if(CMU1394_INCLUDE_PATH AND DC1394_2_INCLUDE_PATH) + set(CMU1394_LIB_DIR "${CMU1394_INCLUDE_PATH}/../lib" CACHE PATH "Full path of CMU1394 library directory") + set(DC1394_2_LIB_DIR "${DC1394_2_INCLUDE_PATH}/../lib" CACHE PATH "Full path of DC1394 2.x library directory") + if(EXISTS "${CMU1394_LIB_DIR}/lib1394camera.a" AND EXISTS "${DC1394_2_LIB_DIR}/libdc1394.a") + set(HAVE_DC1394_2 TRUE) + endif() + endif() + if(HAVE_DC1394_2) + ocv_parse_pkg("libdc1394-2" "${DC1394_2_LIB_DIR}/pkgconfig" "") + ocv_include_directories(${DC1394_2_INCLUDE_PATH}) + set(HIGHGUI_LIBRARIES ${HIGHGUI_LIBRARIES} + "${DC1394_2_LIB_DIR}/libdc1394.a" + "${CMU1394_LIB_DIR}/lib1394camera.a") + endif(HAVE_DC1394_2) + else(WIN32 AND MINGW) + CHECK_MODULE(libdc1394-2 HAVE_DC1394_2) + if(NOT HAVE_DC1394_2) + CHECK_MODULE(libdc1394 HAVE_DC1394) + endif() + endif(WIN32 AND MINGW) endif(WITH_1394) # --- xine --- @@ -111,7 +178,7 @@ endif(WITH_XIMEA) # --- FFMPEG --- ocv_clear_vars(HAVE_FFMPEG HAVE_FFMPEG_CODEC HAVE_FFMPEG_FORMAT HAVE_FFMPEG_UTIL HAVE_FFMPEG_SWSCALE HAVE_GENTOO_FFMPEG HAVE_FFMPEG_FFMPEG) if(WITH_FFMPEG) - if(WIN32) + if(WIN32 AND NOT ARM) include("${OpenCV_SOURCE_DIR}/3rdparty/ffmpeg/ffmpeg_version.cmake") elseif(UNIX) CHECK_MODULE(libavcodec HAVE_FFMPEG_CODEC) @@ -175,15 +242,20 @@ if(WITH_FFMPEG) endif(APPLE) endif(WITH_FFMPEG) -# --- VideoInput --- -if(WITH_VIDEOINPUT) +# --- VideoInput/DirectShow --- +if(WITH_DSHOW) # always have VideoInput on Windows - set(HAVE_VIDEOINPUT 1) -endif(WITH_VIDEOINPUT) + set(HAVE_DSHOW 1) +endif(WITH_DSHOW) + +# --- VideoInput/Microsoft Media Foundation --- +if(WITH_MSMF) + check_include_file(Mfapi.h HAVE_MSMF) +endif(WITH_MSMF) # --- Extra HighGUI libs on Windows --- if(WIN32) - list(APPEND HIGHGUI_LIBRARIES comctl32 gdi32 ole32 vfw32) + list(APPEND HIGHGUI_LIBRARIES comctl32 gdi32 ole32 setupapi ws2_32 vfw32) if(MINGW64) list(APPEND HIGHGUI_LIBRARIES avifil32 avicap32 winmm msvfw32) list(REMOVE_ITEM HIGHGUI_LIBRARIES vfw32) @@ -191,3 +263,17 @@ if(WIN32) list(APPEND HIGHGUI_LIBRARIES winmm) endif() endif(WIN32) + +# --- Apple AV Foundation --- +if(WITH_AVFOUNDATION) + set(HAVE_AVFOUNDATION YES) +endif() + +# --- QuickTime --- +if (NOT IOS) + if(WITH_QUICKTIME) + set(HAVE_QUICKTIME YES) + elseif(APPLE) + set(HAVE_QTKIT YES) + endif() +endif() diff --git a/cmake/OpenCVFindPkgConfig.cmake b/cmake/OpenCVFindPkgConfig.cmake deleted file mode 100644 index 7e439fd8dc..0000000000 --- a/cmake/OpenCVFindPkgConfig.cmake +++ /dev/null @@ -1,365 +0,0 @@ -# -# OpenCV note: the file has been extracted from CMake 2.6.2 distribution. -# It is used to build OpenCV with CMake 2.4.x -# - -# - a pkg-config module for CMake -# -# Usage: -# pkg_check_modules( [REQUIRED] []*) -# checks for all the given modules -# -# pkg_search_module( [REQUIRED] []*) -# checks for given modules and uses the first working one -# -# When the 'REQUIRED' argument was set, macros will fail with an error -# when module(s) could not be found -# -# It sets the following variables: -# PKG_CONFIG_FOUND ... true if pkg-config works on the system -# PKG_CONFIG_EXECUTABLE ... pathname of the pkg-config program -# _FOUND ... set to 1 if module(s) exist -# -# For the following variables two sets of values exist; first one is the -# common one and has the given PREFIX. The second set contains flags -# which are given out when pkgconfig was called with the '--static' -# option. -# _LIBRARIES ... only the libraries (w/o the '-l') -# _LIBRARY_DIRS ... the paths of the libraries (w/o the '-L') -# _LDFLAGS ... all required linker flags -# _LDFLAGS_OTHER ... all other linker flags -# _INCLUDE_DIRS ... the '-I' preprocessor flags (w/o the '-I') -# _CFLAGS ... all required cflags -# _CFLAGS_OTHER ... the other compiler flags -# -# = for common case -# = _STATIC for static linking -# -# There are some special variables whose prefix depends on the count -# of given modules. When there is only one module, stays -# unchanged. When there are multiple modules, the prefix will be -# changed to _: -# _VERSION ... version of the module -# _PREFIX ... prefix-directory of the module -# _INCLUDEDIR ... include-dir of the module -# _LIBDIR ... lib-dir of the module -# -# = when |MODULES| == 1, else -# = _ -# -# A parameter can have the following formats: -# {MODNAME} ... matches any version -# {MODNAME}>={VERSION} ... at least version is required -# {MODNAME}={VERSION} ... exactly version is required -# {MODNAME}<={VERSION} ... modules must not be newer than -# -# Examples -# pkg_check_modules (GLIB2 glib-2.0) -# -# pkg_check_modules (GLIB2 glib-2.0>=2.10) -# requires at least version 2.10 of glib2 and defines e.g. -# GLIB2_VERSION=2.10.3 -# -# pkg_check_modules (FOO glib-2.0>=2.10 gtk+-2.0) -# requires both glib2 and gtk2, and defines e.g. -# FOO_glib-2.0_VERSION=2.10.3 -# FOO_gtk+-2.0_VERSION=2.8.20 -# -# pkg_check_modules (XRENDER REQUIRED xrender) -# defines e.g.: -# XRENDER_LIBRARIES=Xrender;X11 -# XRENDER_STATIC_LIBRARIES=Xrender;X11;pthread;Xau;Xdmcp -# -# pkg_search_module (BAR libxml-2.0 libxml2 libxml>=2) - - -# Copyright (C) 2006 Enrico Scholz -# -# Redistribution and use, with or without modification, are permitted -# provided that the following conditions are met: -# -# 1. Redistributions must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# 2. The name of the author may not be used to endorse or promote -# products derived from this software without specific prior -# written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - - -### Common stuff #### -set(PKG_CONFIG_VERSION 1) -set(PKG_CONFIG_FOUND 0) - -find_program(PKG_CONFIG_EXECUTABLE NAMES pkg-config DOC "pkg-config executable") -mark_as_advanced(PKG_CONFIG_EXECUTABLE) - -if(PKG_CONFIG_EXECUTABLE) - set(PKG_CONFIG_FOUND 1) -endif(PKG_CONFIG_EXECUTABLE) - - -# Unsets the given variables -macro(_pkgconfig_unset var) - set(${var} "" CACHE INTERNAL "") -endmacro(_pkgconfig_unset) - -macro(_pkgconfig_set var value) - set(${var} ${value} CACHE INTERNAL "") -endmacro(_pkgconfig_set) - -# Invokes pkgconfig, cleans up the result and sets variables -macro(_pkgconfig_invoke _pkglist _prefix _varname _regexp) - set(_pkgconfig_invoke_result) - - execute_process( - COMMAND ${PKG_CONFIG_EXECUTABLE} ${ARGN} ${_pkglist} - OUTPUT_VARIABLE _pkgconfig_invoke_result - RESULT_VARIABLE _pkgconfig_failed) - - if (_pkgconfig_failed) - set(_pkgconfig_${_varname} "") - _pkgconfig_unset(${_prefix}_${_varname}) - else(_pkgconfig_failed) - string(REGEX REPLACE "[\r\n]" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}") - string(REGEX REPLACE " +$" "" _pkgconfig_invoke_result "${_pkgconfig_invoke_result}") - - if (NOT ${_regexp} STREQUAL "") - string(REGEX REPLACE "${_regexp}" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}") - endif(NOT ${_regexp} STREQUAL "") - - separate_arguments(_pkgconfig_invoke_result) - - #message(STATUS " ${_varname} ... ${_pkgconfig_invoke_result}") - set(_pkgconfig_${_varname} ${_pkgconfig_invoke_result}) - _pkgconfig_set(${_prefix}_${_varname} "${_pkgconfig_invoke_result}") - endif(_pkgconfig_failed) -endmacro(_pkgconfig_invoke) - -# Invokes pkgconfig two times; once without '--static' and once with -# '--static' -macro(_pkgconfig_invoke_dyn _pkglist _prefix _varname cleanup_regexp) - _pkgconfig_invoke("${_pkglist}" ${_prefix} ${_varname} "${cleanup_regexp}" ${ARGN}) - _pkgconfig_invoke("${_pkglist}" ${_prefix} STATIC_${_varname} "${cleanup_regexp}" --static ${ARGN}) -endmacro(_pkgconfig_invoke_dyn) - -# Splits given arguments into options and a package list -macro(_pkgconfig_parse_options _result _is_req) - set(${_is_req} 0) - - foreach(_pkg ${ARGN}) - if (_pkg STREQUAL "REQUIRED") - set(${_is_req} 1) - endif (_pkg STREQUAL "REQUIRED") - endforeach(_pkg ${ARGN}) - - set(${_result} ${ARGN}) - list(REMOVE_ITEM ${_result} "REQUIRED") -endmacro(_pkgconfig_parse_options) - -### -macro(_pkg_check_modules_internal _is_required _is_silent _prefix) - _pkgconfig_unset(${_prefix}_FOUND) - _pkgconfig_unset(${_prefix}_VERSION) - _pkgconfig_unset(${_prefix}_PREFIX) - _pkgconfig_unset(${_prefix}_INCLUDEDIR) - _pkgconfig_unset(${_prefix}_LIBDIR) - _pkgconfig_unset(${_prefix}_LIBS) - _pkgconfig_unset(${_prefix}_LIBS_L) - _pkgconfig_unset(${_prefix}_LIBS_PATHS) - _pkgconfig_unset(${_prefix}_LIBS_OTHER) - _pkgconfig_unset(${_prefix}_CFLAGS) - _pkgconfig_unset(${_prefix}_CFLAGS_I) - _pkgconfig_unset(${_prefix}_CFLAGS_OTHER) - _pkgconfig_unset(${_prefix}_STATIC_LIBDIR) - _pkgconfig_unset(${_prefix}_STATIC_LIBS) - _pkgconfig_unset(${_prefix}_STATIC_LIBS_L) - _pkgconfig_unset(${_prefix}_STATIC_LIBS_PATHS) - _pkgconfig_unset(${_prefix}_STATIC_LIBS_OTHER) - _pkgconfig_unset(${_prefix}_STATIC_CFLAGS) - _pkgconfig_unset(${_prefix}_STATIC_CFLAGS_I) - _pkgconfig_unset(${_prefix}_STATIC_CFLAGS_OTHER) - - # create a better addressable variable of the modules and calculate its size - set(_pkg_check_modules_list ${ARGN}) - list(LENGTH _pkg_check_modules_list _pkg_check_modules_cnt) - - if(PKG_CONFIG_EXECUTABLE) - # give out status message telling checked module - if (NOT ${_is_silent}) - if (_pkg_check_modules_cnt EQUAL 1) - message(STATUS "checking for module '${_pkg_check_modules_list}'") - else(_pkg_check_modules_cnt EQUAL 1) - message(STATUS "checking for modules '${_pkg_check_modules_list}'") - endif(_pkg_check_modules_cnt EQUAL 1) - endif(NOT ${_is_silent}) - - set(_pkg_check_modules_packages) - set(_pkg_check_modules_failed) - - # iterate through module list and check whether they exist and match the required version - foreach (_pkg_check_modules_pkg ${_pkg_check_modules_list}) - set(_pkg_check_modules_exist_query) - - # check whether version is given - if (_pkg_check_modules_pkg MATCHES ".*(>=|=|<=).*") - string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\1" _pkg_check_modules_pkg_name "${_pkg_check_modules_pkg}") - string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\2" _pkg_check_modules_pkg_op "${_pkg_check_modules_pkg}") - string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\3" _pkg_check_modules_pkg_ver "${_pkg_check_modules_pkg}") - else(_pkg_check_modules_pkg MATCHES ".*(>=|=|<=).*") - set(_pkg_check_modules_pkg_name "${_pkg_check_modules_pkg}") - set(_pkg_check_modules_pkg_op) - set(_pkg_check_modules_pkg_ver) - endif(_pkg_check_modules_pkg MATCHES ".*(>=|=|<=).*") - - # handle the operands - if (_pkg_check_modules_pkg_op STREQUAL ">=") - list(APPEND _pkg_check_modules_exist_query --atleast-version) - endif(_pkg_check_modules_pkg_op STREQUAL ">=") - - if (_pkg_check_modules_pkg_op STREQUAL "=") - list(APPEND _pkg_check_modules_exist_query --exact-version) - endif(_pkg_check_modules_pkg_op STREQUAL "=") - - if (_pkg_check_modules_pkg_op STREQUAL "<=") - list(APPEND _pkg_check_modules_exist_query --max-version) - endif(_pkg_check_modules_pkg_op STREQUAL "<=") - - # create the final query which is of the format: - # * --atleast-version - # * --exact-version - # * --max-version - # * --exists - if (_pkg_check_modules_pkg_op) - list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_ver}") - else(_pkg_check_modules_pkg_op) - list(APPEND _pkg_check_modules_exist_query --exists) - endif(_pkg_check_modules_pkg_op) - - _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_VERSION) - _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_PREFIX) - _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_INCLUDEDIR) - _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_LIBDIR) - - list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_name}") - list(APPEND _pkg_check_modules_packages "${_pkg_check_modules_pkg_name}") - - # execute the query - execute_process( - COMMAND ${PKG_CONFIG_EXECUTABLE} ${_pkg_check_modules_exist_query} - RESULT_VARIABLE _pkgconfig_retval) - - # evaluate result and tell failures - if (_pkgconfig_retval) - if(NOT ${_is_silent}) - message(STATUS " package '${_pkg_check_modules_pkg}' not found") - endif(NOT ${_is_silent}) - - set(_pkg_check_modules_failed 1) - endif(_pkgconfig_retval) - endforeach(_pkg_check_modules_pkg) - - if(_pkg_check_modules_failed) - # fail when requested - if (${_is_required}) - message(SEND_ERROR "A required package was not found") - endif (${_is_required}) - else(_pkg_check_modules_failed) - # when we are here, we checked whether requested modules - # exist. Now, go through them and set variables - - _pkgconfig_set(${_prefix}_FOUND 1) - list(LENGTH _pkg_check_modules_packages pkg_count) - - # iterate through all modules again and set individual variables - foreach (_pkg_check_modules_pkg ${_pkg_check_modules_packages}) - # handle case when there is only one package required - if (pkg_count EQUAL 1) - set(_pkg_check_prefix "${_prefix}") - else(pkg_count EQUAL 1) - set(_pkg_check_prefix "${_prefix}_${_pkg_check_modules_pkg}") - endif(pkg_count EQUAL 1) - - _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" VERSION "" --modversion ) - _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" PREFIX "" --variable=prefix ) - _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" INCLUDEDIR "" --variable=includedir ) - _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" LIBDIR "" --variable=libdir ) - - message(STATUS " found ${_pkg_check_modules_pkg}, version ${_pkgconfig_VERSION}") - endforeach(_pkg_check_modules_pkg) - - # set variables which are combined for multiple modules - _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LIBRARIES "(^| )-l" --libs-only-l ) - _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LIBRARY_DIRS "(^| )-L" --libs-only-L ) - _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LDFLAGS "" --libs ) - _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LDFLAGS_OTHER "" --libs-only-other ) - - _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" INCLUDE_DIRS "(^| )-I" --cflags-only-I ) - _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS "" --cflags ) - _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS_OTHER "" --cflags-only-other ) - endif(_pkg_check_modules_failed) - else(PKG_CONFIG_EXECUTABLE) - if (${_is_required}) - message(SEND_ERROR "pkg-config tool not found") - endif (${_is_required}) - endif(PKG_CONFIG_EXECUTABLE) -endmacro(_pkg_check_modules_internal) - -### -### User visible macros start here -### - -### -macro(pkg_check_modules _prefix _module0) - # check cached value - if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND) - _pkgconfig_parse_options (_pkg_modules _pkg_is_required "${_module0}" ${ARGN}) - _pkg_check_modules_internal("${_pkg_is_required}" 0 "${_prefix}" ${_pkg_modules}) - - _pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION}) - endif(NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND) -endmacro(pkg_check_modules) - -### -macro(pkg_search_module _prefix _module0) - # check cached value - if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND) - set(_pkg_modules_found 0) - _pkgconfig_parse_options(_pkg_modules_alt _pkg_is_required "${_module0}" ${ARGN}) - - message(STATUS "checking for one of the modules '${_pkg_modules_alt}'") - - # iterate through all modules and stop at the first working one. - foreach(_pkg_alt ${_pkg_modules_alt}) - if(NOT _pkg_modules_found) - _pkg_check_modules_internal(0 1 "${_prefix}" "${_pkg_alt}") - endif(NOT _pkg_modules_found) - - if (${_prefix}_FOUND) - set(_pkg_modules_found 1) - endif(${_prefix}_FOUND) - endforeach(_pkg_alt) - - if (NOT ${_prefix}_FOUND) - if(${_pkg_is_required}) - message(SEND_ERROR "None of the required '${_pkg_modules_alt}' found") - endif(${_pkg_is_required}) - endif(NOT ${_prefix}_FOUND) - - _pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION}) - endif(NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND) -endmacro(pkg_search_module) - -### Local Variables: -### mode: cmake -### End: diff --git a/cmake/OpenCVFindXimea.cmake b/cmake/OpenCVFindXimea.cmake index 5600275f47..6b86b609e9 100644 --- a/cmake/OpenCVFindXimea.cmake +++ b/cmake/OpenCVFindXimea.cmake @@ -9,6 +9,7 @@ # # Created: 5 Aug 2011 by Marian Zajko (marian.zajko@ximea.com) # Updated: 25 June 2012 by Igor Kuzmin (parafin@ximea.com) +# Updated: 22 October 2012 by Marian Zajko (marian.zajko@ximea.com) # set(XIMEA_FOUND) @@ -19,10 +20,14 @@ if(WIN32) # Try to find the XIMEA API path in registry. GET_FILENAME_COMPONENT(XIMEA_PATH "[HKEY_CURRENT_USER\\Software\\XIMEA\\CamSupport\\API;Path]" ABSOLUTE) - if(EXISTS XIMEA_PATH) + if(EXISTS ${XIMEA_PATH}) set(XIMEA_FOUND 1) # set LIB folders - set(XIMEA_LIBRARY_DIR "${XIMEA_PATH}/x86") + if(CMAKE_CL_64) + set(XIMEA_LIBRARY_DIR "${XIMEA_PATH}/x64") + else() + set(XIMEA_LIBRARY_DIR "${XIMEA_PATH}/x86") + endif() else() set(XIMEA_FOUND 0) endif() @@ -39,4 +44,3 @@ endif() mark_as_advanced(FORCE XIMEA_FOUND) mark_as_advanced(FORCE XIMEA_PATH) mark_as_advanced(FORCE XIMEA_LIBRARY_DIR) - diff --git a/cmake/OpenCVGenConfig.cmake b/cmake/OpenCVGenConfig.cmake index 705ccc8df1..7ccf3ef42e 100644 --- a/cmake/OpenCVGenConfig.cmake +++ b/cmake/OpenCVGenConfig.cmake @@ -84,7 +84,7 @@ macro(ocv_generate_dependencies_map_configcmake suffix configuration) set(OPENCV_DEPENDENCIES_MAP_${suffix} "${OPENCV_DEPENDENCIES_MAP_${suffix}}set(OpenCV_${__ocv_lib}_LIBNAME_${suffix} \"${__libname}\")\n") set(OPENCV_DEPENDENCIES_MAP_${suffix} "${OPENCV_DEPENDENCIES_MAP_${suffix}}set(OpenCV_${__ocv_lib}_DEPS_${suffix} ${__mod_deps})\n") - set(OPENCV_DEPENDENCIES_MAP_${suffix} "${OPENCV_DEPENDENCIES_MAP_${suffix}}set(OpenCV_${__ocv_lib}_EXTRA_DEPS_${suffix} ${__ext_deps})\n") + set(OPENCV_DEPENDENCIES_MAP_${suffix} "${OPENCV_DEPENDENCIES_MAP_${suffix}}set(OpenCV_${__ocv_lib}_EXTRA_DEPS_${suffix} \"${__ext_deps}\")\n") list(APPEND OPENCV_PROCESSED_LIBS ${__ocv_lib}) list(APPEND OPENCV_LIBS_TO_PROCESS ${${__ocv_lib}_MODULE_DEPS_${suffix}}) @@ -162,7 +162,7 @@ if(UNIX) endif() if(ANDROID) - install(FILES "${OpenCV_SOURCE_DIR}/android/android.toolchain.cmake" DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}/) + install(FILES "${OpenCV_SOURCE_DIR}/platforms/android/android.toolchain.cmake" DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}/) endif() # -------------------------------------------------------------------------------------------- diff --git a/cmake/OpenCVGenHeaders.cmake b/cmake/OpenCVGenHeaders.cmake index d2d38c90a7..c7129fefa3 100644 --- a/cmake/OpenCVGenHeaders.cmake +++ b/cmake/OpenCVGenHeaders.cmake @@ -1,13 +1,3 @@ -# ---------------------------------------------------------------------------- -# Variables for cvconfig.h.cmake -# ---------------------------------------------------------------------------- -set(PACKAGE "opencv") -set(PACKAGE_BUGREPORT "opencvlibrary-devel@lists.sourceforge.net") -set(PACKAGE_NAME "opencv") -set(PACKAGE_STRING "${PACKAGE} ${OPENCV_VERSION}") -set(PACKAGE_TARNAME "${PACKAGE}") -set(PACKAGE_VERSION "${OPENCV_VERSION}") - # platform-specific config file configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/cvconfig.h.cmake" "${OPENCV_CONFIG_FILE_INCLUDE_DIR}/cvconfig.h") diff --git a/cmake/OpenCVGenInfoPlist.cmake b/cmake/OpenCVGenInfoPlist.cmake new file mode 100644 index 0000000000..97c674ceb7 --- /dev/null +++ b/cmake/OpenCVGenInfoPlist.cmake @@ -0,0 +1,4 @@ +if(IOS) + configure_file("${OpenCV_SOURCE_DIR}/platforms/ios/Info.plist.in" + "${CMAKE_BINARY_DIR}/ios/Info.plist") +endif() diff --git a/cmake/OpenCVGenPkgconfig.cmake b/cmake/OpenCVGenPkgconfig.cmake index 49d6707345..7bfc7bc5af 100644 --- a/cmake/OpenCVGenPkgconfig.cmake +++ b/cmake/OpenCVGenPkgconfig.cmake @@ -12,7 +12,6 @@ set(prefix "${CMAKE_INSTALL_PREFIX}") set(exec_prefix "\${prefix}") set(libdir "") #TODO: need link paths for OpenCV_EXTRA_COMPONENTS set(includedir "\${prefix}/${OPENCV_INCLUDE_INSTALL_PATH}") -set(VERSION ${OPENCV_VERSION}) if(CMAKE_BUILD_TYPE MATCHES "Release") set(ocv_optkind OPT) diff --git a/cmake/OpenCVLegacyOptions.cmake b/cmake/OpenCVLegacyOptions.cmake deleted file mode 100644 index a34c9e5abc..0000000000 --- a/cmake/OpenCVLegacyOptions.cmake +++ /dev/null @@ -1,24 +0,0 @@ -macro(ocv_legacy_option old superseded_by) - if(DEFINED ${old}) - if(ARGV2) - set(${superseded_by} ${${old}} CACHE ${ARGV2} "Set via depricated ${old}" FORCE) - else() - set(${superseded_by} ${${old}} CACHE BOOL "Set via depricated ${old}" FORCE) - endif() - unset(${old} CACHE) - endif() -endmacro() - -ocv_legacy_option(BUILD_NEW_PYTHON_SUPPORT BUILD_opencv_python) -ocv_legacy_option(BUILD_JAVA_SUPPORT BUILD_opencv_java) -ocv_legacy_option(WITH_ANDROID_CAMERA BUILD_opencv_androidcamera) - -if(DEFINED OPENCV_BUILD_3RDPARTY_LIBS) - set(BUILD_ZLIB ${OPENCV_BUILD_3RDPARTY_LIBS} CACHE BOOL "Set via depricated OPENCV_BUILD_3RDPARTY_LIBS" FORCE) - set(BUILD_TIFF ${OPENCV_BUILD_3RDPARTY_LIBS} CACHE BOOL "Set via depricated OPENCV_BUILD_3RDPARTY_LIBS" FORCE) - set(BUILD_JASPER ${OPENCV_BUILD_3RDPARTY_LIBS} CACHE BOOL "Set via depricated OPENCV_BUILD_3RDPARTY_LIBS" FORCE) - set(BUILD_JPEG ${OPENCV_BUILD_3RDPARTY_LIBS} CACHE BOOL "Set via depricated OPENCV_BUILD_3RDPARTY_LIBS" FORCE) - set(BUILD_PNG ${OPENCV_BUILD_3RDPARTY_LIBS} CACHE BOOL "Set via depricated OPENCV_BUILD_3RDPARTY_LIBS" FORCE) - unset(OPENCV_BUILD_3RDPARTY_LIBS CACHE) -endif() - diff --git a/cmake/OpenCVMinDepVersions.cmake b/cmake/OpenCVMinDepVersions.cmake new file mode 100644 index 0000000000..b659a83794 --- /dev/null +++ b/cmake/OpenCVMinDepVersions.cmake @@ -0,0 +1,3 @@ +set(MIN_VER_CMAKE 2.8.7) +set(MIN_VER_PYTHON 2.6) +set(MIN_VER_ZLIB 1.2.3) diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index 48aa7139a2..4956edf911 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -33,6 +33,7 @@ # # ocv_add_accuracy_tests() # ocv_add_perf_tests() +# ocv_add_samples() # # # If module have no "extra" then you can define it in one line: @@ -303,7 +304,7 @@ macro(ocv_glob_modules) # collect modules set(OPENCV_INITIAL_PASS ON) foreach(__path ${ARGN}) - ocv_get_real_path(__path "${__path}") + get_filename_component(__path "${__path}" ABSOLUTE) list(FIND __directories_observed "${__path}" __pathIdx) if(__pathIdx GREATER -1) @@ -315,7 +316,7 @@ macro(ocv_glob_modules) if(__ocvmodules) list(SORT __ocvmodules) foreach(mod ${__ocvmodules}) - ocv_get_real_path(__modpath "${__path}/${mod}") + get_filename_component(__modpath "${__path}/${mod}" ABSOLUTE) if(EXISTS "${__modpath}/CMakeLists.txt") list(FIND __directories_observed "${__modpath}" __pathIdx) @@ -432,20 +433,32 @@ macro(ocv_glob_module_sources) file(GLOB lib_hdrs "include/opencv2/*.hpp" "include/opencv2/${name}/*.hpp" "include/opencv2/${name}/*.h") file(GLOB lib_hdrs_detail "include/opencv2/${name}/detail/*.hpp" "include/opencv2/${name}/detail/*.h") - file(GLOB lib_device_srcs "src/cuda/*.cu") - set(device_objs "") - set(lib_device_hdrs "") + file(GLOB lib_cuda_srcs "src/cuda/*.cu") + set(cuda_objs "") + set(lib_cuda_hdrs "") - if (HAVE_CUDA AND lib_device_srcs) + if(HAVE_CUDA AND lib_cuda_srcs) ocv_include_directories(${CUDA_INCLUDE_DIRS}) - file(GLOB lib_device_hdrs "src/cuda/*.hpp") + file(GLOB lib_cuda_hdrs "src/cuda/*.hpp") - ocv_cuda_compile(device_objs ${lib_device_srcs} ${lib_device_hdrs}) - source_group("Src\\Cuda" FILES ${lib_device_srcs} ${lib_device_hdrs}) + ocv_cuda_compile(cuda_objs ${lib_cuda_srcs} ${lib_cuda_hdrs}) + source_group("Src\\Cuda" FILES ${lib_cuda_srcs} ${lib_cuda_hdrs}) + endif() + + file(GLOB cl_kernels "src/opencl/*.cl") + + if(HAVE_OPENCL AND cl_kernels) + ocv_include_directories(${OPENCL_INCLUDE_DIRS}) + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/kernels.cpp" + COMMAND ${CMAKE_COMMAND} -DCL_DIR="${CMAKE_CURRENT_SOURCE_DIR}/src/opencl" -DOUTPUT="${CMAKE_CURRENT_BINARY_DIR}/kernels.cpp" -P "${OpenCV_SOURCE_DIR}/cmake/cl2cpp.cmake" + DEPENDS ${cl_kernels} "${OpenCV_SOURCE_DIR}/cmake/cl2cpp.cmake") + source_group("Src\\OpenCL" FILES ${cl_kernels} "${CMAKE_CURRENT_BINARY_DIR}/kernels.cpp") + list(APPEND lib_srcs ${cl_kernels} "${CMAKE_CURRENT_BINARY_DIR}/kernels.cpp") endif() ocv_set_module_sources(${ARGN} HEADERS ${lib_hdrs} ${lib_hdrs_detail} - SOURCES ${lib_srcs} ${lib_int_hdrs} ${device_objs} ${lib_device_srcs} ${lib_device_hdrs}) + SOURCES ${lib_srcs} ${lib_int_hdrs} ${cuda_objs} ${lib_cuda_srcs} ${lib_cuda_hdrs}) source_group("Src" FILES ${lib_srcs} ${lib_int_hdrs}) source_group("Include" FILES ${lib_hdrs}) @@ -458,13 +471,28 @@ endmacro() # ocv_create_module() # ocv_create_module(SKIP_LINK) macro(ocv_create_module) - add_library(${the_module} ${OPENCV_MODULE_TYPE} ${OPENCV_MODULE_${the_module}_HEADERS} ${OPENCV_MODULE_${the_module}_SOURCES}) + # The condition we ought to be testing here is whether ocv_add_precompiled_headers will + # be called at some point in the future. We can't look into the future, though, + # so this will have to do. + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/precomp.hpp") + get_native_precompiled_header(${the_module} precomp.hpp) + endif() + + add_library(${the_module} ${OPENCV_MODULE_TYPE} ${OPENCV_MODULE_${the_module}_HEADERS} ${OPENCV_MODULE_${the_module}_SOURCES} + "${OPENCV_CONFIG_FILE_INCLUDE_DIR}/cvconfig.h" "${OPENCV_CONFIG_FILE_INCLUDE_DIR}/opencv2/opencv_modules.hpp" + ${${the_module}_pch}) + if(NOT the_module STREQUAL opencv_ts) + set_target_properties(${the_module} PROPERTIES COMPILE_DEFINITIONS OPENCV_NOSTL) + endif() if(NOT "${ARGN}" STREQUAL "SKIP_LINK") target_link_libraries(${the_module} ${OPENCV_MODULE_${the_module}_DEPS} ${OPENCV_MODULE_${the_module}_DEPS_EXT} ${OPENCV_LINKER_LIBS} ${IPP_LIBS} ${ARGN}) if (HAVE_CUDA) target_link_libraries(${the_module} ${CUDA_LIBRARIES} ${CUDA_npp_LIBRARY}) endif() + if(HAVE_OPENCL AND OPENCL_LIBRARIES) + target_link_libraries(${the_module} ${OPENCL_LIBRARIES}) + endif() endif() add_dependencies(opencv_modules ${the_module}) @@ -492,7 +520,8 @@ macro(ocv_create_module) ) endif() - if(BUILD_SHARED_LIBS) + if((NOT DEFINED OPENCV_MODULE_TYPE AND BUILD_SHARED_LIBS) + OR (DEFINED OPENCV_MODULE_TYPE AND OPENCV_MODULE_TYPE STREQUAL SHARED)) if(MSVC) set_target_properties(${the_module} PROPERTIES DEFINE_SYMBOL CVAPI_EXPORTS) else() @@ -517,7 +546,7 @@ macro(ocv_create_module) if(OPENCV_MODULE_${the_module}_HEADERS AND ";${OPENCV_MODULES_PUBLIC};" MATCHES ";${the_module};") foreach(hdr ${OPENCV_MODULE_${the_module}_HEADERS}) string(REGEX REPLACE "^.*opencv2/" "opencv2/" hdr2 "${hdr}") - if(hdr2 MATCHES "^(opencv2/.*)/[^/]+.h(..)?$") + if(NOT hdr2 MATCHES "opencv2/${the_module}/private.*" AND hdr2 MATCHES "^(opencv2/?.*)/[^/]+.h(..)?$" ) install(FILES ${hdr} DESTINATION "${OPENCV_INCLUDE_INSTALL_PATH}/${CMAKE_MATCH_1}" COMPONENT main) endif() endforeach() @@ -553,6 +582,7 @@ macro(ocv_define_module module_name) ocv_add_accuracy_tests() ocv_add_perf_tests() + ocv_add_samples() endmacro() # ensures that all passed modules are available @@ -620,7 +650,9 @@ function(ocv_add_perf_tests) set(OPENCV_PERF_${the_module}_SOURCES ${perf_srcs} ${perf_hdrs}) endif() - add_executable(${the_target} ${OPENCV_PERF_${the_module}_SOURCES}) + get_native_precompiled_header(${the_target} perf_precomp.hpp) + + add_executable(${the_target} ${OPENCV_PERF_${the_module}_SOURCES} ${${the_target}_pch}) target_link_libraries(${the_target} ${OPENCV_MODULE_${the_module}_DEPS} ${perf_deps} ${OPENCV_LINKER_LIBS}) add_dependencies(opencv_perf_tests ${the_target}) @@ -636,9 +668,6 @@ function(ocv_add_perf_tests) ocv_add_precompiled_headers(${the_target}) - if (PYTHON_EXECUTABLE) - add_dependencies(perf ${the_target}) - endif() else(OCV_DEPENDENCIES_FOUND) # TODO: warn about unsatisfied dependencies endif(OCV_DEPENDENCIES_FOUND) @@ -671,7 +700,9 @@ function(ocv_add_accuracy_tests) set(OPENCV_TEST_${the_module}_SOURCES ${test_srcs} ${test_hdrs}) endif() - add_executable(${the_target} ${OPENCV_TEST_${the_module}_SOURCES}) + get_native_precompiled_header(${the_target} test_precomp.hpp) + + add_executable(${the_target} ${OPENCV_TEST_${the_module}_SOURCES} ${${the_target}_pch}) target_link_libraries(${the_target} ${OPENCV_MODULE_${the_module}_DEPS} ${test_deps} ${OPENCV_LINKER_LIBS}) add_dependencies(opencv_tests ${the_target}) @@ -696,6 +727,48 @@ function(ocv_add_accuracy_tests) endif() endfunction() +function(ocv_add_samples) + set(samples_path "${CMAKE_CURRENT_SOURCE_DIR}/samples") + string(REGEX REPLACE "^opencv_" "" module_id ${the_module}) + + if(BUILD_EXAMPLES AND EXISTS "${samples_path}") + set(samples_deps ${the_module} ${OPENCV_MODULE_${the_module}_DEPS} opencv_highgui ${ARGN}) + ocv_check_dependencies(${samples_deps}) + + if(OCV_DEPENDENCIES_FOUND) + file(GLOB sample_sources "${samples_path}/*.cpp") + ocv_include_modules(${OPENCV_MODULE_${the_module}_DEPS}) + + foreach(source ${sample_sources}) + get_filename_component(name "${source}" NAME_WE) + set(the_target "example_${module_id}_${name}") + + add_executable(${the_target} "${source}") + target_link_libraries(${the_target} ${samples_deps}) + + set_target_properties(${the_target} PROPERTIES PROJECT_LABEL "(sample) ${name}") + + if(ENABLE_SOLUTION_FOLDERS) + set_target_properties(${the_target} PROPERTIES + OUTPUT_NAME "${module_id}-example-${name}" + FOLDER "samples/${module_id}") + endif() + + if(WIN32) + install(TARGETS ${the_target} RUNTIME DESTINATION "samples/${module_id}" COMPONENT main) + endif() + endforeach() + endif() + endif() + + if(INSTALL_C_EXAMPLES AND NOT WIN32 AND EXISTS "${samples_path}") + file(GLOB sample_files "${samples_path}/*") + install(FILES ${sample_files} + DESTINATION share/OpenCV/samples/${module_id} + PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) + endif() +endfunction() + # internal macro; finds all link dependencies of the module # should be used at the end of CMake processing macro(__ocv_track_module_link_dependencies the_module optkind) diff --git a/cmake/OpenCVPCHSupport.cmake b/cmake/OpenCVPCHSupport.cmake index cfc4bfa724..060965346a 100644 --- a/cmake/OpenCVPCHSupport.cmake +++ b/cmake/OpenCVPCHSupport.cmake @@ -46,6 +46,13 @@ MACRO(_PCH_GET_COMPILE_FLAGS _out_compile_flags) LIST(APPEND ${_out_compile_flags} "-fPIC") ENDIF() + GET_TARGET_PROPERTY(_target_definitions ${_PCH_current_target} COMPILE_DEFINITIONS) + if(_target_definitions) + foreach(_def ${_target_definitions}) + LIST(APPEND ${_out_compile_flags} "-D${_def}") + endforeach() + endif() + ELSE() ## TODO ... ? or does it work out of the box ENDIF() @@ -272,12 +279,9 @@ ENDMACRO(ADD_PRECOMPILED_HEADER) MACRO(GET_NATIVE_PRECOMPILED_HEADER _targetName _input) if(CMAKE_GENERATOR MATCHES "^Visual.*$") - SET(_dummy_str "#include \"${_input}\"\n" -"// This is required to suppress LNK4221. Very annoying.\n" -"void *g_${_targetName}Dummy = 0\;\n") + set(_dummy_str "#include \"${_input}\"\n") - # Use of cxx extension for generated files (as Qt does) - SET(${_targetName}_pch ${CMAKE_CURRENT_BINARY_DIR}/${_targetName}_pch.cxx) + set(${_targetName}_pch ${CMAKE_CURRENT_BINARY_DIR}/${_targetName}_pch.cpp) if(EXISTS ${${_targetName}_pch}) # Check if contents is the same, if not rewrite # todo @@ -337,11 +341,7 @@ ENDMACRO(ADD_NATIVE_PRECOMPILED_HEADER) macro(ocv_add_precompiled_header_to_target the_target pch_header) if(PCHSupport_FOUND AND ENABLE_PRECOMPILED_HEADERS AND EXISTS "${pch_header}") - if(CMAKE_GENERATOR MATCHES Visual) - string(REGEX REPLACE "hpp$" "cpp" ${the_target}_pch "${pch_header}") - add_native_precompiled_header(${the_target} ${pch_header}) - unset(${the_target}_pch) - elseif(CMAKE_GENERATOR MATCHES Xcode) + if(CMAKE_GENERATOR MATCHES "^Visual" OR CMAKE_GENERATOR MATCHES Xcode) add_native_precompiled_header(${the_target} ${pch_header}) elseif(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_GENERATOR MATCHES "Makefiles|Ninja") add_precompiled_header(${the_target} ${pch_header}) diff --git a/cmake/OpenCVUtils.cmake b/cmake/OpenCVUtils.cmake index db24c99708..ddf0290673 100644 --- a/cmake/OpenCVUtils.cmake +++ b/cmake/OpenCVUtils.cmake @@ -77,7 +77,7 @@ MACRO(ocv_check_compiler_flag LANG FLAG RESULT) if(_fname) MESSAGE(STATUS "Performing Test ${RESULT}") TRY_COMPILE(${RESULT} - ${CMAKE_BINARY_DIR} + "${CMAKE_BINARY_DIR}" "${_fname}" COMPILE_DEFINITIONS "${FLAG}" OUTPUT_VARIABLE OUTPUT) @@ -411,16 +411,6 @@ macro(ocv_regex_escape var regex) endmacro() -# get absolute path with symlinks resolved -macro(ocv_get_real_path VAR PATHSTR) - if(CMAKE_VERSION VERSION_LESS 2.8) - get_filename_component(${VAR} "${PATHSTR}" ABSOLUTE) - else() - get_filename_component(${VAR} "${PATHSTR}" REALPATH) - endif() -endmacro() - - # convert list of paths to full paths macro(ocv_convert_to_full_paths VAR) if(${VAR}) @@ -511,6 +501,13 @@ macro(ocv_parse_header2 LIBNAME HDR_PATH VARNAME) endif() endmacro() +# read single version info from the pkg file +macro(ocv_parse_pkg LIBNAME PKG_PATH SCOPE) + if(EXISTS "${PKG_PATH}/${LIBNAME}.pc") + file(STRINGS "${PKG_PATH}/${LIBNAME}.pc" line_to_parse REGEX "^Version:[ \t]+[0-9.]*.*$" LIMIT_COUNT 1) + STRING(REGEX REPLACE ".*Version: ([^ ]+).*" "\\1" ALIASOF_${LIBNAME}_VERSION "${line_to_parse}" ) + endif() +endmacro() ################################################################################################ # short command to setup source group @@ -518,4 +515,4 @@ function(ocv_source_group group) cmake_parse_arguments(OCV_SOURCE_GROUP "" "" "GLOB" ${ARGN}) file(GLOB srcs ${OCV_SOURCE_GROUP_GLOB}) source_group(${group} FILES ${srcs}) -endfunction() \ No newline at end of file +endfunction() diff --git a/cmake/OpenCVVersion.cmake b/cmake/OpenCVVersion.cmake index 03de98068b..c8ce40308f 100644 --- a/cmake/OpenCVVersion.cmake +++ b/cmake/OpenCVVersion.cmake @@ -1,16 +1,19 @@ SET(OPENCV_VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/modules/core/include/opencv2/core/version.hpp") -FILE(STRINGS "${OPENCV_VERSION_FILE}" OPENCV_VERSION_PARTS REGEX "#define CV_VERSION_[A-Z]+[ ]+[0-9]+" ) +file(STRINGS "${OPENCV_VERSION_FILE}" OPENCV_VERSION_PARTS REGEX "#define CV_VERSION_[A-Z]+[ ]+" ) string(REGEX REPLACE ".+CV_VERSION_EPOCH[ ]+([0-9]+).*" "\\1" OPENCV_VERSION_MAJOR "${OPENCV_VERSION_PARTS}") string(REGEX REPLACE ".+CV_VERSION_MAJOR[ ]+([0-9]+).*" "\\1" OPENCV_VERSION_MINOR "${OPENCV_VERSION_PARTS}") string(REGEX REPLACE ".+CV_VERSION_MINOR[ ]+([0-9]+).*" "\\1" OPENCV_VERSION_PATCH "${OPENCV_VERSION_PARTS}") string(REGEX REPLACE ".+CV_VERSION_REVISION[ ]+([0-9]+).*" "\\1" OPENCV_VERSION_TWEAK "${OPENCV_VERSION_PARTS}") +string(REGEX REPLACE ".+CV_VERSION_STATUS[ ]+\"([^\"]*)\".*" "\\1" OPENCV_VERSION_STATUS "${OPENCV_VERSION_PARTS}") -set(OPENCV_VERSION "${OPENCV_VERSION_MAJOR}.${OPENCV_VERSION_MINOR}.${OPENCV_VERSION_PATCH}") +set(OPENCV_VERSION_PLAIN "${OPENCV_VERSION_MAJOR}.${OPENCV_VERSION_MINOR}.${OPENCV_VERSION_PATCH}") if(OPENCV_VERSION_TWEAK GREATER 0) - set(OPENCV_VERSION "${OPENCV_VERSION}.${OPENCV_VERSION_TWEAK}") + set(OPENCV_VERSION_PLAIN "${OPENCV_VERSION_PLAIN}.${OPENCV_VERSION_TWEAK}") endif() +set(OPENCV_VERSION "${OPENCV_VERSION_PLAIN}${OPENCV_VERSION_STATUS}") + set(OPENCV_SOVERSION "${OPENCV_VERSION_MAJOR}.${OPENCV_VERSION_MINOR}") set(OPENCV_LIBVERSION "${OPENCV_VERSION_MAJOR}.${OPENCV_VERSION_MINOR}.${OPENCV_VERSION_PATCH}") diff --git a/cmake/OpenCVDetectCudaArch.cu b/cmake/checks/OpenCVDetectCudaArch.cu similarity index 99% rename from cmake/OpenCVDetectCudaArch.cu rename to cmake/checks/OpenCVDetectCudaArch.cu index 008f8ba8d0..9d7086cf24 100644 --- a/cmake/OpenCVDetectCudaArch.cu +++ b/cmake/checks/OpenCVDetectCudaArch.cu @@ -11,4 +11,4 @@ int main() printf("%d.%d ", prop.major, prop.minor); } return 0; -} \ No newline at end of file +} diff --git a/cmake/checks/vfwtest.cpp b/cmake/checks/vfwtest.cpp new file mode 100644 index 0000000000..8d8ecb2719 --- /dev/null +++ b/cmake/checks/vfwtest.cpp @@ -0,0 +1,10 @@ + +#include +#include + +int main() +{ + AVIFileInit(); + AVIFileExit(); + return 0; +} diff --git a/cmake/checks/win32uitest.cpp b/cmake/checks/win32uitest.cpp new file mode 100644 index 0000000000..f475e1c963 --- /dev/null +++ b/cmake/checks/win32uitest.cpp @@ -0,0 +1,11 @@ +#include + +int main(int argc, char** argv) +{ + CreateWindow(NULL /*lpClassName*/, NULL /*lpWindowName*/, 0 /*dwStyle*/, 0 /*x*/, + 0 /*y*/, 0 /*nWidth*/, 0 /*nHeight*/, NULL /*hWndParent*/, NULL /*hMenu*/, + NULL /*hInstance*/, NULL /*lpParam*/); + DeleteDC(NULL); + + return 0; +} diff --git a/cmake/checks/winrttest.cpp b/cmake/checks/winrttest.cpp new file mode 100644 index 0000000000..9ec0c9ac1f --- /dev/null +++ b/cmake/checks/winrttest.cpp @@ -0,0 +1,6 @@ +#include + +int main(int, char**) +{ + return 0; +} diff --git a/modules/ocl/cl2cpp.cmake b/cmake/cl2cpp.cmake similarity index 89% rename from modules/ocl/cl2cpp.cmake rename to cmake/cl2cpp.cmake index ca17c61b43..1e932eabdb 100644 --- a/modules/ocl/cl2cpp.cmake +++ b/cmake/cl2cpp.cmake @@ -18,6 +18,7 @@ foreach(cl ${cl_list}) string(REPLACE "\t" " " lines "${lines}") string(REGEX REPLACE "/\\*([^*]/|\\*[^/]|[^*/])*\\*/" "" lines "${lines}") # multiline comments + string(REGEX REPLACE "/\\*([^\n])*\\*/" "" lines "${lines}") # single-line comments string(REGEX REPLACE "[ ]*//[^\n]*\n" "\n" lines "${lines}") # single-line comments string(REGEX REPLACE "\n[ ]*(\n[ ]*)*" "\n" lines "${lines}") # empty lines & leading whitespace string(REGEX REPLACE "^\n" "" lines "${lines}") # leading new line @@ -31,4 +32,4 @@ foreach(cl ${cl_list}) file(APPEND ${OUTPUT} "const char* ${cl_filename}=\"${lines};\n") endforeach() -file(APPEND ${OUTPUT} "}\n}\n") \ No newline at end of file +file(APPEND ${OUTPUT} "}\n}\n") diff --git a/cmake/templates/OpenCVConfig-version.cmake.in b/cmake/templates/OpenCVConfig-version.cmake.in index 0b432a074c..b5ac5f8e29 100644 --- a/cmake/templates/OpenCVConfig-version.cmake.in +++ b/cmake/templates/OpenCVConfig-version.cmake.in @@ -1,4 +1,4 @@ -set(OpenCV_VERSION @OPENCV_VERSION@) +set(OpenCV_VERSION @OPENCV_VERSION_PLAIN@) set(PACKAGE_VERSION ${OpenCV_VERSION}) set(PACKAGE_VERSION_EXACT False) diff --git a/cmake/templates/OpenCVConfig.cmake.in b/cmake/templates/OpenCVConfig.cmake.in index 1dcd840307..90749488a7 100644 --- a/cmake/templates/OpenCVConfig.cmake.in +++ b/cmake/templates/OpenCVConfig.cmake.in @@ -22,11 +22,12 @@ # - OpenCV_INCLUDE_DIRS : The OpenCV include directories. # - OpenCV_COMPUTE_CAPABILITIES : The version of compute capability # - OpenCV_ANDROID_NATIVE_API_LEVEL : Minimum required level of Android API -# - OpenCV_VERSION : The version of this OpenCV build: "@OPENCV_VERSION@" +# - OpenCV_VERSION : The version of this OpenCV build: "@OPENCV_VERSION_PLAIN@" # - OpenCV_VERSION_MAJOR : Major version part of OpenCV_VERSION: "@OPENCV_VERSION_MAJOR@" # - OpenCV_VERSION_MINOR : Minor version part of OpenCV_VERSION: "@OPENCV_VERSION_MINOR@" # - OpenCV_VERSION_PATCH : Patch version part of OpenCV_VERSION: "@OPENCV_VERSION_PATCH@" # - OpenCV_VERSION_TWEAK : Tweak version part of OpenCV_VERSION: "@OPENCV_VERSION_TWEAK@" +# - OpenCV_VERSION_STATUS : Development status of this build: "@OPENCV_VERSION_STATUS@" # # Advanced variables: # - OpenCV_SHARED @@ -96,11 +97,12 @@ mark_as_advanced(FORCE OpenCV_LIB_DIR_OPT OpenCV_LIB_DIR_DBG OpenCV_3RDPARTY_LIB # ====================================================== # Version variables: # ====================================================== -SET(OpenCV_VERSION @OPENCV_VERSION@) +SET(OpenCV_VERSION @OPENCV_VERSION_PLAIN@) SET(OpenCV_VERSION_MAJOR @OPENCV_VERSION_MAJOR@) SET(OpenCV_VERSION_MINOR @OPENCV_VERSION_MINOR@) SET(OpenCV_VERSION_PATCH @OPENCV_VERSION_PATCH@) SET(OpenCV_VERSION_TWEAK @OPENCV_VERSION_TWEAK@) +SET(OpenCV_VERSION_STATUS "@OPENCV_VERSION_STATUS@") # ==================================================================== # Link libraries: e.g. libopencv_core.so, opencv_imgproc220d.lib, etc... diff --git a/cmake/templates/cmake_uninstall.cmake.in b/cmake/templates/cmake_uninstall.cmake.in index 14e601019d..0e63d705cd 100644 --- a/cmake/templates/cmake_uninstall.cmake.in +++ b/cmake/templates/cmake_uninstall.cmake.in @@ -23,5 +23,3 @@ FOREACH(file ${files}) MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") ENDIF(EXISTS "$ENV{DESTDIR}${file}") ENDFOREACH(file) - - diff --git a/cmake/templates/cvconfig.h.cmake b/cmake/templates/cvconfig.h.cmake index 62c8b68b38..56c5d5aadc 100644 --- a/cmake/templates/cvconfig.h.cmake +++ b/cmake/templates/cvconfig.h.cmake @@ -1,17 +1,20 @@ -/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP - systems. This function is required for `alloca.c' support on those systems. - */ -#cmakedefine CRAY_STACKSEG_END +/* OpenCV compiled as static or dynamic libs */ +#cmakedefine BUILD_SHARED_LIBS -/* Define to 1 if using `alloca.c'. */ -#cmakedefine C_ALLOCA +/* Compile for 'real' NVIDIA GPU architectures */ +#define CUDA_ARCH_BIN "${OPENCV_CUDA_ARCH_BIN}" -/* Define to 1 if you have `alloca', as a function or macro. */ -#cmakedefine HAVE_ALLOCA 1 +/* Create PTX or BIN for 1.0 compute capability */ +#cmakedefine CUDA_ARCH_BIN_OR_PTX_10 -/* Define to 1 if you have and it should be used (not on Ultrix). - */ -#cmakedefine HAVE_ALLOCA_H 1 +/* NVIDIA GPU features are used */ +#define CUDA_ARCH_FEATURES "${OPENCV_CUDA_ARCH_FEATURES}" + +/* Compile for 'virtual' NVIDIA PTX architectures */ +#define CUDA_ARCH_PTX "${OPENCV_CUDA_ARCH_PTX}" + +/* AVFoundation video libraries */ +#cmakedefine HAVE_AVFOUNDATION /* V4L capturing support */ #cmakedefine HAVE_CAMV4L @@ -19,15 +22,33 @@ /* V4L2 capturing support */ #cmakedefine HAVE_CAMV4L2 -/* V4L2 capturing support in videoio.h */ -#cmakedefine HAVE_VIDEOIO - -/* V4L/V4L2 capturing support via libv4l */ -#cmakedefine HAVE_LIBV4L - /* Carbon windowing environment */ #cmakedefine HAVE_CARBON +/* AMD's Basic Linear Algebra Subprograms Library*/ +#cmakedefine HAVE_CLAMDBLAS + +/* AMD's OpenCL Fast Fourier Transform Library*/ +#cmakedefine HAVE_CLAMDFFT + +/* Clp support */ +#cmakedefine HAVE_CLP + +/* Cocoa API */ +#cmakedefine HAVE_COCOA + +/* C= */ +#cmakedefine HAVE_CSTRIPES + +/* NVidia Cuda Basic Linear Algebra Subprograms (BLAS) API*/ +#cmakedefine HAVE_CUBLAS + +/* NVidia Cuda Runtime API*/ +#cmakedefine HAVE_CUDA + +/* NVidia Cuda Fast Fourier Transform (FFT) API*/ +#cmakedefine HAVE_CUFFT + /* IEEE1394 capturing support */ #cmakedefine HAVE_DC1394 @@ -37,182 +58,108 @@ /* IEEE1394 capturing support - libdc1394 v2.x */ #cmakedefine HAVE_DC1394_2 +/* DirectShow Video Capture library */ +#cmakedefine HAVE_DSHOW + +/* Eigen Matrix & Linear Algebra Library */ +#cmakedefine HAVE_EIGEN + +/* FFMpeg video library */ +#cmakedefine HAVE_FFMPEG + +/* ffmpeg's libswscale */ +#cmakedefine HAVE_FFMPEG_SWSCALE + /* ffmpeg in Gentoo */ #cmakedefine HAVE_GENTOO_FFMPEG -/* FFMpeg video library */ -#cmakedefine HAVE_FFMPEG - -/* FFMpeg version flag */ -#cmakedefine NEW_FFMPEG - -/* ffmpeg's libswscale */ -#cmakedefine HAVE_FFMPEG_SWSCALE - /* GStreamer multimedia framework */ -#cmakedefine HAVE_GSTREAMER +#cmakedefine HAVE_GSTREAMER /* GTK+ 2.0 Thread support */ -#cmakedefine HAVE_GTHREAD +#cmakedefine HAVE_GTHREAD /* GTK+ 2.x toolkit */ -#cmakedefine HAVE_GTK - -/* OpenEXR codec */ -#cmakedefine HAVE_ILMIMF +#cmakedefine HAVE_GTK /* Define to 1 if you have the header file. */ -#cmakedefine HAVE_INTTYPES_H 1 - -/* JPEG-2000 codec */ -#cmakedefine HAVE_JASPER - -/* IJG JPEG codec */ -#cmakedefine HAVE_JPEG - -/* Define to 1 if you have the `dl' library (-ldl). */ -#cmakedefine HAVE_LIBDL 1 - -/* Define to 1 if you have the `gomp' library (-lgomp). */ -#cmakedefine HAVE_LIBGOMP 1 - -/* Define to 1 if you have the `m' library (-lm). */ -#cmakedefine HAVE_LIBM 1 - -/* libpng/png.h needs to be included */ -#cmakedefine HAVE_LIBPNG_PNG_H - -/* Define to 1 if you have the `pthread' library (-lpthread). */ -#cmakedefine HAVE_LIBPTHREAD 1 - -/* Define to 1 if you have the `lrint' function. */ -#cmakedefine HAVE_LRINT 1 - -/* PNG codec */ -#cmakedefine HAVE_PNG - -/* Define to 1 if you have the `png_get_valid' function. */ -#cmakedefine HAVE_PNG_GET_VALID 1 - -/* png.h needs to be included */ -#cmakedefine HAVE_PNG_H - -/* Define to 1 if you have the `png_set_tRNS_to_alpha' function. */ -#cmakedefine HAVE_PNG_SET_TRNS_TO_ALPHA 1 - -/* QuickTime video libraries */ -#cmakedefine HAVE_QUICKTIME - -/* AVFoundation video libraries */ -#cmakedefine HAVE_AVFOUNDATION - -/* TIFF codec */ -#cmakedefine HAVE_TIFF - -/* Unicap video capture library */ -#cmakedefine HAVE_UNICAP - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_UNISTD_H 1 - -/* Xine video library */ -#cmakedefine HAVE_XINE - -/* OpenNI library */ -#cmakedefine HAVE_OPENNI - -/* LZ77 compression/decompression library (used for PNG) */ -#cmakedefine HAVE_ZLIB +#cmakedefine HAVE_INTTYPES_H 1 /* Intel Integrated Performance Primitives */ -#cmakedefine HAVE_IPP +#cmakedefine HAVE_IPP -/* OpenCV compiled as static or dynamic libs */ -#cmakedefine BUILD_SHARED_LIBS +/* JPEG-2000 codec */ +#cmakedefine HAVE_JASPER -/* Name of package */ -#define PACKAGE "${PACKAGE}" +/* IJG JPEG codec */ +#cmakedefine HAVE_JPEG -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "${PACKAGE_BUGREPORT}" +/* libpng/png.h needs to be included */ +#cmakedefine HAVE_LIBPNG_PNG_H -/* Define to the full name of this package. */ -#define PACKAGE_NAME "${PACKAGE_NAME}" +/* V4L/V4L2 capturing support via libv4l */ +#cmakedefine HAVE_LIBV4L -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "${PACKAGE_STRING}" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "${PACKAGE_TARNAME}" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "${PACKAGE_VERSION}" - -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at runtime. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ -#cmakedefine STACK_DIRECTION - -/* Version number of package */ -#define VERSION "${PACKAGE_VERSION}" - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -#cmakedefine WORDS_BIGENDIAN - -/* Intel Threading Building Blocks */ -#cmakedefine HAVE_TBB - -/* C= */ -#cmakedefine HAVE_CSTRIPES - -/* Eigen Matrix & Linear Algebra Library */ -#cmakedefine HAVE_EIGEN - -/* NVidia Cuda Runtime API*/ -#cmakedefine HAVE_CUDA - -/* NVidia Cuda Fast Fourier Transform (FFT) API*/ -#cmakedefine HAVE_CUFFT - -/* NVidia Cuda Basic Linear Algebra Subprograms (BLAS) API*/ -#cmakedefine HAVE_CUBLAS +/* Microsoft Media Foundation Capture library */ +#cmakedefine HAVE_MSMF /* NVidia Video Decoding API*/ #cmakedefine HAVE_NVCUVID -/* Compile for 'real' NVIDIA GPU architectures */ -#define CUDA_ARCH_BIN "${OPENCV_CUDA_ARCH_BIN}" - -/* Compile for 'virtual' NVIDIA PTX architectures */ -#define CUDA_ARCH_PTX "${OPENCV_CUDA_ARCH_PTX}" - -/* NVIDIA GPU features are used */ -#define CUDA_ARCH_FEATURES "${OPENCV_CUDA_ARCH_FEATURES}" - -/* Create PTX or BIN for 1.0 compute capability */ -#cmakedefine CUDA_ARCH_BIN_OR_PTX_10 - /* OpenCL Support */ #cmakedefine HAVE_OPENCL -/* AMD's OpenCL Fast Fourier Transform Library*/ -#cmakedefine HAVE_CLAMDFFT - -/* AMD's Basic Linear Algebra Subprograms Library*/ -#cmakedefine HAVE_CLAMDBLAS - -/* VideoInput library */ -#cmakedefine HAVE_VIDEOINPUT - -/* XIMEA camera support */ -#cmakedefine HAVE_XIMEA +/* OpenEXR codec */ +#cmakedefine HAVE_OPENEXR /* OpenGL support*/ #cmakedefine HAVE_OPENGL -/* Clp support */ -#cmakedefine HAVE_CLP +/* OpenNI library */ +#cmakedefine HAVE_OPENNI + +/* PNG codec */ +#cmakedefine HAVE_PNG + +/* Qt support */ +#cmakedefine HAVE_QT + +/* Qt OpenGL support */ +#cmakedefine HAVE_QT_OPENGL + +/* QuickTime video libraries */ +#cmakedefine HAVE_QUICKTIME + +/* QTKit video libraries */ +#cmakedefine HAVE_QTKIT + +/* Intel Threading Building Blocks */ +#cmakedefine HAVE_TBB + +/* TIFF codec */ +#cmakedefine HAVE_TIFF + +/* Unicap video capture library */ +#cmakedefine HAVE_UNICAP + +/* Video for Windows support */ +#cmakedefine HAVE_VFW + +/* V4L2 capturing support in videoio.h */ +#cmakedefine HAVE_VIDEOIO + +/* Win32 UI */ +#cmakedefine HAVE_WIN32UI + +/* Windows Runtime support */ +#cmakedefine HAVE_WINRT + +/* XIMEA camera support */ +#cmakedefine HAVE_XIMEA + +/* Xine video library */ +#cmakedefine HAVE_XINE + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#cmakedefine WORDS_BIGENDIAN diff --git a/cmake/templates/opencv-XXX.pc.cmake.in b/cmake/templates/opencv-XXX.pc.cmake.in index 4f6415cab4..5b94e4d6c3 100644 --- a/cmake/templates/opencv-XXX.pc.cmake.in +++ b/cmake/templates/opencv-XXX.pc.cmake.in @@ -8,6 +8,6 @@ includedir_new=@includedir@ Name: OpenCV Description: Open Source Computer Vision Library -Version: @VERSION@ +Version: @OPENCV_VERSION_PLAIN@ Libs: @OpenCV_LIB_COMPONENTS@ Cflags: -I${includedir_old} -I${includedir_new} diff --git a/cmake/templates/opencv_modules.hpp.in b/cmake/templates/opencv_modules.hpp.in index 5d58e40e4c..1498715028 100644 --- a/cmake/templates/opencv_modules.hpp.in +++ b/cmake/templates/opencv_modules.hpp.in @@ -6,4 +6,4 @@ * */ -@OPENCV_MODULE_DEFINITIONS_CONFIGMAKE@ \ No newline at end of file +@OPENCV_MODULE_DEFINITIONS_CONFIGMAKE@ diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 0f2695fc9a..888740bd4f 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -17,7 +17,7 @@ if(BUILD_DOCS AND HAVE_SPHINX) set(OPTIONAL_DOC_LIST "") - set(OPENCV2_BASE_MODULES core imgproc highgui video calib3d features2d objdetect ml flann gpu photo stitching nonfree contrib legacy) + set(OPENCV2_BASE_MODULES core imgproc highgui video calib3d features2d objdetect ml flann gpu photo stitching nonfree contrib legacy bioinspired) # build lists of modules to be documented set(OPENCV2_MODULES "") @@ -49,12 +49,12 @@ if(BUILD_DOCS AND HAVE_SPHINX) set(toc_file "${OPENCV_MODULE_opencv_${mod}_LOCATION}/doc/${mod}.rst") if(EXISTS "${toc_file}") file(RELATIVE_PATH toc_file "${OpenCV_SOURCE_DIR}/modules" "${toc_file}") - set(OPENCV_REFMAN_TOC "${OPENCV_REFMAN_TOC} ${toc_file}\r\n") + set(OPENCV_REFMAN_TOC "${OPENCV_REFMAN_TOC} ${toc_file}\n") endif() endforeach() - file(GLOB_RECURSE _OPENCV_FILES_REF "${OpenCV_SOURCE_DIR}/android/service/doc/*.rst") - file(GLOB_RECURSE _OPENCV_FILES_REF_PICT "${OpenCV_SOURCE_DIR}/android/service/doc/*.png" "${OpenCV_SOURCE_DIR}/android/service/doc/*.jpg") + file(GLOB_RECURSE _OPENCV_FILES_REF "${OpenCV_SOURCE_DIR}/platforms/android/service/doc/*.rst") + file(GLOB_RECURSE _OPENCV_FILES_REF_PICT "${OpenCV_SOURCE_DIR}/platforms/android/service/doc/*.png" "${OpenCV_SOURCE_DIR}/platforms/android/service/doc/*.jpg") list(APPEND OPENCV_FILES_REF ${_OPENCV_FILES_REF}) list(APPEND OPENCV_FILES_REF_PICT ${_OPENCV_FILES_REF_PICT}) @@ -67,9 +67,14 @@ if(BUILD_DOCS AND HAVE_SPHINX) set(OPENCV_DOC_DEPS conf.py ${OPENCV_FILES_REF} ${OPENCV_FILES_REF_PICT} ${OPENCV_FILES_UG} ${OPENCV_FILES_TUT} ${OPENCV_FILES_TUT_PICT}) + set(BUILD_PLANTUML "") + if(PLANTUML) + set(BUILD_PLANTUML "-tplantuml") + endif() + if(PDFLATEX_COMPILER) add_custom_target(docs - COMMAND ${SPHINX_BUILD} -b latex -c ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/.. . + COMMAND ${SPHINX_BUILD} ${BUILD_PLANTUML} -b latex -c ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/.. . COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/pics ${CMAKE_CURRENT_BINARY_DIR}/doc/opencv1/pics COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/mymath.sty ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/patch_refman_latex.py" opencv2refman.tex @@ -103,7 +108,7 @@ if(BUILD_DOCS AND HAVE_SPHINX) endif() add_custom_target(html_docs - COMMAND ${SPHINX_BUILD} -b html -c ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/.. ./_html + COMMAND ${SPHINX_BUILD} ${BUILD_PLANTUML} -b html -c ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/.. ./_html COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/mymath.sty ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${OPENCV_DOC_DEPS} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} @@ -122,4 +127,4 @@ if(BUILD_DOCS AND HAVE_SPHINX) install(FILES "${f}" DESTINATION "${OPENCV_DOC_INSTALL_PATH}" OPTIONAL) endforeach() -endif() \ No newline at end of file +endif() diff --git a/doc/_static/insertIframe.js b/doc/_static/insertIframe.js index 904ff361de..0a3099a8c2 100644 --- a/doc/_static/insertIframe.js +++ b/doc/_static/insertIframe.js @@ -1,4 +1,4 @@ -function insertIframe (elementId, iframeSrc) +function insertIframe (elementId, iframeSrc) { var iframe; if (document.createElement && (iframe = document.createElement('iframe'))) @@ -10,4 +10,3 @@ function insertIframe (elementId, iframeSrc) element.parentNode.replaceChild(iframe, element); } } - diff --git a/doc/_themes/blue/layout.html b/doc/_themes/blue/layout.html index 8bba49b17a..d0d43031c8 100644 --- a/doc/_themes/blue/layout.html +++ b/doc/_themes/blue/layout.html @@ -183,7 +183,7 @@ {% if theme_lang == 'c' %} {% endif %} {% if theme_lang == 'cpp' %} -
  • Try the Cheatsheet.
  • +
  • Try the Cheatsheet.
  • {% endif %} {% if theme_lang == 'py' %}
  • Try the Cookbook.
  • diff --git a/doc/_themes/blue/static/default.css_t b/doc/_themes/blue/static/default.css_t index e2127db1da..4d410be8aa 100644 --- a/doc/_themes/blue/static/default.css_t +++ b/doc/_themes/blue/static/default.css_t @@ -310,21 +310,6 @@ dl.pyfunction > dt:first-child { margin-bottom: 7px; } -dl.pyoldfunction > dt:first-child { - margin-bottom: 7px; - color: #8080B0; -} - -dl.pyoldfunction > dt:first-child tt.descname -{ - color: #8080B0; -} - -dl.pyoldfunction > dt:first-child tt.descclassname -{ - color: #8080B0; -} - dl.jfunction > dt:first-child { margin-bottom: 7px; } @@ -402,4 +387,4 @@ div.sphinxsidebar #searchbox input[type="text"] { div.sphinxsidebar #searchbox input[type="submit"] { width:auto; -} \ No newline at end of file +} diff --git a/doc/_themes/blue/theme.conf b/doc/_themes/blue/theme.conf index 206193f6f2..bc0b99b2a3 100644 --- a/doc/_themes/blue/theme.conf +++ b/doc/_themes/blue/theme.conf @@ -28,4 +28,4 @@ feedbacklinkcolor = #ffffff bodyfont = sans-serif headfont = 'Trebuchet MS', sans-serif guifont = "Lucida Sans","Lucida Sans Unicode","Lucida Grande",Verdana,Arial,Helvetica,sans-serif -lang = none \ No newline at end of file +lang = none diff --git a/doc/check_docs.py b/doc/check_docs.py index 487b390e8a..0290fc70f4 100755 --- a/doc/check_docs.py +++ b/doc/check_docs.py @@ -1,4 +1,4 @@ -#/usr/bin/env python +#!/usr/bin/env python import sys, glob @@ -184,5 +184,3 @@ p = RSTParser() for m in opencv_module_list: print "\n\n*************************** " + m + " *************************\n" p.check_module_docs(m) - - diff --git a/doc/check_docs2.py b/doc/check_docs2.py index 963c7ff1da..36d7068d86 100755 --- a/doc/check_docs2.py +++ b/doc/check_docs2.py @@ -1,4 +1,4 @@ -#/usr/bin/env python +#!/usr/bin/env python import os, sys, fnmatch, re @@ -83,11 +83,15 @@ def get_cv2_object(name): elif name == "DescriptorExtractor": return cv2.DescriptorExtractor_create("ORB"), name elif name == "BackgroundSubtractor": - return cv2.BackgroundSubtractorMOG(), name + return cv2.createBackgroundSubtractorMOG(), name elif name == "StatModel": return cv2.KNearest(), name else: - return getattr(cv2, name)(), name + try: + obj = getattr(cv2, name)() + except AttributeError: + obj = getattr(cv2, "create" + name)() + return obj, name def compareSignatures(f, s): # function names @@ -197,9 +201,9 @@ def process_module(module, path): hdrlist.append(os.path.join(root, filename)) if module == "gpu": - hdrlist.append(os.path.join(path, "..", "core", "include", "opencv2", "core", "cuda_devptrs.hpp")) - hdrlist.append(os.path.join(path, "..", "core", "include", "opencv2", "core", "gpumat.hpp")) - hdrlist.append(os.path.join(path, "..", "core", "include", "opencv2", "core", "stream_accessor.hpp")) + hdrlist.append(os.path.join(path, "..", "core", "include", "opencv2", "core", "gpu_types.hpp")) + hdrlist.append(os.path.join(path, "..", "core", "include", "opencv2", "core", "gpu.hpp")) + hdrlist.append(os.path.join(path, "..", "core", "include", "opencv2", "core", "gpu_stream_accessor.hpp")) decls = [] for hname in hdrlist: diff --git a/doc/conf.py b/doc/conf.py index 7b9b02ecf4..2cbcdf8867 100755 --- a/doc/conf.py +++ b/doc/conf.py @@ -1,4 +1,4 @@ -#/usr/bin/env python +#!/usr/bin/env python # -*- coding: utf-8 -*- # @@ -28,6 +28,16 @@ sys.path.insert(0, os.path.abspath('.')) # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.pngmath', 'sphinx.ext.ifconfig', 'sphinx.ext.todo', 'sphinx.ext.extlinks', 'ocv', 'sphinx.ext.doctest'] + +have_plantuml_ext = False +if tags.has('plantuml'): + try: + import sphinxcontrib.plantuml + extensions.append("sphinxcontrib.plantuml") + have_plantuml_ext = True + except ImportError: + print "No module sphinxcontrib.plantuml found, sphinx will not render UML diagrams" + doctest_test_doctest_blocks = 'block' # Add any paths that contain templates here, relative to this directory. @@ -55,6 +65,7 @@ version_epoch = re.search("^W*#\W*define\W+CV_VERSION_EPOCH\W+(\d+)\W*$", versio version_major = re.search("^W*#\W*define\W+CV_VERSION_MAJOR\W+(\d+)\W*$", version_file, re.MULTILINE).group(1) version_minor = re.search("^W*#\W*define\W+CV_VERSION_MINOR\W+(\d+)\W*$", version_file, re.MULTILINE).group(1) version_patch = re.search("^W*#\W*define\W+CV_VERSION_REVISION\W+(\d+)\W*$", version_file, re.MULTILINE).group(1) +version_status = re.search("^W*#\W*define\W+CV_VERSION_STATUS\W+\"(.*?)\"\W*$", version_file, re.MULTILINE).group(1) # The short X.Y version. version = version_epoch + '.' + version_major @@ -62,6 +73,7 @@ version = version_epoch + '.' + version_major release = version_epoch + '.' + version_major + '.' + version_minor if version_patch: release = release + '.' + version_patch +release += version_status # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -77,6 +89,9 @@ if version_patch: # directories to ignore when looking for source files. exclude_patterns = ['doc/tutorials/definitions'] +if not have_plantuml_ext: + exclude_patterns.append('**/uml/*') + # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None @@ -239,7 +254,7 @@ latex_documents = [ u'', 'manual'), ('doc/tutorials/tutorials', 'opencv_tutorials.tex', u'The OpenCV Tutorials', u'', 'manual'), - ('android/refman', 'opencv2manager.tex', u'The OpenCV Manager Manual', + ('platforms/android/refman', 'opencv2manager.tex', u'The OpenCV Manager Manual', u'', 'manual'), ] @@ -284,120 +299,122 @@ latex_domain_indices = True # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'opencv', u'The OpenCV Reference Manual', - [u'opencv-dev@itseez.com'], 1) + [u'admin@opencv.org'], 1) ] # ---- External links for tutorials ----------------- extlinks = { - 'basicstructures' : ('http://opencv.itseez.com/modules/core/doc/basic_structures.html#%s', None), - 'oldbasicstructures' : ('http://opencv.itseez.com/modules/core/doc/old_basic_structures.html#%s', None), - 'readwriteimagevideo' : ('http://opencv.itseez.com/modules/highgui/doc/reading_and_writing_images_and_video.html#%s', None), - 'operationsonarrays' : ('http://opencv.itseez.com/modules/core/doc/operations_on_arrays.html#%s', None), - 'utilitysystemfunctions':('http://opencv.itseez.com/modules/core/doc/utility_and_system_functions_and_macros.html#%s', None), - 'imgprocfilter':('http://opencv.itseez.com/modules/imgproc/doc/filtering.html#%s', None), - 'svms':('http://opencv.itseez.com/modules/ml/doc/support_vector_machines.html#%s', None), - 'drawingfunc':('http://opencv.itseez.com/modules/core/doc/drawing_functions.html#%s', None), - 'xmlymlpers':('http://opencv.itseez.com/modules/core/doc/xml_yaml_persistence.html#%s', None), - 'hgvideo' : ('http://opencv.itseez.com/modules/highgui/doc/reading_and_writing_images_and_video.html#%s', None), - 'gpuinit' : ('http://opencv.itseez.com/modules/gpu/doc/initalization_and_information.html#%s', None), - 'gpudatastructure' : ('http://opencv.itseez.com/modules/gpu/doc/data_structures.html#%s', None), - 'gpuopmatrices' : ('http://opencv.itseez.com/modules/gpu/doc/operations_on_matrices.html#%s', None), - 'gpuperelement' : ('http://opencv.itseez.com/modules/gpu/doc/per_element_operations.html#%s', None), - 'gpuimgproc' : ('http://opencv.itseez.com/modules/gpu/doc/image_processing.html#%s', None), - 'gpumatrixreduct' : ('http://opencv.itseez.com/modules/gpu/doc/matrix_reductions.html#%s', None), - 'filtering':('http://opencv.itseez.com/modules/imgproc/doc/filtering.html#%s', None), - 'flann' : ('http://opencv.itseez.com/modules/flann/doc/flann_fast_approximate_nearest_neighbor_search.html#%s', None ), - 'calib3d' : ('http://opencv.itseez.com/trunk/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#%s', None ), - 'feature2d' : ('http://opencv.itseez.com/trunk/modules/imgproc/doc/feature_detection.html#%s', None ), - 'imgproc_geometric' : ('http://opencv.itseez.com/trunk/modules/imgproc/doc/geometric_transformations.html#%s', None ), + 'basicstructures' : ('http://docs.opencv.org/modules/core/doc/basic_structures.html#%s', None), + 'oldbasicstructures' : ('http://docs.opencv.org/modules/core/doc/old_basic_structures.html#%s', None), + 'readwriteimagevideo' : ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#%s', None), + 'operationsonarrays' : ('http://docs.opencv.org/modules/core/doc/operations_on_arrays.html#%s', None), + 'utilitysystemfunctions':('http://docs.opencv.org/modules/core/doc/utility_and_system_functions_and_macros.html#%s', None), + 'imgprocfilter':('http://docs.opencv.org/modules/imgproc/doc/filtering.html#%s', None), + 'svms':('http://docs.opencv.org/modules/ml/doc/support_vector_machines.html#%s', None), + 'drawingfunc':('http://docs.opencv.org/modules/core/doc/drawing_functions.html#%s', None), + 'xmlymlpers':('http://docs.opencv.org/modules/core/doc/xml_yaml_persistence.html#%s', None), + 'hgvideo' : ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#%s', None), + 'gpuinit' : ('http://docs.opencv.org/modules/gpu/doc/initalization_and_information.html#%s', None), + 'gpudatastructure' : ('http://docs.opencv.org/modules/gpu/doc/data_structures.html#%s', None), + 'gpuopmatrices' : ('http://docs.opencv.org/modules/gpu/doc/operations_on_matrices.html#%s', None), + 'gpuperelement' : ('http://docs.opencv.org/modules/gpu/doc/per_element_operations.html#%s', None), + 'gpuimgproc' : ('http://docs.opencv.org/modules/gpu/doc/image_processing.html#%s', None), + 'gpumatrixreduct' : ('http://docs.opencv.org/modules/gpu/doc/matrix_reductions.html#%s', None), + 'filtering':('http://docs.opencv.org/modules/imgproc/doc/filtering.html#%s', None), + 'flann' : ('http://docs.opencv.org/modules/flann/doc/flann_fast_approximate_nearest_neighbor_search.html#%s', None ), + 'calib3d' : ('http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#%s', None ), + 'feature2d' : ('http://docs.opencv.org/modules/imgproc/doc/feature_detection.html#%s', None ), + 'imgproc_geometric' : ('http://docs.opencv.org/modules/imgproc/doc/geometric_transformations.html#%s', None ), - 'opencv_group' : ('http://tech.groups.yahoo.com/group/OpenCV/%s', None), + # 'opencv_group' : ('http://answers.opencv.org/%s', None), + 'opencv_qa' : ('http://answers.opencv.org/%s', None), + 'how_to_contribute' : ('http://code.opencv.org/projects/opencv/wiki/How_to_contribute/%s', None), - 'cvt_color': ('http://opencv.itseez.com/modules/imgproc/doc/miscellaneous_transformations.html?highlight=cvtcolor#cvtcolor%s', None), - 'imread': ('http://opencv.itseez.com/modules/highgui/doc/reading_and_writing_images_and_video.html?highlight=imread#imread%s', None), - 'imwrite': ('http://opencv.itseez.com/modules/highgui/doc/reading_and_writing_images_and_video.html?highlight=imwrite#imwrite%s', None), - 'imshow': ('http://opencv.itseez.com/modules/highgui/doc/user_interface.html?highlight=imshow#imshow%s', None), - 'named_window': ('http://opencv.itseez.com/modules/highgui/doc/user_interface.html?highlight=namedwindow#namedwindow%s', None), - 'wait_key': ('http://opencv.itseez.com/modules/highgui/doc/user_interface.html?highlight=waitkey#waitkey%s', None), - 'add_weighted': ('http://opencv.itseez.com/modules/core/doc/operations_on_arrays.html?highlight=addweighted#addweighted%s', None), - 'saturate_cast': ('http://opencv.itseez.com/modules/core/doc/utility_and_system_functions_and_macros.html?highlight=saturate_cast#saturate-cast%s', None), - 'mat_zeros': ('http://opencv.itseez.com/modules/core/doc/basic_structures.html?highlight=zeros#mat-zeros%s', None), - 'convert_to': ('http://opencv.itseez.com/modules/core/doc/basic_structures.html#mat-convertto%s', None), - 'create_trackbar': ('http://opencv.itseez.com/modules/highgui/doc/user_interface.html?highlight=createtrackbar#createtrackbar%s', None), - 'point': ('http://opencv.itseez.com/modules/core/doc/basic_structures.html#point%s', None), - 'scalar': ('http://opencv.itseez.com/modules/core/doc/basic_structures.html#scalar%s', None), - 'line': ('http://opencv.itseez.com/modules/core/doc/drawing_functions.html#line%s', None), - 'ellipse': ('http://opencv.itseez.com/modules/core/doc/drawing_functions.html#ellipse%s', None), - 'rectangle': ('http://opencv.itseez.com/modules/core/doc/drawing_functions.html#rectangle%s', None), - 'circle': ('http://opencv.itseez.com/modules/core/doc/drawing_functions.html#circle%s', None), - 'fill_poly': ('http://opencv.itseez.com/modules/core/doc/drawing_functions.html#fillpoly%s', None), - 'rng': ('http://opencv.itseez.com/modules/core/doc/operations_on_arrays.html?highlight=rng#rng%s', None), - 'put_text': ('http://opencv.itseez.com/modules/core/doc/drawing_functions.html#puttext%s', None), - 'gaussian_blur': ('http://opencv.itseez.com/modules/imgproc/doc/filtering.html?highlight=gaussianblur#gaussianblur%s', None), - 'blur': ('http://opencv.itseez.com/modules/imgproc/doc/filtering.html?highlight=blur#blur%s', None), - 'median_blur': ('http://opencv.itseez.com/modules/imgproc/doc/filtering.html?highlight=medianblur#medianblur%s', None), - 'bilateral_filter': ('http://opencv.itseez.com/modules/imgproc/doc/filtering.html?highlight=bilateralfilter#bilateralfilter%s', None), - 'erode': ('http://opencv.itseez.com/modules/imgproc/doc/filtering.html?highlight=erode#erode%s', None), - 'dilate': ('http://opencv.itseez.com/modules/imgproc/doc/filtering.html?highlight=dilate#dilate%s', None), - 'get_structuring_element': ('http://opencv.itseez.com/modules/imgproc/doc/filtering.html?highlight=getstructuringelement#getstructuringelement%s', None), - 'flood_fill': ( 'http://opencv.itseez.com/modules/imgproc/doc/miscellaneous_transformations.html?highlight=floodfill#floodfill%s', None), - 'morphology_ex': ('http://opencv.itseez.com/modules/imgproc/doc/filtering.html?highlight=morphologyex#morphologyex%s', None), - 'pyr_down': ('http://opencv.itseez.com/modules/imgproc/doc/filtering.html?highlight=pyrdown#pyrdown%s', None), - 'pyr_up': ('http://opencv.itseez.com/modules/imgproc/doc/filtering.html?highlight=pyrup#pyrup%s', None), - 'resize': ('http://opencv.itseez.com/modules/imgproc/doc/geometric_transformations.html?highlight=resize#resize%s', None), - 'threshold': ('http://opencv.itseez.com/modules/imgproc/doc/miscellaneous_transformations.html?highlight=threshold#threshold%s', None), - 'filter2d': ('http://opencv.itseez.com/modules/imgproc/doc/filtering.html?highlight=filter2d#filter2d%s', None), - 'copy_make_border': ('http://opencv.itseez.com/modules/imgproc/doc/filtering.html?highlight=copymakeborder#copymakeborder%s', None), - 'sobel': ('http://opencv.itseez.com/modules/imgproc/doc/filtering.html?highlight=sobel#sobel%s', None), - 'scharr': ('http://opencv.itseez.com/modules/imgproc/doc/filtering.html?highlight=scharr#scharr%s', None), - 'laplacian': ('http://opencv.itseez.com/modules/imgproc/doc/filtering.html?highlight=laplacian#laplacian%s', None), - 'canny': ('http://opencv.itseez.com/modules/imgproc/doc/feature_detection.html?highlight=canny#canny%s', None), - 'copy_to': ('http://opencv.itseez.com/modules/core/doc/basic_structures.html?highlight=copyto#mat-copyto%s', None), - 'hough_lines' : ('http://opencv.itseez.com/modules/imgproc/doc/feature_detection.html?highlight=houghlines#houghlines%s', None), - 'hough_lines_p' : ('http://opencv.itseez.com/modules/imgproc/doc/feature_detection.html?highlight=houghlinesp#houghlinesp%s', None), - 'hough_circles' : ('http://opencv.itseez.com/modules/imgproc/doc/feature_detection.html?highlight=houghcircles#houghcircles%s', None), - 'remap' : ('http://opencv.itseez.com/modules/imgproc/doc/geometric_transformations.html?highlight=remap#remap%s', None), - 'warp_affine' : ('http://opencv.itseez.com/modules/imgproc/doc/geometric_transformations.html?highlight=warpaffine#warpaffine%s' , None), - 'get_rotation_matrix_2d' : ('http://opencv.itseez.com/modules/imgproc/doc/geometric_transformations.html?highlight=getrotationmatrix2d#getrotationmatrix2d%s', None), - 'get_affine_transform' : ('http://opencv.itseez.com/modules/imgproc/doc/geometric_transformations.html?highlight=getaffinetransform#getaffinetransform%s', None), - 'equalize_hist' : ('http://opencv.itseez.com/modules/imgproc/doc/histograms.html?highlight=equalizehist#equalizehist%s', None), - 'split' : ('http://opencv.itseez.com/modules/core/doc/operations_on_arrays.html?highlight=split#split%s', None), - 'calc_hist' : ('http://opencv.itseez.com/modules/imgproc/doc/histograms.html?highlight=calchist#calchist%s', None), - 'normalize' : ('http://opencv.itseez.com/modules/core/doc/operations_on_arrays.html?highlight=normalize#normalize%s', None), - 'match_template' : ('http://opencv.itseez.com/modules/imgproc/doc/object_detection.html?highlight=matchtemplate#matchtemplate%s', None), - 'min_max_loc' : ('http://opencv.itseez.com/modules/core/doc/operations_on_arrays.html?highlight=minmaxloc#minmaxloc%s', None), - 'mix_channels' : ( 'http://opencv.itseez.com/modules/core/doc/operations_on_arrays.html?highlight=mixchannels#mixchannels%s', None), - 'calc_back_project' : ('http://opencv.itseez.com/modules/imgproc/doc/histograms.html?highlight=calcbackproject#calcbackproject%s', None), - 'compare_hist' : ('http://opencv.itseez.com/modules/imgproc/doc/histograms.html?highlight=comparehist#comparehist%s', None), - 'corner_harris' : ('http://opencv.itseez.com/modules/imgproc/doc/feature_detection.html?highlight=cornerharris#cornerharris%s', None), - 'good_features_to_track' : ('http://opencv.itseez.com/modules/imgproc/doc/feature_detection.html?highlight=goodfeaturestotrack#goodfeaturestotrack%s', None), - 'corner_min_eigenval' : ('http://opencv.itseez.com/modules/imgproc/doc/feature_detection.html?highlight=cornermineigenval#cornermineigenval%s', None), - 'corner_eigenvals_and_vecs' : ('http://opencv.itseez.com/modules/imgproc/doc/feature_detection.html?highlight=cornereigenvalsandvecs#cornereigenvalsandvecs%s', None), - 'corner_sub_pix' : ('http://opencv.itseez.com/modules/imgproc/doc/feature_detection.html?highlight=cornersubpix#cornersubpix%s', None), - 'find_contours' : ('http://opencv.itseez.com/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=findcontours#findcontours%s', None), - 'convex_hull' : ('http://opencv.itseez.com/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=convexhull#convexhull%s', None), - 'draw_contours' : ('http://opencv.itseez.com/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=drawcontours#drawcontours%s', None), - 'bounding_rect' : ('http://opencv.itseez.com/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=boundingrect#boundingrect%s', None), - 'min_enclosing_circle' : ('http://opencv.itseez.com/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=minenclosingcircle#minenclosingcircle%s', None), - 'min_area_rect' : ('http://opencv.itseez.com/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=minarearect#minarearect%s', None), - 'fit_ellipse' : ('http://opencv.itseez.com/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=fitellipse#fitellipse%s', None), - 'moments' : ('http://opencv.itseez.com/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=moments#moments%s', None), - 'contour_area' : ('http://opencv.itseez.com/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=contourarea#contourarea%s', None), - 'arc_length' : ('http://opencv.itseez.com/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=arclength#arclength%s', None), - 'point_polygon_test' : ('http://opencv.itseez.com/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=pointpolygontest#pointpolygontest%s', None), - 'feature_detector' : ( 'http://opencv.itseez.com/modules/features2d/doc/common_interfaces_of_feature_detectors.html?highlight=featuredetector#FeatureDetector%s', None), - 'feature_detector_detect' : ('http://opencv.itseez.com/modules/features2d/doc/common_interfaces_of_feature_detectors.html?highlight=detect#featuredetector-detect%s', None ), - 'surf_feature_detector' : ('http://opencv.itseez.com/modules/features2d/doc/common_interfaces_of_feature_detectors.html?highlight=surffeaturedetector#surffeaturedetector%s', None ), - 'draw_keypoints' : ('http://opencv.itseez.com/modules/features2d/doc/drawing_function_of_keypoints_and_matches.html?highlight=drawkeypoints#drawkeypoints%s', None ), - 'descriptor_extractor': ( 'http://opencv.itseez.com/modules/features2d/doc/common_interfaces_of_descriptor_extractors.html?highlight=descriptorextractor#descriptorextractor%s', None ), - 'descriptor_extractor_compute' : ( 'http://opencv.itseez.com/modules/features2d/doc/common_interfaces_of_descriptor_extractors.html?highlight=compute#descriptorextractor-compute%s', None ), - 'surf_descriptor_extractor' : ( 'http://opencv.itseez.com/modules/features2d/doc/common_interfaces_of_descriptor_extractors.html?highlight=surfdescriptorextractor#surfdescriptorextractor%s', None ), - 'draw_matches' : ( 'http://opencv.itseez.com/modules/features2d/doc/drawing_function_of_keypoints_and_matches.html?highlight=drawmatches#drawmatches%s', None ), - 'find_homography' : ('http://opencv.itseez.com/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html?highlight=findhomography#findhomography%s', None), - 'perspective_transform' : ('http://opencv.itseez.com/modules/core/doc/operations_on_arrays.html?highlight=perspectivetransform#perspectivetransform%s', None ), - 'flann_based_matcher' : ('http://opencv.itseez.com/modules/features2d/doc/common_interfaces_of_descriptor_matchers.html?highlight=flannbasedmatcher#flannbasedmatcher%s', None), - 'brute_force_matcher' : ('http://opencv.itseez.com/modules/features2d/doc/common_interfaces_of_descriptor_matchers.html?highlight=bruteforcematcher#bruteforcematcher%s', None ), - 'cascade_classifier' : ('http://opencv.itseez.com/modules/objdetect/doc/cascade_classification.html?highlight=cascadeclassifier#cascadeclassifier%s', None ), - 'cascade_classifier_load' : ('http://opencv.itseez.com/modules/objdetect/doc/cascade_classification.html?highlight=load#cascadeclassifier-load%s', None ), - 'cascade_classifier_detect_multiscale' : ('http://opencv.itseez.com/modules/objdetect/doc/cascade_classification.html?highlight=detectmultiscale#cascadeclassifier-detectmultiscale%s', None ) + 'cvt_color': ('http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html?highlight=cvtcolor#cvtcolor%s', None), + 'imread': ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html?highlight=imread#imread%s', None), + 'imwrite': ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html?highlight=imwrite#imwrite%s', None), + 'imshow': ('http://docs.opencv.org/modules/highgui/doc/user_interface.html?highlight=imshow#imshow%s', None), + 'named_window': ('http://docs.opencv.org/modules/highgui/doc/user_interface.html?highlight=namedwindow#namedwindow%s', None), + 'wait_key': ('http://docs.opencv.org/modules/highgui/doc/user_interface.html?highlight=waitkey#waitkey%s', None), + 'add_weighted': ('http://docs.opencv.org/modules/core/doc/operations_on_arrays.html?highlight=addweighted#addweighted%s', None), + 'saturate_cast': ('http://docs.opencv.org/modules/core/doc/utility_and_system_functions_and_macros.html?highlight=saturate_cast#saturate-cast%s', None), + 'mat_zeros': ('http://docs.opencv.org/modules/core/doc/basic_structures.html?highlight=zeros#mat-zeros%s', None), + 'convert_to': ('http://docs.opencv.org/modules/core/doc/basic_structures.html#mat-convertto%s', None), + 'create_trackbar': ('http://docs.opencv.org/modules/highgui/doc/user_interface.html?highlight=createtrackbar#createtrackbar%s', None), + 'point': ('http://docs.opencv.org/modules/core/doc/basic_structures.html#point%s', None), + 'scalar': ('http://docs.opencv.org/modules/core/doc/basic_structures.html#scalar%s', None), + 'line': ('http://docs.opencv.org/modules/core/doc/drawing_functions.html#line%s', None), + 'ellipse': ('http://docs.opencv.org/modules/core/doc/drawing_functions.html#ellipse%s', None), + 'rectangle': ('http://docs.opencv.org/modules/core/doc/drawing_functions.html#rectangle%s', None), + 'circle': ('http://docs.opencv.org/modules/core/doc/drawing_functions.html#circle%s', None), + 'fill_poly': ('http://docs.opencv.org/modules/core/doc/drawing_functions.html#fillpoly%s', None), + 'rng': ('http://docs.opencv.org/modules/core/doc/operations_on_arrays.html?highlight=rng#rng%s', None), + 'put_text': ('http://docs.opencv.org/modules/core/doc/drawing_functions.html#puttext%s', None), + 'gaussian_blur': ('http://docs.opencv.org/modules/imgproc/doc/filtering.html?highlight=gaussianblur#gaussianblur%s', None), + 'blur': ('http://docs.opencv.org/modules/imgproc/doc/filtering.html?highlight=blur#blur%s', None), + 'median_blur': ('http://docs.opencv.org/modules/imgproc/doc/filtering.html?highlight=medianblur#medianblur%s', None), + 'bilateral_filter': ('http://docs.opencv.org/modules/imgproc/doc/filtering.html?highlight=bilateralfilter#bilateralfilter%s', None), + 'erode': ('http://docs.opencv.org/modules/imgproc/doc/filtering.html?highlight=erode#erode%s', None), + 'dilate': ('http://docs.opencv.org/modules/imgproc/doc/filtering.html?highlight=dilate#dilate%s', None), + 'get_structuring_element': ('http://docs.opencv.org/modules/imgproc/doc/filtering.html?highlight=getstructuringelement#getstructuringelement%s', None), + 'flood_fill': ( 'http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html?highlight=floodfill#floodfill%s', None), + 'morphology_ex': ('http://docs.opencv.org/modules/imgproc/doc/filtering.html?highlight=morphologyex#morphologyex%s', None), + 'pyr_down': ('http://docs.opencv.org/modules/imgproc/doc/filtering.html?highlight=pyrdown#pyrdown%s', None), + 'pyr_up': ('http://docs.opencv.org/modules/imgproc/doc/filtering.html?highlight=pyrup#pyrup%s', None), + 'resize': ('http://docs.opencv.org/modules/imgproc/doc/geometric_transformations.html?highlight=resize#resize%s', None), + 'threshold': ('http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html?highlight=threshold#threshold%s', None), + 'filter2d': ('http://docs.opencv.org/modules/imgproc/doc/filtering.html?highlight=filter2d#filter2d%s', None), + 'copy_make_border': ('http://docs.opencv.org/modules/imgproc/doc/filtering.html?highlight=copymakeborder#copymakeborder%s', None), + 'sobel': ('http://docs.opencv.org/modules/imgproc/doc/filtering.html?highlight=sobel#sobel%s', None), + 'scharr': ('http://docs.opencv.org/modules/imgproc/doc/filtering.html?highlight=scharr#scharr%s', None), + 'laplacian': ('http://docs.opencv.org/modules/imgproc/doc/filtering.html?highlight=laplacian#laplacian%s', None), + 'canny': ('http://docs.opencv.org/modules/imgproc/doc/feature_detection.html?highlight=canny#canny%s', None), + 'copy_to': ('http://docs.opencv.org/modules/core/doc/basic_structures.html?highlight=copyto#mat-copyto%s', None), + 'hough_lines' : ('http://docs.opencv.org/modules/imgproc/doc/feature_detection.html?highlight=houghlines#houghlines%s', None), + 'hough_lines_p' : ('http://docs.opencv.org/modules/imgproc/doc/feature_detection.html?highlight=houghlinesp#houghlinesp%s', None), + 'hough_circles' : ('http://docs.opencv.org/modules/imgproc/doc/feature_detection.html?highlight=houghcircles#houghcircles%s', None), + 'remap' : ('http://docs.opencv.org/modules/imgproc/doc/geometric_transformations.html?highlight=remap#remap%s', None), + 'warp_affine' : ('http://docs.opencv.org/modules/imgproc/doc/geometric_transformations.html?highlight=warpaffine#warpaffine%s' , None), + 'get_rotation_matrix_2d' : ('http://docs.opencv.org/modules/imgproc/doc/geometric_transformations.html?highlight=getrotationmatrix2d#getrotationmatrix2d%s', None), + 'get_affine_transform' : ('http://docs.opencv.org/modules/imgproc/doc/geometric_transformations.html?highlight=getaffinetransform#getaffinetransform%s', None), + 'equalize_hist' : ('http://docs.opencv.org/modules/imgproc/doc/histograms.html?highlight=equalizehist#equalizehist%s', None), + 'split' : ('http://docs.opencv.org/modules/core/doc/operations_on_arrays.html?highlight=split#split%s', None), + 'calc_hist' : ('http://docs.opencv.org/modules/imgproc/doc/histograms.html?highlight=calchist#calchist%s', None), + 'normalize' : ('http://docs.opencv.org/modules/core/doc/operations_on_arrays.html?highlight=normalize#normalize%s', None), + 'match_template' : ('http://docs.opencv.org/modules/imgproc/doc/object_detection.html?highlight=matchtemplate#matchtemplate%s', None), + 'min_max_loc' : ('http://docs.opencv.org/modules/core/doc/operations_on_arrays.html?highlight=minmaxloc#minmaxloc%s', None), + 'mix_channels' : ( 'http://docs.opencv.org/modules/core/doc/operations_on_arrays.html?highlight=mixchannels#mixchannels%s', None), + 'calc_back_project' : ('http://docs.opencv.org/modules/imgproc/doc/histograms.html?highlight=calcbackproject#calcbackproject%s', None), + 'compare_hist' : ('http://docs.opencv.org/modules/imgproc/doc/histograms.html?highlight=comparehist#comparehist%s', None), + 'corner_harris' : ('http://docs.opencv.org/modules/imgproc/doc/feature_detection.html?highlight=cornerharris#cornerharris%s', None), + 'good_features_to_track' : ('http://docs.opencv.org/modules/imgproc/doc/feature_detection.html?highlight=goodfeaturestotrack#goodfeaturestotrack%s', None), + 'corner_min_eigenval' : ('http://docs.opencv.org/modules/imgproc/doc/feature_detection.html?highlight=cornermineigenval#cornermineigenval%s', None), + 'corner_eigenvals_and_vecs' : ('http://docs.opencv.org/modules/imgproc/doc/feature_detection.html?highlight=cornereigenvalsandvecs#cornereigenvalsandvecs%s', None), + 'corner_sub_pix' : ('http://docs.opencv.org/modules/imgproc/doc/feature_detection.html?highlight=cornersubpix#cornersubpix%s', None), + 'find_contours' : ('http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=findcontours#findcontours%s', None), + 'convex_hull' : ('http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=convexhull#convexhull%s', None), + 'draw_contours' : ('http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=drawcontours#drawcontours%s', None), + 'bounding_rect' : ('http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=boundingrect#boundingrect%s', None), + 'min_enclosing_circle' : ('http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=minenclosingcircle#minenclosingcircle%s', None), + 'min_area_rect' : ('http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=minarearect#minarearect%s', None), + 'fit_ellipse' : ('http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=fitellipse#fitellipse%s', None), + 'moments' : ('http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=moments#moments%s', None), + 'contour_area' : ('http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=contourarea#contourarea%s', None), + 'arc_length' : ('http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=arclength#arclength%s', None), + 'point_polygon_test' : ('http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=pointpolygontest#pointpolygontest%s', None), + 'feature_detector' : ( 'http://docs.opencv.org/modules/features2d/doc/common_interfaces_of_feature_detectors.html?highlight=featuredetector#FeatureDetector%s', None), + 'feature_detector_detect' : ('http://docs.opencv.org/modules/features2d/doc/common_interfaces_of_feature_detectors.html?highlight=detect#featuredetector-detect%s', None ), + 'surf_feature_detector' : ('http://docs.opencv.org/modules/features2d/doc/common_interfaces_of_feature_detectors.html?highlight=surffeaturedetector#surffeaturedetector%s', None ), + 'draw_keypoints' : ('http://docs.opencv.org/modules/features2d/doc/drawing_function_of_keypoints_and_matches.html?highlight=drawkeypoints#drawkeypoints%s', None ), + 'descriptor_extractor': ( 'http://docs.opencv.org/modules/features2d/doc/common_interfaces_of_descriptor_extractors.html?highlight=descriptorextractor#descriptorextractor%s', None ), + 'descriptor_extractor_compute' : ( 'http://docs.opencv.org/modules/features2d/doc/common_interfaces_of_descriptor_extractors.html?highlight=compute#descriptorextractor-compute%s', None ), + 'surf_descriptor_extractor' : ( 'http://docs.opencv.org/modules/features2d/doc/common_interfaces_of_descriptor_extractors.html?highlight=surfdescriptorextractor#surfdescriptorextractor%s', None ), + 'draw_matches' : ( 'http://docs.opencv.org/modules/features2d/doc/drawing_function_of_keypoints_and_matches.html?highlight=drawmatches#drawmatches%s', None ), + 'find_homography' : ('http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html?highlight=findhomography#findhomography%s', None), + 'perspective_transform' : ('http://docs.opencv.org/modules/core/doc/operations_on_arrays.html?highlight=perspectivetransform#perspectivetransform%s', None ), + 'flann_based_matcher' : ('http://docs.opencv.org/modules/features2d/doc/common_interfaces_of_descriptor_matchers.html?highlight=flannbasedmatcher#flannbasedmatcher%s', None), + 'brute_force_matcher' : ('http://docs.opencv.org/modules/features2d/doc/common_interfaces_of_descriptor_matchers.html?highlight=bruteforcematcher#bruteforcematcher%s', None ), + 'cascade_classifier' : ('http://docs.opencv.org/modules/objdetect/doc/cascade_classification.html?highlight=cascadeclassifier#cascadeclassifier%s', None ), + 'cascade_classifier_load' : ('http://docs.opencv.org/modules/objdetect/doc/cascade_classification.html?highlight=load#cascadeclassifier-load%s', None ), + 'cascade_classifier_detect_multiscale' : ('http://docs.opencv.org/modules/objdetect/doc/cascade_classification.html?highlight=detectmultiscale#cascadeclassifier-detectmultiscale%s', None ) } diff --git a/doc/mymath.sty b/doc/mymath.sty index 491c160cc3..4da8282121 100644 --- a/doc/mymath.sty +++ b/doc/mymath.sty @@ -39,4 +39,3 @@ #7 & #8 & #9 \end{bmatrix} } - diff --git a/doc/ocv.py b/doc/ocv.py index 4ff8a6deb5..a22d3daa56 100755 --- a/doc/ocv.py +++ b/doc/ocv.py @@ -1,4 +1,4 @@ -#/usr/bin/env python +#!/usr/bin/env python # -*- coding: utf-8 -*- """ ocv domain, a modified copy of sphinx.domains.cpp + shpinx.domains.python. @@ -267,10 +267,6 @@ class OCVPyModulelevel(OCVPyObject): else: return '' -class OCVPyOldModulelevel(OCVPyModulelevel): - directive_prefix = 'pyold' - pass - class OCVPyXRefRole(XRefRole): def process_link(self, env, refnode, has_explicit_title, title, target): refnode['ocv:module'] = env.temp_data.get('ocv:module') @@ -1491,7 +1487,6 @@ class OCVDomain(Domain): 'cfunction': ObjType(l_('cfunction'), 'cfunc', 'cfuncx'), 'jfunction': ObjType(l_('jfunction'), 'jfunc', 'jfuncx'), 'pyfunction': ObjType(l_('pyfunction'), 'pyfunc'), - 'pyoldfunction': ObjType(l_('pyoldfunction'), 'pyoldfunc'), 'member': ObjType(l_('member'), 'member'), 'emember': ObjType(l_('emember'), 'emember'), 'type': ObjType(l_('type'), 'type'), @@ -1505,7 +1500,6 @@ class OCVDomain(Domain): 'cfunction': OCVCFunctionObject, 'jfunction': OCVJavaFunctionObject, 'pyfunction': OCVPyModulelevel, - 'pyoldfunction': OCVPyOldModulelevel, 'member': OCVMemberObject, 'emember': OCVEnumMemberObject, 'type': OCVTypeObject, @@ -1522,7 +1516,6 @@ class OCVDomain(Domain): 'jfunc' : OCVXRefRole(fix_parens=True), 'jfuncx' : OCVXRefRole(), 'pyfunc' : OCVPyXRefRole(), - 'pyoldfunc' : OCVPyXRefRole(), 'member': OCVXRefRole(), 'emember': OCVXRefRole(), 'type': OCVXRefRole(), @@ -1612,7 +1605,6 @@ class OCVDomain(Domain): 'cfunction': _('C function'), 'jfunction': _('Java method'), 'pyfunction': _('Python function'), - 'pyoldfunction': _('Legacy Python function'), 'member': _('C++ member'), 'emember': _('enum member'), 'type': _('C/C++ type'), diff --git a/doc/opencv-logo2.png b/doc/opencv-logo2.png index 615fd2add4..bc71a2ae50 100644 Binary files a/doc/opencv-logo2.png and b/doc/opencv-logo2.png differ diff --git a/doc/opencv_cheatsheet.tex b/doc/opencv_cheatsheet.tex index e76bd016e9..fc0c0fa41b 100644 --- a/doc/opencv_cheatsheet.tex +++ b/doc/opencv_cheatsheet.tex @@ -75,11 +75,11 @@ % if using A4 paper. (This probably isn't strictly necessary.) % If using another size paper, use default 1cm margins. \ifthenelse{\lengthtest { \paperwidth = 11in}} - { \geometry{top=.5in,left=.5in,right=.5in,bottom=.5in} } - {\ifthenelse{ \lengthtest{ \paperwidth = 297mm}} - {\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} } - {\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} } - } + { \geometry{top=.5in,left=.5in,right=.5in,bottom=.5in} } + {\ifthenelse{ \lengthtest{ \paperwidth = 297mm}} + {\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} } + {\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} } + } % Turn off header and footer % \pagestyle{empty} diff --git a/doc/patch_refman_latex.py b/doc/patch_refman_latex.py index 352c46cb56..ff762fc8f3 100755 --- a/doc/patch_refman_latex.py +++ b/doc/patch_refman_latex.py @@ -1,4 +1,4 @@ -#/usr/bin/env python +#!/usr/bin/env python import sys diff --git a/doc/pattern_tools/gen_pattern.py b/doc/pattern_tools/gen_pattern.py index 45b45af2db..3643b6d3b2 100755 --- a/doc/pattern_tools/gen_pattern.py +++ b/doc/pattern_tools/gen_pattern.py @@ -1,4 +1,4 @@ -#/usr/bin/env python +#!/usr/bin/env python """gen_pattern.py To run: diff --git a/doc/pattern_tools/svgfig.py b/doc/pattern_tools/svgfig.py index bf182a8b09..c690c9ff08 100755 --- a/doc/pattern_tools/svgfig.py +++ b/doc/pattern_tools/svgfig.py @@ -1,4 +1,4 @@ -#/usr/bin/env python +#!/usr/bin/env python # svgfig.py copyright (C) 2008 Jim Pivarski # @@ -3667,4 +3667,3 @@ class YErrorBars: output.append(LineAxis(x, start, x, end, start, end, bars, False, False, **self.attr).SVG(trans)) return output - diff --git a/doc/reformat.py b/doc/reformat.py index 00e4aae9e0..017efebb38 100755 --- a/doc/reformat.py +++ b/doc/reformat.py @@ -1,4 +1,4 @@ -#/usr/bin/env python +#!/usr/bin/env python import os, sys, re diff --git a/doc/tutorials/contrib/retina_model/images/retina_TreeHdr_retina.jpg b/doc/tutorials/bioinspired/retina_model/images/retina_TreeHdr_retina.jpg similarity index 100% rename from doc/tutorials/contrib/retina_model/images/retina_TreeHdr_retina.jpg rename to doc/tutorials/bioinspired/retina_model/images/retina_TreeHdr_retina.jpg diff --git a/doc/tutorials/contrib/retina_model/images/retina_TreeHdr_small.jpg b/doc/tutorials/bioinspired/retina_model/images/retina_TreeHdr_small.jpg similarity index 100% rename from doc/tutorials/contrib/retina_model/images/retina_TreeHdr_small.jpg rename to doc/tutorials/bioinspired/retina_model/images/retina_TreeHdr_small.jpg diff --git a/doc/tutorials/contrib/retina_model/images/studentsSample_input.jpg b/doc/tutorials/bioinspired/retina_model/images/studentsSample_input.jpg similarity index 100% rename from doc/tutorials/contrib/retina_model/images/studentsSample_input.jpg rename to doc/tutorials/bioinspired/retina_model/images/studentsSample_input.jpg diff --git a/doc/tutorials/contrib/retina_model/images/studentsSample_magno.jpg b/doc/tutorials/bioinspired/retina_model/images/studentsSample_magno.jpg similarity index 100% rename from doc/tutorials/contrib/retina_model/images/studentsSample_magno.jpg rename to doc/tutorials/bioinspired/retina_model/images/studentsSample_magno.jpg diff --git a/doc/tutorials/contrib/retina_model/images/studentsSample_parvo.jpg b/doc/tutorials/bioinspired/retina_model/images/studentsSample_parvo.jpg similarity index 100% rename from doc/tutorials/contrib/retina_model/images/studentsSample_parvo.jpg rename to doc/tutorials/bioinspired/retina_model/images/studentsSample_parvo.jpg diff --git a/doc/tutorials/contrib/retina_model/retina_model.rst b/doc/tutorials/bioinspired/retina_model/retina_model.rst similarity index 79% rename from doc/tutorials/contrib/retina_model/retina_model.rst rename to doc/tutorials/bioinspired/retina_model/retina_model.rst index 184bb343e1..e8527ee8b6 100644 --- a/doc/tutorials/contrib/retina_model/retina_model.rst +++ b/doc/tutorials/bioinspired/retina_model/retina_model.rst @@ -21,7 +21,7 @@ In this tutorial you will learn how to: General overview ================ -The proposed model originates from Jeanny Herault's research at `Gipsa `_. It is involved in image processing applications with `Listic `_ (code maintainer) lab. This is not a complete model but it already present interesting properties that can be involved for enhanced image processing experience. The model allows the following human retina properties to be used : +The proposed model originates from Jeanny Herault's research [herault2010]_ at `Gipsa `_. It is involved in image processing applications with `Listic `_ (code maintainer and user) lab. This is not a complete model but it already present interesting properties that can be involved for enhanced image processing experience. The model allows the following human retina properties to be used : * spectral whitening that has 3 important effects: high spatio-temporal frequency signals canceling (noise), mid-frequencies details enhancement and low frequencies luminance energy reduction. This *all in one* property directly allows visual signals cleaning of classical undesired distortions introduced by image sensors and input luminance range. @@ -37,7 +37,7 @@ In the figure below, the OpenEXR image sample *CrissyField.exr*, a High Dynamic :alt: A High dynamic range image linearly rescaled within range [0-255]. :align: center -In the following image, as your retina does, local luminance adaptation, spatial noise removal and spectral whitening work together and transmit accurate information on lower range 8bit data channels. On this picture, noise in significantly removed, local details hidden by strong luminance contrasts are enhanced. Output image keeps its naturalness and visual content is enhanced. +In the following image, applying the ideas proposed in [benoit2010]_, as your retina does, local luminance adaptation, spatial noise removal and spectral whitening work together and transmit accurate information on lower range 8bit data channels. On this picture, noise in significantly removed, local details hidden by strong luminance contrasts are enhanced. Output image keeps its naturalness and visual content is enhanced. Color processing is based on the color multiplexing/demultiplexing method proposed in [chaix2007]_. .. image:: images/retina_TreeHdr_retina.jpg :alt: A High dynamic range image compressed within range [0-255] using the retina. @@ -86,31 +86,37 @@ This model can be used basically for spatio-temporal video effects but also in t * performing motion analysis also taking benefit of the previously cited properties. +Literature +========== For more information, refer to the following papers : -* Benoit A., Caplier A., Durette B., Herault, J., "Using Human Visual System Modeling For Bio-Inspired Low Level Image Processing", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773. DOI +.. [benoit2010] Benoit A., Caplier A., Durette B., Herault, J., "Using Human Visual System Modeling For Bio-Inspired Low Level Image Processing", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773. DOI * Please have a look at the reference work of Jeanny Herault that you can read in his book : -Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. +.. [herault2010] Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. This retina filter code includes the research contributions of phd/research collegues from which code has been redrawn by the author : -* take a look at the *retinacolor.hpp* module to discover Brice Chaix de Lavarene phD color mosaicing/demosaicing and his reference paper: B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 +* take a look at the *retinacolor.hpp* module to discover Brice Chaix de Lavarene phD color mosaicing/demosaicing and his reference paper: -* take a look at *imagelogpolprojection.hpp* to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. ====> more information in the above cited Jeanny Heraults's book. +.. [chaix2007] B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 + +* take a look at *imagelogpolprojection.hpp* to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. More informations in the above cited Jeanny Heraults's book. Code tutorial ============= -Please refer to the original tutorial source code in file *opencv_folder/samples/cpp/tutorial_code/contrib/retina_tutorial.cpp*. +Please refer to the original tutorial source code in file *opencv_folder/samples/cpp/tutorial_code/bioinspired/retina_tutorial.cpp*. -To compile it, assuming OpenCV is correctly installed, use the following command. It requires the opencv_core *(cv::Mat and friends objects management)*, opencv_highgui *(display and image/video read)* and opencv_contrib *(Retina description)* libraries to compile. +**Note :** do not forget that the retina model is included in the following namespace : *cv::bioinspired*. + +To compile it, assuming OpenCV is correctly installed, use the following command. It requires the opencv_core *(cv::Mat and friends objects management)*, opencv_highgui *(display and image/video read)* and opencv_bioinspired *(Retina description)* libraries to compile. .. code-block:: cpp // compile - gcc retina_tutorial.cpp -o Retina_tuto -lopencv_core -lopencv_highgui -lopencv_contrib + gcc retina_tutorial.cpp -o Retina_tuto -lopencv_core -lopencv_highgui -lopencv_bioinspired // Run commands : add 'log' as a last parameter to apply a spatial log sampling (simulates retina sampling) // run on webcam @@ -124,7 +130,7 @@ To compile it, assuming OpenCV is correctly installed, use the following command Here is a code explanation : -Retina definition is present in the contrib package and a simple include allows to use it +Retina definition is present in the bioinspired package and a simple include allows to use it. You can rather use the specific header : *opencv2/bioinspired.hpp* if you prefer but then include the other required openv modules : *opencv2/core.hpp* and *opencv2/highgui.hpp* .. code-block:: cpp @@ -225,72 +231,71 @@ Once all input parameters are processed, a first image should have been loaded, return -1; } -Now, everything is ready to run the retina model. I propose here to allocate a retina instance and to manage the eventual log sampling option. The Retina constructor expects at least a cv::Size object that shows the input data size that will have to be managed. One can activate other options such as color and its related color multiplexing strategy (here Bayer multiplexing is chosen using enum cv::RETINA_COLOR_BAYER). If using log sampling, the image reduction factor (smaller output images) and log sampling strengh can be adjusted. +Now, everything is ready to run the retina model. I propose here to allocate a retina instance and to manage the eventual log sampling option. The Retina constructor expects at least a cv::Size object that shows the input data size that will have to be managed. One can activate other options such as color and its related color multiplexing strategy (here Bayer multiplexing is chosen using *enum cv::bioinspired::RETINA_COLOR_BAYER*). If using log sampling, the image reduction factor (smaller output images) and log sampling strengh can be adjusted. .. code-block:: cpp - // pointer to a retina object - cv::Ptr myRetina; - - // if the last parameter is 'log', then activate log sampling (favour foveal vision and subsamples peripheral vision) - if (useLogSampling) - { - myRetina = new cv::Retina(inputFrame.size(), true, cv::RETINA_COLOR_BAYER, true, 2.0, 10.0); - } - else// -> else allocate "classical" retina : - myRetina = new cv::Retina(inputFrame.size()); + // pointer to a retina object + cv::Ptr myRetina; + // if the last parameter is 'log', then activate log sampling (favour foveal vision and subsamples peripheral vision) + if (useLogSampling) + { + myRetina = cv::bioinspired::createRetina(inputFrame.size(), true, cv::bioinspired::RETINA_COLOR_BAYER, true, 2.0, 10.0); + } + else// -> else allocate "classical" retina : + myRetina = cv::bioinspired::createRetina(inputFrame.size()); Once done, the proposed code writes a default xml file that contains the default parameters of the retina. This is useful to make your own config using this template. Here generated template xml file is called *RetinaDefaultParameters.xml*. .. code-block:: cpp - // save default retina parameters file in order to let you see this and maybe modify it and reload using method "setup" - myRetina->write("RetinaDefaultParameters.xml"); + // save default retina parameters file in order to let you see this and maybe modify it and reload using method "setup" + myRetina->write("RetinaDefaultParameters.xml"); In the following line, the retina attempts to load another xml file called *RetinaSpecificParameters.xml*. If you created it and introduced your own setup, it will be loaded, in the other case, default retina parameters are used. .. code-block:: cpp - // load parameters if file exists - myRetina->setup("RetinaSpecificParameters.xml"); + // load parameters if file exists + myRetina->setup("RetinaSpecificParameters.xml"); It is not required here but just to show it is possible, you can reset the retina buffers to zero to force it to forget past events. .. code-block:: cpp - // reset all retina buffers (imagine you close your eyes for a long time) - myRetina->clearBuffers(); + // reset all retina buffers (imagine you close your eyes for a long time) + myRetina->clearBuffers(); Now, it is time to run the retina ! First create some output buffers ready to receive the two retina channels outputs .. code-block:: cpp - // declare retina output buffers - cv::Mat retinaOutput_parvo; - cv::Mat retinaOutput_magno; + // declare retina output buffers + cv::Mat retinaOutput_parvo; + cv::Mat retinaOutput_magno; Then, run retina in a loop, load new frames from video sequence if necessary and get retina outputs back to dedicated buffers. .. code-block:: cpp - // processing loop with no stop condition - while(true) - { - // if using video stream, then, grabbing a new frame, else, input remains the same - if (videoCapture.isOpened()) - videoCapture>>inputFrame; + // processing loop with no stop condition + while(true) + { + // if using video stream, then, grabbing a new frame, else, input remains the same + if (videoCapture.isOpened()) + videoCapture>>inputFrame; - // run retina filter on the loaded input frame - myRetina->run(inputFrame); - // Retrieve and display retina output - myRetina->getParvo(retinaOutput_parvo); - myRetina->getMagno(retinaOutput_magno); - cv::imshow("retina input", inputFrame); - cv::imshow("Retina Parvo", retinaOutput_parvo); - cv::imshow("Retina Magno", retinaOutput_magno); - cv::waitKey(10); - } + // run retina filter on the loaded input frame + myRetina->run(inputFrame); + // Retrieve and display retina output + myRetina->getParvo(retinaOutput_parvo); + myRetina->getMagno(retinaOutput_magno); + cv::imshow("retina input", inputFrame); + cv::imshow("Retina Parvo", retinaOutput_parvo); + cv::imshow("Retina Magno", retinaOutput_magno); + cv::waitKey(10); + } That's done ! But if you want to secure the system, take care and manage Exceptions. The retina can throw some when it sees irrelevant data (no input frame, wrong setup, etc.). Then, i recommend to surround all the retina code by a try/catch system like this : @@ -323,29 +328,28 @@ Once done open the configuration file *RetinaDefaultParameters.xml* generated by .. code-block:: cpp - - - - 1 - 1 - 7.0e-01 - 5.0e-01 - 5.3e-01 - 0. - 1. - 7. - 7.0e-01 - - 1 - 0. - 0. - 7. - 1.2e+00 - 9.5e-01 - 0. - 7. - - + + + + 1 + 1 + 7.5e-01 + 9.0e-01 + 5.7e-01 + 0.01 + 0.5 + 7. + 7.5e-01 + + 1 + 0. + 0. + 7. + 2.0e+00 + 9.5e-01 + 0. + 7. + Here are some hints but actually, the best parameter setup depends more on what you want to do with the retina rather than the images input that you give to retina. Apart from the more specific case of High Dynamic Range images (HDR) that require more specific setup for specific luminance compression objective, the retina behaviors should be rather stable from content to content. Note that OpenCV is able to manage such HDR format thanks to the OpenEXR images compatibility. @@ -381,7 +385,7 @@ This parameter set tunes the neural network connected to the photo-receptors, th * **horizontalCellsGain** here is a critical parameter ! If you are not interested by the mean luminance and focus on details enhancement, then, set to zero. But if you want to keep some environment luminance data, let some low spatial frequencies pass into the system and set a higher value (<1). -* **hcellsTemporalConstant** similar to photo-receptors, this acts on the temporal constant of a low pass temporal filter that smooths input data. Here, a high value generates a high retina after effect while a lower value makes the retina more reactive. +* **hcellsTemporalConstant** similar to photo-receptors, this acts on the temporal constant of a low pass temporal filter that smooths input data. Here, a high value generates a high retina after effect while a lower value makes the retina more reactive. This value should be lower than **photoreceptorsTemporalConstant** to limit strong retina after effects. * **hcellsSpatialConstant** is the spatial constant of the low pass filter of these cells filter. It specifies the lowest spatial frequency allowed in the following. Visually, a high value leads to very low spatial frequencies processing and leads to salient halo effects. Lower values reduce this effect but the limit is : do not go lower than the value of **photoreceptorsSpatialConstant**. Those 2 parameters actually specify the spatial band-pass of the retina. diff --git a/doc/tutorials/bioinspired/retina_model/retina_model.rst~ b/doc/tutorials/bioinspired/retina_model/retina_model.rst~ new file mode 100644 index 0000000000..50bdcbb629 --- /dev/null +++ b/doc/tutorials/bioinspired/retina_model/retina_model.rst~ @@ -0,0 +1,418 @@ +.. _Retina_Model: + +Discovering the human retina and its use for image processing +************************************************************* + +Goal +===== + +I present here a model of human retina that shows some interesting properties for image preprocessing and enhancement. +In this tutorial you will learn how to: + +.. container:: enumeratevisibleitemswithsquare + + + discover the main two channels outing from your retina + + + see the basics to use the retina model + + + discover some parameters tweaks + + +General overview +================ + +The proposed model originates from Jeanny Herault's research [herault2010]_ at `Gipsa `_. It is involved in image processing applications with `Listic `_ (code maintainer and user) lab. This is not a complete model but it already present interesting properties that can be involved for enhanced image processing experience. The model allows the following human retina properties to be used : + +* spectral whitening that has 3 important effects: high spatio-temporal frequency signals canceling (noise), mid-frequencies details enhancement and low frequencies luminance energy reduction. This *all in one* property directly allows visual signals cleaning of classical undesired distortions introduced by image sensors and input luminance range. + +* local logarithmic luminance compression allows details to be enhanced even in low light conditions. + +* decorrelation of the details information (Parvocellular output channel) and transient information (events, motion made available at the Magnocellular output channel). + +The first two points are illustrated below : + +In the figure below, the OpenEXR image sample *CrissyField.exr*, a High Dynamic Range image is shown. In order to make it visible on this web-page, the original input image is linearly rescaled to the classical image luminance range [0-255] and is converted to 8bit/channel format. Such strong conversion hides many details because of too strong local contrasts. Furthermore, noise energy is also strong and pollutes visual information. + +.. image:: images/retina_TreeHdr_small.jpg + :alt: A High dynamic range image linearly rescaled within range [0-255]. + :align: center + +In the following image, applying the ideas proposed in [benoit2010]_, as your retina does, local luminance adaptation, spatial noise removal and spectral whitening work together and transmit accurate information on lower range 8bit data channels. On this picture, noise in significantly removed, local details hidden by strong luminance contrasts are enhanced. Output image keeps its naturalness and visual content is enhanced. Color processing is based on the color multiplexing/demultiplexing method proposed in [chaix2007]_. + +.. image:: images/retina_TreeHdr_retina.jpg + :alt: A High dynamic range image compressed within range [0-255] using the retina. + :align: center + + +*Note :* image sample can be downloaded from the `OpenEXR website `_. Regarding this demonstration, before retina processing, input image has been linearly rescaled within 0-255 keeping its channels float format. 5% of its histogram ends has been cut (mostly removes wrong HDR pixels). Check out the sample *opencv/samples/cpp/OpenEXRimages_HighDynamicRange_Retina_toneMapping.cpp* for similar processing. The following demonstration will only consider classical 8bit/channel images. + +The retina model output channels +================================ + +The retina model presents two outputs that benefit from the above cited behaviors. + +* The first one is called the Parvocellular channel. It is mainly active in the foveal retina area (high resolution central vision with color sensitive photo-receptors), its aim is to provide accurate color vision for visual details remaining static on the retina. On the other hand objects moving on the retina projection are blurred. + +* The second well known channel is the Magnocellular channel. It is mainly active in the retina peripheral vision and send signals related to change events (motion, transient events, etc.). These outing signals also help visual system to focus/center retina on 'transient'/moving areas for more detailed analysis thus improving visual scene context and object classification. + +**NOTE :** regarding the proposed model, contrary to the real retina, we apply these two channels on the entire input images using the same resolution. This allows enhanced visual details and motion information to be extracted on all the considered images... but remember, that these two channels are complementary. For example, if Magnocellular channel gives strong energy in an area, then, the Parvocellular channel is certainly blurred there since there is a transient event. + +As an illustration, we apply in the following the retina model on a webcam video stream of a dark visual scene. In this visual scene, captured in an amphitheater of the university, some students are moving while talking to the teacher. + +In this video sequence, because of the dark ambiance, signal to noise ratio is low and color artifacts are present on visual features edges because of the low quality image capture tool-chain. + +.. image:: images/studentsSample_input.jpg + :alt: an input video stream extract sample + :align: center + +Below is shown the retina foveal vision applied on the entire image. In the used retina configuration, global luminance is preserved and local contrasts are enhanced. Also, signal to noise ratio is improved : since high frequency spatio-temporal noise is reduced, enhanced details are not corrupted by any enhanced noise. + +.. image:: images/studentsSample_parvo.jpg + :alt: the retina Parvocellular output. Enhanced details, luminance adaptation and noise removal. A processing tool for image analysis. + :align: center + +Below is the output of the Magnocellular output of the retina model. Its signals are strong where transient events occur. Here, a student is moving at the bottom of the image thus generating high energy. The remaining of the image is static however, it is corrupted by a strong noise. Here, the retina filters out most of the noise thus generating low false motion area 'alarms'. This channel can be used as a transient/moving areas detector : it would provide relevant information for a low cost segmentation tool that would highlight areas in which an event is occurring. + +.. image:: images/studentsSample_magno.jpg + :alt: the retina Magnocellular output. Enhanced transient signals (motion, etc.). A preprocessing tool for event detection. + :align: center + +Retina use case +=============== + +This model can be used basically for spatio-temporal video effects but also in the aim of : + +* performing texture analysis with enhanced signal to noise ratio and enhanced details robust against input images luminance ranges (check out the Parvocellular retina channel output) + +* performing motion analysis also taking benefit of the previously cited properties. + +Literature +========== +For more information, refer to the following papers : + +.. [benoit2010] Benoit A., Caplier A., Durette B., Herault, J., "Using Human Visual System Modeling For Bio-Inspired Low Level Image Processing", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773. DOI + +* Please have a look at the reference work of Jeanny Herault that you can read in his book : + +.. [herault2010] Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. + +This retina filter code includes the research contributions of phd/research collegues from which code has been redrawn by the author : + +* take a look at the *retinacolor.hpp* module to discover Brice Chaix de Lavarene phD color mosaicing/demosaicing and his reference paper: + +.. [chaix2007] B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 + +* take a look at *imagelogpolprojection.hpp* to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. More informations in the above cited Jeanny Heraults's book. + +Code tutorial +============= + +Please refer to the original tutorial source code in file *opencv_folder/samples/cpp/tutorial_code/bioinspired/retina_tutorial.cpp*. + +**Note :** do not forget that the retina model is included in the following namespace : *cv::bioinspired*. + +To compile it, assuming OpenCV is correctly installed, use the following command. It requires the opencv_core *(cv::Mat and friends objects management)*, opencv_highgui *(display and image/video read)* and opencv_bioinspired *(Retina description)* libraries to compile. + +.. code-block:: cpp + + // compile + gcc retina_tutorial.cpp -o Retina_tuto -lopencv_core -lopencv_highgui -lopencv_bioinspired + + // Run commands : add 'log' as a last parameter to apply a spatial log sampling (simulates retina sampling) + // run on webcam + ./Retina_tuto -video + // run on video file + ./Retina_tuto -video myVideo.avi + // run on an image + ./Retina_tuto -image myPicture.jpg + // run on an image with log sampling + ./Retina_tuto -image myPicture.jpg log + +Here is a code explanation : + +Retina definition is present in the bioinspired package and a simple include allows to use it. You can rather use the specific header : *opencv2/bioinspired.hpp* if you prefer but then include the other required openv modules : *opencv2/core.hpp* and *opencv2/highgui.hpp* + +.. code-block:: cpp + + #include "opencv2/opencv.hpp" + +Provide user some hints to run the program with a help function + +.. code-block:: cpp + + // the help procedure + static void help(std::string errorMessage) + { + std::cout<<"Program init error : "< you can use this to fine tune parameters and load them if you save to file 'RetinaSpecificParameters.xml'"<= 3) + { + std::cout<<"RetinaDemo: processing image "<>inputFrame; + }else + { + // bad command parameter + help("bad command parameter"); + return -1; + } + +Once all input parameters are processed, a first image should have been loaded, if not, display error and stop program : + +.. code-block:: cpp + + if (inputFrame.empty()) + { + help("Input media could not be loaded, aborting"); + return -1; + } + +Now, everything is ready to run the retina model. I propose here to allocate a retina instance and to manage the eventual log sampling option. The Retina constructor expects at least a cv::Size object that shows the input data size that will have to be managed. One can activate other options such as color and its related color multiplexing strategy (here Bayer multiplexing is chosen using *enum cv::bioinspired::RETINA_COLOR_BAYER*). If using log sampling, the image reduction factor (smaller output images) and log sampling strengh can be adjusted. + +.. code-block:: cpp + + // pointer to a retina object + cv::Ptr myRetina; + + // if the last parameter is 'log', then activate log sampling (favour foveal vision and subsamples peripheral vision) + if (useLogSampling) + { + myRetina = cv::bioinspired::createRetina(inputFrame.size(), true, cv::bioinspired::RETINA_COLOR_BAYER, true, 2.0, 10.0); + } + else// -> else allocate "classical" retina : + myRetina = cv::bioinspired::createRetina(inputFrame.size()); + +Once done, the proposed code writes a default xml file that contains the default parameters of the retina. This is useful to make your own config using this template. Here generated template xml file is called *RetinaDefaultParameters.xml*. + +.. code-block:: cpp + + // save default retina parameters file in order to let you see this and maybe modify it and reload using method "setup" + myRetina->write("RetinaDefaultParameters.xml"); + +In the following line, the retina attempts to load another xml file called *RetinaSpecificParameters.xml*. If you created it and introduced your own setup, it will be loaded, in the other case, default retina parameters are used. + +.. code-block:: cpp + + // load parameters if file exists + myRetina->setup("RetinaSpecificParameters.xml"); + +It is not required here but just to show it is possible, you can reset the retina buffers to zero to force it to forget past events. + +.. code-block:: cpp + + // reset all retina buffers (imagine you close your eyes for a long time) + myRetina->clearBuffers(); + +Now, it is time to run the retina ! First create some output buffers ready to receive the two retina channels outputs + +.. code-block:: cpp + + // declare retina output buffers + cv::Mat retinaOutput_parvo; + cv::Mat retinaOutput_magno; + +Then, run retina in a loop, load new frames from video sequence if necessary and get retina outputs back to dedicated buffers. + +.. code-block:: cpp + + // processing loop with no stop condition + while(true) + { + // if using video stream, then, grabbing a new frame, else, input remains the same + if (videoCapture.isOpened()) + videoCapture>>inputFrame; + + // run retina filter on the loaded input frame + myRetina->run(inputFrame); + // Retrieve and display retina output + myRetina->getParvo(retinaOutput_parvo); + myRetina->getMagno(retinaOutput_magno); + cv::imshow("retina input", inputFrame); + cv::imshow("Retina Parvo", retinaOutput_parvo); + cv::imshow("Retina Magno", retinaOutput_magno); + cv::waitKey(10); + } + +That's done ! But if you want to secure the system, take care and manage Exceptions. The retina can throw some when it sees irrelevant data (no input frame, wrong setup, etc.). +Then, i recommend to surround all the retina code by a try/catch system like this : + +.. code-block:: cpp + + try{ + // pointer to a retina object + cv::Ptr myRetina; + [---] + // processing loop with no stop condition + while(true) + { + [---] + } + + }catch(cv::Exception e) + { + std::cerr<<"Error using Retina : "< + +Once done open the configuration file *RetinaDefaultParameters.xml* generated by the demo and let's have a look at it. + +.. code-block:: cpp + + + + + 1 + 1 + 7.5e-01 + 9.0e-01 + 5.7e-01 + 0.01 + 0.5 + 7. + 7.5e-01 + + 1 + 0. + 0. + 7. + 2.0e+00 + 9.5e-01 + 0. + 7. + + +Here are some hints but actually, the best parameter setup depends more on what you want to do with the retina rather than the images input that you give to retina. Apart from the more specific case of High Dynamic Range images (HDR) that require more specific setup for specific luminance compression objective, the retina behaviors should be rather stable from content to content. Note that OpenCV is able to manage such HDR format thanks to the OpenEXR images compatibility. + +Then, if the application target requires details enhancement prior to specific image processing, you need to know if mean luminance information is required or not. If not, the the retina can cancel or significantly reduce its energy thus giving more visibility to higher spatial frequency details. + + +Basic parameters +---------------- + +The most simple parameters are the following : + +* **colorMode** : let the retina process color information (if 1) or gray scale images (if 0). In this last case, only the first channel of the input will be processed. + +* **normaliseOutput** : each channel has this parameter, if value is 1, then the considered channel output is rescaled between 0 and 255. Take care in this case at the Magnocellular output level (motion/transient channel detection). Residual noise will also be rescaled ! + +**Note :** using color requires color channels multiplexing/demultipexing which requires more processing. You can expect much faster processing using gray levels : it would require around 30 product per pixel for all the retina processes and it has recently been parallelized for multicore architectures. + +Photo-receptors parameters +-------------------------- + +The following parameters act on the entry point of the retina - photo-receptors - and impact all the following processes. These sensors are low pass spatio-temporal filters that smooth temporal and spatial data and also adjust there sensitivity to local luminance thus improving details extraction and high frequency noise canceling. + +* **photoreceptorsLocalAdaptationSensitivity** between 0 and 1. Values close to 1 allow high luminance log compression effect at the photo-receptors level. Values closer to 0 give a more linear sensitivity. Increased alone, it can burn the *Parvo (details channel)* output image. If adjusted in collaboration with **ganglionCellsSensitivity** images can be very contrasted whatever the local luminance there is... at the price of a naturalness decrease. + +* **photoreceptorsTemporalConstant** this setups the temporal constant of the low pass filter effect at the entry of the retina. High value lead to strong temporal smoothing effect : moving objects are blurred and can disappear while static object are favored. But when starting the retina processing, stable state is reached lately. + +* **photoreceptorsSpatialConstant** specifies the spatial constant related to photo-receptors low pass filter effect. This parameters specify the minimum allowed spatial signal period allowed in the following. Typically, this filter should cut high frequency noise. Then a 0 value doesn't cut anything noise while higher values start to cut high spatial frequencies and more and more lower frequencies... Then, do not go to high if you wanna see some details of the input images ! A good compromise for color images is 0.53 since this won't affect too much the color spectrum. Higher values would lead to gray and blurred output images. + +Horizontal cells parameters +--------------------------- + +This parameter set tunes the neural network connected to the photo-receptors, the horizontal cells. It modulates photo-receptors sensitivity and completes the processing for final spectral whitening (part of the spatial band pass effect thus favoring visual details enhancement). + +* **horizontalCellsGain** here is a critical parameter ! If you are not interested by the mean luminance and focus on details enhancement, then, set to zero. But if you want to keep some environment luminance data, let some low spatial frequencies pass into the system and set a higher value (<1). + +* **hcellsTemporalConstant** similar to photo-receptors, this acts on the temporal constant of a low pass temporal filter that smooths input data. Here, a high value generates a high retina after effect while a lower value makes the retina more reactive. This value should be lower than **photoreceptorsTemporalConstant** to limit strong retina after effects. + +* **hcellsSpatialConstant** is the spatial constant of the low pass filter of these cells filter. It specifies the lowest spatial frequency allowed in the following. Visually, a high value leads to very low spatial frequencies processing and leads to salient halo effects. Lower values reduce this effect but the limit is : do not go lower than the value of **photoreceptorsSpatialConstant**. Those 2 parameters actually specify the spatial band-pass of the retina. + +**NOTE** after the processing managed by the previous parameters, input data is cleaned from noise and luminance in already partly enhanced. The following parameters act on the last processing stages of the two outing retina signals. + +Parvo (details channel) dedicated parameter +------------------------------------------- + +* **ganglionCellsSensitivity** specifies the strength of the final local adaptation occurring at the output of this details dedicated channel. Parameter values remain between 0 and 1. Low value tend to give a linear response while higher values enforces the remaining low contrasted areas. + +**Note :** this parameter can correct eventual burned images by favoring low energetic details of the visual scene, even in bright areas. + +IPL Magno (motion/transient channel) parameters +----------------------------------------------- + +Once image information is cleaned, this channel acts as a high pass temporal filter that only selects signals related to transient signals (events, motion, etc.). A low pass spatial filter smooths extracted transient data and a final logarithmic compression enhances low transient events thus enhancing event sensitivity. + +* **parasolCells_beta** generally set to zero, can be considered as an amplifier gain at the entry point of this processing stage. Generally set to 0. + +* **parasolCells_tau** the temporal smoothing effect that can be added + +* **parasolCells_k** the spatial constant of the spatial filtering effect, set it at a high value to favor low spatial frequency signals that are lower subject to residual noise. + +* **amacrinCellsTemporalCutFrequency** specifies the temporal constant of the high pass filter. High values let slow transient events to be selected. + +* **V0CompressionParameter** specifies the strength of the log compression. Similar behaviors to previous description but here it enforces sensitivity of transient events. + +* **localAdaptintegration_tau** generally set to 0, no real use here actually + +* **localAdaptintegration_k** specifies the size of the area on which local adaptation is performed. Low values lead to short range local adaptation (higher sensitivity to noise), high values secure log compression. diff --git a/doc/tutorials/contrib/table_of_content_contrib/images/retina_TreeHdr_small.jpg b/doc/tutorials/bioinspired/table_of_content_bioinspired/images/retina_TreeHdr_small.jpg similarity index 100% rename from doc/tutorials/contrib/table_of_content_contrib/images/retina_TreeHdr_small.jpg rename to doc/tutorials/bioinspired/table_of_content_bioinspired/images/retina_TreeHdr_small.jpg diff --git a/doc/tutorials/bioinspired/table_of_content_bioinspired/table_of_content_bioinspired.rst b/doc/tutorials/bioinspired/table_of_content_bioinspired/table_of_content_bioinspired.rst new file mode 100644 index 0000000000..88869e98f9 --- /dev/null +++ b/doc/tutorials/bioinspired/table_of_content_bioinspired/table_of_content_bioinspired.rst @@ -0,0 +1,36 @@ +.. _Table-Of-Content-Bioinspired: + +*bioinspired* module. Algorithms inspired from biological models +---------------------------------------------------------------- + +Here you will learn how to use additional modules of OpenCV defined in the "bioinspired" module. + + .. include:: ../../definitions/tocDefinitions.rst + ++ + .. tabularcolumns:: m{100pt} m{300pt} + .. cssclass:: toctableopencv + + =============== ====================================================== + |RetinaDemoImg| **Title:** :ref:`Retina_Model` + + *Compatibility:* > OpenCV 2.4 + + *Author:* |Author_AlexB| + + You will learn how to process images and video streams with a model of retina filter for details enhancement, spatio-temporal noise removal, luminance correction and spatio-temporal events detection. + + =============== ====================================================== + + .. |RetinaDemoImg| image:: images/retina_TreeHdr_small.jpg + :height: 90pt + :width: 90pt + + .. raw:: latex + + \pagebreak + +.. toctree:: + :hidden: + + ../retina_model/retina_model diff --git a/doc/tutorials/contrib/table_of_content_contrib/table_of_content_contrib.rst b/doc/tutorials/bioinspired/table_of_content_bioinspired/table_of_content_bioinspired.rst~ similarity index 100% rename from doc/tutorials/contrib/table_of_content_contrib/table_of_content_contrib.rst rename to doc/tutorials/bioinspired/table_of_content_bioinspired/table_of_content_bioinspired.rst~ diff --git a/doc/tutorials/calib3d/camera_calibration/camera_calibration.rst b/doc/tutorials/calib3d/camera_calibration/camera_calibration.rst index 77723b2b8b..2cf00f42a9 100644 --- a/doc/tutorials/calib3d/camera_calibration/camera_calibration.rst +++ b/doc/tutorials/calib3d/camera_calibration/camera_calibration.rst @@ -3,42 +3,42 @@ Camera calibration With OpenCV ****************************** -Cameras have been around for a long-long time. However, with the introduction of the cheap *pinhole* cameras in the late 20th century, they became a common occurrence in our everyday life. Unfortunately, this cheapness comes with its price: significant distortion. Luckily, these are constants and with a calibration and some remapping we can correct this. Furthermore, with calibration you may also determinate the relation between the camera's natural units (pixels) and the real world units (for example millimeters). +Cameras have been around for a long-long time. However, with the introduction of the cheap *pinhole* cameras in the late 20th century, they became a common occurrence in our everyday life. Unfortunately, this cheapness comes with its price: significant distortion. Luckily, these are constants and with a calibration and some remapping we can correct this. Furthermore, with calibration you may also determine the relation between the camera's natural units (pixels) and the real world units (for example millimeters). Theory ====== -For the distortion OpenCV takes into account the radial and tangential factors. For the radial one uses the following formula: +For the distortion OpenCV takes into account the radial and tangential factors. For the radial factor one uses the following formula: .. math:: x_{corrected} = x( 1 + k_1 r^2 + k_2 r^4 + k_3 r^6) \\ y_{corrected} = y( 1 + k_1 r^2 + k_2 r^4 + k_3 r^6) -So for an old pixel point at :math:`(x,y)` coordinate in the input image, for a corrected output image its position will be :math:`(x_{corrected} y_{corrected})` . The presence of the radial distortion manifests in form of the "barrel" or "fish-eye" effect. +So for an old pixel point at :math:`(x,y)` coordinates in the input image, its position on the corrected output image will be :math:`(x_{corrected} y_{corrected})`. The presence of the radial distortion manifests in form of the "barrel" or "fish-eye" effect. -Tangential distortion occurs because the image taking lenses are not perfectly parallel to the imaging plane. Correcting this is made via the formulas: +Tangential distortion occurs because the image taking lenses are not perfectly parallel to the imaging plane. It can be corrected via the formulas: .. math:: x_{corrected} = x + [ 2p_1xy + p_2(r^2+2x^2)] \\ y_{corrected} = y + [ p_1(r^2+ 2y^2)+ 2p_2xy] -So we have five distortion parameters, which in OpenCV are organized in a 5 column one row matrix: +So we have five distortion parameters which in OpenCV are presented as one row matrix with 5 columns: .. math:: Distortion_{coefficients}=(k_1 \hspace{10pt} k_2 \hspace{10pt} p_1 \hspace{10pt} p_2 \hspace{10pt} k_3) -Now for the unit conversion, we use the following formula: +Now for the unit conversion we use the following formula: .. math:: \left [ \begin{matrix} x \\ y \\ w \end{matrix} \right ] = \left [ \begin{matrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{matrix} \right ] \left [ \begin{matrix} X \\ Y \\ Z \end{matrix} \right ] -Here the presence of the :math:`w` is cause we use a homography coordinate system (and :math:`w=Z`). The unknown parameters are :math:`f_x` and :math:`f_y` (camera focal lengths) and :math:`(c_x, c_y)` what are the optical centers expressed in pixels coordinates. If for both axes a common focal length is used with a given :math:`a` aspect ratio (usually 1), then :math:`f_y=f_x*a` and in the upper formula we will have a single :math:`f` focal length. The matrix containing these four parameters is referred to as the *camera matrix*. While the distortion coefficients are the same regardless of the camera resolutions used, these should be scaled along with the current resolution from the calibrated resolution. +Here the presence of :math:`w` is explained by the use of homography coordinate system (and :math:`w=Z`). The unknown parameters are :math:`f_x` and :math:`f_y` (camera focal lengths) and :math:`(c_x, c_y)` which are the optical centers expressed in pixels coordinates. If for both axes a common focal length is used with a given :math:`a` aspect ratio (usually 1), then :math:`f_y=f_x*a` and in the upper formula we will have a single focal length :math:`f`. The matrix containing these four parameters is referred to as the *camera matrix*. While the distortion coefficients are the same regardless of the camera resolutions used, these should be scaled along with the current resolution from the calibrated resolution. -The process of determining these two matrices is the calibration. Calculating these parameters is done by some basic geometrical equations. The equations used depend on the calibrating objects used. Currently OpenCV supports three types of object for calibration: +The process of determining these two matrices is the calibration. Calculation of these parameters is done through basic geometrical equations. The equations used depend on the chosen calibrating objects. Currently OpenCV supports three types of objects for calibration: .. container:: enumeratevisibleitemswithsquare @@ -46,7 +46,7 @@ The process of determining these two matrices is the calibration. Calculating th + Symmetrical circle pattern + Asymmetrical circle pattern -Basically, you need to take snapshots of these patterns with your camera and let OpenCV find them. Each found pattern equals in a new equation. To solve the equation you need at least a predetermined number of pattern snapshots to form a well-posed equation system. This number is higher for the chessboard pattern and less for the circle ones. For example, in theory the chessboard one requires at least two. However, in practice we have a good amount of noise present in our input images, so for good results you will probably want at least 10 good snapshots of the input pattern in different position. +Basically, you need to take snapshots of these patterns with your camera and let OpenCV find them. Each found pattern results in a new equation. To solve the equation you need at least a predetermined number of pattern snapshots to form a well-posed equation system. This number is higher for the chessboard pattern and less for the circle ones. For example, in theory the chessboard pattern requires at least two snapshots. However, in practice we have a good amount of noise present in our input images, so for good results you will probably need at least 10 good snapshots of the input pattern in different positions. Goal ==== @@ -55,19 +55,19 @@ The sample application will: .. container:: enumeratevisibleitemswithsquare - + Determinate the distortion matrix - + Determinate the camera matrix - + Input from Camera, Video and Image file list - + Configuration from XML/YAML file + + Determine the distortion matrix + + Determine the camera matrix + + Take input from Camera, Video and Image file list + + Read configuration from XML/YAML file + Save the results into XML/YAML file + Calculate re-projection error Source code =========== -You may also find the source code in the :file:`samples/cpp/tutorial_code/calib3d/camera_calibration/` folder of the OpenCV source library or :download:`download it from here <../../../../samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp>`. The program has a single argument. The name of its configuration file. If none given it will try to open the one named "default.xml". :download:`Here's a sample configuration file <../../../../samples/cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml>` in XML format. In the configuration file you may choose to use as input a camera, a video file or an image list. If you opt for the later one, you need to create a configuration file where you enumerate the images to use. Here's :download:`an example of this <../../../../samples/cpp/tutorial_code/calib3d/camera_calibration/VID5.xml>`. The important part to remember is that the images needs to be specified using the absolute path or the relative one from your applications working directory. You may find all this in the beforehand mentioned directory. +You may also find the source code in the :file:`samples/cpp/tutorial_code/calib3d/camera_calibration/` folder of the OpenCV source library or :download:`download it from here <../../../../samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp>`. The program has a single argument: the name of its configuration file. If none is given then it will try to open the one named "default.xml". :download:`Here's a sample configuration file <../../../../samples/cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml>` in XML format. In the configuration file you may choose to use camera as an input, a video file or an image list. If you opt for the last one, you will need to create a configuration file where you enumerate the images to use. Here's :download:`an example of this <../../../../samples/cpp/tutorial_code/calib3d/camera_calibration/VID5.xml>`. The important part to remember is that the images need to be specified using the absolute path or the relative one from your application's working directory. You may find all this in the samples directory mentioned above. -The application starts up with reading the settings from the configuration file. Although, this is an important part of it, it has nothing to do with the subject of this tutorial: *camera calibration*. Therefore, I've chosen to do not post here the code part for that. The technical background on how to do this you can find in the :ref:`fileInputOutputXMLYAML` tutorial. +The application starts up with reading the settings from the configuration file. Although, this is an important part of it, it has nothing to do with the subject of this tutorial: *camera calibration*. Therefore, I've chosen not to post the code for that part here. Technical background on how to do this you can find in the :ref:`fileInputOutputXMLYAML` tutorial. Explanation =========== @@ -93,9 +93,9 @@ Explanation return -1; } - For this I've used simple OpenCV class input operation. After reading the file I've an additional post-process function that checks for the validity of the input. Only if all of them are good will be the *goodInput* variable true. + For this I've used simple OpenCV class input operation. After reading the file I've an additional post-processing function that checks validity of the input. Only if all inputs are good then *goodInput* variable will be true. -#. **Get next input, if it fails or we have enough of them calibrate**. After this we have a big loop where we do the following operations: get the next image from the image list, camera or video file. If this fails or we have enough images we run the calibration process. In case of image we step out of the loop and otherwise the remaining frames will be undistorted (if the option is set) via changing from *DETECTION* mode to *CALIBRATED* one. +#. **Get next input, if it fails or we have enough of them - calibrate**. After this we have a big loop where we do the following operations: get the next image from the image list, camera or video file. If this fails or we have enough images then we run the calibration process. In case of image we step out of the loop and otherwise the remaining frames will be undistorted (if the option is set) via changing from *DETECTION* mode to the *CALIBRATED* one. .. code-block:: cpp @@ -125,7 +125,7 @@ Explanation For some cameras we may need to flip the input image. Here we do this too. -#. **Find the pattern in the current input**. The formation of the equations I mentioned above consists of finding the major patterns in the input: in case of the chessboard this is their corners of the squares and for the circles, well, the circles itself. The position of these will form the result and is collected into the *pointBuf* vector. +#. **Find the pattern in the current input**. The formation of the equations I mentioned above aims to finding major patterns in the input: in case of the chessboard this are corners of the squares and for the circles, well, the circles themselves. The position of these will form the result which will be written into the *pointBuf* vector. .. code-block:: cpp @@ -146,9 +146,9 @@ Explanation break; } - Depending on the type of the input pattern you use either the :calib3d:`findChessboardCorners ` or the :calib3d:`findCirclesGrid ` function. For both of them you pass on the current image, the size of the board and you'll get back the positions of the patterns. Furthermore, they return a boolean variable that states if in the input we could find or not the pattern (we only need to take into account images where this is true!). + Depending on the type of the input pattern you use either the :calib3d:`findChessboardCorners ` or the :calib3d:`findCirclesGrid ` function. For both of them you pass the current image and the size of the board and you'll get the positions of the patterns. Furthermore, they return a boolean variable which states if the pattern was found in the input (we only need to take into account those images where this is true!). - Then again in case of cameras we only take camera images after an input delay time passed. This is in order to allow for the user to move the chessboard around and as getting different images. Same images mean same equations, and same equations at the calibration will form an ill-posed problem, so the calibration will fail. For square images the position of the corners are only approximate. We may improve this by calling the :feature2d:`cornerSubPix ` function. This way will get a better calibration result. After this we add a valid inputs result to the *imagePoints* vector to collect all of the equations into a single container. Finally, for visualization feedback purposes we will draw the found points on the input image with the :calib3d:`findChessboardCorners ` function. + Then again in case of cameras we only take camera images when an input delay time is passed. This is done in order to allow user moving the chessboard around and getting different images. Similar images result in similar equations, and similar equations at the calibration step will form an ill-posed problem, so the calibration will fail. For square images the positions of the corners are only approximate. We may improve this by calling the :feature2d:`cornerSubPix ` function. It will produce better calibration result. After this we add a valid inputs result to the *imagePoints* vector to collect all of the equations into a single container. Finally, for visualization feedback purposes we will draw the found points on the input image using :calib3d:`findChessboardCorners ` function. .. code-block:: cpp @@ -175,7 +175,7 @@ Explanation drawChessboardCorners( view, s.boardSize, Mat(pointBuf), found ); } -#. **Show state and result for the user, plus command line control of the application**. The showing part consists of a text output on the live feed, and for video or camera input to show the "capturing" frame we simply bitwise negate the input image. +#. **Show state and result to the user, plus command line control of the application**. This part shows text output on the image. .. code-block:: cpp @@ -199,7 +199,7 @@ Explanation if( blinkOutput ) bitwise_not(view, view); - If we only ran the calibration and got the camera matrix plus the distortion coefficients we may just as correct the image with the :imgproc_geometric:`undistort ` function: + If we ran calibration and got camera's matrix with the distortion coefficients we may want to correct the image using :imgproc_geometric:`undistort ` function: .. code-block:: cpp @@ -212,7 +212,7 @@ Explanation //------------------------------ Show image and check for input commands ------------------- imshow("Image View", view); - Then we wait for an input key and if this is *u* we toggle the distortion removal, if it is *g* we start all over the detection process (or simply start it), and finally for the *ESC* key quit the application: + Then we wait for an input key and if this is *u* we toggle the distortion removal, if it is *g* we start again the detection process, and finally for the *ESC* key we quit the application: .. code-block:: cpp @@ -229,7 +229,7 @@ Explanation imagePoints.clear(); } -#. **Show the distortion removal for the images too**. When you work with an image list it is not possible to remove the distortion inside the loop. Therefore, you must append this after the loop. Taking advantage of this now I'll expand the :imgproc_geometric:`undistort ` function, which is in fact first a call of the :imgproc_geometric:`initUndistortRectifyMap ` to find out the transformation matrices and then doing the transformation with the :imgproc_geometric:`remap ` function. Because, after a successful calibration the map calculation needs to be done only once, by using this expanded form you may speed up your application: +#. **Show the distortion removal for the images too**. When you work with an image list it is not possible to remove the distortion inside the loop. Therefore, you must do this after the loop. Taking advantage of this now I'll expand the :imgproc_geometric:`undistort ` function, which is in fact first calls :imgproc_geometric:`initUndistortRectifyMap ` to find transformation matrices and then performs transformation using :imgproc_geometric:`remap ` function. Because, after successful calibration map calculation needs to be done only once, by using this expanded form you may speed up your application: .. code-block:: cpp @@ -256,7 +256,7 @@ Explanation The calibration and save ======================== -Because the calibration needs to be only once per camera it makes sense to save them after a successful calibration. This way later on you can just load these values into your program. Due to this we first make the calibration, and if it succeeds we save the result into an OpenCV style XML or YAML file, depending on the extension you give in the configuration file. +Because the calibration needs to be done only once per camera, it makes sense to save it after a successful calibration. This way later on you can just load these values into your program. Due to this we first make the calibration, and if it succeeds we save the result into an OpenCV style XML or YAML file, depending on the extension you give in the configuration file. Therefore in the first function we just split up these two processes. Because we want to save many of the calibration variables we'll create these variables here and pass on both of them to the calibration and saving function. Again, I'll not show the saving part as that has little in common with the calibration. Explore the source file in order to find out how and what: @@ -280,7 +280,7 @@ Therefore in the first function we just split up these two processes. Because we return ok; } -We do the calibration with the help of the :calib3d:`calibrateCamera ` function. This has the following parameters: +We do the calibration with the help of the :calib3d:`calibrateCamera ` function. It has the following parameters: .. container:: enumeratevisibleitemswithsquare @@ -318,11 +318,11 @@ We do the calibration with the help of the :calib3d:`calibrateCamera ` or the :calib3d:`findCirclesGrid ` function returned. We just need to pass it on. + + The image points. This is a vector of *Point2f* vector which for each input image contains coordinates of the important points (corners for chessboard and centers of the circles for the circle pattern). We have already collected this from :calib3d:`findChessboardCorners ` or :calib3d:`findCirclesGrid ` function. We just need to pass it on. + The size of the image acquired from the camera, video file or the images. - + The camera matrix. If we used the fix aspect ratio option we need to set the :math:`f_x` to zero: + + The camera matrix. If we used the fixed aspect ratio option we need to set the :math:`f_x` to zero: .. code-block:: cpp @@ -336,16 +336,16 @@ We do the calibration with the help of the :calib3d:`calibrateCamera ` to first transform the object point to image point. Then we calculate the absolute norm between what we got with our transformation and the corner/circle finding algorithm. To find the average error we calculate the arithmetical mean of the errors calculate for all the calibration images. + + The function returns the average re-projection error. This number gives a good estimation of precision of the found parameters. This should be as close to zero as possible. Given the intrinsic, distortion, rotation and translation matrices we may calculate the error for one view by using the :calib3d:`projectPoints ` to first transform the object point to image point. Then we calculate the absolute norm between what we got with our transformation and the corner/circle finding algorithm. To find the average error we calculate the arithmetical mean of the errors calculated for all the calibration images. .. code-block:: cpp @@ -378,25 +378,25 @@ We do the calibration with the help of the :calib3d:`calibrateCamera ` that has a size of 9 X 6. I've used an AXIS IP camera to create a couple of snapshots of the board and saved it into a VID5 directory. I've put this inside the :file:`images/CameraCalibraation` folder of my working directory and created the following :file:`VID5.XML` file that describes which images to use: +Let there be :download:`this input chessboard pattern <../../../pattern.png>` which has a size of 9 X 6. I've used an AXIS IP camera to create a couple of snapshots of the board and saved it into VID5 directory. I've put this inside the :file:`images/CameraCalibration` folder of my working directory and created the following :file:`VID5.XML` file that describes which images to use: .. code-block:: xml - images/CameraCalibraation/VID5/xx1.jpg - images/CameraCalibraation/VID5/xx2.jpg - images/CameraCalibraation/VID5/xx3.jpg - images/CameraCalibraation/VID5/xx4.jpg - images/CameraCalibraation/VID5/xx5.jpg - images/CameraCalibraation/VID5/xx6.jpg - images/CameraCalibraation/VID5/xx7.jpg - images/CameraCalibraation/VID5/xx8.jpg + images/CameraCalibration/VID5/xx1.jpg + images/CameraCalibration/VID5/xx2.jpg + images/CameraCalibration/VID5/xx3.jpg + images/CameraCalibration/VID5/xx4.jpg + images/CameraCalibration/VID5/xx5.jpg + images/CameraCalibration/VID5/xx6.jpg + images/CameraCalibration/VID5/xx7.jpg + images/CameraCalibration/VID5/xx8.jpg -Then specified the :file:`images/CameraCalibraation/VID5/VID5.XML` as input in the configuration file. Here's a chessboard pattern found during the runtime of the application: +Then passed :file:`images/CameraCalibration/VID5/VID5.XML` as an input in the configuration file. Here's a chessboard pattern found during the runtime of the application: .. image:: images/fileListImage.jpg :alt: A found chessboard @@ -433,7 +433,7 @@ In both cases in the specified output XML/YAML file you'll find the camera and d -4.1802327176423804e-001 5.0715244063187526e-001 0. 0. -5.7843597214487474e-001 -Add these values as constants to your program, call the :imgproc_geometric:`initUndistortRectifyMap ` and the :imgproc_geometric:`remap ` function to remove distortion and enjoy distortion free inputs with cheap and low quality cameras. +Add these values as constants to your program, call the :imgproc_geometric:`initUndistortRectifyMap ` and the :imgproc_geometric:`remap ` function to remove distortion and enjoy distortion free inputs for cheap and low quality cameras. You may observe a runtime instance of this on the `YouTube here `_. diff --git a/doc/tutorials/calib3d/camera_calibration_square_chess/camera_calibration_square_chess.rst b/doc/tutorials/calib3d/camera_calibration_square_chess/camera_calibration_square_chess.rst index 4eff2640ad..e08550750d 100644 --- a/doc/tutorials/calib3d/camera_calibration_square_chess/camera_calibration_square_chess.rst +++ b/doc/tutorials/calib3d/camera_calibration_square_chess/camera_calibration_square_chess.rst @@ -59,4 +59,4 @@ Now, let us write a code that detects a chessboard in a new image and finds its #. Calculate reprojection error like it is done in ``calibration`` sample (see ``opencv/samples/cpp/calibration.cpp``, function ``computeReprojectionErrors``). -Question: how to calculate the distance from the camera origin to any of the corners? \ No newline at end of file +Question: how to calculate the distance from the camera origin to any of the corners? diff --git a/doc/tutorials/core/adding_images/adding_images.rst b/doc/tutorials/core/adding_images/adding_images.rst index e3135693de..3559132dc2 100644 --- a/doc/tutorials/core/adding_images/adding_images.rst +++ b/doc/tutorials/core/adding_images/adding_images.rst @@ -35,8 +35,7 @@ As usual, after the not-so-lengthy explanation, let's go to the code: .. code-block:: cpp - #include - #include + #include #include using namespace cv; diff --git a/doc/tutorials/core/basic_linear_transform/basic_linear_transform.rst b/doc/tutorials/core/basic_linear_transform/basic_linear_transform.rst index 4c2fb70358..75c2628683 100644 --- a/doc/tutorials/core/basic_linear_transform/basic_linear_transform.rst +++ b/doc/tutorials/core/basic_linear_transform/basic_linear_transform.rst @@ -72,8 +72,7 @@ Code .. code-block:: cpp - #include - #include + #include #include using namespace cv; diff --git a/doc/tutorials/core/file_input_output_with_xml_yml/file_input_output_with_xml_yml.rst b/doc/tutorials/core/file_input_output_with_xml_yml/file_input_output_with_xml_yml.rst index 87166b7cc3..42f6a60915 100644 --- a/doc/tutorials/core/file_input_output_with_xml_yml/file_input_output_with_xml_yml.rst +++ b/doc/tutorials/core/file_input_output_with_xml_yml/file_input_output_with_xml_yml.rst @@ -277,4 +277,3 @@ You may observe a runtime instance of this on the `YouTube here - diff --git a/doc/tutorials/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.rst b/doc/tutorials/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.rst index 99d6692743..9285509b07 100644 --- a/doc/tutorials/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.rst +++ b/doc/tutorials/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.rst @@ -127,6 +127,3 @@ You may observe a runtime instance of this on the `YouTube here - - - diff --git a/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.rst b/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.rst index 03d82bbd46..76c5a4541c 100644 --- a/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.rst +++ b/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.rst @@ -143,7 +143,7 @@ Although *Mat* works really well as an image container, it is also a general mat You cannot initialize the matrix values with this construction. It will only reallocate its matrix data memory if the new size will not fit into the old one. - + MATLAB style initializer: :basicstructures:`zeros() `, :basicstructures:`ones() `, ::basicstructures:`eyes() `. Specify size and data type to use: + + MATLAB style initializer: :basicstructures:`zeros() `, :basicstructures:`ones() `, :basicstructures:`eye() `. Specify size and data type to use: .. literalinclude:: ../../../../samples/cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp :language: cpp diff --git a/doc/tutorials/core/table_of_content_core/table_of_content_core.rst b/doc/tutorials/core/table_of_content_core/table_of_content_core.rst index b50d97635f..4150265d10 100644 --- a/doc/tutorials/core/table_of_content_core/table_of_content_core.rst +++ b/doc/tutorials/core/table_of_content_core/table_of_content_core.rst @@ -218,4 +218,4 @@ Here you will learn the about the basic building blocks of the library. A must r ../random_generator_and_text/random_generator_and_text ../discrete_fourier_transform/discrete_fourier_transform ../file_input_output_with_xml_yml/file_input_output_with_xml_yml - ../interoperability_with_OpenCV_1/interoperability_with_OpenCV_1 \ No newline at end of file + ../interoperability_with_OpenCV_1/interoperability_with_OpenCV_1 diff --git a/doc/tutorials/definitions/README.txt b/doc/tutorials/definitions/README.txt index 829e27cacb..a598a95dd7 100644 --- a/doc/tutorials/definitions/README.txt +++ b/doc/tutorials/definitions/README.txt @@ -1 +1 @@ -Include in this directory only defintion files. None of the reST files entered here will be parsed by the Sphinx Builder. \ No newline at end of file +Include in this directory only defintion files. None of the reST files entered here will be parsed by the Sphinx Builder. diff --git a/doc/tutorials/definitions/noContent.rst b/doc/tutorials/definitions/noContent.rst index ded9e78fa1..c2780c266d 100644 --- a/doc/tutorials/definitions/noContent.rst +++ b/doc/tutorials/definitions/noContent.rst @@ -1,3 +1,3 @@ .. note:: - Unfortunetly we have no tutorials into this section. Nevertheless, our tutorial writting team is working on it. If you have a tutorial suggestion or you have writen yourself a tutorial (or coded a sample code) that you would like to see here please contact us via our :opencv_group:`user group <>`. \ No newline at end of file + Unfortunetly we have no tutorials into this section. And you can help us with that, since OpenCV is a community effort. If you have a tutorial suggestion or you have written a tutorial yourself (or coded a sample code) that you would like to see here, please contact follow these instructions: :ref:`howToWriteTutorial` and :how_to_contribute:`How to contribute <>`. diff --git a/doc/tutorials/features2d/feature_description/feature_description.rst b/doc/tutorials/features2d/feature_description/feature_description.rst index aa1a4a88be..b6e2dfa2bd 100644 --- a/doc/tutorials/features2d/feature_description/feature_description.rst +++ b/doc/tutorials/features2d/feature_description/feature_description.rst @@ -13,7 +13,7 @@ In this tutorial you will learn how to: * Use the :descriptor_extractor:`DescriptorExtractor<>` interface in order to find the feature vector correspondent to the keypoints. Specifically: * Use :surf_descriptor_extractor:`SurfDescriptorExtractor<>` and its function :descriptor_extractor:`compute<>` to perform the required calculations. - * Use a :brute_force_matcher:`BruteForceMatcher<>` to match the features vector + * Use a :brute_force_matcher:`BFMatcher<>` to match the features vector * Use the function :draw_matches:`drawMatches<>` to draw the detected matches. @@ -69,7 +69,7 @@ This tutorial code's is shown lines below. You can also download it from `here < extractor.compute( img_2, keypoints_2, descriptors_2 ); //-- Step 3: Matching descriptor vectors with a brute force matcher - BruteForceMatcher< L2 > matcher; + BFMatcher matcher(NORM_L2); std::vector< DMatch > matches; matcher.match( descriptors_1, descriptors_2, matches ); @@ -100,6 +100,3 @@ Result .. image:: images/Feature_Description_BruteForce_Result.jpg :align: center :height: 200pt - - - diff --git a/doc/tutorials/features2d/feature_detection/feature_detection.rst b/doc/tutorials/features2d/feature_detection/feature_detection.rst index 1c9ca7cf82..02da6d0806 100644 --- a/doc/tutorials/features2d/feature_detection/feature_detection.rst +++ b/doc/tutorials/features2d/feature_detection/feature_detection.rst @@ -31,6 +31,7 @@ This tutorial code's is shown lines below. You can also download it from `here < #include "opencv2/core.hpp" #include "opencv2/features2d.hpp" #include "opencv2/highgui.hpp" + #include "opencv2/nonfree.hpp" using namespace cv; @@ -94,4 +95,3 @@ Result .. image:: images/Feature_Detection_Result_b.jpg :align: center :height: 200pt - diff --git a/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.rst b/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.rst index 9309b05c1d..9839c89841 100644 --- a/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.rst +++ b/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.rst @@ -28,6 +28,7 @@ This tutorial code's is shown lines below. You can also download it from `here < #include "opencv2/core.hpp" #include "opencv2/features2d.hpp" #include "opencv2/highgui.hpp" + #include "opencv2/nonfree.hpp" using namespace cv; @@ -85,7 +86,7 @@ This tutorial code's is shown lines below. You can also download it from `here < std::vector< DMatch > good_matches; for( int i = 0; i < descriptors_1.rows; i++ ) - { if( matches[i].distance < 2*min_dist ) + { if( matches[i].distance <= 2*min_dist ) { good_matches.push_back( matches[i]); } } @@ -127,6 +128,3 @@ Result .. image:: images/Feature_FlannMatcher_Keypoints_Result.jpg :align: center :height: 250pt - - - diff --git a/doc/tutorials/features2d/feature_homography/feature_homography.rst b/doc/tutorials/features2d/feature_homography/feature_homography.rst index 0d78229599..3040ed7d75 100644 --- a/doc/tutorials/features2d/feature_homography/feature_homography.rst +++ b/doc/tutorials/features2d/feature_homography/feature_homography.rst @@ -30,6 +30,7 @@ This tutorial code's is shown lines below. You can also download it from `here < #include "opencv2/features2d.hpp" #include "opencv2/highgui.hpp" #include "opencv2/calib3d.hpp" + #include "opencv2/nonfree.hpp" using namespace cv; @@ -145,4 +146,3 @@ Result .. image:: images/Feature_Homography_Result.jpg :align: center :height: 200pt - diff --git a/doc/tutorials/features2d/table_of_content_features2d/table_of_content_features2d.rst b/doc/tutorials/features2d/table_of_content_features2d/table_of_content_features2d.rst index cc90082b85..f4107804bb 100644 --- a/doc/tutorials/features2d/table_of_content_features2d/table_of_content_features2d.rst +++ b/doc/tutorials/features2d/table_of_content_features2d/table_of_content_features2d.rst @@ -201,4 +201,3 @@ Learn about how to use the feature points detectors, descriptors and matching f ../feature_flann_matcher/feature_flann_matcher ../feature_homography/feature_homography ../detection_of_planar_objects/detection_of_planar_objects - diff --git a/doc/tutorials/features2d/trackingmotion/corner_subpixeles/corner_subpixeles.rst b/doc/tutorials/features2d/trackingmotion/corner_subpixeles/corner_subpixeles.rst index a267b13803..4e9015cb68 100644 --- a/doc/tutorials/features2d/trackingmotion/corner_subpixeles/corner_subpixeles.rst +++ b/doc/tutorials/features2d/trackingmotion/corner_subpixeles/corner_subpixeles.rst @@ -135,4 +135,3 @@ Here is the result: .. image:: images/Corner_Subpixeles_Result.jpg :align: center - diff --git a/doc/tutorials/features2d/trackingmotion/generic_corner_detector/generic_corner_detector.rst b/doc/tutorials/features2d/trackingmotion/generic_corner_detector/generic_corner_detector.rst index 465ff216cb..d33bf3df6c 100644 --- a/doc/tutorials/features2d/trackingmotion/generic_corner_detector/generic_corner_detector.rst +++ b/doc/tutorials/features2d/trackingmotion/generic_corner_detector/generic_corner_detector.rst @@ -37,4 +37,3 @@ Result .. image:: images/My_Shi_Tomasi_corner_detector_Result.jpg :align: center - diff --git a/doc/tutorials/features2d/trackingmotion/good_features_to_track/good_features_to_track.rst b/doc/tutorials/features2d/trackingmotion/good_features_to_track/good_features_to_track.rst index 9f71e987f2..1495befc75 100644 --- a/doc/tutorials/features2d/trackingmotion/good_features_to_track/good_features_to_track.rst +++ b/doc/tutorials/features2d/trackingmotion/good_features_to_track/good_features_to_track.rst @@ -118,5 +118,3 @@ Result .. image:: images/Feature_Detection_Result_a.jpg :align: center - - diff --git a/doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.rst b/doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.rst index 0f6bb33fa8..e0e4ea47e4 100644 --- a/doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.rst +++ b/doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.rst @@ -243,5 +243,3 @@ The detected corners are surrounded by a small black circle .. image:: images/Harris_Detector_Result.jpg :align: center - - diff --git a/doc/tutorials/general/table_of_content_general/table_of_content_general.rst b/doc/tutorials/general/table_of_content_general/table_of_content_general.rst index 2a6d57ffb9..6e127a98f6 100644 --- a/doc/tutorials/general/table_of_content_general/table_of_content_general.rst +++ b/doc/tutorials/general/table_of_content_general/table_of_content_general.rst @@ -10,4 +10,3 @@ These tutorials are the bottom of the iceberg as they link together multiple of .. raw:: latex \pagebreak - diff --git a/doc/tutorials/gpu/gpu-basics-similarity/gpu-basics-similarity.rst b/doc/tutorials/gpu/gpu-basics-similarity/gpu-basics-similarity.rst index 86400bfae4..2e8fe9559b 100644 --- a/doc/tutorials/gpu/gpu-basics-similarity/gpu-basics-similarity.rst +++ b/doc/tutorials/gpu/gpu-basics-similarity/gpu-basics-similarity.rst @@ -1 +1,234 @@ -.. _gpuBasicsSimilarity: Similarity check (PNSR and SSIM) on the GPU ******************************************* Goal ==== In the :ref:`videoInputPSNRMSSIM` tutorial I already presented the PSNR and SSIM methods for checking the similarity between the two images. And as you could see there performing these takes quite some time, especially in the case of the SSIM. However, if the performance numbers of an OpenCV implementation for the CPU do not satisfy you and you happen to have an NVidia CUDA GPU device in your system all is not lost. You may try to port or write your algorithm for the video card. This tutorial will give a good grasp on how to approach coding by using the GPU module of OpenCV. As a prerequisite you should already know how to handle the core, highgui and imgproc modules. So, our goals are: .. container:: enumeratevisibleitemswithsquare + What's different compared to the CPU? + Create the GPU code for the PSNR and SSIM + Optimize the code for maximal performance The source code =============== You may also find the source code and these video file in the :file:`samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity` folder of the OpenCV source library or :download:`download it from here <../../../../samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp>`. The full source code is quite long (due to the controlling of the application via the command line arguments and performance measurement). Therefore, to avoid cluttering up these sections with those you'll find here only the functions itself. The PSNR returns a float number, that if the two inputs are similar between 30 and 50 (higher is better). .. literalinclude:: ../../../../samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp :language: cpp :linenos: :tab-width: 4 :lines: 165-210, 18-23, 210-235 The SSIM returns the MSSIM of the images. This is too a float number between zero and one (higher is better), however we have one for each channel. Therefore, we return a *Scalar* OpenCV data structure: .. literalinclude:: ../../../../samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp :language: cpp :linenos: :tab-width: 4 :lines: 235-355, 26-42, 357- How to do it? - The GPU ======================= Now as you can see we have three types of functions for each operation. One for the CPU and two for the GPU. The reason I made two for the GPU is too illustrate that often simple porting your CPU to GPU will actually make it slower. If you want some performance gain you will need to remember a few rules, whose I'm going to detail later on. The development of the GPU module was made so that it resembles as much as possible its CPU counterpart. This is to make porting easy. The first thing you need to do before writing any code is to link the GPU module to your project, and include the header file for the module. All the functions and data structures of the GPU are in a *gpu* sub namespace of the *cv* namespace. You may add this to the default one via the *use namespace* keyword, or mark it everywhere explicitly via the cv:: to avoid confusion. I'll do the later. .. code-block:: cpp #include // GPU structures and methods GPU stands for **g**\ raphics **p**\ rocessing **u**\ nit. It was originally build to render graphical scenes. These scenes somehow build on a lot of data. Nevertheless, these aren't all dependent one from another in a sequential way and as it is possible a parallel processing of them. Due to this a GPU will contain multiple smaller processing units. These aren't the state of the art processors and on a one on one test with a CPU it will fall behind. However, its strength lies in its numbers. In the last years there has been an increasing trend to harvest these massive parallel powers of the GPU in non-graphical scene rendering too. This gave birth to the general-purpose computation on graphics processing units (GPGPU). The GPU has its own memory. When you read data from the hard drive with OpenCV into a *Mat* object that takes place in your systems memory. The CPU works somehow directly on this (via its cache), however the GPU cannot. He has too transferred the information he will use for calculations from the system memory to its own. This is done via an upload process and takes time. In the end the result will have to be downloaded back to your system memory for your CPU to see it and use it. Porting small functions to GPU is not recommended as the upload/download time will be larger than the amount you gain by a parallel execution. Mat objects are stored only in the system memory (or the CPU cache). For getting an OpenCV matrix to the GPU you'll need to use its GPU counterpart :gpudatastructure:`GpuMat `. It works similar to the Mat with a 2D only limitation and no reference returning for its functions (cannot mix GPU references with CPU ones). To upload a Mat object to the GPU you need to call the upload function after creating an instance of the class. To download you may use simple assignment to a Mat object or use the download function. .. code-block:: cpp Mat I1; // Main memory item - read image into with imread for example gpu::GpuMat gI; // GPU matrix - for now empty gI1.upload(I1); // Upload a data from the system memory to the GPU memory I1 = gI1; // Download, gI1.download(I1) will work too Once you have your data up in the GPU memory you may call GPU enabled functions of OpenCV. Most of the functions keep the same name just as on the CPU, with the difference that they only accept *GpuMat* inputs. A full list of these you will find in the documentation: `online here `_ or the OpenCV reference manual that comes with the source code. Another thing to keep in mind is that not for all channel numbers you can make efficient algorithms on the GPU. Generally, I found that the input images for the GPU images need to be either one or four channel ones and one of the char or float type for the item sizes. No double support on the GPU, sorry. Passing other types of objects for some functions will result in an exception thrown, and an error message on the error output. The documentation details in most of the places the types accepted for the inputs. If you have three channel images as an input you can do two things: either adds a new channel (and use char elements) or split up the image and call the function for each image. The first one isn't really recommended as you waste memory. For some functions, where the position of the elements (neighbor items) doesn't matter quick solution is to just reshape it into a single channel image. This is the case for the PSNR implementation where for the *absdiff* method the value of the neighbors is not important. However, for the *GaussianBlur* this isn't an option and such need to use the split method for the SSIM. With this knowledge you can already make a GPU viable code (like mine GPU one) and run it. You'll be surprised to see that it might turn out slower than your CPU implementation. Optimization ============ The reason for this is that you're throwing out on the window the price for memory allocation and data transfer. And on the GPU this is damn high. Another possibility for optimization is to introduce asynchronous OpenCV GPU calls too with the help of the :gpudatastructure:`gpu::Stream`. 1. Memory allocation on the GPU is considerable. Therefore, if it’s possible allocate new memory as few times as possible. If you create a function what you intend to call multiple times it is a good idea to allocate any local parameters for the function only once, during the first call. To do this you create a data structure containing all the local variables you will use. For instance in case of the PSNR these are: .. code-block:: cpp struct BufferPSNR // Optimized GPU versions { // Data allocations are very expensive on GPU. Use a buffer to solve: allocate once reuse later. gpu::GpuMat gI1, gI2, gs, t1,t2; gpu::GpuMat buf; }; Then create an instance of this in the main program: .. code-block:: cpp BufferPSNR bufferPSNR; And finally pass this to the function each time you call it: .. code-block:: cpp double getPSNR_GPU_optimized(const Mat& I1, const Mat& I2, BufferPSNR& b) Now you access these local parameters as: *b.gI1*, *b.buf* and so on. The GpuMat will only reallocate itself on a new call if the new matrix size is different from the previous one. #. Avoid unnecessary function data transfers. Any small data transfer will be significant one once you go to the GPU. Therefore, if possible make all calculations in-place (in other words do not create new memory objects - for reasons explained at the previous point). For example, although expressing arithmetical operations may be easier to express in one line formulas, it will be slower. In case of the SSIM at one point I need to calculate: .. code-block:: cpp b.t1 = 2 * b.mu1_mu2 + C1; Although the upper call will succeed observe that there is a hidden data transfer present. Before it makes the addition it needs to store somewhere the multiplication. Therefore, it will create a local matrix in the background, add to that the *C1* value and finally assign that to *t1*. To avoid this we use the gpu functions, instead of the arithmetic operators: .. code-block:: cpp gpu::multiply(b.mu1_mu2, 2, b.t1); //b.t1 = 2 * b.mu1_mu2 + C1; gpu::add(b.t1, C1, b.t1); #. Use asynchronous calls (the :gpudatastructure:`gpu::Stream `). By default whenever you call a gpu function it will wait for the call to finish and return with the result afterwards. However, it is possible to make asynchronous calls, meaning it will call for the operation execution, make the costly data allocations for the algorithm and return back right away. Now you can call another function if you wish to do so. For the MSSIM this is a small optimization point. In our default implementation we split up the image into channels and call then for each channel the gpu functions. A small degree of parallelization is possible with the stream. By using a stream we can make the data allocation, upload operations while the GPU is already executing a given method. For example we need to upload two images. We queue these one after another and call already the function that processes it. The functions will wait for the upload to finish, however while that happens makes the output buffer allocations for the function to be executed next. .. code-block:: cpp gpu::Stream stream; stream.enqueueConvert(b.gI1, b.t1, CV_32F); // Upload gpu::split(b.t1, b.vI1, stream); // Methods (pass the stream as final parameter). gpu::multiply(b.vI1[i], b.vI1[i], b.I1_2, stream); // I1^2 Result and conclusion ===================== On an Intel P8700 laptop CPU paired with a low end NVidia GT220M here are the performance numbers: .. code-block:: cpp Time of PSNR CPU (averaged for 10 runs): 41.4122 milliseconds. With result of: 19.2506 Time of PSNR GPU (averaged for 10 runs): 158.977 milliseconds. With result of: 19.2506 Initial call GPU optimized: 31.3418 milliseconds. With result of: 19.2506 Time of PSNR GPU OPTIMIZED ( / 10 runs): 24.8171 milliseconds. With result of: 19.2506 Time of MSSIM CPU (averaged for 10 runs): 484.343 milliseconds. With result of B0.890964 G0.903845 R0.936934 Time of MSSIM GPU (averaged for 10 runs): 745.105 milliseconds. With result of B0.89922 G0.909051 R0.968223 Time of MSSIM GPU Initial Call 357.746 milliseconds. With result of B0.890964 G0.903845 R0.936934 Time of MSSIM GPU OPTIMIZED ( / 10 runs): 203.091 milliseconds. With result of B0.890964 G0.903845 R0.936934 In both cases we managed a performance increase of almost 100% compared to the CPU implementation. It may be just the improvement needed for your application to work. You may observe a runtime instance of this on the `YouTube here `_. .. raw:: html
    \ No newline at end of file +.. _gpuBasicsSimilarity: + +Similarity check (PNSR and SSIM) on the GPU +******************************************* + +Goal +==== + +In the :ref:`videoInputPSNRMSSIM` tutorial I already presented the PSNR and SSIM methods for +checking the similarity between the two images. And as you could see there performing these takes +quite some time, especially in the case of the SSIM. However, if the performance numbers of an +OpenCV implementation for the CPU do not satisfy you and you happen to have an NVidia CUDA GPU +device in your system all is not lost. You may try to port or write your algorithm for the video +card. + +This tutorial will give a good grasp on how to approach coding by using the GPU module of OpenCV. As +a prerequisite you should already know how to handle the core, highgui and imgproc modules. So, our +goals are: + +.. container:: enumeratevisibleitemswithsquare + + + What's different compared to the CPU? + + Create the GPU code for the PSNR and SSIM + + Optimize the code for maximal performance + +The source code +=============== + +You may also find the source code and these video file in the +:file:`samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity` folder of the +OpenCV source library or :download:`download it from here +<../../../../samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp>`. The +full source code is quite long (due to the controlling of the application via the command line +arguments and performance measurement). Therefore, to avoid cluttering up these sections with those +you'll find here only the functions itself. + +The PSNR returns a float number, that if the two inputs are similar between 30 and 50 (higher is +better). + +.. literalinclude:: ../../../../samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp + :language: cpp + :linenos: + :tab-width: 4 + :lines: 165-210, 18-23, 210-235 + +The SSIM returns the MSSIM of the images. This is too a float number between zero and one (higher is +better), however we have one for each channel. Therefore, we return a *Scalar* OpenCV data +structure: + +.. literalinclude:: ../../../../samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp + :language: cpp + :linenos: + :tab-width: 4 + :lines: 235-355, 26-42, 357- + +How to do it? - The GPU +======================= + +Now as you can see we have three types of functions for each operation. One for the CPU and two for +the GPU. The reason I made two for the GPU is too illustrate that often simple porting your CPU to +GPU will actually make it slower. If you want some performance gain you will need to remember a few +rules, whose I'm going to detail later on. + +The development of the GPU module was made so that it resembles as much as possible its CPU +counterpart. This is to make porting easy. The first thing you need to do before writing any code is +to link the GPU module to your project, and include the header file for the module. All the +functions and data structures of the GPU are in a *gpu* sub namespace of the *cv* namespace. You may +add this to the default one via the *use namespace* keyword, or mark it everywhere explicitly via +the cv:: to avoid confusion. I'll do the later. + +.. code-block:: cpp + + #include // GPU structures and methods + +GPU stands for **g**\ raphics **p**\ rocessing **u**\ nit. It was originally build to render +graphical scenes. These scenes somehow build on a lot of data. Nevertheless, these aren't all +dependent one from another in a sequential way and as it is possible a parallel processing of them. +Due to this a GPU will contain multiple smaller processing units. These aren't the state of the art +processors and on a one on one test with a CPU it will fall behind. However, its strength lies in +its numbers. In the last years there has been an increasing trend to harvest these massive parallel +powers of the GPU in non-graphical scene rendering too. This gave birth to the general-purpose +computation on graphics processing units (GPGPU). + +The GPU has its own memory. When you read data from the hard drive with OpenCV into a *Mat* object +that takes place in your systems memory. The CPU works somehow directly on this (via its cache), +however the GPU cannot. He has too transferred the information he will use for calculations from the +system memory to its own. This is done via an upload process and takes time. In the end the result +will have to be downloaded back to your system memory for your CPU to see it and use it. Porting +small functions to GPU is not recommended as the upload/download time will be larger than the amount +you gain by a parallel execution. + +Mat objects are stored only in the system memory (or the CPU cache). For getting an OpenCV matrix +to the GPU you'll need to use its GPU counterpart :gpudatastructure:`GpuMat `. It works +similar to the Mat with a 2D only limitation and no reference returning for its functions (cannot +mix GPU references with CPU ones). To upload a Mat object to the GPU you need to call the upload +function after creating an instance of the class. To download you may use simple assignment to a +Mat object or use the download function. + +.. code-block:: cpp + + Mat I1; // Main memory item - read image into with imread for example + gpu::GpuMat gI; // GPU matrix - for now empty + gI1.upload(I1); // Upload a data from the system memory to the GPU memory + + I1 = gI1; // Download, gI1.download(I1) will work too + +Once you have your data up in the GPU memory you may call GPU enabled functions of OpenCV. Most of +the functions keep the same name just as on the CPU, with the difference that they only accept +*GpuMat* inputs. A full list of these you will find in the documentation: `online here +`_ or the OpenCV reference manual that comes with +the source code. + +Another thing to keep in mind is that not for all channel numbers you can make efficient algorithms +on the GPU. Generally, I found that the input images for the GPU images need to be either one or +four channel ones and one of the char or float type for the item sizes. No double support on the +GPU, sorry. Passing other types of objects for some functions will result in an exception thrown, +and an error message on the error output. The documentation details in most of the places the types +accepted for the inputs. If you have three channel images as an input you can do two things: either +adds a new channel (and use char elements) or split up the image and call the function for each +image. The first one isn't really recommended as you waste memory. + +For some functions, where the position of the elements (neighbor items) doesn't matter quick +solution is to just reshape it into a single channel image. This is the case for the PSNR +implementation where for the *absdiff* method the value of the neighbors is not important. However, +for the *GaussianBlur* this isn't an option and such need to use the split method for the SSIM. With +this knowledge you can already make a GPU viable code (like mine GPU one) and run it. You'll be +surprised to see that it might turn out slower than your CPU implementation. + +Optimization +============ + +The reason for this is that you're throwing out on the window the price for memory allocation and +data transfer. And on the GPU this is damn high. Another possibility for optimization is to +introduce asynchronous OpenCV GPU calls too with the help of the +:gpudatastructure:`gpu::Stream`. + +1. Memory allocation on the GPU is considerable. Therefore, if it’s possible allocate new memory as + few times as possible. If you create a function what you intend to call multiple times it is a + good idea to allocate any local parameters for the function only once, during the first call. + To do this you create a data structure containing all the local variables you will use. For + instance in case of the PSNR these are: + + .. code-block:: cpp + + struct BufferPSNR // Optimized GPU versions + { // Data allocations are very expensive on GPU. Use a buffer to solve: allocate once reuse later. + gpu::GpuMat gI1, gI2, gs, t1,t2; + + gpu::GpuMat buf; + }; + + Then create an instance of this in the main program: + + .. code-block:: cpp + + BufferPSNR bufferPSNR; + + And finally pass this to the function each time you call it: + + .. code-block:: cpp + + double getPSNR_GPU_optimized(const Mat& I1, const Mat& I2, BufferPSNR& b) + + Now you access these local parameters as: *b.gI1*, *b.buf* and so on. The GpuMat will only + reallocate itself on a new call if the new matrix size is different from the previous one. + +#. Avoid unnecessary function data transfers. Any small data transfer will be significant one once + you go to the GPU. Therefore, if possible make all calculations in-place (in other words do not + create new memory objects - for reasons explained at the previous point). For example, although + expressing arithmetical operations may be easier to express in one line formulas, it will be + slower. In case of the SSIM at one point I need to calculate: + + .. code-block:: cpp + + b.t1 = 2 * b.mu1_mu2 + C1; + + Although the upper call will succeed observe that there is a hidden data transfer present. Before + it makes the addition it needs to store somewhere the multiplication. Therefore, it will create a + local matrix in the background, add to that the *C1* value and finally assign that to *t1*. To + avoid this we use the gpu functions, instead of the arithmetic operators: + + .. code-block:: cpp + + gpu::multiply(b.mu1_mu2, 2, b.t1); //b.t1 = 2 * b.mu1_mu2 + C1; + gpu::add(b.t1, C1, b.t1); + +#. Use asynchronous calls (the :gpudatastructure:`gpu::Stream `). By default whenever + you call a gpu function it will wait for the call to finish and return with the result + afterwards. However, it is possible to make asynchronous calls, meaning it will call for the + operation execution, make the costly data allocations for the algorithm and return back right + away. Now you can call another function if you wish to do so. For the MSSIM this is a small + optimization point. In our default implementation we split up the image into channels and call + then for each channel the gpu functions. A small degree of parallelization is possible with the + stream. By using a stream we can make the data allocation, upload operations while the GPU is + already executing a given method. For example we need to upload two images. We queue these one + after another and call already the function that processes it. The functions will wait for the + upload to finish, however while that happens makes the output buffer allocations for the function + to be executed next. + + .. code-block:: cpp + + gpu::Stream stream; + + stream.enqueueConvert(b.gI1, b.t1, CV_32F); // Upload + + gpu::split(b.t1, b.vI1, stream); // Methods (pass the stream as final parameter). + gpu::multiply(b.vI1[i], b.vI1[i], b.I1_2, stream); // I1^2 + +Result and conclusion +===================== + +On an Intel P8700 laptop CPU paired with a low end NVidia GT220M here are the performance numbers: + +.. code-block:: cpp + + Time of PSNR CPU (averaged for 10 runs): 41.4122 milliseconds. With result of: 19.2506 + Time of PSNR GPU (averaged for 10 runs): 158.977 milliseconds. With result of: 19.2506 + Initial call GPU optimized: 31.3418 milliseconds. With result of: 19.2506 + Time of PSNR GPU OPTIMIZED ( / 10 runs): 24.8171 milliseconds. With result of: 19.2506 + + Time of MSSIM CPU (averaged for 10 runs): 484.343 milliseconds. With result of B0.890964 G0.903845 R0.936934 + Time of MSSIM GPU (averaged for 10 runs): 745.105 milliseconds. With result of B0.89922 G0.909051 R0.968223 + Time of MSSIM GPU Initial Call 357.746 milliseconds. With result of B0.890964 G0.903845 R0.936934 + Time of MSSIM GPU OPTIMIZED ( / 10 runs): 203.091 milliseconds. With result of B0.890964 G0.903845 R0.936934 + +In both cases we managed a performance increase of almost 100% compared to the CPU implementation. +It may be just the improvement needed for your application to work. You may observe a runtime +instance of this on the `YouTube here `_. + +.. raw:: html + +
    + +
    diff --git a/doc/tutorials/highgui/table_of_content_highgui/table_of_content_highgui.rst b/doc/tutorials/highgui/table_of_content_highgui/table_of_content_highgui.rst index 0ba7c323cb..ef6eacce27 100644 --- a/doc/tutorials/highgui/table_of_content_highgui/table_of_content_highgui.rst +++ b/doc/tutorials/highgui/table_of_content_highgui/table_of_content_highgui.rst @@ -74,4 +74,4 @@ This section contains valuable tutorials about how to read/save your image/video ../trackbar/trackbar ../video-input-psnr-ssim/video-input-psnr-ssim - ../video-write/video-write \ No newline at end of file + ../video-write/video-write diff --git a/doc/tutorials/highgui/trackbar/trackbar.rst b/doc/tutorials/highgui/trackbar/trackbar.rst index d6f7202ce1..5749123c10 100644 --- a/doc/tutorials/highgui/trackbar/trackbar.rst +++ b/doc/tutorials/highgui/trackbar/trackbar.rst @@ -28,9 +28,7 @@ Let's modify the program made in the tutorial :ref:`Adding_Images`. We will let .. code-block:: cpp - #include - #include - + #include using namespace cv; /// Global Variables @@ -50,41 +48,41 @@ Let's modify the program made in the tutorial :ref:`Adding_Images`. We will let */ void on_trackbar( int, void* ) { - alpha = (double) alpha_slider/alpha_slider_max ; - beta = ( 1.0 - alpha ); + alpha = (double) alpha_slider/alpha_slider_max ; + beta = ( 1.0 - alpha ); - addWeighted( src1, alpha, src2, beta, 0.0, dst); + addWeighted( src1, alpha, src2, beta, 0.0, dst); - imshow( "Linear Blend", dst ); + imshow( "Linear Blend", dst ); } int main( int argc, char** argv ) { - /// Read image ( same size, same type ) - src1 = imread("../../images/LinuxLogo.jpg"); - src2 = imread("../../images/WindowsLogo.jpg"); + /// Read image ( same size, same type ) + src1 = imread("../../images/LinuxLogo.jpg"); + src2 = imread("../../images/WindowsLogo.jpg"); - if( !src1.data ) { printf("Error loading src1 \n"); return -1; } - if( !src2.data ) { printf("Error loading src2 \n"); return -1; } + if( !src1.data ) { printf("Error loading src1 \n"); return -1; } + if( !src2.data ) { printf("Error loading src2 \n"); return -1; } - /// Initialize values - alpha_slider = 0; + /// Initialize values + alpha_slider = 0; - /// Create Windows - namedWindow("Linear Blend", 1); + /// Create Windows + namedWindow("Linear Blend", 1); - /// Create Trackbars - char TrackbarName[50]; - sprintf( TrackbarName, "Alpha x %d", alpha_slider_max ); + /// Create Trackbars + char TrackbarName[50]; + sprintf( TrackbarName, "Alpha x %d", alpha_slider_max ); - createTrackbar( TrackbarName, "Linear Blend", &alpha_slider, alpha_slider_max, on_trackbar ); + createTrackbar( TrackbarName, "Linear Blend", &alpha_slider, alpha_slider_max, on_trackbar ); - /// Show some stuff - on_trackbar( alpha_slider, 0 ); + /// Show some stuff + on_trackbar( alpha_slider, 0 ); - /// Wait until user press some key - waitKey(0); - return 0; + /// Wait until user press some key + waitKey(0); + return 0; } @@ -154,8 +152,3 @@ Result .. image:: images/Adding_Trackbars_Tutorial_Result_1.jpg :alt: Adding Trackbars - Lena :align: center - - - - - diff --git a/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.rst b/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.rst index e163348f03..f313cb9086 100644 --- a/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.rst +++ b/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.rst @@ -60,7 +60,7 @@ Erosion * As the kernel :math:`B` is scanned over the image, we compute the minimal pixel value overlapped by :math:`B` and replace the image pixel under the anchor point with that minimal value. -* Analagously to the example for dilation, we can apply the erosion operator to the original image (shown above). You can see in the result below that the bright areas of the image (the background, apparently), get thinner, whereas the dark zones (the "writing"( gets bigger. +* Analagously to the example for dilation, we can apply the erosion operator to the original image (shown above). You can see in the result below that the bright areas of the image (the background, apparently), get thinner, whereas the dark zones (the "writing") gets bigger. .. image:: images/Morphology_1_Tutorial_Theory_Erosion.png :alt: Erosion result - Theory example diff --git a/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.rst b/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.rst index 133a613add..9277a101d6 100644 --- a/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.rst +++ b/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.rst @@ -329,4 +329,3 @@ Result .. image:: images/Histogram_Calculation_Result.jpg :align: center - diff --git a/doc/tutorials/imgproc/histograms/template_matching/template_matching.rst b/doc/tutorials/imgproc/histograms/template_matching/template_matching.rst index d8a91560e9..afe15ee0dd 100644 --- a/doc/tutorials/imgproc/histograms/template_matching/template_matching.rst +++ b/doc/tutorials/imgproc/histograms/template_matching/template_matching.rst @@ -369,4 +369,3 @@ Results .. image:: images/Template_Matching_Image_Result.jpg :align: center - diff --git a/doc/tutorials/imgproc/imgtrans/canny_detector/canny_detector.rst b/doc/tutorials/imgproc/imgtrans/canny_detector/canny_detector.rst index 01c9050f26..ae2d0c8ace 100644 --- a/doc/tutorials/imgproc/imgtrans/canny_detector/canny_detector.rst +++ b/doc/tutorials/imgproc/imgtrans/canny_detector/canny_detector.rst @@ -282,6 +282,3 @@ Result :align: center * Notice how the image is superposed to the black background on the edge regions. - - - diff --git a/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.rst b/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.rst index ecd4ba2192..96257683ef 100644 --- a/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.rst +++ b/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.rst @@ -40,7 +40,7 @@ Code * Display the detected circle in a window. .. |TutorialHoughCirclesSimpleDownload| replace:: here - .. _TutorialHoughCirclesSimpleDownload: http://code.opencv.org/projects/opencv/repository/revisions/master/raw/samples/cpp/houghlines.cpp + .. _TutorialHoughCirclesSimpleDownload: http://code.opencv.org/projects/opencv/repository/revisions/master/raw/samples/cpp/houghcircles.cpp .. |TutorialHoughCirclesFancyDownload| replace:: here .. _TutorialHoughCirclesFancyDownload: http://code.opencv.org/projects/opencv/repository/revisions/master/raw/samples/cpp/tutorial_code/ImgTrans/HoughCircle_Demo.cpp diff --git a/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.rst b/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.rst index 6b872bff51..d716c08323 100644 --- a/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.rst +++ b/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.rst @@ -290,4 +290,3 @@ We get the following result by using the Probabilistic Hough Line Transform: :align: center You may observe that the number of lines detected vary while you change the *threshold*. The explanation is sort of evident: If you establish a higher threshold, fewer lines will be detected (since you will need more points to declare a line detected). - diff --git a/doc/tutorials/imgproc/imgtrans/remap/remap.rst b/doc/tutorials/imgproc/imgtrans/remap/remap.rst index a8b9fdf744..a060aa779e 100644 --- a/doc/tutorials/imgproc/imgtrans/remap/remap.rst +++ b/doc/tutorials/imgproc/imgtrans/remap/remap.rst @@ -311,4 +311,3 @@ Result :alt: Result 0 for remapping :width: 250pt :align: center - diff --git a/doc/tutorials/imgproc/imgtrans/warp_affine/warp_affine.rst b/doc/tutorials/imgproc/imgtrans/warp_affine/warp_affine.rst index b601929781..d61b493371 100644 --- a/doc/tutorials/imgproc/imgtrans/warp_affine/warp_affine.rst +++ b/doc/tutorials/imgproc/imgtrans/warp_affine/warp_affine.rst @@ -306,4 +306,3 @@ Result :alt: Original image :width: 250pt :align: center - diff --git a/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.rst b/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.rst index 6baa3a3d71..ca9d445464 100644 --- a/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.rst +++ b/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.rst @@ -279,4 +279,3 @@ Results .. image:: images/Morphology_2_Tutorial_Cover.jpg :alt: Morphology 2: Result sample :align: center - diff --git a/doc/tutorials/imgproc/pyramids/pyramids.rst b/doc/tutorials/imgproc/pyramids/pyramids.rst index 00baae2ac1..dacc5b93a1 100644 --- a/doc/tutorials/imgproc/pyramids/pyramids.rst +++ b/doc/tutorials/imgproc/pyramids/pyramids.rst @@ -259,5 +259,3 @@ Results .. image:: images/Pyramids_Tutorial_PyrUp_Result.jpg :alt: Pyramids: PyrUp Result :align: center - - diff --git a/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.rst b/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.rst index f91730ec88..24c276dc31 100644 --- a/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.rst +++ b/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.rst @@ -121,4 +121,3 @@ Result .. |BRC_1| image:: images/Bounding_Rects_Circles_Result.jpg :align: middle - diff --git a/doc/tutorials/imgproc/shapedescriptors/bounding_rotated_ellipses/bounding_rotated_ellipses.rst b/doc/tutorials/imgproc/shapedescriptors/bounding_rotated_ellipses/bounding_rotated_ellipses.rst index 0986e1edcd..9c7fbb85f6 100644 --- a/doc/tutorials/imgproc/shapedescriptors/bounding_rotated_ellipses/bounding_rotated_ellipses.rst +++ b/doc/tutorials/imgproc/shapedescriptors/bounding_rotated_ellipses/bounding_rotated_ellipses.rst @@ -123,4 +123,3 @@ Result .. |BRE_1| image:: images/Bounding_Rotated_Ellipses_Result.jpg :align: middle - diff --git a/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.rst b/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.rst index 1fca7df93a..68cf80dc7c 100644 --- a/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.rst +++ b/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.rst @@ -104,4 +104,3 @@ Result .. |contour_1| image:: images/Find_Contours_Result.jpg :align: middle - diff --git a/doc/tutorials/imgproc/shapedescriptors/hull/hull.rst b/doc/tutorials/imgproc/shapedescriptors/hull/hull.rst index c1ed79cea1..eb5d19e3b5 100644 --- a/doc/tutorials/imgproc/shapedescriptors/hull/hull.rst +++ b/doc/tutorials/imgproc/shapedescriptors/hull/hull.rst @@ -113,4 +113,3 @@ Result .. |Hull_1| image:: images/Hull_Result.jpg :align: middle - diff --git a/doc/tutorials/imgproc/shapedescriptors/moments/moments.rst b/doc/tutorials/imgproc/shapedescriptors/moments/moments.rst index 15ac2f51f7..350ca38d46 100644 --- a/doc/tutorials/imgproc/shapedescriptors/moments/moments.rst +++ b/doc/tutorials/imgproc/shapedescriptors/moments/moments.rst @@ -133,4 +133,3 @@ Result .. |MU_2| image:: images/Moments_Result2.jpg :width: 250pt :align: middle - diff --git a/doc/tutorials/imgproc/shapedescriptors/point_polygon_test/point_polygon_test.rst b/doc/tutorials/imgproc/shapedescriptors/point_polygon_test/point_polygon_test.rst index b7f72c8150..2d68cc2470 100644 --- a/doc/tutorials/imgproc/shapedescriptors/point_polygon_test/point_polygon_test.rst +++ b/doc/tutorials/imgproc/shapedescriptors/point_polygon_test/point_polygon_test.rst @@ -114,4 +114,3 @@ Result .. |PPT_1| image:: images/Point_Polygon_Test_Result.jpg :align: middle - diff --git a/doc/tutorials/imgproc/table_of_content_imgproc/table_of_content_imgproc.rst b/doc/tutorials/imgproc/table_of_content_imgproc/table_of_content_imgproc.rst index 1be239cfb1..a371c02c87 100644 --- a/doc/tutorials/imgproc/table_of_content_imgproc/table_of_content_imgproc.rst +++ b/doc/tutorials/imgproc/table_of_content_imgproc/table_of_content_imgproc.rst @@ -539,6 +539,3 @@ In this section you will learn about the image processing (manipulation) functio ../shapedescriptors/bounding_rotated_ellipses/bounding_rotated_ellipses ../shapedescriptors/moments/moments ../shapedescriptors/point_polygon_test/point_polygon_test - - - diff --git a/doc/tutorials/introduction/android_binary_package/O4A_SDK.rst b/doc/tutorials/introduction/android_binary_package/O4A_SDK.rst index b37126f308..78566e7d28 100644 --- a/doc/tutorials/introduction/android_binary_package/O4A_SDK.rst +++ b/doc/tutorials/introduction/android_binary_package/O4A_SDK.rst @@ -48,10 +48,10 @@ The structure of package contents looks as follows: :: - OpenCV-2.4.4-android-sdk + OpenCV-2.4.6-android-sdk |_ apk - | |_ OpenCV_2.4.4_binary_pack_armv7a.apk - | |_ OpenCV_2.4.4_Manager_2.6_XXX.apk + | |_ OpenCV_2.4.6_binary_pack_armv7a.apk + | |_ OpenCV_2.4.6_Manager_2.9_XXX.apk | |_ doc |_ samples @@ -98,7 +98,7 @@ The structure of package contents looks as follows: * :file:`doc` folder contains various OpenCV documentation in PDF format. It's also available online at http://docs.opencv.org. - .. note:: The most recent docs (nightly build) are at http://docs.opencv.org/trunk/. + .. note:: The most recent docs (nightly build) are at http://docs.opencv.org/2.4. Generally, it's more up-to-date, but can refer to not-yet-released functionality. .. TODO: I'm not sure that this is the best place to talk about OpenCV Manager @@ -157,10 +157,10 @@ Get the OpenCV4Android SDK .. code-block:: bash - unzip ~/Downloads/OpenCV-2.4.4-android-sdk.zip + unzip ~/Downloads/OpenCV-2.4.6-android-sdk.zip -.. |opencv_android_bin_pack| replace:: :file:`OpenCV-2.4.4-android-sdk.zip` -.. _opencv_android_bin_pack_url: http://sourceforge.net/projects/opencvlibrary/files/opencv-android/2.4.4/OpenCV-2.4.4-android-sdk.zip/download +.. |opencv_android_bin_pack| replace:: :file:`OpenCV-2.4.6-android-sdk.zip` +.. _opencv_android_bin_pack_url: http://sourceforge.net/projects/opencvlibrary/files/opencv-android/2.4.6/OpenCV-2.4.6-android-sdk.zip/download .. |opencv_android_bin_pack_url| replace:: |opencv_android_bin_pack| .. |seven_zip| replace:: 7-Zip .. _seven_zip: http://www.7-zip.org/ @@ -295,7 +295,7 @@ Well, running samples from Eclipse is very simple: .. code-block:: sh :linenos: - /platform-tools/adb install /apk/OpenCV_2.4.4_Manager_2.6_armv7a-neon.apk + /platform-tools/adb install /apk/OpenCV_2.4.6_Manager_2.9_armv7a-neon.apk .. note:: ``armeabi``, ``armv7a-neon``, ``arm7a-neon-android8``, ``mips`` and ``x86`` stand for platform targets: diff --git a/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.rst b/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.rst index 41f5166292..243dc35dd8 100644 --- a/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.rst +++ b/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.rst @@ -55,14 +55,14 @@ Manager to access OpenCV libraries externally installed in the target system. :guilabel:`File -> Import -> Existing project in your workspace`. Press :guilabel:`Browse` button and locate OpenCV4Android SDK - (:file:`OpenCV-2.4.4-android-sdk/sdk`). + (:file:`OpenCV-2.4.6-android-sdk/sdk`). .. image:: images/eclipse_opencv_dependency0.png :alt: Add dependency from OpenCV library :align: center #. In application project add a reference to the OpenCV Java SDK in - :guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.4``. + :guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.6``. .. image:: images/eclipse_opencv_dependency1.png :alt: Add dependency from OpenCV library @@ -101,7 +101,7 @@ See the "15-puzzle" OpenCV sample for details. public void onResume() { super.onResume(); - OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback); + OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_6, this, mLoaderCallback); } ... @@ -128,27 +128,27 @@ described above. #. Add the OpenCV library project to your workspace the same way as for the async initialization above. Use menu :guilabel:`File -> Import -> Existing project in your workspace`, press :guilabel:`Browse` button and select OpenCV SDK path - (:file:`OpenCV-2.4.4-android-sdk/sdk`). + (:file:`OpenCV-2.4.6-android-sdk/sdk`). .. image:: images/eclipse_opencv_dependency0.png :alt: Add dependency from OpenCV library :align: center #. In the application project add a reference to the OpenCV4Android SDK in - :guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.4``; + :guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.6``; .. image:: images/eclipse_opencv_dependency1.png :alt: Add dependency from OpenCV library :align: center #. If your application project **doesn't have a JNI part**, just copy the corresponding OpenCV - native libs from :file:`/sdk/native/libs/` to your + native libs from :file:`/sdk/native/libs/` to your project directory to folder :file:`libs/`. In case of the application project **with a JNI part**, instead of manual libraries copying you need to modify your ``Android.mk`` file: add the following two code lines after the ``"include $(CLEAR_VARS)"`` and before - ``"include path_to_OpenCV-2.4.4-android-sdk/sdk/native/jni/OpenCV.mk"`` + ``"include path_to_OpenCV-2.4.6-android-sdk/sdk/native/jni/OpenCV.mk"`` .. code-block:: make :linenos: @@ -221,7 +221,7 @@ taken: .. code-block:: make - include C:\Work\OpenCV4Android\OpenCV-2.4.4-android-sdk\sdk\native\jni\OpenCV.mk + include C:\Work\OpenCV4Android\OpenCV-2.4.6-android-sdk\sdk\native\jni\OpenCV.mk Should be inserted into the :file:`jni/Android.mk` file **after** this line: @@ -379,7 +379,7 @@ result. public void onResume() { super.onResume(); - OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback); + OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_6, this, mLoaderCallback); } #. Defines that your activity implements ``CvViewFrameListener2`` interface and fix activity related diff --git a/doc/tutorials/introduction/how_to_write_a_tutorial/how_to_write_a_tutorial.rst b/doc/tutorials/introduction/how_to_write_a_tutorial/how_to_write_a_tutorial.rst index 26ec076f50..5ae5062492 100644 --- a/doc/tutorials/introduction/how_to_write_a_tutorial/how_to_write_a_tutorial.rst +++ b/doc/tutorials/introduction/how_to_write_a_tutorial/how_to_write_a_tutorial.rst @@ -1 +1,440 @@ -.. _howToWriteTutorial: How to write a tutorial for OpenCV? *********************************** Okay, so assume you have just finished a project of yours implementing something based on OpenCV and you want to present/share it with the community. Luckily, OpenCV is an *open source project*. This means that in theory anyone has access to the full source code and may extend it. While making a robust and practical library (like OpenCV) is great, the success of a library also depends on how user friendly it is. To improve on this aspect, the OpenCV team has already been listening to user feedback from its :opencv_group:`Yahoo user group <>` and by making samples you can find in the source directories sample folder. The addition of the tutorials (in both online and PDF format) is an extension of these efforts. Goal ==== .. _reST: http://docutils.sourceforge.net/rst.html .. |reST| replace:: reStructuredText .. |Sphinx| replace:: Sphinx .. _Sphinx: http://sphinx.pocoo.org/ The tutorials are just as an important part of the library as the implementation of those crafty data structures and algorithms you can find in OpenCV. Therefore, the source codes for the tutorials are part of the library. And yes, I meant source codes. The reason for this formulation is that the tutorials are written by using the |Sphinx|_ documentation generation system. This is based on the popular python documentation system called |reST|_ (reST). ReStructuredText is a really neat language that by using a few simple conventions (indentation, directives) and emulating old school e-mail writing techniques (text only) tries to offer a simple way to create and edit documents. Sphinx extends this with some new features and creates the resulting document in both HTML (for web) and PDF (for offline usage) format. Usually, an OpenCV tutorial has the following parts: 1. A source code demonstration of an OpenCV feature: a. One or more CPP, Python, Java or other type of files depending for what OpenCV offers support and for what language you make the tutorial. #. Occasionaly, input resource files required for running your tutorials application. #. A table of content entry (so people may easily find the tutorial): a. Adding your stuff to the tutorials table of content (**reST** file). #. Add an image file near the TOC entry. #. The content of the tutorial itself: a. The **reST** text of the tutorial #. Images following the idea that "*A picture is worth a thousand words*". #. For more complex demonstrations you may create a video. As you can see you will need at least some basic knowledge of the *reST* system in order to complete the task at hand with success. However, don't worry *reST* (and *Sphinx*) was made with simplicity in mind. It is easy to grasp its basics. I found that the `OpenAlea documentations introduction on this subject `_ (or the `Thomas Cokelaer one `_ ) should enough for this. If for some directive or feature you need a more in-depth description look it up in the official |reST|_ help files or at the |Sphinx|_ documentation. In our world achieving some tasks is possible in multiple ways. However, some of the roads to take may have obvious or hidden advantages over others. Then again, in some other cases it may come down to just simple user preference. Here, I'll present how I decided to write the tutorials, based on my personal experience. If for some of them you know a better solution and you can back it up feel free to use that. I've nothing against it, as long as it gets the job done in an elegant fashion. Now the best would be if you could make the integration yourself. For this you need first to have the source code. I recommend following the guides for your operating system on acquiring OpenCV sources. For Linux users look :ref:`here ` and for :ref:`Windows here `. You must also install python and sphinx with its dependencies in order to be able to build the documentation. Once you have downloaded the repository to your hard drive you can take a look in the OpenCV directory to make sure you have both the samples and doc folder present. Anyone may download the trunk source files from :file:`git://code.opencv.org/opencv.git` . Nevertheless, not everyone has upload (commit/submit) rights. This is to protect the integrity of the library. If you plan doing more than one tutorial, and would like to have an account with commit user rights you should first register an account at http://code.opencv.org/ and then contact dr. Gary Bradski at -delete-bradski@-delete-willowgarage.com. Otherwise, you can just send the resulting files to us via the :opencv_group:`Yahoo user group <>` or to me at -delete-bernat@-delete-primeranks.net and I'll add it. If you have questions, suggestions or constructive critics I will gladly listen to them. If you send it to the OpenCV group please tag its subject with a **[Tutorial]** entry. Format the Source Code ====================== Before I start this let it be clear: the main goal is to have a working sample code. However, for your tutorial to be of a top notch quality you should follow a few guide lines I am going to present here. In case you have an application by using the older interface (with *IplImage*, *CVMat*, *cvLoadImage* and such) consider migrating it to the new C++ interface. The tutorials are intended to be an up to date help for our users. And as of OpenCV 2 the OpenCV emphasis on using the less error prone and clearer C++ interface. Therefore, if possible please convert your code to the C++ interface. For this it may help to read the :ref:`InteroperabilityWithOpenCV1` tutorial. However, once you have an OpenCV 2 working code, then you should make your source code snippet as easy to read as possible. Here're a couple of advices for this: .. container:: enumeratevisibleitemswithsquare + Add a standard output with the description of what your program does. Keep it short and yet, descriptive. This output is at the start of the program. In my example files this usually takes the form of a *help* function containing the output. This way both the source file viewer and application runner can see what all is about in your sample. Here's an instance of this: .. code-block:: cpp void help() { cout << "--------------------------------------------------------------------------" << endl << "This program shows how to write video files. You can extract the R or G or B color channel " << " of the input video. You can choose to use the source codec (Y) or select a custom one. (N)"<< endl << "Usage:" << endl << "./video-write inputvideoName [ R | G | B] [Y | N]" << endl << "--------------------------------------------------------------------------" << endl << endl; } // ... int main(int argc, char *argv[], char *window_name) { help(); // here comes the actual source code } Additionally, finalize the description with a short usage guide. This way the user will know how to call your programs, what leads us to the next point. + Prefer command line argument controlling instead of hard coded one. If your program has some variables that may be changed use command line arguments for this. The tutorials, can be a simple try-out ground for the user. If you offer command line controlling for the input image (for example), then you offer the possibility for the user to try it out with his/her own images, without the need to mess in the source code. In the upper example you can see that the input image, channel and codec selection may all be changed from the command line. Just compile the program and run it with your own input arguments. + Be as verbose as possible. There is no shame in filling the source code with comments. This way the more advanced user may figure out what's happening right from the sample code. This advice goes for the output console too. Specify to the user what's happening. Never leave the user hanging there and thinking on: "Is this program now crashing or just doing some computationally intensive task?." So, if you do a training task that may take some time, make sure you print out a message about this before starting and after finishing it. + Throw out unnecessary stuff from your source code. This is a warning to not take the previous point too seriously. Balance is the key. If it's something that can be done in a fewer lines or simpler than that's the way you should do it. Nevertheless, if for some reason you have such sections notify the user why you have chosen to do so. Keep the amount of information as low as possible, while still getting the job done in an elegant way. + Put your sample file into the :file:`opencv/samples/cpp/tutorial_code/sectionName` folder. If you write a tutorial for other languages than cpp, then change that part of the path. Before completing this you need to decide that to what section (module) does your tutorial goes. Think about on what module relies most heavily your code and that is the one to use. If the answer to this question is more than one modules then the *general* section is the one to use. For finding the *opencv* directory open up your file system and navigate where you downloaded our repository. + If the input resources are hard to acquire for the end user consider adding a few of them to the :file:`opencv/samples/cpp/tutorial_code/images`. Make sure that who reads your code can try it out! Add the TOC entry ================= For this you will need to know some |reST|_. There is no going around this. |reST|_ files have **rst** extensions. However, these are simple text files. Use any text editor you like. Finding a text editor that offers syntax highlighting for |reST|_ was quite a challenge at the time of writing this tutorial. In my experience, `Intype `_ is a solid option on Windows, although there is still place for improvement. Adding your source code to a table of content is important for multiple reasons. First and foremost this will allow for the user base to find your tutorial from our websites tutorial table of content. Secondly, if you omit this *Sphinx* will throw a warning that your tutorial file isn't part of any TOC tree entry. And there is nothing more than the developer team hates than an ever increasing warning/error list for their builds. *Sphinx* also uses this to build up the previous-back-up buttons on the website. Finally, omitting this step will lead to that your tutorial will **not** be added to the PDF version of the tutorials. Navigate to the :file:`opencv/doc/tutorials/section/table_of_content_section` folder (where the section is the module to which you're adding the tutorial). Open the *table_of_content_section* file. Now this may have two forms. If no prior tutorials are present in this section that there is a template message about this and has the following form: .. code-block:: rst .. _Table-Of-Content-Section: Section title ----------------------------------------------------------- Description about the section. .. include:: ../../definitions/noContent.rst .. raw:: latex \pagebreak The first line is a reference to the section title in the reST system. The section title will be a link and you may refer to it via the ``:ref:`` directive. The *include* directive imports the template text from the definitions directories *noContent.rst* file. *Sphinx* does not creates the PDF from scratch. It does this by first creating a latex file. Then creates the PDF from the latex file. With the *raw* directive you can directly add to this output commands. Its unique argument is for what kind of output to add the content of the directive. For the PDFs it may happen that multiple sections will overlap on a single page. To avoid this at the end of the TOC we add a *pagebreak* latex command, that hints to the LATEX system that the next line should be on a new page. If you have one of this, try to transform it to the following form: .. include:: ../../definitions/tocDefinitions.rst .. code-block:: rst .. _Table-Of-Content-Section: Section title ----------------------------------------------------------- .. include:: ../../definitions/tocDefinitions.rst + .. tabularcolumns:: m{100pt} m{300pt} .. cssclass:: toctableopencv =============== ====================================================== |MatBasicIma| **Title:** :ref:`matTheBasicImageContainer` *Compatibility:* > OpenCV 2.0 *Author:* |Author_BernatG| You will learn how to store images in the memory and how to print out their content to the console. =============== ===================================================== .. |MatBasicIma| image:: images/matTheBasicImageStructure.jpg :height: 90pt :width: 90pt .. raw:: latex \pagebreak .. toctree:: :hidden: ../mat - the basic image container/mat - the basic image container If this is already present just add a new section of the content between the include and the raw directives (excluding those lines). Here you'll see a new include directive. This should be present only once in a TOC tree and the reST file contains the definitions of all the authors contributing to the OpenCV tutorials. We are a multicultural community and some of our name may contain some funky characters. However, reST **only supports** ANSI characters. Luckily we can specify Unicode characters with the *unicode* directive. Doing this for all of your tutorials is a troublesome procedure. Therefore, the tocDefinitions file contains the definition of your author name. Add it here once and afterwards just use the replace construction. For example here's the definition for my name: .. code-block:: rst .. |Author_BernatG| unicode:: Bern U+00E1 t U+0020 G U+00E1 bor The ``|Author_BernatG|`` is the text definitions alias. I can use later this to add the definition, like I've done in the TOCs *Author* part. After the ``::`` and a space you start the definition. If you want to add an UNICODE character (non-ASCI) leave an empty space and specify it in the format U+(UNICODE code). To find the UNICODE code of a character I recommend using the `FileFormat `_ websites service. Spaces are trimmed from the definition, therefore we add a space by its UNICODE character (U+0020). Until the *raw* directive what you can see is a TOC tree entry. Here's how a TOC entry will look like: + .. tabularcolumns:: m{100pt} m{300pt} .. cssclass:: toctableopencv =============== ====================================================== |MatBasicIma| **Title:** :ref:`matTheBasicImageContainer` *Compatibility:* > OpenCV 2.0 *Author:* |Author_BernatG| You will learn how to store images in the memory and how to print out their content to the console. =============== ====================================================== .. |MatBasicIma| image:: images/matTheBasicImageStructure.jpg :height: 90pt :width: 90pt As you can see we have an image to the left and a description box to the right. To create two boxes we use a table with two columns and a single row. In the left column is the image and in the right one the description. However, the image directive is way too long to fit in a column. Therefore, we need to use the substitution definition system. We add this definition after the TOC tree. All images for the TOC tree are to be put in the images folder near its |reST|_ file. We use the point measurement system because we are also creating PDFs. PDFs are printable documents, where there is no such thing that pixels (px), just points (pt). And while generally space is no problem for web pages (we have monitors with **huge** resolutions) the size of the paper (A4 or letter) is constant and will be for a long time in the future. Therefore, size constrains come in play more like for the PDF, than the generated HTML code. Now your images should be as small as possible, while still offering the intended information for the user. Remember that the tutorial will become part of the OpenCV source code. If you add large images (that manifest in form of large image size) it will just increase the size of the repository pointlessly. If someone wants to download it later, its download time will be that much longer. Not to mention the larger PDF size for the tutorials and the longer load time for the web pages. In terms of pixels a TOC image should not be larger than 120 X 120 pixels. Resize your images if they are larger! .. note:: If you add a larger image and specify a smaller image size, *Sphinx* will not resize that. At build time will add the full size image and the resize will be done by your browser after the image is loaded. A 120 X 120 image is somewhere below 10KB. If you add a 110KB image, you have just pointlessly added a 100KB extra data to transfer over the internet for every user! Generally speaking you shouldn't need to specify your images size (excluding the TOC entries). If no such is found *Sphinx* will use the size of the image itself (so no resize occurs). Then again if for some reason you decide to specify a size that should be the **width** of the image rather than its height. The reason for this again goes back to the PDFs. On a PDF page the height is larger than the width. In the PDF the images will not be resized. If you specify a size that does not fit in the page, then what does not fits in **will be cut off**. When creating your images for your tutorial you should try to keep the image widths below 500 pixels, and calculate with around 400 point page width when specifying image widths. The image format depends on the content of the image. If you have some complex scene (many random like colors) then use *jpg*. Otherwise, prefer using *png*. They are even some tools out there that optimize the size of *PNG* images, such as `PNGGauntlet `_. Use them to make your images as small as possible in size. Now on the right side column of the table we add the information about the tutorial: .. container:: enumeratevisibleitemswithsquare + In the first line it is the title of the tutorial. However, there is no need to specify it explicitly. We use the reference system. We'll start up our tutorial with a reference specification, just like in case of this TOC entry with its `` .. _Table-Of-Content-Section:`` . If after this you have a title (pointed out by the following line of -), then Sphinx will replace the ``:ref:`Table-Of-Content-Section``` directive with the tile of the section in reference form (creates a link in web page). Here's how the definition looks in my case: .. code-block:: rst .. _matTheBasicImageContainer: Mat - The Basic Image Container ******************************* Note, that according to the |reST|_ rules the * should be as long as your title. + Compatibility. What version of OpenCV is required to run your sample code. + Author. Use the substitution markup of |reST|_. + A short sentence describing the essence of your tutorial. Now before each TOC entry you need to add the three lines of: .. code-block:: cpp + .. tabularcolumns:: m{100pt} m{300pt} .. cssclass:: toctableopencv The plus sign (+) is to enumerate tutorials by using bullet points. So for every TOC entry we have a corresponding bullet point represented by the +. Sphinx is highly indenting sensitive. Indentation is used to express from which point until to which point does a construction last. Un-indentation means end of that construction. So to keep all the bullet points to the same group the following TOC entries (until the next +) should be indented by two spaces. Here, I should also mention that **always** prefer using spaces instead of tabs. Working with only spaces makes possible that if we both use monotype fonts we will see the same thing. Tab size is text editor dependent and as should be avoided. *Sphinx* translates all tabs into 8 spaces before interpreting it. It turns out that the automatic formatting of both the HTML and PDF(LATEX) system messes up our tables. Therefore, we need to help them out a little. For the PDF generation we add the ``.. tabularcolumns:: m{100pt} m{300pt}`` directive. This means that the first column should be 100 points wide and middle aligned. For the HTML look we simply name the following table of a *toctableopencv* class type. Then, we can modify the look of the table by modifying the CSS of our web page. The CSS definitions go into the :file:`opencv/doc/_themes/blue/static/default.css_t` file. .. code-block:: css .toctableopencv { width: 100% ; table-layout: fixed; } .toctableopencv colgroup col:first-child { width: 100pt !important; max-width: 100pt !important; min-width: 100pt !important; } .toctableopencv colgroup col:nth-child(2) { width: 100% !important; } However, you should not need to modify this. Just add these three lines (plus keep the two space indentation) for all TOC entries you add. At the end of the TOC file you'll find: .. code-block:: rst .. raw:: latex \pagebreak .. toctree:: :hidden: ../mat - the basic image container/mat - the basic image container The page break entry comes for separating sections and should be only one in a TOC tree |reST|_ file. Finally, at the end of the TOC tree we need to add our tutorial to the *Sphinx* TOC tree system. *Sphinx* will generate from this the previous-next-up information for the HTML file and add items to the PDF according to the order here. By default this TOC tree directive generates a simple table of contents. However, we already created a fancy looking one so we no longer need this basic one. Therefore, we add the *hidden* option to do not show it. The path is of a relative type. We step back in the file system and then go into the :file:`mat - the basic image container` directory for the :file:`mat - the basic image container.rst` file. Putting out the *rst* extension for the file is optional. Write the tutorial ================== Create a folder with the name of your tutorial. Preferably, use small letters only. Then create a text file in this folder with *rst* extension and the same name. If you have images for the tutorial create an :file:`images` folder and add your images there. When creating your images follow the guidelines described in the previous part! Now here's our recommendation for the structure of the tutorial (although, remember that this is not carved in the stone; if you have a better idea, use it!): .. container:: enumeratevisibleitemswithsquare + Create the reference point and the title. .. code-block:: rst .. _matTheBasicImageContainer: Mat - The Basic Image Container ******************************* You start the tutorial by specifying a reference point by the ``.. _matTheBasicImageContainer:`` and then its title. The name of the reference point should be a unique one over the whole documentation. Therefore, do not use general names like *tutorial1*. Use the * character to underline the title for its full width. The subtitles of the tutorial should be underlined with = charachter. + Goals. You start your tutorial by specifying what you will present. You can also enumerate the sub jobs to be done. For this you can use a bullet point construction. There is a single configuration file for both the reference manual and the tutorial documentation. In the reference manuals at the argument enumeration we do not want any kind of bullet point style enumeration. Therefore, by default all the bullet points at this level are set to do not show the dot before the entries in the HTML. You can override this by putting the bullet point in a container. I've defined a square type bullet point view under the name *enumeratevisibleitemswithsquare*. The CSS style definition for this is again in the :file:`opencv\doc\_themes\blue\static\default.css_t` file. Here's a quick example of using it: .. code-block:: rst .. container:: enumeratevisibleitemswithsquare + Create the reference point and the title. + Second entry + Third entry Note that you need the keep the indentation of the container directive. Directive indentations are always three (3) spaces. Here you may even give usage tips for your sample code. + Source code. Present your samples code to the user. It's a good idea to offer a quick download link for the HTML page by using the *download* directive and pointing out where the user may find your source code in the file system by using the *file* directive: .. code-block:: rst Text :file:`samples/cpp/tutorial_code/highgui/video-write/` folder of the OpenCV source library or :download:`text to appear in the webpage <../../../../samples/cpp/tutorial_code/HighGUI/video-write/video-write.cpp>`. For the download link the path is a relative one, hence the multiple back stepping operations (..). Then you can add the source code either by using the *code block* directive or the *literal include* one. In case of the code block you will need to actually add all the source code text into your |reST|_ text and also apply the required indentation: .. code-block:: rst .. code-block:: cpp int i = 0; l = ++j; The only argument of the directive is the language used (here CPP). Then you add the source code into its content (meaning one empty line after the directive) by keeping the indentation of the directive (3 spaces). With the *literal include* directive you do not need to add the source code of the sample. You just specify the sample and *Sphinx* will load it for you, during build time. Here's an example usage: .. code-block:: rst .. literalinclude:: ../../../../samples/cpp/tutorial_code/HighGUI/video-write/video-write.cpp :language: cpp :linenos: :tab-width: 4 :lines: 1-8, 21-22, 24- After the directive you specify a relative path to the file from what to import. It has four options: the language to use, if you add the ``:linenos:`` the line numbers will be shown, you can specify the tab size with the ``:tab-width:`` and you do not need to load the whole file, you can show just the important lines. Use the *lines* option to do not show redundant information (such as the *help* function). Here basically you specify ranges, if the second range line number is missing than that means that until the end of the file. The ranges specified here do no need to be in an ascending order, you may even reorganize the structure of how you want to show your sample inside the tutorial. + The tutorial. Well here goes the explanation for why and what have you used. Try to be short, clear, concise and yet a thorough one. There's no magic formula. Look into a few already made tutorials and start out from there. Try to mix sample OpenCV code with your explanations. If with words is hard to describe something do not hesitate to add in a reasonable size image, to overcome this issue. When you present OpenCV functionality it's a good idea to give a link to the used OpenCV data structure or function. Because the OpenCV tutorials and reference manual are in separate PDF files it is not possible to make this link work for the PDF format. Therefore, we use here only web page links to the **opencv.itseez.com** website. The OpenCV functions and data structures may be used for multiple tasks. Nevertheless, we want to avoid that every users creates its own reference to a commonly used function. So for this we use the global link collection of *Sphinx*. This is defined in the file:`opencv/doc/conf.py` configuration file. Open it and go all the way down to the last entry: .. code-block:: py # ---- External links for tutorials ----------------- extlinks = { 'hgvideo' : ('http://opencv.itseez.com/modules/highgui/doc/reading_and_writing_images_and_video.html#%s', None) } In short here we defined a new **hgvideo** directive that refers to an external webpage link. Its usage is: .. code-block:: rst A sample function of the highgui modules image write and read page is the :hgvideo:`imread() function `. Which turns to: A sample function of the highgui modules image write and read page is the :hgvideo:`imread() function `. The argument you give between the <> will be put in place of the ``%s`` in the upper definition, and as the link will anchor to the correct function. To find out the anchor of a given function just open up a web page, search for the function and click on it. In the address bar it should appear like: ``http://opencv.itseez.com/modules/highgui/doc/reading_and_writing_images_and_video.html#imread`` . Look here for the name of the directives for each page of the OpenCV reference manual. If none present for one of them feel free to add one for it. For formulas you can add LATEX code that will translate in the web pages into images. You do this by using the *math* directive. A usage tip: .. code-block:: latex .. math:: MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2} That after build turns into: .. math:: MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2} You can even use it inline as ``:math:` MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2}``` that turns into :math:`MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2}`. If you use some crazy LATEX library extension you need to add those to the ones to use at build time. Look into the file:`opencv/doc/conf.py` configuration file for more information on this. + Results. Well, here depending on your program show one of more of the following: - Console outputs by using the code block directive. - Output images. - Runtime videos, visualization. For this use your favorite screens capture software. `Camtasia Studio `_ certainly is one of the better choices, however their prices are out of this world. `CamStudio `_ is a free alternative, but less powerful. If you do a video you can upload it to YouTube and then use the raw directive with HTML option to embed it into the generated web page: .. code-block:: rst You may observe a runtime instance of this on the `YouTube here `_. .. raw:: html
    This results in the text and video: You may observe a runtime instance of this on the `YouTube here `_. .. raw:: html
    When these aren't self-explanatory make sure to throw in a few guiding lines about what and why we can see. + Build the documentation and check for errors or warnings. In the CMake make sure you check or pass the option for building documentation. Then simply build the **docs** project for the PDF file and the **docs_html** project for the web page. Read the output of the build and check for errors/warnings for what you have added. This is also the time to observe and correct any kind of *not so good looking* parts. Remember to keep clean our build logs. + Read again your tutorial and check for both programming and spelling errors. If found any, please correct them. Take home the pride and joy of a job well done! =============================================== Once you are done contact me or dr. Gary Bradski with the tutorial. We may submit the tutorial ourselves to the trunk branch of our repository or ask you to do so. Now, to see your work **live** you may need to wait some time. The PDFs are updated usually at the launch of a new OpenCV version. The web pages are a little more diverse. They are automatically rebuilt in each evening. However, the **opencv.itseez.com** website contains only the most recent **stable branch** of OpenCV. Currently this is 2.3. When we add something new (like a tutorial) that first goes to the **trunk branch** of our repository. A build of this you may find on the **opencv.itseez.com/trunk** website. Although, we try to make a build every night occasionally we might freeze any of the branches to fix upcoming issues. During this it may take a little longer to see your work *live*, however if you submited it, be sure that eventually it will show up. If you have any questions or advices relating to this tutorial you can contact me at -delete-bernat@-delete-primeranks.net. Of course, delete the -delete- parts of that e-mail address. \ No newline at end of file +.. _howToWriteTutorial: + +How to write a tutorial for OpenCV +********************************** + +Okay, so assume you have just finished a project of yours implementing something +based on OpenCV and you want to present/share it with the community. Luckily, OpenCV +is an *open source project*. This means that anyone has access to the full source +code and may propose extensions. And a good tutorial is a valuable addition to the +library! Please read instructions on contribution process here: +http://opencv.org/contribute.html. You may also find this page helpful: +:how_to_contribute:`How to contribute <>`. + +While making a robust and practical library (like OpenCV) is great, the success of a +library also depends on how user friendly it is. To improve on this aspect, the +OpenCV team has already been listening to user feedback at :opencv_qa:`OpenCV Q&A +forum <>` and by making samples you can find in the source directories +:file:`samples` folder. The addition of the tutorials (in both online and PDF format) +is an extension of these efforts. + +Goal +==== + +.. _reST: http://docutils.sourceforge.net/rst.html +.. |reST| replace:: reStructuredText +.. |Sphinx| replace:: Sphinx +.. _Sphinx: http://sphinx.pocoo.org/ + +The tutorials are just as an important part of the library as the implementation of +those crafty data structures and algorithms you can find in OpenCV. Therefore, the +source codes for the tutorials are part of the library. And yes, I meant source +codes. The reason for this formulation is that the tutorials are written by using the +|Sphinx|_ documentation generation system. This is based on the popular Python +documentation system called |reST|_ (reST). ReStructuredText is a really neat +language that by using a few simple conventions (indentation, directives) and +emulating old school email writing techniques (text only) tries to offer a simple +way to create and edit documents. Sphinx extends this with some new features and +creates the resulting document in both HTML (for web) and PDF (for offline usage) +format. + + +Usually, an OpenCV tutorial has the following parts: + +1. A source code demonstration of an OpenCV feature: + + a. One or more CPP, Python, Java or other type of files depending for what OpenCV offers support and for what language you make the tutorial. + #. Occasionaly, input resource files required for running your tutorials application. + + +#. A table of content entry (so people may easily find the tutorial): + + a. Adding your stuff to the tutorials table of content (**reST** file). + #. Add an image file near the TOC entry. + + +#. The content of the tutorial itself: + + a. The **reST** text of the tutorial + #. Images following the idea that "*A picture is worth a thousand words*". + #. For more complex demonstrations you may create a video. + +As you can see you will need at least some basic knowledge of the *reST* system in order to complete the task at hand with success. However, don't worry *reST* (and *Sphinx*) was made with simplicity in mind. It is easy to grasp its basics. I found that the `OpenAlea documentations introduction on this subject `_ (or the `Thomas Cokelaer one `_ ) should enough for this. If for some directive or feature you need a more in-depth description look it up in the official |reST|_ help files or at the |Sphinx|_ documentation. + +In our world achieving some tasks is possible in multiple ways. However, some of the roads to take may have obvious or hidden advantages over others. Then again, in some other cases it may come down to just simple user preference. Here, I'll present how I decided to write the tutorials, based on my personal experience. If for some of them you know a better solution and you can back it up feel free to use that. I've nothing against it, as long as it gets the job done in an elegant fashion. + +Now the best would be if you could make the integration yourself. For this you need first to have the source code. I recommend following the guides for your operating system on acquiring OpenCV sources. For Linux users look :ref:`here ` and for :ref:`Windows here `. You must also install python and sphinx with its dependencies in order to be able to build the documentation. + +Once you have downloaded the repository to your hard drive you can take a look in the OpenCV directory to make sure you have both the samples and doc folder present. Anyone may download the latest source files from :file:`git://github.com/Itseez/opencv.git` . Nevertheless, not everyone has upload (commit/submit) rights. This is to protect the integrity of the library. If you plan doing more than one tutorial, and would like to have an account with commit user rights you should first register an account at http://code.opencv.org/ and then contact OpenCV administrator -delete-admin@-delete-opencv.org. Otherwise, you can just send the resulting files to us at -delete-admin@-delete-opencv.org and we'll add it. + + +Format the Source Code +====================== + +Before I start this let it be clear: the main goal is to have a working sample code. However, for your tutorial to be of a top notch quality you should follow a few guide lines I am going to present here. In case you have an application by using the older interface (with *IplImage*, *cvMat*, *cvLoadImage* and such) consider migrating it to the new C++ interface. The tutorials are intended to be an up to date help for our users. And as of OpenCV 2 the OpenCV emphasis on using the less error prone and clearer C++ interface. Therefore, if possible please convert your code to the C++ interface. For this it may help to read the :ref:`InteroperabilityWithOpenCV1` tutorial. However, once you have an OpenCV 2 working code, then you should make your source code snippet as easy to read as possible. Here're a couple of advices for this: + + +.. container:: enumeratevisibleitemswithsquare + + + Add a standard output with the description of what your program does. Keep it short and yet, descriptive. This output is at the start of the program. In my example files this usually takes the form of a *help* function containing the output. This way both the source file viewer and application runner can see what all is about in your sample. Here's an instance of this: + + .. code-block:: cpp + + void help() + { + cout + << "--------------------------------------------------------------------------" << endl + << "This program shows how to write video files. You can extract the R or G or B color channel " + << " of the input video. You can choose to use the source codec (Y) or select a custom one. (N)"<< endl + << "Usage:" << endl + << "./video-write inputvideoName [ R | G | B] [Y | N]" << endl + << "--------------------------------------------------------------------------" << endl + << endl; + } + // ... + int main(int argc, char *argv[], char *window_name) + { + help(); + // here comes the actual source code + } + + Additionally, finalize the description with a short usage guide. This way the user will know how to call your programs, what leads us to the next point. + + + Prefer command line argument controlling instead of hard coded one. If your program has some variables that may be changed use command line arguments for this. The tutorials, can be a simple try-out ground for the user. If you offer command line controlling for the input image (for example), then you offer the possibility for the user to try it out with his/her own images, without the need to mess in the source code. In the upper example you can see that the input image, channel and codec selection may all be changed from the command line. Just compile the program and run it with your own input arguments. + + + Be as verbose as possible. There is no shame in filling the source code with comments. This way the more advanced user may figure out what's happening right from the sample code. This advice goes for the output console too. Specify to the user what's happening. Never leave the user hanging there and thinking on: "Is this program now crashing or just doing some computationally intensive task?." So, if you do a training task that may take some time, make sure you print out a message about this before starting and after finishing it. + + + Throw out unnecessary stuff from your source code. This is a warning to not take the previous point too seriously. Balance is the key. If it's something that can be done in a fewer lines or simpler than that's the way you should do it. Nevertheless, if for some reason you have such sections notify the user why you have chosen to do so. Keep the amount of information as low as possible, while still getting the job done in an elegant way. + + + Put your sample file into the :file:`opencv/samples/cpp/tutorial_code/sectionName` folder. If you write a tutorial for other languages than cpp, then change that part of the path. Before completing this you need to decide that to what section (module) does your tutorial goes. Think about on what module relies most heavily your code and that is the one to use. If the answer to this question is more than one modules then the *general* section is the one to use. For finding the *opencv* directory open up your file system and navigate where you downloaded our repository. + + + If the input resources are hard to acquire for the end user consider adding a few of them to the :file:`opencv/samples/cpp/tutorial_code/images`. Make sure that who reads your code can try it out! + +Add the TOC entry +================= + +For this you will need to know some |reST|_. There is no going around this. |reST|_ files have **rst** extensions. However, these are simple text files. Use any text editor you like. Finding a text editor that offers syntax highlighting for |reST|_ was quite a challenge at the time of writing this tutorial. In my experience, `Intype `_ is a solid option on Windows, although there is still place for improvement. + +Adding your source code to a table of content is important for multiple reasons. First and foremost this will allow for the user base to find your tutorial from our websites tutorial table of content. Secondly, if you omit this *Sphinx* will throw a warning that your tutorial file isn't part of any TOC tree entry. And there is nothing more than the developer team hates than an ever increasing warning/error list for their builds. *Sphinx* also uses this to build up the previous-back-up buttons on the website. Finally, omitting this step will lead to that your tutorial will **not** be added to the PDF version of the tutorials. + +Navigate to the :file:`opencv/doc/tutorials/section/table_of_content_section` folder (where the section is the module to which you're adding the tutorial). Open the *table_of_content_section* file. Now this may have two forms. If no prior tutorials are present in this section that there is a template message about this and has the following form: + +.. code-block:: rst + + .. _Table-Of-Content-Section: + + Section title + ----------------------------------------------------------- + + Description about the section. + + .. include:: ../../definitions/noContent.rst + + .. raw:: latex + + \pagebreak + +The first line is a reference to the section title in the reST system. The section title will be a link and you may refer to it via the ``:ref:`` directive. The *include* directive imports the template text from the definitions directories *noContent.rst* file. *Sphinx* does not creates the PDF from scratch. It does this by first creating a latex file. Then creates the PDF from the latex file. With the *raw* directive you can directly add to this output commands. Its unique argument is for what kind of output to add the content of the directive. For the PDFs it may happen that multiple sections will overlap on a single page. To avoid this at the end of the TOC we add a *pagebreak* latex command, that hints to the LATEX system that the next line should be on a new page. + +If you have one of this, try to transform it to the following form: + +.. include:: ../../definitions/tocDefinitions.rst + +.. code-block:: rst + + .. _Table-Of-Content-Section: + + Section title + ----------------------------------------------------------- + + .. include:: ../../definitions/tocDefinitions.rst + + + + .. tabularcolumns:: m{100pt} m{300pt} + .. cssclass:: toctableopencv + + =============== ====================================================== + |MatBasicIma| **Title:** :ref:`matTheBasicImageContainer` + + *Compatibility:* > OpenCV 2.0 + + *Author:* |Author_BernatG| + + You will learn how to store images in the memory and how to print out their content to the console. + + =============== ===================================================== + + .. |MatBasicIma| image:: images/matTheBasicImageStructure.jpg + :height: 90pt + :width: 90pt + + .. raw:: latex + + \pagebreak + + .. toctree:: + :hidden: + + ../mat - the basic image container/mat - the basic image container + +If this is already present just add a new section of the content between the include and the raw directives (excluding those lines). Here you'll see a new include directive. This should be present only once in a TOC tree and the reST file contains the definitions of all the authors contributing to the OpenCV tutorials. We are a multicultural community and some of our name may contain some funky characters. However, reST **only supports** ANSI characters. Luckily we can specify Unicode characters with the *unicode* directive. Doing this for all of your tutorials is a troublesome procedure. Therefore, the tocDefinitions file contains the definition of your author name. Add it here once and afterwards just use the replace construction. For example here's the definition for my name: + +.. code-block:: rst + + .. |Author_BernatG| unicode:: Bern U+00E1 t U+0020 G U+00E1 bor + +The ``|Author_BernatG|`` is the text definitions alias. I can use later this to add the definition, like I've done in the TOCs *Author* part. After the ``::`` and a space you start the definition. If you want to add an UNICODE character (non-ASCI) leave an empty space and specify it in the format U+(UNICODE code). To find the UNICODE code of a character I recommend using the `FileFormat `_ websites service. Spaces are trimmed from the definition, therefore we add a space by its UNICODE character (U+0020). + +Until the *raw* directive what you can see is a TOC tree entry. Here's how a TOC entry will look like: + ++ + .. tabularcolumns:: m{100pt} m{300pt} + .. cssclass:: toctableopencv + + =============== ====================================================== + |MatBasicIma| **Title:** :ref:`matTheBasicImageContainer` + + *Compatibility:* > OpenCV 2.0 + + *Author:* |Author_BernatG| + + You will learn how to store images in the memory and how to print out their content to the console. + + =============== ====================================================== + + .. |MatBasicIma| image:: images/matTheBasicImageStructure.jpg + :height: 90pt + :width: 90pt + +As you can see we have an image to the left and a description box to the right. To create two boxes we use a table with two columns and a single row. In the left column is the image and in the right one the description. However, the image directive is way too long to fit in a column. Therefore, we need to use the substitution definition system. We add this definition after the TOC tree. All images for the TOC tree are to be put in the images folder near its |reST|_ file. We use the point measurement system because we are also creating PDFs. PDFs are printable documents, where there is no such thing that pixels (px), just points (pt). And while generally space is no problem for web pages (we have monitors with **huge** resolutions) the size of the paper (A4 or letter) is constant and will be for a long time in the future. Therefore, size constrains come in play more like for the PDF, than the generated HTML code. + +Now your images should be as small as possible, while still offering the intended information for the user. Remember that the tutorial will become part of the OpenCV source code. If you add large images (that manifest in form of large image size) it will just increase the size of the repository pointlessly. If someone wants to download it later, its download time will be that much longer. Not to mention the larger PDF size for the tutorials and the longer load time for the web pages. In terms of pixels a TOC image should not be larger than 120 X 120 pixels. Resize your images if they are larger! + +.. note:: + + If you add a larger image and specify a smaller image size, *Sphinx* will not resize that. At build time will add the full size image and the resize will be done by your browser after the image is loaded. A 120 X 120 image is somewhere below 10KB. If you add a 110KB image, you have just pointlessly added a 100KB extra data to transfer over the internet for every user! + +Generally speaking you shouldn't need to specify your images size (excluding the TOC entries). If no such is found *Sphinx* will use the size of the image itself (so no resize occurs). Then again if for some reason you decide to specify a size that should be the **width** of the image rather than its height. The reason for this again goes back to the PDFs. On a PDF page the height is larger than the width. In the PDF the images will not be resized. If you specify a size that does not fit in the page, then what does not fits in **will be cut off**. When creating your images for your tutorial you should try to keep the image widths below 500 pixels, and calculate with around 400 point page width when specifying image widths. + +The image format depends on the content of the image. If you have some complex scene (many random like colors) then use *jpg*. Otherwise, prefer using *png*. They are even some tools out there that optimize the size of *PNG* images, such as `PNGGauntlet `_. Use them to make your images as small as possible in size. + +Now on the right side column of the table we add the information about the tutorial: + +.. container:: enumeratevisibleitemswithsquare + + + In the first line it is the title of the tutorial. However, there is no need to specify it explicitly. We use the reference system. We'll start up our tutorial with a reference specification, just like in case of this TOC entry with its `` .. _Table-Of-Content-Section:`` . If after this you have a title (pointed out by the following line of -), then Sphinx will replace the ``:ref:`Table-Of-Content-Section``` directive with the tile of the section in reference form (creates a link in web page). Here's how the definition looks in my case: + + .. code-block:: rst + + .. _matTheBasicImageContainer: + + Mat - The Basic Image Container + ******************************* + + Note, that according to the |reST|_ rules the * should be as long as your title. + + + Compatibility. What version of OpenCV is required to run your sample code. + + + Author. Use the substitution markup of |reST|_. + + + A short sentence describing the essence of your tutorial. + +Now before each TOC entry you need to add the three lines of: + +.. code-block:: cpp + + + + .. tabularcolumns:: m{100pt} m{300pt} + .. cssclass:: toctableopencv + +The plus sign (+) is to enumerate tutorials by using bullet points. So for every TOC entry we have a corresponding bullet point represented by the +. Sphinx is highly indenting sensitive. Indentation is used to express from which point until to which point does a construction last. Un-indentation means end of that construction. So to keep all the bullet points to the same group the following TOC entries (until the next +) should be indented by two spaces. + +Here, I should also mention that **always** prefer using spaces instead of tabs. Working with only spaces makes possible that if we both use monotype fonts we will see the same thing. Tab size is text editor dependent and as should be avoided. *Sphinx* translates all tabs into 8 spaces before interpreting it. + +It turns out that the automatic formatting of both the HTML and PDF(LATEX) system messes up our tables. Therefore, we need to help them out a little. For the PDF generation we add the ``.. tabularcolumns:: m{100pt} m{300pt}`` directive. This means that the first column should be 100 points wide and middle aligned. For the HTML look we simply name the following table of a *toctableopencv* class type. Then, we can modify the look of the table by modifying the CSS of our web page. The CSS definitions go into the :file:`opencv/doc/_themes/blue/static/default.css_t` file. + +.. code-block:: css + + .toctableopencv + { + width: 100% ; + table-layout: fixed; + } + + + .toctableopencv colgroup col:first-child + { + width: 100pt !important; + max-width: 100pt !important; + min-width: 100pt !important; + } + + .toctableopencv colgroup col:nth-child(2) + { + width: 100% !important; + } + +However, you should not need to modify this. Just add these three lines (plus keep the two space indentation) for all TOC entries you add. At the end of the TOC file you'll find: + +.. code-block:: rst + + .. raw:: latex + + \pagebreak + + .. toctree:: + :hidden: + + ../mat - the basic image container/mat - the basic image container + +The page break entry comes for separating sections and should be only one in a TOC tree |reST|_ file. Finally, at the end of the TOC tree we need to add our tutorial to the *Sphinx* TOC tree system. *Sphinx* will generate from this the previous-next-up information for the HTML file and add items to the PDF according to the order here. By default this TOC tree directive generates a simple table of contents. However, we already created a fancy looking one so we no longer need this basic one. Therefore, we add the *hidden* option to do not show it. + +The path is of a relative type. We step back in the file system and then go into the :file:`mat - the basic image container` directory for the :file:`mat - the basic image container.rst` file. Putting out the *rst* extension for the file is optional. + +Write the tutorial +================== + +Create a folder with the name of your tutorial. Preferably, use small letters only. Then create a text file in this folder with *rst* extension and the same name. If you have images for the tutorial create an :file:`images` folder and add your images there. When creating your images follow the guidelines described in the previous part! + +Now here's our recommendation for the structure of the tutorial (although, remember that this is not carved in the stone; if you have a better idea, use it!): + + +.. container:: enumeratevisibleitemswithsquare + + + Create the reference point and the title. + + .. code-block:: rst + + .. _matTheBasicImageContainer: + + Mat - The Basic Image Container + ******************************* + + You start the tutorial by specifying a reference point by the ``.. _matTheBasicImageContainer:`` and then its title. The name of the reference point should be a unique one over the whole documentation. Therefore, do not use general names like *tutorial1*. Use the * character to underline the title for its full width. The subtitles of the tutorial should be underlined with = charachter. + + + Goals. You start your tutorial by specifying what you will present. You can also enumerate the sub jobs to be done. For this you can use a bullet point construction. There is a single configuration file for both the reference manual and the tutorial documentation. In the reference manuals at the argument enumeration we do not want any kind of bullet point style enumeration. Therefore, by default all the bullet points at this level are set to do not show the dot before the entries in the HTML. You can override this by putting the bullet point in a container. I've defined a square type bullet point view under the name *enumeratevisibleitemswithsquare*. The CSS style definition for this is again in the :file:`opencv\doc\_themes\blue\static\default.css_t` file. Here's a quick example of using it: + + .. code-block:: rst + + .. container:: enumeratevisibleitemswithsquare + + + Create the reference point and the title. + + Second entry + + Third entry + + Note that you need the keep the indentation of the container directive. Directive indentations are always three (3) spaces. Here you may even give usage tips for your sample code. + + + Source code. Present your samples code to the user. It's a good idea to offer a quick download link for the HTML page by using the *download* directive and pointing out where the user may find your source code in the file system by using the *file* directive: + + .. code-block:: rst + + Text :file:`samples/cpp/tutorial_code/highgui/video-write/` folder of the OpenCV source library + or :download:`text to appear in the webpage + <../../../../samples/cpp/tutorial_code/HighGUI/video-write/video-write.cpp>`. + + For the download link the path is a relative one, hence the multiple back stepping operations (..). Then you can add the source code either by using the *code block* directive or the *literal include* one. In case of the code block you will need to actually add all the source code text into your |reST|_ text and also apply the required indentation: + + .. code-block:: rst + + .. code-block:: cpp + + int i = 0; + l = ++j; + + The only argument of the directive is the language used (here CPP). Then you add the source code into its content (meaning one empty line after the directive) by keeping the indentation of the directive (3 spaces). With the *literal include* directive you do not need to add the source code of the sample. You just specify the sample and *Sphinx* will load it for you, during build time. Here's an example usage: + + .. code-block:: rst + + .. literalinclude:: ../../../../samples/cpp/tutorial_code/HighGUI/video-write/video-write.cpp + :language: cpp + :linenos: + :tab-width: 4 + :lines: 1-8, 21-22, 24- + + After the directive you specify a relative path to the file from what to import. It has four options: the language to use, if you add the ``:linenos:`` the line numbers will be shown, you can specify the tab size with the ``:tab-width:`` and you do not need to load the whole file, you can show just the important lines. Use the *lines* option to do not show redundant information (such as the *help* function). Here basically you specify ranges, if the second range line number is missing than that means that until the end of the file. The ranges specified here do no need to be in an ascending order, you may even reorganize the structure of how you want to show your sample inside the tutorial. + + + The tutorial. Well here goes the explanation for why and what have you used. Try to be short, clear, concise and yet a thorough one. There's no magic formula. Look into a few already made tutorials and start out from there. Try to mix sample OpenCV code with your explanations. If with words is hard to describe something do not hesitate to add in a reasonable size image, to overcome this issue. + + When you present OpenCV functionality it's a good idea to give a link to the used OpenCV data structure or function. Because the OpenCV tutorials and reference manual are in separate PDF files it is not possible to make this link work for the PDF format. Therefore, we use here only web page links to the http://docs.opencv.org website. The OpenCV functions and data structures may be used for multiple tasks. Nevertheless, we want to avoid that every users creates its own reference to a commonly used function. So for this we use the global link collection of *Sphinx*. This is defined in the file:`opencv/doc/conf.py` configuration file. Open it and go all the way down to the last entry: + + .. code-block:: py + + # ---- External links for tutorials ----------------- + extlinks = { + 'hgvideo' : ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#%s', None) + } + + In short here we defined a new **hgvideo** directive that refers to an external webpage link. Its usage is: + + .. code-block:: rst + + A sample function of the highgui modules image write and read page is the :hgvideo:`imread() function `. + + Which turns to: A sample function of the highgui modules image write and read page is the :hgvideo:`imread() function `. The argument you give between the <> will be put in place of the ``%s`` in the upper definition, and as the link will anchor to the correct function. To find out the anchor of a given function just open up a web page, search for the function and click on it. In the address bar it should appear like: ``http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#imread`` . Look here for the name of the directives for each page of the OpenCV reference manual. If none present for one of them feel free to add one for it. + + For formulas you can add LATEX code that will translate in the web pages into images. You do this by using the *math* directive. A usage tip: + + .. code-block:: latex + + .. math:: + + MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2} + + That after build turns into: + + .. math:: + + MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2} + + You can even use it inline as ``:math:` MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2}``` that turns into :math:`MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2}`. + + If you use some crazy LATEX library extension you need to add those to the ones to use at build time. Look into the file:`opencv/doc/conf.py` configuration file for more information on this. + + + Results. Well, here depending on your program show one of more of the following: + + - Console outputs by using the code block directive. + - Output images. + - Runtime videos, visualization. For this use your favorite screens capture software. `Camtasia Studio `_ certainly is one of the better choices, however their prices are out of this world. `CamStudio `_ is a free alternative, but less powerful. If you do a video you can upload it to YouTube and then use the raw directive with HTML option to embed it into the generated web page: + + .. code-block:: rst + + You may observe a runtime instance of this on the `YouTube here `_. + + .. raw:: html + +
    + +
    + + This results in the text and video: You may observe a runtime instance of this on the `YouTube here `_. + + .. raw:: html + +
    + +
    + + When these aren't self-explanatory make sure to throw in a few guiding lines about what and why we can see. + + + Build the documentation and check for errors or warnings. In the CMake make sure you check or pass the option for building documentation. Then simply build the **docs** project for the PDF file and the **docs_html** project for the web page. Read the output of the build and check for errors/warnings for what you have added. This is also the time to observe and correct any kind of *not so good looking* parts. Remember to keep clean our build logs. + + + Read again your tutorial and check for both programming and spelling errors. If found any, please correct them. + + +Take home the pride and joy of a job well done! +=============================================== + +Once you are done please make a GitHub pull request with the tutorial. Now, to see +your work **live** you may need to wait some time. The PDFs are updated usually at +the launch of a new OpenCV version. The web pages are a little more diverse. They are +automatically rebuilt nightly. Currently we use ``2.4`` and ``master`` branches for +daily builds. So, if your pull request was merged to any of these branches, your +material will be published at `docs.opencv.org/2.4 `_ or +`docs.opencv.org/master `_ correspondingly. Everything +that was added to ``2.4`` is merged to ``master`` branch every week. Although, we try +to make a build every night, occasionally we might freeze any of the branches to fix +upcoming issues. During this it may take a little longer to see your work online, +however if you submitted it, be sure that eventually it will show up. + +If you have any questions or advices relating to this tutorial you can contact us at +-delete-admin@-delete-opencv.org (delete the -delete- parts of that email address). diff --git a/doc/tutorials/introduction/ios_install/ios_install.rst b/doc/tutorials/introduction/ios_install/ios_install.rst index cb9e0650b2..2973b7ec2b 100644 --- a/doc/tutorials/introduction/ios_install/ios_install.rst +++ b/doc/tutorials/introduction/ios_install/ios_install.rst @@ -37,7 +37,7 @@ Building OpenCV from Source, using CMake and Command Line .. code-block:: bash cd ~/ - python opencv/ios/build_framework.py ios + python opencv/platforms/ios/build_framework.py ios If everything's fine, a few minutes later you will get ~//ios/opencv2.framework. You can add this framework to your Xcode projects. diff --git a/doc/tutorials/introduction/linux_eclipse/linux_eclipse.rst b/doc/tutorials/introduction/linux_eclipse/linux_eclipse.rst index c1a6fac000..74e0ff9e09 100644 --- a/doc/tutorials/introduction/linux_eclipse/linux_eclipse.rst +++ b/doc/tutorials/introduction/linux_eclipse/linux_eclipse.rst @@ -65,8 +65,7 @@ Making a project .. code-block:: cpp - #include - #include + #include using namespace cv; @@ -81,7 +80,7 @@ Making a project return -1; } - namedWindow( "Display Image", CV_WINDOW_AUTOSIZE ); + namedWindow( "Display Image", WINDOW_AUTOSIZE ); imshow( "Display Image", image ); waitKey(0); @@ -201,29 +200,20 @@ Assuming that the image to use as the argument would be located in ` section of the OpenCV Wiki) - Say you have or create a new file, *helloworld.cpp* in a directory called *foo*: .. code-block:: cpp - #include - #include + #include + using namespace cv; + int main ( int argc, char **argv ) { - cvNamedWindow( "My Window", 1 ); - IplImage *img = cvCreateImage( cvSize( 640, 480 ), IPL_DEPTH_8U, 1 ); - CvFont font; - double hScale = 1.0; - double vScale = 1.0; - int lineWidth = 1; - cvInitFont( &font, CV_FONT_HERSHEY_SIMPLEX | CV_FONT_ITALIC, - hScale, vScale, 0, lineWidth ); - cvPutText( img, "Hello World!", cvPoint( 200, 400 ), &font, - cvScalar( 255, 255, 0 ) ); - cvShowImage( "My Window", img ); - cvWaitKey(); + Mat img(480, 640, CV_8U); + putText(img, "Hello World!", Point( 200, 400 ), FONT_HERSHEY_SIMPLEX | FONT_ITALIC, 1.0, Scalar( 255, 255, 0 )); + imshow("My Window", img); + waitKey(); return 0; } @@ -255,6 +245,3 @@ Say you have or create a new file, *helloworld.cpp* in a directory called *foo*: a. You can also optionally modify the ``Build command:`` from ``make`` to something like ``make VERBOSE=1 -j4`` which tells the compiler to produce detailed symbol files for debugging and also to compile in 4 parallel threads. #. Done! - - - diff --git a/doc/tutorials/introduction/linux_install/linux_install.rst b/doc/tutorials/introduction/linux_install/linux_install.rst index e8b96dab73..1e02b64c9d 100644 --- a/doc/tutorials/introduction/linux_install/linux_install.rst +++ b/doc/tutorials/introduction/linux_install/linux_install.rst @@ -80,4 +80,3 @@ Building OpenCV from Source Using CMake, Using the Command Line .. note:: If the size of the created library is a critical issue (like in case of an Android build) you can use the ``install/strip`` command to get the smallest size as possible. The *stripped* version appears to be twice as small. However, we do not recommend using this unless those extra megabytes do really matter. - diff --git a/doc/tutorials/introduction/load_save_image/load_save_image.rst b/doc/tutorials/introduction/load_save_image/load_save_image.rst index 50fb9ea37f..ac0ee02e5d 100644 --- a/doc/tutorials/introduction/load_save_image/load_save_image.rst +++ b/doc/tutorials/introduction/load_save_image/load_save_image.rst @@ -26,8 +26,7 @@ Here it is: .. code-block:: cpp :linenos: - #include - #include + #include using namespace cv; @@ -45,12 +44,12 @@ Here it is: } Mat gray_image; - cvtColor( image, gray_image, CV_BGR2GRAY ); + cvtColor( image, gray_image, COLOR_BGR2GRAY ); imwrite( "../../images/Gray_Image.jpg", gray_image ); - namedWindow( imageName, CV_WINDOW_AUTOSIZE ); - namedWindow( "Gray image", CV_WINDOW_AUTOSIZE ); + namedWindow( imageName, WINDOW_AUTOSIZE ); + namedWindow( "Gray image", WINDOW_AUTOSIZE ); imshow( imageName, image ); imshow( "Gray image", gray_image ); diff --git a/doc/tutorials/introduction/table_of_content_introduction/images/visual_studio_image_watch.png b/doc/tutorials/introduction/table_of_content_introduction/images/visual_studio_image_watch.png new file mode 100755 index 0000000000..e693344df8 Binary files /dev/null and b/doc/tutorials/introduction/table_of_content_introduction/images/visual_studio_image_watch.png differ diff --git a/doc/tutorials/introduction/table_of_content_introduction/table_of_content_introduction.rst b/doc/tutorials/introduction/table_of_content_introduction/table_of_content_introduction.rst index 5e91a5392c..2238b87878 100644 --- a/doc/tutorials/introduction/table_of_content_introduction/table_of_content_introduction.rst +++ b/doc/tutorials/introduction/table_of_content_introduction/table_of_content_introduction.rst @@ -103,6 +103,21 @@ world of the OpenCV. :height: 90pt :width: 90pt + =========== ====================================================== + |WinVSVis| **Title:** :ref:`Windows_Visual_Studio_Image_Watch` + + *Compatibility:* >= OpenCV 2.4 + + *Author:* Wolf Kienzle + + You will learn how to visualize OpenCV matrices and images within Visual Studio 2012. + + =========== ====================================================== + + .. |WinVSVis| image:: images/visual_studio_image_watch.png + :height: 90pt + :width: 90pt + * **Desktop Java** .. tabularcolumns:: m{100pt} m{300pt} @@ -278,6 +293,7 @@ world of the OpenCV. ../linux_eclipse/linux_eclipse ../windows_install/windows_install ../windows_visual_studio_Opencv/windows_visual_studio_Opencv + ../windows_visual_studio_image_watch/windows_visual_studio_image_watch ../desktop_java/java_dev_intro ../android_binary_package/android_dev_intro ../android_binary_package/O4A_SDK diff --git a/doc/tutorials/introduction/windows_install/windows_install.rst b/doc/tutorials/introduction/windows_install/windows_install.rst index eebda7b066..c29c13aede 100644 --- a/doc/tutorials/introduction/windows_install/windows_install.rst +++ b/doc/tutorials/introduction/windows_install/windows_install.rst @@ -292,7 +292,7 @@ Building the library This will create an *Install* directory inside the *Build* one collecting all the built binaries into a single place. Use this only after you built both the *Release* and *Debug* versions. - To test your build just go into the :file:`Build/bin/Debug` or :file:`Build/bin/Release` directory and start a couple of applications like the *contours.exe*. If they run, you are done. Otherwise, something definitely went awfully wrong. In this case you should contact us via our :opencv_group:`user group <>`. + To test your build just go into the :file:`Build/bin/Debug` or :file:`Build/bin/Release` directory and start a couple of applications like the *contours.exe*. If they run, you are done. Otherwise, something definitely went awfully wrong. In this case you should contact us at our :opencv_qa:`Q&A forum <>`. If everything is okay the *contours.exe* output should resemble the following image (if built with Qt support): .. image:: images/WindowsQtContoursOutput.png @@ -312,9 +312,13 @@ First we set an enviroment variable to make easier our work. This will hold the :: - setx -m OPENCV_DIR D:\OpenCV\Build\x86\vc10 + setx -m OPENCV_DIR D:\OpenCV\Build\x86\vc10 (suggested for Visual Studio 2010 - 32 bit Windows) + setx -m OPENCV_DIR D:\OpenCV\Build\x64\vc10 (suggested for Visual Studio 2010 - 64 bit Windows) -Here the directory is where you have your OpenCV binaries (*extracted* or *built*). You can have different platform (e.g. x64 instead of x86) or compiler type, so substitute appropriate value. Inside this you should have folders like *bin* and *include*. The -m should be added if you wish to make the settings computer wise, instead of user wise. + setx -m OPENCV_DIR D:\OpenCV\Build\x86\vc11 (suggested for Visual Studio 2012 - 32 bit Windows) + setx -m OPENCV_DIR D:\OpenCV\Build\x64\vc11 (suggested for Visual Studio 2012 - 64 bit Windows) + +Here the directory is where you have your OpenCV binaries (*extracted* or *built*). You can have different platform (e.g. x64 instead of x86) or compiler type, so substitute appropriate value. Inside this you should have two folders called *lib* and *bin*. The -m should be added if you wish to make the settings computer wise, instead of user wise. If you built static libraries then you are done. Otherwise, you need to add the *bin* folders path to the systems path. This is cause you will use the OpenCV library in form of *\"Dynamic-link libraries\"* (also known as **DLL**). Inside these are stored all the algorithms and information the OpenCV library contains. The operating system will load them only on demand, during runtime. However, to do this he needs to know where they are. The systems **PATH** contains a list of folders where DLLs can be found. Add the OpenCV library path to this and the OS will know where to look if he ever needs the OpenCV binaries. Otherwise, you will need to copy the used DLLs right beside the applications executable file (*exe*) for the OS to find it, which is highly unpleasent if you work on many projects. To do this start up again the |PathEditor|_ and add the following new entry (right click in the application to bring up the menu): diff --git a/doc/tutorials/introduction/windows_visual_studio_Opencv/images/PropertySheetOpenCVInclude.jpg b/doc/tutorials/introduction/windows_visual_studio_Opencv/images/PropertySheetOpenCVInclude.jpg index 5826f4dd6c..bc61d33862 100644 Binary files a/doc/tutorials/introduction/windows_visual_studio_Opencv/images/PropertySheetOpenCVInclude.jpg and b/doc/tutorials/introduction/windows_visual_studio_Opencv/images/PropertySheetOpenCVInclude.jpg differ diff --git a/doc/tutorials/introduction/windows_visual_studio_Opencv/windows_visual_studio_Opencv.rst b/doc/tutorials/introduction/windows_visual_studio_Opencv/windows_visual_studio_Opencv.rst index ec227e7241..f3058a74d2 100644 --- a/doc/tutorials/introduction/windows_visual_studio_Opencv/windows_visual_studio_Opencv.rst +++ b/doc/tutorials/introduction/windows_visual_studio_Opencv/windows_visual_studio_Opencv.rst @@ -52,7 +52,7 @@ Use for example the *OpenCV_Debug* name. Then by selecting the sheet :menuselect .. code-block:: bash - $(OPENCV_DIR)\include + $(OPENCV_DIR)\..\..\include .. image:: images/PropertySheetOpenCVInclude.jpg :alt: Add the include dir like this. @@ -64,7 +64,7 @@ Next go to the :menuselection:`Linker --> General` and under the *"Additional Li .. code-block:: bash - $(OPENCV_DIR)\libs + $(OPENCV_DIR)\lib .. image:: images/PropertySheetOpenCVLib.jpg :alt: Add the library folder like this. @@ -86,7 +86,7 @@ The names of the libraries are as follow: opencv_(The Name of the module)(The version Number of the library you use)d.lib -A full list, for the currently latest trunk version would contain: +A full list, for the latest version would contain: .. code-block:: bash diff --git a/doc/tutorials/introduction/windows_visual_studio_image_watch/images/breakpoint.png b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/breakpoint.png new file mode 100755 index 0000000000..2597a8deb8 Binary files /dev/null and b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/breakpoint.png differ diff --git a/doc/tutorials/introduction/windows_visual_studio_image_watch/images/edges_zoom.png b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/edges_zoom.png new file mode 100755 index 0000000000..8c76959988 Binary files /dev/null and b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/edges_zoom.png differ diff --git a/doc/tutorials/introduction/windows_visual_studio_image_watch/images/help_button.jpg b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/help_button.jpg new file mode 100644 index 0000000000..38aa809d5b Binary files /dev/null and b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/help_button.jpg differ diff --git a/doc/tutorials/introduction/windows_visual_studio_image_watch/images/input_zoom.png b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/input_zoom.png new file mode 100755 index 0000000000..d4e2df7fb0 Binary files /dev/null and b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/input_zoom.png differ diff --git a/doc/tutorials/introduction/windows_visual_studio_image_watch/images/toolwindow.jpg b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/toolwindow.jpg new file mode 100644 index 0000000000..cd60c00b2d Binary files /dev/null and b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/toolwindow.jpg differ diff --git a/doc/tutorials/introduction/windows_visual_studio_image_watch/images/viewer.jpg b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/viewer.jpg new file mode 100644 index 0000000000..95f4b81a58 Binary files /dev/null and b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/viewer.jpg differ diff --git a/doc/tutorials/introduction/windows_visual_studio_image_watch/images/viewer_context_menu.png b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/viewer_context_menu.png new file mode 100755 index 0000000000..902f23a3dc Binary files /dev/null and b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/viewer_context_menu.png differ diff --git a/doc/tutorials/introduction/windows_visual_studio_image_watch/images/visual_studio_image_watch.png b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/visual_studio_image_watch.png new file mode 100755 index 0000000000..e693344df8 Binary files /dev/null and b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/visual_studio_image_watch.png differ diff --git a/doc/tutorials/introduction/windows_visual_studio_image_watch/images/vs_locals.png b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/vs_locals.png new file mode 100755 index 0000000000..0df403467a Binary files /dev/null and b/doc/tutorials/introduction/windows_visual_studio_image_watch/images/vs_locals.png differ diff --git a/doc/tutorials/introduction/windows_visual_studio_image_watch/windows_visual_studio_image_watch.rst b/doc/tutorials/introduction/windows_visual_studio_image_watch/windows_visual_studio_image_watch.rst new file mode 100644 index 0000000000..91b411682d --- /dev/null +++ b/doc/tutorials/introduction/windows_visual_studio_image_watch/windows_visual_studio_image_watch.rst @@ -0,0 +1,144 @@ +.. _Windows_Visual_Studio_Image_Watch: + +Image Watch: viewing in-memory images in the Visual Studio debugger +******************************************************************* + +Image Watch is a plug-in for Microsoft Visual Studio that lets you to visualize in-memory images (*cv::Mat* or *IplImage\_* objects, for example) while debugging an application. This can be helpful for tracking down bugs, or for simply understanding what a given piece of code is doing. + +Prerequisites +============= + +This tutorial assumes that you have the following available: + +#. Visual Studio 2012 Professional (or better) with Update 1 installed. Update 1 can be downloaded `here `_. + +#. An OpenCV installation on your Windows machine (Tutorial: :ref:`Windows_Installation`). + +#. Ability to create and build OpenCV projects in Visual Studio (Tutorial: :ref:`Windows_Visual_Studio_How_To`). + +Installation +============ + +`Download `_ the Image Watch installer. The installer comes in a single file with extension .vsix (*Visual Studio Extension*). To launch it, simply double-click on the .vsix file in Windows Explorer. When the installer has finished, make sure to restart Visual Studio to complete the installation. + +Example +======== + +Image Watch works with any existing project that uses OpenCV image objects (for example, *cv::Mat*). In this example, we use a minimal test program that loads an image from a file and runs an edge detector. To build the program, create a console application project in Visual Studio, name it "image-watch-demo", and insert the source code below. + +.. code-block:: c++ + + // Test application for the Visual Studio Image Watch Debugger extension + + #include // std::cout + #include // cv::Mat + #include // cv::imread() + #include // cv::Canny() + + using namespace std; + using namespace cv; + + void help() + { + cout + << "----------------------------------------------------" << endl + << "This is a test program for the Image Watch Debugger " << endl + << "plug-in for Visual Studio. The program loads an " << endl + << "image from a file and runs the Canny edge detector. " << endl + << "No output is displayed or written to disk." + << endl + << "Usage:" << endl + << "image-watch-demo inputimage" << endl + << "----------------------------------------------------" << endl + << endl; + } + + int main(int argc, char *argv[]) + { + help(); + + if (argc != 2) + { + cout << "Wrong number of parameters" << endl; + return -1; + } + + cout << "Loading input image: " << argv[1] << endl; + Mat input; + input = imread(argv[1], CV_LOAD_IMAGE_COLOR); + + cout << "Detecting edges in input image" << endl; + Mat edges; + Canny(input, edges, 10, 100); + + return 0; + } + +Make sure your active solution configuration (:menuselection:`Build --> Configuration Manager`) is set to a debug build (usually called "Debug"). This should disable compiler optimizations so that viewing variables in the debugger can work reliably. + +Build your solution (:menuselection:`Build --> Build Solution`, or press *F7*). + +Now set a breakpoint on the source line that says + +.. code-block:: c++ + + Mat edges; + +To set the breakpoint, right-click on the source line and select :menuselection:`Breakpoints --> Insert Breakpoint` from the context menu. + +Launch the program in the debugger (:menuselection:`Debug --> Start Debugging`, or hit *F5*). When the breakpoint is hit, the program is paused and Visual Studio displays a yellow instruction pointer at the breakpoint: + +.. image:: images/breakpoint.png + +Now you can inspect the state of you program. For example, you can bring up the *Locals* window (:menuselection:`Debug --> Windows --> Locals`), which will show the names and values of the variables in the current scope: + +.. image:: images/vs_locals.png + +Note that the built-in *Locals* window will display text only. This is where the Image Watch plug-in comes in. Image Watch is like another *Locals* window, but with an image viewer built into it. To bring up Image Watch, select :menuselection:`View --> Other Windows --> Image Watch`. Like Visual Studio's *Locals* window, Image Watch can dock to the Visual Studio IDE. Also, Visual Studio will remember whether you had Image Watch open, and where it was located between debugging sessions. This means you only have to do this once--the next time you start debugging, Image Watch will be back where you left it. Here's what the docked Image Watch window looks like at our breakpoint: + +.. image:: images/toolwindow.jpg + :height: 320pt + +The radio button at the top left (*Locals/Watch*) selects what is shown in the *Image List* below: *Locals* lists all OpenCV image objects in the current scope (this list is automatically populated). *Watch* shows image expressions that have been pinned for continuous inspection (not described here, see `Image Watch documentation `_ for details). The image list shows basic information such as width, height, number of channels, and, if available, a thumbnail. In our example, the image list contains our two local image variables, *input* and *edges*. + +If an image has a thumbnail, left-clicking on that image will select it for detailed viewing in the *Image Viewer* on the right. The viewer lets you pan (drag mouse) and zoom (mouse wheel). It also displays the pixel coordinate and value at the current mouse position. + +.. image:: images/viewer.jpg + :height: 160pt + +Note that the second image in the list, *edges*, is shown as "invalid". This indicates that some data members of this image object have corrupt or invalid values (for example, a negative image width). This is expected at this point in the program, since the C++ constructor for *edges* has not run yet, and so its members have undefined values (in debug mode they are usually filled with "0xCD" bytes). + +From here you can single-step through your code (:menuselection:`Debug->Step Over`, or press *F10*) and watch the pixels change: if you step once, over the *Mat edges;* statement, the *edges* image will change from "invalid" to "empty", which means that it is now in a valid state (default constructed), even though it has not been initialized yet (using *cv::Mat::create()*, for example). If you make one more step over the *cv::Canny()* call, you will see a thumbnail of the edge image appear in the image list. + +Now assume you want to do a visual sanity check of the *cv::Canny()* implementation. Bring the *edges* image into the viewer by selecting it in the *Image List* and zoom into a region with a clearly defined edge: + +.. image:: images/edges_zoom.png + :height: 160pt + +Right-click on the *Image Viewer* to bring up the view context menu and enable :menuselection:`Link Views` (a check box next to the menu item indicates whether the option is enabled). + +.. image:: images/viewer_context_menu.png + :height: 120pt + +The :menuselection:`Link Views` feature keeps the view region fixed when flipping between images of the same size. To see how this works, select the input image from the image list--you should now see the corresponding zoomed-in region in the input image: + +.. image:: images/input_zoom.png + :height: 160pt + +You may also switch back and forth between viewing input and edges with your up/down cursor keys. That way you can easily verify that the detected edges line up nicely with the data in the input image. + +More ... +==================== + +Image watch has a number of more advanced features, such as + +#. pinning images to a *Watch* list for inspection across scopes or between debugging sessions + +#. clamping, thresholding, or diff'ing images directly inside the Watch window + +#. comparing an in-memory image against a reference image from a file + +Please refer to the online `Image Watch Documentation `_ for details--you also can get to the documentation page by clicking on the *Help* link in the Image Watch window: + +.. image:: images/help_button.jpg + :height: 80pt diff --git a/doc/tutorials/ios/hello/hello.rst b/doc/tutorials/ios/hello/hello.rst index b2a37aa703..8435be54dc 100644 --- a/doc/tutorials/ios/hello/hello.rst +++ b/doc/tutorials/ios/hello/hello.rst @@ -73,4 +73,3 @@ Now we will learn how to write a simple Hello World Application in Xcode using O .. image:: images/output.png :alt: output :align: center - diff --git a/doc/tutorials/ios/image_manipulation/image_manipulation.rst b/doc/tutorials/ios/image_manipulation/image_manipulation.rst index fd2d9c6e3f..c4cde19907 100644 --- a/doc/tutorials/ios/image_manipulation/image_manipulation.rst +++ b/doc/tutorials/ios/image_manipulation/image_manipulation.rst @@ -127,4 +127,4 @@ Check out an instance of running code with more Image Effects on `YouTube - \ No newline at end of file + diff --git a/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.rst b/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.rst index 051765def1..50f734803d 100644 --- a/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.rst +++ b/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.rst @@ -129,7 +129,7 @@ Explanation 3. **Train the SVM** - We call the method `CvSVM::train `_ to build the SVM model. + We call the method `CvSVM::train `_ to build the SVM model. .. code-block:: cpp @@ -185,4 +185,3 @@ Results .. image:: images/result.png :alt: The seperated planes :align: center - diff --git a/doc/tutorials/ml/non_linear_svms/non_linear_svms.rst b/doc/tutorials/ml/non_linear_svms/non_linear_svms.rst index 8fbcc563a7..57e0b1b6ea 100644 --- a/doc/tutorials/ml/non_linear_svms/non_linear_svms.rst +++ b/doc/tutorials/ml/non_linear_svms/non_linear_svms.rst @@ -1 +1,232 @@ -.. _nonLinearSvmS: Support Vector Machines for Non-Linearly Separable Data ******************************************************* Goal ==== In this tutorial you will learn how to: .. container:: enumeratevisibleitemswithsquare + Define the optimization problem for SVMs when it is not possible to separate linearly the training data. + How to configure the parameters in :svms:`CvSVMParams ` to adapt your SVM for this class of problems. Motivation ========== Why is it interesting to extend the SVM optimation problem in order to handle non-linearly separable training data? Most of the applications in which SVMs are used in computer vision require a more powerful tool than a simple linear classifier. This stems from the fact that in these tasks **the training data can be rarely separated using an hyperplane**. Consider one of these tasks, for example, face detection. The training data in this case is composed by a set of images that are faces and another set of images that are non-faces (*every other thing in the world except from faces*). This training data is too complex so as to find a representation of each sample (*feature vector*) that could make the whole set of faces linearly separable from the whole set of non-faces. Extension of the Optimization Problem ===================================== Remember that using SVMs we obtain a separating hyperplane. Therefore, since the training data is now non-linearly separable, we must admit that the hyperplane found will misclassify some of the samples. This *misclassification* is a new variable in the optimization that must be taken into account. The new model has to include both the old requirement of finding the hyperplane that gives the biggest margin and the new one of generalizing the training data correctly by not allowing too many classification errors. We start here from the formulation of the optimization problem of finding the hyperplane which maximizes the **margin** (this is explained in the :ref:`previous tutorial `): .. math:: \min_{\beta, \beta_{0}} L(\beta) = \frac{1}{2}||\beta||^{2} \text{ subject to } y_{i}(\beta^{T} x_{i} + \beta_{0}) \geq 1 \text{ } \forall i There are multiple ways in which this model can be modified so it takes into account the misclassification errors. For example, one could think of minimizing the same quantity plus a constant times the number of misclassification errors in the training data, i.e.: .. math:: \min ||\beta||^{2} + C \text{(\# misclassication errors)} However, this one is not a very good solution since, among some other reasons, we do not distinguish between samples that are misclassified with a small distance to their appropriate decision region or samples that are not. Therefore, a better solution will take into account the *distance of the misclassified samples to their correct decision regions*, i.e.: .. math:: \min ||\beta||^{2} + C \text{(distance of misclassified samples to their correct regions)} For each sample of the training data a new parameter :math:`\xi_{i}` is defined. Each one of these parameters contains the distance from its corresponding training sample to their correct decision region. The following picture shows non-linearly separable training data from two classes, a separating hyperplane and the distances to their correct regions of the samples that are misclassified. .. image:: images/sample-errors-dist.png :alt: Samples misclassified and their distances to their correct regions :align: center .. note:: Only the distances of the samples that are misclassified are shown in the picture. The distances of the rest of the samples are zero since they lay already in their correct decision region. The red and blue lines that appear on the picture are the margins to each one of the decision regions. It is very **important** to realize that each of the :math:`\xi_{i}` goes from a misclassified training sample to the margin of its appropriate region. Finally, the new formulation for the optimization problem is: .. math:: \min_{\beta, \beta_{0}} L(\beta) = ||\beta||^{2} + C \sum_{i} {\xi_{i}} \text{ subject to } y_{i}(\beta^{T} x_{i} + \beta_{0}) \geq 1 - \xi_{i} \text{ and } \xi_{i} \geq 0 \text{ } \forall i How should the parameter C be chosen? It is obvious that the answer to this question depends on how the training data is distributed. Although there is no general answer, it is useful to take into account these rules: .. container:: enumeratevisibleitemswithsquare * Large values of C give solutions with *less misclassification errors* but a *smaller margin*. Consider that in this case it is expensive to make misclassification errors. Since the aim of the optimization is to minimize the argument, few misclassifications errors are allowed. * Small values of C give solutions with *bigger margin* and *more classification errors*. In this case the minimization does not consider that much the term of the sum so it focuses more on finding a hyperplane with big margin. Source Code =========== You may also find the source code and these video file in the :file:`samples/cpp/tutorial_code/gpu/non_linear_svms/non_linear_svms` folder of the OpenCV source library or :download:`download it from here <../../../../samples/cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp>`. .. literalinclude:: ../../../../samples/cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp :language: cpp :linenos: :tab-width: 4 :lines: 1-11, 22-23, 26- Explanation =========== 1. **Set up the training data** The training data of this exercise is formed by a set of labeled 2D-points that belong to one of two different classes. To make the exercise more appealing, the training data is generated randomly using a uniform probability density functions (PDFs). We have divided the generation of the training data into two main parts. In the first part we generate data for both classes that is linearly separable. .. code-block:: cpp // Generate random points for the class 1 Mat trainClass = trainData.rowRange(0, nLinearSamples); // The x coordinate of the points is in [0, 0.4) Mat c = trainClass.colRange(0, 1); rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(0.4 * WIDTH)); // The y coordinate of the points is in [0, 1) c = trainClass.colRange(1,2); rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT)); // Generate random points for the class 2 trainClass = trainData.rowRange(2*NTRAINING_SAMPLES-nLinearSamples, 2*NTRAINING_SAMPLES); // The x coordinate of the points is in [0.6, 1] c = trainClass.colRange(0 , 1); rng.fill(c, RNG::UNIFORM, Scalar(0.6*WIDTH), Scalar(WIDTH)); // The y coordinate of the points is in [0, 1) c = trainClass.colRange(1,2); rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT)); In the second part we create data for both classes that is non-linearly separable, data that overlaps. .. code-block:: cpp // Generate random points for the classes 1 and 2 trainClass = trainData.rowRange( nLinearSamples, 2*NTRAINING_SAMPLES-nLinearSamples); // The x coordinate of the points is in [0.4, 0.6) c = trainClass.colRange(0,1); rng.fill(c, RNG::UNIFORM, Scalar(0.4*WIDTH), Scalar(0.6*WIDTH)); // The y coordinate of the points is in [0, 1) c = trainClass.colRange(1,2); rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT)); 2. **Set up SVM's parameters** .. seealso:: In the previous tutorial :ref:`introductiontosvms` there is an explanation of the atributes of the class :svms:`CvSVMParams ` that we configure here before training the SVM. .. code-block:: cpp CvSVMParams params; params.svm_type = SVM::C_SVC; params.C = 0.1; params.kernel_type = SVM::LINEAR; params.term_crit = TermCriteria(CV_TERMCRIT_ITER, (int)1e7, 1e-6); There are just two differences between the configuration we do here and the one that was done in the :ref:`previous tutorial ` that we use as reference. * *CvSVM::C_SVC*. We chose here a small value of this parameter in order not to punish too much the misclassification errors in the optimization. The idea of doing this stems from the will of obtaining a solution close to the one intuitively expected. However, we recommend to get a better insight of the problem by making adjustments to this parameter. .. note:: Here there are just very few points in the overlapping region between classes, giving a smaller value to **FRAC_LINEAR_SEP** the density of points can be incremented and the impact of the parameter **CvSVM::C_SVC** explored deeply. * *Termination Criteria of the algorithm*. The maximum number of iterations has to be increased considerably in order to solve correctly a problem with non-linearly separable training data. In particular, we have increased in five orders of magnitude this value. 3. **Train the SVM** We call the method :svms:`CvSVM::train ` to build the SVM model. Watch out that the training process may take a quite long time. Have patiance when your run the program. .. code-block:: cpp CvSVM svm; svm.train(trainData, labels, Mat(), Mat(), params); 4. **Show the Decision Regions** The method :svms:`CvSVM::predict ` is used to classify an input sample using a trained SVM. In this example we have used this method in order to color the space depending on the prediction done by the SVM. In other words, an image is traversed interpreting its pixels as points of the Cartesian plane. Each of the points is colored depending on the class predicted by the SVM; in dark green if it is the class with label 1 and in dark blue if it is the class with label 2. .. code-block:: cpp Vec3b green(0,100,0), blue (100,0,0); for (int i = 0; i < I.rows; ++i) for (int j = 0; j < I.cols; ++j) { Mat sampleMat = (Mat_(1,2) << i, j); float response = svm.predict(sampleMat); if (response == 1) I.at(j, i) = green; else if (response == 2) I.at(j, i) = blue; } 5. **Show the training data** The method :drawingFunc:`circle ` is used to show the samples that compose the training data. The samples of the class labeled with 1 are shown in light green and in light blue the samples of the class labeled with 2. .. code-block:: cpp int thick = -1; int lineType = 8; float px, py; // Class 1 for (int i = 0; i < NTRAINING_SAMPLES; ++i) { px = trainData.at(i,0); py = trainData.at(i,1); circle(I, Point( (int) px, (int) py ), 3, Scalar(0, 255, 0), thick, lineType); } // Class 2 for (int i = NTRAINING_SAMPLES; i <2*NTRAINING_SAMPLES; ++i) { px = trainData.at(i,0); py = trainData.at(i,1); circle(I, Point( (int) px, (int) py ), 3, Scalar(255, 0, 0), thick, lineType); } 6. **Support vectors** We use here a couple of methods to obtain information about the support vectors. The method :svms:`CvSVM::get_support_vector_count ` outputs the total number of support vectors used in the problem and with the method :svms:`CvSVM::get_support_vector ` we obtain each of the support vectors using an index. We have used this methods here to find the training examples that are support vectors and highlight them. .. code-block:: cpp thick = 2; lineType = 8; int x = svm.get_support_vector_count(); for (int i = 0; i < x; ++i) { const float* v = svm.get_support_vector(i); circle( I, Point( (int) v[0], (int) v[1]), 6, Scalar(128, 128, 128), thick, lineType); } Results ======= .. container:: enumeratevisibleitemswithsquare * The code opens an image and shows the training examples of both classes. The points of one class are represented with light green and light blue ones are used for the other class. * The SVM is trained and used to classify all the pixels of the image. This results in a division of the image in a blue region and a green region. The boundary between both regions is the separating hyperplane. Since the training data is non-linearly separable, it can be seen that some of the examples of both classes are misclassified; some green points lay on the blue region and some blue points lay on the green one. * Finally the support vectors are shown using gray rings around the training examples. .. image:: images/result.png :alt: Training data and decision regions given by the SVM :width: 300pt :align: center You may observe a runtime instance of this on the `YouTube here `_. .. raw:: html
    \ No newline at end of file +.. _nonLinearSvmS: + +Support Vector Machines for Non-Linearly Separable Data +******************************************************* + +Goal +==== + +In this tutorial you will learn how to: + +.. container:: enumeratevisibleitemswithsquare + + + Define the optimization problem for SVMs when it is not possible to separate linearly the training data. + + + How to configure the parameters in :svms:`CvSVMParams ` to adapt your SVM for this class of problems. + +Motivation +========== + +Why is it interesting to extend the SVM optimation problem in order to handle non-linearly separable training data? Most of the applications in which SVMs are used in computer vision require a more powerful tool than a simple linear classifier. This stems from the fact that in these tasks **the training data can be rarely separated using an hyperplane**. + +Consider one of these tasks, for example, face detection. The training data in this case is composed by a set of images that are faces and another set of images that are non-faces (*every other thing in the world except from faces*). This training data is too complex so as to find a representation of each sample (*feature vector*) that could make the whole set of faces linearly separable from the whole set of non-faces. + +Extension of the Optimization Problem +===================================== + +Remember that using SVMs we obtain a separating hyperplane. Therefore, since the training data is now non-linearly separable, we must admit that the hyperplane found will misclassify some of the samples. This *misclassification* is a new variable in the optimization that must be taken into account. The new model has to include both the old requirement of finding the hyperplane that gives the biggest margin and the new one of generalizing the training data correctly by not allowing too many classification errors. + +We start here from the formulation of the optimization problem of finding the hyperplane which maximizes the **margin** (this is explained in the :ref:`previous tutorial `): + +.. math:: + \min_{\beta, \beta_{0}} L(\beta) = \frac{1}{2}||\beta||^{2} \text{ subject to } y_{i}(\beta^{T} x_{i} + \beta_{0}) \geq 1 \text{ } \forall i + +There are multiple ways in which this model can be modified so it takes into account the misclassification errors. For example, one could think of minimizing the same quantity plus a constant times the number of misclassification errors in the training data, i.e.: + +.. math:: + \min ||\beta||^{2} + C \text{(\# misclassication errors)} + +However, this one is not a very good solution since, among some other reasons, we do not distinguish between samples that are misclassified with a small distance to their appropriate decision region or samples that are not. Therefore, a better solution will take into account the *distance of the misclassified samples to their correct decision regions*, i.e.: + +.. math:: + \min ||\beta||^{2} + C \text{(distance of misclassified samples to their correct regions)} + +For each sample of the training data a new parameter :math:`\xi_{i}` is defined. Each one of these parameters contains the distance from its corresponding training sample to their correct decision region. The following picture shows non-linearly separable training data from two classes, a separating hyperplane and the distances to their correct regions of the samples that are misclassified. + +.. image:: images/sample-errors-dist.png + :alt: Samples misclassified and their distances to their correct regions + :align: center + +.. note:: Only the distances of the samples that are misclassified are shown in the picture. The distances of the rest of the samples are zero since they lay already in their correct decision region. + +The red and blue lines that appear on the picture are the margins to each one of the decision regions. It is very **important** to realize that each of the :math:`\xi_{i}` goes from a misclassified training sample to the margin of its appropriate region. + +Finally, the new formulation for the optimization problem is: + +.. math:: + \min_{\beta, \beta_{0}} L(\beta) = ||\beta||^{2} + C \sum_{i} {\xi_{i}} \text{ subject to } y_{i}(\beta^{T} x_{i} + \beta_{0}) \geq 1 - \xi_{i} \text{ and } \xi_{i} \geq 0 \text{ } \forall i + +How should the parameter C be chosen? It is obvious that the answer to this question depends on how the training data is distributed. Although there is no general answer, it is useful to take into account these rules: + +.. container:: enumeratevisibleitemswithsquare + + * Large values of C give solutions with *less misclassification errors* but a *smaller margin*. Consider that in this case it is expensive to make misclassification errors. Since the aim of the optimization is to minimize the argument, few misclassifications errors are allowed. + + * Small values of C give solutions with *bigger margin* and *more classification errors*. In this case the minimization does not consider that much the term of the sum so it focuses more on finding a hyperplane with big margin. + +Source Code +=========== + +You may also find the source code and these video file in the :file:`samples/cpp/tutorial_code/gpu/non_linear_svms/non_linear_svms` folder of the OpenCV source library or :download:`download it from here <../../../../samples/cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp>`. + +.. literalinclude:: ../../../../samples/cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp + :language: cpp + :linenos: + :tab-width: 4 + :lines: 1-11, 22-23, 26- + +Explanation +=========== + +1. **Set up the training data** + + The training data of this exercise is formed by a set of labeled 2D-points that belong to one of two different classes. To make the exercise more appealing, the training data is generated randomly using a uniform probability density functions (PDFs). + + We have divided the generation of the training data into two main parts. + + In the first part we generate data for both classes that is linearly separable. + + .. code-block:: cpp + + // Generate random points for the class 1 + Mat trainClass = trainData.rowRange(0, nLinearSamples); + // The x coordinate of the points is in [0, 0.4) + Mat c = trainClass.colRange(0, 1); + rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(0.4 * WIDTH)); + // The y coordinate of the points is in [0, 1) + c = trainClass.colRange(1,2); + rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT)); + + // Generate random points for the class 2 + trainClass = trainData.rowRange(2*NTRAINING_SAMPLES-nLinearSamples, 2*NTRAINING_SAMPLES); + // The x coordinate of the points is in [0.6, 1] + c = trainClass.colRange(0 , 1); + rng.fill(c, RNG::UNIFORM, Scalar(0.6*WIDTH), Scalar(WIDTH)); + // The y coordinate of the points is in [0, 1) + c = trainClass.colRange(1,2); + rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT)); + + In the second part we create data for both classes that is non-linearly separable, data that overlaps. + + .. code-block:: cpp + + // Generate random points for the classes 1 and 2 + trainClass = trainData.rowRange( nLinearSamples, 2*NTRAINING_SAMPLES-nLinearSamples); + // The x coordinate of the points is in [0.4, 0.6) + c = trainClass.colRange(0,1); + rng.fill(c, RNG::UNIFORM, Scalar(0.4*WIDTH), Scalar(0.6*WIDTH)); + // The y coordinate of the points is in [0, 1) + c = trainClass.colRange(1,2); + rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT)); + +2. **Set up SVM's parameters** + + .. seealso:: + + In the previous tutorial :ref:`introductiontosvms` there is an explanation of the atributes of the class :svms:`CvSVMParams ` that we configure here before training the SVM. + + .. code-block:: cpp + + CvSVMParams params; + params.svm_type = SVM::C_SVC; + params.C = 0.1; + params.kernel_type = SVM::LINEAR; + params.term_crit = TermCriteria(CV_TERMCRIT_ITER, (int)1e7, 1e-6); + + There are just two differences between the configuration we do here and the one that was done in the :ref:`previous tutorial ` that we use as reference. + + * *CvSVM::C_SVC*. We chose here a small value of this parameter in order not to punish too much the misclassification errors in the optimization. The idea of doing this stems from the will of obtaining a solution close to the one intuitively expected. However, we recommend to get a better insight of the problem by making adjustments to this parameter. + + .. note:: Here there are just very few points in the overlapping region between classes, giving a smaller value to **FRAC_LINEAR_SEP** the density of points can be incremented and the impact of the parameter **CvSVM::C_SVC** explored deeply. + + * *Termination Criteria of the algorithm*. The maximum number of iterations has to be increased considerably in order to solve correctly a problem with non-linearly separable training data. In particular, we have increased in five orders of magnitude this value. + +3. **Train the SVM** + + We call the method :svms:`CvSVM::train ` to build the SVM model. Watch out that the training process may take a quite long time. Have patiance when your run the program. + + .. code-block:: cpp + + CvSVM svm; + svm.train(trainData, labels, Mat(), Mat(), params); + +4. **Show the Decision Regions** + + The method :svms:`CvSVM::predict ` is used to classify an input sample using a trained SVM. In this example we have used this method in order to color the space depending on the prediction done by the SVM. In other words, an image is traversed interpreting its pixels as points of the Cartesian plane. Each of the points is colored depending on the class predicted by the SVM; in dark green if it is the class with label 1 and in dark blue if it is the class with label 2. + + .. code-block:: cpp + + Vec3b green(0,100,0), blue (100,0,0); + for (int i = 0; i < I.rows; ++i) + for (int j = 0; j < I.cols; ++j) + { + Mat sampleMat = (Mat_(1,2) << i, j); + float response = svm.predict(sampleMat); + + if (response == 1) I.at(j, i) = green; + else if (response == 2) I.at(j, i) = blue; + } + +5. **Show the training data** + + The method :drawingFunc:`circle ` is used to show the samples that compose the training data. The samples of the class labeled with 1 are shown in light green and in light blue the samples of the class labeled with 2. + + .. code-block:: cpp + + int thick = -1; + int lineType = 8; + float px, py; + // Class 1 + for (int i = 0; i < NTRAINING_SAMPLES; ++i) + { + px = trainData.at(i,0); + py = trainData.at(i,1); + circle(I, Point( (int) px, (int) py ), 3, Scalar(0, 255, 0), thick, lineType); + } + // Class 2 + for (int i = NTRAINING_SAMPLES; i <2*NTRAINING_SAMPLES; ++i) + { + px = trainData.at(i,0); + py = trainData.at(i,1); + circle(I, Point( (int) px, (int) py ), 3, Scalar(255, 0, 0), thick, lineType); + } + +6. **Support vectors** + + We use here a couple of methods to obtain information about the support vectors. The method :svms:`CvSVM::get_support_vector_count ` outputs the total number of support vectors used in the problem and with the method :svms:`CvSVM::get_support_vector ` we obtain each of the support vectors using an index. We have used this methods here to find the training examples that are support vectors and highlight them. + + .. code-block:: cpp + + thick = 2; + lineType = 8; + int x = svm.get_support_vector_count(); + + for (int i = 0; i < x; ++i) + { + const float* v = svm.get_support_vector(i); + circle( I, Point( (int) v[0], (int) v[1]), 6, Scalar(128, 128, 128), thick, lineType); + } + +Results +======== + +.. container:: enumeratevisibleitemswithsquare + + * The code opens an image and shows the training examples of both classes. The points of one class are represented with light green and light blue ones are used for the other class. + + * The SVM is trained and used to classify all the pixels of the image. This results in a division of the image in a blue region and a green region. The boundary between both regions is the separating hyperplane. Since the training data is non-linearly separable, it can be seen that some of the examples of both classes are misclassified; some green points lay on the blue region and some blue points lay on the green one. + + * Finally the support vectors are shown using gray rings around the training examples. + +.. image:: images/result.png + :alt: Training data and decision regions given by the SVM + :width: 300pt + :align: center + +You may observe a runtime instance of this on the `YouTube here `_. + +.. raw:: html + +
    + +
    diff --git a/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.rst b/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.rst index 146a0ec0be..ba9c2740e2 100644 --- a/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.rst +++ b/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.rst @@ -26,91 +26,90 @@ This tutorial code's is shown lines below. You can also download it from `here < .. code-block:: cpp - #include "opencv2/objdetect.hpp" - #include "opencv2/highgui.hpp" - #include "opencv2/imgproc.hpp" + #include "opencv2/objdetect.hpp" + #include "opencv2/highgui.hpp" + #include "opencv2/imgproc.hpp" - #include - #include + #include + #include - using namespace std; - using namespace cv; + using namespace std; + using namespace cv; - /** Function Headers */ - void detectAndDisplay( Mat frame ); + /** Function Headers */ + void detectAndDisplay( Mat frame ); - /** Global variables */ - String face_cascade_name = "haarcascade_frontalface_alt.xml"; - String eyes_cascade_name = "haarcascade_eye_tree_eyeglasses.xml"; - CascadeClassifier face_cascade; - CascadeClassifier eyes_cascade; - string window_name = "Capture - Face detection"; - RNG rng(12345); + /** Global variables */ + String face_cascade_name = "haarcascade_frontalface_alt.xml"; + String eyes_cascade_name = "haarcascade_eye_tree_eyeglasses.xml"; + CascadeClassifier face_cascade; + CascadeClassifier eyes_cascade; + String window_name = "Capture - Face detection"; - /** @function main */ - int main( int argc, const char** argv ) - { - CvCapture* capture; - Mat frame; - - //-- 1. Load the cascades - if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; }; - if( !eyes_cascade.load( eyes_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; }; - - //-- 2. Read the video stream - capture = cvCaptureFromCAM( -1 ); - if( capture ) - { - while( true ) - { - frame = cvQueryFrame( capture ); - - //-- 3. Apply the classifier to the frame - if( !frame.empty() ) - { detectAndDisplay( frame ); } - else - { printf(" --(!) No captured frame -- Break!"); break; } - - int c = waitKey(10); - if( (char)c == 'c' ) { break; } - } - } - return 0; - } - - /** @function detectAndDisplay */ - void detectAndDisplay( Mat frame ) - { - std::vector faces; - Mat frame_gray; - - cvtColor( frame, frame_gray, CV_BGR2GRAY ); - equalizeHist( frame_gray, frame_gray ); - - //-- Detect faces - face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) ); - - for( int i = 0; i < faces.size(); i++ ) + /** @function main */ + int main( void ) { - Point center( faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5 ); - ellipse( frame, center, Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 ); + VideoCapture capture; + Mat frame; - Mat faceROI = frame_gray( faces[i] ); - std::vector eyes; + //-- 1. Load the cascades + if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading face cascade\n"); return -1; }; + if( !eyes_cascade.load( eyes_cascade_name ) ){ printf("--(!)Error loading eyes cascade\n"); return -1; }; - //-- In each face, detect eyes - eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE, Size(30, 30) ); + //-- 2. Read the video stream + capture.open( -1 ); + if ( ! capture.isOpened() ) { printf("--(!)Error opening video capture\n"); return -1; } - for( int j = 0; j < eyes.size(); j++ ) - { - Point center( faces[i].x + eyes[j].x + eyes[j].width*0.5, faces[i].y + eyes[j].y + eyes[j].height*0.5 ); - int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 ); - circle( frame, center, radius, Scalar( 255, 0, 0 ), 4, 8, 0 ); - } + while ( capture.read(frame) ) + { + if( frame.empty() ) + { + printf(" --(!) No captured frame -- Break!"); + break; + } + + //-- 3. Apply the classifier to the frame + detectAndDisplay( frame ); + + int c = waitKey(10); + if( (char)c == 27 ) { break; } // escape + } + return 0; + } + + /** @function detectAndDisplay */ + void detectAndDisplay( Mat frame ) + { + std::vector faces; + Mat frame_gray; + + cvtColor( frame, frame_gray, COLOR_BGR2GRAY ); + equalizeHist( frame_gray, frame_gray ); + + //-- Detect faces + face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CASCADE_SCALE_IMAGE, Size(30, 30) ); + + for( size_t i = 0; i < faces.size(); i++ ) + { + Point center( faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2 ); + ellipse( frame, center, Size( faces[i].width/2, faces[i].height/2), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 ); + + Mat faceROI = frame_gray( faces[i] ); + std::vector eyes; + + //-- In each face, detect eyes + eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CASCADE_SCALE_IMAGE, Size(30, 30) ); + + for( size_t j = 0; j < eyes.size(); j++ ) + { + Point eye_center( faces[i].x + eyes[j].x + eyes[j].width/2, faces[i].y + eyes[j].y + eyes[j].height/2 ); + int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 ); + circle( frame, eye_center, radius, Scalar( 255, 0, 0 ), 4, 8, 0 ); + } + } + //-- Show what you got + imshow( window_name, frame ); } - //-- Show what you got - imshow( window_name, frame ); - } Explanation ============ @@ -131,4 +130,3 @@ Result .. image:: images/Cascade_Classifier_Tutorial_Result_LBP.jpg :align: center :height: 300pt - diff --git a/doc/tutorials/tutorials.rst b/doc/tutorials/tutorials.rst index cbc51c1956..07bc515d53 100644 --- a/doc/tutorials/tutorials.rst +++ b/doc/tutorials/tutorials.rst @@ -156,17 +156,17 @@ As always, we would be happy to hear your comments and receive your contribution :width: 80pt :alt: gpu icon -* :ref:`Table-Of-Content-Contrib` +* :ref:`Table-Of-Content-Bioinspired` .. tabularcolumns:: m{100pt} m{300pt} .. cssclass:: toctableopencv - =========== ======================================================= - |Contrib| Discover additional contribution to OpenCV. + ============= ======================================================= + |Bioinspired| Algorithms inspired from biological models. - =========== ======================================================= + ============= ======================================================= - .. |Contrib| image:: images/retina.jpg + .. |Bioinspired| image:: images/retina.jpg :height: 80pt :width: 80pt :alt: gpu icon @@ -219,6 +219,6 @@ As always, we would be happy to hear your comments and receive your contribution objdetect/table_of_content_objdetect/table_of_content_objdetect ml/table_of_content_ml/table_of_content_ml gpu/table_of_content_gpu/table_of_content_gpu - contrib/table_of_content_contrib/table_of_content_contrib + bioinspired/table_of_content_bioinspired/table_of_content_bioinspired ios/table_of_content_ios/table_of_content_ios general/table_of_content_general/table_of_content_general diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 1d5909616a..ed3b85a8fc 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -5,5 +5,3 @@ install(FILES ${old_hdrs} install(FILES "opencv2/opencv.hpp" DESTINATION ${OPENCV_INCLUDE_INSTALL_PATH}/opencv2 COMPONENT main) - - diff --git a/include/opencv/cv.h b/include/opencv/cv.h index c878e68818..1ed020a356 100644 --- a/include/opencv/cv.h +++ b/include/opencv/cv.h @@ -61,23 +61,15 @@ //CV_WARNING("This is a deprecated opencv header provided for compatibility. Please include a header from a corresponding opencv module") #include "opencv2/core/core_c.h" -#include "opencv2/core.hpp" #include "opencv2/imgproc/imgproc_c.h" -#include "opencv2/imgproc.hpp" -#include "opencv2/video.hpp" -#include "opencv2/features2d.hpp" -#include "opencv2/flann.hpp" -#include "opencv2/calib3d.hpp" -#include "opencv2/objdetect.hpp" +#include "opencv2/photo/photo_c.h" +#include "opencv2/video/tracking_c.h" +#include "opencv2/objdetect/objdetect_c.h" +#include "opencv2/legacy.hpp" #include "opencv2/legacy/compat.hpp" #if !defined(CV_IMPL) #define CV_IMPL extern "C" #endif //CV_IMPL -#if defined(__cplusplus) -#include "opencv2/core/internal.hpp" -#endif //__cplusplus - #endif // __OPENCV_OLD_CV_H_ - diff --git a/include/opencv/cv.hpp b/include/opencv/cv.hpp index 37b523b31c..e498d7ac1a 100644 --- a/include/opencv/cv.hpp +++ b/include/opencv/cv.hpp @@ -47,6 +47,14 @@ //#warning "This is a deprecated opencv header provided for compatibility. Please include a header from a corresponding opencv module" //#endif -#include +#include "cv.h" +#include "opencv2/core.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/photo.hpp" +#include "opencv2/video.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/features2d.hpp" +#include "opencv2/calib3d.hpp" +#include "opencv2/objdetect.hpp" #endif diff --git a/include/opencv/cvaux.h b/include/opencv/cvaux.h index 52d4f0b648..cb49c086ba 100644 --- a/include/opencv/cvaux.h +++ b/include/opencv/cvaux.h @@ -47,17 +47,16 @@ //#endif #include "opencv2/core/core_c.h" -#include "opencv2/core.hpp" #include "opencv2/imgproc/imgproc_c.h" -#include "opencv2/imgproc.hpp" -#include "opencv2/video.hpp" -#include "opencv2/features2d.hpp" -#include "opencv2/calib3d.hpp" -#include "opencv2/objdetect.hpp" +#include "opencv2/photo/photo_c.h" +#include "opencv2/video/tracking_c.h" +#include "opencv2/objdetect/objdetect_c.h" +#include "opencv2/contrib/compat.hpp" + #include "opencv2/legacy.hpp" #include "opencv2/legacy/compat.hpp" #include "opencv2/legacy/blobtrack.hpp" -#include "opencv2/contrib.hpp" + #endif diff --git a/include/opencv/cvaux.hpp b/include/opencv/cvaux.hpp index 952210b0be..b0e60a3038 100644 --- a/include/opencv/cvaux.hpp +++ b/include/opencv/cvaux.hpp @@ -46,6 +46,7 @@ //#warning "This is a deprecated opencv header provided for compatibility. Please include a header from a corresponding opencv module" //#endif -#include +#include "cvaux.h" +#include "opencv2/core/utility.hpp" #endif diff --git a/include/opencv/cxcore.h b/include/opencv/cxcore.h index 9be80ae96f..0982bd7508 100644 --- a/include/opencv/cxcore.h +++ b/include/opencv/cxcore.h @@ -48,6 +48,5 @@ //#endif #include "opencv2/core/core_c.h" -#include "opencv2/core.hpp" #endif diff --git a/include/opencv/cxcore.hpp b/include/opencv/cxcore.hpp index 033b36556c..9af4ac7460 100644 --- a/include/opencv/cxcore.hpp +++ b/include/opencv/cxcore.hpp @@ -47,6 +47,7 @@ //#warning "This is a deprecated opencv header provided for compatibility. Please include a header from a corresponding opencv module" //#endif -#include +#include "cxcore.h" +#include "opencv2/core.hpp" #endif diff --git a/include/opencv/cxeigen.hpp b/include/opencv/cxeigen.hpp index c503f713d6..1f04d1a3a2 100644 --- a/include/opencv/cxeigen.hpp +++ b/include/opencv/cxeigen.hpp @@ -46,4 +46,3 @@ #include "opencv2/core/eigen.hpp" #endif - diff --git a/include/opencv/cxmisc.h b/include/opencv/cxmisc.h index 6446944643..6c93a0cce4 100644 --- a/include/opencv/cxmisc.h +++ b/include/opencv/cxmisc.h @@ -1,6 +1,8 @@ #ifndef __OPENCV_OLD_CXMISC_H__ #define __OPENCV_OLD_CXMISC_H__ -#include "opencv2/core/internal.hpp" +#ifdef __cplusplus +# include "opencv2/core/utility.hpp" +#endif #endif diff --git a/include/opencv/highgui.h b/include/opencv/highgui.h index 56874e7383..0261029c09 100644 --- a/include/opencv/highgui.h +++ b/include/opencv/highgui.h @@ -43,8 +43,6 @@ #define __OPENCV_OLD_HIGHGUI_H__ #include "opencv2/core/core_c.h" -#include "opencv2/core.hpp" #include "opencv2/highgui/highgui_c.h" -#include "opencv2/highgui.hpp" #endif diff --git a/include/opencv/ml.h b/include/opencv/ml.h index ac21f3c219..d8e967f81b 100644 --- a/include/opencv/ml.h +++ b/include/opencv/ml.h @@ -42,7 +42,6 @@ #define __OPENCV_OLD_ML_H__ #include "opencv2/core/core_c.h" -#include "opencv2/core.hpp" #include "opencv2/ml.hpp" #endif diff --git a/include/opencv2/opencv.hpp b/include/opencv2/opencv.hpp index f9c15df3d4..3b96bdd368 100644 --- a/include/opencv2/opencv.hpp +++ b/include/opencv2/opencv.hpp @@ -43,19 +43,16 @@ #ifndef __OPENCV_ALL_HPP__ #define __OPENCV_ALL_HPP__ -#include "opencv2/core/core_c.h" #include "opencv2/core.hpp" -#include "opencv2/flann/miniflann.hpp" -#include "opencv2/imgproc/imgproc_c.h" #include "opencv2/imgproc.hpp" #include "opencv2/photo.hpp" #include "opencv2/video.hpp" #include "opencv2/features2d.hpp" #include "opencv2/objdetect.hpp" #include "opencv2/calib3d.hpp" -#include "opencv2/ml.hpp" -#include "opencv2/highgui/highgui_c.h" #include "opencv2/highgui.hpp" #include "opencv2/contrib.hpp" +#include "opencv2/bioinspired.hpp" +#include "opencv2/ml.hpp" #endif diff --git a/index.rst b/index.rst index 909bf908b8..5f50b66d0f 100644 --- a/index.rst +++ b/index.rst @@ -10,7 +10,7 @@ Welcome to opencv documentation! :maxdepth: 2 modules/refman.rst - android/refman.rst + platforms/android/refman.rst doc/user_guide/user_guide.rst doc/tutorials/tutorials.rst diff --git a/ios/configure-device_xcode.sh b/ios/configure-device_xcode.sh deleted file mode 100755 index 8c28a3e909..0000000000 --- a/ios/configure-device_xcode.sh +++ /dev/null @@ -1 +0,0 @@ -cmake -GXcode -DCMAKE_TOOLCHAIN_FILE=../opencv/ios/cmake/Toolchains/Toolchain-iPhoneOS_Xcode.cmake -DCMAKE_INSTALL_PREFIX=../OpenCV_iPhoneOS ../opencv diff --git a/ios/configure-simulator_xcode.sh b/ios/configure-simulator_xcode.sh deleted file mode 100755 index 50e00261db..0000000000 --- a/ios/configure-simulator_xcode.sh +++ /dev/null @@ -1 +0,0 @@ -cmake -GXcode -DCMAKE_TOOLCHAIN_FILE=../opencv/ios/cmake/Toolchains/Toolchain-iPhoneSimulator_Xcode.cmake -DCMAKE_INSTALL_PREFIX=../OpenCV_iPhoneSimulator ../opencv diff --git a/ios/readme.txt b/ios/readme.txt deleted file mode 100644 index 1441b241b7..0000000000 --- a/ios/readme.txt +++ /dev/null @@ -1,15 +0,0 @@ -Assuming that your build directory is on the same level that opencv source, -From the build directory run - ../opencv/ios/configure-device_xcode.sh -or - ../opencv/ios/configure-simulator_xcode.sh - -Then from the same folder invoke - -xcodebuild -sdk iphoneos -configuration Release -target ALL_BUILD -xcodebuild -sdk iphoneos -configuration Release -target install install - -or - -xcodebuild -sdk iphonesimulator -configuration Release -target ALL_BUILD -xcodebuild -sdk iphonesimulator -configuration Release -target install install \ No newline at end of file diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index c865eb01ba..400b2a8381 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -4,4 +4,4 @@ if(NOT OPENCV_MODULES_PATH) set(OPENCV_MODULES_PATH "${CMAKE_CURRENT_SOURCE_DIR}") endif() -ocv_glob_modules(${OPENCV_MODULES_PATH}) +ocv_glob_modules(${OPENCV_MODULES_PATH} ${OPENCV_EXTRA_MODULES_PATH}) diff --git a/modules/androidcamera/CMakeLists.txt b/modules/androidcamera/CMakeLists.txt index d54dd5d208..8ac8ced88e 100644 --- a/modules/androidcamera/CMakeLists.txt +++ b/modules/androidcamera/CMakeLists.txt @@ -6,7 +6,7 @@ set(the_description "Auxiliary module for Android native camera support") set(OPENCV_MODULE_TYPE STATIC) ocv_define_module(androidcamera INTERNAL opencv_core log dl) -ocv_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/camera_wrapper" "${OpenCV_SOURCE_DIR}/android/service/engine/jni/include") +ocv_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/camera_wrapper" "${OpenCV_SOURCE_DIR}/platforms/android/service/engine/jni/include") # Android source tree for native camera SET (ANDROID_SOURCE_TREE "ANDROID_SOURCE_TREE-NOTFOUND" CACHE PATH diff --git a/modules/androidcamera/camera_wrapper/camera_wrapper.cpp b/modules/androidcamera/camera_wrapper/camera_wrapper.cpp index f6ec2f09cf..ca631fc21e 100644 --- a/modules/androidcamera/camera_wrapper/camera_wrapper.cpp +++ b/modules/androidcamera/camera_wrapper/camera_wrapper.cpp @@ -1,5 +1,8 @@ -#if !defined(ANDROID_r2_2_0) && !defined(ANDROID_r2_3_3) && !defined(ANDROID_r3_0_1) && !defined(ANDROID_r4_0_0) && !defined(ANDROID_r4_0_3) && !defined(ANDROID_r4_1_1) && !defined(ANDROID_r4_2_0) -# error Building camera wrapper for your version of Android is not supported by OpenCV. You need to modify OpenCV sources in order to compile camera wrapper for your version of Android. +#if !defined(ANDROID_r2_2_0) && !defined(ANDROID_r2_3_3) && !defined(ANDROID_r3_0_1) && \ + !defined(ANDROID_r4_0_0) && !defined(ANDROID_r4_0_3) && !defined(ANDROID_r4_1_1) && \ + !defined(ANDROID_r4_2_0) && !defined(ANDROID_r4_3_0) +# error Building camera wrapper for your version of Android is not supported by OpenCV.\ + You need to modify OpenCV sources in order to compile camera wrapper for your version of Android. #endif #include @@ -16,17 +19,18 @@ //Include SurfaceTexture.h file with the SurfaceTexture class # include # define MAGIC_OPENCV_TEXTURE_ID (0x10) -#else // defined(ANDROID_r3_0_1) || defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3) -//TODO: This is either 2.2 or 2.3. Include the headers for ISurface.h access -#if defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0) -#include -#include +#elif defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0) +# include +# include +#elif defined(ANDROID_r4_3_0) +# include +# include #else # include -#endif // defined(ANDROID_r4_1_1) -#endif // defined(ANDROID_r3_0_1) || defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3) +#endif #include +#include //undef logging macro from /system/core/libcutils/loghack.h #ifdef LOGD @@ -45,7 +49,6 @@ # undef LOGE #endif - // LOGGING #include #define CAMERA_LOG_TAG "OpenCV_NativeCamera" @@ -60,7 +63,7 @@ using namespace android; void debugShowFPS(); -#if defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0) +#if defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0) || defined(ANDROID_r4_3_0) class ConsumerListenerStub: public BufferQueue::ConsumerListener { public: @@ -73,6 +76,29 @@ public: }; #endif +std::string getProcessName() +{ + std::string result; + std::ifstream f; + + f.open("/proc/self/cmdline"); + if (f.is_open()) + { + std::string fullPath; + std::getline(f, fullPath, '\0'); + if (!fullPath.empty()) + { + int i = fullPath.size()-1; + while ((i >= 0) && (fullPath[i] != '/')) i--; + result = fullPath.substr(i+1, std::string::npos); + } + } + + f.close(); + + return result; +} + void debugShowFPS() { static int mFrameCount = 0; @@ -280,7 +306,7 @@ public: } virtual void postData(int32_t msgType, const sp& dataPtr - #if defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3) || defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0) + #if defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3) || defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0) || defined(ANDROID_r4_3_0) ,camera_frame_metadata_t* #endif ) @@ -361,6 +387,11 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, typedef sp (*Android22ConnectFuncType)(); typedef sp (*Android23ConnectFuncType)(int); typedef sp (*Android3DConnectFuncType)(int, int); + typedef sp (*Android43ConnectFuncType)(int, const String16&, int); + + const int ANY_CAMERA_INDEX = -1; + const int BACK_CAMERA_INDEX = 99; + const int FRONT_CAMERA_INDEX = 98; enum { CAMERA_SUPPORT_MODE_2D = 0x01, /* Camera Sensor supports 2D mode. */ @@ -369,11 +400,65 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, CAMERA_SUPPORT_MODE_ZSL = 0x08 /* Camera Sensor supports ZSL mode. */ }; + // used for Android 4.3 + enum { + USE_CALLING_UID = -1 + }; + const char Android22ConnectName[] = "_ZN7android6Camera7connectEv"; const char Android23ConnectName[] = "_ZN7android6Camera7connectEi"; const char Android3DConnectName[] = "_ZN7android6Camera7connectEii"; + const char Android43ConnectName[] = "_ZN7android6Camera7connectEiRKNS_8String16Ei"; - LOGD("CameraHandler::initCameraConnect(%p, %d, %p, %p)", callback, cameraId, userData, prevCameraParameters); + int localCameraIndex = cameraId; + + if (cameraId == ANY_CAMERA_INDEX) + { + localCameraIndex = 0; + } +#if !defined(ANDROID_r2_2_0) + else if (cameraId == BACK_CAMERA_INDEX) + { + LOGD("Back camera selected"); + for (int i = 0; i < Camera::getNumberOfCameras(); i++) + { + CameraInfo info; + Camera::getCameraInfo(i, &info); + if (info.facing == CAMERA_FACING_BACK) + { + localCameraIndex = i; + break; + } + } + } + else if (cameraId == FRONT_CAMERA_INDEX) + { + LOGD("Front camera selected"); + for (int i = 0; i < Camera::getNumberOfCameras(); i++) + { + CameraInfo info; + Camera::getCameraInfo(i, &info); + if (info.facing == CAMERA_FACING_FRONT) + { + localCameraIndex = i; + break; + } + } + } + + if (localCameraIndex == BACK_CAMERA_INDEX) + { + LOGE("Back camera not found!"); + return NULL; + } + else if (localCameraIndex == FRONT_CAMERA_INDEX) + { + LOGE("Front camera not found!"); + return NULL; + } +#endif + + LOGD("CameraHandler::initCameraConnect(%p, %d, %p, %p)", callback, localCameraIndex, userData, prevCameraParameters); sp camera = 0; @@ -381,8 +466,8 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, if (!CameraHALHandle) { - LOGE("Cannot link to \"libcamera_client.so\""); - return NULL; + LOGE("Cannot link to \"libcamera_client.so\""); + return NULL; } // reset errors @@ -390,24 +475,30 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, if (Android22ConnectFuncType Android22Connect = (Android22ConnectFuncType)dlsym(CameraHALHandle, Android22ConnectName)) { - LOGD("Connecting to CameraService v 2.2"); - camera = Android22Connect(); + LOGD("Connecting to CameraService v 2.2"); + camera = Android22Connect(); } else if (Android23ConnectFuncType Android23Connect = (Android23ConnectFuncType)dlsym(CameraHALHandle, Android23ConnectName)) { - LOGD("Connecting to CameraService v 2.3"); - camera = Android23Connect(cameraId); + LOGD("Connecting to CameraService v 2.3"); + camera = Android23Connect(localCameraIndex); } else if (Android3DConnectFuncType Android3DConnect = (Android3DConnectFuncType)dlsym(CameraHALHandle, Android3DConnectName)) { - LOGD("Connecting to CameraService v 3D"); - camera = Android3DConnect(cameraId, CAMERA_SUPPORT_MODE_2D); + LOGD("Connecting to CameraService v 3D"); + camera = Android3DConnect(localCameraIndex, CAMERA_SUPPORT_MODE_2D); + } + else if (Android43ConnectFuncType Android43Connect = (Android43ConnectFuncType)dlsym(CameraHALHandle, Android43ConnectName)) + { + std::string currentProcName = getProcessName(); + LOGD("Current process name for camera init: %s", currentProcName.c_str()); + camera = Android43Connect(localCameraIndex, String16(currentProcName.c_str()), USE_CALLING_UID); } else { - dlclose(CameraHALHandle); - LOGE("Cannot connect to CameraService. Connect method was not found!"); - return NULL; + dlclose(CameraHALHandle); + LOGE("Cannot connect to CameraService. Connect method was not found!"); + return NULL; } dlclose(CameraHALHandle); @@ -422,9 +513,9 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, camera->setListener(handler); handler->camera = camera; - handler->cameraId = cameraId; + handler->cameraId = localCameraIndex; - if (prevCameraParameters != 0) + if (prevCameraParameters != NULL) { LOGI("initCameraConnect: Setting paramers from previous camera handler"); camera->setParameters(prevCameraParameters->flatten()); @@ -456,11 +547,11 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, const char* available_focus_modes = handler->params.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES); if (available_focus_modes != 0) { - if (strstr(available_focus_modes, "continuous-video") != NULL) - { - handler->params.set(CameraParameters::KEY_FOCUS_MODE, CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO); + if (strstr(available_focus_modes, "continuous-video") != NULL) + { + handler->params.set(CameraParameters::KEY_FOCUS_MODE, CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO); - status_t resParams = handler->camera->setParameters(handler->params.flatten()); + status_t resParams = handler->camera->setParameters(handler->params.flatten()); if (resParams != 0) { @@ -470,8 +561,8 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, { LOGD("initCameraConnect: autofocus is set to mode \"continuous-video\""); } + } } - } #endif //check if yuv420sp format available. Set this format as preview format. @@ -513,26 +604,25 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, } } - status_t pdstatus; + status_t bufferStatus; #if defined(ANDROID_r2_2_0) - pdstatus = camera->setPreviewDisplay(sp(0 /*new DummySurface*/)); - if (pdstatus != 0) - LOGE("initCameraConnect: failed setPreviewDisplay(0) call; camera migth not work correctly on some devices"); + bufferStatus = camera->setPreviewDisplay(sp(0 /*new DummySurface*/)); + if (bufferStatus != 0) + LOGE("initCameraConnect: failed setPreviewDisplay(0) call (status %d); camera might not work correctly on some devices", bufferStatus); #elif defined(ANDROID_r2_3_3) /* Do nothing in case of 2.3 for now */ - #elif defined(ANDROID_r3_0_1) || defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3) sp surfaceTexture = new SurfaceTexture(MAGIC_OPENCV_TEXTURE_ID); - pdstatus = camera->setPreviewTexture(surfaceTexture); - if (pdstatus != 0) - LOGE("initCameraConnect: failed setPreviewTexture call; camera migth not work correctly"); -#elif defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0) + bufferStatus = camera->setPreviewTexture(surfaceTexture); + if (bufferStatus != 0) + LOGE("initCameraConnect: failed setPreviewTexture call (status %d); camera might not work correctly", bufferStatus); +#elif defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0) || defined(ANDROID_r4_3_0) sp bufferQueue = new BufferQueue(); sp queueListener = new ConsumerListenerStub(); bufferQueue->consumerConnect(queueListener); - pdstatus = camera->setPreviewTexture(bufferQueue); - if (pdstatus != 0) - LOGE("initCameraConnect: failed setPreviewTexture call; camera migth not work correctly"); + bufferStatus = camera->setPreviewTexture(bufferQueue); + if (bufferStatus != 0) + LOGE("initCameraConnect: failed setPreviewTexture call; camera might not work correctly"); #endif #if (defined(ANDROID_r2_2_0) || defined(ANDROID_r2_3_3) || defined(ANDROID_r3_0_1)) @@ -548,9 +638,9 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, #endif //!(defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3)) LOGD("Starting preview"); - status_t resStart = camera->startPreview(); + status_t previewStatus = camera->startPreview(); - if (resStart != 0) + if (previewStatus != 0) { LOGE("initCameraConnect: startPreview() fails. Closing camera connection..."); handler->closeCameraConnect(); @@ -558,7 +648,7 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, } else { - LOGD("Preview started successfully"); + LOGD("Preview started successfully"); } return handler; @@ -573,9 +663,11 @@ void CameraHandler::closeCameraConnect() } camera->stopPreview(); +#if defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3) || defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0) || defined(ANDROID_r4_3_0) + camera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP); +#endif camera->disconnect(); camera.clear(); - camera=NULL; // ATTENTION!!!!!!!!!!!!!!!!!!!!!!!!!! // When we set @@ -816,14 +908,60 @@ void CameraHandler::applyProperties(CameraHandler** ppcameraHandler) if (*ppcameraHandler == 0) { - LOGE("applyProperties: Passed null *ppcameraHandler"); + LOGE("applyProperties: Passed NULL *ppcameraHandler"); return; } - LOGD("CameraHandler::applyProperties()"); - CameraHandler* previousCameraHandler=*ppcameraHandler; - CameraParameters curCameraParameters(previousCameraHandler->params.flatten()); + CameraParameters curCameraParameters((*ppcameraHandler)->params.flatten()); +#if defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3) || defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0) || defined(ANDROID_r4_3_0) + CameraHandler* handler=*ppcameraHandler; + + handler->camera->stopPreview(); + handler->camera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP); + + status_t reconnectStatus = handler->camera->reconnect(); + if (reconnectStatus != 0) + { + LOGE("applyProperties: failed to reconnect camera (status %d)", reconnectStatus); + return; + } + + handler->camera->setParameters(curCameraParameters.flatten()); + handler->params.unflatten(curCameraParameters.flatten()); + + status_t bufferStatus; +# if defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3) + sp surfaceTexture = new SurfaceTexture(MAGIC_OPENCV_TEXTURE_ID); + bufferStatus = handler->camera->setPreviewTexture(surfaceTexture); + if (bufferStatus != 0) + LOGE("applyProperties: failed setPreviewTexture call (status %d); camera might not work correctly", bufferStatus); +# elif defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0) || defined(ANDROID_r4_3_0) + sp bufferQueue = new BufferQueue(); + sp queueListener = new ConsumerListenerStub(); + bufferQueue->consumerConnect(queueListener); + bufferStatus = handler->camera->setPreviewTexture(bufferQueue); + if (bufferStatus != 0) + LOGE("applyProperties: failed setPreviewTexture call; camera might not work correctly"); +# endif + + handler->camera->setPreviewCallbackFlags( CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK | CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK);//with copy + + LOGD("Starting preview"); + status_t previewStatus = handler->camera->startPreview(); + + if (previewStatus != 0) + { + LOGE("initCameraConnect: startPreview() fails. Closing camera connection..."); + handler->closeCameraConnect(); + handler = NULL; + } + else + { + LOGD("Preview started successfully"); + } +#else + CameraHandler* previousCameraHandler=*ppcameraHandler; CameraCallback cameraCallback=previousCameraHandler->cameraCallback; void* userData=previousCameraHandler->userData; int cameraId=previousCameraHandler->cameraId; @@ -832,7 +970,6 @@ void CameraHandler::applyProperties(CameraHandler** ppcameraHandler) previousCameraHandler->closeCameraConnect(); LOGD("CameraHandler::applyProperties(): after previousCameraHandler->closeCameraConnect"); - LOGD("CameraHandler::applyProperties(): before initCameraConnect"); CameraHandler* handler=initCameraConnect(cameraCallback, cameraId, userData, &curCameraParameters); LOGD("CameraHandler::applyProperties(): after initCameraConnect, handler=0x%x", (int)handler); @@ -845,6 +982,7 @@ void CameraHandler::applyProperties(CameraHandler** ppcameraHandler) } } (*ppcameraHandler)=handler; +#endif } diff --git a/modules/androidcamera/camera_wrapper/camera_wrapper.h b/modules/androidcamera/camera_wrapper/camera_wrapper.h index 88c9c4100b..430dea2dd5 100644 --- a/modules/androidcamera/camera_wrapper/camera_wrapper.h +++ b/modules/androidcamera/camera_wrapper/camera_wrapper.h @@ -14,4 +14,3 @@ double getCameraPropertyC(void* camera, int propIdx); void setCameraPropertyC(void* camera, int propIdx, double value); void applyCameraPropertiesC(void** camera); } - diff --git a/modules/androidcamera/include/camera_activity.hpp b/modules/androidcamera/include/camera_activity.hpp index 8aa25b620e..2af7befe30 100644 --- a/modules/androidcamera/include/camera_activity.hpp +++ b/modules/androidcamera/include/camera_activity.hpp @@ -44,4 +44,4 @@ private: int frameHeight; }; -#endif \ No newline at end of file +#endif diff --git a/modules/androidcamera/src/camera_activity.cpp b/modules/androidcamera/src/camera_activity.cpp index 9ea54d78be..a265d2e8d1 100644 --- a/modules/androidcamera/src/camera_activity.cpp +++ b/modules/androidcamera/src/camera_activity.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -12,6 +11,8 @@ #include "camera_wrapper.h" #include "EngineCommon.h" +#include "opencv2/core.hpp" + #undef LOG_TAG #undef LOGE #undef LOGD @@ -28,6 +29,11 @@ #include #include +struct str_greater +{ + bool operator() (const cv::String& a, const cv::String& b) { return a > b; } +}; + class CameraWrapperConnector { public: @@ -37,17 +43,17 @@ public: static CameraActivity::ErrorCode getProperty(void* camera, int propIdx, double* value); static CameraActivity::ErrorCode applyProperties(void** ppcamera); - static void setPathLibFolder(const std::string& path); + static void setPathLibFolder(const cv::String& path); private: - static std::string pathLibFolder; + static cv::String pathLibFolder; static bool isConnectedToLib; - static std::string getPathLibFolder(); - static std::string getDefaultPathLibFolder(); + static cv::String getPathLibFolder(); + static cv::String getDefaultPathLibFolder(); static CameraActivity::ErrorCode connectToLib(); static CameraActivity::ErrorCode getSymbolFromLib(void * libHandle, const char* symbolName, void** ppSymbol); - static void fillListWrapperLibs(const std::string& folderPath, std::vector& listLibs); + static void fillListWrapperLibs(const cv::String& folderPath, std::vector& listLibs); static InitCameraConnectC pInitCameraC; static CloseCameraConnectC pCloseCameraC; @@ -58,7 +64,7 @@ private: friend bool nextFrame(void* buffer, size_t bufferSize, void* userData); }; -std::string CameraWrapperConnector::pathLibFolder; +cv::String CameraWrapperConnector::pathLibFolder; bool CameraWrapperConnector::isConnectedToLib = false; InitCameraConnectC CameraWrapperConnector::pInitCameraC = 0; @@ -165,7 +171,7 @@ CameraActivity::ErrorCode CameraWrapperConnector::connectToLib() } dlerror(); - std::string folderPath = getPathLibFolder(); + cv::String folderPath = getPathLibFolder(); if (folderPath.empty()) { LOGD("Trying to find native camera in default OpenCV packages"); @@ -174,12 +180,12 @@ CameraActivity::ErrorCode CameraWrapperConnector::connectToLib() LOGD("CameraWrapperConnector::connectToLib: folderPath=%s", folderPath.c_str()); - std::vector listLibs; + std::vector listLibs; fillListWrapperLibs(folderPath, listLibs); - std::sort(listLibs.begin(), listLibs.end(), std::greater()); + std::sort(listLibs.begin(), listLibs.end(), str_greater()); void * libHandle=0; - std::string cur_path; + cv::String cur_path; for(size_t i = 0; i < listLibs.size(); i++) { cur_path=folderPath + listLibs[i]; LOGD("try to load library '%s'", listLibs[i].c_str()); @@ -245,7 +251,7 @@ CameraActivity::ErrorCode CameraWrapperConnector::getSymbolFromLib(void* libHand return CameraActivity::NO_ERROR; } -void CameraWrapperConnector::fillListWrapperLibs(const std::string& folderPath, std::vector& listLibs) +void CameraWrapperConnector::fillListWrapperLibs(const cv::String& folderPath, std::vector& listLibs) { DIR *dp; struct dirent *ep; @@ -264,7 +270,7 @@ void CameraWrapperConnector::fillListWrapperLibs(const std::string& folderPath, } } -std::string CameraWrapperConnector::getDefaultPathLibFolder() +cv::String CameraWrapperConnector::getDefaultPathLibFolder() { #define BIN_PACKAGE_NAME(x) "org.opencv.lib_v" CVAUX_STR(CV_VERSION_EPOCH) CVAUX_STR(CV_VERSION_MAJOR) "_" x const char* const packageList[] = {BIN_PACKAGE_NAME("armv7a"), OPENCV_ENGINE_PACKAGE}; @@ -287,10 +293,10 @@ std::string CameraWrapperConnector::getDefaultPathLibFolder() } } - return std::string(); + return cv::String(); } -std::string CameraWrapperConnector::getPathLibFolder() +cv::String CameraWrapperConnector::getPathLibFolder() { if (!pathLibFolder.empty()) return pathLibFolder; @@ -358,10 +364,10 @@ std::string CameraWrapperConnector::getPathLibFolder() LOGE("Could not get library name and base address"); } - return std::string(); + return cv::String(); } -void CameraWrapperConnector::setPathLibFolder(const std::string& path) +void CameraWrapperConnector::setPathLibFolder(const cv::String& path) { pathLibFolder=path; } @@ -428,14 +434,14 @@ void CameraActivity::applyProperties() int CameraActivity::getFrameWidth() { if (frameWidth <= 0) - frameWidth = getProperty(ANDROID_CAMERA_PROPERTY_FRAMEWIDTH); + frameWidth = getProperty(ANDROID_CAMERA_PROPERTY_FRAMEWIDTH); return frameWidth; } int CameraActivity::getFrameHeight() { if (frameHeight <= 0) - frameHeight = getProperty(ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT); + frameHeight = getProperty(ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT); return frameHeight; } diff --git a/modules/bioinspired/CMakeLists.txt b/modules/bioinspired/CMakeLists.txt new file mode 100644 index 0000000000..b0f152cfcf --- /dev/null +++ b/modules/bioinspired/CMakeLists.txt @@ -0,0 +1,2 @@ +set(the_description "Biologically inspired algorithms") +ocv_define_module(bioinspired opencv_core OPTIONAL opencv_highgui opencv_ocl) diff --git a/modules/bioinspired/doc/bioinspired.rst b/modules/bioinspired/doc/bioinspired.rst new file mode 100644 index 0000000000..6bffcdcf28 --- /dev/null +++ b/modules/bioinspired/doc/bioinspired.rst @@ -0,0 +1,10 @@ +******************************************************************** +bioinspired. Biologically inspired vision models and derivated tools +******************************************************************** + +The module provides biological visual systems models (human visual system and others). It also provides derivated objects that take advantage of those bio-inspired models. + +.. toctree:: + :maxdepth: 2 + + Human retina documentation diff --git a/modules/bioinspired/doc/retina/images/retinaInput.jpg b/modules/bioinspired/doc/retina/images/retinaInput.jpg new file mode 100644 index 0000000000..d3cdeeecbd Binary files /dev/null and b/modules/bioinspired/doc/retina/images/retinaInput.jpg differ diff --git a/modules/bioinspired/doc/retina/images/retinaOutput_default.jpg b/modules/bioinspired/doc/retina/images/retinaOutput_default.jpg new file mode 100644 index 0000000000..0b14a5308f Binary files /dev/null and b/modules/bioinspired/doc/retina/images/retinaOutput_default.jpg differ diff --git a/modules/bioinspired/doc/retina/images/retinaOutput_realistic.jpg b/modules/bioinspired/doc/retina/images/retinaOutput_realistic.jpg new file mode 100644 index 0000000000..1bd60f80cc Binary files /dev/null and b/modules/bioinspired/doc/retina/images/retinaOutput_realistic.jpg differ diff --git a/modules/contrib/doc/retina/index.rst b/modules/bioinspired/doc/retina/index.rst similarity index 57% rename from modules/contrib/doc/retina/index.rst rename to modules/bioinspired/doc/retina/index.rst index a3a5bc82fc..242416baa7 100644 --- a/modules/contrib/doc/retina/index.rst +++ b/modules/bioinspired/doc/retina/index.rst @@ -5,56 +5,96 @@ Retina : a Bio mimetic human retina model Retina ====== +.. ocv:class:: Retina : public Algorithm -.. ocv:class:: Retina +**Note** : do not forget that the retina model is included in the following namespace : *cv::bioinspired*. -Class which provides the main controls to the Gipsa/Listic labs human retina model. Spatio-temporal filtering modelling the two main retina information channels : +Introduction +++++++++++++ -* foveal vision for detailled color vision : the parvocellular pathway). +Class which provides the main controls to the Gipsa/Listic labs human retina model. This is a non separable spatio-temporal filter modelling the two main retina information channels : -* periphearal vision for sensitive transient signals detection (motion and events) : the magnocellular pathway. +* foveal vision for detailled color vision : the parvocellular pathway. -**NOTE : See the Retina tutorial in the tutorial/contrib section for complementary explanations.** +* peripheral vision for sensitive transient signals detection (motion and events) : the magnocellular pathway. -The retina can be settled up with various parameters, by default, the retina cancels mean luminance and enforces all details of the visual scene. In order to use your own parameters, you can use at least one time the *write(std::string fs)* method which will write a proper XML file with all default parameters. Then, tweak it on your own and reload them at any time using method *setup(std::string fs)*. These methods update a *Retina::RetinaParameters* member structure that is described hereafter. :: +From a general point of view, this filter whitens the image spectrum and corrects luminance thanks to local adaptation. An other important property is its hability to filter out spatio-temporal noise while enhancing details. +This model originates from Jeanny Herault work [Herault2010]_. It has been involved in Alexandre Benoit phd and his current research [Benoit2010]_, [Strat2013]_ (he currently maintains this module within OpenCV). It includes the work of other Jeanny's phd student such as [Chaix2007]_ and the log polar transformations of Barthelemy Durette described in Jeanny's book. - class Retina +**NOTES :** + +* For ease of use in computer vision applications, the two retina channels are applied homogeneously on all the input images. This does not follow the real retina topology but this can still be done using the log sampling capabilities proposed within the class. + +* Extend the retina description and code use in the tutorial/contrib section for complementary explanations. + +Preliminary illustration +++++++++++++++++++++++++ + +As a preliminary presentation, let's start with a visual example. We propose to apply the filter on a low quality color jpeg image with backlight problems. Here is the considered input... *"Well, my eyes were able to see more that this strange black shadow..."* + +.. image:: images/retinaInput.jpg + :alt: a low quality color jpeg image with backlight problems. + :align: center + +Below, the retina foveal model applied on the entire image with default parameters. Here contours are enforced, halo effects are voluntary visible with this configuration. See parameters discussion below and increase horizontalCellsGain near 1 to remove them. + +.. image:: images/retinaOutput_default.jpg + :alt: the retina foveal model applied on the entire image with default parameters. Here contours are enforced, luminance is corrected and halo effects are voluntary visible with this configuration, increase horizontalCellsGain near 1 to remove them. + :align: center + +Below, a second retina foveal model output applied on the entire image with a parameters setup focused on naturalness perception. *"Hey, i now recognize my cat, looking at the mountains at the end of the day !"*. Here contours are enforced, luminance is corrected but halos are avoided with this configuration. The backlight effect is corrected and highlight details are still preserved. Then, even on a low quality jpeg image, if some luminance information remains, the retina is able to reconstruct a proper visual signal. Such configuration is also usefull for High Dynamic Range (*HDR*) images compression to 8bit images as discussed in [benoit2010]_ and in the demonstration codes discussed below. +As shown at the end of the page, parameters change from defaults are : + +* horizontalCellsGain=0.3 + +* photoreceptorsLocalAdaptationSensitivity=ganglioncellsSensitivity=0.89. + +.. image:: images/retinaOutput_realistic.jpg + :alt: the retina foveal model applied on the entire image with 'naturalness' parameters. Here contours are enforced but are avoided with this configuration, horizontalCellsGain is 0.3 and photoreceptorsLocalAdaptationSensitivity=ganglioncellsSensitivity=0.89. + :align: center + +As observed in this preliminary demo, the retina can be settled up with various parameters, by default, as shown on the figure above, the retina strongly reduces mean luminance energy and enforces all details of the visual scene. Luminance energy and halo effects can be modulated (exagerated to cancelled as shown on the two examples). In order to use your own parameters, you can use at least one time the *write(String fs)* method which will write a proper XML file with all default parameters. Then, tweak it on your own and reload them at any time using method *setup(String fs)*. These methods update a *Retina::RetinaParameters* member structure that is described hereafter. XML parameters file samples are shown at the end of the page. + +Here is an overview of the abstract Retina interface, allocate one instance with the *createRetina* functions.:: + + namespace cv{namespace bioinspired{ + + class Retina : public Algorithm { public: // parameters setup instance struct RetinaParameters; // this class is detailled later - // constructors - Retina (Size inputSize); - Retina (Size inputSize, const bool colorMode, RETINA_COLORSAMPLINGMETHOD colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0); + // main method for input frame processing (all use method, can also perform High Dynamic Range tone mapping) + void run (InputArray inputImage); - // main method for input frame processing - void run (const Mat &inputImage); + // specific method aiming at correcting luminance only (faster High Dynamic Range tone mapping) + void applyFastToneMapping(InputArray inputImage, OutputArray outputToneMappedImage) // output buffers retreival methods // -> foveal color vision details channel with luminance and noise correction - void getParvo (Mat &retinaOutput_parvo); - void getParvo (std::valarray< float > &retinaOutput_parvo); - const std::valarray< float > & getParvo () const; + void getParvo (OutputArray retinaOutput_parvo); + void getParvoRAW (OutputArray retinaOutput_parvo);// retreive original output buffers without any normalisation + const Mat getParvoRAW () const;// retreive original output buffers without any normalisation // -> peripheral monochrome motion and events (transient information) channel - void getMagno (Mat &retinaOutput_magno); - void getMagno (std::valarray< float > &retinaOutput_magno); - const std::valarray< float > & getMagno () const; + void getMagno (OutputArray retinaOutput_magno); + void getMagnoRAW (OutputArray retinaOutput_magno); // retreive original output buffers without any normalisation + const Mat getMagnoRAW () const;// retreive original output buffers without any normalisation // reset retina buffers... equivalent to closing your eyes for some seconds void clearBuffers (); // retreive input and output buffers sizes - Size inputSize (); - Size outputSize (); + Size getInputSize (); + Size getOutputSize (); // setup methods with specific parameters specification of global xml config file loading/write - void setup (std::string retinaParameterFile="", const bool applyDefaultSetupOnFailure=true); + void setup (String retinaParameterFile="", const bool applyDefaultSetupOnFailure=true); void setup (FileStorage &fs, const bool applyDefaultSetupOnFailure=true); void setup (RetinaParameters newParameters); struct Retina::RetinaParameters getParameters (); - const std::string printSetup (); - virtual void write (std::string fs) const; + const String printSetup (); + virtual void write (String fs) const; virtual void write (FileStorage &fs) const; void setupOPLandIPLParvoChannel (const bool colorMode=true, const bool normaliseOutput=true, const float photoreceptorsLocalAdaptationSensitivity=0.7, const float photoreceptorsTemporalConstant=0.5, const float photoreceptorsSpatialConstant=0.53, const float horizontalCellsGain=0, const float HcellsTemporalConstant=1, const float HcellsSpatialConstant=7, const float ganglionCellsSensitivity=0.7); void setupIPLMagnoChannel (const bool normaliseOutput=true, const float parasolCells_beta=0, const float parasolCells_tau=0, const float parasolCells_k=7, const float amacrinCellsTemporalCutFrequency=1.2, const float V0CompressionParameter=0.95, const float localAdaptintegration_tau=0, const float localAdaptintegration_k=7); @@ -63,11 +103,21 @@ The retina can be settled up with various parameters, by default, the retina can void activateContoursProcessing (const bool activate); }; + // Allocators + cv::Ptr createRetina (Size inputSize); + cv::Ptr createRetina (Size inputSize, const bool colorMode, RETINA_COLORSAMPLINGMETHOD colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0); + }} // cv and bioinspired namespaces end + +.. Sample code:: + + * An example on retina tone mapping can be found at opencv_source_code/samples/cpp/OpenEXRimages_HighDynamicRange_Retina_toneMapping.cpp + * An example on retina tone mapping on video input can be found at opencv_source_code/samples/cpp/OpenEXRimages_HighDynamicRange_Retina_toneMapping.cpp + * A complete example illustrating the retina interface can be found at opencv_source_code/samples/cpp/retinaDemo.cpp Description +++++++++++ -Class which allows the `Gipsa `_ (preliminary work) / `Listic `_ (code maintainer) labs retina model to be used. This class allows human retina spatio-temporal image processing to be applied on still images, images sequences and video sequences. Briefly, here are the main human retina model properties: +Class which allows the `Gipsa `_ (preliminary work) / `Listic `_ (code maintainer and user) labs retina model to be used. This class allows human retina spatio-temporal image processing to be applied on still images, images sequences and video sequences. Briefly, here are the main human retina model properties: * spectral whithening (mid-frequency details enhancement) @@ -83,19 +133,35 @@ Use : this model can be used basically for spatio-temporal video effects but als * performing motion analysis also taking benefit of the previously cited properties (check out the magnocellular retina channel output, by using the provided **getMagno** methods) +* general image/video sequence description using either one or both channels. An example of the use of Retina in a Bag of Words approach is given in [Strat2013]_. + +Literature +========== For more information, refer to the following papers : -* Benoit A., Caplier A., Durette B., Herault, J., "Using Human Visual System Modeling For Bio-Inspired Low Level Image Processing", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773. DOI +* Model description : + +.. [Benoit2010] Benoit A., Caplier A., Durette B., Herault, J., "Using Human Visual System Modeling For Bio-Inspired Low Level Image Processing", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773. DOI + +* Model use in a Bag of Words approach : + +.. [Strat2013] Strat S., Benoit A., Lambert P., "Retina enhanced SIFT descriptors for video indexing", CBMI2013, Veszprém, Hungary, 2013. * Please have a look at the reference work of Jeanny Herault that you can read in his book : -Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. +.. [Herault2010] Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. This retina filter code includes the research contributions of phd/research collegues from which code has been redrawn by the author : -* take a look at the *retinacolor.hpp* module to discover Brice Chaix de Lavarene phD color mosaicing/demosaicing and his reference paper: B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 +* take a look at the *retinacolor.hpp* module to discover Brice Chaix de Lavarene phD color mosaicing/demosaicing and his reference paper: -* take a look at *imagelogpolprojection.hpp* to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. ====> more informations in the above cited Jeanny Heraults's book. +.. [Chaix2007] B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 + +* take a look at *imagelogpolprojection.hpp* to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. More informations in the above cited Jeanny Heraults's book. + +* Meylan&al work on HDR tone mapping that is implemented as a specific method within the model : + +.. [Meylan2007] L. Meylan , D. Alleysson, S. Susstrunk, "A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images", Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816 Demos and experiments ! ======================= @@ -120,32 +186,38 @@ Take a look at the provided C++ examples provided with OpenCV : Then, take a HDR image using bracketing with your camera and generate an OpenEXR image and then process it using the demo. - Typical use, supposing that you have the OpenEXR image *memorial.exr* (present in the samples/cpp/ folder) + Typical use, supposing that you have the OpenEXR image such as *memorial.exr* (present in the samples/cpp/ folder) - **OpenCVReleaseFolder/bin/OpenEXRimages_HighDynamicRange_Retina_toneMapping memorial.exr** + **OpenCVReleaseFolder/bin/OpenEXRimages_HighDynamicRange_Retina_toneMapping memorial.exr [optionnal: 'fast']** Note that some sliders are made available to allow you to play with luminance compression. + If not using the 'fast' option, then, tone mapping is performed using the full retina model [Benoit2010]_. It includes spectral whitening that allows luminance energy to be reduced. When using the 'fast' option, then, a simpler method is used, it is an adaptation of the algorithm presented in [Meylan2007]_. This method gives also good results and is faster to process but it sometimes requires some more parameters adjustement. + Methods description =================== Here are detailled the main methods to control the retina model -Retina::Retina -++++++++++++++ +Ptr::createRetina ++++++++++++++++++++++++++ -.. ocv:function:: Retina::Retina(Size inputSize) -.. ocv:function:: Retina::Retina(Size inputSize, const bool colorMode, RETINA_COLORSAMPLINGMETHOD colorSamplingMethod = RETINA_COLOR_BAYER, const bool useRetinaLogSampling = false, const double reductionFactor = 1.0, const double samplingStrenght = 10.0 ) +.. ocv:function:: Ptr createRetina(Size inputSize) +.. ocv:function:: Ptr createRetina(Size inputSize, const bool colorMode, cv::bioinspired::RETINA_COLORSAMPLINGMETHOD colorSamplingMethod = cv::bioinspired::RETINA_COLOR_BAYER, const bool useRetinaLogSampling = false, const double reductionFactor = 1.0, const double samplingStrenght = 10.0 ) - Constructors + Constructors from standardized interfaces : retreive a smart pointer to a Retina instance :param inputSize: the input frame size :param colorMode: the chosen processing mode : with or without color processing - :param colorSamplingMethod: specifies which kind of color sampling will be used - * RETINA_COLOR_RANDOM: each pixel position is either R, G or B in a random choice - * RETINA_COLOR_DIAGONAL: color sampling is RGBRGBRGB..., line 2 BRGBRGBRG..., line 3, GBRGBRGBR... - * RETINA_COLOR_BAYER: standard bayer sampling + :param colorSamplingMethod: specifies which kind of color sampling will be used : + + * cv::bioinspired::RETINA_COLOR_RANDOM: each pixel position is either R, G or B in a random choice + + * cv::bioinspired::RETINA_COLOR_DIAGONAL: color sampling is RGBRGBRGB..., line 2 BRGBRGBRG..., line 3, GBRGBRGBR... + + * cv::bioinspired::RETINA_COLOR_BAYER: standard bayer sampling + :param useRetinaLogSampling: activate retina log sampling, if true, the 2 following parameters can be used :param reductionFactor: only usefull if param useRetinaLogSampling=true, specifies the reduction factor of the output frame (as the center (fovea) is high resolution and corners can be underscaled, then a reduction of the output is allowed without precision leak :param samplingStrenght: only usefull if param useRetinaLogSampling=true, specifies the strenght of the log scale that is applied @@ -178,55 +250,46 @@ Retina::clearBuffers Retina::getParvo ++++++++++++++++ -.. ocv:function:: void Retina::getParvo( Mat & retinaOutput_parvo ) -.. ocv:function:: void Retina::getParvo( std::valarray & retinaOutput_parvo ) -.. ocv:function:: const std::valarray & Retina::getParvo() const +.. ocv:function:: void Retina::getParvo( OutputArray retinaOutput_parvo ) +.. ocv:function:: void Retina::getParvoRAW( OutputArray retinaOutput_parvo ) +.. ocv:function:: const Mat Retina::getParvoRAW() const - Accessor of the details channel of the retina (models foveal vision) + Accessor of the details channel of the retina (models foveal vision). Warning, getParvoRAW methods return buffers that are not rescaled within range [0;255] while the non RAW method allows a normalized matrix to be retrieved. :param retinaOutput_parvo: the output buffer (reallocated if necessary), format can be : * a Mat, this output is rescaled for standard 8bits image processing use in OpenCV - * a 1D std::valarray Buffer (encoding is R1, R2, ... Rn), this output is the original retina filter model output, without any quantification or rescaling + * RAW methods actually return a 1D matrix (encoding is R1, R2, ... Rn, G1, G2, ..., Gn, B1, B2, ...Bn), this output is the original retina filter model output, without any quantification or rescaling. Retina::getMagno ++++++++++++++++ -.. ocv:function:: void Retina::getMagno( Mat & retinaOutput_magno ) -.. ocv:function:: void Retina::getMagno( std::valarray & retinaOutput_magno ) -.. ocv:function:: const std::valarray & Retina::getMagno() const +.. ocv:function:: void Retina::getMagno( OutputArray retinaOutput_magno ) +.. ocv:function:: void Retina::getMagnoRAW( OutputArray retinaOutput_magno ) +.. ocv:function:: const Mat Retina::getMagnoRAW() const - Accessor of the motion channel of the retina (models peripheral vision) + Accessor of the motion channel of the retina (models peripheral vision). Warning, getMagnoRAW methods return buffers that are not rescaled within range [0;255] while the non RAW method allows a normalized matrix to be retrieved. :param retinaOutput_magno: the output buffer (reallocated if necessary), format can be : * a Mat, this output is rescaled for standard 8bits image processing use in OpenCV - * a 1D std::valarray Buffer (encoding is R1, R2, ... Rn), this output is the original retina filter model output, without any quantification or rescaling + * RAW methods actually return a 1D matrix (encoding is M1, M2,... Mn), this output is the original retina filter model output, without any quantification or rescaling. -Retina::getParameters -+++++++++++++++++++++ +Retina::getInputSize +++++++++++++++++++++ -.. ocv:function:: Retina::RetinaParameters Retina::getParameters() - - Retrieve the current parameters values in a *Retina::RetinaParameters* structure - - :return: the current parameters setup - -Retina::inputSize -+++++++++++++++++ - -.. ocv:function:: Size Retina::inputSize() +.. ocv:function:: Size Retina::getInputSize() Retreive retina input buffer size :return: the retina input buffer size -Retina::outputSize -++++++++++++++++++ +Retina::getOutputSize ++++++++++++++++++++++ -.. ocv:function:: Size Retina::outputSize() +.. ocv:function:: Size Retina::getOutputSize() Retreive retina output buffer size that can be different from the input if a spatial log transformation is applied @@ -235,21 +298,33 @@ Retina::outputSize Retina::printSetup ++++++++++++++++++ -.. ocv:function:: const std::string Retina::printSetup() +.. ocv:function:: const String Retina::printSetup() Outputs a string showing the used parameters setup - :return: a string which contains formatted parameters information + :return: a string which contains formated parameters information Retina::run +++++++++++ -.. ocv:function:: void Retina::run(const Mat & inputImage) +.. ocv:function:: void Retina::run(InputArray inputImage) Method which allows retina to be applied on an input image, after run, encapsulated retina module is ready to deliver its outputs using dedicated acccessors, see getParvo and getMagno methods :param inputImage: the input Mat image to be processed, can be gray level or BGR coded in any format (from 8bit to 16bits) +Retina::applyFastToneMapping +++++++++++++++++++++++++++++ + +.. ocv:function:: void Retina::applyFastToneMapping(InputArray inputImage, OutputArray outputToneMappedImage) + + Method which processes an image in the aim to correct its luminance : correct backlight problems, enhance details in shadows. This method is designed to perform High Dynamic Range image tone mapping (compress >8bit/pixel images to 8bit/pixel). This is a simplified version of the Retina Parvocellular model (simplified version of the run/getParvo methods call) since it does not include the spatio-temporal filter modelling the Outer Plexiform Layer of the retina that performs spectral whitening and many other stuff. However, it works great for tone mapping and in a faster way. + + Check the demos and experiments section to see examples and the way to perform tone mapping using the original retina model and the method. + + :param inputImage: the input image to process (should be coded in float format : CV_32F, CV_32FC1, CV_32F_C3, CV_32F_C4, the 4th channel won't be considered). + :param outputToneMappedImage: the output 8bit/channel tone mapped image (CV_8U or CV_8UC3 format). + Retina::setColorSaturation ++++++++++++++++++++++++++ @@ -264,7 +339,7 @@ Retina::setColorSaturation Retina::setup +++++++++++++ -.. ocv:function:: void Retina::setup(std::string retinaParameterFile = "", const bool applyDefaultSetupOnFailure = true ) +.. ocv:function:: void Retina::setup(String retinaParameterFile = "", const bool applyDefaultSetupOnFailure = true ) .. ocv:function:: void Retina::setup(FileStorage & fs, const bool applyDefaultSetupOnFailure = true ) .. ocv:function:: void Retina::setup(RetinaParameters newParameters) @@ -273,12 +348,12 @@ Retina::setup :param retinaParameterFile: the parameters filename :param applyDefaultSetupOnFailure: set to true if an error must be thrown on error :param fs: the open Filestorage which contains retina parameters - :param newParameters: a parameters structures updated with the new target configuration + :param newParameters: a parameters structures updated with the new target configuration. You can retreive the current parameers structure using method *Retina::RetinaParameters Retina::getParameters()* and update it before running method *setup*. Retina::write +++++++++++++ -.. ocv:function:: void Retina::write( std::string fs ) const +.. ocv:function:: void Retina::write( String fs ) const .. ocv:function:: void Retina::write( FileStorage& fs ) const Write xml/yml formated parameters information @@ -335,7 +410,7 @@ Retina::RetinaParameters photoreceptorsTemporalConstant(0.5f),// the time constant of the first order low pass filter of the photoreceptors, use it to cut high temporal frequencies (noise or fast motion), unit is frames, typical value is 1 frame photoreceptorsSpatialConstant(0.53f),// the spatial constant of the first order low pass filter of the photoreceptors, use it to cut high spatial frequencies (noise or thick contours), unit is pixels, typical value is 1 pixel horizontalCellsGain(0.0f),//gain of the horizontal cells network, if 0, then the mean value of the output is zero, if the parameter is near 1, then, the luminance is not filtered and is still reachable at the output, typicall value is 0 - hcellsTemporalConstant(1.f),// the time constant of the first order low pass filter of the horizontal cells, use it to cut low temporal frequencies (local luminance variations), unit is frames, typical value is 1 frame, as the photoreceptors + hcellsTemporalConstant(1.f),// the time constant of the first order low pass filter of the horizontal cells, use it to cut low temporal frequencies (local luminance variations), unit is frames, typical value is 1 frame, as the photoreceptors. Reduce to 0.5 to limit retina after effects. hcellsSpatialConstant(7.f),//the spatial constant of the first order low pass filter of the horizontal cells, use it to cut low spatial frequencies (local luminance), unit is pixels, typical value is 5 pixel, this value is also used for local contrast computing when computing the local contrast adaptation at the ganglion cells level (Inner Plexiform Layer parvocellular channel model) ganglionCellsSensitivity(0.7f)//the compression strengh of the ganglion cells local adaptation output, set a value between 0.6 and 1 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 0.7 {};// default setup @@ -359,3 +434,60 @@ Retina::RetinaParameters struct OPLandIplParvoParameters OPLandIplParvo; struct IplMagnoParameters IplMagno; }; + +Retina parameters files examples +++++++++++++++++++++++++++++++++ + +Here is the default configuration file of the retina module. It gives results such as the first retina output shown on the top of this page. + +.. code-block:: cpp + + + + + 1 + 1 + 7.5e-01 + 9.0e-01 + 5.3e-01 + 0.01 + 0.5 + 7. + 7.5e-01 + + 1 + 0. + 0. + 7. + 2.0e+00 + 9.5e-01 + 0. + 7. + + +Here is the 'realistic" setup used to obtain the second retina output shown on the top of this page. + +.. code-block:: cpp + + + + + 1 + 1 + 8.9e-01 + 9.0e-01 + 5.3e-01 + 0.3 + 0.5 + 7. + 8.9e-01 + + 1 + 0. + 0. + 7. + 2.0e+00 + 9.5e-01 + 0. + 7. + diff --git a/modules/bioinspired/include/opencv2/bioinspired.hpp b/modules/bioinspired/include/opencv2/bioinspired.hpp new file mode 100644 index 0000000000..5f2f8644d2 --- /dev/null +++ b/modules/bioinspired/include/opencv2/bioinspired.hpp @@ -0,0 +1,50 @@ +/*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_BIOINSPIRED_HPP__ +#define __OPENCV_BIOINSPIRED_HPP__ + +#include "opencv2/core.hpp" +#include "opencv2/bioinspired/retina.hpp" +#include "opencv2/bioinspired/retinafasttonemapping.hpp" + +#endif diff --git a/modules/bioinspired/include/opencv2/bioinspired/bioinspired.hpp b/modules/bioinspired/include/opencv2/bioinspired/bioinspired.hpp new file mode 100644 index 0000000000..40be2854eb --- /dev/null +++ b/modules/bioinspired/include/opencv2/bioinspired/bioinspired.hpp @@ -0,0 +1,48 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#ifdef __OPENCV_BUILD +#error this is a compatibility header which should not be used inside the OpenCV library +#endif + +#include "opencv2/bioinspired.hpp" diff --git a/modules/contrib/include/opencv2/contrib/retina.hpp b/modules/bioinspired/include/opencv2/bioinspired/retina.hpp similarity index 73% rename from modules/contrib/include/opencv2/contrib/retina.hpp rename to modules/bioinspired/include/opencv2/bioinspired/retina.hpp index 456daab443..b4fda7038e 100644 --- a/modules/contrib/include/opencv2/contrib/retina.hpp +++ b/modules/bioinspired/include/opencv2/bioinspired/retina.hpp @@ -6,12 +6,12 @@ ** copy or use the software. ** ** - ** HVStools : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. + ** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. ** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. ** ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) ** - ** Creation - enhancement process 2007-2011 + ** Creation - enhancement process 2007-2013 ** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France ** ** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr). @@ -32,7 +32,7 @@ ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. ** - ** For Human Visual System tools (hvstools) + ** For Human Visual System tools (bioinspired) ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved. ** ** Third party copyrights are property of their respective owners. @@ -62,8 +62,8 @@ ** the use of this software, even if advised of the possibility of such damage. *******************************************************************************/ -#ifndef __OPENCV_CONTRIB_RETINA_HPP__ -#define __OPENCV_CONTRIB_RETINA_HPP__ +#ifndef __OPENCV_BIOINSPIRED_RETINA_HPP__ +#define __OPENCV_BIOINSPIRED_RETINA_HPP__ /* * Retina.hpp @@ -73,22 +73,19 @@ */ #include "opencv2/core.hpp" // for all OpenCV core functionalities access, including cv::Exception support -#include -namespace cv -{ -enum RETINA_COLORSAMPLINGMETHOD -{ +namespace cv{ +namespace bioinspired{ + +enum { RETINA_COLOR_RANDOM, //!< each pixel position is either R, G or B in a random choice RETINA_COLOR_DIAGONAL,//!< color sampling is RGBRGBRGB..., line 2 BRGBRGBRG..., line 3, GBRGBRGBR... RETINA_COLOR_BAYER//!< standard bayer sampling }; -class RetinaFilter; - /** - * @class Retina a wrapper class which allows the Gipsa/Listic Labs model to be used. + * @class Retina a wrapper class which allows the Gipsa/Listic Labs model to be used with OpenCV. * This retina model allows spatio-temporal image processing (applied on still images, video sequences). * As a summary, these are the retina model properties: * => It applies a spectral whithening (mid-frequency details enhancement) @@ -110,7 +107,7 @@ class RetinaFilter; * _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. * ====> more informations in the above cited Jeanny Heraults's book. */ -class CV_EXPORTS Retina { +class CV_EXPORTS Retina : public Algorithm { public: @@ -119,13 +116,13 @@ public: struct OPLandIplParvoParameters{ // Outer Plexiform Layer (OPL) and Inner Plexiform Layer Parvocellular (IplParvo) parameters OPLandIplParvoParameters():colorMode(true), normaliseOutput(true), - photoreceptorsLocalAdaptationSensitivity(0.7f), - photoreceptorsTemporalConstant(0.5f), + photoreceptorsLocalAdaptationSensitivity(0.75f), + photoreceptorsTemporalConstant(0.9f), photoreceptorsSpatialConstant(0.53f), - horizontalCellsGain(0.0f), - hcellsTemporalConstant(1.f), + horizontalCellsGain(0.01f), + hcellsTemporalConstant(0.5f), hcellsSpatialConstant(7.f), - ganglionCellsSensitivity(0.7f){};// default setup + ganglionCellsSensitivity(0.75f){};// default setup bool colorMode, normaliseOutput; float photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, hcellsTemporalConstant, hcellsSpatialConstant, ganglionCellsSensitivity; }; @@ -135,7 +132,7 @@ public: parasolCells_beta(0.f), parasolCells_tau(0.f), parasolCells_k(7.f), - amacrinCellsTemporalCutFrequency(1.2f), + amacrinCellsTemporalCutFrequency(2.0f), V0CompressionParameter(0.95f), localAdaptintegration_tau(0.f), localAdaptintegration_k(7.f){};// default setup @@ -146,34 +143,15 @@ public: struct IplMagnoParameters IplMagno; }; - /** - * Main constructor with most commun use setup : create an instance of color ready retina model - * @param inputSize : the input frame size - */ - Retina(Size inputSize); - - /** - * Complete Retina filter constructor which allows all basic structural parameters definition - * @param inputSize : the input frame size - * @param colorMode : the chosen processing mode : with or without color processing - * @param colorSamplingMethod: specifies which kind of color sampling will be used - * @param useRetinaLogSampling: activate retina log sampling, if true, the 2 following parameters can be used - * @param reductionFactor: only usefull if param useRetinaLogSampling=true, specifies the reduction factor of the output frame (as the center (fovea) is high resolution and corners can be underscaled, then a reduction of the output is allowed without precision leak - * @param samplingStrenght: only usefull if param useRetinaLogSampling=true, specifies the strenght of the log scale that is applied - */ - Retina(Size inputSize, const bool colorMode, RETINA_COLORSAMPLINGMETHOD colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0); - - virtual ~Retina(); - /** * retreive retina input buffer size */ - Size inputSize(); + virtual Size getInputSize()=0; /** * retreive retina output buffer size */ - Size outputSize(); + virtual Size getOutputSize()=0; /** * try to open an XML retina parameters file to adjust current retina instance setup @@ -182,8 +160,7 @@ public: * @param retinaParameterFile : the parameters filename * @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error */ - void setup(std::string retinaParameterFile="", const bool applyDefaultSetupOnFailure=true); - + virtual void setup(String retinaParameterFile="", const bool applyDefaultSetupOnFailure=true)=0; /** * try to open an XML retina parameters file to adjust current retina instance setup @@ -192,7 +169,7 @@ public: * @param fs : the open Filestorage which contains retina parameters * @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error */ - void setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure=true); + virtual void setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure=true)=0; /** * try to open an XML retina parameters file to adjust current retina instance setup @@ -201,31 +178,30 @@ public: * @param newParameters : a parameters structures updated with the new target configuration * @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error */ - void setup(RetinaParameters newParameters); + virtual void setup(RetinaParameters newParameters)=0; /** - * @return the current parameters setup - */ - Retina::RetinaParameters getParameters(); + * @return the current parameters setup + */ + virtual struct Retina::RetinaParameters getParameters()=0; /** * parameters setup display method * @return a string which contains formatted parameters information */ - const std::string printSetup(); + virtual const String printSetup()=0; /** * write xml/yml formated parameters information * @rparam fs : the filename of the xml file that will be open and writen with formatted parameters information */ - virtual void write( std::string fs ) const; - + virtual void write( String fs ) const=0; /** * write xml/yml formated parameters information * @param fs : a cv::Filestorage object ready to be filled */ - virtual void write( FileStorage& fs ) const; + virtual void write( FileStorage& fs ) const=0; /** * setup the OPL and IPL parvo channels (see biologocal model) @@ -242,7 +218,7 @@ public: * @param HcellsSpatialConstant: the spatial constant of the first order low pass filter of the horizontal cells, use it to cut low spatial frequencies (local luminance), unit is pixels, typical value is 5 pixel, this value is also used for local contrast computing when computing the local contrast adaptation at the ganglion cells level (Inner Plexiform Layer parvocellular channel model) * @param ganglionCellsSensitivity: the compression strengh of the ganglion cells local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 230 */ - void setupOPLandIPLParvoChannel(const bool colorMode=true, const bool normaliseOutput = true, const float photoreceptorsLocalAdaptationSensitivity=0.7, const float photoreceptorsTemporalConstant=0.5, const float photoreceptorsSpatialConstant=0.53, const float horizontalCellsGain=0, const float HcellsTemporalConstant=1, const float HcellsSpatialConstant=7, const float ganglionCellsSensitivity=0.7); + virtual void setupOPLandIPLParvoChannel(const bool colorMode=true, const bool normaliseOutput = true, const float photoreceptorsLocalAdaptationSensitivity=0.7, const float photoreceptorsTemporalConstant=0.5, const float photoreceptorsSpatialConstant=0.53, const float horizontalCellsGain=0, const float HcellsTemporalConstant=1, const float HcellsSpatialConstant=7, const float ganglionCellsSensitivity=0.7)=0; /** * set parameters values for the Inner Plexiform Layer (IPL) magnocellular channel @@ -256,41 +232,49 @@ public: * @param localAdaptintegration_tau: specifies the temporal constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation * @param localAdaptintegration_k: specifies the spatial constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation */ - void setupIPLMagnoChannel(const bool normaliseOutput = true, const float parasolCells_beta=0, const float parasolCells_tau=0, const float parasolCells_k=7, const float amacrinCellsTemporalCutFrequency=1.2, const float V0CompressionParameter=0.95, const float localAdaptintegration_tau=0, const float localAdaptintegration_k=7); + virtual void setupIPLMagnoChannel(const bool normaliseOutput = true, const float parasolCells_beta=0, const float parasolCells_tau=0, const float parasolCells_k=7, const float amacrinCellsTemporalCutFrequency=1.2, const float V0CompressionParameter=0.95, const float localAdaptintegration_tau=0, const float localAdaptintegration_k=7)=0; /** * method which allows retina to be applied on an input image, after run, encapsulated retina module is ready to deliver its outputs using dedicated acccessors, see getParvo and getMagno methods * @param inputImage : the input cv::Mat image to be processed, can be gray level or BGR coded in any format (from 8bit to 16bits) */ - void run(const Mat &inputImage); + virtual void run(InputArray inputImage)=0; + + /** + * method that applies a luminance correction (initially High Dynamic Range (HDR) tone mapping) using only the 2 local adaptation stages of the retina parvo channel : photoreceptors level and ganlion cells level. Spatio temporal filtering is applied but limited to temporal smoothing and eventually high frequencies attenuation. This is a lighter method than the one available using the regular run method. It is then faster but it does not include complete temporal filtering nor retina spectral whitening. Then, it can have a more limited effect on images with a very high dynamic range. This is an adptation of the original still image HDR tone mapping algorithm of David Alleyson, Sabine Susstruck and Laurence Meylan's work, please cite: + * -> Meylan L., Alleysson D., and Susstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816 + @param inputImage the input image to process RGB or gray levels + @param outputToneMappedImage the output tone mapped image + */ + virtual void applyFastToneMapping(InputArray inputImage, OutputArray outputToneMappedImage)=0; /** * accessor of the details channel of the retina (models foveal vision) * @param retinaOutput_parvo : the output buffer (reallocated if necessary), this output is rescaled for standard 8bits image processing use in OpenCV */ - void getParvo(Mat &retinaOutput_parvo); + virtual void getParvo(OutputArray retinaOutput_parvo)=0; /** * accessor of the details channel of the retina (models foveal vision) - * @param retinaOutput_parvo : the output buffer (reallocated if necessary), this output is the original retina filter model output, without any quantification or rescaling + * @param retinaOutput_parvo : a cv::Mat header filled with the internal parvo buffer of the retina module. This output is the original retina filter model output, without any quantification or rescaling */ - void getParvo(std::valarray &retinaOutput_parvo); + virtual void getParvoRAW(OutputArray retinaOutput_parvo)=0; /** * accessor of the motion channel of the retina (models peripheral vision) * @param retinaOutput_magno : the output buffer (reallocated if necessary), this output is rescaled for standard 8bits image processing use in OpenCV */ - void getMagno(Mat &retinaOutput_magno); + virtual void getMagno(OutputArray retinaOutput_magno)=0; /** * accessor of the motion channel of the retina (models peripheral vision) - * @param retinaOutput_magno : the output buffer (reallocated if necessary), this output is the original retina filter model output, without any quantification or rescaling + * @param retinaOutput_magno : a cv::Mat header filled with the internal retina magno buffer of the retina module. This output is the original retina filter model output, without any quantification or rescaling */ - void getMagno(std::valarray &retinaOutput_magno); + virtual void getMagnoRAW(OutputArray retinaOutput_magno)=0; - // original API level data accessors : get buffers addresses... - const std::valarray & getMagno() const; - const std::valarray & getParvo() const; + // original API level data accessors : get buffers addresses from a Mat header, similar to getParvoRAW and getMagnoRAW... + virtual const Mat getMagnoRAW() const=0; + virtual const Mat getParvoRAW() const=0; /** * activate color saturation as the final step of the color demultiplexing process @@ -298,59 +282,30 @@ public: * @param saturateColors: boolean that activates color saturation (if true) or desactivate (if false) * @param colorSaturationValue: the saturation factor */ - void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0); + virtual void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0)=0; /** * clear all retina buffers (equivalent to opening the eyes after a long period of eye close ;o) */ - void clearBuffers(); + virtual void clearBuffers()=0; /** * Activate/desactivate the Magnocellular pathway processing (motion information extraction), by default, it is activated * @param activate: true if Magnocellular output should be activated, false if not */ - void activateMovingContoursProcessing(const bool activate); + virtual void activateMovingContoursProcessing(const bool activate)=0; /** * Activate/desactivate the Parvocellular pathway processing (contours information extraction), by default, it is activated * @param activate: true if Parvocellular (contours information extraction) output should be activated, false if not */ - void activateContoursProcessing(const bool activate); - -protected: - // Parameteres setup members - RetinaParameters _retinaParameters; // structure of parameters - - // Retina model related modules - std::valarray _inputBuffer; //!< buffer used to convert input cv::Mat to internal retina buffers format (valarrays) - - // pointer to retina model - RetinaFilter* _retinaFilter; //!< the pointer to the retina module, allocated with instance construction - - /** - * exports a valarray buffer outing from HVStools objects to a cv::Mat in CV_8UC1 (gray level picture) or CV_8UC3 (color) format - * @param grayMatrixToConvert the valarray to export to OpenCV - * @param nbRows : the number of rows of the valarray flatten matrix - * @param nbColumns : the number of rows of the valarray flatten matrix - * @param colorMode : a flag which mentions if matrix is color (true) or graylevel (false) - * @param outBuffer : the output matrix which is reallocated to satisfy Retina output buffer dimensions - */ - void _convertValarrayBuffer2cvMat(const std::valarray &grayMatrixToConvert, const unsigned int nbRows, const unsigned int nbColumns, const bool colorMode, Mat &outBuffer); - - /** - * - * @param inputMatToConvert : the OpenCV cv::Mat that has to be converted to gray or RGB valarray buffer that will be processed by the retina model - * @param outputValarrayMatrix : the output valarray - * @return the input image color mode (color=true, gray levels=false) - */ - bool _convertCvMat2ValarrayBuffer(const cv::Mat inputMatToConvert, std::valarray &outputValarrayMatrix); - - //! private method called by constructors, gathers their parameters and use them in a unified way - void _init(const Size inputSize, const bool colorMode, RETINA_COLORSAMPLINGMETHOD colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0); - - + virtual void activateContoursProcessing(const bool activate)=0; }; +CV_EXPORTS Ptr createRetina(Size inputSize); +CV_EXPORTS Ptr createRetina(Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0); +CV_EXPORTS Ptr createRetina_OCL(Size inputSize); +CV_EXPORTS Ptr createRetina_OCL(Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0); } -#endif /* __OPENCV_CONTRIB_RETINA_HPP__ */ - +} +#endif /* __OPENCV_BIOINSPIRED_RETINA_HPP__ */ diff --git a/modules/bioinspired/include/opencv2/bioinspired/retinafasttonemapping.hpp b/modules/bioinspired/include/opencv2/bioinspired/retinafasttonemapping.hpp new file mode 100644 index 0000000000..6c83f885c8 --- /dev/null +++ b/modules/bioinspired/include/opencv2/bioinspired/retinafasttonemapping.hpp @@ -0,0 +1,121 @@ + +/*#****************************************************************************** + ** 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. + ** + ** + ** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. + ** + ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) + ** + ** Creation - enhancement process 2007-2013 + ** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France + ** + ** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr). + ** Refer to the following research paper for more information: + ** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 + ** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book: + ** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. + ** + ** + ** + ** + ** + ** This class is based on image processing tools of the author and already used within the Retina class (this is the same code as method retina::applyFastToneMapping, but in an independent class, it is ligth from a memory requirement point of view). It implements an adaptation of the efficient tone mapping algorithm propose by David Alleyson, Sabine Susstruck and Laurence Meylan's work, please cite: + ** -> Meylan L., Alleysson D., and Susstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816 + ** + ** + ** License Agreement + ** For Open Source Computer Vision Library + ** + ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. + ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. + ** + ** For Human Visual System tools (bioinspired) + ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: + ** + ** * Redistributions of source code must retain the above copyright notice, + ** this list of conditions and the following disclaimer. + ** + ** * Redistributions 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. + *******************************************************************************/ + +#ifndef __OPENCV_BIOINSPIRED_RETINAFASTTONEMAPPING_HPP__ +#define __OPENCV_BIOINSPIRED_RETINAFASTTONEMAPPING_HPP__ + +/* + * retinafasttonemapping.hpp + * + * Created on: May 26, 2013 + * Author: Alexandre Benoit + */ + +#include "opencv2/core.hpp" // for all OpenCV core functionalities access, including cv::Exception support + +namespace cv{ +namespace bioinspired{ + +/** + * @class RetinaFastToneMappingImpl a wrapper class which allows the tone mapping algorithm of Meylan&al(2007) to be used with OpenCV. + * This algorithm is already implemented in thre Retina class (retina::applyFastToneMapping) but used it does not require all the retina model to be allocated. This allows a light memory use for low memory devices (smartphones, etc. + * As a summary, these are the model properties: + * => 2 stages of local luminance adaptation with a different local neighborhood for each. + * => first stage models the retina photorecetors local luminance adaptation + * => second stage models th ganglion cells local information adaptation + * => compared to the initial publication, this class uses spatio-temporal low pass filters instead of spatial only filters. + * ====> this can help noise robustness and temporal stability for video sequence use cases. + * for more information, read to the following papers : + * Meylan L., Alleysson D., and Susstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 + * regarding spatio-temporal filter and the bigger retina model : + * Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. + */ +class CV_EXPORTS RetinaFastToneMapping : public Algorithm +{ +public: + + /** + * method that applies a luminance correction (initially High Dynamic Range (HDR) tone mapping) using only the 2 local adaptation stages of the retina parvocellular channel : photoreceptors level and ganlion cells level. Spatio temporal filtering is applied but limited to temporal smoothing and eventually high frequencies attenuation. This is a lighter method than the one available using the regular retina::run method. It is then faster but it does not include complete temporal filtering nor retina spectral whitening. Then, it can have a more limited effect on images with a very high dynamic range. This is an adptation of the original still image HDR tone mapping algorithm of David Alleyson, Sabine Susstruck and Laurence Meylan's work, please cite: + * -> Meylan L., Alleysson D., and Susstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816 + @param inputImage the input image to process RGB or gray levels + @param outputToneMappedImage the output tone mapped image + */ + virtual void applyFastToneMapping(InputArray inputImage, OutputArray outputToneMappedImage)=0; + + /** + * setup method that updates tone mapping behaviors by adjusing the local luminance computation area + * @param photoreceptorsNeighborhoodRadius the first stage local adaptation area + * @param ganglioncellsNeighborhoodRadius the second stage local adaptation area + * @param meanLuminanceModulatorK the factor applied to modulate the meanLuminance information (default is 1, see reference paper) + */ + virtual void setup(const float photoreceptorsNeighborhoodRadius=3.f, const float ganglioncellsNeighborhoodRadius=1.f, const float meanLuminanceModulatorK=1.f)=0; +}; + +CV_EXPORTS Ptr createRetinaFastToneMapping(Size inputSize); + +} +} +#endif /* __OPENCV_BIOINSPIRED_RETINAFASTTONEMAPPING_HPP__ */ diff --git a/modules/contrib/src/basicretinafilter.cpp b/modules/bioinspired/src/basicretinafilter.cpp similarity index 98% rename from modules/contrib/src/basicretinafilter.cpp rename to modules/bioinspired/src/basicretinafilter.cpp index 020b8f04e1..7e7b467faa 100644 --- a/modules/contrib/src/basicretinafilter.cpp +++ b/modules/bioinspired/src/basicretinafilter.cpp @@ -6,7 +6,7 @@ ** copy or use the software. ** ** -** HVStools : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. +** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. ** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. ** ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) @@ -32,7 +32,7 @@ ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. ** -** For Human Visual System tools (hvstools) +** For Human Visual System tools (bioinspired) ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved. ** ** Third party copyrights are property of their respective owners. @@ -72,7 +72,8 @@ namespace cv { - +namespace bioinspired +{ // @author Alexandre BENOIT, benoit.alexandre.vision@gmail.com, LISTIC : www.listic.univ-savoie.fr Gipsa-Lab, France: www.gipsa-lab.inpg.fr/ ////////////////////////////////////////////////////////// @@ -883,4 +884,5 @@ void BasicRetinaFilter::_verticalAnticausalFilter_Irregular_multGain(float *outp } } -} +}// end of namespace bioinspired +}// end of namespace cv diff --git a/modules/contrib/src/basicretinafilter.hpp b/modules/bioinspired/src/basicretinafilter.hpp similarity index 98% rename from modules/contrib/src/basicretinafilter.hpp rename to modules/bioinspired/src/basicretinafilter.hpp index a2ece415db..323bff9408 100644 --- a/modules/contrib/src/basicretinafilter.hpp +++ b/modules/bioinspired/src/basicretinafilter.hpp @@ -6,7 +6,7 @@ ** copy or use the software. ** ** -** HVStools : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. +** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. ** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. ** ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) @@ -32,7 +32,7 @@ ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. ** -** For Human Visual System tools (hvstools) +** For Human Visual System tools (bioinspired) ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved. ** ** Third party copyrights are property of their respective owners. @@ -113,6 +113,8 @@ //#define __BASIC_RETINA_ELEMENT_DEBUG namespace cv +{ +namespace bioinspired { class BasicRetinaFilter { @@ -287,7 +289,7 @@ namespace cv * @param maxInputValue: the maximum amplitude value measured after local adaptation processing (c.f. function runFilter_LocalAdapdation & runFilter_LocalAdapdation_autonomous) * @param meanLuminance: the a priori meann luminance of the input data (should be 128 for 8bits images but can vary greatly in case of High Dynamic Range Images (HDRI) */ - void setV0CompressionParameterToneMapping(const float v0, const float maxInputValue, const float meanLuminance=128.0f){ _v0=v0*maxInputValue; _localLuminanceFactor=1.0f; _localLuminanceAddon=meanLuminance*_v0; _maxInputValue=maxInputValue;}; + void setV0CompressionParameterToneMapping(const float v0, const float maxInputValue, const float meanLuminance=128.0f){ _v0=v0*maxInputValue; _localLuminanceFactor=1.0f; _localLuminanceAddon=meanLuminance*v0; _maxInputValue=maxInputValue;}; /** * update compression parameters while keeping v0 parameter value @@ -650,7 +652,6 @@ namespace cv }; -} +}// end of namespace bioinspired +}// end of namespace cv #endif - - diff --git a/modules/contrib/src/imagelogpolprojection.cpp b/modules/bioinspired/src/imagelogpolprojection.cpp similarity index 98% rename from modules/contrib/src/imagelogpolprojection.cpp rename to modules/bioinspired/src/imagelogpolprojection.cpp index 22f5214e7c..0a4c1ed0de 100644 --- a/modules/contrib/src/imagelogpolprojection.cpp +++ b/modules/bioinspired/src/imagelogpolprojection.cpp @@ -6,7 +6,7 @@ ** copy or use the software. ** ** -** HVStools : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. +** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. ** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. ** ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) @@ -32,7 +32,7 @@ ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. ** -** For Human Visual System tools (hvstools) +** For Human Visual System tools (bioinspired) ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved. ** ** Third party copyrights are property of their respective owners. @@ -72,7 +72,8 @@ namespace cv { - +namespace bioinspired +{ // constructor ImageLogPolProjection::ImageLogPolProjection(const unsigned int nbRows, const unsigned int nbColumns, const PROJECTIONTYPE projection, const bool colorModeCapable) :BasicRetinaFilter(nbRows, nbColumns), @@ -446,4 +447,5 @@ std::valarray &ImageLogPolProjection::runProjection(const std::valarray &MagnoRetinaFilter::runFilter(const std::valarray> 2) + +///////////////////////////////////////////////////////// +//******************************************************* +// basicretinafilter +//////////////// _spatiotemporalLPfilter //////////////// +//_horizontalCausalFilter_addInput +kernel void horizontalCausalFilter_addInput( + global const float * input, + global float * output, + const int cols, + const int rows, + const int elements_per_row, + const int in_offset, + const int out_offset, + const float _tau, + const float _a +) +{ + int gid = get_global_id(0); + if(gid >= rows) + { + return; + } + + global const float * iptr = + input + mad24(gid, elements_per_row, in_offset / 4); + global float * optr = + output + mad24(gid, elements_per_row, out_offset / 4); + + float res; + float4 in_v4, out_v4, res_v4 = (float4)(0); + //vectorize to increase throughput + for(int i = 0; i < cols / 4; ++i, iptr += 4, optr += 4) + { + in_v4 = vload4(0, iptr); + out_v4 = vload4(0, optr); + + res_v4.x = in_v4.x + _tau * out_v4.x + _a * res_v4.w; + res_v4.y = in_v4.y + _tau * out_v4.y + _a * res_v4.x; + res_v4.z = in_v4.z + _tau * out_v4.z + _a * res_v4.y; + res_v4.w = in_v4.w + _tau * out_v4.w + _a * res_v4.z; + + vstore4(res_v4, 0, optr); + } + res = res_v4.w; + // there may be left some + for(int i = 0; i < cols % 4; ++i, ++iptr, ++optr) + { + res = *iptr + _tau * *optr + _a * res; + *optr = res; + } +} + +//_horizontalAnticausalFilter +kernel void horizontalAnticausalFilter( + global float * output, + const int cols, + const int rows, + const int elements_per_row, + const int out_offset, + const float _a +) +{ + int gid = get_global_id(0); + if(gid >= rows) + { + return; + } + + global float * optr = output + + mad24(gid + 1, elements_per_row, - 1 + out_offset / 4); + + float4 result_v4 = (float4)(0), out_v4; + float result = 0; + // we assume elements_per_row is multple of WIDTH_MULTIPLE + for(int i = 0; i < WIDTH_MULTIPLE; ++ i, -- optr) + { + if(i >= elements_per_row - cols) + { + result = *optr + _a * result; + } + *optr = result; + } + result_v4.x = result; + optr -= 3; + for(int i = WIDTH_MULTIPLE / 4; i < elements_per_row / 4; ++i, optr -= 4) + { + // shift left, `offset` is type `size_t` so it cannot be negative + out_v4 = vload4(0, optr); + + result_v4.w = out_v4.w + _a * result_v4.x; + result_v4.z = out_v4.z + _a * result_v4.w; + result_v4.y = out_v4.y + _a * result_v4.z; + result_v4.x = out_v4.x + _a * result_v4.y; + + vstore4(result_v4, 0, optr); + } +} + +//_verticalCausalFilter +kernel void verticalCausalFilter( + global float * output, + const int cols, + const int rows, + const int elements_per_row, + const int out_offset, + const float _a +) +{ + int gid = get_global_id(0); + if(gid >= cols) + { + return; + } + + global float * optr = output + gid + out_offset / 4; + float result = 0; + for(int i = 0; i < rows; ++i, optr += elements_per_row) + { + result = *optr + _a * result; + *optr = result; + } +} + +//_verticalCausalFilter +kernel void verticalAnticausalFilter_multGain( + global float * output, + const int cols, + const int rows, + const int elements_per_row, + const int out_offset, + const float _a, + const float _gain +) +{ + int gid = get_global_id(0); + if(gid >= cols) + { + return; + } + + global float * optr = output + (rows - 1) * elements_per_row + gid + out_offset / 4; + float result = 0; + for(int i = 0; i < rows; ++i, optr -= elements_per_row) + { + result = *optr + _a * result; + *optr = _gain * result; + } +} +// +// end of _spatiotemporalLPfilter +///////////////////////////////////////////////////////////////////// + +//////////////// horizontalAnticausalFilter_Irregular //////////////// +kernel void horizontalAnticausalFilter_Irregular( + global float * output, + global float * buffer, + const int cols, + const int rows, + const int elements_per_row, + const int out_offset, + const int buffer_offset +) +{ + int gid = get_global_id(0); + if(gid >= rows) + { + return; + } + + global float * optr = + output + mad24(rows - gid, elements_per_row, -1 + out_offset / 4); + global float * bptr = + buffer + mad24(rows - gid, elements_per_row, -1 + buffer_offset / 4); + + float4 buf_v4, out_v4, res_v4 = (float4)(0); + float result = 0; + // we assume elements_per_row is multple of WIDTH_MULTIPLE + for(int i = 0; i < WIDTH_MULTIPLE; ++ i, -- optr, -- bptr) + { + if(i >= elements_per_row - cols) + { + result = *optr + *bptr * result; + } + *optr = result; + } + res_v4.x = result; + optr -= 3; + bptr -= 3; + for(int i = WIDTH_MULTIPLE / 4; i < elements_per_row / 4; ++i, optr -= 4, bptr -= 4) + { + buf_v4 = vload4(0, bptr); + out_v4 = vload4(0, optr); + + res_v4.w = out_v4.w + buf_v4.w * res_v4.x; + res_v4.z = out_v4.z + buf_v4.z * res_v4.w; + res_v4.y = out_v4.y + buf_v4.y * res_v4.z; + res_v4.x = out_v4.x + buf_v4.x * res_v4.y; + + vstore4(res_v4, 0, optr); + } +} + +//////////////// verticalCausalFilter_Irregular //////////////// +kernel void verticalCausalFilter_Irregular( + global float * output, + global float * buffer, + const int cols, + const int rows, + const int elements_per_row, + const int out_offset, + const int buffer_offset +) +{ + int gid = get_global_id(0); + if(gid >= cols) + { + return; + } + + global float * optr = output + gid + out_offset / 4; + global float * bptr = buffer + gid + buffer_offset / 4; + float result = 0; + for(int i = 0; i < rows; ++i, optr += elements_per_row, bptr += elements_per_row) + { + result = *optr + *bptr * result; + *optr = result; + } +} + +//////////////// _adaptiveHorizontalCausalFilter_addInput //////////////// +kernel void adaptiveHorizontalCausalFilter_addInput( + global const float * input, + global const float * gradient, + global float * output, + const int cols, + const int rows, + const int elements_per_row, + const int in_offset, + const int grad_offset, + const int out_offset +) +{ + int gid = get_global_id(0); + if(gid >= rows) + { + return; + } + + global const float * iptr = + input + mad24(gid, elements_per_row, in_offset / 4); + global const float * gptr = + gradient + mad24(gid, elements_per_row, grad_offset / 4); + global float * optr = + output + mad24(gid, elements_per_row, out_offset / 4); + + float4 in_v4, grad_v4, out_v4, res_v4 = (float4)(0); + for(int i = 0; i < cols / 4; ++i, iptr += 4, gptr += 4, optr += 4) + { + in_v4 = vload4(0, iptr); + grad_v4 = vload4(0, gptr); + + res_v4.x = in_v4.x + grad_v4.x * res_v4.w; + res_v4.y = in_v4.y + grad_v4.y * res_v4.x; + res_v4.z = in_v4.z + grad_v4.z * res_v4.y; + res_v4.w = in_v4.w + grad_v4.w * res_v4.z; + + vstore4(res_v4, 0, optr); + } + for(int i = 0; i < cols % 4; ++i, ++iptr, ++gptr, ++optr) + { + res_v4.w = *iptr + *gptr * res_v4.w; + *optr = res_v4.w; + } +} + +//////////////// _adaptiveVerticalAnticausalFilter_multGain //////////////// +kernel void adaptiveVerticalAnticausalFilter_multGain( + global const float * gradient, + global float * output, + const int cols, + const int rows, + const int elements_per_row, + const int grad_offset, + const int out_offset, + const float gain +) +{ + int gid = get_global_id(0); + if(gid >= cols) + { + return; + } + + int start_idx = mad24(rows - 1, elements_per_row, gid); + + global const float * gptr = gradient + start_idx + grad_offset / 4; + global float * optr = output + start_idx + out_offset / 4; + + float result = 0; + for(int i = 0; i < rows; ++i, gptr -= elements_per_row, optr -= elements_per_row) + { + result = *optr + *gptr * result; + *optr = gain * result; + } +} + +//////////////// _localLuminanceAdaptation //////////////// +// FIXME: +// This kernel seems to have precision problem on GPU +kernel void localLuminanceAdaptation( + global const float * luma, + global const float * input, + global float * output, + const int cols, + const int rows, + const int elements_per_row, + const float _localLuminanceAddon, + const float _localLuminanceFactor, + const float _maxInputValue +) +{ + int gidx = get_global_id(0), gidy = get_global_id(1); + if(gidx >= cols || gidy >= rows) + { + return; + } + int offset = mad24(gidy, elements_per_row, gidx); + + float X0 = luma[offset] * _localLuminanceFactor + _localLuminanceAddon; + float input_val = input[offset]; + // output of the following line may be different between GPU and CPU + output[offset] = (_maxInputValue + X0) * input_val / (input_val + X0 + 0.00000000001f); +} +// end of basicretinafilter +//******************************************************* +///////////////////////////////////////////////////////// + + + +///////////////////////////////////////////////////////// +//****************************************************** +// magno +// TODO: this kernel has too many buffer accesses, better to make it +// vector read/write for fetch efficiency +kernel void amacrineCellsComputing( + global const float * opl_on, + global const float * opl_off, + global float * prev_in_on, + global float * prev_in_off, + global float * out_on, + global float * out_off, + const int cols, + const int rows, + const int elements_per_row, + const float coeff +) +{ + int gidx = get_global_id(0), gidy = get_global_id(1); + if(gidx >= cols || gidy >= rows) + { + return; + } + + int offset = mad24(gidy, elements_per_row, gidx); + opl_on += offset; + opl_off += offset; + prev_in_on += offset; + prev_in_off += offset; + out_on += offset; + out_off += offset; + + float magnoXonPixelResult = coeff * (*out_on + *opl_on - *prev_in_on); + *out_on = fmax(magnoXonPixelResult, 0); + float magnoXoffPixelResult = coeff * (*out_off + *opl_off - *prev_in_off); + *out_off = fmax(magnoXoffPixelResult, 0); + + *prev_in_on = *opl_on; + *prev_in_off = *opl_off; +} + +///////////////////////////////////////////////////////// +//****************************************************** +// parvo +// TODO: this kernel has too many buffer accesses, needs optimization +kernel void OPL_OnOffWaysComputing( + global float4 * photo_out, + global float4 * horiz_out, + global float4 * bipol_on, + global float4 * bipol_off, + global float4 * parvo_on, + global float4 * parvo_off, + const int cols, + const int rows, + const int elements_per_row +) +{ + int gidx = get_global_id(0), gidy = get_global_id(1); + if(gidx * 4 >= cols || gidy >= rows) + { + return; + } + // we assume elements_per_row must be multiples of 4 + int offset = mad24(gidy, elements_per_row >> 2, gidx); + photo_out += offset; + horiz_out += offset; + bipol_on += offset; + bipol_off += offset; + parvo_on += offset; + parvo_off += offset; + + float4 diff = *photo_out - *horiz_out; + float4 isPositive;// = convert_float4(diff > (float4)(0.0f, 0.0f, 0.0f, 0.0f)); + isPositive.x = diff.x > 0.0f; + isPositive.y = diff.y > 0.0f; + isPositive.z = diff.z > 0.0f; + isPositive.w = diff.w > 0.0f; + float4 res_on = isPositive * diff; + float4 res_off = (isPositive - (float4)(1.0f)) * diff; + + *bipol_on = res_on; + *parvo_on = res_on; + + *bipol_off = res_off; + *parvo_off = res_off; +} + +///////////////////////////////////////////////////////// +//****************************************************** +// retinacolor +inline int bayerSampleOffset(int step, int rows, int x, int y) +{ + return mad24(y, step, x) + + ((y % 2) + (x % 2)) * rows * step; +} + + +/////// colorMultiplexing ////// +kernel void runColorMultiplexingBayer( + global const float * input, + global float * output, + const int cols, + const int rows, + const int elements_per_row +) +{ + int gidx = get_global_id(0), gidy = get_global_id(1); + if(gidx >= cols || gidy >= rows) + { + return; + } + + int offset = mad24(gidy, elements_per_row, gidx); + output[offset] = input[bayerSampleOffset(elements_per_row, rows, gidx, gidy)]; +} + +kernel void runColorDemultiplexingBayer( + global const float * input, + global float * output, + const int cols, + const int rows, + const int elements_per_row +) +{ + int gidx = get_global_id(0), gidy = get_global_id(1); + if(gidx >= cols || gidy >= rows) + { + return; + } + + int offset = mad24(gidy, elements_per_row, gidx); + output[bayerSampleOffset(elements_per_row, rows, gidx, gidy)] = input[offset]; +} + +kernel void demultiplexAssign( + global const float * input, + global float * output, + const int cols, + const int rows, + const int elements_per_row +) +{ + int gidx = get_global_id(0), gidy = get_global_id(1); + if(gidx >= cols || gidy >= rows) + { + return; + } + + int offset = bayerSampleOffset(elements_per_row, rows, gidx, gidy); + output[offset] = input[offset]; +} + + +//// normalizeGrayOutputCentredSigmoide +kernel void normalizeGrayOutputCentredSigmoide( + global const float * input, + global float * output, + const int cols, + const int rows, + const int elements_per_row, + const float meanval, + const float X0 +) + +{ + int gidx = get_global_id(0), gidy = get_global_id(1); + if(gidx >= cols || gidy >= rows) + { + return; + } + int offset = mad24(gidy, elements_per_row, gidx); + + float input_val = input[offset]; + output[offset] = meanval + + (meanval + X0) * (input_val - meanval) / (fabs(input_val - meanval) + X0); +} + +//// normalize by photoreceptors density +kernel void normalizePhotoDensity( + global const float * chroma, + global const float * colorDensity, + global const float * multiplex, + global float * luma, + global float * demultiplex, + const int cols, + const int rows, + const int elements_per_row, + const float pG +) +{ + const int gidx = get_global_id(0), gidy = get_global_id(1); + if(gidx >= cols || gidy >= rows) + { + return; + } + const int offset = mad24(gidy, elements_per_row, gidx); + int index = offset; + + float Cr = chroma[index] * colorDensity[index]; + index += elements_per_row * rows; + float Cg = chroma[index] * colorDensity[index]; + index += elements_per_row * rows; + float Cb = chroma[index] * colorDensity[index]; + + const float luma_res = (Cr + Cg + Cb) * pG; + luma[offset] = luma_res; + demultiplex[bayerSampleOffset(elements_per_row, rows, gidx, gidy)] = + multiplex[offset] - luma_res; +} + + + +//////// computeGradient /////// +// TODO: +// this function maybe accelerated by image2d_t or lds +kernel void computeGradient( + global const float * luma, + global float * gradient, + const int cols, + const int rows, + const int elements_per_row +) +{ + int gidx = get_global_id(0) + 2, gidy = get_global_id(1) + 2; + if(gidx >= cols - 2 || gidy >= rows - 2) + { + return; + } + int offset = mad24(gidy, elements_per_row, gidx); + luma += offset; + + // horizontal and vertical local gradients + const float v_grad = fabs(luma[elements_per_row] - luma[- elements_per_row]); + const float h_grad = fabs(luma[1] - luma[-1]); + + // neighborhood horizontal and vertical gradients + const float cur_val = luma[0]; + const float v_grad_p = fabs(cur_val - luma[- 2 * elements_per_row]); + const float h_grad_p = fabs(cur_val - luma[- 2]); + const float v_grad_n = fabs(cur_val - luma[2 * elements_per_row]); + const float h_grad_n = fabs(cur_val - luma[2]); + + const float horiz_grad = 0.5f * h_grad + 0.25f * (h_grad_p + h_grad_n); + const float verti_grad = 0.5f * v_grad + 0.25f * (v_grad_p + v_grad_n); + const bool is_vertical_greater = horiz_grad < verti_grad; + + gradient[offset + elements_per_row * rows] = is_vertical_greater ? 0.06f : 0.57f; + gradient[offset ] = is_vertical_greater ? 0.57f : 0.06f; +} + + +/////// substractResidual /////// +kernel void substractResidual( + global float * input, + const int cols, + const int rows, + const int elements_per_row, + const float pR, + const float pG, + const float pB +) +{ + const int gidx = get_global_id(0), gidy = get_global_id(1); + if(gidx >= cols || gidy >= rows) + { + return; + } + int indices [3] = + { + mad24(gidy, elements_per_row, gidx), + mad24(gidy + rows, elements_per_row, gidx), + mad24(gidy + 2 * rows, elements_per_row, gidx) + }; + float vals[3] = {input[indices[0]], input[indices[1]], input[indices[2]]}; + float residu = pR * vals[0] + pG * vals[1] + pB * vals[2]; + + input[indices[0]] = vals[0] - residu; + input[indices[1]] = vals[1] - residu; + input[indices[2]] = vals[2] - residu; +} + +///// clipRGBOutput_0_maxInputValue ///// +kernel void clipRGBOutput_0_maxInputValue( + global float * input, + const int cols, + const int rows, + const int elements_per_row, + const float maxVal +) +{ + const int gidx = get_global_id(0), gidy = get_global_id(1); + if(gidx >= cols || gidy >= rows) + { + return; + } + const int offset = mad24(gidy, elements_per_row, gidx); + float val = input[offset]; + val = clamp(val, 0.0f, maxVal); + input[offset] = val; +} + +//// normalizeGrayOutputNearZeroCentreredSigmoide //// +kernel void normalizeGrayOutputNearZeroCentreredSigmoide( + global float * input, + global float * output, + const int cols, + const int rows, + const int elements_per_row, + const float maxVal, + const float X0cube +) +{ + const int gidx = get_global_id(0), gidy = get_global_id(1); + if(gidx >= cols || gidy >= rows) + { + return; + } + const int offset = mad24(gidy, elements_per_row, gidx); + float currentCubeLuminance = input[offset]; + currentCubeLuminance = currentCubeLuminance * currentCubeLuminance * currentCubeLuminance; + output[offset] = currentCubeLuminance * X0cube / (X0cube + currentCubeLuminance); +} + +//// centerReductImageLuminance //// +kernel void centerReductImageLuminance( + global float * input, + const int cols, + const int rows, + const int elements_per_row, + const float mean, + const float std_dev +) +{ + const int gidx = get_global_id(0), gidy = get_global_id(1); + if(gidx >= cols || gidy >= rows) + { + return; + } + const int offset = mad24(gidy, elements_per_row, gidx); + + float val = input[offset]; + input[offset] = (val - mean) / std_dev; +} + +//// inverseValue //// +kernel void inverseValue( + global float * input, + const int cols, + const int rows, + const int elements_per_row +) +{ + const int gidx = get_global_id(0), gidy = get_global_id(1); + if(gidx >= cols || gidy >= rows) + { + return; + } + const int offset = mad24(gidy, elements_per_row, gidx); + input[offset] = 1.f / input[offset]; +} + +#define CV_PI 3.1415926535897932384626433832795 + +//// _processRetinaParvoMagnoMapping //// +kernel void processRetinaParvoMagnoMapping( + global float * parvo, + global float * magno, + global float * output, + const int cols, + const int rows, + const int halfCols, + const int halfRows, + const int elements_per_row, + const float minDistance +) +{ + const int gidx = get_global_id(0), gidy = get_global_id(1); + if(gidx >= cols || gidy >= rows) + { + return; + } + const int offset = mad24(gidy, elements_per_row, gidx); + + float distanceToCenter = + sqrt(((float)(gidy - halfRows) * (gidy - halfRows) + (gidx - halfCols) * (gidx - halfCols))); + + float a = distanceToCenter < minDistance ? + (0.5f + 0.5f * (float)cos(CV_PI * distanceToCenter / minDistance)) : 0; + float b = 1.f - a; + + output[offset] = parvo[offset] * a + magno[offset] * b; +} diff --git a/modules/contrib/src/parvoretinafilter.cpp b/modules/bioinspired/src/parvoretinafilter.cpp similarity index 96% rename from modules/contrib/src/parvoretinafilter.cpp rename to modules/bioinspired/src/parvoretinafilter.cpp index 6043b72328..a276d97a4c 100644 --- a/modules/contrib/src/parvoretinafilter.cpp +++ b/modules/bioinspired/src/parvoretinafilter.cpp @@ -6,7 +6,7 @@ ** copy or use the software. ** ** -** HVStools : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. +** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. ** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. ** ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) @@ -32,7 +32,7 @@ ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. ** -** For Human Visual System tools (hvstools) +** For Human Visual System tools (bioinspired) ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved. ** ** Third party copyrights are property of their respective owners. @@ -73,6 +73,8 @@ namespace cv { +namespace bioinspired +{ ////////////////////////////////////////////////////////// // OPL RETINA FILTER ////////////////////////////////////////////////////////// @@ -227,5 +229,5 @@ void ParvoRetinaFilter::_OPL_OnOffWaysComputing() // WARNING : this method requi } #endif } -} - +}// end of namespace bioinspired +}// end of namespace cv diff --git a/modules/contrib/src/parvoretinafilter.hpp b/modules/bioinspired/src/parvoretinafilter.hpp similarity index 97% rename from modules/contrib/src/parvoretinafilter.hpp rename to modules/bioinspired/src/parvoretinafilter.hpp index 40f71ebe9f..f5ffa1a06d 100644 --- a/modules/contrib/src/parvoretinafilter.hpp +++ b/modules/bioinspired/src/parvoretinafilter.hpp @@ -6,7 +6,7 @@ ** copy or use the software. ** ** -** HVStools : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. +** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. ** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. ** ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) @@ -32,7 +32,7 @@ ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. ** -** For Human Visual System tools (hvstools) +** For Human Visual System tools (bioinspired) ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved. ** ** Third party copyrights are property of their respective owners. @@ -103,6 +103,8 @@ namespace cv { +namespace bioinspired +{ //retina classes that derivate from the Basic Retrina class class ParvoRetinaFilter: public BasicRetinaFilter { @@ -256,6 +258,6 @@ private: #endif }; -} +}// end of namespace bioinspired +}// end of namespace cv #endif - diff --git a/modules/bioinspired/src/precomp.hpp b/modules/bioinspired/src/precomp.hpp new file mode 100644 index 0000000000..541b970325 --- /dev/null +++ b/modules/bioinspired/src/precomp.hpp @@ -0,0 +1,67 @@ +/*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_PRECOMP_H__ +#define __OPENCV_PRECOMP_H__ + +#include "opencv2/opencv_modules.hpp" +#include "opencv2/bioinspired.hpp" +#include "opencv2/core/utility.hpp" +#include "opencv2/core/private.hpp" + +#include + +#ifdef HAVE_OPENCV_OCL + #include "opencv2/ocl/private/util.hpp" +#endif + +namespace cv +{ + +// special function to get pointer to constant valarray elements, since +// simple &arr[0] does not compile on VS2005/VS2008. +template inline const T* get_data(const std::valarray& arr) +{ return &((std::valarray&)arr)[0]; } + +} + +#endif diff --git a/modules/bioinspired/src/retina.cpp b/modules/bioinspired/src/retina.cpp new file mode 100644 index 0000000000..4604331076 --- /dev/null +++ b/modules/bioinspired/src/retina.cpp @@ -0,0 +1,743 @@ +/*#****************************************************************************** + ** 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. + ** + ** + ** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. + ** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. + ** + ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) + ** + ** Creation - enhancement process 2007-2011 + ** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France + ** + ** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr). + ** Refer to the following research paper for more information: + ** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 + ** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book: + ** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. + ** + ** The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author : + ** _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper: + ** ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 + ** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. + ** ====> more informations in the above cited Jeanny Heraults's book. + ** + ** License Agreement + ** For Open Source Computer Vision Library + ** + ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. + ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. + ** + ** For Human Visual System tools (bioinspired) + ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: + ** + ** * Redistributions of source code must retain the above copyright notice, + ** this list of conditions and the following disclaimer. + ** + ** * Redistributions 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. + *******************************************************************************/ + +/* + * Retina.cpp + * + * Created on: Jul 19, 2011 + * Author: Alexandre Benoit + */ +#include "precomp.hpp" +#include "retinafilter.hpp" +#include +#include +#include + +namespace cv +{ +namespace bioinspired +{ + +class RetinaImpl : public Retina +{ +public: + /** + * Main constructor with most commun use setup : create an instance of color ready retina model + * @param inputSize : the input frame size + */ + RetinaImpl(Size inputSize); + + /** + * Complete Retina filter constructor which allows all basic structural parameters definition + * @param inputSize : the input frame size + * @param colorMode : the chosen processing mode : with or without color processing + * @param colorSamplingMethod: specifies which kind of color sampling will be used + * @param useRetinaLogSampling: activate retina log sampling, if true, the 2 following parameters can be used + * @param reductionFactor: only usefull if param useRetinaLogSampling=true, specifies the reduction factor of the output frame (as the center (fovea) is high resolution and corners can be underscaled, then a reduction of the output is allowed without precision leak + * @param samplingStrenght: only usefull if param useRetinaLogSampling=true, specifies the strenght of the log scale that is applied + */ + RetinaImpl(Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0); + + virtual ~RetinaImpl(); + /** + * retreive retina input buffer size + */ + Size getInputSize(); + + /** + * retreive retina output buffer size + */ + Size getOutputSize(); + + /** + * try to open an XML retina parameters file to adjust current retina instance setup + * => if the xml file does not exist, then default setup is applied + * => warning, Exceptions are thrown if read XML file is not valid + * @param retinaParameterFile : the parameters filename + * @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error + */ + void setup(String retinaParameterFile="", const bool applyDefaultSetupOnFailure=true); + + + /** + * try to open an XML retina parameters file to adjust current retina instance setup + * => if the xml file does not exist, then default setup is applied + * => warning, Exceptions are thrown if read XML file is not valid + * @param fs : the open Filestorage which contains retina parameters + * @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error + */ + void setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure=true); + + /** + * try to open an XML retina parameters file to adjust current retina instance setup + * => if the xml file does not exist, then default setup is applied + * => warning, Exceptions are thrown if read XML file is not valid + * @param newParameters : a parameters structures updated with the new target configuration + * @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error + */ + void setup(Retina::RetinaParameters newParameters); + + /** + * @return the current parameters setup + */ + struct Retina::RetinaParameters getParameters(); + + /** + * parameters setup display method + * @return a string which contains formatted parameters information + */ + const String printSetup(); + + /** + * write xml/yml formated parameters information + * @rparam fs : the filename of the xml file that will be open and writen with formatted parameters information + */ + virtual void write( String fs ) const; + + + /** + * write xml/yml formated parameters information + * @param fs : a cv::Filestorage object ready to be filled + */ + virtual void write( FileStorage& fs ) const; + + /** + * setup the OPL and IPL parvo channels (see biologocal model) + * OPL is referred as Outer Plexiform Layer of the retina, it allows the spatio-temporal filtering which withens the spectrum and reduces spatio-temporal noise while attenuating global luminance (low frequency energy) + * IPL parvo is the OPL next processing stage, it refers to Inner Plexiform layer of the retina, it allows high contours sensitivity in foveal vision. + * for more informations, please have a look at the paper Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 + * @param colorMode : specifies if (true) color is processed of not (false) to then processing gray level image + * @param normaliseOutput : specifies if (true) output is rescaled between 0 and 255 of not (false) + * @param photoreceptorsLocalAdaptationSensitivity: the photoreceptors sensitivity renage is 0-1 (more log compression effect when value increases) + * @param photoreceptorsTemporalConstant: the time constant of the first order low pass filter of the photoreceptors, use it to cut high temporal frequencies (noise or fast motion), unit is frames, typical value is 1 frame + * @param photoreceptorsSpatialConstant: the spatial constant of the first order low pass filter of the photoreceptors, use it to cut high spatial frequencies (noise or thick contours), unit is pixels, typical value is 1 pixel + * @param horizontalCellsGain: gain of the horizontal cells network, if 0, then the mean value of the output is zero, if the parameter is near 1, then, the luminance is not filtered and is still reachable at the output, typicall value is 0 + * @param HcellsTemporalConstant: the time constant of the first order low pass filter of the horizontal cells, use it to cut low temporal frequencies (local luminance variations), unit is frames, typical value is 1 frame, as the photoreceptors + * @param HcellsSpatialConstant: the spatial constant of the first order low pass filter of the horizontal cells, use it to cut low spatial frequencies (local luminance), unit is pixels, typical value is 5 pixel, this value is also used for local contrast computing when computing the local contrast adaptation at the ganglion cells level (Inner Plexiform Layer parvocellular channel model) + * @param ganglionCellsSensitivity: the compression strengh of the ganglion cells local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 230 + */ + void setupOPLandIPLParvoChannel(const bool colorMode=true, const bool normaliseOutput = true, const float photoreceptorsLocalAdaptationSensitivity=0.7, const float photoreceptorsTemporalConstant=0.5, const float photoreceptorsSpatialConstant=0.53, const float horizontalCellsGain=0, const float HcellsTemporalConstant=1, const float HcellsSpatialConstant=7, const float ganglionCellsSensitivity=0.7); + + /** + * set parameters values for the Inner Plexiform Layer (IPL) magnocellular channel + * this channel processes signals outpint from OPL processing stage in peripheral vision, it allows motion information enhancement. It is decorrelated from the details channel. See reference paper for more details. + * @param normaliseOutput : specifies if (true) output is rescaled between 0 and 255 of not (false) + * @param parasolCells_beta: the low pass filter gain used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), typical value is 0 + * @param parasolCells_tau: the low pass filter time constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is frame, typical value is 0 (immediate response) + * @param parasolCells_k: the low pass filter spatial constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is pixels, typical value is 5 + * @param amacrinCellsTemporalCutFrequency: the time constant of the first order high pass fiter of the magnocellular way (motion information channel), unit is frames, tipicall value is 5 + * @param V0CompressionParameter: the compression strengh of the ganglion cells local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 200 + * @param localAdaptintegration_tau: specifies the temporal constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation + * @param localAdaptintegration_k: specifies the spatial constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation + */ + void setupIPLMagnoChannel(const bool normaliseOutput = true, const float parasolCells_beta=0, const float parasolCells_tau=0, const float parasolCells_k=7, const float amacrinCellsTemporalCutFrequency=1.2, const float V0CompressionParameter=0.95, const float localAdaptintegration_tau=0, const float localAdaptintegration_k=7); + + /** + * method which allows retina to be applied on an input image, after run, encapsulated retina module is ready to deliver its outputs using dedicated acccessors, see getParvo and getMagno methods + * @param inputImage : the input cv::Mat image to be processed, can be gray level or BGR coded in any format (from 8bit to 16bits) + */ + void run(InputArray inputImage); + + /** + * method that applies a luminance correction (initially High Dynamic Range (HDR) tone mapping) using only the 2 local adaptation stages of the retina parvo channel : photoreceptors level and ganlion cells level. Spatio temporal filtering is applied but limited to temporal smoothing and eventually high frequencies attenuation. This is a lighter method than the one available using the regular run method. It is then faster but it does not include complete temporal filtering nor retina spectral whitening. This is an adptation of the original still image HDR tone mapping algorithm of David Alleyson, Sabine Susstruck and Laurence Meylan's work, please cite: + * -> Meylan L., Alleysson D., and Susstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816 + @param inputImage the input image to process RGB or gray levels + @param outputToneMappedImage the output tone mapped image + */ + void applyFastToneMapping(InputArray inputImage, OutputArray outputToneMappedImage); + + /** + * accessor of the details channel of the retina (models foveal vision) + * @param retinaOutput_parvo : the output buffer (reallocated if necessary), this output is rescaled for standard 8bits image processing use in OpenCV + */ + void getParvo(OutputArray retinaOutput_parvo); + + /** + * accessor of the details channel of the retina (models foveal vision) + * @param retinaOutput_parvo : a cv::Mat header filled with the internal parvo buffer of the retina module. This output is the original retina filter model output, without any quantification or rescaling + */ + void getParvoRAW(OutputArray retinaOutput_parvo); + + /** + * accessor of the motion channel of the retina (models peripheral vision) + * @param retinaOutput_magno : the output buffer (reallocated if necessary), this output is rescaled for standard 8bits image processing use in OpenCV + */ + void getMagno(OutputArray retinaOutput_magno); + + /** + * accessor of the motion channel of the retina (models peripheral vision) + * @param retinaOutput_magno : a cv::Mat header filled with the internal retina magno buffer of the retina module. This output is the original retina filter model output, without any quantification or rescaling + */ + void getMagnoRAW(OutputArray retinaOutput_magno); + + // original API level data accessors : get buffers addresses from a Mat header, similar to getParvoRAW and getMagnoRAW... + const Mat getMagnoRAW() const; + const Mat getParvoRAW() const; + + /** + * activate color saturation as the final step of the color demultiplexing process + * -> this saturation is a sigmoide function applied to each channel of the demultiplexed image. + * @param saturateColors: boolean that activates color saturation (if true) or desactivate (if false) + * @param colorSaturationValue: the saturation factor + */ + void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0); + + /** + * clear all retina buffers (equivalent to opening the eyes after a long period of eye close ;o) + */ + void clearBuffers(); + + /** + * Activate/desactivate the Magnocellular pathway processing (motion information extraction), by default, it is activated + * @param activate: true if Magnocellular output should be activated, false if not + */ + void activateMovingContoursProcessing(const bool activate); + + /** + * Activate/desactivate the Parvocellular pathway processing (contours information extraction), by default, it is activated + * @param activate: true if Parvocellular (contours information extraction) output should be activated, false if not + */ + void activateContoursProcessing(const bool activate); +private: + + // Parameteres setup members + RetinaParameters _retinaParameters; // structure of parameters + + // Retina model related modules + std::valarray _inputBuffer; //!< buffer used to convert input cv::Mat to internal retina buffers format (valarrays) + + // pointer to retina model + RetinaFilter* _retinaFilter; //!< the pointer to the retina module, allocated with instance construction + + //! private method called by constructors, gathers their parameters and use them in a unified way + void _init(const Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0); + + /** + * exports a valarray buffer outing from bioinspired objects to a cv::Mat in CV_8UC1 (gray level picture) or CV_8UC3 (color) format + * @param grayMatrixToConvert the valarray to export to OpenCV + * @param nbRows : the number of rows of the valarray flatten matrix + * @param nbColumns : the number of rows of the valarray flatten matrix + * @param colorMode : a flag which mentions if matrix is color (true) or graylevel (false) + * @param outBuffer : the output matrix which is reallocated to satisfy Retina output buffer dimensions + */ + void _convertValarrayBuffer2cvMat(const std::valarray &grayMatrixToConvert, const unsigned int nbRows, const unsigned int nbColumns, const bool colorMode, OutputArray outBuffer); + + /** + * convert a cv::Mat to a valarray buffer in float format + * @param inputMatToConvert : the OpenCV cv::Mat that has to be converted to gray or RGB valarray buffer that will be processed by the retina model + * @param outputValarrayMatrix : the output valarray + * @return the input image color mode (color=true, gray levels=false) + */ + bool _convertCvMat2ValarrayBuffer(InputArray inputMatToConvert, std::valarray &outputValarrayMatrix); + + +}; + +// smart pointers allocation : +Ptr createRetina(Size inputSize){ return makePtr(inputSize); } +Ptr createRetina(Size inputSize, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght){ + return makePtr(inputSize, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght); +} + + +// RetinaImpl code +RetinaImpl::RetinaImpl(const cv::Size inputSz) +{ + _retinaFilter = 0; + _init(inputSz, true, RETINA_COLOR_BAYER, false); +} + +RetinaImpl::RetinaImpl(const cv::Size inputSz, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght) +{ + _retinaFilter = 0; + _init(inputSz, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght); +}; + +RetinaImpl::~RetinaImpl() +{ + if (_retinaFilter) + delete _retinaFilter; +} + +/** +* retreive retina input buffer size +*/ +Size RetinaImpl::getInputSize(){return cv::Size(_retinaFilter->getInputNBcolumns(), _retinaFilter->getInputNBrows());} + +/** +* retreive retina output buffer size +*/ +Size RetinaImpl::getOutputSize(){return cv::Size(_retinaFilter->getOutputNBcolumns(), _retinaFilter->getOutputNBrows());} + + +void RetinaImpl::setColorSaturation(const bool saturateColors, const float colorSaturationValue) +{ + _retinaFilter->setColorSaturation(saturateColors, colorSaturationValue); +} + +struct Retina::RetinaParameters RetinaImpl::getParameters(){return _retinaParameters;} + +void RetinaImpl::setup(String retinaParameterFile, const bool applyDefaultSetupOnFailure) +{ + try + { + // opening retinaParameterFile in read mode + cv::FileStorage fs(retinaParameterFile, cv::FileStorage::READ); + setup(fs, applyDefaultSetupOnFailure); + } + catch(Exception &e) + { + printf("Retina::setup: wrong/unappropriate xml parameter file : error report :`n=>%s\n", e.what()); + if (applyDefaultSetupOnFailure) + { + printf("Retina::setup: resetting retina with default parameters\n"); + setupOPLandIPLParvoChannel(); + setupIPLMagnoChannel(); + } + else + { + printf("=> keeping current parameters\n"); + } + } +} + +void RetinaImpl::setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure) +{ + try + { + // read parameters file if it exists or apply default setup if asked for + if (!fs.isOpened()) + { + printf("Retina::setup: provided parameters file could not be open... skeeping configuration\n"); + return; + // implicit else case : retinaParameterFile could be open (it exists at least) + } + // OPL and Parvo init first... update at the same time the parameters structure and the retina core + cv::FileNode rootFn = fs.root(), currFn=rootFn["OPLandIPLparvo"]; + currFn["colorMode"]>>_retinaParameters.OPLandIplParvo.colorMode; + currFn["normaliseOutput"]>>_retinaParameters.OPLandIplParvo.normaliseOutput; + currFn["photoreceptorsLocalAdaptationSensitivity"]>>_retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity; + currFn["photoreceptorsTemporalConstant"]>>_retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant; + currFn["photoreceptorsSpatialConstant"]>>_retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant; + currFn["horizontalCellsGain"]>>_retinaParameters.OPLandIplParvo.horizontalCellsGain; + currFn["hcellsTemporalConstant"]>>_retinaParameters.OPLandIplParvo.hcellsTemporalConstant; + currFn["hcellsSpatialConstant"]>>_retinaParameters.OPLandIplParvo.hcellsSpatialConstant; + currFn["ganglionCellsSensitivity"]>>_retinaParameters.OPLandIplParvo.ganglionCellsSensitivity; + setupOPLandIPLParvoChannel(_retinaParameters.OPLandIplParvo.colorMode, _retinaParameters.OPLandIplParvo.normaliseOutput, _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity, _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant, _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant, _retinaParameters.OPLandIplParvo.horizontalCellsGain, _retinaParameters.OPLandIplParvo.hcellsTemporalConstant, _retinaParameters.OPLandIplParvo.hcellsSpatialConstant, _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity); + + // init retina IPL magno setup... update at the same time the parameters structure and the retina core + currFn=rootFn["IPLmagno"]; + currFn["normaliseOutput"]>>_retinaParameters.IplMagno.normaliseOutput; + currFn["parasolCells_beta"]>>_retinaParameters.IplMagno.parasolCells_beta; + currFn["parasolCells_tau"]>>_retinaParameters.IplMagno.parasolCells_tau; + currFn["parasolCells_k"]>>_retinaParameters.IplMagno.parasolCells_k; + currFn["amacrinCellsTemporalCutFrequency"]>>_retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency; + currFn["V0CompressionParameter"]>>_retinaParameters.IplMagno.V0CompressionParameter; + currFn["localAdaptintegration_tau"]>>_retinaParameters.IplMagno.localAdaptintegration_tau; + currFn["localAdaptintegration_k"]>>_retinaParameters.IplMagno.localAdaptintegration_k; + + setupIPLMagnoChannel(_retinaParameters.IplMagno.normaliseOutput, _retinaParameters.IplMagno.parasolCells_beta, _retinaParameters.IplMagno.parasolCells_tau, _retinaParameters.IplMagno.parasolCells_k, _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency,_retinaParameters.IplMagno.V0CompressionParameter, _retinaParameters.IplMagno.localAdaptintegration_tau, _retinaParameters.IplMagno.localAdaptintegration_k); + + }catch(Exception &e) + { + printf("RetinaImpl::setup: resetting retina with default parameters\n"); + if (applyDefaultSetupOnFailure) + { + setupOPLandIPLParvoChannel(); + setupIPLMagnoChannel(); + } + printf("Retina::setup: wrong/unappropriate xml parameter file : error report :`n=>%s\n", e.what()); + printf("=> keeping current parameters\n"); + } + + // report current configuration + printf("%s\n", printSetup().c_str()); +} + +void RetinaImpl::setup(Retina::RetinaParameters newConfiguration) +{ + // simply copy structures + memcpy(&_retinaParameters, &newConfiguration, sizeof(Retina::RetinaParameters)); + // apply setup + setupOPLandIPLParvoChannel(_retinaParameters.OPLandIplParvo.colorMode, _retinaParameters.OPLandIplParvo.normaliseOutput, _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity, _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant, _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant, _retinaParameters.OPLandIplParvo.horizontalCellsGain, _retinaParameters.OPLandIplParvo.hcellsTemporalConstant, _retinaParameters.OPLandIplParvo.hcellsSpatialConstant, _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity); + setupIPLMagnoChannel(_retinaParameters.IplMagno.normaliseOutput, _retinaParameters.IplMagno.parasolCells_beta, _retinaParameters.IplMagno.parasolCells_tau, _retinaParameters.IplMagno.parasolCells_k, _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency,_retinaParameters.IplMagno.V0CompressionParameter, _retinaParameters.IplMagno.localAdaptintegration_tau, _retinaParameters.IplMagno.localAdaptintegration_k); + +} + +const String RetinaImpl::printSetup() +{ + std::stringstream outmessage; + + // displaying OPL and IPL parvo setup + outmessage<<"Current Retina instance setup :" + <<"\nOPLandIPLparvo"<<"{" + << "\n\t colorMode : " << _retinaParameters.OPLandIplParvo.colorMode + << "\n\t normalizeParvoOutput :" << _retinaParameters.OPLandIplParvo.normaliseOutput + << "\n\t photoreceptorsLocalAdaptationSensitivity : " << _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity + << "\n\t photoreceptorsTemporalConstant : " << _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant + << "\n\t photoreceptorsSpatialConstant : " << _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant + << "\n\t horizontalCellsGain : " << _retinaParameters.OPLandIplParvo.horizontalCellsGain + << "\n\t hcellsTemporalConstant : " << _retinaParameters.OPLandIplParvo.hcellsTemporalConstant + << "\n\t hcellsSpatialConstant : " << _retinaParameters.OPLandIplParvo.hcellsSpatialConstant + << "\n\t parvoGanglionCellsSensitivity : " << _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity + <<"}\n"; + + // displaying IPL magno setup + outmessage<<"Current Retina instance setup :" + <<"\nIPLmagno"<<"{" + << "\n\t normaliseOutput : " << _retinaParameters.IplMagno.normaliseOutput + << "\n\t parasolCells_beta : " << _retinaParameters.IplMagno.parasolCells_beta + << "\n\t parasolCells_tau : " << _retinaParameters.IplMagno.parasolCells_tau + << "\n\t parasolCells_k : " << _retinaParameters.IplMagno.parasolCells_k + << "\n\t amacrinCellsTemporalCutFrequency : " << _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency + << "\n\t V0CompressionParameter : " << _retinaParameters.IplMagno.V0CompressionParameter + << "\n\t localAdaptintegration_tau : " << _retinaParameters.IplMagno.localAdaptintegration_tau + << "\n\t localAdaptintegration_k : " << _retinaParameters.IplMagno.localAdaptintegration_k + <<"}"; + return outmessage.str().c_str(); +} + +void RetinaImpl::write( String fs ) const +{ + FileStorage parametersSaveFile(fs, cv::FileStorage::WRITE ); + write(parametersSaveFile); +} + +void RetinaImpl::write( FileStorage& fs ) const +{ + if (!fs.isOpened()) + return; // basic error case + fs<<"OPLandIPLparvo"<<"{"; + fs << "colorMode" << _retinaParameters.OPLandIplParvo.colorMode; + fs << "normaliseOutput" << _retinaParameters.OPLandIplParvo.normaliseOutput; + fs << "photoreceptorsLocalAdaptationSensitivity" << _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity; + fs << "photoreceptorsTemporalConstant" << _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant; + fs << "photoreceptorsSpatialConstant" << _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant; + fs << "horizontalCellsGain" << _retinaParameters.OPLandIplParvo.horizontalCellsGain; + fs << "hcellsTemporalConstant" << _retinaParameters.OPLandIplParvo.hcellsTemporalConstant; + fs << "hcellsSpatialConstant" << _retinaParameters.OPLandIplParvo.hcellsSpatialConstant; + fs << "ganglionCellsSensitivity" << _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity; + fs << "}"; + fs<<"IPLmagno"<<"{"; + fs << "normaliseOutput" << _retinaParameters.IplMagno.normaliseOutput; + fs << "parasolCells_beta" << _retinaParameters.IplMagno.parasolCells_beta; + fs << "parasolCells_tau" << _retinaParameters.IplMagno.parasolCells_tau; + fs << "parasolCells_k" << _retinaParameters.IplMagno.parasolCells_k; + fs << "amacrinCellsTemporalCutFrequency" << _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency; + fs << "V0CompressionParameter" << _retinaParameters.IplMagno.V0CompressionParameter; + fs << "localAdaptintegration_tau" << _retinaParameters.IplMagno.localAdaptintegration_tau; + fs << "localAdaptintegration_k" << _retinaParameters.IplMagno.localAdaptintegration_k; + fs<<"}"; +} + +void RetinaImpl::setupOPLandIPLParvoChannel(const bool colorMode, const bool normaliseOutput, const float photoreceptorsLocalAdaptationSensitivity, const float photoreceptorsTemporalConstant, const float photoreceptorsSpatialConstant, const float horizontalCellsGain, const float HcellsTemporalConstant, const float HcellsSpatialConstant, const float ganglionCellsSensitivity) +{ + // retina core parameters setup + _retinaFilter->setColorMode(colorMode); + _retinaFilter->setPhotoreceptorsLocalAdaptationSensitivity(photoreceptorsLocalAdaptationSensitivity); + _retinaFilter->setOPLandParvoParameters(0, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, HcellsTemporalConstant, HcellsSpatialConstant, ganglionCellsSensitivity); + _retinaFilter->setParvoGanglionCellsLocalAdaptationSensitivity(ganglionCellsSensitivity); + _retinaFilter->activateNormalizeParvoOutput_0_maxOutputValue(normaliseOutput); + + // update parameters struture + + _retinaParameters.OPLandIplParvo.colorMode = colorMode; + _retinaParameters.OPLandIplParvo.normaliseOutput = normaliseOutput; + _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity = photoreceptorsLocalAdaptationSensitivity; + _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant = photoreceptorsTemporalConstant; + _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant = photoreceptorsSpatialConstant; + _retinaParameters.OPLandIplParvo.horizontalCellsGain = horizontalCellsGain; + _retinaParameters.OPLandIplParvo.hcellsTemporalConstant = HcellsTemporalConstant; + _retinaParameters.OPLandIplParvo.hcellsSpatialConstant = HcellsSpatialConstant; + _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity = ganglionCellsSensitivity; + +} + +void RetinaImpl::setupIPLMagnoChannel(const bool normaliseOutput, const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float V0CompressionParameter, const float localAdaptintegration_tau, const float localAdaptintegration_k) +{ + + _retinaFilter->setMagnoCoefficientsTable(parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter, localAdaptintegration_tau, localAdaptintegration_k); + _retinaFilter->activateNormalizeMagnoOutput_0_maxOutputValue(normaliseOutput); + + // update parameters struture + _retinaParameters.IplMagno.normaliseOutput = normaliseOutput; + _retinaParameters.IplMagno.parasolCells_beta = parasolCells_beta; + _retinaParameters.IplMagno.parasolCells_tau = parasolCells_tau; + _retinaParameters.IplMagno.parasolCells_k = parasolCells_k; + _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency = amacrinCellsTemporalCutFrequency; + _retinaParameters.IplMagno.V0CompressionParameter = V0CompressionParameter; + _retinaParameters.IplMagno.localAdaptintegration_tau = localAdaptintegration_tau; + _retinaParameters.IplMagno.localAdaptintegration_k = localAdaptintegration_k; +} + +void RetinaImpl::run(InputArray inputMatToConvert) +{ + // first convert input image to the compatible format : std::valarray + const bool colorMode = _convertCvMat2ValarrayBuffer(inputMatToConvert.getMat(), _inputBuffer); + // process the retina + if (!_retinaFilter->runFilter(_inputBuffer, colorMode, false, _retinaParameters.OPLandIplParvo.colorMode && colorMode, false)) + throw cv::Exception(-1, "RetinaImpl cannot be applied, wrong input buffer size", "RetinaImpl::run", "RetinaImpl.h", 0); +} + +void RetinaImpl::applyFastToneMapping(InputArray inputImage, OutputArray outputToneMappedImage) +{ + // first convert input image to the compatible format : + const bool colorMode = _convertCvMat2ValarrayBuffer(inputImage.getMat(), _inputBuffer); + const unsigned int nbPixels=_retinaFilter->getOutputNBrows()*_retinaFilter->getOutputNBcolumns(); + + // process tone mapping + if (colorMode) + { + std::valarray imageOutput(nbPixels*3); + _retinaFilter->runRGBToneMapping(_inputBuffer, imageOutput, true, _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity, _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity); + _convertValarrayBuffer2cvMat(imageOutput, _retinaFilter->getOutputNBrows(), _retinaFilter->getOutputNBcolumns(), true, outputToneMappedImage); + }else + { + std::valarray imageOutput(nbPixels); + _retinaFilter->runGrayToneMapping(_inputBuffer, imageOutput, _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity, _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity); + _convertValarrayBuffer2cvMat(imageOutput, _retinaFilter->getOutputNBrows(), _retinaFilter->getOutputNBcolumns(), false, outputToneMappedImage); + } + +} + +void RetinaImpl::getParvo(OutputArray retinaOutput_parvo) +{ + if (_retinaFilter->getColorMode()) + { + // reallocate output buffer (if necessary) + _convertValarrayBuffer2cvMat(_retinaFilter->getColorOutput(), _retinaFilter->getOutputNBrows(), _retinaFilter->getOutputNBcolumns(), true, retinaOutput_parvo); + }else + { + // reallocate output buffer (if necessary) + _convertValarrayBuffer2cvMat(_retinaFilter->getContours(), _retinaFilter->getOutputNBrows(), _retinaFilter->getOutputNBcolumns(), false, retinaOutput_parvo); + } + //retinaOutput_parvo/=255.0; +} +void RetinaImpl::getMagno(OutputArray retinaOutput_magno) +{ + // reallocate output buffer (if necessary) + _convertValarrayBuffer2cvMat(_retinaFilter->getMovingContours(), _retinaFilter->getOutputNBrows(), _retinaFilter->getOutputNBcolumns(), false, retinaOutput_magno); + //retinaOutput_magno/=255.0; +} + +// original API level data accessors : copy buffers if size matches, reallocate if required +void RetinaImpl::getMagnoRAW(OutputArray magnoOutputBufferCopy){ + // get magno channel header + const cv::Mat magnoChannel=cv::Mat(getMagnoRAW()); + // copy data + magnoChannel.copyTo(magnoOutputBufferCopy); +} + +void RetinaImpl::getParvoRAW(OutputArray parvoOutputBufferCopy){ + // get parvo channel header + const cv::Mat parvoChannel=cv::Mat(getMagnoRAW()); + // copy data + parvoChannel.copyTo(parvoOutputBufferCopy); +} + +// original API level data accessors : get buffers addresses... +const Mat RetinaImpl::getMagnoRAW() const { + // create a cv::Mat header for the valarray + return Mat(_retinaFilter->getMovingContours().size(),1, CV_32F, (void*)get_data(_retinaFilter->getMovingContours())); + +} + +const Mat RetinaImpl::getParvoRAW() const { + if (_retinaFilter->getColorMode()) // check if color mode is enabled + { + // create a cv::Mat table (for RGB planes as a single vector) + return Mat(_retinaFilter->getColorOutput().size(), 1, CV_32F, (void*)get_data(_retinaFilter->getColorOutput())); + } + // otherwise, output is gray level + // create a cv::Mat header for the valarray + return Mat( _retinaFilter->getContours().size(), 1, CV_32F, (void*)get_data(_retinaFilter->getContours())); +} + +// private method called by constructirs +void RetinaImpl::_init(const cv::Size inputSz, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght) +{ + // basic error check + if (inputSz.height*inputSz.width <= 0) + throw cv::Exception(-1, "Bad retina size setup : size height and with must be superior to zero", "RetinaImpl::setup", "Retina.cpp", 0); + + unsigned int nbPixels=inputSz.height*inputSz.width; + // resize buffers if size does not match + _inputBuffer.resize(nbPixels*3); // buffer supports gray images but also 3 channels color buffers... (larger is better...) + + // allocate the retina model + if (_retinaFilter) + delete _retinaFilter; + _retinaFilter = new RetinaFilter(inputSz.height, inputSz.width, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght); + + _retinaParameters.OPLandIplParvo.colorMode = colorMode; + // prepare the default parameter XML file with default setup + setup(_retinaParameters); + + // init retina + _retinaFilter->clearAllBuffers(); + + // report current configuration + printf("%s\n", printSetup().c_str()); +} + +void RetinaImpl::_convertValarrayBuffer2cvMat(const std::valarray &grayMatrixToConvert, const unsigned int nbRows, const unsigned int nbColumns, const bool colorMode, OutputArray outBuffer) +{ + // fill output buffer with the valarray buffer + const float *valarrayPTR=get_data(grayMatrixToConvert); + if (!colorMode) + { + outBuffer.create(cv::Size(nbColumns, nbRows), CV_8U); + Mat outMat = outBuffer.getMat(); + for (unsigned int i=0;i(pixel)=(unsigned char)*(valarrayPTR++); + } + } + }else + { + const unsigned int nbPixels=nbColumns*nbRows; + const unsigned int doubleNBpixels=nbColumns*nbRows*2; + outBuffer.create(cv::Size(nbColumns, nbRows), CV_8UC3); + Mat outMat = outBuffer.getMat(); + for (unsigned int i=0;i(pixel)=pixelValues; + } + } + } +} + +bool RetinaImpl::_convertCvMat2ValarrayBuffer(InputArray inputMat, std::valarray &outputValarrayMatrix) +{ + const Mat inputMatToConvert=inputMat.getMat(); + // first check input consistency + if (inputMatToConvert.empty()) + throw cv::Exception(-1, "RetinaImpl cannot be applied, input buffer is empty", "RetinaImpl::run", "RetinaImpl.h", 0); + + // retreive color mode from image input + int imageNumberOfChannels = inputMatToConvert.channels(); + + // convert to float AND fill the valarray buffer + typedef float T; // define here the target pixel format, here, float + const int dsttype = DataType::depth; // output buffer is float format + + const unsigned int nbPixels=inputMat.getMat().rows*inputMat.getMat().cols; + const unsigned int doubleNBpixels=inputMat.getMat().rows*inputMat.getMat().cols*2; + + if(imageNumberOfChannels==4) + { + // create a cv::Mat table (for RGBA planes) + cv::Mat planes[4] = + { + cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[doubleNBpixels]), + cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[nbPixels]), + cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[0]) + }; + planes[3] = cv::Mat(inputMatToConvert.size(), dsttype); // last channel (alpha) does not point on the valarray (not usefull in our case) + // split color cv::Mat in 4 planes... it fills valarray directely + cv::split(Mat_ >(inputMatToConvert), planes); + } + else if (imageNumberOfChannels==3) + { + // create a cv::Mat table (for RGB planes) + cv::Mat planes[] = + { + cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[doubleNBpixels]), + cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[nbPixels]), + cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[0]) + }; + // split color cv::Mat in 3 planes... it fills valarray directely + cv::split(cv::Mat_ >(inputMatToConvert), planes); + } + else if(imageNumberOfChannels==1) + { + // create a cv::Mat header for the valarray + cv::Mat dst(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[0]); + inputMatToConvert.convertTo(dst, dsttype); + } + else + CV_Error(Error::StsUnsupportedFormat, "input image must be single channel (gray levels), bgr format (color) or bgra (color with transparency which won't be considered"); + + return imageNumberOfChannels>1; // return bool : false for gray level image processing, true for color mode +} + +void RetinaImpl::clearBuffers() {_retinaFilter->clearAllBuffers();} + +void RetinaImpl::activateMovingContoursProcessing(const bool activate){_retinaFilter->activateMovingContoursProcessing(activate);} + +void RetinaImpl::activateContoursProcessing(const bool activate){_retinaFilter->activateContoursProcessing(activate);} + +}// end of namespace bioinspired +}// end of namespace cv diff --git a/modules/bioinspired/src/retina_ocl.cpp b/modules/bioinspired/src/retina_ocl.cpp new file mode 100644 index 0000000000..c294ebfebe --- /dev/null +++ b/modules/bioinspired/src/retina_ocl.cpp @@ -0,0 +1,1648 @@ +/*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) 2010-2013, Multicoreware, Inc., all rights reserved. +// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// @Authors +// Peng Xiao, pengxiao@multicorewareinc.com +// +// 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 oclMaterials 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 "precomp.hpp" +#include "retina_ocl.hpp" +#include +#include + +#ifdef HAVE_OPENCV_OCL + +#define NOT_IMPLEMENTED CV_Error(cv::Error::StsNotImplemented, "Not implemented") + +namespace cv +{ +namespace ocl +{ +//OpenCL kernel file string pointer +extern const char * retina_kernel; +} +} + +namespace cv +{ +namespace bioinspired +{ +namespace ocl +{ +using namespace cv::ocl; + +class RetinaOCLImpl : public Retina +{ +public: + RetinaOCLImpl(Size getInputSize); + RetinaOCLImpl(Size getInputSize, const bool colorMode, int colorSamplingMethod = RETINA_COLOR_BAYER, const bool useRetinaLogSampling = false, const double reductionFactor = 1.0, const double samplingStrenght = 10.0); + virtual ~RetinaOCLImpl(); + + Size getInputSize(); + Size getOutputSize(); + + void setup(String retinaParameterFile = "", const bool applyDefaultSetupOnFailure = true); + void setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure = true); + void setup(RetinaParameters newParameters); + + RetinaOCLImpl::RetinaParameters getParameters(); + + const String printSetup(); + virtual void write( String fs ) const; + virtual void write( FileStorage& fs ) const; + + void setupOPLandIPLParvoChannel(const bool colorMode = true, const bool normaliseOutput = true, const float photoreceptorsLocalAdaptationSensitivity = 0.7, const float photoreceptorsTemporalConstant = 0.5, const float photoreceptorsSpatialConstant = 0.53, const float horizontalCellsGain = 0, const float HcellsTemporalConstant = 1, const float HcellsSpatialConstant = 7, const float ganglionCellsSensitivity = 0.7); + void setupIPLMagnoChannel(const bool normaliseOutput = true, const float parasolCells_beta = 0, const float parasolCells_tau = 0, const float parasolCells_k = 7, const float amacrinCellsTemporalCutFrequency = 1.2, const float V0CompressionParameter = 0.95, const float localAdaptintegration_tau = 0, const float localAdaptintegration_k = 7); + + void run(InputArray inputImage); + void getParvo(OutputArray retinaOutput_parvo); + void getMagno(OutputArray retinaOutput_magno); + + void setColorSaturation(const bool saturateColors = true, const float colorSaturationValue = 4.0); + void clearBuffers(); + void activateMovingContoursProcessing(const bool activate); + void activateContoursProcessing(const bool activate); + + // unimplemented interfaces: + void applyFastToneMapping(InputArray /*inputImage*/, OutputArray /*outputToneMappedImage*/) { NOT_IMPLEMENTED; } + void getParvoRAW(OutputArray /*retinaOutput_parvo*/) { NOT_IMPLEMENTED; } + void getMagnoRAW(OutputArray /*retinaOutput_magno*/) { NOT_IMPLEMENTED; } + const Mat getMagnoRAW() const { NOT_IMPLEMENTED; return Mat(); } + const Mat getParvoRAW() const { NOT_IMPLEMENTED; return Mat(); } + +protected: + RetinaParameters _retinaParameters; + cv::ocl::oclMat _inputBuffer; + RetinaFilter* _retinaFilter; + bool convertToColorPlanes(const cv::ocl::oclMat& input, cv::ocl::oclMat &output); + void convertToInterleaved(const cv::ocl::oclMat& input, bool colorMode, cv::ocl::oclMat &output); + void _init(const Size getInputSize, const bool colorMode, int colorSamplingMethod = RETINA_COLOR_BAYER, const bool useRetinaLogSampling = false, const double reductionFactor = 1.0, const double samplingStrenght = 10.0); +}; + +RetinaOCLImpl::RetinaOCLImpl(const cv::Size inputSz) +{ + _retinaFilter = 0; + _init(inputSz, true, RETINA_COLOR_BAYER, false); +} + +RetinaOCLImpl::RetinaOCLImpl(const cv::Size inputSz, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght) +{ + _retinaFilter = 0; + _init(inputSz, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght); +}; + +RetinaOCLImpl::~RetinaOCLImpl() +{ + if (_retinaFilter) + { + delete _retinaFilter; + } +} + +/** +* retreive retina input buffer size +*/ +Size RetinaOCLImpl::getInputSize() +{ + return cv::Size(_retinaFilter->getInputNBcolumns(), _retinaFilter->getInputNBrows()); +} + +/** +* retreive retina output buffer size +*/ +Size RetinaOCLImpl::getOutputSize() +{ + return cv::Size(_retinaFilter->getOutputNBcolumns(), _retinaFilter->getOutputNBrows()); +} + + +void RetinaOCLImpl::setColorSaturation(const bool saturateColors, const float colorSaturationValue) +{ + _retinaFilter->setColorSaturation(saturateColors, colorSaturationValue); +} + +struct RetinaOCLImpl::RetinaParameters RetinaOCLImpl::getParameters() +{ + return _retinaParameters; +} + + +void RetinaOCLImpl::setup(String retinaParameterFile, const bool applyDefaultSetupOnFailure) +{ + try + { + // opening retinaParameterFile in read mode + cv::FileStorage fs(retinaParameterFile, cv::FileStorage::READ); + setup(fs, applyDefaultSetupOnFailure); + } + catch(Exception &e) + { + std::cout << "RetinaOCLImpl::setup: wrong/unappropriate xml parameter file : error report :`n=>" << e.what() << std::endl; + if (applyDefaultSetupOnFailure) + { + std::cout << "RetinaOCLImpl::setup: resetting retina with default parameters" << std::endl; + setupOPLandIPLParvoChannel(); + setupIPLMagnoChannel(); + } + else + { + std::cout << "=> keeping current parameters" << std::endl; + } + } +} + +void RetinaOCLImpl::setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure) +{ + try + { + // read parameters file if it exists or apply default setup if asked for + if (!fs.isOpened()) + { + std::cout << "RetinaOCLImpl::setup: provided parameters file could not be open... skeeping configuration" << std::endl; + return; + // implicit else case : retinaParameterFile could be open (it exists at least) + } + // OPL and Parvo init first... update at the same time the parameters structure and the retina core + cv::FileNode rootFn = fs.root(), currFn = rootFn["OPLandIPLparvo"]; + currFn["colorMode"] >> _retinaParameters.OPLandIplParvo.colorMode; + currFn["normaliseOutput"] >> _retinaParameters.OPLandIplParvo.normaliseOutput; + currFn["photoreceptorsLocalAdaptationSensitivity"] >> _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity; + currFn["photoreceptorsTemporalConstant"] >> _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant; + currFn["photoreceptorsSpatialConstant"] >> _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant; + currFn["horizontalCellsGain"] >> _retinaParameters.OPLandIplParvo.horizontalCellsGain; + currFn["hcellsTemporalConstant"] >> _retinaParameters.OPLandIplParvo.hcellsTemporalConstant; + currFn["hcellsSpatialConstant"] >> _retinaParameters.OPLandIplParvo.hcellsSpatialConstant; + currFn["ganglionCellsSensitivity"] >> _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity; + setupOPLandIPLParvoChannel(_retinaParameters.OPLandIplParvo.colorMode, _retinaParameters.OPLandIplParvo.normaliseOutput, _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity, _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant, _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant, _retinaParameters.OPLandIplParvo.horizontalCellsGain, _retinaParameters.OPLandIplParvo.hcellsTemporalConstant, _retinaParameters.OPLandIplParvo.hcellsSpatialConstant, _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity); + + // init retina IPL magno setup... update at the same time the parameters structure and the retina core + currFn = rootFn["IPLmagno"]; + currFn["normaliseOutput"] >> _retinaParameters.IplMagno.normaliseOutput; + currFn["parasolCells_beta"] >> _retinaParameters.IplMagno.parasolCells_beta; + currFn["parasolCells_tau"] >> _retinaParameters.IplMagno.parasolCells_tau; + currFn["parasolCells_k"] >> _retinaParameters.IplMagno.parasolCells_k; + currFn["amacrinCellsTemporalCutFrequency"] >> _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency; + currFn["V0CompressionParameter"] >> _retinaParameters.IplMagno.V0CompressionParameter; + currFn["localAdaptintegration_tau"] >> _retinaParameters.IplMagno.localAdaptintegration_tau; + currFn["localAdaptintegration_k"] >> _retinaParameters.IplMagno.localAdaptintegration_k; + + setupIPLMagnoChannel(_retinaParameters.IplMagno.normaliseOutput, _retinaParameters.IplMagno.parasolCells_beta, _retinaParameters.IplMagno.parasolCells_tau, _retinaParameters.IplMagno.parasolCells_k, _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency, _retinaParameters.IplMagno.V0CompressionParameter, _retinaParameters.IplMagno.localAdaptintegration_tau, _retinaParameters.IplMagno.localAdaptintegration_k); + + } + catch(Exception &e) + { + std::cout << "RetinaOCLImpl::setup: resetting retina with default parameters" << std::endl; + if (applyDefaultSetupOnFailure) + { + setupOPLandIPLParvoChannel(); + setupIPLMagnoChannel(); + } + std::cout << "RetinaOCLImpl::setup: wrong/unappropriate xml parameter file : error report :`n=>" << e.what() << std::endl; + std::cout << "=> keeping current parameters" << std::endl; + } +} + +void RetinaOCLImpl::setup(cv::bioinspired::Retina::RetinaParameters newConfiguration) +{ + // simply copy structures + memcpy(&_retinaParameters, &newConfiguration, sizeof(cv::bioinspired::Retina::RetinaParameters)); + // apply setup + setupOPLandIPLParvoChannel(_retinaParameters.OPLandIplParvo.colorMode, _retinaParameters.OPLandIplParvo.normaliseOutput, _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity, _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant, _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant, _retinaParameters.OPLandIplParvo.horizontalCellsGain, _retinaParameters.OPLandIplParvo.hcellsTemporalConstant, _retinaParameters.OPLandIplParvo.hcellsSpatialConstant, _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity); + setupIPLMagnoChannel(_retinaParameters.IplMagno.normaliseOutput, _retinaParameters.IplMagno.parasolCells_beta, _retinaParameters.IplMagno.parasolCells_tau, _retinaParameters.IplMagno.parasolCells_k, _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency, _retinaParameters.IplMagno.V0CompressionParameter, _retinaParameters.IplMagno.localAdaptintegration_tau, _retinaParameters.IplMagno.localAdaptintegration_k); +} + +const String RetinaOCLImpl::printSetup() +{ + std::stringstream outmessage; + + // displaying OPL and IPL parvo setup + outmessage << "Current Retina instance setup :" + << "\nOPLandIPLparvo" << "{" + << "\n==> colorMode : " << _retinaParameters.OPLandIplParvo.colorMode + << "\n==> normalizeParvoOutput :" << _retinaParameters.OPLandIplParvo.normaliseOutput + << "\n==> photoreceptorsLocalAdaptationSensitivity : " << _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity + << "\n==> photoreceptorsTemporalConstant : " << _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant + << "\n==> photoreceptorsSpatialConstant : " << _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant + << "\n==> horizontalCellsGain : " << _retinaParameters.OPLandIplParvo.horizontalCellsGain + << "\n==> hcellsTemporalConstant : " << _retinaParameters.OPLandIplParvo.hcellsTemporalConstant + << "\n==> hcellsSpatialConstant : " << _retinaParameters.OPLandIplParvo.hcellsSpatialConstant + << "\n==> parvoGanglionCellsSensitivity : " << _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity + << "}\n"; + + // displaying IPL magno setup + outmessage << "Current Retina instance setup :" + << "\nIPLmagno" << "{" + << "\n==> normaliseOutput : " << _retinaParameters.IplMagno.normaliseOutput + << "\n==> parasolCells_beta : " << _retinaParameters.IplMagno.parasolCells_beta + << "\n==> parasolCells_tau : " << _retinaParameters.IplMagno.parasolCells_tau + << "\n==> parasolCells_k : " << _retinaParameters.IplMagno.parasolCells_k + << "\n==> amacrinCellsTemporalCutFrequency : " << _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency + << "\n==> V0CompressionParameter : " << _retinaParameters.IplMagno.V0CompressionParameter + << "\n==> localAdaptintegration_tau : " << _retinaParameters.IplMagno.localAdaptintegration_tau + << "\n==> localAdaptintegration_k : " << _retinaParameters.IplMagno.localAdaptintegration_k + << "}"; + return outmessage.str().c_str(); +} + +void RetinaOCLImpl::write( String fs ) const +{ + FileStorage parametersSaveFile(fs, cv::FileStorage::WRITE ); + write(parametersSaveFile); +} + +void RetinaOCLImpl::write( FileStorage& fs ) const +{ + if (!fs.isOpened()) + { + return; // basic error case + } + fs << "OPLandIPLparvo" << "{"; + fs << "colorMode" << _retinaParameters.OPLandIplParvo.colorMode; + fs << "normaliseOutput" << _retinaParameters.OPLandIplParvo.normaliseOutput; + fs << "photoreceptorsLocalAdaptationSensitivity" << _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity; + fs << "photoreceptorsTemporalConstant" << _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant; + fs << "photoreceptorsSpatialConstant" << _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant; + fs << "horizontalCellsGain" << _retinaParameters.OPLandIplParvo.horizontalCellsGain; + fs << "hcellsTemporalConstant" << _retinaParameters.OPLandIplParvo.hcellsTemporalConstant; + fs << "hcellsSpatialConstant" << _retinaParameters.OPLandIplParvo.hcellsSpatialConstant; + fs << "ganglionCellsSensitivity" << _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity; + fs << "}"; + fs << "IPLmagno" << "{"; + fs << "normaliseOutput" << _retinaParameters.IplMagno.normaliseOutput; + fs << "parasolCells_beta" << _retinaParameters.IplMagno.parasolCells_beta; + fs << "parasolCells_tau" << _retinaParameters.IplMagno.parasolCells_tau; + fs << "parasolCells_k" << _retinaParameters.IplMagno.parasolCells_k; + fs << "amacrinCellsTemporalCutFrequency" << _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency; + fs << "V0CompressionParameter" << _retinaParameters.IplMagno.V0CompressionParameter; + fs << "localAdaptintegration_tau" << _retinaParameters.IplMagno.localAdaptintegration_tau; + fs << "localAdaptintegration_k" << _retinaParameters.IplMagno.localAdaptintegration_k; + fs << "}"; +} + +void RetinaOCLImpl::setupOPLandIPLParvoChannel(const bool colorMode, const bool normaliseOutput, const float photoreceptorsLocalAdaptationSensitivity, const float photoreceptorsTemporalConstant, const float photoreceptorsSpatialConstant, const float horizontalCellsGain, const float HcellsTemporalConstant, const float HcellsSpatialConstant, const float ganglionCellsSensitivity) +{ + // retina core parameters setup + _retinaFilter->setColorMode(colorMode); + _retinaFilter->setPhotoreceptorsLocalAdaptationSensitivity(photoreceptorsLocalAdaptationSensitivity); + _retinaFilter->setOPLandParvoParameters(0, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, HcellsTemporalConstant, HcellsSpatialConstant, ganglionCellsSensitivity); + _retinaFilter->setParvoGanglionCellsLocalAdaptationSensitivity(ganglionCellsSensitivity); + _retinaFilter->activateNormalizeParvoOutput_0_maxOutputValue(normaliseOutput); + + // update parameters struture + + _retinaParameters.OPLandIplParvo.colorMode = colorMode; + _retinaParameters.OPLandIplParvo.normaliseOutput = normaliseOutput; + _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity = photoreceptorsLocalAdaptationSensitivity; + _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant = photoreceptorsTemporalConstant; + _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant = photoreceptorsSpatialConstant; + _retinaParameters.OPLandIplParvo.horizontalCellsGain = horizontalCellsGain; + _retinaParameters.OPLandIplParvo.hcellsTemporalConstant = HcellsTemporalConstant; + _retinaParameters.OPLandIplParvo.hcellsSpatialConstant = HcellsSpatialConstant; + _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity = ganglionCellsSensitivity; +} + +void RetinaOCLImpl::setupIPLMagnoChannel(const bool normaliseOutput, const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float V0CompressionParameter, const float localAdaptintegration_tau, const float localAdaptintegration_k) +{ + + _retinaFilter->setMagnoCoefficientsTable(parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter, localAdaptintegration_tau, localAdaptintegration_k); + _retinaFilter->activateNormalizeMagnoOutput_0_maxOutputValue(normaliseOutput); + + // update parameters struture + _retinaParameters.IplMagno.normaliseOutput = normaliseOutput; + _retinaParameters.IplMagno.parasolCells_beta = parasolCells_beta; + _retinaParameters.IplMagno.parasolCells_tau = parasolCells_tau; + _retinaParameters.IplMagno.parasolCells_k = parasolCells_k; + _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency = amacrinCellsTemporalCutFrequency; + _retinaParameters.IplMagno.V0CompressionParameter = V0CompressionParameter; + _retinaParameters.IplMagno.localAdaptintegration_tau = localAdaptintegration_tau; + _retinaParameters.IplMagno.localAdaptintegration_k = localAdaptintegration_k; +} + +void RetinaOCLImpl::run(const InputArray input) +{ + oclMat &inputMatToConvert = getOclMatRef(input); + bool colorMode = convertToColorPlanes(inputMatToConvert, _inputBuffer); + // first convert input image to the compatible format : std::valarray + // process the retina + if (!_retinaFilter->runFilter(_inputBuffer, colorMode, false, _retinaParameters.OPLandIplParvo.colorMode && colorMode, false)) + { + throw cv::Exception(-1, "Retina cannot be applied, wrong input buffer size", "RetinaOCLImpl::run", "Retina.h", 0); + } +} + +void RetinaOCLImpl::getParvo(OutputArray output) +{ + oclMat &retinaOutput_parvo = getOclMatRef(output); + if (_retinaFilter->getColorMode()) + { + // reallocate output buffer (if necessary) + convertToInterleaved(_retinaFilter->getColorOutput(), true, retinaOutput_parvo); + } + else + { + // reallocate output buffer (if necessary) + convertToInterleaved(_retinaFilter->getContours(), false, retinaOutput_parvo); + } + //retinaOutput_parvo/=255.0; +} +void RetinaOCLImpl::getMagno(OutputArray output) +{ + oclMat &retinaOutput_magno = getOclMatRef(output); + // reallocate output buffer (if necessary) + convertToInterleaved(_retinaFilter->getMovingContours(), false, retinaOutput_magno); + //retinaOutput_magno/=255.0; +} +// private method called by constructirs +void RetinaOCLImpl::_init(const cv::Size inputSz, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght) +{ + // basic error check + if (inputSz.height*inputSz.width <= 0) + { + throw cv::Exception(-1, "Bad retina size setup : size height and with must be superior to zero", "RetinaOCLImpl::setup", "Retina.h", 0); + } + + // allocate the retina model + if (_retinaFilter) + { + delete _retinaFilter; + } + _retinaFilter = new RetinaFilter(inputSz.height, inputSz.width, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght); + + // prepare the default parameter XML file with default setup + setup(_retinaParameters); + + // init retina + _retinaFilter->clearAllBuffers(); +} + +bool RetinaOCLImpl::convertToColorPlanes(const oclMat& input, oclMat &output) +{ + oclMat convert_input; + input.convertTo(convert_input, CV_32F); + if(convert_input.channels() == 3 || convert_input.channels() == 4) + { + ocl::ensureSizeIsEnough(int(_retinaFilter->getInputNBrows() * 4), + int(_retinaFilter->getInputNBcolumns()), CV_32FC1, output); + oclMat channel_splits[4] = + { + output(Rect(Point(0, _retinaFilter->getInputNBrows() * 2), getInputSize())), + output(Rect(Point(0, _retinaFilter->getInputNBrows()), getInputSize())), + output(Rect(Point(0, 0), getInputSize())), + output(Rect(Point(0, _retinaFilter->getInputNBrows() * 3), getInputSize())) + }; + ocl::split(convert_input, channel_splits); + return true; + } + else if(convert_input.channels() == 1) + { + convert_input.copyTo(output); + return false; + } + else + { + CV_Error(-1, "Retina ocl only support 1, 3, 4 channel input"); + return false; + } +} +void RetinaOCLImpl::convertToInterleaved(const oclMat& input, bool colorMode, oclMat &output) +{ + input.convertTo(output, CV_8U); + if(colorMode) + { + int numOfSplits = input.rows / getInputSize().height; + std::vector channel_splits(numOfSplits); + for(int i = 0; i < static_cast(channel_splits.size()); i ++) + { + channel_splits[i] = + output(Rect(Point(0, _retinaFilter->getInputNBrows() * (numOfSplits - i - 1)), getInputSize())); + } + merge(channel_splits, output); + } + else + { + //... + } +} + +void RetinaOCLImpl::clearBuffers() +{ + _retinaFilter->clearAllBuffers(); +} + +void RetinaOCLImpl::activateMovingContoursProcessing(const bool activate) +{ + _retinaFilter->activateMovingContoursProcessing(activate); +} + +void RetinaOCLImpl::activateContoursProcessing(const bool activate) +{ + _retinaFilter->activateContoursProcessing(activate); +} + +/////////////////////////////////////// +///////// BasicRetinaFilter /////////// +/////////////////////////////////////// +BasicRetinaFilter::BasicRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns, const unsigned int parametersListSize, const bool) + : _NBrows(NBrows), _NBcols(NBcolumns), + _filterOutput(NBrows, NBcolumns, CV_32FC1), + _localBuffer(NBrows, NBcolumns, CV_32FC1), + _filteringCoeficientsTable(3 * parametersListSize) +{ + _halfNBrows = _filterOutput.rows / 2; + _halfNBcolumns = _filterOutput.cols / 2; + + // set default values + _maxInputValue = 256.0; + + // reset all buffers + clearAllBuffers(); +} + +BasicRetinaFilter::~BasicRetinaFilter() +{ +} + +void BasicRetinaFilter::resize(const unsigned int NBrows, const unsigned int NBcolumns) +{ + // resizing buffers + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _filterOutput); + + // updating variables + _halfNBrows = _filterOutput.rows / 2; + _halfNBcolumns = _filterOutput.cols / 2; + + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _localBuffer); + // reset buffers + clearAllBuffers(); +} + +void BasicRetinaFilter::setLPfilterParameters(const float beta, const float tau, const float desired_k, const unsigned int filterIndex) +{ + float _beta = beta + tau; + float k = desired_k; + // check if the spatial constant is correct (avoid 0 value to avoid division by 0) + if (desired_k <= 0) + { + k = 0.001f; + std::cerr << "BasicRetinaFilter::spatial constant of the low pass filter must be superior to zero !!! correcting parameter setting to 0,001" << std::endl; + } + + float _alpha = k * k; + float _mu = 0.8f; + unsigned int tableOffset = filterIndex * 3; + if (k <= 0) + { + std::cerr << "BasicRetinaFilter::spatial filtering coefficient must be superior to zero, correcting value to 0.01" << std::endl; + _alpha = 0.0001f; + } + + float _temp = (1.0f + _beta) / (2.0f * _mu * _alpha); + float a = _filteringCoeficientsTable[tableOffset] = 1.0f + _temp - (float)sqrt( (1.0f + _temp) * (1.0f + _temp) - 1.0f); + _filteringCoeficientsTable[1 + tableOffset] = (1.0f - a) * (1.0f - a) * (1.0f - a) * (1.0f - a) / (1.0f + _beta); + _filteringCoeficientsTable[2 + tableOffset] = tau; +} +const oclMat &BasicRetinaFilter::runFilter_LocalAdapdation(const oclMat &inputFrame, const oclMat &localLuminance) +{ + _localLuminanceAdaptation(inputFrame, localLuminance, _filterOutput); + return _filterOutput; +} + + +void BasicRetinaFilter::runFilter_LocalAdapdation(const oclMat &inputFrame, const oclMat &localLuminance, oclMat &outputFrame) +{ + _localLuminanceAdaptation(inputFrame, localLuminance, outputFrame); +} + +const oclMat &BasicRetinaFilter::runFilter_LocalAdapdation_autonomous(const oclMat &inputFrame) +{ + _spatiotemporalLPfilter(inputFrame, _filterOutput); + _localLuminanceAdaptation(inputFrame, _filterOutput, _filterOutput); + return _filterOutput; +} +void BasicRetinaFilter::runFilter_LocalAdapdation_autonomous(const oclMat &inputFrame, oclMat &outputFrame) +{ + _spatiotemporalLPfilter(inputFrame, _filterOutput); + _localLuminanceAdaptation(inputFrame, _filterOutput, outputFrame); +} + +void BasicRetinaFilter::_localLuminanceAdaptation(oclMat &inputOutputFrame, const oclMat &localLuminance) +{ + _localLuminanceAdaptation(inputOutputFrame, localLuminance, inputOutputFrame, false); +} + +void BasicRetinaFilter::_localLuminanceAdaptation(const oclMat &inputFrame, const oclMat &localLuminance, oclMat &outputFrame, const bool updateLuminanceMean) +{ + if (updateLuminanceMean) + { + float meanLuminance = saturate_cast(ocl::sum(inputFrame)[0]) / getNBpixels(); + updateCompressionParameter(meanLuminance); + } + int elements_per_row = static_cast(inputFrame.step / inputFrame.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {_NBcols, _NBrows, 1}; + size_t localSize[] = {16, 16, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &localLuminance.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &inputFrame.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); + args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); + args.push_back(std::make_pair(sizeof(cl_int), &_NBrows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + args.push_back(std::make_pair(sizeof(cl_float), &_localLuminanceAddon)); + args.push_back(std::make_pair(sizeof(cl_float), &_localLuminanceFactor)); + args.push_back(std::make_pair(sizeof(cl_float), &_maxInputValue)); + openCLExecuteKernel(ctx, &retina_kernel, "localLuminanceAdaptation", globalSize, localSize, args, -1, -1); +} + +const oclMat &BasicRetinaFilter::runFilter_LPfilter(const oclMat &inputFrame, const unsigned int filterIndex) +{ + _spatiotemporalLPfilter(inputFrame, _filterOutput, filterIndex); + return _filterOutput; +} +void BasicRetinaFilter::runFilter_LPfilter(const oclMat &inputFrame, oclMat &outputFrame, const unsigned int filterIndex) +{ + _spatiotemporalLPfilter(inputFrame, outputFrame, filterIndex); +} + +void BasicRetinaFilter::_spatiotemporalLPfilter(const oclMat &inputFrame, oclMat &LPfilterOutput, const unsigned int filterIndex) +{ + unsigned int coefTableOffset = filterIndex * 3; + + _a = _filteringCoeficientsTable[coefTableOffset]; + _gain = _filteringCoeficientsTable[1 + coefTableOffset]; + _tau = _filteringCoeficientsTable[2 + coefTableOffset]; + + _horizontalCausalFilter_addInput(inputFrame, LPfilterOutput); + _horizontalAnticausalFilter(LPfilterOutput); + _verticalCausalFilter(LPfilterOutput); + _verticalAnticausalFilter_multGain(LPfilterOutput); +} + +void BasicRetinaFilter::_horizontalCausalFilter_addInput(const oclMat &inputFrame, oclMat &outputFrame) +{ + int elements_per_row = static_cast(inputFrame.step / inputFrame.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {_NBrows, 1, 1}; + size_t localSize[] = {256, 1, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &inputFrame.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); + args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); + args.push_back(std::make_pair(sizeof(cl_int), &_NBrows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + args.push_back(std::make_pair(sizeof(cl_int), &inputFrame.offset)); + args.push_back(std::make_pair(sizeof(cl_int), &inputFrame.offset)); + args.push_back(std::make_pair(sizeof(cl_float), &_tau)); + args.push_back(std::make_pair(sizeof(cl_float), &_a)); + openCLExecuteKernel(ctx, &retina_kernel, "horizontalCausalFilter_addInput", globalSize, localSize, args, -1, -1); +} + +void BasicRetinaFilter::_horizontalAnticausalFilter(oclMat &outputFrame) +{ + int elements_per_row = static_cast(outputFrame.step / outputFrame.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {_NBrows, 1, 1}; + size_t localSize[] = {256, 1, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); + args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); + args.push_back(std::make_pair(sizeof(cl_int), &_NBrows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.offset)); + args.push_back(std::make_pair(sizeof(cl_float), &_a)); + openCLExecuteKernel(ctx, &retina_kernel, "horizontalAnticausalFilter", globalSize, localSize, args, -1, -1); +} + +void BasicRetinaFilter::_verticalCausalFilter(oclMat &outputFrame) +{ + int elements_per_row = static_cast(outputFrame.step / outputFrame.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {_NBcols, 1, 1}; + size_t localSize[] = {256, 1, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); + args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); + args.push_back(std::make_pair(sizeof(cl_int), &_NBrows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.offset)); + args.push_back(std::make_pair(sizeof(cl_float), &_a)); + openCLExecuteKernel(ctx, &retina_kernel, "verticalCausalFilter", globalSize, localSize, args, -1, -1); +} + +void BasicRetinaFilter::_verticalAnticausalFilter_multGain(oclMat &outputFrame) +{ + int elements_per_row = static_cast(outputFrame.step / outputFrame.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {_NBcols, 1, 1}; + size_t localSize[] = {256, 1, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); + args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); + args.push_back(std::make_pair(sizeof(cl_int), &_NBrows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.offset)); + args.push_back(std::make_pair(sizeof(cl_float), &_a)); + args.push_back(std::make_pair(sizeof(cl_float), &_gain)); + openCLExecuteKernel(ctx, &retina_kernel, "verticalAnticausalFilter_multGain", globalSize, localSize, args, -1, -1); +} + +void BasicRetinaFilter::_horizontalAnticausalFilter_Irregular(oclMat &outputFrame, const oclMat &spatialConstantBuffer) +{ + int elements_per_row = static_cast(outputFrame.step / outputFrame.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {outputFrame.rows, 1, 1}; + size_t localSize[] = {256, 1, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &spatialConstantBuffer.data)); + args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.cols)); + args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.rows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.offset)); + args.push_back(std::make_pair(sizeof(cl_int), &spatialConstantBuffer.offset)); + openCLExecuteKernel(ctx, &retina_kernel, "horizontalAnticausalFilter_Irregular", globalSize, localSize, args, -1, -1); +} + +// vertical anticausal filter +void BasicRetinaFilter::_verticalCausalFilter_Irregular(oclMat &outputFrame, const oclMat &spatialConstantBuffer) +{ + int elements_per_row = static_cast(outputFrame.step / outputFrame.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {outputFrame.cols, 1, 1}; + size_t localSize[] = {256, 1, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &spatialConstantBuffer.data)); + args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.cols)); + args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.rows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.offset)); + args.push_back(std::make_pair(sizeof(cl_int), &spatialConstantBuffer.offset)); + openCLExecuteKernel(ctx, &retina_kernel, "verticalCausalFilter_Irregular", globalSize, localSize, args, -1, -1); +} + +void normalizeGrayOutput_0_maxOutputValue(oclMat &inputOutputBuffer, const float maxOutputValue) +{ + double min_val, max_val; + ocl::minMax(inputOutputBuffer, &min_val, &max_val); + float factor = maxOutputValue / static_cast(max_val - min_val); + float offset = - static_cast(min_val) * factor; + ocl::multiply(factor, inputOutputBuffer, inputOutputBuffer); + ocl::add(inputOutputBuffer, offset, inputOutputBuffer); +} + +void normalizeGrayOutputCentredSigmoide(const float meanValue, const float sensitivity, oclMat &in, oclMat &out, const float maxValue) +{ + if (sensitivity == 1.0f) + { + std::cerr << "TemplateBuffer::TemplateBuffer::normalizeGrayOutputCentredSigmoide error: 2nd parameter (sensitivity) must not equal 0, copying original data..." << std::endl; + in.copyTo(out); + return; + } + + float X0 = maxValue / (sensitivity - 1.0f); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {in.cols, out.rows, 1}; + size_t localSize[] = {16, 16, 1}; + + int elements_per_row = static_cast(out.step / out.elemSize()); + + args.push_back(std::make_pair(sizeof(cl_mem), &in.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &out.data)); + args.push_back(std::make_pair(sizeof(cl_int), &in.cols)); + args.push_back(std::make_pair(sizeof(cl_int), &in.rows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + args.push_back(std::make_pair(sizeof(cl_float), &meanValue)); + args.push_back(std::make_pair(sizeof(cl_float), &X0)); + openCLExecuteKernel(ctx, &retina_kernel, "normalizeGrayOutputCentredSigmoide", globalSize, localSize, args, -1, -1); +} + +void normalizeGrayOutputNearZeroCentreredSigmoide(oclMat &inputPicture, oclMat &outputBuffer, const float sensitivity, const float maxOutputValue) +{ + float X0cube = sensitivity * sensitivity * sensitivity; + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {inputPicture.cols, inputPicture.rows, 1}; + size_t localSize[] = {16, 16, 1}; + + int elements_per_row = static_cast(inputPicture.step / inputPicture.elemSize()); + args.push_back(std::make_pair(sizeof(cl_mem), &inputPicture.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &outputBuffer.data)); + args.push_back(std::make_pair(sizeof(cl_int), &inputPicture.cols)); + args.push_back(std::make_pair(sizeof(cl_int), &inputPicture.rows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + args.push_back(std::make_pair(sizeof(cl_float), &maxOutputValue)); + args.push_back(std::make_pair(sizeof(cl_float), &X0cube)); + openCLExecuteKernel(ctx, &retina_kernel, "normalizeGrayOutputNearZeroCentreredSigmoide", globalSize, localSize, args, -1, -1); +} + +void centerReductImageLuminance(oclMat &inputoutput) +{ + Scalar mean, stddev; + cv::meanStdDev((Mat)inputoutput, mean, stddev); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {inputoutput.cols, inputoutput.rows, 1}; + size_t localSize[] = {16, 16, 1}; + + float f_mean = static_cast(mean[0]); + float f_stddev = static_cast(stddev[0]); + int elements_per_row = static_cast(inputoutput.step / inputoutput.elemSize()); + args.push_back(std::make_pair(sizeof(cl_mem), &inputoutput.data)); + args.push_back(std::make_pair(sizeof(cl_int), &inputoutput.cols)); + args.push_back(std::make_pair(sizeof(cl_int), &inputoutput.rows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + args.push_back(std::make_pair(sizeof(cl_float), &f_mean)); + args.push_back(std::make_pair(sizeof(cl_float), &f_stddev)); + openCLExecuteKernel(ctx, &retina_kernel, "centerReductImageLuminance", globalSize, localSize, args, -1, -1); +} + +/////////////////////////////////////// +///////// ParvoRetinaFilter /////////// +/////////////////////////////////////// +ParvoRetinaFilter::ParvoRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns) + : BasicRetinaFilter(NBrows, NBcolumns, 3), + _photoreceptorsOutput(NBrows, NBcolumns, CV_32FC1), + _horizontalCellsOutput(NBrows, NBcolumns, CV_32FC1), + _parvocellularOutputON(NBrows, NBcolumns, CV_32FC1), + _parvocellularOutputOFF(NBrows, NBcolumns, CV_32FC1), + _bipolarCellsOutputON(NBrows, NBcolumns, CV_32FC1), + _bipolarCellsOutputOFF(NBrows, NBcolumns, CV_32FC1), + _localAdaptationOFF(NBrows, NBcolumns, CV_32FC1) +{ + // link to the required local parent adaptation buffers + _localAdaptationON = _localBuffer; + _parvocellularOutputONminusOFF = _filterOutput; + + // init: set all the values to 0 + clearAllBuffers(); +} + +ParvoRetinaFilter::~ParvoRetinaFilter() +{ +} + +void ParvoRetinaFilter::clearAllBuffers() +{ + BasicRetinaFilter::clearAllBuffers(); + _photoreceptorsOutput = 0; + _horizontalCellsOutput = 0; + _parvocellularOutputON = 0; + _parvocellularOutputOFF = 0; + _bipolarCellsOutputON = 0; + _bipolarCellsOutputOFF = 0; + _localAdaptationOFF = 0; +} +void ParvoRetinaFilter::resize(const unsigned int NBrows, const unsigned int NBcolumns) +{ + BasicRetinaFilter::resize(NBrows, NBcolumns); + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _photoreceptorsOutput); + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _horizontalCellsOutput); + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _parvocellularOutputON); + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _parvocellularOutputOFF); + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _bipolarCellsOutputON); + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _bipolarCellsOutputOFF); + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _localAdaptationOFF); + + // link to the required local parent adaptation buffers + _localAdaptationON = _localBuffer; + _parvocellularOutputONminusOFF = _filterOutput; + + // clean buffers + clearAllBuffers(); +} + +void ParvoRetinaFilter::setOPLandParvoFiltersParameters(const float beta1, const float tau1, const float k1, const float beta2, const float tau2, const float k2) +{ + // init photoreceptors low pass filter + setLPfilterParameters(beta1, tau1, k1); + // init horizontal cells low pass filter + setLPfilterParameters(beta2, tau2, k2, 1); + // init parasol ganglion cells low pass filter (default parameters) + setLPfilterParameters(0, tau1, k1, 2); + +} +const oclMat &ParvoRetinaFilter::runFilter(const oclMat &inputFrame, const bool useParvoOutput) +{ + _spatiotemporalLPfilter(inputFrame, _photoreceptorsOutput); + _spatiotemporalLPfilter(_photoreceptorsOutput, _horizontalCellsOutput, 1); + _OPL_OnOffWaysComputing(); + + if (useParvoOutput) + { + // local adaptation processes on ON and OFF ways + _spatiotemporalLPfilter(_bipolarCellsOutputON, _localAdaptationON, 2); + _localLuminanceAdaptation(_parvocellularOutputON, _localAdaptationON); + _spatiotemporalLPfilter(_bipolarCellsOutputOFF, _localAdaptationOFF, 2); + _localLuminanceAdaptation(_parvocellularOutputOFF, _localAdaptationOFF); + ocl::subtract(_parvocellularOutputON, _parvocellularOutputOFF, _parvocellularOutputONminusOFF); + } + + return _parvocellularOutputONminusOFF; +} +void ParvoRetinaFilter::_OPL_OnOffWaysComputing() +{ + int elements_per_row = static_cast(_photoreceptorsOutput.step / _photoreceptorsOutput.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {(_photoreceptorsOutput.cols + 3) / 4, _photoreceptorsOutput.rows, 1}; + size_t localSize[] = {16, 16, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &_photoreceptorsOutput.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &_horizontalCellsOutput.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &_bipolarCellsOutputON.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &_bipolarCellsOutputOFF.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &_parvocellularOutputON.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &_parvocellularOutputOFF.data)); + args.push_back(std::make_pair(sizeof(cl_int), &_photoreceptorsOutput.cols)); + args.push_back(std::make_pair(sizeof(cl_int), &_photoreceptorsOutput.rows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + openCLExecuteKernel(ctx, &retina_kernel, "OPL_OnOffWaysComputing", globalSize, localSize, args, -1, -1); +} + +/////////////////////////////////////// +//////////// MagnoFilter ////////////// +/////////////////////////////////////// +MagnoRetinaFilter::MagnoRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns) + : BasicRetinaFilter(NBrows, NBcolumns, 2), + _previousInput_ON(NBrows, NBcolumns, CV_32FC1), + _previousInput_OFF(NBrows, NBcolumns, CV_32FC1), + _amacrinCellsTempOutput_ON(NBrows, NBcolumns, CV_32FC1), + _amacrinCellsTempOutput_OFF(NBrows, NBcolumns, CV_32FC1), + _magnoXOutputON(NBrows, NBcolumns, CV_32FC1), + _magnoXOutputOFF(NBrows, NBcolumns, CV_32FC1), + _localProcessBufferON(NBrows, NBcolumns, CV_32FC1), + _localProcessBufferOFF(NBrows, NBcolumns, CV_32FC1) +{ + _magnoYOutput = _filterOutput; + _magnoYsaturated = _localBuffer; + + clearAllBuffers(); +} + +MagnoRetinaFilter::~MagnoRetinaFilter() +{ +} +void MagnoRetinaFilter::clearAllBuffers() +{ + BasicRetinaFilter::clearAllBuffers(); + _previousInput_ON = 0; + _previousInput_OFF = 0; + _amacrinCellsTempOutput_ON = 0; + _amacrinCellsTempOutput_OFF = 0; + _magnoXOutputON = 0; + _magnoXOutputOFF = 0; + _localProcessBufferON = 0; + _localProcessBufferOFF = 0; + +} +void MagnoRetinaFilter::resize(const unsigned int NBrows, const unsigned int NBcolumns) +{ + BasicRetinaFilter::resize(NBrows, NBcolumns); + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _previousInput_ON); + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _previousInput_OFF); + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _amacrinCellsTempOutput_ON); + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _amacrinCellsTempOutput_OFF); + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _magnoXOutputON); + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _magnoXOutputOFF); + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _localProcessBufferON); + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _localProcessBufferOFF); + + // to be sure, relink buffers + _magnoYOutput = _filterOutput; + _magnoYsaturated = _localBuffer; + + // reset all buffers + clearAllBuffers(); +} + +void MagnoRetinaFilter::setCoefficientsTable(const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float localAdaptIntegration_tau, const float localAdaptIntegration_k ) +{ + _temporalCoefficient = (float)std::exp(-1.0f / amacrinCellsTemporalCutFrequency); + // the first set of parameters is dedicated to the low pass filtering property of the ganglion cells + BasicRetinaFilter::setLPfilterParameters(parasolCells_beta, parasolCells_tau, parasolCells_k, 0); + // the second set of parameters is dedicated to the ganglion cells output intergartion for their local adaptation property + BasicRetinaFilter::setLPfilterParameters(0, localAdaptIntegration_tau, localAdaptIntegration_k, 1); +} + +void MagnoRetinaFilter::_amacrineCellsComputing( + const oclMat &OPL_ON, + const oclMat &OPL_OFF +) +{ + int elements_per_row = static_cast(OPL_ON.step / OPL_ON.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {OPL_ON.cols, OPL_ON.rows, 1}; + size_t localSize[] = {16, 16, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &OPL_ON.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &OPL_OFF.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &_previousInput_ON.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &_previousInput_OFF.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &_amacrinCellsTempOutput_ON.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &_amacrinCellsTempOutput_OFF.data)); + args.push_back(std::make_pair(sizeof(cl_int), &OPL_ON.cols)); + args.push_back(std::make_pair(sizeof(cl_int), &OPL_ON.rows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + args.push_back(std::make_pair(sizeof(cl_float), &_temporalCoefficient)); + openCLExecuteKernel(ctx, &retina_kernel, "amacrineCellsComputing", globalSize, localSize, args, -1, -1); +} + +const oclMat &MagnoRetinaFilter::runFilter(const oclMat &OPL_ON, const oclMat &OPL_OFF) +{ + // Compute the high pass temporal filter + _amacrineCellsComputing(OPL_ON, OPL_OFF); + + // apply low pass filtering on ON and OFF ways after temporal high pass filtering + _spatiotemporalLPfilter(_amacrinCellsTempOutput_ON, _magnoXOutputON, 0); + _spatiotemporalLPfilter(_amacrinCellsTempOutput_OFF, _magnoXOutputOFF, 0); + + // local adaptation of the ganglion cells to the local contrast of the moving contours + _spatiotemporalLPfilter(_magnoXOutputON, _localProcessBufferON, 1); + _localLuminanceAdaptation(_magnoXOutputON, _localProcessBufferON); + + _spatiotemporalLPfilter(_magnoXOutputOFF, _localProcessBufferOFF, 1); + _localLuminanceAdaptation(_magnoXOutputOFF, _localProcessBufferOFF); + + _magnoYOutput = _magnoXOutputON + _magnoXOutputOFF; + + return _magnoYOutput; +} + +/////////////////////////////////////// +//////////// RetinaColor ////////////// +/////////////////////////////////////// + +// define an array of ROI headers of input x +#define MAKE_OCLMAT_SLICES(x, n) \ + oclMat x##_slices[n];\ + for(int _SLICE_INDEX_ = 0; _SLICE_INDEX_ < n; _SLICE_INDEX_ ++)\ + {\ + x##_slices[_SLICE_INDEX_] = x(getROI(_SLICE_INDEX_));\ + } + +RetinaColor::RetinaColor(const unsigned int NBrows, const unsigned int NBcolumns, const int samplingMethod) + : BasicRetinaFilter(NBrows, NBcolumns, 3), + _RGBmosaic(NBrows * 3, NBcolumns, CV_32FC1), + _tempMultiplexedFrame(NBrows, NBcolumns, CV_32FC1), + _demultiplexedTempBuffer(NBrows * 3, NBcolumns, CV_32FC1), + _demultiplexedColorFrame(NBrows * 3, NBcolumns, CV_32FC1), + _chrominance(NBrows * 3, NBcolumns, CV_32FC1), + _colorLocalDensity(NBrows * 3, NBcolumns, CV_32FC1), + _imageGradient(NBrows * 3, NBcolumns, CV_32FC1) +{ + // link to parent buffers (let's recycle !) + _luminance = _filterOutput; + _multiplexedFrame = _localBuffer; + + _objectInit = false; + _samplingMethod = samplingMethod; + _saturateColors = false; + _colorSaturationValue = 4.0; + + // set default spatio-temporal filter parameters + setLPfilterParameters(0.0, 0.0, 1.5); + setLPfilterParameters(0.0, 0.0, 10.5, 1);// for the low pass filter dedicated to contours energy extraction (demultiplexing process) + setLPfilterParameters(0.f, 0.f, 0.9f, 2); + + // init default value on image Gradient + _imageGradient = 0.57f; + + // init color sampling map + _initColorSampling(); + + // flush all buffers + clearAllBuffers(); +} + +RetinaColor::~RetinaColor() +{ + +} + +void RetinaColor::clearAllBuffers() +{ + BasicRetinaFilter::clearAllBuffers(); + _tempMultiplexedFrame = 0.f; + _demultiplexedTempBuffer = 0.f; + + _demultiplexedColorFrame = 0.f; + _chrominance = 0.f; + _imageGradient = 0.57f; +} + +void RetinaColor::resize(const unsigned int NBrows, const unsigned int NBcolumns) +{ + BasicRetinaFilter::clearAllBuffers(); + ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _tempMultiplexedFrame); + ensureSizeIsEnough(NBrows * 2, NBcolumns, CV_32FC1, _imageGradient); + ensureSizeIsEnough(NBrows * 3, NBcolumns, CV_32FC1, _RGBmosaic); + ensureSizeIsEnough(NBrows * 3, NBcolumns, CV_32FC1, _demultiplexedTempBuffer); + ensureSizeIsEnough(NBrows * 3, NBcolumns, CV_32FC1, _demultiplexedColorFrame); + ensureSizeIsEnough(NBrows * 3, NBcolumns, CV_32FC1, _chrominance); + ensureSizeIsEnough(NBrows * 3, NBcolumns, CV_32FC1, _colorLocalDensity); + + // link to parent buffers (let's recycle !) + _luminance = _filterOutput; + _multiplexedFrame = _localBuffer; + + // init color sampling map + _initColorSampling(); + + // clean buffers + clearAllBuffers(); +} + +static void inverseValue(oclMat &input) +{ + int elements_per_row = static_cast(input.step / input.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {input.cols, input.rows, 1}; + size_t localSize[] = {16, 16, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &input.data)); + args.push_back(std::make_pair(sizeof(cl_int), &input.cols)); + args.push_back(std::make_pair(sizeof(cl_int), &input.rows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + openCLExecuteKernel(ctx, &retina_kernel, "inverseValue", globalSize, localSize, args, -1, -1); +} + +void RetinaColor::_initColorSampling() +{ + CV_Assert(_samplingMethod == RETINA_COLOR_BAYER); + _pR = _pB = 0.25; + _pG = 0.5; + // filling the mosaic buffer: + _RGBmosaic = 0; + Mat tmp_mat(_NBrows * 3, _NBcols, CV_32FC1); + float * tmp_mat_ptr = tmp_mat.ptr(); + tmp_mat.setTo(0); + for (unsigned int index = 0 ; index < getNBpixels(); ++index) + { + tmp_mat_ptr[bayerSampleOffset(index)] = 1.0; + } + _RGBmosaic.upload(tmp_mat); + // computing photoreceptors local density + MAKE_OCLMAT_SLICES(_RGBmosaic, 3); + MAKE_OCLMAT_SLICES(_colorLocalDensity, 3); + _colorLocalDensity.setTo(0); + _spatiotemporalLPfilter(_RGBmosaic_slices[0], _colorLocalDensity_slices[0]); + _spatiotemporalLPfilter(_RGBmosaic_slices[1], _colorLocalDensity_slices[1]); + _spatiotemporalLPfilter(_RGBmosaic_slices[2], _colorLocalDensity_slices[2]); + + //_colorLocalDensity = oclMat(_colorLocalDensity.size(), _colorLocalDensity.type(), 1.f) / _colorLocalDensity; + inverseValue(_colorLocalDensity); + + _objectInit = true; +} + +static void demultiplex(const oclMat &input, oclMat &ouput) +{ + int elements_per_row = static_cast(input.step / input.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {input.cols, input.rows, 1}; + size_t localSize[] = {16, 16, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &input.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &ouput.data)); + args.push_back(std::make_pair(sizeof(cl_int), &input.cols)); + args.push_back(std::make_pair(sizeof(cl_int), &input.rows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + openCLExecuteKernel(ctx, &retina_kernel, "runColorDemultiplexingBayer", globalSize, localSize, args, -1, -1); +} + +static void normalizePhotoDensity( + const oclMat &chroma, + const oclMat &colorDensity, + const oclMat &multiplex, + oclMat &ocl_luma, + oclMat &demultiplex, + const float pG +) +{ + int elements_per_row = static_cast(ocl_luma.step / ocl_luma.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {ocl_luma.cols, ocl_luma.rows, 1}; + size_t localSize[] = {16, 16, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &chroma.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &colorDensity.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &multiplex.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &ocl_luma.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &demultiplex.data)); + args.push_back(std::make_pair(sizeof(cl_int), &ocl_luma.cols)); + args.push_back(std::make_pair(sizeof(cl_int), &ocl_luma.rows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + args.push_back(std::make_pair(sizeof(cl_float), &pG)); + openCLExecuteKernel(ctx, &retina_kernel, "normalizePhotoDensity", globalSize, localSize, args, -1, -1); +} + +static void substractResidual( + oclMat &colorDemultiplex, + float pR, + float pG, + float pB +) +{ + int elements_per_row = static_cast(colorDemultiplex.step / colorDemultiplex.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + int rows = colorDemultiplex.rows / 3, cols = colorDemultiplex.cols; + size_t globalSize[] = {cols, rows, 1}; + size_t localSize[] = {16, 16, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &colorDemultiplex.data)); + args.push_back(std::make_pair(sizeof(cl_int), &cols)); + args.push_back(std::make_pair(sizeof(cl_int), &rows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + args.push_back(std::make_pair(sizeof(cl_float), &pR)); + args.push_back(std::make_pair(sizeof(cl_float), &pG)); + args.push_back(std::make_pair(sizeof(cl_float), &pB)); + openCLExecuteKernel(ctx, &retina_kernel, "substractResidual", globalSize, localSize, args, -1, -1); +} + +static void demultiplexAssign(const oclMat& input, const oclMat& output) +{ + // only supports bayer + int elements_per_row = static_cast(input.step / input.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + int rows = input.rows / 3, cols = input.cols; + size_t globalSize[] = {cols, rows, 1}; + size_t localSize[] = {16, 16, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &input.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &output.data)); + args.push_back(std::make_pair(sizeof(cl_int), &cols)); + args.push_back(std::make_pair(sizeof(cl_int), &rows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + openCLExecuteKernel(ctx, &retina_kernel, "demultiplexAssign", globalSize, localSize, args, -1, -1); +} + +void RetinaColor::runColorDemultiplexing( + const oclMat &ocl_multiplexed_input, + const bool adaptiveFiltering, + const float maxInputValue +) +{ + MAKE_OCLMAT_SLICES(_demultiplexedTempBuffer, 3); + MAKE_OCLMAT_SLICES(_chrominance, 3); + MAKE_OCLMAT_SLICES(_RGBmosaic, 3); + MAKE_OCLMAT_SLICES(_demultiplexedColorFrame, 3); + MAKE_OCLMAT_SLICES(_colorLocalDensity, 3); + + _demultiplexedTempBuffer.setTo(0); + demultiplex(ocl_multiplexed_input, _demultiplexedTempBuffer); + + // interpolate the demultiplexed frame depending on the color sampling method + if (!adaptiveFiltering) + { + CV_Assert(adaptiveFiltering == false); + } + + _spatiotemporalLPfilter(_demultiplexedTempBuffer_slices[0], _chrominance_slices[0]); + _spatiotemporalLPfilter(_demultiplexedTempBuffer_slices[1], _chrominance_slices[1]); + _spatiotemporalLPfilter(_demultiplexedTempBuffer_slices[2], _chrominance_slices[2]); + + if (!adaptiveFiltering)// compute the gradient on the luminance + { + // TODO: implement me! + CV_Assert(adaptiveFiltering == false); + } + else + { + normalizePhotoDensity(_chrominance, _colorLocalDensity, ocl_multiplexed_input, _luminance, _demultiplexedTempBuffer, _pG); + // compute the gradient of the luminance + _computeGradient(_luminance, _imageGradient); + + _adaptiveSpatialLPfilter(_RGBmosaic_slices[0], _imageGradient, _chrominance_slices[0]); + _adaptiveSpatialLPfilter(_RGBmosaic_slices[1], _imageGradient, _chrominance_slices[1]); + _adaptiveSpatialLPfilter(_RGBmosaic_slices[2], _imageGradient, _chrominance_slices[2]); + + _adaptiveSpatialLPfilter(_demultiplexedTempBuffer_slices[0], _imageGradient, _demultiplexedColorFrame_slices[0]); + _adaptiveSpatialLPfilter(_demultiplexedTempBuffer_slices[1], _imageGradient, _demultiplexedColorFrame_slices[1]); + _adaptiveSpatialLPfilter(_demultiplexedTempBuffer_slices[2], _imageGradient, _demultiplexedColorFrame_slices[2]); + + _demultiplexedColorFrame /= _chrominance; // per element division + substractResidual(_demultiplexedColorFrame, _pR, _pG, _pB); + runColorMultiplexing(_demultiplexedColorFrame, _tempMultiplexedFrame); + + _demultiplexedTempBuffer.setTo(0); + _luminance = ocl_multiplexed_input - _tempMultiplexedFrame; + demultiplexAssign(_demultiplexedColorFrame, _demultiplexedTempBuffer); + + for(int i = 0; i < 3; i ++) + { + _spatiotemporalLPfilter(_demultiplexedTempBuffer_slices[i], _demultiplexedTempBuffer_slices[i]); + _demultiplexedColorFrame_slices[i] = _demultiplexedTempBuffer_slices[i] * _colorLocalDensity_slices[i] + _luminance; + } + } + // eliminate saturated colors by simple clipping values to the input range + clipRGBOutput_0_maxInputValue(_demultiplexedColorFrame, maxInputValue); + + if (_saturateColors) + { + ocl::normalizeGrayOutputCentredSigmoide(128, maxInputValue, _demultiplexedColorFrame, _demultiplexedColorFrame); + } +} +void RetinaColor::runColorMultiplexing(const oclMat &demultiplexedInputFrame, oclMat &multiplexedFrame) +{ + int elements_per_row = static_cast(multiplexedFrame.step / multiplexedFrame.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {multiplexedFrame.cols, multiplexedFrame.rows, 1}; + size_t localSize[] = {16, 16, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &demultiplexedInputFrame.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &multiplexedFrame.data)); + args.push_back(std::make_pair(sizeof(cl_int), &multiplexedFrame.cols)); + args.push_back(std::make_pair(sizeof(cl_int), &multiplexedFrame.rows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + openCLExecuteKernel(ctx, &retina_kernel, "runColorMultiplexingBayer", globalSize, localSize, args, -1, -1); +} + +void RetinaColor::clipRGBOutput_0_maxInputValue(oclMat &inputOutputBuffer, const float maxInputValue) +{ + // the kernel is equivalent to: + //ocl::threshold(inputOutputBuffer, inputOutputBuffer, maxInputValue, maxInputValue, THRESH_TRUNC); + //ocl::threshold(inputOutputBuffer, inputOutputBuffer, 0, 0, THRESH_TOZERO); + int elements_per_row = static_cast(inputOutputBuffer.step / inputOutputBuffer.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {_NBcols, inputOutputBuffer.rows, 1}; + size_t localSize[] = {16, 16, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &inputOutputBuffer.data)); + args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); + args.push_back(std::make_pair(sizeof(cl_int), &inputOutputBuffer.rows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + args.push_back(std::make_pair(sizeof(cl_float), &maxInputValue)); + openCLExecuteKernel(ctx, &retina_kernel, "clipRGBOutput_0_maxInputValue", globalSize, localSize, args, -1, -1); +} + +void RetinaColor::_adaptiveSpatialLPfilter(const oclMat &inputFrame, const oclMat &gradient, oclMat &outputFrame) +{ + /**********/ + _gain = (1 - 0.57f) * (1 - 0.57f) * (1 - 0.06f) * (1 - 0.06f); + + // launch the serie of 1D directional filters in order to compute the 2D low pass filter + // -> horizontal filters work with the first layer of imageGradient + _adaptiveHorizontalCausalFilter_addInput(inputFrame, gradient, outputFrame); + _horizontalAnticausalFilter_Irregular(outputFrame, gradient); + // -> horizontal filters work with the second layer of imageGradient + _verticalCausalFilter_Irregular(outputFrame, gradient(getROI(1))); + _adaptiveVerticalAnticausalFilter_multGain(gradient, outputFrame); +} + +void RetinaColor::_adaptiveHorizontalCausalFilter_addInput(const oclMat &inputFrame, const oclMat &gradient, oclMat &outputFrame) +{ + int elements_per_row = static_cast(inputFrame.step / inputFrame.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {_NBrows, 1, 1}; + size_t localSize[] = {256, 1, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &inputFrame.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &gradient.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); + args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); + args.push_back(std::make_pair(sizeof(cl_int), &_NBrows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + args.push_back(std::make_pair(sizeof(cl_int), &inputFrame.offset)); + args.push_back(std::make_pair(sizeof(cl_int), &gradient.offset)); + args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.offset)); + openCLExecuteKernel(ctx, &retina_kernel, "adaptiveHorizontalCausalFilter_addInput", globalSize, localSize, args, -1, -1); +} + +void RetinaColor::_adaptiveVerticalAnticausalFilter_multGain(const oclMat &gradient, oclMat &outputFrame) +{ + int elements_per_row = static_cast(outputFrame.step / outputFrame.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {_NBcols, 1, 1}; + size_t localSize[] = {256, 1, 1}; + + int gradOffset = gradient.offset + static_cast(gradient.step * _NBrows); + + args.push_back(std::make_pair(sizeof(cl_mem), &gradient.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); + args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); + args.push_back(std::make_pair(sizeof(cl_int), &_NBrows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + args.push_back(std::make_pair(sizeof(cl_int), &gradOffset)); + args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.offset)); + args.push_back(std::make_pair(sizeof(cl_float), &_gain)); + openCLExecuteKernel(ctx, &retina_kernel, "adaptiveVerticalAnticausalFilter_multGain", globalSize, localSize, args, -1, -1); +} +void RetinaColor::_computeGradient(const oclMat &luminance, oclMat &gradient) +{ + int elements_per_row = static_cast(luminance.step / luminance.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {_NBcols, _NBrows, 1}; + size_t localSize[] = {16, 16, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &luminance.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &gradient.data)); + args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); + args.push_back(std::make_pair(sizeof(cl_int), &_NBrows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + openCLExecuteKernel(ctx, &retina_kernel, "computeGradient", globalSize, localSize, args, -1, -1); +} + +/////////////////////////////////////// +//////////// RetinaFilter ///////////// +/////////////////////////////////////// +RetinaFilter::RetinaFilter(const unsigned int sizeRows, const unsigned int sizeColumns, const bool colorMode, const int samplingMethod, const bool useRetinaLogSampling, const double, const double) + : + _photoreceptorsPrefilter(sizeRows, sizeColumns, 4), + _ParvoRetinaFilter(sizeRows, sizeColumns), + _MagnoRetinaFilter(sizeRows, sizeColumns), + _colorEngine(sizeRows, sizeColumns, samplingMethod) +{ + CV_Assert(!useRetinaLogSampling); + + // set default processing activities + _useParvoOutput = true; + _useMagnoOutput = true; + + _useColorMode = colorMode; + + // set default parameters + setGlobalParameters(); + + // stability controls values init + _setInitPeriodCount(); + _globalTemporalConstant = 25; + + // reset all buffers + clearAllBuffers(); +} + +RetinaFilter::~RetinaFilter() +{ +} + +void RetinaFilter::clearAllBuffers() +{ + _photoreceptorsPrefilter.clearAllBuffers(); + _ParvoRetinaFilter.clearAllBuffers(); + _MagnoRetinaFilter.clearAllBuffers(); + _colorEngine.clearAllBuffers(); + // stability controls value init + _setInitPeriodCount(); +} + +void RetinaFilter::resize(const unsigned int NBrows, const unsigned int NBcolumns) +{ + unsigned int rows = NBrows, cols = NBcolumns; + + // resize optionnal member and adjust other modules size if required + _photoreceptorsPrefilter.resize(rows, cols); + _ParvoRetinaFilter.resize(rows, cols); + _MagnoRetinaFilter.resize(rows, cols); + _colorEngine.resize(rows, cols); + + // clean buffers + clearAllBuffers(); + +} + +void RetinaFilter::_setInitPeriodCount() +{ + // find out the maximum temporal constant value and apply a security factor + // false value (obviously too long) but appropriate for simple use + _globalTemporalConstant = (unsigned int)(_ParvoRetinaFilter.getPhotoreceptorsTemporalConstant() + _ParvoRetinaFilter.getHcellsTemporalConstant() + _MagnoRetinaFilter.getTemporalConstant()); + // reset frame counter + _ellapsedFramesSinceLastReset = 0; +} + +void RetinaFilter::setGlobalParameters(const float OPLspatialResponse1, const float OPLtemporalresponse1, const float OPLassymetryGain, const float OPLspatialResponse2, const float OPLtemporalresponse2, const float LPfilterSpatialResponse, const float LPfilterGain, const float LPfilterTemporalresponse, const float MovingContoursExtractorCoefficient, const bool normalizeParvoOutput_0_maxOutputValue, const bool normalizeMagnoOutput_0_maxOutputValue, const float maxOutputValue, const float maxInputValue, const float meanValue) +{ + _normalizeParvoOutput_0_maxOutputValue = normalizeParvoOutput_0_maxOutputValue; + _normalizeMagnoOutput_0_maxOutputValue = normalizeMagnoOutput_0_maxOutputValue; + _maxOutputValue = maxOutputValue; + _photoreceptorsPrefilter.setV0CompressionParameter(0.9f, maxInputValue, meanValue); + _photoreceptorsPrefilter.setLPfilterParameters(0, 0, 10, 3); // keeps low pass filter with low cut frequency in memory (usefull for the tone mapping function) + _ParvoRetinaFilter.setOPLandParvoFiltersParameters(0, OPLtemporalresponse1, OPLspatialResponse1, OPLassymetryGain, OPLtemporalresponse2, OPLspatialResponse2); + _ParvoRetinaFilter.setV0CompressionParameter(0.9f, maxInputValue, meanValue); + _MagnoRetinaFilter.setCoefficientsTable(LPfilterGain, LPfilterTemporalresponse, LPfilterSpatialResponse, MovingContoursExtractorCoefficient, 0, 2.0f * LPfilterSpatialResponse); + _MagnoRetinaFilter.setV0CompressionParameter(0.7f, maxInputValue, meanValue); + + // stability controls value init + _setInitPeriodCount(); +} + +bool RetinaFilter::checkInput(const oclMat &input, const bool) +{ + BasicRetinaFilter *inputTarget = &_photoreceptorsPrefilter; + + bool test = (input.rows == static_cast(inputTarget->getNBrows()) + || input.rows == static_cast(inputTarget->getNBrows()) * 3 + || input.rows == static_cast(inputTarget->getNBrows()) * 4) + && input.cols == static_cast(inputTarget->getNBcolumns()); + if (!test) + { + std::cerr << "RetinaFilter::checkInput: input buffer does not match retina buffer size, conversion aborted" << std::endl; + return false; + } + + return true; +} + +// main function that runs the filter for a given input frame +bool RetinaFilter::runFilter(const oclMat &imageInput, const bool useAdaptiveFiltering, const bool processRetinaParvoMagnoMapping, const bool useColorMode, const bool inputIsColorMultiplexed) +{ + // preliminary check + bool processSuccess = true; + if (!checkInput(imageInput, useColorMode)) + { + return false; + } + + // run the color multiplexing if needed and compute each suub filter of the retina: + // -> local adaptation + // -> contours OPL extraction + // -> moving contours extraction + + // stability controls value update + ++_ellapsedFramesSinceLastReset; + + _useColorMode = useColorMode; + + oclMat selectedPhotoreceptorsLocalAdaptationInput = imageInput; + oclMat selectedPhotoreceptorsColorInput = imageInput; + + //********** Following is input data specific photoreceptors processing + if (useColorMode && (!inputIsColorMultiplexed)) // not multiplexed color input case + { + _colorEngine.runColorMultiplexing(selectedPhotoreceptorsColorInput); + selectedPhotoreceptorsLocalAdaptationInput = _colorEngine.getMultiplexedFrame(); + } + //********** Following is generic Retina processing + + // photoreceptors local adaptation + _photoreceptorsPrefilter.runFilter_LocalAdapdation(selectedPhotoreceptorsLocalAdaptationInput, _ParvoRetinaFilter.getHorizontalCellsOutput()); + + // run parvo filter + _ParvoRetinaFilter.runFilter(_photoreceptorsPrefilter.getOutput(), _useParvoOutput); + + if (_useParvoOutput) + { + _ParvoRetinaFilter.normalizeGrayOutputCentredSigmoide(); // models the saturation of the cells, usefull for visualisation of the ON-OFF Parvo Output, Bipolar cells outputs do not change !!! + _ParvoRetinaFilter.centerReductImageLuminance(); // best for further spectrum analysis + + if (_normalizeParvoOutput_0_maxOutputValue) + { + _ParvoRetinaFilter.normalizeGrayOutput_0_maxOutputValue(_maxOutputValue); + } + } + + if (_useParvoOutput && _useMagnoOutput) + { + _MagnoRetinaFilter.runFilter(_ParvoRetinaFilter.getBipolarCellsON(), _ParvoRetinaFilter.getBipolarCellsOFF()); + if (_normalizeMagnoOutput_0_maxOutputValue) + { + _MagnoRetinaFilter.normalizeGrayOutput_0_maxOutputValue(_maxOutputValue); + } + _MagnoRetinaFilter.normalizeGrayOutputNearZeroCentreredSigmoide(); + } + + if (_useParvoOutput && _useMagnoOutput && processRetinaParvoMagnoMapping) + { + _processRetinaParvoMagnoMapping(); + if (_useColorMode) + { + _colorEngine.runColorDemultiplexing(_retinaParvoMagnoMappedFrame, useAdaptiveFiltering, _maxOutputValue); + } + return processSuccess; + } + + if (_useParvoOutput && _useColorMode) + { + _colorEngine.runColorDemultiplexing(_ParvoRetinaFilter.getOutput(), useAdaptiveFiltering, _maxOutputValue); + } + return processSuccess; +} + +const oclMat &RetinaFilter::getContours() +{ + if (_useColorMode) + { + return _colorEngine.getLuminance(); + } + else + { + return _ParvoRetinaFilter.getOutput(); + } +} +void RetinaFilter::_processRetinaParvoMagnoMapping() +{ + oclMat parvo = _ParvoRetinaFilter.getOutput(); + oclMat magno = _MagnoRetinaFilter.getOutput(); + + int halfRows = parvo.rows / 2; + int halfCols = parvo.cols / 2; + float minDistance = MIN(halfRows, halfCols) * 0.7f; + + int elements_per_row = static_cast(parvo.step / parvo.elemSize()); + + Context * ctx = Context::getContext(); + std::vector > args; + size_t globalSize[] = {parvo.cols, parvo.rows, 1}; + size_t localSize[] = {16, 16, 1}; + + args.push_back(std::make_pair(sizeof(cl_mem), &parvo.data)); + args.push_back(std::make_pair(sizeof(cl_mem), &magno.data)); + args.push_back(std::make_pair(sizeof(cl_int), &parvo.cols)); + args.push_back(std::make_pair(sizeof(cl_int), &parvo.rows)); + args.push_back(std::make_pair(sizeof(cl_int), &halfCols)); + args.push_back(std::make_pair(sizeof(cl_int), &halfRows)); + args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); + args.push_back(std::make_pair(sizeof(cl_float), &minDistance)); + openCLExecuteKernel(ctx, &retina_kernel, "processRetinaParvoMagnoMapping", globalSize, localSize, args, -1, -1); +} +} /* namespace ocl */ + +Ptr createRetina_OCL(Size getInputSize){ return makePtr(getInputSize); } +Ptr createRetina_OCL(Size getInputSize, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght) +{ + return makePtr(getInputSize, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght); +} + +} /* namespace bioinspired */ +} /* namespace cv */ + +#endif /* #ifdef HAVE_OPENCV_OCL */ diff --git a/modules/bioinspired/src/retina_ocl.hpp b/modules/bioinspired/src/retina_ocl.hpp new file mode 100644 index 0000000000..90df0601c4 --- /dev/null +++ b/modules/bioinspired/src/retina_ocl.hpp @@ -0,0 +1,634 @@ +/*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) 2010-2013, Multicoreware, Inc., all rights reserved. +// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// @Authors +// Peng Xiao, pengxiao@multicorewareinc.com +// +// 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 oclMaterials 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 __OCL_RETINA_HPP__ +#define __OCL_RETINA_HPP__ + +#include "precomp.hpp" + +#ifdef HAVE_OPENCV_OCL + +// please refer to c++ headers for API comments +namespace cv +{ +namespace bioinspired +{ +namespace ocl +{ +void normalizeGrayOutputCentredSigmoide(const float meanValue, const float sensitivity, cv::ocl::oclMat &in, cv::ocl::oclMat &out, const float maxValue = 255.f); +void normalizeGrayOutput_0_maxOutputValue(cv::ocl::oclMat &inputOutputBuffer, const float maxOutputValue = 255.0); +void normalizeGrayOutputNearZeroCentreredSigmoide(cv::ocl::oclMat &inputPicture, cv::ocl::oclMat &outputBuffer, const float sensitivity = 40, const float maxOutputValue = 255.0f); +void centerReductImageLuminance(cv::ocl::oclMat &inputOutputBuffer); + +class BasicRetinaFilter +{ +public: + BasicRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns, const unsigned int parametersListSize = 1, const bool useProgressiveFilter = false); + ~BasicRetinaFilter(); + inline void clearOutputBuffer() + { + _filterOutput = 0; + }; + inline void clearSecondaryBuffer() + { + _localBuffer = 0; + }; + inline void clearAllBuffers() + { + clearOutputBuffer(); + clearSecondaryBuffer(); + }; + void resize(const unsigned int NBrows, const unsigned int NBcolumns); + const cv::ocl::oclMat &runFilter_LPfilter(const cv::ocl::oclMat &inputFrame, const unsigned int filterIndex = 0); + void runFilter_LPfilter(const cv::ocl::oclMat &inputFrame, cv::ocl::oclMat &outputFrame, const unsigned int filterIndex = 0); + void runFilter_LPfilter_Autonomous(cv::ocl::oclMat &inputOutputFrame, const unsigned int filterIndex = 0); + const cv::ocl::oclMat &runFilter_LocalAdapdation(const cv::ocl::oclMat &inputOutputFrame, const cv::ocl::oclMat &localLuminance); + void runFilter_LocalAdapdation(const cv::ocl::oclMat &inputFrame, const cv::ocl::oclMat &localLuminance, cv::ocl::oclMat &outputFrame); + const cv::ocl::oclMat &runFilter_LocalAdapdation_autonomous(const cv::ocl::oclMat &inputFrame); + void runFilter_LocalAdapdation_autonomous(const cv::ocl::oclMat &inputFrame, cv::ocl::oclMat &outputFrame); + void setLPfilterParameters(const float beta, const float tau, const float k, const unsigned int filterIndex = 0); + inline void setV0CompressionParameter(const float v0, const float maxInputValue, const float) + { + _v0 = v0 * maxInputValue; + _localLuminanceFactor = v0; + _localLuminanceAddon = maxInputValue * (1.0f - v0); + _maxInputValue = maxInputValue; + }; + inline void setV0CompressionParameter(const float v0, const float meanLuminance) + { + this->setV0CompressionParameter(v0, _maxInputValue, meanLuminance); + }; + inline void setV0CompressionParameter(const float v0) + { + _v0 = v0 * _maxInputValue; + _localLuminanceFactor = v0; + _localLuminanceAddon = _maxInputValue * (1.0f - v0); + }; + inline void setV0CompressionParameterToneMapping(const float v0, const float maxInputValue, const float meanLuminance = 128.0f) + { + _v0 = v0 * maxInputValue; + _localLuminanceFactor = 1.0f; + _localLuminanceAddon = meanLuminance * _v0; + _maxInputValue = maxInputValue; + }; + inline void updateCompressionParameter(const float meanLuminance) + { + _localLuminanceFactor = 1; + _localLuminanceAddon = meanLuminance * _v0; + }; + inline float getV0CompressionParameter() + { + return _v0 / _maxInputValue; + }; + inline const cv::ocl::oclMat &getOutput() const + { + return _filterOutput; + }; + inline unsigned int getNBrows() + { + return _filterOutput.rows; + }; + inline unsigned int getNBcolumns() + { + return _filterOutput.cols; + }; + inline unsigned int getNBpixels() + { + return _filterOutput.size().area(); + }; + inline void normalizeGrayOutput_0_maxOutputValue(const float maxValue) + { + ocl::normalizeGrayOutput_0_maxOutputValue(_filterOutput, maxValue); + }; + inline void normalizeGrayOutputCentredSigmoide() + { + ocl::normalizeGrayOutputCentredSigmoide(0.0, 2.0, _filterOutput, _filterOutput); + }; + inline void centerReductImageLuminance() + { + ocl::centerReductImageLuminance(_filterOutput); + }; + inline float getMaxInputValue() + { + return this->_maxInputValue; + }; + inline void setMaxInputValue(const float newMaxInputValue) + { + this->_maxInputValue = newMaxInputValue; + }; + +protected: + + int _NBrows; + int _NBcols; + unsigned int _halfNBrows; + unsigned int _halfNBcolumns; + + cv::ocl::oclMat _filterOutput; + cv::ocl::oclMat _localBuffer; + + std::valarray _filteringCoeficientsTable; + float _v0; + float _maxInputValue; + float _meanInputValue; + float _localLuminanceFactor; + float _localLuminanceAddon; + + float _a; + float _tau; + float _gain; + + void _spatiotemporalLPfilter(const cv::ocl::oclMat &inputFrame, cv::ocl::oclMat &LPfilterOutput, const unsigned int coefTableOffset = 0); + float _squaringSpatiotemporalLPfilter(const cv::ocl::oclMat &inputFrame, cv::ocl::oclMat &outputFrame, const unsigned int filterIndex = 0); + void _spatiotemporalLPfilter_Irregular(const cv::ocl::oclMat &inputFrame, cv::ocl::oclMat &outputFrame, const unsigned int filterIndex = 0); + void _localSquaringSpatioTemporalLPfilter(const cv::ocl::oclMat &inputFrame, cv::ocl::oclMat &LPfilterOutput, const unsigned int *integrationAreas, const unsigned int filterIndex = 0); + void _localLuminanceAdaptation(const cv::ocl::oclMat &inputFrame, const cv::ocl::oclMat &localLuminance, cv::ocl::oclMat &outputFrame, const bool updateLuminanceMean = true); + void _localLuminanceAdaptation(cv::ocl::oclMat &inputOutputFrame, const cv::ocl::oclMat &localLuminance); + void _localLuminanceAdaptationPosNegValues(const cv::ocl::oclMat &inputFrame, const cv::ocl::oclMat &localLuminance, float *outputFrame); + void _horizontalCausalFilter_addInput(const cv::ocl::oclMat &inputFrame, cv::ocl::oclMat &outputFrame); + void _horizontalAnticausalFilter(cv::ocl::oclMat &outputFrame); + void _verticalCausalFilter(cv::ocl::oclMat &outputFrame); + void _horizontalAnticausalFilter_Irregular(cv::ocl::oclMat &outputFrame, const cv::ocl::oclMat &spatialConstantBuffer); + void _verticalCausalFilter_Irregular(cv::ocl::oclMat &outputFrame, const cv::ocl::oclMat &spatialConstantBuffer); + void _verticalAnticausalFilter_multGain(cv::ocl::oclMat &outputFrame); +}; + +class MagnoRetinaFilter: public BasicRetinaFilter +{ +public: + MagnoRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns); + virtual ~MagnoRetinaFilter(); + void clearAllBuffers(); + void resize(const unsigned int NBrows, const unsigned int NBcolumns); + void setCoefficientsTable(const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float localAdaptIntegration_tau, const float localAdaptIntegration_k); + + const cv::ocl::oclMat &runFilter(const cv::ocl::oclMat &OPL_ON, const cv::ocl::oclMat &OPL_OFF); + + inline const cv::ocl::oclMat &getMagnoON() const + { + return _magnoXOutputON; + }; + inline const cv::ocl::oclMat &getMagnoOFF() const + { + return _magnoXOutputOFF; + }; + inline const cv::ocl::oclMat &getMagnoYsaturated() const + { + return _magnoYsaturated; + }; + inline void normalizeGrayOutputNearZeroCentreredSigmoide() + { + ocl::normalizeGrayOutputNearZeroCentreredSigmoide(_magnoYOutput, _magnoYsaturated); + }; + inline float getTemporalConstant() + { + return this->_filteringCoeficientsTable[2]; + }; +private: + cv::ocl::oclMat _previousInput_ON; + cv::ocl::oclMat _previousInput_OFF; + cv::ocl::oclMat _amacrinCellsTempOutput_ON; + cv::ocl::oclMat _amacrinCellsTempOutput_OFF; + cv::ocl::oclMat _magnoXOutputON; + cv::ocl::oclMat _magnoXOutputOFF; + cv::ocl::oclMat _localProcessBufferON; + cv::ocl::oclMat _localProcessBufferOFF; + cv::ocl::oclMat _magnoYOutput; + cv::ocl::oclMat _magnoYsaturated; + + float _temporalCoefficient; + void _amacrineCellsComputing(const cv::ocl::oclMat &OPL_ON, const cv::ocl::oclMat &OPL_OFF); +}; + +class ParvoRetinaFilter: public BasicRetinaFilter +{ +public: + ParvoRetinaFilter(const unsigned int NBrows = 480, const unsigned int NBcolumns = 640); + virtual ~ParvoRetinaFilter(); + void resize(const unsigned int NBrows, const unsigned int NBcolumns); + void clearAllBuffers(); + void setOPLandParvoFiltersParameters(const float beta1, const float tau1, const float k1, const float beta2, const float tau2, const float k2); + + inline void setGanglionCellsLocalAdaptationLPfilterParameters(const float tau, const float k) + { + BasicRetinaFilter::setLPfilterParameters(0, tau, k, 2); + }; + const cv::ocl::oclMat &runFilter(const cv::ocl::oclMat &inputFrame, const bool useParvoOutput = true); + + inline const cv::ocl::oclMat &getPhotoreceptorsLPfilteringOutput() const + { + return _photoreceptorsOutput; + }; + + inline const cv::ocl::oclMat &getHorizontalCellsOutput() const + { + return _horizontalCellsOutput; + }; + + inline const cv::ocl::oclMat &getParvoON() const + { + return _parvocellularOutputON; + }; + + inline const cv::ocl::oclMat &getParvoOFF() const + { + return _parvocellularOutputOFF; + }; + + inline const cv::ocl::oclMat &getBipolarCellsON() const + { + return _bipolarCellsOutputON; + }; + + inline const cv::ocl::oclMat &getBipolarCellsOFF() const + { + return _bipolarCellsOutputOFF; + }; + + inline float getPhotoreceptorsTemporalConstant() + { + return this->_filteringCoeficientsTable[2]; + }; + + inline float getHcellsTemporalConstant() + { + return this->_filteringCoeficientsTable[5]; + }; +private: + cv::ocl::oclMat _photoreceptorsOutput; + cv::ocl::oclMat _horizontalCellsOutput; + cv::ocl::oclMat _parvocellularOutputON; + cv::ocl::oclMat _parvocellularOutputOFF; + cv::ocl::oclMat _bipolarCellsOutputON; + cv::ocl::oclMat _bipolarCellsOutputOFF; + cv::ocl::oclMat _localAdaptationOFF; + cv::ocl::oclMat _localAdaptationON; + cv::ocl::oclMat _parvocellularOutputONminusOFF; + void _OPL_OnOffWaysComputing(); +}; +class RetinaColor: public BasicRetinaFilter +{ +public: + RetinaColor(const unsigned int NBrows, const unsigned int NBcolumns, const int samplingMethod = RETINA_COLOR_DIAGONAL); + virtual ~RetinaColor(); + + void clearAllBuffers(); + void resize(const unsigned int NBrows, const unsigned int NBcolumns); + inline void runColorMultiplexing(const cv::ocl::oclMat &inputRGBFrame) + { + runColorMultiplexing(inputRGBFrame, _multiplexedFrame); + }; + void runColorMultiplexing(const cv::ocl::oclMat &demultiplexedInputFrame, cv::ocl::oclMat &multiplexedFrame); + void runColorDemultiplexing(const cv::ocl::oclMat &multiplexedColorFrame, const bool adaptiveFiltering = false, const float maxInputValue = 255.0); + + void setColorSaturation(const bool saturateColors = true, const float colorSaturationValue = 4.0) + { + _saturateColors = saturateColors; + _colorSaturationValue = colorSaturationValue; + }; + + void setChrominanceLPfilterParameters(const float beta, const float tau, const float k) + { + setLPfilterParameters(beta, tau, k); + }; + + bool applyKrauskopfLMS2Acr1cr2Transform(cv::ocl::oclMat &result); + bool applyLMS2LabTransform(cv::ocl::oclMat &result); + inline const cv::ocl::oclMat &getMultiplexedFrame() const + { + return _multiplexedFrame; + }; + + inline const cv::ocl::oclMat &getDemultiplexedColorFrame() const + { + return _demultiplexedColorFrame; + }; + + inline const cv::ocl::oclMat &getLuminance() const + { + return _luminance; + }; + inline const cv::ocl::oclMat &getChrominance() const + { + return _chrominance; + }; + void clipRGBOutput_0_maxInputValue(cv::ocl::oclMat &inputOutputBuffer, const float maxOutputValue = 255.0); + void normalizeRGBOutput_0_maxOutputValue(const float maxOutputValue = 255.0); + inline void setDemultiplexedColorFrame(const cv::ocl::oclMat &demultiplexedImage) + { + _demultiplexedColorFrame = demultiplexedImage; + }; +protected: + inline unsigned int bayerSampleOffset(unsigned int index) + { + return index + ((index / getNBcolumns()) % 2) * getNBpixels() + ((index % getNBcolumns()) % 2) * getNBpixels(); + } + inline Rect getROI(int idx) + { + return Rect(0, idx * _NBrows, _NBcols, _NBrows); + } + int _samplingMethod; + bool _saturateColors; + float _colorSaturationValue; + cv::ocl::oclMat _luminance; + cv::ocl::oclMat _multiplexedFrame; + cv::ocl::oclMat _RGBmosaic; + cv::ocl::oclMat _tempMultiplexedFrame; + cv::ocl::oclMat _demultiplexedTempBuffer; + cv::ocl::oclMat _demultiplexedColorFrame; + cv::ocl::oclMat _chrominance; + cv::ocl::oclMat _colorLocalDensity; + cv::ocl::oclMat _imageGradient; + + float _pR, _pG, _pB; + bool _objectInit; + + void _initColorSampling(); + void _adaptiveSpatialLPfilter(const cv::ocl::oclMat &inputFrame, const cv::ocl::oclMat &gradient, cv::ocl::oclMat &outputFrame); + void _adaptiveHorizontalCausalFilter_addInput(const cv::ocl::oclMat &inputFrame, const cv::ocl::oclMat &gradient, cv::ocl::oclMat &outputFrame); + void _adaptiveVerticalAnticausalFilter_multGain(const cv::ocl::oclMat &gradient, cv::ocl::oclMat &outputFrame); + void _computeGradient(const cv::ocl::oclMat &luminance, cv::ocl::oclMat &gradient); + void _normalizeOutputs_0_maxOutputValue(void); + void _applyImageColorSpaceConversion(const cv::ocl::oclMat &inputFrame, cv::ocl::oclMat &outputFrame, const float *transformTable); +}; +class RetinaFilter +{ +public: + RetinaFilter(const unsigned int sizeRows, const unsigned int sizeColumns, const bool colorMode = false, const int samplingMethod = RETINA_COLOR_BAYER, const bool useRetinaLogSampling = false, const double reductionFactor = 1.0, const double samplingStrenght = 10.0); + ~RetinaFilter(); + + void clearAllBuffers(); + void resize(const unsigned int NBrows, const unsigned int NBcolumns); + bool checkInput(const cv::ocl::oclMat &input, const bool colorMode); + bool runFilter(const cv::ocl::oclMat &imageInput, const bool useAdaptiveFiltering = true, const bool processRetinaParvoMagnoMapping = false, const bool useColorMode = false, const bool inputIsColorMultiplexed = false); + + void setGlobalParameters(const float OPLspatialResponse1 = 0.7, const float OPLtemporalresponse1 = 1, const float OPLassymetryGain = 0, const float OPLspatialResponse2 = 5, const float OPLtemporalresponse2 = 1, const float LPfilterSpatialResponse = 5, const float LPfilterGain = 0, const float LPfilterTemporalresponse = 0, const float MovingContoursExtractorCoefficient = 5, const bool normalizeParvoOutput_0_maxOutputValue = false, const bool normalizeMagnoOutput_0_maxOutputValue = false, const float maxOutputValue = 255.0, const float maxInputValue = 255.0, const float meanValue = 128.0); + + inline void setPhotoreceptorsLocalAdaptationSensitivity(const float V0CompressionParameter) + { + _photoreceptorsPrefilter.setV0CompressionParameter(1 - V0CompressionParameter); + _setInitPeriodCount(); + }; + + inline void setParvoGanglionCellsLocalAdaptationSensitivity(const float V0CompressionParameter) + { + _ParvoRetinaFilter.setV0CompressionParameter(V0CompressionParameter); + _setInitPeriodCount(); + }; + + inline void setGanglionCellsLocalAdaptationLPfilterParameters(const float spatialResponse, const float temporalResponse) + { + _ParvoRetinaFilter.setGanglionCellsLocalAdaptationLPfilterParameters(temporalResponse, spatialResponse); + _setInitPeriodCount(); + }; + + inline void setMagnoGanglionCellsLocalAdaptationSensitivity(const float V0CompressionParameter) + { + _MagnoRetinaFilter.setV0CompressionParameter(V0CompressionParameter); + _setInitPeriodCount(); + }; + + void setOPLandParvoParameters(const float beta1, const float tau1, const float k1, const float beta2, const float tau2, const float k2, const float V0CompressionParameter) + { + _ParvoRetinaFilter.setOPLandParvoFiltersParameters(beta1, tau1, k1, beta2, tau2, k2); + _ParvoRetinaFilter.setV0CompressionParameter(V0CompressionParameter); + _setInitPeriodCount(); + }; + + void setMagnoCoefficientsTable(const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float V0CompressionParameter, const float localAdaptintegration_tau, const float localAdaptintegration_k) + { + _MagnoRetinaFilter.setCoefficientsTable(parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, localAdaptintegration_tau, localAdaptintegration_k); + _MagnoRetinaFilter.setV0CompressionParameter(V0CompressionParameter); + _setInitPeriodCount(); + }; + + inline void activateNormalizeParvoOutput_0_maxOutputValue(const bool normalizeParvoOutput_0_maxOutputValue) + { + _normalizeParvoOutput_0_maxOutputValue = normalizeParvoOutput_0_maxOutputValue; + }; + + inline void activateNormalizeMagnoOutput_0_maxOutputValue(const bool normalizeMagnoOutput_0_maxOutputValue) + { + _normalizeMagnoOutput_0_maxOutputValue = normalizeMagnoOutput_0_maxOutputValue; + }; + + inline void setMaxOutputValue(const float maxOutputValue) + { + _maxOutputValue = maxOutputValue; + }; + + void setColorMode(const bool desiredColorMode) + { + _useColorMode = desiredColorMode; + }; + inline void setColorSaturation(const bool saturateColors = true, const float colorSaturationValue = 4.0) + { + _colorEngine.setColorSaturation(saturateColors, colorSaturationValue); + }; + inline const cv::ocl::oclMat &getLocalAdaptation() const + { + return _photoreceptorsPrefilter.getOutput(); + }; + inline const cv::ocl::oclMat &getPhotoreceptors() const + { + return _ParvoRetinaFilter.getPhotoreceptorsLPfilteringOutput(); + }; + + inline const cv::ocl::oclMat &getHorizontalCells() const + { + return _ParvoRetinaFilter.getHorizontalCellsOutput(); + }; + inline bool areContoursProcessed() + { + return _useParvoOutput; + }; + bool getParvoFoveaResponse(cv::ocl::oclMat &parvoFovealResponse); + inline void activateContoursProcessing(const bool useParvoOutput) + { + _useParvoOutput = useParvoOutput; + }; + + const cv::ocl::oclMat &getContours(); + + inline const cv::ocl::oclMat &getContoursON() const + { + return _ParvoRetinaFilter.getParvoON(); + }; + + inline const cv::ocl::oclMat &getContoursOFF() const + { + return _ParvoRetinaFilter.getParvoOFF(); + }; + + inline bool areMovingContoursProcessed() + { + return _useMagnoOutput; + }; + + inline void activateMovingContoursProcessing(const bool useMagnoOutput) + { + _useMagnoOutput = useMagnoOutput; + }; + + inline const cv::ocl::oclMat &getMovingContours() const + { + return _MagnoRetinaFilter.getOutput(); + }; + + inline const cv::ocl::oclMat &getMovingContoursSaturated() const + { + return _MagnoRetinaFilter.getMagnoYsaturated(); + }; + + inline const cv::ocl::oclMat &getMovingContoursON() const + { + return _MagnoRetinaFilter.getMagnoON(); + }; + + inline const cv::ocl::oclMat &getMovingContoursOFF() const + { + return _MagnoRetinaFilter.getMagnoOFF(); + }; + + inline const cv::ocl::oclMat &getRetinaParvoMagnoMappedOutput() const + { + return _retinaParvoMagnoMappedFrame; + }; + + inline const cv::ocl::oclMat &getParvoContoursChannel() const + { + return _colorEngine.getLuminance(); + }; + + inline const cv::ocl::oclMat &getParvoChrominance() const + { + return _colorEngine.getChrominance(); + }; + inline const cv::ocl::oclMat &getColorOutput() const + { + return _colorEngine.getDemultiplexedColorFrame(); + }; + + inline bool isColorMode() + { + return _useColorMode; + }; + bool getColorMode() + { + return _useColorMode; + }; + + inline bool isInitTransitionDone() + { + if (_ellapsedFramesSinceLastReset < _globalTemporalConstant) + { + return false; + } + return true; + }; + inline float getRetinaSamplingBackProjection(const float projectedRadiusLength) + { + return projectedRadiusLength; + }; + + inline unsigned int getInputNBrows() + { + return _photoreceptorsPrefilter.getNBrows(); + }; + + inline unsigned int getInputNBcolumns() + { + return _photoreceptorsPrefilter.getNBcolumns(); + }; + + inline unsigned int getInputNBpixels() + { + return _photoreceptorsPrefilter.getNBpixels(); + }; + + inline unsigned int getOutputNBrows() + { + return _photoreceptorsPrefilter.getNBrows(); + }; + + inline unsigned int getOutputNBcolumns() + { + return _photoreceptorsPrefilter.getNBcolumns(); + }; + + inline unsigned int getOutputNBpixels() + { + return _photoreceptorsPrefilter.getNBpixels(); + }; +private: + bool _useParvoOutput; + bool _useMagnoOutput; + + unsigned int _ellapsedFramesSinceLastReset; + unsigned int _globalTemporalConstant; + + cv::ocl::oclMat _retinaParvoMagnoMappedFrame; + BasicRetinaFilter _photoreceptorsPrefilter; + ParvoRetinaFilter _ParvoRetinaFilter; + MagnoRetinaFilter _MagnoRetinaFilter; + RetinaColor _colorEngine; + + bool _useMinimalMemoryForToneMappingONLY; + bool _normalizeParvoOutput_0_maxOutputValue; + bool _normalizeMagnoOutput_0_maxOutputValue; + float _maxOutputValue; + bool _useColorMode; + + void _setInitPeriodCount(); + void _processRetinaParvoMagnoMapping(); + void _runGrayToneMapping(const cv::ocl::oclMat &grayImageInput, cv::ocl::oclMat &grayImageOutput , const float PhotoreceptorsCompression = 0.6, const float ganglionCellsCompression = 0.6); +}; + +} /* namespace ocl */ +} /* namespace bioinspired */ +} /* namespace cv */ + +#endif /* HAVE_OPENCV_OCL */ +#endif /* __OCL_RETINA_HPP__ */ diff --git a/modules/contrib/src/retinacolor.cpp b/modules/bioinspired/src/retinacolor.cpp similarity index 97% rename from modules/contrib/src/retinacolor.cpp rename to modules/bioinspired/src/retinacolor.cpp index d138582ce4..3fbc553852 100644 --- a/modules/contrib/src/retinacolor.cpp +++ b/modules/bioinspired/src/retinacolor.cpp @@ -6,7 +6,7 @@ ** copy or use the software. ** ** -** HVStools : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. +** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. ** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. ** ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) @@ -32,7 +32,7 @@ ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. ** -** For Human Visual System tools (hvstools) +** For Human Visual System tools (bioinspired) ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved. ** ** Third party copyrights are property of their respective owners. @@ -73,14 +73,15 @@ namespace cv { - +namespace bioinspired +{ // init static values static float _LMStoACr1Cr2[]={1.0, 1.0, 0.0, 1.0, -1.0, 0.0, -0.5, -0.5, 1.0}; //static double _ACr1Cr2toLMS[]={0.5, 0.5, 0.0, 0.5, -0.5, 0.0, 0.5, 0.0, 1.0}; static float _LMStoLab[]={0.5774f, 0.5774f, 0.5774f, 0.4082f, 0.4082f, -0.8165f, 0.7071f, -0.7071f, 0.f}; // constructor/desctructor -RetinaColor::RetinaColor(const unsigned int NBrows, const unsigned int NBcolumns, const RETINA_COLORSAMPLINGMETHOD samplingMethod) +RetinaColor::RetinaColor(const unsigned int NBrows, const unsigned int NBcolumns, const int samplingMethod) :BasicRetinaFilter(NBrows, NBcolumns, 3), _colorSampling(NBrows*NBcolumns), _RGBmosaic(NBrows*NBcolumns*3), @@ -338,8 +339,11 @@ void RetinaColor::runColorDemultiplexing(const std::valarray &multiplexed } // compute the gradient of the luminance +#ifdef MAKE_PARALLEL // call the TemplateBuffer TBB clipping method + cv::parallel_for_(cv::Range(2,_filterOutput.getNBrows()-2), Parallel_computeGradient(_filterOutput.getNBcolumns(), _filterOutput.getNBrows(), &(*_luminance)[0], &_imageGradient[0])); +#else _computeGradient(&(*_luminance)[0]); - +#endif // adaptively filter the submosaics to get the adaptive densities, here the buffer _chrominance is used as a temp buffer _adaptiveSpatialLPfilter(&_RGBmosaic[0], &_chrominance[0]); _adaptiveSpatialLPfilter(&_RGBmosaic[0]+_filterOutput.getNBpixels(), &_chrominance[0]+_filterOutput.getNBpixels()); @@ -717,4 +721,5 @@ void RetinaColor::_applyImageColorSpaceConversion(const std::valarray &in } } -} +}// end of namespace bioinspired +}// end of namespace cv diff --git a/modules/contrib/src/retinacolor.hpp b/modules/bioinspired/src/retinacolor.hpp similarity index 86% rename from modules/contrib/src/retinacolor.hpp rename to modules/bioinspired/src/retinacolor.hpp index 056d006e4b..3fb6be8f9e 100644 --- a/modules/contrib/src/retinacolor.hpp +++ b/modules/bioinspired/src/retinacolor.hpp @@ -6,7 +6,7 @@ ** copy or use the software. ** ** -** HVStools : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. +** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. ** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. ** ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) @@ -32,7 +32,7 @@ ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. ** -** For Human Visual System tools (hvstools) +** For Human Visual System tools (bioinspired) ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved. ** ** Third party copyrights are property of their respective owners. @@ -85,7 +85,8 @@ namespace cv { - +namespace bioinspired +{ class RetinaColor: public BasicRetinaFilter { public: @@ -99,7 +100,7 @@ namespace cv * @param NBcolumns: number of columns of the input image * @param samplingMethod: the chosen color sampling method */ - RetinaColor(const unsigned int NBrows, const unsigned int NBcolumns, const RETINA_COLORSAMPLINGMETHOD samplingMethod=RETINA_COLOR_DIAGONAL); + RetinaColor(const unsigned int NBrows, const unsigned int NBcolumns, const int samplingMethod=RETINA_COLOR_BAYER); /** * standard destructor @@ -219,7 +220,7 @@ namespace cv protected: // private functions - RETINA_COLORSAMPLINGMETHOD _samplingMethod; + int _samplingMethod; bool _saturateColors; float _colorSaturationValue; // links to parent buffers (more convienient names @@ -333,10 +334,56 @@ namespace cv } } }; + + class Parallel_computeGradient: public cv::ParallelLoopBody + { + private: + float *imageGradient; + const float *luminance; + unsigned int nbColumns, doubleNbColumns, nbRows, nbPixels; + public: + Parallel_computeGradient(const unsigned int nbCols, const unsigned int nbRws, const float *lum, float *imageGrad) + :imageGradient(imageGrad), luminance(lum), nbColumns(nbCols), doubleNbColumns(2*nbCols), nbRows(nbRws), nbPixels(nbRws*nbCols){}; + + virtual void operator()( const Range& r ) const { + for (int idLine=r.start;idLine!=r.end;++idLine) + { + for (unsigned int idColumn=2;idColumn Meylan L., Alleysson D., and Susstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816 + ** + ** + ** License Agreement + ** For Open Source Computer Vision Library + ** + ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. + ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. + ** + ** For Human Visual System tools (bioinspired) + ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: + ** + ** * Redistributions of source code must retain the above copyright notice, + ** this list of conditions and the following disclaimer. + ** + ** * Redistributions 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. + *******************************************************************************/ + +/* + * retinafasttonemapping.cpp + * + * Created on: May 26, 2013 + * Author: Alexandre Benoit + */ + +#include "precomp.hpp" +#include "basicretinafilter.hpp" +#include "retinacolor.hpp" +#include +#include +#include + +namespace cv +{ +namespace bioinspired +{ +/** + * @class RetinaFastToneMappingImpl a wrapper class which allows the tone mapping algorithm of Meylan&al(2007) to be used with OpenCV. + * This algorithm is already implemented in thre Retina class (retina::applyFastToneMapping) but used it does not require all the retina model to be allocated. This allows a light memory use for low memory devices (smartphones, etc. + * As a summary, these are the model properties: + * => 2 stages of local luminance adaptation with a different local neighborhood for each. + * => first stage models the retina photorecetors local luminance adaptation + * => second stage models th ganglion cells local information adaptation + * => compared to the initial publication, this class uses spatio-temporal low pass filters instead of spatial only filters. + * ====> this can help noise robustness and temporal stability for video sequence use cases. + * for more information, read to the following papers : + * Meylan L., Alleysson D., and Susstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 + * regarding spatio-temporal filter and the bigger retina model : + * Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. + */ + +class RetinaFastToneMappingImpl : public RetinaFastToneMapping +{ +public: + /** + * constructor + * @param imageInput: the size of the images to process + */ + RetinaFastToneMappingImpl(Size imageInput) + { + unsigned int nbPixels=imageInput.height*imageInput.width; + + // basic error check + if (nbPixels <= 0) + throw cv::Exception(-1, "Bad retina size setup : size height and with must be superior to zero", "RetinaImpl::setup", "retinafasttonemapping.cpp", 0); + + // resize buffers + _inputBuffer.resize(nbPixels*3); // buffer supports gray images but also 3 channels color buffers... (larger is better...) + _imageOutput.resize(nbPixels*3); + _temp2.resize(nbPixels); + // allocate the main filter with 2 setup sets properties (one for each low pass filter + _multiuseFilter = makePtr(imageInput.height, imageInput.width, 2); + // allocate the color manager (multiplexer/demultiplexer + _colorEngine = makePtr(imageInput.height, imageInput.width); + // setup filter behaviors with default values + setup(); + } + + /** + * basic destructor + */ + virtual ~RetinaFastToneMappingImpl(){}; + + /** + * method that applies a luminance correction (initially High Dynamic Range (HDR) tone mapping) using only the 2 local adaptation stages of the retina parvocellular channel : photoreceptors level and ganlion cells level. Spatio temporal filtering is applied but limited to temporal smoothing and eventually high frequencies attenuation. This is a lighter method than the one available using the regular retina::run method. It is then faster but it does not include complete temporal filtering nor retina spectral whitening. Then, it can have a more limited effect on images with a very high dynamic range. This is an adptation of the original still image HDR tone mapping algorithm of David Alleyson, Sabine Susstruck and Laurence Meylan's work, please cite: + * -> Meylan L., Alleysson D., and Susstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816 + @param inputImage the input image to process RGB or gray levels + @param outputToneMappedImage the output tone mapped image + */ + virtual void applyFastToneMapping(InputArray inputImage, OutputArray outputToneMappedImage) + { + // first convert input image to the compatible format : + const bool colorMode = _convertCvMat2ValarrayBuffer(inputImage.getMat(), _inputBuffer); + + // process tone mapping + if (colorMode) + { + _runRGBToneMapping(_inputBuffer, _imageOutput, true); + _convertValarrayBuffer2cvMat(_imageOutput, _multiuseFilter->getNBrows(), _multiuseFilter->getNBcolumns(), true, outputToneMappedImage); + }else + { + _runGrayToneMapping(_inputBuffer, _imageOutput); + _convertValarrayBuffer2cvMat(_imageOutput, _multiuseFilter->getNBrows(), _multiuseFilter->getNBcolumns(), false, outputToneMappedImage); + } + + } + + /** + * setup method that updates tone mapping behaviors by adjusing the local luminance computation area + * @param photoreceptorsNeighborhoodRadius the first stage local adaptation area + * @param ganglioncellsNeighborhoodRadius the second stage local adaptation area + * @param meanLuminanceModulatorK the factor applied to modulate the meanLuminance information (default is 1, see reference paper) + */ + virtual void setup(const float photoreceptorsNeighborhoodRadius=3.f, const float ganglioncellsNeighborhoodRadius=1.f, const float meanLuminanceModulatorK=1.f) + { + // setup the spatio-temporal properties of each filter + _meanLuminanceModulatorK = meanLuminanceModulatorK; + _multiuseFilter->setV0CompressionParameter(1.f, 255.f, 128.f); + _multiuseFilter->setLPfilterParameters(0.f, 0.f, photoreceptorsNeighborhoodRadius, 1); + _multiuseFilter->setLPfilterParameters(0.f, 0.f, ganglioncellsNeighborhoodRadius, 2); + } + +private: + // a filter able to perform local adaptation and low pass spatio-temporal filtering + cv::Ptr _multiuseFilter; + cv::Ptr _colorEngine; + + //!< buffer used to convert input cv::Mat to internal retina buffers format (valarrays) + std::valarray _inputBuffer; + std::valarray _imageOutput; + std::valarray _temp2; + float _meanLuminanceModulatorK; + + +void _convertValarrayBuffer2cvMat(const std::valarray &grayMatrixToConvert, const unsigned int nbRows, const unsigned int nbColumns, const bool colorMode, OutputArray outBuffer) +{ + // fill output buffer with the valarray buffer + const float *valarrayPTR=get_data(grayMatrixToConvert); + if (!colorMode) + { + outBuffer.create(cv::Size(nbColumns, nbRows), CV_8U); + Mat outMat = outBuffer.getMat(); + for (unsigned int i=0;i(pixel)=(unsigned char)*(valarrayPTR++); + } + } + }else + { + const unsigned int nbPixels=nbColumns*nbRows; + const unsigned int doubleNBpixels=nbColumns*nbRows*2; + outBuffer.create(cv::Size(nbColumns, nbRows), CV_8UC3); + Mat outMat = outBuffer.getMat(); + for (unsigned int i=0;i(pixel)=pixelValues; + } + } + } +} + +bool _convertCvMat2ValarrayBuffer(InputArray inputMat, std::valarray &outputValarrayMatrix) +{ + const Mat inputMatToConvert=inputMat.getMat(); + // first check input consistency + if (inputMatToConvert.empty()) + throw cv::Exception(-1, "RetinaImpl cannot be applied, input buffer is empty", "RetinaImpl::run", "RetinaImpl.h", 0); + + // retreive color mode from image input + int imageNumberOfChannels = inputMatToConvert.channels(); + + // convert to float AND fill the valarray buffer + typedef float T; // define here the target pixel format, here, float + const int dsttype = DataType::depth; // output buffer is float format + + const unsigned int nbPixels=inputMat.getMat().rows*inputMat.getMat().cols; + const unsigned int doubleNBpixels=inputMat.getMat().rows*inputMat.getMat().cols*2; + + if(imageNumberOfChannels==4) + { + // create a cv::Mat table (for RGBA planes) + cv::Mat planes[4] = + { + cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[doubleNBpixels]), + cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[nbPixels]), + cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[0]) + }; + planes[3] = cv::Mat(inputMatToConvert.size(), dsttype); // last channel (alpha) does not point on the valarray (not usefull in our case) + // split color cv::Mat in 4 planes... it fills valarray directely + cv::split(Mat_ >(inputMatToConvert), planes); + } + else if (imageNumberOfChannels==3) + { + // create a cv::Mat table (for RGB planes) + cv::Mat planes[] = + { + cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[doubleNBpixels]), + cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[nbPixels]), + cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[0]) + }; + // split color cv::Mat in 3 planes... it fills valarray directely + cv::split(cv::Mat_ >(inputMatToConvert), planes); + } + else if(imageNumberOfChannels==1) + { + // create a cv::Mat header for the valarray + cv::Mat dst(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[0]); + inputMatToConvert.convertTo(dst, dsttype); + } + else + CV_Error(Error::StsUnsupportedFormat, "input image must be single channel (gray levels), bgr format (color) or bgra (color with transparency which won't be considered"); + + return imageNumberOfChannels>1; // return bool : false for gray level image processing, true for color mode +} + + + // run the initilized retina filter in order to perform gray image tone mapping, after this call all retina outputs are updated + void _runGrayToneMapping(const std::valarray &grayImageInput, std::valarray &grayImageOutput) + { + // apply tone mapping on the multiplexed image + // -> photoreceptors local adaptation (large area adaptation) + _multiuseFilter->runFilter_LPfilter(grayImageInput, grayImageOutput, 0); // compute low pass filtering modeling the horizontal cells filtering to acess local luminance + _multiuseFilter->setV0CompressionParameterToneMapping(1.f, grayImageOutput.max(), _meanLuminanceModulatorK*grayImageOutput.sum()/(float)_multiuseFilter->getNBpixels()); + _multiuseFilter->runFilter_LocalAdapdation(grayImageInput, grayImageOutput, _temp2); // adapt contrast to local luminance + + // -> ganglion cells local adaptation (short area adaptation) + _multiuseFilter->runFilter_LPfilter(_temp2, grayImageOutput, 1); // compute low pass filtering (high cut frequency (remove spatio-temporal noise) + _multiuseFilter->setV0CompressionParameterToneMapping(1.f, _temp2.max(), _meanLuminanceModulatorK*grayImageOutput.sum()/(float)_multiuseFilter->getNBpixels()); + _multiuseFilter->runFilter_LocalAdapdation(_temp2, grayImageOutput, grayImageOutput); // adapt contrast to local luminance + + } + + // run the initilized retina filter in order to perform color tone mapping, after this call all retina outputs are updated + void _runRGBToneMapping(const std::valarray &RGBimageInput, std::valarray &RGBimageOutput, const bool useAdaptiveFiltering) + { + // multiplex the image with the color sampling method specified in the constructor + _colorEngine->runColorMultiplexing(RGBimageInput); + + // apply tone mapping on the multiplexed image + _runGrayToneMapping(_colorEngine->getMultiplexedFrame(), RGBimageOutput); + + // demultiplex tone maped image + _colorEngine->runColorDemultiplexing(RGBimageOutput, useAdaptiveFiltering, _multiuseFilter->getMaxInputValue());//_ColorEngine->getMultiplexedFrame());//_ParvoRetinaFilter->getPhotoreceptorsLPfilteringOutput()); + + // rescaling result between 0 and 255 + _colorEngine->normalizeRGBOutput_0_maxOutputValue(255.0); + + // return the result + RGBimageOutput=_colorEngine->getDemultiplexedColorFrame(); + } + +}; + +CV_EXPORTS Ptr createRetinaFastToneMapping(Size inputSize) +{ + return makePtr(inputSize); +} + +}// end of namespace bioinspired +}// end of namespace cv diff --git a/modules/contrib/src/retinafilter.cpp b/modules/bioinspired/src/retinafilter.cpp similarity index 96% rename from modules/contrib/src/retinafilter.cpp rename to modules/bioinspired/src/retinafilter.cpp index 4cf6019f57..e1e24c89bf 100644 --- a/modules/contrib/src/retinafilter.cpp +++ b/modules/bioinspired/src/retinafilter.cpp @@ -6,7 +6,7 @@ ** copy or use the software. ** ** -** HVStools : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. +** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. ** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. ** ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) @@ -32,7 +32,7 @@ ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. ** -** For Human Visual System tools (hvstools) +** For Human Visual System tools (bioinspired) ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved. ** ** Third party copyrights are property of their respective owners. @@ -72,9 +72,11 @@ #include namespace cv +{ +namespace bioinspired { // standard constructor without any log sampling of the input frame - RetinaFilter::RetinaFilter(const unsigned int sizeRows, const unsigned int sizeColumns, const bool colorMode, const RETINA_COLORSAMPLINGMETHOD samplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght) + RetinaFilter::RetinaFilter(const unsigned int sizeRows, const unsigned int sizeColumns, const bool colorMode, const int samplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght) : _retinaParvoMagnoMappedFrame(0), _retinaParvoMagnoMapCoefTable(0), @@ -375,21 +377,15 @@ namespace cv // apply tone mapping on the multiplexed image // -> photoreceptors local adaptation (large area adaptation) _photoreceptorsPrefilter.runFilter_LPfilter(grayImageInput, grayImageOutput, 2); // compute low pass filtering modeling the horizontal cells filtering to acess local luminance - _photoreceptorsPrefilter.setV0CompressionParameterToneMapping(PhotoreceptorsCompression, grayImageOutput.sum()/(float)_photoreceptorsPrefilter.getNBpixels()); + _photoreceptorsPrefilter.setV0CompressionParameterToneMapping(1.f-PhotoreceptorsCompression, grayImageOutput.max(), 1.f*grayImageOutput.sum()/(float)_photoreceptorsPrefilter.getNBpixels()); _photoreceptorsPrefilter.runFilter_LocalAdapdation(grayImageInput, grayImageOutput, temp2); // adapt contrast to local luminance - // high pass filter - //_spatiotemporalLPfilter(_localBuffer, _filterOutput, 2); // compute low pass filtering (high cut frequency (remove spatio-temporal noise) - - //for (unsigned int i=0;i<_NBpixels;++i) - // _localBuffer[i]-= _filterOutput[i]/2.0; - // -> ganglion cells local adaptation (short area adaptation) _photoreceptorsPrefilter.runFilter_LPfilter(temp2, grayImageOutput, 1); // compute low pass filtering (high cut frequency (remove spatio-temporal noise) - _photoreceptorsPrefilter.setV0CompressionParameterToneMapping(ganglionCellsCompression, temp2.max(), temp2.sum()/(float)_photoreceptorsPrefilter.getNBpixels()); + _photoreceptorsPrefilter.setV0CompressionParameterToneMapping(1.f-ganglionCellsCompression, temp2.max(), 1.f*temp2.sum()/(float)_photoreceptorsPrefilter.getNBpixels()); _photoreceptorsPrefilter.runFilter_LocalAdapdation(temp2, grayImageOutput, grayImageOutput); // adapt contrast to local luminance - } + // run the initilized retina filter in order to perform color tone mapping, after this call all retina outputs are updated void RetinaFilter::runRGBToneMapping(const std::valarray &RGBimageInput, std::valarray &RGBimageOutput, const bool useAdaptiveFiltering, const float PhotoreceptorsCompression, const float ganglionCellsCompression) { @@ -526,4 +522,5 @@ namespace cv return true; } -} +}// end of namespace bioinspired +}// end of namespace cv diff --git a/modules/contrib/src/retinafilter.hpp b/modules/bioinspired/src/retinafilter.hpp similarity index 98% rename from modules/contrib/src/retinafilter.hpp rename to modules/bioinspired/src/retinafilter.hpp index 7fa2a078c8..3e204885fc 100644 --- a/modules/contrib/src/retinafilter.hpp +++ b/modules/bioinspired/src/retinafilter.hpp @@ -6,7 +6,7 @@ ** copy or use the software. ** ** -** HVStools : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. +** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. ** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. ** ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) @@ -32,7 +32,7 @@ ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. ** -** For Human Visual System tools (hvstools) +** For Human Visual System tools (bioinspired) ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved. ** ** Third party copyrights are property of their respective owners. @@ -110,7 +110,8 @@ //#define __RETINADEBUG // define RETINADEBUG to display debug data namespace cv { - +namespace bioinspired +{ // retina class that process the 3 outputs of the retina filtering stages class RetinaFilter//: public BasicRetinaFilter { @@ -126,7 +127,7 @@ public: * @param reductionFactor: only usefull if param useRetinaLogSampling=true, specifies the reduction factor of the output frame (as the center (fovea) is high resolution and corners can be underscaled, then a reduction of the output is allowed without precision leak * @param samplingStrenght: only usefull if param useRetinaLogSampling=true, specifies the strenght of the log scale that is applied */ - RetinaFilter(const unsigned int sizeRows, const unsigned int sizeColumns, const bool colorMode=false, const RETINA_COLORSAMPLINGMETHOD samplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0); + RetinaFilter(const unsigned int sizeRows, const unsigned int sizeColumns, const bool colorMode=false, const int samplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0); /** * standard destructor @@ -541,9 +542,7 @@ private: }; -} +}// end of namespace bioinspired +}// end of namespace cv + #endif /*RETINACLASSES_H_*/ - - - - diff --git a/modules/contrib/src/templatebuffer.hpp b/modules/bioinspired/src/templatebuffer.hpp similarity index 98% rename from modules/contrib/src/templatebuffer.hpp rename to modules/bioinspired/src/templatebuffer.hpp index 21414b4da7..827eb709fa 100644 --- a/modules/contrib/src/templatebuffer.hpp +++ b/modules/bioinspired/src/templatebuffer.hpp @@ -6,7 +6,7 @@ ** copy or use the software. ** ** -** HVStools : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. +** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. ** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. ** ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) @@ -32,7 +32,7 @@ ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. ** -** For Human Visual System tools (hvstools) +** For Human Visual System tools (bioinspired) ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved. ** ** Third party copyrights are property of their respective owners. @@ -71,6 +71,12 @@ #include +//#define __TEMPLATEBUFFERDEBUG //define TEMPLATEBUFFERDEBUG in order to display debug information + +namespace cv +{ +namespace bioinspired +{ //// If a parallelization method is available then, you should define MAKE_PARALLEL, in the other case, the classical serial code will be used #define MAKE_PARALLEL // ==> then include required includes @@ -101,10 +107,6 @@ public: }; #endif -//#define __TEMPLATEBUFFERDEBUG //define TEMPLATEBUFFERDEBUG in order to display debug information - -namespace cv -{ /** * @class TemplateBuffer * @brief this class is a simple template memory buffer which contains basic functions to get information on or normalize the buffer content @@ -548,8 +550,6 @@ namespace cv return std::fabs(x); } -} +}// end of namespace bioinspired +}// end of namespace cv #endif - - - diff --git a/modules/features2d/test/test_precomp.cpp b/modules/bioinspired/test/test_main.cpp similarity index 58% rename from modules/features2d/test/test_precomp.cpp rename to modules/bioinspired/test/test_main.cpp index 5956e13e3e..6b24993447 100644 --- a/modules/features2d/test/test_precomp.cpp +++ b/modules/bioinspired/test/test_main.cpp @@ -1 +1,3 @@ #include "test_precomp.hpp" + +CV_TEST_MAIN("cv") diff --git a/modules/bioinspired/test/test_precomp.hpp b/modules/bioinspired/test/test_precomp.hpp new file mode 100644 index 0000000000..b1672149ab --- /dev/null +++ b/modules/bioinspired/test/test_precomp.hpp @@ -0,0 +1,16 @@ +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wmissing-declarations" +# if defined __clang__ || defined __APPLE__ +# pragma GCC diagnostic ignored "-Wmissing-prototypes" +# pragma GCC diagnostic ignored "-Wextra" +# endif +#endif + +#ifndef __OPENCV_TEST_PRECOMP_HPP__ +#define __OPENCV_TEST_PRECOMP_HPP__ + +#include "opencv2/ts.hpp" +#include "opencv2/bioinspired.hpp" +#include + +#endif diff --git a/modules/bioinspired/test/test_retina_ocl.cpp b/modules/bioinspired/test/test_retina_ocl.cpp new file mode 100644 index 0000000000..b09ce50366 --- /dev/null +++ b/modules/bioinspired/test/test_retina_ocl.cpp @@ -0,0 +1,144 @@ +/*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) 2010-2013, Multicoreware, Inc., all rights reserved. +// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// @Authors +// Peng Xiao, pengxiao@multicorewareinc.com +// +// 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 oclMaterials 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 "test_precomp.hpp" +#include "opencv2/opencv_modules.hpp" +#include "opencv2/bioinspired.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" + +#if defined(HAVE_OPENCV_OCL) + +#include "opencv2/ocl.hpp" +#define RETINA_ITERATIONS 5 + +static double checkNear(const cv::Mat &m1, const cv::Mat &m2) +{ + return cv::norm(m1, m2, cv::NORM_INF); +} + +#define PARAM_TEST_CASE(name, ...) struct name : testing::TestWithParam< std::tr1::tuple< __VA_ARGS__ > > +#define GET_PARAM(k) std::tr1::get< k >(GetParam()) + +static int oclInit = false; + +PARAM_TEST_CASE(Retina_OCL, bool, int, bool, double, double) +{ + bool colorMode; + int colorSamplingMethod; + bool useLogSampling; + double reductionFactor; + double samplingStrength; + + std::vector infos; + + virtual void SetUp() + { + colorMode = GET_PARAM(0); + colorSamplingMethod = GET_PARAM(1); + useLogSampling = GET_PARAM(2); + reductionFactor = GET_PARAM(3); + samplingStrength = GET_PARAM(4); + + if(!oclInit) + { + cv::ocl::getDevice(infos); + std::cout << "Device name:" << infos[0].DeviceName[0] << std::endl; + oclInit = true; + } + } +}; + +TEST_P(Retina_OCL, Accuracy) +{ + using namespace cv; + Mat input = imread(cvtest::TS::ptr()->get_data_path() + "shared/lena.png", colorMode); + CV_Assert(!input.empty()); + ocl::oclMat ocl_input(input); + + Ptr ocl_retina = bioinspired::createRetina_OCL( + input.size(), + colorMode, + colorSamplingMethod, + useLogSampling, + reductionFactor, + samplingStrength); + + Ptr gold_retina = bioinspired::createRetina( + input.size(), + colorMode, + colorSamplingMethod, + useLogSampling, + reductionFactor, + samplingStrength); + + Mat gold_parvo; + Mat gold_magno; + ocl::oclMat ocl_parvo; + ocl::oclMat ocl_magno; + + for(int i = 0; i < RETINA_ITERATIONS; i ++) + { + ocl_retina->run(ocl_input); + gold_retina->run(input); + + gold_retina->getParvo(gold_parvo); + gold_retina->getMagno(gold_magno); + + ocl_retina->getParvo(ocl_parvo); + ocl_retina->getMagno(ocl_magno); + + EXPECT_LE(checkNear(gold_parvo, (Mat)ocl_parvo), 1.0); + EXPECT_LE(checkNear(gold_magno, (Mat)ocl_magno), 1.0); + } +} + +INSTANTIATE_TEST_CASE_P(Contrib, Retina_OCL, testing::Combine( + testing::Values(false, true), + testing::Values((int)cv::bioinspired::RETINA_COLOR_BAYER), + testing::Values(false/*,true*/), + testing::Values(1.0, 0.5), + testing::Values(10.0, 5.0))); +#endif diff --git a/modules/calib3d/doc/calib3d.rst b/modules/calib3d/doc/calib3d.rst index 0ac8d51960..0c056843d2 100644 --- a/modules/calib3d/doc/calib3d.rst +++ b/modules/calib3d/doc/calib3d.rst @@ -6,4 +6,3 @@ calib3d. Camera Calibration and 3D Reconstruction :maxdepth: 2 camera_calibration_and_3d_reconstruction - diff --git a/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst b/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst index 26c73f1b69..cb30dc36d5 100644 --- a/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst +++ b/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst @@ -81,7 +81,7 @@ is extended as: :math:`s_1`, :math:`s_2`, :math:`s_3`, and -:math:`s_4`, are the thin prism distortion coefficients. +:math:`s_4`, are the thin prism distortion coefficients. Higher-order coefficients are not considered in OpenCV. In the functions below the coefficients are passed or returned as .. math:: @@ -109,20 +109,27 @@ The functions below use the above model to do the following: * Estimate the relative position and orientation of the stereo camera "heads" and compute the *rectification* transformation that makes the camera optical axes parallel. +.. note:: + * A calibration sample for 3 cameras in horizontal position can be found at opencv_source_code/samples/cpp/3calibration.cpp + * A calibration sample based on a sequence of images can be found at opencv_source_code/samples/cpp/calibration.cpp + * A calibration sample in order to do 3D reconstruction can be found at opencv_source_code/samples/cpp/build3dmodel.cpp + * A calibration sample of an artificially generated camera and chessboard patterns can be found at opencv_source_code/samples/cpp/calibration_artificial.cpp + * A calibration example on stereo calibration can be found at opencv_source_code/samples/cpp/stereo_calib.cpp + * A calibration example on stereo matching can be found at opencv_source_code/samples/cpp/stereo_match.cpp + + * (Python) A camera calibration sample can be found at opencv_source_code/samples/python2/calibrate.py calibrateCamera --------------- Finds the camera intrinsic and extrinsic parameters from several views of a calibration pattern. -.. ocv:function:: double calibrateCamera( InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, Size imageSize, InputOutputArray cameraMatrix, InputOutputArray distCoeffs, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, int flags=0, TermCriteria criteria=TermCriteria( TermCriteria::COUNT+TermCriteria::EPS, 30, DBL_EPSILON) ) +.. ocv:function:: double calibrateCamera( InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, Size imageSize, InputOutputArray cameraMatrix, InputOutputArray distCoeffs, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, int flags=0, TermCriteria criteria=TermCriteria( TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) ) .. ocv:pyfunction:: cv2.calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs[, rvecs[, tvecs[, flags[, criteria]]]]) -> retval, cameraMatrix, distCoeffs, rvecs, tvecs .. ocv:cfunction:: double cvCalibrateCamera2( const CvMat* object_points, const CvMat* image_points, const CvMat* point_counts, CvSize image_size, CvMat* camera_matrix, CvMat* distortion_coeffs, CvMat* rotation_vectors=NULL, CvMat* translation_vectors=NULL, int flags=0, CvTermCriteria term_crit=cvTermCriteria( CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,DBL_EPSILON) ) -.. ocv:pyoldfunction:: cv.CalibrateCamera2(objectPoints, imagePoints, pointCounts, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, flags=0)-> None - :param objectPoints: In the new interface it is a vector of vectors of calibration pattern points in the calibration pattern coordinate space. The outer vector contains as many elements as the number of the pattern views. If the same calibration pattern is shown in each view and it is fully visible, all the vectors will be the same. Although, it is possible to use partially occluded patterns, or even different patterns in different views. Then, the vectors will be different. The points are 3D, but since they are in a pattern coordinate system, then, if the rig is planar, it may make sense to put the model to a XY coordinate plane so that Z-coordinate of each input object point is 0. In the old interface all the vectors of object points from different views are concatenated together. @@ -156,9 +163,9 @@ Finds the camera intrinsic and extrinsic parameters from several views of a cali * **CV_CALIB_FIX_K1,...,CV_CALIB_FIX_K6** The corresponding radial distortion coefficient is not changed during the optimization. If ``CV_CALIB_USE_INTRINSIC_GUESS`` is set, the coefficient from the supplied ``distCoeffs`` matrix is used. Otherwise, it is set to 0. * **CV_CALIB_RATIONAL_MODEL** Coefficients k4, k5, and k6 are enabled. To provide the backward compatibility, this extra flag should be explicitly specified to make the calibration function use the rational model and return 8 coefficients. If the flag is not set, the function computes and returns only 5 distortion coefficients. - + * **CALIB_THIN_PRISM_MODEL** Coefficients s1, s2, s3 and s4 are enabled. To provide the backward compatibility, this extra flag should be explicitly specified to make the calibration function use the thin prism model and return 12 coefficients. If the flag is not set, the function computes and returns only 5 distortion coefficients. - + * **CALIB_FIX_S1_S2_S3_S4** The thin prism distortion coefficients are not changed during the optimization. If ``CV_CALIB_USE_INTRINSIC_GUESS`` is set, the coefficient from the supplied ``distCoeffs`` matrix is used. Otherwise, it is set to 0. @@ -279,7 +286,7 @@ For points in an image of a stereo pair, computes the corresponding epilines in .. ocv:cfunction:: void cvComputeCorrespondEpilines( const CvMat* points, int which_image, const CvMat* fundamental_matrix, CvMat* correspondent_lines ) -.. ocv:pyoldfunction:: cv.ComputeCorrespondEpilines(points, whichImage, F, lines) -> None +.. ocv:pyfunction:: cv2.computeCorrespondEpilines(points, whichImage, F[, lines]) -> lines :param points: Input points. :math:`N \times 1` or :math:`1 \times N` matrix of type ``CV_32FC2`` or ``vector`` . @@ -354,7 +361,6 @@ Converts points to/from homogeneous coordinates. .. ocv:function:: void convertPointsHomogeneous( InputArray src, OutputArray dst ) .. ocv:cfunction:: void cvConvertPointsHomogeneous( const CvMat* src, CvMat* dst ) -.. ocv:pyoldfunction:: cv.ConvertPointsHomogeneous(src, dst) -> None :param src: Input array or vector of 2D, 3D, or 4D points. @@ -400,8 +406,6 @@ Decomposes a projection matrix into a rotation matrix and a camera matrix. .. ocv:cfunction:: void cvDecomposeProjectionMatrix( const CvMat * projMatr, CvMat * calibMatr, CvMat * rotMatr, CvMat * posVect, CvMat * rotMatrX=NULL, CvMat * rotMatrY=NULL, CvMat * rotMatrZ=NULL, CvPoint3D64f * eulerAngles=NULL ) -.. ocv:pyoldfunction:: cv.DecomposeProjectionMatrix(projMatrix, cameraMatrix, rotMatrix, transVect, rotMatrX=None, rotMatrY=None, rotMatrZ=None) -> eulerAngles - :param projMatrix: 3x4 input projection matrix P. :param cameraMatrix: Output 3x3 camera matrix K. @@ -436,7 +440,6 @@ Renders the detected chessboard corners. .. ocv:pyfunction:: cv2.drawChessboardCorners(image, patternSize, corners, patternWasFound) -> image .. ocv:cfunction:: void cvDrawChessboardCorners( CvArr* image, CvSize pattern_size, CvPoint2D32f* corners, int count, int pattern_was_found ) -.. ocv:pyoldfunction:: cv.DrawChessboardCorners(image, patternSize, corners, patternWasFound)-> None :param image: Destination image. It must be an 8-bit color image. @@ -454,12 +457,11 @@ findChessboardCorners ------------------------- Finds the positions of internal corners of the chessboard. -.. ocv:function:: bool findChessboardCorners( InputArray image, Size patternSize, OutputArray corners, int flags=CALIB_CB_ADAPTIVE_THRESH+CALIB_CB_NORMALIZE_IMAGE ) +.. ocv:function:: bool findChessboardCorners( InputArray image, Size patternSize, OutputArray corners, int flags=CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE ) .. ocv:pyfunction:: cv2.findChessboardCorners(image, patternSize[, corners[, flags]]) -> retval, corners .. ocv:cfunction:: int cvFindChessboardCorners( const void* image, CvSize pattern_size, CvPoint2D32f* corners, int* corner_count=NULL, int flags=CV_CALIB_CB_ADAPTIVE_THRESH+CV_CALIB_CB_NORMALIZE_IMAGE ) -.. ocv:pyoldfunction:: cv.FindChessboardCorners(image, patternSize, flags=CV_CALIB_CB_ADAPTIVE_THRESH) -> corners :param image: Source chessboard view. It must be an 8-bit grayscale or color image. @@ -513,9 +515,9 @@ findCirclesGrid ------------------- Finds centers in the grid of circles. -.. ocv:function:: bool findCirclesGrid( InputArray image, Size patternSize, OutputArray centers, int flags=CALIB_CB_SYMMETRIC_GRID, const Ptr &blobDetector = new SimpleBlobDetector() ) +.. ocv:function:: bool findCirclesGrid( InputArray image, Size patternSize, OutputArray centers, int flags=CALIB_CB_SYMMETRIC_GRID, const Ptr &blobDetector = makePtr() ) -.. ocv:pyfunction:: cv2.findCirclesGridDefault(image, patternSize[, centers[, flags]]) -> retval, centers +.. ocv:pyfunction:: cv2.findCirclesGrid(image, patternSize[, centers[, flags[, blobDetector]]]) -> retval, centers :param image: grid view of input circles; it must be an 8-bit grayscale or color image. @@ -564,8 +566,6 @@ Finds an object pose from 3D-2D point correspondences. .. ocv:cfunction:: void cvFindExtrinsicCameraParams2( const CvMat* object_points, const CvMat* image_points, const CvMat* camera_matrix, const CvMat* distortion_coeffs, CvMat* rotation_vector, CvMat* translation_vector, int use_extrinsic_guess=0 ) -.. ocv:pyoldfunction:: cv.FindExtrinsicCameraParams2(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec, useExtrinsicGuess=0 ) -> None - :param objectPoints: Array of object points in the object coordinate space, 3xN/Nx3 1-channel or 1xN/Nx1 3-channel, where N is the number of points. ``vector`` can be also passed here. :param imagePoints: Array of corresponding image points, 2xN/Nx2 1-channel or 1xN/Nx1 2-channel, where N is the number of points. ``vector`` can be also passed here. @@ -588,7 +588,9 @@ Finds an object pose from 3D-2D point correspondences. The function estimates the object pose given a set of object points, their corresponding image projections, as well as the camera matrix and the distortion coefficients. +.. note:: + * An example of how to use solvePNP for planar augmented reality can be found at opencv_source_code/samples/python2/plane_ar.py solvePnPRansac ------------------ @@ -636,7 +638,6 @@ Calculates a fundamental matrix from the corresponding points in two images. .. ocv:pyfunction:: cv2.findFundamentalMat(points1, points2[, method[, param1[, param2[, mask]]]]) -> retval, mask .. ocv:cfunction:: int cvFindFundamentalMat( const CvMat* points1, const CvMat* points2, CvMat* fundamental_matrix, int method=CV_FM_RANSAC, double param1=3., double param2=0.99, CvMat* status=NULL ) -.. ocv:pyoldfunction:: cv.FindFundamentalMat(points1, points2, fundamentalMatrix, method=CV_FM_RANSAC, param1=1., param2=0.99, status=None) -> retval :param points1: Array of ``N`` points from the first image. The point coordinates should be floating-point (single or double precision). @@ -694,7 +695,7 @@ findEssentialMat ------------------ Calculates an essential matrix from the corresponding points in two images. -.. ocv:function:: Mat findEssentialMat( InputArray points1, InputArray points2, double focal=1.0, Point2d pp=Point2d(0, 0), int method=CV_RANSAC, double prob=0.999, double threshold=1.0, OutputArray mask=noArray() ) +.. ocv:function:: Mat findEssentialMat( InputArray points1, InputArray points2, double focal=1.0, Point2d pp=Point2d(0, 0), int method=RANSAC, double prob=0.999, double threshold=1.0, OutputArray mask=noArray() ) :param points1: Array of ``N`` ``(N >= 5)`` 2D points from the first image. The point coordinates should be floating-point (single or double precision). @@ -715,7 +716,7 @@ Calculates an essential matrix from the corresponding points in two images. :param mask: Output array of N elements, every element of which is set to 0 for outliers and to 1 for the other points. The array is computed only in the RANSAC and LMedS methods. -This function estimates essential matrix based on an implementation of five-point algorithm [Nister03]_ [SteweniusCFS]_. +This function estimates essential matrix based on the five-point algorithm solver in [Nister03]_. [SteweniusCFS]_ is also a related. The epipolar geometry is described by the following equation: .. math:: @@ -820,8 +821,6 @@ Finds a perspective transformation between two planes. .. ocv:cfunction:: int cvFindHomography( const CvMat* src_points, const CvMat* dst_points, CvMat* homography, int method=0, double ransacReprojThreshold=3, CvMat* mask=0 ) -.. ocv:pyoldfunction:: cv.FindHomography(srcPoints, dstPoints, H, method=0, ransacReprojThreshold=3.0, status=None) -> None - :param srcPoints: Coordinates of the points in the original plane, a matrix of the type ``CV_32FC2`` or ``vector`` . :param dstPoints: Coordinates of the points in the target plane, a matrix of the type ``CV_32FC2`` or a ``vector`` . @@ -893,6 +892,9 @@ Homography matrix is determined up to a scale. Thus, it is normalized so that :ocv:func:`warpPerspective`, :ocv:func:`perspectiveTransform` +.. note:: + + * A example on calculating a homography for image matching can be found at opencv_source_code/samples/cpp/video_homography.cpp estimateAffine3D -------------------- @@ -946,8 +948,6 @@ Returns the new camera matrix based on the free scaling parameter. .. ocv:cfunction:: void cvGetOptimalNewCameraMatrix( const CvMat* camera_matrix, const CvMat* dist_coeffs, CvSize image_size, double alpha, CvMat* new_camera_matrix, CvSize new_imag_size=cvSize(0,0), CvRect* valid_pixel_ROI=0, int center_principal_point=0 ) -.. ocv:pyoldfunction:: cv.GetOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, alpha, newCameraMatrix, newImageSize=(0, 0), validPixROI=0, centerPrincipalPoint=0) -> None - :param cameraMatrix: Input camera matrix. :param distCoeffs: Input vector of distortion coefficients :math:`(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6],[s_1, s_2, s_3, s_4]])` of 4, 5, 8 or 12 elements. If the vector is NULL/empty, the zero distortion coefficients are assumed. @@ -975,14 +975,12 @@ initCameraMatrix2D ---------------------- Finds an initial camera matrix from 3D-2D point correspondences. -.. ocv:function:: Mat initCameraMatrix2D( InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, Size imageSize, double aspectRatio=1.) +.. ocv:function:: Mat initCameraMatrix2D( InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, Size imageSize, double aspectRatio=1.0 ) .. ocv:pyfunction:: cv2.initCameraMatrix2D(objectPoints, imagePoints, imageSize[, aspectRatio]) -> retval .. ocv:cfunction:: void cvInitIntrinsicParams2D( const CvMat* object_points, const CvMat* image_points, const CvMat* npoints, CvSize image_size, CvMat* camera_matrix, double aspect_ratio=1. ) -.. ocv:pyoldfunction:: cv.InitIntrinsicParams2D(objectPoints, imagePoints, npoints, imageSize, cameraMatrix, aspectRatio=1.) -> None - :param objectPoints: Vector of vectors of the calibration pattern points in the calibration pattern coordinate space. In the old interface all the per-view vectors are concatenated. See :ocv:func:`calibrateCamera` for details. :param imagePoints: Vector of vectors of the projections of the calibration pattern points. In the old interface all the per-view vectors are concatenated. @@ -1030,8 +1028,6 @@ Projects 3D points to an image plane. .. ocv:cfunction:: void cvProjectPoints2( const CvMat* object_points, const CvMat* rotation_vector, const CvMat* translation_vector, const CvMat* camera_matrix, const CvMat* distortion_coeffs, CvMat* image_points, CvMat* dpdrot=NULL, CvMat* dpdt=NULL, CvMat* dpdf=NULL, CvMat* dpdc=NULL, CvMat* dpddist=NULL, double aspect_ratio=0 ) -.. ocv:pyoldfunction:: cv.ProjectPoints2(objectPoints, rvec, tvec, cameraMatrix, distCoeffs, imagePoints, dpdrot=None, dpdt=None, dpdf=None, dpdc=None, dpddist=None)-> None - :param objectPoints: Array of object points, 3xN/Nx3 1-channel or 1xN/Nx1 3-channel (or ``vector`` ), where N is the number of points in the view. :param rvec: Rotation vector. See :ocv:func:`Rodrigues` for details. @@ -1075,15 +1071,13 @@ Reprojects a disparity image to 3D space. .. ocv:cfunction:: void cvReprojectImageTo3D( const CvArr* disparityImage, CvArr* _3dImage, const CvMat* Q, int handleMissingValues=0 ) -.. ocv:pyoldfunction:: cv.ReprojectImageTo3D(disparity, _3dImage, Q, handleMissingValues=0) -> None - :param disparity: Input single-channel 8-bit unsigned, 16-bit signed, 32-bit signed or 32-bit floating-point disparity image. :param _3dImage: Output 3-channel floating-point image of the same size as ``disparity`` . Each element of ``_3dImage(x,y)`` contains 3D coordinates of the point ``(x,y)`` computed from the disparity map. :param Q: :math:`4 \times 4` perspective transformation matrix that can be obtained with :ocv:func:`stereoRectify`. - :param handleMissingValues: Indicates, whether the function should handle missing values (i.e. points where the disparity was not computed). If ``handleMissingValues=true``, then pixels with the minimal disparity that corresponds to the outliers (see :ocv:funcx:`StereoBM::operator()` ) are transformed to 3D points with a very large Z value (currently set to 10000). + :param handleMissingValues: Indicates, whether the function should handle missing values (i.e. points where the disparity was not computed). If ``handleMissingValues=true``, then pixels with the minimal disparity that corresponds to the outliers (see :ocv:funcx:`StereoMatcher::compute` ) are transformed to 3D points with a very large Z value (currently set to 10000). :param ddepth: The optional output array depth. If it is ``-1``, the output image will have ``CV_32F`` depth. ``ddepth`` can also be set to ``CV_16S``, ``CV_32S`` or ``CV_32F``. @@ -1109,7 +1103,6 @@ Computes an RQ decomposition of 3x3 matrices. .. ocv:pyfunction:: cv2.RQDecomp3x3(src[, mtxR[, mtxQ[, Qx[, Qy[, Qz]]]]]) -> retval, mtxR, mtxQ, Qx, Qy, Qz .. ocv:cfunction:: void cvRQDecomp3x3( const CvMat * matrixM, CvMat * matrixR, CvMat * matrixQ, CvMat * matrixQx=NULL, CvMat * matrixQy=NULL, CvMat * matrixQz=NULL, CvPoint3D64f * eulerAngles=NULL ) -.. ocv:pyoldfunction:: cv.RQDecomp3x3(M, R, Q, Qx=None, Qy=None, Qz=None) -> eulerAngles :param src: 3x3 input matrix. @@ -1140,8 +1133,6 @@ Converts a rotation matrix to a rotation vector or vice versa. .. ocv:cfunction:: int cvRodrigues2( const CvMat* src, CvMat* dst, CvMat* jacobian=0 ) -.. ocv:pyoldfunction:: cv.Rodrigues2(src, dst, jacobian=0)-> None - :param src: Input rotation vector (3x1 or 1x3) or rotation matrix (3x3). :param dst: Output rotation matrix (3x3) or rotation vector (3x1 or 1x3), respectively. @@ -1166,155 +1157,84 @@ used in the global 3D geometry optimization procedures like :ocv:func:`solvePnP` . +StereoMatcher +------------- +.. ocv:class:: StereoMatcher : public Algorithm -StereoBM --------- -.. ocv:class:: StereoBM +The base class for stereo correspondence algorithms. -Class for computing stereo correspondence using the block matching algorithm. :: - - // Block matching stereo correspondence algorithm class StereoBM - { - enum { NORMALIZED_RESPONSE = CV_STEREO_BM_NORMALIZED_RESPONSE, - BASIC_PRESET=CV_STEREO_BM_BASIC, - FISH_EYE_PRESET=CV_STEREO_BM_FISH_EYE, - NARROW_PRESET=CV_STEREO_BM_NARROW }; - - StereoBM(); - // the preset is one of ..._PRESET above. - // ndisparities is the size of disparity range, - // in which the optimal disparity at each pixel is searched for. - // SADWindowSize is the size of averaging window used to match pixel blocks - // (larger values mean better robustness to noise, but yield blurry disparity maps) - StereoBM(int preset, int ndisparities=0, int SADWindowSize=21); - // separate initialization function - void init(int preset, int ndisparities=0, int SADWindowSize=21); - // computes the disparity for the two rectified 8-bit single-channel images. - // the disparity will be 16-bit signed (fixed-point) or 32-bit floating-point image of the same size as left. - void operator()( InputArray left, InputArray right, OutputArray disparity, int disptype=CV_16S ); - - Ptr state; - }; - -The class is a C++ wrapper for the associated functions. In particular, :ocv:funcx:`StereoBM::operator()` is the wrapper for -:ocv:cfunc:`cvFindStereoCorrespondenceBM`. - - -StereoBM::StereoBM ------------------- -The constructors. - -.. ocv:function:: StereoBM::StereoBM() -.. ocv:function:: StereoBM::StereoBM(int preset, int ndisparities=0, int SADWindowSize=21) - -.. ocv:pyfunction:: cv2.StereoBM([preset[, ndisparities[, SADWindowSize]]]) -> - -.. ocv:cfunction:: CvStereoBMState* cvCreateStereoBMState( int preset=CV_STEREO_BM_BASIC, int numberOfDisparities=0 ) - -.. ocv:pyoldfunction:: cv.CreateStereoBMState(preset=CV_STEREO_BM_BASIC, numberOfDisparities=0)-> CvStereoBMState - - :param preset: specifies the whole set of algorithm parameters, one of: - - * BASIC_PRESET - parameters suitable for general cameras - * FISH_EYE_PRESET - parameters suitable for wide-angle cameras - * NARROW_PRESET - parameters suitable for narrow-angle cameras - - After constructing the class, you can override any parameters set by the preset. - - :param ndisparities: the disparity search range. For each pixel algorithm will find the best disparity from 0 (default minimum disparity) to ``ndisparities``. The search range can then be shifted by changing the minimum disparity. - - :param SADWindowSize: the linear size of the blocks compared by the algorithm. The size should be odd (as the block is centered at the current pixel). Larger block size implies smoother, though less accurate disparity map. Smaller block size gives more detailed disparity map, but there is higher chance for algorithm to find a wrong correspondence. - -The constructors initialize ``StereoBM`` state. You can then call ``StereoBM::operator()`` to compute disparity for a specific stereo pair. - -.. note:: In the C API you need to deallocate ``CvStereoBM`` state when it is not needed anymore using ``cvReleaseStereoBMState(&stereobm)``. - -StereoBM::operator() +StereoMatcher::compute ----------------------- -Computes disparity using the BM algorithm for a rectified stereo pair. +Computes disparity map for the specified stereo pair -.. ocv:function:: void StereoBM::operator()( InputArray left, InputArray right, OutputArray disparity, int disptype=CV_16S ) +.. ocv:function:: void StereoMatcher::compute( InputArray left, InputArray right, OutputArray disparity ) -.. ocv:pyfunction:: cv2.StereoBM.compute(left, right[, disparity[, disptype]]) -> disparity - -.. ocv:cfunction:: void cvFindStereoCorrespondenceBM( const CvArr* left, const CvArr* right, CvArr* disparity, CvStereoBMState* state ) - -.. ocv:pyoldfunction:: cv.FindStereoCorrespondenceBM(left, right, disparity, state)-> None +.. ocv:pyfunction:: cv2.StereoBM.compute(left, right[, disparity]) -> disparity :param left: Left 8-bit single-channel image. :param right: Right image of the same size and the same type as the left one. - :param disparity: Output disparity map. It has the same size as the input images. When ``disptype==CV_16S``, the map is a 16-bit signed single-channel image, containing disparity values scaled by 16. To get the true disparity values from such fixed-point representation, you will need to divide each ``disp`` element by 16. If ``disptype==CV_32F``, the disparity map will already contain the real disparity values on output. + :param disparity: Output disparity map. It has the same size as the input images. Some algorithms, like StereoBM or StereoSGBM compute 16-bit fixed-point disparity map (where each disparity value has 4 fractional bits), whereas other algorithms output 32-bit floating-point disparity map. - :param disptype: Type of the output disparity map, ``CV_16S`` (default) or ``CV_32F``. - :param state: The pre-initialized ``CvStereoBMState`` structure in the case of the old API. +StereoBM +-------- +.. ocv:class:: StereoBM : public StereoMatcher -The method executes the BM algorithm on a rectified stereo pair. See the ``stereo_match.cpp`` OpenCV sample on how to prepare images and call the method. Note that the method is not constant, thus you should not use the same ``StereoBM`` instance from within different threads simultaneously. The function is parallelized with the TBB library. +Class for computing stereo correspondence using the block matching algorithm, introduced and contributed to OpenCV by K. Konolige. +.. Sample code: + + (Ocl) An example for using the stereoBM matching algorithm can be found at opencv_source_code/samples/ocl/stereo_match.cpp + +createStereoBM +------------------ +Creates StereoBM object + +.. ocv:function:: Ptr createStereoBM(int numDisparities=0, int blockSize=21) + +.. ocv:pyfunction:: cv2.createStereoBM([numDisparities[, blockSize]]) -> retval + + :param numDisparities: the disparity search range. For each pixel algorithm will find the best disparity from 0 (default minimum disparity) to ``numDisparities``. The search range can then be shifted by changing the minimum disparity. + + :param blockSize: the linear size of the blocks compared by the algorithm. The size should be odd (as the block is centered at the current pixel). Larger block size implies smoother, though less accurate disparity map. Smaller block size gives more detailed disparity map, but there is higher chance for algorithm to find a wrong correspondence. + +The function create ``StereoBM`` object. You can then call ``StereoBM::compute()`` to compute disparity for a specific stereo pair. StereoSGBM ---------- -.. ocv:class:: StereoSGBM - -Class for computing stereo correspondence using the semi-global block matching algorithm. :: - - class StereoSGBM - { - StereoSGBM(); - StereoSGBM(int minDisparity, int numDisparities, int SADWindowSize, - int P1=0, int P2=0, int disp12MaxDiff=0, - int preFilterCap=0, int uniquenessRatio=0, - int speckleWindowSize=0, int speckleRange=0, - bool fullDP=false); - virtual ~StereoSGBM(); - - virtual void operator()(InputArray left, InputArray right, OutputArray disp); - - int minDisparity; - int numberOfDisparities; - int SADWindowSize; - int preFilterCap; - int uniquenessRatio; - int P1, P2; - int speckleWindowSize; - int speckleRange; - int disp12MaxDiff; - bool fullDP; - - ... - }; +.. ocv:class:: StereoSGBM : public StereoMatcher The class implements the modified H. Hirschmuller algorithm [HH08]_ that differs from the original one as follows: - * By default, the algorithm is single-pass, which means that you consider only 5 directions instead of 8. Set ``fullDP=true`` to run the full variant of the algorithm but beware that it may consume a lot of memory. + * By default, the algorithm is single-pass, which means that you consider only 5 directions instead of 8. Set ``mode=StereoSGBM::MODE_HH`` in ``createStereoSGBM`` to run the full variant of the algorithm but beware that it may consume a lot of memory. - * The algorithm matches blocks, not individual pixels. Though, setting ``SADWindowSize=1`` reduces the blocks to single pixels. + * The algorithm matches blocks, not individual pixels. Though, setting ``blockSize=1`` reduces the blocks to single pixels. * Mutual information cost function is not implemented. Instead, a simpler Birchfield-Tomasi sub-pixel metric from [BT98]_ is used. Though, the color images are supported as well. - * Some pre- and post- processing steps from K. Konolige algorithm :ocv:funcx:`StereoBM::operator()` are included, for example: pre-filtering (``CV_STEREO_BM_XSOBEL`` type) and post-filtering (uniqueness check, quadratic interpolation and speckle filtering). + * Some pre- and post- processing steps from K. Konolige algorithm ``StereoBM`` are included, for example: pre-filtering (``StereoBM::PREFILTER_XSOBEL`` type) and post-filtering (uniqueness check, quadratic interpolation and speckle filtering). +.. note:: + * (Python) An example illustrating the use of the StereoSGBM matching algorithm can be found at opencv_source_code/samples/python2/stereo_match.py -StereoSGBM::StereoSGBM +createStereoSGBM -------------------------- -.. ocv:function:: StereoSGBM::StereoSGBM() +Creates StereoSGBM object -.. ocv:function:: StereoSGBM::StereoSGBM( int minDisparity, int numDisparities, int SADWindowSize, int P1=0, int P2=0, int disp12MaxDiff=0, int preFilterCap=0, int uniquenessRatio=0, int speckleWindowSize=0, int speckleRange=0, bool fullDP=false) +.. ocv:function:: Ptr createStereoSGBM( int minDisparity, int numDisparities, int blockSize, int P1=0, int P2=0, int disp12MaxDiff=0, int preFilterCap=0, int uniquenessRatio=0, int speckleWindowSize=0, int speckleRange=0, int mode=StereoSGBM::MODE_SGBM) -.. ocv:pyfunction:: cv2.StereoSGBM([minDisparity, numDisparities, SADWindowSize[, P1[, P2[, disp12MaxDiff[, preFilterCap[, uniquenessRatio[, speckleWindowSize[, speckleRange[, fullDP]]]]]]]]]) -> - - Initializes ``StereoSGBM`` and sets parameters to custom values.?? +.. ocv:pyfunction:: cv2.createStereoSGBM(minDisparity, numDisparities, blockSize[, P1[, P2[, disp12MaxDiff[, preFilterCap[, uniquenessRatio[, speckleWindowSize[, speckleRange[, mode]]]]]]]]) -> retval :param minDisparity: Minimum possible disparity value. Normally, it is zero but sometimes rectification algorithms can shift images, so this parameter needs to be adjusted accordingly. :param numDisparities: Maximum disparity minus minimum disparity. The value is always greater than zero. In the current implementation, this parameter must be divisible by 16. - :param SADWindowSize: Matched block size. It must be an odd number ``>=1`` . Normally, it should be somewhere in the ``3..11`` range. + :param blockSize: Matched block size. It must be an odd number ``>=1`` . Normally, it should be somewhere in the ``3..11`` range. :param P1: The first parameter controlling the disparity smoothness. See below. @@ -1330,32 +1250,12 @@ StereoSGBM::StereoSGBM :param speckleRange: Maximum disparity variation within each connected component. If you do speckle filtering, set the parameter to a positive value, it will be implicitly multiplied by 16. Normally, 1 or 2 is good enough. - :param fullDP: Set it to ``true`` to run the full-scale two-pass dynamic programming algorithm. It will consume O(W*H*numDisparities) bytes, which is large for 640x480 stereo and huge for HD-size pictures. By default, it is set to ``false`` . + :param mode: Set it to ``StereoSGBM::MODE_HH`` to run the full-scale two-pass dynamic programming algorithm. It will consume O(W*H*numDisparities) bytes, which is large for 640x480 stereo and huge for HD-size pictures. By default, it is set to ``false`` . -The first constructor initializes ``StereoSGBM`` with all the default parameters. So, you only have to set ``StereoSGBM::numberOfDisparities`` at minimum. The second constructor enables you to set each parameter to a custom value. +The first constructor initializes ``StereoSGBM`` with all the default parameters. So, you only have to set ``StereoSGBM::numDisparities`` at minimum. The second constructor enables you to set each parameter to a custom value. -StereoSGBM::operator () ------------------------ - -.. ocv:function:: void StereoSGBM::operator()(InputArray left, InputArray right, OutputArray disp) - -.. ocv:pyfunction:: cv2.StereoSGBM.compute(left, right[, disp]) -> disp - - Computes disparity using the SGBM algorithm for a rectified stereo pair. - - :param left: Left 8-bit single-channel or 3-channel image. - - :param right: Right image of the same size and the same type as the left one. - - :param disp: Output disparity map. It is a 16-bit signed single-channel image of the same size as the input image. It contains disparity values scaled by 16. So, to get the floating-point disparity map, you need to divide each ``disp`` element by 16. - -The method executes the SGBM algorithm on a rectified stereo pair. See ``stereo_match.cpp`` OpenCV sample on how to prepare images and call the method. - -.. note:: The method is not constant, so you should not use the same ``StereoSGBM`` instance from different threads simultaneously. - - stereoCalibrate ------------------- Calibrates the stereo camera. @@ -1366,8 +1266,6 @@ Calibrates the stereo camera. .. ocv:cfunction:: double cvStereoCalibrate( const CvMat* object_points, const CvMat* image_points1, const CvMat* image_points2, const CvMat* npoints, CvMat* camera_matrix1, CvMat* dist_coeffs1, CvMat* camera_matrix2, CvMat* dist_coeffs2, CvSize image_size, CvMat* R, CvMat* T, CvMat* E=0, CvMat* F=0, CvTermCriteria term_crit=cvTermCriteria( CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,1e-6), int flags=CV_CALIB_FIX_INTRINSIC ) -.. ocv:pyoldfunction:: cv.StereoCalibrate(objectPoints, imagePoints1, imagePoints2, pointCounts, cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R, T, E=None, F=None, term_crit=(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 30, 1e-6), flags=CV_CALIB_FIX_INTRINSIC)-> None - :param objectPoints: Vector of vectors of the calibration pattern points. :param imagePoints1: Vector of vectors of the projections of the calibration pattern points, observed by the first camera. @@ -1413,9 +1311,9 @@ Calibrates the stereo camera. * **CV_CALIB_FIX_K1,...,CV_CALIB_FIX_K6** Do not change the corresponding radial distortion coefficient during the optimization. If ``CV_CALIB_USE_INTRINSIC_GUESS`` is set, the coefficient from the supplied ``distCoeffs`` matrix is used. Otherwise, it is set to 0. * **CV_CALIB_RATIONAL_MODEL** Enable coefficients k4, k5, and k6. To provide the backward compatibility, this extra flag should be explicitly specified to make the calibration function use the rational model and return 8 coefficients. If the flag is not set, the function computes and returns only 5 distortion coefficients. - + * **CALIB_THIN_PRISM_MODEL** Coefficients s1, s2, s3 and s4 are enabled. To provide the backward compatibility, this extra flag should be explicitly specified to make the calibration function use the thin prism model and return 12 coefficients. If the flag is not set, the function computes and returns only 5 distortion coefficients. - + * **CALIB_FIX_S1_S2_S3_S4** The thin prism distortion coefficients are not changed during the optimization. If ``CV_CALIB_USE_INTRINSIC_GUESS`` is set, the coefficient from the supplied ``distCoeffs`` matrix is used. Otherwise, it is set to 0. The function estimates transformation between two cameras making a stereo pair. If you have a stereo camera where the relative position and orientation of two cameras is fixed, and if you computed poses of an object relative to the first camera and to the second camera, (R1, T1) and (R2, T2), respectively (this can be done with @@ -1459,8 +1357,6 @@ Computes rectification transforms for each head of a calibrated stereo camera. .. ocv:cfunction:: void cvStereoRectify( const CvMat* camera_matrix1, const CvMat* camera_matrix2, const CvMat* dist_coeffs1, const CvMat* dist_coeffs2, CvSize image_size, const CvMat* R, const CvMat* T, CvMat* R1, CvMat* R2, CvMat* P1, CvMat* P2, CvMat* Q=0, int flags=CV_CALIB_ZERO_DISPARITY, double alpha=-1, CvSize new_image_size=cvSize(0,0), CvRect* valid_pix_ROI1=0, CvRect* valid_pix_ROI2=0 ) -.. ocv:pyoldfunction:: cv.StereoRectify(cameraMatrix1, cameraMatrix2, distCoeffs1, distCoeffs2, imageSize, R, T, R1, R2, P1, P2, Q=None, flags=CV_CALIB_ZERO_DISPARITY, alpha=-1, newImageSize=(0, 0)) -> (roi1, roi2) - :param cameraMatrix1: First camera matrix. :param cameraMatrix2: Second camera matrix. @@ -1548,8 +1444,6 @@ Computes a rectification transform for an uncalibrated stereo camera. .. ocv:cfunction:: int cvStereoRectifyUncalibrated( const CvMat* points1, const CvMat* points2, const CvMat* F, CvSize img_size, CvMat* H1, CvMat* H2, double threshold=5 ) -.. ocv:pyoldfunction:: cv.StereoRectifyUncalibrated(points1, points2, F, imageSize, H1, H2, threshold=5)-> None - :param points1: Array of feature points in the first image. :param points2: The corresponding points in the second image. The same formats as in :ocv:func:`findFundamentalMat` are supported. @@ -1614,6 +1508,6 @@ The function reconstructs 3-dimensional points (in homogeneous coordinates) by u .. [SteweniusCFS] Stewénius, H., Calibrated Fivepoint solver. http://www.vis.uky.edu/~stewe/FIVEPOINT/ -.. [Slabaugh] Slabaugh, G.G. Computing Euler angles from a rotation matrix. http://gregslabaugh.name/publications/euler.pdf +.. [Slabaugh] Slabaugh, G.G. Computing Euler angles from a rotation matrix. http://www.soi.city.ac.uk/~sbbh653/publications/euler.pdf (verified: 2013-04-15) .. [Zhang2000] Z. Zhang. A Flexible New Technique for Camera Calibration. IEEE Transactions on Pattern Analysis and Machine Intelligence, 22(11):1330-1334, 2000. diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d.hpp index 989912cda8..1a8777b93c 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d.hpp @@ -7,11 +7,12 @@ // copy or use the software. // // -// License Agreement +// License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -46,556 +47,181 @@ #include "opencv2/core.hpp" #include "opencv2/features2d.hpp" -#ifdef __cplusplus -extern "C" { -#endif - -/****************************************************************************************\ -* Camera Calibration, Pose Estimation and Stereo * -\****************************************************************************************/ - -typedef struct CvPOSITObject CvPOSITObject; - -/* Allocates and initializes CvPOSITObject structure before doing cvPOSIT */ -CVAPI(CvPOSITObject*) cvCreatePOSITObject( CvPoint3D32f* points, int point_count ); - - -/* Runs POSIT (POSe from ITeration) algorithm for determining 3d position of - an object given its model and projection in a weak-perspective case */ -CVAPI(void) cvPOSIT( CvPOSITObject* posit_object, CvPoint2D32f* image_points, - double focal_length, CvTermCriteria criteria, - float* rotation_matrix, float* translation_vector); - -/* Releases CvPOSITObject structure */ -CVAPI(void) cvReleasePOSITObject( CvPOSITObject** posit_object ); - -/* updates the number of RANSAC iterations */ -CVAPI(int) cvRANSACUpdateNumIters( double p, double err_prob, - int model_points, int max_iters ); - -CVAPI(void) cvConvertPointsHomogeneous( const CvMat* src, CvMat* dst ); - -/* Calculates fundamental matrix given a set of corresponding points */ -#define CV_FM_7POINT 1 -#define CV_FM_8POINT 2 - -#define CV_LMEDS 4 -#define CV_RANSAC 8 - -#define CV_FM_LMEDS_ONLY CV_LMEDS -#define CV_FM_RANSAC_ONLY CV_RANSAC -#define CV_FM_LMEDS CV_LMEDS -#define CV_FM_RANSAC CV_RANSAC - -enum -{ - CV_ITERATIVE = 0, - CV_EPNP = 1, // F.Moreno-Noguer, V.Lepetit and P.Fua "EPnP: Efficient Perspective-n-Point Camera Pose Estimation" - CV_P3P = 2 // X.S. Gao, X.-R. Hou, J. Tang, H.-F. Chang; "Complete Solution Classification for the Perspective-Three-Point Problem" -}; - -CVAPI(int) cvFindFundamentalMat( const CvMat* points1, const CvMat* points2, - CvMat* fundamental_matrix, - int method CV_DEFAULT(CV_FM_RANSAC), - double param1 CV_DEFAULT(3.), double param2 CV_DEFAULT(0.99), - CvMat* status CV_DEFAULT(NULL) ); - -/* For each input point on one of images - computes parameters of the corresponding - epipolar line on the other image */ -CVAPI(void) cvComputeCorrespondEpilines( const CvMat* points, - int which_image, - const CvMat* fundamental_matrix, - CvMat* correspondent_lines ); - -/* Triangulation functions */ - -CVAPI(void) cvTriangulatePoints(CvMat* projMatr1, CvMat* projMatr2, - CvMat* projPoints1, CvMat* projPoints2, - CvMat* points4D); - -CVAPI(void) cvCorrectMatches(CvMat* F, CvMat* points1, CvMat* points2, - CvMat* new_points1, CvMat* new_points2); - - -/* Computes the optimal new camera matrix according to the free scaling parameter alpha: - alpha=0 - only valid pixels will be retained in the undistorted image - alpha=1 - all the source image pixels will be retained in the undistorted image -*/ -CVAPI(void) cvGetOptimalNewCameraMatrix( const CvMat* camera_matrix, - const CvMat* dist_coeffs, - CvSize image_size, double alpha, - CvMat* new_camera_matrix, - CvSize new_imag_size CV_DEFAULT(cvSize(0,0)), - CvRect* valid_pixel_ROI CV_DEFAULT(0), - int center_principal_point CV_DEFAULT(0)); - -/* Converts rotation vector to rotation matrix or vice versa */ -CVAPI(int) cvRodrigues2( const CvMat* src, CvMat* dst, - CvMat* jacobian CV_DEFAULT(0) ); - -/* Finds perspective transformation between the object plane and image (view) plane */ -CVAPI(int) cvFindHomography( const CvMat* src_points, - const CvMat* dst_points, - CvMat* homography, - int method CV_DEFAULT(0), - double ransacReprojThreshold CV_DEFAULT(3), - CvMat* mask CV_DEFAULT(0)); - -/* Computes RQ decomposition for 3x3 matrices */ -CVAPI(void) cvRQDecomp3x3( const CvMat *matrixM, CvMat *matrixR, CvMat *matrixQ, - CvMat *matrixQx CV_DEFAULT(NULL), - CvMat *matrixQy CV_DEFAULT(NULL), - CvMat *matrixQz CV_DEFAULT(NULL), - CvPoint3D64f *eulerAngles CV_DEFAULT(NULL)); - -/* Computes projection matrix decomposition */ -CVAPI(void) cvDecomposeProjectionMatrix( const CvMat *projMatr, CvMat *calibMatr, - CvMat *rotMatr, CvMat *posVect, - CvMat *rotMatrX CV_DEFAULT(NULL), - CvMat *rotMatrY CV_DEFAULT(NULL), - CvMat *rotMatrZ CV_DEFAULT(NULL), - CvPoint3D64f *eulerAngles CV_DEFAULT(NULL)); - -/* Computes d(AB)/dA and d(AB)/dB */ -CVAPI(void) cvCalcMatMulDeriv( const CvMat* A, const CvMat* B, CvMat* dABdA, CvMat* dABdB ); - -/* Computes r3 = rodrigues(rodrigues(r2)*rodrigues(r1)), - t3 = rodrigues(r2)*t1 + t2 and the respective derivatives */ -CVAPI(void) cvComposeRT( const CvMat* _rvec1, const CvMat* _tvec1, - const CvMat* _rvec2, const CvMat* _tvec2, - CvMat* _rvec3, CvMat* _tvec3, - CvMat* dr3dr1 CV_DEFAULT(0), CvMat* dr3dt1 CV_DEFAULT(0), - CvMat* dr3dr2 CV_DEFAULT(0), CvMat* dr3dt2 CV_DEFAULT(0), - CvMat* dt3dr1 CV_DEFAULT(0), CvMat* dt3dt1 CV_DEFAULT(0), - CvMat* dt3dr2 CV_DEFAULT(0), CvMat* dt3dt2 CV_DEFAULT(0) ); - -/* Projects object points to the view plane using - the specified extrinsic and intrinsic camera parameters */ -CVAPI(void) cvProjectPoints2( const CvMat* object_points, const CvMat* rotation_vector, - const CvMat* translation_vector, const CvMat* camera_matrix, - const CvMat* distortion_coeffs, CvMat* image_points, - CvMat* dpdrot CV_DEFAULT(NULL), CvMat* dpdt CV_DEFAULT(NULL), - CvMat* dpdf CV_DEFAULT(NULL), CvMat* dpdc CV_DEFAULT(NULL), - CvMat* dpddist CV_DEFAULT(NULL), - double aspect_ratio CV_DEFAULT(0)); - -/* Finds extrinsic camera parameters from - a few known corresponding point pairs and intrinsic parameters */ -CVAPI(void) cvFindExtrinsicCameraParams2( const CvMat* object_points, - const CvMat* image_points, - const CvMat* camera_matrix, - const CvMat* distortion_coeffs, - CvMat* rotation_vector, - CvMat* translation_vector, - int use_extrinsic_guess CV_DEFAULT(0) ); - -/* Computes initial estimate of the intrinsic camera parameters - in case of planar calibration target (e.g. chessboard) */ -CVAPI(void) cvInitIntrinsicParams2D( const CvMat* object_points, - const CvMat* image_points, - const CvMat* npoints, CvSize image_size, - CvMat* camera_matrix, - double aspect_ratio CV_DEFAULT(1.) ); - -#define CV_CALIB_CB_ADAPTIVE_THRESH 1 -#define CV_CALIB_CB_NORMALIZE_IMAGE 2 -#define CV_CALIB_CB_FILTER_QUADS 4 -#define CV_CALIB_CB_FAST_CHECK 8 - -// Performs a fast check if a chessboard is in the input image. This is a workaround to -// a problem of cvFindChessboardCorners being slow on images with no chessboard -// - src: input image -// - size: chessboard size -// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called, -// 0 if there is no chessboard, -1 in case of error -CVAPI(int) cvCheckChessboard(IplImage* src, CvSize size); - - /* Detects corners on a chessboard calibration pattern */ -CVAPI(int) cvFindChessboardCorners( const void* image, CvSize pattern_size, - CvPoint2D32f* corners, - int* corner_count CV_DEFAULT(NULL), - int flags CV_DEFAULT(CV_CALIB_CB_ADAPTIVE_THRESH+CV_CALIB_CB_NORMALIZE_IMAGE) ); - -/* Draws individual chessboard corners or the whole chessboard detected */ -CVAPI(void) cvDrawChessboardCorners( CvArr* image, CvSize pattern_size, - CvPoint2D32f* corners, - int count, int pattern_was_found ); - -#define CV_CALIB_USE_INTRINSIC_GUESS 1 -#define CV_CALIB_FIX_ASPECT_RATIO 2 -#define CV_CALIB_FIX_PRINCIPAL_POINT 4 -#define CV_CALIB_ZERO_TANGENT_DIST 8 -#define CV_CALIB_FIX_FOCAL_LENGTH 16 -#define CV_CALIB_FIX_K1 32 -#define CV_CALIB_FIX_K2 64 -#define CV_CALIB_FIX_K3 128 -#define CV_CALIB_FIX_K4 2048 -#define CV_CALIB_FIX_K5 4096 -#define CV_CALIB_FIX_K6 8192 -#define CV_CALIB_RATIONAL_MODEL 16384 -#define CV_CALIB_THIN_PRISM_MODEL 32768 -#define CV_CALIB_FIX_S1_S2_S3_S4 65536 - - -/* Finds intrinsic and extrinsic camera parameters - from a few views of known calibration pattern */ -CVAPI(double) cvCalibrateCamera2( const CvMat* object_points, - const CvMat* image_points, - const CvMat* point_counts, - CvSize image_size, - CvMat* camera_matrix, - CvMat* distortion_coeffs, - CvMat* rotation_vectors CV_DEFAULT(NULL), - CvMat* translation_vectors CV_DEFAULT(NULL), - int flags CV_DEFAULT(0), - CvTermCriteria term_crit CV_DEFAULT(cvTermCriteria( - CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,DBL_EPSILON)) ); - -/* Computes various useful characteristics of the camera from the data computed by - cvCalibrateCamera2 */ -CVAPI(void) cvCalibrationMatrixValues( const CvMat *camera_matrix, - CvSize image_size, - double aperture_width CV_DEFAULT(0), - double aperture_height CV_DEFAULT(0), - double *fovx CV_DEFAULT(NULL), - double *fovy CV_DEFAULT(NULL), - double *focal_length CV_DEFAULT(NULL), - CvPoint2D64f *principal_point CV_DEFAULT(NULL), - double *pixel_aspect_ratio CV_DEFAULT(NULL)); - -#define CV_CALIB_FIX_INTRINSIC 256 -#define CV_CALIB_SAME_FOCAL_LENGTH 512 - -/* Computes the transformation from one camera coordinate system to another one - from a few correspondent views of the same calibration target. Optionally, calibrates - both cameras */ -CVAPI(double) cvStereoCalibrate( const CvMat* object_points, const CvMat* image_points1, - const CvMat* image_points2, const CvMat* npoints, - CvMat* camera_matrix1, CvMat* dist_coeffs1, - CvMat* camera_matrix2, CvMat* dist_coeffs2, - CvSize image_size, CvMat* R, CvMat* T, - CvMat* E CV_DEFAULT(0), CvMat* F CV_DEFAULT(0), - CvTermCriteria term_crit CV_DEFAULT(cvTermCriteria( - CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,1e-6)), - int flags CV_DEFAULT(CV_CALIB_FIX_INTRINSIC)); - -#define CV_CALIB_ZERO_DISPARITY 1024 - -/* Computes 3D rotations (+ optional shift) for each camera coordinate system to make both - views parallel (=> to make all the epipolar lines horizontal or vertical) */ -CVAPI(void) cvStereoRectify( const CvMat* camera_matrix1, const CvMat* camera_matrix2, - const CvMat* dist_coeffs1, const CvMat* dist_coeffs2, - CvSize image_size, const CvMat* R, const CvMat* T, - CvMat* R1, CvMat* R2, CvMat* P1, CvMat* P2, - CvMat* Q CV_DEFAULT(0), - int flags CV_DEFAULT(CV_CALIB_ZERO_DISPARITY), - double alpha CV_DEFAULT(-1), - CvSize new_image_size CV_DEFAULT(cvSize(0,0)), - CvRect* valid_pix_ROI1 CV_DEFAULT(0), - CvRect* valid_pix_ROI2 CV_DEFAULT(0)); - -/* Computes rectification transformations for uncalibrated pair of images using a set - of point correspondences */ -CVAPI(int) cvStereoRectifyUncalibrated( const CvMat* points1, const CvMat* points2, - const CvMat* F, CvSize img_size, - CvMat* H1, CvMat* H2, - double threshold CV_DEFAULT(5)); - - - -/* stereo correspondence parameters and functions */ - -#define CV_STEREO_BM_NORMALIZED_RESPONSE 0 -#define CV_STEREO_BM_XSOBEL 1 - -/* Block matching algorithm structure */ -typedef struct CvStereoBMState -{ - // pre-filtering (normalization of input images) - int preFilterType; // =CV_STEREO_BM_NORMALIZED_RESPONSE now - int preFilterSize; // averaging window size: ~5x5..21x21 - int preFilterCap; // the output of pre-filtering is clipped by [-preFilterCap,preFilterCap] - - // correspondence using Sum of Absolute Difference (SAD) - int SADWindowSize; // ~5x5..21x21 - int minDisparity; // minimum disparity (can be negative) - int numberOfDisparities; // maximum disparity - minimum disparity (> 0) - - // post-filtering - int textureThreshold; // the disparity is only computed for pixels - // with textured enough neighborhood - int uniquenessRatio; // accept the computed disparity d* only if - // SAD(d) >= SAD(d*)*(1 + uniquenessRatio/100.) - // for any d != d*+/-1 within the search range. - int speckleWindowSize; // disparity variation window - int speckleRange; // acceptable range of variation in window - - int trySmallerWindows; // if 1, the results may be more accurate, - // at the expense of slower processing - CvRect roi1, roi2; - int disp12MaxDiff; - - // temporary buffers - CvMat* preFilteredImg0; - CvMat* preFilteredImg1; - CvMat* slidingSumBuf; - CvMat* cost; - CvMat* disp; -} CvStereoBMState; - -#define CV_STEREO_BM_BASIC 0 -#define CV_STEREO_BM_FISH_EYE 1 -#define CV_STEREO_BM_NARROW 2 - -CVAPI(CvStereoBMState*) cvCreateStereoBMState(int preset CV_DEFAULT(CV_STEREO_BM_BASIC), - int numberOfDisparities CV_DEFAULT(0)); - -CVAPI(void) cvReleaseStereoBMState( CvStereoBMState** state ); - -CVAPI(void) cvFindStereoCorrespondenceBM( const CvArr* left, const CvArr* right, - CvArr* disparity, CvStereoBMState* state ); - -CVAPI(CvRect) cvGetValidDisparityROI( CvRect roi1, CvRect roi2, int minDisparity, - int numberOfDisparities, int SADWindowSize ); - -CVAPI(void) cvValidateDisparity( CvArr* disparity, const CvArr* cost, - int minDisparity, int numberOfDisparities, - int disp12MaxDiff CV_DEFAULT(1) ); - -/* Reprojects the computed disparity image to the 3D space using the specified 4x4 matrix */ -CVAPI(void) cvReprojectImageTo3D( const CvArr* disparityImage, - CvArr* _3dImage, const CvMat* Q, - int handleMissingValues CV_DEFAULT(0) ); - - -#ifdef __cplusplus -} - -////////////////////////////////////////////////////////////////////////////////////////// -class CV_EXPORTS CvLevMarq -{ -public: - CvLevMarq(); - CvLevMarq( int nparams, int nerrs, CvTermCriteria criteria= - cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON), - bool completeSymmFlag=false ); - ~CvLevMarq(); - void init( int nparams, int nerrs, CvTermCriteria criteria= - cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON), - bool completeSymmFlag=false ); - bool update( const CvMat*& param, CvMat*& J, CvMat*& err ); - bool updateAlt( const CvMat*& param, CvMat*& JtJ, CvMat*& JtErr, double*& errNorm ); - - void clear(); - void step(); - enum { DONE=0, STARTED=1, CALC_J=2, CHECK_ERR=3 }; - - cv::Ptr mask; - cv::Ptr prevParam; - cv::Ptr param; - cv::Ptr J; - cv::Ptr err; - cv::Ptr JtJ; - cv::Ptr JtJN; - cv::Ptr JtErr; - cv::Ptr JtJV; - cv::Ptr JtJW; - double prevErrNorm, errNorm; - int lambdaLg10; - CvTermCriteria criteria; - int state; - int iters; - bool completeSymmFlag; -}; - namespace cv { -//! converts rotation vector to rotation matrix or vice versa using Rodrigues transformation -CV_EXPORTS_W void Rodrigues(InputArray src, OutputArray dst, OutputArray jacobian=noArray()); //! type of the robust estimation algorithm -enum -{ - LMEDS=CV_LMEDS, //!< least-median algorithm - RANSAC=CV_RANSAC //!< RANSAC algorithm -}; +enum { LMEDS = 4, //!< least-median algorithm + RANSAC = 8 //!< RANSAC algorithm + }; + +enum { ITERATIVE = 0, + EPNP = 1, // F.Moreno-Noguer, V.Lepetit and P.Fua "EPnP: Efficient Perspective-n-Point Camera Pose Estimation" + P3P = 2 // X.S. Gao, X.-R. Hou, J. Tang, H.-F. Chang; "Complete Solution Classification for the Perspective-Three-Point Problem" + }; + +enum { CALIB_CB_ADAPTIVE_THRESH = 1, + CALIB_CB_NORMALIZE_IMAGE = 2, + CALIB_CB_FILTER_QUADS = 4, + CALIB_CB_FAST_CHECK = 8 + }; + +enum { CALIB_CB_SYMMETRIC_GRID = 1, + CALIB_CB_ASYMMETRIC_GRID = 2, + CALIB_CB_CLUSTERING = 4 + }; + +enum { CALIB_USE_INTRINSIC_GUESS = 0x00001, + CALIB_FIX_ASPECT_RATIO = 0x00002, + CALIB_FIX_PRINCIPAL_POINT = 0x00004, + CALIB_ZERO_TANGENT_DIST = 0x00008, + CALIB_FIX_FOCAL_LENGTH = 0x00010, + CALIB_FIX_K1 = 0x00020, + CALIB_FIX_K2 = 0x00040, + CALIB_FIX_K3 = 0x00080, + CALIB_FIX_K4 = 0x00800, + CALIB_FIX_K5 = 0x01000, + CALIB_FIX_K6 = 0x02000, + CALIB_RATIONAL_MODEL = 0x04000, + CALIB_THIN_PRISM_MODEL = 0x08000, + CALIB_FIX_S1_S2_S3_S4 = 0x10000, + // only for stereo + CALIB_FIX_INTRINSIC = 0x00100, + CALIB_SAME_FOCAL_LENGTH = 0x00200, + // for stereo rectification + CALIB_ZERO_DISPARITY = 0x00400 + }; + +//! the algorithm for finding fundamental matrix +enum { FM_7POINT = 1, //!< 7-point algorithm + FM_8POINT = 2, //!< 8-point algorithm + FM_LMEDS = 4, //!< least-median algorithm + FM_RANSAC = 8 //!< RANSAC algorithm + }; + + + +//! converts rotation vector to rotation matrix or vice versa using Rodrigues transformation +CV_EXPORTS_W void Rodrigues( InputArray src, OutputArray dst, OutputArray jacobian = noArray() ); //! computes the best-fit perspective transformation mapping srcPoints to dstPoints. CV_EXPORTS_W Mat findHomography( InputArray srcPoints, InputArray dstPoints, - int method=0, double ransacReprojThreshold=3, + int method = 0, double ransacReprojThreshold = 3, OutputArray mask=noArray()); //! variant of findHomography for backward compatibility CV_EXPORTS Mat findHomography( InputArray srcPoints, InputArray dstPoints, - OutputArray mask, int method=0, double ransacReprojThreshold=3); + OutputArray mask, int method = 0, double ransacReprojThreshold = 3 ); //! Computes RQ decomposition of 3x3 matrix CV_EXPORTS_W Vec3d RQDecomp3x3( InputArray src, OutputArray mtxR, OutputArray mtxQ, - OutputArray Qx=noArray(), - OutputArray Qy=noArray(), - OutputArray Qz=noArray()); + OutputArray Qx = noArray(), + OutputArray Qy = noArray(), + OutputArray Qz = noArray()); //! Decomposes the projection matrix into camera matrix and the rotation martix and the translation vector CV_EXPORTS_W void decomposeProjectionMatrix( InputArray projMatrix, OutputArray cameraMatrix, OutputArray rotMatrix, OutputArray transVect, - OutputArray rotMatrixX=noArray(), - OutputArray rotMatrixY=noArray(), - OutputArray rotMatrixZ=noArray(), - OutputArray eulerAngles=noArray() ); + OutputArray rotMatrixX = noArray(), + OutputArray rotMatrixY = noArray(), + OutputArray rotMatrixZ = noArray(), + OutputArray eulerAngles =noArray() ); //! computes derivatives of the matrix product w.r.t each of the multiplied matrix coefficients -CV_EXPORTS_W void matMulDeriv( InputArray A, InputArray B, - OutputArray dABdA, - OutputArray dABdB ); +CV_EXPORTS_W void matMulDeriv( InputArray A, InputArray B, OutputArray dABdA, OutputArray dABdB ); //! composes 2 [R|t] transformations together. Also computes the derivatives of the result w.r.t the arguments CV_EXPORTS_W void composeRT( InputArray rvec1, InputArray tvec1, InputArray rvec2, InputArray tvec2, OutputArray rvec3, OutputArray tvec3, - OutputArray dr3dr1=noArray(), OutputArray dr3dt1=noArray(), - OutputArray dr3dr2=noArray(), OutputArray dr3dt2=noArray(), - OutputArray dt3dr1=noArray(), OutputArray dt3dt1=noArray(), - OutputArray dt3dr2=noArray(), OutputArray dt3dt2=noArray() ); + OutputArray dr3dr1 = noArray(), OutputArray dr3dt1 = noArray(), + OutputArray dr3dr2 = noArray(), OutputArray dr3dt2 = noArray(), + OutputArray dt3dr1 = noArray(), OutputArray dt3dt1 = noArray(), + OutputArray dt3dr2 = noArray(), OutputArray dt3dt2 = noArray() ); //! projects points from the model coordinate space to the image coordinates. Also computes derivatives of the image coordinates w.r.t the intrinsic and extrinsic camera parameters CV_EXPORTS_W void projectPoints( InputArray objectPoints, InputArray rvec, InputArray tvec, InputArray cameraMatrix, InputArray distCoeffs, OutputArray imagePoints, - OutputArray jacobian=noArray(), - double aspectRatio=0 ); + OutputArray jacobian = noArray(), + double aspectRatio = 0 ); //! computes the camera pose from a few 3D points and the corresponding projections. The outliers are not handled. -enum -{ - ITERATIVE=CV_ITERATIVE, - EPNP=CV_EPNP, - P3P=CV_P3P -}; CV_EXPORTS_W bool solvePnP( InputArray objectPoints, InputArray imagePoints, InputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec, OutputArray tvec, - bool useExtrinsicGuess=false, int flags=ITERATIVE); + bool useExtrinsicGuess = false, int flags = ITERATIVE ); //! computes the camera pose from a few 3D points and the corresponding projections. The outliers are possible. -CV_EXPORTS_W void solvePnPRansac( InputArray objectPoints, - InputArray imagePoints, - InputArray cameraMatrix, - InputArray distCoeffs, - OutputArray rvec, - OutputArray tvec, - bool useExtrinsicGuess = false, - int iterationsCount = 100, - float reprojectionError = 8.0, - int minInliersCount = 100, - OutputArray inliers = noArray(), - int flags = ITERATIVE); +CV_EXPORTS_W void solvePnPRansac( InputArray objectPoints, InputArray imagePoints, + InputArray cameraMatrix, InputArray distCoeffs, + OutputArray rvec, OutputArray tvec, + bool useExtrinsicGuess = false, int iterationsCount = 100, + float reprojectionError = 8.0, int minInliersCount = 100, + OutputArray inliers = noArray(), int flags = ITERATIVE ); //! initializes camera matrix from a few 3D points and the corresponding projections. CV_EXPORTS_W Mat initCameraMatrix2D( InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, - Size imageSize, double aspectRatio=1. ); - -enum { CALIB_CB_ADAPTIVE_THRESH = 1, CALIB_CB_NORMALIZE_IMAGE = 2, - CALIB_CB_FILTER_QUADS = 4, CALIB_CB_FAST_CHECK = 8 }; + Size imageSize, double aspectRatio = 1.0 ); //! finds checkerboard pattern of the specified size in the image -CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize, - OutputArray corners, - int flags=CALIB_CB_ADAPTIVE_THRESH+CALIB_CB_NORMALIZE_IMAGE ); +CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize, OutputArray corners, + int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE ); //! finds subpixel-accurate positions of the chessboard corners -CV_EXPORTS bool find4QuadCornerSubpix(InputArray img, InputOutputArray corners, Size region_size); +CV_EXPORTS bool find4QuadCornerSubpix( InputArray img, InputOutputArray corners, Size region_size ); //! draws the checkerboard pattern (found or partly found) in the image CV_EXPORTS_W void drawChessboardCorners( InputOutputArray image, Size patternSize, InputArray corners, bool patternWasFound ); -enum { CALIB_CB_SYMMETRIC_GRID = 1, CALIB_CB_ASYMMETRIC_GRID = 2, - CALIB_CB_CLUSTERING = 4 }; - //! finds circles' grid pattern of the specified size in the image CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize, - OutputArray centers, int flags=CALIB_CB_SYMMETRIC_GRID, - const Ptr &blobDetector = new SimpleBlobDetector()); - -//! the deprecated function. Use findCirclesGrid() instead of it. -CV_EXPORTS_W bool findCirclesGridDefault( InputArray image, Size patternSize, - OutputArray centers, int flags=CALIB_CB_SYMMETRIC_GRID ); -enum -{ - CALIB_USE_INTRINSIC_GUESS = CV_CALIB_USE_INTRINSIC_GUESS, - CALIB_FIX_ASPECT_RATIO = CV_CALIB_FIX_ASPECT_RATIO, - CALIB_FIX_PRINCIPAL_POINT = CV_CALIB_FIX_PRINCIPAL_POINT, - CALIB_ZERO_TANGENT_DIST = CV_CALIB_ZERO_TANGENT_DIST, - CALIB_FIX_FOCAL_LENGTH = CV_CALIB_FIX_FOCAL_LENGTH, - CALIB_FIX_K1 = CV_CALIB_FIX_K1, - CALIB_FIX_K2 = CV_CALIB_FIX_K2, - CALIB_FIX_K3 = CV_CALIB_FIX_K3, - CALIB_FIX_K4 = CV_CALIB_FIX_K4, - CALIB_FIX_K5 = CV_CALIB_FIX_K5, - CALIB_FIX_K6 = CV_CALIB_FIX_K6, - CALIB_RATIONAL_MODEL = CV_CALIB_RATIONAL_MODEL, - CALIB_THIN_PRISM_MODEL = CV_CALIB_THIN_PRISM_MODEL, - CALIB_FIX_S1_S2_S3_S4=CV_CALIB_FIX_S1_S2_S3_S4, - // only for stereo - CALIB_FIX_INTRINSIC = CV_CALIB_FIX_INTRINSIC, - CALIB_SAME_FOCAL_LENGTH = CV_CALIB_SAME_FOCAL_LENGTH, - // for stereo rectification - CALIB_ZERO_DISPARITY = CV_CALIB_ZERO_DISPARITY -}; + OutputArray centers, int flags = CALIB_CB_SYMMETRIC_GRID, + const Ptr &blobDetector = makePtr()); //! finds intrinsic and extrinsic camera parameters from several fews of a known calibration pattern. CV_EXPORTS_W double calibrateCamera( InputArrayOfArrays objectPoints, - InputArrayOfArrays imagePoints, - Size imageSize, - InputOutputArray cameraMatrix, - InputOutputArray distCoeffs, + InputArrayOfArrays imagePoints, Size imageSize, + InputOutputArray cameraMatrix, InputOutputArray distCoeffs, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, - int flags=0, TermCriteria criteria = TermCriteria( - TermCriteria::COUNT+TermCriteria::EPS, 30, DBL_EPSILON) ); + int flags = 0, TermCriteria criteria = TermCriteria( + TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) ); //! computes several useful camera characteristics from the camera matrix, camera frame resolution and the physical sensor size. -CV_EXPORTS_W void calibrationMatrixValues( InputArray cameraMatrix, - Size imageSize, - double apertureWidth, - double apertureHeight, - CV_OUT double& fovx, - CV_OUT double& fovy, - CV_OUT double& focalLength, - CV_OUT Point2d& principalPoint, - CV_OUT double& aspectRatio ); +CV_EXPORTS_W void calibrationMatrixValues( InputArray cameraMatrix, Size imageSize, + double apertureWidth, double apertureHeight, + CV_OUT double& fovx, CV_OUT double& fovy, + CV_OUT double& focalLength, CV_OUT Point2d& principalPoint, + CV_OUT double& aspectRatio ); //! finds intrinsic and extrinsic parameters of a stereo camera CV_EXPORTS_W double stereoCalibrate( InputArrayOfArrays objectPoints, - InputArrayOfArrays imagePoints1, - InputArrayOfArrays imagePoints2, - InputOutputArray cameraMatrix1, - InputOutputArray distCoeffs1, - InputOutputArray cameraMatrix2, - InputOutputArray distCoeffs2, - Size imageSize, OutputArray R, - OutputArray T, OutputArray E, OutputArray F, + InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, + InputOutputArray cameraMatrix1, InputOutputArray distCoeffs1, + InputOutputArray cameraMatrix2, InputOutputArray distCoeffs2, + Size imageSize, OutputArray R,OutputArray T, OutputArray E, OutputArray F, TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 1e-6), - int flags=CALIB_FIX_INTRINSIC ); + int flags = CALIB_FIX_INTRINSIC ); //! computes the rectification transformation for a stereo camera from its intrinsic and extrinsic parameters CV_EXPORTS_W void stereoRectify( InputArray cameraMatrix1, InputArray distCoeffs1, - InputArray cameraMatrix2, InputArray distCoeffs2, - Size imageSize, InputArray R, InputArray T, - OutputArray R1, OutputArray R2, - OutputArray P1, OutputArray P2, - OutputArray Q, int flags=CALIB_ZERO_DISPARITY, - double alpha=-1, Size newImageSize=Size(), - CV_OUT Rect* validPixROI1=0, CV_OUT Rect* validPixROI2=0 ); + InputArray cameraMatrix2, InputArray distCoeffs2, + Size imageSize, InputArray R, InputArray T, + OutputArray R1, OutputArray R2, + OutputArray P1, OutputArray P2, + OutputArray Q, int flags = CALIB_ZERO_DISPARITY, + double alpha = -1, Size newImageSize = Size(), + CV_OUT Rect* validPixROI1 = 0, CV_OUT Rect* validPixROI2 = 0 ); //! computes the rectification transformation for an uncalibrated stereo camera (zero distortion is assumed) CV_EXPORTS_W bool stereoRectifyUncalibrated( InputArray points1, InputArray points2, InputArray F, Size imgSize, OutputArray H1, OutputArray H2, - double threshold=5 ); + double threshold = 5 ); //! computes the rectification transformations for 3-head camera, where all the heads are on the same line. CV_EXPORTS_W float rectify3Collinear( InputArray cameraMatrix1, InputArray distCoeffs1, @@ -611,8 +237,9 @@ CV_EXPORTS_W float rectify3Collinear( InputArray cameraMatrix1, InputArray distC //! returns the optimal new camera matrix CV_EXPORTS_W Mat getOptimalNewCameraMatrix( InputArray cameraMatrix, InputArray distCoeffs, - Size imageSize, double alpha, Size newImgSize=Size(), - CV_OUT Rect* validPixROI=0, bool centerPrincipalPoint=false); + Size imageSize, double alpha, Size newImgSize = Size(), + CV_OUT Rect* validPixROI = 0, + bool centerPrincipalPoint = false); //! converts point coordinates from normal pixel coordinates to homogeneous coordinates ((x,y)->(x,y,1)) CV_EXPORTS_W void convertPointsToHomogeneous( InputArray src, OutputArray dst ); @@ -623,44 +250,36 @@ CV_EXPORTS_W void convertPointsFromHomogeneous( InputArray src, OutputArray dst //! for backward compatibility CV_EXPORTS void convertPointsHomogeneous( InputArray src, OutputArray dst ); -//! the algorithm for finding fundamental matrix -enum -{ - FM_7POINT = CV_FM_7POINT, //!< 7-point algorithm - FM_8POINT = CV_FM_8POINT, //!< 8-point algorithm - FM_LMEDS = CV_FM_LMEDS, //!< least-median algorithm - FM_RANSAC = CV_FM_RANSAC //!< RANSAC algorithm -}; - //! finds fundamental matrix from a set of corresponding 2D points CV_EXPORTS_W Mat findFundamentalMat( InputArray points1, InputArray points2, - int method=FM_RANSAC, - double param1=3., double param2=0.99, - OutputArray mask=noArray()); + int method = FM_RANSAC, + double param1 = 3., double param2 = 0.99, + OutputArray mask = noArray() ); //! variant of findFundamentalMat for backward compatibility CV_EXPORTS Mat findFundamentalMat( InputArray points1, InputArray points2, - OutputArray mask, int method=FM_RANSAC, - double param1=3., double param2=0.99); + OutputArray mask, int method = FM_RANSAC, + double param1 = 3., double param2 = 0.99 ); //! finds essential matrix from a set of corresponding 2D points using five-point algorithm -CV_EXPORTS Mat findEssentialMat( InputArray points1, InputArray points2, double focal = 1.0, Point2d pp = Point2d(0, 0), - int method = CV_RANSAC, - double prob = 0.999, double threshold = 1.0, OutputArray mask = noArray() ); +CV_EXPORTS_W Mat findEssentialMat( InputArray points1, InputArray points2, + double focal = 1.0, Point2d pp = Point2d(0, 0), + int method = RANSAC, double prob = 0.999, + double threshold = 1.0, OutputArray mask = noArray() ); //! decompose essential matrix to possible rotation matrix and one translation vector -CV_EXPORTS void decomposeEssentialMat( InputArray E, OutputArray R1, OutputArray R2, OutputArray t ); +CV_EXPORTS_W void decomposeEssentialMat( InputArray E, OutputArray R1, OutputArray R2, OutputArray t ); //! recover relative camera pose from a set of corresponding 2D points -CV_EXPORTS int recoverPose( InputArray E, InputArray points1, InputArray points2, OutputArray R, OutputArray t, +CV_EXPORTS_W int recoverPose( InputArray E, InputArray points1, InputArray points2, + OutputArray R, OutputArray t, double focal = 1.0, Point2d pp = Point2d(0, 0), - InputOutputArray mask = noArray()); + InputOutputArray mask = noArray() ); //! finds coordinates of epipolar lines corresponding the specified points -CV_EXPORTS void computeCorrespondEpilines( InputArray points, - int whichImage, InputArray F, - OutputArray lines ); +CV_EXPORTS_W void computeCorrespondEpilines( InputArray points, int whichImage, + InputArray F, OutputArray lines ); CV_EXPORTS_W void triangulatePoints( InputArray projMatr1, InputArray projMatr2, InputArray projPoints1, InputArray projPoints2, @@ -669,89 +288,10 @@ CV_EXPORTS_W void triangulatePoints( InputArray projMatr1, InputArray projMatr2, CV_EXPORTS_W void correctMatches( InputArray F, InputArray points1, InputArray points2, OutputArray newPoints1, OutputArray newPoints2 ); - -class CV_EXPORTS_W StereoMatcher : public Algorithm -{ -public: - CV_WRAP virtual void compute( InputArray left, InputArray right, - OutputArray disparity ) = 0; -}; - -enum { STEREO_DISP_SCALE=16, STEREO_PREFILTER_NORMALIZED_RESPONSE = 0, STEREO_PREFILTER_XSOBEL = 1 }; - -CV_EXPORTS Ptr createStereoBM(int numDisparities=0, int SADWindowSize=21); - -CV_EXPORTS Ptr createStereoSGBM(int minDisparity, int numDisparities, int SADWindowSize, - int P1=0, int P2=0, int disp12MaxDiff=0, - int preFilterCap=0, int uniquenessRatio=0, - int speckleWindowSize=0, int speckleRange=0, - bool fullDP=false); - -template<> CV_EXPORTS void Ptr::delete_obj(); - -// to be moved to "compat" module -class CV_EXPORTS_W StereoBM -{ -public: - enum { PREFILTER_NORMALIZED_RESPONSE = 0, PREFILTER_XSOBEL = 1, - BASIC_PRESET=0, FISH_EYE_PRESET=1, NARROW_PRESET=2 }; - - //! the default constructor - CV_WRAP StereoBM(); - //! the full constructor taking the camera-specific preset, number of disparities and the SAD window size - CV_WRAP StereoBM(int preset, int ndisparities=0, int SADWindowSize=21); - //! the method that reinitializes the state. The previous content is destroyed - void init(int preset, int ndisparities=0, int SADWindowSize=21); - //! the stereo correspondence operator. Finds the disparity for the specified rectified stereo pair - CV_WRAP_AS(compute) void operator()( InputArray left, InputArray right, - OutputArray disparity, int disptype=CV_16S ); - - //! pointer to the underlying CvStereoBMState - Ptr state; -}; - - -// to be moved to "compat" module -class CV_EXPORTS_W StereoSGBM -{ -public: - enum { DISP_SHIFT=4, DISP_SCALE = (1< sm; -}; - //! filters off speckles (small regions of incorrectly computed disparity) -CV_EXPORTS_W void filterSpeckles( InputOutputArray img, double newVal, int maxSpeckleSize, double maxDiff, - InputOutputArray buf=noArray() ); +CV_EXPORTS_W void filterSpeckles( InputOutputArray img, double newVal, + int maxSpeckleSize, double maxDiff, + InputOutputArray buf = noArray() ); //! computes valid disparity ROI from the valid ROIs of the rectified images (that are returned by cv::stereoRectify()) CV_EXPORTS_W Rect getValidDisparityROI( Rect roi1, Rect roi2, @@ -761,20 +301,116 @@ CV_EXPORTS_W Rect getValidDisparityROI( Rect roi1, Rect roi2, //! validates disparity using the left-right check. The matrix "cost" should be computed by the stereo correspondence algorithm CV_EXPORTS_W void validateDisparity( InputOutputArray disparity, InputArray cost, int minDisparity, int numberOfDisparities, - int disp12MaxDisp=1 ); + int disp12MaxDisp = 1 ); //! reprojects disparity image to 3D: (x,y,d)->(X,Y,Z) using the matrix Q returned by cv::stereoRectify CV_EXPORTS_W void reprojectImageTo3D( InputArray disparity, OutputArray _3dImage, InputArray Q, - bool handleMissingValues=false, - int ddepth=-1 ); + bool handleMissingValues = false, + int ddepth = -1 ); CV_EXPORTS_W int estimateAffine3D(InputArray src, InputArray dst, OutputArray out, OutputArray inliers, - double ransacThreshold=3, double confidence=0.99); + double ransacThreshold = 3, double confidence = 0.99); -} - -#endif + + +class CV_EXPORTS_W StereoMatcher : public Algorithm +{ +public: + enum { DISP_SHIFT = 4, + DISP_SCALE = (1 << DISP_SHIFT) + }; + + CV_WRAP virtual void compute( InputArray left, InputArray right, + OutputArray disparity ) = 0; + + CV_WRAP virtual int getMinDisparity() const = 0; + CV_WRAP virtual void setMinDisparity(int minDisparity) = 0; + + CV_WRAP virtual int getNumDisparities() const = 0; + CV_WRAP virtual void setNumDisparities(int numDisparities) = 0; + + CV_WRAP virtual int getBlockSize() const = 0; + CV_WRAP virtual void setBlockSize(int blockSize) = 0; + + CV_WRAP virtual int getSpeckleWindowSize() const = 0; + CV_WRAP virtual void setSpeckleWindowSize(int speckleWindowSize) = 0; + + CV_WRAP virtual int getSpeckleRange() const = 0; + CV_WRAP virtual void setSpeckleRange(int speckleRange) = 0; + + CV_WRAP virtual int getDisp12MaxDiff() const = 0; + CV_WRAP virtual void setDisp12MaxDiff(int disp12MaxDiff) = 0; +}; + + + +class CV_EXPORTS_W StereoBM : public StereoMatcher +{ +public: + enum { PREFILTER_NORMALIZED_RESPONSE = 0, + PREFILTER_XSOBEL = 1 + }; + + CV_WRAP virtual int getPreFilterType() const = 0; + CV_WRAP virtual void setPreFilterType(int preFilterType) = 0; + + CV_WRAP virtual int getPreFilterSize() const = 0; + CV_WRAP virtual void setPreFilterSize(int preFilterSize) = 0; + + CV_WRAP virtual int getPreFilterCap() const = 0; + CV_WRAP virtual void setPreFilterCap(int preFilterCap) = 0; + + CV_WRAP virtual int getTextureThreshold() const = 0; + CV_WRAP virtual void setTextureThreshold(int textureThreshold) = 0; + + CV_WRAP virtual int getUniquenessRatio() const = 0; + CV_WRAP virtual void setUniquenessRatio(int uniquenessRatio) = 0; + + CV_WRAP virtual int getSmallerBlockSize() const = 0; + CV_WRAP virtual void setSmallerBlockSize(int blockSize) = 0; + + CV_WRAP virtual Rect getROI1() const = 0; + CV_WRAP virtual void setROI1(Rect roi1) = 0; + + CV_WRAP virtual Rect getROI2() const = 0; + CV_WRAP virtual void setROI2(Rect roi2) = 0; +}; + +CV_EXPORTS_W Ptr createStereoBM(int numDisparities = 0, int blockSize = 21); + + +class CV_EXPORTS_W StereoSGBM : public StereoMatcher +{ +public: + enum { MODE_SGBM = 0, + MODE_HH = 1 + }; + + CV_WRAP virtual int getPreFilterCap() const = 0; + CV_WRAP virtual void setPreFilterCap(int preFilterCap) = 0; + + CV_WRAP virtual int getUniquenessRatio() const = 0; + CV_WRAP virtual void setUniquenessRatio(int uniquenessRatio) = 0; + + CV_WRAP virtual int getP1() const = 0; + CV_WRAP virtual void setP1(int P1) = 0; + + CV_WRAP virtual int getP2() const = 0; + CV_WRAP virtual void setP2(int P2) = 0; + + CV_WRAP virtual int getMode() const = 0; + CV_WRAP virtual void setMode(int mode) = 0; +}; + + +CV_EXPORTS_W Ptr createStereoSGBM(int minDisparity, int numDisparities, int blockSize, + int P1 = 0, int P2 = 0, int disp12MaxDiff = 0, + int preFilterCap = 0, int uniquenessRatio = 0, + int speckleWindowSize = 0, int speckleRange = 0, + int mode = StereoSGBM::MODE_SGBM); + +} // cv #endif diff --git a/modules/calib3d/include/opencv2/calib3d/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d/calib3d.hpp index 302de229bd..b3da45edd5 100644 --- a/modules/calib3d/include/opencv2/calib3d/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d/calib3d.hpp @@ -45,4 +45,4 @@ #error this is a compatibility header which should not be used inside the OpenCV library #endif -#include "opencv2/calib3d.hpp" \ No newline at end of file +#include "opencv2/calib3d.hpp" diff --git a/modules/calib3d/include/opencv2/calib3d/calib3d_c.h b/modules/calib3d/include/opencv2/calib3d/calib3d_c.h new file mode 100644 index 0000000000..a505d526db --- /dev/null +++ b/modules/calib3d/include/opencv2/calib3d/calib3d_c.h @@ -0,0 +1,413 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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_CALIB3D_C_H__ +#define __OPENCV_CALIB3D_C_H__ + +#include "opencv2/core/core_c.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************************\ +* Camera Calibration, Pose Estimation and Stereo * +\****************************************************************************************/ + +typedef struct CvPOSITObject CvPOSITObject; + +/* Allocates and initializes CvPOSITObject structure before doing cvPOSIT */ +CVAPI(CvPOSITObject*) cvCreatePOSITObject( CvPoint3D32f* points, int point_count ); + + +/* Runs POSIT (POSe from ITeration) algorithm for determining 3d position of + an object given its model and projection in a weak-perspective case */ +CVAPI(void) cvPOSIT( CvPOSITObject* posit_object, CvPoint2D32f* image_points, + double focal_length, CvTermCriteria criteria, + float* rotation_matrix, float* translation_vector); + +/* Releases CvPOSITObject structure */ +CVAPI(void) cvReleasePOSITObject( CvPOSITObject** posit_object ); + +/* updates the number of RANSAC iterations */ +CVAPI(int) cvRANSACUpdateNumIters( double p, double err_prob, + int model_points, int max_iters ); + +CVAPI(void) cvConvertPointsHomogeneous( const CvMat* src, CvMat* dst ); + +/* Calculates fundamental matrix given a set of corresponding points */ +#define CV_FM_7POINT 1 +#define CV_FM_8POINT 2 + +#define CV_LMEDS 4 +#define CV_RANSAC 8 + +#define CV_FM_LMEDS_ONLY CV_LMEDS +#define CV_FM_RANSAC_ONLY CV_RANSAC +#define CV_FM_LMEDS CV_LMEDS +#define CV_FM_RANSAC CV_RANSAC + +enum +{ + CV_ITERATIVE = 0, + CV_EPNP = 1, // F.Moreno-Noguer, V.Lepetit and P.Fua "EPnP: Efficient Perspective-n-Point Camera Pose Estimation" + CV_P3P = 2 // X.S. Gao, X.-R. Hou, J. Tang, H.-F. Chang; "Complete Solution Classification for the Perspective-Three-Point Problem" +}; + +CVAPI(int) cvFindFundamentalMat( const CvMat* points1, const CvMat* points2, + CvMat* fundamental_matrix, + int method CV_DEFAULT(CV_FM_RANSAC), + double param1 CV_DEFAULT(3.), double param2 CV_DEFAULT(0.99), + CvMat* status CV_DEFAULT(NULL) ); + +/* For each input point on one of images + computes parameters of the corresponding + epipolar line on the other image */ +CVAPI(void) cvComputeCorrespondEpilines( const CvMat* points, + int which_image, + const CvMat* fundamental_matrix, + CvMat* correspondent_lines ); + +/* Triangulation functions */ + +CVAPI(void) cvTriangulatePoints(CvMat* projMatr1, CvMat* projMatr2, + CvMat* projPoints1, CvMat* projPoints2, + CvMat* points4D); + +CVAPI(void) cvCorrectMatches(CvMat* F, CvMat* points1, CvMat* points2, + CvMat* new_points1, CvMat* new_points2); + + +/* Computes the optimal new camera matrix according to the free scaling parameter alpha: + alpha=0 - only valid pixels will be retained in the undistorted image + alpha=1 - all the source image pixels will be retained in the undistorted image +*/ +CVAPI(void) cvGetOptimalNewCameraMatrix( const CvMat* camera_matrix, + const CvMat* dist_coeffs, + CvSize image_size, double alpha, + CvMat* new_camera_matrix, + CvSize new_imag_size CV_DEFAULT(cvSize(0,0)), + CvRect* valid_pixel_ROI CV_DEFAULT(0), + int center_principal_point CV_DEFAULT(0)); + +/* Converts rotation vector to rotation matrix or vice versa */ +CVAPI(int) cvRodrigues2( const CvMat* src, CvMat* dst, + CvMat* jacobian CV_DEFAULT(0) ); + +/* Finds perspective transformation between the object plane and image (view) plane */ +CVAPI(int) cvFindHomography( const CvMat* src_points, + const CvMat* dst_points, + CvMat* homography, + int method CV_DEFAULT(0), + double ransacReprojThreshold CV_DEFAULT(3), + CvMat* mask CV_DEFAULT(0)); + +/* Computes RQ decomposition for 3x3 matrices */ +CVAPI(void) cvRQDecomp3x3( const CvMat *matrixM, CvMat *matrixR, CvMat *matrixQ, + CvMat *matrixQx CV_DEFAULT(NULL), + CvMat *matrixQy CV_DEFAULT(NULL), + CvMat *matrixQz CV_DEFAULT(NULL), + CvPoint3D64f *eulerAngles CV_DEFAULT(NULL)); + +/* Computes projection matrix decomposition */ +CVAPI(void) cvDecomposeProjectionMatrix( const CvMat *projMatr, CvMat *calibMatr, + CvMat *rotMatr, CvMat *posVect, + CvMat *rotMatrX CV_DEFAULT(NULL), + CvMat *rotMatrY CV_DEFAULT(NULL), + CvMat *rotMatrZ CV_DEFAULT(NULL), + CvPoint3D64f *eulerAngles CV_DEFAULT(NULL)); + +/* Computes d(AB)/dA and d(AB)/dB */ +CVAPI(void) cvCalcMatMulDeriv( const CvMat* A, const CvMat* B, CvMat* dABdA, CvMat* dABdB ); + +/* Computes r3 = rodrigues(rodrigues(r2)*rodrigues(r1)), + t3 = rodrigues(r2)*t1 + t2 and the respective derivatives */ +CVAPI(void) cvComposeRT( const CvMat* _rvec1, const CvMat* _tvec1, + const CvMat* _rvec2, const CvMat* _tvec2, + CvMat* _rvec3, CvMat* _tvec3, + CvMat* dr3dr1 CV_DEFAULT(0), CvMat* dr3dt1 CV_DEFAULT(0), + CvMat* dr3dr2 CV_DEFAULT(0), CvMat* dr3dt2 CV_DEFAULT(0), + CvMat* dt3dr1 CV_DEFAULT(0), CvMat* dt3dt1 CV_DEFAULT(0), + CvMat* dt3dr2 CV_DEFAULT(0), CvMat* dt3dt2 CV_DEFAULT(0) ); + +/* Projects object points to the view plane using + the specified extrinsic and intrinsic camera parameters */ +CVAPI(void) cvProjectPoints2( const CvMat* object_points, const CvMat* rotation_vector, + const CvMat* translation_vector, const CvMat* camera_matrix, + const CvMat* distortion_coeffs, CvMat* image_points, + CvMat* dpdrot CV_DEFAULT(NULL), CvMat* dpdt CV_DEFAULT(NULL), + CvMat* dpdf CV_DEFAULT(NULL), CvMat* dpdc CV_DEFAULT(NULL), + CvMat* dpddist CV_DEFAULT(NULL), + double aspect_ratio CV_DEFAULT(0)); + +/* Finds extrinsic camera parameters from + a few known corresponding point pairs and intrinsic parameters */ +CVAPI(void) cvFindExtrinsicCameraParams2( const CvMat* object_points, + const CvMat* image_points, + const CvMat* camera_matrix, + const CvMat* distortion_coeffs, + CvMat* rotation_vector, + CvMat* translation_vector, + int use_extrinsic_guess CV_DEFAULT(0) ); + +/* Computes initial estimate of the intrinsic camera parameters + in case of planar calibration target (e.g. chessboard) */ +CVAPI(void) cvInitIntrinsicParams2D( const CvMat* object_points, + const CvMat* image_points, + const CvMat* npoints, CvSize image_size, + CvMat* camera_matrix, + double aspect_ratio CV_DEFAULT(1.) ); + +#define CV_CALIB_CB_ADAPTIVE_THRESH 1 +#define CV_CALIB_CB_NORMALIZE_IMAGE 2 +#define CV_CALIB_CB_FILTER_QUADS 4 +#define CV_CALIB_CB_FAST_CHECK 8 + +// Performs a fast check if a chessboard is in the input image. This is a workaround to +// a problem of cvFindChessboardCorners being slow on images with no chessboard +// - src: input image +// - size: chessboard size +// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called, +// 0 if there is no chessboard, -1 in case of error +CVAPI(int) cvCheckChessboard(IplImage* src, CvSize size); + + /* Detects corners on a chessboard calibration pattern */ +CVAPI(int) cvFindChessboardCorners( const void* image, CvSize pattern_size, + CvPoint2D32f* corners, + int* corner_count CV_DEFAULT(NULL), + int flags CV_DEFAULT(CV_CALIB_CB_ADAPTIVE_THRESH+CV_CALIB_CB_NORMALIZE_IMAGE) ); + +/* Draws individual chessboard corners or the whole chessboard detected */ +CVAPI(void) cvDrawChessboardCorners( CvArr* image, CvSize pattern_size, + CvPoint2D32f* corners, + int count, int pattern_was_found ); + +#define CV_CALIB_USE_INTRINSIC_GUESS 1 +#define CV_CALIB_FIX_ASPECT_RATIO 2 +#define CV_CALIB_FIX_PRINCIPAL_POINT 4 +#define CV_CALIB_ZERO_TANGENT_DIST 8 +#define CV_CALIB_FIX_FOCAL_LENGTH 16 +#define CV_CALIB_FIX_K1 32 +#define CV_CALIB_FIX_K2 64 +#define CV_CALIB_FIX_K3 128 +#define CV_CALIB_FIX_K4 2048 +#define CV_CALIB_FIX_K5 4096 +#define CV_CALIB_FIX_K6 8192 +#define CV_CALIB_RATIONAL_MODEL 16384 +#define CV_CALIB_THIN_PRISM_MODEL 32768 +#define CV_CALIB_FIX_S1_S2_S3_S4 65536 + + +/* Finds intrinsic and extrinsic camera parameters + from a few views of known calibration pattern */ +CVAPI(double) cvCalibrateCamera2( const CvMat* object_points, + const CvMat* image_points, + const CvMat* point_counts, + CvSize image_size, + CvMat* camera_matrix, + CvMat* distortion_coeffs, + CvMat* rotation_vectors CV_DEFAULT(NULL), + CvMat* translation_vectors CV_DEFAULT(NULL), + int flags CV_DEFAULT(0), + CvTermCriteria term_crit CV_DEFAULT(cvTermCriteria( + CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,DBL_EPSILON)) ); + +/* Computes various useful characteristics of the camera from the data computed by + cvCalibrateCamera2 */ +CVAPI(void) cvCalibrationMatrixValues( const CvMat *camera_matrix, + CvSize image_size, + double aperture_width CV_DEFAULT(0), + double aperture_height CV_DEFAULT(0), + double *fovx CV_DEFAULT(NULL), + double *fovy CV_DEFAULT(NULL), + double *focal_length CV_DEFAULT(NULL), + CvPoint2D64f *principal_point CV_DEFAULT(NULL), + double *pixel_aspect_ratio CV_DEFAULT(NULL)); + +#define CV_CALIB_FIX_INTRINSIC 256 +#define CV_CALIB_SAME_FOCAL_LENGTH 512 + +/* Computes the transformation from one camera coordinate system to another one + from a few correspondent views of the same calibration target. Optionally, calibrates + both cameras */ +CVAPI(double) cvStereoCalibrate( const CvMat* object_points, const CvMat* image_points1, + const CvMat* image_points2, const CvMat* npoints, + CvMat* camera_matrix1, CvMat* dist_coeffs1, + CvMat* camera_matrix2, CvMat* dist_coeffs2, + CvSize image_size, CvMat* R, CvMat* T, + CvMat* E CV_DEFAULT(0), CvMat* F CV_DEFAULT(0), + CvTermCriteria term_crit CV_DEFAULT(cvTermCriteria( + CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,1e-6)), + int flags CV_DEFAULT(CV_CALIB_FIX_INTRINSIC)); + +#define CV_CALIB_ZERO_DISPARITY 1024 + +/* Computes 3D rotations (+ optional shift) for each camera coordinate system to make both + views parallel (=> to make all the epipolar lines horizontal or vertical) */ +CVAPI(void) cvStereoRectify( const CvMat* camera_matrix1, const CvMat* camera_matrix2, + const CvMat* dist_coeffs1, const CvMat* dist_coeffs2, + CvSize image_size, const CvMat* R, const CvMat* T, + CvMat* R1, CvMat* R2, CvMat* P1, CvMat* P2, + CvMat* Q CV_DEFAULT(0), + int flags CV_DEFAULT(CV_CALIB_ZERO_DISPARITY), + double alpha CV_DEFAULT(-1), + CvSize new_image_size CV_DEFAULT(cvSize(0,0)), + CvRect* valid_pix_ROI1 CV_DEFAULT(0), + CvRect* valid_pix_ROI2 CV_DEFAULT(0)); + +/* Computes rectification transformations for uncalibrated pair of images using a set + of point correspondences */ +CVAPI(int) cvStereoRectifyUncalibrated( const CvMat* points1, const CvMat* points2, + const CvMat* F, CvSize img_size, + CvMat* H1, CvMat* H2, + double threshold CV_DEFAULT(5)); + + + +/* stereo correspondence parameters and functions */ + +#define CV_STEREO_BM_NORMALIZED_RESPONSE 0 +#define CV_STEREO_BM_XSOBEL 1 + +/* Block matching algorithm structure */ +typedef struct CvStereoBMState +{ + // pre-filtering (normalization of input images) + int preFilterType; // =CV_STEREO_BM_NORMALIZED_RESPONSE now + int preFilterSize; // averaging window size: ~5x5..21x21 + int preFilterCap; // the output of pre-filtering is clipped by [-preFilterCap,preFilterCap] + + // correspondence using Sum of Absolute Difference (SAD) + int SADWindowSize; // ~5x5..21x21 + int minDisparity; // minimum disparity (can be negative) + int numberOfDisparities; // maximum disparity - minimum disparity (> 0) + + // post-filtering + int textureThreshold; // the disparity is only computed for pixels + // with textured enough neighborhood + int uniquenessRatio; // accept the computed disparity d* only if + // SAD(d) >= SAD(d*)*(1 + uniquenessRatio/100.) + // for any d != d*+/-1 within the search range. + int speckleWindowSize; // disparity variation window + int speckleRange; // acceptable range of variation in window + + int trySmallerWindows; // if 1, the results may be more accurate, + // at the expense of slower processing + CvRect roi1, roi2; + int disp12MaxDiff; + + // temporary buffers + CvMat* preFilteredImg0; + CvMat* preFilteredImg1; + CvMat* slidingSumBuf; + CvMat* cost; + CvMat* disp; +} CvStereoBMState; + +#define CV_STEREO_BM_BASIC 0 +#define CV_STEREO_BM_FISH_EYE 1 +#define CV_STEREO_BM_NARROW 2 + +CVAPI(CvStereoBMState*) cvCreateStereoBMState(int preset CV_DEFAULT(CV_STEREO_BM_BASIC), + int numberOfDisparities CV_DEFAULT(0)); + +CVAPI(void) cvReleaseStereoBMState( CvStereoBMState** state ); + +CVAPI(void) cvFindStereoCorrespondenceBM( const CvArr* left, const CvArr* right, + CvArr* disparity, CvStereoBMState* state ); + +CVAPI(CvRect) cvGetValidDisparityROI( CvRect roi1, CvRect roi2, int minDisparity, + int numberOfDisparities, int SADWindowSize ); + +CVAPI(void) cvValidateDisparity( CvArr* disparity, const CvArr* cost, + int minDisparity, int numberOfDisparities, + int disp12MaxDiff CV_DEFAULT(1) ); + +/* Reprojects the computed disparity image to the 3D space using the specified 4x4 matrix */ +CVAPI(void) cvReprojectImageTo3D( const CvArr* disparityImage, + CvArr* _3dImage, const CvMat* Q, + int handleMissingValues CV_DEFAULT(0) ); + +#ifdef __cplusplus +} // extern "C" + +////////////////////////////////////////////////////////////////////////////////////////// +class CV_EXPORTS CvLevMarq +{ +public: + CvLevMarq(); + CvLevMarq( int nparams, int nerrs, CvTermCriteria criteria= + cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON), + bool completeSymmFlag=false ); + ~CvLevMarq(); + void init( int nparams, int nerrs, CvTermCriteria criteria= + cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON), + bool completeSymmFlag=false ); + bool update( const CvMat*& param, CvMat*& J, CvMat*& err ); + bool updateAlt( const CvMat*& param, CvMat*& JtJ, CvMat*& JtErr, double*& errNorm ); + + void clear(); + void step(); + enum { DONE=0, STARTED=1, CALC_J=2, CHECK_ERR=3 }; + + cv::Ptr mask; + cv::Ptr prevParam; + cv::Ptr param; + cv::Ptr J; + cv::Ptr err; + cv::Ptr JtJ; + cv::Ptr JtJN; + cv::Ptr JtErr; + cv::Ptr JtJV; + cv::Ptr JtJW; + double prevErrNorm, errNorm; + int lambdaLg10; + CvTermCriteria criteria; + int state; + int iters; + bool completeSymmFlag; +}; + +#endif + +#endif /* __OPENCV_CALIB3D_C_H__ */ diff --git a/modules/calib3d/perf/perf_pnp.cpp b/modules/calib3d/perf/perf_pnp.cpp index e0ffd70cfb..7a7acb052d 100644 --- a/modules/calib3d/perf/perf_pnp.cpp +++ b/modules/calib3d/perf/perf_pnp.cpp @@ -1,5 +1,8 @@ #include "perf_precomp.hpp" -#include "opencv2/core/internal.hpp" + +#ifdef HAVE_TBB +#include "tbb/task_scheduler_init.h" +#endif using namespace std; using namespace cv; @@ -7,7 +10,7 @@ using namespace perf; using std::tr1::make_tuple; using std::tr1::get; -CV_ENUM(pnpAlgo, CV_ITERATIVE, CV_EPNP /*, CV_P3P*/) +CV_ENUM(pnpAlgo, ITERATIVE, EPNP /*, P3P*/) typedef std::tr1::tuple PointsNum_Algo_t; typedef perf::TestBaseWithParam PointsNum_Algo; @@ -17,7 +20,7 @@ typedef perf::TestBaseWithParam PointsNum; PERF_TEST_P(PointsNum_Algo, solvePnP, testing::Combine( testing::Values(/*4,*/ 3*9, 7*13), //TODO: find why results on 4 points are too unstable - testing::Values((int)CV_ITERATIVE, (int)CV_EPNP) + testing::Values((int)ITERATIVE, (int)EPNP) ) ) { @@ -90,7 +93,7 @@ PERF_TEST(PointsNum_Algo, solveP3P) TEST_CYCLE_N(1000) { - solvePnP(points3d, points2d, intrinsics, distortion, rvec, tvec, false, CV_P3P); + solvePnP(points3d, points2d, intrinsics, distortion, rvec, tvec, false, P3P); } SANITY_CHECK(rvec, 1e-6); @@ -127,7 +130,7 @@ PERF_TEST_P(PointsNum, DISABLED_SolvePnPRansac, testing::Values(4, 3*9, 7*13)) #ifdef HAVE_TBB // limit concurrency to get determenistic result - cv::Ptr one_thread = new tbb::task_scheduler_init(1); + tbb::task_scheduler_init one_thread(1); #endif TEST_CYCLE() diff --git a/modules/calib3d/perf/perf_precomp.cpp b/modules/calib3d/perf/perf_precomp.cpp deleted file mode 100644 index 8552ac3d42..0000000000 --- a/modules/calib3d/perf/perf_precomp.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "perf_precomp.hpp" diff --git a/modules/calib3d/src/calib3d_init.cpp b/modules/calib3d/src/calib3d_init.cpp index 06303bd985..6192c7998a 100644 --- a/modules/calib3d/src/calib3d_init.cpp +++ b/modules/calib3d/src/calib3d_init.cpp @@ -47,7 +47,7 @@ using namespace cv; ////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/modules/calib3d/src/calibinit.cpp b/modules/calib3d/src/calibinit.cpp index 0a349584e7..844fde4999 100644 --- a/modules/calib3d/src/calibinit.cpp +++ b/modules/calib3d/src/calibinit.cpp @@ -60,6 +60,8 @@ \************************************************************************************/ #include "precomp.hpp" +#include "opencv2/imgproc/imgproc_c.h" +#include "opencv2/calib3d/calib3d_c.h" #include "circlesgrid.hpp" #include @@ -269,8 +271,8 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, if( !out_corners ) CV_Error( CV_StsNullPtr, "Null pointer to corners" ); - storage = cvCreateMemStorage(0); - thresh_img = cvCreateMat( img->rows, img->cols, CV_8UC1 ); + storage.reset(cvCreateMemStorage(0)); + thresh_img.reset(cvCreateMat( img->rows, img->cols, CV_8UC1 )); #ifdef DEBUG_CHESSBOARD dbg_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3 ); @@ -282,7 +284,7 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, { // equalize the input image histogram - // that should make the contrast between "black" and "white" areas big enough - norm_img = cvCreateMat( img->rows, img->cols, CV_8UC1 ); + norm_img.reset(cvCreateMat( img->rows, img->cols, CV_8UC1 )); if( CV_MAT_CN(img->type) != 1 ) { @@ -539,12 +541,12 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, cv::Ptr gray; if( CV_MAT_CN(img->type) != 1 ) { - gray = cvCreateMat(img->rows, img->cols, CV_8UC1); + gray.reset(cvCreateMat(img->rows, img->cols, CV_8UC1)); cvCvtColor(img, gray, CV_BGR2GRAY); } else { - gray = cvCloneMat(img); + gray.reset(cvCloneMat(img)); } int wsize = 2; cvFindCornerSubPix( gray, out_corners, pattern_size.width*pattern_size.height, @@ -625,7 +627,7 @@ icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, int *all_count, CvCBQuad **all_quads, CvCBCorner **corners, CvSize pattern_size, CvMemStorage* storage ) { - cv::Ptr temp_storage = cvCreateChildMemStorage( storage ); + cv::Ptr temp_storage(cvCreateChildMemStorage( storage )); CvSeq* stack = cvCreateSeq( 0, sizeof(*stack), sizeof(void*), temp_storage ); // first find an interior quad @@ -1095,7 +1097,7 @@ icvOrderQuad(CvCBQuad *quad, CvCBCorner *corner, int common) static int icvCleanFoundConnectedQuads( int quad_count, CvCBQuad **quad_group, CvSize pattern_size ) { - CvPoint2D32f center = {0,0}; + CvPoint2D32f center; int i, j, k; // number of quads this pattern should contain int count = ((pattern_size.width + 1)*(pattern_size.height + 1) + 1)/2; @@ -1107,11 +1109,11 @@ icvCleanFoundConnectedQuads( int quad_count, CvCBQuad **quad_group, CvSize patte // create an array of quadrangle centers cv::AutoBuffer centers( quad_count ); - cv::Ptr temp_storage = cvCreateMemStorage(0); + cv::Ptr temp_storage(cvCreateMemStorage(0)); for( i = 0; i < quad_count; i++ ) { - CvPoint2D32f ci = {0,0}; + CvPoint2D32f ci; CvCBQuad* q = quad_group[i]; for( j = 0; j < 4; j++ ) @@ -1203,7 +1205,7 @@ static int icvFindConnectedQuads( CvCBQuad *quad, int quad_count, CvCBQuad **out_group, int group_idx, CvMemStorage* storage ) { - cv::Ptr temp_storage = cvCreateChildMemStorage( storage ); + cv::Ptr temp_storage(cvCreateChildMemStorage( storage )); CvSeq* stack = cvCreateSeq( 0, sizeof(*stack), sizeof(void*), temp_storage ); int i, count = 0; @@ -1672,7 +1674,7 @@ icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners, min_size = 25; //cvRound( image->cols * image->rows * .03 * 0.01 * 0.92 ); // create temporary storage for contours and the sequence of pointers to found quadrangles - temp_storage = cvCreateChildMemStorage( storage ); + temp_storage.reset(cvCreateChildMemStorage( storage )); root = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvSeq*), temp_storage ); // initialize contour retrieving routine @@ -1833,7 +1835,7 @@ cvDrawChessboardCorners( CvArr* _image, CvSize pattern_size, if( !found ) { - CvScalar color = {{0,0,255}}; + CvScalar color(0,0,255,0); if( cn == 1 ) color = cvScalarAll(200); color.val[0] *= scale; @@ -1856,17 +1858,17 @@ cvDrawChessboardCorners( CvArr* _image, CvSize pattern_size, else { int x, y; - CvPoint prev_pt = {0, 0}; + CvPoint prev_pt; const int line_max = 7; static const CvScalar line_colors[line_max] = { - {{0,0,255}}, - {{0,128,255}}, - {{0,200,200}}, - {{0,255,0}}, - {{200,200,0}}, - {{255,0,0}}, - {{255,0,255}} + CvScalar(0,0,255), + CvScalar(0,128,255), + CvScalar(0,200,200), + CvScalar(0,255,0), + CvScalar(200,200,0), + CvScalar(255,0,0), + CvScalar(255,0,255) }; for( y = 0, i = 0; y < pattern_size.height; y++ ) diff --git a/modules/calib3d/src/calibration.cpp b/modules/calib3d/src/calibration.cpp index e36c1e5ede..ff5e425b1b 100644 --- a/modules/calib3d/src/calibration.cpp +++ b/modules/calib3d/src/calibration.cpp @@ -41,6 +41,8 @@ //M*/ #include "precomp.hpp" +#include "opencv2/imgproc/imgproc_c.h" +#include "opencv2/calib3d/calib3d_c.h" #include #include @@ -566,7 +568,7 @@ CV_IMPL void cvProjectPoints2( const CvMat* objectPoints, (objectPoints->rows == count && CV_MAT_CN(objectPoints->type)*objectPoints->cols == 3) || (objectPoints->rows == 3 && CV_MAT_CN(objectPoints->type) == 1 && objectPoints->cols == count))) { - matM = cvCreateMat( objectPoints->rows, objectPoints->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(objectPoints->type)) ); + matM.reset(cvCreateMat( objectPoints->rows, objectPoints->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(objectPoints->type)) )); cvConvert(objectPoints, matM); } else @@ -582,7 +584,7 @@ CV_IMPL void cvProjectPoints2( const CvMat* objectPoints, (imagePoints->rows == count && CV_MAT_CN(imagePoints->type)*imagePoints->cols == 2) || (imagePoints->rows == 2 && CV_MAT_CN(imagePoints->type) == 1 && imagePoints->cols == count))) { - _m = cvCreateMat( imagePoints->rows, imagePoints->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(imagePoints->type)) ); + _m.reset(cvCreateMat( imagePoints->rows, imagePoints->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(imagePoints->type)) )); cvConvert(imagePoints, _m); } else @@ -662,10 +664,10 @@ CV_IMPL void cvProjectPoints2( const CvMat* objectPoints, if( CV_MAT_TYPE(dpdr->type) == CV_64FC1 ) { - _dpdr = cvCloneMat(dpdr); + _dpdr.reset(cvCloneMat(dpdr)); } else - _dpdr = cvCreateMat( 2*count, 3, CV_64FC1 ); + _dpdr.reset(cvCreateMat( 2*count, 3, CV_64FC1 )); dpdr_p = _dpdr->data.db; dpdr_step = _dpdr->step/sizeof(dpdr_p[0]); } @@ -680,10 +682,10 @@ CV_IMPL void cvProjectPoints2( const CvMat* objectPoints, if( CV_MAT_TYPE(dpdt->type) == CV_64FC1 ) { - _dpdt = cvCloneMat(dpdt); + _dpdt.reset(cvCloneMat(dpdt)); } else - _dpdt = cvCreateMat( 2*count, 3, CV_64FC1 ); + _dpdt.reset(cvCreateMat( 2*count, 3, CV_64FC1 )); dpdt_p = _dpdt->data.db; dpdt_step = _dpdt->step/sizeof(dpdt_p[0]); } @@ -697,10 +699,10 @@ CV_IMPL void cvProjectPoints2( const CvMat* objectPoints, if( CV_MAT_TYPE(dpdf->type) == CV_64FC1 ) { - _dpdf = cvCloneMat(dpdf); + _dpdf.reset(cvCloneMat(dpdf)); } else - _dpdf = cvCreateMat( 2*count, 2, CV_64FC1 ); + _dpdf.reset(cvCreateMat( 2*count, 2, CV_64FC1 )); dpdf_p = _dpdf->data.db; dpdf_step = _dpdf->step/sizeof(dpdf_p[0]); } @@ -714,10 +716,10 @@ CV_IMPL void cvProjectPoints2( const CvMat* objectPoints, if( CV_MAT_TYPE(dpdc->type) == CV_64FC1 ) { - _dpdc = cvCloneMat(dpdc); + _dpdc.reset(cvCloneMat(dpdc)); } else - _dpdc = cvCreateMat( 2*count, 2, CV_64FC1 ); + _dpdc.reset(cvCreateMat( 2*count, 2, CV_64FC1 )); dpdc_p = _dpdc->data.db; dpdc_step = _dpdc->step/sizeof(dpdc_p[0]); } @@ -734,10 +736,10 @@ CV_IMPL void cvProjectPoints2( const CvMat* objectPoints, if( CV_MAT_TYPE(dpdk->type) == CV_64FC1 ) { - _dpdk = cvCloneMat(dpdk); + _dpdk.reset(cvCloneMat(dpdk)); } else - _dpdk = cvCreateMat( dpdk->rows, dpdk->cols, CV_64FC1 ); + _dpdk.reset(cvCreateMat( dpdk->rows, dpdk->cols, CV_64FC1 )); dpdk_p = _dpdk->data.db; dpdk_step = _dpdk->step/sizeof(dpdk_p[0]); } @@ -824,7 +826,7 @@ CV_IMPL void cvProjectPoints2( const CvMat* objectPoints, dpdk_p[dpdk_step+7] = fy*y*cdist*(-icdist2)*icdist2*r6; if( _dpdk->cols > 8 ) { - dpdk_p[8] = fx*r2; //s1 + dpdk_p[8] = fx*r2; //s1 dpdk_p[9] = fx*r4; //s2 dpdk_p[10] = 0;//s3 dpdk_p[11] = 0;//s4 @@ -948,8 +950,8 @@ CV_IMPL void cvFindExtrinsicCameraParams2( const CvMat* objectPoints, CV_IS_MAT(A) && CV_IS_MAT(rvec) && CV_IS_MAT(tvec) ); count = MAX(objectPoints->cols, objectPoints->rows); - matM = cvCreateMat( 1, count, CV_64FC3 ); - _m = cvCreateMat( 1, count, CV_64FC2 ); + matM.reset(cvCreateMat( 1, count, CV_64FC3 )); + _m.reset(cvCreateMat( 1, count, CV_64FC2 )); cvConvertPointsHomogeneous( objectPoints, matM ); cvConvertPointsHomogeneous( imagePoints, _m ); @@ -961,8 +963,8 @@ CV_IMPL void cvFindExtrinsicCameraParams2( const CvMat* objectPoints, CV_Assert( (CV_MAT_DEPTH(tvec->type) == CV_64F || CV_MAT_DEPTH(tvec->type) == CV_32F) && (tvec->rows == 1 || tvec->cols == 1) && tvec->rows*tvec->cols*CV_MAT_CN(tvec->type) == 3 ); - _mn = cvCreateMat( 1, count, CV_64FC2 ); - _Mxy = cvCreateMat( 1, count, CV_64FC2 ); + _mn.reset(cvCreateMat( 1, count, CV_64FC2 )); + _Mxy.reset(cvCreateMat( 1, count, CV_64FC2 )); // normalize image points // (unapply the intrinsic matrix transformation and distortion) @@ -1053,7 +1055,7 @@ CV_IMPL void cvFindExtrinsicCameraParams2( const CvMat* objectPoints, CvPoint3D64f* M = (CvPoint3D64f*)matM->data.db; CvPoint2D64f* mn = (CvPoint2D64f*)_mn->data.db; - matL = cvCreateMat( 2*count, 12, CV_64F ); + matL.reset(cvCreateMat( 2*count, 12, CV_64F )); L = matL->data.db; for( i = 0; i < count; i++, L += 24 ) @@ -1160,11 +1162,11 @@ CV_IMPL void cvInitIntrinsicParams2D( const CvMat* objectPoints, if( objectPoints->rows != 1 || imagePoints->rows != 1 ) CV_Error( CV_StsBadSize, "object points and image points must be a single-row matrices" ); - matA = cvCreateMat( 2*nimages, 2, CV_64F ); - _b = cvCreateMat( 2*nimages, 1, CV_64F ); + matA.reset(cvCreateMat( 2*nimages, 2, CV_64F )); + _b.reset(cvCreateMat( 2*nimages, 1, CV_64F )); a[2] = (imageSize.width - 1)*0.5; a[5] = (imageSize.height - 1)*0.5; - _allH = cvCreateMat( nimages, 9, CV_64F ); + _allH.reset(cvCreateMat( nimages, 9, CV_64F )); // extract vanishing points in order to obtain initial value for the focal length for( i = 0, pos = 0; i < nimages; i++, pos += ni ) @@ -1254,7 +1256,7 @@ CV_IMPL double cvCalibrateCamera2( const CvMat* objectPoints, //when the thin prism model is used the distortion coefficients matrix must have 12 parameters if((flags & CV_CALIB_THIN_PRISM_MODEL) && (distCoeffs->cols*distCoeffs->rows != 12)) CV_Error( CV_StsBadArg, "Thin prism model must have 12 parameters in the distortion matrix" ); - + nimages = npoints->rows*npoints->cols; npstep = npoints->rows == 1 ? 1 : npoints->step/CV_ELEM_SIZE(npoints->type); @@ -1308,16 +1310,16 @@ CV_IMPL double cvCalibrateCamera2( const CvMat* objectPoints, total += ni; } - matM = cvCreateMat( 1, total, CV_64FC3 ); - _m = cvCreateMat( 1, total, CV_64FC2 ); + matM.reset(cvCreateMat( 1, total, CV_64FC3 )); + _m.reset(cvCreateMat( 1, total, CV_64FC2 )); cvConvertPointsHomogeneous( objectPoints, matM ); cvConvertPointsHomogeneous( imagePoints, _m ); nparams = NINTRINSIC + nimages*6; - _Ji = cvCreateMat( maxPoints*2, NINTRINSIC, CV_64FC1 ); - _Je = cvCreateMat( maxPoints*2, 6, CV_64FC1 ); - _err = cvCreateMat( maxPoints*2, 1, CV_64FC1 ); + _Ji.reset(cvCreateMat( maxPoints*2, NINTRINSIC, CV_64FC1 )); + _Je.reset(cvCreateMat( maxPoints*2, 6, CV_64FC1 )); + _err.reset(cvCreateMat( maxPoints*2, 1, CV_64FC1 )); cvZero( _Ji ); _k = cvMat( distCoeffs->rows, distCoeffs->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(distCoeffs->type)), k); @@ -1636,12 +1638,12 @@ double cvStereoCalibrate( const CvMat* _objectPoints, const CvMat* _imagePoints1 CvTermCriteria termCrit, int flags ) { - const int NINTRINSIC = 12; + const int NINTRINSIC = 16; Ptr npoints, err, J_LR, Je, Ji, imagePoints[2], objectPoints, RT0; CvLevMarq solver; double reprojErr = 0; - double A[2][9], dk[2][8]={{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}}, rlr[9]; + double A[2][9], dk[2][12]={{0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0}}, rlr[9]; CvMat K[2], Dist[2], om_LR, T_LR; CvMat R_LR = cvMat(3, 3, CV_64F, rlr); int i, k, p, ni = 0, ofs, nimages, pointsTotal, maxPoints = 0; @@ -1660,7 +1662,7 @@ double cvStereoCalibrate( const CvMat* _objectPoints, const CvMat* _imagePoints1 CV_MAT_TYPE(_npoints->type) == CV_32SC1 ); nimages = _npoints->cols + _npoints->rows - 1; - npoints = cvCreateMat( _npoints->rows, _npoints->cols, _npoints->type ); + npoints.reset(cvCreateMat( _npoints->rows, _npoints->cols, _npoints->type )); cvCopy( _npoints, npoints ); for( i = 0, pointsTotal = 0; i < nimages; i++ ) @@ -1669,8 +1671,8 @@ double cvStereoCalibrate( const CvMat* _objectPoints, const CvMat* _imagePoints1 pointsTotal += npoints->data.i[i]; } - objectPoints = cvCreateMat( _objectPoints->rows, _objectPoints->cols, - CV_64FC(CV_MAT_CN(_objectPoints->type))); + objectPoints.reset(cvCreateMat( _objectPoints->rows, _objectPoints->cols, + CV_64FC(CV_MAT_CN(_objectPoints->type)))); cvConvert( _objectPoints, objectPoints ); cvReshape( objectPoints, objectPoints, 3, 1 ); @@ -1687,9 +1689,9 @@ double cvStereoCalibrate( const CvMat* _objectPoints, const CvMat* _imagePoints1 (_imagePoints1->rows == 1 && _imagePoints1->cols == pointsTotal && cn == 2)) ); K[k] = cvMat(3,3,CV_64F,A[k]); - Dist[k] = cvMat(1,8,CV_64F,dk[k]); + Dist[k] = cvMat(1,12,CV_64F,dk[k]); - imagePoints[k] = cvCreateMat( points->rows, points->cols, CV_64FC(CV_MAT_CN(points->type))); + imagePoints[k].reset(cvCreateMat( points->rows, points->cols, CV_64FC(CV_MAT_CN(points->type)))); cvConvert( points, imagePoints[k] ); cvReshape( imagePoints[k], imagePoints[k], 2, 1 ); @@ -1727,10 +1729,10 @@ double cvStereoCalibrate( const CvMat* _objectPoints, const CvMat* _imagePoints1 recomputeIntrinsics = (flags & CV_CALIB_FIX_INTRINSIC) == 0; - err = cvCreateMat( maxPoints*2, 1, CV_64F ); - Je = cvCreateMat( maxPoints*2, 6, CV_64F ); - J_LR = cvCreateMat( maxPoints*2, 6, CV_64F ); - Ji = cvCreateMat( maxPoints*2, NINTRINSIC, CV_64F ); + err.reset(cvCreateMat( maxPoints*2, 1, CV_64F )); + Je.reset(cvCreateMat( maxPoints*2, 6, CV_64F )); + J_LR.reset(cvCreateMat( maxPoints*2, 6, CV_64F )); + Ji.reset(cvCreateMat( maxPoints*2, NINTRINSIC, CV_64F )); cvZero( Ji ); // we optimize for the inter-camera R(3),t(3), then, optionally, @@ -1738,7 +1740,7 @@ double cvStereoCalibrate( const CvMat* _objectPoints, const CvMat* _imagePoints1 nparams = 6*(nimages+1) + (recomputeIntrinsics ? NINTRINSIC*2 : 0); // storage for initial [om(R){i}|t{i}] (in order to compute the median for each component) - RT0 = cvCreateMat( 6, nimages, CV_64F ); + RT0.reset(cvCreateMat( 6, nimages, CV_64F )); solver.init( nparams, 0, termCrit ); if( recomputeIntrinsics ) @@ -1746,6 +1748,8 @@ double cvStereoCalibrate( const CvMat* _objectPoints, const CvMat* _imagePoints1 uchar* imask = solver.mask->data.ptr + nparams - NINTRINSIC*2; if( !(flags & CV_CALIB_RATIONAL_MODEL) ) flags |= CV_CALIB_FIX_K4 | CV_CALIB_FIX_K5 | CV_CALIB_FIX_K6; + if( !(flags & CV_CALIB_THIN_PRISM_MODEL) ) + flags |= CV_CALIB_FIX_S1_S2_S3_S4; if( flags & CV_CALIB_FIX_ASPECT_RATIO ) imask[0] = imask[NINTRINSIC] = 0; if( flags & CV_CALIB_FIX_FOCAL_LENGTH ) @@ -1766,6 +1770,13 @@ double cvStereoCalibrate( const CvMat* _objectPoints, const CvMat* _imagePoints1 imask[10] = imask[NINTRINSIC+10] = 0; if( flags & CV_CALIB_FIX_K6 ) imask[11] = imask[NINTRINSIC+11] = 0; + if( flags & CV_CALIB_FIX_S1_S2_S3_S4 ) + { + imask[12] = imask[NINTRINSIC+12] = 0; + imask[13] = imask[NINTRINSIC+13] = 0; + imask[14] = imask[NINTRINSIC+14] = 0; + imask[15] = imask[NINTRINSIC+15] = 0; + } } /* @@ -1840,6 +1851,10 @@ double cvStereoCalibrate( const CvMat* _objectPoints, const CvMat* _imagePoints1 iparam[4] = dk[k][0]; iparam[5] = dk[k][1]; iparam[6] = dk[k][2]; iparam[7] = dk[k][3]; iparam[8] = dk[k][4]; iparam[9] = dk[k][5]; iparam[10] = dk[k][6]; iparam[11] = dk[k][7]; + iparam[12] = dk[k][8]; + iparam[13] = dk[k][9]; + iparam[14] = dk[k][10]; + iparam[15] = dk[k][11]; } om_LR = cvMat(3, 1, CV_64F, solver.param->data.db); @@ -1906,6 +1921,10 @@ double cvStereoCalibrate( const CvMat* _objectPoints, const CvMat* _imagePoints1 dk[k][5] = iparam[k*NINTRINSIC+9]; dk[k][6] = iparam[k*NINTRINSIC+10]; dk[k][7] = iparam[k*NINTRINSIC+11]; + dk[k][8] = iparam[k*NINTRINSIC+12]; + dk[k][9] = iparam[k*NINTRINSIC+13]; + dk[k][10] = iparam[k*NINTRINSIC+14]; + dk[k][11] = iparam[k*NINTRINSIC+15]; } } @@ -2078,7 +2097,7 @@ icvGetRectangles( const CvMat* cameraMatrix, const CvMat* distCoeffs, { const int N = 9; int x, y, k; - cv::Ptr _pts = cvCreateMat(1, N*N, CV_32FC2); + cv::Ptr _pts(cvCreateMat(1, N*N, CV_32FC2)); CvPoint2D32f* pts = (CvPoint2D32f*)(_pts->data.ptr); for( y = k = 0; y < N; y++ ) @@ -2437,10 +2456,10 @@ CV_IMPL int cvStereoRectifyUncalibrated( npoints = _points1->rows * _points1->cols * CV_MAT_CN(_points1->type) / 2; - _m1 = cvCreateMat( _points1->rows, _points1->cols, CV_64FC(CV_MAT_CN(_points1->type)) ); - _m2 = cvCreateMat( _points2->rows, _points2->cols, CV_64FC(CV_MAT_CN(_points2->type)) ); - _lines1 = cvCreateMat( 1, npoints, CV_64FC3 ); - _lines2 = cvCreateMat( 1, npoints, CV_64FC3 ); + _m1.reset(cvCreateMat( _points1->rows, _points1->cols, CV_64FC(CV_MAT_CN(_points1->type)) )); + _m2.reset(cvCreateMat( _points2->rows, _points2->cols, CV_64FC(CV_MAT_CN(_points2->type)) )); + _lines1.reset(cvCreateMat( 1, npoints, CV_64FC3 )); + _lines2.reset(cvCreateMat( 1, npoints, CV_64FC3 )); cvConvert( F0, &F ); @@ -2688,7 +2707,7 @@ void cv::reprojectImageTo3D( InputArray _disparity, for( x = 0; x < cols*3; x++ ) { int ival = cvRound(dptr[x]); - dptr0[x] = CV_CAST_16S(ival); + dptr0[x] = cv::saturate_cast(ival); } } else if( dtype == CV_32SC3 ) diff --git a/modules/calib3d/src/checkchessboard.cpp b/modules/calib3d/src/checkchessboard.cpp index 9191fc8c84..715fe73ef8 100644 --- a/modules/calib3d/src/checkchessboard.cpp +++ b/modules/calib3d/src/checkchessboard.cpp @@ -40,6 +40,8 @@ //M*/ #include "precomp.hpp" +#include "opencv2/imgproc/imgproc_c.h" +#include "opencv2/calib3d/calib3d_c.h" #include #include diff --git a/modules/calib3d/src/circlesgrid.cpp b/modules/calib3d/src/circlesgrid.cpp index 9d893ffe97..969611fbc6 100644 --- a/modules/calib3d/src/circlesgrid.cpp +++ b/modules/calib3d/src/circlesgrid.cpp @@ -41,6 +41,7 @@ //M*/ #include "circlesgrid.hpp" +#include //#define DEBUG_CIRCLES #ifdef DEBUG_CIRCLES @@ -202,12 +203,12 @@ void CirclesGridClusterFinder::findCorners(const std::vector &hull2 //corners are the most sharp angles (6) Mat anglesMat = Mat(angles); Mat sortedIndices; - sortIdx(anglesMat, sortedIndices, CV_SORT_EVERY_COLUMN + CV_SORT_DESCENDING); + sortIdx(anglesMat, sortedIndices, SORT_EVERY_COLUMN + SORT_DESCENDING); CV_Assert(sortedIndices.type() == CV_32SC1); CV_Assert(sortedIndices.cols == 1); const int cornersCount = isAsymmetricGrid ? 6 : 4; Mat cornersIndices; - cv::sort(sortedIndices.rowRange(0, cornersCount), cornersIndices, CV_SORT_EVERY_COLUMN + CV_SORT_ASCENDING); + cv::sort(sortedIndices.rowRange(0, cornersCount), cornersIndices, SORT_EVERY_COLUMN + SORT_ASCENDING); corners.clear(); for(int i=0; i (id, Vertex())); } void Graph::addEdge(size_t id1, size_t id2) { - assert( doesVertexExist( id1 ) ); - assert( doesVertexExist( id2 ) ); + CV_Assert( doesVertexExist( id1 ) ); + CV_Assert( doesVertexExist( id2 ) ); vertices[id1].neighbors.insert(id2); vertices[id2].neighbors.insert(id1); @@ -454,8 +455,8 @@ void Graph::addEdge(size_t id1, size_t id2) void Graph::removeEdge(size_t id1, size_t id2) { - assert( doesVertexExist( id1 ) ); - assert( doesVertexExist( id2 ) ); + CV_Assert( doesVertexExist( id1 ) ); + CV_Assert( doesVertexExist( id2 ) ); vertices[id1].neighbors.erase(id2); vertices[id2].neighbors.erase(id1); @@ -463,8 +464,8 @@ void Graph::removeEdge(size_t id1, size_t id2) bool Graph::areVerticesAdjacent(size_t id1, size_t id2) const { - assert( doesVertexExist( id1 ) ); - assert( doesVertexExist( id2 ) ); + CV_Assert( doesVertexExist( id1 ) ); + CV_Assert( doesVertexExist( id2 ) ); Vertices::const_iterator it = vertices.find(id1); return it->second.neighbors.find(id2) != it->second.neighbors.end(); @@ -477,7 +478,7 @@ size_t Graph::getVerticesCount() const size_t Graph::getDegree(size_t id) const { - assert( doesVertexExist(id) ); + CV_Assert( doesVertexExist(id) ); Vertices::const_iterator it = vertices.find(id); return it->second.neighbors.size(); @@ -495,7 +496,7 @@ void Graph::floydWarshall(cv::Mat &distanceMatrix, int infinity) const distanceMatrix.at ((int)it1->first, (int)it1->first) = 0; for (Neighbors::const_iterator it2 = it1->second.neighbors.begin(); it2 != it1->second.neighbors.end(); it2++) { - assert( it1->first != *it2 ); + CV_Assert( it1->first != *it2 ); distanceMatrix.at ((int)it1->first, (int)*it2) = edgeWeight; } } @@ -524,7 +525,7 @@ void Graph::floydWarshall(cv::Mat &distanceMatrix, int infinity) const const Graph::Neighbors& Graph::getNeighbors(size_t id) const { - assert( doesVertexExist(id) ); + CV_Assert( doesVertexExist(id) ); Vertices::const_iterator it = vertices.find(id); return it->second.neighbors; @@ -604,7 +605,7 @@ bool CirclesGridFinder::findHoles() } default: - CV_Error(CV_StsBadArg, "Unkown pattern type"); + CV_Error(Error::StsBadArg, "Unkown pattern type"); } return (isDetectionCorrect()); //CV_Error( 0, "Detection is not correct" ); @@ -813,7 +814,7 @@ void CirclesGridFinder::findMCS(const std::vector &basis, std::vector& centers, const std::vector &keypoints, std::vector &warpedKeypoints) { - assert( !centers.empty() ); + CV_Assert( !centers.empty() ); const float edgeLength = 30; const Point2f offset(150, 150); @@ -832,7 +833,7 @@ Mat CirclesGridFinder::rectifyGrid(Size detectedGridSize, const std::vector srcKeypoints; @@ -912,7 +913,7 @@ void CirclesGridFinder::findCandidateLine(std::vector &line, size_t seed } } - assert( line.size() == seeds.size() ); + CV_Assert( line.size() == seeds.size() ); } void CirclesGridFinder::findCandidateHoles(std::vector &above, std::vector &below, bool addRow, Point2f basisVec, @@ -927,9 +928,9 @@ void CirclesGridFinder::findCandidateHoles(std::vector &above, std::vect size_t lastIdx = addRow ? holes.size() - 1 : holes[0].size() - 1; findCandidateLine(below, lastIdx, addRow, basisVec, belowSeeds); - assert( below.size() == above.size() ); - assert( belowSeeds.size() == aboveSeeds.size() ); - assert( below.size() == belowSeeds.size() ); + CV_Assert( below.size() == above.size() ); + CV_Assert( belowSeeds.size() == aboveSeeds.size() ); + CV_Assert( below.size() == belowSeeds.size() ); } bool CirclesGridFinder::areCentersNew(const std::vector &newCenters, const std::vector > &holes) @@ -1000,10 +1001,10 @@ void CirclesGridFinder::insertWinner(float aboveConfidence, float belowConfidenc float CirclesGridFinder::computeGraphConfidence(const std::vector &basisGraphs, bool addRow, const std::vector &points, const std::vector &seeds) { - assert( points.size() == seeds.size() ); + CV_Assert( points.size() == seeds.size() ); float confidence = 0; const size_t vCount = basisGraphs[0].getVerticesCount(); - assert( basisGraphs[0].getVerticesCount() == basisGraphs[1].getVerticesCount() ); + CV_Assert( basisGraphs[0].getVerticesCount() == basisGraphs[1].getVerticesCount() ); for (size_t i = 0; i < seeds.size(); i++) { @@ -1087,7 +1088,7 @@ void CirclesGridFinder::findBasis(const std::vector &samples, std::vect const int clustersCount = 4; kmeans(Mat(samples).reshape(1, 0), clustersCount, bestLabels, termCriteria, parameters.kmeansAttempts, KMEANS_RANDOM_CENTERS, centers); - assert( centers.type() == CV_32FC1 ); + CV_Assert( centers.type() == CV_32FC1 ); std::vector basisIndices; //TODO: only remove duplicate @@ -1204,7 +1205,7 @@ void CirclesGridFinder::computeRNG(Graph &rng, std::vector &vectors void computePredecessorMatrix(const Mat &dm, int verticesCount, Mat &predecessorMatrix) { - assert( dm.type() == CV_32SC1 ); + CV_Assert( dm.type() == CV_32SC1 ); predecessorMatrix.create(verticesCount, verticesCount, CV_32SC1); predecessorMatrix = -1; for (int i = 0; i < predecessorMatrix.rows; i++) @@ -1253,7 +1254,6 @@ size_t CirclesGridFinder::findLongestPath(std::vector &basisGraphs, Path double maxVal; Point maxLoc; - assert (infinity < 0); minMaxLoc(distanceMatrix, 0, &maxVal, 0, &maxLoc); if (maxVal > longestPaths[0].length) @@ -1364,7 +1364,7 @@ void CirclesGridFinder::drawHoles(const Mat &srcImage, Mat &drawImage) const const Scalar holeColor = Scalar(0, 255, 0); if (srcImage.channels() == 1) - cvtColor(srcImage, drawImage, CV_GRAY2RGB); + cvtColor(srcImage, drawImage, COLOR_GRAY2RGB); else srcImage.copyTo(drawImage); @@ -1594,9 +1594,3 @@ size_t CirclesGridFinder::getFirstCorner(std::vector &largeCornerIndices, return cornerIdx; } - -bool cv::findCirclesGridDefault( InputArray image, Size patternSize, - OutputArray centers, int flags ) -{ - return findCirclesGrid(image, patternSize, centers, flags); -} diff --git a/modules/calib3d/src/circlesgrid.hpp b/modules/calib3d/src/circlesgrid.hpp index 3028c58b56..fae6b3cac7 100644 --- a/modules/calib3d/src/circlesgrid.hpp +++ b/modules/calib3d/src/circlesgrid.hpp @@ -47,6 +47,7 @@ #include #include #include +#include #include "precomp.hpp" diff --git a/modules/calib3d/src/compat_ptsetreg.cpp b/modules/calib3d/src/compat_ptsetreg.cpp index dca0d0dabe..e8f4108580 100644 --- a/modules/calib3d/src/compat_ptsetreg.cpp +++ b/modules/calib3d/src/compat_ptsetreg.cpp @@ -41,6 +41,7 @@ //M*/ #include "precomp.hpp" +#include "opencv2/calib3d/calib3d_c.h" /************************************************************************************\ Some backward compatibility stuff, to be moved to legacy or compat module @@ -52,7 +53,6 @@ using cv::Ptr; CvLevMarq::CvLevMarq() { - mask = prevParam = param = J = err = JtJ = JtJN = JtErr = JtJV = JtJW = Ptr(); lambdaLg10 = 0; state = DONE; criteria = cvTermCriteria(0,0,0); iters = 0; @@ -61,7 +61,6 @@ CvLevMarq::CvLevMarq() CvLevMarq::CvLevMarq( int nparams, int nerrs, CvTermCriteria criteria0, bool _completeSymmFlag ) { - mask = prevParam = param = J = err = JtJ = JtJN = JtErr = JtJV = JtJW = Ptr(); init(nparams, nerrs, criteria0, _completeSymmFlag); } @@ -88,19 +87,19 @@ void CvLevMarq::init( int nparams, int nerrs, CvTermCriteria criteria0, bool _co { if( !param || param->rows != nparams || nerrs != (err ? err->rows : 0) ) clear(); - mask = cvCreateMat( nparams, 1, CV_8U ); + mask.reset(cvCreateMat( nparams, 1, CV_8U )); cvSet(mask, cvScalarAll(1)); - prevParam = cvCreateMat( nparams, 1, CV_64F ); - param = cvCreateMat( nparams, 1, CV_64F ); - JtJ = cvCreateMat( nparams, nparams, CV_64F ); - JtJN = cvCreateMat( nparams, nparams, CV_64F ); - JtJV = cvCreateMat( nparams, nparams, CV_64F ); - JtJW = cvCreateMat( nparams, 1, CV_64F ); - JtErr = cvCreateMat( nparams, 1, CV_64F ); + prevParam.reset(cvCreateMat( nparams, 1, CV_64F )); + param.reset(cvCreateMat( nparams, 1, CV_64F )); + JtJ.reset(cvCreateMat( nparams, nparams, CV_64F )); + JtJN.reset(cvCreateMat( nparams, nparams, CV_64F )); + JtJV.reset(cvCreateMat( nparams, nparams, CV_64F )); + JtJW.reset(cvCreateMat( nparams, 1, CV_64F )); + JtErr.reset(cvCreateMat( nparams, 1, CV_64F )); if( nerrs > 0 ) { - J = cvCreateMat( nerrs, nparams, CV_64F ); - err = cvCreateMat( nerrs, 1, CV_64F ); + J.reset(cvCreateMat( nerrs, nparams, CV_64F )); + err.reset(cvCreateMat( nerrs, 1, CV_64F )); } prevErrNorm = DBL_MAX; lambdaLg10 = -3; @@ -195,7 +194,7 @@ bool CvLevMarq::updateAlt( const CvMat*& _param, CvMat*& _JtJ, CvMat*& _JtErr, d { double change; - CV_Assert( err.empty() ); + CV_Assert( !err ); if( state == DONE ) { _param = param; @@ -427,4 +426,3 @@ CV_IMPL void cvConvertPointsHomogeneous( const CvMat* _src, CvMat* _dst ) dst.convertTo(dst0, dst0.type()); } } - diff --git a/modules/calib3d/src/compat_stereo.cpp b/modules/calib3d/src/compat_stereo.cpp index 7b9ed33e41..16eefc6847 100644 --- a/modules/calib3d/src/compat_stereo.cpp +++ b/modules/calib3d/src/compat_stereo.cpp @@ -41,6 +41,7 @@ //M*/ #include "precomp.hpp" +#include "opencv2/calib3d/calib3d_c.h" CvStereoBMState* cvCreateStereoBMState( int /*preset*/, int numberOfDisparities ) { @@ -83,10 +84,6 @@ void cvReleaseStereoBMState( CvStereoBMState** state ) cvFree( state ); } -template<> void cv::Ptr::delete_obj() -{ cvReleaseStereoBMState(&obj); } - - void cvFindStereoCorrespondenceBM( const CvArr* leftarr, const CvArr* rightarr, CvArr* disparr, CvStereoBMState* state ) { @@ -124,93 +121,3 @@ void cvValidateDisparity( CvArr* _disp, const CvArr* _cost, int minDisparity, cv::Mat disp = cv::cvarrToMat(_disp), cost = cv::cvarrToMat(_cost); cv::validateDisparity( disp, cost, minDisparity, numberOfDisparities, disp12MaxDiff ); } - -namespace cv -{ - -StereoBM::StereoBM() -{ init(BASIC_PRESET); } - -StereoBM::StereoBM(int _preset, int _ndisparities, int _SADWindowSize) -{ init(_preset, _ndisparities, _SADWindowSize); } - -void StereoBM::init(int _preset, int _ndisparities, int _SADWindowSize) -{ - state = cvCreateStereoBMState(_preset, _ndisparities); - state->SADWindowSize = _SADWindowSize; -} - -void StereoBM::operator()( InputArray _left, InputArray _right, - OutputArray _disparity, int disptype ) -{ - Mat left = _left.getMat(), right = _right.getMat(); - CV_Assert( disptype == CV_16S || disptype == CV_32F ); - _disparity.create(left.size(), disptype); - Mat disp = _disparity.getMat(); - - CvMat left_c = left, right_c = right, disp_c = disp; - cvFindStereoCorrespondenceBM(&left_c, &right_c, &disp_c, state); -} - - -StereoSGBM::StereoSGBM() -{ - minDisparity = numberOfDisparities = 0; - SADWindowSize = 0; - P1 = P2 = 0; - disp12MaxDiff = 0; - preFilterCap = 0; - uniquenessRatio = 0; - speckleWindowSize = 0; - speckleRange = 0; - fullDP = false; - - sm = createStereoSGBM(0, 0, 0); -} - -StereoSGBM::StereoSGBM( int _minDisparity, int _numDisparities, int _SADWindowSize, - int _P1, int _P2, int _disp12MaxDiff, int _preFilterCap, - int _uniquenessRatio, int _speckleWindowSize, int _speckleRange, - bool _fullDP ) -{ - minDisparity = _minDisparity; - numberOfDisparities = _numDisparities; - SADWindowSize = _SADWindowSize; - P1 = _P1; - P2 = _P2; - disp12MaxDiff = _disp12MaxDiff; - preFilterCap = _preFilterCap; - uniquenessRatio = _uniquenessRatio; - speckleWindowSize = _speckleWindowSize; - speckleRange = _speckleRange; - fullDP = _fullDP; - - sm = createStereoSGBM(0, 0, 0); -} - -StereoSGBM::~StereoSGBM() -{ -} - -void StereoSGBM::operator ()( InputArray _left, InputArray _right, - OutputArray _disp ) -{ - sm->set("minDisparity", minDisparity); - sm->set("numDisparities", numberOfDisparities); - sm->set("SADWindowSize", SADWindowSize); - sm->set("P1", P1); - sm->set("P2", P2); - sm->set("disp12MaxDiff", disp12MaxDiff); - sm->set("preFilterCap", preFilterCap); - sm->set("uniquenessRatio", uniquenessRatio); - sm->set("speckleWindowSize", speckleWindowSize); - sm->set("speckleRange", speckleRange); - sm->set("fullDP", fullDP); - - sm->compute(_left, _right, _disp); -} - -} - - - diff --git a/modules/calib3d/src/epnp.cpp b/modules/calib3d/src/epnp.cpp index 7fb63254dc..edbcaffd39 100644 --- a/modules/calib3d/src/epnp.cpp +++ b/modules/calib3d/src/epnp.cpp @@ -621,4 +621,3 @@ void epnp::qr_solve(CvMat * A, CvMat * b, CvMat * X) pX[i] = (pb[i] - sum) / A2[i]; } } - diff --git a/modules/calib3d/src/epnp.h b/modules/calib3d/src/epnp.h index 203830a6d6..fe01606305 100644 --- a/modules/calib3d/src/epnp.h +++ b/modules/calib3d/src/epnp.h @@ -2,6 +2,7 @@ #define epnp_h #include "precomp.hpp" +#include "opencv2/core/core_c.h" class epnp { public: diff --git a/modules/calib3d/src/five-point.cpp b/modules/calib3d/src/five-point.cpp index 57f941e381..9922247008 100644 --- a/modules/calib3d/src/five-point.cpp +++ b/modules/calib3d/src/five-point.cpp @@ -1,47 +1,35 @@ -/*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*/ +/* This is a 5-point algorithm contributed to OpenCV by the author, Bo Li. + It implements the 5-point algorithm solver from Nister's paper: + Nister, An efficient solution to the five-point relative pose problem, PAMI, 2004. +*/ + +/* Copyright (c) 2013, Bo Li (prclibo@gmail.com), ETH Zurich + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions 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. + * Neither the name of the copyright holder nor the + names of its contributors may 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 COPYRIGHT HOLDER 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. +*/ #include "precomp.hpp" -#include namespace cv { @@ -71,16 +59,10 @@ public: SVD::compute(Q, W, U, Vt, SVD::MODIFY_A | SVD::FULL_UV); Mat EE = Mat(Vt.t()).colRange(5, 9) * 1.0; - Mat AA(20, 10, CV_64F); - EE = EE.t(); - calibrated_fivepoint_helper((double*)EE.data, (double*)AA.data); - AA = AA.t(); - EE = EE.t(); - Mat A(10, 20, CV_64F); - int perm[20] = {0, 3, 1, 2, 4, 10, 6, 12, 5, 11, 7, 13, 16, 8, 14, 17, 9, 15, 18, 19}; - for (int i = 0; i < 20; i++) - A.col(i) = AA.col(perm[i]) * 1.0; + EE = EE.t(); + getCoeffMat((double*)EE.data, (double*)A.data); + EE = EE.t(); A = A.colRange(0, 10).inv() * A.colRange(10, 20); @@ -118,7 +100,7 @@ public: c[1] = (b[29]*b[7]*b[24]-b[29]*b[20]*b[11]+b[2]*b[20]*b[38]-b[2]*b[25]*b[33]-b[28]*b[20]*b[12]+b[28]*b[7]*b[25]-b[29]*b[19]*b[12]-b[3]*b[24]*b[33]+b[15]*b[33]*b[12]+b[3]*b[19]*b[38]-b[16]*b[6]*b[38]+b[3]*b[20]*b[37]+b[16]*b[32]*b[12]+b[29]*b[6]*b[25]-b[16]*b[7]*b[37]-b[3]*b[25]*b[32]-b[15]*b[7]*b[38]+b[16]*b[33]*b[11]); c[0] = -b[29]*b[20]*b[12]+b[29]*b[7]*b[25]+b[16]*b[33]*b[12]-b[16]*b[7]*b[38]+b[3]*b[20]*b[38]-b[3]*b[25]*b[33]; - std::vector > roots; + std::vector > roots; solvePoly(coeffs, roots); std::vector xs, ys, zs; @@ -128,8 +110,8 @@ public: double* e = ematrix.ptr(); for (size_t i = 0; i < roots.size(); i++) { - if (fabs(roots[i].imag()) > 1e-10) continue; - double z1 = roots[i].real(); + if (fabs(roots[i].im) > 1e-10) continue; + double z1 = roots[i].re; double z2 = z1 * z1; double z3 = z2 * z1; double z4 = z3 * z1; @@ -146,355 +128,248 @@ public: Mat Bz(3, 3, CV_64F, bz); cv::Mat xy1; SVD::solveZ(Bz, xy1); - - if (fabs(xy1.at(2)) < 1e-10) continue; - xs.push_back(xy1.at(0) / xy1.at(2)); - ys.push_back(xy1.at(1) / xy1.at(2)); - zs.push_back(z1); - - cv::Mat Evec = EE.col(0) * xs.back() + EE.col(1) * ys.back() + EE.col(2) * zs.back() + EE.col(3); - Evec /= norm(Evec); - - memcpy(e + count * 9, Evec.data, 9 * sizeof(double)); - count++; + + if (fabs(xy1.at(2)) < 1e-10) continue; + xs.push_back(xy1.at(0) / xy1.at(2)); + ys.push_back(xy1.at(1) / xy1.at(2)); + zs.push_back(z1); + + cv::Mat Evec = EE.col(0) * xs.back() + EE.col(1) * ys.back() + EE.col(2) * zs.back() + EE.col(3); + Evec /= norm(Evec); + + memcpy(e + count * 9, Evec.data, 9 * sizeof(double)); + count++; } ematrix.rowRange(0, count*3).copyTo(_model); return count; } -protected: - void calibrated_fivepoint_helper( double *EE, double* A ) const +protected: + void getCoeffMat(double *e, double *A) const { - double e00,e01,e02,e03,e04,e05,e06,e07,e08; - double e10,e11,e12,e13,e14,e15,e16,e17,e18; - double e20,e21,e22,e23,e24,e25,e26,e27,e28; - double e30,e31,e32,e33,e34,e35,e36,e37,e38; + double ep2[36], ep3[36]; + for (int i = 0; i < 36; i++) + { + ep2[i] = e[i] * e[i]; + ep3[i] = ep2[i] * e[i]; + } - double e002,e012,e022,e032,e042,e052,e062,e072,e082; - double e102,e112,e122,e132,e142,e152,e162,e172,e182; - double e202,e212,e222,e232,e242,e252,e262,e272,e282; - double e302,e312,e322,e332,e342,e352,e362,e372,e382; + A[0]=e[33]*e[28]*e[32]-e[33]*e[31]*e[29]+e[30]*e[34]*e[29]-e[30]*e[28]*e[35]-e[27]*e[32]*e[34]+e[27]*e[31]*e[35]; + A[146]=.5000000000*e[6]*ep2[8]-.5000000000*e[6]*ep2[5]+.5000000000*ep3[6]+.5000000000*e[6]*ep2[7]-.5000000000*e[6]*ep2[4]+e[0]*e[2]*e[8]+e[3]*e[4]*e[7]+e[3]*e[5]*e[8]+e[0]*e[1]*e[7]-.5000000000*e[6]*ep2[1]-.5000000000*e[6]*ep2[2]+.5000000000*ep2[0]*e[6]+.5000000000*ep2[3]*e[6]; + A[1]=e[30]*e[34]*e[2]+e[33]*e[1]*e[32]-e[3]*e[28]*e[35]+e[0]*e[31]*e[35]+e[3]*e[34]*e[29]-e[30]*e[1]*e[35]+e[27]*e[31]*e[8]-e[27]*e[32]*e[7]-e[30]*e[28]*e[8]-e[33]*e[31]*e[2]-e[0]*e[32]*e[34]+e[6]*e[28]*e[32]-e[33]*e[4]*e[29]+e[33]*e[28]*e[5]+e[30]*e[7]*e[29]+e[27]*e[4]*e[35]-e[27]*e[5]*e[34]-e[6]*e[31]*e[29]; + A[147]=e[9]*e[27]*e[15]+e[9]*e[29]*e[17]+e[9]*e[11]*e[35]+e[9]*e[28]*e[16]+e[9]*e[10]*e[34]+e[27]*e[11]*e[17]+e[27]*e[10]*e[16]+e[12]*e[30]*e[15]+e[12]*e[32]*e[17]+e[12]*e[14]*e[35]+e[12]*e[31]*e[16]+e[12]*e[13]*e[34]+e[30]*e[14]*e[17]+e[30]*e[13]*e[16]+e[15]*e[35]*e[17]+e[15]*e[34]*e[16]-1.*e[15]*e[28]*e[10]-1.*e[15]*e[31]*e[13]-1.*e[15]*e[32]*e[14]-1.*e[15]*e[29]*e[11]+.5000000000*ep2[9]*e[33]+.5000000000*e[33]*ep2[16]-.5000000000*e[33]*ep2[11]+.5000000000*e[33]*ep2[12]+1.500000000*e[33]*ep2[15]+.5000000000*e[33]*ep2[17]-.5000000000*e[33]*ep2[10]-.5000000000*e[33]*ep2[14]-.5000000000*e[33]*ep2[13]; + A[2]=-e[33]*e[22]*e[29]-e[33]*e[31]*e[20]-e[27]*e[32]*e[25]+e[27]*e[22]*e[35]-e[27]*e[23]*e[34]+e[27]*e[31]*e[26]+e[33]*e[28]*e[23]-e[21]*e[28]*e[35]+e[30]*e[25]*e[29]+e[24]*e[28]*e[32]-e[24]*e[31]*e[29]+e[18]*e[31]*e[35]-e[30]*e[28]*e[26]-e[30]*e[19]*e[35]+e[21]*e[34]*e[29]+e[33]*e[19]*e[32]-e[18]*e[32]*e[34]+e[30]*e[34]*e[20]; + A[144]=e[18]*e[2]*e[17]+e[3]*e[21]*e[15]+e[3]*e[12]*e[24]+e[3]*e[23]*e[17]+e[3]*e[14]*e[26]+e[3]*e[22]*e[16]+e[3]*e[13]*e[25]+3.*e[6]*e[24]*e[15]+e[6]*e[26]*e[17]+e[6]*e[25]*e[16]+e[0]*e[20]*e[17]+e[0]*e[11]*e[26]+e[0]*e[19]*e[16]+e[0]*e[10]*e[25]+e[15]*e[26]*e[8]-1.*e[15]*e[20]*e[2]-1.*e[15]*e[19]*e[1]-1.*e[15]*e[22]*e[4]+e[15]*e[25]*e[7]-1.*e[15]*e[23]*e[5]+e[12]*e[21]*e[6]+e[12]*e[22]*e[7]+e[12]*e[4]*e[25]+e[12]*e[23]*e[8]+e[12]*e[5]*e[26]-1.*e[24]*e[11]*e[2]-1.*e[24]*e[10]*e[1]-1.*e[24]*e[13]*e[4]+e[24]*e[16]*e[7]-1.*e[24]*e[14]*e[5]+e[24]*e[17]*e[8]+e[21]*e[13]*e[7]+e[21]*e[4]*e[16]+e[21]*e[14]*e[8]+e[21]*e[5]*e[17]-1.*e[6]*e[23]*e[14]-1.*e[6]*e[20]*e[11]-1.*e[6]*e[19]*e[10]-1.*e[6]*e[22]*e[13]+e[9]*e[18]*e[6]+e[9]*e[0]*e[24]+e[9]*e[19]*e[7]+e[9]*e[1]*e[25]+e[9]*e[20]*e[8]+e[9]*e[2]*e[26]+e[18]*e[0]*e[15]+e[18]*e[10]*e[7]+e[18]*e[1]*e[16]+e[18]*e[11]*e[8]; + A[3]=e[33]*e[10]*e[32]+e[33]*e[28]*e[14]-e[33]*e[13]*e[29]-e[33]*e[31]*e[11]+e[9]*e[31]*e[35]-e[9]*e[32]*e[34]+e[27]*e[13]*e[35]-e[27]*e[32]*e[16]+e[27]*e[31]*e[17]-e[27]*e[14]*e[34]+e[12]*e[34]*e[29]-e[12]*e[28]*e[35]+e[30]*e[34]*e[11]+e[30]*e[16]*e[29]-e[30]*e[10]*e[35]-e[30]*e[28]*e[17]+e[15]*e[28]*e[32]-e[15]*e[31]*e[29]; + A[145]=e[0]*e[27]*e[6]+e[0]*e[28]*e[7]+e[0]*e[1]*e[34]+e[0]*e[29]*e[8]+e[0]*e[2]*e[35]+e[6]*e[34]*e[7]-1.*e[6]*e[32]*e[5]+e[6]*e[30]*e[3]+e[6]*e[35]*e[8]-1.*e[6]*e[29]*e[2]-1.*e[6]*e[28]*e[1]-1.*e[6]*e[31]*e[4]+e[27]*e[1]*e[7]+e[27]*e[2]*e[8]+e[3]*e[31]*e[7]+e[3]*e[4]*e[34]+e[3]*e[32]*e[8]+e[3]*e[5]*e[35]+e[30]*e[4]*e[7]+e[30]*e[5]*e[8]+.5000000000*ep2[0]*e[33]+1.500000000*e[33]*ep2[6]-.5000000000*e[33]*ep2[4]-.5000000000*e[33]*ep2[5]-.5000000000*e[33]*ep2[1]+.5000000000*e[33]*ep2[7]+.5000000000*e[33]*ep2[3]-.5000000000*e[33]*ep2[2]+.5000000000*e[33]*ep2[8]; + A[4]=-e[0]*e[23]*e[16]+e[9]*e[4]*e[26]+e[9]*e[22]*e[8]-e[9]*e[5]*e[25]-e[9]*e[23]*e[7]+e[18]*e[4]*e[17]+e[18]*e[13]*e[8]-e[18]*e[5]*e[16]-e[18]*e[14]*e[7]+e[3]*e[16]*e[20]+e[3]*e[25]*e[11]-e[3]*e[10]*e[26]-e[3]*e[19]*e[17]+e[12]*e[7]*e[20]+e[12]*e[25]*e[2]-e[12]*e[1]*e[26]-e[12]*e[19]*e[8]+e[21]*e[7]*e[11]+e[21]*e[16]*e[2]-e[21]*e[1]*e[17]-e[21]*e[10]*e[8]+e[6]*e[10]*e[23]+e[6]*e[19]*e[14]-e[6]*e[13]*e[20]-e[6]*e[22]*e[11]+e[15]*e[1]*e[23]+e[15]*e[19]*e[5]-e[15]*e[4]*e[20]-e[15]*e[22]*e[2]+e[24]*e[1]*e[14]+e[24]*e[10]*e[5]-e[24]*e[4]*e[11]-e[24]*e[13]*e[2]+e[0]*e[13]*e[26]+e[0]*e[22]*e[17]-e[0]*e[14]*e[25]; + A[150]=e[18]*e[19]*e[25]+.5000000000*ep3[24]-.5000000000*e[24]*ep2[23]+e[18]*e[20]*e[26]+e[21]*e[22]*e[25]+e[21]*e[23]*e[26]-.5000000000*e[24]*ep2[19]+.5000000000*ep2[21]*e[24]+.5000000000*e[24]*ep2[26]-.5000000000*e[24]*ep2[20]+.5000000000*ep2[18]*e[24]-.5000000000*e[24]*ep2[22]+.5000000000*e[24]*ep2[25]; + A[5]=-e[3]*e[1]*e[35]-e[0]*e[32]*e[7]+e[27]*e[4]*e[8]+e[33]*e[1]*e[5]-e[33]*e[4]*e[2]+e[0]*e[4]*e[35]+e[3]*e[34]*e[2]-e[30]*e[1]*e[8]+e[30]*e[7]*e[2]-e[6]*e[4]*e[29]+e[3]*e[7]*e[29]+e[6]*e[1]*e[32]-e[0]*e[5]*e[34]-e[3]*e[28]*e[8]+e[0]*e[31]*e[8]+e[6]*e[28]*e[5]-e[6]*e[31]*e[2]-e[27]*e[5]*e[7]; + A[151]=e[33]*e[16]*e[7]-1.*e[33]*e[14]*e[5]+e[33]*e[17]*e[8]+e[30]*e[13]*e[7]+e[30]*e[4]*e[16]+e[30]*e[14]*e[8]+e[30]*e[5]*e[17]+e[6]*e[27]*e[9]-1.*e[6]*e[28]*e[10]-1.*e[6]*e[31]*e[13]-1.*e[6]*e[32]*e[14]-1.*e[6]*e[29]*e[11]+e[9]*e[28]*e[7]+e[9]*e[1]*e[34]+e[9]*e[29]*e[8]+e[9]*e[2]*e[35]+e[27]*e[10]*e[7]+e[27]*e[1]*e[16]+e[27]*e[11]*e[8]+e[27]*e[2]*e[17]+e[3]*e[30]*e[15]+e[3]*e[12]*e[33]+e[3]*e[32]*e[17]+e[3]*e[14]*e[35]+e[3]*e[31]*e[16]+e[3]*e[13]*e[34]+3.*e[6]*e[33]*e[15]+e[6]*e[35]*e[17]+e[6]*e[34]*e[16]+e[0]*e[27]*e[15]+e[0]*e[9]*e[33]+e[0]*e[29]*e[17]+e[0]*e[11]*e[35]+e[0]*e[28]*e[16]+e[0]*e[10]*e[34]+e[15]*e[34]*e[7]-1.*e[15]*e[32]*e[5]+e[15]*e[35]*e[8]-1.*e[15]*e[29]*e[2]-1.*e[15]*e[28]*e[1]-1.*e[15]*e[31]*e[4]+e[12]*e[30]*e[6]+e[12]*e[31]*e[7]+e[12]*e[4]*e[34]+e[12]*e[32]*e[8]+e[12]*e[5]*e[35]-1.*e[33]*e[11]*e[2]-1.*e[33]*e[10]*e[1]-1.*e[33]*e[13]*e[4]; + A[6]=e[6]*e[1]*e[5]-e[6]*e[4]*e[2]+e[3]*e[7]*e[2]+e[0]*e[4]*e[8]-e[0]*e[5]*e[7]-e[3]*e[1]*e[8]; + A[148]=.5000000000*ep3[15]+e[9]*e[10]*e[16]-.5000000000*e[15]*ep2[11]+e[9]*e[11]*e[17]+.5000000000*ep2[12]*e[15]+.5000000000*e[15]*ep2[16]+.5000000000*e[15]*ep2[17]-.5000000000*e[15]*ep2[13]+.5000000000*ep2[9]*e[15]+e[12]*e[14]*e[17]-.5000000000*e[15]*ep2[10]-.5000000000*e[15]*ep2[14]+e[12]*e[13]*e[16]; + A[7]=e[15]*e[28]*e[14]-e[15]*e[13]*e[29]-e[15]*e[31]*e[11]+e[33]*e[10]*e[14]-e[33]*e[13]*e[11]+e[9]*e[13]*e[35]-e[9]*e[32]*e[16]+e[9]*e[31]*e[17]-e[9]*e[14]*e[34]+e[27]*e[13]*e[17]-e[27]*e[14]*e[16]+e[12]*e[34]*e[11]+e[12]*e[16]*e[29]-e[12]*e[10]*e[35]-e[12]*e[28]*e[17]+e[30]*e[16]*e[11]-e[30]*e[10]*e[17]+e[15]*e[10]*e[32]; + A[149]=e[18]*e[27]*e[24]+e[18]*e[28]*e[25]+e[18]*e[19]*e[34]+e[18]*e[29]*e[26]+e[18]*e[20]*e[35]+e[27]*e[19]*e[25]+e[27]*e[20]*e[26]+e[21]*e[30]*e[24]+e[21]*e[31]*e[25]+e[21]*e[22]*e[34]+e[21]*e[32]*e[26]+e[21]*e[23]*e[35]+e[30]*e[22]*e[25]+e[30]*e[23]*e[26]+e[24]*e[34]*e[25]+e[24]*e[35]*e[26]-1.*e[24]*e[29]*e[20]-1.*e[24]*e[31]*e[22]-1.*e[24]*e[32]*e[23]-1.*e[24]*e[28]*e[19]+1.500000000*e[33]*ep2[24]+.5000000000*e[33]*ep2[25]+.5000000000*e[33]*ep2[26]-.5000000000*e[33]*ep2[23]-.5000000000*e[33]*ep2[19]-.5000000000*e[33]*ep2[20]-.5000000000*e[33]*ep2[22]+.5000000000*ep2[18]*e[33]+.5000000000*ep2[21]*e[33]; + A[9]=e[21]*e[25]*e[29]-e[27]*e[23]*e[25]+e[24]*e[19]*e[32]-e[21]*e[28]*e[26]-e[21]*e[19]*e[35]+e[18]*e[31]*e[26]-e[30]*e[19]*e[26]-e[24]*e[31]*e[20]+e[24]*e[28]*e[23]+e[27]*e[22]*e[26]+e[30]*e[25]*e[20]-e[33]*e[22]*e[20]+e[33]*e[19]*e[23]+e[21]*e[34]*e[20]-e[18]*e[23]*e[34]-e[24]*e[22]*e[29]-e[18]*e[32]*e[25]+e[18]*e[22]*e[35]; + A[155]=e[12]*e[14]*e[8]+e[12]*e[5]*e[17]+e[15]*e[16]*e[7]+e[15]*e[17]*e[8]+e[0]*e[11]*e[17]+e[0]*e[9]*e[15]+e[0]*e[10]*e[16]+e[3]*e[14]*e[17]+e[3]*e[13]*e[16]+e[9]*e[10]*e[7]+e[9]*e[1]*e[16]+e[9]*e[11]*e[8]+e[9]*e[2]*e[17]-1.*e[15]*e[11]*e[2]-1.*e[15]*e[10]*e[1]-1.*e[15]*e[13]*e[4]-1.*e[15]*e[14]*e[5]+e[12]*e[3]*e[15]+e[12]*e[13]*e[7]+e[12]*e[4]*e[16]+.5000000000*ep2[12]*e[6]+1.500000000*ep2[15]*e[6]+.5000000000*e[6]*ep2[17]+.5000000000*e[6]*ep2[16]+.5000000000*e[6]*ep2[9]-.5000000000*e[6]*ep2[11]-.5000000000*e[6]*ep2[10]-.5000000000*e[6]*ep2[14]-.5000000000*e[6]*ep2[13]; + A[8]=-e[9]*e[14]*e[16]-e[12]*e[10]*e[17]+e[9]*e[13]*e[17]-e[15]*e[13]*e[11]+e[15]*e[10]*e[14]+e[12]*e[16]*e[11]; + A[154]=e[21]*e[14]*e[17]+e[21]*e[13]*e[16]+e[15]*e[26]*e[17]+e[15]*e[25]*e[16]-1.*e[15]*e[23]*e[14]-1.*e[15]*e[20]*e[11]-1.*e[15]*e[19]*e[10]-1.*e[15]*e[22]*e[13]+e[9]*e[20]*e[17]+e[9]*e[11]*e[26]+e[9]*e[19]*e[16]+e[9]*e[10]*e[25]+.5000000000*ep2[12]*e[24]+1.500000000*e[24]*ep2[15]+.5000000000*e[24]*ep2[17]+.5000000000*e[24]*ep2[16]+.5000000000*ep2[9]*e[24]-.5000000000*e[24]*ep2[11]-.5000000000*e[24]*ep2[10]-.5000000000*e[24]*ep2[14]-.5000000000*e[24]*ep2[13]+e[18]*e[11]*e[17]+e[18]*e[9]*e[15]+e[18]*e[10]*e[16]+e[12]*e[21]*e[15]+e[12]*e[23]*e[17]+e[12]*e[14]*e[26]+e[12]*e[22]*e[16]+e[12]*e[13]*e[25]; + A[11]=-e[9]*e[5]*e[34]+e[9]*e[31]*e[8]-e[9]*e[32]*e[7]+e[27]*e[4]*e[17]+e[27]*e[13]*e[8]-e[27]*e[5]*e[16]-e[27]*e[14]*e[7]+e[0]*e[13]*e[35]-e[0]*e[32]*e[16]+e[0]*e[31]*e[17]-e[0]*e[14]*e[34]+e[9]*e[4]*e[35]+e[6]*e[10]*e[32]+e[6]*e[28]*e[14]-e[6]*e[13]*e[29]-e[6]*e[31]*e[11]+e[15]*e[1]*e[32]+e[3]*e[34]*e[11]+e[3]*e[16]*e[29]-e[3]*e[10]*e[35]-e[3]*e[28]*e[17]-e[12]*e[1]*e[35]+e[12]*e[7]*e[29]+e[12]*e[34]*e[2]-e[12]*e[28]*e[8]+e[15]*e[28]*e[5]-e[15]*e[4]*e[29]-e[15]*e[31]*e[2]+e[33]*e[1]*e[14]+e[33]*e[10]*e[5]-e[33]*e[4]*e[11]-e[33]*e[13]*e[2]+e[30]*e[7]*e[11]+e[30]*e[16]*e[2]-e[30]*e[1]*e[17]-e[30]*e[10]*e[8]; + A[153]=e[21]*e[31]*e[7]+e[21]*e[4]*e[34]+e[21]*e[32]*e[8]+e[21]*e[5]*e[35]+e[30]*e[22]*e[7]+e[30]*e[4]*e[25]+e[30]*e[23]*e[8]+e[30]*e[5]*e[26]+3.*e[24]*e[33]*e[6]+e[24]*e[34]*e[7]+e[24]*e[35]*e[8]+e[33]*e[25]*e[7]+e[33]*e[26]*e[8]+e[0]*e[27]*e[24]+e[0]*e[18]*e[33]+e[0]*e[28]*e[25]+e[0]*e[19]*e[34]+e[0]*e[29]*e[26]+e[0]*e[20]*e[35]+e[18]*e[27]*e[6]+e[18]*e[28]*e[7]+e[18]*e[1]*e[34]+e[18]*e[29]*e[8]+e[18]*e[2]*e[35]+e[27]*e[19]*e[7]+e[27]*e[1]*e[25]+e[27]*e[20]*e[8]+e[27]*e[2]*e[26]+e[3]*e[30]*e[24]+e[3]*e[21]*e[33]+e[3]*e[31]*e[25]+e[3]*e[22]*e[34]+e[3]*e[32]*e[26]+e[3]*e[23]*e[35]+e[6]*e[30]*e[21]-1.*e[6]*e[29]*e[20]+e[6]*e[35]*e[26]-1.*e[6]*e[31]*e[22]-1.*e[6]*e[32]*e[23]-1.*e[6]*e[28]*e[19]+e[6]*e[34]*e[25]-1.*e[24]*e[32]*e[5]-1.*e[24]*e[29]*e[2]-1.*e[24]*e[28]*e[1]-1.*e[24]*e[31]*e[4]-1.*e[33]*e[20]*e[2]-1.*e[33]*e[19]*e[1]-1.*e[33]*e[22]*e[4]-1.*e[33]*e[23]*e[5]; + A[10]=e[21]*e[25]*e[20]-e[21]*e[19]*e[26]+e[18]*e[22]*e[26]-e[18]*e[23]*e[25]-e[24]*e[22]*e[20]+e[24]*e[19]*e[23]; + A[152]=e[3]*e[4]*e[25]+e[3]*e[23]*e[8]+e[3]*e[5]*e[26]+e[21]*e[4]*e[7]+e[21]*e[5]*e[8]+e[6]*e[25]*e[7]+e[6]*e[26]*e[8]+e[0]*e[19]*e[7]+e[0]*e[1]*e[25]+e[0]*e[20]*e[8]+e[0]*e[2]*e[26]-1.*e[6]*e[20]*e[2]-1.*e[6]*e[19]*e[1]-1.*e[6]*e[22]*e[4]-1.*e[6]*e[23]*e[5]+e[18]*e[1]*e[7]+e[18]*e[0]*e[6]+e[18]*e[2]*e[8]+e[3]*e[21]*e[6]+e[3]*e[22]*e[7]-.5000000000*e[24]*ep2[4]+.5000000000*e[24]*ep2[0]+1.500000000*e[24]*ep2[6]-.5000000000*e[24]*ep2[5]-.5000000000*e[24]*ep2[1]+.5000000000*e[24]*ep2[7]+.5000000000*e[24]*ep2[3]-.5000000000*e[24]*ep2[2]+.5000000000*e[24]*ep2[8]; + A[13]=e[6]*e[28]*e[23]-e[6]*e[22]*e[29]-e[6]*e[31]*e[20]-e[3]*e[19]*e[35]+e[3]*e[34]*e[20]+e[3]*e[25]*e[29]-e[21]*e[1]*e[35]+e[21]*e[7]*e[29]+e[21]*e[34]*e[2]+e[24]*e[1]*e[32]+e[24]*e[28]*e[5]-e[24]*e[4]*e[29]-e[24]*e[31]*e[2]+e[33]*e[1]*e[23]+e[33]*e[19]*e[5]-e[33]*e[4]*e[20]-e[33]*e[22]*e[2]-e[21]*e[28]*e[8]+e[30]*e[7]*e[20]+e[30]*e[25]*e[2]-e[30]*e[1]*e[26]+e[18]*e[4]*e[35]-e[18]*e[5]*e[34]+e[18]*e[31]*e[8]-e[18]*e[32]*e[7]+e[27]*e[4]*e[26]+e[27]*e[22]*e[8]-e[27]*e[5]*e[25]-e[27]*e[23]*e[7]-e[3]*e[28]*e[26]-e[0]*e[32]*e[25]+e[0]*e[22]*e[35]-e[0]*e[23]*e[34]+e[0]*e[31]*e[26]-e[30]*e[19]*e[8]+e[6]*e[19]*e[32]; + A[159]=.5000000000*ep2[18]*e[6]+.5000000000*ep2[21]*e[6]+1.500000000*ep2[24]*e[6]+.5000000000*e[6]*ep2[26]-.5000000000*e[6]*ep2[23]-.5000000000*e[6]*ep2[19]-.5000000000*e[6]*ep2[20]-.5000000000*e[6]*ep2[22]+.5000000000*e[6]*ep2[25]+e[21]*e[3]*e[24]+e[18]*e[20]*e[8]+e[21]*e[4]*e[25]+e[18]*e[19]*e[7]+e[18]*e[1]*e[25]+e[21]*e[22]*e[7]+e[21]*e[23]*e[8]+e[18]*e[0]*e[24]+e[18]*e[2]*e[26]+e[21]*e[5]*e[26]+e[24]*e[26]*e[8]-1.*e[24]*e[20]*e[2]-1.*e[24]*e[19]*e[1]-1.*e[24]*e[22]*e[4]+e[24]*e[25]*e[7]-1.*e[24]*e[23]*e[5]+e[0]*e[19]*e[25]+e[0]*e[20]*e[26]+e[3]*e[22]*e[25]+e[3]*e[23]*e[26]; + A[12]=e[18]*e[4]*e[8]+e[3]*e[7]*e[20]+e[3]*e[25]*e[2]-e[3]*e[1]*e[26]-e[18]*e[5]*e[7]+e[6]*e[1]*e[23]+e[6]*e[19]*e[5]-e[6]*e[4]*e[20]-e[6]*e[22]*e[2]+e[21]*e[7]*e[2]-e[21]*e[1]*e[8]+e[24]*e[1]*e[5]-e[24]*e[4]*e[2]-e[3]*e[19]*e[8]+e[0]*e[4]*e[26]+e[0]*e[22]*e[8]-e[0]*e[5]*e[25]-e[0]*e[23]*e[7]; + A[158]=e[9]*e[1]*e[7]+e[9]*e[0]*e[6]+e[9]*e[2]*e[8]+e[3]*e[12]*e[6]+e[3]*e[13]*e[7]+e[3]*e[4]*e[16]+e[3]*e[14]*e[8]+e[3]*e[5]*e[17]+e[12]*e[4]*e[7]+e[12]*e[5]*e[8]+e[6]*e[16]*e[7]+e[6]*e[17]*e[8]-1.*e[6]*e[11]*e[2]-1.*e[6]*e[10]*e[1]-1.*e[6]*e[13]*e[4]-1.*e[6]*e[14]*e[5]+e[0]*e[10]*e[7]+e[0]*e[1]*e[16]+e[0]*e[11]*e[8]+e[0]*e[2]*e[17]+.5000000000*ep2[3]*e[15]+1.500000000*e[15]*ep2[6]+.5000000000*e[15]*ep2[7]+.5000000000*e[15]*ep2[8]+.5000000000*ep2[0]*e[15]-.5000000000*e[15]*ep2[4]-.5000000000*e[15]*ep2[5]-.5000000000*e[15]*ep2[1]-.5000000000*e[15]*ep2[2]; + A[15]=-e[15]*e[13]*e[2]-e[6]*e[13]*e[11]-e[15]*e[4]*e[11]+e[12]*e[16]*e[2]-e[3]*e[10]*e[17]+e[3]*e[16]*e[11]+e[0]*e[13]*e[17]-e[0]*e[14]*e[16]+e[15]*e[1]*e[14]-e[12]*e[10]*e[8]+e[9]*e[4]*e[17]+e[9]*e[13]*e[8]-e[9]*e[5]*e[16]-e[9]*e[14]*e[7]+e[15]*e[10]*e[5]+e[12]*e[7]*e[11]+e[6]*e[10]*e[14]-e[12]*e[1]*e[17]; + A[157]=e[12]*e[30]*e[24]+e[12]*e[21]*e[33]+e[12]*e[31]*e[25]+e[12]*e[22]*e[34]+e[12]*e[32]*e[26]+e[12]*e[23]*e[35]+e[9]*e[27]*e[24]+e[9]*e[18]*e[33]+e[9]*e[28]*e[25]+e[9]*e[19]*e[34]+e[9]*e[29]*e[26]+e[9]*e[20]*e[35]+e[21]*e[30]*e[15]+e[21]*e[32]*e[17]+e[21]*e[14]*e[35]+e[21]*e[31]*e[16]+e[21]*e[13]*e[34]+e[30]*e[23]*e[17]+e[30]*e[14]*e[26]+e[30]*e[22]*e[16]+e[30]*e[13]*e[25]+e[15]*e[27]*e[18]+3.*e[15]*e[33]*e[24]-1.*e[15]*e[29]*e[20]+e[15]*e[35]*e[26]-1.*e[15]*e[31]*e[22]-1.*e[15]*e[32]*e[23]-1.*e[15]*e[28]*e[19]+e[15]*e[34]*e[25]+e[18]*e[29]*e[17]+e[18]*e[11]*e[35]+e[18]*e[28]*e[16]+e[18]*e[10]*e[34]+e[27]*e[20]*e[17]+e[27]*e[11]*e[26]+e[27]*e[19]*e[16]+e[27]*e[10]*e[25]-1.*e[24]*e[28]*e[10]-1.*e[24]*e[31]*e[13]-1.*e[24]*e[32]*e[14]+e[24]*e[34]*e[16]+e[24]*e[35]*e[17]-1.*e[24]*e[29]*e[11]-1.*e[33]*e[23]*e[14]+e[33]*e[25]*e[16]+e[33]*e[26]*e[17]-1.*e[33]*e[20]*e[11]-1.*e[33]*e[19]*e[10]-1.*e[33]*e[22]*e[13]; + A[14]=e[18]*e[13]*e[17]+e[9]*e[13]*e[26]+e[9]*e[22]*e[17]-e[9]*e[14]*e[25]-e[18]*e[14]*e[16]-e[15]*e[13]*e[20]-e[15]*e[22]*e[11]+e[12]*e[16]*e[20]+e[12]*e[25]*e[11]-e[12]*e[10]*e[26]-e[12]*e[19]*e[17]+e[21]*e[16]*e[11]-e[21]*e[10]*e[17]-e[9]*e[23]*e[16]+e[24]*e[10]*e[14]-e[24]*e[13]*e[11]+e[15]*e[10]*e[23]+e[15]*e[19]*e[14]; + A[156]=e[21]*e[12]*e[24]+e[21]*e[23]*e[17]+e[21]*e[14]*e[26]+e[21]*e[22]*e[16]+e[21]*e[13]*e[25]+e[24]*e[26]*e[17]+e[24]*e[25]*e[16]+e[9]*e[19]*e[25]+e[9]*e[18]*e[24]+e[9]*e[20]*e[26]+e[12]*e[22]*e[25]+e[12]*e[23]*e[26]+e[18]*e[20]*e[17]+e[18]*e[11]*e[26]+e[18]*e[19]*e[16]+e[18]*e[10]*e[25]-1.*e[24]*e[23]*e[14]-1.*e[24]*e[20]*e[11]-1.*e[24]*e[19]*e[10]-1.*e[24]*e[22]*e[13]+.5000000000*ep2[21]*e[15]+1.500000000*ep2[24]*e[15]+.5000000000*e[15]*ep2[25]+.5000000000*e[15]*ep2[26]+.5000000000*e[15]*ep2[18]-.5000000000*e[15]*ep2[23]-.5000000000*e[15]*ep2[19]-.5000000000*e[15]*ep2[20]-.5000000000*e[15]*ep2[22]; + A[18]=e[6]*e[1]*e[14]+e[15]*e[1]*e[5]-e[0]*e[5]*e[16]-e[0]*e[14]*e[7]+e[0]*e[13]*e[8]-e[15]*e[4]*e[2]+e[12]*e[7]*e[2]+e[6]*e[10]*e[5]+e[3]*e[7]*e[11]-e[6]*e[4]*e[11]+e[3]*e[16]*e[2]-e[6]*e[13]*e[2]-e[3]*e[1]*e[17]-e[9]*e[5]*e[7]-e[3]*e[10]*e[8]-e[12]*e[1]*e[8]+e[0]*e[4]*e[17]+e[9]*e[4]*e[8]; + A[128]=-.5000000000*e[14]*ep2[16]-.5000000000*e[14]*ep2[10]-.5000000000*e[14]*ep2[9]+e[11]*e[9]*e[12]+.5000000000*ep3[14]+e[17]*e[13]*e[16]+.5000000000*e[14]*ep2[12]+e[11]*e[10]*e[13]-.5000000000*e[14]*ep2[15]+.5000000000*e[14]*ep2[17]+e[17]*e[12]*e[15]+.5000000000*ep2[11]*e[14]+.5000000000*e[14]*ep2[13]; + A[19]=-e[21]*e[19]*e[8]+e[18]*e[4]*e[26]-e[18]*e[5]*e[25]-e[18]*e[23]*e[7]+e[21]*e[25]*e[2]-e[21]*e[1]*e[26]+e[6]*e[19]*e[23]+e[18]*e[22]*e[8]-e[0]*e[23]*e[25]-e[6]*e[22]*e[20]+e[24]*e[1]*e[23]+e[24]*e[19]*e[5]-e[24]*e[4]*e[20]-e[24]*e[22]*e[2]+e[3]*e[25]*e[20]-e[3]*e[19]*e[26]+e[0]*e[22]*e[26]+e[21]*e[7]*e[20]; + A[129]=.5000000000*ep2[20]*e[32]+1.500000000*e[32]*ep2[23]+.5000000000*e[32]*ep2[22]+.5000000000*e[32]*ep2[21]+.5000000000*e[32]*ep2[26]-.5000000000*e[32]*ep2[18]-.5000000000*e[32]*ep2[19]-.5000000000*e[32]*ep2[24]-.5000000000*e[32]*ep2[25]+e[20]*e[27]*e[21]+e[20]*e[18]*e[30]+e[20]*e[28]*e[22]+e[20]*e[19]*e[31]+e[20]*e[29]*e[23]+e[29]*e[19]*e[22]+e[29]*e[18]*e[21]+e[23]*e[30]*e[21]+e[23]*e[31]*e[22]+e[26]*e[30]*e[24]+e[26]*e[21]*e[33]+e[26]*e[31]*e[25]+e[26]*e[22]*e[34]+e[26]*e[23]*e[35]+e[35]*e[22]*e[25]+e[35]*e[21]*e[24]-1.*e[23]*e[27]*e[18]-1.*e[23]*e[33]*e[24]-1.*e[23]*e[28]*e[19]-1.*e[23]*e[34]*e[25]; + A[16]=-e[9]*e[23]*e[25]-e[21]*e[10]*e[26]-e[21]*e[19]*e[17]-e[18]*e[23]*e[16]+e[18]*e[13]*e[26]+e[12]*e[25]*e[20]-e[12]*e[19]*e[26]-e[15]*e[22]*e[20]+e[21]*e[16]*e[20]+e[21]*e[25]*e[11]+e[24]*e[10]*e[23]+e[24]*e[19]*e[14]-e[24]*e[13]*e[20]-e[24]*e[22]*e[11]+e[18]*e[22]*e[17]-e[18]*e[14]*e[25]+e[9]*e[22]*e[26]+e[15]*e[19]*e[23]; + A[130]=.5000000000*e[23]*ep2[21]+e[20]*e[19]*e[22]+e[20]*e[18]*e[21]+.5000000000*ep3[23]+e[26]*e[22]*e[25]+.5000000000*e[23]*ep2[26]-.5000000000*e[23]*ep2[18]+.5000000000*e[23]*ep2[22]-.5000000000*e[23]*ep2[19]+e[26]*e[21]*e[24]+.5000000000*ep2[20]*e[23]-.5000000000*e[23]*ep2[24]-.5000000000*e[23]*ep2[25]; + A[17]=e[18]*e[13]*e[35]-e[18]*e[32]*e[16]+e[18]*e[31]*e[17]-e[18]*e[14]*e[34]+e[27]*e[13]*e[26]+e[27]*e[22]*e[17]-e[27]*e[14]*e[25]-e[27]*e[23]*e[16]-e[9]*e[32]*e[25]+e[9]*e[22]*e[35]-e[9]*e[23]*e[34]+e[9]*e[31]*e[26]+e[15]*e[19]*e[32]+e[15]*e[28]*e[23]-e[15]*e[22]*e[29]-e[15]*e[31]*e[20]+e[24]*e[10]*e[32]+e[24]*e[28]*e[14]-e[24]*e[13]*e[29]-e[24]*e[31]*e[11]+e[33]*e[10]*e[23]+e[33]*e[19]*e[14]-e[33]*e[13]*e[20]-e[33]*e[22]*e[11]+e[21]*e[16]*e[29]-e[21]*e[10]*e[35]-e[21]*e[28]*e[17]+e[30]*e[16]*e[20]+e[30]*e[25]*e[11]-e[30]*e[10]*e[26]-e[30]*e[19]*e[17]-e[12]*e[28]*e[26]-e[12]*e[19]*e[35]+e[12]*e[34]*e[20]+e[12]*e[25]*e[29]+e[21]*e[34]*e[11]; + A[131]=-1.*e[32]*e[10]*e[1]+e[32]*e[13]*e[4]-1.*e[32]*e[16]*e[7]-1.*e[32]*e[15]*e[6]-1.*e[32]*e[9]*e[0]+e[32]*e[12]*e[3]+e[17]*e[30]*e[6]+e[17]*e[3]*e[33]+e[17]*e[31]*e[7]+e[17]*e[4]*e[34]+e[17]*e[5]*e[35]-1.*e[5]*e[27]*e[9]-1.*e[5]*e[28]*e[10]-1.*e[5]*e[33]*e[15]-1.*e[5]*e[34]*e[16]+e[5]*e[29]*e[11]+e[35]*e[12]*e[6]+e[35]*e[3]*e[15]+e[35]*e[13]*e[7]+e[35]*e[4]*e[16]+e[11]*e[27]*e[3]+e[11]*e[0]*e[30]+e[11]*e[28]*e[4]+e[11]*e[1]*e[31]+e[29]*e[9]*e[3]+e[29]*e[0]*e[12]+e[29]*e[10]*e[4]+e[29]*e[1]*e[13]+e[5]*e[30]*e[12]+3.*e[5]*e[32]*e[14]+e[5]*e[31]*e[13]+e[8]*e[30]*e[15]+e[8]*e[12]*e[33]+e[8]*e[32]*e[17]+e[8]*e[14]*e[35]+e[8]*e[31]*e[16]+e[8]*e[13]*e[34]+e[2]*e[27]*e[12]+e[2]*e[9]*e[30]+e[2]*e[29]*e[14]+e[2]*e[11]*e[32]+e[2]*e[28]*e[13]+e[2]*e[10]*e[31]-1.*e[14]*e[27]*e[0]-1.*e[14]*e[34]*e[7]-1.*e[14]*e[33]*e[6]+e[14]*e[30]*e[3]-1.*e[14]*e[28]*e[1]+e[14]*e[31]*e[4]; + A[22]=.5000000000*e[18]*ep2[29]+.5000000000*e[18]*ep2[28]+.5000000000*e[18]*ep2[30]+.5000000000*e[18]*ep2[33]-.5000000000*e[18]*ep2[32]-.5000000000*e[18]*ep2[31]-.5000000000*e[18]*ep2[34]-.5000000000*e[18]*ep2[35]+1.500000000*e[18]*ep2[27]+e[27]*e[28]*e[19]+e[27]*e[29]*e[20]+e[21]*e[27]*e[30]+e[21]*e[29]*e[32]+e[21]*e[28]*e[31]+e[30]*e[28]*e[22]+e[30]*e[19]*e[31]+e[30]*e[29]*e[23]+e[30]*e[20]*e[32]+e[24]*e[27]*e[33]+e[24]*e[29]*e[35]+e[24]*e[28]*e[34]+e[33]*e[28]*e[25]+e[33]*e[19]*e[34]+e[33]*e[29]*e[26]+e[33]*e[20]*e[35]-1.*e[27]*e[35]*e[26]-1.*e[27]*e[31]*e[22]-1.*e[27]*e[32]*e[23]-1.*e[27]*e[34]*e[25]; + A[132]=e[20]*e[1]*e[4]+e[20]*e[0]*e[3]+e[20]*e[2]*e[5]+e[5]*e[21]*e[3]+e[5]*e[22]*e[4]+e[8]*e[21]*e[6]+e[8]*e[3]*e[24]+e[8]*e[22]*e[7]+e[8]*e[4]*e[25]+e[8]*e[5]*e[26]+e[26]*e[4]*e[7]+e[26]*e[3]*e[6]+e[2]*e[18]*e[3]+e[2]*e[0]*e[21]+e[2]*e[19]*e[4]+e[2]*e[1]*e[22]-1.*e[5]*e[19]*e[1]-1.*e[5]*e[18]*e[0]-1.*e[5]*e[25]*e[7]-1.*e[5]*e[24]*e[6]+.5000000000*e[23]*ep2[4]-.5000000000*e[23]*ep2[0]-.5000000000*e[23]*ep2[6]+1.500000000*e[23]*ep2[5]-.5000000000*e[23]*ep2[1]-.5000000000*e[23]*ep2[7]+.5000000000*e[23]*ep2[3]+.5000000000*e[23]*ep2[2]+.5000000000*e[23]*ep2[8]; + A[23]=1.500000000*e[9]*ep2[27]+.5000000000*e[9]*ep2[29]+.5000000000*e[9]*ep2[28]-.5000000000*e[9]*ep2[32]-.5000000000*e[9]*ep2[31]+.5000000000*e[9]*ep2[33]+.5000000000*e[9]*ep2[30]-.5000000000*e[9]*ep2[34]-.5000000000*e[9]*ep2[35]+e[33]*e[27]*e[15]+e[33]*e[29]*e[17]+e[33]*e[11]*e[35]+e[33]*e[28]*e[16]+e[33]*e[10]*e[34]+e[27]*e[29]*e[11]+e[27]*e[28]*e[10]+e[27]*e[30]*e[12]-1.*e[27]*e[31]*e[13]-1.*e[27]*e[32]*e[14]-1.*e[27]*e[34]*e[16]-1.*e[27]*e[35]*e[17]+e[30]*e[29]*e[14]+e[30]*e[11]*e[32]+e[30]*e[28]*e[13]+e[30]*e[10]*e[31]+e[12]*e[29]*e[32]+e[12]*e[28]*e[31]+e[15]*e[29]*e[35]+e[15]*e[28]*e[34]; + A[133]=-1.*e[32]*e[24]*e[6]+e[8]*e[30]*e[24]+e[8]*e[21]*e[33]+e[8]*e[31]*e[25]+e[8]*e[22]*e[34]+e[26]*e[30]*e[6]+e[26]*e[3]*e[33]+e[26]*e[31]*e[7]+e[26]*e[4]*e[34]+e[26]*e[32]*e[8]+e[26]*e[5]*e[35]+e[35]*e[21]*e[6]+e[35]*e[3]*e[24]+e[35]*e[22]*e[7]+e[35]*e[4]*e[25]+e[35]*e[23]*e[8]+e[2]*e[27]*e[21]+e[2]*e[18]*e[30]+e[2]*e[28]*e[22]+e[2]*e[19]*e[31]+e[2]*e[29]*e[23]+e[2]*e[20]*e[32]+e[20]*e[27]*e[3]+e[20]*e[0]*e[30]+e[20]*e[28]*e[4]+e[20]*e[1]*e[31]+e[20]*e[29]*e[5]+e[29]*e[18]*e[3]+e[29]*e[0]*e[21]+e[29]*e[19]*e[4]+e[29]*e[1]*e[22]+e[5]*e[30]*e[21]+e[5]*e[31]*e[22]+3.*e[5]*e[32]*e[23]-1.*e[5]*e[27]*e[18]-1.*e[5]*e[33]*e[24]-1.*e[5]*e[28]*e[19]-1.*e[5]*e[34]*e[25]-1.*e[23]*e[27]*e[0]-1.*e[23]*e[34]*e[7]-1.*e[23]*e[33]*e[6]+e[23]*e[30]*e[3]-1.*e[23]*e[28]*e[1]+e[23]*e[31]*e[4]+e[32]*e[21]*e[3]-1.*e[32]*e[19]*e[1]+e[32]*e[22]*e[4]-1.*e[32]*e[18]*e[0]-1.*e[32]*e[25]*e[7]; + A[20]=.5000000000*e[27]*ep2[33]-.5000000000*e[27]*ep2[32]-.5000000000*e[27]*ep2[31]-.5000000000*e[27]*ep2[34]-.5000000000*e[27]*ep2[35]+e[33]*e[29]*e[35]+.5000000000*e[27]*ep2[29]+e[30]*e[29]*e[32]+e[30]*e[28]*e[31]+e[33]*e[28]*e[34]+.5000000000*e[27]*ep2[28]+.5000000000*e[27]*ep2[30]+.5000000000*ep3[27]; + A[134]=e[14]*e[21]*e[12]+e[14]*e[22]*e[13]+e[17]*e[21]*e[15]+e[17]*e[12]*e[24]+e[17]*e[14]*e[26]+e[17]*e[22]*e[16]+e[17]*e[13]*e[25]+e[26]*e[12]*e[15]+e[26]*e[13]*e[16]-1.*e[14]*e[24]*e[15]-1.*e[14]*e[25]*e[16]-1.*e[14]*e[18]*e[9]-1.*e[14]*e[19]*e[10]+e[11]*e[18]*e[12]+e[11]*e[9]*e[21]+e[11]*e[19]*e[13]+e[11]*e[10]*e[22]+e[20]*e[11]*e[14]+e[20]*e[9]*e[12]+e[20]*e[10]*e[13]+1.500000000*e[23]*ep2[14]+.5000000000*e[23]*ep2[12]+.5000000000*e[23]*ep2[13]+.5000000000*e[23]*ep2[17]+.5000000000*ep2[11]*e[23]-.5000000000*e[23]*ep2[16]-.5000000000*e[23]*ep2[9]-.5000000000*e[23]*ep2[15]-.5000000000*e[23]*ep2[10]; + A[21]=1.500000000*e[0]*ep2[27]+.5000000000*e[0]*ep2[29]+.5000000000*e[0]*ep2[28]+.5000000000*e[0]*ep2[30]-.5000000000*e[0]*ep2[32]-.5000000000*e[0]*ep2[31]+.5000000000*e[0]*ep2[33]-.5000000000*e[0]*ep2[34]-.5000000000*e[0]*ep2[35]-1.*e[27]*e[31]*e[4]+e[3]*e[27]*e[30]+e[3]*e[29]*e[32]+e[3]*e[28]*e[31]+e[30]*e[28]*e[4]+e[30]*e[1]*e[31]+e[30]*e[29]*e[5]+e[30]*e[2]*e[32]+e[6]*e[27]*e[33]+e[6]*e[29]*e[35]+e[6]*e[28]*e[34]+e[27]*e[28]*e[1]+e[27]*e[29]*e[2]+e[33]*e[28]*e[7]+e[33]*e[1]*e[34]+e[33]*e[29]*e[8]+e[33]*e[2]*e[35]-1.*e[27]*e[34]*e[7]-1.*e[27]*e[32]*e[5]-1.*e[27]*e[35]*e[8]; + A[135]=e[14]*e[12]*e[3]+e[14]*e[13]*e[4]+e[17]*e[12]*e[6]+e[17]*e[3]*e[15]+e[17]*e[13]*e[7]+e[17]*e[4]*e[16]+e[17]*e[14]*e[8]+e[8]*e[12]*e[15]+e[8]*e[13]*e[16]+e[2]*e[11]*e[14]+e[2]*e[9]*e[12]+e[2]*e[10]*e[13]+e[11]*e[9]*e[3]+e[11]*e[0]*e[12]+e[11]*e[10]*e[4]+e[11]*e[1]*e[13]-1.*e[14]*e[10]*e[1]-1.*e[14]*e[16]*e[7]-1.*e[14]*e[15]*e[6]-1.*e[14]*e[9]*e[0]-.5000000000*e[5]*ep2[16]-.5000000000*e[5]*ep2[9]+.5000000000*e[5]*ep2[11]+.5000000000*e[5]*ep2[12]-.5000000000*e[5]*ep2[15]-.5000000000*e[5]*ep2[10]+.5000000000*e[5]*ep2[13]+1.500000000*ep2[14]*e[5]+.5000000000*e[5]*ep2[17]; + A[27]=1.500000000*e[27]*ep2[9]-.5000000000*e[27]*ep2[16]+.5000000000*e[27]*ep2[11]+.5000000000*e[27]*ep2[12]+.5000000000*e[27]*ep2[15]-.5000000000*e[27]*ep2[17]+.5000000000*e[27]*ep2[10]-.5000000000*e[27]*ep2[14]-.5000000000*e[27]*ep2[13]+e[12]*e[10]*e[31]+e[30]*e[11]*e[14]+e[30]*e[10]*e[13]+e[15]*e[9]*e[33]+e[15]*e[29]*e[17]+e[15]*e[11]*e[35]+e[15]*e[28]*e[16]+e[15]*e[10]*e[34]+e[33]*e[11]*e[17]+e[33]*e[10]*e[16]-1.*e[9]*e[31]*e[13]-1.*e[9]*e[32]*e[14]-1.*e[9]*e[34]*e[16]-1.*e[9]*e[35]*e[17]+e[9]*e[29]*e[11]+e[9]*e[28]*e[10]+e[12]*e[9]*e[30]+e[12]*e[29]*e[14]+e[12]*e[11]*e[32]+e[12]*e[28]*e[13]; + A[137]=e[29]*e[18]*e[12]+e[29]*e[9]*e[21]+e[29]*e[19]*e[13]+e[29]*e[10]*e[22]+e[17]*e[30]*e[24]+e[17]*e[21]*e[33]+e[17]*e[31]*e[25]+e[17]*e[22]*e[34]+e[17]*e[32]*e[26]+e[17]*e[23]*e[35]-1.*e[23]*e[27]*e[9]-1.*e[23]*e[28]*e[10]-1.*e[23]*e[33]*e[15]-1.*e[23]*e[34]*e[16]-1.*e[32]*e[24]*e[15]-1.*e[32]*e[25]*e[16]-1.*e[32]*e[18]*e[9]-1.*e[32]*e[19]*e[10]+e[26]*e[30]*e[15]+e[26]*e[12]*e[33]+e[26]*e[31]*e[16]+e[26]*e[13]*e[34]+e[35]*e[21]*e[15]+e[35]*e[12]*e[24]+e[35]*e[22]*e[16]+e[35]*e[13]*e[25]+e[14]*e[30]*e[21]+e[14]*e[31]*e[22]+3.*e[14]*e[32]*e[23]+e[11]*e[27]*e[21]+e[11]*e[18]*e[30]+e[11]*e[28]*e[22]+e[11]*e[19]*e[31]+e[11]*e[29]*e[23]+e[11]*e[20]*e[32]+e[23]*e[30]*e[12]+e[23]*e[31]*e[13]+e[32]*e[21]*e[12]+e[32]*e[22]*e[13]-1.*e[14]*e[27]*e[18]-1.*e[14]*e[33]*e[24]+e[14]*e[29]*e[20]+e[14]*e[35]*e[26]-1.*e[14]*e[28]*e[19]-1.*e[14]*e[34]*e[25]+e[20]*e[27]*e[12]+e[20]*e[9]*e[30]+e[20]*e[28]*e[13]+e[20]*e[10]*e[31]; + A[26]=.5000000000*e[0]*ep2[1]+.5000000000*e[0]*ep2[2]+e[6]*e[2]*e[8]+e[6]*e[1]*e[7]+.5000000000*e[0]*ep2[3]+e[3]*e[1]*e[4]+.5000000000*e[0]*ep2[6]+e[3]*e[2]*e[5]-.5000000000*e[0]*ep2[5]-.5000000000*e[0]*ep2[8]+.5000000000*ep3[0]-.5000000000*e[0]*ep2[7]-.5000000000*e[0]*ep2[4]; + A[136]=1.500000000*ep2[23]*e[14]+.5000000000*e[14]*ep2[26]-.5000000000*e[14]*ep2[18]-.5000000000*e[14]*ep2[19]+.5000000000*e[14]*ep2[20]+.5000000000*e[14]*ep2[22]-.5000000000*e[14]*ep2[24]+.5000000000*e[14]*ep2[21]-.5000000000*e[14]*ep2[25]+e[23]*e[21]*e[12]+e[23]*e[22]*e[13]+e[26]*e[21]*e[15]+e[26]*e[12]*e[24]+e[26]*e[23]*e[17]+e[26]*e[22]*e[16]+e[26]*e[13]*e[25]+e[17]*e[22]*e[25]+e[17]*e[21]*e[24]+e[11]*e[19]*e[22]+e[11]*e[18]*e[21]+e[11]*e[20]*e[23]+e[20]*e[18]*e[12]+e[20]*e[9]*e[21]+e[20]*e[19]*e[13]+e[20]*e[10]*e[22]-1.*e[23]*e[24]*e[15]-1.*e[23]*e[25]*e[16]-1.*e[23]*e[18]*e[9]-1.*e[23]*e[19]*e[10]; + A[25]=1.500000000*e[27]*ep2[0]-.5000000000*e[27]*ep2[4]+.5000000000*e[27]*ep2[6]-.5000000000*e[27]*ep2[5]+.5000000000*e[27]*ep2[1]-.5000000000*e[27]*ep2[7]+.5000000000*e[27]*ep2[3]+.5000000000*e[27]*ep2[2]-.5000000000*e[27]*ep2[8]+e[0]*e[33]*e[6]+e[0]*e[30]*e[3]-1.*e[0]*e[35]*e[8]-1.*e[0]*e[31]*e[4]+e[3]*e[28]*e[4]+e[3]*e[1]*e[31]+e[3]*e[29]*e[5]+e[3]*e[2]*e[32]+e[30]*e[1]*e[4]+e[30]*e[2]*e[5]+e[6]*e[28]*e[7]+e[6]*e[1]*e[34]+e[6]*e[29]*e[8]+e[6]*e[2]*e[35]+e[33]*e[1]*e[7]+e[33]*e[2]*e[8]+e[0]*e[28]*e[1]+e[0]*e[29]*e[2]-1.*e[0]*e[34]*e[7]-1.*e[0]*e[32]*e[5]; + A[139]=e[8]*e[22]*e[25]+e[8]*e[21]*e[24]+e[20]*e[18]*e[3]+e[20]*e[0]*e[21]+e[20]*e[19]*e[4]+e[20]*e[1]*e[22]+e[20]*e[2]*e[23]+e[23]*e[21]*e[3]+e[23]*e[22]*e[4]+e[23]*e[26]*e[8]-1.*e[23]*e[19]*e[1]-1.*e[23]*e[18]*e[0]-1.*e[23]*e[25]*e[7]-1.*e[23]*e[24]*e[6]+e[2]*e[19]*e[22]+e[2]*e[18]*e[21]+e[26]*e[21]*e[6]+e[26]*e[3]*e[24]+e[26]*e[22]*e[7]+e[26]*e[4]*e[25]+.5000000000*ep2[20]*e[5]+1.500000000*ep2[23]*e[5]+.5000000000*e[5]*ep2[22]+.5000000000*e[5]*ep2[21]+.5000000000*e[5]*ep2[26]-.5000000000*e[5]*ep2[18]-.5000000000*e[5]*ep2[19]-.5000000000*e[5]*ep2[24]-.5000000000*e[5]*ep2[25]; + A[24]=e[24]*e[11]*e[8]+e[24]*e[2]*e[17]+3.*e[9]*e[18]*e[0]+e[9]*e[19]*e[1]+e[9]*e[20]*e[2]+e[18]*e[10]*e[1]+e[18]*e[11]*e[2]+e[3]*e[18]*e[12]+e[3]*e[9]*e[21]+e[3]*e[20]*e[14]+e[3]*e[11]*e[23]+e[3]*e[19]*e[13]+e[3]*e[10]*e[22]+e[6]*e[18]*e[15]+e[6]*e[9]*e[24]+e[6]*e[20]*e[17]+e[6]*e[11]*e[26]+e[6]*e[19]*e[16]+e[6]*e[10]*e[25]+e[0]*e[20]*e[11]+e[0]*e[19]*e[10]-1.*e[9]*e[26]*e[8]-1.*e[9]*e[22]*e[4]-1.*e[9]*e[25]*e[7]-1.*e[9]*e[23]*e[5]+e[12]*e[0]*e[21]+e[12]*e[19]*e[4]+e[12]*e[1]*e[22]+e[12]*e[20]*e[5]+e[12]*e[2]*e[23]-1.*e[18]*e[13]*e[4]-1.*e[18]*e[16]*e[7]-1.*e[18]*e[14]*e[5]-1.*e[18]*e[17]*e[8]+e[21]*e[10]*e[4]+e[21]*e[1]*e[13]+e[21]*e[11]*e[5]+e[21]*e[2]*e[14]+e[15]*e[0]*e[24]+e[15]*e[19]*e[7]+e[15]*e[1]*e[25]+e[15]*e[20]*e[8]+e[15]*e[2]*e[26]-1.*e[0]*e[23]*e[14]-1.*e[0]*e[25]*e[16]-1.*e[0]*e[26]*e[17]-1.*e[0]*e[22]*e[13]+e[24]*e[10]*e[7]+e[24]*e[1]*e[16]; + A[138]=e[11]*e[1]*e[4]+e[11]*e[0]*e[3]+e[11]*e[2]*e[5]+e[5]*e[12]*e[3]+e[5]*e[13]*e[4]+e[8]*e[12]*e[6]+e[8]*e[3]*e[15]+e[8]*e[13]*e[7]+e[8]*e[4]*e[16]+e[8]*e[5]*e[17]+e[17]*e[4]*e[7]+e[17]*e[3]*e[6]-1.*e[5]*e[10]*e[1]-1.*e[5]*e[16]*e[7]-1.*e[5]*e[15]*e[6]-1.*e[5]*e[9]*e[0]+e[2]*e[9]*e[3]+e[2]*e[0]*e[12]+e[2]*e[10]*e[4]+e[2]*e[1]*e[13]+.5000000000*ep2[2]*e[14]-.5000000000*e[14]*ep2[0]-.5000000000*e[14]*ep2[6]-.5000000000*e[14]*ep2[1]-.5000000000*e[14]*ep2[7]+1.500000000*e[14]*ep2[5]+.5000000000*e[14]*ep2[4]+.5000000000*e[14]*ep2[3]+.5000000000*e[14]*ep2[8]; + A[31]=e[3]*e[27]*e[12]+e[3]*e[9]*e[30]+e[3]*e[29]*e[14]+e[3]*e[11]*e[32]+e[3]*e[28]*e[13]+e[3]*e[10]*e[31]+e[6]*e[27]*e[15]+e[6]*e[9]*e[33]+e[6]*e[29]*e[17]+e[6]*e[11]*e[35]+e[6]*e[28]*e[16]+e[6]*e[10]*e[34]+3.*e[0]*e[27]*e[9]+e[0]*e[29]*e[11]+e[0]*e[28]*e[10]-1.*e[9]*e[34]*e[7]-1.*e[9]*e[32]*e[5]-1.*e[9]*e[35]*e[8]+e[9]*e[29]*e[2]+e[9]*e[28]*e[1]-1.*e[9]*e[31]*e[4]+e[12]*e[0]*e[30]+e[12]*e[28]*e[4]+e[12]*e[1]*e[31]+e[12]*e[29]*e[5]+e[12]*e[2]*e[32]+e[27]*e[11]*e[2]+e[27]*e[10]*e[1]-1.*e[27]*e[13]*e[4]-1.*e[27]*e[16]*e[7]-1.*e[27]*e[14]*e[5]-1.*e[27]*e[17]*e[8]+e[30]*e[10]*e[4]+e[30]*e[1]*e[13]+e[30]*e[11]*e[5]+e[30]*e[2]*e[14]+e[15]*e[0]*e[33]+e[15]*e[28]*e[7]+e[15]*e[1]*e[34]+e[15]*e[29]*e[8]+e[15]*e[2]*e[35]-1.*e[0]*e[31]*e[13]-1.*e[0]*e[32]*e[14]-1.*e[0]*e[34]*e[16]-1.*e[0]*e[35]*e[17]+e[33]*e[10]*e[7]+e[33]*e[1]*e[16]+e[33]*e[11]*e[8]+e[33]*e[2]*e[17]; + A[141]=.5000000000*ep2[30]*e[6]+.5000000000*e[6]*ep2[27]-.5000000000*e[6]*ep2[32]-.5000000000*e[6]*ep2[28]-.5000000000*e[6]*ep2[29]-.5000000000*e[6]*ep2[31]+1.500000000*e[6]*ep2[33]+.5000000000*e[6]*ep2[34]+.5000000000*e[6]*ep2[35]+e[0]*e[27]*e[33]+e[0]*e[29]*e[35]+e[0]*e[28]*e[34]+e[3]*e[30]*e[33]+e[3]*e[32]*e[35]+e[3]*e[31]*e[34]+e[30]*e[31]*e[7]+e[30]*e[4]*e[34]+e[30]*e[32]*e[8]+e[30]*e[5]*e[35]+e[27]*e[28]*e[7]+e[27]*e[1]*e[34]+e[27]*e[29]*e[8]+e[27]*e[2]*e[35]+e[33]*e[34]*e[7]+e[33]*e[35]*e[8]-1.*e[33]*e[32]*e[5]-1.*e[33]*e[29]*e[2]-1.*e[33]*e[28]*e[1]-1.*e[33]*e[31]*e[4]; + A[30]=e[24]*e[20]*e[26]+e[21]*e[19]*e[22]-.5000000000*e[18]*ep2[22]-.5000000000*e[18]*ep2[25]+.5000000000*ep3[18]+.5000000000*e[18]*ep2[21]+e[21]*e[20]*e[23]+.5000000000*e[18]*ep2[20]+.5000000000*e[18]*ep2[19]+.5000000000*e[18]*ep2[24]+e[24]*e[19]*e[25]-.5000000000*e[18]*ep2[23]-.5000000000*e[18]*ep2[26]; + A[140]=.5000000000*e[33]*ep2[35]+.5000000000*ep3[33]+.5000000000*ep2[27]*e[33]+.5000000000*ep2[30]*e[33]-.5000000000*e[33]*ep2[29]+.5000000000*e[33]*ep2[34]-.5000000000*e[33]*ep2[32]-.5000000000*e[33]*ep2[28]+e[30]*e[32]*e[35]-.5000000000*e[33]*ep2[31]+e[27]*e[29]*e[35]+e[27]*e[28]*e[34]+e[30]*e[31]*e[34]; + A[29]=1.500000000*e[27]*ep2[18]+.5000000000*e[27]*ep2[19]+.5000000000*e[27]*ep2[20]+.5000000000*e[27]*ep2[21]+.5000000000*e[27]*ep2[24]-.5000000000*e[27]*ep2[26]-.5000000000*e[27]*ep2[23]-.5000000000*e[27]*ep2[22]-.5000000000*e[27]*ep2[25]+e[33]*e[20]*e[26]-1.*e[18]*e[35]*e[26]-1.*e[18]*e[31]*e[22]-1.*e[18]*e[32]*e[23]-1.*e[18]*e[34]*e[25]+e[18]*e[28]*e[19]+e[18]*e[29]*e[20]+e[21]*e[18]*e[30]+e[21]*e[28]*e[22]+e[21]*e[19]*e[31]+e[21]*e[29]*e[23]+e[21]*e[20]*e[32]+e[30]*e[19]*e[22]+e[30]*e[20]*e[23]+e[24]*e[18]*e[33]+e[24]*e[28]*e[25]+e[24]*e[19]*e[34]+e[24]*e[29]*e[26]+e[24]*e[20]*e[35]+e[33]*e[19]*e[25]; + A[143]=e[9]*e[27]*e[33]+e[9]*e[29]*e[35]+e[9]*e[28]*e[34]+e[33]*e[35]*e[17]+e[33]*e[34]*e[16]+e[27]*e[29]*e[17]+e[27]*e[11]*e[35]+e[27]*e[28]*e[16]+e[27]*e[10]*e[34]+e[33]*e[30]*e[12]-1.*e[33]*e[28]*e[10]-1.*e[33]*e[31]*e[13]-1.*e[33]*e[32]*e[14]-1.*e[33]*e[29]*e[11]+e[30]*e[32]*e[17]+e[30]*e[14]*e[35]+e[30]*e[31]*e[16]+e[30]*e[13]*e[34]+e[12]*e[32]*e[35]+e[12]*e[31]*e[34]+.5000000000*e[15]*ep2[27]-.5000000000*e[15]*ep2[32]-.5000000000*e[15]*ep2[28]-.5000000000*e[15]*ep2[29]-.5000000000*e[15]*ep2[31]+1.500000000*e[15]*ep2[33]+.5000000000*e[15]*ep2[30]+.5000000000*e[15]*ep2[34]+.5000000000*e[15]*ep2[35]; + A[28]=.5000000000*e[9]*ep2[12]-.5000000000*e[9]*ep2[16]+.5000000000*e[9]*ep2[10]-.5000000000*e[9]*ep2[17]-.5000000000*e[9]*ep2[13]+e[15]*e[10]*e[16]+e[12]*e[11]*e[14]+.5000000000*e[9]*ep2[11]+.5000000000*e[9]*ep2[15]-.5000000000*e[9]*ep2[14]+e[15]*e[11]*e[17]+.5000000000*ep3[9]+e[12]*e[10]*e[13]; + A[142]=e[18]*e[27]*e[33]+e[18]*e[29]*e[35]+e[18]*e[28]*e[34]+e[27]*e[28]*e[25]+e[27]*e[19]*e[34]+e[27]*e[29]*e[26]+e[27]*e[20]*e[35]+e[21]*e[30]*e[33]+e[21]*e[32]*e[35]+e[21]*e[31]*e[34]+e[30]*e[31]*e[25]+e[30]*e[22]*e[34]+e[30]*e[32]*e[26]+e[30]*e[23]*e[35]+e[33]*e[34]*e[25]+e[33]*e[35]*e[26]-1.*e[33]*e[29]*e[20]-1.*e[33]*e[31]*e[22]-1.*e[33]*e[32]*e[23]-1.*e[33]*e[28]*e[19]+.5000000000*ep2[27]*e[24]+.5000000000*ep2[30]*e[24]+1.500000000*e[24]*ep2[33]+.5000000000*e[24]*ep2[35]+.5000000000*e[24]*ep2[34]-.5000000000*e[24]*ep2[32]-.5000000000*e[24]*ep2[28]-.5000000000*e[24]*ep2[29]-.5000000000*e[24]*ep2[31]; + A[36]=.5000000000*e[9]*ep2[21]+.5000000000*e[9]*ep2[24]+.5000000000*e[9]*ep2[19]+1.500000000*e[9]*ep2[18]+.5000000000*e[9]*ep2[20]-.5000000000*e[9]*ep2[26]-.5000000000*e[9]*ep2[23]-.5000000000*e[9]*ep2[22]-.5000000000*e[9]*ep2[25]+e[21]*e[18]*e[12]+e[21]*e[20]*e[14]+e[21]*e[11]*e[23]+e[21]*e[19]*e[13]+e[21]*e[10]*e[22]+e[24]*e[18]*e[15]+e[24]*e[20]*e[17]+e[24]*e[11]*e[26]+e[24]*e[19]*e[16]+e[24]*e[10]*e[25]+e[15]*e[19]*e[25]+e[15]*e[20]*e[26]+e[12]*e[19]*e[22]+e[12]*e[20]*e[23]+e[18]*e[20]*e[11]+e[18]*e[19]*e[10]-1.*e[18]*e[23]*e[14]-1.*e[18]*e[25]*e[16]-1.*e[18]*e[26]*e[17]-1.*e[18]*e[22]*e[13]; + A[182]=.5000000000*ep2[29]*e[26]+.5000000000*ep2[32]*e[26]+.5000000000*e[26]*ep2[33]+1.500000000*e[26]*ep2[35]+.5000000000*e[26]*ep2[34]-.5000000000*e[26]*ep2[27]-.5000000000*e[26]*ep2[28]-.5000000000*e[26]*ep2[31]-.5000000000*e[26]*ep2[30]+e[20]*e[27]*e[33]+e[20]*e[29]*e[35]+e[20]*e[28]*e[34]+e[29]*e[27]*e[24]+e[29]*e[18]*e[33]+e[29]*e[28]*e[25]+e[29]*e[19]*e[34]+e[23]*e[30]*e[33]+e[23]*e[32]*e[35]+e[23]*e[31]*e[34]+e[32]*e[30]*e[24]+e[32]*e[21]*e[33]+e[32]*e[31]*e[25]+e[32]*e[22]*e[34]+e[35]*e[33]*e[24]+e[35]*e[34]*e[25]-1.*e[35]*e[27]*e[18]-1.*e[35]*e[30]*e[21]-1.*e[35]*e[31]*e[22]-1.*e[35]*e[28]*e[19]; + A[37]=e[12]*e[19]*e[31]+e[12]*e[29]*e[23]+e[12]*e[20]*e[32]+3.*e[9]*e[27]*e[18]+e[9]*e[28]*e[19]+e[9]*e[29]*e[20]+e[21]*e[9]*e[30]+e[21]*e[29]*e[14]+e[21]*e[11]*e[32]+e[21]*e[28]*e[13]+e[21]*e[10]*e[31]+e[30]*e[20]*e[14]+e[30]*e[11]*e[23]+e[30]*e[19]*e[13]+e[30]*e[10]*e[22]+e[9]*e[33]*e[24]-1.*e[9]*e[35]*e[26]-1.*e[9]*e[31]*e[22]-1.*e[9]*e[32]*e[23]-1.*e[9]*e[34]*e[25]+e[18]*e[29]*e[11]+e[18]*e[28]*e[10]+e[27]*e[20]*e[11]+e[27]*e[19]*e[10]+e[15]*e[27]*e[24]+e[15]*e[18]*e[33]+e[15]*e[28]*e[25]+e[15]*e[19]*e[34]+e[15]*e[29]*e[26]+e[15]*e[20]*e[35]-1.*e[18]*e[31]*e[13]-1.*e[18]*e[32]*e[14]-1.*e[18]*e[34]*e[16]-1.*e[18]*e[35]*e[17]-1.*e[27]*e[23]*e[14]-1.*e[27]*e[25]*e[16]-1.*e[27]*e[26]*e[17]-1.*e[27]*e[22]*e[13]+e[24]*e[29]*e[17]+e[24]*e[11]*e[35]+e[24]*e[28]*e[16]+e[24]*e[10]*e[34]+e[33]*e[20]*e[17]+e[33]*e[11]*e[26]+e[33]*e[19]*e[16]+e[33]*e[10]*e[25]+e[12]*e[27]*e[21]+e[12]*e[18]*e[30]+e[12]*e[28]*e[22]; + A[183]=-.5000000000*e[17]*ep2[27]+.5000000000*e[17]*ep2[32]-.5000000000*e[17]*ep2[28]+.5000000000*e[17]*ep2[29]-.5000000000*e[17]*ep2[31]+.5000000000*e[17]*ep2[33]-.5000000000*e[17]*ep2[30]+.5000000000*e[17]*ep2[34]+1.500000000*e[17]*ep2[35]+e[32]*e[30]*e[15]+e[32]*e[12]*e[33]+e[32]*e[31]*e[16]+e[32]*e[13]*e[34]+e[14]*e[30]*e[33]+e[14]*e[31]*e[34]+e[11]*e[27]*e[33]+e[11]*e[29]*e[35]+e[11]*e[28]*e[34]+e[35]*e[33]*e[15]+e[35]*e[34]*e[16]+e[29]*e[27]*e[15]+e[29]*e[9]*e[33]+e[29]*e[28]*e[16]+e[29]*e[10]*e[34]-1.*e[35]*e[27]*e[9]-1.*e[35]*e[30]*e[12]-1.*e[35]*e[28]*e[10]-1.*e[35]*e[31]*e[13]+e[35]*e[32]*e[14]; + A[38]=.5000000000*e[9]*ep2[1]+1.500000000*e[9]*ep2[0]+.5000000000*e[9]*ep2[2]+.5000000000*e[9]*ep2[3]+.5000000000*e[9]*ep2[6]-.5000000000*e[9]*ep2[4]-.5000000000*e[9]*ep2[5]-.5000000000*e[9]*ep2[7]-.5000000000*e[9]*ep2[8]+e[6]*e[0]*e[15]+e[6]*e[10]*e[7]+e[6]*e[1]*e[16]+e[6]*e[11]*e[8]+e[6]*e[2]*e[17]+e[15]*e[1]*e[7]+e[15]*e[2]*e[8]+e[0]*e[11]*e[2]+e[0]*e[10]*e[1]-1.*e[0]*e[13]*e[4]-1.*e[0]*e[16]*e[7]-1.*e[0]*e[14]*e[5]-1.*e[0]*e[17]*e[8]+e[3]*e[0]*e[12]+e[3]*e[10]*e[4]+e[3]*e[1]*e[13]+e[3]*e[11]*e[5]+e[3]*e[2]*e[14]+e[12]*e[1]*e[4]+e[12]*e[2]*e[5]; + A[180]=.5000000000*e[35]*ep2[33]+.5000000000*e[35]*ep2[34]-.5000000000*e[35]*ep2[27]-.5000000000*e[35]*ep2[28]-.5000000000*e[35]*ep2[31]-.5000000000*e[35]*ep2[30]+e[32]*e[31]*e[34]+.5000000000*ep2[29]*e[35]+.5000000000*ep2[32]*e[35]+e[29]*e[28]*e[34]+e[32]*e[30]*e[33]+.5000000000*ep3[35]+e[29]*e[27]*e[33]; + A[39]=.5000000000*e[0]*ep2[19]+.5000000000*e[0]*ep2[20]+.5000000000*e[0]*ep2[24]-.5000000000*e[0]*ep2[26]-.5000000000*e[0]*ep2[23]-.5000000000*e[0]*ep2[22]-.5000000000*e[0]*ep2[25]+1.500000000*ep2[18]*e[0]+.5000000000*e[0]*ep2[21]+e[18]*e[19]*e[1]+e[18]*e[20]*e[2]+e[21]*e[18]*e[3]+e[21]*e[19]*e[4]+e[21]*e[1]*e[22]+e[21]*e[20]*e[5]+e[21]*e[2]*e[23]-1.*e[18]*e[26]*e[8]-1.*e[18]*e[22]*e[4]-1.*e[18]*e[25]*e[7]-1.*e[18]*e[23]*e[5]+e[18]*e[24]*e[6]+e[3]*e[19]*e[22]+e[3]*e[20]*e[23]+e[24]*e[19]*e[7]+e[24]*e[1]*e[25]+e[24]*e[20]*e[8]+e[24]*e[2]*e[26]+e[6]*e[19]*e[25]+e[6]*e[20]*e[26]; + A[181]=.5000000000*ep2[32]*e[8]-.5000000000*e[8]*ep2[27]-.5000000000*e[8]*ep2[28]+.5000000000*e[8]*ep2[29]-.5000000000*e[8]*ep2[31]+.5000000000*e[8]*ep2[33]-.5000000000*e[8]*ep2[30]+.5000000000*e[8]*ep2[34]+1.500000000*e[8]*ep2[35]+e[2]*e[27]*e[33]+e[2]*e[29]*e[35]+e[2]*e[28]*e[34]+e[5]*e[30]*e[33]+e[5]*e[32]*e[35]+e[5]*e[31]*e[34]+e[32]*e[30]*e[6]+e[32]*e[3]*e[33]+e[32]*e[31]*e[7]+e[32]*e[4]*e[34]+e[29]*e[27]*e[6]+e[29]*e[0]*e[33]+e[29]*e[28]*e[7]+e[29]*e[1]*e[34]+e[35]*e[33]*e[6]+e[35]*e[34]*e[7]-1.*e[35]*e[27]*e[0]-1.*e[35]*e[30]*e[3]-1.*e[35]*e[28]*e[1]-1.*e[35]*e[31]*e[4]; + A[32]=-.5000000000*e[18]*ep2[4]+1.500000000*e[18]*ep2[0]+.5000000000*e[18]*ep2[6]-.5000000000*e[18]*ep2[5]+.5000000000*e[18]*ep2[1]-.5000000000*e[18]*ep2[7]+.5000000000*e[18]*ep2[3]+.5000000000*e[18]*ep2[2]-.5000000000*e[18]*ep2[8]+e[3]*e[0]*e[21]+e[3]*e[19]*e[4]+e[3]*e[1]*e[22]+e[3]*e[20]*e[5]+e[3]*e[2]*e[23]+e[21]*e[1]*e[4]+e[21]*e[2]*e[5]+e[6]*e[0]*e[24]+e[6]*e[19]*e[7]+e[6]*e[1]*e[25]+e[6]*e[20]*e[8]+e[6]*e[2]*e[26]+e[24]*e[1]*e[7]+e[24]*e[2]*e[8]+e[0]*e[19]*e[1]+e[0]*e[20]*e[2]-1.*e[0]*e[26]*e[8]-1.*e[0]*e[22]*e[4]-1.*e[0]*e[25]*e[7]-1.*e[0]*e[23]*e[5]; + A[178]=e[10]*e[1]*e[7]+e[10]*e[0]*e[6]+e[10]*e[2]*e[8]+e[4]*e[12]*e[6]+e[4]*e[3]*e[15]+e[4]*e[13]*e[7]+e[4]*e[14]*e[8]+e[4]*e[5]*e[17]+e[13]*e[3]*e[6]+e[13]*e[5]*e[8]+e[7]*e[15]*e[6]+e[7]*e[17]*e[8]-1.*e[7]*e[11]*e[2]-1.*e[7]*e[9]*e[0]-1.*e[7]*e[14]*e[5]-1.*e[7]*e[12]*e[3]+e[1]*e[9]*e[6]+e[1]*e[0]*e[15]+e[1]*e[11]*e[8]+e[1]*e[2]*e[17]+1.500000000*e[16]*ep2[7]+.5000000000*e[16]*ep2[6]+.5000000000*e[16]*ep2[8]+.5000000000*ep2[1]*e[16]-.5000000000*e[16]*ep2[0]-.5000000000*e[16]*ep2[5]-.5000000000*e[16]*ep2[3]-.5000000000*e[16]*ep2[2]+.5000000000*ep2[4]*e[16]; + A[33]=e[0]*e[30]*e[21]-1.*e[0]*e[35]*e[26]-1.*e[0]*e[31]*e[22]-1.*e[0]*e[32]*e[23]-1.*e[0]*e[34]*e[25]-1.*e[18]*e[34]*e[7]-1.*e[18]*e[32]*e[5]-1.*e[18]*e[35]*e[8]-1.*e[18]*e[31]*e[4]-1.*e[27]*e[26]*e[8]-1.*e[27]*e[22]*e[4]-1.*e[27]*e[25]*e[7]-1.*e[27]*e[23]*e[5]+e[6]*e[28]*e[25]+e[6]*e[19]*e[34]+e[6]*e[29]*e[26]+e[6]*e[20]*e[35]+e[21]*e[28]*e[4]+e[21]*e[1]*e[31]+e[21]*e[29]*e[5]+e[21]*e[2]*e[32]+e[30]*e[19]*e[4]+e[30]*e[1]*e[22]+e[30]*e[20]*e[5]+e[30]*e[2]*e[23]+e[24]*e[27]*e[6]+e[24]*e[0]*e[33]+e[24]*e[28]*e[7]+e[24]*e[1]*e[34]+e[24]*e[29]*e[8]+e[24]*e[2]*e[35]+e[33]*e[18]*e[6]+e[33]*e[19]*e[7]+e[33]*e[1]*e[25]+e[33]*e[20]*e[8]+e[33]*e[2]*e[26]+3.*e[0]*e[27]*e[18]+e[0]*e[28]*e[19]+e[0]*e[29]*e[20]+e[18]*e[28]*e[1]+e[18]*e[29]*e[2]+e[27]*e[19]*e[1]+e[27]*e[20]*e[2]+e[3]*e[27]*e[21]+e[3]*e[18]*e[30]+e[3]*e[28]*e[22]+e[3]*e[19]*e[31]+e[3]*e[29]*e[23]+e[3]*e[20]*e[32]; + A[179]=e[19]*e[18]*e[6]+e[19]*e[0]*e[24]+e[19]*e[1]*e[25]+e[19]*e[20]*e[8]+e[19]*e[2]*e[26]+e[22]*e[21]*e[6]+e[22]*e[3]*e[24]+e[22]*e[4]*e[25]+e[22]*e[23]*e[8]+e[22]*e[5]*e[26]-1.*e[25]*e[21]*e[3]+e[25]*e[26]*e[8]-1.*e[25]*e[20]*e[2]-1.*e[25]*e[18]*e[0]-1.*e[25]*e[23]*e[5]+e[25]*e[24]*e[6]+e[1]*e[18]*e[24]+e[1]*e[20]*e[26]+e[4]*e[21]*e[24]+e[4]*e[23]*e[26]+.5000000000*ep2[19]*e[7]+.5000000000*ep2[22]*e[7]+1.500000000*ep2[25]*e[7]+.5000000000*e[7]*ep2[26]-.5000000000*e[7]*ep2[18]-.5000000000*e[7]*ep2[23]-.5000000000*e[7]*ep2[20]+.5000000000*e[7]*ep2[24]-.5000000000*e[7]*ep2[21]; + A[34]=.5000000000*e[18]*ep2[11]+1.500000000*e[18]*ep2[9]+.5000000000*e[18]*ep2[10]+.5000000000*e[18]*ep2[12]+.5000000000*e[18]*ep2[15]-.5000000000*e[18]*ep2[16]-.5000000000*e[18]*ep2[17]-.5000000000*e[18]*ep2[14]-.5000000000*e[18]*ep2[13]+e[12]*e[9]*e[21]+e[12]*e[20]*e[14]+e[12]*e[11]*e[23]+e[12]*e[19]*e[13]+e[12]*e[10]*e[22]+e[21]*e[11]*e[14]+e[21]*e[10]*e[13]+e[15]*e[9]*e[24]+e[15]*e[20]*e[17]+e[15]*e[11]*e[26]+e[15]*e[19]*e[16]+e[15]*e[10]*e[25]+e[24]*e[11]*e[17]+e[24]*e[10]*e[16]-1.*e[9]*e[23]*e[14]-1.*e[9]*e[25]*e[16]-1.*e[9]*e[26]*e[17]+e[9]*e[20]*e[11]+e[9]*e[19]*e[10]-1.*e[9]*e[22]*e[13]; + A[176]=e[13]*e[21]*e[24]+e[13]*e[23]*e[26]+e[19]*e[18]*e[15]+e[19]*e[9]*e[24]+e[19]*e[20]*e[17]+e[19]*e[11]*e[26]-1.*e[25]*e[23]*e[14]-1.*e[25]*e[20]*e[11]-1.*e[25]*e[18]*e[9]-1.*e[25]*e[21]*e[12]+e[22]*e[21]*e[15]+e[22]*e[12]*e[24]+e[22]*e[23]*e[17]+e[22]*e[14]*e[26]+e[22]*e[13]*e[25]+e[25]*e[24]*e[15]+e[25]*e[26]*e[17]+e[10]*e[19]*e[25]+e[10]*e[18]*e[24]+e[10]*e[20]*e[26]-.5000000000*e[16]*ep2[18]-.5000000000*e[16]*ep2[23]+.5000000000*e[16]*ep2[19]-.5000000000*e[16]*ep2[20]-.5000000000*e[16]*ep2[21]+.5000000000*ep2[22]*e[16]+1.500000000*ep2[25]*e[16]+.5000000000*e[16]*ep2[24]+.5000000000*e[16]*ep2[26]; + A[35]=.5000000000*e[0]*ep2[12]+.5000000000*e[0]*ep2[15]+.5000000000*e[0]*ep2[11]+1.500000000*e[0]*ep2[9]+.5000000000*e[0]*ep2[10]-.5000000000*e[0]*ep2[16]-.5000000000*e[0]*ep2[17]-.5000000000*e[0]*ep2[14]-.5000000000*e[0]*ep2[13]+e[12]*e[9]*e[3]+e[12]*e[10]*e[4]+e[12]*e[1]*e[13]+e[12]*e[11]*e[5]+e[12]*e[2]*e[14]+e[15]*e[9]*e[6]+e[15]*e[10]*e[7]+e[15]*e[1]*e[16]+e[15]*e[11]*e[8]+e[15]*e[2]*e[17]+e[6]*e[11]*e[17]+e[6]*e[10]*e[16]+e[3]*e[11]*e[14]+e[3]*e[10]*e[13]+e[9]*e[10]*e[1]+e[9]*e[11]*e[2]-1.*e[9]*e[13]*e[4]-1.*e[9]*e[16]*e[7]-1.*e[9]*e[14]*e[5]-1.*e[9]*e[17]*e[8]; + A[177]=e[19]*e[11]*e[35]+e[28]*e[18]*e[15]+e[28]*e[9]*e[24]+e[28]*e[20]*e[17]+e[28]*e[11]*e[26]-1.*e[25]*e[27]*e[9]-1.*e[25]*e[30]*e[12]-1.*e[25]*e[32]*e[14]+e[25]*e[33]*e[15]+e[25]*e[35]*e[17]-1.*e[25]*e[29]*e[11]-1.*e[34]*e[23]*e[14]+e[34]*e[24]*e[15]+e[34]*e[26]*e[17]-1.*e[34]*e[20]*e[11]-1.*e[34]*e[18]*e[9]-1.*e[34]*e[21]*e[12]+e[13]*e[30]*e[24]+e[13]*e[21]*e[33]+e[13]*e[31]*e[25]+e[13]*e[22]*e[34]+e[13]*e[32]*e[26]+e[13]*e[23]*e[35]+e[10]*e[27]*e[24]+e[10]*e[18]*e[33]+e[10]*e[28]*e[25]+e[10]*e[19]*e[34]+e[10]*e[29]*e[26]+e[10]*e[20]*e[35]+e[22]*e[30]*e[15]+e[22]*e[12]*e[33]+e[22]*e[32]*e[17]+e[22]*e[14]*e[35]+e[22]*e[31]*e[16]+e[31]*e[21]*e[15]+e[31]*e[12]*e[24]+e[31]*e[23]*e[17]+e[31]*e[14]*e[26]-1.*e[16]*e[27]*e[18]+e[16]*e[33]*e[24]-1.*e[16]*e[30]*e[21]-1.*e[16]*e[29]*e[20]+e[16]*e[35]*e[26]-1.*e[16]*e[32]*e[23]+e[16]*e[28]*e[19]+3.*e[16]*e[34]*e[25]+e[19]*e[27]*e[15]+e[19]*e[9]*e[33]+e[19]*e[29]*e[17]; + A[45]=e[4]*e[27]*e[3]+e[4]*e[0]*e[30]+e[4]*e[29]*e[5]+e[4]*e[2]*e[32]+e[31]*e[0]*e[3]+e[31]*e[2]*e[5]+e[7]*e[27]*e[6]+e[7]*e[0]*e[33]+e[7]*e[29]*e[8]+e[7]*e[2]*e[35]+e[34]*e[0]*e[6]+e[34]*e[2]*e[8]+e[1]*e[27]*e[0]+e[1]*e[29]*e[2]+e[1]*e[34]*e[7]-1.*e[1]*e[32]*e[5]-1.*e[1]*e[33]*e[6]-1.*e[1]*e[30]*e[3]-1.*e[1]*e[35]*e[8]+e[1]*e[31]*e[4]+1.500000000*e[28]*ep2[1]+.5000000000*e[28]*ep2[4]+.5000000000*e[28]*ep2[0]-.5000000000*e[28]*ep2[6]-.5000000000*e[28]*ep2[5]+.5000000000*e[28]*ep2[7]-.5000000000*e[28]*ep2[3]+.5000000000*e[28]*ep2[2]-.5000000000*e[28]*ep2[8]; + A[191]=-1.*e[35]*e[10]*e[1]-1.*e[35]*e[13]*e[4]+e[35]*e[16]*e[7]+e[35]*e[15]*e[6]-1.*e[35]*e[9]*e[0]-1.*e[35]*e[12]*e[3]+e[32]*e[12]*e[6]+e[32]*e[3]*e[15]+e[32]*e[13]*e[7]+e[32]*e[4]*e[16]-1.*e[8]*e[27]*e[9]-1.*e[8]*e[30]*e[12]-1.*e[8]*e[28]*e[10]-1.*e[8]*e[31]*e[13]+e[8]*e[29]*e[11]+e[11]*e[27]*e[6]+e[11]*e[0]*e[33]+e[11]*e[28]*e[7]+e[11]*e[1]*e[34]+e[29]*e[9]*e[6]+e[29]*e[0]*e[15]+e[29]*e[10]*e[7]+e[29]*e[1]*e[16]+e[5]*e[30]*e[15]+e[5]*e[12]*e[33]+e[5]*e[32]*e[17]+e[5]*e[14]*e[35]+e[5]*e[31]*e[16]+e[5]*e[13]*e[34]+e[8]*e[33]*e[15]+3.*e[8]*e[35]*e[17]+e[8]*e[34]*e[16]+e[2]*e[27]*e[15]+e[2]*e[9]*e[33]+e[2]*e[29]*e[17]+e[2]*e[11]*e[35]+e[2]*e[28]*e[16]+e[2]*e[10]*e[34]-1.*e[17]*e[27]*e[0]+e[17]*e[34]*e[7]+e[17]*e[33]*e[6]-1.*e[17]*e[30]*e[3]-1.*e[17]*e[28]*e[1]-1.*e[17]*e[31]*e[4]+e[14]*e[30]*e[6]+e[14]*e[3]*e[33]+e[14]*e[31]*e[7]+e[14]*e[4]*e[34]+e[14]*e[32]*e[8]; + A[44]=e[19]*e[11]*e[2]+e[4]*e[18]*e[12]+e[4]*e[9]*e[21]+e[4]*e[20]*e[14]+e[4]*e[11]*e[23]+e[4]*e[19]*e[13]+e[4]*e[10]*e[22]+e[7]*e[18]*e[15]+e[7]*e[9]*e[24]+e[7]*e[20]*e[17]+e[7]*e[11]*e[26]+e[7]*e[19]*e[16]+e[7]*e[10]*e[25]+e[1]*e[18]*e[9]+e[1]*e[20]*e[11]-1.*e[10]*e[21]*e[3]-1.*e[10]*e[26]*e[8]-1.*e[10]*e[23]*e[5]-1.*e[10]*e[24]*e[6]+e[13]*e[18]*e[3]+e[13]*e[0]*e[21]+e[13]*e[1]*e[22]+e[13]*e[20]*e[5]+e[13]*e[2]*e[23]-1.*e[19]*e[15]*e[6]-1.*e[19]*e[14]*e[5]-1.*e[19]*e[12]*e[3]-1.*e[19]*e[17]*e[8]+e[22]*e[9]*e[3]+e[22]*e[0]*e[12]+e[22]*e[11]*e[5]+e[22]*e[2]*e[14]+e[16]*e[18]*e[6]+e[16]*e[0]*e[24]+e[16]*e[1]*e[25]+e[16]*e[20]*e[8]+e[16]*e[2]*e[26]-1.*e[1]*e[23]*e[14]-1.*e[1]*e[24]*e[15]-1.*e[1]*e[26]*e[17]-1.*e[1]*e[21]*e[12]+e[25]*e[9]*e[6]+e[25]*e[0]*e[15]+e[25]*e[11]*e[8]+e[25]*e[2]*e[17]+e[10]*e[18]*e[0]+3.*e[10]*e[19]*e[1]+e[10]*e[20]*e[2]+e[19]*e[9]*e[0]; + A[190]=.5000000000*ep2[23]*e[26]+.5000000000*e[26]*ep2[25]+.5000000000*ep2[20]*e[26]-.5000000000*e[26]*ep2[18]+.5000000000*ep3[26]+.5000000000*e[26]*ep2[24]+e[20]*e[19]*e[25]-.5000000000*e[26]*ep2[19]-.5000000000*e[26]*ep2[21]+e[20]*e[18]*e[24]-.5000000000*e[26]*ep2[22]+e[23]*e[21]*e[24]+e[23]*e[22]*e[25]; + A[47]=e[16]*e[9]*e[33]+e[16]*e[29]*e[17]+e[16]*e[11]*e[35]+e[16]*e[10]*e[34]+e[34]*e[11]*e[17]+e[34]*e[9]*e[15]-1.*e[10]*e[30]*e[12]-1.*e[10]*e[32]*e[14]-1.*e[10]*e[33]*e[15]-1.*e[10]*e[35]*e[17]+e[10]*e[27]*e[9]+e[10]*e[29]*e[11]+e[13]*e[27]*e[12]+e[13]*e[9]*e[30]+e[13]*e[29]*e[14]+e[13]*e[11]*e[32]+e[13]*e[10]*e[31]+e[31]*e[11]*e[14]+e[31]*e[9]*e[12]+e[16]*e[27]*e[15]+1.500000000*e[28]*ep2[10]+.5000000000*e[28]*ep2[16]+.5000000000*e[28]*ep2[9]+.5000000000*e[28]*ep2[11]-.5000000000*e[28]*ep2[12]-.5000000000*e[28]*ep2[15]-.5000000000*e[28]*ep2[17]-.5000000000*e[28]*ep2[14]+.5000000000*e[28]*ep2[13]; + A[189]=.5000000000*ep2[20]*e[35]+.5000000000*ep2[23]*e[35]+1.500000000*e[35]*ep2[26]+.5000000000*e[35]*ep2[25]+.5000000000*e[35]*ep2[24]-.5000000000*e[35]*ep2[18]-.5000000000*e[35]*ep2[19]-.5000000000*e[35]*ep2[22]-.5000000000*e[35]*ep2[21]+e[20]*e[27]*e[24]+e[20]*e[18]*e[33]+e[20]*e[28]*e[25]+e[20]*e[19]*e[34]+e[20]*e[29]*e[26]+e[29]*e[19]*e[25]+e[29]*e[18]*e[24]+e[23]*e[30]*e[24]+e[23]*e[21]*e[33]+e[23]*e[31]*e[25]+e[23]*e[22]*e[34]+e[23]*e[32]*e[26]+e[32]*e[22]*e[25]+e[32]*e[21]*e[24]+e[26]*e[33]*e[24]+e[26]*e[34]*e[25]-1.*e[26]*e[27]*e[18]-1.*e[26]*e[30]*e[21]-1.*e[26]*e[31]*e[22]-1.*e[26]*e[28]*e[19]; + A[46]=e[4]*e[2]*e[5]+.5000000000*e[1]*ep2[0]-.5000000000*e[1]*ep2[6]+e[7]*e[0]*e[6]+.5000000000*e[1]*ep2[7]+.5000000000*e[1]*ep2[4]-.5000000000*e[1]*ep2[8]+.5000000000*e[1]*ep2[2]-.5000000000*e[1]*ep2[3]+.5000000000*ep3[1]+e[7]*e[2]*e[8]-.5000000000*e[1]*ep2[5]+e[4]*e[0]*e[3]; + A[188]=-.5000000000*e[17]*ep2[13]-.5000000000*e[17]*ep2[9]+.5000000000*e[17]*ep2[16]+.5000000000*e[17]*ep2[15]+.5000000000*ep3[17]-.5000000000*e[17]*ep2[10]+e[14]*e[13]*e[16]+e[14]*e[12]*e[15]+.5000000000*ep2[14]*e[17]+e[11]*e[10]*e[16]-.5000000000*e[17]*ep2[12]+.5000000000*ep2[11]*e[17]+e[11]*e[9]*e[15]; + A[41]=e[4]*e[27]*e[30]+e[4]*e[29]*e[32]+e[4]*e[28]*e[31]+e[31]*e[27]*e[3]+e[31]*e[0]*e[30]+e[31]*e[29]*e[5]+e[31]*e[2]*e[32]+e[7]*e[27]*e[33]+e[7]*e[29]*e[35]+e[7]*e[28]*e[34]+e[28]*e[27]*e[0]+e[28]*e[29]*e[2]+e[34]*e[27]*e[6]+e[34]*e[0]*e[33]+e[34]*e[29]*e[8]+e[34]*e[2]*e[35]-1.*e[28]*e[32]*e[5]-1.*e[28]*e[33]*e[6]-1.*e[28]*e[30]*e[3]-1.*e[28]*e[35]*e[8]+.5000000000*e[1]*ep2[27]+.5000000000*e[1]*ep2[29]+1.500000000*e[1]*ep2[28]+.5000000000*e[1]*ep2[31]-.5000000000*e[1]*ep2[32]-.5000000000*e[1]*ep2[33]-.5000000000*e[1]*ep2[30]+.5000000000*e[1]*ep2[34]-.5000000000*e[1]*ep2[35]; + A[187]=.5000000000*ep2[11]*e[35]+.5000000000*e[35]*ep2[16]-.5000000000*e[35]*ep2[9]-.5000000000*e[35]*ep2[12]+.5000000000*e[35]*ep2[15]+1.500000000*e[35]*ep2[17]-.5000000000*e[35]*ep2[10]+.5000000000*e[35]*ep2[14]-.5000000000*e[35]*ep2[13]+e[11]*e[27]*e[15]+e[11]*e[9]*e[33]+e[11]*e[29]*e[17]+e[11]*e[28]*e[16]+e[11]*e[10]*e[34]+e[29]*e[9]*e[15]+e[29]*e[10]*e[16]+e[14]*e[30]*e[15]+e[14]*e[12]*e[33]+e[14]*e[32]*e[17]+e[14]*e[31]*e[16]+e[14]*e[13]*e[34]+e[32]*e[12]*e[15]+e[32]*e[13]*e[16]+e[17]*e[33]*e[15]+e[17]*e[34]*e[16]-1.*e[17]*e[27]*e[9]-1.*e[17]*e[30]*e[12]-1.*e[17]*e[28]*e[10]-1.*e[17]*e[31]*e[13]; + A[40]=e[34]*e[27]*e[33]+e[34]*e[29]*e[35]-.5000000000*e[28]*ep2[30]-.5000000000*e[28]*ep2[35]+.5000000000*ep3[28]+.5000000000*e[28]*ep2[27]+.5000000000*e[28]*ep2[29]+e[31]*e[27]*e[30]+e[31]*e[29]*e[32]-.5000000000*e[28]*ep2[32]-.5000000000*e[28]*ep2[33]+.5000000000*e[28]*ep2[31]+.5000000000*e[28]*ep2[34]; + A[186]=.5000000000*ep2[5]*e[8]+e[2]*e[0]*e[6]+.5000000000*ep2[2]*e[8]+.5000000000*ep3[8]-.5000000000*e[8]*ep2[0]+e[5]*e[4]*e[7]+e[5]*e[3]*e[6]+.5000000000*e[8]*ep2[7]+e[2]*e[1]*e[7]-.5000000000*e[8]*ep2[1]-.5000000000*e[8]*ep2[4]-.5000000000*e[8]*ep2[3]+.5000000000*e[8]*ep2[6]; + A[43]=e[28]*e[27]*e[9]+e[28]*e[29]*e[11]-1.*e[28]*e[30]*e[12]+e[28]*e[31]*e[13]-1.*e[28]*e[32]*e[14]-1.*e[28]*e[33]*e[15]-1.*e[28]*e[35]*e[17]+e[31]*e[27]*e[12]+e[31]*e[9]*e[30]+e[31]*e[29]*e[14]+e[31]*e[11]*e[32]+e[13]*e[27]*e[30]+e[13]*e[29]*e[32]+e[16]*e[27]*e[33]+e[16]*e[29]*e[35]+e[34]*e[27]*e[15]+e[34]*e[9]*e[33]+e[34]*e[29]*e[17]+e[34]*e[11]*e[35]+e[34]*e[28]*e[16]+.5000000000*e[10]*ep2[27]+.5000000000*e[10]*ep2[29]+1.500000000*e[10]*ep2[28]-.5000000000*e[10]*ep2[32]+.5000000000*e[10]*ep2[31]-.5000000000*e[10]*ep2[33]-.5000000000*e[10]*ep2[30]+.5000000000*e[10]*ep2[34]-.5000000000*e[10]*ep2[35]; + A[185]=-.5000000000*e[35]*ep2[1]+.5000000000*e[35]*ep2[7]-.5000000000*e[35]*ep2[3]+.5000000000*ep2[2]*e[35]+1.500000000*e[35]*ep2[8]-.5000000000*e[35]*ep2[4]-.5000000000*e[35]*ep2[0]+.5000000000*e[35]*ep2[6]+.5000000000*e[35]*ep2[5]+e[2]*e[27]*e[6]+e[2]*e[0]*e[33]+e[2]*e[28]*e[7]+e[2]*e[1]*e[34]+e[2]*e[29]*e[8]-1.*e[8]*e[27]*e[0]+e[8]*e[34]*e[7]+e[8]*e[32]*e[5]+e[8]*e[33]*e[6]-1.*e[8]*e[30]*e[3]-1.*e[8]*e[28]*e[1]-1.*e[8]*e[31]*e[4]+e[29]*e[1]*e[7]+e[29]*e[0]*e[6]+e[5]*e[30]*e[6]+e[5]*e[3]*e[33]+e[5]*e[31]*e[7]+e[5]*e[4]*e[34]+e[32]*e[4]*e[7]+e[32]*e[3]*e[6]; + A[42]=e[28]*e[27]*e[18]+e[28]*e[29]*e[20]+e[22]*e[27]*e[30]+e[22]*e[29]*e[32]+e[22]*e[28]*e[31]+e[31]*e[27]*e[21]+e[31]*e[18]*e[30]+e[31]*e[29]*e[23]+e[31]*e[20]*e[32]+e[25]*e[27]*e[33]+e[25]*e[29]*e[35]+e[25]*e[28]*e[34]+e[34]*e[27]*e[24]+e[34]*e[18]*e[33]+e[34]*e[29]*e[26]+e[34]*e[20]*e[35]-1.*e[28]*e[33]*e[24]-1.*e[28]*e[30]*e[21]-1.*e[28]*e[35]*e[26]-1.*e[28]*e[32]*e[23]-.5000000000*e[19]*ep2[33]-.5000000000*e[19]*ep2[30]-.5000000000*e[19]*ep2[35]+.5000000000*e[19]*ep2[27]+.5000000000*e[19]*ep2[29]+1.500000000*e[19]*ep2[28]+.5000000000*e[19]*ep2[31]+.5000000000*e[19]*ep2[34]-.5000000000*e[19]*ep2[32]; + A[184]=e[23]*e[3]*e[15]-1.*e[17]*e[19]*e[1]-1.*e[17]*e[22]*e[4]-1.*e[17]*e[18]*e[0]+e[17]*e[25]*e[7]+e[17]*e[24]*e[6]+e[14]*e[21]*e[6]+e[14]*e[3]*e[24]+e[14]*e[22]*e[7]+e[14]*e[4]*e[25]+e[14]*e[23]*e[8]-1.*e[26]*e[10]*e[1]-1.*e[26]*e[13]*e[4]+e[26]*e[16]*e[7]+e[26]*e[15]*e[6]-1.*e[26]*e[9]*e[0]-1.*e[26]*e[12]*e[3]+e[23]*e[12]*e[6]+e[11]*e[18]*e[6]+e[11]*e[0]*e[24]+e[11]*e[19]*e[7]+e[11]*e[1]*e[25]+e[11]*e[20]*e[8]+e[11]*e[2]*e[26]+e[20]*e[9]*e[6]+e[20]*e[0]*e[15]+e[20]*e[10]*e[7]+e[20]*e[1]*e[16]+e[20]*e[2]*e[17]+e[5]*e[21]*e[15]+e[5]*e[12]*e[24]+e[5]*e[23]*e[17]+e[5]*e[14]*e[26]+e[5]*e[22]*e[16]+e[5]*e[13]*e[25]+e[8]*e[24]*e[15]+3.*e[8]*e[26]*e[17]+e[8]*e[25]*e[16]+e[2]*e[18]*e[15]+e[2]*e[9]*e[24]+e[2]*e[19]*e[16]+e[2]*e[10]*e[25]-1.*e[17]*e[21]*e[3]+e[23]*e[4]*e[16]+e[23]*e[13]*e[7]-1.*e[8]*e[18]*e[9]-1.*e[8]*e[21]*e[12]-1.*e[8]*e[19]*e[10]-1.*e[8]*e[22]*e[13]; + A[54]=e[13]*e[18]*e[12]+e[13]*e[9]*e[21]+e[13]*e[20]*e[14]+e[13]*e[11]*e[23]+e[13]*e[10]*e[22]+e[22]*e[11]*e[14]+e[22]*e[9]*e[12]+e[16]*e[18]*e[15]+e[16]*e[9]*e[24]+e[16]*e[20]*e[17]+e[16]*e[11]*e[26]+e[16]*e[10]*e[25]+e[25]*e[11]*e[17]+e[25]*e[9]*e[15]-1.*e[10]*e[23]*e[14]-1.*e[10]*e[24]*e[15]-1.*e[10]*e[26]*e[17]+e[10]*e[20]*e[11]+e[10]*e[18]*e[9]-1.*e[10]*e[21]*e[12]+.5000000000*e[19]*ep2[11]+.5000000000*e[19]*ep2[9]+1.500000000*e[19]*ep2[10]+.5000000000*e[19]*ep2[13]+.5000000000*e[19]*ep2[16]-.5000000000*e[19]*ep2[12]-.5000000000*e[19]*ep2[15]-.5000000000*e[19]*ep2[17]-.5000000000*e[19]*ep2[14]; + A[164]=e[10]*e[18]*e[6]+e[10]*e[0]*e[24]+e[10]*e[19]*e[7]+e[10]*e[1]*e[25]+e[10]*e[20]*e[8]+e[10]*e[2]*e[26]+e[19]*e[9]*e[6]+e[19]*e[0]*e[15]+e[19]*e[1]*e[16]+e[19]*e[11]*e[8]+e[19]*e[2]*e[17]+e[4]*e[21]*e[15]+e[4]*e[12]*e[24]+e[4]*e[23]*e[17]+e[4]*e[14]*e[26]+e[4]*e[22]*e[16]+e[4]*e[13]*e[25]+e[7]*e[24]*e[15]+e[7]*e[26]*e[17]+3.*e[7]*e[25]*e[16]+e[1]*e[18]*e[15]+e[1]*e[9]*e[24]+e[1]*e[20]*e[17]+e[1]*e[11]*e[26]-1.*e[16]*e[21]*e[3]+e[16]*e[26]*e[8]-1.*e[16]*e[20]*e[2]-1.*e[16]*e[18]*e[0]-1.*e[16]*e[23]*e[5]+e[16]*e[24]*e[6]+e[13]*e[21]*e[6]+e[13]*e[3]*e[24]+e[13]*e[22]*e[7]+e[13]*e[23]*e[8]+e[13]*e[5]*e[26]-1.*e[25]*e[11]*e[2]+e[25]*e[15]*e[6]-1.*e[25]*e[9]*e[0]-1.*e[25]*e[14]*e[5]-1.*e[25]*e[12]*e[3]+e[25]*e[17]*e[8]+e[22]*e[12]*e[6]+e[22]*e[3]*e[15]+e[22]*e[14]*e[8]+e[22]*e[5]*e[17]-1.*e[7]*e[23]*e[14]-1.*e[7]*e[20]*e[11]-1.*e[7]*e[18]*e[9]-1.*e[7]*e[21]*e[12]; + A[55]=e[13]*e[9]*e[3]+e[13]*e[0]*e[12]+e[13]*e[10]*e[4]+e[13]*e[11]*e[5]+e[13]*e[2]*e[14]+e[16]*e[9]*e[6]+e[16]*e[0]*e[15]+e[16]*e[10]*e[7]+e[16]*e[11]*e[8]+e[16]*e[2]*e[17]+e[7]*e[11]*e[17]+e[7]*e[9]*e[15]+e[4]*e[11]*e[14]+e[4]*e[9]*e[12]+e[10]*e[9]*e[0]+e[10]*e[11]*e[2]-1.*e[10]*e[15]*e[6]-1.*e[10]*e[14]*e[5]-1.*e[10]*e[12]*e[3]-1.*e[10]*e[17]*e[8]+.5000000000*e[1]*ep2[11]+.5000000000*e[1]*ep2[9]+1.500000000*e[1]*ep2[10]-.5000000000*e[1]*ep2[12]-.5000000000*e[1]*ep2[15]-.5000000000*e[1]*ep2[17]-.5000000000*e[1]*ep2[14]+.5000000000*e[1]*ep2[13]+.5000000000*e[1]*ep2[16]; + A[165]=e[1]*e[27]*e[6]+e[1]*e[0]*e[33]+e[1]*e[28]*e[7]+e[1]*e[29]*e[8]+e[1]*e[2]*e[35]-1.*e[7]*e[27]*e[0]-1.*e[7]*e[32]*e[5]+e[7]*e[33]*e[6]-1.*e[7]*e[30]*e[3]+e[7]*e[35]*e[8]-1.*e[7]*e[29]*e[2]+e[7]*e[31]*e[4]+e[28]*e[0]*e[6]+e[28]*e[2]*e[8]+e[4]*e[30]*e[6]+e[4]*e[3]*e[33]+e[4]*e[32]*e[8]+e[4]*e[5]*e[35]+e[31]*e[3]*e[6]+e[31]*e[5]*e[8]+.5000000000*ep2[1]*e[34]+1.500000000*e[34]*ep2[7]+.5000000000*e[34]*ep2[4]-.5000000000*e[34]*ep2[0]+.5000000000*e[34]*ep2[6]-.5000000000*e[34]*ep2[5]-.5000000000*e[34]*ep2[3]-.5000000000*e[34]*ep2[2]+.5000000000*e[34]*ep2[8]; + A[52]=e[4]*e[18]*e[3]+e[4]*e[0]*e[21]+e[4]*e[1]*e[22]+e[4]*e[20]*e[5]+e[4]*e[2]*e[23]+e[22]*e[0]*e[3]+e[22]*e[2]*e[5]+e[7]*e[18]*e[6]+e[7]*e[0]*e[24]+e[7]*e[1]*e[25]+e[7]*e[20]*e[8]+e[7]*e[2]*e[26]+e[25]*e[0]*e[6]+e[25]*e[2]*e[8]+e[1]*e[18]*e[0]+e[1]*e[20]*e[2]-1.*e[1]*e[21]*e[3]-1.*e[1]*e[26]*e[8]-1.*e[1]*e[23]*e[5]-1.*e[1]*e[24]*e[6]+.5000000000*e[19]*ep2[4]+.5000000000*e[19]*ep2[0]-.5000000000*e[19]*ep2[6]-.5000000000*e[19]*ep2[5]+1.500000000*e[19]*ep2[1]+.5000000000*e[19]*ep2[7]-.5000000000*e[19]*ep2[3]+.5000000000*e[19]*ep2[2]-.5000000000*e[19]*ep2[8]; + A[166]=-.5000000000*e[7]*ep2[0]+e[4]*e[5]*e[8]+.5000000000*ep2[4]*e[7]-.5000000000*e[7]*ep2[2]+.5000000000*e[7]*ep2[8]-.5000000000*e[7]*ep2[5]+.5000000000*e[7]*ep2[6]+e[1]*e[0]*e[6]+.5000000000*ep3[7]+e[4]*e[3]*e[6]+e[1]*e[2]*e[8]-.5000000000*e[7]*ep2[3]+.5000000000*ep2[1]*e[7]; + A[53]=-1.*e[1]*e[32]*e[23]-1.*e[19]*e[32]*e[5]-1.*e[19]*e[33]*e[6]-1.*e[19]*e[30]*e[3]-1.*e[19]*e[35]*e[8]-1.*e[28]*e[21]*e[3]-1.*e[28]*e[26]*e[8]-1.*e[28]*e[23]*e[5]-1.*e[28]*e[24]*e[6]+e[7]*e[27]*e[24]+e[7]*e[18]*e[33]+e[7]*e[29]*e[26]+e[7]*e[20]*e[35]+e[22]*e[27]*e[3]+e[22]*e[0]*e[30]+e[22]*e[29]*e[5]+e[22]*e[2]*e[32]+e[31]*e[18]*e[3]+e[31]*e[0]*e[21]+e[31]*e[20]*e[5]+e[31]*e[2]*e[23]+e[25]*e[27]*e[6]+e[25]*e[0]*e[33]+e[25]*e[28]*e[7]+e[25]*e[1]*e[34]+e[25]*e[29]*e[8]+e[25]*e[2]*e[35]+e[34]*e[18]*e[6]+e[34]*e[0]*e[24]+e[34]*e[19]*e[7]+e[34]*e[20]*e[8]+e[34]*e[2]*e[26]+e[1]*e[27]*e[18]+3.*e[1]*e[28]*e[19]+e[1]*e[29]*e[20]+e[19]*e[27]*e[0]+e[19]*e[29]*e[2]+e[28]*e[18]*e[0]+e[28]*e[20]*e[2]+e[4]*e[27]*e[21]+e[4]*e[18]*e[30]+e[4]*e[28]*e[22]+e[4]*e[19]*e[31]+e[4]*e[29]*e[23]+e[4]*e[20]*e[32]-1.*e[1]*e[33]*e[24]-1.*e[1]*e[30]*e[21]-1.*e[1]*e[35]*e[26]+e[1]*e[31]*e[22]; + A[167]=e[10]*e[27]*e[15]+e[10]*e[9]*e[33]+e[10]*e[29]*e[17]+e[10]*e[11]*e[35]+e[10]*e[28]*e[16]+e[28]*e[11]*e[17]+e[28]*e[9]*e[15]+e[13]*e[30]*e[15]+e[13]*e[12]*e[33]+e[13]*e[32]*e[17]+e[13]*e[14]*e[35]+e[13]*e[31]*e[16]+e[31]*e[14]*e[17]+e[31]*e[12]*e[15]+e[16]*e[33]*e[15]+e[16]*e[35]*e[17]-1.*e[16]*e[27]*e[9]-1.*e[16]*e[30]*e[12]-1.*e[16]*e[32]*e[14]-1.*e[16]*e[29]*e[11]+.5000000000*ep2[10]*e[34]+1.500000000*e[34]*ep2[16]-.5000000000*e[34]*ep2[9]-.5000000000*e[34]*ep2[11]-.5000000000*e[34]*ep2[12]+.5000000000*e[34]*ep2[15]+.5000000000*e[34]*ep2[17]-.5000000000*e[34]*ep2[14]+.5000000000*e[34]*ep2[13]; + A[50]=.5000000000*e[19]*ep2[18]+.5000000000*e[19]*ep2[25]+.5000000000*e[19]*ep2[22]+e[25]*e[20]*e[26]-.5000000000*e[19]*ep2[21]+.5000000000*e[19]*ep2[20]-.5000000000*e[19]*ep2[26]-.5000000000*e[19]*ep2[23]-.5000000000*e[19]*ep2[24]+.5000000000*ep3[19]+e[22]*e[20]*e[23]+e[25]*e[18]*e[24]+e[22]*e[18]*e[21]; + A[160]=.5000000000*e[34]*ep2[33]+.5000000000*e[34]*ep2[35]-.5000000000*e[34]*ep2[27]-.5000000000*e[34]*ep2[32]-.5000000000*e[34]*ep2[29]-.5000000000*e[34]*ep2[30]+.5000000000*ep2[28]*e[34]+e[31]*e[30]*e[33]+e[31]*e[32]*e[35]+e[28]*e[27]*e[33]+.5000000000*ep3[34]+e[28]*e[29]*e[35]+.5000000000*ep2[31]*e[34]; + A[51]=e[4]*e[28]*e[13]+e[4]*e[10]*e[31]+e[7]*e[27]*e[15]+e[7]*e[9]*e[33]+e[7]*e[29]*e[17]+e[7]*e[11]*e[35]+e[7]*e[28]*e[16]+e[7]*e[10]*e[34]+e[1]*e[27]*e[9]+e[1]*e[29]*e[11]+3.*e[1]*e[28]*e[10]+e[10]*e[27]*e[0]-1.*e[10]*e[32]*e[5]-1.*e[10]*e[33]*e[6]-1.*e[10]*e[30]*e[3]-1.*e[10]*e[35]*e[8]+e[10]*e[29]*e[2]+e[13]*e[27]*e[3]+e[13]*e[0]*e[30]+e[13]*e[1]*e[31]+e[13]*e[29]*e[5]+e[13]*e[2]*e[32]+e[28]*e[11]*e[2]-1.*e[28]*e[15]*e[6]+e[28]*e[9]*e[0]-1.*e[28]*e[14]*e[5]-1.*e[28]*e[12]*e[3]-1.*e[28]*e[17]*e[8]+e[31]*e[9]*e[3]+e[31]*e[0]*e[12]+e[31]*e[11]*e[5]+e[31]*e[2]*e[14]+e[16]*e[27]*e[6]+e[16]*e[0]*e[33]+e[16]*e[1]*e[34]+e[16]*e[29]*e[8]+e[16]*e[2]*e[35]-1.*e[1]*e[30]*e[12]-1.*e[1]*e[32]*e[14]-1.*e[1]*e[33]*e[15]-1.*e[1]*e[35]*e[17]+e[34]*e[9]*e[6]+e[34]*e[0]*e[15]+e[34]*e[11]*e[8]+e[34]*e[2]*e[17]+e[4]*e[27]*e[12]+e[4]*e[9]*e[30]+e[4]*e[29]*e[14]+e[4]*e[11]*e[32]; + A[161]=e[4]*e[30]*e[33]+e[4]*e[32]*e[35]+e[4]*e[31]*e[34]+e[31]*e[30]*e[6]+e[31]*e[3]*e[33]+e[31]*e[32]*e[8]+e[31]*e[5]*e[35]+e[28]*e[27]*e[6]+e[28]*e[0]*e[33]+e[28]*e[29]*e[8]+e[28]*e[2]*e[35]+e[34]*e[33]*e[6]+e[34]*e[35]*e[8]-1.*e[34]*e[27]*e[0]-1.*e[34]*e[32]*e[5]-1.*e[34]*e[30]*e[3]-1.*e[34]*e[29]*e[2]+e[1]*e[27]*e[33]+e[1]*e[29]*e[35]+e[1]*e[28]*e[34]+.5000000000*ep2[31]*e[7]-.5000000000*e[7]*ep2[27]-.5000000000*e[7]*ep2[32]+.5000000000*e[7]*ep2[28]-.5000000000*e[7]*ep2[29]+.5000000000*e[7]*ep2[33]-.5000000000*e[7]*ep2[30]+1.500000000*e[7]*ep2[34]+.5000000000*e[7]*ep2[35]; + A[48]=-.5000000000*e[10]*ep2[14]-.5000000000*e[10]*ep2[17]-.5000000000*e[10]*ep2[15]+e[13]*e[11]*e[14]+e[16]*e[11]*e[17]+.5000000000*e[10]*ep2[13]+e[13]*e[9]*e[12]-.5000000000*e[10]*ep2[12]+.5000000000*ep3[10]+e[16]*e[9]*e[15]+.5000000000*e[10]*ep2[16]+.5000000000*e[10]*ep2[11]+.5000000000*e[10]*ep2[9]; + A[162]=e[22]*e[32]*e[35]+e[22]*e[31]*e[34]+e[31]*e[30]*e[24]+e[31]*e[21]*e[33]+e[31]*e[32]*e[26]+e[31]*e[23]*e[35]+e[34]*e[33]*e[24]+e[34]*e[35]*e[26]-1.*e[34]*e[27]*e[18]-1.*e[34]*e[30]*e[21]-1.*e[34]*e[29]*e[20]-1.*e[34]*e[32]*e[23]+e[19]*e[27]*e[33]+e[19]*e[29]*e[35]+e[19]*e[28]*e[34]+e[28]*e[27]*e[24]+e[28]*e[18]*e[33]+e[28]*e[29]*e[26]+e[28]*e[20]*e[35]+e[22]*e[30]*e[33]+.5000000000*ep2[28]*e[25]+.5000000000*ep2[31]*e[25]+.5000000000*e[25]*ep2[33]+.5000000000*e[25]*ep2[35]+1.500000000*e[25]*ep2[34]-.5000000000*e[25]*ep2[27]-.5000000000*e[25]*ep2[32]-.5000000000*e[25]*ep2[29]-.5000000000*e[25]*ep2[30]; + A[49]=-1.*e[19]*e[35]*e[26]-1.*e[19]*e[32]*e[23]+e[19]*e[27]*e[18]+e[19]*e[29]*e[20]+e[22]*e[27]*e[21]+e[22]*e[18]*e[30]+e[22]*e[19]*e[31]+e[22]*e[29]*e[23]+e[22]*e[20]*e[32]+e[31]*e[18]*e[21]+e[31]*e[20]*e[23]+e[25]*e[27]*e[24]+e[25]*e[18]*e[33]+e[25]*e[19]*e[34]+e[25]*e[29]*e[26]+e[25]*e[20]*e[35]+e[34]*e[18]*e[24]+e[34]*e[20]*e[26]-1.*e[19]*e[33]*e[24]-1.*e[19]*e[30]*e[21]+1.500000000*e[28]*ep2[19]+.5000000000*e[28]*ep2[18]+.5000000000*e[28]*ep2[20]+.5000000000*e[28]*ep2[22]+.5000000000*e[28]*ep2[25]-.5000000000*e[28]*ep2[26]-.5000000000*e[28]*ep2[23]-.5000000000*e[28]*ep2[24]-.5000000000*e[28]*ep2[21]; + A[163]=e[10]*e[27]*e[33]+e[10]*e[29]*e[35]+e[10]*e[28]*e[34]+e[34]*e[33]*e[15]+e[34]*e[35]*e[17]+e[28]*e[27]*e[15]+e[28]*e[9]*e[33]+e[28]*e[29]*e[17]+e[28]*e[11]*e[35]-1.*e[34]*e[27]*e[9]-1.*e[34]*e[30]*e[12]+e[34]*e[31]*e[13]-1.*e[34]*e[32]*e[14]-1.*e[34]*e[29]*e[11]+e[31]*e[30]*e[15]+e[31]*e[12]*e[33]+e[31]*e[32]*e[17]+e[31]*e[14]*e[35]+e[13]*e[30]*e[33]+e[13]*e[32]*e[35]-.5000000000*e[16]*ep2[27]-.5000000000*e[16]*ep2[32]+.5000000000*e[16]*ep2[28]-.5000000000*e[16]*ep2[29]+.5000000000*e[16]*ep2[31]+.5000000000*e[16]*ep2[33]-.5000000000*e[16]*ep2[30]+1.500000000*e[16]*ep2[34]+.5000000000*e[16]*ep2[35]; + A[63]=e[29]*e[32]*e[14]-1.*e[29]*e[33]*e[15]-1.*e[29]*e[34]*e[16]+e[32]*e[27]*e[12]+e[32]*e[9]*e[30]+e[32]*e[28]*e[13]+e[32]*e[10]*e[31]+e[14]*e[27]*e[30]+e[14]*e[28]*e[31]+e[17]*e[27]*e[33]+e[17]*e[28]*e[34]+e[35]*e[27]*e[15]+e[35]*e[9]*e[33]+e[35]*e[29]*e[17]+e[35]*e[28]*e[16]+e[35]*e[10]*e[34]+e[29]*e[27]*e[9]+e[29]*e[28]*e[10]-1.*e[29]*e[30]*e[12]-1.*e[29]*e[31]*e[13]+.5000000000*e[11]*ep2[27]+1.500000000*e[11]*ep2[29]+.5000000000*e[11]*ep2[28]+.5000000000*e[11]*ep2[32]-.5000000000*e[11]*ep2[31]-.5000000000*e[11]*ep2[33]-.5000000000*e[11]*ep2[30]-.5000000000*e[11]*ep2[34]+.5000000000*e[11]*ep2[35]; + A[173]=e[1]*e[20]*e[35]+e[19]*e[27]*e[6]+e[19]*e[0]*e[33]+e[19]*e[28]*e[7]+e[19]*e[29]*e[8]+e[19]*e[2]*e[35]+e[28]*e[18]*e[6]+e[28]*e[0]*e[24]+e[28]*e[20]*e[8]+e[28]*e[2]*e[26]+e[4]*e[30]*e[24]+e[4]*e[21]*e[33]+e[4]*e[31]*e[25]+e[4]*e[22]*e[34]+e[4]*e[32]*e[26]+e[4]*e[23]*e[35]-1.*e[7]*e[27]*e[18]+e[7]*e[33]*e[24]-1.*e[7]*e[30]*e[21]-1.*e[7]*e[29]*e[20]+e[7]*e[35]*e[26]+e[7]*e[31]*e[22]-1.*e[7]*e[32]*e[23]-1.*e[25]*e[27]*e[0]-1.*e[25]*e[32]*e[5]-1.*e[25]*e[30]*e[3]-1.*e[25]*e[29]*e[2]-1.*e[34]*e[21]*e[3]-1.*e[34]*e[20]*e[2]-1.*e[34]*e[18]*e[0]-1.*e[34]*e[23]*e[5]+e[22]*e[30]*e[6]+e[22]*e[3]*e[33]+e[22]*e[32]*e[8]+e[22]*e[5]*e[35]+e[31]*e[21]*e[6]+e[31]*e[3]*e[24]+e[31]*e[23]*e[8]+e[31]*e[5]*e[26]+e[34]*e[26]*e[8]+e[1]*e[27]*e[24]+e[1]*e[18]*e[33]+e[1]*e[28]*e[25]+e[1]*e[19]*e[34]+e[1]*e[29]*e[26]+e[34]*e[24]*e[6]+e[25]*e[33]*e[6]+3.*e[25]*e[34]*e[7]+e[25]*e[35]*e[8]; + A[62]=.5000000000*e[20]*ep2[27]+1.500000000*e[20]*ep2[29]+.5000000000*e[20]*ep2[28]+.5000000000*e[20]*ep2[32]+.5000000000*e[20]*ep2[35]-.5000000000*e[20]*ep2[31]-.5000000000*e[20]*ep2[33]-.5000000000*e[20]*ep2[30]-.5000000000*e[20]*ep2[34]+e[29]*e[27]*e[18]+e[29]*e[28]*e[19]+e[23]*e[27]*e[30]+e[23]*e[29]*e[32]+e[23]*e[28]*e[31]+e[32]*e[27]*e[21]+e[32]*e[18]*e[30]+e[32]*e[28]*e[22]+e[32]*e[19]*e[31]+e[26]*e[27]*e[33]+e[26]*e[29]*e[35]+e[26]*e[28]*e[34]+e[35]*e[27]*e[24]+e[35]*e[18]*e[33]+e[35]*e[28]*e[25]+e[35]*e[19]*e[34]-1.*e[29]*e[33]*e[24]-1.*e[29]*e[30]*e[21]-1.*e[29]*e[31]*e[22]-1.*e[29]*e[34]*e[25]; + A[172]=e[19]*e[1]*e[7]+e[19]*e[0]*e[6]+e[19]*e[2]*e[8]+e[4]*e[21]*e[6]+e[4]*e[3]*e[24]+e[4]*e[22]*e[7]+e[4]*e[23]*e[8]+e[4]*e[5]*e[26]+e[22]*e[3]*e[6]+e[22]*e[5]*e[8]+e[7]*e[24]*e[6]+e[7]*e[26]*e[8]+e[1]*e[18]*e[6]+e[1]*e[0]*e[24]+e[1]*e[20]*e[8]+e[1]*e[2]*e[26]-1.*e[7]*e[21]*e[3]-1.*e[7]*e[20]*e[2]-1.*e[7]*e[18]*e[0]-1.*e[7]*e[23]*e[5]+.5000000000*e[25]*ep2[4]-.5000000000*e[25]*ep2[0]+.5000000000*e[25]*ep2[6]-.5000000000*e[25]*ep2[5]+.5000000000*e[25]*ep2[1]+1.500000000*e[25]*ep2[7]-.5000000000*e[25]*ep2[3]-.5000000000*e[25]*ep2[2]+.5000000000*e[25]*ep2[8]; + A[61]=e[5]*e[27]*e[30]+e[5]*e[29]*e[32]+e[5]*e[28]*e[31]+e[32]*e[27]*e[3]+e[32]*e[0]*e[30]+e[32]*e[28]*e[4]+e[32]*e[1]*e[31]+e[8]*e[27]*e[33]+e[8]*e[29]*e[35]+e[8]*e[28]*e[34]+e[29]*e[27]*e[0]+e[29]*e[28]*e[1]+e[35]*e[27]*e[6]+e[35]*e[0]*e[33]+e[35]*e[28]*e[7]+e[35]*e[1]*e[34]-1.*e[29]*e[34]*e[7]-1.*e[29]*e[33]*e[6]-1.*e[29]*e[30]*e[3]-1.*e[29]*e[31]*e[4]+.5000000000*e[2]*ep2[27]+1.500000000*e[2]*ep2[29]+.5000000000*e[2]*ep2[28]+.5000000000*e[2]*ep2[32]-.5000000000*e[2]*ep2[31]-.5000000000*e[2]*ep2[33]-.5000000000*e[2]*ep2[30]-.5000000000*e[2]*ep2[34]+.5000000000*e[2]*ep2[35]; + A[175]=e[13]*e[12]*e[6]+e[13]*e[3]*e[15]+e[13]*e[4]*e[16]+e[13]*e[14]*e[8]+e[13]*e[5]*e[17]+e[16]*e[15]*e[6]+e[16]*e[17]*e[8]+e[1]*e[11]*e[17]+e[1]*e[9]*e[15]+e[1]*e[10]*e[16]+e[4]*e[14]*e[17]+e[4]*e[12]*e[15]+e[10]*e[9]*e[6]+e[10]*e[0]*e[15]+e[10]*e[11]*e[8]+e[10]*e[2]*e[17]-1.*e[16]*e[11]*e[2]-1.*e[16]*e[9]*e[0]-1.*e[16]*e[14]*e[5]-1.*e[16]*e[12]*e[3]+.5000000000*ep2[13]*e[7]+1.500000000*ep2[16]*e[7]+.5000000000*e[7]*ep2[17]+.5000000000*e[7]*ep2[15]-.5000000000*e[7]*ep2[9]-.5000000000*e[7]*ep2[11]-.5000000000*e[7]*ep2[12]+.5000000000*e[7]*ep2[10]-.5000000000*e[7]*ep2[14]; + A[60]=.5000000000*e[29]*ep2[32]+.5000000000*e[29]*ep2[35]-.5000000000*e[29]*ep2[31]-.5000000000*e[29]*ep2[33]-.5000000000*e[29]*ep2[30]-.5000000000*e[29]*ep2[34]+e[32]*e[27]*e[30]+.5000000000*ep3[29]+.5000000000*e[29]*ep2[28]+e[35]*e[28]*e[34]+.5000000000*e[29]*ep2[27]+e[35]*e[27]*e[33]+e[32]*e[28]*e[31]; + A[174]=-1.*e[16]*e[21]*e[12]+e[10]*e[18]*e[15]+e[10]*e[9]*e[24]+e[10]*e[20]*e[17]+e[10]*e[11]*e[26]+e[19]*e[11]*e[17]+e[19]*e[9]*e[15]+e[19]*e[10]*e[16]+e[13]*e[21]*e[15]+e[13]*e[12]*e[24]+e[13]*e[23]*e[17]+e[13]*e[14]*e[26]+e[13]*e[22]*e[16]+e[22]*e[14]*e[17]+e[22]*e[12]*e[15]+e[16]*e[24]*e[15]+e[16]*e[26]*e[17]-1.*e[16]*e[23]*e[14]-1.*e[16]*e[20]*e[11]-1.*e[16]*e[18]*e[9]+.5000000000*ep2[13]*e[25]+1.500000000*e[25]*ep2[16]+.5000000000*e[25]*ep2[17]+.5000000000*e[25]*ep2[15]+.5000000000*ep2[10]*e[25]-.5000000000*e[25]*ep2[9]-.5000000000*e[25]*ep2[11]-.5000000000*e[25]*ep2[12]-.5000000000*e[25]*ep2[14]; + A[59]=e[19]*e[20]*e[2]+e[22]*e[18]*e[3]+e[22]*e[0]*e[21]+e[22]*e[19]*e[4]+e[22]*e[20]*e[5]+e[22]*e[2]*e[23]-1.*e[19]*e[21]*e[3]-1.*e[19]*e[26]*e[8]+e[19]*e[25]*e[7]-1.*e[19]*e[23]*e[5]-1.*e[19]*e[24]*e[6]+e[4]*e[18]*e[21]+e[4]*e[20]*e[23]+e[25]*e[18]*e[6]+e[25]*e[0]*e[24]+e[25]*e[20]*e[8]+e[25]*e[2]*e[26]+e[7]*e[18]*e[24]+e[7]*e[20]*e[26]+e[19]*e[18]*e[0]+1.500000000*ep2[19]*e[1]+.5000000000*e[1]*ep2[22]+.5000000000*e[1]*ep2[18]+.5000000000*e[1]*ep2[20]+.5000000000*e[1]*ep2[25]-.5000000000*e[1]*ep2[26]-.5000000000*e[1]*ep2[23]-.5000000000*e[1]*ep2[24]-.5000000000*e[1]*ep2[21]; + A[169]=e[19]*e[27]*e[24]+e[19]*e[18]*e[33]+e[19]*e[28]*e[25]+e[19]*e[29]*e[26]+e[19]*e[20]*e[35]+e[28]*e[18]*e[24]+e[28]*e[20]*e[26]+e[22]*e[30]*e[24]+e[22]*e[21]*e[33]+e[22]*e[31]*e[25]+e[22]*e[32]*e[26]+e[22]*e[23]*e[35]+e[31]*e[21]*e[24]+e[31]*e[23]*e[26]+e[25]*e[33]*e[24]+e[25]*e[35]*e[26]-1.*e[25]*e[27]*e[18]-1.*e[25]*e[30]*e[21]-1.*e[25]*e[29]*e[20]-1.*e[25]*e[32]*e[23]-.5000000000*e[34]*ep2[18]-.5000000000*e[34]*ep2[23]-.5000000000*e[34]*ep2[20]-.5000000000*e[34]*ep2[21]+.5000000000*ep2[19]*e[34]+.5000000000*ep2[22]*e[34]+1.500000000*e[34]*ep2[25]+.5000000000*e[34]*ep2[24]+.5000000000*e[34]*ep2[26]; + A[58]=e[16]*e[0]*e[6]+e[16]*e[2]*e[8]+e[1]*e[11]*e[2]-1.*e[1]*e[15]*e[6]+e[1]*e[9]*e[0]-1.*e[1]*e[14]*e[5]-1.*e[1]*e[12]*e[3]-1.*e[1]*e[17]*e[8]+e[4]*e[9]*e[3]+e[4]*e[0]*e[12]+e[4]*e[1]*e[13]+e[4]*e[11]*e[5]+e[4]*e[2]*e[14]+e[13]*e[0]*e[3]+e[13]*e[2]*e[5]+e[7]*e[9]*e[6]+e[7]*e[0]*e[15]+e[7]*e[1]*e[16]+e[7]*e[11]*e[8]+e[7]*e[2]*e[17]-.5000000000*e[10]*ep2[6]-.5000000000*e[10]*ep2[5]-.5000000000*e[10]*ep2[3]-.5000000000*e[10]*ep2[8]+1.500000000*e[10]*ep2[1]+.5000000000*e[10]*ep2[0]+.5000000000*e[10]*ep2[2]+.5000000000*e[10]*ep2[4]+.5000000000*e[10]*ep2[7]; + A[168]=e[13]*e[14]*e[17]+e[13]*e[12]*e[15]+e[10]*e[9]*e[15]+.5000000000*e[16]*ep2[15]-.5000000000*e[16]*ep2[11]-.5000000000*e[16]*ep2[12]-.5000000000*e[16]*ep2[14]+e[10]*e[11]*e[17]+.5000000000*ep2[10]*e[16]+.5000000000*ep3[16]-.5000000000*e[16]*ep2[9]+.5000000000*e[16]*ep2[17]+.5000000000*ep2[13]*e[16]; + A[57]=e[10]*e[29]*e[20]+e[22]*e[27]*e[12]+e[22]*e[9]*e[30]+e[22]*e[29]*e[14]+e[22]*e[11]*e[32]+e[22]*e[10]*e[31]+e[31]*e[18]*e[12]+e[31]*e[9]*e[21]+e[31]*e[20]*e[14]+e[31]*e[11]*e[23]-1.*e[10]*e[33]*e[24]-1.*e[10]*e[30]*e[21]-1.*e[10]*e[35]*e[26]-1.*e[10]*e[32]*e[23]+e[10]*e[34]*e[25]+e[19]*e[27]*e[9]+e[19]*e[29]*e[11]+e[28]*e[18]*e[9]+e[28]*e[20]*e[11]+e[16]*e[27]*e[24]+e[16]*e[18]*e[33]+e[16]*e[28]*e[25]+e[16]*e[19]*e[34]+e[16]*e[29]*e[26]+e[16]*e[20]*e[35]-1.*e[19]*e[30]*e[12]-1.*e[19]*e[32]*e[14]-1.*e[19]*e[33]*e[15]-1.*e[19]*e[35]*e[17]-1.*e[28]*e[23]*e[14]-1.*e[28]*e[24]*e[15]-1.*e[28]*e[26]*e[17]-1.*e[28]*e[21]*e[12]+e[25]*e[27]*e[15]+e[25]*e[9]*e[33]+e[25]*e[29]*e[17]+e[25]*e[11]*e[35]+e[34]*e[18]*e[15]+e[34]*e[9]*e[24]+e[34]*e[20]*e[17]+e[34]*e[11]*e[26]+e[13]*e[27]*e[21]+e[13]*e[18]*e[30]+e[13]*e[28]*e[22]+e[13]*e[19]*e[31]+e[13]*e[29]*e[23]+e[13]*e[20]*e[32]+e[10]*e[27]*e[18]+3.*e[10]*e[28]*e[19]; + A[171]=e[4]*e[30]*e[15]+e[4]*e[12]*e[33]+e[4]*e[32]*e[17]+e[4]*e[14]*e[35]+e[4]*e[31]*e[16]+e[4]*e[13]*e[34]+e[7]*e[33]*e[15]+e[7]*e[35]*e[17]+3.*e[7]*e[34]*e[16]+e[1]*e[27]*e[15]+e[1]*e[9]*e[33]+e[1]*e[29]*e[17]+e[1]*e[11]*e[35]+e[1]*e[28]*e[16]+e[1]*e[10]*e[34]-1.*e[16]*e[27]*e[0]-1.*e[16]*e[32]*e[5]+e[16]*e[33]*e[6]-1.*e[16]*e[30]*e[3]+e[16]*e[35]*e[8]-1.*e[16]*e[29]*e[2]+e[13]*e[30]*e[6]+e[13]*e[3]*e[33]+e[13]*e[31]*e[7]+e[13]*e[32]*e[8]+e[13]*e[5]*e[35]-1.*e[34]*e[11]*e[2]+e[34]*e[15]*e[6]-1.*e[34]*e[9]*e[0]-1.*e[34]*e[14]*e[5]-1.*e[34]*e[12]*e[3]+e[34]*e[17]*e[8]+e[31]*e[12]*e[6]+e[31]*e[3]*e[15]+e[31]*e[14]*e[8]+e[31]*e[5]*e[17]-1.*e[7]*e[27]*e[9]-1.*e[7]*e[30]*e[12]+e[7]*e[28]*e[10]-1.*e[7]*e[32]*e[14]+e[10]*e[27]*e[6]+e[10]*e[0]*e[33]+e[10]*e[29]*e[8]+e[10]*e[2]*e[35]+e[28]*e[9]*e[6]+e[28]*e[0]*e[15]+e[28]*e[11]*e[8]+e[28]*e[2]*e[17]-1.*e[7]*e[29]*e[11]; + A[56]=e[22]*e[18]*e[12]+e[22]*e[9]*e[21]+e[22]*e[20]*e[14]+e[22]*e[11]*e[23]+e[22]*e[19]*e[13]+e[25]*e[18]*e[15]+e[25]*e[9]*e[24]+e[25]*e[20]*e[17]+e[25]*e[11]*e[26]+e[25]*e[19]*e[16]+e[16]*e[18]*e[24]+e[16]*e[20]*e[26]+e[13]*e[18]*e[21]+e[13]*e[20]*e[23]+e[19]*e[18]*e[9]+e[19]*e[20]*e[11]-1.*e[19]*e[23]*e[14]-1.*e[19]*e[24]*e[15]-1.*e[19]*e[26]*e[17]-1.*e[19]*e[21]*e[12]+.5000000000*e[10]*ep2[22]+.5000000000*e[10]*ep2[25]+1.500000000*e[10]*ep2[19]+.5000000000*e[10]*ep2[18]+.5000000000*e[10]*ep2[20]-.5000000000*e[10]*ep2[26]-.5000000000*e[10]*ep2[23]-.5000000000*e[10]*ep2[24]-.5000000000*e[10]*ep2[21]; + A[170]=e[19]*e[20]*e[26]-.5000000000*e[25]*ep2[20]+e[22]*e[21]*e[24]+e[19]*e[18]*e[24]+.5000000000*ep2[22]*e[25]-.5000000000*e[25]*ep2[21]-.5000000000*e[25]*ep2[23]+.5000000000*ep2[19]*e[25]-.5000000000*e[25]*ep2[18]+.5000000000*e[25]*ep2[24]+.5000000000*e[25]*ep2[26]+.5000000000*ep3[25]+e[22]*e[23]*e[26]; + A[73]=-1.*e[20]*e[33]*e[6]-1.*e[20]*e[30]*e[3]-1.*e[20]*e[31]*e[4]-1.*e[29]*e[21]*e[3]-1.*e[29]*e[22]*e[4]-1.*e[29]*e[25]*e[7]-1.*e[29]*e[24]*e[6]+e[8]*e[27]*e[24]+e[8]*e[18]*e[33]+e[8]*e[28]*e[25]+e[8]*e[19]*e[34]+e[23]*e[27]*e[3]+e[23]*e[0]*e[30]+e[23]*e[28]*e[4]+e[23]*e[1]*e[31]+e[32]*e[18]*e[3]+e[32]*e[0]*e[21]+e[32]*e[19]*e[4]+e[32]*e[1]*e[22]+e[26]*e[27]*e[6]+e[26]*e[0]*e[33]+e[26]*e[28]*e[7]+e[26]*e[1]*e[34]+e[26]*e[29]*e[8]+e[26]*e[2]*e[35]+e[35]*e[18]*e[6]+e[35]*e[0]*e[24]+e[35]*e[19]*e[7]+e[35]*e[1]*e[25]+e[35]*e[20]*e[8]+e[2]*e[27]*e[18]+e[2]*e[28]*e[19]+3.*e[2]*e[29]*e[20]+e[20]*e[27]*e[0]+e[20]*e[28]*e[1]+e[29]*e[18]*e[0]+e[29]*e[19]*e[1]+e[5]*e[27]*e[21]+e[5]*e[18]*e[30]+e[5]*e[28]*e[22]+e[5]*e[19]*e[31]+e[5]*e[29]*e[23]+e[5]*e[20]*e[32]-1.*e[2]*e[33]*e[24]-1.*e[2]*e[30]*e[21]-1.*e[2]*e[31]*e[22]+e[2]*e[32]*e[23]-1.*e[2]*e[34]*e[25]-1.*e[20]*e[34]*e[7]; + A[72]=e[5]*e[18]*e[3]+e[5]*e[0]*e[21]+e[5]*e[19]*e[4]+e[5]*e[1]*e[22]+e[5]*e[2]*e[23]+e[23]*e[1]*e[4]+e[23]*e[0]*e[3]+e[8]*e[18]*e[6]+e[8]*e[0]*e[24]+e[8]*e[19]*e[7]+e[8]*e[1]*e[25]+e[8]*e[2]*e[26]+e[26]*e[1]*e[7]+e[26]*e[0]*e[6]+e[2]*e[18]*e[0]+e[2]*e[19]*e[1]-1.*e[2]*e[21]*e[3]-1.*e[2]*e[22]*e[4]-1.*e[2]*e[25]*e[7]-1.*e[2]*e[24]*e[6]-.5000000000*e[20]*ep2[4]+.5000000000*e[20]*ep2[0]-.5000000000*e[20]*ep2[6]+.5000000000*e[20]*ep2[5]+.5000000000*e[20]*ep2[1]-.5000000000*e[20]*ep2[7]-.5000000000*e[20]*ep2[3]+1.500000000*e[20]*ep2[2]+.5000000000*e[20]*ep2[8]; + A[75]=e[14]*e[9]*e[3]+e[14]*e[0]*e[12]+e[14]*e[10]*e[4]+e[14]*e[1]*e[13]+e[14]*e[11]*e[5]+e[17]*e[9]*e[6]+e[17]*e[0]*e[15]+e[17]*e[10]*e[7]+e[17]*e[1]*e[16]+e[17]*e[11]*e[8]+e[8]*e[9]*e[15]+e[8]*e[10]*e[16]+e[5]*e[9]*e[12]+e[5]*e[10]*e[13]+e[11]*e[9]*e[0]+e[11]*e[10]*e[1]-1.*e[11]*e[13]*e[4]-1.*e[11]*e[16]*e[7]-1.*e[11]*e[15]*e[6]-1.*e[11]*e[12]*e[3]+.5000000000*e[2]*ep2[14]+.5000000000*e[2]*ep2[17]+1.500000000*e[2]*ep2[11]+.5000000000*e[2]*ep2[9]+.5000000000*e[2]*ep2[10]-.5000000000*e[2]*ep2[16]-.5000000000*e[2]*ep2[12]-.5000000000*e[2]*ep2[15]-.5000000000*e[2]*ep2[13]; + A[74]=e[14]*e[18]*e[12]+e[14]*e[9]*e[21]+e[14]*e[11]*e[23]+e[14]*e[19]*e[13]+e[14]*e[10]*e[22]+e[23]*e[9]*e[12]+e[23]*e[10]*e[13]+e[17]*e[18]*e[15]+e[17]*e[9]*e[24]+e[17]*e[11]*e[26]+e[17]*e[19]*e[16]+e[17]*e[10]*e[25]+e[26]*e[9]*e[15]+e[26]*e[10]*e[16]-1.*e[11]*e[24]*e[15]-1.*e[11]*e[25]*e[16]+e[11]*e[18]*e[9]-1.*e[11]*e[21]*e[12]+e[11]*e[19]*e[10]-1.*e[11]*e[22]*e[13]+1.500000000*e[20]*ep2[11]+.5000000000*e[20]*ep2[9]+.5000000000*e[20]*ep2[10]+.5000000000*e[20]*ep2[14]+.5000000000*e[20]*ep2[17]-.5000000000*e[20]*ep2[16]-.5000000000*e[20]*ep2[12]-.5000000000*e[20]*ep2[15]-.5000000000*e[20]*ep2[13]; + A[77]=e[23]*e[10]*e[31]+e[32]*e[18]*e[12]+e[32]*e[9]*e[21]+e[32]*e[19]*e[13]+e[32]*e[10]*e[22]-1.*e[11]*e[33]*e[24]-1.*e[11]*e[30]*e[21]+e[11]*e[35]*e[26]-1.*e[11]*e[31]*e[22]-1.*e[11]*e[34]*e[25]+e[20]*e[27]*e[9]+e[20]*e[28]*e[10]+e[29]*e[18]*e[9]+e[29]*e[19]*e[10]+e[17]*e[27]*e[24]+e[17]*e[18]*e[33]+e[17]*e[28]*e[25]+e[17]*e[19]*e[34]+e[17]*e[29]*e[26]+e[17]*e[20]*e[35]-1.*e[20]*e[30]*e[12]-1.*e[20]*e[31]*e[13]-1.*e[20]*e[33]*e[15]-1.*e[20]*e[34]*e[16]-1.*e[29]*e[24]*e[15]-1.*e[29]*e[25]*e[16]-1.*e[29]*e[21]*e[12]-1.*e[29]*e[22]*e[13]+e[26]*e[27]*e[15]+e[26]*e[9]*e[33]+e[26]*e[28]*e[16]+e[26]*e[10]*e[34]+e[35]*e[18]*e[15]+e[35]*e[9]*e[24]+e[35]*e[19]*e[16]+e[35]*e[10]*e[25]+e[14]*e[27]*e[21]+e[14]*e[18]*e[30]+e[14]*e[28]*e[22]+e[14]*e[19]*e[31]+e[14]*e[29]*e[23]+e[14]*e[20]*e[32]+e[11]*e[27]*e[18]+e[11]*e[28]*e[19]+3.*e[11]*e[29]*e[20]+e[23]*e[27]*e[12]+e[23]*e[9]*e[30]+e[23]*e[11]*e[32]+e[23]*e[28]*e[13]; + A[76]=e[23]*e[18]*e[12]+e[23]*e[9]*e[21]+e[23]*e[20]*e[14]+e[23]*e[19]*e[13]+e[23]*e[10]*e[22]+e[26]*e[18]*e[15]+e[26]*e[9]*e[24]+e[26]*e[20]*e[17]+e[26]*e[19]*e[16]+e[26]*e[10]*e[25]+e[17]*e[19]*e[25]+e[17]*e[18]*e[24]+e[14]*e[19]*e[22]+e[14]*e[18]*e[21]+e[20]*e[18]*e[9]+e[20]*e[19]*e[10]-1.*e[20]*e[24]*e[15]-1.*e[20]*e[25]*e[16]-1.*e[20]*e[21]*e[12]-1.*e[20]*e[22]*e[13]+.5000000000*e[11]*ep2[23]+.5000000000*e[11]*ep2[26]+.5000000000*e[11]*ep2[19]+.5000000000*e[11]*ep2[18]+1.500000000*e[11]*ep2[20]-.5000000000*e[11]*ep2[22]-.5000000000*e[11]*ep2[24]-.5000000000*e[11]*ep2[21]-.5000000000*e[11]*ep2[25]; + A[79]=-1.*e[20]*e[21]*e[3]+e[20]*e[26]*e[8]-1.*e[20]*e[22]*e[4]-1.*e[20]*e[25]*e[7]-1.*e[20]*e[24]*e[6]+e[5]*e[19]*e[22]+e[5]*e[18]*e[21]+e[26]*e[18]*e[6]+e[26]*e[0]*e[24]+e[26]*e[19]*e[7]+e[26]*e[1]*e[25]+e[8]*e[19]*e[25]+e[8]*e[18]*e[24]+e[20]*e[18]*e[0]+e[20]*e[19]*e[1]+e[23]*e[18]*e[3]+e[23]*e[0]*e[21]+e[23]*e[19]*e[4]+e[23]*e[1]*e[22]+e[23]*e[20]*e[5]+1.500000000*ep2[20]*e[2]+.5000000000*e[2]*ep2[23]+.5000000000*e[2]*ep2[19]+.5000000000*e[2]*ep2[18]+.5000000000*e[2]*ep2[26]-.5000000000*e[2]*ep2[22]-.5000000000*e[2]*ep2[24]-.5000000000*e[2]*ep2[21]-.5000000000*e[2]*ep2[25]; + A[78]=-1.*e[2]*e[15]*e[6]+e[2]*e[9]*e[0]-1.*e[2]*e[12]*e[3]+e[5]*e[9]*e[3]+e[5]*e[0]*e[12]+e[5]*e[10]*e[4]+e[5]*e[1]*e[13]+e[5]*e[2]*e[14]+e[14]*e[1]*e[4]+e[14]*e[0]*e[3]+e[8]*e[9]*e[6]+e[8]*e[0]*e[15]+e[8]*e[10]*e[7]+e[8]*e[1]*e[16]+e[8]*e[2]*e[17]+e[17]*e[1]*e[7]+e[17]*e[0]*e[6]+e[2]*e[10]*e[1]-1.*e[2]*e[13]*e[4]-1.*e[2]*e[16]*e[7]+.5000000000*e[11]*ep2[1]+.5000000000*e[11]*ep2[0]+1.500000000*e[11]*ep2[2]+.5000000000*e[11]*ep2[5]+.5000000000*e[11]*ep2[8]-.5000000000*e[11]*ep2[4]-.5000000000*e[11]*ep2[6]-.5000000000*e[11]*ep2[7]-.5000000000*e[11]*ep2[3]; + A[64]=e[5]*e[19]*e[13]+e[5]*e[10]*e[22]+e[8]*e[18]*e[15]+e[8]*e[9]*e[24]+e[8]*e[20]*e[17]+e[8]*e[11]*e[26]+e[8]*e[19]*e[16]+e[8]*e[10]*e[25]+e[2]*e[18]*e[9]+e[2]*e[19]*e[10]-1.*e[11]*e[21]*e[3]-1.*e[11]*e[22]*e[4]-1.*e[11]*e[25]*e[7]-1.*e[11]*e[24]*e[6]+e[14]*e[18]*e[3]+e[14]*e[0]*e[21]+e[14]*e[19]*e[4]+e[14]*e[1]*e[22]+e[14]*e[2]*e[23]-1.*e[20]*e[13]*e[4]-1.*e[20]*e[16]*e[7]-1.*e[20]*e[15]*e[6]-1.*e[20]*e[12]*e[3]+e[23]*e[9]*e[3]+e[23]*e[0]*e[12]+e[23]*e[10]*e[4]+e[23]*e[1]*e[13]+e[17]*e[18]*e[6]+e[17]*e[0]*e[24]+e[17]*e[19]*e[7]+e[17]*e[1]*e[25]+e[17]*e[2]*e[26]-1.*e[2]*e[24]*e[15]-1.*e[2]*e[25]*e[16]-1.*e[2]*e[21]*e[12]-1.*e[2]*e[22]*e[13]+e[26]*e[9]*e[6]+e[26]*e[0]*e[15]+e[26]*e[10]*e[7]+e[26]*e[1]*e[16]+e[11]*e[18]*e[0]+e[11]*e[19]*e[1]+3.*e[11]*e[20]*e[2]+e[20]*e[9]*e[0]+e[20]*e[10]*e[1]+e[5]*e[18]*e[12]+e[5]*e[9]*e[21]+e[5]*e[20]*e[14]+e[5]*e[11]*e[23]; + A[65]=e[32]*e[1]*e[4]+e[32]*e[0]*e[3]+e[8]*e[27]*e[6]+e[8]*e[0]*e[33]+e[8]*e[28]*e[7]+e[8]*e[1]*e[34]+e[35]*e[1]*e[7]+e[35]*e[0]*e[6]+e[2]*e[27]*e[0]+e[2]*e[28]*e[1]-1.*e[2]*e[34]*e[7]+e[2]*e[32]*e[5]-1.*e[2]*e[33]*e[6]-1.*e[2]*e[30]*e[3]+e[2]*e[35]*e[8]-1.*e[2]*e[31]*e[4]+e[5]*e[27]*e[3]+e[5]*e[0]*e[30]+e[5]*e[28]*e[4]+e[5]*e[1]*e[31]+1.500000000*e[29]*ep2[2]-.5000000000*e[29]*ep2[4]+.5000000000*e[29]*ep2[0]-.5000000000*e[29]*ep2[6]+.5000000000*e[29]*ep2[5]+.5000000000*e[29]*ep2[1]-.5000000000*e[29]*ep2[7]-.5000000000*e[29]*ep2[3]+.5000000000*e[29]*ep2[8]; + A[66]=e[5]*e[0]*e[3]+e[8]*e[1]*e[7]+e[8]*e[0]*e[6]+e[5]*e[1]*e[4]-.5000000000*e[2]*ep2[4]+.5000000000*ep3[2]+.5000000000*e[2]*ep2[1]-.5000000000*e[2]*ep2[3]+.5000000000*e[2]*ep2[0]+.5000000000*e[2]*ep2[8]+.5000000000*e[2]*ep2[5]-.5000000000*e[2]*ep2[6]-.5000000000*e[2]*ep2[7]; + A[67]=e[35]*e[9]*e[15]+e[35]*e[10]*e[16]-1.*e[11]*e[30]*e[12]-1.*e[11]*e[31]*e[13]-1.*e[11]*e[33]*e[15]-1.*e[11]*e[34]*e[16]+e[11]*e[27]*e[9]+e[11]*e[28]*e[10]+e[14]*e[27]*e[12]+e[14]*e[9]*e[30]+e[14]*e[11]*e[32]+e[14]*e[28]*e[13]+e[14]*e[10]*e[31]+e[32]*e[9]*e[12]+e[32]*e[10]*e[13]+e[17]*e[27]*e[15]+e[17]*e[9]*e[33]+e[17]*e[11]*e[35]+e[17]*e[28]*e[16]+e[17]*e[10]*e[34]+1.500000000*e[29]*ep2[11]-.5000000000*e[29]*ep2[16]+.5000000000*e[29]*ep2[9]-.5000000000*e[29]*ep2[12]-.5000000000*e[29]*ep2[15]+.5000000000*e[29]*ep2[17]+.5000000000*e[29]*ep2[10]+.5000000000*e[29]*ep2[14]-.5000000000*e[29]*ep2[13]; + A[68]=e[14]*e[9]*e[12]+e[17]*e[10]*e[16]+e[17]*e[9]*e[15]+.5000000000*ep3[11]+e[14]*e[10]*e[13]+.5000000000*e[11]*ep2[10]-.5000000000*e[11]*ep2[15]+.5000000000*e[11]*ep2[14]-.5000000000*e[11]*ep2[13]-.5000000000*e[11]*ep2[12]+.5000000000*e[11]*ep2[9]-.5000000000*e[11]*ep2[16]+.5000000000*e[11]*ep2[17]; + A[69]=e[20]*e[27]*e[18]+e[20]*e[28]*e[19]+e[23]*e[27]*e[21]+e[23]*e[18]*e[30]+e[23]*e[28]*e[22]+e[23]*e[19]*e[31]+e[23]*e[20]*e[32]+e[32]*e[19]*e[22]+e[32]*e[18]*e[21]+e[26]*e[27]*e[24]+e[26]*e[18]*e[33]+e[26]*e[28]*e[25]+e[26]*e[19]*e[34]+e[26]*e[20]*e[35]+e[35]*e[19]*e[25]+e[35]*e[18]*e[24]-1.*e[20]*e[33]*e[24]-1.*e[20]*e[30]*e[21]-1.*e[20]*e[31]*e[22]-1.*e[20]*e[34]*e[25]+.5000000000*e[29]*ep2[23]+.5000000000*e[29]*ep2[26]-.5000000000*e[29]*ep2[22]-.5000000000*e[29]*ep2[24]-.5000000000*e[29]*ep2[21]-.5000000000*e[29]*ep2[25]+1.500000000*e[29]*ep2[20]+.5000000000*e[29]*ep2[19]+.5000000000*e[29]*ep2[18]; + A[70]=.5000000000*e[20]*ep2[26]+.5000000000*e[20]*ep2[18]+.5000000000*ep3[20]+.5000000000*e[20]*ep2[19]+e[26]*e[18]*e[24]+.5000000000*e[20]*ep2[23]-.5000000000*e[20]*ep2[25]+e[23]*e[19]*e[22]-.5000000000*e[20]*ep2[24]-.5000000000*e[20]*ep2[21]-.5000000000*e[20]*ep2[22]+e[23]*e[18]*e[21]+e[26]*e[19]*e[25]; + A[71]=e[8]*e[28]*e[16]+e[8]*e[10]*e[34]+e[2]*e[27]*e[9]+3.*e[2]*e[29]*e[11]+e[2]*e[28]*e[10]+e[11]*e[27]*e[0]-1.*e[11]*e[34]*e[7]-1.*e[11]*e[33]*e[6]-1.*e[11]*e[30]*e[3]+e[11]*e[28]*e[1]-1.*e[11]*e[31]*e[4]+e[14]*e[27]*e[3]+e[14]*e[0]*e[30]+e[14]*e[28]*e[4]+e[14]*e[1]*e[31]+e[14]*e[2]*e[32]+e[29]*e[10]*e[1]-1.*e[29]*e[13]*e[4]-1.*e[29]*e[16]*e[7]-1.*e[29]*e[15]*e[6]+e[29]*e[9]*e[0]-1.*e[29]*e[12]*e[3]+e[32]*e[9]*e[3]+e[32]*e[0]*e[12]+e[32]*e[10]*e[4]+e[32]*e[1]*e[13]+e[17]*e[27]*e[6]+e[17]*e[0]*e[33]+e[17]*e[28]*e[7]+e[17]*e[1]*e[34]+e[17]*e[2]*e[35]-1.*e[2]*e[30]*e[12]-1.*e[2]*e[31]*e[13]-1.*e[2]*e[33]*e[15]-1.*e[2]*e[34]*e[16]+e[35]*e[9]*e[6]+e[35]*e[0]*e[15]+e[35]*e[10]*e[7]+e[35]*e[1]*e[16]+e[5]*e[27]*e[12]+e[5]*e[9]*e[30]+e[5]*e[29]*e[14]+e[5]*e[11]*e[32]+e[5]*e[28]*e[13]+e[5]*e[10]*e[31]+e[8]*e[27]*e[15]+e[8]*e[9]*e[33]+e[8]*e[29]*e[17]+e[8]*e[11]*e[35]; + A[91]=-1.*e[12]*e[34]*e[7]+e[12]*e[32]*e[5]-1.*e[12]*e[35]*e[8]-1.*e[12]*e[29]*e[2]-1.*e[12]*e[28]*e[1]+e[12]*e[31]*e[4]-1.*e[30]*e[11]*e[2]-1.*e[30]*e[10]*e[1]+e[30]*e[13]*e[4]-1.*e[30]*e[16]*e[7]+e[30]*e[14]*e[5]-1.*e[30]*e[17]*e[8]+e[15]*e[3]*e[33]+e[15]*e[31]*e[7]+e[15]*e[4]*e[34]+e[15]*e[32]*e[8]+e[15]*e[5]*e[35]+e[3]*e[27]*e[9]-1.*e[3]*e[28]*e[10]-1.*e[3]*e[34]*e[16]-1.*e[3]*e[35]*e[17]-1.*e[3]*e[29]*e[11]+e[33]*e[13]*e[7]+e[33]*e[4]*e[16]+e[33]*e[14]*e[8]+e[33]*e[5]*e[17]+e[9]*e[28]*e[4]+e[9]*e[1]*e[31]+e[9]*e[29]*e[5]+e[9]*e[2]*e[32]+e[27]*e[10]*e[4]+e[27]*e[1]*e[13]+e[27]*e[11]*e[5]+e[27]*e[2]*e[14]+3.*e[3]*e[30]*e[12]+e[3]*e[32]*e[14]+e[3]*e[31]*e[13]+e[6]*e[30]*e[15]+e[6]*e[12]*e[33]+e[6]*e[32]*e[17]+e[6]*e[14]*e[35]+e[6]*e[31]*e[16]+e[6]*e[13]*e[34]+e[0]*e[27]*e[12]+e[0]*e[9]*e[30]+e[0]*e[29]*e[14]+e[0]*e[11]*e[32]+e[0]*e[28]*e[13]+e[0]*e[10]*e[31]; + A[90]=.5000000000*e[21]*ep2[24]-.5000000000*e[21]*ep2[25]+.5000000000*e[21]*ep2[23]-.5000000000*e[21]*ep2[26]+.5000000000*ep2[18]*e[21]+.5000000000*e[21]*ep2[22]-.5000000000*e[21]*ep2[20]+e[24]*e[22]*e[25]+e[24]*e[23]*e[26]-.5000000000*e[21]*ep2[19]+e[18]*e[19]*e[22]+e[18]*e[20]*e[23]+.5000000000*ep3[21]; + A[89]=-.5000000000*e[30]*ep2[26]-.5000000000*e[30]*ep2[19]-.5000000000*e[30]*ep2[20]-.5000000000*e[30]*ep2[25]+.5000000000*ep2[18]*e[30]+1.500000000*e[30]*ep2[21]+.5000000000*e[30]*ep2[22]+.5000000000*e[30]*ep2[23]+.5000000000*e[30]*ep2[24]+e[18]*e[27]*e[21]+e[18]*e[28]*e[22]+e[18]*e[19]*e[31]+e[18]*e[29]*e[23]+e[18]*e[20]*e[32]+e[27]*e[19]*e[22]+e[27]*e[20]*e[23]+e[21]*e[31]*e[22]+e[21]*e[32]*e[23]+e[24]*e[21]*e[33]+e[24]*e[31]*e[25]+e[24]*e[22]*e[34]+e[24]*e[32]*e[26]+e[24]*e[23]*e[35]+e[33]*e[22]*e[25]+e[33]*e[23]*e[26]-1.*e[21]*e[29]*e[20]-1.*e[21]*e[35]*e[26]-1.*e[21]*e[28]*e[19]-1.*e[21]*e[34]*e[25]; + A[88]=.5000000000*e[12]*ep2[15]-.5000000000*e[12]*ep2[17]+e[15]*e[13]*e[16]-.5000000000*e[12]*ep2[10]+e[15]*e[14]*e[17]-.5000000000*e[12]*ep2[16]-.5000000000*e[12]*ep2[11]+e[9]*e[10]*e[13]+.5000000000*e[12]*ep2[13]+.5000000000*ep2[9]*e[12]+.5000000000*ep3[12]+e[9]*e[11]*e[14]+.5000000000*e[12]*ep2[14]; + A[95]=e[12]*e[13]*e[4]+e[12]*e[14]*e[5]+e[15]*e[12]*e[6]+e[15]*e[13]*e[7]+e[15]*e[4]*e[16]+e[15]*e[14]*e[8]+e[15]*e[5]*e[17]+e[6]*e[14]*e[17]+e[6]*e[13]*e[16]+e[0]*e[11]*e[14]+e[0]*e[9]*e[12]+e[0]*e[10]*e[13]+e[9]*e[10]*e[4]+e[9]*e[1]*e[13]+e[9]*e[11]*e[5]+e[9]*e[2]*e[14]-1.*e[12]*e[11]*e[2]-1.*e[12]*e[10]*e[1]-1.*e[12]*e[16]*e[7]-1.*e[12]*e[17]*e[8]+1.500000000*ep2[12]*e[3]+.5000000000*e[3]*ep2[15]-.5000000000*e[3]*ep2[16]+.5000000000*e[3]*ep2[9]-.5000000000*e[3]*ep2[11]-.5000000000*e[3]*ep2[17]-.5000000000*e[3]*ep2[10]+.5000000000*e[3]*ep2[14]+.5000000000*e[3]*ep2[13]; + A[94]=e[18]*e[11]*e[14]+e[18]*e[9]*e[12]+e[18]*e[10]*e[13]+e[12]*e[23]*e[14]+e[12]*e[22]*e[13]+e[15]*e[12]*e[24]+e[15]*e[23]*e[17]+e[15]*e[14]*e[26]+e[15]*e[22]*e[16]+e[15]*e[13]*e[25]+e[24]*e[14]*e[17]+e[24]*e[13]*e[16]-1.*e[12]*e[25]*e[16]-1.*e[12]*e[26]*e[17]-1.*e[12]*e[20]*e[11]-1.*e[12]*e[19]*e[10]+e[9]*e[20]*e[14]+e[9]*e[11]*e[23]+e[9]*e[19]*e[13]+e[9]*e[10]*e[22]+.5000000000*ep2[9]*e[21]-.5000000000*e[21]*ep2[16]-.5000000000*e[21]*ep2[11]-.5000000000*e[21]*ep2[17]-.5000000000*e[21]*ep2[10]+1.500000000*e[21]*ep2[12]+.5000000000*e[21]*ep2[14]+.5000000000*e[21]*ep2[13]+.5000000000*e[21]*ep2[15]; + A[93]=-1.*e[21]*e[35]*e[8]-1.*e[21]*e[29]*e[2]-1.*e[21]*e[28]*e[1]+e[21]*e[31]*e[4]-1.*e[30]*e[26]*e[8]-1.*e[30]*e[20]*e[2]-1.*e[30]*e[19]*e[1]+e[30]*e[22]*e[4]-1.*e[30]*e[25]*e[7]+e[30]*e[23]*e[5]+e[6]*e[31]*e[25]+e[6]*e[22]*e[34]+e[6]*e[32]*e[26]+e[6]*e[23]*e[35]+e[24]*e[30]*e[6]+e[24]*e[3]*e[33]+e[24]*e[31]*e[7]+e[24]*e[4]*e[34]+e[24]*e[32]*e[8]+e[24]*e[5]*e[35]+e[33]*e[21]*e[6]+e[33]*e[22]*e[7]+e[33]*e[4]*e[25]+e[33]*e[23]*e[8]+e[33]*e[5]*e[26]+e[0]*e[27]*e[21]+e[0]*e[18]*e[30]+e[0]*e[28]*e[22]+e[0]*e[19]*e[31]+e[0]*e[29]*e[23]+e[0]*e[20]*e[32]+e[18]*e[27]*e[3]+e[18]*e[28]*e[4]+e[18]*e[1]*e[31]+e[18]*e[29]*e[5]+e[18]*e[2]*e[32]+e[27]*e[19]*e[4]+e[27]*e[1]*e[22]+e[27]*e[20]*e[5]+e[27]*e[2]*e[23]+3.*e[3]*e[30]*e[21]+e[3]*e[31]*e[22]+e[3]*e[32]*e[23]-1.*e[3]*e[29]*e[20]-1.*e[3]*e[35]*e[26]-1.*e[3]*e[28]*e[19]-1.*e[3]*e[34]*e[25]-1.*e[21]*e[34]*e[7]+e[21]*e[32]*e[5]; + A[92]=e[18]*e[1]*e[4]+e[18]*e[0]*e[3]+e[18]*e[2]*e[5]+e[3]*e[22]*e[4]+e[3]*e[23]*e[5]+e[6]*e[3]*e[24]+e[6]*e[22]*e[7]+e[6]*e[4]*e[25]+e[6]*e[23]*e[8]+e[6]*e[5]*e[26]+e[24]*e[4]*e[7]+e[24]*e[5]*e[8]+e[0]*e[19]*e[4]+e[0]*e[1]*e[22]+e[0]*e[20]*e[5]+e[0]*e[2]*e[23]-1.*e[3]*e[26]*e[8]-1.*e[3]*e[20]*e[2]-1.*e[3]*e[19]*e[1]-1.*e[3]*e[25]*e[7]+.5000000000*e[21]*ep2[4]+.5000000000*e[21]*ep2[0]+.5000000000*e[21]*ep2[6]+.5000000000*e[21]*ep2[5]-.5000000000*e[21]*ep2[1]-.5000000000*e[21]*ep2[7]+1.500000000*e[21]*ep2[3]-.5000000000*e[21]*ep2[2]-.5000000000*e[21]*ep2[8]; + A[82]=.5000000000*ep2[27]*e[21]+1.500000000*e[21]*ep2[30]+.5000000000*e[21]*ep2[32]+.5000000000*e[21]*ep2[31]+.5000000000*e[21]*ep2[33]-.5000000000*e[21]*ep2[28]-.5000000000*e[21]*ep2[29]-.5000000000*e[21]*ep2[34]-.5000000000*e[21]*ep2[35]+e[18]*e[27]*e[30]+e[18]*e[29]*e[32]+e[18]*e[28]*e[31]+e[27]*e[28]*e[22]+e[27]*e[19]*e[31]+e[27]*e[29]*e[23]+e[27]*e[20]*e[32]+e[30]*e[31]*e[22]+e[30]*e[32]*e[23]+e[24]*e[30]*e[33]+e[24]*e[32]*e[35]+e[24]*e[31]*e[34]+e[33]*e[31]*e[25]+e[33]*e[22]*e[34]+e[33]*e[32]*e[26]+e[33]*e[23]*e[35]-1.*e[30]*e[29]*e[20]-1.*e[30]*e[35]*e[26]-1.*e[30]*e[28]*e[19]-1.*e[30]*e[34]*e[25]; + A[192]=-.5000000000*e[26]*ep2[4]-.5000000000*e[26]*ep2[0]+.5000000000*e[26]*ep2[6]+.5000000000*e[26]*ep2[5]-.5000000000*e[26]*ep2[1]+.5000000000*e[26]*ep2[7]-.5000000000*e[26]*ep2[3]+.5000000000*e[26]*ep2[2]+1.500000000*e[26]*ep2[8]+e[20]*e[0]*e[6]+e[20]*e[2]*e[8]+e[5]*e[21]*e[6]+e[5]*e[3]*e[24]+e[5]*e[22]*e[7]+e[5]*e[4]*e[25]+e[5]*e[23]*e[8]+e[23]*e[4]*e[7]+e[23]*e[3]*e[6]+e[8]*e[24]*e[6]+e[8]*e[25]*e[7]+e[2]*e[18]*e[6]+e[2]*e[0]*e[24]+e[2]*e[19]*e[7]+e[2]*e[1]*e[25]-1.*e[8]*e[21]*e[3]-1.*e[8]*e[19]*e[1]-1.*e[8]*e[22]*e[4]-1.*e[8]*e[18]*e[0]+e[20]*e[1]*e[7]; + A[83]=e[9]*e[27]*e[30]+e[9]*e[29]*e[32]+e[9]*e[28]*e[31]+e[33]*e[30]*e[15]+e[33]*e[32]*e[17]+e[33]*e[14]*e[35]+e[33]*e[31]*e[16]+e[33]*e[13]*e[34]+e[27]*e[29]*e[14]+e[27]*e[11]*e[32]+e[27]*e[28]*e[13]+e[27]*e[10]*e[31]-1.*e[30]*e[28]*e[10]+e[30]*e[31]*e[13]+e[30]*e[32]*e[14]-1.*e[30]*e[34]*e[16]-1.*e[30]*e[35]*e[17]-1.*e[30]*e[29]*e[11]+e[15]*e[32]*e[35]+e[15]*e[31]*e[34]-.5000000000*e[12]*ep2[34]-.5000000000*e[12]*ep2[35]+.5000000000*e[12]*ep2[27]+.5000000000*e[12]*ep2[32]-.5000000000*e[12]*ep2[28]-.5000000000*e[12]*ep2[29]+.5000000000*e[12]*ep2[31]+.5000000000*e[12]*ep2[33]+1.500000000*e[12]*ep2[30]; + A[193]=e[23]*e[30]*e[6]+e[23]*e[3]*e[33]+e[23]*e[31]*e[7]+e[23]*e[4]*e[34]+e[32]*e[21]*e[6]+e[32]*e[3]*e[24]+e[32]*e[22]*e[7]+e[32]*e[4]*e[25]+e[26]*e[33]*e[6]+e[26]*e[34]*e[7]+3.*e[26]*e[35]*e[8]+e[35]*e[24]*e[6]+e[35]*e[25]*e[7]+e[2]*e[27]*e[24]+e[2]*e[18]*e[33]+e[2]*e[28]*e[25]+e[2]*e[19]*e[34]+e[2]*e[29]*e[26]+e[2]*e[20]*e[35]+e[20]*e[27]*e[6]+e[20]*e[0]*e[33]+e[20]*e[28]*e[7]+e[20]*e[1]*e[34]+e[20]*e[29]*e[8]+e[29]*e[18]*e[6]+e[29]*e[0]*e[24]+e[29]*e[19]*e[7]+e[29]*e[1]*e[25]+e[5]*e[30]*e[24]+e[5]*e[21]*e[33]+e[5]*e[31]*e[25]+e[5]*e[22]*e[34]+e[5]*e[32]*e[26]+e[5]*e[23]*e[35]-1.*e[8]*e[27]*e[18]+e[8]*e[33]*e[24]-1.*e[8]*e[30]*e[21]-1.*e[8]*e[31]*e[22]+e[8]*e[32]*e[23]-1.*e[8]*e[28]*e[19]+e[8]*e[34]*e[25]-1.*e[26]*e[27]*e[0]-1.*e[26]*e[30]*e[3]-1.*e[26]*e[28]*e[1]-1.*e[26]*e[31]*e[4]-1.*e[35]*e[21]*e[3]-1.*e[35]*e[19]*e[1]-1.*e[35]*e[22]*e[4]-1.*e[35]*e[18]*e[0]; + A[80]=e[27]*e[29]*e[32]+e[27]*e[28]*e[31]+e[33]*e[32]*e[35]+e[33]*e[31]*e[34]+.5000000000*ep3[30]-.5000000000*e[30]*ep2[28]-.5000000000*e[30]*ep2[29]-.5000000000*e[30]*ep2[34]+.5000000000*e[30]*ep2[33]+.5000000000*ep2[27]*e[30]+.5000000000*e[30]*ep2[32]+.5000000000*e[30]*ep2[31]-.5000000000*e[30]*ep2[35]; + A[194]=.5000000000*ep2[14]*e[26]+1.500000000*e[26]*ep2[17]+.5000000000*e[26]*ep2[15]+.5000000000*e[26]*ep2[16]+.5000000000*ep2[11]*e[26]-.5000000000*e[26]*ep2[9]-.5000000000*e[26]*ep2[12]-.5000000000*e[26]*ep2[10]-.5000000000*e[26]*ep2[13]+e[20]*e[11]*e[17]+e[20]*e[9]*e[15]+e[20]*e[10]*e[16]+e[14]*e[21]*e[15]+e[14]*e[12]*e[24]+e[14]*e[23]*e[17]+e[14]*e[22]*e[16]+e[14]*e[13]*e[25]+e[23]*e[12]*e[15]+e[23]*e[13]*e[16]+e[17]*e[24]*e[15]+e[17]*e[25]*e[16]-1.*e[17]*e[18]*e[9]-1.*e[17]*e[21]*e[12]-1.*e[17]*e[19]*e[10]-1.*e[17]*e[22]*e[13]+e[11]*e[18]*e[15]+e[11]*e[9]*e[24]+e[11]*e[19]*e[16]+e[11]*e[10]*e[25]; + A[81]=e[0]*e[27]*e[30]+e[0]*e[29]*e[32]+e[0]*e[28]*e[31]+e[30]*e[31]*e[4]+e[30]*e[32]*e[5]+e[6]*e[30]*e[33]+e[6]*e[32]*e[35]+e[6]*e[31]*e[34]+e[27]*e[28]*e[4]+e[27]*e[1]*e[31]+e[27]*e[29]*e[5]+e[27]*e[2]*e[32]+e[33]*e[31]*e[7]+e[33]*e[4]*e[34]+e[33]*e[32]*e[8]+e[33]*e[5]*e[35]-1.*e[30]*e[34]*e[7]-1.*e[30]*e[35]*e[8]-1.*e[30]*e[29]*e[2]-1.*e[30]*e[28]*e[1]+1.500000000*e[3]*ep2[30]+.5000000000*e[3]*ep2[32]+.5000000000*e[3]*ep2[31]+.5000000000*e[3]*ep2[27]-.5000000000*e[3]*ep2[28]-.5000000000*e[3]*ep2[29]+.5000000000*e[3]*ep2[33]-.5000000000*e[3]*ep2[34]-.5000000000*e[3]*ep2[35]; + A[195]=.5000000000*ep2[14]*e[8]+1.500000000*ep2[17]*e[8]+.5000000000*e[8]*ep2[15]+.5000000000*e[8]*ep2[16]-.5000000000*e[8]*ep2[9]+.5000000000*e[8]*ep2[11]-.5000000000*e[8]*ep2[12]-.5000000000*e[8]*ep2[10]-.5000000000*e[8]*ep2[13]+e[14]*e[12]*e[6]+e[14]*e[3]*e[15]+e[14]*e[13]*e[7]+e[14]*e[4]*e[16]+e[14]*e[5]*e[17]+e[17]*e[15]*e[6]+e[17]*e[16]*e[7]+e[2]*e[11]*e[17]+e[2]*e[9]*e[15]+e[2]*e[10]*e[16]+e[5]*e[12]*e[15]+e[5]*e[13]*e[16]+e[11]*e[9]*e[6]+e[11]*e[0]*e[15]+e[11]*e[10]*e[7]+e[11]*e[1]*e[16]-1.*e[17]*e[10]*e[1]-1.*e[17]*e[13]*e[4]-1.*e[17]*e[9]*e[0]-1.*e[17]*e[12]*e[3]; + A[86]=-.5000000000*e[3]*ep2[1]-.5000000000*e[3]*ep2[7]+.5000000000*ep3[3]-.5000000000*e[3]*ep2[8]+e[0]*e[2]*e[5]+.5000000000*e[3]*ep2[6]+.5000000000*e[3]*ep2[4]-.5000000000*e[3]*ep2[2]+e[0]*e[1]*e[4]+e[6]*e[4]*e[7]+.5000000000*ep2[0]*e[3]+.5000000000*e[3]*ep2[5]+e[6]*e[5]*e[8]; + A[196]=.5000000000*ep2[23]*e[17]+1.500000000*ep2[26]*e[17]+.5000000000*e[17]*ep2[25]+.5000000000*e[17]*ep2[24]-.5000000000*e[17]*ep2[18]-.5000000000*e[17]*ep2[19]+.5000000000*e[17]*ep2[20]-.5000000000*e[17]*ep2[22]-.5000000000*e[17]*ep2[21]+e[23]*e[21]*e[15]+e[23]*e[12]*e[24]+e[23]*e[14]*e[26]+e[23]*e[22]*e[16]+e[23]*e[13]*e[25]+e[26]*e[24]*e[15]+e[26]*e[25]*e[16]+e[11]*e[19]*e[25]+e[11]*e[18]*e[24]+e[11]*e[20]*e[26]+e[14]*e[22]*e[25]+e[14]*e[21]*e[24]+e[20]*e[18]*e[15]+e[20]*e[9]*e[24]+e[20]*e[19]*e[16]+e[20]*e[10]*e[25]-1.*e[26]*e[18]*e[9]-1.*e[26]*e[21]*e[12]-1.*e[26]*e[19]*e[10]-1.*e[26]*e[22]*e[13]; + A[87]=-1.*e[12]*e[34]*e[16]-1.*e[12]*e[35]*e[17]-1.*e[12]*e[29]*e[11]+e[9]*e[27]*e[12]+e[9]*e[29]*e[14]+e[9]*e[11]*e[32]+e[9]*e[28]*e[13]+e[9]*e[10]*e[31]+e[27]*e[11]*e[14]+e[27]*e[10]*e[13]+e[12]*e[32]*e[14]+e[12]*e[31]*e[13]+e[15]*e[12]*e[33]+e[15]*e[32]*e[17]+e[15]*e[14]*e[35]+e[15]*e[31]*e[16]+e[15]*e[13]*e[34]+e[33]*e[14]*e[17]+e[33]*e[13]*e[16]-1.*e[12]*e[28]*e[10]+.5000000000*ep2[9]*e[30]-.5000000000*e[30]*ep2[16]-.5000000000*e[30]*ep2[11]+1.500000000*e[30]*ep2[12]+.5000000000*e[30]*ep2[15]-.5000000000*e[30]*ep2[17]-.5000000000*e[30]*ep2[10]+.5000000000*e[30]*ep2[14]+.5000000000*e[30]*ep2[13]; + A[197]=e[32]*e[22]*e[16]+e[32]*e[13]*e[25]-1.*e[17]*e[27]*e[18]+e[17]*e[33]*e[24]-1.*e[17]*e[30]*e[21]+e[17]*e[29]*e[20]+3.*e[17]*e[35]*e[26]-1.*e[17]*e[31]*e[22]-1.*e[17]*e[28]*e[19]+e[17]*e[34]*e[25]+e[20]*e[27]*e[15]+e[20]*e[9]*e[33]+e[20]*e[28]*e[16]+e[20]*e[10]*e[34]+e[29]*e[18]*e[15]+e[29]*e[9]*e[24]+e[29]*e[19]*e[16]+e[29]*e[10]*e[25]-1.*e[26]*e[27]*e[9]-1.*e[26]*e[30]*e[12]-1.*e[26]*e[28]*e[10]-1.*e[26]*e[31]*e[13]+e[26]*e[33]*e[15]+e[26]*e[34]*e[16]+e[35]*e[24]*e[15]+e[35]*e[25]*e[16]-1.*e[35]*e[18]*e[9]-1.*e[35]*e[21]*e[12]-1.*e[35]*e[19]*e[10]-1.*e[35]*e[22]*e[13]+e[14]*e[30]*e[24]+e[14]*e[21]*e[33]+e[14]*e[31]*e[25]+e[14]*e[22]*e[34]+e[14]*e[32]*e[26]+e[14]*e[23]*e[35]+e[11]*e[27]*e[24]+e[11]*e[18]*e[33]+e[11]*e[28]*e[25]+e[11]*e[19]*e[34]+e[11]*e[29]*e[26]+e[11]*e[20]*e[35]+e[23]*e[30]*e[15]+e[23]*e[12]*e[33]+e[23]*e[32]*e[17]+e[23]*e[31]*e[16]+e[23]*e[13]*e[34]+e[32]*e[21]*e[15]+e[32]*e[12]*e[24]; + A[84]=e[6]*e[23]*e[17]+e[6]*e[14]*e[26]+e[6]*e[22]*e[16]+e[6]*e[13]*e[25]+e[0]*e[20]*e[14]+e[0]*e[11]*e[23]+e[0]*e[19]*e[13]+e[0]*e[10]*e[22]-1.*e[12]*e[26]*e[8]-1.*e[12]*e[20]*e[2]-1.*e[12]*e[19]*e[1]+e[12]*e[22]*e[4]-1.*e[12]*e[25]*e[7]+e[12]*e[23]*e[5]-1.*e[21]*e[11]*e[2]-1.*e[21]*e[10]*e[1]+e[21]*e[13]*e[4]-1.*e[21]*e[16]*e[7]+e[21]*e[14]*e[5]-1.*e[21]*e[17]*e[8]+e[15]*e[3]*e[24]+e[15]*e[22]*e[7]+e[15]*e[4]*e[25]+e[15]*e[23]*e[8]+e[15]*e[5]*e[26]-1.*e[3]*e[25]*e[16]-1.*e[3]*e[26]*e[17]-1.*e[3]*e[20]*e[11]-1.*e[3]*e[19]*e[10]+e[24]*e[13]*e[7]+e[24]*e[4]*e[16]+e[24]*e[14]*e[8]+e[24]*e[5]*e[17]+e[9]*e[18]*e[3]+e[9]*e[0]*e[21]+e[9]*e[19]*e[4]+e[9]*e[1]*e[22]+e[9]*e[20]*e[5]+e[9]*e[2]*e[23]+e[18]*e[0]*e[12]+e[18]*e[10]*e[4]+e[18]*e[1]*e[13]+e[18]*e[11]*e[5]+e[18]*e[2]*e[14]+3.*e[3]*e[21]*e[12]+e[3]*e[23]*e[14]+e[3]*e[22]*e[13]+e[6]*e[21]*e[15]+e[6]*e[12]*e[24]; + A[198]=.5000000000*ep2[5]*e[17]+1.500000000*e[17]*ep2[8]+.5000000000*e[17]*ep2[7]+.5000000000*e[17]*ep2[6]+.5000000000*ep2[2]*e[17]-.5000000000*e[17]*ep2[4]-.5000000000*e[17]*ep2[0]-.5000000000*e[17]*ep2[1]-.5000000000*e[17]*ep2[3]+e[11]*e[1]*e[7]+e[11]*e[0]*e[6]+e[11]*e[2]*e[8]+e[5]*e[12]*e[6]+e[5]*e[3]*e[15]+e[5]*e[13]*e[7]+e[5]*e[4]*e[16]+e[5]*e[14]*e[8]+e[14]*e[4]*e[7]+e[14]*e[3]*e[6]+e[8]*e[15]*e[6]+e[8]*e[16]*e[7]-1.*e[8]*e[10]*e[1]-1.*e[8]*e[13]*e[4]-1.*e[8]*e[9]*e[0]-1.*e[8]*e[12]*e[3]+e[2]*e[9]*e[6]+e[2]*e[0]*e[15]+e[2]*e[10]*e[7]+e[2]*e[1]*e[16]; + A[85]=e[6]*e[4]*e[34]+e[6]*e[32]*e[8]+e[6]*e[5]*e[35]+e[33]*e[4]*e[7]+e[33]*e[5]*e[8]+e[0]*e[27]*e[3]+e[0]*e[28]*e[4]+e[0]*e[1]*e[31]+e[0]*e[29]*e[5]+e[0]*e[2]*e[32]-1.*e[3]*e[34]*e[7]+e[3]*e[32]*e[5]+e[3]*e[33]*e[6]-1.*e[3]*e[35]*e[8]-1.*e[3]*e[29]*e[2]-1.*e[3]*e[28]*e[1]+e[3]*e[31]*e[4]+e[27]*e[1]*e[4]+e[27]*e[2]*e[5]+e[6]*e[31]*e[7]+.5000000000*e[30]*ep2[4]+.5000000000*e[30]*ep2[6]+.5000000000*e[30]*ep2[5]-.5000000000*e[30]*ep2[1]-.5000000000*e[30]*ep2[7]-.5000000000*e[30]*ep2[2]-.5000000000*e[30]*ep2[8]+.5000000000*ep2[0]*e[30]+1.500000000*e[30]*ep2[3]; + A[199]=.5000000000*ep2[23]*e[8]+1.500000000*ep2[26]*e[8]-.5000000000*e[8]*ep2[18]-.5000000000*e[8]*ep2[19]-.5000000000*e[8]*ep2[22]+.5000000000*e[8]*ep2[24]-.5000000000*e[8]*ep2[21]+.5000000000*e[8]*ep2[25]+.5000000000*ep2[20]*e[8]+e[20]*e[18]*e[6]+e[20]*e[0]*e[24]+e[20]*e[19]*e[7]+e[20]*e[1]*e[25]+e[20]*e[2]*e[26]+e[23]*e[21]*e[6]+e[23]*e[3]*e[24]+e[23]*e[22]*e[7]+e[23]*e[4]*e[25]+e[23]*e[5]*e[26]-1.*e[26]*e[21]*e[3]-1.*e[26]*e[19]*e[1]-1.*e[26]*e[22]*e[4]-1.*e[26]*e[18]*e[0]+e[26]*e[25]*e[7]+e[26]*e[24]*e[6]+e[2]*e[19]*e[25]+e[2]*e[18]*e[24]+e[5]*e[22]*e[25]+e[5]*e[21]*e[24]; + A[109]=e[19]*e[27]*e[21]+e[19]*e[18]*e[30]+e[19]*e[28]*e[22]+e[19]*e[29]*e[23]+e[19]*e[20]*e[32]+e[28]*e[18]*e[21]+e[28]*e[20]*e[23]+e[22]*e[30]*e[21]+e[22]*e[32]*e[23]+e[25]*e[30]*e[24]+e[25]*e[21]*e[33]+e[25]*e[22]*e[34]+e[25]*e[32]*e[26]+e[25]*e[23]*e[35]+e[34]*e[21]*e[24]+e[34]*e[23]*e[26]-1.*e[22]*e[27]*e[18]-1.*e[22]*e[33]*e[24]-1.*e[22]*e[29]*e[20]-1.*e[22]*e[35]*e[26]+.5000000000*ep2[19]*e[31]+1.500000000*e[31]*ep2[22]+.5000000000*e[31]*ep2[21]+.5000000000*e[31]*ep2[23]+.5000000000*e[31]*ep2[25]-.5000000000*e[31]*ep2[26]-.5000000000*e[31]*ep2[18]-.5000000000*e[31]*ep2[20]-.5000000000*e[31]*ep2[24]; + A[108]=-.5000000000*e[13]*ep2[15]+.5000000000*e[13]*ep2[16]+.5000000000*e[13]*ep2[12]+e[16]*e[12]*e[15]+.5000000000*ep3[13]+e[10]*e[11]*e[14]+.5000000000*e[13]*ep2[14]-.5000000000*e[13]*ep2[17]-.5000000000*e[13]*ep2[11]-.5000000000*e[13]*ep2[9]+.5000000000*ep2[10]*e[13]+e[10]*e[9]*e[12]+e[16]*e[14]*e[17]; + A[111]=-1.*e[13]*e[29]*e[2]-1.*e[31]*e[11]*e[2]-1.*e[31]*e[15]*e[6]-1.*e[31]*e[9]*e[0]+e[31]*e[14]*e[5]+e[31]*e[12]*e[3]-1.*e[31]*e[17]*e[8]+e[16]*e[30]*e[6]+e[16]*e[3]*e[33]+e[16]*e[4]*e[34]+e[16]*e[32]*e[8]+e[16]*e[5]*e[35]-1.*e[4]*e[27]*e[9]+e[4]*e[28]*e[10]-1.*e[4]*e[33]*e[15]-1.*e[4]*e[35]*e[17]-1.*e[4]*e[29]*e[11]+e[34]*e[12]*e[6]+e[34]*e[3]*e[15]+e[34]*e[14]*e[8]+e[34]*e[5]*e[17]+e[10]*e[27]*e[3]+e[10]*e[0]*e[30]+e[10]*e[29]*e[5]+e[10]*e[2]*e[32]+e[28]*e[9]*e[3]+e[28]*e[0]*e[12]+e[28]*e[11]*e[5]+e[28]*e[2]*e[14]+e[4]*e[30]*e[12]+e[4]*e[32]*e[14]+3.*e[4]*e[31]*e[13]+e[7]*e[30]*e[15]+e[7]*e[12]*e[33]+e[7]*e[32]*e[17]+e[7]*e[14]*e[35]+e[7]*e[31]*e[16]+e[7]*e[13]*e[34]+e[1]*e[27]*e[12]+e[1]*e[9]*e[30]+e[1]*e[29]*e[14]+e[1]*e[11]*e[32]+e[1]*e[28]*e[13]+e[1]*e[10]*e[31]-1.*e[13]*e[27]*e[0]+e[13]*e[32]*e[5]-1.*e[13]*e[33]*e[6]+e[13]*e[30]*e[3]-1.*e[13]*e[35]*e[8]; + A[110]=e[25]*e[23]*e[26]+e[19]*e[20]*e[23]+e[19]*e[18]*e[21]+e[25]*e[21]*e[24]+.5000000000*ep3[22]+.5000000000*e[22]*ep2[23]+.5000000000*ep2[19]*e[22]-.5000000000*e[22]*ep2[18]-.5000000000*e[22]*ep2[24]+.5000000000*e[22]*ep2[21]+.5000000000*e[22]*ep2[25]-.5000000000*e[22]*ep2[20]-.5000000000*e[22]*ep2[26]; + A[105]=e[34]*e[5]*e[8]+e[1]*e[27]*e[3]+e[1]*e[0]*e[30]+e[1]*e[28]*e[4]+e[1]*e[29]*e[5]+e[1]*e[2]*e[32]-1.*e[4]*e[27]*e[0]+e[4]*e[34]*e[7]+e[4]*e[32]*e[5]-1.*e[4]*e[33]*e[6]+e[4]*e[30]*e[3]-1.*e[4]*e[35]*e[8]-1.*e[4]*e[29]*e[2]+e[28]*e[0]*e[3]+e[28]*e[2]*e[5]+e[7]*e[30]*e[6]+e[7]*e[3]*e[33]+e[7]*e[32]*e[8]+e[7]*e[5]*e[35]+e[34]*e[3]*e[6]+.5000000000*ep2[1]*e[31]+1.500000000*e[31]*ep2[4]-.5000000000*e[31]*ep2[0]-.5000000000*e[31]*ep2[6]+.5000000000*e[31]*ep2[5]+.5000000000*e[31]*ep2[7]+.5000000000*e[31]*ep2[3]-.5000000000*e[31]*ep2[2]-.5000000000*e[31]*ep2[8]; + A[104]=e[1]*e[20]*e[14]+e[1]*e[11]*e[23]+e[13]*e[21]*e[3]-1.*e[13]*e[26]*e[8]-1.*e[13]*e[20]*e[2]-1.*e[13]*e[18]*e[0]+e[13]*e[23]*e[5]-1.*e[13]*e[24]*e[6]-1.*e[22]*e[11]*e[2]-1.*e[22]*e[15]*e[6]-1.*e[22]*e[9]*e[0]+e[22]*e[14]*e[5]+e[22]*e[12]*e[3]-1.*e[22]*e[17]*e[8]+e[16]*e[21]*e[6]+e[16]*e[3]*e[24]+e[16]*e[4]*e[25]+e[16]*e[23]*e[8]+e[16]*e[5]*e[26]-1.*e[4]*e[24]*e[15]-1.*e[4]*e[26]*e[17]-1.*e[4]*e[20]*e[11]-1.*e[4]*e[18]*e[9]+e[25]*e[12]*e[6]+e[25]*e[3]*e[15]+e[25]*e[14]*e[8]+e[25]*e[5]*e[17]+e[10]*e[18]*e[3]+e[10]*e[0]*e[21]+e[10]*e[19]*e[4]+e[10]*e[1]*e[22]+e[10]*e[20]*e[5]+e[10]*e[2]*e[23]+e[19]*e[9]*e[3]+e[19]*e[0]*e[12]+e[19]*e[1]*e[13]+e[19]*e[11]*e[5]+e[19]*e[2]*e[14]+e[4]*e[21]*e[12]+e[4]*e[23]*e[14]+3.*e[4]*e[22]*e[13]+e[7]*e[21]*e[15]+e[7]*e[12]*e[24]+e[7]*e[23]*e[17]+e[7]*e[14]*e[26]+e[7]*e[22]*e[16]+e[7]*e[13]*e[25]+e[1]*e[18]*e[12]+e[1]*e[9]*e[21]; + A[107]=e[10]*e[27]*e[12]+e[10]*e[9]*e[30]+e[10]*e[29]*e[14]+e[10]*e[11]*e[32]+e[10]*e[28]*e[13]+e[28]*e[11]*e[14]+e[28]*e[9]*e[12]+e[13]*e[30]*e[12]+e[13]*e[32]*e[14]+e[16]*e[30]*e[15]+e[16]*e[12]*e[33]+e[16]*e[32]*e[17]+e[16]*e[14]*e[35]+e[16]*e[13]*e[34]+e[34]*e[14]*e[17]+e[34]*e[12]*e[15]-1.*e[13]*e[27]*e[9]-1.*e[13]*e[33]*e[15]-1.*e[13]*e[35]*e[17]-1.*e[13]*e[29]*e[11]+.5000000000*ep2[10]*e[31]+.5000000000*e[31]*ep2[16]-.5000000000*e[31]*ep2[9]-.5000000000*e[31]*ep2[11]+.5000000000*e[31]*ep2[12]-.5000000000*e[31]*ep2[15]-.5000000000*e[31]*ep2[17]+.5000000000*e[31]*ep2[14]+1.500000000*e[31]*ep2[13]; + A[106]=-.5000000000*e[4]*ep2[6]-.5000000000*e[4]*ep2[0]+e[1]*e[2]*e[5]+.5000000000*e[4]*ep2[7]+e[1]*e[0]*e[3]+e[7]*e[5]*e[8]-.5000000000*e[4]*ep2[8]+.5000000000*e[4]*ep2[3]+.5000000000*e[4]*ep2[5]+e[7]*e[3]*e[6]-.5000000000*e[4]*ep2[2]+.5000000000*ep3[4]+.5000000000*ep2[1]*e[4]; + A[100]=e[34]*e[32]*e[35]-.5000000000*e[31]*ep2[35]+.5000000000*e[31]*ep2[34]+.5000000000*ep2[28]*e[31]+.5000000000*ep3[31]+.5000000000*e[31]*ep2[32]+e[34]*e[30]*e[33]-.5000000000*e[31]*ep2[27]+.5000000000*e[31]*ep2[30]-.5000000000*e[31]*ep2[33]-.5000000000*e[31]*ep2[29]+e[28]*e[29]*e[32]+e[28]*e[27]*e[30]; + A[101]=e[1]*e[27]*e[30]+e[1]*e[29]*e[32]+e[1]*e[28]*e[31]+e[31]*e[30]*e[3]+e[31]*e[32]*e[5]+e[7]*e[30]*e[33]+e[7]*e[32]*e[35]+e[7]*e[31]*e[34]+e[28]*e[27]*e[3]+e[28]*e[0]*e[30]+e[28]*e[29]*e[5]+e[28]*e[2]*e[32]+e[34]*e[30]*e[6]+e[34]*e[3]*e[33]+e[34]*e[32]*e[8]+e[34]*e[5]*e[35]-1.*e[31]*e[27]*e[0]-1.*e[31]*e[33]*e[6]-1.*e[31]*e[35]*e[8]-1.*e[31]*e[29]*e[2]+.5000000000*e[4]*ep2[30]+.5000000000*e[4]*ep2[32]+1.500000000*e[4]*ep2[31]-.5000000000*e[4]*ep2[27]+.5000000000*e[4]*ep2[28]-.5000000000*e[4]*ep2[29]-.5000000000*e[4]*ep2[33]+.5000000000*e[4]*ep2[34]-.5000000000*e[4]*ep2[35]; + A[102]=.5000000000*e[22]*ep2[30]+.5000000000*e[22]*ep2[32]+1.500000000*e[22]*ep2[31]+.5000000000*e[22]*ep2[34]-.5000000000*e[22]*ep2[27]-.5000000000*e[22]*ep2[29]-.5000000000*e[22]*ep2[33]-.5000000000*e[22]*ep2[35]+e[28]*e[18]*e[30]+e[28]*e[29]*e[23]+e[28]*e[20]*e[32]+e[31]*e[30]*e[21]+e[31]*e[32]*e[23]+e[25]*e[30]*e[33]+e[25]*e[32]*e[35]+e[25]*e[31]*e[34]+e[34]*e[30]*e[24]+e[34]*e[21]*e[33]+e[34]*e[32]*e[26]+e[34]*e[23]*e[35]-1.*e[31]*e[27]*e[18]-1.*e[31]*e[33]*e[24]-1.*e[31]*e[29]*e[20]-1.*e[31]*e[35]*e[26]+e[19]*e[27]*e[30]+e[19]*e[29]*e[32]+e[19]*e[28]*e[31]+e[28]*e[27]*e[21]+.5000000000*ep2[28]*e[22]; + A[103]=e[16]*e[30]*e[33]+e[16]*e[32]*e[35]+e[10]*e[27]*e[30]+e[10]*e[29]*e[32]+e[10]*e[28]*e[31]+e[34]*e[30]*e[15]+e[34]*e[12]*e[33]+e[34]*e[32]*e[17]+e[34]*e[14]*e[35]+e[34]*e[31]*e[16]+e[28]*e[27]*e[12]+e[28]*e[9]*e[30]+e[28]*e[29]*e[14]+e[28]*e[11]*e[32]-1.*e[31]*e[27]*e[9]+e[31]*e[30]*e[12]+e[31]*e[32]*e[14]-1.*e[31]*e[33]*e[15]-1.*e[31]*e[35]*e[17]-1.*e[31]*e[29]*e[11]-.5000000000*e[13]*ep2[27]+.5000000000*e[13]*ep2[32]+.5000000000*e[13]*ep2[28]-.5000000000*e[13]*ep2[29]+1.500000000*e[13]*ep2[31]-.5000000000*e[13]*ep2[33]+.5000000000*e[13]*ep2[30]+.5000000000*e[13]*ep2[34]-.5000000000*e[13]*ep2[35]; + A[96]=e[21]*e[23]*e[14]+e[21]*e[22]*e[13]+e[24]*e[21]*e[15]+e[24]*e[23]*e[17]+e[24]*e[14]*e[26]+e[24]*e[22]*e[16]+e[24]*e[13]*e[25]+e[15]*e[22]*e[25]+e[15]*e[23]*e[26]+e[9]*e[19]*e[22]+e[9]*e[18]*e[21]+e[9]*e[20]*e[23]+e[18]*e[20]*e[14]+e[18]*e[11]*e[23]+e[18]*e[19]*e[13]+e[18]*e[10]*e[22]-1.*e[21]*e[25]*e[16]-1.*e[21]*e[26]*e[17]-1.*e[21]*e[20]*e[11]-1.*e[21]*e[19]*e[10]+1.500000000*ep2[21]*e[12]+.5000000000*e[12]*ep2[24]-.5000000000*e[12]*ep2[26]+.5000000000*e[12]*ep2[18]+.5000000000*e[12]*ep2[23]-.5000000000*e[12]*ep2[19]-.5000000000*e[12]*ep2[20]+.5000000000*e[12]*ep2[22]-.5000000000*e[12]*ep2[25]; + A[97]=-1.*e[12]*e[29]*e[20]-1.*e[12]*e[35]*e[26]-1.*e[12]*e[28]*e[19]-1.*e[12]*e[34]*e[25]+e[18]*e[29]*e[14]+e[18]*e[11]*e[32]+e[18]*e[28]*e[13]+e[18]*e[10]*e[31]+e[27]*e[20]*e[14]+e[27]*e[11]*e[23]+e[27]*e[19]*e[13]+e[27]*e[10]*e[22]+e[15]*e[30]*e[24]+e[15]*e[21]*e[33]+e[15]*e[31]*e[25]+e[15]*e[22]*e[34]+e[15]*e[32]*e[26]+e[15]*e[23]*e[35]-1.*e[21]*e[28]*e[10]-1.*e[21]*e[34]*e[16]-1.*e[21]*e[35]*e[17]-1.*e[21]*e[29]*e[11]-1.*e[30]*e[25]*e[16]-1.*e[30]*e[26]*e[17]-1.*e[30]*e[20]*e[11]-1.*e[30]*e[19]*e[10]+e[24]*e[32]*e[17]+e[24]*e[14]*e[35]+e[24]*e[31]*e[16]+e[24]*e[13]*e[34]+e[33]*e[23]*e[17]+e[33]*e[14]*e[26]+e[33]*e[22]*e[16]+e[33]*e[13]*e[25]+3.*e[12]*e[30]*e[21]+e[12]*e[31]*e[22]+e[12]*e[32]*e[23]+e[9]*e[27]*e[21]+e[9]*e[18]*e[30]+e[9]*e[28]*e[22]+e[9]*e[19]*e[31]+e[9]*e[29]*e[23]+e[9]*e[20]*e[32]+e[21]*e[32]*e[14]+e[21]*e[31]*e[13]+e[30]*e[23]*e[14]+e[30]*e[22]*e[13]+e[12]*e[27]*e[18]+e[12]*e[33]*e[24]; + A[98]=e[0]*e[11]*e[5]+e[0]*e[2]*e[14]+e[9]*e[1]*e[4]+e[9]*e[0]*e[3]+e[9]*e[2]*e[5]+e[3]*e[13]*e[4]+e[3]*e[14]*e[5]+e[6]*e[3]*e[15]+e[6]*e[13]*e[7]+e[6]*e[4]*e[16]+e[6]*e[14]*e[8]+e[6]*e[5]*e[17]+e[15]*e[4]*e[7]+e[15]*e[5]*e[8]-1.*e[3]*e[11]*e[2]-1.*e[3]*e[10]*e[1]-1.*e[3]*e[16]*e[7]-1.*e[3]*e[17]*e[8]+e[0]*e[10]*e[4]+e[0]*e[1]*e[13]+1.500000000*e[12]*ep2[3]+.5000000000*e[12]*ep2[4]+.5000000000*e[12]*ep2[5]+.5000000000*e[12]*ep2[6]+.5000000000*ep2[0]*e[12]-.5000000000*e[12]*ep2[1]-.5000000000*e[12]*ep2[7]-.5000000000*e[12]*ep2[2]-.5000000000*e[12]*ep2[8]; + A[99]=e[21]*e[24]*e[6]+e[0]*e[19]*e[22]+e[0]*e[20]*e[23]+e[24]*e[22]*e[7]+e[24]*e[4]*e[25]+e[24]*e[23]*e[8]+e[24]*e[5]*e[26]+e[6]*e[22]*e[25]+e[6]*e[23]*e[26]+e[18]*e[0]*e[21]+e[18]*e[19]*e[4]+e[18]*e[1]*e[22]+e[18]*e[20]*e[5]+e[18]*e[2]*e[23]+e[21]*e[22]*e[4]+e[21]*e[23]*e[5]-1.*e[21]*e[26]*e[8]-1.*e[21]*e[20]*e[2]-1.*e[21]*e[19]*e[1]-1.*e[21]*e[25]*e[7]+1.500000000*ep2[21]*e[3]+.5000000000*e[3]*ep2[22]+.5000000000*e[3]*ep2[23]+.5000000000*e[3]*ep2[24]-.5000000000*e[3]*ep2[26]-.5000000000*e[3]*ep2[19]-.5000000000*e[3]*ep2[20]-.5000000000*e[3]*ep2[25]+.5000000000*ep2[18]*e[3]; + A[127]=e[11]*e[27]*e[12]+e[11]*e[9]*e[30]+e[11]*e[29]*e[14]+e[11]*e[28]*e[13]+e[11]*e[10]*e[31]+e[29]*e[9]*e[12]+e[29]*e[10]*e[13]+e[14]*e[30]*e[12]+e[14]*e[31]*e[13]+e[17]*e[30]*e[15]+e[17]*e[12]*e[33]+e[17]*e[14]*e[35]+e[17]*e[31]*e[16]+e[17]*e[13]*e[34]+e[35]*e[12]*e[15]+e[35]*e[13]*e[16]-1.*e[14]*e[27]*e[9]-1.*e[14]*e[28]*e[10]-1.*e[14]*e[33]*e[15]-1.*e[14]*e[34]*e[16]+.5000000000*ep2[11]*e[32]-.5000000000*e[32]*ep2[16]-.5000000000*e[32]*ep2[9]+.5000000000*e[32]*ep2[12]-.5000000000*e[32]*ep2[15]+.5000000000*e[32]*ep2[17]-.5000000000*e[32]*ep2[10]+1.500000000*e[32]*ep2[14]+.5000000000*e[32]*ep2[13]; + A[126]=e[8]*e[3]*e[6]+.5000000000*ep2[2]*e[5]-.5000000000*e[5]*ep2[0]+.5000000000*e[5]*ep2[4]-.5000000000*e[5]*ep2[6]+.5000000000*e[5]*ep2[8]+e[8]*e[4]*e[7]+.5000000000*ep3[5]+e[2]*e[0]*e[3]+.5000000000*e[5]*ep2[3]-.5000000000*e[5]*ep2[7]+e[2]*e[1]*e[4]-.5000000000*e[5]*ep2[1]; + A[125]=e[2]*e[27]*e[3]+e[2]*e[0]*e[30]+e[2]*e[28]*e[4]+e[2]*e[1]*e[31]+e[2]*e[29]*e[5]-1.*e[5]*e[27]*e[0]-1.*e[5]*e[34]*e[7]-1.*e[5]*e[33]*e[6]+e[5]*e[30]*e[3]+e[5]*e[35]*e[8]-1.*e[5]*e[28]*e[1]+e[5]*e[31]*e[4]+e[29]*e[1]*e[4]+e[29]*e[0]*e[3]+e[8]*e[30]*e[6]+e[8]*e[3]*e[33]+e[8]*e[31]*e[7]+e[8]*e[4]*e[34]+e[35]*e[4]*e[7]+e[35]*e[3]*e[6]+.5000000000*ep2[2]*e[32]+1.500000000*e[32]*ep2[5]+.5000000000*e[32]*ep2[4]-.5000000000*e[32]*ep2[0]-.5000000000*e[32]*ep2[6]-.5000000000*e[32]*ep2[1]-.5000000000*e[32]*ep2[7]+.5000000000*e[32]*ep2[3]+.5000000000*e[32]*ep2[8]; + A[124]=-1.*e[14]*e[19]*e[1]+e[14]*e[22]*e[4]-1.*e[14]*e[18]*e[0]-1.*e[14]*e[25]*e[7]-1.*e[14]*e[24]*e[6]-1.*e[23]*e[10]*e[1]+e[23]*e[13]*e[4]-1.*e[23]*e[16]*e[7]-1.*e[23]*e[15]*e[6]-1.*e[23]*e[9]*e[0]+e[23]*e[12]*e[3]+e[17]*e[21]*e[6]+e[17]*e[3]*e[24]+e[17]*e[22]*e[7]+e[17]*e[4]*e[25]+e[17]*e[5]*e[26]-1.*e[5]*e[24]*e[15]-1.*e[5]*e[25]*e[16]-1.*e[5]*e[18]*e[9]-1.*e[5]*e[19]*e[10]+e[26]*e[12]*e[6]+e[26]*e[3]*e[15]+e[26]*e[13]*e[7]+e[26]*e[4]*e[16]+e[11]*e[18]*e[3]+e[11]*e[0]*e[21]+e[11]*e[19]*e[4]+e[11]*e[1]*e[22]+e[11]*e[20]*e[5]+e[11]*e[2]*e[23]+e[20]*e[9]*e[3]+e[20]*e[0]*e[12]+e[20]*e[10]*e[4]+e[20]*e[1]*e[13]+e[20]*e[2]*e[14]+e[5]*e[21]*e[12]+3.*e[5]*e[23]*e[14]+e[5]*e[22]*e[13]+e[8]*e[21]*e[15]+e[8]*e[12]*e[24]+e[8]*e[23]*e[17]+e[8]*e[14]*e[26]+e[8]*e[22]*e[16]+e[8]*e[13]*e[25]+e[2]*e[18]*e[12]+e[2]*e[9]*e[21]+e[2]*e[19]*e[13]+e[2]*e[10]*e[22]+e[14]*e[21]*e[3]; + A[123]=-.5000000000*e[14]*ep2[27]+1.500000000*e[14]*ep2[32]-.5000000000*e[14]*ep2[28]+.5000000000*e[14]*ep2[29]+.5000000000*e[14]*ep2[31]-.5000000000*e[14]*ep2[33]+.5000000000*e[14]*ep2[30]-.5000000000*e[14]*ep2[34]+.5000000000*e[14]*ep2[35]+e[11]*e[27]*e[30]+e[11]*e[29]*e[32]+e[11]*e[28]*e[31]+e[35]*e[30]*e[15]+e[35]*e[12]*e[33]+e[35]*e[32]*e[17]+e[35]*e[31]*e[16]+e[35]*e[13]*e[34]+e[29]*e[27]*e[12]+e[29]*e[9]*e[30]+e[29]*e[28]*e[13]+e[29]*e[10]*e[31]-1.*e[32]*e[27]*e[9]+e[32]*e[30]*e[12]-1.*e[32]*e[28]*e[10]+e[32]*e[31]*e[13]-1.*e[32]*e[33]*e[15]-1.*e[32]*e[34]*e[16]+e[17]*e[30]*e[33]+e[17]*e[31]*e[34]; + A[122]=-.5000000000*e[23]*ep2[33]-.5000000000*e[23]*ep2[34]+.5000000000*ep2[29]*e[23]+.5000000000*e[23]*ep2[30]+1.500000000*e[23]*ep2[32]+.5000000000*e[23]*ep2[31]+.5000000000*e[23]*ep2[35]-.5000000000*e[23]*ep2[27]-.5000000000*e[23]*ep2[28]+e[32]*e[30]*e[21]+e[32]*e[31]*e[22]+e[26]*e[30]*e[33]+e[26]*e[32]*e[35]+e[26]*e[31]*e[34]+e[35]*e[30]*e[24]+e[35]*e[21]*e[33]+e[35]*e[31]*e[25]+e[35]*e[22]*e[34]-1.*e[32]*e[27]*e[18]-1.*e[32]*e[33]*e[24]-1.*e[32]*e[28]*e[19]-1.*e[32]*e[34]*e[25]+e[20]*e[27]*e[30]+e[20]*e[29]*e[32]+e[20]*e[28]*e[31]+e[29]*e[27]*e[21]+e[29]*e[18]*e[30]+e[29]*e[28]*e[22]+e[29]*e[19]*e[31]; + A[121]=e[2]*e[27]*e[30]+e[2]*e[29]*e[32]+e[2]*e[28]*e[31]+e[32]*e[30]*e[3]+e[32]*e[31]*e[4]+e[8]*e[30]*e[33]+e[8]*e[32]*e[35]+e[8]*e[31]*e[34]+e[29]*e[27]*e[3]+e[29]*e[0]*e[30]+e[29]*e[28]*e[4]+e[29]*e[1]*e[31]+e[35]*e[30]*e[6]+e[35]*e[3]*e[33]+e[35]*e[31]*e[7]+e[35]*e[4]*e[34]-1.*e[32]*e[27]*e[0]-1.*e[32]*e[34]*e[7]-1.*e[32]*e[33]*e[6]-1.*e[32]*e[28]*e[1]+.5000000000*e[5]*ep2[30]+1.500000000*e[5]*ep2[32]+.5000000000*e[5]*ep2[31]-.5000000000*e[5]*ep2[27]-.5000000000*e[5]*ep2[28]+.5000000000*e[5]*ep2[29]-.5000000000*e[5]*ep2[33]-.5000000000*e[5]*ep2[34]+.5000000000*e[5]*ep2[35]; + A[120]=.5000000000*e[32]*ep2[31]+.5000000000*e[32]*ep2[35]-.5000000000*e[32]*ep2[27]+e[29]*e[27]*e[30]+e[29]*e[28]*e[31]+e[35]*e[30]*e[33]+e[35]*e[31]*e[34]+.5000000000*ep2[29]*e[32]+.5000000000*ep3[32]-.5000000000*e[32]*ep2[33]-.5000000000*e[32]*ep2[34]+.5000000000*e[32]*ep2[30]-.5000000000*e[32]*ep2[28]; + A[118]=e[10]*e[1]*e[4]+e[10]*e[0]*e[3]+e[10]*e[2]*e[5]+e[4]*e[12]*e[3]+e[4]*e[14]*e[5]+e[7]*e[12]*e[6]+e[7]*e[3]*e[15]+e[7]*e[4]*e[16]+e[7]*e[14]*e[8]+e[7]*e[5]*e[17]+e[16]*e[3]*e[6]+e[16]*e[5]*e[8]-1.*e[4]*e[11]*e[2]-1.*e[4]*e[15]*e[6]-1.*e[4]*e[9]*e[0]-1.*e[4]*e[17]*e[8]+e[1]*e[9]*e[3]+e[1]*e[0]*e[12]+e[1]*e[11]*e[5]+e[1]*e[2]*e[14]+1.500000000*e[13]*ep2[4]+.5000000000*e[13]*ep2[3]+.5000000000*e[13]*ep2[5]+.5000000000*e[13]*ep2[7]+.5000000000*ep2[1]*e[13]-.5000000000*e[13]*ep2[0]-.5000000000*e[13]*ep2[6]-.5000000000*e[13]*ep2[2]-.5000000000*e[13]*ep2[8]; + A[119]=e[25]*e[21]*e[6]+e[25]*e[3]*e[24]+e[25]*e[23]*e[8]+e[25]*e[5]*e[26]+e[7]*e[21]*e[24]+e[7]*e[23]*e[26]+e[19]*e[18]*e[3]+e[19]*e[0]*e[21]+e[19]*e[1]*e[22]+e[19]*e[20]*e[5]+e[19]*e[2]*e[23]+e[22]*e[21]*e[3]+e[22]*e[23]*e[5]-1.*e[22]*e[26]*e[8]-1.*e[22]*e[20]*e[2]-1.*e[22]*e[18]*e[0]+e[22]*e[25]*e[7]-1.*e[22]*e[24]*e[6]+e[1]*e[18]*e[21]+e[1]*e[20]*e[23]+.5000000000*e[4]*ep2[25]-.5000000000*e[4]*ep2[26]-.5000000000*e[4]*ep2[18]-.5000000000*e[4]*ep2[20]-.5000000000*e[4]*ep2[24]+.5000000000*ep2[19]*e[4]+1.500000000*ep2[22]*e[4]+.5000000000*e[4]*ep2[21]+.5000000000*e[4]*ep2[23]; + A[116]=e[22]*e[21]*e[12]+e[22]*e[23]*e[14]+e[25]*e[21]*e[15]+e[25]*e[12]*e[24]+e[25]*e[23]*e[17]+e[25]*e[14]*e[26]+e[25]*e[22]*e[16]+e[16]*e[21]*e[24]+e[16]*e[23]*e[26]+e[10]*e[19]*e[22]+e[10]*e[18]*e[21]+e[10]*e[20]*e[23]+e[19]*e[18]*e[12]+e[19]*e[9]*e[21]+e[19]*e[20]*e[14]+e[19]*e[11]*e[23]-1.*e[22]*e[24]*e[15]-1.*e[22]*e[26]*e[17]-1.*e[22]*e[20]*e[11]-1.*e[22]*e[18]*e[9]-.5000000000*e[13]*ep2[26]-.5000000000*e[13]*ep2[18]+.5000000000*e[13]*ep2[23]+.5000000000*e[13]*ep2[19]-.5000000000*e[13]*ep2[20]-.5000000000*e[13]*ep2[24]+.5000000000*e[13]*ep2[21]+1.500000000*ep2[22]*e[13]+.5000000000*e[13]*ep2[25]; + A[117]=e[13]*e[30]*e[21]+3.*e[13]*e[31]*e[22]+e[13]*e[32]*e[23]+e[10]*e[27]*e[21]+e[10]*e[18]*e[30]+e[10]*e[28]*e[22]+e[10]*e[19]*e[31]+e[10]*e[29]*e[23]+e[10]*e[20]*e[32]+e[22]*e[30]*e[12]+e[22]*e[32]*e[14]+e[31]*e[21]*e[12]+e[31]*e[23]*e[14]-1.*e[13]*e[27]*e[18]-1.*e[13]*e[33]*e[24]-1.*e[13]*e[29]*e[20]-1.*e[13]*e[35]*e[26]+e[13]*e[28]*e[19]+e[13]*e[34]*e[25]+e[19]*e[27]*e[12]+e[19]*e[9]*e[30]+e[19]*e[29]*e[14]+e[19]*e[11]*e[32]+e[28]*e[18]*e[12]+e[28]*e[9]*e[21]+e[28]*e[20]*e[14]+e[28]*e[11]*e[23]+e[16]*e[30]*e[24]+e[16]*e[21]*e[33]+e[16]*e[31]*e[25]+e[16]*e[22]*e[34]+e[16]*e[32]*e[26]+e[16]*e[23]*e[35]-1.*e[22]*e[27]*e[9]-1.*e[22]*e[33]*e[15]-1.*e[22]*e[35]*e[17]-1.*e[22]*e[29]*e[11]-1.*e[31]*e[24]*e[15]-1.*e[31]*e[26]*e[17]-1.*e[31]*e[20]*e[11]-1.*e[31]*e[18]*e[9]+e[25]*e[30]*e[15]+e[25]*e[12]*e[33]+e[25]*e[32]*e[17]+e[25]*e[14]*e[35]+e[34]*e[21]*e[15]+e[34]*e[12]*e[24]+e[34]*e[23]*e[17]+e[34]*e[14]*e[26]; + A[114]=e[19]*e[11]*e[14]+e[19]*e[9]*e[12]+e[19]*e[10]*e[13]+e[13]*e[21]*e[12]+e[13]*e[23]*e[14]+e[16]*e[21]*e[15]+e[16]*e[12]*e[24]+e[16]*e[23]*e[17]+e[16]*e[14]*e[26]+e[16]*e[13]*e[25]+e[25]*e[14]*e[17]+e[25]*e[12]*e[15]-1.*e[13]*e[24]*e[15]-1.*e[13]*e[26]*e[17]-1.*e[13]*e[20]*e[11]-1.*e[13]*e[18]*e[9]+e[10]*e[18]*e[12]+e[10]*e[9]*e[21]+e[10]*e[20]*e[14]+e[10]*e[11]*e[23]+1.500000000*e[22]*ep2[13]+.5000000000*e[22]*ep2[14]+.5000000000*e[22]*ep2[12]+.5000000000*e[22]*ep2[16]+.5000000000*ep2[10]*e[22]-.5000000000*e[22]*ep2[9]-.5000000000*e[22]*ep2[11]-.5000000000*e[22]*ep2[15]-.5000000000*e[22]*ep2[17]; + A[115]=e[13]*e[12]*e[3]+e[13]*e[14]*e[5]+e[16]*e[12]*e[6]+e[16]*e[3]*e[15]+e[16]*e[13]*e[7]+e[16]*e[14]*e[8]+e[16]*e[5]*e[17]+e[7]*e[14]*e[17]+e[7]*e[12]*e[15]+e[1]*e[11]*e[14]+e[1]*e[9]*e[12]+e[1]*e[10]*e[13]+e[10]*e[9]*e[3]+e[10]*e[0]*e[12]+e[10]*e[11]*e[5]+e[10]*e[2]*e[14]-1.*e[13]*e[11]*e[2]-1.*e[13]*e[15]*e[6]-1.*e[13]*e[9]*e[0]-1.*e[13]*e[17]*e[8]+1.500000000*ep2[13]*e[4]+.5000000000*e[4]*ep2[16]-.5000000000*e[4]*ep2[9]-.5000000000*e[4]*ep2[11]+.5000000000*e[4]*ep2[12]-.5000000000*e[4]*ep2[15]-.5000000000*e[4]*ep2[17]+.5000000000*e[4]*ep2[10]+.5000000000*e[4]*ep2[14]; + A[112]=e[19]*e[1]*e[4]+e[19]*e[0]*e[3]+e[19]*e[2]*e[5]+e[4]*e[21]*e[3]+e[4]*e[23]*e[5]+e[7]*e[21]*e[6]+e[7]*e[3]*e[24]+e[7]*e[4]*e[25]+e[7]*e[23]*e[8]+e[7]*e[5]*e[26]+e[25]*e[3]*e[6]+e[25]*e[5]*e[8]+e[1]*e[18]*e[3]+e[1]*e[0]*e[21]+e[1]*e[20]*e[5]+e[1]*e[2]*e[23]-1.*e[4]*e[26]*e[8]-1.*e[4]*e[20]*e[2]-1.*e[4]*e[18]*e[0]-1.*e[4]*e[24]*e[6]+1.500000000*e[22]*ep2[4]-.5000000000*e[22]*ep2[0]-.5000000000*e[22]*ep2[6]+.5000000000*e[22]*ep2[5]+.5000000000*e[22]*ep2[1]+.5000000000*e[22]*ep2[7]+.5000000000*e[22]*ep2[3]-.5000000000*e[22]*ep2[2]-.5000000000*e[22]*ep2[8]; + A[113]=-1.*e[31]*e[20]*e[2]-1.*e[31]*e[18]*e[0]+e[31]*e[23]*e[5]-1.*e[31]*e[24]*e[6]+e[7]*e[30]*e[24]+e[7]*e[21]*e[33]+e[7]*e[32]*e[26]+e[7]*e[23]*e[35]+e[25]*e[30]*e[6]+e[25]*e[3]*e[33]+e[25]*e[31]*e[7]+e[25]*e[4]*e[34]+e[25]*e[32]*e[8]+e[25]*e[5]*e[35]+e[34]*e[21]*e[6]+e[34]*e[3]*e[24]+e[34]*e[22]*e[7]+e[34]*e[23]*e[8]+e[34]*e[5]*e[26]+e[1]*e[27]*e[21]+e[1]*e[18]*e[30]+e[1]*e[28]*e[22]+e[1]*e[19]*e[31]+e[1]*e[29]*e[23]+e[1]*e[20]*e[32]+e[19]*e[27]*e[3]+e[19]*e[0]*e[30]+e[19]*e[28]*e[4]+e[19]*e[29]*e[5]+e[19]*e[2]*e[32]+e[28]*e[18]*e[3]+e[28]*e[0]*e[21]+e[28]*e[20]*e[5]+e[28]*e[2]*e[23]+e[4]*e[30]*e[21]+3.*e[4]*e[31]*e[22]+e[4]*e[32]*e[23]-1.*e[4]*e[27]*e[18]-1.*e[4]*e[33]*e[24]-1.*e[4]*e[29]*e[20]-1.*e[4]*e[35]*e[26]-1.*e[22]*e[27]*e[0]+e[22]*e[32]*e[5]-1.*e[22]*e[33]*e[6]+e[22]*e[30]*e[3]-1.*e[22]*e[35]*e[8]-1.*e[22]*e[29]*e[2]+e[31]*e[21]*e[3]-1.*e[31]*e[26]*e[8]; - double e003,e013,e023,e033,e043,e053,e063,e073,e083; - double e103,e113,e123,e133,e143,e153,e163,e173,e183; - double e203,e213,e223,e233,e243,e253,e263,e273,e283; - double e303,e313,e323,e333,e343,e353,e363,e373,e383; - e00 = EE[0*9 + 0 ]; - e10 = EE[1*9 + 0 ]; - e20 = EE[2*9 + 0 ]; - e30 = EE[3*9 + 0 ]; - e01 = EE[0*9 + 1 ]; - e11 = EE[1*9 + 1 ]; - e21 = EE[2*9 + 1 ]; - e31 = EE[3*9 + 1 ]; - e02 = EE[0*9 + 2 ]; - e12 = EE[1*9 + 2 ]; - e22 = EE[2*9 + 2 ]; - e32 = EE[3*9 + 2 ]; - e03 = EE[0*9 + 3 ]; - e13 = EE[1*9 + 3 ]; - e23 = EE[2*9 + 3 ]; - e33 = EE[3*9 + 3 ]; - e04 = EE[0*9 + 4 ]; - e14 = EE[1*9 + 4 ]; - e24 = EE[2*9 + 4 ]; - e34 = EE[3*9 + 4 ]; - e05 = EE[0*9 + 5 ]; - e15 = EE[1*9 + 5 ]; - e25 = EE[2*9 + 5 ]; - e35 = EE[3*9 + 5 ]; - e06 = EE[0*9 + 6 ]; - e16 = EE[1*9 + 6 ]; - e26 = EE[2*9 + 6 ]; - e36 = EE[3*9 + 6 ]; - e07 = EE[0*9 + 7 ]; - e17 = EE[1*9 + 7 ]; - e27 = EE[2*9 + 7 ]; - e37 = EE[3*9 + 7 ]; - e08 = EE[0*9 + 8 ]; - e18 = EE[1*9 + 8 ]; - e28 = EE[2*9 + 8 ]; - e38 = EE[3*9 + 8 ]; + int perm[20] = {6, 8, 18, 15, 12, 5, 14, 7, 4, 11, 19, 13, 1, 16, 17, 3, 10, 9, 2, 0}; + double AA[200]; + for (int i = 0; i < 20; i++) + { + for (int j = 0; j < 10; j++) AA[i + j * 20] = A[perm[i] + j * 20]; + } - - e002 =e00*e00; - e102 =e10*e10; - e202 =e20*e20; - e302 =e30*e30; - e012 =e01*e01; - e112 =e11*e11; - e212 =e21*e21; - e312 =e31*e31; - e022 =e02*e02; - e122 =e12*e12; - e222 =e22*e22; - e322 =e32*e32; - e032 =e03*e03; - e132 =e13*e13; - e232 =e23*e23; - e332 =e33*e33; - e042 =e04*e04; - e142 =e14*e14; - e242 =e24*e24; - e342 =e34*e34; - e052 =e05*e05; - e152 =e15*e15; - e252 =e25*e25; - e352 =e35*e35; - e062 =e06*e06; - e162 =e16*e16; - e262 =e26*e26; - e362 =e36*e36; - e072 =e07*e07; - e172 =e17*e17; - e272 =e27*e27; - e372 =e37*e37; - e082 =e08*e08; - e182 =e18*e18; - e282 =e28*e28; - e382 =e38*e38; - - e003 =e00*e00*e00; - e103 =e10*e10*e10; - e203 =e20*e20*e20; - e303 =e30*e30*e30; - e013 =e01*e01*e01; - e113 =e11*e11*e11; - e213 =e21*e21*e21; - e313 =e31*e31*e31; - e023 =e02*e02*e02; - e123 =e12*e12*e12; - e223 =e22*e22*e22; - e323 =e32*e32*e32; - e033 =e03*e03*e03; - e133 =e13*e13*e13; - e233 =e23*e23*e23; - e333 =e33*e33*e33; - e043 =e04*e04*e04; - e143 =e14*e14*e14; - e243 =e24*e24*e24; - e343 =e34*e34*e34; - e053 =e05*e05*e05; - e153 =e15*e15*e15; - e253 =e25*e25*e25; - e353 =e35*e35*e35; - e063 =e06*e06*e06; - e163 =e16*e16*e16; - e263 =e26*e26*e26; - e363 =e36*e36*e36; - e073 =e07*e07*e07; - e173 =e17*e17*e17; - e273 =e27*e27*e27; - e373 =e37*e37*e37; - e083 =e08*e08*e08; - e183 =e18*e18*e18; - e283 =e28*e28*e28; - e383 =e38*e38*e38; - - - A[0 + 10*0]=0.5*e003+0.5*e00*e012+0.5*e00*e022+0.5*e00*e032+e03*e01*e04+e03*e02*e05+0.5*e00*e062+e06*e01*e07+e06*e02*e08-0.5*e00*e042-0.5*e00*e052-0.5*e00*e072-0.5*e00*e082; - A[0 + 10*1]=e00*e11*e01+e00*e12*e02+e03*e00*e13+e03*e11*e04+e03*e01*e14+e03*e12*e05+e03*e02*e15+e13*e01*e04+e13*e02*e05+e06*e00*e16+1.5*e10*e002+0.5*e10*e012+0.5*e10*e022+0.5*e10*e062-0.5*e10*e042-0.5*e10*e052-0.5*e10*e072+0.5*e10*e032+e06*e11*e07+e06*e01*e17+e06*e12*e08+e06*e02*e18+e16*e01*e07+e16*e02*e08-e00*e14*e04-e00*e17*e07-e00*e15*e05-e00*e18*e08-0.5*e10*e082; - A[0 + 10*2]=e16*e02*e18+e03*e12*e15+e10*e11*e01+e10*e12*e02+e03*e10*e13+e03*e11*e14+e13*e11*e04+e13*e01*e14+e13*e12*e05+e13*e02*e15+e06*e10*e16+e06*e12*e18+e06*e11*e17+e16*e11*e07+e16*e01*e17+e16*e12*e08-e10*e14*e04-e10*e17*e07-e10*e15*e05-e10*e18*e08+1.5*e00*e102+0.5*e00*e122+0.5*e00*e112+0.5*e00*e132+0.5*e00*e162-0.5*e00*e152-0.5*e00*e172-0.5*e00*e182-0.5*e00*e142; - A[0 + 10*3]=0.5*e103+0.5*e10*e122+0.5*e10*e112+0.5*e10*e132+e13*e12*e15+e13*e11*e14+0.5*e10*e162+e16*e12*e18+e16*e11*e17-0.5*e10*e152-0.5*e10*e172-0.5*e10*e182-0.5*e10*e142; - A[0 + 10*4]=-e00*e28*e08-e00*e25*e05-e00*e27*e07-e00*e24*e04+e26*e02*e08+e26*e01*e07+e06*e02*e28+e06*e22*e08+e06*e01*e27+e06*e21*e07+e23*e02*e05+e23*e01*e04+e03*e02*e25+e03*e22*e05+e03*e01*e24+e03*e21*e04+e00*e22*e02+e00*e21*e01-0.5*e20*e082-0.5*e20*e052-0.5*e20*e072-0.5*e20*e042+e06*e00*e26+0.5*e20*e062+e03*e00*e23+0.5*e20*e022+1.5*e20*e002+0.5*e20*e032+0.5*e20*e012; - A[0 + 10*5]=-e10*e24*e04-e10*e27*e07-e10*e25*e05-e10*e28*e08-e20*e14*e04-e20*e17*e07-e20*e15*e05-e20*e18*e08-e00*e24*e14-e00*e25*e15-e00*e27*e17-e00*e28*e18+e06*e21*e17+e06*e22*e18+e06*e12*e28+e16*e00*e26+e16*e21*e07+e16*e01*e27+e16*e22*e08+e16*e02*e28+e26*e11*e07+e26*e01*e17+e26*e12*e08+e26*e02*e18+e06*e11*e27+e23*e11*e04+e23*e01*e14+e23*e12*e05+e23*e02*e15+e06*e20*e16+e06*e10*e26+e03*e21*e14+e03*e22*e15+e03*e12*e25+e13*e00*e23+e13*e21*e04+e13*e01*e24+e13*e22*e05+e13*e02*e25+e03*e11*e24+e03*e20*e13+e03*e10*e23+e00*e21*e11+3*e00*e20*e10+e00*e22*e12+e20*e12*e02+e20*e11*e01+e10*e22*e02+e10*e21*e01; - A[0 + 10*6]=-0.5*e20*e152+e26*e11*e17-e10*e24*e14-e10*e25*e15-e10*e27*e17-e10*e28*e18+0.5*e20*e162+e13*e10*e23+e13*e22*e15+e23*e12*e15+e23*e11*e14+e16*e10*e26+e16*e21*e17+e16*e11*e27+e16*e22*e18+e16*e12*e28+e26*e12*e18+e13*e12*e25+0.5*e20*e132+1.5*e20*e102+0.5*e20*e122+0.5*e20*e112+e10*e21*e11+e10*e22*e12+e13*e11*e24-0.5*e20*e172-0.5*e20*e182-0.5*e20*e142+e13*e21*e14; - A[0 + 10*7]=-e20*e25*e05-e20*e28*e08-0.5*e00*e272-0.5*e00*e282-0.5*e00*e242+0.5*e00*e262-0.5*e00*e252+e06*e20*e26+0.5*e00*e232+e06*e22*e28+e06*e21*e27+e26*e21*e07+e26*e01*e27+e26*e22*e08+e26*e02*e28-e20*e24*e04-e20*e27*e07+e03*e20*e23+e03*e22*e25+e03*e21*e24+e23*e21*e04+e23*e01*e24+e23*e22*e05+e23*e02*e25+e20*e21*e01+e20*e22*e02+1.5*e00*e202+0.5*e00*e222+0.5*e00*e212; - A[0 + 10*8]=e23*e21*e14+e23*e11*e24+e23*e22*e15+e23*e12*e25+e16*e20*e26+e16*e22*e28+e16*e21*e27+e26*e21*e17+e26*e11*e27+e26*e22*e18+e26*e12*e28+1.5*e10*e202+0.5*e10*e222+0.5*e10*e212+0.5*e10*e232+e20*e21*e11+e20*e22*e12+e13*e20*e23+e13*e22*e25+e13*e21*e24-e20*e24*e14-e20*e25*e15-e20*e27*e17-e20*e28*e18-0.5*e10*e272-0.5*e10*e282-0.5*e10*e242-0.5*e10*e252+0.5*e10*e262; - A[0 + 10*9]=0.5*e203+0.5*e20*e222+0.5*e20*e212+0.5*e20*e232+e23*e22*e25+e23*e21*e24+0.5*e20*e262+e26*e22*e28+e26*e21*e27-0.5*e20*e252-0.5*e20*e272-0.5*e20*e282-0.5*e20*e242; - A[0 + 10*10]=e06*e32*e08-0.5*e30*e082-0.5*e30*e042-0.5*e30*e052-0.5*e30*e072+0.5*e30*e012+0.5*e30*e022+0.5*e30*e032+0.5*e30*e062+1.5*e30*e002+e00*e31*e01+e00*e32*e02+e03*e31*e04+e03*e01*e34+e03*e32*e05+e03*e02*e35+e33*e01*e04+e33*e02*e05+e06*e00*e36+e06*e31*e07+e06*e01*e37+e06*e02*e38+e36*e01*e07+e36*e02*e08-e00*e34*e04-e00*e37*e07-e00*e35*e05-e00*e38*e08+e03*e00*e33; - A[0 + 10*11]=e06*e30*e16+e03*e30*e13+e16*e31*e07+e06*e10*e36-e10*e37*e07+3*e00*e30*e10+e00*e32*e12-e00*e38*e18-e10*e34*e04-e10*e35*e05-e10*e38*e08-e30*e14*e04-e30*e17*e07-e30*e15*e05-e30*e18*e08+e00*e31*e11+e10*e31*e01+e10*e32*e02+e30*e11*e01+e30*e12*e02+e03*e10*e33-e00*e34*e14-e00*e35*e15-e00*e37*e17+e03*e31*e14+e03*e11*e34+e03*e32*e15+e03*e12*e35+e13*e00*e33+e13*e31*e04+e13*e01*e34+e13*e32*e05+e13*e02*e35+e33*e11*e04+e33*e01*e14+e33*e12*e05+e33*e02*e15+e06*e31*e17+e06*e11*e37+e06*e32*e18+e06*e12*e38+e16*e00*e36+e16*e01*e37+e16*e32*e08+e16*e02*e38+e36*e11*e07+e36*e01*e17+e36*e12*e08+e36*e02*e18; - A[0 + 10*12]=e13*e10*e33+e33*e11*e14+e16*e10*e36+e16*e31*e17+e16*e11*e37+e16*e32*e18+e16*e12*e38+e36*e12*e18+e36*e11*e17-e10*e34*e14-e10*e35*e15-e10*e37*e17-e10*e38*e18+e10*e31*e11+e10*e32*e12+e13*e31*e14+e13*e11*e34+e13*e32*e15+e13*e12*e35+e33*e12*e15+1.5*e30*e102+0.5*e30*e122+0.5*e30*e112+0.5*e30*e132+0.5*e30*e162-0.5*e30*e152-0.5*e30*e172-0.5*e30*e182-0.5*e30*e142; - A[0 + 10*13]=e00*e32*e22+3*e00*e30*e20+e00*e31*e21+e20*e31*e01+e20*e32*e02+e30*e21*e01+e30*e22*e02+e03*e20*e33+e03*e32*e25+e03*e22*e35+e03*e31*e24+e03*e21*e34+e23*e00*e33+e23*e31*e04+e23*e01*e34+e23*e32*e05+e23*e02*e35+e33*e21*e04+e33*e01*e24+e33*e22*e05+e33*e02*e25+e06*e30*e26+e06*e20*e36+e06*e32*e28+e06*e22*e38+e06*e31*e27+e06*e21*e37+e26*e00*e36+e26*e31*e07+e03*e30*e23+e26*e01*e37+e26*e32*e08+e26*e02*e38+e36*e21*e07+e36*e01*e27+e36*e22*e08+e36*e02*e28-e00*e35*e25-e00*e37*e27-e00*e38*e28-e00*e34*e24-e20*e34*e04-e20*e37*e07-e20*e35*e05-e20*e38*e08-e30*e24*e04-e30*e27*e07-e30*e25*e05-e30*e28*e08; - A[0 + 10*14]=e16*e30*e26+e13*e21*e34+3*e10*e30*e20+e10*e32*e22+e10*e31*e21+e20*e31*e11+e20*e32*e12+e30*e21*e11+e30*e22*e12+e13*e30*e23+e13*e20*e33+e13*e32*e25+e13*e22*e35+e13*e31*e24+e23*e10*e33+e23*e31*e14+e23*e11*e34+e23*e32*e15+e23*e12*e35+e33*e21*e14+e33*e11*e24+e33*e22*e15+e33*e12*e25+e16*e20*e36+e16*e32*e28+e16*e22*e38+e16*e31*e27+e16*e21*e37+e26*e10*e36+e26*e31*e17+e26*e11*e37+e26*e32*e18+e26*e12*e38+e36*e21*e17+e36*e11*e27+e36*e22*e18+e36*e12*e28-e10*e35*e25-e10*e37*e27-e10*e38*e28-e10*e34*e24-e20*e34*e14-e20*e35*e15-e20*e37*e17-e20*e38*e18-e30*e24*e14-e30*e25*e15-e30*e27*e17-e30*e28*e18; - A[0 + 10*15]=-e20*e34*e24+0.5*e30*e262-0.5*e30*e252-0.5*e30*e272-0.5*e30*e282-0.5*e30*e242+1.5*e30*e202+0.5*e30*e222+0.5*e30*e212+0.5*e30*e232+e20*e32*e22+e20*e31*e21+e23*e20*e33+e23*e32*e25+e23*e22*e35+e23*e31*e24+e23*e21*e34+e33*e22*e25+e33*e21*e24+e26*e20*e36+e26*e32*e28+e26*e22*e38+e26*e31*e27+e26*e21*e37+e36*e22*e28+e36*e21*e27-e20*e35*e25-e20*e37*e27-e20*e38*e28; - A[0 + 10*16]=0.5*e00*e322+e30*e32*e02+e30*e31*e01+1.5*e00*e302+0.5*e00*e312+e03*e32*e35+e33*e31*e04+e33*e01*e34+e33*e32*e05+e33*e02*e35+e06*e30*e36+e06*e31*e37+e06*e32*e38+e36*e31*e07+e36*e01*e37+e36*e32*e08+e36*e02*e38-e30*e34*e04-e30*e37*e07-e30*e35*e05-e30*e38*e08+0.5*e00*e332+0.5*e00*e362-0.5*e00*e382-0.5*e00*e352-0.5*e00*e342-0.5*e00*e372+e03*e30*e33+e03*e31*e34; - A[0 + 10*17]=0.5*e10*e362-0.5*e10*e382-0.5*e10*e352-0.5*e10*e342-0.5*e10*e372+e36*e31*e17+e36*e11*e37+e36*e32*e18+e36*e12*e38-e30*e34*e14-e30*e35*e15-e30*e37*e17-e30*e38*e18+1.5*e10*e302+0.5*e10*e312+0.5*e10*e322+0.5*e10*e332+e30*e31*e11+e30*e32*e12+e13*e30*e33+e13*e31*e34+e13*e32*e35+e33*e31*e14+e33*e11*e34+e33*e32*e15+e33*e12*e35+e16*e30*e36+e16*e31*e37+e16*e32*e38; - A[0 + 10*18]=e33*e31*e24+e33*e21*e34+e26*e30*e36+e26*e31*e37+e26*e32*e38+e36*e32*e28+e36*e22*e38+e36*e31*e27+e36*e21*e37-e30*e35*e25-e30*e37*e27-e30*e38*e28-e30*e34*e24+e33*e22*e35+1.5*e20*e302+0.5*e20*e312+0.5*e20*e322+0.5*e20*e332+0.5*e20*e362-0.5*e20*e382-0.5*e20*e352-0.5*e20*e342-0.5*e20*e372+e30*e32*e22+e30*e31*e21+e23*e30*e33+e23*e31*e34+e23*e32*e35+e33*e32*e25; - A[0 + 10*19]=0.5*e303+0.5*e30*e312+0.5*e30*e322+0.5*e30*e332+e33*e31*e34+e33*e32*e35+0.5*e30*e362+e36*e31*e37+e36*e32*e38-0.5*e30*e382-0.5*e30*e352-0.5*e30*e342-0.5*e30*e372; - A[1 + 10*0]=e00*e01*e04+0.5*e002*e03+e00*e02*e05+0.5*e033+0.5*e03*e042+0.5*e03*e052+0.5*e03*e062+e06*e04*e07+e06*e05*e08-0.5*e03*e012-0.5*e03*e072-0.5*e03*e022-0.5*e03*e082; - A[1 + 10*1]=e03*e14*e04+e10*e01*e04+e16*e05*e08+e00*e10*e03+e00*e11*e04+e00*e01*e14+e00*e12*e05+e00*e02*e15+e10*e02*e05+e03*e15*e05+e06*e03*e16+e06*e14*e07+e06*e04*e17+e06*e15*e08+e06*e05*e18+0.5*e002*e13+1.5*e13*e032+0.5*e13*e042+0.5*e13*e052+0.5*e13*e062-0.5*e13*e012-0.5*e13*e072-0.5*e13*e022-0.5*e13*e082+e16*e04*e07-e03*e12*e02-e03*e11*e01-e03*e17*e07-e03*e18*e08; - A[1 + 10*2]=-e13*e11*e01+e00*e10*e13+e00*e12*e15+e00*e11*e14+e10*e11*e04+e10*e01*e14+e10*e12*e05+e10*e02*e15+e13*e14*e04+e13*e15*e05+e06*e13*e16+e06*e15*e18+e06*e14*e17+e16*e14*e07+e16*e04*e17+e16*e15*e08+e16*e05*e18-e13*e12*e02-e13*e17*e07-e13*e18*e08+0.5*e102*e03+1.5*e03*e132+0.5*e03*e152+0.5*e03*e142+0.5*e03*e162-0.5*e03*e112-0.5*e03*e172-0.5*e03*e122-0.5*e03*e182; - A[1 + 10*3]=0.5*e102*e13+e10*e11*e14+e10*e12*e15+0.5*e133+0.5*e13*e152+0.5*e13*e142+0.5*e13*e162+e16*e15*e18+e16*e14*e17-0.5*e13*e112-0.5*e13*e122-0.5*e13*e172-0.5*e13*e182; - A[1 + 10*4]=-e03*e28*e08-e03*e27*e07-e03*e21*e01-e03*e22*e02+e26*e05*e08+e26*e04*e07+e06*e05*e28+e06*e25*e08+e06*e04*e27+e06*e24*e07+e03*e25*e05+e03*e24*e04+e20*e02*e05+e20*e01*e04+e00*e02*e25+e00*e22*e05+e00*e01*e24+e00*e21*e04+e00*e20*e03-0.5*e23*e072-0.5*e23*e082-0.5*e23*e022-0.5*e23*e012+e06*e03*e26+0.5*e23*e052+0.5*e23*e062+1.5*e23*e032+0.5*e23*e042+0.5*e002*e23; - A[1 + 10*5]=e00*e21*e14+e00*e11*e24+e00*e10*e23+e00*e22*e15+e00*e12*e25+e20*e12*e05+e20*e01*e14+e20*e11*e04+e00*e20*e13+e10*e02*e25+e10*e22*e05+e10*e01*e24+e10*e21*e04+e10*e20*e03+e23*e15*e05+e23*e14*e04+e13*e25*e05+e13*e24*e04+e03*e24*e14+e03*e25*e15+3*e03*e23*e13+e20*e02*e15+e16*e03*e26+e06*e14*e27-e23*e18*e08+e06*e24*e17+e06*e15*e28+e06*e25*e18+e06*e13*e26+e06*e23*e16+e26*e04*e17+e26*e14*e07+e16*e05*e28+e16*e25*e08+e16*e04*e27+e16*e24*e07-e03*e22*e12-e03*e21*e11+e26*e05*e18+e26*e15*e08-e03*e27*e17-e03*e28*e18-e13*e22*e02-e13*e28*e08-e13*e27*e07-e13*e21*e01-e23*e17*e07-e23*e11*e01-e23*e12*e02; - A[1 + 10*6]=-0.5*e23*e182-0.5*e23*e172-0.5*e23*e112-0.5*e23*e122-e13*e22*e12-e13*e27*e17-e13*e28*e18+e26*e15*e18+e26*e14*e17-e13*e21*e11+e20*e12*e15+e13*e25*e15+e13*e24*e14+e16*e13*e26+e16*e25*e18+e16*e15*e28+e16*e24*e17+e16*e14*e27+1.5*e23*e132+0.5*e23*e152+0.5*e23*e142+0.5*e23*e162+e10*e20*e13+e10*e21*e14+e10*e11*e24+e10*e22*e15+e10*e12*e25+e20*e11*e14+0.5*e102*e23; - A[1 + 10*7]=e26*e04*e27+e00*e22*e25-e23*e28*e08+0.5*e03*e262-0.5*e03*e212-0.5*e03*e272-0.5*e03*e222-0.5*e03*e282+e23*e24*e04+e23*e25*e05+0.5*e202*e03+e06*e23*e26+e06*e24*e27+e06*e25*e28+e26*e24*e07+e26*e25*e08+e26*e05*e28-e23*e22*e02-e23*e21*e01-e23*e27*e07+e00*e20*e23+e00*e21*e24+e20*e21*e04+e20*e01*e24+e20*e22*e05+e20*e02*e25+1.5*e03*e232+0.5*e03*e242+0.5*e03*e252; - A[1 + 10*8]=e20*e11*e24-0.5*e13*e212-0.5*e13*e272-0.5*e13*e222-0.5*e13*e282-e23*e27*e17-e23*e28*e18+e26*e25*e18+e26*e24*e17+e26*e14*e27-e23*e21*e11-e23*e22*e12+e26*e15*e28+e23*e25*e15+e23*e24*e14+e16*e23*e26+e16*e24*e27+e16*e25*e28+0.5*e13*e262+e20*e21*e14+e20*e22*e15+e20*e12*e25+0.5*e13*e242+0.5*e13*e252+0.5*e202*e13+1.5*e13*e232+e10*e20*e23+e10*e22*e25+e10*e21*e24; - A[1 + 10*9]=0.5*e202*e23+e20*e22*e25+e20*e21*e24+0.5*e233+0.5*e23*e242+0.5*e23*e252+0.5*e23*e262+e26*e24*e27+e26*e25*e28-0.5*e23*e212-0.5*e23*e272-0.5*e23*e222-0.5*e23*e282; - A[1 + 10*10]=e00*e30*e03+0.5*e33*e062-0.5*e33*e012-0.5*e33*e022-0.5*e33*e072+e03*e35*e05+e06*e03*e36+e06*e34*e07+e06*e04*e37+e06*e35*e08+e06*e05*e38+e36*e04*e07+e36*e05*e08-e03*e32*e02-e03*e31*e01-e03*e37*e07+e00*e31*e04+e00*e01*e34+e00*e32*e05+e00*e02*e35+e30*e01*e04+e30*e02*e05+e03*e34*e04-e03*e38*e08+0.5*e002*e33+1.5*e33*e032+0.5*e33*e042+0.5*e33*e052-0.5*e33*e082; - A[1 + 10*11]=e06*e35*e18+e06*e33*e16+e00*e30*e13+e00*e10*e33+e00*e31*e14+e00*e11*e34+e00*e32*e15+e00*e12*e35+e10*e30*e03-e33*e17*e07-e33*e18*e08+e10*e31*e04+e10*e01*e34+e10*e32*e05+e10*e02*e35+e30*e11*e04+e30*e01*e14+e30*e12*e05+e30*e02*e15+3*e03*e33*e13+e03*e35*e15+e03*e34*e14+e13*e34*e04+e13*e35*e05+e33*e14*e04+e33*e15*e05+e06*e13*e36+e06*e15*e38+e06*e34*e17+e06*e14*e37+e16*e03*e36+e16*e34*e07+e16*e04*e37+e16*e35*e08+e16*e05*e38+e36*e14*e07+e36*e04*e17+e36*e15*e08+e36*e05*e18-e03*e31*e11-e03*e32*e12-e03*e37*e17-e03*e38*e18-e13*e32*e02-e13*e31*e01-e13*e37*e07-e13*e38*e08-e33*e12*e02-e33*e11*e01; - A[1 + 10*12]=e16*e13*e36+e10*e11*e34+0.5*e33*e152+0.5*e33*e142+0.5*e33*e162-0.5*e33*e112-0.5*e33*e122-0.5*e33*e172-0.5*e33*e182+0.5*e102*e33+1.5*e33*e132+e10*e30*e13+e10*e31*e14+e10*e32*e15+e10*e12*e35+e30*e11*e14+e30*e12*e15+e13*e35*e15+e13*e34*e14+e16*e35*e18+e16*e15*e38+e16*e34*e17+e16*e14*e37+e36*e15*e18+e36*e14*e17-e13*e31*e11-e13*e32*e12-e13*e37*e17-e13*e38*e18; - A[1 + 10*13]=e06*e35*e28+e36*e04*e27+e00*e20*e33+e00*e30*e23+3*e03*e33*e23+e03*e34*e24+e03*e35*e25+e23*e34*e04+e23*e35*e05+e33*e24*e04+e33*e25*e05+e06*e33*e26+e06*e23*e36+e06*e34*e27+e06*e24*e37+e06*e25*e38+e26*e03*e36+e26*e34*e07+e26*e04*e37+e26*e35*e08+e26*e05*e38+e36*e24*e07+e36*e25*e08+e36*e05*e28-e03*e31*e21-e03*e37*e27-e03*e32*e22-e03*e38*e28-e23*e32*e02-e23*e31*e01-e23*e37*e07-e23*e38*e08-e33*e22*e02-e33*e21*e01-e33*e27*e07-e33*e28*e08+e00*e32*e25+e00*e22*e35+e00*e31*e24+e00*e21*e34+e20*e30*e03+e20*e31*e04+e20*e01*e34+e20*e32*e05+e20*e02*e35+e30*e21*e04+e30*e01*e24+e30*e22*e05+e30*e02*e25; - A[1 + 10*14]=e10*e30*e23+e10*e20*e33+e10*e22*e35+e10*e32*e25+e10*e31*e24+e10*e21*e34+e20*e30*e13+e20*e31*e14+e20*e11*e34+e20*e32*e15+e20*e12*e35+e30*e21*e14+e30*e11*e24+e30*e22*e15+e30*e12*e25+3*e13*e33*e23+e13*e34*e24+e13*e35*e25+e23*e35*e15+e23*e34*e14+e33*e25*e15+e33*e24*e14+e16*e33*e26+e16*e23*e36+e16*e34*e27+e16*e24*e37+e16*e35*e28+e16*e25*e38+e26*e13*e36+e26*e35*e18+e26*e15*e38+e26*e34*e17+e26*e14*e37+e36*e25*e18+e36*e15*e28+e36*e24*e17+e36*e14*e27-e13*e31*e21-e13*e37*e27-e13*e32*e22-e13*e38*e28-e23*e31*e11-e23*e32*e12-e23*e37*e17-e23*e38*e18-e33*e21*e11-e33*e22*e12-e33*e27*e17-e33*e28*e18; - A[1 + 10*15]=-0.5*e33*e212-0.5*e33*e272-0.5*e33*e222-0.5*e33*e282+e26*e23*e36+e20*e30*e23+e20*e32*e25+e20*e22*e35+e20*e31*e24+e20*e21*e34+e30*e22*e25+e30*e21*e24+e23*e34*e24+e23*e35*e25+e26*e34*e27+e26*e24*e37+e26*e35*e28+e26*e25*e38+e36*e24*e27+e36*e25*e28-e23*e31*e21-e23*e37*e27-e23*e32*e22-e23*e38*e28+0.5*e202*e33+1.5*e33*e232+0.5*e33*e242+0.5*e33*e252+0.5*e33*e262; - A[1 + 10*16]=e33*e35*e05+e30*e32*e05+0.5*e03*e362+0.5*e302*e03+1.5*e03*e332+0.5*e03*e352+0.5*e03*e342+e00*e30*e33+e00*e31*e34+e00*e32*e35+e30*e31*e04+e30*e01*e34+e30*e02*e35+e33*e34*e04+e06*e33*e36+e06*e35*e38+e06*e34*e37+e36*e34*e07+e36*e04*e37+e36*e35*e08+e36*e05*e38-e33*e32*e02-e33*e31*e01-e33*e37*e07-e33*e38*e08-0.5*e03*e322-0.5*e03*e382-0.5*e03*e312-0.5*e03*e372; - A[1 + 10*17]=-e33*e31*e11-e33*e32*e12-e33*e38*e18+e30*e11*e34+e30*e32*e15+e30*e12*e35+e33*e35*e15+e33*e34*e14+e16*e33*e36+e16*e35*e38+e16*e34*e37+e36*e35*e18+e36*e15*e38+e36*e34*e17+e36*e14*e37-e33*e37*e17+0.5*e302*e13+1.5*e13*e332+0.5*e13*e352+0.5*e13*e342+0.5*e13*e362-0.5*e13*e322-0.5*e13*e382-0.5*e13*e312-0.5*e13*e372+e10*e30*e33+e10*e31*e34+e10*e32*e35+e30*e31*e14; - A[1 + 10*18]=e36*e25*e38+0.5*e302*e23+1.5*e23*e332+0.5*e23*e352+0.5*e23*e342+0.5*e23*e362-0.5*e23*e322-0.5*e23*e382-0.5*e23*e312-0.5*e23*e372+e20*e30*e33+e20*e31*e34+e20*e32*e35+e30*e32*e25+e30*e22*e35+e30*e31*e24+e30*e21*e34+e33*e34*e24+e33*e35*e25+e26*e33*e36+e26*e35*e38+e26*e34*e37+e36*e34*e27+e36*e24*e37+e36*e35*e28-e33*e31*e21-e33*e37*e27-e33*e32*e22-e33*e38*e28; - A[1 + 10*19]=0.5*e302*e33+e30*e31*e34+e30*e32*e35+0.5*e333+0.5*e33*e352+0.5*e33*e342+0.5*e33*e362+e36*e35*e38+e36*e34*e37-0.5*e33*e322-0.5*e33*e382-0.5*e33*e312-0.5*e33*e372; - A[2 + 10*0]=0.5*e002*e06+e00*e01*e07+e00*e02*e08+0.5*e032*e06+e03*e04*e07+e03*e05*e08+0.5*e063+0.5*e06*e072+0.5*e06*e082-0.5*e06*e012-0.5*e06*e022-0.5*e06*e042-0.5*e06*e052; - A[2 + 10*1]=e00*e10*e06+0.5*e002*e16+0.5*e032*e16+1.5*e16*e062+0.5*e16*e072+0.5*e16*e082-0.5*e16*e012-0.5*e16*e022-0.5*e16*e042-0.5*e16*e052+e00*e11*e07+e00*e01*e17+e00*e12*e08+e00*e02*e18+e10*e01*e07+e10*e02*e08+e03*e13*e06+e03*e14*e07+e03*e04*e17+e03*e15*e08+e03*e05*e18+e13*e04*e07+e13*e05*e08+e06*e17*e07+e06*e18*e08-e06*e12*e02-e06*e11*e01-e06*e14*e04-e06*e15*e05; - A[2 + 10*2]=e13*e14*e07+0.5*e102*e06+e00*e10*e16+e00*e12*e18+e00*e11*e17+e10*e11*e07+e10*e01*e17+e10*e12*e08+e10*e02*e18+e03*e13*e16+e03*e15*e18+e03*e14*e17+e13*e04*e17+e13*e15*e08+e13*e05*e18+e16*e17*e07+e16*e18*e08-e16*e12*e02-e16*e11*e01-e16*e14*e04-e16*e15*e05+0.5*e132*e06+1.5*e06*e162+0.5*e06*e182+0.5*e06*e172-0.5*e06*e112-0.5*e06*e122-0.5*e06*e142-0.5*e06*e152; - A[2 + 10*3]=0.5*e102*e16+e10*e12*e18+e10*e11*e17+0.5*e132*e16+e13*e15*e18+e13*e14*e17+0.5*e163+0.5*e16*e182+0.5*e16*e172-0.5*e16*e112-0.5*e16*e122-0.5*e16*e142-0.5*e16*e152; - A[2 + 10*4]=e06*e27*e07+e23*e05*e08+e23*e04*e07+e03*e05*e28+e03*e25*e08+e03*e04*e27+e03*e24*e07+e20*e02*e08+e20*e01*e07+e00*e02*e28+e00*e22*e08+e00*e01*e27+e00*e21*e07+e00*e20*e06-e06*e25*e05-e06*e24*e04-e06*e21*e01-e06*e22*e02+e06*e28*e08-0.5*e26*e042-0.5*e26*e052-0.5*e26*e012-0.5*e26*e022+0.5*e26*e082+0.5*e26*e072+1.5*e26*e062+0.5*e002*e26+e03*e23*e06+0.5*e032*e26; - A[2 + 10*5]=e13*e05*e28+e00*e12*e28+e13*e25*e08+e13*e04*e27+e13*e24*e07+e13*e23*e06+e03*e14*e27+e03*e24*e17+e03*e15*e28+e03*e25*e18+e03*e13*e26+e03*e23*e16+e20*e02*e18+e20*e12*e08+e20*e01*e17+e20*e11*e07+e00*e21*e17+e10*e02*e28+e10*e22*e08+e10*e01*e27+e10*e21*e07+e10*e20*e06+e00*e11*e27-e26*e15*e05-e26*e14*e04-e26*e11*e01-e26*e12*e02-e16*e25*e05-e16*e24*e04-e16*e21*e01-e16*e22*e02-e06*e24*e14-e06*e22*e12-e06*e21*e11-e06*e25*e15+e00*e20*e16+e00*e22*e18+e00*e10*e26+e26*e18*e08+e26*e17*e07+e16*e28*e08+e16*e27*e07+e06*e27*e17+e06*e28*e18+3*e06*e26*e16+e23*e05*e18+e23*e15*e08+e23*e04*e17+e23*e14*e07; - A[2 + 10*6]=e10*e22*e18+0.5*e26*e182+0.5*e26*e172+e16*e28*e18+e16*e27*e17-e16*e25*e15-e16*e21*e11-e16*e22*e12+1.5*e26*e162+e13*e15*e28+e13*e24*e17+e13*e14*e27+e23*e15*e18+e23*e14*e17+e10*e12*e28+e10*e21*e17+e10*e11*e27+e20*e12*e18+e20*e11*e17+e13*e23*e16+e13*e25*e18+e10*e20*e16+0.5*e102*e26-0.5*e26*e122-0.5*e26*e142-0.5*e26*e152-e16*e24*e14-0.5*e26*e112+0.5*e132*e26; - A[2 + 10*7]=-0.5*e06*e212-0.5*e06*e252-0.5*e06*e242+0.5*e06*e272+0.5*e06*e282-0.5*e06*e222+e20*e02*e28+e03*e23*e26+e03*e24*e27+e03*e25*e28+e23*e24*e07+e23*e04*e27+e23*e25*e08+e23*e05*e28+e26*e28*e08-e26*e22*e02-e26*e21*e01-e26*e24*e04-e26*e25*e05+e26*e27*e07+e00*e20*e26+e00*e21*e27+e00*e22*e28+e20*e21*e07+e20*e01*e27+e20*e22*e08+0.5*e202*e06+0.5*e232*e06+1.5*e06*e262; - A[2 + 10*8]=-e26*e24*e14-0.5*e16*e212-0.5*e16*e252-0.5*e16*e242-e26*e25*e15-0.5*e16*e222-e26*e21*e11+e26*e28*e18+e26*e27*e17-e26*e22*e12+e23*e15*e28+e23*e24*e17+e23*e14*e27+0.5*e232*e16+1.5*e16*e262+0.5*e16*e272+0.5*e16*e282+e10*e20*e26+e10*e21*e27+e10*e22*e28+e20*e22*e18+e20*e12*e28+e20*e21*e17+e20*e11*e27+e13*e23*e26+e13*e24*e27+e13*e25*e28+e23*e25*e18+0.5*e202*e16; - A[2 + 10*9]=0.5*e202*e26+e20*e21*e27+e20*e22*e28+0.5*e232*e26+e23*e24*e27+e23*e25*e28+0.5*e263+0.5*e26*e272+0.5*e26*e282-0.5*e26*e222-0.5*e26*e212-0.5*e26*e252-0.5*e26*e242; - A[2 + 10*10]=e03*e34*e07+0.5*e032*e36+1.5*e36*e062+e03*e33*e06+e00*e31*e07+e00*e01*e37+e00*e32*e08+e00*e02*e38+e30*e01*e07+e30*e02*e08+e03*e04*e37+e03*e35*e08+e03*e05*e38+0.5*e002*e36-0.5*e36*e022-0.5*e36*e042-0.5*e36*e052+0.5*e36*e072+0.5*e36*e082-0.5*e36*e012+e33*e04*e07+e33*e05*e08+e06*e37*e07+e06*e38*e08-e06*e32*e02-e06*e31*e01-e06*e34*e04-e06*e35*e05+e00*e30*e06; - A[2 + 10*11]=e13*e33*e06+e13*e34*e07+e13*e04*e37+e13*e35*e08+e13*e05*e38+e33*e14*e07+e33*e04*e17+e33*e15*e08+e33*e05*e18+3*e06*e36*e16+e06*e38*e18+e06*e37*e17+e16*e37*e07+e16*e38*e08+e36*e17*e07+e36*e18*e08-e06*e35*e15-e06*e31*e11-e06*e32*e12+e00*e31*e17+e00*e11*e37+e10*e30*e06+e10*e31*e07+e10*e01*e37+e10*e32*e08+e10*e02*e38+e30*e11*e07+e30*e01*e17+e30*e12*e08+e30*e02*e18+e03*e33*e16+e03*e13*e36+e03*e35*e18+e03*e15*e38+e03*e34*e17+e03*e14*e37+e00*e30*e16+e00*e12*e38-e06*e34*e14-e16*e32*e02-e16*e31*e01-e16*e34*e04-e16*e35*e05-e36*e12*e02-e36*e11*e01-e36*e14*e04-e36*e15*e05+e00*e10*e36+e00*e32*e18; - A[2 + 10*12]=0.5*e36*e182+0.5*e36*e172-0.5*e36*e112-0.5*e36*e122-0.5*e36*e142-0.5*e36*e152+0.5*e102*e36+0.5*e132*e36+1.5*e36*e162+e10*e30*e16+e10*e32*e18+e10*e12*e38+e10*e31*e17+e10*e11*e37+e30*e12*e18+e30*e11*e17+e13*e33*e16+e13*e35*e18+e13*e15*e38+e13*e34*e17+e13*e14*e37+e33*e15*e18+e33*e14*e17+e16*e38*e18+e16*e37*e17-e16*e35*e15-e16*e31*e11-e16*e32*e12-e16*e34*e14; - A[2 + 10*13]=e00*e20*e36+e00*e31*e27+e00*e21*e37+e00*e32*e28+e00*e22*e38+e20*e30*e06+e20*e31*e07+e20*e01*e37+e20*e32*e08+e20*e02*e38+e30*e21*e07+e30*e01*e27+e30*e22*e08+e30*e02*e28+e03*e33*e26+e03*e23*e36+e03*e34*e27+e03*e24*e37+e03*e35*e28-e26*e31*e01-e26*e35*e05-e36*e22*e02-e36*e21*e01-e36*e24*e04-e36*e25*e05-e26*e34*e04+e03*e25*e38+e23*e34*e07+e23*e04*e37+e23*e35*e08+e23*e05*e38+e33*e24*e07+e33*e04*e27+e33*e25*e08+e33*e05*e28+3*e06*e36*e26+e06*e37*e27+e06*e38*e28+e26*e37*e07+e26*e38*e08+e36*e27*e07+e36*e28*e08-e06*e32*e22-e06*e31*e21-e06*e35*e25-e06*e34*e24-e26*e32*e02+e00*e30*e26+e23*e33*e06; - A[2 + 10*14]=e10*e30*e26+e10*e20*e36+e10*e31*e27+e10*e21*e37+e10*e32*e28+e10*e22*e38+e20*e30*e16+e20*e32*e18+e20*e12*e38+e20*e31*e17+e20*e11*e37+e30*e22*e18+e30*e12*e28+e30*e21*e17+e30*e11*e27+e13*e33*e26+e13*e23*e36+e13*e34*e27+e13*e24*e37+e13*e35*e28+e13*e25*e38+e23*e33*e16+e23*e35*e18+e23*e15*e38+e23*e34*e17+e23*e14*e37+e33*e25*e18+e33*e15*e28+e33*e24*e17+e33*e14*e27+3*e16*e36*e26+e16*e37*e27+e16*e38*e28+e26*e38*e18+e26*e37*e17+e36*e28*e18+e36*e27*e17-e16*e32*e22-e16*e31*e21-e16*e35*e25-e16*e34*e24-e26*e35*e15-e26*e31*e11-e26*e32*e12-e26*e34*e14-e36*e25*e15-e36*e21*e11-e36*e22*e12-e36*e24*e14; - A[2 + 10*15]=e33*e25*e28+e20*e30*e26+e20*e32*e28+e20*e31*e27+e20*e21*e37+e20*e22*e38+e30*e21*e27+e30*e22*e28+e23*e33*e26+e23*e34*e27+e23*e24*e37+e23*e35*e28+e23*e25*e38+e33*e24*e27+e26*e37*e27+e26*e38*e28-e26*e32*e22-e26*e31*e21-e26*e35*e25-e26*e34*e24+0.5*e202*e36+0.5*e232*e36+1.5*e36*e262+0.5*e36*e272+0.5*e36*e282-0.5*e36*e222-0.5*e36*e212-0.5*e36*e252-0.5*e36*e242; - A[2 + 10*16]=e00*e30*e36+e00*e32*e38+e00*e31*e37+e30*e31*e07+e30*e01*e37+e30*e32*e08+e30*e02*e38+e03*e33*e36-0.5*e06*e342+e03*e35*e38+e33*e34*e07+e33*e04*e37+e33*e35*e08+e33*e05*e38+e36*e37*e07+e36*e38*e08-e36*e32*e02-e36*e31*e01-e36*e34*e04-e36*e35*e05+e03*e34*e37+0.5*e302*e06+0.5*e332*e06+1.5*e06*e362+0.5*e06*e382+0.5*e06*e372-0.5*e06*e352-0.5*e06*e312-0.5*e06*e322; - A[2 + 10*17]=-e36*e35*e15+e10*e30*e36+0.5*e302*e16+0.5*e332*e16+1.5*e16*e362+0.5*e16*e382+0.5*e16*e372-0.5*e16*e352-0.5*e16*e312-0.5*e16*e322-0.5*e16*e342+e10*e32*e38+e10*e31*e37+e30*e32*e18+e30*e12*e38+e30*e31*e17+e30*e11*e37+e13*e33*e36+e13*e35*e38+e13*e34*e37+e33*e35*e18+e33*e15*e38+e33*e34*e17+e33*e14*e37+e36*e38*e18+e36*e37*e17-e36*e31*e11-e36*e32*e12-e36*e34*e14; - A[2 + 10*18]=-e36*e35*e25+e30*e32*e28+0.5*e302*e26+0.5*e332*e26+1.5*e26*e362+0.5*e26*e382+0.5*e26*e372-0.5*e26*e352-0.5*e26*e312-0.5*e26*e322-0.5*e26*e342+e20*e30*e36+e20*e32*e38+e20*e31*e37+e30*e31*e27+e30*e21*e37+e30*e22*e38+e23*e33*e36+e23*e35*e38+e23*e34*e37+e33*e34*e27+e33*e24*e37+e33*e35*e28+e33*e25*e38+e36*e37*e27+e36*e38*e28-e36*e32*e22-e36*e31*e21-e36*e34*e24; - A[2 + 10*19]=0.5*e302*e36+e30*e32*e38+e30*e31*e37+0.5*e332*e36+e33*e35*e38+e33*e34*e37+0.5*e363+0.5*e36*e382+0.5*e36*e372-0.5*e36*e352-0.5*e36*e312-0.5*e36*e322-0.5*e36*e342; - A[3 + 10*0]=0.5*e01*e002+0.5*e013+0.5*e01*e022+e04*e00*e03+0.5*e01*e042+e04*e02*e05+e07*e00*e06+0.5*e01*e072+e07*e02*e08-0.5*e01*e032-0.5*e01*e052-0.5*e01*e062-0.5*e01*e082; - A[3 + 10*1]=1.5*e11*e012+0.5*e11*e002+0.5*e11*e022+0.5*e11*e042+0.5*e11*e072-0.5*e11*e032-0.5*e11*e052-0.5*e11*e062-0.5*e11*e082+e01*e10*e00+e01*e12*e02+e04*e10*e03+e04*e00*e13+e04*e01*e14+e04*e12*e05+e04*e02*e15+e14*e00*e03+e14*e02*e05+e07*e10*e06+e07*e00*e16+e07*e01*e17+e07*e12*e08+e07*e02*e18+e17*e00*e06+e17*e02*e08-e01*e13*e03-e01*e16*e06-e01*e15*e05-e01*e18*e08; - A[3 + 10*2]=e17*e02*e18+e14*e10*e03+e11*e12*e02-e11*e18*e08+0.5*e01*e102+0.5*e01*e122+1.5*e01*e112+0.5*e01*e142+0.5*e01*e172-0.5*e01*e132-0.5*e01*e152-0.5*e01*e162-0.5*e01*e182+e11*e10*e00+e04*e10*e13+e04*e12*e15+e04*e11*e14+e14*e00*e13+e14*e12*e05+e14*e02*e15+e07*e10*e16+e07*e12*e18+e07*e11*e17+e17*e10*e06+e17*e00*e16+e17*e12*e08-e11*e13*e03-e11*e16*e06-e11*e15*e05; - A[3 + 10*3]=0.5*e11*e102+0.5*e11*e122+0.5*e113+e14*e10*e13+e14*e12*e15+0.5*e11*e142+e17*e10*e16+e17*e12*e18+0.5*e11*e172-0.5*e11*e132-0.5*e11*e152-0.5*e11*e162-0.5*e11*e182; - A[3 + 10*4]=-e01*e25*e05-e01*e26*e06-e01*e23*e03+e27*e02*e08+e27*e00*e06+e07*e02*e28+e07*e22*e08+e07*e01*e27+e07*e00*e26+e24*e02*e05+e24*e00*e03+e04*e02*e25+e04*e22*e05+e04*e01*e24+e04*e00*e23+e04*e20*e03+e01*e22*e02+e01*e20*e00-e01*e28*e08+e07*e20*e06+0.5*e21*e072+0.5*e21*e042+0.5*e21*e022+0.5*e21*e002+1.5*e21*e012-0.5*e21*e082-0.5*e21*e052-0.5*e21*e062-0.5*e21*e032; - A[3 + 10*5]=e11*e20*e00+e07*e20*e16+3*e01*e21*e11+e01*e22*e12-e21*e18*e08-e21*e15*e05-e21*e16*e06-e21*e13*e03-e11*e28*e08-e11*e25*e05-e11*e26*e06-e11*e23*e03-e01*e28*e18-e01*e23*e13-e01*e25*e15-e01*e26*e16+e27*e02*e18+e27*e12*e08+e27*e00*e16+e27*e10*e06+e17*e02*e28+e17*e22*e08+e17*e01*e27+e17*e00*e26+e17*e20*e06+e07*e11*e27+e07*e21*e17+e07*e12*e28+e07*e22*e18+e07*e10*e26+e24*e02*e15+e24*e12*e05+e24*e00*e13+e24*e10*e03+e14*e02*e25+e14*e22*e05+e14*e01*e24+e14*e00*e23+e14*e20*e03+e04*e11*e24+e04*e21*e14+e04*e12*e25+e04*e22*e15+e21*e12*e02+e04*e20*e13+e01*e20*e10+e11*e22*e02+e21*e10*e00+e04*e10*e23; - A[3 + 10*6]=1.5*e21*e112+0.5*e21*e102+0.5*e21*e122+e11*e20*e10+e11*e22*e12+e14*e10*e23+e14*e22*e15+e14*e12*e25-0.5*e21*e162-0.5*e21*e152-0.5*e21*e132-0.5*e21*e182+e27*e12*e18-e11*e26*e16-e11*e25*e15-e11*e23*e13-e11*e28*e18+e17*e20*e16+e17*e10*e26+e17*e22*e18+e17*e12*e28+e17*e11*e27+e27*e10*e16+0.5*e21*e172+e14*e11*e24+e24*e10*e13+e24*e12*e15+0.5*e21*e142+e14*e20*e13; - A[3 + 10*7]=-0.5*e01*e262-0.5*e01*e282-0.5*e01*e252-0.5*e01*e232+0.5*e01*e272+e27*e22*e08+e27*e02*e28-e21*e23*e03-e21*e26*e06-e21*e25*e05-e21*e28*e08+e04*e22*e25+e24*e20*e03+e24*e00*e23+e24*e22*e05+e24*e02*e25+e07*e20*e26+e07*e21*e27+e07*e22*e28+e27*e20*e06+e27*e00*e26+e21*e20*e00+e21*e22*e02+e04*e20*e23+e04*e21*e24+0.5*e01*e222+0.5*e01*e242+1.5*e01*e212+0.5*e01*e202; - A[3 + 10*8]=-0.5*e11*e282-0.5*e11*e252-e21*e26*e16+e27*e12*e28-e21*e25*e15-e21*e23*e13-e21*e28*e18+e17*e20*e26+e17*e21*e27+e17*e22*e28+e27*e20*e16+e27*e10*e26+e27*e22*e18+0.5*e11*e242+0.5*e11*e272-0.5*e11*e232-0.5*e11*e262+0.5*e11*e202+1.5*e11*e212+0.5*e11*e222+e21*e20*e10+e14*e20*e23+e14*e21*e24+e14*e22*e25+e24*e20*e13+e24*e10*e23+e24*e22*e15+e24*e12*e25+e21*e22*e12; - A[3 + 10*9]=0.5*e21*e202+0.5*e213+0.5*e21*e222+e24*e20*e23+0.5*e21*e242+e24*e22*e25+e27*e20*e26+0.5*e21*e272+e27*e22*e28-0.5*e21*e232-0.5*e21*e262-0.5*e21*e282-0.5*e21*e252; - A[3 + 10*10]=-0.5*e31*e032-0.5*e31*e052-0.5*e31*e062-0.5*e31*e082+e07*e30*e06+e07*e00*e36+e07*e01*e37+e07*e32*e08+e07*e02*e38+e37*e00*e06+e37*e02*e08-e01*e33*e03-e01*e36*e06-e01*e35*e05-e01*e38*e08+0.5*e31*e072+e04*e30*e03+e04*e00*e33+e04*e01*e34+e04*e32*e05+e04*e02*e35+e34*e00*e03+e34*e02*e05+0.5*e31*e002+0.5*e31*e022+0.5*e31*e042+e01*e30*e00+e01*e32*e02+1.5*e31*e012; - A[3 + 10*11]=e34*e12*e05+e34*e02*e15+e07*e10*e36+e07*e32*e18+e07*e12*e38+e07*e31*e17+e07*e11*e37+e17*e30*e06+e17*e00*e36+e17*e01*e37+e17*e32*e08+e17*e02*e38+e37*e10*e06+e37*e00*e16+e37*e12*e08+e37*e02*e18-e01*e36*e16-e01*e35*e15-e01*e33*e13-e01*e38*e18-e11*e33*e03-e11*e36*e06-e11*e35*e05+e01*e30*e10+e01*e32*e12+3*e01*e31*e11+e11*e30*e00+e11*e32*e02+e31*e10*e00+e31*e12*e02+e04*e30*e13+e04*e10*e33+e04*e32*e15+e04*e12*e35+e04*e31*e14+e04*e11*e34+e14*e30*e03+e14*e00*e33+e14*e01*e34+e14*e32*e05+e14*e02*e35+e34*e10*e03+e34*e00*e13+e07*e30*e16-e11*e38*e08-e31*e13*e03-e31*e16*e06-e31*e15*e05-e31*e18*e08; - A[3 + 10*12]=-e11*e33*e13-e11*e38*e18+0.5*e31*e142+0.5*e31*e172-0.5*e31*e162-0.5*e31*e152-0.5*e31*e132-0.5*e31*e182+0.5*e31*e122+0.5*e31*e102+e11*e30*e10+e11*e32*e12+e14*e30*e13+e14*e10*e33+e14*e32*e15+e14*e12*e35+e14*e11*e34+e34*e10*e13+e34*e12*e15+e17*e30*e16+e17*e10*e36+e17*e32*e18+e17*e12*e38+e17*e11*e37+e37*e10*e16+e37*e12*e18-e11*e36*e16-e11*e35*e15+1.5*e31*e112; - A[3 + 10*13]=-e21*e35*e05+e07*e32*e28+e01*e30*e20-e21*e33*e03-e21*e36*e06-e21*e38*e08-e31*e23*e03-e31*e26*e06-e31*e25*e05-e31*e28*e08+3*e01*e31*e21+e01*e32*e22+e21*e30*e00+e21*e32*e02+e31*e20*e00+e31*e22*e02+e04*e30*e23+e04*e20*e33+e04*e31*e24+e04*e21*e34+e04*e32*e25+e04*e22*e35+e24*e30*e03+e24*e00*e33+e24*e01*e34+e24*e32*e05+e24*e02*e35+e34*e20*e03+e34*e00*e23+e34*e22*e05+e34*e02*e25+e07*e30*e26+e07*e20*e36+e07*e31*e27+e07*e21*e37+e07*e22*e38+e27*e30*e06+e27*e00*e36+e27*e01*e37+e27*e32*e08+e27*e02*e38+e37*e00*e26+e37*e22*e08+e37*e02*e28-e01*e33*e23-e01*e36*e26-e01*e38*e28-e01*e35*e25+e37*e20*e06; - A[3 + 10*14]=e11*e32*e22+e34*e12*e25+e11*e30*e20+3*e11*e31*e21+e21*e30*e10+e21*e32*e12+e34*e10*e23+e34*e22*e15+e17*e30*e26+e17*e20*e36+e17*e31*e27+e17*e21*e37+e17*e32*e28+e17*e22*e38+e27*e30*e16+e27*e10*e36+e27*e32*e18+e27*e12*e38+e27*e11*e37+e37*e20*e16+e37*e10*e26+e37*e22*e18+e37*e12*e28-e11*e33*e23-e11*e36*e26-e11*e38*e28-e11*e35*e25-e21*e36*e16-e21*e35*e15-e21*e33*e13-e21*e38*e18-e31*e26*e16-e31*e25*e15-e31*e23*e13-e31*e28*e18+e31*e20*e10+e31*e22*e12+e14*e30*e23+e14*e20*e33+e14*e31*e24+e14*e21*e34+e14*e32*e25+e14*e22*e35+e24*e30*e13+e24*e10*e33+e24*e32*e15+e24*e12*e35+e24*e11*e34+e34*e20*e13; - A[3 + 10*15]=-e21*e36*e26+e37*e22*e28-e21*e33*e23-e21*e38*e28-e21*e35*e25+0.5*e31*e222+0.5*e31*e242+0.5*e31*e272-0.5*e31*e232-0.5*e31*e262-0.5*e31*e282-0.5*e31*e252+e21*e30*e20+e21*e32*e22+e24*e30*e23+e24*e20*e33+e24*e21*e34+e24*e32*e25+e24*e22*e35+e34*e20*e23+e34*e22*e25+e27*e30*e26+e27*e20*e36+e27*e21*e37+e27*e32*e28+e27*e22*e38+e37*e20*e26+1.5*e31*e212+0.5*e31*e202; - A[3 + 10*16]=e04*e32*e35+0.5*e01*e372-0.5*e01*e352-0.5*e01*e362-0.5*e01*e332-0.5*e01*e382+e04*e31*e34+e34*e30*e03+e34*e00*e33+e34*e32*e05+e34*e02*e35+e07*e30*e36+e07*e32*e38+e07*e31*e37+e37*e30*e06+e37*e00*e36+e37*e32*e08+e04*e30*e33+e37*e02*e38-e31*e33*e03-e31*e36*e06-e31*e35*e05-e31*e38*e08+0.5*e01*e302+0.5*e01*e322+1.5*e01*e312+0.5*e01*e342+e31*e30*e00+e31*e32*e02; - A[3 + 10*17]=e31*e32*e12+e14*e30*e33+e14*e32*e35+e14*e31*e34+e34*e30*e13+e34*e10*e33+e34*e32*e15+e34*e12*e35+e17*e30*e36+e17*e32*e38+e17*e31*e37+e37*e30*e16+e37*e10*e36+e37*e32*e18+e37*e12*e38-e31*e36*e16-e31*e35*e15+0.5*e11*e302+0.5*e11*e322+1.5*e11*e312-e31*e33*e13-e31*e38*e18+0.5*e11*e342+0.5*e11*e372+e31*e30*e10-0.5*e11*e352-0.5*e11*e362-0.5*e11*e332-0.5*e11*e382; - A[3 + 10*18]=e34*e32*e25+0.5*e21*e342+0.5*e21*e372-0.5*e21*e352-0.5*e21*e362-0.5*e21*e332-0.5*e21*e382+0.5*e21*e302+0.5*e21*e322+1.5*e21*e312+e31*e30*e20+e31*e32*e22+e24*e30*e33+e24*e32*e35+e24*e31*e34+e34*e30*e23+e34*e20*e33+e34*e22*e35+e27*e30*e36+e27*e32*e38+e27*e31*e37+e37*e30*e26+e37*e20*e36+e37*e32*e28+e37*e22*e38-e31*e33*e23-e31*e36*e26-e31*e38*e28-e31*e35*e25; - A[3 + 10*19]=0.5*e31*e302+0.5*e31*e322+0.5*e313+e34*e30*e33+e34*e32*e35+0.5*e31*e342+e37*e30*e36+e37*e32*e38+0.5*e31*e372-0.5*e31*e352-0.5*e31*e362-0.5*e31*e332-0.5*e31*e382; - A[4 + 10*0]=e01*e00*e03+0.5*e012*e04+e01*e02*e05+0.5*e04*e032+0.5*e043+0.5*e04*e052+e07*e03*e06+0.5*e04*e072+e07*e05*e08-0.5*e04*e002-0.5*e04*e022-0.5*e04*e062-0.5*e04*e082; - A[4 + 10*1]=e07*e13*e06+e01*e10*e03-0.5*e14*e002-0.5*e14*e022-0.5*e14*e062-0.5*e14*e082+e01*e00*e13+e01*e11*e04+e01*e12*e05+e01*e02*e15+e11*e00*e03+e11*e02*e05+e04*e13*e03+e04*e15*e05+e07*e03*e16+e07*e04*e17+e07*e15*e08+e07*e05*e18+e17*e03*e06+e17*e05*e08-e04*e10*e00-e04*e12*e02-e04*e16*e06-e04*e18*e08+0.5*e012*e14+1.5*e14*e042+0.5*e14*e032+0.5*e14*e052+0.5*e14*e072; - A[4 + 10*2]=e11*e10*e03+0.5*e112*e04+0.5*e04*e132+0.5*e04*e152+1.5*e04*e142+0.5*e04*e172-0.5*e04*e102-0.5*e04*e162-0.5*e04*e122-0.5*e04*e182+e01*e10*e13+e01*e12*e15+e01*e11*e14+e11*e00*e13+e11*e12*e05+e11*e02*e15+e14*e13*e03+e14*e15*e05+e07*e13*e16+e07*e15*e18+e07*e14*e17+e17*e13*e06+e17*e03*e16+e17*e15*e08+e17*e05*e18-e14*e10*e00-e14*e12*e02-e14*e16*e06-e14*e18*e08; - A[4 + 10*3]=e11*e10*e13+e11*e12*e15+0.5*e112*e14+0.5*e14*e132+0.5*e14*e152+0.5*e143+e17*e13*e16+e17*e15*e18+0.5*e14*e172-0.5*e14*e102-0.5*e14*e162-0.5*e14*e122-0.5*e14*e182; - A[4 + 10*4]=-e04*e28*e08-e04*e26*e06-e04*e22*e02-e04*e20*e00+e27*e05*e08+e27*e03*e06+e07*e05*e28+e07*e25*e08+e07*e04*e27+e07*e03*e26+e07*e23*e06+e04*e25*e05+e04*e23*e03+e21*e02*e05+e21*e00*e03+e01*e02*e25+e01*e22*e05+e01*e21*e04+e01*e00*e23+e01*e20*e03+0.5*e012*e24+0.5*e24*e072+0.5*e24*e052+0.5*e24*e032+1.5*e24*e042-0.5*e24*e022-0.5*e24*e002-0.5*e24*e082-0.5*e24*e062; - A[4 + 10*5]=e11*e02*e25+e11*e22*e05+e11*e21*e04-e24*e18*e08-e24*e16*e06-e24*e12*e02-e14*e28*e08-e14*e26*e06-e14*e22*e02-e14*e20*e00-e04*e28*e18-e04*e22*e12-e04*e26*e16-e04*e20*e10+e27*e05*e18+e27*e15*e08+e27*e03*e16+e27*e13*e06+e17*e05*e28+e17*e25*e08+e17*e04*e27+e17*e03*e26+e17*e23*e06+e07*e14*e27+e07*e24*e17+e07*e15*e28+e07*e25*e18+e07*e13*e26+e07*e23*e16+e24*e15*e05+e24*e13*e03+e14*e25*e05+e14*e23*e03+3*e04*e24*e14+e04*e25*e15+e04*e23*e13+e21*e02*e15+e21*e12*e05+e21*e00*e13+e21*e10*e03-e24*e10*e00+e01*e20*e13+e01*e10*e23+e01*e22*e15+e01*e12*e25+e01*e11*e24+e11*e20*e03+e11*e00*e23+e01*e21*e14; - A[4 + 10*6]=e11*e12*e25-0.5*e24*e182-0.5*e24*e102-0.5*e24*e162-0.5*e24*e122+e27*e13*e16+e27*e15*e18-e14*e20*e10-e14*e26*e16-e14*e22*e12-e14*e28*e18+e17*e15*e28+e17*e14*e27+1.5*e24*e142+0.5*e24*e132+0.5*e24*e152+0.5*e112*e24+0.5*e24*e172+e11*e21*e14+e11*e22*e15+e11*e10*e23+e11*e20*e13+e21*e10*e13+e21*e12*e15+e17*e13*e26+e17*e23*e16+e14*e25*e15+e14*e23*e13+e17*e25*e18; - A[4 + 10*7]=e27*e03*e26+e27*e25*e08+e27*e05*e28-e24*e20*e00-e24*e22*e02-e24*e26*e06-e24*e28*e08+0.5*e04*e232+1.5*e04*e242+0.5*e04*e252+0.5*e04*e272-0.5*e04*e202-0.5*e04*e222-0.5*e04*e262-0.5*e04*e282+e24*e23*e03+e24*e25*e05+e07*e23*e26+e07*e24*e27+e07*e25*e28+e27*e23*e06+e21*e20*e03+e21*e00*e23+e21*e22*e05+e21*e02*e25+0.5*e212*e04+e01*e20*e23+e01*e21*e24+e01*e22*e25; - A[4 + 10*8]=-e24*e22*e12-e24*e28*e18+0.5*e14*e272-0.5*e14*e202-0.5*e14*e222-0.5*e14*e262-0.5*e14*e282+e17*e23*e26+e17*e24*e27+e17*e25*e28+e27*e23*e16+e27*e13*e26+e27*e25*e18+e27*e15*e28-e24*e20*e10-e24*e26*e16+0.5*e14*e232+1.5*e14*e242+0.5*e14*e252+e21*e10*e23+e21*e22*e15+e21*e12*e25+e24*e23*e13+e24*e25*e15+e21*e20*e13+0.5*e212*e14+e11*e20*e23+e11*e22*e25+e11*e21*e24; - A[4 + 10*9]=e21*e20*e23+0.5*e212*e24+e21*e22*e25+0.5*e24*e232+0.5*e243+0.5*e24*e252+e27*e23*e26+0.5*e24*e272+e27*e25*e28-0.5*e24*e202-0.5*e24*e222-0.5*e24*e262-0.5*e24*e282; - A[4 + 10*10]=-e04*e38*e08-e04*e32*e02-e04*e36*e06-0.5*e34*e002-0.5*e34*e022-0.5*e34*e062-0.5*e34*e082+e37*e03*e06+e37*e05*e08-e04*e30*e00+0.5*e34*e032+0.5*e34*e052+0.5*e34*e072+1.5*e34*e042+e01*e30*e03+e01*e00*e33+e01*e31*e04+e01*e32*e05+e01*e02*e35+e31*e00*e03+e31*e02*e05+e04*e33*e03+e04*e35*e05+e07*e03*e36+e07*e04*e37+e07*e35*e08+e07*e05*e38+0.5*e012*e34+e07*e33*e06; - A[4 + 10*11]=e07*e13*e36+e01*e12*e35-e04*e30*e10+e17*e04*e37+e17*e35*e08+e17*e05*e38+e37*e13*e06+e37*e03*e16+e37*e15*e08+e37*e05*e18-e04*e36*e16+e17*e33*e06+e04*e33*e13+e04*e35*e15+3*e04*e34*e14+e14*e33*e03+e14*e35*e05+e34*e13*e03+e34*e15*e05+e07*e33*e16+e07*e35*e18+e07*e15*e38+e07*e34*e17+e07*e14*e37+e17*e03*e36+e31*e10*e03+e01*e30*e13+e01*e10*e33+e01*e32*e15+e01*e31*e14+e01*e11*e34+e11*e30*e03+e11*e00*e33+e11*e31*e04+e11*e32*e05+e11*e02*e35+e31*e00*e13+e31*e12*e05+e31*e02*e15-e34*e12*e02-e34*e16*e06-e34*e18*e08-e14*e32*e02-e14*e36*e06-e14*e38*e08-e34*e10*e00-e04*e32*e12-e04*e38*e18-e14*e30*e00; - A[4 + 10*12]=e11*e32*e15-0.5*e34*e102-0.5*e34*e162-0.5*e34*e122-0.5*e34*e182+e37*e13*e16+0.5*e112*e34+1.5*e34*e142+0.5*e34*e132+0.5*e34*e152+0.5*e34*e172+e11*e30*e13+e11*e10*e33+e11*e12*e35+e11*e31*e14+e31*e10*e13+e31*e12*e15+e14*e33*e13+e14*e35*e15+e17*e33*e16+e17*e13*e36+e17*e35*e18+e17*e15*e38+e17*e14*e37+e37*e15*e18-e14*e30*e10-e14*e36*e16-e14*e32*e12-e14*e38*e18; - A[4 + 10*13]=e01*e22*e35-e04*e30*e20-e04*e32*e22+e01*e31*e24+e01*e21*e34+e01*e32*e25+e21*e30*e03+e21*e00*e33+e21*e31*e04+e21*e32*e05+e21*e02*e35+e31*e20*e03+e31*e00*e23+e31*e22*e05+e31*e02*e25+e04*e33*e23+3*e04*e34*e24+e04*e35*e25+e24*e33*e03+e37*e05*e28-e04*e36*e26-e04*e38*e28-e24*e30*e00-e24*e32*e02-e24*e36*e06-e24*e38*e08+e24*e35*e05+e34*e23*e03+e34*e25*e05+e07*e33*e26+e07*e23*e36+e07*e34*e27+e07*e24*e37+e07*e35*e28+e07*e25*e38+e27*e33*e06+e27*e03*e36+e27*e04*e37+e27*e35*e08+e27*e05*e38+e37*e23*e06+e37*e03*e26+e37*e25*e08-e34*e20*e00-e34*e22*e02-e34*e26*e06-e34*e28*e08+e01*e30*e23+e01*e20*e33; - A[4 + 10*14]=e21*e10*e33+e11*e30*e23+e11*e20*e33+e11*e31*e24+e11*e21*e34+e11*e32*e25+e11*e22*e35+e21*e30*e13+e21*e32*e15+e21*e12*e35+e21*e31*e14+e31*e20*e13+e31*e10*e23+e31*e22*e15+e31*e12*e25+e14*e33*e23+3*e14*e34*e24+e14*e35*e25+e24*e33*e13+e24*e35*e15+e34*e23*e13+e34*e25*e15+e17*e33*e26+e17*e23*e36+e17*e34*e27+e17*e24*e37+e17*e35*e28+e17*e25*e38+e27*e33*e16+e27*e13*e36+e27*e35*e18+e27*e15*e38+e27*e14*e37+e37*e23*e16+e37*e13*e26+e37*e25*e18+e37*e15*e28-e34*e28*e18-e34*e22*e12-e14*e32*e22-e14*e36*e26-e14*e38*e28-e24*e30*e10-e24*e36*e16-e24*e32*e12-e24*e38*e18-e34*e20*e10-e34*e26*e16-e14*e30*e20; - A[4 + 10*15]=-0.5*e34*e202-0.5*e34*e222-0.5*e34*e262-0.5*e34*e282+e37*e25*e28-e24*e32*e22-e24*e36*e26-e24*e38*e28-e24*e30*e20+0.5*e212*e34+1.5*e34*e242+0.5*e34*e232+0.5*e34*e252+0.5*e34*e272+e21*e30*e23+e21*e20*e33+e21*e31*e24+e21*e32*e25+e21*e22*e35+e31*e20*e23+e31*e22*e25+e24*e33*e23+e24*e35*e25+e27*e33*e26+e27*e23*e36+e27*e24*e37+e27*e35*e28+e27*e25*e38+e37*e23*e26; - A[4 + 10*16]=e37*e33*e06+e01*e30*e33+e01*e31*e34+e31*e30*e03+e31*e02*e35+e34*e33*e03+e34*e35*e05+e07*e33*e36+e07*e35*e38+e07*e34*e37+e37*e03*e36+e37*e35*e08+e37*e05*e38-e34*e32*e02-e34*e36*e06-e34*e38*e08+e31*e32*e05+e31*e00*e33+0.5*e312*e04+0.5*e04*e332+0.5*e04*e352+1.5*e04*e342+0.5*e04*e372+e01*e32*e35-0.5*e04*e302-0.5*e04*e322-0.5*e04*e362-0.5*e04*e382-e34*e30*e00; - A[4 + 10*17]=0.5*e14*e372-0.5*e14*e302-0.5*e14*e322-0.5*e14*e362-0.5*e14*e382+0.5*e312*e14+0.5*e14*e332+0.5*e14*e352+1.5*e14*e342+e11*e30*e33+e11*e32*e35+e11*e31*e34+e31*e30*e13+e31*e10*e33+e31*e32*e15+e31*e12*e35+e34*e33*e13+e34*e35*e15+e17*e33*e36+e17*e35*e38+e17*e34*e37+e37*e33*e16+e37*e13*e36+e37*e35*e18+e37*e15*e38-e34*e30*e10-e34*e36*e16-e34*e32*e12-e34*e38*e18; - A[4 + 10*18]=-e34*e32*e22-e34*e36*e26-e34*e38*e28+0.5*e24*e332+0.5*e24*e352+1.5*e24*e342+0.5*e24*e372-0.5*e24*e302-0.5*e24*e322-0.5*e24*e362-0.5*e24*e382+e21*e30*e33+0.5*e312*e24+e21*e32*e35+e21*e31*e34+e31*e30*e23+e31*e20*e33+e31*e32*e25+e31*e22*e35+e34*e33*e23+e34*e35*e25+e27*e33*e36+e27*e35*e38+e27*e34*e37+e37*e33*e26+e37*e23*e36+e37*e35*e28+e37*e25*e38-e34*e30*e20; - A[4 + 10*19]=e31*e30*e33+e31*e32*e35+0.5*e312*e34+0.5*e34*e332+0.5*e34*e352+0.5*e343+e37*e33*e36+e37*e35*e38+0.5*e34*e372-0.5*e34*e302-0.5*e34*e322-0.5*e34*e362-0.5*e34*e382; - A[5 + 10*0]=e01*e00*e06+0.5*e012*e07+e01*e02*e08+e04*e03*e06+0.5*e042*e07+e04*e05*e08+0.5*e07*e062+0.5*e073+0.5*e07*e082-0.5*e07*e002-0.5*e07*e022-0.5*e07*e032-0.5*e07*e052; - A[5 + 10*1]=e04*e13*e06+0.5*e042*e17+1.5*e17*e072+0.5*e17*e062+0.5*e17*e082-0.5*e17*e002-0.5*e17*e022-0.5*e17*e032-0.5*e17*e052+e01*e10*e06+e07*e16*e06+e07*e18*e08-e07*e10*e00-e07*e12*e02-e07*e13*e03-e07*e15*e05+e01*e00*e16+e01*e11*e07+e01*e12*e08+e01*e02*e18+e11*e00*e06+e11*e02*e08+e04*e03*e16+e04*e14*e07+e04*e15*e08+e04*e05*e18+e14*e03*e06+e14*e05*e08+0.5*e012*e17; - A[5 + 10*2]=-e17*e10*e00+0.5*e112*e07+0.5*e142*e07+0.5*e07*e162+0.5*e07*e182+1.5*e07*e172-0.5*e07*e102-0.5*e07*e152-0.5*e07*e132-0.5*e07*e122+e01*e10*e16+e01*e12*e18+e01*e11*e17+e11*e10*e06+e11*e00*e16+e11*e12*e08+e11*e02*e18+e04*e13*e16+e04*e15*e18+e04*e14*e17+e14*e13*e06+e14*e03*e16+e14*e15*e08+e14*e05*e18+e17*e16*e06+e17*e18*e08-e17*e12*e02-e17*e13*e03-e17*e15*e05; - A[5 + 10*3]=e11*e10*e16+e11*e12*e18+0.5*e112*e17+e14*e13*e16+e14*e15*e18+0.5*e142*e17+0.5*e17*e162+0.5*e17*e182+0.5*e173-0.5*e17*e102-0.5*e17*e152-0.5*e17*e132-0.5*e17*e122; - A[5 + 10*4]=e01*e22*e08+e07*e28*e08-e07*e20*e00-e07*e23*e03-e07*e22*e02-e07*e25*e05+0.5*e012*e27+0.5*e042*e27+1.5*e27*e072+0.5*e27*e062+0.5*e27*e082-0.5*e27*e002-0.5*e27*e022-0.5*e27*e032-0.5*e27*e052+e07*e26*e06+e01*e20*e06+e01*e00*e26+e01*e21*e07+e01*e02*e28+e21*e00*e06+e21*e02*e08+e04*e23*e06+e04*e03*e26+e04*e24*e07+e04*e25*e08+e04*e05*e28+e24*e03*e06+e24*e05*e08; - A[5 + 10*5]=e14*e24*e07+e14*e03*e26+e14*e23*e06+e04*e14*e27+e04*e24*e17+e04*e15*e28+e04*e25*e18+e04*e13*e26+e04*e23*e16+e21*e02*e18+e21*e12*e08-e27*e15*e05-e27*e13*e03-e27*e12*e02-e27*e10*e00-e17*e25*e05-e17*e23*e03-e17*e22*e02-e17*e20*e00-e07*e22*e12-e07*e23*e13-e07*e25*e15-e07*e20*e10+e27*e18*e08+e27*e16*e06+e17*e28*e08+e17*e26*e06+3*e07*e27*e17+e07*e28*e18+e07*e26*e16+e24*e05*e18+e24*e15*e08+e24*e03*e16+e24*e13*e06+e14*e05*e28+e14*e25*e08+e01*e12*e28+e01*e20*e16+e01*e10*e26+e01*e22*e18+e01*e21*e17+e11*e20*e06+e01*e11*e27+e21*e00*e16+e21*e10*e06+e11*e21*e07+e11*e22*e08+e11*e02*e28+e11*e00*e26; - A[5 + 10*6]=-0.5*e27*e102-0.5*e27*e152-0.5*e27*e132-0.5*e27*e122+0.5*e142*e27+1.5*e27*e172+0.5*e27*e162+0.5*e27*e182+0.5*e112*e27+e11*e22*e18+e11*e10*e26+e11*e20*e16-e17*e22*e12-e17*e23*e13-e17*e25*e15-e17*e20*e10+e17*e28*e18+e17*e26*e16+e24*e15*e18+e24*e13*e16+e14*e24*e17+e14*e15*e28+e14*e25*e18+e14*e13*e26+e14*e23*e16+e21*e12*e18+e21*e10*e16+e11*e21*e17+e11*e12*e28; - A[5 + 10*7]=-0.5*e07*e252+e27*e26*e06+e27*e28*e08-e27*e20*e00-e27*e22*e02-e27*e23*e03-e27*e25*e05+1.5*e07*e272+0.5*e07*e282+e01*e22*e28+e21*e20*e06+e21*e00*e26+e21*e22*e08+e21*e02*e28+e04*e23*e26+e04*e24*e27+e04*e25*e28+e24*e23*e06+e24*e03*e26+e24*e25*e08+e24*e05*e28+0.5*e212*e07+0.5*e242*e07+0.5*e07*e262+e01*e20*e26+e01*e21*e27-0.5*e07*e202-0.5*e07*e232-0.5*e07*e222; - A[5 + 10*8]=-e27*e25*e15-e27*e23*e13-e27*e22*e12-0.5*e17*e252-0.5*e17*e202-0.5*e17*e222-0.5*e17*e232+0.5*e17*e262+1.5*e17*e272+0.5*e17*e282+e24*e23*e16+e24*e13*e26+e24*e25*e18+e24*e15*e28+e27*e26*e16+e27*e28*e18-e27*e20*e10+e14*e24*e27+e14*e25*e28+0.5*e212*e17+0.5*e242*e17+e11*e20*e26+e11*e21*e27+e11*e22*e28+e21*e20*e16+e21*e10*e26+e21*e22*e18+e21*e12*e28+e14*e23*e26; - A[5 + 10*9]=e21*e20*e26+0.5*e212*e27+e21*e22*e28+e24*e23*e26+0.5*e242*e27+e24*e25*e28+0.5*e27*e262+0.5*e273+0.5*e27*e282-0.5*e27*e202-0.5*e27*e222-0.5*e27*e232-0.5*e27*e252; - A[5 + 10*10]=e04*e05*e38+e01*e30*e06-0.5*e37*e002-0.5*e37*e022-0.5*e37*e032-0.5*e37*e052-e07*e32*e02-e07*e35*e05-e07*e33*e03+e07*e36*e06+e07*e38*e08-e07*e30*e00+1.5*e37*e072+0.5*e37*e062+0.5*e37*e082+e01*e02*e38+e31*e00*e06+e31*e02*e08+e04*e33*e06+e04*e03*e36+e04*e34*e07+e04*e35*e08+e34*e03*e06+e34*e05*e08+0.5*e012*e37+0.5*e042*e37+e01*e00*e36+e01*e31*e07+e01*e32*e08; - A[5 + 10*11]=e14*e33*e06+e11*e30*e06+e11*e00*e36+e11*e31*e07+e31*e10*e06+e11*e32*e08+e11*e02*e38+e31*e00*e16+e31*e12*e08+e31*e02*e18+e04*e33*e16+e04*e13*e36+e04*e35*e18+e04*e15*e38+e01*e10*e36+e01*e32*e18+e01*e12*e38+e01*e31*e17+e01*e11*e37+e01*e30*e16-e17*e35*e05-e37*e10*e00-e37*e12*e02-e37*e13*e03-e37*e15*e05+e37*e18*e08-e07*e30*e10-e07*e35*e15-e07*e33*e13-e07*e32*e12-e17*e30*e00-e17*e32*e02-e17*e33*e03+e07*e38*e18+3*e07*e37*e17+e17*e36*e06+e17*e38*e08+e37*e16*e06+e04*e34*e17+e04*e14*e37+e14*e03*e36+e14*e34*e07+e14*e35*e08+e14*e05*e38+e34*e13*e06+e34*e03*e16+e34*e15*e08+e34*e05*e18+e07*e36*e16; - A[5 + 10*12]=e11*e32*e18-0.5*e37*e102-0.5*e37*e152-0.5*e37*e132-0.5*e37*e122+0.5*e112*e37+0.5*e142*e37+1.5*e37*e172+0.5*e37*e162+0.5*e37*e182+e11*e10*e36+e11*e12*e38+e11*e31*e17+e31*e10*e16+e31*e12*e18+e14*e33*e16+e14*e13*e36+e14*e35*e18+e14*e15*e38+e14*e34*e17+e34*e13*e16+e34*e15*e18+e17*e36*e16+e17*e38*e18-e17*e30*e10-e17*e35*e15-e17*e33*e13-e17*e32*e12+e11*e30*e16; - A[5 + 10*13]=e01*e20*e36+e01*e31*e27+e01*e21*e37+e01*e32*e28+e01*e22*e38+e21*e30*e06+e21*e00*e36+e21*e31*e07+e21*e32*e08+e21*e02*e38+e01*e30*e26+e31*e20*e06+e31*e00*e26+e31*e22*e08+e31*e02*e28+e04*e33*e26+e04*e23*e36+e04*e34*e27+e04*e24*e37+e04*e35*e28+e04*e25*e38+e24*e33*e06+e24*e03*e36+e24*e34*e07+e24*e35*e08+e24*e05*e38+e34*e23*e06+e34*e03*e26+e34*e25*e08+e34*e05*e28+e07*e36*e26+3*e07*e37*e27+e07*e38*e28+e27*e36*e06+e27*e38*e08+e37*e26*e06+e37*e28*e08-e07*e30*e20-e07*e32*e22-e07*e33*e23-e07*e35*e25-e27*e30*e00-e27*e32*e02-e27*e33*e03-e27*e35*e05-e37*e20*e00-e37*e22*e02-e37*e23*e03-e37*e25*e05; - A[5 + 10*14]=e11*e30*e26+e11*e20*e36+e11*e31*e27+e11*e21*e37+e11*e32*e28+e11*e22*e38+e21*e10*e36+e21*e32*e18+e21*e12*e38+e21*e31*e17+e31*e20*e16+e31*e10*e26+e31*e22*e18+e31*e12*e28+e14*e33*e26+e14*e23*e36+e14*e34*e27+e14*e24*e37+e14*e35*e28+e14*e25*e38+e24*e33*e16+e24*e13*e36+e24*e35*e18+e24*e15*e38+e24*e34*e17+e34*e23*e16+e34*e13*e26+e34*e25*e18+e34*e15*e28+e17*e36*e26+3*e17*e37*e27+e17*e38*e28+e27*e36*e16+e27*e38*e18+e37*e26*e16+e37*e28*e18-e17*e30*e20-e17*e32*e22-e17*e33*e23-e17*e35*e25-e27*e30*e10-e27*e35*e15-e27*e33*e13-e27*e32*e12-e37*e20*e10-e37*e25*e15-e37*e23*e13-e37*e22*e12+e21*e30*e16; - A[5 + 10*15]=e21*e20*e36+e21*e31*e27+e21*e32*e28+e21*e22*e38+e31*e22*e28+e24*e33*e26+e24*e23*e36+e24*e34*e27+e24*e35*e28+e24*e25*e38+e34*e23*e26+e34*e25*e28+e27*e36*e26+e27*e38*e28-e27*e30*e20-e27*e32*e22-e27*e33*e23-e27*e35*e25+0.5*e242*e37+1.5*e37*e272+0.5*e37*e262+0.5*e37*e282+e31*e20*e26+e21*e30*e26+0.5*e212*e37-0.5*e37*e202-0.5*e37*e222-0.5*e37*e232-0.5*e37*e252; - A[5 + 10*16]=e01*e30*e36+e01*e32*e38+e01*e31*e37+e31*e30*e06+e31*e00*e36+e31*e32*e08+e31*e02*e38+e04*e33*e36+e04*e35*e38+e04*e34*e37+e34*e33*e06+e34*e03*e36+e34*e35*e08+e34*e05*e38+e37*e36*e06+e37*e38*e08-e37*e30*e00-e37*e32*e02-e37*e33*e03-e37*e35*e05+0.5*e312*e07+0.5*e342*e07+0.5*e07*e362+0.5*e07*e382+1.5*e07*e372-0.5*e07*e302-0.5*e07*e352-0.5*e07*e322-0.5*e07*e332; - A[5 + 10*17]=0.5*e312*e17+0.5*e342*e17+0.5*e17*e362+0.5*e17*e382+1.5*e17*e372-0.5*e17*e302-0.5*e17*e352-0.5*e17*e322-0.5*e17*e332-e37*e32*e12-e37*e33*e13+e11*e30*e36+e11*e32*e38+e11*e31*e37+e31*e30*e16+e31*e10*e36+e31*e32*e18+e31*e12*e38+e14*e33*e36+e14*e35*e38+e14*e34*e37+e34*e33*e16+e34*e13*e36+e34*e35*e18+e34*e15*e38+e37*e36*e16+e37*e38*e18-e37*e30*e10-e37*e35*e15; - A[5 + 10*18]=e21*e31*e37-0.5*e27*e332+e21*e30*e36+e21*e32*e38+e31*e30*e26+e31*e20*e36+e31*e32*e28+e31*e22*e38+e24*e33*e36+e24*e35*e38+e24*e34*e37+e34*e33*e26+e34*e23*e36+e34*e35*e28+e34*e25*e38+e37*e36*e26+e37*e38*e28-e37*e30*e20-e37*e32*e22-e37*e33*e23-e37*e35*e25+0.5*e312*e27+0.5*e342*e27+0.5*e27*e362+0.5*e27*e382+1.5*e27*e372-0.5*e27*e302-0.5*e27*e352-0.5*e27*e322; - A[5 + 10*19]=e31*e30*e36+e31*e32*e38+0.5*e312*e37+e34*e33*e36+e34*e35*e38+0.5*e342*e37+0.5*e37*e362+0.5*e37*e382+0.5*e373-0.5*e37*e302-0.5*e37*e352-0.5*e37*e322-0.5*e37*e332; - A[6 + 10*0]=0.5*e02*e002+0.5*e02*e012+0.5*e023+e05*e00*e03+e05*e01*e04+0.5*e02*e052+e08*e00*e06+e08*e01*e07+0.5*e02*e082-0.5*e02*e032-0.5*e02*e042-0.5*e02*e062-0.5*e02*e072; - A[6 + 10*1]=-0.5*e12*e042-0.5*e12*e062-0.5*e12*e072+0.5*e12*e082-0.5*e12*e032+1.5*e12*e022+0.5*e12*e002+0.5*e12*e012+0.5*e12*e052+e02*e10*e00+e02*e11*e01+e05*e10*e03+e05*e00*e13+e05*e11*e04+e05*e01*e14+e05*e02*e15+e15*e00*e03+e15*e01*e04+e08*e10*e06+e08*e00*e16+e08*e11*e07+e08*e01*e17+e08*e02*e18+e18*e00*e06+e18*e01*e07-e02*e13*e03-e02*e14*e04-e02*e16*e06-e02*e17*e07; - A[6 + 10*2]=0.5*e02*e102+1.5*e02*e122+0.5*e02*e112+0.5*e02*e152+0.5*e02*e182-0.5*e02*e162-0.5*e02*e172-0.5*e02*e132-0.5*e02*e142+e12*e10*e00+e12*e11*e01+e05*e10*e13+e05*e12*e15+e05*e11*e14+e15*e10*e03+e15*e00*e13+e15*e11*e04+e15*e01*e14+e08*e10*e16+e08*e12*e18+e08*e11*e17+e18*e10*e06+e18*e00*e16+e18*e11*e07+e18*e01*e17-e12*e13*e03-e12*e14*e04-e12*e16*e06-e12*e17*e07; - A[6 + 10*3]=0.5*e12*e102+0.5*e123+0.5*e12*e112+e15*e10*e13+0.5*e12*e152+e15*e11*e14+e18*e10*e16+0.5*e12*e182+e18*e11*e17-0.5*e12*e162-0.5*e12*e172-0.5*e12*e132-0.5*e12*e142; - A[6 + 10*4]=-0.5*e22*e032-0.5*e22*e042-0.5*e22*e062-0.5*e22*e072+0.5*e22*e082+1.5*e22*e022+0.5*e22*e002+0.5*e22*e012+0.5*e22*e052+e02*e20*e00+e02*e21*e01+e05*e20*e03+e05*e00*e23+e05*e21*e04+e05*e01*e24+e05*e02*e25+e25*e00*e03+e25*e01*e04+e08*e20*e06+e08*e00*e26+e08*e21*e07+e08*e01*e27+e08*e02*e28+e28*e00*e06+e28*e01*e07-e02*e27*e07-e02*e23*e03-e02*e24*e04-e02*e26*e06; - A[6 + 10*5]=-e22*e17*e07-e22*e16*e06-e22*e14*e04-e22*e13*e03-e12*e26*e06-e12*e24*e04-e12*e23*e03-e12*e27*e07-e02*e24*e14-e02*e23*e13-e02*e27*e17-e02*e26*e16+e28*e01*e17+e28*e11*e07+e28*e00*e16+e28*e10*e06+e18*e02*e28+e18*e01*e27+e18*e21*e07+e18*e00*e26+e18*e20*e06+e08*e11*e27+e08*e21*e17+e08*e12*e28+e08*e22*e18+e08*e10*e26+e25*e01*e14+e25*e11*e04+e25*e00*e13+e25*e10*e03+e15*e01*e24+e02*e21*e11+e12*e21*e01+e15*e02*e25+e15*e21*e04+e05*e22*e15+e05*e11*e24+e15*e20*e03+e15*e00*e23+e05*e10*e23+e05*e12*e25+e05*e21*e14+e22*e10*e00+e22*e11*e01+e02*e20*e10+3*e02*e22*e12+e12*e20*e00+e08*e20*e16+e05*e20*e13; - A[6 + 10*6]=-e12*e24*e14-e12*e23*e13-e12*e27*e17-e12*e26*e16+e28*e11*e17+e28*e10*e16+e18*e11*e27+e18*e21*e17+e18*e12*e28+e18*e10*e26+e18*e20*e16+e25*e11*e14+e25*e10*e13+e15*e11*e24+e15*e21*e14+e15*e12*e25+e15*e10*e23+e15*e20*e13+e12*e21*e11+0.5*e22*e182+0.5*e22*e152+1.5*e22*e122+0.5*e22*e102+e12*e20*e10+0.5*e22*e112-0.5*e22*e172-0.5*e22*e132-0.5*e22*e142-0.5*e22*e162; - A[6 + 10*7]=0.5*e02*e282+e28*e01*e27-e22*e27*e07-e22*e23*e03-e22*e24*e04-e22*e26*e06+0.5*e02*e252+e05*e20*e23+e05*e22*e25+e25*e20*e03+e25*e00*e23+e25*e21*e04+e25*e01*e24+e08*e20*e26+e08*e21*e27+e08*e22*e28+e28*e20*e06+e28*e00*e26+e28*e21*e07+e05*e21*e24+0.5*e02*e202+0.5*e02*e212+1.5*e02*e222+e22*e20*e00+e22*e21*e01-0.5*e02*e272-0.5*e02*e242-0.5*e02*e232-0.5*e02*e262; - A[6 + 10*8]=-e22*e27*e17-e22*e23*e13-e22*e24*e14-0.5*e12*e232-0.5*e12*e262-0.5*e12*e242-0.5*e12*e272+0.5*e12*e282+e18*e21*e27+e28*e20*e16+e28*e10*e26+e28*e21*e17+e28*e11*e27-e22*e26*e16+e18*e22*e28+0.5*e12*e252+0.5*e12*e202+0.5*e12*e212+1.5*e12*e222+e22*e20*e10+e15*e20*e23+e15*e21*e24+e15*e22*e25+e25*e20*e13+e25*e10*e23+e25*e21*e14+e25*e11*e24+e18*e20*e26+e22*e21*e11; - A[6 + 10*9]=0.5*e22*e202+0.5*e22*e212+0.5*e223+e25*e20*e23+e25*e21*e24+0.5*e22*e252+e28*e20*e26+e28*e21*e27+0.5*e22*e282-0.5*e22*e232-0.5*e22*e262-0.5*e22*e242-0.5*e22*e272; - A[6 + 10*10]=e08*e31*e07-0.5*e32*e032-e02*e33*e03-e02*e34*e04-e02*e36*e06-0.5*e32*e042-0.5*e32*e062-0.5*e32*e072+e38*e01*e07+e38*e00*e06-e02*e37*e07+e05*e31*e04+e05*e01*e34+e05*e02*e35+e35*e01*e04+e35*e00*e03+e08*e30*e06+e08*e00*e36+e08*e01*e37+e08*e02*e38+0.5*e32*e052+e02*e30*e00+e02*e31*e01+e05*e30*e03+e05*e00*e33+1.5*e32*e022+0.5*e32*e012+0.5*e32*e002+0.5*e32*e082; - A[6 + 10*11]=e05*e32*e15+e32*e11*e01+e38*e10*e06+e08*e12*e38-e32*e14*e04-e32*e16*e06-e32*e17*e07-e12*e36*e06-e32*e13*e03-e02*e34*e14-e12*e37*e07-e12*e33*e03-e12*e34*e04-e02*e37*e17-e02*e33*e13+e38*e01*e17-e02*e36*e16+e18*e01*e37+e18*e02*e38+e38*e00*e16+e38*e11*e07+e08*e30*e16+e08*e10*e36+e08*e32*e18+e08*e31*e17+e08*e11*e37+e18*e30*e06+e18*e00*e36+e18*e31*e07+e35*e10*e03+e35*e00*e13+e35*e11*e04+e35*e01*e14+e15*e02*e35+e05*e10*e33+e05*e12*e35+e05*e31*e14+e05*e11*e34+e15*e30*e03+e15*e00*e33+e15*e31*e04+e15*e01*e34+e05*e30*e13+e02*e30*e10+e02*e31*e11+3*e02*e32*e12+e12*e30*e00+e12*e31*e01+e32*e10*e00; - A[6 + 10*12]=0.5*e32*e102+0.5*e32*e112+e12*e30*e10+1.5*e32*e122+e12*e31*e11+e15*e30*e13+e15*e10*e33+e15*e12*e35+e15*e31*e14+e15*e11*e34+e35*e10*e13-0.5*e32*e162-0.5*e32*e172-0.5*e32*e132-0.5*e32*e142-e12*e37*e17-e12*e33*e13-e12*e34*e14+0.5*e32*e182+0.5*e32*e152+e35*e11*e14+e18*e30*e16+e18*e10*e36+e18*e12*e38+e18*e31*e17+e18*e11*e37+e38*e10*e16+e38*e11*e17-e12*e36*e16; - A[6 + 10*13]=3*e02*e32*e22+e05*e31*e24+e08*e22*e38+e02*e31*e21+e22*e30*e00+e22*e31*e01+e32*e20*e00+e32*e21*e01+e05*e30*e23+e05*e20*e33+e05*e21*e34-e22*e37*e07-e22*e33*e03-e22*e34*e04-e22*e36*e06-e32*e27*e07-e32*e23*e03-e32*e24*e04-e32*e26*e06+e05*e32*e25+e25*e30*e03+e25*e00*e33+e25*e31*e04+e25*e01*e34+e25*e02*e35+e35*e20*e03+e35*e00*e23+e35*e21*e04+e35*e01*e24+e08*e30*e26+e08*e20*e36+e08*e31*e27+e08*e21*e37+e08*e32*e28+e28*e30*e06+e28*e00*e36+e28*e31*e07+e28*e01*e37+e28*e02*e38+e38*e20*e06+e38*e00*e26+e38*e21*e07+e38*e01*e27-e02*e33*e23-e02*e36*e26-e02*e34*e24-e02*e37*e27+e05*e22*e35+e02*e30*e20; - A[6 + 10*14]=e18*e22*e38+e12*e31*e21+3*e12*e32*e22+e22*e30*e10+e22*e31*e11+e32*e20*e10+e32*e21*e11+e15*e30*e23+e15*e20*e33+e15*e31*e24+e15*e21*e34+e15*e32*e25+e15*e22*e35+e25*e30*e13+e25*e10*e33+e25*e12*e35+e25*e31*e14+e25*e11*e34+e35*e20*e13+e35*e10*e23+e35*e21*e14+e35*e11*e24+e18*e30*e26+e18*e20*e36+e18*e31*e27+e18*e21*e37+e18*e32*e28+e28*e30*e16+e28*e10*e36+e28*e12*e38+e28*e31*e17+e28*e11*e37+e38*e20*e16+e38*e10*e26+e12*e30*e20-e22*e37*e17-e22*e33*e13-e22*e34*e14-e32*e26*e16-e32*e27*e17-e32*e23*e13-e32*e24*e14-e22*e36*e16+e38*e21*e17+e38*e11*e27-e12*e33*e23-e12*e36*e26-e12*e34*e24-e12*e37*e27; - A[6 + 10*15]=e25*e30*e23+e22*e30*e20+e22*e31*e21+e25*e20*e33+e25*e31*e24+e25*e21*e34+e25*e22*e35+e35*e20*e23+e35*e21*e24+e28*e30*e26+e28*e20*e36+e28*e31*e27+e28*e21*e37+e28*e22*e38+e38*e20*e26+e38*e21*e27-e22*e33*e23-e22*e36*e26-e22*e34*e24-e22*e37*e27+0.5*e32*e212+0.5*e32*e252+1.5*e32*e222+0.5*e32*e202+0.5*e32*e282-0.5*e32*e232-0.5*e32*e262-0.5*e32*e242-0.5*e32*e272; - A[6 + 10*16]=0.5*e02*e302+1.5*e02*e322+0.5*e02*e312+0.5*e02*e352+0.5*e02*e382-0.5*e02*e342-0.5*e02*e362-0.5*e02*e332-0.5*e02*e372+e38*e30*e06+e32*e30*e00+e32*e31*e01+e05*e30*e33+e05*e32*e35+e05*e31*e34+e35*e30*e03+e35*e00*e33+e35*e31*e04+e35*e01*e34+e08*e30*e36+e08*e32*e38+e08*e31*e37+e38*e00*e36+e38*e31*e07+e38*e01*e37-e32*e37*e07-e32*e33*e03-e32*e34*e04-e32*e36*e06; - A[6 + 10*17]=e32*e30*e10+e32*e31*e11+e15*e30*e33+e15*e32*e35+e15*e31*e34+e35*e30*e13+e35*e10*e33+e35*e31*e14+e35*e11*e34+e18*e30*e36+e18*e32*e38+e18*e31*e37+e38*e30*e16+e38*e10*e36+e38*e31*e17+e38*e11*e37-e32*e36*e16-e32*e37*e17-e32*e33*e13-e32*e34*e14+0.5*e12*e382-0.5*e12*e342-0.5*e12*e362-0.5*e12*e332-0.5*e12*e372+0.5*e12*e352+1.5*e12*e322+0.5*e12*e312+0.5*e12*e302; - A[6 + 10*18]=0.5*e22*e302+0.5*e22*e312+0.5*e22*e352+0.5*e22*e382-0.5*e22*e342-0.5*e22*e362-0.5*e22*e332-0.5*e22*e372+1.5*e22*e322+e32*e30*e20+e32*e31*e21+e25*e30*e33+e25*e32*e35+e25*e31*e34+e35*e30*e23+e35*e20*e33+e35*e31*e24+e35*e21*e34+e28*e30*e36+e28*e32*e38+e28*e31*e37+e38*e30*e26+e38*e20*e36+e38*e31*e27+e38*e21*e37-e32*e33*e23-e32*e36*e26-e32*e34*e24-e32*e37*e27; - A[6 + 10*19]=0.5*e32*e302+0.5*e323+0.5*e32*e312+e35*e30*e33+0.5*e32*e352+e35*e31*e34+e38*e30*e36+0.5*e32*e382+e38*e31*e37-0.5*e32*e342-0.5*e32*e362-0.5*e32*e332-0.5*e32*e372; - A[7 + 10*0]=e02*e01*e04+e02*e00*e03+0.5*e022*e05+0.5*e05*e032+0.5*e05*e042+0.5*e053+e08*e03*e06+e08*e04*e07+0.5*e05*e082-0.5*e05*e002-0.5*e05*e062-0.5*e05*e012-0.5*e05*e072; - A[7 + 10*1]=e08*e13*e06+e02*e10*e03+e02*e00*e13+e02*e11*e04+e02*e01*e14+e02*e12*e05+e12*e01*e04+e12*e00*e03+e05*e13*e03+e05*e14*e04+e08*e03*e16+e08*e14*e07+e08*e04*e17+e08*e05*e18+e18*e03*e06+e18*e04*e07-e05*e10*e00-e05*e11*e01-e05*e16*e06-e05*e17*e07+0.5*e022*e15+1.5*e15*e052+0.5*e15*e032+0.5*e15*e042+0.5*e15*e082-0.5*e15*e002-0.5*e15*e062-0.5*e15*e012-0.5*e15*e072; - A[7 + 10*2]=0.5*e122*e05+0.5*e05*e132+1.5*e05*e152+0.5*e05*e142+0.5*e05*e182-0.5*e05*e102-0.5*e05*e162-0.5*e05*e112-0.5*e05*e172+e02*e10*e13+e02*e12*e15+e02*e11*e14+e12*e10*e03+e12*e00*e13+e12*e11*e04+e12*e01*e14+e15*e13*e03+e15*e14*e04+e08*e13*e16+e08*e15*e18+e08*e14*e17+e18*e13*e06+e18*e03*e16+e18*e14*e07+e18*e04*e17-e15*e11*e01-e15*e16*e06-e15*e17*e07-e15*e10*e00; - A[7 + 10*3]=e12*e10*e13+0.5*e122*e15+e12*e11*e14+0.5*e15*e132+0.5*e153+0.5*e15*e142+e18*e13*e16+0.5*e15*e182+e18*e14*e17-0.5*e15*e102-0.5*e15*e162-0.5*e15*e112-0.5*e15*e172; - A[7 + 10*4]=0.5*e25*e082-0.5*e25*e002-0.5*e25*e062-0.5*e25*e012-0.5*e25*e072+e02*e20*e03+e02*e00*e23+e02*e21*e04+e02*e01*e24+e02*e22*e05+e22*e01*e04+e22*e00*e03+e05*e23*e03+e05*e24*e04+e08*e23*e06+e08*e03*e26+e08*e24*e07+e08*e04*e27+e08*e05*e28+e28*e03*e06+e28*e04*e07-e05*e20*e00-e05*e27*e07-e05*e21*e01-e05*e26*e06+0.5*e022*e25+1.5*e25*e052+0.5*e25*e032+0.5*e25*e042; - A[7 + 10*5]=-e25*e17*e07-e25*e16*e06-e25*e11*e01-e25*e10*e00-e15*e26*e06-e15*e21*e01-e15*e27*e07-e15*e20*e00-e05*e27*e17-e05*e21*e11-e05*e26*e16-e05*e20*e10+e28*e04*e17+e28*e14*e07+e28*e03*e16+e28*e13*e06+e18*e05*e28+e18*e04*e27+e18*e24*e07+e18*e03*e26+e18*e23*e06+e08*e14*e27+e08*e24*e17+e08*e15*e28+e08*e25*e18+e08*e13*e26+e08*e23*e16+e25*e14*e04+e25*e13*e03+e15*e24*e04+e15*e23*e03+e05*e24*e14+3*e05*e25*e15+e05*e23*e13+e22*e01*e14+e22*e11*e04+e22*e00*e13+e22*e10*e03+e12*e22*e05+e12*e01*e24+e12*e21*e04+e12*e00*e23+e12*e20*e03+e02*e11*e24+e02*e21*e14+e02*e12*e25+e02*e22*e15+e02*e10*e23+e02*e20*e13; - A[7 + 10*6]=-e15*e27*e17-e15*e21*e11-e15*e26*e16+e28*e14*e17+e28*e13*e16+e18*e14*e27+e18*e24*e17+e18*e15*e28+e18*e13*e26+e15*e24*e14+e15*e23*e13+e22*e11*e14+e22*e10*e13+e12*e11*e24+e12*e21*e14+e12*e22*e15+e12*e10*e23+e18*e23*e16+0.5*e25*e142+0.5*e25*e182+1.5*e25*e152+0.5*e25*e132+0.5*e122*e25+e12*e20*e13-0.5*e25*e172-0.5*e25*e162-0.5*e25*e112-0.5*e25*e102-e15*e20*e10; - A[7 + 10*7]=e28*e24*e07-0.5*e05*e272-0.5*e05*e262-0.5*e05*e212+0.5*e05*e282-0.5*e05*e202+e28*e23*e06+e08*e23*e26+e08*e25*e28+e08*e24*e27+e28*e03*e26+e28*e04*e27-e25*e27*e07-e25*e21*e01-e25*e26*e06+e02*e20*e23+e02*e22*e25+e02*e21*e24+e22*e20*e03+e22*e00*e23+e22*e21*e04+e22*e01*e24+e25*e23*e03+e25*e24*e04+0.5*e222*e05+0.5*e05*e232+1.5*e05*e252+0.5*e05*e242-e25*e20*e00; - A[7 + 10*8]=-0.5*e15*e202-0.5*e15*e262-0.5*e15*e212-0.5*e15*e272+e18*e23*e26+e18*e25*e28+e18*e24*e27+e28*e23*e16+e28*e13*e26+e28*e24*e17+e28*e14*e27-e25*e20*e10-e25*e26*e16-e25*e21*e11-e25*e27*e17+0.5*e15*e282+0.5*e15*e232+1.5*e15*e252+0.5*e15*e242+0.5*e222*e15+e12*e21*e24+e22*e20*e13+e22*e10*e23+e22*e21*e14+e22*e11*e24+e25*e23*e13+e25*e24*e14+e12*e20*e23+e12*e22*e25; - A[7 + 10*9]=e22*e20*e23+0.5*e222*e25+e22*e21*e24+0.5*e25*e232+0.5*e253+0.5*e25*e242+e28*e23*e26+0.5*e25*e282+e28*e24*e27-0.5*e25*e202-0.5*e25*e262-0.5*e25*e212-0.5*e25*e272; - A[7 + 10*10]=-0.5*e35*e062-0.5*e35*e012-0.5*e35*e072-e05*e30*e00-e05*e31*e01-e05*e36*e06-e05*e37*e07-0.5*e35*e002+0.5*e35*e082+e05*e34*e04+e08*e33*e06+e08*e03*e36+e08*e34*e07+e08*e04*e37+e08*e05*e38+e38*e04*e07+e38*e03*e06+0.5*e022*e35+1.5*e35*e052+0.5*e35*e042+0.5*e35*e032+e02*e30*e03+e02*e00*e33+e02*e31*e04+e02*e01*e34+e02*e32*e05+e32*e01*e04+e32*e00*e03+e05*e33*e03; - A[7 + 10*11]=e08*e33*e16-e35*e16*e06-e35*e17*e07-e15*e30*e00-e15*e37*e07-e15*e31*e01-e15*e36*e06-e35*e10*e00-e35*e11*e01-e05*e37*e17-e05*e31*e11+e38*e04*e17-e05*e30*e10-e05*e36*e16+e18*e33*e06+e18*e03*e36+e18*e34*e07+e18*e04*e37+e18*e05*e38+e38*e13*e06+e38*e03*e16+e38*e14*e07+e35*e14*e04+e08*e13*e36+e08*e35*e18+e08*e15*e38+e08*e34*e17+e08*e14*e37+e35*e13*e03+e05*e33*e13+3*e05*e35*e15+e05*e34*e14+e15*e33*e03+e15*e34*e04+e12*e01*e34+e12*e32*e05+e32*e10*e03+e32*e00*e13+e32*e11*e04+e32*e01*e14+e12*e30*e03+e02*e30*e13+e02*e32*e15+e02*e10*e33+e02*e12*e35+e12*e00*e33+e02*e31*e14+e02*e11*e34+e12*e31*e04; - A[7 + 10*12]=-0.5*e35*e162-0.5*e35*e172-e15*e36*e16-e15*e31*e11-e15*e37*e17-0.5*e35*e102-0.5*e35*e112-e15*e30*e10+e18*e13*e36+e18*e15*e38+e18*e34*e17+e18*e14*e37+e38*e13*e16+e38*e14*e17+e18*e33*e16+1.5*e35*e152+0.5*e35*e132+0.5*e35*e142+0.5*e35*e182+0.5*e122*e35+e32*e10*e13+e32*e11*e14+e15*e33*e13+e15*e34*e14+e12*e10*e33+e12*e32*e15+e12*e31*e14+e12*e11*e34+e12*e30*e13; - A[7 + 10*13]=e05*e33*e23+3*e05*e35*e25+e05*e34*e24+e25*e33*e03+e25*e34*e04+e35*e23*e03+e35*e24*e04+e08*e33*e26+e08*e23*e36+e08*e35*e28+e02*e20*e33+e02*e32*e25+e02*e22*e35+e02*e31*e24+e02*e21*e34+e22*e30*e03+e22*e00*e33+e22*e31*e04+e22*e01*e34+e22*e32*e05+e32*e20*e03+e32*e00*e23+e32*e21*e04+e32*e01*e24+e02*e30*e23-e35*e27*e07-e35*e21*e01-e35*e26*e06+e08*e25*e38+e08*e34*e27+e08*e24*e37+e28*e33*e06+e28*e03*e36+e28*e34*e07+e28*e04*e37+e28*e05*e38+e38*e23*e06+e38*e03*e26+e38*e24*e07+e38*e04*e27-e05*e30*e20-e05*e36*e26-e05*e31*e21-e05*e37*e27-e25*e30*e00-e25*e37*e07-e25*e31*e01-e25*e36*e06-e35*e20*e00; - A[7 + 10*14]=e12*e21*e34+e18*e25*e38+e12*e30*e23+e12*e20*e33+e12*e32*e25+e12*e22*e35+e12*e31*e24+e22*e30*e13+e22*e10*e33+e22*e32*e15+e22*e31*e14+e22*e11*e34+e32*e20*e13+e32*e10*e23+e32*e21*e14-e25*e30*e10-e25*e36*e16-e25*e31*e11-e25*e37*e17-e35*e20*e10-e35*e26*e16-e35*e21*e11-e35*e27*e17+e15*e33*e23+3*e15*e35*e25+e15*e34*e24+e25*e33*e13+e25*e34*e14+e35*e23*e13+e35*e24*e14+e18*e33*e26+e18*e23*e36+e18*e35*e28+e18*e34*e27+e18*e24*e37+e28*e33*e16+e28*e13*e36+e28*e15*e38+e28*e34*e17+e28*e14*e37+e38*e23*e16+e38*e13*e26+e38*e24*e17+e38*e14*e27-e15*e30*e20-e15*e36*e26-e15*e31*e21-e15*e37*e27+e32*e11*e24; - A[7 + 10*15]=-0.5*e35*e202-0.5*e35*e262-0.5*e35*e212-0.5*e35*e272+e25*e34*e24+e28*e23*e36+e28*e25*e38+e28*e34*e27+e28*e24*e37+e38*e23*e26+e38*e24*e27-e25*e30*e20-e25*e36*e26-e25*e31*e21-e25*e37*e27+e25*e33*e23+0.5*e222*e35+1.5*e35*e252+0.5*e35*e232+0.5*e35*e242+0.5*e35*e282+e22*e30*e23+e22*e20*e33+e22*e32*e25+e22*e31*e24+e22*e21*e34+e32*e20*e23+e32*e21*e24+e28*e33*e26; - A[7 + 10*16]=-e35*e30*e00-e35*e31*e01-e35*e36*e06-e35*e37*e07+0.5*e322*e05+0.5*e05*e332+0.5*e05*e342+1.5*e05*e352+0.5*e05*e382-0.5*e05*e302-0.5*e05*e362-0.5*e05*e312-0.5*e05*e372+e02*e30*e33+e02*e31*e34+e02*e32*e35+e32*e30*e03+e32*e00*e33+e32*e31*e04+e32*e01*e34+e35*e33*e03+e35*e34*e04+e08*e33*e36+e08*e34*e37+e08*e35*e38+e38*e33*e06+e38*e03*e36+e38*e34*e07+e38*e04*e37; - A[7 + 10*17]=-e35*e30*e10+e12*e32*e35-0.5*e15*e362-0.5*e15*e312-0.5*e15*e372-e35*e36*e16+0.5*e322*e15+0.5*e15*e332+0.5*e15*e342+1.5*e15*e352+0.5*e15*e382-0.5*e15*e302+e12*e30*e33+e12*e31*e34+e32*e30*e13+e32*e10*e33+e32*e31*e14+e32*e11*e34+e35*e33*e13+e35*e34*e14+e18*e33*e36+e18*e34*e37+e18*e35*e38+e38*e33*e16+e38*e13*e36+e38*e34*e17+e38*e14*e37-e35*e31*e11-e35*e37*e17; - A[7 + 10*18]=-0.5*e25*e302-0.5*e25*e362-0.5*e25*e312-0.5*e25*e372+0.5*e322*e25+0.5*e25*e332+0.5*e25*e342+1.5*e25*e352+0.5*e25*e382+e22*e30*e33+e22*e31*e34+e22*e32*e35+e32*e30*e23+e32*e20*e33+e32*e31*e24+e32*e21*e34+e35*e33*e23+e35*e34*e24+e28*e33*e36+e28*e34*e37+e28*e35*e38+e38*e33*e26+e38*e23*e36+e38*e34*e27+e38*e24*e37-e35*e30*e20-e35*e36*e26-e35*e31*e21-e35*e37*e27; - A[7 + 10*19]=e32*e30*e33+e32*e31*e34+0.5*e322*e35+0.5*e35*e332+0.5*e35*e342+0.5*e353+e38*e33*e36+e38*e34*e37+0.5*e35*e382-0.5*e35*e302-0.5*e35*e362-0.5*e35*e312-0.5*e35*e372; - A[8 + 10*0]=e02*e00*e06+e02*e01*e07+0.5*e022*e08+e05*e04*e07+e05*e03*e06+0.5*e052*e08+0.5*e08*e062+0.5*e08*e072+0.5*e083-0.5*e08*e042-0.5*e08*e002-0.5*e08*e012-0.5*e08*e032; - A[8 + 10*1]=e02*e10*e06+e02*e00*e16+e02*e11*e07+e02*e01*e17+e02*e12*e08+e12*e00*e06+e12*e01*e07+e05*e13*e06+e05*e03*e16+e05*e14*e07+e05*e04*e17+e05*e15*e08+e15*e04*e07+e15*e03*e06+e08*e16*e06+e08*e17*e07-e08*e10*e00-e08*e11*e01-e08*e13*e03-e08*e14*e04+0.5*e022*e18+0.5*e052*e18+1.5*e18*e082+0.5*e18*e062+0.5*e18*e072-0.5*e18*e042-0.5*e18*e002-0.5*e18*e012-0.5*e18*e032; - A[8 + 10*2]=e12*e01*e17+0.5*e152*e08+0.5*e08*e162+1.5*e08*e182+0.5*e08*e172-0.5*e08*e102-0.5*e08*e112-0.5*e08*e132-0.5*e08*e142+e05*e13*e16+e05*e14*e17+e05*e15*e18+e15*e13*e06+e15*e03*e16+e15*e14*e07+e15*e04*e17+e18*e16*e06+e18*e17*e07-e18*e10*e00-e18*e11*e01-e18*e13*e03-e18*e14*e04+0.5*e122*e08+e02*e10*e16+e02*e12*e18+e02*e11*e17+e12*e10*e06+e12*e00*e16+e12*e11*e07; - A[8 + 10*3]=e12*e10*e16+0.5*e122*e18+e12*e11*e17+e15*e13*e16+e15*e14*e17+0.5*e152*e18+0.5*e18*e162+0.5*e183+0.5*e18*e172-0.5*e18*e102-0.5*e18*e112-0.5*e18*e132-0.5*e18*e142; - A[8 + 10*4]=-e08*e20*e00+e08*e27*e07-e08*e21*e01-e08*e23*e03-e08*e24*e04+e02*e20*e06+e02*e00*e26+e02*e21*e07+e02*e01*e27+e02*e22*e08+e22*e00*e06+e22*e01*e07+e05*e23*e06+e05*e03*e26+e05*e24*e07+e05*e04*e27+e05*e25*e08+e25*e04*e07+e25*e03*e06+e08*e26*e06+0.5*e022*e28+0.5*e052*e28+1.5*e28*e082+0.5*e28*e062+0.5*e28*e072-0.5*e28*e042-0.5*e28*e002-0.5*e28*e012-0.5*e28*e032; - A[8 + 10*5]=e22*e10*e06+e22*e11*e07+e22*e01*e17+e05*e23*e16+e05*e13*e26+e05*e25*e18+e05*e15*e28+e05*e24*e17+e05*e14*e27+e15*e23*e06+e15*e03*e26+e15*e24*e07+e15*e04*e27+e15*e25*e08+e25*e13*e06+e25*e03*e16+e25*e14*e07+e25*e04*e17+e08*e26*e16+3*e08*e28*e18+e08*e27*e17+e18*e26*e06+e18*e27*e07+e22*e00*e16+e28*e16*e06+e28*e17*e07-e08*e20*e10-e08*e21*e11-e08*e23*e13-e08*e24*e14-e18*e20*e00-e18*e21*e01-e18*e23*e03-e18*e24*e04-e28*e10*e00-e28*e11*e01-e28*e13*e03-e28*e14*e04+e02*e20*e16+e02*e10*e26+e02*e22*e18+e02*e12*e28+e02*e21*e17+e02*e11*e27+e12*e20*e06+e12*e00*e26+e12*e21*e07+e12*e01*e27+e12*e22*e08; - A[8 + 10*6]=-e18*e24*e14-e18*e21*e11-e18*e23*e13-e18*e20*e10+e18*e27*e17+e18*e26*e16+e25*e14*e17+e25*e13*e16+e15*e25*e18+e15*e14*e27+e15*e24*e17+e15*e13*e26+e15*e23*e16+e22*e11*e17+e22*e10*e16+e12*e11*e27+e12*e21*e17+e12*e22*e18+e12*e10*e26+e12*e20*e16+0.5*e28*e162+0.5*e28*e172+1.5*e28*e182+0.5*e152*e28-0.5*e28*e142-0.5*e28*e112-0.5*e28*e132-0.5*e28*e102+0.5*e122*e28; - A[8 + 10*7]=-e28*e24*e04-e28*e21*e01-e28*e23*e03-e28*e20*e00+e28*e27*e07+e28*e26*e06+e25*e04*e27+e25*e24*e07+e25*e03*e26+e05*e24*e27+e05*e25*e28+e05*e23*e26+e22*e01*e27+e22*e21*e07+e22*e00*e26+e22*e20*e06+e02*e22*e28+e02*e20*e26+e02*e21*e27+0.5*e222*e08-0.5*e08*e242-0.5*e08*e212-0.5*e08*e232-0.5*e08*e202+0.5*e08*e262+0.5*e08*e272+1.5*e08*e282+0.5*e252*e08+e25*e23*e06; - A[8 + 10*8]=e25*e24*e17+e25*e14*e27+e28*e26*e16+e28*e27*e17-e28*e21*e11-e28*e24*e14+e12*e22*e28+e22*e10*e26+e22*e21*e17+e22*e11*e27+e15*e23*e26+e15*e25*e28+e15*e24*e27+e25*e23*e16+e25*e13*e26+e22*e20*e16+0.5*e222*e18+0.5*e252*e18+0.5*e18*e262+0.5*e18*e272+e12*e20*e26+e12*e21*e27-e28*e20*e10-0.5*e18*e232-0.5*e18*e242-e28*e23*e13-0.5*e18*e212+1.5*e18*e282-0.5*e18*e202; - A[8 + 10*9]=e22*e20*e26+e22*e21*e27+0.5*e222*e28+e25*e23*e26+0.5*e252*e28+e25*e24*e27+0.5*e28*e262+0.5*e28*e272+0.5*e283-0.5*e28*e202-0.5*e28*e212-0.5*e28*e232-0.5*e28*e242; - A[8 + 10*10]=-e08*e30*e00-0.5*e38*e042-0.5*e38*e002-0.5*e38*e012-0.5*e38*e032+1.5*e38*e082+0.5*e38*e062+0.5*e38*e072+e32*e01*e07+e05*e33*e06+e05*e03*e36+e05*e34*e07+e05*e04*e37+e05*e35*e08+e35*e04*e07+e35*e03*e06+e08*e36*e06+e08*e37*e07+0.5*e052*e38+e32*e00*e06+e02*e30*e06+e02*e00*e36+e02*e31*e07+e02*e01*e37+e02*e32*e08+0.5*e022*e38-e08*e33*e03-e08*e31*e01-e08*e34*e04; - A[8 + 10*11]=-e38*e11*e01-e38*e14*e04-e38*e10*e00-e38*e13*e03-e18*e30*e00-e18*e33*e03-e18*e31*e01-e18*e34*e04-e08*e30*e10-e08*e33*e13-e08*e31*e11-e08*e34*e14+3*e08*e38*e18+e08*e37*e17+e18*e36*e06+e18*e37*e07+e38*e16*e06+e38*e17*e07+e15*e35*e08+e35*e13*e06+e35*e03*e16+e35*e14*e07+e35*e04*e17+e08*e36*e16+e05*e35*e18+e05*e15*e38+e15*e33*e06+e15*e03*e36+e15*e34*e07+e15*e04*e37+e05*e14*e37+e12*e30*e06+e12*e31*e07+e12*e01*e37+e12*e00*e36+e12*e32*e08+e32*e10*e06+e32*e00*e16+e32*e11*e07+e32*e01*e17+e05*e33*e16+e05*e13*e36+e05*e34*e17+e02*e30*e16+e02*e10*e36+e02*e32*e18+e02*e12*e38+e02*e31*e17+e02*e11*e37; - A[8 + 10*12]=e12*e30*e16+e12*e10*e36+e12*e32*e18+e12*e31*e17+e12*e11*e37+e32*e10*e16+e32*e11*e17+e15*e33*e16+e15*e13*e36-0.5*e38*e102-0.5*e38*e112-0.5*e38*e132-0.5*e38*e142+0.5*e38*e162+0.5*e38*e172+e15*e34*e17+e15*e14*e37+e15*e35*e18+e35*e13*e16+e35*e14*e17+e18*e36*e16+e18*e37*e17-e18*e30*e10-e18*e33*e13-e18*e31*e11-e18*e34*e14+0.5*e122*e38+0.5*e152*e38+1.5*e38*e182; - A[8 + 10*13]=e22*e30*e06-e28*e34*e04+e05*e35*e28+e02*e22*e38+e22*e00*e36+e22*e31*e07+e22*e01*e37+e02*e32*e28+e02*e21*e37-e38*e20*e00-e28*e31*e01-e38*e23*e03-e38*e21*e01-e38*e24*e04-e28*e30*e00-e08*e30*e20-e08*e31*e21-e08*e33*e23-e08*e34*e24-e28*e33*e03+e35*e24*e07+e35*e04*e27+e08*e36*e26+e08*e37*e27+3*e08*e38*e28+e28*e36*e06+e28*e37*e07+e38*e26*e06+e38*e27*e07+e25*e04*e37+e25*e35*e08+e35*e23*e06+e35*e03*e26+e05*e23*e36+e05*e25*e38+e05*e34*e27+e05*e24*e37+e25*e33*e06+e25*e03*e36+e25*e34*e07+e05*e33*e26+e32*e21*e07+e32*e01*e27+e22*e32*e08+e32*e20*e06+e32*e00*e26+e02*e30*e26+e02*e20*e36+e02*e31*e27; - A[8 + 10*14]=e35*e13*e26-e38*e21*e11-e38*e24*e14+e35*e24*e17+e35*e14*e27+e18*e36*e26+e18*e37*e27+3*e18*e38*e28+e28*e36*e16+e28*e37*e17+e38*e26*e16+e38*e27*e17-e18*e30*e20-e18*e31*e21-e18*e33*e23-e18*e34*e24-e28*e30*e10-e28*e33*e13-e28*e31*e11-e28*e34*e14-e38*e20*e10-e38*e23*e13+e35*e23*e16+e12*e20*e36+e12*e30*e26+e12*e31*e27+e12*e21*e37+e12*e32*e28+e12*e22*e38+e22*e30*e16+e22*e10*e36+e22*e32*e18+e22*e31*e17+e22*e11*e37+e32*e20*e16+e32*e10*e26+e32*e21*e17+e32*e11*e27+e15*e33*e26+e15*e23*e36+e15*e35*e28+e15*e25*e38+e15*e34*e27+e15*e24*e37+e25*e33*e16+e25*e13*e36+e25*e34*e17+e25*e14*e37+e25*e35*e18; - A[8 + 10*15]=-e28*e30*e20+e22*e30*e26+e22*e20*e36+e22*e31*e27+e22*e21*e37+e22*e32*e28+e32*e20*e26+e32*e21*e27+e25*e33*e26+e25*e23*e36+e25*e35*e28+e25*e34*e27+e25*e24*e37+e35*e23*e26+e35*e24*e27+e28*e36*e26+e28*e37*e27-e28*e31*e21-e28*e33*e23-e28*e34*e24-0.5*e38*e242+0.5*e252*e38+1.5*e38*e282+0.5*e38*e262+0.5*e38*e272-0.5*e38*e202-0.5*e38*e212-0.5*e38*e232+0.5*e222*e38; - A[8 + 10*16]=-0.5*e08*e312-0.5*e08*e342+0.5*e352*e08+0.5*e08*e362+1.5*e08*e382+0.5*e08*e372-0.5*e08*e302-0.5*e08*e332+e02*e30*e36+e02*e32*e38+e02*e31*e37+e32*e30*e06+e32*e00*e36+e32*e31*e07+e32*e01*e37+e05*e33*e36+e05*e34*e37+e05*e35*e38+e35*e33*e06+e35*e03*e36+e35*e34*e07+e35*e04*e37+0.5*e322*e08+e38*e36*e06+e38*e37*e07-e38*e30*e00-e38*e33*e03-e38*e31*e01-e38*e34*e04; - A[8 + 10*17]=-e38*e30*e10+e38*e36*e16+e38*e37*e17-e38*e33*e13-e38*e31*e11-e38*e34*e14+0.5*e18*e362+e12*e30*e36+e12*e32*e38+e12*e31*e37+e32*e30*e16+e32*e10*e36+e32*e31*e17+e32*e11*e37+e15*e33*e36+e15*e34*e37+e15*e35*e38+e35*e33*e16+e35*e13*e36+e35*e34*e17+e35*e14*e37+0.5*e322*e18+0.5*e352*e18+1.5*e18*e382+0.5*e18*e372-0.5*e18*e302-0.5*e18*e332-0.5*e18*e312-0.5*e18*e342; - A[8 + 10*18]=-e38*e30*e20+e25*e35*e38+e22*e30*e36+e22*e32*e38+e22*e31*e37+e32*e30*e26+e32*e20*e36+e32*e31*e27+e32*e21*e37+e25*e33*e36+e25*e34*e37+e35*e33*e26+e35*e23*e36+e35*e34*e27+e35*e24*e37+e38*e36*e26+e38*e37*e27-e38*e31*e21-e38*e33*e23-e38*e34*e24-0.5*e28*e332-0.5*e28*e312-0.5*e28*e342+0.5*e322*e28+0.5*e352*e28+0.5*e28*e362+1.5*e28*e382+0.5*e28*e372-0.5*e28*e302; - A[8 + 10*19]=e32*e30*e36+0.5*e322*e38+e32*e31*e37+e35*e33*e36+e35*e34*e37+0.5*e352*e38+0.5*e38*e362+0.5*e383+0.5*e38*e372-0.5*e38*e302-0.5*e38*e332-0.5*e38*e312-0.5*e38*e342; - A[9 + 10*0]=e00*e04*e08-e00*e05*e07+e03*e02*e07-e03*e01*e08-e06*e02*e04+e06*e01*e05; - A[9 + 10*1]=e06*e01*e15-e16*e02*e04+e16*e01*e05+e03*e02*e17-e13*e01*e08+e06*e11*e05+e13*e02*e07+e00*e04*e18+e00*e14*e08-e00*e05*e17-e10*e05*e07-e00*e15*e07-e06*e12*e04-e06*e02*e14-e03*e01*e18-e03*e11*e08+e10*e04*e08+e03*e12*e07; - A[9 + 10*2]=-e13*e01*e18-e13*e11*e08+e13*e12*e07+e13*e02*e17+e03*e12*e17-e10*e15*e07+e10*e04*e18+e10*e14*e08-e10*e05*e17-e00*e15*e17+e00*e14*e18+e16*e01*e15+e06*e11*e15-e06*e12*e14-e16*e12*e04-e16*e02*e14+e16*e11*e05-e03*e11*e18; - A[9 + 10*3]=e10*e14*e18-e10*e15*e17-e13*e11*e18+e13*e12*e17+e16*e11*e15-e16*e12*e14; - A[9 + 10*4]=-e20*e05*e07+e03*e22*e07+e06*e21*e05+e06*e01*e25-e23*e01*e08+e23*e02*e07+e00*e24*e08-e00*e25*e07-e00*e05*e27+e00*e04*e28-e06*e22*e04-e06*e02*e24-e03*e21*e08-e03*e01*e28-e26*e02*e04+e26*e01*e05+e03*e02*e27+e20*e04*e08; - A[9 + 10*5]=e23*e12*e07-e26*e02*e14+e16*e21*e05-e23*e11*e08+e10*e24*e08-e20*e05*e17+e26*e11*e05+e26*e01*e15+e10*e04*e28+e00*e24*e18-e00*e15*e27+e03*e22*e17-e13*e01*e28+e23*e02*e17+e16*e01*e25+e20*e04*e18+e06*e11*e25+e13*e02*e27-e23*e01*e18-e20*e15*e07-e10*e25*e07+e13*e22*e07-e06*e22*e14-e26*e12*e04-e03*e11*e28-e03*e21*e18-e16*e22*e04-e16*e02*e24-e06*e12*e24+e06*e21*e15+e00*e14*e28-e00*e25*e17+e20*e14*e08-e13*e21*e08-e10*e05*e27+e03*e12*e27; - A[9 + 10*6]=-e13*e11*e28+e13*e12*e27+e13*e22*e17+e16*e11*e25+e10*e14*e28-e13*e21*e18-e23*e11*e18+e23*e12*e17+e20*e14*e18-e20*e15*e17+e26*e11*e15-e10*e15*e27-e10*e25*e17-e16*e22*e14-e16*e12*e24+e16*e21*e15-e26*e12*e14+e10*e24*e18; - A[9 + 10*7]=e26*e21*e05+e26*e01*e25+e20*e04*e28+e20*e24*e08-e20*e25*e07+e23*e22*e07+e03*e22*e27-e03*e21*e28-e26*e22*e04-e20*e05*e27-e00*e25*e27+e06*e21*e25-e06*e22*e24+e00*e24*e28-e26*e02*e24-e23*e21*e08-e23*e01*e28+e23*e02*e27; - A[9 + 10*8]=-e10*e25*e27+e10*e24*e28-e20*e15*e27-e20*e25*e17+e20*e14*e28+e20*e24*e18+e26*e11*e25+e23*e22*e17-e23*e11*e28+e23*e12*e27-e23*e21*e18-e13*e21*e28+e13*e22*e27-e26*e12*e24+e26*e21*e15-e16*e22*e24+e16*e21*e25-e26*e22*e14; - A[9 + 10*9]=-e20*e25*e27+e20*e24*e28-e23*e21*e28+e23*e22*e27-e26*e22*e24+e26*e21*e25; - A[9 + 10*10]=e03*e02*e37-e03*e31*e08-e03*e01*e38+e03*e32*e07-e00*e35*e07+e30*e04*e08+e06*e31*e05-e36*e02*e04+e36*e01*e05-e06*e32*e04-e06*e02*e34+e06*e01*e35+e00*e04*e38-e00*e05*e37+e33*e02*e07-e33*e01*e08-e30*e05*e07+e00*e34*e08; - A[9 + 10*11]=-e36*e12*e04+e30*e04*e18-e30*e15*e07-e36*e02*e14-e30*e05*e17+e30*e14*e08-e00*e35*e17-e00*e15*e37+e33*e02*e17-e06*e32*e14-e06*e12*e34-e16*e32*e04+e06*e31*e15+e06*e11*e35+e00*e34*e18-e10*e35*e07-e33*e11*e08-e33*e01*e18+e16*e01*e35-e16*e02*e34+e16*e31*e05-e03*e31*e18-e03*e11*e38+e03*e32*e17+e13*e02*e37-e13*e31*e08-e13*e01*e38+e10*e34*e08+e00*e14*e38+e36*e11*e05+e36*e01*e15+e03*e12*e37-e10*e05*e37+e10*e04*e38+e33*e12*e07+e13*e32*e07; - A[9 + 10*12]=-e36*e12*e14-e30*e15*e17+e13*e32*e17-e13*e31*e18-e33*e11*e18+e33*e12*e17+e10*e14*e38+e30*e14*e18-e13*e11*e38+e13*e12*e37-e10*e35*e17+e10*e34*e18-e16*e12*e34-e16*e32*e14+e16*e11*e35+e16*e31*e15+e36*e11*e15-e10*e15*e37; - A[9 + 10*13]=-e06*e22*e34-e06*e32*e24-e00*e25*e37-e00*e35*e27+e23*e02*e37+e00*e24*e38-e23*e01*e38-e03*e31*e28-e33*e01*e28+e03*e22*e37+e03*e32*e27+e33*e02*e27-e03*e21*e38-e26*e32*e04-e33*e21*e08+e36*e01*e25+e36*e21*e05-e20*e05*e37+e20*e04*e38+e30*e04*e28-e20*e35*e07+e33*e22*e07+e30*e24*e08-e30*e25*e07-e23*e31*e08+e23*e32*e07+e00*e34*e28+e06*e21*e35+e06*e31*e25-e36*e02*e24+e26*e01*e35-e36*e22*e04+e26*e31*e05-e26*e02*e34+e20*e34*e08-e30*e05*e27; - A[9 + 10*14]=e33*e22*e17+e33*e12*e27+e16*e21*e35-e16*e22*e34-e16*e32*e24+e23*e32*e17-e23*e11*e38-e23*e31*e18+e23*e12*e37-e13*e21*e38-e13*e31*e28+e13*e22*e37+e36*e21*e15-e36*e12*e24+e36*e11*e25-e26*e12*e34-e20*e35*e17+e20*e14*e38+e20*e34*e18+e30*e24*e18-e30*e15*e27-e30*e25*e17+e30*e14*e28-e33*e21*e18+e10*e34*e28+e10*e24*e38-e10*e35*e27-e10*e25*e37-e20*e15*e37-e26*e32*e14+e26*e11*e35+e26*e31*e15-e36*e22*e14+e13*e32*e27+e16*e31*e25-e33*e11*e28; - A[9 + 10*15]=-e20*e35*e27-e20*e25*e37+e20*e34*e28+e20*e24*e38+e30*e24*e28-e30*e25*e27+e23*e32*e27+e23*e22*e37-e23*e31*e28-e23*e21*e38+e33*e22*e27-e26*e22*e34-e26*e32*e24+e26*e21*e35+e26*e31*e25-e36*e22*e24+e36*e21*e25-e33*e21*e28; - A[9 + 10*16]=-e33*e01*e38-e03*e31*e38+e00*e34*e38+e33*e32*e07+e03*e32*e37+e06*e31*e35-e00*e35*e37-e36*e32*e04-e06*e32*e34-e36*e02*e34+e36*e01*e35+e36*e31*e05+e30*e04*e38+e30*e34*e08-e33*e31*e08+e33*e02*e37-e30*e05*e37-e30*e35*e07; - A[9 + 10*17]=-e33*e31*e18-e33*e11*e38+e10*e34*e38+e30*e14*e38-e10*e35*e37-e30*e15*e37-e13*e31*e38+e13*e32*e37-e30*e35*e17+e33*e12*e37+e30*e34*e18+e33*e32*e17+e16*e31*e35-e16*e32*e34-e36*e12*e34-e36*e32*e14+e36*e11*e35+e36*e31*e15; - A[9 + 10*18]=-e20*e35*e37+e20*e34*e38+e30*e24*e38-e30*e35*e27-e30*e25*e37+e30*e34*e28+e23*e32*e37-e23*e31*e38-e33*e21*e38-e33*e31*e28+e33*e22*e37+e33*e32*e27+e26*e31*e35-e26*e32*e34-e36*e22*e34-e36*e32*e24+e36*e21*e35+e36*e31*e25; - A[9 + 10*19]=-e33*e31*e38-e30*e35*e37+e36*e31*e35+e33*e32*e37+e30*e34*e38-e36*e32*e34; + for (int i = 0; i < 200; i++) + { + A[i] = AA[i]; + } } + void computeError( InputArray _m1, InputArray _m2, InputArray _model, OutputArray _err ) const { Mat X1 = _m1.getMat(), X2 = _m2.getMat(), model = _model.getMat(); @@ -518,31 +393,31 @@ protected: double b = Ex1[1] * Ex1[1]; double c = Etx2[0] * Etx2[0]; double d = Etx2[1] * Etx2[1]; - + err.at(i) = (float)(x2tEx1 * x2tEx1 / (a + b + c + d)); } } -}; +}; } // Input should be a vector of n 2D points or a Nx2 matrix cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, double focal, Point2d pp, - int method, double prob, double threshold, OutputArray _mask) + int method, double prob, double threshold, OutputArray _mask) { - Mat points1, points2; - _points1.getMat().convertTo(points1, CV_64F); - _points2.getMat().convertTo(points2, CV_64F); + Mat points1, points2; + _points1.getMat().convertTo(points1, CV_64F); + _points2.getMat().convertTo(points2, CV_64F); - int npoints = points1.checkVector(2); + int npoints = points1.checkVector(2); CV_Assert( npoints >= 5 && points2.checkVector(2) == npoints && - points1.type() == points2.type()); + points1.type() == points2.type()); - if( points1.channels() > 1 ) - { - points1 = points1.reshape(1, npoints); - points2 = points2.reshape(1, npoints); - } + if( points1.channels() > 1 ) + { + points1 = points1.reshape(1, npoints); + points2 = points2.reshape(1, npoints); + } double ifocal = focal != 0 ? 1./focal : 1.; for( int i = 0; i < npoints; i++ ) @@ -553,177 +428,187 @@ cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, double f points2.at(i, 1) = (points2.at(i, 1) - pp.y)*ifocal; } - // Reshape data to fit opencv ransac function - points1 = points1.reshape(2, npoints); - points2 = points2.reshape(2, npoints); + // Reshape data to fit opencv ransac function + points1 = points1.reshape(2, npoints); + points2 = points2.reshape(2, npoints); - threshold /= focal; + threshold /= focal; Mat E; - if( method == CV_RANSAC ) - createRANSACPointSetRegistrator(new EMEstimatorCallback, 5, threshold, prob)->run(points1, points2, E, _mask); + if( method == RANSAC ) + createRANSACPointSetRegistrator(makePtr(), 5, threshold, prob)->run(points1, points2, E, _mask); else - createLMeDSPointSetRegistrator(new EMEstimatorCallback, 5, prob)->run(points1, points2, E, _mask); + createLMeDSPointSetRegistrator(makePtr(), 5, prob)->run(points1, points2, E, _mask); - return E; + return E; } int cv::recoverPose( InputArray E, InputArray _points1, InputArray _points2, OutputArray _R, - OutputArray _t, double focal, Point2d pp, InputOutputArray _mask) + OutputArray _t, double focal, Point2d pp, InputOutputArray _mask) { - Mat points1, points2; - _points1.getMat().copyTo(points1); - _points2.getMat().copyTo(points2); - - int npoints = points1.checkVector(2); + Mat points1, points2; + _points1.getMat().copyTo(points1); + _points2.getMat().copyTo(points2); + + int npoints = points1.checkVector(2); CV_Assert( npoints >= 0 && points2.checkVector(2) == npoints && - points1.type() == points2.type()); + points1.type() == points2.type()); - if (points1.channels() > 1) - { - points1 = points1.reshape(1, npoints); - points2 = points2.reshape(1, npoints); - } - points1.convertTo(points1, CV_64F); - points2.convertTo(points2, CV_64F); + if (points1.channels() > 1) + { + points1 = points1.reshape(1, npoints); + points2 = points2.reshape(1, npoints); + } + points1.convertTo(points1, CV_64F); + points2.convertTo(points2, CV_64F); - points1.col(0) = (points1.col(0) - pp.x) / focal; - points2.col(0) = (points2.col(0) - pp.x) / focal; - points1.col(1) = (points1.col(1) - pp.y) / focal; - points2.col(1) = (points2.col(1) - pp.y) / focal; + points1.col(0) = (points1.col(0) - pp.x) / focal; + points2.col(0) = (points2.col(0) - pp.x) / focal; + points1.col(1) = (points1.col(1) - pp.y) / focal; + points2.col(1) = (points2.col(1) - pp.y) / focal; - points1 = points1.t(); - points2 = points2.t(); - - Mat R1, R2, t; - decomposeEssentialMat(E, R1, R2, t); - Mat P0 = Mat::eye(3, 4, R1.type()); - Mat P1(3, 4, R1.type()), P2(3, 4, R1.type()), P3(3, 4, R1.type()), P4(3, 4, R1.type()); - P1(Range::all(), Range(0, 3)) = R1 * 1.0; P1.col(3) = t * 1.0; - P2(Range::all(), Range(0, 3)) = R2 * 1.0; P2.col(3) = t * 1.0; - P3(Range::all(), Range(0, 3)) = R1 * 1.0; P3.col(3) = -t * 1.0; - P4(Range::all(), Range(0, 3)) = R2 * 1.0; P4.col(3) = -t * 1.0; + points1 = points1.t(); + points2 = points2.t(); - // Do the cheirality check. - // Notice here a threshold dist is used to filter - // out far away points (i.e. infinite points) since - // there depth may vary between postive and negtive. - double dist = 50.0; - Mat Q; - triangulatePoints(P0, P1, points1, points2, Q); - Mat mask1 = Q.row(2).mul(Q.row(3)) > 0; - Q.row(0) /= Q.row(3); - Q.row(1) /= Q.row(3); - Q.row(2) /= Q.row(3); - Q.row(3) /= Q.row(3); - mask1 = (Q.row(2) < dist) & mask1; - Q = P1 * Q; - mask1 = (Q.row(2) > 0) & mask1; - mask1 = (Q.row(2) < dist) & mask1; + Mat R1, R2, t; + decomposeEssentialMat(E, R1, R2, t); + Mat P0 = Mat::eye(3, 4, R1.type()); + Mat P1(3, 4, R1.type()), P2(3, 4, R1.type()), P3(3, 4, R1.type()), P4(3, 4, R1.type()); + P1(Range::all(), Range(0, 3)) = R1 * 1.0; P1.col(3) = t * 1.0; + P2(Range::all(), Range(0, 3)) = R2 * 1.0; P2.col(3) = t * 1.0; + P3(Range::all(), Range(0, 3)) = R1 * 1.0; P3.col(3) = -t * 1.0; + P4(Range::all(), Range(0, 3)) = R2 * 1.0; P4.col(3) = -t * 1.0; - triangulatePoints(P0, P2, points1, points2, Q); - Mat mask2 = Q.row(2).mul(Q.row(3)) > 0; - Q.row(0) /= Q.row(3); - Q.row(1) /= Q.row(3); - Q.row(2) /= Q.row(3); - Q.row(3) /= Q.row(3); - mask2 = (Q.row(2) < dist) & mask2; - Q = P2 * Q; - mask2 = (Q.row(2) > 0) & mask2; - mask2 = (Q.row(2) < dist) & mask2; + // Do the cheirality check. + // Notice here a threshold dist is used to filter + // out far away points (i.e. infinite points) since + // there depth may vary between postive and negtive. + double dist = 50.0; + Mat Q; + triangulatePoints(P0, P1, points1, points2, Q); + Mat mask1 = Q.row(2).mul(Q.row(3)) > 0; + Q.row(0) /= Q.row(3); + Q.row(1) /= Q.row(3); + Q.row(2) /= Q.row(3); + Q.row(3) /= Q.row(3); + mask1 = (Q.row(2) < dist) & mask1; + Q = P1 * Q; + mask1 = (Q.row(2) > 0) & mask1; + mask1 = (Q.row(2) < dist) & mask1; - triangulatePoints(P0, P3, points1, points2, Q); - Mat mask3 = Q.row(2).mul(Q.row(3)) > 0; - Q.row(0) /= Q.row(3); - Q.row(1) /= Q.row(3); - Q.row(2) /= Q.row(3); - Q.row(3) /= Q.row(3); - mask3 = (Q.row(2) < dist) & mask3; - Q = P3 * Q; - mask3 = (Q.row(2) > 0) & mask3; - mask3 = (Q.row(2) < dist) & mask3; + triangulatePoints(P0, P2, points1, points2, Q); + Mat mask2 = Q.row(2).mul(Q.row(3)) > 0; + Q.row(0) /= Q.row(3); + Q.row(1) /= Q.row(3); + Q.row(2) /= Q.row(3); + Q.row(3) /= Q.row(3); + mask2 = (Q.row(2) < dist) & mask2; + Q = P2 * Q; + mask2 = (Q.row(2) > 0) & mask2; + mask2 = (Q.row(2) < dist) & mask2; - triangulatePoints(P0, P4, points1, points2, Q); - Mat mask4 = Q.row(2).mul(Q.row(3)) > 0; - Q.row(0) /= Q.row(3); - Q.row(1) /= Q.row(3); - Q.row(2) /= Q.row(3); - Q.row(3) /= Q.row(3); - mask4 = (Q.row(2) < dist) & mask4; - Q = P4 * Q; - mask4 = (Q.row(2) > 0) & mask4; - mask4 = (Q.row(2) < dist) & mask4; + triangulatePoints(P0, P3, points1, points2, Q); + Mat mask3 = Q.row(2).mul(Q.row(3)) > 0; + Q.row(0) /= Q.row(3); + Q.row(1) /= Q.row(3); + Q.row(2) /= Q.row(3); + Q.row(3) /= Q.row(3); + mask3 = (Q.row(2) < dist) & mask3; + Q = P3 * Q; + mask3 = (Q.row(2) > 0) & mask3; + mask3 = (Q.row(2) < dist) & mask3; - // If _mask is given, then use it to filter outliers. - if (_mask.needed()) - { - _mask.create(1, npoints, CV_8U, -1, true); - Mat mask = _mask.getMat(); - bitwise_and(mask, mask1, mask1); - bitwise_and(mask, mask2, mask2); - bitwise_and(mask, mask3, mask3); - bitwise_and(mask, mask4, mask4); - } + triangulatePoints(P0, P4, points1, points2, Q); + Mat mask4 = Q.row(2).mul(Q.row(3)) > 0; + Q.row(0) /= Q.row(3); + Q.row(1) /= Q.row(3); + Q.row(2) /= Q.row(3); + Q.row(3) /= Q.row(3); + mask4 = (Q.row(2) < dist) & mask4; + Q = P4 * Q; + mask4 = (Q.row(2) > 0) & mask4; + mask4 = (Q.row(2) < dist) & mask4; - CV_Assert(_R.needed() && _t.needed()); - _R.create(3, 3, R1.type()); - _t.create(3, 1, t.type()); + mask1 = mask1.t(); + mask2 = mask2.t(); + mask3 = mask3.t(); + mask4 = mask4.t(); - int good1 = countNonZero(mask1); - int good2 = countNonZero(mask2); - int good3 = countNonZero(mask3); - int good4 = countNonZero(mask4); - if (good1 >= good2 && good1 >= good3 && good1 >= good4) - { - R1.copyTo(_R); - t.copyTo(_t); - if (_mask.needed()) mask1.copyTo(_mask); - return good1; - } - else if (good2 >= good1 && good2 >= good3 && good2 >= good4) - { - R2.copyTo(_R); - t.copyTo(_t); - if (_mask.needed()) mask2.copyTo(_mask); - return good2; - } - else if (good3 >= good1 && good3 >= good2 && good3 >= good4) - { - t = -t; + // If _mask is given, then use it to filter outliers. + if (!_mask.empty()) + { + Mat mask = _mask.getMat(); + CV_Assert(mask.size() == mask1.size()); + bitwise_and(mask, mask1, mask1); + bitwise_and(mask, mask2, mask2); + bitwise_and(mask, mask3, mask3); + bitwise_and(mask, mask4, mask4); + } + if (_mask.empty() && _mask.needed()) + { + _mask.create(mask1.size(), CV_8U); + } + + CV_Assert(_R.needed() && _t.needed()); + _R.create(3, 3, R1.type()); + _t.create(3, 1, t.type()); + + int good1 = countNonZero(mask1); + int good2 = countNonZero(mask2); + int good3 = countNonZero(mask3); + int good4 = countNonZero(mask4); + + if (good1 >= good2 && good1 >= good3 && good1 >= good4) + { R1.copyTo(_R); - t.copyTo(_t); - if (_mask.needed()) mask3.copyTo(_mask); - return good3; - } - else - { - t = -t; + t.copyTo(_t); + if (_mask.needed()) mask1.copyTo(_mask); + return good1; + } + else if (good2 >= good1 && good2 >= good3 && good2 >= good4) + { R2.copyTo(_R); t.copyTo(_t); - if (_mask.needed()) mask4.copyTo(_mask); - return good4; - } + if (_mask.needed()) mask2.copyTo(_mask); + return good2; + } + else if (good3 >= good1 && good3 >= good2 && good3 >= good4) + { + t = -t; + R1.copyTo(_R); + t.copyTo(_t); + if (_mask.needed()) mask3.copyTo(_mask); + return good3; + } + else + { + t = -t; + R2.copyTo(_R); + t.copyTo(_t); + if (_mask.needed()) mask4.copyTo(_mask); + return good4; + } } -void cv::decomposeEssentialMat( InputArray _E, OutputArray _R1, OutputArray _R2, OutputArray _t ) +void cv::decomposeEssentialMat( InputArray _E, OutputArray _R1, OutputArray _R2, OutputArray _t ) { Mat E = _E.getMat().reshape(1, 3); - CV_Assert(E.cols == 3 && E.rows == 3); - - Mat D, U, Vt; - SVD::compute(E, D, U, Vt); - - if (determinant(U) < 0) U *= -1.; - if (determinant(Vt) < 0) Vt *= -1.; + CV_Assert(E.cols == 3 && E.rows == 3); - Mat W = (Mat_(3, 3) << 0, 1, 0, -1, 0, 0, 0, 0, 1); - W.convertTo(W, E.type()); - - Mat R1, R2, t; - R1 = U * W * Vt; - R2 = U * W.t() * Vt; - t = U.col(2) * 1.0; + Mat D, U, Vt; + SVD::compute(E, D, U, Vt); + + if (determinant(U) < 0) U *= -1.; + if (determinant(Vt) < 0) Vt *= -1.; + + Mat W = (Mat_(3, 3) << 0, 1, 0, -1, 0, 0, 0, 0, 1); + W.convertTo(W, E.type()); + + Mat R1, R2, t; + R1 = U * W * Vt; + R2 = U * W.t() * Vt; + t = U.col(2) * 1.0; R1.copyTo(_R1); R2.copyTo(_R2); diff --git a/modules/calib3d/src/fundam.cpp b/modules/calib3d/src/fundam.cpp index 0db8fcab9b..d1c6e8cd0b 100644 --- a/modules/calib3d/src/fundam.cpp +++ b/modules/calib3d/src/fundam.cpp @@ -181,12 +181,12 @@ public: LtL[j][k] += Lx[j]*Lx[k] + Ly[j]*Ly[k]; } completeSymm( _LtL ); - + eigen( _LtL, matW, matV ); _Htemp = _invHnorm*_H0; _H0 = _Htemp*_Hnorm2; _H0.convertTo(_model, _H0.type(), 1./_H0.at(2,2) ); - + return 1; } @@ -259,6 +259,8 @@ public: Jptr[8] = Jptr[9] = Jptr[10] = 0.; Jptr[11] = Mx*ww; Jptr[12] = My*ww; Jptr[13] = ww; Jptr[14] = -Mx*ww*yi; Jptr[15] = -My*ww*yi; + + Jptr += 16; } } @@ -292,7 +294,7 @@ cv::Mat cv::findHomography( InputArray _points1, InputArray _points2, { npoints = p.checkVector(3, -1, false); if( npoints < 0 ) - CV_Error(CV_StsBadArg, "The input arrays should be 2D or 3D point sets"); + CV_Error(Error::StsBadArg, "The input arrays should be 2D or 3D point sets"); if( npoints == 0 ) return Mat(); convertPointsFromHomogeneous(p, p); @@ -305,7 +307,7 @@ cv::Mat cv::findHomography( InputArray _points1, InputArray _points2, if( ransacReprojThreshold <= 0 ) ransacReprojThreshold = defaultRANSACReprojThreshold; - Ptr cb = new HomographyEstimatorCallback; + Ptr cb = makePtr(); if( method == 0 || npoints == 4 ) { @@ -317,7 +319,7 @@ cv::Mat cv::findHomography( InputArray _points1, InputArray _points2, else if( method == LMEDS ) result = createLMeDSPointSetRegistrator(cb, 4, confidence, maxIters)->run(src, dst, H, tempMask); else - CV_Error(CV_StsBadArg, "Unknown estimation method"); + CV_Error(Error::StsBadArg, "Unknown estimation method"); if( result && npoints > 4 ) { @@ -332,7 +334,7 @@ cv::Mat cv::findHomography( InputArray _points1, InputArray _points2, if( method == RANSAC || method == LMEDS ) cb->runKernel( src, dst, H ); Mat H8(8, 1, CV_64F, H.ptr()); - createLMSolver(new HomographyRefineCallback(src, dst), 10)->run(H8); + createLMSolver(makePtr(src, dst), 10)->run(H8); } } @@ -475,7 +477,7 @@ static int run7Point( const Mat& _m1, const Mat& _m2, Mat& _fmatrix ) return n; } - + static int run8Point( const Mat& _m1, const Mat& _m2, Mat& _fmatrix ) { double a[9*9], w[9], v[9*9]; @@ -585,11 +587,11 @@ static int run8Point( const Mat& _m1, const Mat& _m2, Mat& _fmatrix ) gemm( T2, F0, 1., 0, 0., TF, GEMM_1_T ); F0 = Mat(3, 3, CV_64F, fmatrix); gemm( TF, T1, 1., 0, 0., F0, 0 ); - + // make F(3,3) = 1 if( fabs(F0.at(2,2)) > FLT_EPSILON ) F0 *= 1./F0.at(2,2); - + return 1; } @@ -671,7 +673,7 @@ cv::Mat cv::findFundamentalMat( InputArray _points1, InputArray _points2, { npoints = p.checkVector(3, -1, false); if( npoints < 0 ) - CV_Error(CV_StsBadArg, "The input arrays should be 2D or 3D point sets"); + CV_Error(Error::StsBadArg, "The input arrays should be 2D or 3D point sets"); if( npoints == 0 ) return Mat(); convertPointsFromHomogeneous(p, p); @@ -684,7 +686,7 @@ cv::Mat cv::findFundamentalMat( InputArray _points1, InputArray _points2, if( npoints < 7 ) return Mat(); - Ptr cb = new FMEstimatorCallback; + Ptr cb = makePtr(); int result; if( npoints == 7 || method == FM_8POINT ) @@ -739,7 +741,7 @@ void cv::computeCorrespondEpilines( InputArray _points, int whichImage, { npoints = points.checkVector(3); if( npoints < 0 ) - CV_Error( CV_StsBadArg, "The input should be a 2D or 3D point set"); + CV_Error( Error::StsBadArg, "The input should be a 2D or 3D point set"); Mat temp; convertPointsFromHomogeneous(points, temp); points = temp; @@ -893,7 +895,7 @@ void cv::convertPointsFromHomogeneous( InputArray _src, OutputArray _dst ) } } else - CV_Error(CV_StsUnsupportedFormat, ""); + CV_Error(Error::StsUnsupportedFormat, ""); } @@ -974,7 +976,7 @@ void cv::convertPointsToHomogeneous( InputArray _src, OutputArray _dst ) } } else - CV_Error(CV_StsUnsupportedFormat, ""); + CV_Error(Error::StsUnsupportedFormat, ""); } diff --git a/modules/calib3d/src/levmarq.cpp b/modules/calib3d/src/levmarq.cpp index 539c804e2b..55704132cf 100644 --- a/modules/calib3d/src/levmarq.cpp +++ b/modules/calib3d/src/levmarq.cpp @@ -47,30 +47,30 @@ This is translation to C++ of the Matlab's LMSolve package by Miroslav Balda. Here is the original copyright: ============================================================================ - + Copyright (c) 2007, Miroslav Balda All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in + * Redistributions 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 - 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 COPYRIGHT OWNER 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 + 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 COPYRIGHT OWNER 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. */ @@ -95,7 +95,7 @@ public: int ptype = param0.type(); CV_Assert( (param0.cols == 1 || param0.rows == 1) && (ptype == CV_32F || ptype == CV_64F)); - CV_Assert( !cb.empty() ); + CV_Assert( cb ); int lx = param0.rows + param0.cols - 1; param0.convertTo(x, CV_64F); @@ -112,7 +112,7 @@ public: gemm(J, r, 1, noArray(), 0, v, GEMM_1_T); Mat D = A.diag().clone(); - + const double Rlo = 0.25, Rhi = 0.75; double lambda = 1, lc = 0.75; int i, iter = 0; @@ -220,7 +220,7 @@ CV_INIT_ALGORITHM(LMSolverImpl, "LMSolver", Ptr createLMSolver(const Ptr& cb, int maxIters) { CV_Assert( !LMSolverImpl_info_auto.name().empty() ); - return new LMSolverImpl(cb, maxIters); + return makePtr(cb, maxIters); } - + } diff --git a/modules/calib3d/src/p3p.cpp b/modules/calib3d/src/p3p.cpp index 92e7954721..882868d6b8 100644 --- a/modules/calib3d/src/p3p.cpp +++ b/modules/calib3d/src/p3p.cpp @@ -411,4 +411,3 @@ bool p3p::jacobi_4x4(double * A, double * D, double * U) return false; } - diff --git a/modules/calib3d/src/p3p.h b/modules/calib3d/src/p3p.h index a58b0fa149..57f8d7df88 100644 --- a/modules/calib3d/src/p3p.h +++ b/modules/calib3d/src/p3p.h @@ -59,4 +59,3 @@ class p3p }; #endif // P3P_H - diff --git a/modules/calib3d/src/posit.cpp b/modules/calib3d/src/posit.cpp index c8c1c2c2f1..14c33e1e7b 100644 --- a/modules/calib3d/src/posit.cpp +++ b/modules/calib3d/src/posit.cpp @@ -39,6 +39,7 @@ // //M*/ #include "precomp.hpp" +#include "opencv2/calib3d/calib3d_c.h" /* POSIT structure */ struct CvPOSITObject diff --git a/modules/calib3d/src/precomp.cpp b/modules/calib3d/src/precomp.cpp deleted file mode 100644 index 3e0ec42de9..0000000000 --- a/modules/calib3d/src/precomp.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/*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. -// -// -// Intel License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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 "precomp.hpp" - -/* End of file. */ diff --git a/modules/calib3d/src/precomp.hpp b/modules/calib3d/src/precomp.hpp index 5951ea1fd2..12885f37a7 100644 --- a/modules/calib3d/src/precomp.hpp +++ b/modules/calib3d/src/precomp.hpp @@ -42,16 +42,12 @@ #ifndef __OPENCV_PRECOMP_H__ #define __OPENCV_PRECOMP_H__ -#ifdef HAVE_CVCONFIG_H -#include "cvconfig.h" -#endif - #include "opencv2/calib3d.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/imgproc/imgproc_c.h" -#include "opencv2/core/internal.hpp" #include "opencv2/features2d.hpp" -#include +#include "opencv2/core/utility.hpp" + +#include "opencv2/core/private.hpp" #ifdef HAVE_TEGRA_OPTIMIZATION #include "opencv2/calib3d/calib3d_tegra.hpp" diff --git a/modules/calib3d/src/ptsetreg.cpp b/modules/calib3d/src/ptsetreg.cpp index 58cad5cf38..aa361a9118 100644 --- a/modules/calib3d/src/ptsetreg.cpp +++ b/modules/calib3d/src/ptsetreg.cpp @@ -53,7 +53,7 @@ namespace cv int RANSACUpdateNumIters( double p, double ep, int modelPoints, int maxIters ) { if( modelPoints <= 0 ) - CV_Error( CV_StsOutOfRange, "the number of model points should be positive" ); + CV_Error( Error::StsOutOfRange, "the number of model points should be positive" ); p = MAX(p, 0.); p = MIN(p, 1.); @@ -154,7 +154,7 @@ public: continue; break; } - + return i == modelPoints && iters < maxAttempts; } @@ -171,7 +171,7 @@ public: RNG rng((uint64)-1); - CV_Assert( !cb.empty() ); + CV_Assert( cb ); CV_Assert( confidence > 0 && confidence < 1 ); CV_Assert( count >= 0 && count2 == count ); @@ -235,7 +235,7 @@ public: } } } - + if( maxGoodCount > 0 ) { if( bestMask.data != bestMask0.data ) @@ -250,7 +250,7 @@ public: } else _model.release(); - + return result; } @@ -267,9 +267,6 @@ public: int maxIters; }; - -static CV_IMPLEMENT_QSORT( sortDistances, int, CV_LT ) - class LMeDSPointSetRegistrator : public RANSACPointSetRegistrator { public: @@ -291,7 +288,7 @@ public: RNG rng((uint64)-1); - CV_Assert( !cb.empty() ); + CV_Assert( cb ); CV_Assert( confidence > 0 && confidence < 1 ); CV_Assert( count >= 0 && count2 == count ); @@ -347,7 +344,7 @@ public: else errf = err; CV_Assert( errf.isContinuous() && errf.type() == CV_32F && (int)errf.total() == count ); - sortDistances( (int*)errf.data, count, 0 ); + std::sort((int*)errf.data, (int*)errf.data + count); double median = count % 2 != 0 ? errf.at(count/2) : (errf.at(count/2-1) + errf.at(count/2))*0.5; @@ -359,7 +356,7 @@ public: } } } - + if( minMedian < DBL_MAX ) { sigma = 2.5*1.4826*(1 + 5./(count - modelPoints))*std::sqrt(minMedian); @@ -378,7 +375,7 @@ public: } else _model.release(); - + return result; } @@ -400,7 +397,8 @@ Ptr createRANSACPointSetRegistrator(const Ptr( + new RANSACPointSetRegistrator(_cb, _modelPoints, _threshold, _confidence, _maxIters)); } @@ -408,7 +406,8 @@ Ptr createLMeDSPointSetRegistrator(const Ptr( + new LMeDSPointSetRegistrator(_cb, _modelPoints, _confidence, _maxIters)); } class Affine3DEstimatorCallback : public PointSetRegistrator::Callback @@ -534,7 +533,6 @@ int cv::estimateAffine3D(InputArray _from, InputArray _to, const double epsilon = DBL_EPSILON; param1 = param1 <= 0 ? 3 : param1; param2 = (param2 < epsilon) ? 0.99 : (param2 > 1 - epsilon) ? 0.99 : param2; - - return createRANSACPointSetRegistrator(new Affine3DEstimatorCallback, 4, param1, param2)->run(dFrom, dTo, _out, _inliers); -} + return createRANSACPointSetRegistrator(makePtr(), 4, param1, param2)->run(dFrom, dTo, _out, _inliers); +} diff --git a/modules/calib3d/src/quadsubpix.cpp b/modules/calib3d/src/quadsubpix.cpp index 26f26b5807..2e98a462b5 100644 --- a/modules/calib3d/src/quadsubpix.cpp +++ b/modules/calib3d/src/quadsubpix.cpp @@ -47,40 +47,8 @@ #include -//#define _SUBPIX_VERBOSE - -#undef max - namespace cv { - -// static void drawCircles(Mat& img, const std::vector& corners, const std::vector& radius) -// { -// for(size_t i = 0; i < corners.size(); i++) -// { -// circle(img, corners[i], cvRound(radius[i]), CV_RGB(255, 0, 0)); -// } -// } - -// static int histQuantile(const Mat& hist, float quantile) -// { -// if(hist.dims > 1) return -1; // works for 1D histograms only - -// float cur_sum = 0; -// float total_sum = (float)sum(hist).val[0]; -// float quantile_sum = total_sum*quantile; -// for(int j = 0; j < hist.size[0]; j++) -// { -// cur_sum += (float)hist.at(j); -// if(cur_sum > quantile_sum) -// { -// return j; -// } -// } - -// return hist.size[0] - 1; -// } - inline bool is_smaller(const std::pair& p1, const std::pair& p2) { return p1.second < p2.second; @@ -124,29 +92,6 @@ static void findLinesCrossPoint(Point2f origin1, Point2f dir1, Point2f origin2, cross_point = origin1 + dir1*alpha; } -// static void findCorner(const std::vector& contour, Point2f point, Point2f& corner) -// { -// // find the nearest point -// double min_dist = std::numeric_limits::max(); -// int min_idx = -1; - -// // find corner idx -// for(size_t i = 0; i < contour.size(); i++) -// { -// double dist = norm(Point2f((float)contour[i].x, (float)contour[i].y) - point); -// if(dist < min_dist) -// { -// min_dist = dist; -// min_idx = (int)i; -// } -// } -// assert(min_idx >= 0); - -// // temporary solution, have to make something more precise -// corner = contour[min_idx]; -// return; -// } - static void findCorner(const std::vector& contour, Point2f point, Point2f& corner) { // find the nearest point @@ -163,7 +108,7 @@ static void findCorner(const std::vector& contour, Point2f point, Point min_idx = (int)i; } } - assert(min_idx >= 0); + CV_Assert(min_idx >= 0); // temporary solution, have to make something more precise corner = contour[min_idx]; @@ -173,13 +118,7 @@ static void findCorner(const std::vector& contour, Point2f point, Point static int segment_hist_max(const Mat& hist, int& low_thresh, int& high_thresh) { Mat bw; - //const double max_bell_width = 20; // we expect two bells with width bounded above - //const double min_bell_width = 5; // and below - double total_sum = sum(hist).val[0]; - //double thresh = total_sum/(2*max_bell_width)*0.25f; // quarter of a bar inside a bell - -// threshold(hist, bw, thresh, 255.0, CV_THRESH_BINARY); double quantile_sum = 0.0; //double min_quantile = 0.2; @@ -233,12 +172,6 @@ bool cv::find4QuadCornerSubpix(InputArray _img, InputOutputArray _corners, Size const float* _ranges = ranges; Mat hist; -#if defined(_SUBPIX_VERBOSE) - std::vector radius; - radius.assign(corners.size(), 0.0f); -#endif //_SUBPIX_VERBOSE - - Mat black_comp, white_comp; for(int i = 0; i < ncorners; i++) { @@ -248,39 +181,20 @@ bool cv::find4QuadCornerSubpix(InputArray _img, InputOutputArray _corners, Size Mat img_roi = img(roi); calcHist(&img_roi, 1, &channels, Mat(), hist, 1, &nbins, &_ranges); -#if 0 - int black_thresh = histQuantile(hist, 0.45f); - int white_thresh = histQuantile(hist, 0.55f); -#else int black_thresh = 0, white_thresh = 0; segment_hist_max(hist, black_thresh, white_thresh); -#endif - threshold(img, black_comp, black_thresh, 255.0, CV_THRESH_BINARY_INV); - threshold(img, white_comp, white_thresh, 255.0, CV_THRESH_BINARY); + threshold(img, black_comp, black_thresh, 255.0, THRESH_BINARY_INV); + threshold(img, white_comp, white_thresh, 255.0, THRESH_BINARY); const int erode_count = 1; erode(black_comp, black_comp, Mat(), Point(-1, -1), erode_count); erode(white_comp, white_comp, Mat(), Point(-1, -1), erode_count); -#if defined(_SUBPIX_VERBOSE) - namedWindow("roi", 1); - imshow("roi", img_roi); - imwrite("test.jpg", img); - namedWindow("black", 1); - imshow("black", black_comp); - namedWindow("white", 1); - imshow("white", white_comp); - cvWaitKey(0); - imwrite("black.jpg", black_comp); - imwrite("white.jpg", white_comp); -#endif - - std::vector > white_contours, black_contours; std::vector white_hierarchy, black_hierarchy; - findContours(black_comp, black_contours, black_hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); - findContours(white_comp, white_contours, white_hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); + findContours(black_comp, black_contours, black_hierarchy, RETR_LIST, CHAIN_APPROX_SIMPLE); + findContours(white_comp, white_contours, white_hierarchy, RETR_LIST, CHAIN_APPROX_SIMPLE); if(black_contours.size() < 5 || white_contours.size() < 5) continue; @@ -302,15 +216,11 @@ bool cv::find4QuadCornerSubpix(InputArray _img, InputOutputArray _corners, Size Point2f quad_corners[4]; for(int k = 0; k < 4; k++) { -#if 1 std::vector temp; for(size_t j = 0; j < quads[k]->size(); j++) temp.push_back((*quads[k])[j]); approxPolyDP(Mat(temp), quads_approx[k], 0.5, true); findCorner(quads_approx[k], corners[i], quad_corners[k]); -#else - findCorner(*quads[k], corners[i], quad_corners[k]); -#endif quad_corners[k] += Point2f(0.5f, 0.5f); } @@ -323,44 +233,7 @@ bool cv::find4QuadCornerSubpix(InputArray _img, InputOutputArray _corners, Size if(cvIsNaN(angle) || cvIsInf(angle) || angle < 0.5 || angle > CV_PI - 0.5) continue; findLinesCrossPoint(origin1, dir1, origin2, dir2, corners[i]); - -#if defined(_SUBPIX_VERBOSE) - radius[i] = norm(corners[i] - ground_truth_corners[ground_truth_idx])*6; - -#if 1 - Mat test(img.size(), CV_32FC3); - cvtColor(img, test, CV_GRAY2RGB); -// line(test, quad_corners[0] - corners[i] + Point2f(30, 30), quad_corners[1] - corners[i] + Point2f(30, 30), cvScalar(0, 255, 0)); -// line(test, quad_corners[2] - corners[i] + Point2f(30, 30), quad_corners[3] - corners[i] + Point2f(30, 30), cvScalar(0, 255, 0)); - std::vector > contrs; - contrs.resize(1); - for(int k = 0; k < 4; k++) - { - //contrs[0] = quads_approx[k]; - contrs[0].clear(); - for(size_t j = 0; j < quads_approx[k].size(); j++) contrs[0].push_back(quads_approx[k][j]); - drawContours(test, contrs, 0, CV_RGB(0, 0, 255), 1, 1, std::vector(), 2); - circle(test, quad_corners[k], 0.5, CV_RGB(255, 0, 0)); - } - Mat test1 = test(Rect(corners[i].x - 30, corners[i].y - 30, 60, 60)); - namedWindow("1", 1); - imshow("1", test1); - imwrite("test.jpg", test); - waitKey(0); -#endif -#endif //_SUBPIX_VERBOSE - } -#if defined(_SUBPIX_VERBOSE) - Mat test(img.size(), CV_32FC3); - cvtColor(img, test, CV_GRAY2RGB); - drawCircles(test, corners, radius); - - namedWindow("corners", 1); - imshow("corners", test); - waitKey(); -#endif //_SUBPIX_VERBOSE - return true; } diff --git a/modules/calib3d/src/solvepnp.cpp b/modules/calib3d/src/solvepnp.cpp index 5bcffb3166..698302b942 100644 --- a/modules/calib3d/src/solvepnp.cpp +++ b/modules/calib3d/src/solvepnp.cpp @@ -43,6 +43,8 @@ #include "precomp.hpp" #include "epnp.h" #include "p3p.h" +#include "opencv2/calib3d/calib3d_c.h" + #include using namespace cv; @@ -57,7 +59,7 @@ bool cv::solvePnP( InputArray _opoints, InputArray _ipoints, _tvec.create(3, 1, CV_64F); Mat cameraMatrix = _cameraMatrix.getMat(), distCoeffs = _distCoeffs.getMat(); - if (flags == CV_EPNP) + if (flags == EPNP) { cv::Mat undistortedPoints; cv::undistortPoints(ipoints, undistortedPoints, cameraMatrix, distCoeffs); @@ -68,7 +70,7 @@ bool cv::solvePnP( InputArray _opoints, InputArray _ipoints, cv::Rodrigues(R, rvec); return true; } - else if (flags == CV_P3P) + else if (flags == P3P) { CV_Assert( npoints == 4); cv::Mat undistortedPoints; @@ -81,7 +83,7 @@ bool cv::solvePnP( InputArray _opoints, InputArray _ipoints, cv::Rodrigues(R, rvec); return result; } - else if (flags == CV_ITERATIVE) + else if (flags == ITERATIVE) { CvMat c_objectPoints = opoints, c_imagePoints = ipoints; CvMat c_cameraMatrix = cameraMatrix, c_distCoeffs = distCoeffs; @@ -115,31 +117,6 @@ namespace cv transform(points, modif_points, transformation); } - class Mutex - { - public: - Mutex() { - } - void lock() - { -#ifdef HAVE_TBB - resultsMutex.lock(); -#endif - } - - void unlock() - { -#ifdef HAVE_TBB - resultsMutex.unlock(); -#endif - } - - private: -#ifdef HAVE_TBB - tbb::mutex resultsMutex; -#endif - }; - struct CameraParameters { void init(Mat _intrinsics, Mat _distCoeffs) @@ -342,7 +319,7 @@ void cv::solvePnPRansac(InputArray _opoints, InputArray _ipoints, if (localInliers.size() >= (size_t)pnpransac::MIN_POINTS_COUNT) { - if (flags != CV_P3P) + if (flags != P3P) { int i, pointsCount = (int)localInliers.size(); Mat inlierObjectPoints(1, pointsCount, CV_32FC3), inlierImagePoints(1, pointsCount, CV_32FC2); @@ -371,4 +348,3 @@ void cv::solvePnPRansac(InputArray _opoints, InputArray _ipoints, } return; } - diff --git a/modules/calib3d/src/stereobm.cpp b/modules/calib3d/src/stereobm.cpp index 158881bd94..ee131db76d 100644 --- a/modules/calib3d/src/stereobm.cpp +++ b/modules/calib3d/src/stereobm.cpp @@ -56,7 +56,7 @@ struct StereoBMParams { StereoBMParams(int _numDisparities=64, int _SADWindowSize=21) { - preFilterType = STEREO_PREFILTER_XSOBEL; + preFilterType = StereoBM::PREFILTER_XSOBEL; preFilterSize = 9; preFilterCap = 31; SADWindowSize = _SADWindowSize; @@ -84,7 +84,7 @@ struct StereoBMParams int disp12MaxDiff; int dispType; }; - + static void prefilterNorm( const Mat& src, Mat& dst, int winsize, int ftzero, uchar* buf ) { @@ -183,7 +183,7 @@ prefilterXSobel( const Mat& src, Mat& dst, int ftzero ) if( useSIMD ) { __m128i z = _mm_setzero_si128(), ftz = _mm_set1_epi16((short)ftzero), - ftz2 = _mm_set1_epi8(CV_CAST_8U(ftzero*2)); + ftz2 = _mm_set1_epi8(cv::saturate_cast(ftzero*2)); for( ; x <= size.width-9; x += 8 ) { __m128i c0 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow0 + x - 1)), z); @@ -195,9 +195,9 @@ prefilterXSobel( const Mat& src, Mat& dst, int ftzero ) d1 = _mm_sub_epi16(d1, c1); __m128i c2 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow2 + x - 1)), z); - __m128i c3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow2 + x - 1)), z); + __m128i c3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow3 + x - 1)), z); __m128i d2 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow2 + x + 1)), z); - __m128i d3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow2 + x + 1)), z); + __m128i d3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow3 + x + 1)), z); d2 = _mm_sub_epi16(d2, c2); d3 = _mm_sub_epi16(d3, c3); @@ -676,7 +676,7 @@ struct PrefilterInvoker : public ParallelLoopBody { for( int i = range.start; i < range.end; i++ ) { - if( state->preFilterType == STEREO_PREFILTER_NORMALIZED_RESPONSE ) + if( state->preFilterType == StereoBM::PREFILTER_NORMALIZED_RESPONSE ) prefilterNorm( *imgs0[i], *imgs[i], state->preFilterSize, state->preFilterCap, buf[i] ); else prefilterXSobel( *imgs0[i], *imgs[i], state->preFilterCap ); @@ -771,8 +771,7 @@ protected: Rect validDisparityRect; }; - -class StereoBMImpl : public StereoMatcher +class StereoBMImpl : public StereoBM { public: StereoBMImpl() @@ -784,46 +783,46 @@ public: { params = StereoBMParams(_numDisparities, _SADWindowSize); } - + void compute( InputArray leftarr, InputArray rightarr, OutputArray disparr ) { Mat left0 = leftarr.getMat(), right0 = rightarr.getMat(); int dtype = disparr.fixedType() ? disparr.type() : params.dispType; if (left0.size() != right0.size()) - CV_Error( CV_StsUnmatchedSizes, "All the images must have the same size" ); + CV_Error( Error::StsUnmatchedSizes, "All the images must have the same size" ); if (left0.type() != CV_8UC1 || right0.type() != CV_8UC1) - CV_Error( CV_StsUnsupportedFormat, "Both input images must have CV_8UC1" ); + CV_Error( Error::StsUnsupportedFormat, "Both input images must have CV_8UC1" ); if (dtype != CV_16SC1 && dtype != CV_32FC1) - CV_Error( CV_StsUnsupportedFormat, "Disparity image must have CV_16SC1 or CV_32FC1 format" ); + CV_Error( Error::StsUnsupportedFormat, "Disparity image must have CV_16SC1 or CV_32FC1 format" ); disparr.create(left0.size(), dtype); Mat disp0 = disparr.getMat(); - if( params.preFilterType != STEREO_PREFILTER_NORMALIZED_RESPONSE && - params.preFilterType != STEREO_PREFILTER_XSOBEL ) - CV_Error( CV_StsOutOfRange, "preFilterType must be = CV_STEREO_BM_NORMALIZED_RESPONSE" ); + if( params.preFilterType != PREFILTER_NORMALIZED_RESPONSE && + params.preFilterType != PREFILTER_XSOBEL ) + CV_Error( Error::StsOutOfRange, "preFilterType must be = CV_STEREO_BM_NORMALIZED_RESPONSE" ); if( params.preFilterSize < 5 || params.preFilterSize > 255 || params.preFilterSize % 2 == 0 ) - CV_Error( CV_StsOutOfRange, "preFilterSize must be odd and be within 5..255" ); + CV_Error( Error::StsOutOfRange, "preFilterSize must be odd and be within 5..255" ); if( params.preFilterCap < 1 || params.preFilterCap > 63 ) - CV_Error( CV_StsOutOfRange, "preFilterCap must be within 1..63" ); + CV_Error( Error::StsOutOfRange, "preFilterCap must be within 1..63" ); if( params.SADWindowSize < 5 || params.SADWindowSize > 255 || params.SADWindowSize % 2 == 0 || params.SADWindowSize >= std::min(left0.cols, left0.rows) ) - CV_Error( CV_StsOutOfRange, "SADWindowSize must be odd, be within 5..255 and be not larger than image width or height" ); + CV_Error( Error::StsOutOfRange, "SADWindowSize must be odd, be within 5..255 and be not larger than image width or height" ); if( params.numDisparities <= 0 || params.numDisparities % 16 != 0 ) - CV_Error( CV_StsOutOfRange, "numDisparities must be positive and divisble by 16" ); + CV_Error( Error::StsOutOfRange, "numDisparities must be positive and divisble by 16" ); if( params.textureThreshold < 0 ) - CV_Error( CV_StsOutOfRange, "texture threshold must be non-negative" ); + CV_Error( Error::StsOutOfRange, "texture threshold must be non-negative" ); if( params.uniquenessRatio < 0 ) - CV_Error( CV_StsOutOfRange, "uniqueness ratio must be non-negative" ); + CV_Error( Error::StsOutOfRange, "uniqueness ratio must be non-negative" ); preFilteredImg0.create( left0.size(), CV_8U ); preFilteredImg1.create( left0.size(), CV_8U ); @@ -888,48 +887,111 @@ public: R2.area() > 0 ? Rect(0, 0, width, height) : validDisparityRect, params.minDisparity, params.numDisparities, params.SADWindowSize); - + parallel_for_(Range(0, nstripes), FindStereoCorrespInvoker(left, right, disp, ¶ms, nstripes, bufSize0, useShorts, validDisparityRect, slidingSumBuf, cost)); - + if( params.speckleRange >= 0 && params.speckleWindowSize > 0 ) filterSpeckles(disp, FILTERED, params.speckleWindowSize, params.speckleRange, slidingSumBuf); - + if (disp0.data != disp.data) disp.convertTo(disp0, disp0.type(), 1./(1 << DISPARITY_SHIFT), 0); } - AlgorithmInfo* info() const; + AlgorithmInfo* info() const { return 0; } + + int getMinDisparity() const { return params.minDisparity; } + void setMinDisparity(int minDisparity) { params.minDisparity = minDisparity; } + + int getNumDisparities() const { return params.numDisparities; } + void setNumDisparities(int numDisparities) { params.numDisparities = numDisparities; } + + int getBlockSize() const { return params.SADWindowSize; } + void setBlockSize(int blockSize) { params.SADWindowSize = blockSize; } + + int getSpeckleWindowSize() const { return params.speckleWindowSize; } + void setSpeckleWindowSize(int speckleWindowSize) { params.speckleWindowSize = speckleWindowSize; } + + int getSpeckleRange() const { return params.speckleRange; } + void setSpeckleRange(int speckleRange) { params.speckleRange = speckleRange; } + + int getDisp12MaxDiff() const { return params.disp12MaxDiff; } + void setDisp12MaxDiff(int disp12MaxDiff) { params.disp12MaxDiff = disp12MaxDiff; } + + int getPreFilterType() const { return params.preFilterType; } + void setPreFilterType(int preFilterType) { params.preFilterType = preFilterType; } + + int getPreFilterSize() const { return params.preFilterSize; } + void setPreFilterSize(int preFilterSize) { params.preFilterSize = preFilterSize; } + + int getPreFilterCap() const { return params.preFilterCap; } + void setPreFilterCap(int preFilterCap) { params.preFilterCap = preFilterCap; } + + int getTextureThreshold() const { return params.textureThreshold; } + void setTextureThreshold(int textureThreshold) { params.textureThreshold = textureThreshold; } + + int getUniquenessRatio() const { return params.uniquenessRatio; } + void setUniquenessRatio(int uniquenessRatio) { params.uniquenessRatio = uniquenessRatio; } + + int getSmallerBlockSize() const { return 0; } + void setSmallerBlockSize(int) {} + + Rect getROI1() const { return params.roi1; } + void setROI1(Rect roi1) { params.roi1 = roi1; } + + Rect getROI2() const { return params.roi2; } + void setROI2(Rect roi2) { params.roi2 = roi2; } + + void write(FileStorage& fs) const + { + fs << "name" << name_ + << "minDisparity" << params.minDisparity + << "numDisparities" << params.numDisparities + << "blockSize" << params.SADWindowSize + << "speckleWindowSize" << params.speckleWindowSize + << "speckleRange" << params.speckleRange + << "disp12MaxDiff" << params.disp12MaxDiff + << "preFilterType" << params.preFilterType + << "preFilterSize" << params.preFilterSize + << "preFilterCap" << params.preFilterCap + << "textureThreshold" << params.textureThreshold + << "uniquenessRatio" << params.uniquenessRatio; + } + + void read(const FileNode& fn) + { + FileNode n = fn["name"]; + CV_Assert( n.isString() && String(n) == name_ ); + params.minDisparity = (int)fn["minDisparity"]; + params.numDisparities = (int)fn["numDisparities"]; + params.SADWindowSize = (int)fn["blockSize"]; + params.speckleWindowSize = (int)fn["speckleWindowSize"]; + params.speckleRange = (int)fn["speckleRange"]; + params.disp12MaxDiff = (int)fn["disp12MaxDiff"]; + params.preFilterType = (int)fn["preFilterType"]; + params.preFilterSize = (int)fn["preFilterSize"]; + params.preFilterCap = (int)fn["preFilterCap"]; + params.textureThreshold = (int)fn["textureThreshold"]; + params.uniquenessRatio = (int)fn["uniquenessRatio"]; + params.roi1 = params.roi2 = Rect(); + } StereoBMParams params; Mat preFilteredImg0, preFilteredImg1, cost, dispbuf; Mat slidingSumBuf; + + static const char* name_; }; -#define add_param(n) \ - obj.info()->addParam(obj, #n, obj.params.n) - -CV_INIT_ALGORITHM(StereoBMImpl, "StereoMatcher.BM", - add_param(preFilterType); - add_param(preFilterSize); - add_param(preFilterCap); - add_param(SADWindowSize); - add_param(minDisparity); - add_param(numDisparities); - add_param(textureThreshold); - add_param(uniquenessRatio); - add_param(speckleRange); - add_param(speckleWindowSize); - add_param(disp12MaxDiff); - add_param(dispType)); +const char* StereoBMImpl::name_ = "StereoMatcher.BM"; } -cv::Ptr cv::createStereoBM(int _numDisparities, int _SADWindowSize) +cv::Ptr cv::createStereoBM(int _numDisparities, int _SADWindowSize) { - return new StereoBMImpl(_numDisparities, _SADWindowSize); + return makePtr(_numDisparities, _SADWindowSize); } /* End of file. */ diff --git a/modules/calib3d/src/stereosgbm.cpp b/modules/calib3d/src/stereosgbm.cpp index 026201fc03..6d75d8f53d 100644 --- a/modules/calib3d/src/stereosgbm.cpp +++ b/modules/calib3d/src/stereosgbm.cpp @@ -75,13 +75,13 @@ struct StereoSGBMParams uniquenessRatio = 0; speckleWindowSize = 0; speckleRange = 0; - fullDP = false; + mode = StereoSGBM::MODE_SGBM; } StereoSGBMParams( int _minDisparity, int _numDisparities, int _SADWindowSize, int _P1, int _P2, int _disp12MaxDiff, int _preFilterCap, int _uniquenessRatio, int _speckleWindowSize, int _speckleRange, - bool _fullDP ) + int _mode ) { minDisparity = _minDisparity; numDisparities = _numDisparities; @@ -93,7 +93,7 @@ struct StereoSGBMParams uniquenessRatio = _uniquenessRatio; speckleWindowSize = _speckleWindowSize; speckleRange = _speckleRange; - fullDP = _fullDP; + mode = _mode; } int minDisparity; @@ -106,7 +106,7 @@ struct StereoSGBMParams int speckleWindowSize; int speckleRange; int disp12MaxDiff; - bool fullDP; + int mode; }; /* @@ -328,8 +328,8 @@ static void computeDisparitySGBM( const Mat& img1, const Mat& img2, #endif const int ALIGN = 16; - const int DISP_SHIFT = StereoSGBM::DISP_SHIFT; - const int DISP_SCALE = StereoSGBM::DISP_SCALE; + const int DISP_SHIFT = StereoMatcher::DISP_SHIFT; + const int DISP_SCALE = (1 << DISP_SHIFT); const CostType MAX_COST = SHRT_MAX; int minD = params.minDisparity, maxD = minD + params.numDisparities; @@ -344,7 +344,8 @@ static void computeDisparitySGBM( const Mat& img1, const Mat& img2, int D = maxD - minD, width1 = maxX1 - minX1; int INVALID_DISP = minD - 1, INVALID_DISP_SCALED = INVALID_DISP*DISP_SCALE; int SW2 = SADWindowSize.width/2, SH2 = SADWindowSize.height/2; - int npasses = params.fullDP ? 2 : 1; + bool fullDP = params.mode == StereoSGBM::MODE_HH; + int npasses = fullDP ? 2 : 1; const int TAB_OFS = 256*4, TAB_SIZE = 256 + TAB_OFS*2; PixType clipTab[TAB_SIZE]; @@ -373,7 +374,7 @@ static void computeDisparitySGBM( const Mat& img1, const Mat& img2, // we keep pixel difference cost (C) and the summary cost over NR directions (S). // we also keep all the partial costs for the previous line L_r(x,d) and also min_k L_r(x, k) size_t costBufSize = width1*D; - size_t CSBufSize = costBufSize*(params.fullDP ? height : 1); + size_t CSBufSize = costBufSize*(fullDP ? height : 1); size_t minLrSize = (width1 + LrBorder*2)*NR2, LrSize = minLrSize*D2; int hsumBufNRows = SH2*2 + 2; size_t totalBufSize = (LrSize + minLrSize)*NLR*sizeof(CostType) + // minLr[] and Lr[] @@ -434,8 +435,8 @@ static void computeDisparitySGBM( const Mat& img1, const Mat& img2, { int x, d; DispType* disp1ptr = disp1.ptr(y); - CostType* C = Cbuf + (!params.fullDP ? 0 : y*costBufSize); - CostType* S = Sbuf + (!params.fullDP ? 0 : y*costBufSize); + CostType* C = Cbuf + (!fullDP ? 0 : y*costBufSize); + CostType* S = Sbuf + (!fullDP ? 0 : y*costBufSize); if( pass == 1 ) // compute C on the first pass, and reuse it on the second pass, if any. { @@ -460,7 +461,7 @@ static void computeDisparitySGBM( const Mat& img1, const Mat& img2, if( y > 0 ) { const CostType* hsumSub = hsumBuf + (std::max(y - SH2 - 1, 0) % hsumBufNRows)*costBufSize; - const CostType* Cprev = !params.fullDP || y == 0 ? C : C - costBufSize; + const CostType* Cprev = !fullDP || y == 0 ? C : C - costBufSize; for( x = D; x < width1*D; x += D ) { @@ -828,8 +829,7 @@ static void computeDisparitySGBM( const Mat& img1, const Mat& img2, } } - -class StereoSGBMImpl : public StereoMatcher +class StereoSGBMImpl : public StereoSGBM { public: StereoSGBMImpl() @@ -840,12 +840,12 @@ public: StereoSGBMImpl( int _minDisparity, int _numDisparities, int _SADWindowSize, int _P1, int _P2, int _disp12MaxDiff, int _preFilterCap, int _uniquenessRatio, int _speckleWindowSize, int _speckleRange, - bool _fullDP ) + int _mode ) { params = StereoSGBMParams( _minDisparity, _numDisparities, _SADWindowSize, _P1, _P2, _disp12MaxDiff, _preFilterCap, _uniquenessRatio, _speckleWindowSize, _speckleRange, - _fullDP ); + _mode ); } void compute( InputArray leftarr, InputArray rightarr, OutputArray disparr ) @@ -861,47 +861,100 @@ public: medianBlur(disp, disp, 3); if( params.speckleWindowSize > 0 ) - filterSpeckles(disp, (params.minDisparity - 1)*STEREO_DISP_SCALE, params.speckleWindowSize, - STEREO_DISP_SCALE*params.speckleRange, buffer); + filterSpeckles(disp, (params.minDisparity - 1)*StereoMatcher::DISP_SCALE, params.speckleWindowSize, + StereoMatcher::DISP_SCALE*params.speckleRange, buffer); } - AlgorithmInfo* info() const; + AlgorithmInfo* info() const { return 0; } + + int getMinDisparity() const { return params.minDisparity; } + void setMinDisparity(int minDisparity) { params.minDisparity = minDisparity; } + + int getNumDisparities() const { return params.numDisparities; } + void setNumDisparities(int numDisparities) { params.numDisparities = numDisparities; } + + int getBlockSize() const { return params.SADWindowSize; } + void setBlockSize(int blockSize) { params.SADWindowSize = blockSize; } + + int getSpeckleWindowSize() const { return params.speckleWindowSize; } + void setSpeckleWindowSize(int speckleWindowSize) { params.speckleWindowSize = speckleWindowSize; } + + int getSpeckleRange() const { return params.speckleRange; } + void setSpeckleRange(int speckleRange) { params.speckleRange = speckleRange; } + + int getDisp12MaxDiff() const { return params.disp12MaxDiff; } + void setDisp12MaxDiff(int disp12MaxDiff) { params.disp12MaxDiff = disp12MaxDiff; } + + int getPreFilterCap() const { return params.preFilterCap; } + void setPreFilterCap(int preFilterCap) { params.preFilterCap = preFilterCap; } + + int getUniquenessRatio() const { return params.uniquenessRatio; } + void setUniquenessRatio(int uniquenessRatio) { params.uniquenessRatio = uniquenessRatio; } + + int getP1() const { return params.P1; } + void setP1(int P1) { params.P1 = P1; } + + int getP2() const { return params.P2; } + void setP2(int P2) { params.P2 = P2; } + + int getMode() const { return params.mode; } + void setMode(int mode) { params.mode = mode; } + + void write(FileStorage& fs) const + { + fs << "name" << name_ + << "minDisparity" << params.minDisparity + << "numDisparities" << params.numDisparities + << "blockSize" << params.SADWindowSize + << "speckleWindowSize" << params.speckleWindowSize + << "speckleRange" << params.speckleRange + << "disp12MaxDiff" << params.disp12MaxDiff + << "preFilterCap" << params.preFilterCap + << "uniquenessRatio" << params.uniquenessRatio + << "P1" << params.P1 + << "P2" << params.P2 + << "mode" << params.mode; + } + + void read(const FileNode& fn) + { + FileNode n = fn["name"]; + CV_Assert( n.isString() && String(n) == name_ ); + params.minDisparity = (int)fn["minDisparity"]; + params.numDisparities = (int)fn["numDisparities"]; + params.SADWindowSize = (int)fn["blockSize"]; + params.speckleWindowSize = (int)fn["speckleWindowSize"]; + params.speckleRange = (int)fn["speckleRange"]; + params.disp12MaxDiff = (int)fn["disp12MaxDiff"]; + params.preFilterCap = (int)fn["preFilterCap"]; + params.uniquenessRatio = (int)fn["uniquenessRatio"]; + params.P1 = (int)fn["P1"]; + params.P2 = (int)fn["P2"]; + params.mode = (int)fn["mode"]; + } StereoSGBMParams params; Mat buffer; + static const char* name_; }; +const char* StereoSGBMImpl::name_ = "StereoMatcher.SGBM"; -Ptr createStereoSGBM(int minDisparity, int numDisparities, int SADWindowSize, - int P1, int P2, int disp12MaxDiff, - int preFilterCap, int uniquenessRatio, - int speckleWindowSize, int speckleRange, - bool fullDP) + +Ptr createStereoSGBM(int minDisparity, int numDisparities, int SADWindowSize, + int P1, int P2, int disp12MaxDiff, + int preFilterCap, int uniquenessRatio, + int speckleWindowSize, int speckleRange, + int mode) { - return new StereoSGBMImpl(minDisparity, numDisparities, SADWindowSize, - P1, P2, disp12MaxDiff, - preFilterCap, uniquenessRatio, - speckleWindowSize, speckleRange, - fullDP); + return Ptr( + new StereoSGBMImpl(minDisparity, numDisparities, SADWindowSize, + P1, P2, disp12MaxDiff, + preFilterCap, uniquenessRatio, + speckleWindowSize, speckleRange, + mode)); } - -#define add_param(n) \ - obj.info()->addParam(obj, #n, obj.params.n) - -CV_INIT_ALGORITHM(StereoSGBMImpl, "StereoMatcher.SGBM", - add_param(minDisparity); - add_param(numDisparities); - add_param(SADWindowSize); - add_param(preFilterCap); - add_param(uniquenessRatio); - add_param(P1); - add_param(P2); - add_param(speckleWindowSize); - add_param(speckleRange); - add_param(disp12MaxDiff); - add_param(fullDP)); - Rect getValidDisparityROI( Rect roi1, Rect roi2, int minDisparity, int numberOfDisparities, @@ -1117,4 +1170,3 @@ void cv::validateDisparity( InputOutputArray _disp, InputArray _cost, int minDis } } } - diff --git a/modules/calib3d/src/triangulate.cpp b/modules/calib3d/src/triangulate.cpp index 9f52b37163..b0af3dc466 100644 --- a/modules/calib3d/src/triangulate.cpp +++ b/modules/calib3d/src/triangulate.cpp @@ -40,6 +40,7 @@ //M*/ #include "precomp.hpp" +#include "opencv2/calib3d/calib3d_c.h" // cvCorrectMatches function is Copyright (C) 2009, Jostein Austvik Jacobsen. // cvTriangulatePoints function is derived from icvReconstructPointsFor3View, originally by Valery Mosyagin. @@ -239,32 +240,32 @@ cvCorrectMatches(CvMat *F_, CvMat *points1_, CvMat *points2_, CvMat *new_points1 } // Make sure F uses double precision - F = cvCreateMat(3,3,CV_64FC1); + F.reset(cvCreateMat(3,3,CV_64FC1)); cvConvert(F_, F); // Make sure points1 uses double precision - points1 = cvCreateMat(points1_->rows,points1_->cols,CV_64FC2); + points1.reset(cvCreateMat(points1_->rows,points1_->cols,CV_64FC2)); cvConvert(points1_, points1); // Make sure points2 uses double precision - points2 = cvCreateMat(points2_->rows,points2_->cols,CV_64FC2); + points2.reset(cvCreateMat(points2_->rows,points2_->cols,CV_64FC2)); cvConvert(points2_, points2); - tmp33 = cvCreateMat(3,3,CV_64FC1); - tmp31 = cvCreateMat(3,1,CV_64FC1), tmp31_2 = cvCreateMat(3,1,CV_64FC1); - T1i = cvCreateMat(3,3,CV_64FC1), T2i = cvCreateMat(3,3,CV_64FC1); - R1 = cvCreateMat(3,3,CV_64FC1), R2 = cvCreateMat(3,3,CV_64FC1); - TFT = cvCreateMat(3,3,CV_64FC1), TFTt = cvCreateMat(3,3,CV_64FC1), RTFTR = cvCreateMat(3,3,CV_64FC1); - U = cvCreateMat(3,3,CV_64FC1); - S = cvCreateMat(3,3,CV_64FC1); - V = cvCreateMat(3,3,CV_64FC1); - e1 = cvCreateMat(3,1,CV_64FC1), e2 = cvCreateMat(3,1,CV_64FC1); + tmp33.reset(cvCreateMat(3,3,CV_64FC1)); + tmp31.reset(cvCreateMat(3,1,CV_64FC1)), tmp31_2.reset(cvCreateMat(3,1,CV_64FC1)); + T1i.reset(cvCreateMat(3,3,CV_64FC1)), T2i.reset(cvCreateMat(3,3,CV_64FC1)); + R1.reset(cvCreateMat(3,3,CV_64FC1)), R2.reset(cvCreateMat(3,3,CV_64FC1)); + TFT.reset(cvCreateMat(3,3,CV_64FC1)), TFTt.reset(cvCreateMat(3,3,CV_64FC1)), RTFTR.reset(cvCreateMat(3,3,CV_64FC1)); + U.reset(cvCreateMat(3,3,CV_64FC1)); + S.reset(cvCreateMat(3,3,CV_64FC1)); + V.reset(cvCreateMat(3,3,CV_64FC1)); + e1.reset(cvCreateMat(3,1,CV_64FC1)), e2.reset(cvCreateMat(3,1,CV_64FC1)); double x1, y1, x2, y2; double scale; double f1, f2, a, b, c, d; - polynomial = cvCreateMat(1,7,CV_64FC1); - result = cvCreateMat(1,6,CV_64FC2); + polynomial.reset(cvCreateMat(1,7,CV_64FC1)); + result.reset(cvCreateMat(1,6,CV_64FC2)); double t_min, s_val, t, s; for (int p = 0; p < points1->cols; ++p) { // Replace F by T2-t * F * T1-t diff --git a/modules/calib3d/test/test_affine3.cpp b/modules/calib3d/test/test_affine3.cpp index 196d428e45..62326e9203 100644 --- a/modules/calib3d/test/test_affine3.cpp +++ b/modules/calib3d/test/test_affine3.cpp @@ -52,30 +52,30 @@ TEST(Calib3d_Affine3f, accuracy) cv::Mat expected; cv::Rodrigues(rvec, expected); - - + + ASSERT_EQ(0, norm(cv::Mat(affine.matrix, false).colRange(0, 3).rowRange(0, 3) != expected)); ASSERT_EQ(0, norm(cv::Mat(affine.linear()) != expected)); - - + + cv::Matx33d R = cv::Matx33d::eye(); - + double angle = 50; R.val[0] = R.val[4] = std::cos(CV_PI*angle/180.0); R.val[3] = std::sin(CV_PI*angle/180.0); R.val[1] = -R.val[3]; - - + + cv::Affine3d affine1(cv::Mat(cv::Vec3d(0.2, 0.5, 0.3)).reshape(1, 1), cv::Vec3d(4, 5, 6)); cv::Affine3d affine2(R, cv::Vec3d(1, 1, 0.4)); - + cv::Affine3d result = affine1.inv() * affine2; - + expected = cv::Mat(affine1.matrix.inv(cv::DECOMP_SVD)) * cv::Mat(affine2.matrix, false); - + cv::Mat diff; cv::absdiff(expected, result.matrix, diff); - + ASSERT_LT(cv::norm(diff, cv::NORM_INF), 1e-15); } diff --git a/modules/calib3d/test/test_affine3d_estimator.cpp b/modules/calib3d/test/test_affine3d_estimator.cpp index ff061aacfa..f31e2e7324 100644 --- a/modules/calib3d/test/test_affine3d_estimator.cpp +++ b/modules/calib3d/test/test_affine3d_estimator.cpp @@ -195,4 +195,3 @@ void CV_Affine3D_EstTest::run( int /* start_from */) } TEST(Calib3d_EstimateAffineTransform, accuracy) { CV_Affine3D_EstTest test; test.safe_run(); } - diff --git a/modules/calib3d/test/test_cameracalibration.cpp b/modules/calib3d/test/test_cameracalibration.cpp index e8b5570949..fb82382377 100644 --- a/modules/calib3d/test/test_cameracalibration.cpp +++ b/modules/calib3d/test/test_cameracalibration.cpp @@ -40,6 +40,7 @@ //M*/ #include "test_precomp.hpp" +#include "opencv2/calib3d/calib3d_c.h" #include diff --git a/modules/calib3d/test/test_cameracalibration_artificial.cpp b/modules/calib3d/test/test_cameracalibration_artificial.cpp index 733f0069c7..1ff13c9e87 100644 --- a/modules/calib3d/test/test_cameracalibration_artificial.cpp +++ b/modules/calib3d/test/test_cameracalibration_artificial.cpp @@ -304,7 +304,7 @@ protected: for(size_t i = 0; i < brdsNum; ++i) { Mat gray; - cvtColor(boards[i], gray, CV_BGR2GRAY); + cvtColor(boards[i], gray, COLOR_BGR2GRAY); vector tmp = imagePoints_findCb[i]; cornerSubPix(gray, tmp, Size(5, 5), Size(-1,-1), tc); imagePoints.push_back(tmp); @@ -314,7 +314,7 @@ protected: for(size_t i = 0; i < brdsNum; ++i) { Mat gray; - cvtColor(boards[i], gray, CV_BGR2GRAY); + cvtColor(boards[i], gray, COLOR_BGR2GRAY); vector tmp = imagePoints_findCb[i]; find4QuadCornerSubpix(gray, tmp, Size(5, 5)); imagePoints.push_back(tmp); @@ -327,7 +327,7 @@ protected: Mat camMat_est = Mat::eye(3, 3, CV_64F), distCoeffs_est = Mat::zeros(1, 5, CV_64F); vector rvecs_est, tvecs_est; - int flags = /*CV_CALIB_FIX_K3|*/CV_CALIB_FIX_K4|CV_CALIB_FIX_K5|CV_CALIB_FIX_K6; //CALIB_FIX_K3; //CALIB_FIX_ASPECT_RATIO | | CALIB_ZERO_TANGENT_DIST; + int flags = /*CALIB_FIX_K3|*/CALIB_FIX_K4|CALIB_FIX_K5|CALIB_FIX_K6; //CALIB_FIX_K3; //CALIB_FIX_ASPECT_RATIO | | CALIB_ZERO_TANGENT_DIST; TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 100, DBL_EPSILON); double rep_error = calibrateCamera(objectPoints, imagePoints, imgSize, camMat_est, distCoeffs_est, rvecs_est, tvecs_est, flags, criteria); rep_error /= brdsNum * cornersSize.area(); diff --git a/modules/calib3d/test/test_cameracalibration_badarg.cpp b/modules/calib3d/test/test_cameracalibration_badarg.cpp index b805e71a49..3edab8becf 100644 --- a/modules/calib3d/test/test_cameracalibration_badarg.cpp +++ b/modules/calib3d/test/test_cameracalibration_badarg.cpp @@ -41,6 +41,7 @@ #include "test_precomp.hpp" #include "test_chessboardgenerator.hpp" +#include "opencv2/calib3d/calib3d_c.h" #include @@ -734,5 +735,3 @@ protected: TEST(Calib3d_CalibrateCamera_C, badarg) { CV_CameraCalibrationBadArgTest test; test.safe_run(); } TEST(Calib3d_Rodrigues_C, badarg) { CV_Rodrigues2BadArgTest test; test.safe_run(); } TEST(Calib3d_ProjectPoints_C, badarg) { CV_ProjectPoints2BadArgTest test; test.safe_run(); } - - diff --git a/modules/calib3d/test/test_chessboardgenerator.cpp b/modules/calib3d/test/test_chessboardgenerator.cpp index 7c761fc572..7c0bd34dc7 100644 --- a/modules/calib3d/test/test_chessboardgenerator.cpp +++ b/modules/calib3d/test/test_chessboardgenerator.cpp @@ -161,15 +161,15 @@ Mat cv::ChessBoardGenerator::generateChessBoard(const Mat& bg, const Mat& camMat if (rendererResolutionMultiplier == 1) { result = bg.clone(); - drawContours(result, whole_contour, -1, Scalar::all(255), CV_FILLED, CV_AA); - drawContours(result, squares_black, -1, Scalar::all(0), CV_FILLED, CV_AA); + drawContours(result, whole_contour, -1, Scalar::all(255), FILLED, LINE_AA); + drawContours(result, squares_black, -1, Scalar::all(0), FILLED, LINE_AA); } else { Mat tmp; resize(bg, tmp, bg.size() * rendererResolutionMultiplier); - drawContours(tmp, whole_contour, -1, Scalar::all(255), CV_FILLED, CV_AA); - drawContours(tmp, squares_black, -1, Scalar::all(0), CV_FILLED, CV_AA); + drawContours(tmp, whole_contour, -1, Scalar::all(255), FILLED, LINE_AA); + drawContours(tmp, squares_black, -1, Scalar::all(0), FILLED, LINE_AA); resize(tmp, result, bg.size(), 0, 0, INTER_AREA); } @@ -329,4 +329,3 @@ Mat cv::ChessBoardGenerator::operator ()(const Mat& bg, const Mat& camMat, const return generateChessBoard(bg, camMat, distCoeffs, zero, pb1, pb2, squareSize.width, squareSize.height, pts3d, corners); } - diff --git a/modules/calib3d/test/test_chesscorners.cpp b/modules/calib3d/test/test_chesscorners.cpp index 42c25b86ad..f9625d540a 100644 --- a/modules/calib3d/test/test_chesscorners.cpp +++ b/modules/calib3d/test/test_chesscorners.cpp @@ -57,14 +57,14 @@ void show_points( const Mat& gray, const Mat& u, const vector& v, Size merge(vector(3, gray), rgb); for(size_t i = 0; i < v.size(); i++ ) - circle( rgb, v[i], 3, CV_RGB(255, 0, 0), CV_FILLED); + circle( rgb, v[i], 3, Scalar(255, 0, 0), FILLED); if( !u.empty() ) { const Point2f* u_data = u.ptr(); size_t count = u.cols * u.rows; for(size_t i = 0; i < count; i++ ) - circle( rgb, u_data[i], 3, CV_RGB(0, 255, 0), CV_FILLED); + circle( rgb, u_data[i], 3, Scalar(0, 255, 0), FILLED); } if (!v.empty()) { @@ -208,7 +208,7 @@ void CV_ChessboardDetectorTest::run_batch( const string& filename ) } int progress = 0; - int max_idx = board_list.node->data.seq->total/2; + int max_idx = board_list.size()/2; double sum_error = 0.0; int count = 0; @@ -217,7 +217,7 @@ void CV_ChessboardDetectorTest::run_batch( const string& filename ) ts->update_context( this, idx, true ); /* read the image */ - string img_file = board_list[idx * 2]; + String img_file = board_list[idx * 2]; Mat gray = imread( folder + img_file, 0); if( gray.empty() ) @@ -227,7 +227,7 @@ void CV_ChessboardDetectorTest::run_batch( const string& filename ) return; } - string _filename = folder + (string)board_list[idx * 2 + 1]; + String _filename = folder + (String)board_list[idx * 2 + 1]; bool doesContatinChessboard; Mat expected; { @@ -244,7 +244,7 @@ void CV_ChessboardDetectorTest::run_batch( const string& filename ) switch( pattern ) { case CHESSBOARD: - result = findChessboardCorners(gray, pattern_size, v, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_NORMALIZE_IMAGE); + result = findChessboardCorners(gray, pattern_size, v, CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE); break; case CIRCLES_GRID: result = findCirclesGrid(gray, pattern_size, v); @@ -459,7 +459,7 @@ bool CV_ChessboardDetectorTest::checkByGenerator() vector& cnt = cnts[0]; cnt.push_back(cg[ 0]); cnt.push_back(cg[0+2]); cnt.push_back(cg[7+0]); cnt.push_back(cg[7+2]); - cv::drawContours(cb, cnts, -1, Scalar::all(128), CV_FILLED); + cv::drawContours(cb, cnts, -1, Scalar::all(128), FILLED); found = findChessboardCorners(cb, cbg.cornersSize(), corners_found); if (found) diff --git a/modules/calib3d/test/test_chesscorners_badarg.cpp b/modules/calib3d/test/test_chesscorners_badarg.cpp index d7c4c4f4ce..318912eeb4 100644 --- a/modules/calib3d/test/test_chesscorners_badarg.cpp +++ b/modules/calib3d/test/test_chesscorners_badarg.cpp @@ -41,6 +41,7 @@ #include "test_precomp.hpp" #include "test_chessboardgenerator.hpp" +#include "opencv2/calib3d/calib3d_c.h" #include diff --git a/modules/calib3d/test/test_chesscorners_timing.cpp b/modules/calib3d/test/test_chesscorners_timing.cpp index 6195c04b07..47653f88d8 100644 --- a/modules/calib3d/test/test_chesscorners_timing.cpp +++ b/modules/calib3d/test/test_chesscorners_timing.cpp @@ -40,6 +40,8 @@ //M*/ #include "test_precomp.hpp" +#include "opencv2/imgproc/imgproc_c.h" +#include "opencv2/calib3d/calib3d_c.h" class CV_ChessboardDetectorTimingTest : public cvtest::BaseTest { @@ -66,7 +68,7 @@ void CV_ChessboardDetectorTimingTest::run( int start_from ) CvMat* _v = 0; CvPoint2D32f* v; - IplImage* img = 0; + IplImage img; IplImage* gray = 0; IplImage* thresh = 0; @@ -105,9 +107,10 @@ void CV_ChessboardDetectorTimingTest::run( int start_from ) /* read the image */ sprintf( filename, "%s%s", filepath, imgname ); - img = cvLoadImage( filename ); + cv::Mat img2 = cv::imread( filename ); + img = img2; - if( !img ) + if( img2.empty() ) { ts->printf( cvtest::TS::LOG, "one of chessboard images can't be read: %s\n", filename ); if( max_idx == 1 ) @@ -120,9 +123,9 @@ void CV_ChessboardDetectorTimingTest::run( int start_from ) ts->printf(cvtest::TS::LOG, "%s: chessboard %d:\n", imgname, is_chessboard); - gray = cvCreateImage( cvSize( img->width, img->height ), IPL_DEPTH_8U, 1 ); - thresh = cvCreateImage( cvSize( img->width, img->height ), IPL_DEPTH_8U, 1 ); - cvCvtColor( img, gray, CV_BGR2GRAY ); + gray = cvCreateImage( cvSize( img.width, img.height ), IPL_DEPTH_8U, 1 ); + thresh = cvCreateImage( cvSize( img.width, img.height ), IPL_DEPTH_8U, 1 ); + cvCvtColor( &img, gray, CV_BGR2GRAY ); count0 = pattern_size.width*pattern_size.height; @@ -164,7 +167,6 @@ void CV_ChessboardDetectorTimingTest::run( int start_from ) find_chessboard_time*1e-6, find_chessboard_time/num_pixels); cvReleaseMat( &_v ); - cvReleaseImage( &img ); cvReleaseImage( &gray ); cvReleaseImage( &thresh ); progress = update_progress( progress, idx-1, max_idx, 0 ); @@ -175,7 +177,6 @@ _exit_: /* release occupied memory */ cvReleaseMat( &_v ); cvReleaseFileStorage( &fs ); - cvReleaseImage( &img ); cvReleaseImage( &gray ); cvReleaseImage( &thresh ); diff --git a/modules/calib3d/test/test_compose_rt.cpp b/modules/calib3d/test/test_compose_rt.cpp index b71288e6d4..577cc06270 100644 --- a/modules/calib3d/test/test_compose_rt.cpp +++ b/modules/calib3d/test/test_compose_rt.cpp @@ -212,4 +212,3 @@ protected: }; TEST(Calib3d_ComposeRT, accuracy) { CV_composeRT_Test test; test.safe_run(); } - diff --git a/modules/calib3d/test/test_cornerssubpix.cpp b/modules/calib3d/test/test_cornerssubpix.cpp index 88f7deee06..4426d5ea5e 100644 --- a/modules/calib3d/test/test_cornerssubpix.cpp +++ b/modules/calib3d/test/test_cornerssubpix.cpp @@ -40,6 +40,7 @@ //M*/ #include "test_precomp.hpp" +#include "opencv2/imgproc/imgproc_c.h" #include #include "test_chessboardgenerator.hpp" diff --git a/modules/calib3d/test/test_fundam.cpp b/modules/calib3d/test/test_fundam.cpp index 19ee70fa1b..7e6f9a8e71 100644 --- a/modules/calib3d/test/test_fundam.cpp +++ b/modules/calib3d/test/test_fundam.cpp @@ -40,6 +40,7 @@ //M*/ #include "test_precomp.hpp" +#include "opencv2/calib3d/calib3d_c.h" using namespace cv; using namespace std; @@ -1079,7 +1080,7 @@ protected: void run_func(); void prepare_to_validation( int ); - double sampson_error(const double* f, double x1, double y1, double x2, double y2); + double sampson_error(const double* f, double x1, double y1, double x2, double y2); int method; int img_size; @@ -1145,9 +1146,8 @@ void CV_EssentialMatTest::get_test_array_types_and_sizes( int /*test_case_idx*/, int pt_count = MAX(5, cvRound(exp(pt_count_exp))); dims = cvtest::randInt(rng) % 2 + 2; - dims = 2; + dims = 2; method = CV_LMEDS << (cvtest::randInt(rng) % 2); - types[INPUT][0] = CV_MAKETYPE(pt_depth, 1); @@ -1192,11 +1192,11 @@ void CV_EssentialMatTest::get_test_array_types_and_sizes( int /*test_case_idx*/, sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(3,1); types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1; sizes[OUTPUT][1] = sizes[REF_OUTPUT][1] = cvSize(pt_count,1); - types[OUTPUT][1] = types[REF_OUTPUT][1] = CV_8UC1; + types[OUTPUT][1] = types[REF_OUTPUT][1] = CV_8UC1; sizes[OUTPUT][2] = sizes[REF_OUTPUT][2] = cvSize(1,1); types[OUTPUT][2] = types[REF_OUTPUT][2] = CV_64FC1; sizes[OUTPUT][3] = sizes[REF_OUTPUT][3] = cvSize(1,1); - types[OUTPUT][3] = types[REF_OUTPUT][3] = CV_8UC1; + types[OUTPUT][3] = types[REF_OUTPUT][3] = CV_8UC1; } @@ -1289,46 +1289,46 @@ int CV_EssentialMatTest::prepare_test_case( int test_case_idx ) void CV_EssentialMatTest::run_func() { Mat _input0(test_mat[INPUT][0]), _input1(test_mat[INPUT][1]); - Mat K(test_mat[INPUT][4]); - double focal(K.at(0, 0)); - cv::Point2d pp(K.at(0, 2), K.at(1, 2)); + Mat K(test_mat[INPUT][4]); + double focal(K.at(0, 0)); + cv::Point2d pp(K.at(0, 2), K.at(1, 2)); RNG& rng = ts->get_rng(); Mat E, mask1(test_mat[TEMP][1]); - E = cv::findEssentialMat( _input0, _input1, focal, pp, method, 0.99, MAX(sigma*3, 0.0001), mask1 ); - if (E.rows > 3) + E = cv::findEssentialMat( _input0, _input1, focal, pp, method, 0.99, MAX(sigma*3, 0.0001), mask1 ); + if (E.rows > 3) { - int count = E.rows / 3; - int row = (cvtest::randInt(rng) % count) * 3; - E = E.rowRange(row, row + 3) * 1.0; + int count = E.rows / 3; + int row = (cvtest::randInt(rng) % count) * 3; + E = E.rowRange(row, row + 3) * 1.0; } - E.copyTo(test_mat[TEMP][0]); + E.copyTo(test_mat[TEMP][0]); - Mat R, t, mask2; - recoverPose( E, _input0, _input1, R, t, focal, pp, mask2 ); - R.copyTo(test_mat[TEMP][2]); - t.copyTo(test_mat[TEMP][3]); - mask2.copyTo(test_mat[TEMP][4]); + Mat R, t, mask2; + recoverPose( E, _input0, _input1, R, t, focal, pp, mask2 ); + R.copyTo(test_mat[TEMP][2]); + t.copyTo(test_mat[TEMP][3]); + mask2.copyTo(test_mat[TEMP][4]); } double CV_EssentialMatTest::sampson_error(const double * f, double x1, double y1, double x2, double y2) { double Fx1[3] = { - f[0] * x1 + f[1] * y1 + f[2], - f[3] * x1 + f[4] * y1 + f[5], + f[0] * x1 + f[1] * y1 + f[2], + f[3] * x1 + f[4] * y1 + f[5], f[6] * x1 + f[7] * y1 + f[8] - }; + }; double Ftx2[3] = { - f[0] * x2 + f[3] * y2 + f[6], - f[1] * x2 + f[4] * y2 + f[7], + f[0] * x2 + f[3] * y2 + f[6], + f[1] * x2 + f[4] * y2 + f[7], f[2] * x2 + f[5] * y2 + f[8] - }; - double x2tFx1 = Fx1[0] * x2 + Fx1[1] * y2 + Fx1[2]; + }; + double x2tFx1 = Fx1[0] * x2 + Fx1[1] * y2 + Fx1[2]; - double error = x2tFx1 * x2tFx1 / (Fx1[0] * Fx1[0] + Fx1[1] * Fx1[1] + Ftx2[0] * Ftx2[0] + Ftx2[1] * Ftx2[1]); - error = sqrt(error); - return error; + double error = x2tFx1 * x2tFx1 / (Fx1[0] * Fx1[0] + Fx1[1] * Fx1[1] + Ftx2[0] * Ftx2[0] + Ftx2[1] * Ftx2[1]); + error = sqrt(error); + return error; } @@ -1338,7 +1338,7 @@ void CV_EssentialMatTest::prepare_to_validation( int test_case_idx ) const Mat& A = test_mat[INPUT][4]; double f0[9], f[9], e[9]; Mat F0(3, 3, CV_64FC1, f0), F(3, 3, CV_64F, f); - Mat E(3, 3, CV_64F, e); + Mat E(3, 3, CV_64F, e); Mat invA, R=Rt0.colRange(0, 3), T1, T2; @@ -1362,7 +1362,7 @@ void CV_EssentialMatTest::prepare_to_validation( int test_case_idx ) uchar* mtfm2 = test_mat[OUTPUT][1].data; double* e_prop1 = (double*)test_mat[REF_OUTPUT][0].data; double* e_prop2 = (double*)test_mat[OUTPUT][0].data; - Mat E_prop2 = Mat(3, 1, CV_64F, e_prop2); + Mat E_prop2 = Mat(3, 1, CV_64F, e_prop2); int i, pt_count = test_mat[INPUT][2].cols; Mat p1( 1, pt_count, CV_64FC2 ); @@ -1381,8 +1381,8 @@ void CV_EssentialMatTest::prepare_to_validation( int test_case_idx ) double y1 = p1.at(i).y; double x2 = p2.at(i).x; double y2 = p2.at(i).y; -// double t0 = sampson_error(f0, x1, y1, x2, y2); -// double t = sampson_error(f, x1, y1, x2, y2); +// double t0 = sampson_error(f0, x1, y1, x2, y2); +// double t = sampson_error(f, x1, y1, x2, y2); double n1 = 1./sqrt(x1*x1 + y1*y1 + 1); double n2 = 1./sqrt(x2*x2 + y2*y2 + 1); double t0 = fabs(f0[0]*x2*x1 + f0[1]*x2*y1 + f0[2]*x2 + @@ -1394,7 +1394,7 @@ void CV_EssentialMatTest::prepare_to_validation( int test_case_idx ) mtfm1[i] = 1; mtfm2[i] = !status[i] || t0 > err_level || t < err_level; } - + e_prop1[0] = sqrt(0.5); e_prop1[1] = sqrt(0.5); e_prop1[2] = 0; @@ -1402,26 +1402,26 @@ void CV_EssentialMatTest::prepare_to_validation( int test_case_idx ) e_prop2[0] = 0; e_prop2[1] = 0; e_prop2[2] = 0; - SVD::compute(E, E_prop2); + SVD::compute(E, E_prop2); - double* pose_prop1 = (double*)test_mat[REF_OUTPUT][2].data; - double* pose_prop2 = (double*)test_mat[OUTPUT][2].data; - double terr1 = norm(Rt0.col(3) / norm(Rt0.col(3)) + test_mat[TEMP][3]); - double terr2 = norm(Rt0.col(3) / norm(Rt0.col(3)) - test_mat[TEMP][3]); - Mat rvec; - Rodrigues(Rt0.colRange(0, 3), rvec); - pose_prop1[0] = 0; - // No check for CV_LMeDS on translation. Since it - // involves with some degraded problem, when data is exact inliers. - pose_prop2[0] = method == CV_LMEDS || pt_count == 5 ? 0 : MIN(terr1, terr2); + double* pose_prop1 = (double*)test_mat[REF_OUTPUT][2].data; + double* pose_prop2 = (double*)test_mat[OUTPUT][2].data; + double terr1 = norm(Rt0.col(3) / norm(Rt0.col(3)) + test_mat[TEMP][3]); + double terr2 = norm(Rt0.col(3) / norm(Rt0.col(3)) - test_mat[TEMP][3]); + Mat rvec; + Rodrigues(Rt0.colRange(0, 3), rvec); + pose_prop1[0] = 0; + // No check for CV_LMeDS on translation. Since it + // involves with some degraded problem, when data is exact inliers. + pose_prop2[0] = method == CV_LMEDS || pt_count == 5 ? 0 : MIN(terr1, terr2); -// int inliers_count = countNonZero(test_mat[TEMP][1]); -// int good_count = countNonZero(test_mat[TEMP][4]); - test_mat[OUTPUT][3] = true; //good_count >= inliers_count / 2; - test_mat[REF_OUTPUT][3] = true; +// int inliers_count = countNonZero(test_mat[TEMP][1]); +// int good_count = countNonZero(test_mat[TEMP][4]); + test_mat[OUTPUT][3] = true; //good_count >= inliers_count / 2; + test_mat[REF_OUTPUT][3] = true; } diff --git a/modules/calib3d/test/test_homography.cpp b/modules/calib3d/test/test_homography.cpp index f68af1d7c1..5bb50bb265 100644 --- a/modules/calib3d/test/test_homography.cpp +++ b/modules/calib3d/test/test_homography.cpp @@ -65,7 +65,7 @@ #define METHODS_COUNT 3 int NORM_TYPE[COUNT_NORM_TYPES] = {cv::NORM_L1, cv::NORM_L2, cv::NORM_INF}; -int METHOD[METHODS_COUNT] = {0, CV_RANSAC, CV_LMEDS}; +int METHOD[METHODS_COUNT] = {0, cv::RANSAC, cv::LMEDS}; using namespace cv; using namespace std; @@ -309,7 +309,7 @@ void CV_HomographyTest::run(int) switch (method) { case 0: - case CV_LMEDS: + case LMEDS: { Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, method), cv::findHomography(src_mat_2f, dst_vec, method), @@ -339,14 +339,14 @@ void CV_HomographyTest::run(int) continue; } - case CV_RANSAC: + case RANSAC: { cv::Mat mask [4]; double diff; - Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, CV_RANSAC, reproj_threshold, mask[0]), - cv::findHomography(src_mat_2f, dst_vec, CV_RANSAC, reproj_threshold, mask[1]), - cv::findHomography(src_vec, dst_mat_2f, CV_RANSAC, reproj_threshold, mask[2]), - cv::findHomography(src_vec, dst_vec, CV_RANSAC, reproj_threshold, mask[3]) }; + Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, RANSAC, reproj_threshold, mask[0]), + cv::findHomography(src_mat_2f, dst_vec, RANSAC, reproj_threshold, mask[1]), + cv::findHomography(src_vec, dst_mat_2f, RANSAC, reproj_threshold, mask[2]), + cv::findHomography(src_vec, dst_vec, RANSAC, reproj_threshold, mask[3]) }; for (int j = 0; j < 4; ++j) { @@ -411,7 +411,7 @@ void CV_HomographyTest::run(int) switch (method) { case 0: - case CV_LMEDS: + case LMEDS: { Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f), cv::findHomography(src_mat_2f, dst_vec), @@ -466,14 +466,14 @@ void CV_HomographyTest::run(int) continue; } - case CV_RANSAC: + case RANSAC: { cv::Mat mask_res [4]; - Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, CV_RANSAC, reproj_threshold, mask_res[0]), - cv::findHomography(src_mat_2f, dst_vec, CV_RANSAC, reproj_threshold, mask_res[1]), - cv::findHomography(src_vec, dst_mat_2f, CV_RANSAC, reproj_threshold, mask_res[2]), - cv::findHomography(src_vec, dst_vec, CV_RANSAC, reproj_threshold, mask_res[3]) }; + Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, RANSAC, reproj_threshold, mask_res[0]), + cv::findHomography(src_mat_2f, dst_vec, RANSAC, reproj_threshold, mask_res[1]), + cv::findHomography(src_vec, dst_mat_2f, RANSAC, reproj_threshold, mask_res[2]), + cv::findHomography(src_vec, dst_vec, RANSAC, reproj_threshold, mask_res[3]) }; for (int j = 0; j < 4; ++j) { diff --git a/modules/calib3d/test/test_modelest.cpp b/modules/calib3d/test/test_modelest.cpp index 5b0a860169..55cb79ebaf 100644 --- a/modules/calib3d/test/test_modelest.cpp +++ b/modules/calib3d/test/test_modelest.cpp @@ -229,4 +229,3 @@ void CV_ModelEstimator2_Test::run_func() TEST(Calib3d_ModelEstimator2, accuracy) { CV_ModelEstimator2_Test test; test.safe_run(); } #endif - diff --git a/modules/calib3d/test/test_posit.cpp b/modules/calib3d/test/test_posit.cpp index 34f3cc4d53..8a77d19ad8 100644 --- a/modules/calib3d/test/test_posit.cpp +++ b/modules/calib3d/test/test_posit.cpp @@ -40,6 +40,7 @@ //M*/ #include "test_precomp.hpp" +#include "opencv2/calib3d/calib3d_c.h" using namespace cv; using namespace std; @@ -189,13 +190,13 @@ void CV_POSITTest::run( int start_from ) rotation->data.fl, translation->data.fl ); cvReleasePOSITObject( &object ); - //Mat _rotation = cvarrToMat(rotation), _true_rotation = cvarrToMat(true_rotation); - //Mat _translation = cvarrToMat(translation), _true_translation = cvarrToMat(true_translation); - code = cvtest::cmpEps2( ts, rotation, true_rotation, flEpsilon, false, "rotation matrix" ); + Mat _rotation = cvarrToMat(rotation), _true_rotation = cvarrToMat(true_rotation); + Mat _translation = cvarrToMat(translation), _true_translation = cvarrToMat(true_translation); + code = cvtest::cmpEps2( ts, _rotation, _true_rotation, flEpsilon, false, "rotation matrix" ); if( code < 0 ) break; - code = cvtest::cmpEps2( ts, translation, true_translation, flEpsilon, false, "translation vector" ); + code = cvtest::cmpEps2( ts, _translation, _true_translation, flEpsilon, false, "translation vector" ); if( code < 0 ) break; } diff --git a/modules/calib3d/test/test_precomp.hpp b/modules/calib3d/test/test_precomp.hpp index fee6551f0c..d670a4c220 100644 --- a/modules/calib3d/test/test_precomp.hpp +++ b/modules/calib3d/test/test_precomp.hpp @@ -9,12 +9,11 @@ #ifndef __OPENCV_TEST_PRECOMP_HPP__ #define __OPENCV_TEST_PRECOMP_HPP__ +#include #include "opencv2/ts.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/imgproc/imgproc_c.h" #include "opencv2/calib3d.hpp" #include "opencv2/highgui.hpp" -#include namespace cvtest { @@ -22,4 +21,3 @@ namespace cvtest } #endif - diff --git a/modules/calib3d/test/test_reproject_image_to_3d.cpp b/modules/calib3d/test/test_reproject_image_to_3d.cpp index a93804f74e..daf89e0f0d 100644 --- a/modules/calib3d/test/test_reproject_image_to_3d.cpp +++ b/modules/calib3d/test/test_reproject_image_to_3d.cpp @@ -41,6 +41,7 @@ //M*/ #include "test_precomp.hpp" +#include "opencv2/calib3d/calib3d_c.h" #include #include @@ -172,4 +173,3 @@ protected: }; TEST(Calib3d_ReprojectImageTo3D, accuracy) { CV_ReprojectImageTo3DTest test; test.safe_run(); } - diff --git a/modules/calib3d/test/test_solvepnp_ransac.cpp b/modules/calib3d/test/test_solvepnp_ransac.cpp index dc66c1dc70..ae744a4d7e 100644 --- a/modules/calib3d/test/test_solvepnp_ransac.cpp +++ b/modules/calib3d/test/test_solvepnp_ransac.cpp @@ -41,7 +41,10 @@ //M*/ #include "test_precomp.hpp" -#include "opencv2/core/internal.hpp" + +#ifdef HAVE_TBB +#include "tbb/task_scheduler_init.h" +#endif using namespace cv; using namespace std; @@ -51,9 +54,9 @@ class CV_solvePnPRansac_Test : public cvtest::BaseTest public: CV_solvePnPRansac_Test() { - eps[CV_ITERATIVE] = 1.0e-2; - eps[CV_EPNP] = 1.0e-2; - eps[CV_P3P] = 1.0e-2; + eps[ITERATIVE] = 1.0e-2; + eps[EPNP] = 1.0e-2; + eps[P3P] = 1.0e-2; totalTestsCount = 10; } ~CV_solvePnPRansac_Test() {} @@ -190,9 +193,9 @@ class CV_solvePnP_Test : public CV_solvePnPRansac_Test public: CV_solvePnP_Test() { - eps[CV_ITERATIVE] = 1.0e-6; - eps[CV_EPNP] = 1.0e-6; - eps[CV_P3P] = 1.0e-4; + eps[ITERATIVE] = 1.0e-6; + eps[EPNP] = 1.0e-6; + eps[P3P] = 1.0e-4; totalTestsCount = 1000; } @@ -236,7 +239,7 @@ protected: } }; -TEST(Calib3d_SolvePnPRansac, accuracy) { CV_solvePnPRansac_Test test; test.safe_run(); } +TEST(DISABLED_Calib3d_SolvePnPRansac, accuracy) { CV_solvePnPRansac_Test test; test.safe_run(); } TEST(Calib3d_SolvePnP, accuracy) { CV_solvePnP_Test test; test.safe_run(); } @@ -273,7 +276,7 @@ TEST(DISABLED_Calib3d_SolvePnPRansac, concurrency) { // limit concurrency to get determenistic result cv::theRNG().state = 20121010; - cv::Ptr one_thread = new tbb::task_scheduler_init(1); + tbb::task_scheduler_init one_thread(1); solvePnPRansac(object, image, camera_mat, dist_coef, rvec1, tvec1); } @@ -292,7 +295,7 @@ TEST(DISABLED_Calib3d_SolvePnPRansac, concurrency) { // single thread again cv::theRNG().state = 20121010; - cv::Ptr one_thread = new tbb::task_scheduler_init(1); + tbb::task_scheduler_init one_thread(1); solvePnPRansac(object, image, camera_mat, dist_coef, rvec2, tvec2); } @@ -303,4 +306,4 @@ TEST(DISABLED_Calib3d_SolvePnPRansac, concurrency) EXPECT_LT(tnorm, 1e-6); } -#endif \ No newline at end of file +#endif diff --git a/modules/calib3d/test/test_stereomatching.cpp b/modules/calib3d/test/test_stereomatching.cpp index 4b35dad990..8e1120e475 100644 --- a/modules/calib3d/test/test_stereomatching.cpp +++ b/modules/calib3d/test/test_stereomatching.cpp @@ -48,6 +48,7 @@ #include "test_precomp.hpp" #include #include +#include using namespace std; using namespace cv; @@ -74,12 +75,12 @@ void computeTextureBasedMasks( const Mat& _img, Mat* texturelessMask, Mat* textu if( !texturelessMask && !texturedMask ) return; if( _img.empty() ) - CV_Error( CV_StsBadArg, "img is empty" ); + CV_Error( Error::StsBadArg, "img is empty" ); Mat img = _img; if( _img.channels() > 1) { - Mat tmp; cvtColor( _img, tmp, CV_BGR2GRAY ); img = tmp; + Mat tmp; cvtColor( _img, tmp, COLOR_BGR2GRAY ); img = tmp; } Mat dxI; Sobel( img, dxI, CV_32FC1, 1, 0, 3 ); Mat dxI2; pow( dxI / 8.f/*normalize*/, 2, dxI2 ); @@ -94,21 +95,21 @@ void computeTextureBasedMasks( const Mat& _img, Mat* texturelessMask, Mat* textu void checkTypeAndSizeOfDisp( const Mat& dispMap, const Size* sz ) { if( dispMap.empty() ) - CV_Error( CV_StsBadArg, "dispMap is empty" ); + CV_Error( Error::StsBadArg, "dispMap is empty" ); if( dispMap.type() != CV_32FC1 ) - CV_Error( CV_StsBadArg, "dispMap must have CV_32FC1 type" ); + CV_Error( Error::StsBadArg, "dispMap must have CV_32FC1 type" ); if( sz && (dispMap.rows != sz->height || dispMap.cols != sz->width) ) - CV_Error( CV_StsBadArg, "dispMap has incorrect size" ); + CV_Error( Error::StsBadArg, "dispMap has incorrect size" ); } void checkTypeAndSizeOfMask( const Mat& mask, Size sz ) { if( mask.empty() ) - CV_Error( CV_StsBadArg, "mask is empty" ); + CV_Error( Error::StsBadArg, "mask is empty" ); if( mask.type() != CV_8UC1 ) - CV_Error( CV_StsBadArg, "mask must have CV_8UC1 type" ); + CV_Error( Error::StsBadArg, "mask must have CV_8UC1 type" ); if( mask.rows != sz.height || mask.cols != sz.width ) - CV_Error( CV_StsBadArg, "mask has incorrect size" ); + CV_Error( Error::StsBadArg, "mask has incorrect size" ); } void checkDispMapsAndUnknDispMasks( const Mat& leftDispMap, const Mat& rightDispMap, @@ -142,7 +143,7 @@ void checkDispMapsAndUnknDispMasks( const Mat& leftDispMap, const Mat& rightDisp minMaxLoc( rightDispMap, &rightMinVal, 0, 0, 0, ~rightUnknDispMask ); } if( leftMinVal < 0 || rightMinVal < 0) - CV_Error( CV_StsBadArg, "known disparity values must be positive" ); + CV_Error( Error::StsBadArg, "known disparity values must be positive" ); } /* @@ -162,7 +163,7 @@ void computeOcclusionBasedMasks( const Mat& leftDisp, const Mat& _rightDisp, if( _rightDisp.empty() ) { if( !rightUnknDispMask.empty() ) - CV_Error( CV_StsBadArg, "rightUnknDispMask must be empty if _rightDisp is empty" ); + CV_Error( Error::StsBadArg, "rightUnknDispMask must be empty if _rightDisp is empty" ); rightDisp.create(leftDisp.size(), CV_32FC1); rightDisp.setTo(Scalar::all(0) ); for( int leftY = 0; leftY < leftDisp.rows; leftY++ ) @@ -229,9 +230,9 @@ void computeDepthDiscontMask( const Mat& disp, Mat& depthDiscontMask, const Mat& float dispGap = EVAL_DISP_GAP, int discontWidth = EVAL_DISCONT_WIDTH ) { if( disp.empty() ) - CV_Error( CV_StsBadArg, "disp is empty" ); + CV_Error( Error::StsBadArg, "disp is empty" ); if( disp.type() != CV_32FC1 ) - CV_Error( CV_StsBadArg, "disp must have CV_32FC1 type" ); + CV_Error( Error::StsBadArg, "disp must have CV_32FC1 type" ); if( !unknDispMask.empty() ) checkTypeAndSizeOfMask( unknDispMask, disp.size() ); @@ -459,14 +460,29 @@ void CV_StereoMatchingTest::run(int) continue; } int dispScaleFactor = datasetsParams[datasetName].dispScaleFactor; - Mat tmp; trueLeftDisp.convertTo( tmp, CV_32FC1, 1.f/dispScaleFactor ); trueLeftDisp = tmp; tmp.release(); + Mat tmp; + + trueLeftDisp.convertTo( tmp, CV_32FC1, 1.f/dispScaleFactor ); + trueLeftDisp = tmp; + tmp.release(); + if( !trueRightDisp.empty() ) - trueRightDisp.convertTo( tmp, CV_32FC1, 1.f/dispScaleFactor ); trueRightDisp = tmp; tmp.release(); + { + trueRightDisp.convertTo( tmp, CV_32FC1, 1.f/dispScaleFactor ); + trueRightDisp = tmp; + tmp.release(); + } Mat leftDisp, rightDisp; int ignBorder = max(runStereoMatchingAlgorithm(leftImg, rightImg, leftDisp, rightDisp, ci), EVAL_IGNORE_BORDER); - leftDisp.convertTo( tmp, CV_32FC1 ); leftDisp = tmp; tmp.release(); - rightDisp.convertTo( tmp, CV_32FC1 ); rightDisp = tmp; tmp.release(); + + leftDisp.convertTo( tmp, CV_32FC1 ); + leftDisp = tmp; + tmp.release(); + + rightDisp.convertTo( tmp, CV_32FC1 ); + rightDisp = tmp; + tmp.release(); int tempCode = processStereoMatchingResults( resFS, ci, isWrite, leftImg, rightImg, trueLeftDisp, trueRightDisp, leftDisp, rightDisp, QualityEvalParams(ignBorder)); @@ -530,7 +546,8 @@ int CV_StereoMatchingTest::processStereoMatchingResults( FileStorage& fs, int ca // rightDisp is not used in current test virsion int code = cvtest::TS::OK; assert( fs.isOpened() ); - assert( trueLeftDisp.type() == CV_32FC1 && trueRightDisp.type() == CV_32FC1 ); + assert( trueLeftDisp.type() == CV_32FC1 ); + assert( trueRightDisp.empty() || trueRightDisp.type() == CV_32FC1 ); assert( leftDisp.type() == CV_32FC1 && rightDisp.type() == CV_32FC1 ); // get masks for unknown ground truth disparity values @@ -554,9 +571,9 @@ int CV_StereoMatchingTest::processStereoMatchingResults( FileStorage& fs, int ca if( isWrite ) { fs << caseNames[caseIdx] << "{"; - cvWriteComment( fs.fs, RMS_STR.c_str(), 0 ); + //cvWriteComment( fs.fs, RMS_STR.c_str(), 0 ); writeErrors( RMS_STR, rmss, &fs ); - cvWriteComment( fs.fs, BAD_PXLS_FRACTION_STR.c_str(), 0 ); + //cvWriteComment( fs.fs, BAD_PXLS_FRACTION_STR.c_str(), 0 ); writeErrors( BAD_PXLS_FRACTION_STR, badPxlsFractions, &fs ); fs << "}"; // datasetName } @@ -593,10 +610,10 @@ int CV_StereoMatchingTest::readDatasetsParams( FileStorage& fs ) assert(fn.isSeq()); for( int i = 0; i < (int)fn.size(); i+=3 ) { - string _name = fn[i]; + String _name = fn[i]; DatasetParams params; - string sf = fn[i+1]; params.dispScaleFactor = atoi(sf.c_str()); - string uv = fn[i+2]; params.dispUnknVal = atoi(uv.c_str()); + String sf = fn[i+1]; params.dispScaleFactor = atoi(sf.c_str()); + String uv = fn[i+2]; params.dispUnknVal = atoi(uv.c_str()); datasetsParams[_name] = params; } return cvtest::TS::OK; @@ -680,10 +697,10 @@ protected: assert(fn.isSeq()); for( int i = 0; i < (int)fn.size(); i+=4 ) { - string caseName = fn[i], datasetName = fn[i+1]; + String caseName = fn[i], datasetName = fn[i+1]; RunParams params; - string ndisp = fn[i+2]; params.ndisp = atoi(ndisp.c_str()); - string winSize = fn[i+3]; params.winSize = atoi(winSize.c_str()); + String ndisp = fn[i+2]; params.ndisp = atoi(ndisp.c_str()); + String winSize = fn[i+3]; params.winSize = atoi(winSize.c_str()); caseNames.push_back( caseName ); caseDatasets.push_back( datasetName ); caseRunParams.push_back( params ); @@ -697,11 +714,13 @@ protected: RunParams params = caseRunParams[caseIdx]; assert( params.ndisp%16 == 0 ); assert( _leftImg.type() == CV_8UC3 && _rightImg.type() == CV_8UC3 ); - Mat leftImg; cvtColor( _leftImg, leftImg, CV_BGR2GRAY ); - Mat rightImg; cvtColor( _rightImg, rightImg, CV_BGR2GRAY ); + Mat leftImg; cvtColor( _leftImg, leftImg, COLOR_BGR2GRAY ); + Mat rightImg; cvtColor( _rightImg, rightImg, COLOR_BGR2GRAY ); - StereoBM bm( StereoBM::BASIC_PRESET, params.ndisp, params.winSize ); - bm( leftImg, rightImg, leftDisp, CV_32F ); + Ptr bm = createStereoBM( params.ndisp, params.winSize ); + Mat tempDisp; + bm->compute( leftImg, rightImg, tempDisp ); + tempDisp.convertTo(leftDisp, CV_32F, 1./StereoMatcher::DISP_SCALE); return params.winSize/2; } }; @@ -734,11 +753,11 @@ protected: assert(fn.isSeq()); for( int i = 0; i < (int)fn.size(); i+=5 ) { - string caseName = fn[i], datasetName = fn[i+1]; + String caseName = fn[i], datasetName = fn[i+1]; RunParams params; - string ndisp = fn[i+2]; params.ndisp = atoi(ndisp.c_str()); - string winSize = fn[i+3]; params.winSize = atoi(winSize.c_str()); - string fullDP = fn[i+4]; params.fullDP = atoi(fullDP.c_str()) == 0 ? false : true; + String ndisp = fn[i+2]; params.ndisp = atoi(ndisp.c_str()); + String winSize = fn[i+3]; params.winSize = atoi(winSize.c_str()); + String fullDP = fn[i+4]; params.fullDP = atoi(fullDP.c_str()) == 0 ? false : true; caseNames.push_back( caseName ); caseDatasets.push_back( datasetName ); caseRunParams.push_back( params ); @@ -751,10 +770,13 @@ protected: { RunParams params = caseRunParams[caseIdx]; assert( params.ndisp%16 == 0 ); - StereoSGBM sgbm( 0, params.ndisp, params.winSize, 10*params.winSize*params.winSize, 40*params.winSize*params.winSize, - 1, 63, 10, 100, 32, params.fullDP ); - sgbm( leftImg, rightImg, leftDisp ); - assert( leftDisp.type() == CV_16SC1 ); + Ptr sgbm = createStereoSGBM( 0, params.ndisp, params.winSize, + 10*params.winSize*params.winSize, + 40*params.winSize*params.winSize, + 1, 63, 10, 100, 32, params.fullDP ? + StereoSGBM::MODE_HH : StereoSGBM::MODE_SGBM ); + sgbm->compute( leftImg, rightImg, leftDisp ); + CV_Assert( leftDisp.type() == CV_16SC1 ); leftDisp/=16; return 0; } diff --git a/modules/calib3d/test/test_undistort.cpp b/modules/calib3d/test/test_undistort.cpp index 745daeaf6d..959d8bec71 100644 --- a/modules/calib3d/test/test_undistort.cpp +++ b/modules/calib3d/test/test_undistort.cpp @@ -41,6 +41,7 @@ //M*/ #include "test_precomp.hpp" +#include "opencv2/imgproc/imgproc_c.h" using namespace cv; using namespace std; @@ -491,7 +492,7 @@ void CV_UndistortPointsTest::distortPoints(const CvMat* _src, CvMat* _dst, const __P = cvCreateMat(3,4,CV_64F); if (matP) { - cvTsConvert(matP,__P); + cvtest::convert(cvarrToMat(matP), cvarrToMat(__P), -1); } else { @@ -500,7 +501,7 @@ void CV_UndistortPointsTest::distortPoints(const CvMat* _src, CvMat* _dst, const __P->data.db[4] = 1; __P->data.db[8] = 1; } - CvMat* __R = cvCreateMat(3,3,CV_64F);; + CvMat* __R = cvCreateMat(3,3,CV_64F); if (matR) { cvCopy(matR,__R); @@ -847,16 +848,16 @@ void CV_InitUndistortRectifyMapTest::prepare_to_validation(int/* test_case_idx*/ CvMat _input3 = test_mat[INPUT][3]; CvMat _input4 = test_mat[INPUT][4]; - cvTsConvert(&_input1,&_camera); - cvTsConvert(&_input2,&_distort); - cvTsConvert(&_input3,&_rot); - cvTsConvert(&_input4,&_new_cam); + cvtest::convert(cvarrToMat(&_input1), cvarrToMat(&_camera), -1); + cvtest::convert(cvarrToMat(&_input2), cvarrToMat(&_distort), -1); + cvtest::convert(cvarrToMat(&_input3), cvarrToMat(&_rot), -1); + cvtest::convert(cvarrToMat(&_input4), cvarrToMat(&_new_cam), -1); //Applying precalculated undistort rectify map if (!useCPlus) { - mapx = cv::Mat(_mapx); - mapy = cv::Mat(_mapy); + mapx = cv::cvarrToMat(_mapx); + mapy = cv::cvarrToMat(_mapy); } cv::Mat map1,map2; cv::convertMaps(mapx,mapy,map1,map2,CV_32FC1); @@ -876,7 +877,7 @@ void CV_InitUndistortRectifyMapTest::prepare_to_validation(int/* test_case_idx*/ zero_distortion ? 0 : &_distort, zero_R ? 0 : &_rot, zero_new_cam ? &_camera : &_new_cam); //cvTsDistortPoints(&_points,&ref_points,&_camera,&_distort,&_rot,&_new_cam); CvMat dst = test_mat[REF_OUTPUT][0]; - cvTsConvert(&ref_points,&dst); + cvtest::convert(cvarrToMat(&ref_points), cvarrToMat(&dst), -1); cvtest::copy(test_mat[INPUT][0],test_mat[OUTPUT][0]); diff --git a/modules/calib3d/test/test_undistort_badarg.cpp b/modules/calib3d/test/test_undistort_badarg.cpp index 074d193731..60460a55a0 100644 --- a/modules/calib3d/test/test_undistort_badarg.cpp +++ b/modules/calib3d/test/test_undistort_badarg.cpp @@ -40,6 +40,7 @@ //M*/ #include "test_precomp.hpp" +#include "opencv2/imgproc/imgproc_c.h" class CV_UndistortPointsBadArgTest : public cvtest::BadArgTest { @@ -243,27 +244,27 @@ void CV_UndistortPointsBadArgTest::run(int) //C++ tests useCPlus = true; - camera_mat = cv::Mat(&_camera_mat_orig); - distortion_coeffs = cv::Mat(&_distortion_coeffs_orig); - P = cv::Mat(&_P_orig); - R = cv::Mat(&_R_orig); - src_points = cv::Mat(&_src_points_orig); + camera_mat = cv::cvarrToMat(&_camera_mat_orig); + distortion_coeffs = cv::cvarrToMat(&_distortion_coeffs_orig); + P = cv::cvarrToMat(&_P_orig); + R = cv::cvarrToMat(&_R_orig); + src_points = cv::cvarrToMat(&_src_points_orig); temp = cvCreateMat(2,2,CV_32FC2); - src_points = cv::Mat(temp); + src_points = cv::cvarrToMat(temp); errcount += run_test_case( CV_StsAssert, "Invalid input data matrix size" ); - src_points = cv::Mat(&_src_points_orig); + src_points = cv::cvarrToMat(&_src_points_orig); cvReleaseMat(&temp); temp = cvCreateMat(1,4,CV_64FC2); - src_points = cv::Mat(temp); + src_points = cv::cvarrToMat(temp); errcount += run_test_case( CV_StsAssert, "Invalid input data matrix type" ); - src_points = cv::Mat(&_src_points_orig); + src_points = cv::cvarrToMat(&_src_points_orig); cvReleaseMat(&temp); src_points = cv::Mat(); errcount += run_test_case( CV_StsAssert, "Input data matrix is not continuous" ); - src_points = cv::Mat(&_src_points_orig); + src_points = cv::cvarrToMat(&_src_points_orig); cvReleaseMat(&temp); @@ -360,12 +361,12 @@ void CV_InitUndistortRectifyMapBadArgTest::run(int) //C++ tests useCPlus = true; - camera_mat = cv::Mat(&_camera_mat_orig); - distortion_coeffs = cv::Mat(&_distortion_coeffs_orig); - new_camera_mat = cv::Mat(&_new_camera_mat_orig); - R = cv::Mat(&_R_orig); - mapx = cv::Mat(&_mapx_orig); - mapy = cv::Mat(&_mapy_orig); + camera_mat = cv::cvarrToMat(&_camera_mat_orig); + distortion_coeffs = cv::cvarrToMat(&_distortion_coeffs_orig); + new_camera_mat = cv::cvarrToMat(&_new_camera_mat_orig); + R = cv::cvarrToMat(&_R_orig); + mapx = cv::cvarrToMat(&_mapx_orig); + mapy = cv::cvarrToMat(&_mapy_orig); mat_type = CV_64F; @@ -373,21 +374,21 @@ void CV_InitUndistortRectifyMapBadArgTest::run(int) mat_type = mat_type_orig; temp = cvCreateMat(3,2,CV_32FC1); - camera_mat = cv::Mat(temp); + camera_mat = cv::cvarrToMat(temp); errcount += run_test_case( CV_StsAssert, "Invalid camera data matrix size" ); - camera_mat = cv::Mat(&_camera_mat_orig); + camera_mat = cv::cvarrToMat(&_camera_mat_orig); cvReleaseMat(&temp); temp = cvCreateMat(4,3,CV_32FC1); - R = cv::Mat(temp); + R = cv::cvarrToMat(temp); errcount += run_test_case( CV_StsAssert, "Invalid R data matrix size" ); - R = cv::Mat(&_R_orig); + R = cv::cvarrToMat(&_R_orig); cvReleaseMat(&temp); temp = cvCreateMat(6,1,CV_32FC1); - distortion_coeffs = cv::Mat(temp); + distortion_coeffs = cv::cvarrToMat(temp); errcount += run_test_case( CV_StsAssert, "Invalid distortion coefficients data matrix size" ); - distortion_coeffs = cv::Mat(&_distortion_coeffs_orig); + distortion_coeffs = cv::cvarrToMat(&_distortion_coeffs_orig); cvReleaseMat(&temp); //------------ @@ -499,11 +500,11 @@ void CV_UndistortBadArgTest::run(int) //C++ tests useCPlus = true; - camera_mat = cv::Mat(&_camera_mat_orig); - distortion_coeffs = cv::Mat(&_distortion_coeffs_orig); - new_camera_mat = cv::Mat(&_new_camera_mat_orig); - src = cv::Mat(&_src_orig); - dst = cv::Mat(&_dst_orig); + camera_mat = cv::cvarrToMat(&_camera_mat_orig); + distortion_coeffs = cv::cvarrToMat(&_distortion_coeffs_orig); + new_camera_mat = cv::cvarrToMat(&_new_camera_mat_orig); + src = cv::cvarrToMat(&_src_orig); + dst = cv::cvarrToMat(&_dst_orig); //------------ delete[] arr_src; diff --git a/modules/calib3d/test/test_undistort_points.cpp b/modules/calib3d/test/test_undistort_points.cpp index c1ace3d4df..5dabd213db 100644 --- a/modules/calib3d/test/test_undistort_points.cpp +++ b/modules/calib3d/test/test_undistort_points.cpp @@ -94,4 +94,4 @@ void CV_UndistortTest::run(int /* start_from */) } } -TEST(Calib3d_Undistort, accuracy) { CV_UndistortTest test; test.safe_run(); } \ No newline at end of file +TEST(Calib3d_Undistort, accuracy) { CV_UndistortTest test; test.safe_run(); } diff --git a/modules/contrib/CMakeLists.txt b/modules/contrib/CMakeLists.txt index 81c9ea4aa5..1d3432b598 100644 --- a/modules/contrib/CMakeLists.txt +++ b/modules/contrib/CMakeLists.txt @@ -1 +1 @@ -ocv_define_module(contrib opencv_imgproc opencv_calib3d opencv_features2d opencv_ml opencv_video opencv_objdetect OPTIONAL opencv_highgui) +ocv_define_module(contrib opencv_imgproc opencv_calib3d opencv_ml opencv_video opencv_objdetect OPTIONAL opencv_highgui) diff --git a/modules/contrib/doc/contrib.rst b/modules/contrib/doc/contrib.rst index 798d38d5bb..de14d33efe 100644 --- a/modules/contrib/doc/contrib.rst +++ b/modules/contrib/doc/contrib.rst @@ -9,5 +9,4 @@ The module contains some recently added functionality that has not been stabiliz stereo FaceRecognizer Documentation - Retina Documentation openfabmap diff --git a/modules/contrib/doc/facerec/colormaps.rst b/modules/contrib/doc/facerec/colormaps.rst index beba413fdb..95750ab5c0 100644 --- a/modules/contrib/doc/facerec/colormaps.rst +++ b/modules/contrib/doc/facerec/colormaps.rst @@ -51,9 +51,9 @@ In OpenCV 2.4 you only need :ocv:func:`applyColorMap` to apply a colormap on a g int main(int argc, const char *argv[]) { // Get the path to the image, if it was given // if no arguments were given. - string filename; + String filename; if (argc > 1) { - filename = string(argv[1]); + filename = String(argv[1]); } // The following lines show how to apply a colormap on a given image // and show it with cv::imshow example with an image. An exception is diff --git a/modules/contrib/doc/facerec/facerec_api.rst b/modules/contrib/doc/facerec/facerec_api.rst index 8bea7070ae..c2c7f56d0c 100644 --- a/modules/contrib/doc/facerec/facerec_api.rst +++ b/modules/contrib/doc/facerec/facerec_api.rst @@ -3,6 +3,12 @@ FaceRecognizer .. highlight:: cpp +.. Sample code:: + + * An example using the FaceRecognizer class can be found at opencv_source_code/samples/cpp/facerec_demo.cpp + + * (Python) An example using the FaceRecognizer class can be found at opencv_source_code/samples/python2/facerec_demo.py + FaceRecognizer -------------- @@ -30,10 +36,10 @@ a unified access to all face recongition algorithms in OpenCV. :: virtual void predict(InputArray src, int &label, double &confidence) const = 0; // Serializes this object to a given filename. - virtual void save(const string& filename) const; + virtual void save(const String& filename) const; // Deserializes this object from a given filename. - virtual void load(const string& filename); + virtual void load(const String& filename); // Serializes this object to a given cv::FileStorage. virtual void save(FileStorage& fs) const = 0; @@ -52,7 +58,7 @@ I'll go a bit more into detail explaining :ocv:class:`FaceRecognizer`, because i * So called “virtual constructor”. That is, each Algorithm derivative is registered at program start and you can get the list of registered algorithms and create instance of a particular algorithm by its name (see :ocv:func:`Algorithm::create`). If you plan to add your own algorithms, it is good practice to add a unique prefix to your algorithms to distinguish them from other algorithms. -* Setting/Retrieving algorithm parameters by name. If you used video capturing functionality from OpenCV highgui module, you are probably familar with :ocv:cfunc:`cvSetCaptureProperty`, :ocv:cfunc:`cvGetCaptureProperty`, :ocv:func:`VideoCapture::set` and :ocv:func:`VideoCapture::get`. :ocv:class:`Algorithm` provides similar method where instead of integer id's you specify the parameter names as text strings. See :ocv:func:`Algorithm::set` and :ocv:func:`Algorithm::get` for details. +* Setting/Retrieving algorithm parameters by name. If you used video capturing functionality from OpenCV highgui module, you are probably familar with :ocv:cfunc:`cvSetCaptureProperty`, :ocv:cfunc:`cvGetCaptureProperty`, :ocv:func:`VideoCapture::set` and :ocv:func:`VideoCapture::get`. :ocv:class:`Algorithm` provides similar method where instead of integer id's you specify the parameter names as text Strings. See :ocv:func:`Algorithm::set` and :ocv:func:`Algorithm::get` for details. * Reading and writing parameters from/to XML or YAML files. Every Algorithm derivative can store all its parameters and then read them back. There is no need to re-implement it each time. @@ -64,6 +70,8 @@ Moreover every :ocv:class:`FaceRecognizer` supports the: * **Loading/Saving** the model state from/to a given XML or YAML. +.. note:: When using the FaceRecognizer interface in combination with Python, please stick to Python 2. Some underlying scripts like create_csv will not work in other versions, like Python 3. + Setting the Thresholds +++++++++++++++++++++++ @@ -113,7 +121,7 @@ Since every :ocv:class:`FaceRecognizer` is a :ocv:class:`Algorithm`, you can use // Create a FaceRecognizer: Ptr model = createEigenFaceRecognizer(); // And here's how to get its name: - std::string name = model->name(); + String name = model->name(); FaceRecognizer::train @@ -251,7 +259,7 @@ FaceRecognizer::save Saves a :ocv:class:`FaceRecognizer` and its model state. -.. ocv:function:: void FaceRecognizer::save(const string& filename) const +.. ocv:function:: void FaceRecognizer::save(const String& filename) const Saves this model to a given filename, either as XML or YAML. @@ -265,7 +273,7 @@ Saves a :ocv:class:`FaceRecognizer` and its model state. Every :ocv:class:`FaceRecognizer` overwrites ``FaceRecognizer::save(FileStorage& fs)`` -to save the internal model state. ``FaceRecognizer::save(const string& filename)`` saves +to save the internal model state. ``FaceRecognizer::save(const String& filename)`` saves the state of a model to the given filename. The suffix ``const`` means that prediction does not affect the internal model @@ -276,13 +284,13 @@ FaceRecognizer::load Loads a :ocv:class:`FaceRecognizer` and its model state. -.. ocv:function:: void FaceRecognizer::load( const string& filename ) +.. ocv:function:: void FaceRecognizer::load( const String& filename ) .. ocv:function:: void FaceRecognizer::load( const FileStorage& fs ) = 0 Loads a persisted model and state from a given XML or YAML file . Every :ocv:class:`FaceRecognizer` has to overwrite ``FaceRecognizer::load(FileStorage& fs)`` to enable loading the model state. ``FaceRecognizer::load(FileStorage& fs)`` in -turn gets called by ``FaceRecognizer::load(const string& filename)``, to ease +turn gets called by ``FaceRecognizer::load(const String& filename)``, to ease saving a model. createEigenFaceRecognizer diff --git a/modules/contrib/doc/facerec/facerec_tutorial.rst b/modules/contrib/doc/facerec/facerec_tutorial.rst index 170da8ff24..cbfb417971 100644 --- a/modules/contrib/doc/facerec/facerec_tutorial.rst +++ b/modules/contrib/doc/facerec/facerec_tutorial.rst @@ -7,7 +7,7 @@ Face Recognition with OpenCV Introduction ============ -`OpenCV (Open Source Computer Vision) `_ is a popular computer vision library started by `Intel `_ in 1999. The cross-platform library sets its focus on real-time image processing and includes patent-free implementations of the latest computer vision algorithms. In 2008 `Willow Garage `_ took over support and OpenCV 2.3.1 now comes with a programming interface to C, C++, `Python `_ and `Android `_. OpenCV is released under a BSD license so it is used in academic projects and commercial products alike. +`OpenCV (Open Source Computer Vision) `_ is a popular computer vision library started by `Intel `_ in 1999. The cross-platform library sets its focus on real-time image processing and includes patent-free implementations of the latest computer vision algorithms. In 2008 `Willow Garage `_ took over support and OpenCV 2.3.1 now comes with a programming interface to C, C++, `Python `_ and `Android `_. OpenCV is released under a BSD license so it is used in academic projects and commercial products alike. OpenCV 2.4 now comes with the very new :ocv:class:`FaceRecognizer` class for face recognition, so you can start experimenting with face recognition right away. This document is the guide I've wished for, when I was working myself into face recognition. It shows you how to perform face recognition with :ocv:class:`FaceRecognizer` in OpenCV (with full source code listings) and gives you an introduction into the algorithms behind. I'll also show how to create the visualizations you can find in many publications, because a lot of people asked for. @@ -626,5 +626,3 @@ CSV for the AT&T Facedatabase .. literalinclude:: etc/at.txt :language: none :linenos: - - diff --git a/modules/contrib/doc/facerec/index.rst b/modules/contrib/doc/facerec/index.rst index ce8a15e677..b871448c55 100644 --- a/modules/contrib/doc/facerec/index.rst +++ b/modules/contrib/doc/facerec/index.rst @@ -30,4 +30,3 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` * :ref:`search` - diff --git a/modules/contrib/doc/facerec/src/CMakeLists.txt b/modules/contrib/doc/facerec/src/CMakeLists.txt index 10720048c0..94aa36fbe0 100644 --- a/modules/contrib/doc/facerec/src/CMakeLists.txt +++ b/modules/contrib/doc/facerec/src/CMakeLists.txt @@ -6,7 +6,7 @@ project(facerec_cpp_samples) #SET(OpenCV_DIR /path/to/your/opencv/installation) # packages -find_package(OpenCV REQUIRED) # http://opencv.willowgarage.com +find_package(OpenCV REQUIRED) # http://opencv.org # probably you should loop through the sample files here add_executable(facerec_demo facerec_demo.cpp) @@ -23,4 +23,3 @@ target_link_libraries(facerec_fisherfaces opencv_contrib opencv_core opencv_imgp add_executable(facerec_lbph facerec_lbph.cpp) target_link_libraries(facerec_lbph opencv_contrib opencv_core opencv_imgproc opencv_highgui) - diff --git a/modules/contrib/doc/facerec/src/create_csv.py b/modules/contrib/doc/facerec/src/create_csv.py index 71d773c017..c4de778f98 100755 --- a/modules/contrib/doc/facerec/src/create_csv.py +++ b/modules/contrib/doc/facerec/src/create_csv.py @@ -1,4 +1,4 @@ -#/usr/bin/env python +#!/usr/bin/env python import sys import os.path diff --git a/modules/contrib/doc/facerec/tutorial/facerec_gender_classification.rst b/modules/contrib/doc/facerec/tutorial/facerec_gender_classification.rst index 0c7398d2fb..770083170d 100644 --- a/modules/contrib/doc/facerec/tutorial/facerec_gender_classification.rst +++ b/modules/contrib/doc/facerec/tutorial/facerec_gender_classification.rst @@ -231,5 +231,3 @@ Here are some examples: +---------------------------------+----------------------------------------------------------------------------+ | 0.2 (20%), 0.2 (20%), (70,70) | .. image:: ../img/tutorial/gender_classification/arnie_20_20_70_70.jpg | +---------------------------------+----------------------------------------------------------------------------+ - - diff --git a/modules/contrib/doc/facerec/tutorial/facerec_save_load.rst b/modules/contrib/doc/facerec/tutorial/facerec_save_load.rst index 7948bcd73a..2d0b65dffd 100644 --- a/modules/contrib/doc/facerec/tutorial/facerec_save_load.rst +++ b/modules/contrib/doc/facerec/tutorial/facerec_save_load.rst @@ -44,4 +44,3 @@ And here is the Reconstruction, which is the same as the original: .. image:: ../img/eigenface_reconstruction_opencv.png :align: center - diff --git a/modules/contrib/doc/facerec/tutorial/facerec_video_recognition.rst b/modules/contrib/doc/facerec/tutorial/facerec_video_recognition.rst index b692fe5137..76e76eebe2 100644 --- a/modules/contrib/doc/facerec/tutorial/facerec_video_recognition.rst +++ b/modules/contrib/doc/facerec/tutorial/facerec_video_recognition.rst @@ -205,5 +205,3 @@ Here are some examples: +---------------------------------+----------------------------------------------------------------------------+ | 0.2 (20%), 0.2 (20%), (70,70) | .. image:: ../img/tutorial/gender_classification/arnie_20_20_70_70.jpg | +---------------------------------+----------------------------------------------------------------------------+ - - diff --git a/modules/contrib/doc/openfabmap.rst b/modules/contrib/doc/openfabmap.rst index 2f2ad40745..e2f157a075 100644 --- a/modules/contrib/doc/openfabmap.rst +++ b/modules/contrib/doc/openfabmap.rst @@ -9,6 +9,10 @@ FAB-MAP is an approach to appearance-based place recognition. FAB-MAP compares i openFABMAP requires training data (e.g. a collection of images from a similar but not identical environment) to construct a visual vocabulary for the visual bag-of-words model, along with a Chow-Liu tree representation of feature likelihood and for use in the Sampled new place method (see below). +.. note:: + + * An example using the openFABMAP package can be found at opencv_source_code/samples/cpp/fabmap_sample.cpp + of2::FabMap -------------------- diff --git a/modules/contrib/doc/stereo.rst b/modules/contrib/doc/stereo.rst index d5f2d00801..103bd0f3fd 100644 --- a/modules/contrib/doc/stereo.rst +++ b/modules/contrib/doc/stereo.rst @@ -113,5 +113,3 @@ The method executes the variational algorithm on a rectified stereo pair. See `` **Note**: The method is not constant, so you should not use the same ``StereoVar`` instance from different threads simultaneously. - - diff --git a/modules/contrib/include/opencv2/contrib.hpp b/modules/contrib/include/opencv2/contrib.hpp index 44bf3313ed..75c6f3db0e 100644 --- a/modules/contrib/include/opencv2/contrib.hpp +++ b/modules/contrib/include/opencv2/contrib.hpp @@ -48,927 +48,591 @@ #include "opencv2/features2d.hpp" #include "opencv2/objdetect.hpp" -#ifdef __cplusplus - -/****************************************************************************************\ -* Adaptive Skin Detector * -\****************************************************************************************/ - -class CV_EXPORTS CvAdaptiveSkinDetector -{ -private: - enum { - GSD_HUE_LT = 3, - GSD_HUE_UT = 33, - GSD_INTENSITY_LT = 15, - GSD_INTENSITY_UT = 250 - }; - - class CV_EXPORTS Histogram - { - private: - enum { - HistogramSize = (GSD_HUE_UT - GSD_HUE_LT + 1) - }; - - protected: - int findCoverageIndex(double surfaceToCover, int defaultValue = 0); - - public: - CvHistogram *fHistogram; - Histogram(); - virtual ~Histogram(); - - void findCurveThresholds(int &x1, int &x2, double percent = 0.05); - void mergeWith(Histogram *source, double weight); - }; - - int nStartCounter, nFrameCount, nSkinHueLowerBound, nSkinHueUpperBound, nMorphingMethod, nSamplingDivider; - double fHistogramMergeFactor, fHuePercentCovered; - Histogram histogramHueMotion, skinHueHistogram; - IplImage *imgHueFrame, *imgSaturationFrame, *imgLastGrayFrame, *imgMotionFrame, *imgFilteredFrame; - IplImage *imgShrinked, *imgTemp, *imgGrayFrame, *imgHSVFrame; - -protected: - void initData(IplImage *src, int widthDivider, int heightDivider); - void adaptiveFilter(); - -public: - - enum { - MORPHING_METHOD_NONE = 0, - MORPHING_METHOD_ERODE = 1, - MORPHING_METHOD_ERODE_ERODE = 2, - MORPHING_METHOD_ERODE_DILATE = 3 - }; - - CvAdaptiveSkinDetector(int samplingDivider = 1, int morphingMethod = MORPHING_METHOD_NONE); - virtual ~CvAdaptiveSkinDetector(); - - virtual void process(IplImage *inputBGRImage, IplImage *outputHueMask); -}; - - -/****************************************************************************************\ - * Fuzzy MeanShift Tracker * - \****************************************************************************************/ - -class CV_EXPORTS CvFuzzyPoint { -public: - double x, y, value; - - CvFuzzyPoint(double _x, double _y); -}; - -class CV_EXPORTS CvFuzzyCurve { -private: - std::vector points; - double value, centre; - - bool between(double x, double x1, double x2); - -public: - CvFuzzyCurve(); - ~CvFuzzyCurve(); - - void setCentre(double _centre); - double getCentre(); - void clear(); - void addPoint(double x, double y); - double calcValue(double param); - double getValue(); - void setValue(double _value); -}; - -class CV_EXPORTS CvFuzzyFunction { -public: - std::vector curves; - - CvFuzzyFunction(); - ~CvFuzzyFunction(); - void addCurve(CvFuzzyCurve *curve, double value = 0); - void resetValues(); - double calcValue(); - CvFuzzyCurve *newCurve(); -}; - -class CV_EXPORTS CvFuzzyRule { -private: - CvFuzzyCurve *fuzzyInput1, *fuzzyInput2; - CvFuzzyCurve *fuzzyOutput; -public: - CvFuzzyRule(); - ~CvFuzzyRule(); - void setRule(CvFuzzyCurve *c1, CvFuzzyCurve *c2, CvFuzzyCurve *o1); - double calcValue(double param1, double param2); - CvFuzzyCurve *getOutputCurve(); -}; - -class CV_EXPORTS CvFuzzyController { -private: - std::vector rules; -public: - CvFuzzyController(); - ~CvFuzzyController(); - void addRule(CvFuzzyCurve *c1, CvFuzzyCurve *c2, CvFuzzyCurve *o1); - double calcOutput(double param1, double param2); -}; - -class CV_EXPORTS CvFuzzyMeanShiftTracker -{ -private: - class FuzzyResizer - { - private: - CvFuzzyFunction iInput, iOutput; - CvFuzzyController fuzzyController; - public: - FuzzyResizer(); - int calcOutput(double edgeDensity, double density); - }; - - class SearchWindow - { - public: - FuzzyResizer *fuzzyResizer; - int x, y; - int width, height, maxWidth, maxHeight, ellipseHeight, ellipseWidth; - int ldx, ldy, ldw, ldh, numShifts, numIters; - int xGc, yGc; - long m00, m01, m10, m11, m02, m20; - double ellipseAngle; - double density; - unsigned int depthLow, depthHigh; - int verticalEdgeLeft, verticalEdgeRight, horizontalEdgeTop, horizontalEdgeBottom; - - SearchWindow(); - ~SearchWindow(); - void setSize(int _x, int _y, int _width, int _height); - void initDepthValues(IplImage *maskImage, IplImage *depthMap); - bool shift(); - void extractInfo(IplImage *maskImage, IplImage *depthMap, bool initDepth); - void getResizeAttribsEdgeDensityLinear(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh); - void getResizeAttribsInnerDensity(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh); - void getResizeAttribsEdgeDensityFuzzy(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh); - bool meanShift(IplImage *maskImage, IplImage *depthMap, int maxIteration, bool initDepth); - }; - -public: - enum TrackingState - { - tsNone = 0, - tsSearching = 1, - tsTracking = 2, - tsSetWindow = 3, - tsDisabled = 10 - }; - - enum ResizeMethod { - rmEdgeDensityLinear = 0, - rmEdgeDensityFuzzy = 1, - rmInnerDensity = 2 - }; - - enum { - MinKernelMass = 1000 - }; - - SearchWindow kernel; - int searchMode; - -private: - enum - { - MaxMeanShiftIteration = 5, - MaxSetSizeIteration = 5 - }; - - void findOptimumSearchWindow(SearchWindow &searchWindow, IplImage *maskImage, IplImage *depthMap, int maxIteration, int resizeMethod, bool initDepth); - -public: - CvFuzzyMeanShiftTracker(); - ~CvFuzzyMeanShiftTracker(); - - void track(IplImage *maskImage, IplImage *depthMap, int resizeMethod, bool resetSearch, int minKernelMass = MinKernelMass); -}; - - namespace cv { - - class CV_EXPORTS Octree +class CV_EXPORTS Octree +{ +public: + struct Node { - public: - struct Node - { - Node() {} - int begin, end; - float x_min, x_max, y_min, y_max, z_min, z_max; - int maxLevels; - bool isLeaf; - int children[8]; - }; - - Octree(); - Octree( const std::vector& points, int maxLevels = 10, int minPoints = 20 ); - virtual ~Octree(); - - virtual void buildTree( const std::vector& points, int maxLevels = 10, int minPoints = 20 ); - virtual void getPointsWithinSphere( const Point3f& center, float radius, - std::vector& points ) const; - const std::vector& getNodes() const { return nodes; } - private: - int minPoints; - std::vector points; - std::vector nodes; - - virtual void buildNext(size_t node_ind); + Node() {} + int begin, end; + float x_min, x_max, y_min, y_max, z_min, z_max; + int maxLevels; + bool isLeaf; + int children[8]; }; + Octree(); + Octree( const std::vector& points, int maxLevels = 10, int minPoints = 20 ); + virtual ~Octree(); - class CV_EXPORTS Mesh3D - { - public: - struct EmptyMeshException {}; + virtual void buildTree( const std::vector& points, int maxLevels = 10, int minPoints = 20 ); + virtual void getPointsWithinSphere( const Point3f& center, float radius, + std::vector& points ) const; + const std::vector& getNodes() const { return nodes; } +private: + int minPoints; + std::vector points; + std::vector nodes; - Mesh3D(); - Mesh3D(const std::vector& vtx); - ~Mesh3D(); + virtual void buildNext(size_t node_ind); +}; - void buildOctree(); - void clearOctree(); - float estimateResolution(float tryRatio = 0.1f); - void computeNormals(float normalRadius, int minNeighbors = 20); - void computeNormals(const std::vector& subset, float normalRadius, int minNeighbors = 20); - void writeAsVrml(const std::string& file, const std::vector& colors = std::vector()) const; +class CV_EXPORTS Mesh3D +{ +public: + struct EmptyMeshException {}; - std::vector vtx; - std::vector normals; - float resolution; - Octree octree; + Mesh3D(); + Mesh3D(const std::vector& vtx); + ~Mesh3D(); - const static Point3f allzero; - }; + void buildOctree(); + void clearOctree(); + float estimateResolution(float tryRatio = 0.1f); + void computeNormals(float normalRadius, int minNeighbors = 20); + void computeNormals(const std::vector& subset, float normalRadius, int minNeighbors = 20); - class CV_EXPORTS SpinImageModel - { - public: + void writeAsVrml(const String& file, const std::vector& colors = std::vector()) const; - /* model parameters, leave unset for default or auto estimate */ - float normalRadius; - int minNeighbors; + std::vector vtx; + std::vector normals; + float resolution; + Octree octree; - float binSize; - int imageWidth; + const static Point3f allzero; +}; - float lambda; - float gamma; +class CV_EXPORTS SpinImageModel +{ +public: - float T_GeometriccConsistency; - float T_GroupingCorespondances; + /* model parameters, leave unset for default or auto estimate */ + float normalRadius; + int minNeighbors; - /* public interface */ - SpinImageModel(); - explicit SpinImageModel(const Mesh3D& mesh); - ~SpinImageModel(); + float binSize; + int imageWidth; - void setLogger(std::ostream* log); - void selectRandomSubset(float ratio); - void setSubset(const std::vector& subset); - void compute(); + float lambda; + float gamma; - void match(const SpinImageModel& scene, std::vector< std::vector >& result); + float T_GeometriccConsistency; + float T_GroupingCorespondances; - Mat packRandomScaledSpins(bool separateScale = false, size_t xCount = 10, size_t yCount = 10) const; + /* public interface */ + SpinImageModel(); + explicit SpinImageModel(const Mesh3D& mesh); + ~SpinImageModel(); - size_t getSpinCount() const { return spinImages.rows; } - Mat getSpinImage(size_t index) const { return spinImages.row((int)index); } - const Point3f& getSpinVertex(size_t index) const { return mesh.vtx[subset[index]]; } - const Point3f& getSpinNormal(size_t index) const { return mesh.normals[subset[index]]; } + void selectRandomSubset(float ratio); + void setSubset(const std::vector& subset); + void compute(); - const Mesh3D& getMesh() const { return mesh; } - Mesh3D& getMesh() { return mesh; } + void match(const SpinImageModel& scene, std::vector< std::vector >& result); - /* static utility functions */ - static bool spinCorrelation(const Mat& spin1, const Mat& spin2, float lambda, float& result); + Mat packRandomScaledSpins(bool separateScale = false, size_t xCount = 10, size_t yCount = 10) const; - static Point2f calcSpinMapCoo(const Point3f& point, const Point3f& vertex, const Point3f& normal); + size_t getSpinCount() const { return spinImages.rows; } + Mat getSpinImage(size_t index) const { return spinImages.row((int)index); } + const Point3f& getSpinVertex(size_t index) const { return mesh.vtx[subset[index]]; } + const Point3f& getSpinNormal(size_t index) const { return mesh.normals[subset[index]]; } - static float geometricConsistency(const Point3f& pointScene1, const Point3f& normalScene1, - const Point3f& pointModel1, const Point3f& normalModel1, - const Point3f& pointScene2, const Point3f& normalScene2, - const Point3f& pointModel2, const Point3f& normalModel2); + const Mesh3D& getMesh() const { return mesh; } + Mesh3D& getMesh() { return mesh; } - static float groupingCreteria(const Point3f& pointScene1, const Point3f& normalScene1, + /* static utility functions */ + static bool spinCorrelation(const Mat& spin1, const Mat& spin2, float lambda, float& result); + + static Point2f calcSpinMapCoo(const Point3f& point, const Point3f& vertex, const Point3f& normal); + + static float geometricConsistency(const Point3f& pointScene1, const Point3f& normalScene1, const Point3f& pointModel1, const Point3f& normalModel1, const Point3f& pointScene2, const Point3f& normalScene2, - const Point3f& pointModel2, const Point3f& normalModel2, - float gamma); - protected: - void defaultParams(); + const Point3f& pointModel2, const Point3f& normalModel2); - void matchSpinToModel(const Mat& spin, std::vector& indeces, - std::vector& corrCoeffs, bool useExtremeOutliers = true) const; + static float groupingCreteria(const Point3f& pointScene1, const Point3f& normalScene1, + const Point3f& pointModel1, const Point3f& normalModel1, + const Point3f& pointScene2, const Point3f& normalScene2, + const Point3f& pointModel2, const Point3f& normalModel2, + float gamma); +protected: + void defaultParams(); - void repackSpinImages(const std::vector& mask, Mat& spinImages, bool reAlloc = true) const; + void matchSpinToModel(const Mat& spin, std::vector& indeces, + std::vector& corrCoeffs, bool useExtremeOutliers = true) const; - std::vector subset; - Mesh3D mesh; - Mat spinImages; - std::ostream* out; - }; + void repackSpinImages(const std::vector& mask, Mat& spinImages, bool reAlloc = true) const; - class CV_EXPORTS TickMeter + std::vector subset; + Mesh3D mesh; + Mat spinImages; +}; + +class CV_EXPORTS TickMeter +{ +public: + TickMeter(); + void start(); + void stop(); + + int64 getTimeTicks() const; + double getTimeMicro() const; + double getTimeMilli() const; + double getTimeSec() const; + int64 getCounter() const; + + void reset(); +private: + int64 counter; + int64 sumTime; + int64 startTime; +}; + +//CV_EXPORTS std::ostream& operator<<(std::ostream& out, const TickMeter& tm); + +class CV_EXPORTS SelfSimDescriptor +{ +public: + SelfSimDescriptor(); + SelfSimDescriptor(int _ssize, int _lsize, + int _startDistanceBucket=DEFAULT_START_DISTANCE_BUCKET, + int _numberOfDistanceBuckets=DEFAULT_NUM_DISTANCE_BUCKETS, + int _nangles=DEFAULT_NUM_ANGLES); + SelfSimDescriptor(const SelfSimDescriptor& ss); + virtual ~SelfSimDescriptor(); + SelfSimDescriptor& operator = (const SelfSimDescriptor& ss); + + size_t getDescriptorSize() const; + Size getGridSize( Size imgsize, Size winStride ) const; + + virtual void compute(const Mat& img, std::vector& descriptors, Size winStride=Size(), + const std::vector& locations=std::vector()) const; + virtual void computeLogPolarMapping(Mat& mappingMask) const; + virtual void SSD(const Mat& img, Point pt, Mat& ssd) const; + + int smallSize; + int largeSize; + int startDistanceBucket; + int numberOfDistanceBuckets; + int numberOfAngles; + + enum { DEFAULT_SMALL_SIZE = 5, DEFAULT_LARGE_SIZE = 41, + DEFAULT_NUM_ANGLES = 20, DEFAULT_START_DISTANCE_BUCKET = 3, + DEFAULT_NUM_DISTANCE_BUCKETS = 7 }; +}; + + +CV_EXPORTS_W int chamerMatching( Mat& img, Mat& templ, + CV_OUT std::vector >& results, CV_OUT std::vector& cost, + double templScale=1, int maxMatches = 20, + double minMatchDistance = 1.0, int padX = 3, + int padY = 3, int scales = 5, double minScale = 0.6, double maxScale = 1.6, + double orientationWeight = 0.5, double truncate = 20); + + +class CV_EXPORTS_W StereoVar +{ +public: + // Flags + enum {USE_INITIAL_DISPARITY = 1, USE_EQUALIZE_HIST = 2, USE_SMART_ID = 4, USE_AUTO_PARAMS = 8, USE_MEDIAN_FILTERING = 16}; + enum {CYCLE_O, CYCLE_V}; + enum {PENALIZATION_TICHONOV, PENALIZATION_CHARBONNIER, PENALIZATION_PERONA_MALIK}; + + //! the default constructor + CV_WRAP StereoVar(); + + //! the full constructor taking all the necessary algorithm parameters + CV_WRAP StereoVar(int levels, double pyrScale, int nIt, int minDisp, int maxDisp, int poly_n, double poly_sigma, float fi, float lambda, int penalization, int cycle, int flags); + + //! the destructor + virtual ~StereoVar(); + + //! the stereo correspondence operator that computes disparity map for the specified rectified stereo pair + CV_WRAP_AS(compute) virtual void operator()(const Mat& left, const Mat& right, CV_OUT Mat& disp); + + CV_PROP_RW int levels; + CV_PROP_RW double pyrScale; + CV_PROP_RW int nIt; + CV_PROP_RW int minDisp; + CV_PROP_RW int maxDisp; + CV_PROP_RW int poly_n; + CV_PROP_RW double poly_sigma; + CV_PROP_RW float fi; + CV_PROP_RW float lambda; + CV_PROP_RW int penalization; + CV_PROP_RW int cycle; + CV_PROP_RW int flags; + +private: + void autoParams(); + void FMG(Mat &I1, Mat &I2, Mat &I2x, Mat &u, int level); + void VCycle_MyFAS(Mat &I1_h, Mat &I2_h, Mat &I2x_h, Mat &u_h, int level); + void VariationalSolver(Mat &I1_h, Mat &I2_h, Mat &I2x_h, Mat &u_h, int level); +}; + +CV_EXPORTS void polyfit(const Mat& srcx, const Mat& srcy, Mat& dst, int order); + +class CV_EXPORTS Directory +{ + public: + static std::vector GetListFiles ( const String& path, const String & exten = "*", bool addPath = true ); + static std::vector GetListFilesR ( const String& path, const String & exten = "*", bool addPath = true ); + static std::vector GetListFolders( const String& path, const String & exten = "*", bool addPath = true ); +}; + +/* + * Generation of a set of different colors by the following way: + * 1) generate more then need colors (in "factor" times) in RGB, + * 2) convert them to Lab, + * 3) choose the needed count of colors from the set that are more different from + * each other, + * 4) convert the colors back to RGB + */ +CV_EXPORTS void generateColors( std::vector& colors, size_t count, size_t factor=100 ); + + +/* + * Estimate the rigid body motion from frame0 to frame1. The method is based on the paper + * "Real-Time Visual Odometry from Dense RGB-D Images", F. Steinbucker, J. Strum, D. Cremers, ICCV, 2011. + */ +enum { ROTATION = 1, + TRANSLATION = 2, + RIGID_BODY_MOTION = 4 + }; +CV_EXPORTS bool RGBDOdometry( Mat& Rt, const Mat& initRt, + const Mat& image0, const Mat& depth0, const Mat& mask0, + const Mat& image1, const Mat& depth1, const Mat& mask1, + const Mat& cameraMatrix, float minDepth=0.f, float maxDepth=4.f, float maxDepthDiff=0.07f, + const std::vector& iterCounts=std::vector(), + const std::vector& minGradientMagnitudes=std::vector(), + int transformType=RIGID_BODY_MOTION ); + +/** +*Bilinear interpolation technique. +* +*The value of a desired cortical pixel is obtained through a bilinear interpolation of the values +*of the four nearest neighbouring Cartesian pixels to the center of the RF. +*The same principle is applied to the inverse transformation. +* +*More details can be found in http://dx.doi.org/10.1007/978-3-642-23968-7_5 +*/ +class CV_EXPORTS LogPolar_Interp +{ +public: + + LogPolar_Interp() {} + + /** + *Constructor + *\param w the width of the input image + *\param h the height of the input image + *\param center the transformation center: where the output precision is maximal + *\param R the number of rings of the cortical image (default value 70 pixel) + *\param ro0 the radius of the blind spot (default value 3 pixel) + *\param full \a 1 (default value) means that the retinal image (the inverse transform) is computed within the circumscribing circle. + * \a 0 means that the retinal image is computed within the inscribed circle. + *\param S the number of sectors of the cortical image (default value 70 pixel). + * Its value is usually internally computed to obtain a pixel aspect ratio equals to 1. + *\param sp \a 1 (default value) means that the parameter \a S is internally computed. + * \a 0 means that the parameter \a S is provided by the user. + */ + LogPolar_Interp(int w, int h, Point2i center, int R=70, double ro0=3.0, + int interp=INTER_LINEAR, int full=1, int S=117, int sp=1); + /** + *Transformation from Cartesian image to cortical (log-polar) image. + *\param source the Cartesian image + *\return the transformed image (cortical image) + */ + const Mat to_cortical(const Mat &source); + /** + *Transformation from cortical image to retinal (inverse log-polar) image. + *\param source the cortical image + *\return the transformed image (retinal image) + */ + const Mat to_cartesian(const Mat &source); + /** + *Destructor + */ + ~LogPolar_Interp(); + +protected: + + Mat Rsri; + Mat Csri; + + int S, R, M, N; + int top, bottom,left,right; + double ro0, romax, a, q; + int interp; + + Mat ETAyx; + Mat CSIyx; + + void create_map(int M, int N, int R, int S, double ro0); +}; + +/** +*Overlapping circular receptive fields technique +* +*The Cartesian plane is divided in two regions: the fovea and the periphery. +*The fovea (oversampling) is handled by using the bilinear interpolation technique described above, whereas in +*the periphery we use the overlapping Gaussian circular RFs. +* +*More details can be found in http://dx.doi.org/10.1007/978-3-642-23968-7_5 +*/ +class CV_EXPORTS LogPolar_Overlapping +{ +public: + LogPolar_Overlapping() {} + + /** + *Constructor + *\param w the width of the input image + *\param h the height of the input image + *\param center the transformation center: where the output precision is maximal + *\param R the number of rings of the cortical image (default value 70 pixel) + *\param ro0 the radius of the blind spot (default value 3 pixel) + *\param full \a 1 (default value) means that the retinal image (the inverse transform) is computed within the circumscribing circle. + * \a 0 means that the retinal image is computed within the inscribed circle. + *\param S the number of sectors of the cortical image (default value 70 pixel). + * Its value is usually internally computed to obtain a pixel aspect ratio equals to 1. + *\param sp \a 1 (default value) means that the parameter \a S is internally computed. + * \a 0 means that the parameter \a S is provided by the user. + */ + LogPolar_Overlapping(int w, int h, Point2i center, int R=70, + double ro0=3.0, int full=1, int S=117, int sp=1); + /** + *Transformation from Cartesian image to cortical (log-polar) image. + *\param source the Cartesian image + *\return the transformed image (cortical image) + */ + const Mat to_cortical(const Mat &source); + /** + *Transformation from cortical image to retinal (inverse log-polar) image. + *\param source the cortical image + *\return the transformed image (retinal image) + */ + const Mat to_cartesian(const Mat &source); + /** + *Destructor + */ + ~LogPolar_Overlapping(); + +protected: + + Mat Rsri; + Mat Csri; + std::vector Rsr; + std::vector Csr; + std::vector Wsr; + + int S, R, M, N, ind1; + int top, bottom,left,right; + double ro0, romax, a, q; + + struct kernel { - public: - TickMeter(); - void start(); - void stop(); - - int64 getTimeTicks() const; - double getTimeMicro() const; - double getTimeMilli() const; - double getTimeSec() const; - int64 getCounter() const; - - void reset(); - private: - int64 counter; - int64 sumTime; - int64 startTime; + kernel() { w = 0; } + std::vector weights; + int w; }; - CV_EXPORTS std::ostream& operator<<(std::ostream& out, const TickMeter& tm); + Mat ETAyx; + Mat CSIyx; + std::vector w_ker_2D; - class CV_EXPORTS SelfSimDescriptor - { - public: - SelfSimDescriptor(); - SelfSimDescriptor(int _ssize, int _lsize, - int _startDistanceBucket=DEFAULT_START_DISTANCE_BUCKET, - int _numberOfDistanceBuckets=DEFAULT_NUM_DISTANCE_BUCKETS, - int _nangles=DEFAULT_NUM_ANGLES); - SelfSimDescriptor(const SelfSimDescriptor& ss); - virtual ~SelfSimDescriptor(); - SelfSimDescriptor& operator = (const SelfSimDescriptor& ss); + void create_map(int M, int N, int R, int S, double ro0); +}; - size_t getDescriptorSize() const; - Size getGridSize( Size imgsize, Size winStride ) const; +/** +* Adjacent receptive fields technique +* +*All the Cartesian pixels, whose coordinates in the cortical domain share the same integer part, are assigned to the same RF. +*The precision of the boundaries of the RF can be improved by breaking each pixel into subpixels and assigning each of them to the correct RF. +*This technique is implemented from: Traver, V., Pla, F.: Log-polar mapping template design: From task-level requirements +*to geometry parameters. Image Vision Comput. 26(10) (2008) 1354-1370 +* +*More details can be found in http://dx.doi.org/10.1007/978-3-642-23968-7_5 +*/ +class CV_EXPORTS LogPolar_Adjacent +{ +public: + LogPolar_Adjacent() {} - virtual void compute(const Mat& img, std::vector& descriptors, Size winStride=Size(), - const std::vector& locations=std::vector()) const; - virtual void computeLogPolarMapping(Mat& mappingMask) const; - virtual void SSD(const Mat& img, Point pt, Mat& ssd) const; - - int smallSize; - int largeSize; - int startDistanceBucket; - int numberOfDistanceBuckets; - int numberOfAngles; - - enum { DEFAULT_SMALL_SIZE = 5, DEFAULT_LARGE_SIZE = 41, - DEFAULT_NUM_ANGLES = 20, DEFAULT_START_DISTANCE_BUCKET = 3, - DEFAULT_NUM_DISTANCE_BUCKETS = 7 }; - }; - - - typedef bool (*BundleAdjustCallback)(int iteration, double norm_error, void* user_data); - - class CV_EXPORTS LevMarqSparse { - public: - LevMarqSparse(); - LevMarqSparse(int npoints, // number of points - int ncameras, // number of cameras - int nPointParams, // number of params per one point (3 in case of 3D points) - int nCameraParams, // number of parameters per one camera - int nErrParams, // number of parameters in measurement vector - // for 1 point at one camera (2 in case of 2D projections) - Mat& visibility, // visibility matrix. rows correspond to points, columns correspond to cameras - // 1 - point is visible for the camera, 0 - invisible - Mat& P0, // starting vector of parameters, first cameras then points - Mat& X, // measurements, in order of visibility. non visible cases are skipped - TermCriteria criteria, // termination criteria - - // callback for estimation of Jacobian matrices - void (CV_CDECL * fjac)(int i, int j, Mat& point_params, - Mat& cam_params, Mat& A, Mat& B, void* data), - // callback for estimation of backprojection errors - void (CV_CDECL * func)(int i, int j, Mat& point_params, - Mat& cam_params, Mat& estim, void* data), - void* data, // user-specific data passed to the callbacks - BundleAdjustCallback cb, void* user_data - ); - - virtual ~LevMarqSparse(); - - virtual void run( int npoints, // number of points - int ncameras, // number of cameras - int nPointParams, // number of params per one point (3 in case of 3D points) - int nCameraParams, // number of parameters per one camera - int nErrParams, // number of parameters in measurement vector - // for 1 point at one camera (2 in case of 2D projections) - Mat& visibility, // visibility matrix. rows correspond to points, columns correspond to cameras - // 1 - point is visible for the camera, 0 - invisible - Mat& P0, // starting vector of parameters, first cameras then points - Mat& X, // measurements, in order of visibility. non visible cases are skipped - TermCriteria criteria, // termination criteria - - // callback for estimation of Jacobian matrices - void (CV_CDECL * fjac)(int i, int j, Mat& point_params, - Mat& cam_params, Mat& A, Mat& B, void* data), - // callback for estimation of backprojection errors - void (CV_CDECL * func)(int i, int j, Mat& point_params, - Mat& cam_params, Mat& estim, void* data), - void* data // user-specific data passed to the callbacks - ); - - virtual void clear(); - - // useful function to do simple bundle adjustment tasks - static void bundleAdjust(std::vector& points, // positions of points in global coordinate system (input and output) - const std::vector >& imagePoints, // projections of 3d points for every camera - const std::vector >& visibility, // visibility of 3d points for every camera - std::vector& cameraMatrix, // intrinsic matrices of all cameras (input and output) - std::vector& R, // rotation matrices of all cameras (input and output) - std::vector& T, // translation vector of all cameras (input and output) - std::vector& distCoeffs, // distortion coefficients of all cameras (input and output) - const TermCriteria& criteria= - TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, DBL_EPSILON), - BundleAdjustCallback cb = 0, void* user_data = 0); - - public: - virtual void optimize(CvMat &_vis); //main function that runs minimization - - //iteratively asks for measurement for visible camera-point pairs - void ask_for_proj(CvMat &_vis,bool once=false); - //iteratively asks for Jacobians for every camera_point pair - void ask_for_projac(CvMat &_vis); - - CvMat* err; //error X-hX - double prevErrNorm, errNorm; - double lambda; - CvTermCriteria criteria; - int iters; - - CvMat** U; //size of array is equal to number of cameras - CvMat** V; //size of array is equal to number of points - CvMat** inv_V_star; //inverse of V* - - CvMat** A; - CvMat** B; - CvMat** W; - - CvMat* X; //measurement - CvMat* hX; //current measurement extimation given new parameter vector - - CvMat* prevP; //current already accepted parameter. - CvMat* P; // parameters used to evaluate function with new params - // this parameters may be rejected - - CvMat* deltaP; //computed increase of parameters (result of normal system solution ) - - CvMat** ea; // sum_i AijT * e_ij , used as right part of normal equation - // length of array is j = number of cameras - CvMat** eb; // sum_j BijT * e_ij , used as right part of normal equation - // length of array is i = number of points - - CvMat** Yj; //length of array is i = num_points - - CvMat* S; //big matrix of block Sjk , each block has size num_cam_params x num_cam_params - - CvMat* JtJ_diag; //diagonal of JtJ, used to backup diagonal elements before augmentation - - CvMat* Vis_index; // matrix which element is index of measurement for point i and camera j - - int num_cams; - int num_points; - int num_err_param; - int num_cam_param; - int num_point_param; - - //target function and jacobian pointers, which needs to be initialized - void (*fjac)(int i, int j, Mat& point_params, Mat& cam_params, Mat& A, Mat& B, void* data); - void (*func)(int i, int j, Mat& point_params, Mat& cam_params, Mat& estim, void* data); - - void* data; - - BundleAdjustCallback cb; - void* user_data; - }; - - CV_EXPORTS_W int chamerMatching( Mat& img, Mat& templ, - CV_OUT std::vector >& results, CV_OUT std::vector& cost, - double templScale=1, int maxMatches = 20, - double minMatchDistance = 1.0, int padX = 3, - int padY = 3, int scales = 5, double minScale = 0.6, double maxScale = 1.6, - double orientationWeight = 0.5, double truncate = 20); - - - class CV_EXPORTS_W StereoVar - { - public: - // Flags - enum {USE_INITIAL_DISPARITY = 1, USE_EQUALIZE_HIST = 2, USE_SMART_ID = 4, USE_AUTO_PARAMS = 8, USE_MEDIAN_FILTERING = 16}; - enum {CYCLE_O, CYCLE_V}; - enum {PENALIZATION_TICHONOV, PENALIZATION_CHARBONNIER, PENALIZATION_PERONA_MALIK}; - - //! the default constructor - CV_WRAP StereoVar(); - - //! the full constructor taking all the necessary algorithm parameters - CV_WRAP StereoVar(int levels, double pyrScale, int nIt, int minDisp, int maxDisp, int poly_n, double poly_sigma, float fi, float lambda, int penalization, int cycle, int flags); - - //! the destructor - virtual ~StereoVar(); - - //! the stereo correspondence operator that computes disparity map for the specified rectified stereo pair - CV_WRAP_AS(compute) virtual void operator()(const Mat& left, const Mat& right, CV_OUT Mat& disp); - - CV_PROP_RW int levels; - CV_PROP_RW double pyrScale; - CV_PROP_RW int nIt; - CV_PROP_RW int minDisp; - CV_PROP_RW int maxDisp; - CV_PROP_RW int poly_n; - CV_PROP_RW double poly_sigma; - CV_PROP_RW float fi; - CV_PROP_RW float lambda; - CV_PROP_RW int penalization; - CV_PROP_RW int cycle; - CV_PROP_RW int flags; - - private: - void autoParams(); - void FMG(Mat &I1, Mat &I2, Mat &I2x, Mat &u, int level); - void VCycle_MyFAS(Mat &I1_h, Mat &I2_h, Mat &I2x_h, Mat &u_h, int level); - void VariationalSolver(Mat &I1_h, Mat &I2_h, Mat &I2x_h, Mat &u_h, int level); - }; - - CV_EXPORTS void polyfit(const Mat& srcx, const Mat& srcy, Mat& dst, int order); - - class CV_EXPORTS Directory - { - public: - static std::vector GetListFiles ( const std::string& path, const std::string & exten = "*", bool addPath = true ); - static std::vector GetListFilesR ( const std::string& path, const std::string & exten = "*", bool addPath = true ); - static std::vector GetListFolders( const std::string& path, const std::string & exten = "*", bool addPath = true ); - }; - - /* - * Generation of a set of different colors by the following way: - * 1) generate more then need colors (in "factor" times) in RGB, - * 2) convert them to Lab, - * 3) choose the needed count of colors from the set that are more different from - * each other, - * 4) convert the colors back to RGB + /** + *Constructor + *\param w the width of the input image + *\param h the height of the input image + *\param center the transformation center: where the output precision is maximal + *\param R the number of rings of the cortical image (default value 70 pixel) + *\param ro0 the radius of the blind spot (default value 3 pixel) + *\param smin the size of the subpixel (default value 0.25 pixel) + *\param full \a 1 (default value) means that the retinal image (the inverse transform) is computed within the circumscribing circle. + * \a 0 means that the retinal image is computed within the inscribed circle. + *\param S the number of sectors of the cortical image (default value 70 pixel). + * Its value is usually internally computed to obtain a pixel aspect ratio equals to 1. + *\param sp \a 1 (default value) means that the parameter \a S is internally computed. + * \a 0 means that the parameter \a S is provided by the user. */ - CV_EXPORTS void generateColors( std::vector& colors, size_t count, size_t factor=100 ); - - - /* - * Estimate the rigid body motion from frame0 to frame1. The method is based on the paper - * "Real-Time Visual Odometry from Dense RGB-D Images", F. Steinbucker, J. Strum, D. Cremers, ICCV, 2011. + LogPolar_Adjacent(int w, int h, Point2i center, int R=70, double ro0=3.0, double smin=0.25, int full=1, int S=117, int sp=1); + /** + *Transformation from Cartesian image to cortical (log-polar) image. + *\param source the Cartesian image + *\return the transformed image (cortical image) */ - enum { ROTATION = 1, - TRANSLATION = 2, - RIGID_BODY_MOTION = 4 - }; - CV_EXPORTS bool RGBDOdometry( Mat& Rt, const Mat& initRt, - const Mat& image0, const Mat& depth0, const Mat& mask0, - const Mat& image1, const Mat& depth1, const Mat& mask1, - const Mat& cameraMatrix, float minDepth=0.f, float maxDepth=4.f, float maxDepthDiff=0.07f, - const std::vector& iterCounts=std::vector(), - const std::vector& minGradientMagnitudes=std::vector(), - int transformType=RIGID_BODY_MOTION ); - + const Mat to_cortical(const Mat &source); /** - *Bilinear interpolation technique. - * - *The value of a desired cortical pixel is obtained through a bilinear interpolation of the values - *of the four nearest neighbouring Cartesian pixels to the center of the RF. - *The same principle is applied to the inverse transformation. - * - *More details can be found in http://dx.doi.org/10.1007/978-3-642-23968-7_5 - */ - class CV_EXPORTS LogPolar_Interp - { - public: - - LogPolar_Interp() {} - - /** - *Constructor - *\param w the width of the input image - *\param h the height of the input image - *\param center the transformation center: where the output precision is maximal - *\param R the number of rings of the cortical image (default value 70 pixel) - *\param ro0 the radius of the blind spot (default value 3 pixel) - *\param full \a 1 (default value) means that the retinal image (the inverse transform) is computed within the circumscribing circle. - * \a 0 means that the retinal image is computed within the inscribed circle. - *\param S the number of sectors of the cortical image (default value 70 pixel). - * Its value is usually internally computed to obtain a pixel aspect ratio equals to 1. - *\param sp \a 1 (default value) means that the parameter \a S is internally computed. - * \a 0 means that the parameter \a S is provided by the user. - */ - LogPolar_Interp(int w, int h, Point2i center, int R=70, double ro0=3.0, - int interp=INTER_LINEAR, int full=1, int S=117, int sp=1); - /** - *Transformation from Cartesian image to cortical (log-polar) image. - *\param source the Cartesian image - *\return the transformed image (cortical image) - */ - const Mat to_cortical(const Mat &source); - /** - *Transformation from cortical image to retinal (inverse log-polar) image. - *\param source the cortical image - *\return the transformed image (retinal image) - */ - const Mat to_cartesian(const Mat &source); - /** - *Destructor - */ - ~LogPolar_Interp(); - - protected: - - Mat Rsri; - Mat Csri; - - int S, R, M, N; - int top, bottom,left,right; - double ro0, romax, a, q; - int interp; - - Mat ETAyx; - Mat CSIyx; - - void create_map(int M, int N, int R, int S, double ro0); - }; - + *Transformation from cortical image to retinal (inverse log-polar) image. + *\param source the cortical image + *\return the transformed image (retinal image) + */ + const Mat to_cartesian(const Mat &source); /** - *Overlapping circular receptive fields technique - * - *The Cartesian plane is divided in two regions: the fovea and the periphery. - *The fovea (oversampling) is handled by using the bilinear interpolation technique described above, whereas in - *the periphery we use the overlapping Gaussian circular RFs. - * - *More details can be found in http://dx.doi.org/10.1007/978-3-642-23968-7_5 - */ - class CV_EXPORTS LogPolar_Overlapping + *Destructor + */ + ~LogPolar_Adjacent(); + +protected: + struct pixel { - public: - LogPolar_Overlapping() {} - - /** - *Constructor - *\param w the width of the input image - *\param h the height of the input image - *\param center the transformation center: where the output precision is maximal - *\param R the number of rings of the cortical image (default value 70 pixel) - *\param ro0 the radius of the blind spot (default value 3 pixel) - *\param full \a 1 (default value) means that the retinal image (the inverse transform) is computed within the circumscribing circle. - * \a 0 means that the retinal image is computed within the inscribed circle. - *\param S the number of sectors of the cortical image (default value 70 pixel). - * Its value is usually internally computed to obtain a pixel aspect ratio equals to 1. - *\param sp \a 1 (default value) means that the parameter \a S is internally computed. - * \a 0 means that the parameter \a S is provided by the user. - */ - LogPolar_Overlapping(int w, int h, Point2i center, int R=70, - double ro0=3.0, int full=1, int S=117, int sp=1); - /** - *Transformation from Cartesian image to cortical (log-polar) image. - *\param source the Cartesian image - *\return the transformed image (cortical image) - */ - const Mat to_cortical(const Mat &source); - /** - *Transformation from cortical image to retinal (inverse log-polar) image. - *\param source the cortical image - *\return the transformed image (retinal image) - */ - const Mat to_cartesian(const Mat &source); - /** - *Destructor - */ - ~LogPolar_Overlapping(); - - protected: - - Mat Rsri; - Mat Csri; - std::vector Rsr; - std::vector Csr; - std::vector Wsr; - - int S, R, M, N, ind1; - int top, bottom,left,right; - double ro0, romax, a, q; - - struct kernel - { - kernel() { w = 0; } - std::vector weights; - int w; - }; - - Mat ETAyx; - Mat CSIyx; - std::vector w_ker_2D; - - void create_map(int M, int N, int R, int S, double ro0); + pixel() { u = v = 0; a = 0.; } + int u; + int v; + double a; }; + int S, R, M, N; + int top, bottom,left,right; + double ro0, romax, a, q; + std::vector > L; + std::vector A; - /** - * Adjacent receptive fields technique - * - *All the Cartesian pixels, whose coordinates in the cortical domain share the same integer part, are assigned to the same RF. - *The precision of the boundaries of the RF can be improved by breaking each pixel into subpixels and assigning each of them to the correct RF. - *This technique is implemented from: Traver, V., Pla, F.: Log-polar mapping template design: From task-level requirements - *to geometry parameters. Image Vision Comput. 26(10) (2008) 1354-1370 - * - *More details can be found in http://dx.doi.org/10.1007/978-3-642-23968-7_5 - */ - class CV_EXPORTS LogPolar_Adjacent + void subdivide_recursively(double x, double y, int i, int j, double length, double smin); + bool get_uv(double x, double y, int&u, int&v); + void create_map(int M, int N, int R, int S, double ro0, double smin); +}; + +CV_EXPORTS Mat subspaceProject(InputArray W, InputArray mean, InputArray src); +CV_EXPORTS Mat subspaceReconstruct(InputArray W, InputArray mean, InputArray src); + +class CV_EXPORTS LDA +{ +public: + // Initializes a LDA with num_components (default 0) and specifies how + // samples are aligned (default dataAsRow=true). + LDA(int num_components = 0) : + _num_components(num_components) {}; + + // Initializes and performs a Discriminant Analysis with Fisher's + // Optimization Criterion on given data in src and corresponding labels + // in labels. If 0 (or less) number of components are given, they are + // automatically determined for given data in computation. + LDA(InputArrayOfArrays src, InputArray labels, + int num_components = 0) : + _num_components(num_components) { - public: - LogPolar_Adjacent() {} + this->compute(src, labels); //! compute eigenvectors and eigenvalues + } - /** - *Constructor - *\param w the width of the input image - *\param h the height of the input image - *\param center the transformation center: where the output precision is maximal - *\param R the number of rings of the cortical image (default value 70 pixel) - *\param ro0 the radius of the blind spot (default value 3 pixel) - *\param smin the size of the subpixel (default value 0.25 pixel) - *\param full \a 1 (default value) means that the retinal image (the inverse transform) is computed within the circumscribing circle. - * \a 0 means that the retinal image is computed within the inscribed circle. - *\param S the number of sectors of the cortical image (default value 70 pixel). - * Its value is usually internally computed to obtain a pixel aspect ratio equals to 1. - *\param sp \a 1 (default value) means that the parameter \a S is internally computed. - * \a 0 means that the parameter \a S is provided by the user. - */ - LogPolar_Adjacent(int w, int h, Point2i center, int R=70, double ro0=3.0, double smin=0.25, int full=1, int S=117, int sp=1); - /** - *Transformation from Cartesian image to cortical (log-polar) image. - *\param source the Cartesian image - *\return the transformed image (cortical image) - */ - const Mat to_cortical(const Mat &source); - /** - *Transformation from cortical image to retinal (inverse log-polar) image. - *\param source the cortical image - *\return the transformed image (retinal image) - */ - const Mat to_cartesian(const Mat &source); - /** - *Destructor - */ - ~LogPolar_Adjacent(); + // Serializes this object to a given filename. + void save(const String& filename) const; - protected: - struct pixel - { - pixel() { u = v = 0; a = 0.; } - int u; - int v; - double a; - }; - int S, R, M, N; - int top, bottom,left,right; - double ro0, romax, a, q; - std::vector > L; - std::vector A; + // Deserializes this object from a given filename. + void load(const String& filename); - void subdivide_recursively(double x, double y, int i, int j, double length, double smin); - bool get_uv(double x, double y, int&u, int&v); - void create_map(int M, int N, int R, int S, double ro0, double smin); - }; - - CV_EXPORTS Mat subspaceProject(InputArray W, InputArray mean, InputArray src); - CV_EXPORTS Mat subspaceReconstruct(InputArray W, InputArray mean, InputArray src); - - class CV_EXPORTS LDA - { - public: - // Initializes a LDA with num_components (default 0) and specifies how - // samples are aligned (default dataAsRow=true). - LDA(int num_components = 0) : - _num_components(num_components) {}; - - // Initializes and performs a Discriminant Analysis with Fisher's - // Optimization Criterion on given data in src and corresponding labels - // in labels. If 0 (or less) number of components are given, they are - // automatically determined for given data in computation. - LDA(InputArrayOfArrays src, InputArray labels, - int num_components = 0) : - _num_components(num_components) - { - this->compute(src, labels); //! compute eigenvectors and eigenvalues - } - - // Serializes this object to a given filename. - void save(const std::string& filename) const; - - // Deserializes this object from a given filename. - void load(const std::string& filename); - - // Serializes this object to a given cv::FileStorage. - void save(FileStorage& fs) const; - - // Deserializes this object from a given cv::FileStorage. - void load(const FileStorage& node); - - // Destructor. - ~LDA() {} - - //! Compute the discriminants for data in src and labels. - void compute(InputArrayOfArrays src, InputArray labels); - - // Projects samples into the LDA subspace. - Mat project(InputArray src); - - // Reconstructs projections from the LDA subspace. - Mat reconstruct(InputArray src); - - // Returns the eigenvectors of this LDA. - Mat eigenvectors() const { return _eigenvectors; }; - - // Returns the eigenvalues of this LDA. - Mat eigenvalues() const { return _eigenvalues; } - - protected: - bool _dataAsRow; - int _num_components; - Mat _eigenvectors; - Mat _eigenvalues; - - void lda(InputArrayOfArrays src, InputArray labels); - }; - - class CV_EXPORTS_W FaceRecognizer : public Algorithm - { - public: - //! virtual destructor - virtual ~FaceRecognizer() {} - - // Trains a FaceRecognizer. - CV_WRAP virtual void train(InputArrayOfArrays src, InputArray labels) = 0; - - // Updates a FaceRecognizer. - CV_WRAP virtual void update(InputArrayOfArrays src, InputArray labels); - - // Gets a prediction from a FaceRecognizer. - virtual int predict(InputArray src) const = 0; - - // Predicts the label and confidence for a given sample. - CV_WRAP virtual void predict(InputArray src, CV_OUT int &label, CV_OUT double &confidence) const = 0; - - // Serializes this object to a given filename. - CV_WRAP virtual void save(const std::string& filename) const; - - // Deserializes this object from a given filename. - CV_WRAP virtual void load(const std::string& filename); - - // Serializes this object to a given cv::FileStorage. - virtual void save(FileStorage& fs) const = 0; + // Serializes this object to a given cv::FileStorage. + void save(FileStorage& fs) const; // Deserializes this object from a given cv::FileStorage. - virtual void load(const FileStorage& fs) = 0; + void load(const FileStorage& node); - }; + // Destructor. + ~LDA() {} - CV_EXPORTS_W Ptr createEigenFaceRecognizer(int num_components = 0, double threshold = DBL_MAX); - CV_EXPORTS_W Ptr createFisherFaceRecognizer(int num_components = 0, double threshold = DBL_MAX); - CV_EXPORTS_W Ptr createLBPHFaceRecognizer(int radius=1, int neighbors=8, - int grid_x=8, int grid_y=8, double threshold = DBL_MAX); + //! Compute the discriminants for data in src and labels. + void compute(InputArrayOfArrays src, InputArray labels); - enum - { - COLORMAP_AUTUMN = 0, - COLORMAP_BONE = 1, - COLORMAP_JET = 2, - COLORMAP_WINTER = 3, - COLORMAP_RAINBOW = 4, - COLORMAP_OCEAN = 5, - COLORMAP_SUMMER = 6, - COLORMAP_SPRING = 7, - COLORMAP_COOL = 8, - COLORMAP_HSV = 9, - COLORMAP_PINK = 10, - COLORMAP_HOT = 11 - }; + // Projects samples into the LDA subspace. + Mat project(InputArray src); - CV_EXPORTS_W void applyColorMap(InputArray src, OutputArray dst, int colormap); + // Reconstructs projections from the LDA subspace. + Mat reconstruct(InputArray src); - CV_EXPORTS bool initModule_contrib(); + // Returns the eigenvectors of this LDA. + Mat eigenvectors() const { return _eigenvectors; }; + + // Returns the eigenvalues of this LDA. + Mat eigenvalues() const { return _eigenvalues; } + +protected: + bool _dataAsRow; + int _num_components; + Mat _eigenvectors; + Mat _eigenvalues; + + void lda(InputArrayOfArrays src, InputArray labels); +}; + +class CV_EXPORTS_W FaceRecognizer : public Algorithm +{ +public: + //! virtual destructor + virtual ~FaceRecognizer() {} + + // Trains a FaceRecognizer. + CV_WRAP virtual void train(InputArrayOfArrays src, InputArray labels) = 0; + + // Updates a FaceRecognizer. + CV_WRAP virtual void update(InputArrayOfArrays src, InputArray labels); + + // Gets a prediction from a FaceRecognizer. + virtual int predict(InputArray src) const = 0; + + // Predicts the label and confidence for a given sample. + CV_WRAP virtual void predict(InputArray src, CV_OUT int &label, CV_OUT double &confidence) const = 0; + + // Serializes this object to a given filename. + CV_WRAP virtual void save(const String& filename) const; + + // Deserializes this object from a given filename. + CV_WRAP virtual void load(const String& filename); + + // Serializes this object to a given cv::FileStorage. + virtual void save(FileStorage& fs) const = 0; + + // Deserializes this object from a given cv::FileStorage. + virtual void load(const FileStorage& fs) = 0; + +}; + +CV_EXPORTS_W Ptr createEigenFaceRecognizer(int num_components = 0, double threshold = DBL_MAX); +CV_EXPORTS_W Ptr createFisherFaceRecognizer(int num_components = 0, double threshold = DBL_MAX); +CV_EXPORTS_W Ptr createLBPHFaceRecognizer(int radius=1, int neighbors=8, + int grid_x=8, int grid_y=8, double threshold = DBL_MAX); + +enum +{ + COLORMAP_AUTUMN = 0, + COLORMAP_BONE = 1, + COLORMAP_JET = 2, + COLORMAP_WINTER = 3, + COLORMAP_RAINBOW = 4, + COLORMAP_OCEAN = 5, + COLORMAP_SUMMER = 6, + COLORMAP_SPRING = 7, + COLORMAP_COOL = 8, + COLORMAP_HSV = 9, + COLORMAP_PINK = 10, + COLORMAP_HOT = 11 +}; + +CV_EXPORTS_W void applyColorMap(InputArray src, OutputArray dst, int colormap); + +CV_EXPORTS bool initModule_contrib(); } -#include "opencv2/contrib/retina.hpp" - #include "opencv2/contrib/openfabmap.hpp" #endif - -#endif diff --git a/modules/contrib/include/opencv2/contrib/compat.hpp b/modules/contrib/include/opencv2/contrib/compat.hpp new file mode 100644 index 0000000000..ba758c235f --- /dev/null +++ b/modules/contrib/include/opencv2/contrib/compat.hpp @@ -0,0 +1,384 @@ +/*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-2011, 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_CONTRIB_COMPAT_HPP__ +#define __OPENCV_CONTRIB_COMPAT_HPP__ + +#include "opencv2/core/core_c.h" + +#ifdef __cplusplus + +/****************************************************************************************\ +* Adaptive Skin Detector * +\****************************************************************************************/ + +class CV_EXPORTS CvAdaptiveSkinDetector +{ +private: + enum { + GSD_HUE_LT = 3, + GSD_HUE_UT = 33, + GSD_INTENSITY_LT = 15, + GSD_INTENSITY_UT = 250 + }; + + class CV_EXPORTS Histogram + { + private: + enum { + HistogramSize = (GSD_HUE_UT - GSD_HUE_LT + 1) + }; + + protected: + int findCoverageIndex(double surfaceToCover, int defaultValue = 0); + + public: + CvHistogram *fHistogram; + Histogram(); + virtual ~Histogram(); + + void findCurveThresholds(int &x1, int &x2, double percent = 0.05); + void mergeWith(Histogram *source, double weight); + }; + + int nStartCounter, nFrameCount, nSkinHueLowerBound, nSkinHueUpperBound, nMorphingMethod, nSamplingDivider; + double fHistogramMergeFactor, fHuePercentCovered; + Histogram histogramHueMotion, skinHueHistogram; + IplImage *imgHueFrame, *imgSaturationFrame, *imgLastGrayFrame, *imgMotionFrame, *imgFilteredFrame; + IplImage *imgShrinked, *imgTemp, *imgGrayFrame, *imgHSVFrame; + +protected: + void initData(IplImage *src, int widthDivider, int heightDivider); + void adaptiveFilter(); + +public: + + enum { + MORPHING_METHOD_NONE = 0, + MORPHING_METHOD_ERODE = 1, + MORPHING_METHOD_ERODE_ERODE = 2, + MORPHING_METHOD_ERODE_DILATE = 3 + }; + + CvAdaptiveSkinDetector(int samplingDivider = 1, int morphingMethod = MORPHING_METHOD_NONE); + virtual ~CvAdaptiveSkinDetector(); + + virtual void process(IplImage *inputBGRImage, IplImage *outputHueMask); +}; + + +/****************************************************************************************\ + * Fuzzy MeanShift Tracker * + \****************************************************************************************/ + +class CV_EXPORTS CvFuzzyPoint { +public: + double x, y, value; + + CvFuzzyPoint(double _x, double _y); +}; + +class CV_EXPORTS CvFuzzyCurve { +private: + std::vector points; + double value, centre; + + bool between(double x, double x1, double x2); + +public: + CvFuzzyCurve(); + ~CvFuzzyCurve(); + + void setCentre(double _centre); + double getCentre(); + void clear(); + void addPoint(double x, double y); + double calcValue(double param); + double getValue(); + void setValue(double _value); +}; + +class CV_EXPORTS CvFuzzyFunction { +public: + std::vector curves; + + CvFuzzyFunction(); + ~CvFuzzyFunction(); + void addCurve(CvFuzzyCurve *curve, double value = 0); + void resetValues(); + double calcValue(); + CvFuzzyCurve *newCurve(); +}; + +class CV_EXPORTS CvFuzzyRule { +private: + CvFuzzyCurve *fuzzyInput1, *fuzzyInput2; + CvFuzzyCurve *fuzzyOutput; +public: + CvFuzzyRule(); + ~CvFuzzyRule(); + void setRule(CvFuzzyCurve *c1, CvFuzzyCurve *c2, CvFuzzyCurve *o1); + double calcValue(double param1, double param2); + CvFuzzyCurve *getOutputCurve(); +}; + +class CV_EXPORTS CvFuzzyController { +private: + std::vector rules; +public: + CvFuzzyController(); + ~CvFuzzyController(); + void addRule(CvFuzzyCurve *c1, CvFuzzyCurve *c2, CvFuzzyCurve *o1); + double calcOutput(double param1, double param2); +}; + +class CV_EXPORTS CvFuzzyMeanShiftTracker +{ +private: + class FuzzyResizer + { + private: + CvFuzzyFunction iInput, iOutput; + CvFuzzyController fuzzyController; + public: + FuzzyResizer(); + int calcOutput(double edgeDensity, double density); + }; + + class SearchWindow + { + public: + FuzzyResizer *fuzzyResizer; + int x, y; + int width, height, maxWidth, maxHeight, ellipseHeight, ellipseWidth; + int ldx, ldy, ldw, ldh, numShifts, numIters; + int xGc, yGc; + long m00, m01, m10, m11, m02, m20; + double ellipseAngle; + double density; + unsigned int depthLow, depthHigh; + int verticalEdgeLeft, verticalEdgeRight, horizontalEdgeTop, horizontalEdgeBottom; + + SearchWindow(); + ~SearchWindow(); + void setSize(int _x, int _y, int _width, int _height); + void initDepthValues(IplImage *maskImage, IplImage *depthMap); + bool shift(); + void extractInfo(IplImage *maskImage, IplImage *depthMap, bool initDepth); + void getResizeAttribsEdgeDensityLinear(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh); + void getResizeAttribsInnerDensity(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh); + void getResizeAttribsEdgeDensityFuzzy(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh); + bool meanShift(IplImage *maskImage, IplImage *depthMap, int maxIteration, bool initDepth); + }; + +public: + enum TrackingState + { + tsNone = 0, + tsSearching = 1, + tsTracking = 2, + tsSetWindow = 3, + tsDisabled = 10 + }; + + enum ResizeMethod { + rmEdgeDensityLinear = 0, + rmEdgeDensityFuzzy = 1, + rmInnerDensity = 2 + }; + + enum { + MinKernelMass = 1000 + }; + + SearchWindow kernel; + int searchMode; + +private: + enum + { + MaxMeanShiftIteration = 5, + MaxSetSizeIteration = 5 + }; + + void findOptimumSearchWindow(SearchWindow &searchWindow, IplImage *maskImage, IplImage *depthMap, int maxIteration, int resizeMethod, bool initDepth); + +public: + CvFuzzyMeanShiftTracker(); + ~CvFuzzyMeanShiftTracker(); + + void track(IplImage *maskImage, IplImage *depthMap, int resizeMethod, bool resetSearch, int minKernelMass = MinKernelMass); +}; + + +namespace cv +{ + +typedef bool (*BundleAdjustCallback)(int iteration, double norm_error, void* user_data); + +class CV_EXPORTS LevMarqSparse { +public: + LevMarqSparse(); + LevMarqSparse(int npoints, // number of points + int ncameras, // number of cameras + int nPointParams, // number of params per one point (3 in case of 3D points) + int nCameraParams, // number of parameters per one camera + int nErrParams, // number of parameters in measurement vector + // for 1 point at one camera (2 in case of 2D projections) + Mat& visibility, // visibility matrix. rows correspond to points, columns correspond to cameras + // 1 - point is visible for the camera, 0 - invisible + Mat& P0, // starting vector of parameters, first cameras then points + Mat& X, // measurements, in order of visibility. non visible cases are skipped + TermCriteria criteria, // termination criteria + + // callback for estimation of Jacobian matrices + void (*fjac)(int i, int j, Mat& point_params, + Mat& cam_params, Mat& A, Mat& B, void* data), + // callback for estimation of backprojection errors + void (*func)(int i, int j, Mat& point_params, + Mat& cam_params, Mat& estim, void* data), + void* data, // user-specific data passed to the callbacks + BundleAdjustCallback cb, void* user_data + ); + + virtual ~LevMarqSparse(); + + virtual void run( int npoints, // number of points + int ncameras, // number of cameras + int nPointParams, // number of params per one point (3 in case of 3D points) + int nCameraParams, // number of parameters per one camera + int nErrParams, // number of parameters in measurement vector + // for 1 point at one camera (2 in case of 2D projections) + Mat& visibility, // visibility matrix. rows correspond to points, columns correspond to cameras + // 1 - point is visible for the camera, 0 - invisible + Mat& P0, // starting vector of parameters, first cameras then points + Mat& X, // measurements, in order of visibility. non visible cases are skipped + TermCriteria criteria, // termination criteria + + // callback for estimation of Jacobian matrices + void (CV_CDECL * fjac)(int i, int j, Mat& point_params, + Mat& cam_params, Mat& A, Mat& B, void* data), + // callback for estimation of backprojection errors + void (CV_CDECL * func)(int i, int j, Mat& point_params, + Mat& cam_params, Mat& estim, void* data), + void* data // user-specific data passed to the callbacks + ); + + virtual void clear(); + + // useful function to do simple bundle adjustment tasks + static void bundleAdjust(std::vector& points, // positions of points in global coordinate system (input and output) + const std::vector >& imagePoints, // projections of 3d points for every camera + const std::vector >& visibility, // visibility of 3d points for every camera + std::vector& cameraMatrix, // intrinsic matrices of all cameras (input and output) + std::vector& R, // rotation matrices of all cameras (input and output) + std::vector& T, // translation vector of all cameras (input and output) + std::vector& distCoeffs, // distortion coefficients of all cameras (input and output) + const TermCriteria& criteria= + TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, DBL_EPSILON), + BundleAdjustCallback cb = 0, void* user_data = 0); + +public: + virtual void optimize(CvMat &_vis); //main function that runs minimization + + //iteratively asks for measurement for visible camera-point pairs + void ask_for_proj(CvMat &_vis,bool once=false); + //iteratively asks for Jacobians for every camera_point pair + void ask_for_projac(CvMat &_vis); + + CvMat* err; //error X-hX + double prevErrNorm, errNorm; + double lambda; + CvTermCriteria criteria; + int iters; + + CvMat** U; //size of array is equal to number of cameras + CvMat** V; //size of array is equal to number of points + CvMat** inv_V_star; //inverse of V* + + CvMat** A; + CvMat** B; + CvMat** W; + + CvMat* X; //measurement + CvMat* hX; //current measurement extimation given new parameter vector + + CvMat* prevP; //current already accepted parameter. + CvMat* P; // parameters used to evaluate function with new params + // this parameters may be rejected + + CvMat* deltaP; //computed increase of parameters (result of normal system solution ) + + CvMat** ea; // sum_i AijT * e_ij , used as right part of normal equation + // length of array is j = number of cameras + CvMat** eb; // sum_j BijT * e_ij , used as right part of normal equation + // length of array is i = number of points + + CvMat** Yj; //length of array is i = num_points + + CvMat* S; //big matrix of block Sjk , each block has size num_cam_params x num_cam_params + + CvMat* JtJ_diag; //diagonal of JtJ, used to backup diagonal elements before augmentation + + CvMat* Vis_index; // matrix which element is index of measurement for point i and camera j + + int num_cams; + int num_points; + int num_err_param; + int num_cam_param; + int num_point_param; + + //target function and jacobian pointers, which needs to be initialized + void (*fjac)(int i, int j, Mat& point_params, Mat& cam_params, Mat& A, Mat& B, void* data); + void (*func)(int i, int j, Mat& point_params, Mat& cam_params, Mat& estim, void* data); + + void* data; + + BundleAdjustCallback cb; + void* user_data; +}; + +} // cv + +#endif /* __cplusplus */ + +#endif /* __OPENCV_CONTRIB_COMPAT_HPP__ */ diff --git a/modules/contrib/include/opencv2/contrib/contrib.hpp b/modules/contrib/include/opencv2/contrib/contrib.hpp index 7a43631fce..b9edf94f59 100644 --- a/modules/contrib/include/opencv2/contrib/contrib.hpp +++ b/modules/contrib/include/opencv2/contrib/contrib.hpp @@ -45,4 +45,4 @@ #error this is a compatibility header which should not be used inside the OpenCV library #endif -#include "opencv2/contrib.hpp" \ No newline at end of file +#include "opencv2/contrib.hpp" diff --git a/modules/contrib/include/opencv2/contrib/detection_based_tracker.hpp b/modules/contrib/include/opencv2/contrib/detection_based_tracker.hpp index c3db03ab9f..c11904ea19 100644 --- a/modules/contrib/include/opencv2/contrib/detection_based_tracker.hpp +++ b/modules/contrib/include/opencv2/contrib/detection_based_tracker.hpp @@ -1,6 +1,6 @@ #pragma once -#if defined(__linux__) || defined(LINUX) || defined(__APPLE__) || defined(ANDROID) +#if defined(__linux__) || defined(LINUX) || defined(__APPLE__) || defined(__ANDROID__) #include #include @@ -9,7 +9,7 @@ namespace cv { -class DetectionBasedTracker +class CV_EXPORTS DetectionBasedTracker { public: struct Parameters diff --git a/modules/contrib/src/adaptiveskindetector.cpp b/modules/contrib/src/adaptiveskindetector.cpp index a44c42077f..092e48cb47 100644 --- a/modules/contrib/src/adaptiveskindetector.cpp +++ b/modules/contrib/src/adaptiveskindetector.cpp @@ -35,6 +35,8 @@ //M*/ #include "precomp.hpp" +#include "opencv2/imgproc/imgproc_c.h" +#include "opencv2/contrib/compat.hpp" #define ASD_INTENSITY_SET_PIXEL(pointer, qq) {(*pointer) = (unsigned char)qq;} @@ -284,5 +286,3 @@ void CvAdaptiveSkinDetector::Histogram::mergeWith(CvAdaptiveSkinDetector::Histog } } }; - - diff --git a/modules/contrib/src/ba.cpp b/modules/contrib/src/ba.cpp index 39acd45798..9a8002e96f 100644 --- a/modules/contrib/src/ba.cpp +++ b/modules/contrib/src/ba.cpp @@ -41,6 +41,8 @@ #include "precomp.hpp" #include "opencv2/calib3d.hpp" +#include "opencv2/contrib/compat.hpp" +#include "opencv2/calib3d/calib3d_c.h" #include using namespace cv; @@ -359,7 +361,7 @@ void LevMarqSparse::ask_for_proj(CvMat &/*_vis*/,bool once) { cvGetSubRect( P, &cam_mat, cvRect( 0, j * num_cam_param, 1, num_cam_param )); CvMat measur_mat; cvGetSubRect( hX, &measur_mat, cvRect( 0, ind * num_err_param, 1, num_err_param )); - Mat _point_mat(&point_mat), _cam_mat(&cam_mat), _measur_mat(&measur_mat); + Mat _point_mat = cv::cvarrToMat(&point_mat), _cam_mat = cv::cvarrToMat(&cam_mat), _measur_mat = cv::cvarrToMat(&measur_mat); func( i, j, _point_mat, _cam_mat, _measur_mat, data); assert( ind*num_err_param == ((int*)(Vis_index->data.ptr + i * Vis_index->step))[j]); ind+=1; @@ -398,7 +400,7 @@ void LevMarqSparse::ask_for_projac(CvMat &/*_vis*/) //should be evaluated at p //CvMat* Bij = B_line[j]; //CvMat* Bij = ((CvMat**)(B->data.ptr + B->step * i))[j]; - Mat _point_mat(&point_mat), _cam_mat(&cam_mat), _Aij(Aij), _Bij(Bij); + Mat _point_mat = cv::cvarrToMat(&point_mat), _cam_mat = cv::cvarrToMat(&cam_mat), _Aij = cv::cvarrToMat(Aij), _Bij = cv::cvarrToMat(Bij); (*fjac)(i, j, _point_mat, _cam_mat, _Aij, _Bij, data); } } @@ -744,7 +746,7 @@ static void fjac(int /*i*/, int /*j*/, CvMat *point_params, CvMat* cam_params, C CvMat* _mp = cvCreateMat(1, 1, CV_64FC2 ); //projection of the point //split camera params into different matrices - CvMat _ri, _ti, _k; + CvMat _ri, _ti, _k = cvMat(0, 0, CV_64F, NULL); // dummy initialization to fix warning of cl.exe cvGetRows( cam_params, &_ri, 0, 3 ); cvGetRows( cam_params, &_ti, 3, 6 ); @@ -1100,16 +1102,17 @@ void LevMarqSparse::bundleAdjust( std::vector& points, //positions of p } //fill camera params //R.clear();T.clear();cameraMatrix.clear(); + Mat levmarP = cv::cvarrToMat(levmar.P); for( int i = 0; i < num_cameras; i++ ) { //rotation - Mat rot_vec = Mat(levmar.P).rowRange(i*num_cam_param, i*num_cam_param+3); + Mat rot_vec = levmarP.rowRange(i*num_cam_param, i*num_cam_param+3); Rodrigues( rot_vec, R[i] ); //translation - T[i] = Mat(levmar.P).rowRange(i*num_cam_param + 3, i*num_cam_param+6); + levmarP.rowRange(i*num_cam_param + 3, i*num_cam_param+6).copyTo(T[i]); //intrinsic camera matrix double* intr_data = (double*)cameraMatrix[i].data; - double* intr = (double*)(Mat(levmar.P).data + Mat(levmar.P).step * (i*num_cam_param+6)); + double* intr = (double*)(levmarP.data +levmarP.step * (i*num_cam_param+6)); //focals intr_data[0] = intr[0]; //fx intr_data[4] = intr[1]; //fy @@ -1119,7 +1122,7 @@ void LevMarqSparse::bundleAdjust( std::vector& points, //positions of p //add distortion if exists if( distCoeffs.size() ) { - Mat(levmar.P).rowRange(i*num_cam_param + 10, i*num_cam_param+10+numdist).copyTo(distCoeffs[i]); + levmarP.rowRange(i*num_cam_param + 10, i*num_cam_param+10+numdist).copyTo(distCoeffs[i]); } } } diff --git a/modules/contrib/src/bowmsctrainer.cpp b/modules/contrib/src/bowmsctrainer.cpp index c1e945f9ba..3057691204 100644 --- a/modules/contrib/src/bowmsctrainer.cpp +++ b/modules/contrib/src/bowmsctrainer.cpp @@ -136,4 +136,3 @@ Mat BOWMSCTrainer::cluster(const Mat& _descriptors) const { } } - diff --git a/modules/contrib/src/chamfermatching.cpp b/modules/contrib/src/chamfermatching.cpp index bd30ad9916..fd2899c5f0 100644 --- a/modules/contrib/src/chamfermatching.cpp +++ b/modules/contrib/src/chamfermatching.cpp @@ -142,7 +142,7 @@ private: LocationScaleImageRange(const std::vector& locations, const std::vector& _scales) : locations_(locations), scales_(_scales) { - assert(locations.size()==_scales.size()); + CV_Assert(locations.size()==_scales.size()); } ImageIterator* iterator() const @@ -393,7 +393,7 @@ private: LocationScaleImageIterator(const std::vector& locations, const std::vector& _scales) : locations_(locations), scales_(_scales) { - assert(locations.size()==_scales.size()); + CV_Assert(locations.size()==_scales.size()); reset(); } @@ -622,7 +622,7 @@ void ChamferMatcher::Matching::followContour(Mat& templ_img, template_coords_t& coordinate_t next; unsigned char ptr; - assert (direction==-1 || !coords.empty()); + CV_Assert (direction==-1 || !coords.empty()); coordinate_t crt = coords.back(); @@ -903,19 +903,18 @@ void ChamferMatcher::Template::show() const p2.x = x + pad*(int)(sin(orientations[i])*100)/100; p2.y = y + pad*(int)(cos(orientations[i])*100)/100; - line(templ_color, p1,p2, CV_RGB(255,0,0)); + line(templ_color, p1,p2, Scalar(255,0,0)); } } - circle(templ_color,Point(center.x + pad, center.y + pad),1,CV_RGB(0,255,0)); + circle(templ_color,Point(center.x + pad, center.y + pad),1,Scalar(0,255,0)); #ifdef HAVE_OPENCV_HIGHGUI namedWindow("templ",1); imshow("templ",templ_color); - - cvWaitKey(0); + waitKey(); #else - CV_Error(CV_StsNotImplemented, "OpenCV has been compiled without GUI support"); + CV_Error(Error::StsNotImplemented, "OpenCV has been compiled without GUI support"); #endif templ_color.release(); @@ -1060,7 +1059,7 @@ void ChamferMatcher::Matching::fillNonContourOrientations(Mat& annotated_img, Ma int cols = annotated_img.cols; int rows = annotated_img.rows; - assert(orientation_img.cols==cols && orientation_img.rows==rows); + CV_Assert(orientation_img.cols==cols && orientation_img.rows==rows); for (int y=0;ycoords; for (size_t i=0;i& edges) { } } - diff --git a/modules/contrib/src/colormap.cpp b/modules/contrib/src/colormap.cpp index ca98b3a918..08ff44a5c6 100644 --- a/modules/contrib/src/colormap.cpp +++ b/modules/contrib/src/colormap.cpp @@ -40,7 +40,7 @@ static Mat linspace(float x0, float x1, int n) static void sortMatrixRowsByIndices(InputArray _src, InputArray _indices, OutputArray _dst) { if(_indices.getMat().type() != CV_32SC1) - CV_Error(CV_StsUnsupportedFormat, "cv::sortRowsByIndices only works on integer indices!"); + CV_Error(Error::StsUnsupportedFormat, "cv::sortRowsByIndices only works on integer indices!"); Mat src = _src.getMat(); std::vector indices = _indices.getMat(); _dst.create(src.rows, src.cols, src.type()); @@ -64,8 +64,8 @@ static Mat argsort(InputArray _src, bool ascending=true) { Mat src = _src.getMat(); if (src.rows != 1 && src.cols != 1) - CV_Error(CV_StsBadArg, "cv::argsort only sorts 1D matrices."); - int flags = CV_SORT_EVERY_ROW+(ascending ? CV_SORT_ASCENDING : CV_SORT_DESCENDING); + CV_Error(Error::StsBadArg, "cv::argsort only sorts 1D matrices."); + int flags = SORT_EVERY_ROW | (ascending ? SORT_ASCENDING : SORT_DESCENDING); Mat sorted_indices; sortIdx(src.reshape(1,1),sorted_indices,flags); return sorted_indices; @@ -116,8 +116,8 @@ static Mat interp1(InputArray _x, InputArray _Y, InputArray _xi) Mat Y = _Y.getMat(); Mat xi = _xi.getMat(); // check types & alignment - assert((x.type() == Y.type()) && (Y.type() == xi.type())); - assert((x.cols == 1) && (x.rows == Y.rows) && (x.cols == Y.cols)); + CV_Assert((x.type() == Y.type()) && (Y.type() == xi.type())); + CV_Assert((x.cols == 1) && (x.rows == Y.rows) && (x.cols == Y.cols)); // call templated interp1 switch(x.type()) { case CV_8SC1: return interp1_(x,Y,xi); break; @@ -127,7 +127,7 @@ static Mat interp1(InputArray _x, InputArray _Y, InputArray _xi) case CV_32SC1: return interp1_(x,Y,xi); break; case CV_32FC1: return interp1_(x,Y,xi); break; case CV_64FC1: return interp1_(x,Y,xi); break; - default: CV_Error(CV_StsUnsupportedFormat, ""); break; + default: CV_Error(Error::StsUnsupportedFormat, ""); break; } return Mat(); } @@ -473,7 +473,7 @@ namespace colormap void ColorMap::operator()(InputArray _src, OutputArray _dst) const { if(_lut.total() != 256) - CV_Error(CV_StsAssert, "cv::LUT only supports tables of size 256."); + CV_Error(Error::StsAssert, "cv::LUT only supports tables of size 256."); Mat src = _src.getMat(); // Return original matrix if wrong type is given (is fail loud better here?) if(src.type() != CV_8UC1 && src.type() != CV_8UC3) @@ -483,8 +483,8 @@ namespace colormap } // Turn into a BGR matrix into its grayscale representation. if(src.type() == CV_8UC3) - cvtColor(src.clone(), src, CV_BGR2GRAY); - cvtColor(src.clone(), src, CV_GRAY2BGR); + cvtColor(src.clone(), src, COLOR_BGR2GRAY); + cvtColor(src.clone(), src, COLOR_GRAY2BGR); // Apply the ColorMap. LUT(src, _lut, _dst); } @@ -521,7 +521,7 @@ namespace colormap colormap == COLORMAP_WINTER ? (colormap::ColorMap*)(new colormap::Winter) : 0; if( !cm ) - CV_Error( CV_StsBadArg, "Unknown colormap id; use one of COLORMAP_*"); + CV_Error( Error::StsBadArg, "Unknown colormap id; use one of COLORMAP_*"); (*cm)(src, dst); diff --git a/modules/contrib/src/colortracker.cpp b/modules/contrib/src/colortracker.cpp index 5a9d9b7c43..a3eeb052b2 100644 --- a/modules/contrib/src/colortracker.cpp +++ b/modules/contrib/src/colortracker.cpp @@ -60,7 +60,7 @@ void CvMeanShiftTracker::newTrackingWindow(Mat image, Rect selection) float srange[] = { 0, 1 }; const float* ranges[] = {hrange, srange}; - cvtColor(image, hsv, CV_BGR2HSV); + cvtColor(image, hsv, COLOR_BGR2HSV); inRange(hsv, Scalar(0, 30, MIN(10, 256)), Scalar(180, 256, MAX(10, 256)), mask); hue.create(hsv.size(), CV_8UC2); @@ -83,7 +83,7 @@ RotatedRect CvMeanShiftTracker::updateTrackingWindow(Mat image) float srange[] = { 0, 1 }; const float* ranges[] = {hrange, srange}; - cvtColor(image, hsv, CV_BGR2HSV); + cvtColor(image, hsv, COLOR_BGR2HSV); inRange(hsv, Scalar(0, 30, MIN(10, 256)), Scalar(180, 256, MAX(10, 256)), mask); hue.create(hsv.size(), CV_8UC2); mixChannels(&hsv, 1, &hue, 1, channels, 2); @@ -132,5 +132,3 @@ Point2f CvMeanShiftTracker::getTrackingCenter() { return prev_center; } - - diff --git a/modules/contrib/src/contrib_init.cpp b/modules/contrib/src/contrib_init.cpp index a80f6f5e11..317867a59f 100644 --- a/modules/contrib/src/contrib_init.cpp +++ b/modules/contrib/src/contrib_init.cpp @@ -41,4 +41,3 @@ //M*/ #include "precomp.hpp" - diff --git a/modules/contrib/src/detection_based_tracker.cpp b/modules/contrib/src/detection_based_tracker.cpp index 117a6e916a..27807290af 100644 --- a/modules/contrib/src/detection_based_tracker.cpp +++ b/modules/contrib/src/detection_based_tracker.cpp @@ -1,5 +1,6 @@ #if defined(__linux__) || defined(LINUX) || defined(__APPLE__) || defined(ANDROID) #include "opencv2/contrib/detection_based_tracker.hpp" +#include "opencv2/core/utility.hpp" #include @@ -127,7 +128,7 @@ cv::DetectionBasedTracker::SeparateDetectionWork::SeparateDetectionWork(Detectio stateThread(STATE_THREAD_STOPPED), timeWhenDetectingThreadStartedWork(-1) { - CV_Assert(!_detector.empty()); + CV_Assert(_detector); cascadeInThread = _detector; @@ -461,11 +462,11 @@ cv::DetectionBasedTracker::DetectionBasedTracker(cv::Ptr mainDetector cascadeForTracking(trackingDetector) { CV_Assert( (params.maxTrackLifetime >= 0) -// && (!mainDetector.empty()) - && (!trackingDetector.empty()) ); +// && mainDetector + && trackingDetector ); - if (!mainDetector.empty()) { - separateDetectionWork = new SeparateDetectionWork(*this, mainDetector); + if (mainDetector) { + separateDetectionWork.reset(new SeparateDetectionWork(*this, mainDetector)); } weightsPositionsSmoothing.push_back(1); @@ -482,7 +483,7 @@ void DetectionBasedTracker::process(const Mat& imageGray) { CV_Assert(imageGray.type()==CV_8UC1); - if ( (!separateDetectionWork.empty()) && (!separateDetectionWork->isWorking()) ) { + if ( separateDetectionWork && !separateDetectionWork->isWorking() ) { separateDetectionWork->run(); } @@ -500,7 +501,7 @@ void DetectionBasedTracker::process(const Mat& imageGray) std::vector rectsWhereRegions; bool shouldHandleResult=false; - if (!separateDetectionWork.empty()) { + if (separateDetectionWork) { shouldHandleResult = separateDetectionWork->communicateWithDetectingThread(imageGray, rectsWhereRegions); } @@ -588,7 +589,7 @@ void cv::DetectionBasedTracker::getObjects(std::vector& result) const bool cv::DetectionBasedTracker::run() { - if (!separateDetectionWork.empty()) { + if (separateDetectionWork) { return separateDetectionWork->run(); } return false; @@ -596,14 +597,14 @@ bool cv::DetectionBasedTracker::run() void cv::DetectionBasedTracker::stop() { - if (!separateDetectionWork.empty()) { + if (separateDetectionWork) { separateDetectionWork->stop(); } } void cv::DetectionBasedTracker::resetTracking() { - if (!separateDetectionWork.empty()) { + if (separateDetectionWork) { separateDetectionWork->resetTracking(); } trackedObjects.clear(); @@ -875,11 +876,11 @@ bool cv::DetectionBasedTracker::setParameters(const Parameters& params) return false; } - if (!separateDetectionWork.empty()) { + if (separateDetectionWork) { separateDetectionWork->lock(); } parameters=params; - if (!separateDetectionWork.empty()) { + if (separateDetectionWork) { separateDetectionWork->unlock(); } return true; @@ -891,4 +892,3 @@ const cv::DetectionBasedTracker::Parameters& DetectionBasedTracker::getParameter } #endif - diff --git a/modules/contrib/src/facerec.cpp b/modules/contrib/src/facerec.cpp index 9ce082819e..1bea74e89e 100644 --- a/modules/contrib/src/facerec.cpp +++ b/modules/contrib/src/facerec.cpp @@ -17,6 +17,7 @@ */ #include "precomp.hpp" #include +#include namespace cv { @@ -35,7 +36,7 @@ inline void readFileNodeList(const FileNode& fn, std::vector<_Tp>& result) { // Writes the a list of given items to a cv::FileStorage. template -inline void writeFileNodeList(FileStorage& fs, const std::string& name, +inline void writeFileNodeList(FileStorage& fs, const String& name, const std::vector<_Tp>& items) { // typedefs typedef typename std::vector<_Tp>::const_iterator constVecIterator; @@ -50,8 +51,8 @@ inline void writeFileNodeList(FileStorage& fs, const std::string& name, static Mat asRowMatrix(InputArrayOfArrays src, int rtype, double alpha=1, double beta=0) { // make sure the input data is a vector of matrices or vector of vector if(src.kind() != _InputArray::STD_VECTOR_MAT && src.kind() != _InputArray::STD_VECTOR_VECTOR) { - std::string error_message = "The data is expected as InputArray::STD_VECTOR_MAT (a std::vector) or _InputArray::STD_VECTOR_VECTOR (a std::vector< std::vector<...> >)."; - CV_Error(CV_StsBadArg, error_message); + String error_message = "The data is expected as InputArray::STD_VECTOR_MAT (a std::vector) or _InputArray::STD_VECTOR_VECTOR (a std::vector< std::vector<...> >)."; + CV_Error(Error::StsBadArg, error_message); } // number of samples size_t n = src.total(); @@ -66,8 +67,8 @@ static Mat asRowMatrix(InputArrayOfArrays src, int rtype, double alpha=1, double for(unsigned int i = 0; i < n; i++) { // make sure data can be reshaped, throw exception if not! if(src.getMat(i).total() != d) { - std::string error_message = format("Wrong number of elements in matrix #%d! Expected %d was %d.", i, d, src.getMat(i).total()); - CV_Error(CV_StsBadArg, error_message); + String error_message = format("Wrong number of elements in matrix #%d! Expected %d was %d.", i, d, src.getMat(i).total()); + CV_Error(Error::StsBadArg, error_message); } // get a hold of the current row Mat xi = data.row(i); @@ -305,22 +306,22 @@ void FaceRecognizer::update(InputArrayOfArrays src, InputArray labels ) { return; } - std::string error_msg = format("This FaceRecognizer (%s) does not support updating, you have to use FaceRecognizer::train to update it.", this->name().c_str()); - CV_Error(CV_StsNotImplemented, error_msg); + String error_msg = format("This FaceRecognizer (%s) does not support updating, you have to use FaceRecognizer::train to update it.", this->name().c_str()); + CV_Error(Error::StsNotImplemented, error_msg); } -void FaceRecognizer::save(const std::string& filename) const { +void FaceRecognizer::save(const String& filename) const { FileStorage fs(filename, FileStorage::WRITE); if (!fs.isOpened()) - CV_Error(CV_StsError, "File can't be opened for writing!"); + CV_Error(Error::StsError, "File can't be opened for writing!"); this->save(fs); fs.release(); } -void FaceRecognizer::load(const std::string& filename) { +void FaceRecognizer::load(const String& filename) { FileStorage fs(filename, FileStorage::READ); if (!fs.isOpened()) - CV_Error(CV_StsError, "File can't be opened for writing!"); + CV_Error(Error::StsError, "File can't be opened for writing!"); this->load(fs); fs.release(); } @@ -330,18 +331,18 @@ void FaceRecognizer::load(const std::string& filename) { //------------------------------------------------------------------------------ void Eigenfaces::train(InputArrayOfArrays _src, InputArray _local_labels) { if(_src.total() == 0) { - std::string error_message = format("Empty training data was given. You'll need more than one sample to learn a model."); - CV_Error(CV_StsBadArg, error_message); + String error_message = format("Empty training data was given. You'll need more than one sample to learn a model."); + CV_Error(Error::StsBadArg, error_message); } else if(_local_labels.getMat().type() != CV_32SC1) { - std::string error_message = format("Labels must be given as integer (CV_32SC1). Expected %d, but was %d.", CV_32SC1, _local_labels.type()); - CV_Error(CV_StsBadArg, error_message); + String error_message = format("Labels must be given as integer (CV_32SC1). Expected %d, but was %d.", CV_32SC1, _local_labels.type()); + CV_Error(Error::StsBadArg, error_message); } // make sure data has correct size if(_src.total() > 1) { for(int i = 1; i < static_cast(_src.total()); i++) { if(_src.getMat(i-1).total() != _src.getMat(i).total()) { - std::string error_message = format("In the Eigenfaces method all input samples (training images) must be of equal size! Expected %d pixels, but was %d pixels.", _src.getMat(i-1).total(), _src.getMat(i).total()); - CV_Error(CV_StsUnsupportedFormat, error_message); + String error_message = format("In the Eigenfaces method all input samples (training images) must be of equal size! Expected %d pixels, but was %d pixels.", _src.getMat(i-1).total(), _src.getMat(i).total()); + CV_Error(Error::StsUnsupportedFormat, error_message); } } } @@ -354,8 +355,8 @@ void Eigenfaces::train(InputArrayOfArrays _src, InputArray _local_labels) { int n = data.rows; // assert there are as much samples as labels if(static_cast(labels.total()) != n) { - std::string error_message = format("The number of samples (src) must equal the number of labels (labels)! len(src)=%d, len(labels)=%d.", n, labels.total()); - CV_Error(CV_StsBadArg, error_message); + String error_message = format("The number of samples (src) must equal the number of labels (labels)! len(src)=%d, len(labels)=%d.", n, labels.total()); + CV_Error(Error::StsBadArg, error_message); } // clear existing model data _labels.release(); @@ -365,7 +366,7 @@ void Eigenfaces::train(InputArrayOfArrays _src, InputArray _local_labels) { _num_components = n; // perform the PCA - PCA pca(data, Mat(), CV_PCA_DATA_AS_ROW, _num_components); + PCA pca(data, Mat(), PCA::DATA_AS_ROW, _num_components); // copy the PCA results _mean = pca.mean.reshape(1,1); // store the mean vector _eigenvalues = pca.eigenvalues.clone(); // eigenvalues by row @@ -385,12 +386,12 @@ void Eigenfaces::predict(InputArray _src, int &minClass, double &minDist) const // make sure the user is passing correct data if(_projections.empty()) { // throw error if no data (or simply return -1?) - std::string error_message = "This Eigenfaces model is not computed yet. Did you call Eigenfaces::train?"; - CV_Error(CV_StsError, error_message); + String error_message = "This Eigenfaces model is not computed yet. Did you call Eigenfaces::train?"; + CV_Error(Error::StsError, error_message); } else if(_eigenvectors.rows != static_cast(src.total())) { // check data alignment just for clearer exception messages - std::string error_message = format("Wrong input image size. Reason: Training and Test images must be of equal size! Expected an image with %d elements, but got %d.", _eigenvectors.rows, src.total()); - CV_Error(CV_StsBadArg, error_message); + String error_message = format("Wrong input image size. Reason: Training and Test images must be of equal size! Expected an image with %d elements, but got %d.", _eigenvectors.rows, src.total()); + CV_Error(Error::StsBadArg, error_message); } // project into PCA subspace Mat q = subspaceProject(_eigenvectors, _mean, src.reshape(1,1)); @@ -439,18 +440,18 @@ void Eigenfaces::save(FileStorage& fs) const { //------------------------------------------------------------------------------ void Fisherfaces::train(InputArrayOfArrays src, InputArray _lbls) { if(src.total() == 0) { - std::string error_message = format("Empty training data was given. You'll need more than one sample to learn a model."); - CV_Error(CV_StsBadArg, error_message); + String error_message = format("Empty training data was given. You'll need more than one sample to learn a model."); + CV_Error(Error::StsBadArg, error_message); } else if(_lbls.getMat().type() != CV_32SC1) { - std::string error_message = format("Labels must be given as integer (CV_32SC1). Expected %d, but was %d.", CV_32SC1, _lbls.type()); - CV_Error(CV_StsBadArg, error_message); + String error_message = format("Labels must be given as integer (CV_32SC1). Expected %d, but was %d.", CV_32SC1, _lbls.type()); + CV_Error(Error::StsBadArg, error_message); } // make sure data has correct size if(src.total() > 1) { for(int i = 1; i < static_cast(src.total()); i++) { if(src.getMat(i-1).total() != src.getMat(i).total()) { - std::string error_message = format("In the Fisherfaces method all input samples (training images) must be of equal size! Expected %d pixels, but was %d pixels.", src.getMat(i-1).total(), src.getMat(i).total()); - CV_Error(CV_StsUnsupportedFormat, error_message); + String error_message = format("In the Fisherfaces method all input samples (training images) must be of equal size! Expected %d pixels, but was %d pixels.", src.getMat(i-1).total(), src.getMat(i).total()); + CV_Error(Error::StsUnsupportedFormat, error_message); } } } @@ -461,11 +462,11 @@ void Fisherfaces::train(InputArrayOfArrays src, InputArray _lbls) { int N = data.rows; // make sure labels are passed in correct shape if(labels.total() != (size_t) N) { - std::string error_message = format("The number of samples (src) must equal the number of labels (labels)! len(src)=%d, len(labels)=%d.", N, labels.total()); - CV_Error(CV_StsBadArg, error_message); + String error_message = format("The number of samples (src) must equal the number of labels (labels)! len(src)=%d, len(labels)=%d.", N, labels.total()); + CV_Error(Error::StsBadArg, error_message); } else if(labels.rows != 1 && labels.cols != 1) { - std::string error_message = format("Expected the labels in a matrix with one row or column! Given dimensions are rows=%s, cols=%d.", labels.rows, labels.cols); - CV_Error(CV_StsBadArg, error_message); + String error_message = format("Expected the labels in a matrix with one row or column! Given dimensions are rows=%s, cols=%d.", labels.rows, labels.cols); + CV_Error(Error::StsBadArg, error_message); } // clear existing model data _labels.release(); @@ -481,7 +482,7 @@ void Fisherfaces::train(InputArrayOfArrays src, InputArray _lbls) { if((_num_components <= 0) || (_num_components > (C-1))) _num_components = (C-1); // perform a PCA and keep (N-C) components - PCA pca(data, Mat(), CV_PCA_DATA_AS_ROW, (N-C)); + PCA pca(data, Mat(), PCA::DATA_AS_ROW, (N-C)); // project the data and perform a LDA on it LDA lda(pca.project(data),labels, _num_components); // store the total mean vector @@ -505,11 +506,11 @@ void Fisherfaces::predict(InputArray _src, int &minClass, double &minDist) const // check data alignment just for clearer exception messages if(_projections.empty()) { // throw error if no data (or simply return -1?) - std::string error_message = "This Fisherfaces model is not computed yet. Did you call Fisherfaces::train?"; - CV_Error(CV_StsBadArg, error_message); + String error_message = "This Fisherfaces model is not computed yet. Did you call Fisherfaces::train?"; + CV_Error(Error::StsBadArg, error_message); } else if(src.total() != (size_t) _eigenvectors.rows) { - std::string error_message = format("Wrong input image size. Reason: Training and Test images must be of equal size! Expected an image with %d elements, but got %d.", _eigenvectors.rows, src.total()); - CV_Error(CV_StsBadArg, error_message); + String error_message = format("Wrong input image size. Reason: Training and Test images must be of equal size! Expected an image with %d elements, but got %d.", _eigenvectors.rows, src.total()); + CV_Error(Error::StsBadArg, error_message); } // project into LDA subspace Mat q = subspaceProject(_eigenvectors, _mean, src.reshape(1,1)); @@ -640,8 +641,8 @@ static void elbp(InputArray src, OutputArray dst, int radius, int neighbors) case CV_32FC1: elbp_(src,dst, radius, neighbors); break; case CV_64FC1: elbp_(src,dst, radius, neighbors); break; default: - std::string error_msg = format("Using Original Local Binary Patterns for feature extraction only works on single-channel images (given %d). Please pass the image data as a grayscale image!", type); - CV_Error(CV_StsNotImplemented, error_msg); + String error_msg = format("Using Original Local Binary Patterns for feature extraction only works on single-channel images (given %d). Please pass the image data as a grayscale image!", type); + CV_Error(Error::StsNotImplemented, error_msg); break; } } @@ -687,7 +688,7 @@ static Mat histc(InputArray _src, int minVal, int maxVal, bool normed) return histc_(src, minVal, maxVal, normed); break; default: - CV_Error(CV_StsUnmatchedFormats, "This type is not implemented yet."); break; + CV_Error(Error::StsUnmatchedFormats, "This type is not implemented yet."); break; } return Mat(); } @@ -768,15 +769,15 @@ void LBPH::update(InputArrayOfArrays _in_src, InputArray _in_labels) { void LBPH::train(InputArrayOfArrays _in_src, InputArray _in_labels, bool preserveData) { if(_in_src.kind() != _InputArray::STD_VECTOR_MAT && _in_src.kind() != _InputArray::STD_VECTOR_VECTOR) { - std::string error_message = "The images are expected as InputArray::STD_VECTOR_MAT (a std::vector) or _InputArray::STD_VECTOR_VECTOR (a std::vector< std::vector<...> >)."; - CV_Error(CV_StsBadArg, error_message); + String error_message = "The images are expected as InputArray::STD_VECTOR_MAT (a std::vector) or _InputArray::STD_VECTOR_VECTOR (a std::vector< std::vector<...> >)."; + CV_Error(Error::StsBadArg, error_message); } if(_in_src.total() == 0) { - std::string error_message = format("Empty training data was given. You'll need more than one sample to learn a model."); - CV_Error(CV_StsUnsupportedFormat, error_message); + String error_message = format("Empty training data was given. You'll need more than one sample to learn a model."); + CV_Error(Error::StsUnsupportedFormat, error_message); } else if(_in_labels.getMat().type() != CV_32SC1) { - std::string error_message = format("Labels must be given as integer (CV_32SC1). Expected %d, but was %d.", CV_32SC1, _in_labels.type()); - CV_Error(CV_StsUnsupportedFormat, error_message); + String error_message = format("Labels must be given as integer (CV_32SC1). Expected %d, but was %d.", CV_32SC1, _in_labels.type()); + CV_Error(Error::StsUnsupportedFormat, error_message); } // get the vector of matrices std::vector src; @@ -785,8 +786,8 @@ void LBPH::train(InputArrayOfArrays _in_src, InputArray _in_labels, bool preserv Mat labels = _in_labels.getMat(); // check if data is well- aligned if(labels.total() != src.size()) { - std::string error_message = format("The number of samples (src) must equal the number of labels (labels). Was len(samples)=%d, len(labels)=%d.", src.size(), _labels.total()); - CV_Error(CV_StsBadArg, error_message); + String error_message = format("The number of samples (src) must equal the number of labels (labels). Was len(samples)=%d, len(labels)=%d.", src.size(), _labels.total()); + CV_Error(Error::StsBadArg, error_message); } // if this model should be trained without preserving old data, delete old model data if(!preserveData) { @@ -816,8 +817,8 @@ void LBPH::train(InputArrayOfArrays _in_src, InputArray _in_labels, bool preserv void LBPH::predict(InputArray _src, int &minClass, double &minDist) const { if(_histograms.empty()) { // throw error if no data (or simply return -1?) - std::string error_message = "This LBPH model is not computed yet. Did you call the train method?"; - CV_Error(CV_StsBadArg, error_message); + String error_message = "This LBPH model is not computed yet. Did you call the train method?"; + CV_Error(Error::StsBadArg, error_message); } Mat src = _src.getMat(); // get the spatial histogram from input image @@ -832,7 +833,7 @@ void LBPH::predict(InputArray _src, int &minClass, double &minDist) const { minDist = DBL_MAX; minClass = -1; for(size_t sampleIdx = 0; sampleIdx < _histograms.size(); sampleIdx++) { - double dist = compareHist(_histograms[sampleIdx], query, CV_COMP_CHISQR); + double dist = compareHist(_histograms[sampleIdx], query, HISTCMP_CHISQR); if((dist < minDist) && (dist < _threshold)) { minDist = dist; minClass = _labels.at((int) sampleIdx); @@ -850,18 +851,18 @@ int LBPH::predict(InputArray _src) const { Ptr createEigenFaceRecognizer(int num_components, double threshold) { - return new Eigenfaces(num_components, threshold); + return makePtr(num_components, threshold); } Ptr createFisherFaceRecognizer(int num_components, double threshold) { - return new Fisherfaces(num_components, threshold); + return makePtr(num_components, threshold); } Ptr createLBPHFaceRecognizer(int radius, int neighbors, int grid_x, int grid_y, double threshold) { - return new LBPH(radius, neighbors, grid_x, grid_y, threshold); + return makePtr(radius, neighbors, grid_x, grid_y, threshold); } CV_INIT_ALGORITHM(Eigenfaces, "FaceRecognizer.Eigenfaces", @@ -893,7 +894,7 @@ CV_INIT_ALGORITHM(LBPH, "FaceRecognizer.LBPH", bool initModule_contrib() { - Ptr efaces = createEigenfaces(), ffaces = createFisherfaces(), lbph = createLBPH(); + Ptr efaces = createEigenfaces_ptr_hidden(), ffaces = createFisherfaces_ptr_hidden(), lbph = createLBPH_ptr_hidden(); return efaces->info() != 0 && ffaces->info() != 0 && lbph->info() != 0; } diff --git a/modules/contrib/src/featuretracker.cpp b/modules/contrib/src/featuretracker.cpp index 575f69abf9..795c1a08fa 100644 --- a/modules/contrib/src/featuretracker.cpp +++ b/modules/contrib/src/featuretracker.cpp @@ -54,23 +54,26 @@ CvFeatureTracker::CvFeatureTracker(CvFeatureTrackerParams _params) : { case CvFeatureTrackerParams::SIFT: dd = Algorithm::create("Feature2D.SIFT"); - if( dd.empty() ) + if( !dd ) CV_Error(CV_StsNotImplemented, "OpenCV has been compiled without SIFT support"); dd->set("nOctaveLayers", 5); dd->set("contrastThreshold", 0.04); dd->set("edgeThreshold", 10.7); + break; case CvFeatureTrackerParams::SURF: dd = Algorithm::create("Feature2D.SURF"); - if( dd.empty() ) + if( !dd ) CV_Error(CV_StsNotImplemented, "OpenCV has been compiled without SURF support"); dd->set("hessianThreshold", 400); dd->set("nOctaves", 3); dd->set("nOctaveLayers", 4); + break; default: CV_Error(CV_StsBadArg, "Unknown feature type"); + break; } - matcher = new BFMatcher(NORM_L2); + matcher = makePtr(int(NORM_L2)); } CvFeatureTracker::~CvFeatureTracker() @@ -80,7 +83,7 @@ CvFeatureTracker::~CvFeatureTracker() void CvFeatureTracker::newTrackingWindow(Mat image, Rect selection) { image.copyTo(prev_image); - cvtColor(prev_image, prev_image_bw, CV_BGR2GRAY); + cvtColor(prev_image, prev_image_bw, COLOR_BGR2GRAY); prev_trackwindow = selection; prev_center.x = selection.x; prev_center.y = selection.y; @@ -131,7 +134,7 @@ Rect CvFeatureTracker::updateTrackingWindowWithSIFT(Mat image) curr_keys.push_back(curr_keypoints[matches[i].trainIdx].pt); } - Mat T = findHomography(prev_keys, curr_keys, CV_LMEDS); + Mat T = findHomography(prev_keys, curr_keys, LMEDS); prev_trackwindow.x += cvRound(T.at (0, 2)); prev_trackwindow.y += cvRound(T.at (1, 2)); @@ -148,12 +151,12 @@ Rect CvFeatureTracker::updateTrackingWindowWithFlow(Mat image) ittr++; Size subPixWinSize(10,10), winSize(31,31); Mat image_bw; - TermCriteria termcrit(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03); + TermCriteria termcrit(TermCriteria::COUNT | TermCriteria::EPS, 20, 0.03); std::vector status; std::vector err; - cvtColor(image, image_bw, CV_BGR2GRAY); - cvtColor(prev_image, prev_image_bw, CV_BGR2GRAY); + cvtColor(image, image_bw, COLOR_BGR2GRAY); + cvtColor(prev_image, prev_image_bw, COLOR_BGR2GRAY); if (ittr == 1) { @@ -218,4 +221,3 @@ Point2f CvFeatureTracker::getTrackingCenter() center.y = (float)(prev_center.y + prev_trackwindow.height/2.0); return center; } - diff --git a/modules/contrib/src/fuzzymeanshifttracker.cpp b/modules/contrib/src/fuzzymeanshifttracker.cpp index 443b961ed1..5e5ebc7e99 100644 --- a/modules/contrib/src/fuzzymeanshifttracker.cpp +++ b/modules/contrib/src/fuzzymeanshifttracker.cpp @@ -35,6 +35,7 @@ //M*/ #include "precomp.hpp" +#include "opencv2/contrib/compat.hpp" CvFuzzyPoint::CvFuzzyPoint(double _x, double _y) { @@ -380,6 +381,7 @@ void CvFuzzyMeanShiftTracker::SearchWindow::initDepthValues(IplImage *maskImage, { if (*depthData) { + d = *depthData; m1 += d; if (d < mind) mind = d; @@ -719,4 +721,3 @@ void CvFuzzyMeanShiftTracker::track(IplImage *maskImage, IplImage *depthMap, int searchMode = tsTracking; } }; - diff --git a/modules/contrib/src/gencolors.cpp b/modules/contrib/src/gencolors.cpp index 504015308c..24796ec03d 100644 --- a/modules/contrib/src/gencolors.cpp +++ b/modules/contrib/src/gencolors.cpp @@ -85,7 +85,7 @@ static void downsamplePoints( const Mat& src, Mat& dst, size_t count ) candidatePointsMask.at(0, maxLoc.x) = 0; Mat minDists; - reduce( activedDists, minDists, 0, CV_REDUCE_MIN ); + reduce( activedDists, minDists, 0, REDUCE_MIN ); minMaxLoc( minDists, 0, &maxVal, 0, &maxLoc, candidatePointsMask ); dst.at >((int)i) = src.at >(maxLoc.x); } @@ -118,7 +118,7 @@ void cv::generateColors( std::vector& colors, size_t count, size_t facto // Convert the colors set to Lab space. // Distances between colors in this space correspond a human perception. Mat lab; - cvtColor( bgr, lab, CV_BGR2Lab); + cvtColor( bgr, lab, COLOR_BGR2Lab); // Subsample colors from the generated set so that // to maximize the minimum distances between each other. @@ -128,7 +128,7 @@ void cv::generateColors( std::vector& colors, size_t count, size_t facto // Convert subsampled colors back to RGB Mat bgr_subset; - cvtColor( lab_subset, bgr_subset, CV_Lab2BGR ); + cvtColor( lab_subset, bgr_subset, COLOR_Lab2BGR ); CV_Assert( bgr_subset.total() == count ); for( size_t i = 0; i < count; i++ ) diff --git a/modules/contrib/src/hybridtracker.cpp b/modules/contrib/src/hybridtracker.cpp index 23a6ecbbad..d93f76d0d3 100644 --- a/modules/contrib/src/hybridtracker.cpp +++ b/modules/contrib/src/hybridtracker.cpp @@ -233,4 +233,3 @@ void CvHybridTracker::updateTrackerWithLowPassFilter(Mat) { Rect CvHybridTracker::getTrackingWindow() { return prev_window; } - diff --git a/modules/contrib/src/inputoutput.cpp b/modules/contrib/src/inputoutput.cpp index ee97e1287b..7f583558e8 100644 --- a/modules/contrib/src/inputoutput.cpp +++ b/modules/contrib/src/inputoutput.cpp @@ -1,7 +1,7 @@ - #include "opencv2/contrib.hpp" +#include "cvconfig.h" -#ifdef WIN32 +#if defined(WIN32) || defined(_WIN32) #include #include #else @@ -10,16 +10,27 @@ namespace cv { - std::vector Directory::GetListFiles( const std::string& path, const std::string & exten, bool addPath ) + std::vector Directory::GetListFiles( const String& path, const String & exten, bool addPath ) { - std::vector list; + std::vector list; list.clear(); - std::string path_f = path + "/" + exten; + String path_f = path + "/" + exten; #ifdef WIN32 - WIN32_FIND_DATA FindFileData; - HANDLE hFind; + #ifdef HAVE_WINRT + WIN32_FIND_DATAW FindFileData; + #else + WIN32_FIND_DATAA FindFileData; + #endif + HANDLE hFind; - hFind = FindFirstFile((LPCSTR)path_f.c_str(), &FindFileData); + #ifdef HAVE_WINRT + wchar_t wpath[MAX_PATH]; + size_t copied = mbstowcs(wpath, path_f.c_str(), MAX_PATH); + CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1)); + hFind = FindFirstFileExW(wpath, FindExInfoStandard, &FindFileData, FindExSearchNameMatch, NULL, 0); + #else + hFind = FindFirstFileA((LPCSTR)path_f.c_str(), &FindFileData); + #endif if (hFind == INVALID_HANDLE_VALUE) { return list; @@ -34,13 +45,26 @@ namespace cv FindFileData.dwFileAttributes == FILE_ATTRIBUTE_SYSTEM || FindFileData.dwFileAttributes == FILE_ATTRIBUTE_READONLY) { + char* fname; + #ifdef HAVE_WINRT + char fname_tmp[MAX_PATH] = {0}; + size_t copied = wcstombs(fname_tmp, FindFileData.cFileName, MAX_PATH); + CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1)); + fname = fname_tmp; + #else + fname = FindFileData.cFileName; + #endif if (addPath) - list.push_back(path + "/" + FindFileData.cFileName); + list.push_back(path + "/" + String(fname)); else - list.push_back(FindFileData.cFileName); + list.push_back(String(fname)); } } - while(FindNextFile(hFind, &FindFileData)); + #ifdef HAVE_WINRT + while(FindNextFileW(hFind, &FindFileData)); + #else + while(FindNextFileA(hFind, &FindFileData)); + #endif FindClose(hFind); } #else @@ -57,10 +81,10 @@ namespace cv if (dirp->d_type == DT_REG) { if (exten.compare("*") == 0) - list.push_back(static_cast(dirp->d_name)); + list.push_back(static_cast(dirp->d_name)); else - if (std::string(dirp->d_name).find(exten) != std::string::npos) - list.push_back(static_cast(dirp->d_name)); + if (String(dirp->d_name).find(exten) != String::npos) + list.push_back(static_cast(dirp->d_name)); } } closedir(dp); @@ -69,16 +93,28 @@ namespace cv return list; } - std::vector Directory::GetListFolders( const std::string& path, const std::string & exten, bool addPath ) + std::vector Directory::GetListFolders( const String& path, const String & exten, bool addPath ) { - std::vector list; - std::string path_f = path + "/" + exten; + std::vector list; + String path_f = path + "/" + exten; list.clear(); #ifdef WIN32 - WIN32_FIND_DATA FindFileData; + #ifdef HAVE_WINRT + WIN32_FIND_DATAW FindFileData; + #else + WIN32_FIND_DATAA FindFileData; + #endif HANDLE hFind; - hFind = FindFirstFile((LPCSTR)path_f.c_str(), &FindFileData); + #ifdef HAVE_WINRT + wchar_t wpath [MAX_PATH]; + size_t copied = mbstowcs(wpath, path_f.c_str(), path_f.size()); + CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1)); + + hFind = FindFirstFileExW(wpath, FindExInfoStandard, &FindFileData, FindExSearchNameMatch, NULL, 0); + #else + hFind = FindFirstFileA((LPCSTR)path_f.c_str(), &FindFileData); + #endif if (hFind == INVALID_HANDLE_VALUE) { return list; @@ -87,17 +123,37 @@ namespace cv { do { +#ifdef HAVE_WINRT + if (FindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY && + wcscmp(FindFileData.cFileName, L".") != 0 && + wcscmp(FindFileData.cFileName, L"..") != 0) +#else if (FindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY && strcmp(FindFileData.cFileName, ".") != 0 && strcmp(FindFileData.cFileName, "..") != 0) +#endif { + char* fname; + #ifdef HAVE_WINRT + char fname_tmp[MAX_PATH]; + size_t copied = wcstombs(fname_tmp, FindFileData.cFileName, MAX_PATH); + CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1)); + fname = fname_tmp; + #else + fname = FindFileData.cFileName; + #endif + if (addPath) - list.push_back(path + "/" + FindFileData.cFileName); + list.push_back(path + "/" + String(fname)); else - list.push_back(FindFileData.cFileName); + list.push_back(String(fname)); } } - while(FindNextFile(hFind, &FindFileData)); + #ifdef HAVE_WINRT + while(FindNextFileW(hFind, &FindFileData)); + #else + while(FindNextFileA(hFind, &FindFileData)); + #endif FindClose(hFind); } @@ -117,10 +173,10 @@ namespace cv strcmp(dirp->d_name, "..") != 0 ) { if (exten.compare("*") == 0) - list.push_back(static_cast(dirp->d_name)); + list.push_back(static_cast(dirp->d_name)); else - if (std::string(dirp->d_name).find(exten) != std::string::npos) - list.push_back(static_cast(dirp->d_name)); + if (String(dirp->d_name).find(exten) != String::npos) + list.push_back(static_cast(dirp->d_name)); } } closedir(dp); @@ -129,16 +185,16 @@ namespace cv return list; } - std::vector Directory::GetListFilesR ( const std::string& path, const std::string & exten, bool addPath ) + std::vector Directory::GetListFilesR ( const String& path, const String & exten, bool addPath ) { - std::vector list = Directory::GetListFiles(path, exten, addPath); + std::vector list = Directory::GetListFiles(path, exten, addPath); - std::vector dirs = Directory::GetListFolders(path, exten, addPath); + std::vector dirs = Directory::GetListFolders(path, exten, addPath); - std::vector::const_iterator it; + std::vector::const_iterator it; for (it = dirs.begin(); it != dirs.end(); ++it) { - std::vector cl = Directory::GetListFiles(*it, exten, addPath); + std::vector cl = Directory::GetListFiles(*it, exten, addPath); list.insert(list.end(), cl.begin(), cl.end()); } diff --git a/modules/contrib/src/lda.cpp b/modules/contrib/src/lda.cpp index 442d567508..fe60e89237 100644 --- a/modules/contrib/src/lda.cpp +++ b/modules/contrib/src/lda.cpp @@ -42,10 +42,10 @@ static Mat argsort(InputArray _src, bool ascending=true) { Mat src = _src.getMat(); if (src.rows != 1 && src.cols != 1) { - std::string error_message = "Wrong shape of input matrix! Expected a matrix with one row or column."; - CV_Error(CV_StsBadArg, error_message); + String error_message = "Wrong shape of input matrix! Expected a matrix with one row or column."; + CV_Error(Error::StsBadArg, error_message); } - int flags = CV_SORT_EVERY_ROW+(ascending ? CV_SORT_ASCENDING : CV_SORT_DESCENDING); + int flags = SORT_EVERY_ROW | (ascending ? SORT_ASCENDING : SORT_DESCENDING); Mat sorted_indices; sortIdx(src.reshape(1,1),sorted_indices,flags); return sorted_indices; @@ -54,8 +54,8 @@ static Mat argsort(InputArray _src, bool ascending=true) static Mat asRowMatrix(InputArrayOfArrays src, int rtype, double alpha=1, double beta=0) { // make sure the input data is a vector of matrices or vector of vector if(src.kind() != _InputArray::STD_VECTOR_MAT && src.kind() != _InputArray::STD_VECTOR_VECTOR) { - std::string error_message = "The data is expected as InputArray::STD_VECTOR_MAT (a std::vector) or _InputArray::STD_VECTOR_VECTOR (a std::vector< std::vector<...> >)."; - CV_Error(CV_StsBadArg, error_message); + String error_message = "The data is expected as InputArray::STD_VECTOR_MAT (a std::vector) or _InputArray::STD_VECTOR_VECTOR (a std::vector< std::vector<...> >)."; + CV_Error(Error::StsBadArg, error_message); } // number of samples size_t n = src.total(); @@ -70,8 +70,8 @@ static Mat asRowMatrix(InputArrayOfArrays src, int rtype, double alpha=1, double for(int i = 0; i < (int)n; i++) { // make sure data can be reshaped, throw exception if not! if(src.getMat(i).total() != d) { - std::string error_message = format("Wrong number of elements in matrix #%d! Expected %d was %d.", i, (int)d, (int)src.getMat(i).total()); - CV_Error(CV_StsBadArg, error_message); + String error_message = format("Wrong number of elements in matrix #%d! Expected %d was %d.", i, (int)d, (int)src.getMat(i).total()); + CV_Error(Error::StsBadArg, error_message); } // get a hold of the current row Mat xi = data.row(i); @@ -87,7 +87,7 @@ static Mat asRowMatrix(InputArrayOfArrays src, int rtype, double alpha=1, double static void sortMatrixColumnsByIndices(InputArray _src, InputArray _indices, OutputArray _dst) { if(_indices.getMat().type() != CV_32SC1) { - CV_Error(CV_StsUnsupportedFormat, "cv::sortColumnsByIndices only works on integer indices!"); + CV_Error(Error::StsUnsupportedFormat, "cv::sortColumnsByIndices only works on integer indices!"); } Mat src = _src.getMat(); std::vector indices = _indices.getMat(); @@ -178,13 +178,13 @@ Mat subspaceProject(InputArray _W, InputArray _mean, InputArray _src) { int d = src.cols; // make sure the data has the correct shape if(W.rows != d) { - std::string error_message = format("Wrong shapes for given matrices. Was size(src) = (%d,%d), size(W) = (%d,%d).", src.rows, src.cols, W.rows, W.cols); - CV_Error(CV_StsBadArg, error_message); + String error_message = format("Wrong shapes for given matrices. Was size(src) = (%d,%d), size(W) = (%d,%d).", src.rows, src.cols, W.rows, W.cols); + CV_Error(Error::StsBadArg, error_message); } // make sure mean is correct if not empty if(!mean.empty() && (mean.total() != (size_t) d)) { - std::string error_message = format("Wrong mean shape for the given data matrix. Expected %d, but was %d.", d, mean.total()); - CV_Error(CV_StsBadArg, error_message); + String error_message = format("Wrong mean shape for the given data matrix. Expected %d, but was %d.", d, mean.total()); + CV_Error(Error::StsBadArg, error_message); } // create temporary matrices Mat X, Y; @@ -216,13 +216,13 @@ Mat subspaceReconstruct(InputArray _W, InputArray _mean, InputArray _src) int d = src.cols; // make sure the data has the correct shape if(W.cols != d) { - std::string error_message = format("Wrong shapes for given matrices. Was size(src) = (%d,%d), size(W) = (%d,%d).", src.rows, src.cols, W.rows, W.cols); - CV_Error(CV_StsBadArg, error_message); + String error_message = format("Wrong shapes for given matrices. Was size(src) = (%d,%d), size(W) = (%d,%d).", src.rows, src.cols, W.rows, W.cols); + CV_Error(Error::StsBadArg, error_message); } // make sure mean is correct if not empty if(!mean.empty() && (mean.total() != (size_t) W.rows)) { - std::string error_message = format("Wrong mean shape for the given eigenvector matrix. Expected %d, but was %d.", W.cols, mean.total()); - CV_Error(CV_StsBadArg, error_message); + String error_message = format("Wrong mean shape for the given eigenvector matrix. Expected %d, but was %d.", W.cols, mean.total()); + CV_Error(Error::StsBadArg, error_message); } // initalize temporary matrices Mat X, Y; @@ -936,20 +936,20 @@ public: //------------------------------------------------------------------------------ // Linear Discriminant Analysis implementation //------------------------------------------------------------------------------ -void LDA::save(const std::string& filename) const { +void LDA::save(const String& filename) const { FileStorage fs(filename, FileStorage::WRITE); if (!fs.isOpened()) { - CV_Error(CV_StsError, "File can't be opened for writing!"); + CV_Error(Error::StsError, "File can't be opened for writing!"); } this->save(fs); fs.release(); } // Deserializes this object from a given filename. -void LDA::load(const std::string& filename) { +void LDA::load(const String& filename) { FileStorage fs(filename, FileStorage::READ); if (!fs.isOpened()) - CV_Error(CV_StsError, "File can't be opened for writing!"); + CV_Error(Error::StsError, "File can't be opened for writing!"); this->load(fs); fs.release(); } @@ -1001,13 +1001,13 @@ void LDA::lda(InputArrayOfArrays _src, InputArray _lbls) { // we can't do a LDA on one class, what do you // want to separate from each other then? if(C == 1) { - std::string error_message = "At least two classes are needed to perform a LDA. Reason: Only one class was given!"; - CV_Error(CV_StsBadArg, error_message); + String error_message = "At least two classes are needed to perform a LDA. Reason: Only one class was given!"; + CV_Error(Error::StsBadArg, error_message); } // throw error if less labels, than samples if (labels.size() != static_cast(N)) { - std::string error_message = format("The number of samples must equal the number of labels. Given %d labels, %d samples. ", labels.size(), N); - CV_Error(CV_StsBadArg, error_message); + String error_message = format("The number of samples must equal the number of labels. Given %d labels, %d samples. ", labels.size(), N); + CV_Error(Error::StsBadArg, error_message); } // warn if within-classes scatter matrix becomes singular if (N < D) { @@ -1089,8 +1089,8 @@ void LDA::compute(InputArrayOfArrays _src, InputArray _lbls) { lda(_src.getMat(), _lbls); break; default: - std::string error_message= format("InputArray Datatype %d is not supported.", _src.kind()); - CV_Error(CV_StsBadArg, error_message); + String error_message= format("InputArray Datatype %d is not supported.", _src.kind()); + CV_Error(Error::StsBadArg, error_message); break; } } @@ -1106,4 +1106,3 @@ Mat LDA::reconstruct(InputArray src) { } } - diff --git a/modules/contrib/src/logpolar_bsm.cpp b/modules/contrib/src/logpolar_bsm.cpp index 70c7437bbe..8327b0a2da 100644 --- a/modules/contrib/src/logpolar_bsm.cpp +++ b/modules/contrib/src/logpolar_bsm.cpp @@ -649,4 +649,3 @@ LogPolar_Adjacent::~LogPolar_Adjacent() } } - diff --git a/modules/contrib/src/octree.cpp b/modules/contrib/src/octree.cpp index 80d2564945..b612372753 100644 --- a/modules/contrib/src/octree.cpp +++ b/modules/contrib/src/octree.cpp @@ -258,7 +258,7 @@ namespace cv void Octree::buildTree(const std::vector& points3d, int maxLevels, int _minPoints) { - assert((size_t)maxLevels * 8 < MAX_STACK_SIZE); + CV_Assert((size_t)maxLevels * 8 < MAX_STACK_SIZE); points.resize(points3d.size()); std::copy(points3d.begin(), points3d.end(), points.begin()); minPoints = _minPoints; diff --git a/modules/contrib/src/precomp.cpp b/modules/contrib/src/precomp.cpp deleted file mode 100644 index 3e0ec42de9..0000000000 --- a/modules/contrib/src/precomp.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/*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. -// -// -// Intel License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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 "precomp.hpp" - -/* End of file. */ diff --git a/modules/contrib/src/precomp.hpp b/modules/contrib/src/precomp.hpp index 7819148ddc..09ffd086ce 100644 --- a/modules/contrib/src/precomp.hpp +++ b/modules/contrib/src/precomp.hpp @@ -43,16 +43,13 @@ #ifndef __OPENCV_PRECOMP_H__ #define __OPENCV_PRECOMP_H__ -#ifdef HAVE_CVCONFIG_H -#include "cvconfig.h" -#endif - #include "opencv2/contrib.hpp" #include "opencv2/features2d.hpp" #include "opencv2/objdetect.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/imgproc/imgproc_c.h" -#include "opencv2/core/internal.hpp" +#include "opencv2/core/utility.hpp" + +#include "opencv2/core/private.hpp" namespace cv { diff --git a/modules/contrib/src/retina.cpp b/modules/contrib/src/retina.cpp deleted file mode 100644 index 1464896871..0000000000 --- a/modules/contrib/src/retina.cpp +++ /dev/null @@ -1,463 +0,0 @@ -/*#****************************************************************************** - ** 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. - ** - ** - ** HVStools : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. - ** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. - ** - ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) - ** - ** Creation - enhancement process 2007-2011 - ** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France - ** - ** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr). - ** Refer to the following research paper for more information: - ** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 - ** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book: - ** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. - ** - ** The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author : - ** _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper: - ** ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 - ** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. - ** ====> more informations in the above cited Jeanny Heraults's book. - ** - ** License Agreement - ** For Open Source Computer Vision Library - ** - ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. - ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. - ** - ** For Human Visual System tools (hvstools) - ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: - ** - ** * Redistributions of source code must retain the above copyright notice, - ** this list of conditions and the following disclaimer. - ** - ** * Redistributions 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. - *******************************************************************************/ - -/* - * Retina.cpp - * - * Created on: Jul 19, 2011 - * Author: Alexandre Benoit - */ -#include "precomp.hpp" -#include "retinafilter.hpp" -#include - -namespace cv -{ - -Retina::Retina(const cv::Size inputSz) -{ - _retinaFilter = 0; - _init(inputSz, true, RETINA_COLOR_BAYER, false); -} - -Retina::Retina(const cv::Size inputSz, const bool colorMode, RETINA_COLORSAMPLINGMETHOD colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght) -{ - _retinaFilter = 0; - _init(inputSz, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght); -}; - -Retina::~Retina() -{ - if (_retinaFilter) - delete _retinaFilter; -} - -/** -* retreive retina input buffer size -*/ -Size Retina::inputSize(){return cv::Size(_retinaFilter->getInputNBcolumns(), _retinaFilter->getInputNBrows());} - -/** -* retreive retina output buffer size -*/ -Size Retina::outputSize(){return cv::Size(_retinaFilter->getOutputNBcolumns(), _retinaFilter->getOutputNBrows());} - - -void Retina::setColorSaturation(const bool saturateColors, const float colorSaturationValue) -{ - _retinaFilter->setColorSaturation(saturateColors, colorSaturationValue); -} - -struct Retina::RetinaParameters Retina::getParameters(){return _retinaParameters;} - - -void Retina::setup(std::string retinaParameterFile, const bool applyDefaultSetupOnFailure) -{ - try - { - // opening retinaParameterFile in read mode - cv::FileStorage fs(retinaParameterFile, cv::FileStorage::READ); - setup(fs, applyDefaultSetupOnFailure); - }catch(Exception &e) - { - std::cout<<"Retina::setup: wrong/unappropriate xml parameter file : error report :`n=>"< keeping current parameters"<>_retinaParameters.OPLandIplParvo.colorMode; - currFn["normaliseOutput"]>>_retinaParameters.OPLandIplParvo.normaliseOutput; - currFn["photoreceptorsLocalAdaptationSensitivity"]>>_retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity; - currFn["photoreceptorsTemporalConstant"]>>_retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant; - currFn["photoreceptorsSpatialConstant"]>>_retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant; - currFn["horizontalCellsGain"]>>_retinaParameters.OPLandIplParvo.horizontalCellsGain; - currFn["hcellsTemporalConstant"]>>_retinaParameters.OPLandIplParvo.hcellsTemporalConstant; - currFn["hcellsSpatialConstant"]>>_retinaParameters.OPLandIplParvo.hcellsSpatialConstant; - currFn["ganglionCellsSensitivity"]>>_retinaParameters.OPLandIplParvo.ganglionCellsSensitivity; - setupOPLandIPLParvoChannel(_retinaParameters.OPLandIplParvo.colorMode, _retinaParameters.OPLandIplParvo.normaliseOutput, _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity, _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant, _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant, _retinaParameters.OPLandIplParvo.horizontalCellsGain, _retinaParameters.OPLandIplParvo.hcellsTemporalConstant, _retinaParameters.OPLandIplParvo.hcellsSpatialConstant, _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity); - - // init retina IPL magno setup... update at the same time the parameters structure and the retina core - currFn=rootFn["IPLmagno"]; - currFn["normaliseOutput"]>>_retinaParameters.IplMagno.normaliseOutput; - currFn["parasolCells_beta"]>>_retinaParameters.IplMagno.parasolCells_beta; - currFn["parasolCells_tau"]>>_retinaParameters.IplMagno.parasolCells_tau; - currFn["parasolCells_k"]>>_retinaParameters.IplMagno.parasolCells_k; - currFn["amacrinCellsTemporalCutFrequency"]>>_retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency; - currFn["V0CompressionParameter"]>>_retinaParameters.IplMagno.V0CompressionParameter; - currFn["localAdaptintegration_tau"]>>_retinaParameters.IplMagno.localAdaptintegration_tau; - currFn["localAdaptintegration_k"]>>_retinaParameters.IplMagno.localAdaptintegration_k; - - setupIPLMagnoChannel(_retinaParameters.IplMagno.normaliseOutput, _retinaParameters.IplMagno.parasolCells_beta, _retinaParameters.IplMagno.parasolCells_tau, _retinaParameters.IplMagno.parasolCells_k, _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency,_retinaParameters.IplMagno.V0CompressionParameter, _retinaParameters.IplMagno.localAdaptintegration_tau, _retinaParameters.IplMagno.localAdaptintegration_k); - - }catch(Exception &e) - { - std::cout<<"Retina::setup: resetting retina with default parameters"<"< keeping current parameters"< colorMode : " << _retinaParameters.OPLandIplParvo.colorMode - << "\n==> normalizeParvoOutput :" << _retinaParameters.OPLandIplParvo.normaliseOutput - << "\n==> photoreceptorsLocalAdaptationSensitivity : " << _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity - << "\n==> photoreceptorsTemporalConstant : " << _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant - << "\n==> photoreceptorsSpatialConstant : " << _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant - << "\n==> horizontalCellsGain : " << _retinaParameters.OPLandIplParvo.horizontalCellsGain - << "\n==> hcellsTemporalConstant : " << _retinaParameters.OPLandIplParvo.hcellsTemporalConstant - << "\n==> hcellsSpatialConstant : " << _retinaParameters.OPLandIplParvo.hcellsSpatialConstant - << "\n==> parvoGanglionCellsSensitivity : " << _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity - <<"}\n"; - - // displaying IPL magno setup - outmessage<<"Current Retina instance setup :" - <<"\nIPLmagno"<<"{" - << "\n==> normaliseOutput : " << _retinaParameters.IplMagno.normaliseOutput - << "\n==> parasolCells_beta : " << _retinaParameters.IplMagno.parasolCells_beta - << "\n==> parasolCells_tau : " << _retinaParameters.IplMagno.parasolCells_tau - << "\n==> parasolCells_k : " << _retinaParameters.IplMagno.parasolCells_k - << "\n==> amacrinCellsTemporalCutFrequency : " << _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency - << "\n==> V0CompressionParameter : " << _retinaParameters.IplMagno.V0CompressionParameter - << "\n==> localAdaptintegration_tau : " << _retinaParameters.IplMagno.localAdaptintegration_tau - << "\n==> localAdaptintegration_k : " << _retinaParameters.IplMagno.localAdaptintegration_k - <<"}"; - return outmessage.str(); -} - -void Retina::write( std::string fs ) const -{ - FileStorage parametersSaveFile(fs, cv::FileStorage::WRITE ); - write(parametersSaveFile); -} - -void Retina::write( FileStorage& fs ) const -{ - if (!fs.isOpened()) - return; // basic error case - fs<<"OPLandIPLparvo"<<"{"; - fs << "colorMode" << _retinaParameters.OPLandIplParvo.colorMode; - fs << "normaliseOutput" << _retinaParameters.OPLandIplParvo.normaliseOutput; - fs << "photoreceptorsLocalAdaptationSensitivity" << _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity; - fs << "photoreceptorsTemporalConstant" << _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant; - fs << "photoreceptorsSpatialConstant" << _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant; - fs << "horizontalCellsGain" << _retinaParameters.OPLandIplParvo.horizontalCellsGain; - fs << "hcellsTemporalConstant" << _retinaParameters.OPLandIplParvo.hcellsTemporalConstant; - fs << "hcellsSpatialConstant" << _retinaParameters.OPLandIplParvo.hcellsSpatialConstant; - fs << "ganglionCellsSensitivity" << _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity; - fs << "}"; - fs<<"IPLmagno"<<"{"; - fs << "normaliseOutput" << _retinaParameters.IplMagno.normaliseOutput; - fs << "parasolCells_beta" << _retinaParameters.IplMagno.parasolCells_beta; - fs << "parasolCells_tau" << _retinaParameters.IplMagno.parasolCells_tau; - fs << "parasolCells_k" << _retinaParameters.IplMagno.parasolCells_k; - fs << "amacrinCellsTemporalCutFrequency" << _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency; - fs << "V0CompressionParameter" << _retinaParameters.IplMagno.V0CompressionParameter; - fs << "localAdaptintegration_tau" << _retinaParameters.IplMagno.localAdaptintegration_tau; - fs << "localAdaptintegration_k" << _retinaParameters.IplMagno.localAdaptintegration_k; - fs<<"}"; -} - -void Retina::setupOPLandIPLParvoChannel(const bool colorMode, const bool normaliseOutput, const float photoreceptorsLocalAdaptationSensitivity, const float photoreceptorsTemporalConstant, const float photoreceptorsSpatialConstant, const float horizontalCellsGain, const float HcellsTemporalConstant, const float HcellsSpatialConstant, const float ganglionCellsSensitivity) -{ - // retina core parameters setup - _retinaFilter->setColorMode(colorMode); - _retinaFilter->setPhotoreceptorsLocalAdaptationSensitivity(photoreceptorsLocalAdaptationSensitivity); - _retinaFilter->setOPLandParvoParameters(0, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, HcellsTemporalConstant, HcellsSpatialConstant, ganglionCellsSensitivity); - _retinaFilter->setParvoGanglionCellsLocalAdaptationSensitivity(ganglionCellsSensitivity); - _retinaFilter->activateNormalizeParvoOutput_0_maxOutputValue(normaliseOutput); - - // update parameters struture - - _retinaParameters.OPLandIplParvo.colorMode = colorMode; - _retinaParameters.OPLandIplParvo.normaliseOutput = normaliseOutput; - _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity = photoreceptorsLocalAdaptationSensitivity; - _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant = photoreceptorsTemporalConstant; - _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant = photoreceptorsSpatialConstant; - _retinaParameters.OPLandIplParvo.horizontalCellsGain = horizontalCellsGain; - _retinaParameters.OPLandIplParvo.hcellsTemporalConstant = HcellsTemporalConstant; - _retinaParameters.OPLandIplParvo.hcellsSpatialConstant = HcellsSpatialConstant; - _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity = ganglionCellsSensitivity; - -} - -void Retina::setupIPLMagnoChannel(const bool normaliseOutput, const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float V0CompressionParameter, const float localAdaptintegration_tau, const float localAdaptintegration_k) -{ - - _retinaFilter->setMagnoCoefficientsTable(parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter, localAdaptintegration_tau, localAdaptintegration_k); - _retinaFilter->activateNormalizeMagnoOutput_0_maxOutputValue(normaliseOutput); - - // update parameters struture - _retinaParameters.IplMagno.normaliseOutput = normaliseOutput; - _retinaParameters.IplMagno.parasolCells_beta = parasolCells_beta; - _retinaParameters.IplMagno.parasolCells_tau = parasolCells_tau; - _retinaParameters.IplMagno.parasolCells_k = parasolCells_k; - _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency = amacrinCellsTemporalCutFrequency; - _retinaParameters.IplMagno.V0CompressionParameter = V0CompressionParameter; - _retinaParameters.IplMagno.localAdaptintegration_tau = localAdaptintegration_tau; - _retinaParameters.IplMagno.localAdaptintegration_k = localAdaptintegration_k; -} - -void Retina::run(const cv::Mat &inputMatToConvert) -{ - // first convert input image to the compatible format : std::valarray - const bool colorMode = _convertCvMat2ValarrayBuffer(inputMatToConvert, _inputBuffer); - // process the retina - if (!_retinaFilter->runFilter(_inputBuffer, colorMode, false, _retinaParameters.OPLandIplParvo.colorMode && colorMode, false)) - throw cv::Exception(-1, "Retina cannot be applied, wrong input buffer size", "Retina::run", "Retina.h", 0); -} - -void Retina::getParvo(cv::Mat &retinaOutput_parvo) -{ - if (_retinaFilter->getColorMode()) - { - // reallocate output buffer (if necessary) - _convertValarrayBuffer2cvMat(_retinaFilter->getColorOutput(), _retinaFilter->getOutputNBrows(), _retinaFilter->getOutputNBcolumns(), true, retinaOutput_parvo); - }else - { - // reallocate output buffer (if necessary) - _convertValarrayBuffer2cvMat(_retinaFilter->getContours(), _retinaFilter->getOutputNBrows(), _retinaFilter->getOutputNBcolumns(), false, retinaOutput_parvo); - } - //retinaOutput_parvo/=255.0; -} -void Retina::getMagno(cv::Mat &retinaOutput_magno) -{ - // reallocate output buffer (if necessary) - _convertValarrayBuffer2cvMat(_retinaFilter->getMovingContours(), _retinaFilter->getOutputNBrows(), _retinaFilter->getOutputNBcolumns(), false, retinaOutput_magno); - //retinaOutput_magno/=255.0; -} - -// original API level data accessors : copy buffers if size matches -void Retina::getMagno(std::valarray &magnoOutputBufferCopy){if (magnoOutputBufferCopy.size()==_retinaFilter->getMovingContours().size()) magnoOutputBufferCopy = _retinaFilter->getMovingContours();} -void Retina::getParvo(std::valarray &parvoOutputBufferCopy){if (parvoOutputBufferCopy.size()==_retinaFilter->getContours().size()) parvoOutputBufferCopy = _retinaFilter->getContours();} -// original API level data accessors : get buffers addresses... -const std::valarray & Retina::getMagno() const {return _retinaFilter->getMovingContours();} -const std::valarray & Retina::getParvo() const {if (_retinaFilter->getColorMode())return _retinaFilter->getColorOutput(); /* implicite else */return _retinaFilter->getContours();} - -// private method called by constructirs -void Retina::_init(const cv::Size inputSz, const bool colorMode, RETINA_COLORSAMPLINGMETHOD colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght) -{ - // basic error check - if (inputSz.height*inputSz.width <= 0) - throw cv::Exception(-1, "Bad retina size setup : size height and with must be superior to zero", "Retina::setup", "Retina.h", 0); - - unsigned int nbPixels=inputSz.height*inputSz.width; - // resize buffers if size does not match - _inputBuffer.resize(nbPixels*3); // buffer supports gray images but also 3 channels color buffers... (larger is better...) - - // allocate the retina model - if (_retinaFilter) - delete _retinaFilter; - _retinaFilter = new RetinaFilter(inputSz.height, inputSz.width, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght); - - // prepare the default parameter XML file with default setup - setup(_retinaParameters); - - // init retina - _retinaFilter->clearAllBuffers(); - - // report current configuration - std::cout< &grayMatrixToConvert, const unsigned int nbRows, const unsigned int nbColumns, const bool colorMode, cv::Mat &outBuffer) -{ - // fill output buffer with the valarray buffer - const float *valarrayPTR=get_data(grayMatrixToConvert); - if (!colorMode) - { - outBuffer.create(cv::Size(nbColumns, nbRows), CV_8U); - for (unsigned int i=0;i(pixel)=(unsigned char)*(valarrayPTR++); - } - } - }else - { - const unsigned int doubleNBpixels=_retinaFilter->getOutputNBpixels()*2; - outBuffer.create(cv::Size(nbColumns, nbRows), CV_8UC3); - for (unsigned int i=0;igetOutputNBpixels()); - pixelValues[0]=(unsigned char)*(valarrayPTR+doubleNBpixels); - - outBuffer.at(pixel)=pixelValues; - } - } - } -} - -bool Retina::_convertCvMat2ValarrayBuffer(const cv::Mat inputMatToConvert, std::valarray &outputValarrayMatrix) -{ - // first check input consistency - if (inputMatToConvert.empty()) - throw cv::Exception(-1, "Retina cannot be applied, input buffer is empty", "Retina::run", "Retina.h", 0); - - // retreive color mode from image input - int imageNumberOfChannels = inputMatToConvert.channels(); - - // convert to float AND fill the valarray buffer - typedef float T; // define here the target pixel format, here, float - const int dsttype = DataType::depth; // output buffer is float format - - - if(imageNumberOfChannels==4) - { - // create a cv::Mat table (for RGBA planes) - cv::Mat planes[4] = - { - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[_retinaFilter->getInputNBpixels()*2]), - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[_retinaFilter->getInputNBpixels()]), - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[0]) - }; - planes[3] = cv::Mat(inputMatToConvert.size(), dsttype); // last channel (alpha) does not point on the valarray (not usefull in our case) - // split color cv::Mat in 4 planes... it fills valarray directely - cv::split(cv::Mat_ >(inputMatToConvert), planes); - } - else if (imageNumberOfChannels==3) - { - // create a cv::Mat table (for RGB planes) - cv::Mat planes[] = - { - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[_retinaFilter->getInputNBpixels()*2]), - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[_retinaFilter->getInputNBpixels()]), - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[0]) - }; - // split color cv::Mat in 3 planes... it fills valarray directely - cv::split(cv::Mat_ >(inputMatToConvert), planes); - } - else if(imageNumberOfChannels==1) - { - // create a cv::Mat header for the valarray - cv::Mat dst(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[0]); - inputMatToConvert.convertTo(dst, dsttype); - } - else - CV_Error(CV_StsUnsupportedFormat, "input image must be single channel (gray levels), bgr format (color) or bgra (color with transparency which won't be considered"); - - return imageNumberOfChannels>1; // return bool : false for gray level image processing, true for color mode -} - -void Retina::clearBuffers() {_retinaFilter->clearAllBuffers();} - -void Retina::activateMovingContoursProcessing(const bool activate){_retinaFilter->activateMovingContoursProcessing(activate);} - -void Retina::activateContoursProcessing(const bool activate){_retinaFilter->activateContoursProcessing(activate);} - -} // end of namespace cv - diff --git a/modules/contrib/src/rgbdodometry.cpp b/modules/contrib/src/rgbdodometry.cpp index 1fa800b0ae..6f86f17ec4 100644 --- a/modules/contrib/src/rgbdodometry.cpp +++ b/modules/contrib/src/rgbdodometry.cpp @@ -54,7 +54,6 @@ #include #include -#include "opencv2/core/internal.hpp" #if defined(HAVE_EIGEN) && EIGEN_WORLD_VERSION == 3 # ifdef ANDROID template Scalar log2(Scalar v) { return std::log(v)/std::log(Scalar(2)); } @@ -423,7 +422,7 @@ bool computeKsi( int transformType, computeCFuncPtr = computeC_Translation; } else - CV_Error( CV_StsBadFlag, "Unsupported value of transformation type flag."); + CV_Error(Error::StsBadFlag, "Unsupported value of transformation type flag."); Mat C( correspsCount, Cwidth, CV_64FC1 ); Mat dI_dt( correspsCount, 1, CV_64FC1 ); diff --git a/modules/contrib/src/spinimages.cpp b/modules/contrib/src/spinimages.cpp index 7f7a8ad63f..4e58472bfb 100644 --- a/modules/contrib/src/spinimages.cpp +++ b/modules/contrib/src/spinimages.cpp @@ -56,24 +56,24 @@ namespace { const static Scalar colors[] = { - CV_RGB(255, 0, 0), - CV_RGB( 0, 255, 0), - CV_RGB( 0, 0, 255), - CV_RGB(255, 255, 0), - CV_RGB(255, 0, 255), - CV_RGB( 0, 255, 255), - CV_RGB(255, 127, 127), - CV_RGB(127, 127, 255), - CV_RGB(127, 255, 127), - CV_RGB(255, 255, 127), - CV_RGB(127, 255, 255), - CV_RGB(255, 127, 255), - CV_RGB(127, 0, 0), - CV_RGB( 0, 127, 0), - CV_RGB( 0, 0, 127), - CV_RGB(127, 127, 0), - CV_RGB(127, 0, 127), - CV_RGB( 0, 127, 127) + Scalar(255, 0, 0), + Scalar( 0, 255, 0), + Scalar( 0, 0, 255), + Scalar(255, 255, 0), + Scalar(255, 0, 255), + Scalar( 0, 255, 255), + Scalar(255, 127, 127), + Scalar(127, 127, 255), + Scalar(127, 255, 127), + Scalar(255, 255, 127), + Scalar(127, 255, 255), + Scalar(255, 127, 255), + Scalar(127, 0, 0), + Scalar( 0, 127, 0), + Scalar( 0, 0, 127), + Scalar(127, 127, 0), + Scalar(127, 0, 127), + Scalar( 0, 127, 127) }; size_t colors_mum = sizeof(colors)/sizeof(colors[0]); @@ -199,7 +199,7 @@ void convertTransformMatrix(const float* matrix, float* sseMatrix) inline __m128 transformSSE(const __m128* matrix, const __m128& in) { - assert(((size_t)matrix & 15) == 0); + CV_DbgAssert(((size_t)matrix & 15) == 0); __m128 a0 = _mm_mul_ps(_mm_load_ps((float*)(matrix+0)), _mm_shuffle_ps(in,in,_MM_SHUFFLE(0,0,0,0))); __m128 a1 = _mm_mul_ps(_mm_load_ps((float*)(matrix+1)), _mm_shuffle_ps(in,in,_MM_SHUFFLE(1,1,1,1))); __m128 a2 = _mm_mul_ps(_mm_load_ps((float*)(matrix+2)), _mm_shuffle_ps(in,in,_MM_SHUFFLE(2,2,2,2))); @@ -221,8 +221,8 @@ void computeSpinImages( const Octree& Octree, const std::vector& points float pixelsPerMeter = 1.f / binSize; float support = imageWidth * binSize; - assert(normals.size() == points.size()); - assert(mask.size() == points.size()); + CV_Assert(normals.size() == points.size()); + CV_Assert(mask.size() == points.size()); size_t points_size = points.size(); mask.resize(points_size); @@ -250,7 +250,7 @@ void computeSpinImages( const Octree& Octree, const std::vector& points if (mask[i] == 0) continue; - int t = cvGetThreadNum(); + int t = getThreadNum(); std::vector& pointsInSphere = pointsInSpherePool[t]; const Point3f& center = points[i]; @@ -289,7 +289,7 @@ void computeSpinImages( const Octree& Octree, const std::vector& points __m128 ppm4 = _mm_set1_ps(pixelsPerMeter); __m128i height4m1 = _mm_set1_epi32(spinImage.rows-1); __m128i width4m1 = _mm_set1_epi32(spinImage.cols-1); - assert( spinImage.step <= 0xffff ); + CV_Assert( spinImage.step <= 0xffff ); __m128i step4 = _mm_set1_epi16((short)step); __m128i zero4 = _mm_setzero_si128(); __m128i one4i = _mm_set1_epi32(1); @@ -472,7 +472,7 @@ float cv::Mesh3D::estimateResolution(float /*tryRatio*/) return resolution = (float)dist[ dist.size() / 2 ]; #else - CV_Error(CV_StsNotImplemented, ""); + CV_Error(Error::StsNotImplemented, ""); return 1.f; #endif } @@ -494,7 +494,7 @@ void cv::Mesh3D::computeNormals(const std::vector& subset, float normalRadi ::computeNormals(octree, vtx, normals, mask, normalRadius, minNeighbors); } -void cv::Mesh3D::writeAsVrml(const std::string& file, const std::vector& _colors) const +void cv::Mesh3D::writeAsVrml(const String& file, const std::vector& _colors) const { std::ofstream ofs(file.c_str()); @@ -686,16 +686,15 @@ inline float cv::SpinImageModel::groupingCreteria(const Point3f& pointScene1, co } -cv::SpinImageModel::SpinImageModel(const Mesh3D& _mesh) : mesh(_mesh) , out(0) +cv::SpinImageModel::SpinImageModel(const Mesh3D& _mesh) : mesh(_mesh) { if (mesh.vtx.empty()) throw Mesh3D::EmptyMeshException(); defaultParams(); } -cv::SpinImageModel::SpinImageModel() : out(0) { defaultParams(); } -cv::SpinImageModel::~SpinImageModel() {} -void cv::SpinImageModel::setLogger(std::ostream* log) { out = log; } +cv::SpinImageModel::SpinImageModel() { defaultParams(); } +cv::SpinImageModel::~SpinImageModel() {} void cv::SpinImageModel::defaultParams() { @@ -756,7 +755,7 @@ Mat cv::SpinImageModel::packRandomScaledSpins(bool separateScale, size_t xCount, int sz = spins.front().cols; Mat result((int)(yCount * sz + (yCount - 1)), (int)(xCount * sz + (xCount - 1)), CV_8UC3); - result = colors[(static_cast(cvGetTickCount()/cvGetTickFrequency())/1000) % colors_mum]; + result = colors[(static_cast(getTickCount()/getTickFrequency())/1000) % colors_mum]; int pos = 0; for(int y = 0; y < (int)yCount; ++y) @@ -770,7 +769,7 @@ Mat cv::SpinImageModel::packRandomScaledSpins(bool separateScale, size_t xCount, int endx = (x + 1) * sz + x; Mat color; - cvtColor(spins[pos++], color, CV_GRAY2BGR); + cvtColor(spins[pos++], color, COLOR_GRAY2BGR); Mat roi = result(Range(starty, endy), Range(startx, endx)); color.copyTo(roi); } @@ -809,7 +808,7 @@ void cv::SpinImageModel::selectRandomSubset(float ratio) left[pos] = left.back(); left.resize(left.size() - 1); } - sort(subset, std::less()); + std::sort(subset.begin(), subset.end()); } } @@ -928,7 +927,7 @@ void cv::SpinImageModel::matchSpinToModel(const Mat& spin, std::vector& ind if(total < 5) return; - sort(cleanCorrs, std::less()); + std::sort(cleanCorrs.begin(), cleanCorrs.end()); float lower_fourth = cleanCorrs[(1 * total) / 4 - 1]; float upper_fourth = cleanCorrs[(3 * total) / 4 - 0]; @@ -1016,7 +1015,7 @@ private: std::vector nonzero(model.spinImages.rows); for(int i = 0; i < model.spinImages.rows; ++i) nonzero[i] = countNonZero(model.spinImages.row(i)); - sort(nonzero, std::less()); + std::sort(nonzero.begin(), nonzero.end()); model.lambda = static_cast( nonzero[ nonzero.size()/2 ] ) / 2; } @@ -1030,12 +1029,8 @@ private: matchSpinToModel(scene.spinImages.row(i), indeces, coeffs); for(size_t t = 0; t < indeces.size(); ++t) allMatches.push_back(Match(i, indeces[t], coeffs[t])); - - if (out) if (i % 100 == 0) *out << "Comparing scene spinimage " << i << " of " << scene.spinImages.rows << std::endl; } corr_timer.stop(); - if (out) *out << "Spin correlation time = " << corr_timer << std::endl; - if (out) *out << "Matches number = " << allMatches.size() << std::endl; if(allMatches.empty()) return; @@ -1046,7 +1041,6 @@ private: allMatches.erase( remove_if(allMatches.begin(), allMatches.end(), bind2nd(std::less(), maxMeasure * fraction)), allMatches.end()); - if (out) *out << "Matches number [filtered by similarity measure] = " << allMatches.size() << std::endl; int matchesSize = (int)allMatches.size(); if(matchesSize == 0) @@ -1095,15 +1089,12 @@ private: allMatches.erase( std::remove_if(allMatches.begin(), allMatches.end(), std::bind2nd(std::equal_to(), infinity)), allMatches.end()); - if (out) *out << "Matches number [filtered by geometric consistency] = " << allMatches.size() << std::endl; matchesSize = (int)allMatches.size(); if(matchesSize == 0) return; - if (out) *out << "grouping ..." << std::endl; - Mat groupingMat((int)matchesSize, (int)matchesSize, CV_32F); groupingMat = Scalar(0); @@ -1151,8 +1142,6 @@ private: for(int g = 0; g < matchesSize; ++g) { - if (out) if (g % 100 == 0) *out << "G = " << g << std::endl; - group_t left = allMatchesInds; group_t group; @@ -1201,16 +1190,16 @@ private: cv::TickMeter::TickMeter() { reset(); } int64 cv::TickMeter::getTimeTicks() const { return sumTime; } -double cv::TickMeter::getTimeMicro() const { return (double)getTimeTicks()/cvGetTickFrequency(); } +double cv::TickMeter::getTimeMicro() const { return (double)getTimeTicks()/getTickFrequency(); } double cv::TickMeter::getTimeMilli() const { return getTimeMicro()*1e-3; } double cv::TickMeter::getTimeSec() const { return getTimeMilli()*1e-3; } int64 cv::TickMeter::getCounter() const { return counter; } void cv::TickMeter::reset() {startTime = 0; sumTime = 0; counter = 0; } -void cv::TickMeter::start(){ startTime = cvGetTickCount(); } +void cv::TickMeter::start(){ startTime = getTickCount(); } void cv::TickMeter::stop() { - int64 time = cvGetTickCount(); + int64 time = getTickCount(); if ( startTime == 0 ) return; @@ -1220,4 +1209,4 @@ void cv::TickMeter::stop() startTime = 0; } -std::ostream& cv::operator<<(std::ostream& out, const TickMeter& tm){ return out << tm.getTimeSec() << "sec"; } +//std::ostream& cv::operator<<(std::ostream& out, const TickMeter& tm){ return out << tm.getTimeSec() << "sec"; } diff --git a/modules/contrib/src/stereovar.cpp b/modules/contrib/src/stereovar.cpp index a825ad8d82..b2141b1f15 100644 --- a/modules/contrib/src/stereovar.cpp +++ b/modules/contrib/src/stereovar.cpp @@ -239,8 +239,8 @@ void StereoVar::VariationalSolver(Mat &I1, Mat &I2, Mat &I2x, Mat &u, int level) void StereoVar::VCycle_MyFAS(Mat &I1, Mat &I2, Mat &I2x, Mat &_u, int level) { - CvSize imgSize = _u.size(); - CvSize frmSize = cvSize((int) (imgSize.width * pyrScale + 0.5), (int) (imgSize.height * pyrScale + 0.5)); + Size imgSize = _u.size(); + Size frmSize = Size((int) (imgSize.width * pyrScale + 0.5), (int) (imgSize.height * pyrScale + 0.5)); Mat I1_h, I2_h, I2x_h, u_h, U, U_h; //PRE relaxation @@ -285,7 +285,7 @@ void StereoVar::VCycle_MyFAS(Mat &I1, Mat &I2, Mat &I2x, Mat &_u, int level) void StereoVar::FMG(Mat &I1, Mat &I2, Mat &I2x, Mat &u, int level) { double scale = std::pow(pyrScale, (double) level); - CvSize frmSize = cvSize((int) (u.cols * scale + 0.5), (int) (u.rows * scale + 0.5)); + Size frmSize = Size((int) (u.cols * scale + 0.5), (int) (u.rows * scale + 0.5)); Mat I1_h, I2_h, I2x_h, u_h; //scaling DOWN @@ -350,7 +350,7 @@ void StereoVar::autoParams() void StereoVar::operator ()( const Mat& left, const Mat& right, Mat& disp ) { CV_Assert(left.size() == right.size() && left.type() == right.type()); - CvSize imgSize = left.size(); + Size imgSize = left.size(); int MaxD = MAX(labs(minDisp), labs(maxDisp)); int SignD = 1; if (MIN(minDisp, maxDisp) < 0) SignD = -1; if (minDisp >= maxDisp) {MaxD = 256; SignD = 1;} @@ -367,8 +367,8 @@ void StereoVar::operator ()( const Mat& left, const Mat& right, Mat& disp ) // Preprocessing Mat leftgray, rightgray; if (left.type() != CV_8UC1) { - cvtColor(left, leftgray, CV_BGR2GRAY); - cvtColor(right, rightgray, CV_BGR2GRAY); + cvtColor(left, leftgray, COLOR_BGR2GRAY); + cvtColor(right, rightgray, COLOR_BGR2GRAY); } else { left.copyTo(leftgray); right.copyTo(rightgray); @@ -378,8 +378,8 @@ void StereoVar::operator ()( const Mat& left, const Mat& right, Mat& disp ) equalizeHist(rightgray, rightgray); } if (poly_sigma > 0.0001) { - GaussianBlur(leftgray, leftgray, cvSize(poly_n, poly_n), poly_sigma); - GaussianBlur(rightgray, rightgray, cvSize(poly_n, poly_n), poly_sigma); + GaussianBlur(leftgray, leftgray, Size(poly_n, poly_n), poly_sigma); + GaussianBlur(rightgray, rightgray, Size(poly_n, poly_n), poly_sigma); } if (flags & USE_AUTO_PARAMS) { @@ -408,4 +408,4 @@ void StereoVar::operator ()( const Mat& left, const Mat& right, Mat& disp ) u.release(); } -} // namespace \ No newline at end of file +} // namespace diff --git a/modules/contrib/test/test_precomp.cpp b/modules/contrib/test/test_precomp.cpp deleted file mode 100644 index 5956e13e3e..0000000000 --- a/modules/contrib/test/test_precomp.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "test_precomp.hpp" diff --git a/modules/contrib/test/test_precomp.hpp b/modules/contrib/test/test_precomp.hpp index de9e283ee2..992ff28dfa 100644 --- a/modules/contrib/test/test_precomp.hpp +++ b/modules/contrib/test/test_precomp.hpp @@ -14,4 +14,3 @@ #include #endif - diff --git a/modules/core/CMakeLists.txt b/modules/core/CMakeLists.txt index e538d1acae..b83a591490 100644 --- a/modules/core/CMakeLists.txt +++ b/modules/core/CMakeLists.txt @@ -1,12 +1,24 @@ set(the_description "The Core Functionality") -ocv_add_module(core ${ZLIB_LIBRARIES}) -ocv_module_include_directories(${ZLIB_INCLUDE_DIR} "${OpenCV_SOURCE_DIR}/modules/gpu/include") +ocv_add_module(core ${ZLIB_LIBRARIES} OPTIONAL opencv_cudev) +ocv_module_include_directories(${ZLIB_INCLUDE_DIRS}) -if(HAVE_CUDA) - ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef) +if (HAVE_WINRT) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /ZW /GS /Gm- /AI\"${WINDOWS_SDK_PATH}/References/CommonConfiguration/Neutral\" /AI\"${VISUAL_STUDIO_PATH}/vcpackages\"") endif() -ocv_glob_module_sources(SOURCES "${opencv_core_BINARY_DIR}/version_string.inc") +if(HAVE_CUDA) + ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef -Wenum-compare -Wunused-function) +endif() + +file(GLOB lib_cuda_hdrs "include/opencv2/${name}/cuda/*.hpp" "include/opencv2/${name}/cuda/*.h") +file(GLOB lib_cuda_hdrs_detail "include/opencv2/${name}/cuda/detail/*.hpp" "include/opencv2/${name}/cuda/detail/*.h") + +source_group("Cuda Headers" FILES ${lib_cuda_hdrs}) +source_group("Cuda Headers\\Detail" FILES ${lib_cuda_hdrs_detail}) + +ocv_glob_module_sources(SOURCES "${opencv_core_BINARY_DIR}/version_string.inc" + HEADERS ${lib_cuda_hdrs} ${lib_cuda_hdrs_detail}) + ocv_create_module() ocv_add_precompiled_headers(${the_module}) diff --git a/modules/core/doc/basic_structures.rst b/modules/core/doc/basic_structures.rst index d9cc303315..93e7ca479c 100644 --- a/modules/core/doc/basic_structures.rst +++ b/modules/core/doc/basic_structures.rst @@ -49,6 +49,43 @@ Point\_ ------- .. ocv:class:: Point_ +:: + + template class CV_EXPORTS Point_ + { + public: + typedef _Tp value_type; + + // various constructors + Point_(); + Point_(_Tp _x, _Tp _y); + Point_(const Point_& pt); + Point_(const CvPoint& pt); + Point_(const CvPoint2D32f& pt); + Point_(const Size_<_Tp>& sz); + Point_(const Vec<_Tp, 2>& v); + + Point_& operator = (const Point_& pt); + //! conversion to another data type + template operator Point_<_Tp2>() const; + + //! conversion to the old-style C structures + operator CvPoint() const; + operator CvPoint2D32f() const; + operator Vec<_Tp, 2>() const; + + //! dot product + _Tp dot(const Point_& pt) const; + //! dot product computed in double-precision arithmetics + double ddot(const Point_& pt) const; + //! cross-product + double cross(const Point_& pt) const; + //! checks whether the point is inside the specified rectangle + bool inside(const Rect_<_Tp>& r) const; + + _Tp x, y; //< the point coordinates + }; + Template class for 2D points specified by its coordinates :math:`x` and :math:`y` . @@ -84,6 +121,39 @@ Point3\_ -------- .. ocv:class:: Point3_ +:: + + template class CV_EXPORTS Point3_ + { + public: + typedef _Tp value_type; + + // various constructors + Point3_(); + Point3_(_Tp _x, _Tp _y, _Tp _z); + Point3_(const Point3_& pt); + explicit Point3_(const Point_<_Tp>& pt); + Point3_(const CvPoint3D32f& pt); + Point3_(const Vec<_Tp, 3>& v); + + Point3_& operator = (const Point3_& pt); + //! conversion to another data type + template operator Point3_<_Tp2>() const; + //! conversion to the old-style CvPoint... + operator CvPoint3D32f() const; + //! conversion to cv::Vec<> + operator Vec<_Tp, 3>() const; + + //! dot product + _Tp dot(const Point3_& pt) const; + //! dot product computed in double-precision arithmetics + double ddot(const Point3_& pt) const; + //! cross product of the 2 3D points + Point3_ cross(const Point3_& pt) const; + + _Tp x, y, z; //< the point coordinates + }; + Template class for 3D points specified by its coordinates :math:`x`, :math:`y` and @@ -100,6 +170,35 @@ Size\_ ------ .. ocv:class:: Size_ +:: + + template class CV_EXPORTS Size_ + { + public: + typedef _Tp value_type; + + //! various constructors + Size_(); + Size_(_Tp _width, _Tp _height); + Size_(const Size_& sz); + Size_(const CvSize& sz); + Size_(const CvSize2D32f& sz); + Size_(const Point_<_Tp>& pt); + + Size_& operator = (const Size_& sz); + //! the area (width*height) + _Tp area() const; + + //! conversion of another data type. + template operator Size_<_Tp2>() const; + + //! conversion to the old-style OpenCV types + operator CvSize() const; + operator CvSize2D32f() const; + + _Tp width, height; // the width and the height + }; + Template class for specifying the size of an image or rectangle. The class includes two members called ``width`` and ``height``. The structure can be converted to and from the old OpenCV structures ``CvSize`` and ``CvSize2D32f`` . The same set of arithmetic and comparison operations as for ``Point_`` is available. @@ -113,6 +212,43 @@ Rect\_ ------ .. ocv:class:: Rect_ +:: + + template class CV_EXPORTS Rect_ + { + public: + typedef _Tp value_type; + + //! various constructors + Rect_(); + Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height); + Rect_(const Rect_& r); + Rect_(const CvRect& r); + Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz); + Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2); + + Rect_& operator = ( const Rect_& r ); + //! the top-left corner + Point_<_Tp> tl() const; + //! the bottom-right corner + Point_<_Tp> br() const; + + //! size (width, height) of the rectangle + Size_<_Tp> size() const; + //! area (width*height) of the rectangle + _Tp area() const; + + //! conversion to another data type + template operator Rect_<_Tp2>() const; + //! conversion to the old-style CvRect + operator CvRect() const; + + //! checks whether the rectangle contains the point + bool contains(const Point_<_Tp>& pt) const; + + _Tp x, y, width, height; //< the top-left corner, as well as width and height of the rectangle + }; + Template class for 2D rectangles, described by the following parameters: * Coordinates of the top-left corner. This is a default interpretation of ``Rect_::x`` and ``Rect_::y`` in OpenCV. Though, in your algorithms you may count ``x`` and ``y`` from the bottom-left corner. @@ -171,11 +307,32 @@ RotatedRect ----------- .. ocv:class:: RotatedRect +:: + + class CV_EXPORTS RotatedRect + { + public: + //! various constructors + RotatedRect(); + RotatedRect(const Point2f& center, const Size2f& size, float angle); + RotatedRect(const CvBox2D& box); + + //! returns 4 vertices of the rectangle + void points(Point2f pts[]) const; + //! returns the minimal up-right rectangle containing the rotated rectangle + Rect boundingRect() const; + //! conversion to the old-style CvBox2D structure + operator CvBox2D() const; + + Point2f center; //< the rectangle mass center + Size2f size; //< width and height of the rectangle + float angle; //< the rotation angle. When the angle is 0, 90, 180, 270 etc., the rectangle becomes an up-right rectangle. + }; + The class represents rotated (i.e. not up-right) rectangles on a plane. Each rectangle is specified by the center point (mass center), length of each side (represented by cv::Size2f structure) and the rotation angle in degrees. .. ocv:function:: RotatedRect::RotatedRect() .. ocv:function:: RotatedRect::RotatedRect(const Point2f& center, const Size2f& size, float angle) - .. ocv:function:: RotatedRect::RotatedRect(const CvBox2D& box) :param center: The rectangle mass center. :param size: Width and height of the rectangle. @@ -184,7 +341,6 @@ The class represents rotated (i.e. not up-right) rectangles on a plane. Each rec .. ocv:function:: void RotatedRect::points( Point2f pts[] ) const .. ocv:function:: Rect RotatedRect::boundingRect() const - .. ocv:function:: RotatedRect::operator CvBox2D() const :param pts: The points array for storing rectangle vertices. @@ -219,7 +375,33 @@ TermCriteria ------------ .. ocv:class:: TermCriteria - The class defining termination criteria for iterative algorithms. You can initialize it by default constructor and then override any parameters, or the structure may be fully initialized using the advanced variant of the constructor. +:: + + class CV_EXPORTS TermCriteria + { + public: + enum + { + COUNT=1, //!< the maximum number of iterations or elements to compute + MAX_ITER=COUNT, //!< ditto + EPS=2 //!< the desired accuracy or change in parameters at which the iterative algorithm stops + }; + + //! default constructor + TermCriteria(); + //! full constructor + TermCriteria(int type, int maxCount, double epsilon); + //! conversion from CvTermCriteria + TermCriteria(const CvTermCriteria& criteria); + //! conversion to CvTermCriteria + operator CvTermCriteria() const; + + int type; //!< the type of termination criteria: COUNT, EPS or COUNT + EPS + int maxCount; // the maximum number of iterations/elements + double epsilon; // the desired accuracy + }; + +The class defining termination criteria for iterative algorithms. You can initialize it by default constructor and then override any parameters, or the structure may be fully initialized using the advanced variant of the constructor. TermCriteria::TermCriteria -------------------------- @@ -229,8 +411,6 @@ The constructors. .. ocv:function:: TermCriteria::TermCriteria(int type, int maxCount, double epsilon) -.. ocv:function:: TermCriteria::TermCriteria(const CvTermCriteria& criteria) - :param type: The type of termination criteria: ``TermCriteria::COUNT``, ``TermCriteria::EPS`` or ``TermCriteria::COUNT`` + ``TermCriteria::EPS``. :param maxCount: The maximum number of iterations or elements to compute. @@ -239,11 +419,6 @@ The constructors. :param criteria: Termination criteria in the deprecated ``CvTermCriteria`` format. -TermCriteria::operator CvTermCriteria -------------------------------------- -Converts to the deprecated ``CvTermCriteria`` format. - -.. ocv:function:: TermCriteria::operator CvTermCriteria() const Matx ---- @@ -330,9 +505,36 @@ Scalar\_ -------- .. ocv:class:: Scalar_ -Template class for a 4-element vector derived from Vec. :: +Template class for a 4-element vector derived from Vec. - template class Scalar_ : public Vec<_Tp, 4> { ... }; +:: + + template class CV_EXPORTS Scalar_ : public Vec<_Tp, 4> + { + public: + //! various constructors + Scalar_(); + Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0); + Scalar_(const CvScalar& s); + Scalar_(_Tp v0); + + //! returns a scalar with all elements set to v0 + static Scalar_<_Tp> all(_Tp v0); + //! conversion to the old-style CvScalar + operator CvScalar() const; + + //! conversion to another data type + template operator Scalar_() const; + + //! per-element product + Scalar_<_Tp> mul(const Scalar_<_Tp>& t, double scale=1 ) const; + + // returns (v0, -v1, -v2, -v3) + Scalar_<_Tp> conj() const; + + // returns true iff v1 == v2 == v3 == 0 + bool isReal() const; + }; typedef Scalar_ Scalar; @@ -342,12 +544,21 @@ Range ----- .. ocv:class:: Range -Template class specifying a continuous subsequence (slice) of a sequence. :: +Template class specifying a continuous subsequence (slice) of a sequence. - class Range +:: + + class CV_EXPORTS Range { public: - ... + Range(); + Range(int _start, int _end); + Range(const CvSlice& slice); + int size() const; + bool empty() const; + static Range all(); + operator CvSlice() const; + int start, end; }; @@ -368,187 +579,466 @@ The static method ``Range::all()`` returns a special variable that means "the wh } -.. _Ptr: +KeyPoint +-------- +.. ocv:class:: KeyPoint + + Data structure for salient point detectors. + + .. ocv:member:: Point2f pt + + coordinates of the keypoint + + .. ocv:member:: float size + + diameter of the meaningful keypoint neighborhood + + .. ocv:member:: float angle + + computed orientation of the keypoint (-1 if not applicable). Its possible values are in a range [0,360) degrees. It is measured relative to image coordinate system (y-axis is directed downward), ie in clockwise. + + .. ocv:member:: float response + + the response by which the most strong keypoints have been selected. Can be used for further sorting or subsampling + + .. ocv:member:: int octave + + octave (pyramid layer) from which the keypoint has been extracted + + .. ocv:member:: int class_id + + object id that can be used to clustered keypoints by an object they belong to + +KeyPoint::KeyPoint +------------------ +The keypoint constructors + +.. ocv:function:: KeyPoint::KeyPoint() + +.. ocv:function:: KeyPoint::KeyPoint(Point2f _pt, float _size, float _angle=-1, float _response=0, int _octave=0, int _class_id=-1) + +.. ocv:function:: KeyPoint::KeyPoint(float x, float y, float _size, float _angle=-1, float _response=0, int _octave=0, int _class_id=-1) + +.. ocv:pyfunction:: cv2.KeyPoint([x, y, _size[, _angle[, _response[, _octave[, _class_id]]]]]) -> + + :param x: x-coordinate of the keypoint + + :param y: y-coordinate of the keypoint + + :param _pt: x & y coordinates of the keypoint + + :param _size: keypoint diameter + + :param _angle: keypoint orientation + + :param _response: keypoint detector response on the keypoint (that is, strength of the keypoint) + + :param _octave: pyramid octave in which the keypoint has been detected + + :param _class_id: object id + + +KeyPoint::convert +-------------------- + +This method converts vector of keypoints to vector of points or the reverse, where each keypoint is assigned the same size and the same orientation. + +.. ocv:function:: void KeyPoint::convert(const std::vector& keypoints, std::vector& points2f, const std::vector& keypointIndexes=std::vector()) + +.. ocv:function:: void KeyPoint::convert(const std::vector& points2f, std::vector& keypoints, float size=1, float response=1, int octave=0, int class_id=-1) + +.. ocv:pyfunction:: cv2.KeyPoint_convert(keypoints[, keypointIndexes]) -> points2f + +.. ocv:pyfunction:: cv2.KeyPoint_convert(points2f[, size[, response[, octave[, class_id]]]]) -> keypoints + + :param keypoints: Keypoints obtained from any feature detection algorithm like SIFT/SURF/ORB + + :param points2f: Array of (x,y) coordinates of each keypoint + + :param keypointIndexes: Array of indexes of keypoints to be converted to points. (Acts like a mask to convert only specified keypoints) + + :param _size: keypoint diameter + + :param _response: keypoint detector response on the keypoint (that is, strength of the keypoint) + + :param _octave: pyramid octave in which the keypoint has been detected + + :param _class_id: object id + + +KeyPoint::overlap +-------------------- + +This method computes overlap for pair of keypoints. Overlap is the ratio between area of keypoint regions' intersection and area of keypoint regions' union (considering keypoint region as circle). If they don't overlap, we get zero. If they coincide at same location with same size, we get 1. + +.. ocv:function:: float KeyPoint::overlap(const KeyPoint& kp1, const KeyPoint& kp2) + +.. ocv:pyfunction:: cv2.KeyPoint_overlap(kp1, kp2) -> retval + + :param kp1: First keypoint + + :param kp2: Second keypoint + + +DMatch +------ +.. ocv:class:: DMatch + +Class for matching keypoint descriptors: query descriptor index, +train descriptor index, train image index, and distance between descriptors. :: + + class DMatch + { + public: + DMatch() : queryIdx(-1), trainIdx(-1), imgIdx(-1), + distance(std::numeric_limits::max()) {} + DMatch( int _queryIdx, int _trainIdx, float _distance ) : + queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(-1), + distance(_distance) {} + DMatch( int _queryIdx, int _trainIdx, int _imgIdx, float _distance ) : + queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(_imgIdx), + distance(_distance) {} + + int queryIdx; // query descriptor index + int trainIdx; // train descriptor index + int imgIdx; // train image index + + float distance; + + // less is better + bool operator<( const DMatch &m ) const; + }; + Ptr --- .. ocv:class:: Ptr -Template class for smart reference-counting pointers :: +Template class for smart pointers with shared ownership. :: - template class Ptr + template + struct Ptr { - public: - // default constructor + typedef T element_type; + Ptr(); - // constructor that wraps the object pointer - Ptr(_Tp* _obj); - // destructor: calls release() + + template + explicit Ptr(Y* p); + template + Ptr(Y* p, D d); + + Ptr(const Ptr& o); + template + Ptr(const Ptr& o); + template + Ptr(const Ptr& o, T* p); + ~Ptr(); - // copy constructor; increments ptr's reference counter - Ptr(const Ptr& ptr); - // assignment operator; decrements own reference counter - // (with release()) and increments ptr's reference counter - Ptr& operator = (const Ptr& ptr); - // increments reference counter - void addref(); - // decrements reference counter; when it becomes 0, - // delete_obj() is called + + Ptr& operator = (const Ptr& o); + template + Ptr& operator = (const Ptr& o); + void release(); - // user-specified custom object deletion operation. - // by default, "delete obj;" is called - void delete_obj(); - // returns true if obj == 0; + + template + void reset(Y* p); + template + void reset(Y* p, D d); + + void swap(Ptr& o); + + T* get() const; + + T& operator * () const; + T* operator -> () const; + operator T* () const; + bool empty() const; - // provide access to the object fields and methods - _Tp* operator -> (); - const _Tp* operator -> () const; - - // return the underlying object pointer; - // thanks to the methods, the Ptr<_Tp> can be - // used instead of _Tp* - operator _Tp* (); - operator const _Tp*() const; - protected: - // the encapsulated object pointer - _Tp* obj; - // the associated reference counter - int* refcount; + template + Ptr staticCast() const; + template + Ptr constCast() const; + template + Ptr dynamicCast() const; }; -The ``Ptr<_Tp>`` class is a template class that wraps pointers of the corresponding type. It is -similar to ``shared_ptr`` that is part of the Boost library -(http://www.boost.org/doc/libs/1_40_0/libs/smart_ptr/shared_ptr.htm) and also part of the -`C++0x `_ standard. +A ``Ptr`` pretends to be a pointer to an object of type T. +Unlike an ordinary pointer, however, the object will be automatically +cleaned up once all ``Ptr`` instances pointing to it are destroyed. -This class provides the following options: +``Ptr`` is similar to ``boost::shared_ptr`` that is part of the Boost library +(http://www.boost.org/doc/libs/release/libs/smart_ptr/shared_ptr.htm) +and ``std::shared_ptr`` from the `C++11 `_ standard. + +This class provides the following advantages: * Default constructor, copy constructor, and assignment operator for an arbitrary C++ class - or a C structure. For some objects, like files, windows, mutexes, sockets, and others, a copy + or C structure. For some objects, like files, windows, mutexes, sockets, and others, a copy constructor or an assignment operator are difficult to define. For some other objects, like complex classifiers in OpenCV, copy constructors are absent and not easy to implement. Finally, some of complex OpenCV and your own data structures may be written in C. - However, copy constructors and default constructors can simplify programming a lot.Besides, - they are often required (for example, by STL containers). By wrapping a pointer to such a - complex object ``TObj`` to ``Ptr``, you automatically get all of the necessary + However, copy constructors and default constructors can simplify programming a lot. Besides, + they are often required (for example, by STL containers). By using a ``Ptr`` to such an + object instead of the object itself, you automatically get all of the necessary constructors and the assignment operator. * *O(1)* complexity of the above-mentioned operations. While some structures, like ``std::vector``, provide a copy constructor and an assignment operator, the operations may take a considerable - amount of time if the data structures are large. But if the structures are put into ``Ptr<>``, + amount of time if the data structures are large. But if the structures are put into a ``Ptr``, the overhead is small and independent of the data size. * - Automatic destruction, even for C structures. See the example below with ``FILE*``. + Automatic and customizable cleanup, even for C structures. See the example below with ``FILE*``. * Heterogeneous collections of objects. The standard STL and most other C++ and OpenCV containers can store only objects of the same type and the same size. The classical solution to store objects - of different types in the same container is to store pointers to the base class ``base_class_t*`` - instead but then you loose the automatic memory management. Again, by using ``Ptr()`` - instead of the raw pointers, you can solve the problem. + of different types in the same container is to store pointers to the base class (``Base*``) + instead but then you lose the automatic memory management. Again, by using ``Ptr`` + instead of raw pointers, you can solve the problem. -The ``Ptr`` class treats the wrapped object as a black box. The reference counter is allocated and -managed separately. The only thing the pointer class needs to know about the object is how to -deallocate it. This knowledge is encapsulated in the ``Ptr::delete_obj()`` method that is called when -the reference counter becomes 0. If the object is a C++ class instance, no additional coding is -needed, because the default implementation of this method calls ``delete obj;``. However, if the -object is deallocated in a different way, the specialized method should be created. For example, -if you want to wrap ``FILE``, the ``delete_obj`` may be implemented as follows: :: +A ``Ptr`` is said to *own* a pointer - that is, for each ``Ptr`` there is a pointer that will be deleted +once all ``Ptr`` instances that own it are destroyed. The owned pointer may be null, in which case nothing is deleted. +Each ``Ptr`` also *stores* a pointer. The stored pointer is the pointer the ``Ptr`` pretends to be; +that is, the one you get when you use :ocv:func:`Ptr::get` or the conversion to ``T*``. It's usually +the same as the owned pointer, but if you use casts or the general shared-ownership constructor, the two may diverge: +the ``Ptr`` will still own the original pointer, but will itself point to something else. - template<> inline void Ptr::delete_obj() - { - fclose(obj); // no need to clear the pointer afterwards, - // it is done externally. - } - ... +The owned pointer is treated as a black box. The only thing ``Ptr`` needs to know about it is how to +delete it. This knowledge is encapsulated in the *deleter* - an auxiliary object that is associated +with the owned pointer and shared between all ``Ptr`` instances that own it. The default deleter is +an instance of ``DefaultDeleter``, which uses the standard C++ ``delete`` operator; as such it +will work with any pointer allocated with the standard ``new`` operator. - // now use it: - Ptr f(fopen("myfile.txt", "r")); - if(f.empty()) - throw ...; +However, if the pointer must be deleted in a different way, you must specify a custom deleter upon +``Ptr`` construction. A deleter is simply a callable object that accepts the pointer as its sole argument. +For example, if you want to wrap ``FILE``, you may do so as follows:: + + Ptr f(fopen("myfile.txt", "w"), fclose); + if(!f) throw ...; fprintf(f, ....); ... - // the file will be closed automatically by the Ptr destructor. + // the file will be closed automatically by f's destructor. +Alternatively, if you want all pointers of a particular type to be deleted the same way, +you can specialize ``DefaultDeleter::operator()`` for that type, like this:: -.. note:: The reference increment/decrement operations are implemented as atomic operations, - and therefore it is normally safe to use the classes in multi-threaded applications. - The same is true for :ocv:class:`Mat` and other C++ OpenCV classes that operate on - the reference counters. + namespace cv { + template<> void DefaultDeleter::operator ()(FILE * obj) const + { + fclose(obj); + } + } -Ptr::Ptr --------- -Various Ptr constructors. +For convenience, the following types from the OpenCV C API already have such a specialization +that calls the appropriate release function: + +* ``CvCapture`` +* :ocv:struct:`CvDTreeSplit` +* :ocv:struct:`CvFileStorage` +* ``CvHaarClassifierCascade`` +* :ocv:struct:`CvMat` +* :ocv:struct:`CvMatND` +* :ocv:struct:`CvMemStorage` +* :ocv:struct:`CvSparseMat` +* ``CvVideoWriter`` +* :ocv:struct:`IplImage` + +.. note:: The shared ownership mechanism is implemented with reference counting. As such, + cyclic ownership (e.g. when object ``a`` contains a ``Ptr`` to object ``b``, which + contains a ``Ptr`` to object ``a``) will lead to all involved objects never being + cleaned up. Avoid such situations. + +.. note:: It is safe to concurrently read (but not write) a ``Ptr`` instance from multiple threads + and therefore it is normally safe to use it in multi-threaded applications. + The same is true for :ocv:class:`Mat` and other C++ OpenCV classes that use internal + reference counts. + +Ptr::Ptr (null) +------------------ .. ocv:function:: Ptr::Ptr() -.. ocv:function:: Ptr::Ptr(_Tp* _obj) -.. ocv:function:: Ptr::Ptr(const Ptr& ptr) + + The default constructor creates a null ``Ptr`` - one that owns and stores a null pointer. + +Ptr::Ptr (assuming ownership) +----------------------------- + +.. ocv:function:: template Ptr::Ptr(Y* p) +.. ocv:function:: template Ptr::Ptr(Y* p, D d) + + :param d: Deleter to use for the owned pointer. + :param p: Pointer to own. + + If ``p`` is null, these are equivalent to the default constructor. + + Otherwise, these constructors assume ownership of ``p`` - that is, the created ``Ptr`` owns + and stores ``p`` and assumes it is the sole owner of it. Don't use them if ``p`` is already + owned by another ``Ptr``, or else ``p`` will get deleted twice. + + With the first constructor, ``DefaultDeleter()`` becomes the associated deleter (so ``p`` + will eventually be deleted with the standard ``delete`` operator). ``Y`` must be a complete + type at the point of invocation. + + With the second constructor, ``d`` becomes the associated deleter. + + ``Y*`` must be convertible to ``T*``. + + .. note:: It is often easier to use :ocv:func:`makePtr` instead. + +Ptr::Ptr (sharing ownership) +---------------------------- + +.. ocv:function:: Ptr::Ptr(const Ptr& o) +.. ocv:function:: template Ptr::Ptr(const Ptr& o) +.. ocv:function:: template Ptr::Ptr(const Ptr& o, T* p) + + :param o: ``Ptr`` to share ownership with. + :param p: Pointer to store. + + These constructors create a ``Ptr`` that shares ownership with another ``Ptr`` - that is, + own the same pointer as ``o``. + + With the first two, the same pointer is stored, as well; for the second, ``Y*`` must be convertible to ``T*``. + + With the third, ``p`` is stored, and ``Y`` may be any type. This constructor allows to have completely + unrelated owned and stored pointers, and should be used with care to avoid confusion. A relatively + benign use is to create a non-owning ``Ptr``, like this:: + + ptr = Ptr(Ptr(), dont_delete_me); // owns nothing; will not delete the pointer. Ptr::~Ptr --------- -The Ptr destructor. .. ocv:function:: Ptr::~Ptr() + The destructor is equivalent to calling :ocv:func:`Ptr::release`. + Ptr::operator = ---------------- -Assignment operator. -.. ocv:function:: Ptr& Ptr::operator = (const Ptr& ptr) +.. ocv:function:: Ptr& Ptr::operator = (const Ptr& o) +.. ocv:function:: template Ptr& Ptr::operator = (const Ptr& o) -Decrements own reference counter (with ``release()``) and increments ptr's reference counter. + :param o: ``Ptr`` to share ownership with. -Ptr::addref ------------ -Increments reference counter. + Assignment replaces the current ``Ptr`` instance with one that owns and stores same + pointers as ``o`` and then destroys the old instance. -.. ocv:function:: void Ptr::addref() Ptr::release ------------ -Decrements reference counter; when it becomes 0, ``delete_obj()`` is called. .. ocv:function:: void Ptr::release() -Ptr::delete_obj ---------------- -User-specified custom object deletion operation. By default, ``delete obj;`` is called. + If no other ``Ptr`` instance owns the owned pointer, deletes it with the associated deleter. + Then sets both the owned and the stored pointers to ``NULL``. -.. ocv:function:: void Ptr::delete_obj() + +Ptr::reset +---------- + +.. ocv:function:: template void Ptr::reset(Y* p) +.. ocv:function:: template void Ptr::reset(Y* p, D d) + + :param d: Deleter to use for the owned pointer. + :param p: Pointer to own. + + ``ptr.reset(...)`` is equivalent to ``ptr = Ptr(...)``. + +Ptr::swap +--------- + +.. ocv:function:: void Ptr::swap(Ptr& o) + + :param o: ``Ptr`` to swap with. + + Swaps the owned and stored pointers (and deleters, if any) of this and ``o``. + +Ptr::get +-------- + +.. ocv:function:: T* Ptr::get() const + + Returns the stored pointer. + +Ptr pointer emulation +--------------------- + +.. ocv:function:: T& Ptr::operator * () const +.. ocv:function:: T* Ptr::operator -> () const +.. ocv:function:: Ptr::operator T* () const + + These operators are what allows ``Ptr`` to pretend to be a pointer. + + If ``ptr`` is a ``Ptr``, then ``*ptr`` is equivalent to ``*ptr.get()`` + and ``ptr->foo`` is equivalent to ``ptr.get()->foo``. In addition, ``ptr`` + is implicitly convertible to ``T*``, and such conversion is equivalent to + ``ptr.get()``. As a corollary, ``if (ptr)`` is equivalent to ``if (ptr.get())``. + In other words, a ``Ptr`` behaves as if it was its own stored pointer. Ptr::empty ---------- -Returns true if obj == 0; -bool empty() const; +.. ocv:function:: bool Ptr::empty() const -Ptr::operator -> ----------------- -Provide access to the object fields and methods. + ``ptr.empty()`` is equivalent to ``!ptr.get()``. - .. ocv:function:: template _Tp* Ptr::operator -> () - .. ocv:function:: template const _Tp* Ptr::operator -> () const +Ptr casts +--------- +.. ocv:function:: template Ptr Ptr::staticCast() const +.. ocv:function:: template Ptr Ptr::constCast() const +.. ocv:function:: template Ptr Ptr::dynamicCast() const -Ptr::operator _Tp* ------------------- -Returns the underlying object pointer. Thanks to the methods, the ``Ptr<_Tp>`` can be used instead -of ``_Tp*``. + If ``ptr`` is a ``Ptr``, then ``ptr.fooCast()`` is equivalent to + ``Ptr(ptr, foo_cast(ptr.get()))``. That is, these functions create + a new ``Ptr`` with the same owned pointer and a cast stored pointer. - .. ocv:function:: template Ptr::operator _Tp* () - .. ocv:function:: template Ptr::operator const _Tp*() const +Ptr global swap +--------------- +.. ocv:function:: template void swap(Ptr& ptr1, Ptr& ptr2) + + Equivalent to ``ptr1.swap(ptr2)``. Provided to help write generic algorithms. + +Ptr comparisons +--------------- + +.. ocv:function:: template bool operator == (const Ptr& ptr1, const Ptr& ptr2) +.. ocv:function:: template bool operator != (const Ptr& ptr1, const Ptr& ptr2) + + Return whether ``ptr1.get()`` and ``ptr2.get()`` are equal and not equal, respectively. + +makePtr +------- + +.. ocv:function:: template Ptr makePtr() +.. ocv:function:: template Ptr makePtr(const A1& a1) +.. ocv:function:: template Ptr makePtr(const A1& a1, const A2& a2) +.. ocv:function:: template Ptr makePtr(const A1& a1, const A2& a2, const A3& a3) + + (and so on...) + + ``makePtr(...)`` is equivalent to ``Ptr(new T(...))``. It is shorter than the latter, and + it's marginally safer than using a constructor or :ocv:func:`Ptr::reset`, since it ensures that + the owned pointer is new and thus not owned by any other ``Ptr`` instance. + + Unfortunately, perfect forwarding is impossible to implement in C++03, and so ``makePtr`` is limited + to constructors of ``T`` that have up to 10 arguments, none of which are non-const references. Mat --- .. ocv:class:: Mat -OpenCV C++ n-dimensional dense array class :: +OpenCV C++ n-dimensional dense array class +:: class CV_EXPORTS Mat { @@ -578,7 +1068,6 @@ OpenCV C++ n-dimensional dense array class :: ... }; - The class ``Mat`` represents an n-dimensional dense numerical single-channel or multi-channel array. It can be used to store real or complex-valued vectors and matrices, grayscale or color images, voxel volumes, vector fields, point clouds, tensors, histograms (though, very high-dimensional histograms may be better stored in a ``SparseMat`` ). The data layout of the array :math:`M` is defined by the array ``M.step[]``, so that the address of element :math:`(i_0,...,i_{M.dims-1})`, where @@ -798,6 +1287,9 @@ Finally, there are STL-style iterators that are smart enough to skip gaps betwee The matrix iterators are random-access iterators, so they can be passed to any STL algorithm, including ``std::sort()`` . +.. note:: + + * An example demonstrating the serial out capabilities of cv::Mat can be found at opencv_source_code/samples/cpp/cout_mat.cpp .. _MatrixExpressions: @@ -911,10 +1403,6 @@ Various Mat constructors .. ocv:function:: Mat::Mat(const Mat& m, const Rect& roi) -.. ocv:function:: Mat::Mat(const CvMat* m, bool copyData=false) - -.. ocv:function:: Mat::Mat(const IplImage* img, bool copyData=false) - .. ocv:function:: template explicit Mat::Mat(const Vec& vec, bool copyData=true) .. ocv:function:: template explicit Mat::Mat(const Matx& vec, bool copyData=true) @@ -1064,7 +1552,7 @@ The method makes a new header for the specified row span of the matrix. Similarl Mat::colRange ------------- -Creates a matrix header for the specified row span. +Creates a matrix header for the specified column span. .. ocv:function:: Mat Mat::colRange(int startcol, int endcol) const @@ -1398,7 +1886,7 @@ Such a scheme makes the memory management robust and efficient at the same time Mat color; ... Mat gray(color.rows, color.cols, color.depth()); - cvtColor(color, gray, CV_BGR2GRAY); + cvtColor(color, gray, COLOR_BGR2GRAY); you can simply write: :: @@ -1406,7 +1894,7 @@ you can simply write: :: Mat color; ... Mat gray; - cvtColor(color, gray, CV_BGR2GRAY); + cvtColor(color, gray, COLOR_BGR2GRAY); because ``cvtColor`` , as well as the most of OpenCV functions, calls ``Mat::create()`` for the output array internally. @@ -1465,6 +1953,7 @@ Adds elements to the bottom of the matrix. .. ocv:function:: void Mat::push_back( const Mat& m ) :param elem: Added element(s). + :param m: Added line(s). The methods add one or more elements to the bottom of the matrix. They emulate the corresponding method of the STL vector class. When ``elem`` is ``Mat`` , its type and the number of columns must be the same as in the container matrix. @@ -1552,33 +2041,6 @@ The operators make a new header for the specified sub-array of ``*this`` . They :ocv:func:`Mat::colRange` . For example, ``A(Range(0, 10), Range::all())`` is equivalent to ``A.rowRange(0, 10)`` . Similarly to all of the above, the operators are O(1) operations, that is, no matrix data is copied. -Mat::operator CvMat -------------------- -Creates the ``CvMat`` header for the matrix. - -.. ocv:function:: Mat::operator CvMat() const - - -The operator creates the ``CvMat`` header for the matrix without copying the underlying data. The reference counter is not taken into account by this operation. Thus, you should make sure than the original matrix is not deallocated while the ``CvMat`` header is used. The operator is useful for intermixing the new and the old OpenCV API's, for example: :: - - Mat img(Size(320, 240), CV_8UC3); - ... - - CvMat cvimg = img; - mycvOldFunc( &cvimg, ...); - - -where ``mycvOldFunc`` is a function written to work with OpenCV 1.x data structures. - - -Mat::operator IplImage ----------------------- -Creates the ``IplImage`` header for the matrix. - -.. ocv:function:: Mat::operator IplImage() const - -The operator creates the ``IplImage`` header for the matrix without copying the underlying data. You should make sure than the original matrix is not deallocated while the ``IplImage`` header is used. Similarly to ``Mat::operator CvMat`` , the operator is useful for intermixing the new and the old OpenCV API's. - Mat::total ---------- Returns the total number of array elements. @@ -1691,7 +2153,7 @@ Returns the depth of a matrix element. .. ocv:function:: int Mat::depth() const -The method returns the identifier of the matrix element depth (the type of each individual channel). For example, for a 16-bit signed 3-channel array, the method returns ``CV_16S`` . A complete list of matrix types contains the following values: +The method returns the identifier of the matrix element depth (the type of each individual channel). For example, for a 16-bit signed element array, the method returns ``CV_16S`` . A complete list of matrix types contains the following values: * ``CV_8U`` - 8-bit unsigned integers ( ``0..255`` ) @@ -2153,14 +2615,12 @@ Various SparseMat constructors. .. ocv:function:: SparseMat::SparseMat( int dims, const int* _sizes, int _type ) .. ocv:function:: SparseMat::SparseMat( const SparseMat& m ) .. ocv:function:: SparseMat::SparseMat( const Mat& m ) -.. ocv:function:: SparseMat::SparseMat( const CvSparseMat* m ) :param m: Source matrix for copy constructor. If m is dense matrix (ocv:class:`Mat`) then it will be converted to sparse representation. :param dims: Array dimensionality. :param _sizes: Sparce matrix size on all dementions. :param _type: Sparse matrix data type. - :param try1d: if try1d is true and matrix is a single-column matrix (Nx1), then the sparse matrix will be 1-dimensional. SparseMat::~SparseMat --------------------- @@ -2175,6 +2635,8 @@ Provides sparse matrix assignment operators. .. ocv:function:: SparseMat& SparseMat::operator = (const SparseMat& m) .. ocv:function:: SparseMat& SparseMat::operator = (const Mat& m) + :param m: Matrix for assignment. + The last variant is equivalent to the corresponding constructor with try1d=false. @@ -2202,6 +2664,10 @@ Convert sparse matrix with possible type change and scaling. .. ocv:function:: void SparseMat::convertTo( SparseMat& m, int rtype, double alpha=1 ) const .. ocv:function:: void SparseMat::convertTo( Mat& m, int rtype, double alpha=1, double beta=0 ) const + :param m: Destination matrix. + :param rtype: Destination matrix type. + :param alpha: Conversion multiplier. + The first version converts arbitrary sparse matrix to dense matrix and multiplies all the matrix elements by the specified scalar. The second versiob converts sparse matrix to dense matrix with optional type conversion and scaling. When rtype=-1, the destination element type will be the same as the sparse matrix element type. @@ -2294,7 +2760,7 @@ The method returns the number of matrix channels. SparseMat::size --------------- -Returns the array of sizes or matrix size by i dimention and 0 if the matrix is not allocated. +Returns the array of sizes or matrix size by i dimension and 0 if the matrix is not allocated. .. ocv:function:: const int* SparseMat::size() const .. ocv:function:: int SparseMat::size(int i) const @@ -2322,6 +2788,11 @@ Compute element hash value from the element indices. .. ocv:function:: size_t SparseMat::hash(int i0, int i1, int i2) const .. ocv:function:: size_t SparseMat::hash(const int* idx) const + :param i0: The first dimension index. + :param i1: The second dimension index. + :param i2: The third dimension index. + :param idx: Array of element indices for multidimensional matices. + SparseMat::ptr -------------- Low-level element-access functions, special variants for 1D, 2D, 3D cases, and the generic one for n-D case. @@ -2331,6 +2802,12 @@ Low-level element-access functions, special variants for 1D, 2D, 3D cases, and t .. ocv:function:: uchar* SparseMat::ptr(int i0, int i1, int i2, bool createMissing, size_t* hashval=0) .. ocv:function:: uchar* SparseMat::ptr(const int* idx, bool createMissing, size_t* hashval=0) + :param i0: The first dimension index. + :param i1: The second dimension index. + :param i2: The third dimension index. + :param idx: Array of element indices for multidimensional matices. + :param createMissing: Create new element with 0 value if it does not exist in SparseMat. + Return pointer to the matrix element. If the element is there (it is non-zero), the pointer to it is returned. If it is not there and ``createMissing=false``, NULL pointer is returned. If it is not there and ``createMissing=true``, the new elementis created and initialized with 0. Pointer to it is returned. If the optional hashval pointer is not ``NULL``, @@ -2344,6 +2821,11 @@ Erase the specified matrix element. When there is no such an element, the method .. ocv:function:: void SparseMat::erase(int i0, int i1, int i2, size_t* hashval=0) .. ocv:function:: void SparseMat::erase(const int* idx, size_t* hashval=0) + :param i0: The first dimension index. + :param i1: The second dimension index. + :param i2: The third dimension index. + :param idx: Array of element indices for multidimensional matices. + SparseMat\_ ----------- .. ocv:class:: SparseMat_ @@ -2412,6 +2894,82 @@ Algorithm --------- .. ocv:class:: Algorithm +:: + + class CV_EXPORTS_W Algorithm + { + public: + Algorithm(); + virtual ~Algorithm(); + string name() const; + + template typename ParamType<_Tp>::member_type get(const string& name) const; + template typename ParamType<_Tp>::member_type get(const char* name) const; + + CV_WRAP int getInt(const string& name) const; + CV_WRAP double getDouble(const string& name) const; + CV_WRAP bool getBool(const string& name) const; + CV_WRAP string getString(const string& name) const; + CV_WRAP Mat getMat(const string& name) const; + CV_WRAP vector getMatVector(const string& name) const; + CV_WRAP Ptr getAlgorithm(const string& name) const; + + void set(const string& name, int value); + void set(const string& name, double value); + void set(const string& name, bool value); + void set(const string& name, const string& value); + void set(const string& name, const Mat& value); + void set(const string& name, const vector& value); + void set(const string& name, const Ptr& value); + template void set(const string& name, const Ptr<_Tp>& value); + + CV_WRAP void setInt(const string& name, int value); + CV_WRAP void setDouble(const string& name, double value); + CV_WRAP void setBool(const string& name, bool value); + CV_WRAP void setString(const string& name, const string& value); + CV_WRAP void setMat(const string& name, const Mat& value); + CV_WRAP void setMatVector(const string& name, const vector& value); + CV_WRAP void setAlgorithm(const string& name, const Ptr& value); + template void setAlgorithm(const string& name, const Ptr<_Tp>& value); + + void set(const char* name, int value); + void set(const char* name, double value); + void set(const char* name, bool value); + void set(const char* name, const string& value); + void set(const char* name, const Mat& value); + void set(const char* name, const vector& value); + void set(const char* name, const Ptr& value); + template void set(const char* name, const Ptr<_Tp>& value); + + void setInt(const char* name, int value); + void setDouble(const char* name, double value); + void setBool(const char* name, bool value); + void setString(const char* name, const string& value); + void setMat(const char* name, const Mat& value); + void setMatVector(const char* name, const vector& value); + void setAlgorithm(const char* name, const Ptr& value); + template void setAlgorithm(const char* name, const Ptr<_Tp>& value); + + CV_WRAP string paramHelp(const string& name) const; + int paramType(const char* name) const; + CV_WRAP int paramType(const string& name) const; + CV_WRAP void getParams(CV_OUT vector& names) const; + + + virtual void write(FileStorage& fs) const; + virtual void read(const FileNode& fn); + + typedef Algorithm* (*Constructor)(void); + typedef int (Algorithm::*Getter)() const; + typedef void (Algorithm::*Setter)(int); + + CV_WRAP static void getList(CV_OUT vector& algorithms); + CV_WRAP static Ptr _create(const string& name); + template static Ptr<_Tp> create(const string& name); + + virtual AlgorithmInfo* info() const /* TODO: make it = 0;*/ { return 0; } + }; + This is a base class for all more or less complex algorithms in OpenCV, especially for classes of algorithms, for which there can be multiple implementations. The examples are stereo correspondence (for which there are algorithms like block matching, semi-global block matching, graph-cut etc.), background subtraction (which can be done using mixture-of-gaussians models, codebook-based algorithm etc.), optical flow (block matching, Lucas-Kanade, Horn-Schunck etc.). The class provides the following features for all derived classes: @@ -2457,13 +3015,13 @@ Algorithm::name --------------- Returns the algorithm name -.. ocv:function:: string Algorithm::name() const +.. ocv:function:: String Algorithm::name() const Algorithm::get -------------- Returns the algorithm parameter -.. ocv:function:: template typename ParamType<_Tp>::member_type Algorithm::get(const string& name) const +.. ocv:function:: template typename ParamType<_Tp>::member_type Algorithm::get(const String& name) const :param name: The parameter name. @@ -2472,7 +3030,7 @@ The method returns value of the particular parameter. Since the compiler can not * myalgo.get("param_name") * myalgo.get("param_name") * myalgo.get("param_name") - * myalgo.get("param_name") + * myalgo.get("param_name") * myalgo.get("param_name") * myalgo.get >("param_name") * myalgo.get("param_name") (it returns Ptr). @@ -2484,13 +3042,13 @@ Algorithm::set -------------- Sets the algorithm parameter -.. ocv:function:: void Algorithm::set(const string& name, int value) -.. ocv:function:: void Algorithm::set(const string& name, double value) -.. ocv:function:: void Algorithm::set(const string& name, bool value) -.. ocv:function:: void Algorithm::set(const string& name, const string& value) -.. ocv:function:: void Algorithm::set(const string& name, const Mat& value) -.. ocv:function:: void Algorithm::set(const string& name, const vector& value) -.. ocv:function:: void Algorithm::set(const string& name, const Ptr& value) +.. ocv:function:: void Algorithm::set(const String& name, int value) +.. ocv:function:: void Algorithm::set(const String& name, double value) +.. ocv:function:: void Algorithm::set(const String& name, bool value) +.. ocv:function:: void Algorithm::set(const String& name, const String& value) +.. ocv:function:: void Algorithm::set(const String& name, const Mat& value) +.. ocv:function:: void Algorithm::set(const String& name, const vector& value) +.. ocv:function:: void Algorithm::set(const String& name, const Ptr& value) :param name: The parameter name. :param value: The parameter value. @@ -2529,13 +3087,13 @@ Algorithm::getList ------------------ Returns the list of registered algorithms -.. ocv:function:: void Algorithm::getList(vector& algorithms) +.. ocv:function:: void Algorithm::getList(vector& algorithms) :param algorithms: The output vector of algorithm names. This static method returns the list of registered algorithms in alphabetical order. Here is how to use it :: - vector algorithms; + vector algorithms; Algorithm::getList(algorithms); cout << "Algorithms: " << algorithms.size() << endl; for (size_t i=0; i < algorithms.size(); i++) @@ -2546,11 +3104,11 @@ Algorithm::create ----------------- Creates algorithm instance by name -.. ocv:function:: template Ptr<_Tp> Algorithm::create(const string& name) +.. ocv:function:: template Ptr<_Tp> Algorithm::create(const String& name) :param name: The algorithm name, one of the names returned by ``Algorithm::getList()``. -This static method creates a new instance of the specified algorithm. If there is no such algorithm, the method will silently return null pointer (that can be checked by ``Ptr::empty()`` method). Also, you should specify the particular ``Algorithm`` subclass as ``_Tp`` (or simply ``Algorithm`` if you do not know it at that point). :: +This static method creates a new instance of the specified algorithm. If there is no such algorithm, the method will silently return a null pointer. Also, you should specify the particular ``Algorithm`` subclass as ``_Tp`` (or simply ``Algorithm`` if you do not know it at that point). :: Ptr bgfg = Algorithm::create("BackgroundSubtractor.MOG2"); @@ -2566,4 +3124,3 @@ The above methods are usually enough for users. If you want to make your own alg * Add public virtual method ``AlgorithmInfo* info() const;`` to your class. * Add constructor function, ``AlgorithmInfo`` instance and implement the ``info()`` method. The simplest way is to take http://code.opencv.org/projects/opencv/repository/revisions/master/entry/modules/ml/src/ml_init.cpp as the reference and modify it according to the list of your parameters. * Add some public function (e.g. ``initModule_()``) that calls info() of your algorithm and put it into the same source file as ``info()`` implementation. This is to force C++ linker to include this object file into the target application. See ``Algorithm::create()`` for details. - diff --git a/modules/core/doc/clustering.rst b/modules/core/doc/clustering.rst index 60fb189285..dc9b28799d 100644 --- a/modules/core/doc/clustering.rst +++ b/modules/core/doc/clustering.rst @@ -13,16 +13,20 @@ Finds centers of clusters and groups input samples around the clusters. .. ocv:cfunction:: int cvKMeans2( const CvArr* samples, int cluster_count, CvArr* labels, CvTermCriteria termcrit, int attempts=1, CvRNG* rng=0, int flags=0, CvArr* _centers=0, double* compactness=0 ) -.. ocv:pyoldfunction:: cv.KMeans2(samples, nclusters, labels, termcrit, attempts=1, flags=0, centers=None) -> float - :param samples: Floating-point matrix of input samples, one row per sample. + :param data: Data for clustering. + :param cluster_count: Number of clusters to split the set by. + :param K: Number of clusters to split the set by. + :param labels: Input/output integer array that stores the cluster indices for every sample. :param criteria: The algorithm termination criteria, that is, the maximum number of iterations and/or the desired accuracy. The accuracy is specified as ``criteria.epsilon``. As soon as each of the cluster centers moves by less than ``criteria.epsilon`` on some iteration, the algorithm stops. + :param termcrit: The algorithm termination criteria, that is, the maximum number of iterations and/or the desired accuracy. + :param attempts: Flag to specify the number of times the algorithm is executed using different initial labellings. The algorithm returns the labels that yield the best compactness (see the last function parameter). :param rng: CvRNG state initialized by RNG(). @@ -37,6 +41,8 @@ Finds centers of clusters and groups input samples around the clusters. :param centers: Output matrix of the cluster centers, one row per each cluster center. + :param _centers: Output matrix of the cluster centers, one row per each cluster center. + :param compactness: The returned value that is described below. The function ``kmeans`` implements a k-means algorithm that finds the @@ -58,6 +64,12 @@ Basically, you can use only the core of the function, set the number of attempts to 1, initialize labels each time using a custom algorithm, pass them with the ( ``flags`` = ``KMEANS_USE_INITIAL_LABELS`` ) flag, and then choose the best (most-compact) clustering. +.. note:: + + * An example on K-means clustering can be found at opencv_source_code/samples/cpp/kmeans.cpp + + * (Python) An example on K-means clustering can be found at opencv_source_code/samples/python2/kmeans.py + partition ------------- Splits an element set into equivalency classes. diff --git a/modules/core/doc/command_line_parser.rst b/modules/core/doc/command_line_parser.rst index 53396b23bc..c1f69f4e50 100644 --- a/modules/core/doc/command_line_parser.rst +++ b/modules/core/doc/command_line_parser.rst @@ -10,13 +10,13 @@ CommandLineParser The CommandLineParser class is designed for command line arguments parsing - .. ocv:function:: CommandLineParser::CommandLineParser( int argc, const char* const argv[], const string& keys ) + .. ocv:function:: CommandLineParser::CommandLineParser( int argc, const char* const argv[], const String& keys ) :param argc: :param argv: :param keys: - .. ocv:function:: template T CommandLineParser::get(const std::string& name, bool space_delete = true) + .. ocv:function:: template T CommandLineParser::get(const String& name, bool space_delete = true) :param name: :param space_delete: @@ -26,14 +26,14 @@ The CommandLineParser class is designed for command line arguments parsing :param index: :param space_delete: - .. ocv:function:: bool CommandLineParser::has(const std::string& name) + .. ocv:function:: bool CommandLineParser::has(const String& name) :param name: .. ocv:function:: bool CommandLineParser::check() - .. ocv:function:: void CommandLineParser::about( const string& message ) + .. ocv:function:: void CommandLineParser::about( const String& message ) :param message: @@ -41,7 +41,7 @@ The CommandLineParser class is designed for command line arguments parsing .. ocv:function:: void CommandLineParser::printErrors() - .. ocv:function:: std::string CommandLineParser::getPathToApplication() + .. ocv:function:: String CommandLineParser::getPathToApplication() The sample below demonstrates how to use CommandLineParser: @@ -59,12 +59,12 @@ The sample below demonstrates how to use CommandLineParser: int N = parser.get("N"); double fps = parser.get("fps"); - std::string path = parser.get("path"); + String path = parser.get("path"); use_time_stamp = parser.has("timestamp"); - std::string img1 = parser.get(0); - std::string img2 = parser.get(1); + String img1 = parser.get(0); + String img2 = parser.get(1); int repeat = parser.get(2); @@ -78,7 +78,7 @@ Syntax: :: - const std::string keys = + const String keys = "{help h usage ? | | print this message }" "{@image1 | | image1 for compare }" "{@image2 | | image2 for compare }" @@ -98,4 +98,3 @@ Use: # ./app -fps=aaa ERRORS: Exception: can not convert: [aaa] to [double] - diff --git a/modules/core/doc/core.rst b/modules/core/doc/core.rst index 90caeebc79..73bfc35367 100644 --- a/modules/core/doc/core.rst +++ b/modules/core/doc/core.rst @@ -15,4 +15,4 @@ core. The Core Functionality old_xml_yaml_persistence clustering utility_and_system_functions_and_macros - + opengl_interop diff --git a/modules/core/doc/drawing_functions.rst b/modules/core/doc/drawing_functions.rst index 6c0ac4b35f..258cfe6ef3 100644 --- a/modules/core/doc/drawing_functions.rst +++ b/modules/core/doc/drawing_functions.rst @@ -6,7 +6,7 @@ Drawing Functions Drawing functions work with matrices/images of arbitrary depth. The boundaries of the shapes can be rendered with antialiasing (implemented only for 8-bit images for now). All the functions include the parameter ``color`` that uses an RGB value (that may be constructed -with ``CV_RGB`` or the :ocv:class:`Scalar_` constructor +with the ``Scalar`` constructor ) for color images and brightness for grayscale images. For color images, the channel ordering is normally *Blue, Green, Red*. @@ -26,18 +26,20 @@ If a drawn figure is partially or completely outside the image, the drawing func .. note:: The functions do not support alpha-transparency when the target image is 4-channel. In this case, the ``color[3]`` is simply copied to the repainted pixels. Thus, if you want to paint semi-transparent shapes, you can paint them in a separate buffer and then blend it with the main image. +.. note:: + + * An example on using variate drawing functions like line, rectangle, ... can be found at opencv_source_code/samples/cpp/drawing.cpp + circle ---------- Draws a circle. -.. ocv:function:: void circle(Mat& img, Point center, int radius, const Scalar& color, int thickness=1, int lineType=8, int shift=0) +.. ocv:function:: void circle( Mat& img, Point center, int radius, const Scalar& color, int thickness=1, int lineType=LINE_8, int shift=0 ) .. ocv:pyfunction:: cv2.circle(img, center, radius, color[, thickness[, lineType[, shift]]]) -> img .. ocv:cfunction:: void cvCircle( CvArr* img, CvPoint center, int radius, CvScalar color, int thickness=1, int line_type=8, int shift=0 ) -.. ocv:pyoldfunction:: cv.Circle(img, center, radius, color, thickness=1, lineType=8, shift=0)-> None - :param img: Image where the circle is drawn. :param center: Center of the circle. @@ -66,8 +68,6 @@ Clips the line against the image rectangle. .. ocv:cfunction:: int cvClipLine( CvSize img_size, CvPoint* pt1, CvPoint* pt2 ) -.. ocv:pyoldfunction:: cv.ClipLine(imgSize, pt1, pt2) -> (point1, point2) - :param imgSize: Image size. The image rectangle is ``Rect(0, 0, imgSize.width, imgSize.height)`` . :param imgRect: Image rectangle. @@ -83,9 +83,9 @@ ellipse ----------- Draws a simple or thick elliptic arc or fills an ellipse sector. -.. ocv:function:: void ellipse(Mat& img, Point center, Size axes, double angle, double startAngle, double endAngle, const Scalar& color, int thickness=1, int lineType=8, int shift=0) +.. ocv:function:: void ellipse( Mat& img, Point center, Size axes, double angle, double startAngle, double endAngle, const Scalar& color, int thickness=1, int lineType=LINE_8, int shift=0 ) -.. ocv:function:: void ellipse(Mat& img, const RotatedRect& box, const Scalar& color, int thickness=1, int lineType=8) +.. ocv:function:: void ellipse( Mat& img, const RotatedRect& box, const Scalar& color, int thickness=1, int lineType=LINE_8 ) .. ocv:pyfunction:: cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color[, thickness[, lineType[, shift]]]) -> img @@ -93,12 +93,8 @@ Draws a simple or thick elliptic arc or fills an ellipse sector. .. ocv:cfunction:: void cvEllipse( CvArr* img, CvPoint center, CvSize axes, double angle, double start_angle, double end_angle, CvScalar color, int thickness=1, int line_type=8, int shift=0 ) -.. ocv:pyoldfunction:: cv.Ellipse(img, center, axes, angle, start_angle, end_angle, color, thickness=1, lineType=8, shift=0)-> None - .. ocv:cfunction:: void cvEllipseBox( CvArr* img, CvBox2D box, CvScalar color, int thickness=1, int line_type=8, int shift=0 ) -.. ocv:pyoldfunction:: cv.EllipseBox(img, box, color, thickness=1, lineType=8, shift=0)-> None - :param img: Image. :param center: Center of the ellipse. @@ -162,14 +158,14 @@ fillConvexPoly ------------------ Fills a convex polygon. -.. ocv:function:: void fillConvexPoly(Mat& img, const Point* pts, int npts, const Scalar& color, int lineType=8, int shift=0) +.. ocv:function:: void fillConvexPoly( Mat& img, const Point* pts, int npts, const Scalar& color, int lineType=LINE_8, int shift=0 ) + +.. ocv:function:: void fillConvexPoly( InputOutputArray img, InputArray points, const Scalar& color, int lineType=LINE_8, int shift=0 ) .. ocv:pyfunction:: cv2.fillConvexPoly(img, points, color[, lineType[, shift]]) -> img .. ocv:cfunction:: void cvFillConvexPoly( CvArr* img, const CvPoint* pts, int npts, CvScalar color, int line_type=8, int shift=0 ) -.. ocv:pyoldfunction:: cv.FillConvexPoly(img, pn, color, lineType=8, shift=0)-> None - :param img: Image. :param pts: Polygon vertices. @@ -192,14 +188,14 @@ fillPoly ------------ Fills the area bounded by one or more polygons. -.. ocv:function:: void fillPoly(Mat& img, const Point** pts, const int* npts, int ncontours, const Scalar& color, int lineType=8, int shift=0, Point offset=Point() ) +.. ocv:function:: void fillPoly( Mat& img, const Point** pts, const int* npts, int ncontours, const Scalar& color, int lineType=LINE_8, int shift=0, Point offset=Point() ) + +.. ocv:function:: void fillPoly( InputOutputArray img, InputArrayOfArrays pts, const Scalar& color, int lineType=LINE_8, int shift=0, Point offset=Point() ) .. ocv:pyfunction:: cv2.fillPoly(img, pts, color[, lineType[, shift[, offset]]]) -> img .. ocv:cfunction:: void cvFillPoly( CvArr* img, CvPoint** pts, const int* npts, int contours, CvScalar color, int line_type=8, int shift=0 ) -.. ocv:pyoldfunction:: cv.FillPoly(img, polys, color, lineType=8, shift=0)-> None - :param img: Image. :param pts: Array of polygons where each polygon is represented as an array of points. @@ -225,16 +221,16 @@ getTextSize --------------- Calculates the width and height of a text string. -.. ocv:function:: Size getTextSize(const string& text, int fontFace, double fontScale, int thickness, int* baseLine) +.. ocv:function:: Size getTextSize(const String& text, int fontFace, double fontScale, int thickness, int* baseLine) .. ocv:pyfunction:: cv2.getTextSize(text, fontFace, fontScale, thickness) -> retval, baseLine .. ocv:cfunction:: void cvGetTextSize( const char* text_string, const CvFont* font, CvSize* text_size, int* baseline ) -.. ocv:pyoldfunction:: cv.GetTextSize(textString, font)-> (textSize, baseline) - :param text: Input text string. + :param text_string: Input text string in C format. + :param fontFace: Font to use. See the :ocv:func:`putText` for details. :param fontScale: Font scale. See the :ocv:func:`putText` for details. @@ -243,10 +239,16 @@ Calculates the width and height of a text string. :param baseLine: Output parameter - y-coordinate of the baseline relative to the bottom-most text point. + :param baseline: Output parameter - y-coordinate of the baseline relative to the bottom-most text point. + + :param font: Font description in terms of old C API. + + :param text_size: Output parameter - The size of a box that contains the specified text. + The function ``getTextSize`` calculates and returns the size of a box that contains the specified text. That is, the following code renders some text, the tight box surrounding it, and the baseline: :: - string text = "Funny text inside the box"; + String text = "Funny text inside the box"; int fontFace = FONT_HERSHEY_SCRIPT_SIMPLEX; double fontScale = 2; int thickness = 3; @@ -330,14 +332,12 @@ line -------- Draws a line segment connecting two points. -.. ocv:function:: void line(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0) +.. ocv:function:: void line( Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=LINE_8, int shift=0 ) .. ocv:pyfunction:: cv2.line(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) -> img .. ocv:cfunction:: void cvLine( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color, int thickness=1, int line_type=8, int shift=0 ) -.. ocv:pyoldfunction:: cv.Line(img, pt1, pt2, color, thickness=1, lineType=8, shift=0)-> None - :param img: Image. :param pt1: First point of the line segment. @@ -350,16 +350,16 @@ Draws a line segment connecting two points. :param lineType: Type of the line: - * **8** (or omitted) - 8-connected line. + * **LINE_8** (or omitted) - 8-connected line. - * **4** - 4-connected line. + * **LINE_4** - 4-connected line. - * **CV_AA** - antialiased line. + * **LINE_AA** - antialiased line. :param shift: Number of fractional bits in the point coordinates. The function ``line`` draws the line segment between ``pt1`` and ``pt2`` points in the image. The line is clipped by the image boundaries. For non-antialiased lines with integer coordinates, the 8-connected or 4-connected Bresenham algorithm is used. Thick lines are drawn with rounding endings. -Antialiased lines are drawn using Gaussian filtering. To specify the line color, you may use the macro ``CV_RGB(r, g, b)`` . +Antialiased lines are drawn using Gaussian filtering. LineIterator @@ -418,16 +418,14 @@ rectangle ------------- Draws a simple, thick, or filled up-right rectangle. -.. ocv:function:: void rectangle(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0) +.. ocv:function:: void rectangle( Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=LINE_8, int shift=0 ) -.. ocv:function:: void rectangle( Mat& img, Rect rec, const Scalar& color, int thickness=1, int lineType=8, int shift=0 ) +.. ocv:function:: void rectangle( Mat& img, Rect rec, const Scalar& color, int thickness=1, int lineType=LINE_8, int shift=0 ) .. ocv:pyfunction:: cv2.rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) -> img .. ocv:cfunction:: void cvRectangle( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color, int thickness=1, int line_type=8, int shift=0 ) -.. ocv:pyoldfunction:: cv.Rectangle(img, pt1, pt2, color, thickness=1, lineType=8, shift=0)-> None - :param img: Image. :param pt1: Vertex of the rectangle. @@ -452,16 +450,14 @@ polylines ------------- Draws several polygonal curves. -.. ocv:function:: void polylines( Mat& img, const Point* const* pts, const int* npts, int ncontours, bool isClosed, const Scalar& color, int thickness=1, int lineType=8, int shift=0 ) +.. ocv:function:: void polylines( Mat& img, const Point* const* pts, const int* npts, int ncontours, bool isClosed, const Scalar& color, int thickness=1, int lineType=LINE_8, int shift=0 ) -.. ocv:function:: void polylines( InputOutputArray img, InputArrayOfArrays pts, bool isClosed, const Scalar& color, int thickness=1, int lineType=8, int shift=0 ) +.. ocv:function:: void polylines( InputOutputArray img, InputArrayOfArrays pts, bool isClosed, const Scalar& color, int thickness=1, int lineType=LINE_8, int shift=0 ) .. ocv:pyfunction:: cv2.polylines(img, pts, isClosed, color[, thickness[, lineType[, shift]]]) -> img .. ocv:cfunction:: void cvPolyLine( CvArr* img, CvPoint** pts, const int* npts, int contours, int is_closed, CvScalar color, int thickness=1, int line_type=8, int shift=0 ) -.. ocv:pyoldfunction:: cv.PolyLine(img, polys, is_closed, color, thickness=1, lineType=8, shift=0) -> None - :param img: Image. :param pts: Array of polygonal curves. @@ -487,14 +483,12 @@ drawContours ---------------- Draws contours outlines or filled contours. -.. ocv:function:: void drawContours( InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point() ) +.. ocv:function:: void drawContours( InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=LINE_8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point() ) .. ocv:pyfunction:: cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]]) -> image .. ocv:cfunction:: void cvDrawContours( CvArr * img, CvSeq* contour, CvScalar external_color, CvScalar hole_color, int max_level, int thickness=1, int line_type=8, CvPoint offset=cvPoint(0,0) ) -.. ocv:pyoldfunction:: cv.DrawContours(img, contour, external_color, hole_color, max_level, thickness=1, lineType=8, offset=(0, 0))-> None - :param image: Destination image. :param contours: All the input contours. Each contour is stored as a point vector. @@ -525,10 +519,11 @@ The function draws contour outlines in the image if :math:`\texttt{thickness} \ge 0` or fills the area bounded by the contours if :math:`\texttt{thickness}<0` . The example below shows how to retrieve connected components from the binary image and label them: :: - #include "cv.h" - #include "highgui.h" + #include "opencv2/imgproc.hpp" + #include "opencv2/highgui.hpp" using namespace cv; + using namespace std; int main( int argc, char** argv ) { @@ -548,7 +543,7 @@ The function draws contour outlines in the image if vector hierarchy; findContours( src, contours, hierarchy, - CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE ); + RETR_CCOMP, CHAIN_APPROX_SIMPLE ); // iterate through all the top-level contours, // draw each connected component with its own random color @@ -556,7 +551,7 @@ The function draws contour outlines in the image if for( ; idx >= 0; idx = hierarchy[idx][0] ) { Scalar color( rand()&255, rand()&255, rand()&255 ); - drawContours( dst, contours, idx, color, CV_FILLED, 8, hierarchy ); + drawContours( dst, contours, idx, color, FILLED, 8, hierarchy ); } namedWindow( "Components", 1 ); @@ -564,18 +559,23 @@ The function draws contour outlines in the image if waitKey(0); } +.. note:: + + * An example using the drawContour functionality can be found at opencv_source_code/samples/cpp/contours2.cpp + * An example using drawContours to clean up a background segmentation result at opencv_source_code/samples/cpp/segment_objects.cpp + + * (Python) An example using the drawContour functionality can be found at opencv_source/samples/python2/contours.py putText ----------- Draws a text string. -.. ocv:function:: void putText( Mat& img, const string& text, Point org, int fontFace, double fontScale, Scalar color, int thickness=1, int lineType=8, bool bottomLeftOrigin=false ) +.. ocv:function:: void putText( Mat& img, const String& text, Point org, int fontFace, double fontScale, Scalar color, int thickness=1, int lineType=LINE_8, bool bottomLeftOrigin=false ) .. ocv:pyfunction:: cv2.putText(img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]]) -> None .. ocv:cfunction:: void cvPutText( CvArr* img, const char* text, CvPoint org, const CvFont* font, CvScalar color ) -.. ocv:pyoldfunction:: cv.PutText(img, text, org, font, color)-> None :param img: Image. @@ -602,4 +602,3 @@ The function ``putText`` renders the specified text string in the image. Symbols that cannot be rendered using the specified font are replaced by question marks. See :ocv:func:`getTextSize` for a text rendering code example. - diff --git a/modules/core/doc/dynamic_structures.rst b/modules/core/doc/dynamic_structures.rst index e333971c06..0f3df5d12e 100644 --- a/modules/core/doc/dynamic_structures.rst +++ b/modules/core/doc/dynamic_structures.rst @@ -279,7 +279,6 @@ CloneSeq Creates a copy of a sequence. .. ocv:cfunction:: CvSeq* cvCloneSeq( const CvSeq* seq, CvMemStorage* storage=NULL ) -.. ocv:pyoldfunction:: cv.CloneSeq(seq, storage)-> None :param seq: Sequence @@ -388,9 +387,6 @@ Creates memory storage. .. ocv:cfunction:: CvMemStorage* cvCreateMemStorage( int block_size=0 ) -.. ocv:pyoldfunction:: cv.CreateMemStorage(blockSize=0) -> memstorage - - :param block_size: Size of the storage blocks in bytes. If it is 0, the block size is set to a default value - currently it is about 64K. The function creates an empty memory storage. See @@ -1584,4 +1580,3 @@ Gathers all node pointers to a single sequence. :param storage: Container for the sequence The function puts pointers of all nodes reachable from ``first`` into a single sequence. The pointers are written sequentially in the depth-first order. - diff --git a/modules/core/doc/intro.rst b/modules/core/doc/intro.rst index 806f434b26..6d9fdfca5e 100644 --- a/modules/core/doc/intro.rst +++ b/modules/core/doc/intro.rst @@ -4,7 +4,7 @@ Introduction .. highlight:: cpp -OpenCV (Open Source Computer Vision Library: http://opencv.willowgarage.com/wiki/) is an open-source BSD-licensed library that includes several hundreds of computer vision algorithms. The document describes the so-called OpenCV 2.x API, which is essentially a C++ API, as opposite to the C-based OpenCV 1.x API. The latter is described in opencv1x.pdf. +OpenCV (Open Source Computer Vision Library: http://opencv.org) is an open-source BSD-licensed library that includes several hundreds of computer vision algorithms. The document describes the so-called OpenCV 2.x API, which is essentially a C++ API, as opposite to the C-based OpenCV 1.x API. The latter is described in opencv1x.pdf. OpenCV has a modular structure, which means that the package includes several shared or static libraries. The following modules are available: @@ -83,17 +83,22 @@ First of all, ``std::vector``, ``Mat``, and other data structures used by the fu // matrix will be deallocated, since it is not referenced by anyone C = C.clone(); -You see that the use of ``Mat`` and other basic structures is simple. But what about high-level classes or even user data types created without taking automatic memory management into account? For them, OpenCV offers the ``Ptr<>`` template class that is similar to ``std::shared_ptr`` from C++ TR1. So, instead of using plain pointers:: +You see that the use of ``Mat`` and other basic structures is simple. But what about high-level classes or even user +data types created without taking automatic memory management into account? For them, OpenCV offers the :ocv:class:`Ptr` +template class that is similar to ``std::shared_ptr`` from C++11. So, instead of using plain pointers:: T* ptr = new T(...); you can use:: - Ptr ptr = new T(...); + Ptr ptr(new T(...)); -That is, ``Ptr ptr`` encapsulates a pointer to a ``T`` instance and a reference counter associated with the pointer. See the -:ocv:class:`Ptr` -description for details. +or:: + + Ptr ptr = makePtr(...); + +``Ptr`` encapsulates a pointer to a ``T`` instance and a reference counter associated with the pointer. See the +:ocv:class:`Ptr` description for details. .. _AutomaticAllocation: @@ -104,8 +109,8 @@ OpenCV deallocates the memory automatically, as well as automatically allocates Example: :: - #include "cv.h" - #include "highgui.h" + #include "opencv2/imgproc.hpp" + #include "opencv2/highgui.hpp" using namespace cv; @@ -119,7 +124,7 @@ Example: :: for(;;) { cap >> frame; - cvtColor(frame, edges, CV_BGR2GRAY); + cvtColor(frame, edges, COLOR_BGR2GRAY); GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5); Canny(edges, edges, 0, 30, 3); imshow("edges", edges); @@ -128,7 +133,7 @@ Example: :: return 0; } -The array ``frame`` is automatically allocated by the ``>>`` operator since the video frame resolution and the bit-depth is known to the video capturing module. The array ``edges`` is automatically allocated by the ``cvtColor`` function. It has the same size and the bit-depth as the input array. The number of channels is 1 because the color conversion code ``CV_BGR2GRAY`` is passed, which means a color to grayscale conversion. Note that ``frame`` and ``edges`` are allocated only once during the first execution of the loop body since all the next video frames have the same resolution. If you somehow change the video resolution, the arrays are automatically reallocated. +The array ``frame`` is automatically allocated by the ``>>`` operator since the video frame resolution and the bit-depth is known to the video capturing module. The array ``edges`` is automatically allocated by the ``cvtColor`` function. It has the same size and the bit-depth as the input array. The number of channels is 1 because the color conversion code ``COLOR_BGR2GRAY`` is passed, which means a color to grayscale conversion. Note that ``frame`` and ``edges`` are allocated only once during the first execution of the loop body since all the next video frames have the same resolution. If you somehow change the video resolution, the arrays are automatically reallocated. The key component of this technology is the ``Mat::create`` method. It takes the desired array size and type. If the array already has the specified size and type, the method does nothing. Otherwise, it releases the previously allocated data, if any (this part involves decrementing the reference counter and comparing it with zero), and then allocates a new buffer of the required size. Most functions call the ``Mat::create`` method for each output array, and so the automatic output data allocation is implemented. diff --git a/modules/core/doc/old_basic_structures.rst b/modules/core/doc/old_basic_structures.rst index 0596e04bff..906306dcb2 100644 --- a/modules/core/doc/old_basic_structures.rst +++ b/modules/core/doc/old_basic_structures.rst @@ -478,8 +478,6 @@ Clears a specific array element. .. ocv:cfunction:: void cvClearND( CvArr* arr, const int* idx ) -.. ocv:pyoldfunction:: cv.ClearND(arr, idx)-> None - :param arr: Input array :param idx: Array of the element indices @@ -490,7 +488,6 @@ CloneImage Makes a full copy of an image, including the header, data, and ROI. .. ocv:cfunction:: IplImage* cvCloneImage(const IplImage* image) -.. ocv:pyoldfunction:: cv.CloneImage(image) -> image :param image: The original image @@ -499,7 +496,6 @@ CloneMat Creates a full matrix copy. .. ocv:cfunction:: CvMat* cvCloneMat(const CvMat* mat) -.. ocv:pyoldfunction:: cv.CloneMat(mat) -> mat :param mat: Matrix to be copied @@ -510,7 +506,6 @@ CloneMatND Creates full copy of a multi-dimensional array and returns a pointer to the copy. .. ocv:cfunction:: CvMatND* cvCloneMatND(const CvMatND* mat) -.. ocv:pyoldfunction:: cv.CloneMatND(mat) -> matND :param mat: Input array @@ -530,8 +525,6 @@ ConvertScale Converts one array to another with optional linear transformation. .. ocv:cfunction:: void cvConvertScale(const CvArr* src, CvArr* dst, double scale=1, double shift=0) -.. ocv:pyoldfunction:: cv.ConvertScale(src, dst, scale=1.0, shift=0.0)-> None -.. ocv:pyoldfunction:: cv.Convert(src, dst)-> None :: @@ -569,7 +562,6 @@ Copy Copies one array to another. .. ocv:cfunction:: void cvCopy(const CvArr* src, CvArr* dst, const CvArr* mask=NULL) -.. ocv:pyoldfunction:: cv.Copy(src, dst, mask=None)-> None :param src: The source array @@ -591,7 +583,6 @@ CreateData Allocates array data .. ocv:cfunction:: void cvCreateData(CvArr* arr) -.. ocv:pyoldfunction:: cv.CreateData(arr) -> None :param arr: Array header @@ -603,7 +594,6 @@ CreateImage Creates an image header and allocates the image data. .. ocv:cfunction:: IplImage* cvCreateImage(CvSize size, int depth, int channels) -.. ocv:pyoldfunction:: cv.CreateImage(size, depth, channels)->image :param size: Image width and height @@ -621,7 +611,6 @@ CreateImageHeader Creates an image header but does not allocate the image data. .. ocv:cfunction:: IplImage* cvCreateImageHeader(CvSize size, int depth, int channels) -.. ocv:pyoldfunction:: cv.CreateImageHeader(size, depth, channels) -> image :param size: Image width and height @@ -634,7 +623,6 @@ CreateMat Creates a matrix header and allocates the matrix data. .. ocv:cfunction:: CvMat* cvCreateMat( int rows, int cols, int type) -.. ocv:pyoldfunction:: cv.CreateMat(rows, cols, type) -> mat :param rows: Number of rows in the matrix @@ -652,7 +640,6 @@ CreateMatHeader Creates a matrix header but does not allocate the matrix data. .. ocv:cfunction:: CvMat* cvCreateMatHeader( int rows, int cols, int type) -.. ocv:pyoldfunction:: cv.CreateMatHeader(rows, cols, type) -> mat :param rows: Number of rows in the matrix @@ -667,7 +654,6 @@ CreateMatND Creates the header and allocates the data for a multi-dimensional dense array. .. ocv:cfunction:: CvMatND* cvCreateMatND( int dims, const int* sizes, int type) -.. ocv:pyoldfunction:: cv.CreateMatND(dims, type) -> matND :param dims: Number of array dimensions. This must not exceed CV_MAX_DIM (32 by default, but can be changed at build time). @@ -685,7 +671,6 @@ CreateMatNDHeader Creates a new matrix header but does not allocate the matrix data. .. ocv:cfunction:: CvMatND* cvCreateMatNDHeader( int dims, const int* sizes, int type) -.. ocv:pyoldfunction:: cv.CreateMatNDHeader(dims, type) -> matND :param dims: Number of array dimensions @@ -716,7 +701,6 @@ CrossProduct Calculates the cross product of two 3D vectors. .. ocv:cfunction:: void cvCrossProduct(const CvArr* src1, const CvArr* src2, CvArr* dst) -.. ocv:pyoldfunction:: cv.CrossProduct(src1, src2, dst)-> None :param src1: The first source vector @@ -742,7 +726,6 @@ DotProduct Calculates the dot product of two arrays in Euclidean metrics. .. ocv:cfunction:: double cvDotProduct(const CvArr* src1, const CvArr* src2) -.. ocv:pyoldfunction:: cv.DotProduct(src1, src2) -> float :param src1: The first source array @@ -767,11 +750,6 @@ Get?D .. ocv:cfunction:: CvScalar cvGet3D(const CvArr* arr, int idx0, int idx1, int idx2) .. ocv:cfunction:: CvScalar cvGetND( const CvArr* arr, const int* idx ) -.. ocv:pyoldfunction:: cv.Get1D(arr, idx) -> scalar -.. ocv:pyoldfunction:: cv.Get2D(arr, idx0, idx1) -> scalar -.. ocv:pyoldfunction:: cv.Get3D(arr, idx0, idx1, idx2) -> scalar -.. ocv:pyoldfunction:: cv.GetND(arr, indices) -> scalar - Return a specific array element. :param arr: Input array @@ -794,10 +772,6 @@ Returns one of more array columns. .. ocv:cfunction:: CvMat* cvGetCols( const CvArr* arr, CvMat* submat, int start_col, int end_col ) -.. ocv:pyoldfunction:: cv.GetCol(arr, col)-> submat - -.. ocv:pyoldfunction:: cv.GetCols(arr, startCol, endCol)-> submat - :param arr: Input array :param submat: Pointer to the resulting sub-array header @@ -815,7 +789,6 @@ GetDiag Returns one of array diagonals. .. ocv:cfunction:: CvMat* cvGetDiag(const CvArr* arr, CvMat* submat, int diag=0) -.. ocv:pyoldfunction:: cv.GetDiag(arr, diag=0)-> submat :param arr: Input array @@ -830,7 +803,6 @@ GetDims Return number of array dimensions .. ocv:cfunction:: int cvGetDims(const CvArr* arr, int* sizes=NULL) -.. ocv:pyoldfunction:: cv.GetDims(arr) -> (dim1, dim2, ...) :param arr: Input array @@ -861,7 +833,6 @@ GetElemType Returns type of array elements. .. ocv:cfunction:: int cvGetElemType(const CvArr* arr) -.. ocv:pyoldfunction:: cv.GetElemType(arr)-> int :param arr: Input array @@ -877,8 +848,6 @@ Returns image header for arbitrary array. .. ocv:cfunction:: IplImage* cvGetImage( const CvArr* arr, IplImage* image_header ) -.. ocv:pyoldfunction:: cv.GetImage(arr) -> iplimage - :param arr: Input array :param image_header: Pointer to ``IplImage`` structure used as a temporary buffer @@ -890,7 +859,6 @@ GetImageCOI Returns the index of the channel of interest. .. ocv:cfunction:: int cvGetImageCOI(const IplImage* image) -.. ocv:pyoldfunction:: cv.GetImageCOI(image) -> int :param image: A pointer to the image header @@ -902,7 +870,6 @@ GetImageROI Returns the image ROI. .. ocv:cfunction:: CvRect cvGetImageROI(const IplImage* image) -.. ocv:pyoldfunction:: cv.GetImageROI(image)-> CvRect :param image: A pointer to the image header @@ -913,7 +880,6 @@ GetMat Returns matrix header for arbitrary array. .. ocv:cfunction:: CvMat* cvGetMat(const CvArr* arr, CvMat* header, int* coi=NULL, int allowND=0) -.. ocv:pyoldfunction:: cv.GetMat(arr, allowND=0) -> mat :param arr: Input array @@ -1002,11 +968,6 @@ Return a specific element of single-channel 1D, 2D, 3D or nD array. .. ocv:cfunction:: double cvGetReal3D(const CvArr* arr, int idx0, int idx1, int idx2) .. ocv:cfunction:: double cvGetRealND( const CvArr* arr, const int* idx ) -.. ocv:pyoldfunction:: cv.GetReal1D(arr, idx0)->float -.. ocv:pyoldfunction:: cv.GetReal2D(arr, idx0, idx1)->float -.. ocv:pyoldfunction:: cv.GetReal3D(arr, idx0, idx1, idx2)->float -.. ocv:pyoldfunction:: cv.GetRealND(arr, idx)->float - :param arr: Input array. Must have a single channel. :param idx0: The first zero-based component of the element index @@ -1030,9 +991,6 @@ Returns array row or row span. .. ocv:cfunction:: CvMat* cvGetRows( const CvArr* arr, CvMat* submat, int start_row, int end_row, int delta_row=1 ) -.. ocv:pyoldfunction:: cv.GetRow(arr, row)-> submat -.. ocv:pyoldfunction:: cv.GetRows(arr, startRow, endRow, deltaRow=1)-> submat - :param arr: Input array :param submat: Pointer to the resulting sub-array header @@ -1053,7 +1011,6 @@ GetSize Returns size of matrix or image ROI. .. ocv:cfunction:: CvSize cvGetSize(const CvArr* arr) -.. ocv:pyoldfunction:: cv.GetSize(arr)-> (width, height) :param arr: array header @@ -1064,7 +1021,6 @@ GetSubRect Returns matrix header corresponding to the rectangular sub-array of input image or matrix. .. ocv:cfunction:: CvMat* cvGetSubRect(const CvArr* arr, CvMat* submat, CvRect rect) -.. ocv:pyoldfunction:: cv.GetSubRect(arr, rect) -> submat :param arr: Input array @@ -1357,7 +1313,6 @@ ResetImageROI Resets the image ROI to include the entire image and releases the ROI structure. .. ocv:cfunction:: void cvResetImageROI(IplImage* image) -.. ocv:pyoldfunction:: cv.ResetImageROI(image)-> None :param image: A pointer to the image header @@ -1374,8 +1329,6 @@ Changes shape of matrix/image without copying data. .. ocv:cfunction:: CvMat* cvReshape( const CvArr* arr, CvMat* header, int new_cn, int new_rows=0 ) -.. ocv:pyoldfunction:: cv.Reshape(arr, newCn, newRows=0) -> mat - :param arr: Input array :param header: Output header to be filled @@ -1412,8 +1365,6 @@ Changes the shape of a multi-dimensional array without copying the data. .. ocv:cfunction:: CvArr* cvReshapeMatND( const CvArr* arr, int sizeof_header, CvArr* header, int new_cn, int new_dims, int* new_sizes ) -.. ocv:pyoldfunction:: cv.ReshapeMatND(arr, newCn, newDims) -> mat - :param arr: Input array :param sizeof_header: Size of output header to distinguish between IplImage, CvMat and CvMatND output headers @@ -1453,7 +1404,6 @@ Set Sets every element of an array to a given value. .. ocv:cfunction:: void cvSet(CvArr* arr, CvScalar value, const CvArr* mask=NULL) -.. ocv:pyoldfunction:: cv.Set(arr, value, mask=None)-> None :param arr: The destination array @@ -1481,12 +1431,6 @@ Change the particular array element. .. ocv:cfunction:: void cvSetND( CvArr* arr, const int* idx, CvScalar value ) -.. ocv:pyoldfunction:: cv.Set1D(arr, idx, value) -> None -.. ocv:pyoldfunction:: cv.Set2D(arr, idx0, idx1, value) -> None -.. ocv:pyoldfunction:: cv.Set3D(arr, idx0, idx1, idx2, value) -> None -.. ocv:pyoldfunction:: cv.SetND(arr, indices, value) -> None - - :param arr: Input array :param idx0: The first zero-based component of the element index @@ -1506,7 +1450,6 @@ SetData Assigns user data to the array header. .. ocv:cfunction:: void cvSetData(CvArr* arr, void* data, int step) -.. ocv:pyoldfunction:: cv.SetData(arr, data, step)-> None :param arr: Array header @@ -1525,7 +1468,6 @@ SetImageCOI Sets the channel of interest in an IplImage. .. ocv:cfunction:: void cvSetImageCOI( IplImage* image, int coi) -.. ocv:pyoldfunction:: cv.SetImageCOI(image, coi)-> None :param image: A pointer to the image header @@ -1539,7 +1481,6 @@ SetImageROI Sets an image Region Of Interest (ROI) for a given rectangle. .. ocv:cfunction:: void cvSetImageROI( IplImage* image, CvRect rect) -.. ocv:pyoldfunction:: cv.SetImageROI(image, rect)-> None :param image: A pointer to the image header @@ -1562,11 +1503,6 @@ Change a specific array element. .. ocv:cfunction:: void cvSetRealND( CvArr* arr, const int* idx, double value ) -.. ocv:pyoldfunction:: cv.SetReal1D(arr, idx, value) -> None -.. ocv:pyoldfunction:: cv.SetReal2D(arr, idx0, idx1, value) -> None -.. ocv:pyoldfunction:: cv.SetReal3D(arr, idx0, idx1, idx2, value) -> None -.. ocv:pyoldfunction:: cv.SetRealND(arr, indices, value) -> None - :param arr: Input array :param idx0: The first zero-based component of the element index @@ -1588,7 +1524,6 @@ SetZero Clears the array. .. ocv:cfunction:: void cvSetZero(CvArr* arr) -.. ocv:pyoldfunction:: cv.SetZero(arr) -> None :param arr: Array to be cleared @@ -1599,7 +1534,6 @@ mGet Returns the particular element of single-channel floating-point matrix. .. ocv:cfunction:: double cvmGet(const CvMat* mat, int row, int col) -.. ocv:pyoldfunction:: cv.mGet(mat, row, col) -> float :param mat: Input matrix @@ -1614,7 +1548,6 @@ mSet Sets a specific element of a single-channel floating-point matrix. .. ocv:cfunction:: void cvmSet(CvMat* mat, int row, int col, double value) -.. ocv:pyoldfunction:: cv.mSet(mat, row, col, value)-> None :param mat: The matrix @@ -1655,7 +1588,6 @@ RNG Initializes a random number generator state. .. ocv:cfunction:: CvRNG cvRNG(int64 seed=-1) -.. ocv:pyoldfunction:: cv.RNG(seed=-1LL)-> CvRNG :param seed: 64-bit value used to initiate a random sequence @@ -1670,8 +1602,6 @@ Fills an array with random numbers and updates the RNG state. .. ocv:cfunction:: void cvRandArr( CvRNG* rng, CvArr* arr, int dist_type, CvScalar param1, CvScalar param2 ) -.. ocv:pyoldfunction:: cv.RandArr(rng, arr, distType, param1, param2)-> None - :param rng: CvRNG state initialized by :ocv:cfunc:`RNG` :param arr: The destination array @@ -1695,7 +1625,6 @@ RandInt Returns a 32-bit unsigned integer and updates RNG. .. ocv:cfunction:: unsigned cvRandInt(CvRNG* rng) -.. ocv:pyoldfunction:: cv.RandInt(rng)-> unsigned :param rng: CvRNG state initialized by :ocv:cfunc:`RNG`. @@ -1707,7 +1636,6 @@ RandReal Returns a floating-point random number and updates RNG. .. ocv:cfunction:: double cvRandReal(CvRNG* rng) -.. ocv:pyoldfunction:: cv.RandReal(rng) -> float :param rng: RNG state initialized by :ocv:cfunc:`RNG` @@ -1718,8 +1646,6 @@ fromarray --------- Create a CvMat from an object that supports the array interface. -.. ocv:pyoldfunction:: cv.fromarray(array, allowND=False) -> mat - :param object: Any object that supports the array interface :param allowND: If true, will return a CvMatND @@ -1751,4 +1677,3 @@ For example, `NumPy `_ arrays support the array interfa (480, 640, 3) 1 .. note:: In the new Python wrappers (**cv2** module) the function is not needed, since cv2 can process Numpy arrays (and this is the only supported array type). - diff --git a/modules/core/doc/old_xml_yaml_persistence.rst b/modules/core/doc/old_xml_yaml_persistence.rst index bdd4c2ded4..7492213b6c 100644 --- a/modules/core/doc/old_xml_yaml_persistence.rst +++ b/modules/core/doc/old_xml_yaml_persistence.rst @@ -327,8 +327,6 @@ Loads an object from a file. .. ocv:cfunction:: void* cvLoad( const char* filename, CvMemStorage* memstorage=NULL, const char* name=NULL, const char** real_name=NULL ) -.. ocv:pyoldfunction:: cv.Load(filename, storage=None, name=None)-> generic - :param filename: File name :param memstorage: Memory storage for dynamic structures, such as :ocv:struct:`CvSeq` or :ocv:struct:`CvGraph` . It is not used for matrices or images. @@ -596,8 +594,6 @@ Saves an object to a file. .. ocv:cfunction:: void cvSave( const char* filename, const void* struct_ptr, const char* name=NULL, const char* comment=NULL, CvAttrList attributes=cvAttrList() ) -.. ocv:pyoldfunction:: cv.Save(filename, structPtr, name=None, comment=None)-> None - :param filename: File name :param struct_ptr: Object to save diff --git a/modules/core/doc/opengl_interop.rst b/modules/core/doc/opengl_interop.rst new file mode 100644 index 0000000000..5267c4d451 --- /dev/null +++ b/modules/core/doc/opengl_interop.rst @@ -0,0 +1,543 @@ +OpenGL interoperability +======================= + +.. highlight:: cpp + + + +General Information +------------------- +This section describes OpenGL interoperability. + +To enable OpenGL support, configure OpenCV using ``CMake`` with ``WITH_OPENGL=ON`` . +Currently OpenGL is supported only with WIN32, GTK and Qt backends on Windows and Linux (MacOS and Android are not supported). +For GTK backend ``gtkglext-1.0`` library is required. + +To use OpenGL functionality you should first create OpenGL context (window or frame buffer). +You can do this with :ocv:func:`namedWindow` function or with other OpenGL toolkit (GLUT, for example). + + + +ogl::Buffer +----------- +Smart pointer for OpenGL buffer object with reference counting. + +.. ocv:class:: ogl::Buffer + +Buffer Objects are OpenGL objects that store an array of unformatted memory allocated by the OpenGL context. +These can be used to store vertex data, pixel data retrieved from images or the framebuffer, and a variety of other things. + +``ogl::Buffer`` has interface similar with :ocv:class:`Mat` interface and represents 2D array memory. + +``ogl::Buffer`` supports memory transfers between host and device and also can be mapped to CUDA memory. + + + +ogl::Buffer::Target +------------------- +The target defines how you intend to use the buffer object. + +.. ocv:enum:: ogl::Buffer::Target + + .. ocv:emember:: ARRAY_BUFFER + + The buffer will be used as a source for vertex data. + + .. ocv:emember:: ELEMENT_ARRAY_BUFFER + + The buffer will be used for indices (in ``glDrawElements`` or :ocv:func:`ogl::render`, for example). + + .. ocv:emember:: PIXEL_PACK_BUFFER + + The buffer will be used for reading from OpenGL textures. + + .. ocv:emember:: PIXEL_UNPACK_BUFFER + + The buffer will be used for writing to OpenGL textures. + + + +ogl::Buffer::Buffer +------------------- +The constructors. + +.. ocv:function:: ogl::Buffer::Buffer() + +.. ocv:function:: ogl::Buffer::Buffer(int arows, int acols, int atype, unsigned int abufId, bool autoRelease = false) + +.. ocv:function:: ogl::Buffer::Buffer(Size asize, int atype, unsigned int abufId, bool autoRelease = false) + +.. ocv:function:: ogl::Buffer::Buffer(int arows, int acols, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false) + +.. ocv:function:: ogl::Buffer::Buffer(Size asize, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false) + +.. ocv:function:: ogl::Buffer::Buffer(InputArray arr, Target target = ARRAY_BUFFER, bool autoRelease = false) + + :param arows: Number of rows in a 2D array. + + :param acols: Number of columns in a 2D array. + + :param asize: 2D array size. + + :param atype: Array type ( ``CV_8UC1, ..., CV_64FC4`` ). See :ocv:class:`Mat` for details. + + :param abufId: Buffer object name. + + :param arr: Input array (host or device memory, it can be :ocv:class:`Mat` , :ocv:class:`gpu::GpuMat` or ``std::vector`` ). + + :param target: Buffer usage. See :ocv:enum:`ogl::Buffer::Target` . + + :param autoRelease: Auto release mode (if true, release will be called in object's destructor). + +Creates empty ``ogl::Buffer`` object, creates ``ogl::Buffer`` object from existed buffer ( ``abufId`` parameter), +allocates memory for ``ogl::Buffer`` object or copies from host/device memory. + + + +ogl::Buffer::create +------------------- +Allocates memory for ``ogl::Buffer`` object. + +.. ocv:function:: void ogl::Buffer::create(int arows, int acols, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false) + +.. ocv:function:: void ogl::Buffer::create(Size asize, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false) + + :param arows: Number of rows in a 2D array. + + :param acols: Number of columns in a 2D array. + + :param asize: 2D array size. + + :param atype: Array type ( ``CV_8UC1, ..., CV_64FC4`` ). See :ocv:class:`Mat` for details. + + :param target: Buffer usage. See :ocv:enum:`ogl::Buffer::Target` . + + :param autoRelease: Auto release mode (if true, release will be called in object's destructor). + + + +ogl::Buffer::release +-------------------- +Decrements the reference counter and destroys the buffer object if needed. + +.. ocv:function:: void ogl::Buffer::release() + +The function will call `setAutoRelease(true)` . + + + +ogl::Buffer::setAutoRelease +--------------------------- +Sets auto release mode. + +.. ocv:function:: void ogl::Buffer::setAutoRelease(bool flag) + + :param flag: Auto release mode (if true, release will be called in object's destructor). + +The lifetime of the OpenGL object is tied to the lifetime of the context. +If OpenGL context was bound to a window it could be released at any time (user can close a window). +If object's destructor is called after destruction of the context it will cause an error. +Thus ``ogl::Buffer`` doesn't destroy OpenGL object in destructor by default (all OpenGL resources will be released with OpenGL context). +This function can force ``ogl::Buffer`` destructor to destroy OpenGL object. + + + +ogl::Buffer::copyFrom +--------------------- +Copies from host/device memory to OpenGL buffer. + +.. ocv:function:: void ogl::Buffer::copyFrom(InputArray arr, Target target = ARRAY_BUFFER, bool autoRelease = false) + + :param arr: Input array (host or device memory, it can be :ocv:class:`Mat` , :ocv:class:`gpu::GpuMat` or ``std::vector`` ). + + :param target: Buffer usage. See :ocv:enum:`ogl::Buffer::Target` . + + :param autoRelease: Auto release mode (if true, release will be called in object's destructor). + + + +ogl::Buffer::copyTo +------------------- +Copies from OpenGL buffer to host/device memory or another OpenGL buffer object. + +.. ocv:function:: void ogl::Buffer::copyTo(OutputArray arr) const + + :param arr: Destination array (host or device memory, can be :ocv:class:`Mat` , :ocv:class:`gpu::GpuMat` , ``std::vector`` or ``ogl::Buffer`` ). + + + +ogl::Buffer::clone +------------------ +Creates a full copy of the buffer object and the underlying data. + +.. ocv:function:: Buffer ogl::Buffer::clone(Target target = ARRAY_BUFFER, bool autoRelease = false) const + + :param target: Buffer usage for destination buffer. + + :param autoRelease: Auto release mode for destination buffer. + + + +ogl::Buffer::bind +----------------- +Binds OpenGL buffer to the specified buffer binding point. + +.. ocv:function:: void ogl::Buffer::bind(Target target) const + + :param target: Binding point. See :ocv:enum:`ogl::Buffer::Target` . + + + +ogl::Buffer::unbind +------------------- +Unbind any buffers from the specified binding point. + +.. ocv:function:: static void ogl::Buffer::unbind(Target target) + + :param target: Binding point. See :ocv:enum:`ogl::Buffer::Target` . + + + +ogl::Buffer::mapHost +-------------------- +Maps OpenGL buffer to host memory. + +.. ocv:function:: Mat ogl::Buffer::mapHost(Access access) + + :param access: Access policy, indicating whether it will be possible to read from, write to, or both read from and write to the buffer object's mapped data store. The symbolic constant must be ``ogl::Buffer::READ_ONLY`` , ``ogl::Buffer::WRITE_ONLY`` or ``ogl::Buffer::READ_WRITE`` . + +``mapHost`` maps to the client's address space the entire data store of the buffer object. +The data can then be directly read and/or written relative to the returned pointer, depending on the specified ``access`` policy. + +A mapped data store must be unmapped with :ocv:func:`ogl::Buffer::unmapHost` before its buffer object is used. + +This operation can lead to memory transfers between host and device. + +Only one buffer object can be mapped at a time. + + + +ogl::Buffer::unmapHost +---------------------- +Unmaps OpenGL buffer. + +.. ocv:function:: void ogl::Buffer::unmapHost() + + + +ogl::Buffer::mapDevice +---------------------- +Maps OpenGL buffer to CUDA device memory. + +.. ocv:function:: gpu::GpuMat ogl::Buffer::mapDevice() + +This operatation doesn't copy data. +Several buffer objects can be mapped to CUDA memory at a time. + +A mapped data store must be unmapped with :ocv:func:`ogl::Buffer::unmapDevice` before its buffer object is used. + + + +ogl::Buffer::unmapDevice +------------------------ +Unmaps OpenGL buffer. + +.. ocv:function:: void ogl::Buffer::unmapDevice() + + + +ogl::Texture2D +-------------- +Smart pointer for OpenGL 2D texture memory with reference counting. + +.. ocv:class:: ogl::Texture2D + + + +ogl::Texture2D::Format +---------------------- +An Image Format describes the way that the images in Textures store their data. + +.. ocv:enum:: ogl::Texture2D::Format + + .. ocv:emember:: NONE + .. ocv:emember:: DEPTH_COMPONENT + .. ocv:emember:: RGB + .. ocv:emember:: RGBA + + + +ogl::Texture2D::Texture2D +------------------------- +The constructors. + +.. ocv:function:: ogl::Texture2D::Texture2D() + +.. ocv:function:: ogl::Texture2D::Texture2D(int arows, int acols, Format aformat, unsigned int atexId, bool autoRelease = false) + +.. ocv:function:: ogl::Texture2D::Texture2D(Size asize, Format aformat, unsigned int atexId, bool autoRelease = false) + +.. ocv:function:: ogl::Texture2D::Texture2D(int arows, int acols, Format aformat, bool autoRelease = false) + +.. ocv:function:: ogl::Texture2D::Texture2D(Size asize, Format aformat, bool autoRelease = false) + +.. ocv:function:: ogl::Texture2D::Texture2D(InputArray arr, bool autoRelease = false) + + :param arows: Number of rows. + + :param acols: Number of columns. + + :param asize: 2D array size. + + :param aformat: Image format. See :ocv:enum:`ogl::Texture2D::Format` . + + :param arr: Input array (host or device memory, it can be :ocv:class:`Mat` , :ocv:class:`gpu::GpuMat` or :ocv:class:`ogl::Buffer` ). + + :param autoRelease: Auto release mode (if true, release will be called in object's destructor). + +Creates empty ``ogl::Texture2D`` object, allocates memory for ``ogl::Texture2D`` object or copies from host/device memory. + + + +ogl::Texture2D::create +---------------------- +Allocates memory for ``ogl::Texture2D`` object. + +.. ocv:function:: void ogl::Texture2D::create(int arows, int acols, Format aformat, bool autoRelease = false) + +.. ocv:function:: void ogl::Texture2D::create(Size asize, Format aformat, bool autoRelease = false) + + :param arows: Number of rows. + + :param acols: Number of columns. + + :param asize: 2D array size. + + :param aformat: Image format. See :ocv:enum:`ogl::Texture2D::Format` . + + :param autoRelease: Auto release mode (if true, release will be called in object's destructor). + + + +ogl::Texture2D::release +----------------------- +Decrements the reference counter and destroys the texture object if needed. + +.. ocv:function:: void ogl::Texture2D::release() + +The function will call `setAutoRelease(true)` . + + + +ogl::Texture2D::setAutoRelease +------------------------------ +Sets auto release mode. + +.. ocv:function:: void ogl::Texture2D::setAutoRelease(bool flag) + + :param flag: Auto release mode (if true, release will be called in object's destructor). + +The lifetime of the OpenGL object is tied to the lifetime of the context. +If OpenGL context was bound to a window it could be released at any time (user can close a window). +If object's destructor is called after destruction of the context it will cause an error. +Thus ``ogl::Texture2D`` doesn't destroy OpenGL object in destructor by default (all OpenGL resources will be released with OpenGL context). +This function can force ``ogl::Texture2D`` destructor to destroy OpenGL object. + + + +ogl::Texture2D::copyFrom +------------------------ +Copies from host/device memory to OpenGL texture. + +.. ocv:function:: void ogl::Texture2D::copyFrom(InputArray arr, bool autoRelease = false) + + :param arr: Input array (host or device memory, it can be :ocv:class:`Mat` , :ocv:class:`gpu::GpuMat` or :ocv:class:`ogl::Buffer` ). + + :param autoRelease: Auto release mode (if true, release will be called in object's destructor). + + + +ogl::Texture2D::copyTo +---------------------- +Copies from OpenGL texture to host/device memory or another OpenGL texture object. + +.. ocv:function:: void ogl::Texture2D::copyTo(OutputArray arr, int ddepth = CV_32F, bool autoRelease = false) const + + :param arr: Destination array (host or device memory, can be :ocv:class:`Mat` , :ocv:class:`gpu::GpuMat` , :ocv:class:`ogl::Buffer` or ``ogl::Texture2D`` ). + + :param ddepth: Destination depth. + + :param autoRelease: Auto release mode for destination buffer (if ``arr`` is OpenGL buffer or texture). + + + +ogl::Texture2D::bind +-------------------- +Binds texture to current active texture unit for ``GL_TEXTURE_2D`` target. + +.. ocv:function:: void ogl::Texture2D::bind() const + + + +ogl::Arrays +----------- +Wrapper for OpenGL Client-Side Vertex arrays. + +.. ocv:class:: ogl::Arrays + +``ogl::Arrays`` stores vertex data in :ocv:class:`ogl::Buffer` objects. + + + +ogl::Arrays::setVertexArray +--------------------------- +Sets an array of vertex coordinates. + +.. ocv:function:: void ogl::Arrays::setVertexArray(InputArray vertex) + + :param vertex: array with vertex coordinates, can be both host and device memory. + + + +ogl::Arrays::resetVertexArray +----------------------------- +Resets vertex coordinates. + +.. ocv:function:: void ogl::Arrays::resetVertexArray() + + + +ogl::Arrays::setColorArray +-------------------------- +Sets an array of vertex colors. + +.. ocv:function:: void ogl::Arrays::setColorArray(InputArray color) + + :param color: array with vertex colors, can be both host and device memory. + + + +ogl::Arrays::resetColorArray +---------------------------- +Resets vertex colors. + +.. ocv:function:: void ogl::Arrays::resetColorArray() + + + +ogl::Arrays::setNormalArray +--------------------------- +Sets an array of vertex normals. + +.. ocv:function:: void ogl::Arrays::setNormalArray(InputArray normal) + + :param normal: array with vertex normals, can be both host and device memory. + + + +ogl::Arrays::resetNormalArray +----------------------------- +Resets vertex normals. + +.. ocv:function:: void ogl::Arrays::resetNormalArray() + + + +ogl::Arrays::setTexCoordArray +----------------------------- +Sets an array of vertex texture coordinates. + +.. ocv:function:: void ogl::Arrays::setTexCoordArray(InputArray texCoord) + + :param texCoord: array with vertex texture coordinates, can be both host and device memory. + + + +ogl::Arrays::resetTexCoordArray +------------------------------- +Resets vertex texture coordinates. + +.. ocv:function:: void ogl::Arrays::resetTexCoordArray() + + + +ogl::Arrays::release +-------------------- +Releases all inner buffers. + +.. ocv:function:: void ogl::Arrays::release() + + + +ogl::Arrays::setAutoRelease +--------------------------- +Sets auto release mode all inner buffers. + +.. ocv:function:: void ogl::Arrays::setAutoRelease(bool flag) + + :param flag: Auto release mode. + + + +ogl::Arrays::bind +----------------- +Binds all vertex arrays. + +.. ocv:function:: void ogl::Arrays::bind() const + + + +ogl::Arrays::size +----------------- +Returns the vertex count. + +.. ocv:function:: int ogl::Arrays::size() const + + + +ogl::render +----------- +Render OpenGL texture or primitives. + +.. ocv:function:: void ogl::render(const Texture2D& tex, Rect_ wndRect = Rect_(0.0, 0.0, 1.0, 1.0), Rect_ texRect = Rect_(0.0, 0.0, 1.0, 1.0)) + +.. ocv:function:: void ogl::render(const Arrays& arr, int mode = POINTS, Scalar color = Scalar::all(255)) + +.. ocv:function:: void ogl::render(const Arrays& arr, InputArray indices, int mode = POINTS, Scalar color = Scalar::all(255)) + + :param tex: Texture to draw. + + :param wndRect: Region of window, where to draw a texture (normalized coordinates). + + :param texRect: Region of texture to draw (normalized coordinates). + + :param arr: Array of privitives vertices. + + :param indices: Array of vertices indices (host or device memory). + + :param mode: Render mode. Available options: + + * **POINTS** + * **LINES** + * **LINE_LOOP** + * **LINE_STRIP** + * **TRIANGLES** + * **TRIANGLE_STRIP** + * **TRIANGLE_FAN** + * **QUADS** + * **QUAD_STRIP** + * **POLYGON** + + :param color: Color for all vertices. Will be used if ``arr`` doesn't contain color array. + + + +gpu::setGlDevice +---------------- +Sets a CUDA device and initializes it for the current thread with OpenGL interoperability. + +.. ocv:function:: void gpu::setGlDevice( int device = 0 ) + + :param device: System index of a GPU device starting with 0. + +This function should be explicitly called after OpenGL context creation and before any CUDA calls. diff --git a/modules/core/doc/operations_on_arrays.rst b/modules/core/doc/operations_on_arrays.rst index 64ca686184..d38f57ac33 100644 --- a/modules/core/doc/operations_on_arrays.rst +++ b/modules/core/doc/operations_on_arrays.rst @@ -36,8 +36,6 @@ Calculates the per-element absolute difference between two arrays or between an .. ocv:cfunction:: void cvAbsDiff(const CvArr* src1, const CvArr* src2, CvArr* dst) .. ocv:cfunction:: void cvAbsDiffS(const CvArr* src, CvArr* dst, CvScalar value) -.. ocv:pyoldfunction:: cv.AbsDiff(src1, src2, dst)-> None -.. ocv:pyoldfunction:: cv.AbsDiffS(src, dst, value)-> None :param src1: first input array or a scalar. @@ -90,8 +88,6 @@ Calculates the per-element sum of two arrays or an array and a scalar. .. ocv:cfunction:: void cvAdd(const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL) .. ocv:cfunction:: void cvAddS(const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL) -.. ocv:pyoldfunction:: cv.Add(src1, src2, dst, mask=None)-> None -.. ocv:pyoldfunction:: cv.AddS(src, value, dst, mask=None)-> None :param src1: first input array or a scalar. @@ -103,7 +99,7 @@ Calculates the per-element sum of two arrays or an array and a scalar. :param dst: output array that has the same size and number of channels as the input array(s); the depth is defined by ``dtype`` or ``src1``/``src2``. - :param mask: optional operation mask – 8-bit single channel array, that specifies elements of the output array to be changed. + :param mask: optional operation mask - 8-bit single channel array, that specifies elements of the output array to be changed. :param dtype: optional depth of the output array (see the discussion below). @@ -160,7 +156,6 @@ Calculates the weighted sum of two arrays. .. ocv:pyfunction:: cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) -> dst .. ocv:cfunction:: void cvAddWeighted(const CvArr* src1, double alpha, const CvArr* src2, double beta, double gamma, CvArr* dst) -.. ocv:pyoldfunction:: cv.AddWeighted(src1, alpha, src2, beta, gamma, dst)-> None :param src1: first input array. @@ -210,8 +205,6 @@ Calculates the per-element bit-wise conjunction of two arrays or an array and a .. ocv:cfunction:: void cvAnd(const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL) .. ocv:cfunction:: void cvAndS(const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL) -.. ocv:pyoldfunction:: cv.And(src1, src2, dst, mask=None)-> None -.. ocv:pyoldfunction:: cv.AndS(src, value, dst, mask=None)-> None :param src1: first input array or a scalar. @@ -262,7 +255,6 @@ Inverts every bit of an array. .. ocv:pyfunction:: cv2.bitwise_not(src[, dst[, mask]]) -> dst .. ocv:cfunction:: void cvNot(const CvArr* src, CvArr* dst) -.. ocv:pyoldfunction:: cv.Not(src, dst)-> None :param src: input array. @@ -290,8 +282,6 @@ Calculates the per-element bit-wise disjunction of two arrays or an array and a .. ocv:cfunction:: void cvOr(const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL) .. ocv:cfunction:: void cvOrS(const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL) -.. ocv:pyoldfunction:: cv.Or(src1, src2, dst, mask=None)-> None -.. ocv:pyoldfunction:: cv.OrS(src, value, dst, mask=None)-> None :param src1: first input array or a scalar. @@ -342,8 +332,6 @@ Calculates the per-element bit-wise "exclusive or" operation on two arrays or an .. ocv:cfunction:: void cvXor(const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL) .. ocv:cfunction:: void cvXorS(const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL) -.. ocv:pyoldfunction:: cv.Xor(src1, src2, dst, mask=None)-> None -.. ocv:pyoldfunction:: cv.XorS(src, value, dst, mask=None)-> None :param src1: first input array or a scalar. @@ -396,8 +384,6 @@ Calculates the covariance matrix of a set of vectors. .. ocv:cfunction:: void cvCalcCovarMatrix( const CvArr** vects, int count, CvArr* cov_mat, CvArr* avg, int flags ) -.. ocv:pyoldfunction:: cv.CalcCovarMatrix(vects, covMat, avg, flags)-> None - :param samples: samples stored either as separate matrices or as rows/columns of a single matrix. :param nsamples: number of samples when they are stored separately. @@ -456,8 +442,6 @@ Calculates the magnitude and angle of 2D vectors. .. ocv:cfunction:: void cvCartToPolar( const CvArr* x, const CvArr* y, CvArr* magnitude, CvArr* angle=NULL, int angle_in_degrees=0 ) -.. ocv:pyoldfunction:: cv.CartToPolar(x, y, magnitude, angle=None, angleInDegrees=0)-> None - :param x: array of x-coordinates; this must be a single-precision or double-precision floating-point array. :param y: array of y-coordinates, that must have the same size and same type as ``x``. @@ -518,12 +502,8 @@ Performs the per-element comparison of two arrays or an array and scalar value. .. ocv:cfunction:: void cvCmp( const CvArr* src1, const CvArr* src2, CvArr* dst, int cmp_op ) -.. ocv:pyoldfunction:: cv.Cmp(src1, src2, dst, cmpOp)-> None - .. ocv:cfunction:: void cvCmpS( const CvArr* src, double value, CvArr* dst, int cmp_op ) -.. ocv:pyoldfunction:: cv.CmpS(src, value, dst, cmpOp)-> None - :param src1: first input array or a scalar (in the case of ``cvCmp``, ``cv.Cmp``, ``cvCmpS``, ``cv.CmpS`` it is always an array); when it is an array, it must have a single channel. :param src2: second input array or a scalar (in the case of ``cvCmp`` and ``cv.Cmp`` it is always an array; in the case of ``cvCmpS``, ``cv.CmpS`` it is always a scalar); when it is an array, it must have a single channel. @@ -532,7 +512,7 @@ Performs the per-element comparison of two arrays or an array and scalar value. :param value: scalar value. - :param dst: output array that has the same size as the input arrays and type= ``CV_8UC1`` . + :param dst: output array that has the same size and type as the input arrays. :param cmpop: a flag, that specifies correspondence between the arrays: @@ -624,7 +604,6 @@ Scales, calculates absolute values, and converts the result to 8-bit. .. ocv:pyfunction:: cv2.convertScaleAbs(src[, dst[, alpha[, beta]]]) -> dst .. ocv:cfunction:: void cvConvertScaleAbs(const CvArr* src, CvArr* dst, double scale=1, double shift=0) -.. ocv:pyoldfunction:: cv.ConvertScaleAbs(src, dst, scale=1.0, shift=0.0)-> None :param src: input array. @@ -668,8 +647,6 @@ Counts non-zero array elements. .. ocv:cfunction:: int cvCountNonZero(const CvArr* arr) -.. ocv:pyoldfunction:: cv.CountNonZero(arr)-> int - :param src: single-channel array. The function returns the number of non-zero elements in ``src`` : @@ -760,7 +737,6 @@ Performs a forward or inverse discrete Cosine transform of 1D or 2D array. .. ocv:pyfunction:: cv2.dct(src[, dst[, flags]]) -> dst .. ocv:cfunction:: void cvDCT(const CvArr* src, CvArr* dst, int flags) -.. ocv:pyoldfunction:: cv.DCT(src, dst, flags)-> None :param src: input floating-point array. @@ -855,8 +831,6 @@ Performs a forward or inverse Discrete Fourier transform of a 1D or 2D floating- .. ocv:cfunction:: void cvDFT( const CvArr* src, CvArr* dst, int flags, int nonzero_rows=0 ) -.. ocv:pyoldfunction:: cv.DFT(src, dst, flags, nonzeroRows=0)-> None - :param src: input array that could be real or complex. :param dst: output array whose size and type depends on the ``flags`` . @@ -868,7 +842,7 @@ Performs a forward or inverse Discrete Fourier transform of a 1D or 2D floating- * **DFT_SCALE** scales the result: divide it by the number of array elements. Normally, it is combined with ``DFT_INVERSE``. * **DFT_ROWS** performs a forward or inverse transform of every individual row of the input matrix; this flag enables you to transform multiple vectors simultaneously and can be used to decrease the overhead (which is sometimes several times larger than the processing itself) to perform 3D and higher-dimensional transformations and so forth. - * **DFT_COMPLEX_OUTPUT** performs a forward transformation of 1D or 2D real array; the result, though being a complex array, has complex-conjugate symmetry (*CCS*, see the function description below for details), and such an array can be packed into a real array of the same size as input, which is the fastest option and which is what the function does by default; however, you may wish to get a full complex array (for simpler spectrum analysis, and so on) – pass the flag to enable the function to produce a full-size complex output array. + * **DFT_COMPLEX_OUTPUT** performs a forward transformation of 1D or 2D real array; the result, though being a complex array, has complex-conjugate symmetry (*CCS*, see the function description below for details), and such an array can be packed into a real array of the same size as input, which is the fastest option and which is what the function does by default; however, you may wish to get a full complex array (for simpler spectrum analysis, and so on) - pass the flag to enable the function to produce a full-size complex output array. * **DFT_REAL_OUTPUT** performs an inverse transformation of a 1D or 2D complex array; the result is normally a complex array of the same size, however, if the input array has conjugate-complex symmetry (for example, it is a result of forward transformation with ``DFT_COMPLEX_OUTPUT`` flag), the output is a real array; while the function itself does not check whether the input is symmetrical or not, you can pass the flag and then the function will assume the symmetry and produce the real output array (note that when the input is packed into a real array and inverse transformation is executed, the function treats the input as a packed complex-conjugate symmetrical array, and the output will also be a real array). @@ -997,6 +971,12 @@ All of the above improvements have been implemented in :ocv:func:`matchTemplate` .. seealso:: :ocv:func:`dct` , :ocv:func:`getOptimalDFTSize` , :ocv:func:`mulSpectrums`, :ocv:func:`filter2D` , :ocv:func:`matchTemplate` , :ocv:func:`flip` , :ocv:func:`cartToPolar` , :ocv:func:`magnitude` , :ocv:func:`phase` +.. note:: + + * An example using the discrete fourier transform can be found at opencv_source_code/samples/cpp/dft.cpp + + * (Python) An example using the dft functionality to perform Wiener deconvolution can be found at opencv_source/samples/python2/deconvolution.py + * (Python) An example rearranging the quadrants of a Fourier image can be found at opencv_source/samples/python2/dft.py divide @@ -1011,7 +991,6 @@ Performs per-element division of two arrays or a scalar by an array. .. ocv:pyfunction:: cv2.divide(scale, src2[, dst[, dtype]]) -> dst .. ocv:cfunction:: void cvDiv(const CvArr* src1, const CvArr* src2, CvArr* dst, double scale=1) -.. ocv:pyoldfunction:: cv.Div(src1, src2, dst, scale=1) -> None :param src1: first input array. @@ -1058,10 +1037,10 @@ Returns the determinant of a square floating-point matrix. .. ocv:cfunction:: double cvDet( const CvArr* mat ) -.. ocv:pyoldfunction:: cv.Det(mat) -> float - :param mtx: input matrix that must have ``CV_32FC1`` or ``CV_64FC1`` type and square size. + :param mat: input matrix that must have ``CV_32FC1`` or ``CV_64FC1`` type and square size. + The function ``determinant`` calculates and returns the determinant of the specified matrix. For small matrices ( ``mtx.cols=mtx.rows<=3`` ), the direct method is used. For larger matrices, the function uses LU factorization with partial pivoting. @@ -1081,16 +1060,12 @@ eigen ----- Calculates eigenvalues and eigenvectors of a symmetric matrix. -.. ocv:function:: bool eigen(InputArray src, OutputArray eigenvalues, int lowindex=-1, int highindex=-1) +.. ocv:function:: bool eigen( InputArray src, OutputArray eigenvalues, OutputArray eigenvectors=noArray() ) -.. ocv:function:: bool eigen(InputArray src, OutputArray eigenvalues, OutputArray eigenvectors, int lowindex=-1,int highindex=-1) - -.. ocv:pyfunction:: cv2.eigen(src, computeEigenvectors[, eigenvalues[, eigenvectors]]) -> retval, eigenvalues, eigenvectors +.. ocv:pyfunction:: cv2.eigen(src[, eigenvalues[, eigenvectors]]) -> retval, eigenvalues, eigenvectors .. ocv:cfunction:: void cvEigenVV( CvArr* mat, CvArr* evects, CvArr* evals, double eps=0, int lowindex=-1, int highindex=-1 ) -.. ocv:pyoldfunction:: cv.EigenVV(mat, evects, evals, eps, lowindex=-1, highindex=-1)-> None - :param src: input matrix that must have ``CV_32FC1`` or ``CV_64FC1`` type, square size and be symmetrical (``src`` :sup:`T` == ``src``). :param eigenvalues: output vector of eigenvalues of the same type as ``src``; the eigenvalues are stored in the descending order. @@ -1120,7 +1095,6 @@ Calculates the exponent of every array element. .. ocv:pyfunction:: cv2.exp(src[, dst]) -> dst .. ocv:cfunction:: void cvExp(const CvArr* src, CvArr* dst) -.. ocv:pyoldfunction:: cv.Exp(src, dst)-> None :param src: input array. @@ -1201,8 +1175,6 @@ Flips a 2D array around vertical, horizontal, or both axes. .. ocv:cfunction:: void cvFlip( const CvArr* src, CvArr* dst=NULL, int flip_mode=0 ) -.. ocv:pyoldfunction:: cv.Flip(src, dst=None, flipMode=0)-> None - :param src: input array. :param dst: output array of the same size and type as ``src``. @@ -1249,7 +1221,6 @@ Performs generalized matrix multiplication. .. ocv:pyfunction:: cv2.gemm(src1, src2, alpha, src3, gamma[, dst[, flags]]) -> dst .. ocv:cfunction:: void cvGEMM( const CvArr* src1, const CvArr* src2, double alpha, const CvArr* src3, double beta, CvArr* dst, int tABC=0) -.. ocv:pyoldfunction:: cv.GEMM(src1, src2, alpha, src3, beta, dst, tABC=0)-> None :param src1: first multiplied input matrix that should have ``CV_32FC1``, ``CV_64FC1``, ``CV_32FC2``, or ``CV_64FC2`` type. @@ -1284,40 +1255,6 @@ The function can be replaced with a matrix expression. For example, the above ca -getConvertElem --------------- -Returns a conversion function for a single pixel. - -.. ocv:function:: ConvertData getConvertElem(int fromType, int toType) - -.. ocv:function:: ConvertScaleData getConvertScaleElem(int fromType, int toType) - - :param fromType: input pixel type. - - :param toType: output pixel type. - - :param from: callback parameter: pointer to the input pixel. - - :param to: callback parameter: pointer to the output pixel - - :param cn: callback parameter: the number of channels; it can be arbitrary, 1, 100, 100000, etc. - - :param alpha: ``ConvertScaleData`` callback optional parameter: the scale factor. - - :param beta: ``ConvertScaleData`` callback optional parameter: the delta or offset. - -The functions ``getConvertElem`` and ``getConvertScaleElem`` return pointers to the functions for converting individual pixels from one type to another. While the main function purpose is to convert single pixels (actually, for converting sparse matrices from one type to another), you can use them to convert the whole row of a dense matrix or the whole matrix at once, by setting ``cn = matrix.cols*matrix.rows*matrix.channels()`` if the matrix data is continuous. - -``ConvertData`` and ``ConvertScaleData`` are defined as: :: - - typedef void (*ConvertData)(const void* from, void* to, int cn) - typedef void (*ConvertScaleData)(const void* from, void* to, - int cn, double alpha, double beta) - -.. seealso:: :ocv:func:`Mat::convertTo` , :ocv:func:`SparseMat::convertTo` - - - getOptimalDFTSize ----------------- Returns the optimal DFT size for a given vector size. @@ -1327,7 +1264,6 @@ Returns the optimal DFT size for a given vector size. .. ocv:pyfunction:: cv2.getOptimalDFTSize(vecsize) -> retval .. ocv:cfunction:: int cvGetOptimalDFTSize(int size0) -.. ocv:pyoldfunction:: cv.GetOptimalDFTSize(size0)-> int :param vecsize: vector size. @@ -1411,8 +1347,6 @@ Checks if array elements lie between the elements of two other arrays. .. ocv:cfunction:: void cvInRange(const CvArr* src, const CvArr* lower, const CvArr* upper, CvArr* dst) .. ocv:cfunction:: void cvInRangeS(const CvArr* src, CvScalar lower, CvScalar upper, CvArr* dst) -.. ocv:pyoldfunction:: cv.InRange(src, lower, upper, dst)-> None -.. ocv:pyoldfunction:: cv.InRangeS(src, lower, upper, dst)-> None :param src: first input array. @@ -1453,8 +1387,6 @@ Finds the inverse or pseudo-inverse of a matrix. .. ocv:cfunction:: double cvInvert( const CvArr* src, CvArr* dst, int method=CV_LU ) -.. ocv:pyoldfunction:: cv.Invert(src, dst, method=CV_LU) -> float - :param src: input floating-point ``M x N`` matrix. :param dst: output matrix of ``N x M`` size and the same type as ``src``. @@ -1492,7 +1424,6 @@ Calculates the natural logarithm of every array element. .. ocv:pyfunction:: cv2.log(src[, dst]) -> dst .. ocv:cfunction:: void cvLog(const CvArr* src, CvArr* dst) -.. ocv:pyoldfunction:: cv.Log(src, dst)-> None :param src: input array. @@ -1523,12 +1454,11 @@ LUT --- Performs a look-up table transform of an array. -.. ocv:function:: void LUT( InputArray src, InputArray lut, OutputArray dst, int interpolation=0 ) +.. ocv:function:: void LUT( InputArray src, InputArray lut, OutputArray dst ) -.. ocv:pyfunction:: cv2.LUT(src, lut[, dst[, interpolation]]) -> dst +.. ocv:pyfunction:: cv2.LUT(src, lut[, dst]) -> dst .. ocv:cfunction:: void cvLUT(const CvArr* src, CvArr* dst, const CvArr* lut) -.. ocv:pyoldfunction:: cv.LUT(src, dst, lut)-> None :param src: input array of 8-bit elements. @@ -1594,8 +1524,6 @@ Calculates the Mahalanobis distance between two vectors. .. ocv:cfunction:: double cvMahalanobis( const CvArr* vec1, const CvArr* vec2, const CvArr* mat ) -.. ocv:pyoldfunction:: cv.Mahalonobis(vec1, vec2, mat) -> None - :param vec1: first 1D input vector. :param vec2: second 1D input vector. @@ -1628,14 +1556,10 @@ Calculates per-element maximum of two arrays or an array and a scalar. .. ocv:function:: void max(const Mat& src1, const Mat& src2, Mat& dst) -.. ocv:function:: void max( const Mat& src1, double src2, Mat& dst ) - .. ocv:pyfunction:: cv2.max(src1, src2[, dst]) -> dst .. ocv:cfunction:: void cvMax(const CvArr* src1, const CvArr* src2, CvArr* dst) .. ocv:cfunction:: void cvMaxS(const CvArr* src, double value, CvArr* dst) -.. ocv:pyoldfunction:: cv.Max(src1, src2, dst)-> None -.. ocv:pyoldfunction:: cv.MaxS(src, value, dst)-> None :param src1: first input array. @@ -1681,8 +1605,6 @@ Calculates an average (mean) of array elements. .. ocv:cfunction:: CvScalar cvAvg( const CvArr* arr, const CvArr* mask=NULL ) -.. ocv:pyoldfunction:: cv.Avg(arr, mask=None) -> scalar - :param src: input array that should have from 1 to 4 channels so that the result can be stored in :ocv:class:`Scalar_` . :param mask: optional operation mask. @@ -1714,8 +1636,6 @@ Calculates a mean and standard deviation of array elements. .. ocv:cfunction:: void cvAvgSdv( const CvArr* arr, CvScalar* mean, CvScalar* std_dev, const CvArr* mask=NULL ) -.. ocv:pyoldfunction:: cv.AvgSdv(arr, mask=None) -> (mean, stdDev) - :param src: input array that should have from 1 to 4 channels so that the results can be stored in :ocv:class:`Scalar_` 's. :param mean: output parameter: calculated mean value. @@ -1755,7 +1675,6 @@ Creates one multichannel array out of several single-channel ones. .. ocv:pyfunction:: cv2.merge(mv[, dst]) -> dst .. ocv:cfunction:: void cvMerge(const CvArr* src0, const CvArr* src1, const CvArr* src2, const CvArr* src3, CvArr* dst) -.. ocv:pyoldfunction:: cv.Merge(src0, src1, src2, src3, dst)-> None :param mv: input array or vector of matrices to be merged; all the matrices in ``mv`` must have the same size and the same depth. @@ -1791,14 +1710,10 @@ Calculates per-element minimum of two arrays or an array and a scalar. .. ocv:function:: void min(const Mat& src1, const Mat& src2, Mat& dst) -.. ocv:function:: void min( const Mat& src1, double src2, Mat& dst ) - .. ocv:pyfunction:: cv2.min(src1, src2[, dst]) -> dst .. ocv:cfunction:: void cvMin(const CvArr* src1, const CvArr* src2, CvArr* dst) .. ocv:cfunction:: void cvMinS(const CvArr* src, double value, CvArr* dst) -.. ocv:pyoldfunction:: cv.Min(src1, src2, dst)-> None -.. ocv:pyoldfunction:: cv.MinS(src, value, dst)-> None :param src1: first input array. @@ -1838,7 +1753,7 @@ minMaxIdx --------- Finds the global minimum and maximum in an array -.. ocv:function:: void minMaxIdx(InputArray src, double* minVal, double* maxVal, int* minIdx=0, int* maxIdx=0, InputArray mask=noArray()) +.. ocv:function:: void minMaxIdx(InputArray src, double* minVal, double* maxVal = 0, int* minIdx=0, int* maxIdx=0, InputArray mask=noArray()) :param src: input single-channel array. @@ -1878,8 +1793,6 @@ Finds the global minimum and maximum in an array. .. ocv:cfunction:: void cvMinMaxLoc( const CvArr* arr, double* min_val, double* max_val, CvPoint* min_loc=NULL, CvPoint* max_loc=NULL, const CvArr* mask=NULL ) -.. ocv:pyoldfunction:: cv.MinMaxLoc(arr, mask=None)-> (minVal, maxVal, minLoc, maxLoc) - :param src: input single-channel array. :param minVal: pointer to the returned minimum value; ``NULL`` is used if not required. @@ -1920,14 +1833,14 @@ Copies specified channels from input arrays to the specified channels of output .. ocv:function:: void mixChannels( const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, const int* fromTo, size_t npairs ) -.. ocv:function:: void mixChannels( const vector& src, vector& dst, const int* fromTo, size_t npairs ) +.. ocv:function:: void mixChannels( InputArrayOfArrays src, InputOutputArrayOfArrays dst, const int* fromTo, size_t npairs ) -.. ocv:pyfunction:: cv2.mixChannels(src, dst, fromTo) -> None +.. ocv:function:: void mixChannels( InputArrayOfArrays src, InputOutputArrayOfArrays dst, const std::vector& fromTo ) + +.. ocv:pyfunction:: cv2.mixChannels(src, dst, fromTo) -> dst .. ocv:cfunction:: void cvMixChannels( const CvArr** src, int src_count, CvArr** dst, int dst_count, const int* from_to, int pair_count ) -.. ocv:pyoldfunction:: cv.MixChannels(src, dst, fromTo) -> None - :param src: input array or vector of matricesl; all of the matrices must have the same size and the same depth. :param nsrcs: number of matrices in ``src``. @@ -1980,7 +1893,6 @@ Performs the per-element multiplication of two Fourier spectrums. .. ocv:pyfunction:: cv2.mulSpectrums(a, b, flags[, c[, conjB]]) -> c .. ocv:cfunction:: void cvMulSpectrums( const CvArr* src1, const CvArr* src2, CvArr* dst, int flags) -.. ocv:pyoldfunction:: cv.MulSpectrums(src1, src2, dst, flags)-> None :param src1: first input array. @@ -2010,7 +1922,6 @@ Calculates the per-element scaled product of two arrays. .. ocv:pyfunction:: cv2.multiply(src1, src2[, dst[, scale[, dtype]]]) -> dst .. ocv:cfunction:: void cvMul(const CvArr* src1, const CvArr* src2, CvArr* dst, double scale=1) -.. ocv:pyoldfunction:: cv.Mul(src1, src2, dst, scale=1) -> None :param src1: first input array. @@ -2060,8 +1971,6 @@ Calculates the product of a matrix and its transposition. .. ocv:cfunction:: void cvMulTransposed( const CvArr* src, CvArr* dst, int order, const CvArr* delta=NULL, double scale=1. ) -.. ocv:pyoldfunction:: cv.MulTransposed(src, dst, order, delta=None, scale=1.0) -> None - :param src: input single-channel matrix. Note that unlike :ocv:func:`gemm`, the function can multiply not only floating-point matrices. :param dst: output square matrix. @@ -2112,8 +2021,6 @@ Calculates an absolute array norm, an absolute difference norm, or a relative di .. ocv:cfunction:: double cvNorm( const CvArr* arr1, const CvArr* arr2=NULL, int norm_type=CV_L2, const CvArr* mask=NULL ) -.. ocv:pyoldfunction:: cv.Norm(arr1, arr2, normType=CV_L2, mask=None) -> float - :param src1: first input array. :param src2: second input array of the same size and the same type as ``src1``. @@ -2260,7 +2167,9 @@ The sample below is the function that takes two matrices. The first function sto :ocv:func:`dft`, :ocv:func:`dct` +.. note:: + * An example using PCA for dimensionality reduction while maintaining an amount of variance can be found at opencv_source_code/samples/cpp/pca.cpp PCA::PCA -------- @@ -2369,7 +2278,6 @@ Performs the perspective matrix transformation of vectors. .. ocv:pyfunction:: cv2.perspectiveTransform(src, m[, dst]) -> dst .. ocv:cfunction:: void cvPerspectiveTransform(const CvArr* src, CvArr* dst, const CvMat* mat) -.. ocv:pyoldfunction:: cv.PerspectiveTransform(src, dst, mat)-> None :param src: input two-channel or three-channel floating-point array; each element is a 2D/3D vector to be transformed. @@ -2443,8 +2351,6 @@ Calculates x and y coordinates of 2D vectors from their magnitude and angle. .. ocv:cfunction:: void cvPolarToCart( const CvArr* magnitude, const CvArr* angle, CvArr* x, CvArr* y, int angle_in_degrees=0 ) -.. ocv:pyoldfunction:: cv.PolarToCart(magnitude, angle, x, y, angleInDegrees=0)-> None - :param magnitude: input floating-point array of magnitudes of 2D vectors; it can be an empty matrix (``=Mat()``), in this case, the function assumes that all the magnitudes are =1; if it is not empty, it must have the same size and type as ``angle``. :param angle: input floating-point array of angles of 2D vectors. @@ -2484,7 +2390,6 @@ Raises every array element to a power. .. ocv:pyfunction:: cv2.pow(src, power[, dst]) -> dst .. ocv:cfunction:: void cvPow( const CvArr* src, CvArr* dst, double power) -.. ocv:pyoldfunction:: cv.Pow(src, dst, power)-> None :param src: input array. @@ -2752,7 +2657,6 @@ Reduces a matrix to a vector. .. ocv:pyfunction:: cv2.reduce(src, dim, rtype[, dst[, dtype]]) -> dst .. ocv:cfunction:: void cvReduce(const CvArr* src, CvArr* dst, int dim=-1, int op=CV_REDUCE_SUM) -.. ocv:pyoldfunction:: cv.Reduce(src, dst, dim=-1, op=CV_REDUCE_SUM)-> None :param src: input 2D matrix. @@ -2790,8 +2694,6 @@ Fills the output array with repeated copies of the input array. .. ocv:cfunction:: void cvRepeat(const CvArr* src, CvArr* dst) -.. ocv:pyoldfunction:: cv.Repeat(src, dst)-> None - :param src: input array to replicate. :param dst: output array of the same type as ``src``. @@ -2826,7 +2728,6 @@ Calculates the sum of a scaled array and another array. .. ocv:pyfunction:: cv2.scaleAdd(src1, alpha, src2[, dst]) -> dst .. ocv:cfunction:: void cvScaleAdd(const CvArr* src1, CvScalar scale, const CvArr* src2, CvArr* dst) -.. ocv:pyoldfunction:: cv.ScaleAdd(src1, scale, src2, dst)-> None :param src1: first input array. @@ -2870,8 +2771,6 @@ Initializes a scaled identity matrix. .. ocv:cfunction:: void cvSetIdentity(CvArr* mat, CvScalar value=cvRealScalar(1)) -.. ocv:pyoldfunction:: cv.SetIdentity(mat, value=1)-> None - :param mtx: matrix to initialize (not necessarily square). :param value: value to assign to diagonal elements. @@ -2908,7 +2807,6 @@ Solves one or more linear systems or least-squares problems. .. ocv:pyfunction:: cv2.solve(src1, src2[, dst[, flags]]) -> retval, dst .. ocv:cfunction:: int cvSolve(const CvArr* src1, const CvArr* src2, CvArr* dst, int method=CV_LU) -.. ocv:pyoldfunction:: cv.Solve(A, B, X, method=CV_LU)-> None :param src1: input matrix on the left-hand side of the system. @@ -2959,8 +2857,6 @@ Finds the real roots of a cubic equation. .. ocv:cfunction:: int cvSolveCubic( const CvMat* coeffs, CvMat* roots ) -.. ocv:pyoldfunction:: cv.SolveCubic(coeffs, roots)-> None - :param coeffs: equation coefficients, an array of 3 or 4 elements. :param roots: output array of real roots that has 1 or 3 elements. @@ -3086,8 +2982,6 @@ Divides a multi-channel array into several single-channel arrays. .. ocv:cfunction:: void cvSplit(const CvArr* src, CvArr* dst0, CvArr* dst1, CvArr* dst2, CvArr* dst3) -.. ocv:pyoldfunction:: cv.Split(src, dst0, dst1, dst2, dst3)-> None - :param src: input multi-channel array. :param mv: output array or vector of arrays; in the first variant of the function the number of arrays must match ``src.channels()``; the arrays themselves are reallocated, if needed. @@ -3118,7 +3012,6 @@ Calculates a square root of array elements. .. ocv:pyfunction:: cv2.sqrt(src[, dst]) -> dst .. ocv:cfunction:: float cvSqrt(float value) -.. ocv:pyoldfunction:: cv.Sqrt(value)-> float :param src: input floating-point array. @@ -3145,10 +3038,6 @@ Calculates the per-element difference between two arrays or array and a scalar. .. ocv:cfunction:: void cvSubRS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL ) .. ocv:cfunction:: void cvSubS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL ) -.. ocv:pyoldfunction:: cv.Sub(src1, src2, dst, mask=None) -> None -.. ocv:pyoldfunction:: cv.SubRS(src, value, dst, mask=None) -> None -.. ocv:pyoldfunction:: cv.SubS(src, value, dst, mask=None) -> None - :param src1: first input array or a scalar. :param src2: second input array or a scalar. @@ -3281,8 +3170,6 @@ Performs SVD of a matrix .. ocv:cfunction:: void cvSVD( CvArr* A, CvArr* W, CvArr* U=NULL, CvArr* V=NULL, int flags=0 ) -.. ocv:pyoldfunction:: cv.SVD(A, W, U=None, V=None, flags=0) -> None - :param src: decomposed matrix :param w: calculated singular values @@ -3331,8 +3218,6 @@ Performs a singular value back substitution. .. ocv:cfunction:: void cvSVBkSb( const CvArr* W, const CvArr* U, const CvArr* V, const CvArr* B, CvArr* X, int flags ) -.. ocv:pyoldfunction:: cv.SVBkSb(W, U, V, B, X, flags) -> None - :param w: singular values :param u: left singular vectors @@ -3367,8 +3252,6 @@ Calculates the sum of array elements. .. ocv:cfunction:: CvScalar cvSum(const CvArr* arr) -.. ocv:pyoldfunction:: cv.Sum(arr) -> scalar - :param arr: input array that must have from 1 to 4 channels. The functions ``sum`` calculate and return the sum of array elements, independently for each channel. @@ -3412,8 +3295,6 @@ Returns the trace of a matrix. .. ocv:cfunction:: CvScalar cvTrace(const CvArr* mat) -.. ocv:pyoldfunction:: cv.Trace(mat) -> scalar - :param mat: input matrix. The function ``trace`` returns the sum of the diagonal elements of the matrix ``mtx`` . @@ -3434,8 +3315,6 @@ Performs the matrix transformation of every array element. .. ocv:cfunction:: void cvTransform( const CvArr* src, CvArr* dst, const CvMat* transmat, const CvMat* shiftvec=NULL ) -.. ocv:pyoldfunction:: cv.Transform(src, dst, transmat, shiftvec=None)-> None - :param src: input array that must have as many channels (1 to 4) as ``m.cols`` or ``m.cols-1``. :param dst: output array of the same size and depth as ``src``; it has as many channels as ``m.rows``. @@ -3485,7 +3364,6 @@ Transposes a matrix. .. ocv:pyfunction:: cv2.transpose(src[, dst]) -> dst .. ocv:cfunction:: void cvTranspose(const CvArr* src, CvArr* dst) -.. ocv:pyoldfunction:: cv.Transpose(src, dst)-> None :param src: input array. @@ -3498,3 +3376,101 @@ The function :ocv:func:`transpose` transposes the matrix ``src`` : \texttt{dst} (i,j) = \texttt{src} (j,i) .. note:: No complex conjugation is done in case of a complex matrix. It it should be done separately if needed. + + +borderInterpolate +----------------- +Computes the source location of an extrapolated pixel. + +.. ocv:function:: int borderInterpolate( int p, int len, int borderType ) + +.. ocv:pyfunction:: cv2.borderInterpolate(p, len, borderType) -> retval + + :param p: 0-based coordinate of the extrapolated pixel along one of the axes, + likely <0 or >= ``len`` . + + :param len: Length of the array along the corresponding axis. + + :param borderType: Border type, one of the ``BORDER_*`` , except for ``BORDER_TRANSPARENT`` + and ``BORDER_ISOLATED`` . When ``borderType==BORDER_CONSTANT`` , the + function always returns -1, regardless of ``p`` and ``len`` . + +The function computes and returns the coordinate of a donor pixel corresponding to the specified +extrapolated pixel when using the specified extrapolation border mode. For example, if you use +``BORDER_WRAP`` mode in the horizontal direction, ``BORDER_REFLECT_101`` in the vertical direction +and want to compute value of the "virtual" pixel ``Point(-5, 100)`` in a floating-point image +``img`` , it looks like: :: + + float val = img.at(borderInterpolate(100, img.rows, BORDER_REFLECT_101), + borderInterpolate(-5, img.cols, BORDER_WRAP)); + + +Normally, the function is not called directly. It is used inside :ocv:class:`FilterEngine` +and :ocv:func:`copyMakeBorder` to compute tables for quick extrapolation. + +.. seealso:: + + :ocv:class:`FilterEngine`, + :ocv:func:`copyMakeBorder` + + +copyMakeBorder +-------------- +Forms a border around an image. + +.. ocv:function:: void copyMakeBorder( InputArray src, OutputArray dst, int top, int bottom, int left, int right, int borderType, const Scalar& value=Scalar() ) + +.. ocv:pyfunction:: cv2.copyMakeBorder(src, top, bottom, left, right, borderType[, dst[, value]]) -> dst + + :param src: Source image. + + :param dst: Destination image of the same type as ``src`` and the + size ``Size(src.cols+left+right, src.rows+top+bottom)`` . + + :param top: + + :param bottom: + + :param left: + + :param right: Parameter specifying how many pixels in each direction from the source image + rectangle to extrapolate. For example, ``top=1, bottom=1, left=1, right=1`` + mean that 1 pixel-wide border needs to be built. + + :param borderType: Border type. See :ocv:func:`borderInterpolate` for details. + + :param value: Border value if ``borderType==BORDER_CONSTANT`` . + +The function copies the source image into the middle of the destination image. The areas to the +left, to the right, above and below the copied source image will be filled with extrapolated pixels. +This is not what :ocv:class:`FilterEngine` or filtering functions based on it do (they extrapolate +pixels on-fly), but what other more complex functions, including your own, may do to simplify image +boundary handling. + +The function supports the mode when ``src`` is already in the middle of ``dst`` . In this case, the +function does not copy ``src`` itself but simply constructs the border, for example: :: + + // let border be the same in all directions + int border=2; + // constructs a larger image to fit both the image and the border + Mat gray_buf(rgb.rows + border*2, rgb.cols + border*2, rgb.depth()); + // select the middle part of it w/o copying data + Mat gray(gray_canvas, Rect(border, border, rgb.cols, rgb.rows)); + // convert image from RGB to grayscale + cvtColor(rgb, gray, COLOR_RGB2GRAY); + // form a border in-place + copyMakeBorder(gray, gray_buf, border, border, + border, border, BORDER_REPLICATE); + // now do some custom filtering ... + ... + + +.. note:: + + When the source image is a part (ROI) of a bigger image, the function will try to use the pixels + outside of the ROI to form a border. To disable this feature and always do extrapolation, as if + ``src`` was not a ROI, use ``borderType | BORDER_ISOLATED``. + +.. seealso:: + + :ocv:func:`borderInterpolate` diff --git a/modules/core/doc/utility_and_system_functions_and_macros.rst b/modules/core/doc/utility_and_system_functions_and_macros.rst index 54198b058a..d5052fa5ac 100644 --- a/modules/core/doc/utility_and_system_functions_and_macros.rst +++ b/modules/core/doc/utility_and_system_functions_and_macros.rst @@ -76,7 +76,6 @@ Calculates the angle of a 2D vector in degrees. .. ocv:pyfunction:: cv2.fastAtan2(y, x) -> retval .. ocv:cfunction:: float cvFastArctan(float y, float x) -.. ocv:pyoldfunction:: cv.FastArctan(y, x)-> float :param x: x-coordinate of the vector. @@ -95,8 +94,6 @@ Computes the cube root of an argument. .. ocv:cfunction:: float cvCbrt( float value ) -.. ocv:pyoldfunction:: cv.Cbrt(value)-> float - :param val: A function argument. The function ``cubeRoot`` computes :math:`\sqrt[3]{\texttt{val}}`. Negative arguments are handled correctly. NaN and Inf are not handled. The accuracy approaches the maximum possible accuracy for single-precision data. @@ -107,7 +104,6 @@ Ceil Rounds floating-point number to the nearest integer not smaller than the original. .. ocv:cfunction:: int cvCeil(double value) -.. ocv:pyoldfunction:: cv.Ceil(value) -> int :param value: floating-point number. If the value is outside of ``INT_MIN`` ... ``INT_MAX`` range, the result is not defined. @@ -123,7 +119,6 @@ Floor Rounds floating-point number to the nearest integer not larger than the original. .. ocv:cfunction:: int cvFloor(double value) -.. ocv:pyoldfunction:: cv.Floor(value) -> int :param value: floating-point number. If the value is outside of ``INT_MIN`` ... ``INT_MAX`` range, the result is not defined. @@ -139,7 +134,6 @@ Round Rounds floating-point number to the nearest integer .. ocv:cfunction:: int cvRound(double value) -.. ocv:pyoldfunction:: cv.Round(value) -> int :param value: floating-point number. If the value is outside of ``INT_MIN`` ... ``INT_MAX`` range, the result is not defined. @@ -149,7 +143,6 @@ IsInf Determines if the argument is Infinity. .. ocv:cfunction:: int cvIsInf(double value) -.. ocv:pyoldfunction:: cv.IsInf(value)-> int :param value: The input floating-point value @@ -160,7 +153,6 @@ IsNaN Determines if the argument is Not A Number. .. ocv:cfunction:: int cvIsNaN(double value) -.. ocv:pyoldfunction:: cv.IsNaN(value)-> int :param value: The input floating-point value @@ -173,6 +165,8 @@ Checks a condition at runtime and throws exception if it fails .. ocv:function:: CV_Assert(expr) + :param expr: Expression for check. + The macros ``CV_Assert`` (and ``CV_DbgAssert``) evaluate the specified expression. If it is 0, the macros raise an error (see :ocv:func:`error` ). The macro ``CV_Assert`` checks the condition in both Debug and Release configurations while ``CV_DbgAssert`` is only retained in the Debug configuration. @@ -188,8 +182,14 @@ Signals an error and raises an exception. :param status: Error code. Normally, it is a negative value. The list of pre-defined error codes can be found in ``cxerror.h`` . + :param func_name: The function name where error occurs. + :param err_msg: Text of the error message. + :param file_name: The file name where error occurs. + + :param line: The line number where error occurs. + :param args: ``printf`` -like formatted error message in parentheses. The function and the helper macros ``CV_Error`` and ``CV_Error_``: :: @@ -218,19 +218,19 @@ Exception class passed to an error. :: public: // various constructors and the copy operation Exception() { code = 0; line = 0; } - Exception(int _code, const string& _err, - const string& _func, const string& _file, int _line); + Exception(int _code, const String& _err, + const String& _func, const String& _file, int _line); Exception(const Exception& exc); Exception& operator = (const Exception& exc); // the error code int code; // the error text message - string err; + String err; // function name where the error happened - string func; + String func; // the source file name where the error happened - string file; + String file; // the source file line where the error happened int line; }; @@ -249,6 +249,7 @@ Allocates an aligned memory buffer. .. ocv:cfunction:: void* cvAlloc( size_t size ) :param size: Allocated buffer size. + :param bufSize: Allocated buffer size. The function allocates the buffer of the specified size and returns it. When the buffer size is 16 bytes or more, the returned buffer is aligned to 16 bytes. @@ -272,7 +273,7 @@ format ------ Returns a text string formatted using the ``printf``\ -like expression. -.. ocv:function:: string format( const char* fmt, ... ) +.. ocv:function:: String format( const char* fmt, ... ) :param fmt: ``printf`` -compatible formatting specifiers. @@ -284,7 +285,7 @@ getBuildInformation ------------------- Returns full configuration time cmake output. -.. ocv:function:: const std::string& getBuildInformation() +.. ocv:function:: const String& getBuildInformation() Returned value is raw cmake output including version control system revision, compiler version, compiler flags, enabled modules and third party libraries, etc. Output format depends on target architecture. diff --git a/modules/core/doc/xml_yaml_persistence.rst b/modules/core/doc/xml_yaml_persistence.rst index 102dafc704..cf3cfb4476 100644 --- a/modules/core/doc/xml_yaml_persistence.rst +++ b/modules/core/doc/xml_yaml_persistence.rst @@ -11,7 +11,7 @@ You can store and then restore various OpenCV data structures to/from XML (http: Use the following procedure to write something to XML or YAML: #. Create new :ocv:class:`FileStorage` and open it for writing. It can be done with a single call to :ocv:func:`FileStorage::FileStorage` constructor that takes a filename, or you can use the default constructor and then call :ocv:func:`FileStorage::open`. Format of the file (XML or YAML) is determined from the filename extension (".xml" and ".yml"/".yaml", respectively) - #. Write all the data you want using the streaming operator ``>>``, just like in the case of STL streams. + #. Write all the data you want using the streaming operator ``<<``, just like in the case of STL streams. #. Close the file using :ocv:func:`FileStorage::release`. ``FileStorage`` destructor also closes the file. Here is an example: :: @@ -91,6 +91,10 @@ Several things can be noted by looking at the sample code and the output: * In YAML (but not XML), mappings and sequences can be written in a compact Python-like inline form. In the sample above matrix elements, as well as each feature, including its lbp value, is stored in such inline form. To store a mapping/sequence in a compact form, put ":" after the opening character, e.g. use **"{:"** instead of **"{"** and **"[:"** instead of **"["**. When the data is written to XML, those extra ":" are ignored. +.. note:: + + * A complete example using the FileStorage interface can be found at opencv_source_code/samples/cpp/filestorage.cpp + Reading data from a file storage. --------------------------------- @@ -113,7 +117,7 @@ Here is how to read the file created by the code sample above: :: // first method: use (type) operator on FileNode. int frameCount = (int)fs2["frameCount"]; - std::string date; + String date; // second method: use FileNode::operator >> fs2["calibrationDate"] >> date; @@ -156,7 +160,7 @@ The constructors. .. ocv:function:: FileStorage::FileStorage() -.. ocv:function:: FileStorage::FileStorage(const string& source, int flags, const string& encoding=string()) +.. ocv:function:: FileStorage::FileStorage(const String& source, int flags, const String& encoding=String()) :param source: Name of the file to open or the text string to read the data from. Extension of the file (``.xml`` or ``.yml``/``.yaml``) determines its format (XML or YAML respectively). Also you can append ``.gz`` to work with compressed files, for example ``myHugeMatrix.xml.gz``. If both ``FileStorage::WRITE`` and ``FileStorage::MEMORY`` flags are specified, ``source`` is used just to specify the output file format (e.g. ``mydata.xml``, ``.yml`` etc.). @@ -179,7 +183,18 @@ FileStorage::open ----------------- Opens a file. -.. ocv:function:: bool FileStorage::open(const string& filename, int flags, const string& encoding=string()) +.. ocv:function:: bool FileStorage::open(const String& filename, int flags, const String& encoding=String()) + + :param filename: Name of the file to open or the text string to read the data from. + Extension of the file (``.xml`` or ``.yml``/``.yaml``) determines its format (XML or YAML respectively). + Also you can append ``.gz`` to work with compressed files, for example ``myHugeMatrix.xml.gz``. + If both ``FileStorage::WRITE`` and ``FileStorage::MEMORY`` flags are specified, ``source`` + is used just to specify the output file format (e.g. ``mydata.xml``, ``.yml`` etc.). + + :param flags: Mode of operation. See FileStorage constructor for more details. + + :param encoding: Encoding of the file. Note that UTF-16 XML encoding is not supported currently and you should use 8-bit encoding instead of it. + See description of parameters in :ocv:func:`FileStorage::FileStorage`. The method calls :ocv:func:`FileStorage::release` before opening the file. @@ -208,7 +223,7 @@ FileStorage::releaseAndGetString -------------------------------- Closes the file and releases all the memory buffers. -.. ocv:function:: string FileStorage::releaseAndGetString() +.. ocv:function:: String FileStorage::releaseAndGetString() Call this method after all I/O operations with the storage are finished. If the storage was opened for writing data and ``FileStorage::WRITE`` was specified @@ -237,7 +252,7 @@ FileStorage::operator[] ----------------------- Returns the specified element of the top-level mapping. -.. ocv:function:: FileNode FileStorage::operator[](const string& nodename) const +.. ocv:function:: FileNode FileStorage::operator[](const String& nodename) const .. ocv:function:: FileNode FileStorage::operator[](const char* nodename) const @@ -261,7 +276,7 @@ FileStorage::writeRaw --------------------- Writes multiple numbers. -.. ocv:function:: void FileStorage::writeRaw( const string& fmt, const uchar* vec, size_t len ) +.. ocv:function:: void FileStorage::writeRaw( const String& fmt, const uchar* vec, size_t len ) :param fmt: Specification of each array element that has the following format ``([count]{'u'|'c'|'w'|'s'|'i'|'f'|'d'})...`` where the characters correspond to fundamental C++ types: @@ -293,7 +308,7 @@ FileStorage::writeObj --------------------- Writes the registered C structure (CvMat, CvMatND, CvSeq). -.. ocv:function:: void FileStorage::writeObj( const string& name, const void* obj ) +.. ocv:function:: void FileStorage::writeObj( const String& name, const void* obj ) :param name: Name of the written object. @@ -306,7 +321,7 @@ FileStorage::getDefaultObjectName --------------------------------- Returns the normalized object name for the specified name of a file. -.. ocv:function:: static string FileStorage::getDefaultObjectName(const string& filename) +.. ocv:function:: static String FileStorage::getDefaultObjectName(const String& filename) :param filename: Name of a file @@ -383,7 +398,7 @@ FileNode::operator[] -------------------- Returns element of a mapping node or a sequence node. -.. ocv:function:: FileNode FileNode::operator[](const string& nodename) const +.. ocv:function:: FileNode FileNode::operator[](const String& nodename) const .. ocv:function:: FileNode FileNode::operator[](const char* nodename) const @@ -507,7 +522,7 @@ FileNode::name -------------- Returns the node name. -.. ocv:function:: string FileNode::name() const +.. ocv:function:: String FileNode::name() const :returns: The node name or an empty string if the node is nameless. @@ -548,11 +563,11 @@ Returns the node content as double. :returns: The node content as double. -FileNode::operator std::string +FileNode::operator String ------------------------------ Returns the node content as text string. -.. ocv:function:: FileNode::operator std::string() const +.. ocv:function:: FileNode::operator String() const :returns: The node content as a text string. @@ -588,7 +603,7 @@ FileNode::readRaw ----------------- Reads node elements to the buffer with the specified format. -.. ocv:function:: void FileNode::readRaw( const string& fmt, uchar* vec, size_t len ) const +.. ocv:function:: void FileNode::readRaw( const String& fmt, uchar* vec, size_t len ) const :param fmt: Specification of each array element. It has the same format as in :ocv:func:`FileStorage::writeRaw`. @@ -692,7 +707,7 @@ FileNodeIterator::readRaw ------------------------- Reads node elements to the buffer with the specified format. -.. ocv:function:: FileNodeIterator& FileNodeIterator::readRaw( const string& fmt, uchar* vec, size_t maxCount=(size_t)INT_MAX ) +.. ocv:function:: FileNodeIterator& FileNodeIterator::readRaw( const String& fmt, uchar* vec, size_t maxCount=(size_t)INT_MAX ) :param fmt: Specification of each array element. It has the same format as in :ocv:func:`FileStorage::writeRaw`. diff --git a/modules/core/include/opencv2/core.hpp b/modules/core/include/opencv2/core.hpp index 5e204e8411..c7f07ed459 100644 --- a/modules/core/include/opencv2/core.hpp +++ b/modules/core/include/opencv2/core.hpp @@ -1,6 +1,3 @@ -/*! \file core.hpp - \brief The Core Functionality - */ /*M/////////////////////////////////////////////////////////////////////////////////////// // // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. @@ -46,77 +43,25 @@ #ifndef __OPENCV_CORE_HPP__ #define __OPENCV_CORE_HPP__ +#ifndef __cplusplus +# error core.hpp header must be compiled as C++ +#endif + #include "opencv2/core/cvdef.h" - -#include "opencv2/core/types_c.h" #include "opencv2/core/version.hpp" - -#ifdef __cplusplus - -#ifndef SKIP_INCLUDES -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif // SKIP_INCLUDES +#include "opencv2/core/base.hpp" +#include "opencv2/core/cvstd.hpp" +#include "opencv2/core/traits.hpp" +#include "opencv2/core/matx.hpp" +#include "opencv2/core/types.hpp" +#include "opencv2/core/mat.hpp" +#include "opencv2/core/persistence.hpp" /*! \namespace cv Namespace where all the C++ OpenCV functionality resides */ namespace cv { -template class CV_EXPORTS Size_; -template class CV_EXPORTS Point_; -template class CV_EXPORTS Rect_; -template class CV_EXPORTS Vec; -template class CV_EXPORTS Matx; - -class Mat; -class SparseMat; -typedef Mat MatND; - -namespace ogl { - class Buffer; - class Texture2D; - class Arrays; -} - -namespace gpu { - class GpuMat; -} - -class CV_EXPORTS MatExpr; -class CV_EXPORTS MatOp_Base; -class CV_EXPORTS MatArg; -class CV_EXPORTS MatConstIterator; - -template class CV_EXPORTS Mat_; -template class CV_EXPORTS MatIterator_; -template class CV_EXPORTS MatConstIterator_; -template class CV_EXPORTS MatCommaInitializer_; - -template class CV_EXPORTS AutoBuffer; - -CV_EXPORTS std::string format( const char* fmt, ... ); -CV_EXPORTS std::string tempfile( const char* suffix CV_DEFAULT(0)); - -CV_EXPORTS void glob(std::string pattern, std::vector& result, bool recursive = false); - -// matrix decomposition types -enum { DECOMP_LU=0, DECOMP_SVD=1, DECOMP_EIG=2, DECOMP_CHOLESKY=3, DECOMP_QR=4, DECOMP_NORMAL=16 }; -enum { NORM_INF=1, NORM_L1=2, NORM_L2=4, NORM_L2SQR=5, NORM_HAMMING=6, NORM_HAMMING2=7, NORM_TYPE_MASK=7, NORM_RELATIVE=8, NORM_MINMAX=32 }; -enum { CMP_EQ=0, CMP_GT=1, CMP_GE=2, CMP_LT=3, CMP_LE=4, CMP_NE=5 }; -enum { GEMM_1_T=1, GEMM_2_T=2, GEMM_3_T=4 }; -enum { DFT_INVERSE=1, DFT_SCALE=2, DFT_ROWS=4, DFT_COMPLEX_OUTPUT=16, DFT_REAL_OUTPUT=32, - DCT_INVERSE = DFT_INVERSE, DCT_ROWS=DFT_ROWS }; - - /*! The standard OpenCV exception class. Instances of the class are thrown by various functions and methods in the case of critical errors. @@ -132,7 +77,7 @@ public: Full constructor. Normally the constuctor is not called explicitly. Instead, the macros CV_Error(), CV_Error_() and CV_Assert() are used. */ - Exception(int _code, const std::string& _err, const std::string& _func, const std::string& _file, int _line); + Exception(int _code, const String& _err, const String& _func, const String& _file, int _line); virtual ~Exception() throw(); /*! @@ -141,12 +86,12 @@ public: virtual const char *what() const throw(); void formatMessage(); - std::string msg; ///< the formatted error message + String msg; ///< the formatted error message int code; ///< error code @see CVStatus - std::string err; ///< error description - std::string func; ///< function name. Available only when the compiler supports __func__ macro - std::string file; ///< source file name where the error has occured + String err; ///< error description + String func; ///< function name. Available only when the compiler supports __func__ macro + String file; ///< source file name where the error has occured int line; ///< line number in the source file where the error has occured }; @@ -160,2027 +105,179 @@ public: \param exc the exception raisen. */ +//TODO: drop this version CV_EXPORTS void error( const Exception& exc ); -//! Sets/resets the break-on-error mode. + +enum { SORT_EVERY_ROW = 0, + SORT_EVERY_COLUMN = 1, + SORT_ASCENDING = 0, + SORT_DESCENDING = 16 + }; + +enum { COVAR_SCRAMBLED = 0, + COVAR_NORMAL = 1, + COVAR_USE_AVG = 2, + COVAR_SCALE = 4, + COVAR_ROWS = 8, + COVAR_COLS = 16 + }; /*! - When the break-on-error mode is set, the default error handler - issues a hardware exception, which can make debugging more convenient. - - \return the previous state - */ -CV_EXPORTS bool setBreakOnError(bool flag); - -typedef int (CV_CDECL *ErrorCallback)( int status, const char* func_name, - const char* err_msg, const char* file_name, - int line, void* userdata ); - -//! Sets the new error handler and the optional user data. - -/*! - The function sets the new error handler, called from cv::error(). - - \param errCallback the new error handler. If NULL, the default error handler is used. - \param userdata the optional user data pointer, passed to the callback. - \param prevUserdata the optional output parameter where the previous user data pointer is stored - - \return the previous error handler + k-Means flags */ -CV_EXPORTS ErrorCallback redirectError( ErrorCallback errCallback, - void* userdata=0, void** prevUserdata=0); +enum { KMEANS_RANDOM_CENTERS = 0, // Chooses random centers for k-Means initialization + KMEANS_PP_CENTERS = 2, // Uses k-Means++ algorithm for initialization + KMEANS_USE_INITIAL_LABELS = 1 // Uses the user-provided labels for K-Means initialization + }; + +enum { FILLED = -1, + LINE_4 = 4, + LINE_8 = 8, + LINE_AA = 16 + }; + +enum { FONT_HERSHEY_SIMPLEX = 0, + FONT_HERSHEY_PLAIN = 1, + FONT_HERSHEY_DUPLEX = 2, + FONT_HERSHEY_COMPLEX = 3, + FONT_HERSHEY_TRIPLEX = 4, + FONT_HERSHEY_COMPLEX_SMALL = 5, + FONT_HERSHEY_SCRIPT_SIMPLEX = 6, + FONT_HERSHEY_SCRIPT_COMPLEX = 7, + FONT_ITALIC = 16 + }; + +enum { REDUCE_SUM = 0, + REDUCE_AVG = 1, + REDUCE_MAX = 2, + REDUCE_MIN = 3 + }; -#ifdef __GNUC__ -#define CV_Error( code, msg ) cv::error( cv::Exception(code, msg, __func__, __FILE__, __LINE__) ) -#define CV_Error_( code, args ) cv::error( cv::Exception(code, cv::format args, __func__, __FILE__, __LINE__) ) -#define CV_Assert( expr ) if(!!(expr)) ; else cv::error( cv::Exception(CV_StsAssert, #expr, __func__, __FILE__, __LINE__) ) -#else -#define CV_Error( code, msg ) cv::error( cv::Exception(code, msg, "", __FILE__, __LINE__) ) -#define CV_Error_( code, args ) cv::error( cv::Exception(code, cv::format args, "", __FILE__, __LINE__) ) -#define CV_Assert( expr ) if(!!(expr)) ; else cv::error( cv::Exception(CV_StsAssert, #expr, "", __FILE__, __LINE__) ) -#endif - -#ifdef _DEBUG -#define CV_DbgAssert(expr) CV_Assert(expr) -#else -#define CV_DbgAssert(expr) -#endif - -CV_EXPORTS void setNumThreads(int nthreads); -CV_EXPORTS int getNumThreads(); -CV_EXPORTS int getThreadNum(); - -CV_EXPORTS_W const std::string& getBuildInformation(); - -//! Returns the number of ticks. - -/*! - The function returns the number of ticks since the certain event (e.g. when the machine was turned on). - It can be used to initialize cv::RNG or to measure a function execution time by reading the tick count - before and after the function call. The granularity of ticks depends on the hardware and OS used. Use - cv::getTickFrequency() to convert ticks to seconds. -*/ -CV_EXPORTS_W int64 getTickCount(); - -/*! - Returns the number of ticks per seconds. - - The function returns the number of ticks (as returned by cv::getTickCount()) per second. - The following code computes the execution time in milliseconds: - - \code - double exec_time = (double)getTickCount(); - // do something ... - exec_time = ((double)getTickCount() - exec_time)*1000./getTickFrequency(); - \endcode -*/ -CV_EXPORTS_W double getTickFrequency(); - -/*! - Returns the number of CPU ticks. - - On platforms where the feature is available, the function returns the number of CPU ticks - since the certain event (normally, the system power-on moment). Using this function - one can accurately measure the execution time of very small code fragments, - for which cv::getTickCount() granularity is not enough. -*/ -CV_EXPORTS_W int64 getCPUTickCount(); - -/*! - Returns SSE etc. support status - - The function returns true if certain hardware features are available. - Currently, the following features are recognized: - - CV_CPU_MMX - MMX - - CV_CPU_SSE - SSE - - CV_CPU_SSE2 - SSE 2 - - CV_CPU_SSE3 - SSE 3 - - CV_CPU_SSSE3 - SSSE 3 - - CV_CPU_SSE4_1 - SSE 4.1 - - CV_CPU_SSE4_2 - SSE 4.2 - - CV_CPU_POPCNT - POPCOUNT - - CV_CPU_AVX - AVX - - \note {Note that the function output is not static. Once you called cv::useOptimized(false), - most of the hardware acceleration is disabled and thus the function will returns false, - until you call cv::useOptimized(true)} -*/ -CV_EXPORTS_W bool checkHardwareSupport(int feature); - -//! returns the number of CPUs (including hyper-threading) -CV_EXPORTS_W int getNumberOfCPUs(); - -/*! - Allocates memory buffer - - This is specialized OpenCV memory allocation function that returns properly aligned memory buffers. - The usage is identical to malloc(). The allocated buffers must be freed with cv::fastFree(). - If there is not enough memory, the function calls cv::error(), which raises an exception. - - \param bufSize buffer size in bytes - \return the allocated memory buffer. -*/ -CV_EXPORTS void* fastMalloc(size_t bufSize); - -/*! - Frees the memory allocated with cv::fastMalloc - - This is the corresponding deallocation function for cv::fastMalloc(). - When ptr==NULL, the function has no effect. -*/ -CV_EXPORTS void fastFree(void* ptr); - -template static inline _Tp* allocate(size_t n) -{ - return new _Tp[n]; -} - -template static inline void deallocate(_Tp* ptr, size_t) -{ - delete[] ptr; -} - -/*! - Aligns pointer by the certain number of bytes - - This small inline function aligns the pointer by the certian number of bytes by shifting - it forward by 0 or a positive offset. -*/ -template static inline _Tp* alignPtr(_Tp* ptr, int n=(int)sizeof(_Tp)) -{ - return (_Tp*)(((size_t)ptr + n-1) & -n); -} - -/*! - Aligns buffer size by the certain number of bytes - - This small inline function aligns a buffer size by the certian number of bytes by enlarging it. -*/ -static inline size_t alignSize(size_t sz, int n) -{ - return (sz + n-1) & -n; -} - -/*! - Turns on/off available optimization - - The function turns on or off the optimized code in OpenCV. Some optimization can not be enabled - or disabled, but, for example, most of SSE code in OpenCV can be temporarily turned on or off this way. - - \note{Since optimization may imply using special data structures, it may be unsafe - to call this function anywhere in the code. Instead, call it somewhere at the top level.} -*/ -CV_EXPORTS_W void setUseOptimized(bool onoff); - -/*! - Returns the current optimization status - - The function returns the current optimization status, which is controlled by cv::setUseOptimized(). -*/ -CV_EXPORTS_W bool useOptimized(); - -/*! - The STL-compilant memory Allocator based on cv::fastMalloc() and cv::fastFree() -*/ -template class CV_EXPORTS Allocator -{ -public: - typedef _Tp value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - template class rebind { typedef Allocator other; }; - - explicit Allocator() {} - ~Allocator() {} - explicit Allocator(Allocator const&) {} - template - explicit Allocator(Allocator const&) {} - - // address - pointer address(reference r) { return &r; } - const_pointer address(const_reference r) { return &r; } - - pointer allocate(size_type count, const void* =0) - { return reinterpret_cast(fastMalloc(count * sizeof (_Tp))); } - - void deallocate(pointer p, size_type) {fastFree(p); } - - size_type max_size() const - { return max(static_cast<_Tp>(-1)/sizeof(_Tp), 1); } - - void construct(pointer p, const _Tp& v) { new(static_cast(p)) _Tp(v); } - void destroy(pointer p) { p->~_Tp(); } -}; - -/////////////////////// Vec (used as element of multi-channel images ///////////////////// - -/*! - A helper class for cv::DataType - - The class is specialized for each fundamental numerical data type supported by OpenCV. - It provides DataDepth::value constant. -*/ -template class CV_EXPORTS DataDepth {}; - -template<> class DataDepth { public: enum { value = CV_8U, fmt=(int)'u' }; }; -template<> class DataDepth { public: enum { value = CV_8U, fmt=(int)'u' }; }; -template<> class DataDepth { public: enum { value = CV_8S, fmt=(int)'c' }; }; -template<> class DataDepth { public: enum { value = CV_8S, fmt=(int)'c' }; }; -template<> class DataDepth { public: enum { value = CV_16U, fmt=(int)'w' }; }; -template<> class DataDepth { public: enum { value = CV_16S, fmt=(int)'s' }; }; -template<> class DataDepth { public: enum { value = CV_32S, fmt=(int)'i' }; }; -// this is temporary solution to support 32-bit unsigned integers -template<> class DataDepth { public: enum { value = CV_32S, fmt=(int)'i' }; }; -template<> class DataDepth { public: enum { value = CV_32F, fmt=(int)'f' }; }; -template<> class DataDepth { public: enum { value = CV_64F, fmt=(int)'d' }; }; -template class DataDepth<_Tp*> { public: enum { value = CV_USRTYPE1, fmt=(int)'r' }; }; - - -////////////////////////////// Small Matrix /////////////////////////// - -/*! - A short numerical vector. - - This template class represents short numerical vectors (of 1, 2, 3, 4 ... elements) - on which you can perform basic arithmetical operations, access individual elements using [] operator etc. - The vectors are allocated on stack, as opposite to std::valarray, std::vector, cv::Mat etc., - which elements are dynamically allocated in the heap. - - The template takes 2 parameters: - -# _Tp element type - -# cn the number of elements - - In addition to the universal notation like Vec, you can use shorter aliases - for the most popular specialized variants of Vec, e.g. Vec3f ~ Vec. - */ - -struct CV_EXPORTS Matx_AddOp {}; -struct CV_EXPORTS Matx_SubOp {}; -struct CV_EXPORTS Matx_ScaleOp {}; -struct CV_EXPORTS Matx_MulOp {}; -struct CV_EXPORTS Matx_MatMulOp {}; -struct CV_EXPORTS Matx_TOp {}; - -template class CV_EXPORTS Matx -{ -public: - typedef _Tp value_type; - typedef Matx<_Tp, (m < n ? m : n), 1> diag_type; - typedef Matx<_Tp, m, n> mat_type; - enum { depth = DataDepth<_Tp>::value, rows = m, cols = n, channels = rows*cols, - type = CV_MAKETYPE(depth, channels) }; - - //! default constructor - Matx(); - - Matx(_Tp v0); //!< 1x1 matrix - Matx(_Tp v0, _Tp v1); //!< 1x2 or 2x1 matrix - Matx(_Tp v0, _Tp v1, _Tp v2); //!< 1x3 or 3x1 matrix - Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3); //!< 1x4, 2x2 or 4x1 matrix - Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4); //!< 1x5 or 5x1 matrix - Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5); //!< 1x6, 2x3, 3x2 or 6x1 matrix - Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6); //!< 1x7 or 7x1 matrix - Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7); //!< 1x8, 2x4, 4x2 or 8x1 matrix - Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8); //!< 1x9, 3x3 or 9x1 matrix - Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9); //!< 1x10, 2x5 or 5x2 or 10x1 matrix - 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); //!< 1x12, 2x6, 3x4, 4x3, 6x2 or 12x1 matrix - 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); //!< 1x16, 4x4 or 16x1 matrix - explicit Matx(const _Tp* vals); //!< initialize from a plain array - - static Matx all(_Tp alpha); - static Matx zeros(); - static Matx ones(); - static Matx eye(); - static Matx diag(const diag_type& d); - static Matx randu(_Tp a, _Tp b); - static Matx randn(_Tp a, _Tp b); - - //! dot product computed with the default precision - _Tp dot(const Matx<_Tp, m, n>& v) const; - - //! dot product computed in double-precision arithmetics - double ddot(const Matx<_Tp, m, n>& v) const; - - //! convertion to another data type - template operator Matx() const; - - //! change the matrix shape - template Matx<_Tp, m1, n1> reshape() const; - - //! extract part of the matrix - template Matx<_Tp, m1, n1> get_minor(int i, int j) const; - - //! extract the matrix row - Matx<_Tp, 1, n> row(int i) const; - - //! extract the matrix column - Matx<_Tp, m, 1> col(int i) const; - - //! extract the matrix diagonal - diag_type diag() const; - - //! transpose the matrix - Matx<_Tp, n, m> t() const; - - //! invert matrix the matrix - Matx<_Tp, n, m> inv(int method=DECOMP_LU) const; - - //! solve linear system - template Matx<_Tp, n, l> solve(const Matx<_Tp, m, l>& rhs, int flags=DECOMP_LU) const; - Vec<_Tp, n> solve(const Vec<_Tp, m>& rhs, int method) const; - - //! multiply two matrices element-wise - Matx<_Tp, m, n> mul(const Matx<_Tp, m, n>& a) const; - - //! element access - const _Tp& operator ()(int i, int j) const; - _Tp& operator ()(int i, int j); - - //! 1D element access - const _Tp& operator ()(int i) const; - _Tp& operator ()(int i); - - Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_AddOp); - Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_SubOp); - template Matx(const Matx<_Tp, m, n>& a, _T2 alpha, Matx_ScaleOp); - Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_MulOp); - template Matx(const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b, Matx_MatMulOp); - Matx(const Matx<_Tp, n, m>& a, Matx_TOp); - - _Tp val[m*n]; //< matrix elements -}; - - -typedef Matx Matx12f; -typedef Matx Matx12d; -typedef Matx Matx13f; -typedef Matx Matx13d; -typedef Matx Matx14f; -typedef Matx Matx14d; -typedef Matx Matx16f; -typedef Matx Matx16d; - -typedef Matx Matx21f; -typedef Matx Matx21d; -typedef Matx Matx31f; -typedef Matx Matx31d; -typedef Matx Matx41f; -typedef Matx Matx41d; -typedef Matx Matx61f; -typedef Matx Matx61d; - -typedef Matx Matx22f; -typedef Matx Matx22d; -typedef Matx Matx23f; -typedef Matx Matx23d; -typedef Matx Matx32f; -typedef Matx Matx32d; - -typedef Matx Matx33f; -typedef Matx Matx33d; - -typedef Matx Matx34f; -typedef Matx Matx34d; -typedef Matx Matx43f; -typedef Matx Matx43d; - -typedef Matx Matx44f; -typedef Matx Matx44d; -typedef Matx Matx66f; -typedef Matx Matx66d; - - -/*! - A short numerical vector. - - This template class represents short numerical vectors (of 1, 2, 3, 4 ... elements) - on which you can perform basic arithmetical operations, access individual elements using [] operator etc. - The vectors are allocated on stack, as opposite to std::valarray, std::vector, cv::Mat etc., - which elements are dynamically allocated in the heap. - - The template takes 2 parameters: - -# _Tp element type - -# cn the number of elements - - In addition to the universal notation like Vec, you can use shorter aliases - for the most popular specialized variants of Vec, e.g. Vec3f ~ Vec. -*/ -template class CV_EXPORTS Vec : public Matx<_Tp, cn, 1> -{ -public: - typedef _Tp value_type; - enum { depth = DataDepth<_Tp>::value, channels = cn, type = CV_MAKETYPE(depth, channels) }; - - //! default constructor - Vec(); - - Vec(_Tp v0); //!< 1-element vector constructor - Vec(_Tp v0, _Tp v1); //!< 2-element vector constructor - Vec(_Tp v0, _Tp v1, _Tp v2); //!< 3-element vector constructor - Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3); //!< 4-element vector constructor - Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4); //!< 5-element vector constructor - Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5); //!< 6-element vector constructor - Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6); //!< 7-element vector constructor - Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7); //!< 8-element vector constructor - Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8); //!< 9-element vector constructor - Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9); //!< 10-element vector constructor - explicit Vec(const _Tp* values); - - Vec(const Vec<_Tp, cn>& v); - - static Vec all(_Tp alpha); - - //! per-element multiplication - Vec mul(const Vec<_Tp, cn>& v) const; - - //! conjugation (makes sense for complex numbers and quaternions) - Vec conj() const; - - /*! - cross product of the two 3D vectors. - - For other dimensionalities the exception is raised - */ - Vec cross(const Vec& v) const; - //! convertion to another data type - template operator Vec() const; - //! conversion to 4-element CvScalar. - operator CvScalar() const; - - /*! element access */ - const _Tp& operator [](int i) const; - _Tp& operator[](int i); - const _Tp& operator ()(int i) const; - _Tp& operator ()(int i); - - Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_AddOp); - Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_SubOp); - template Vec(const Matx<_Tp, cn, 1>& a, _T2 alpha, Matx_ScaleOp); -}; - - -/* \typedef - - Shorter aliases for the most popular specializations of Vec -*/ -typedef Vec Vec2b; -typedef Vec Vec3b; -typedef Vec Vec4b; - -typedef Vec Vec2s; -typedef Vec Vec3s; -typedef Vec Vec4s; - -typedef Vec Vec2w; -typedef Vec Vec3w; -typedef Vec Vec4w; - -typedef Vec Vec2i; -typedef Vec Vec3i; -typedef Vec Vec4i; -typedef Vec Vec6i; -typedef Vec Vec8i; - -typedef Vec Vec2f; -typedef Vec Vec3f; -typedef Vec Vec4f; -typedef Vec Vec6f; - -typedef Vec Vec2d; -typedef Vec Vec3d; -typedef Vec Vec4d; -typedef Vec Vec6d; - - -//////////////////////////////// Complex ////////////////////////////// - -/*! - A complex number class. - - The template class is similar and compatible with std::complex, however it provides slightly - more convenient access to the real and imaginary parts using through the simple field access, as opposite - to std::complex::real() and std::complex::imag(). -*/ -template class CV_EXPORTS Complex -{ -public: - - //! constructors - Complex(); - Complex( _Tp _re, _Tp _im=0 ); - Complex( const std::complex<_Tp>& c ); - - //! conversion to another data type - template operator Complex() const; - //! conjugation - Complex conj() const; - //! conversion to std::complex - operator std::complex<_Tp>() const; - - _Tp re, im; //< the real and the imaginary parts -}; - - -/*! - \typedef -*/ -typedef Complex Complexf; -typedef Complex Complexd; - - -//////////////////////////////// Point_ //////////////////////////////// - -/*! - template 2D point class. - - The class defines a point in 2D space. Data type of the point coordinates is specified - as a template parameter. There are a few shorter aliases available for user convenience. - See cv::Point, cv::Point2i, cv::Point2f and cv::Point2d. -*/ -template class CV_EXPORTS Point_ -{ -public: - typedef _Tp value_type; - - // various constructors - Point_(); - Point_(_Tp _x, _Tp _y); - Point_(const Point_& pt); - Point_(const CvPoint& pt); - Point_(const CvPoint2D32f& pt); - Point_(const Size_<_Tp>& sz); - Point_(const Vec<_Tp, 2>& v); - - Point_& operator = (const Point_& pt); - //! conversion to another data type - template operator Point_<_Tp2>() const; - - //! conversion to the old-style C structures - operator CvPoint() const; - operator CvPoint2D32f() const; - operator Vec<_Tp, 2>() const; - - //! dot product - _Tp dot(const Point_& pt) const; - //! dot product computed in double-precision arithmetics - double ddot(const Point_& pt) const; - //! cross-product - double cross(const Point_& pt) const; - //! checks whether the point is inside the specified rectangle - bool inside(const Rect_<_Tp>& r) const; - - _Tp x, y; //< the point coordinates -}; - -/*! - template 3D point class. - - The class defines a point in 3D space. Data type of the point coordinates is specified - as a template parameter. - - \see cv::Point3i, cv::Point3f and cv::Point3d -*/ -template class CV_EXPORTS Point3_ -{ -public: - typedef _Tp value_type; - - // various constructors - Point3_(); - Point3_(_Tp _x, _Tp _y, _Tp _z); - Point3_(const Point3_& pt); - explicit Point3_(const Point_<_Tp>& pt); - Point3_(const CvPoint3D32f& pt); - Point3_(const Vec<_Tp, 3>& v); - - Point3_& operator = (const Point3_& pt); - //! conversion to another data type - template operator Point3_<_Tp2>() const; - //! conversion to the old-style CvPoint... - operator CvPoint3D32f() const; - //! conversion to cv::Vec<> - operator Vec<_Tp, 3>() const; - - //! dot product - _Tp dot(const Point3_& pt) const; - //! dot product computed in double-precision arithmetics - double ddot(const Point3_& pt) const; - //! cross product of the 2 3D points - Point3_ cross(const Point3_& pt) const; - - _Tp x, y, z; //< the point coordinates -}; - -//////////////////////////////// Size_ //////////////////////////////// - -/*! - The 2D size class - - The class represents the size of a 2D rectangle, image size, matrix size etc. - Normally, cv::Size ~ cv::Size_ is used. -*/ -template class CV_EXPORTS Size_ -{ -public: - typedef _Tp value_type; - - //! various constructors - Size_(); - Size_(_Tp _width, _Tp _height); - Size_(const Size_& sz); - Size_(const CvSize& sz); - Size_(const CvSize2D32f& sz); - Size_(const Point_<_Tp>& pt); - - Size_& operator = (const Size_& sz); - //! the area (width*height) - _Tp area() const; - - //! conversion of another data type. - template operator Size_<_Tp2>() const; - - //! conversion to the old-style OpenCV types - operator CvSize() const; - operator CvSize2D32f() const; - - _Tp width, height; // the width and the height -}; - -//////////////////////////////// Rect_ //////////////////////////////// - -/*! - The 2D up-right rectangle class - - The class represents a 2D rectangle with coordinates of the specified data type. - Normally, cv::Rect ~ cv::Rect_ is used. -*/ -template class CV_EXPORTS Rect_ -{ -public: - typedef _Tp value_type; - - //! various constructors - Rect_(); - Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height); - Rect_(const Rect_& r); - Rect_(const CvRect& r); - Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz); - Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2); - - Rect_& operator = ( const Rect_& r ); - //! the top-left corner - Point_<_Tp> tl() const; - //! the bottom-right corner - Point_<_Tp> br() const; - - //! size (width, height) of the rectangle - Size_<_Tp> size() const; - //! area (width*height) of the rectangle - _Tp area() const; - - //! conversion to another data type - template operator Rect_<_Tp2>() const; - //! conversion to the old-style CvRect - operator CvRect() const; - - //! checks whether the rectangle contains the point - bool contains(const Point_<_Tp>& pt) const; - - _Tp x, y, width, height; //< the top-left corner, as well as width and height of the rectangle -}; - - -/*! - \typedef - - shorter aliases for the most popular cv::Point_<>, cv::Size_<> and cv::Rect_<> specializations -*/ -typedef Point_ Point2i; -typedef Point2i Point; -typedef Size_ Size2i; -typedef Size2i Size; -typedef Rect_ Rect; -typedef Point_ Point2f; -typedef Point_ Point2d; -typedef Size_ Size2f; -typedef Point3_ Point3i; -typedef Point3_ Point3f; -typedef Point3_ Point3d; - - -/*! - The rotated 2D rectangle. - - The class represents rotated (i.e. not up-right) rectangles on a plane. - Each rectangle is described by the center point (mass center), length of each side - (represented by cv::Size2f structure) and the rotation angle in degrees. -*/ -class CV_EXPORTS RotatedRect -{ -public: - //! various constructors - RotatedRect(); - RotatedRect(const Point2f& center, const Size2f& size, float angle); - RotatedRect(const CvBox2D& box); - - //! returns 4 vertices of the rectangle - void points(Point2f pts[]) const; - //! returns the minimal up-right rectangle containing the rotated rectangle - Rect boundingRect() const; - //! conversion to the old-style CvBox2D structure - operator CvBox2D() const; - - Point2f center; //< the rectangle mass center - Size2f size; //< width and height of the rectangle - float angle; //< the rotation angle. When the angle is 0, 90, 180, 270 etc., the rectangle becomes an up-right rectangle. -}; - -//////////////////////////////// Scalar_ /////////////////////////////// - -/*! - The template scalar class. - - This is partially specialized cv::Vec class with the number of elements = 4, i.e. a short vector of four elements. - Normally, cv::Scalar ~ cv::Scalar_ is used. -*/ -template class CV_EXPORTS Scalar_ : public Vec<_Tp, 4> -{ -public: - //! various constructors - Scalar_(); - Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0); - Scalar_(const CvScalar& s); - Scalar_(_Tp v0); - - //! returns a scalar with all elements set to v0 - static Scalar_<_Tp> all(_Tp v0); - //! conversion to the old-style CvScalar - operator CvScalar() const; - - //! conversion to another data type - template operator Scalar_() const; - - //! per-element product - Scalar_<_Tp> mul(const Scalar_<_Tp>& t, double scale=1 ) const; - - // returns (v0, -v1, -v2, -v3) - Scalar_<_Tp> conj() const; - - // returns true iff v1 == v2 == v3 == 0 - bool isReal() const; -}; - -typedef Scalar_ Scalar; - -CV_EXPORTS void scalarToRawData(const Scalar& s, void* buf, int type, int unroll_to=0); - -//////////////////////////////// Range ///////////////////////////////// - -/*! - The 2D range class - - This is the class used to specify a continuous subsequence, i.e. part of a contour, or a column span in a matrix. -*/ -class CV_EXPORTS Range -{ -public: - Range(); - Range(int _start, int _end); - Range(const CvSlice& slice); - int size() const; - bool empty() const; - static Range all(); - operator CvSlice() const; - - int start, end; -}; - -/////////////////////////////// DataType //////////////////////////////// - -/*! - Informative template class for OpenCV "scalars". - - The class is specialized for each primitive numerical type supported by OpenCV (such as unsigned char or float), - as well as for more complex types, like cv::Complex<>, std::complex<>, cv::Vec<> etc. - The common property of all such types (called "scalars", do not confuse it with cv::Scalar_) - is that each of them is basically a tuple of numbers of the same type. Each "scalar" can be represented - by the depth id (CV_8U ... CV_64F) and the number of channels. - OpenCV matrices, 2D or nD, dense or sparse, can store "scalars", - as long as the number of channels does not exceed CV_CN_MAX. -*/ -template class DataType -{ -public: - typedef _Tp value_type; - typedef value_type work_type; - typedef value_type channel_type; - typedef value_type vec_type; - enum { generic_type = 1, depth = -1, channels = 1, fmt=0, - type = CV_MAKETYPE(depth, channels) }; -}; - -template<> class DataType -{ -public: - typedef bool value_type; - typedef int work_type; - typedef value_type channel_type; - typedef value_type vec_type; - enum { generic_type = 0, depth = DataDepth::value, channels = 1, - fmt=DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; -}; - -template<> class DataType -{ -public: - typedef uchar value_type; - typedef int work_type; - typedef value_type channel_type; - typedef value_type vec_type; - enum { generic_type = 0, depth = DataDepth::value, channels = 1, - fmt=DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; -}; - -template<> class DataType -{ -public: - typedef schar value_type; - typedef int work_type; - typedef value_type channel_type; - typedef value_type vec_type; - enum { generic_type = 0, depth = DataDepth::value, channels = 1, - fmt=DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; -}; - -template<> class DataType -{ -public: - typedef schar value_type; - typedef int work_type; - typedef value_type channel_type; - typedef value_type vec_type; - enum { generic_type = 0, depth = DataDepth::value, channels = 1, - fmt=DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; -}; - -template<> class DataType -{ -public: - typedef ushort value_type; - typedef int work_type; - typedef value_type channel_type; - typedef value_type vec_type; - enum { generic_type = 0, depth = DataDepth::value, channels = 1, - fmt=DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; -}; - -template<> class DataType -{ -public: - typedef short value_type; - typedef int work_type; - typedef value_type channel_type; - typedef value_type vec_type; - enum { generic_type = 0, depth = DataDepth::value, channels = 1, - fmt=DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; -}; - -template<> class DataType -{ -public: - typedef int value_type; - typedef value_type work_type; - typedef value_type channel_type; - typedef value_type vec_type; - enum { generic_type = 0, depth = DataDepth::value, channels = 1, - fmt=DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; -}; - -template<> class DataType -{ -public: - typedef float value_type; - typedef value_type work_type; - typedef value_type channel_type; - typedef value_type vec_type; - enum { generic_type = 0, depth = DataDepth::value, channels = 1, - fmt=DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; -}; - -template<> class DataType -{ -public: - typedef double value_type; - typedef value_type work_type; - typedef value_type channel_type; - typedef value_type vec_type; - enum { generic_type = 0, depth = DataDepth::value, channels = 1, - fmt=DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; -}; - -template class DataType > -{ -public: - typedef Matx<_Tp, m, n> value_type; - typedef Matx::work_type, m, n> work_type; - typedef _Tp channel_type; - typedef value_type vec_type; - enum { generic_type = 0, depth = DataDepth::value, channels = m*n, - fmt = ((channels-1)<<8) + DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; -}; - -template class DataType > -{ -public: - typedef Vec<_Tp, cn> value_type; - typedef Vec::work_type, cn> work_type; - typedef _Tp channel_type; - typedef value_type vec_type; - enum { generic_type = 0, depth = DataDepth::value, channels = cn, - fmt = ((channels-1)<<8) + DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; -}; - -template class DataType > -{ -public: - typedef std::complex<_Tp> value_type; - typedef value_type work_type; - typedef _Tp channel_type; - enum { generic_type = 0, depth = DataDepth::value, channels = 2, - fmt = ((channels-1)<<8) + DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; - typedef Vec vec_type; -}; - -template class DataType > -{ -public: - typedef Complex<_Tp> value_type; - typedef value_type work_type; - typedef _Tp channel_type; - enum { generic_type = 0, depth = DataDepth::value, channels = 2, - fmt = ((channels-1)<<8) + DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; - typedef Vec vec_type; -}; - -template class DataType > -{ -public: - typedef Point_<_Tp> value_type; - typedef Point_::work_type> work_type; - typedef _Tp channel_type; - enum { generic_type = 0, depth = DataDepth::value, channels = 2, - fmt = ((channels-1)<<8) + DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; - typedef Vec vec_type; -}; - -template class DataType > -{ -public: - typedef Point3_<_Tp> value_type; - typedef Point3_::work_type> work_type; - typedef _Tp channel_type; - enum { generic_type = 0, depth = DataDepth::value, channels = 3, - fmt = ((channels-1)<<8) + DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; - typedef Vec vec_type; -}; - -template class DataType > -{ -public: - typedef Size_<_Tp> value_type; - typedef Size_::work_type> work_type; - typedef _Tp channel_type; - enum { generic_type = 0, depth = DataDepth::value, channels = 2, - fmt = ((channels-1)<<8) + DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; - typedef Vec vec_type; -}; - -template class DataType > -{ -public: - typedef Rect_<_Tp> value_type; - typedef Rect_::work_type> work_type; - typedef _Tp channel_type; - enum { generic_type = 0, depth = DataDepth::value, channels = 4, - fmt = ((channels-1)<<8) + DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; - typedef Vec vec_type; -}; - -template class DataType > -{ -public: - typedef Scalar_<_Tp> value_type; - typedef Scalar_::work_type> work_type; - typedef _Tp channel_type; - enum { generic_type = 0, depth = DataDepth::value, channels = 4, - fmt = ((channels-1)<<8) + DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; - typedef Vec vec_type; -}; - -template<> class DataType -{ -public: - typedef Range value_type; - typedef value_type work_type; - typedef int channel_type; - enum { generic_type = 0, depth = DataDepth::value, channels = 2, - fmt = ((channels-1)<<8) + DataDepth::fmt, - type = CV_MAKETYPE(depth, channels) }; - typedef Vec vec_type; -}; - -//////////////////// generic_type ref-counting pointer class for C/C++ objects //////////////////////// - -/*! - Smart pointer to dynamically allocated objects. - - This is template pointer-wrapping class that stores the associated reference counter along with the - object pointer. The class is similar to std::smart_ptr<> from the recent addons to the C++ standard, - but is shorter to write :) and self-contained (i.e. does add any dependency on the compiler or an external library). - - Basically, you can use "Ptr ptr" (or faster "const Ptr& ptr" for read-only access) - everywhere instead of "MyObjectType* ptr", where MyObjectType is some C structure or a C++ class. - To make it all work, you need to specialize Ptr<>::delete_obj(), like: - - \code - template<> void Ptr::delete_obj() { call_destructor_func(obj); } - \endcode - - \note{if MyObjectType is a C++ class with a destructor, you do not need to specialize delete_obj(), - since the default implementation calls "delete obj;"} - - \note{Another good property of the class is that the operations on the reference counter are atomic, - i.e. it is safe to use the class in multi-threaded applications} -*/ -template class CV_EXPORTS Ptr -{ -public: - //! empty constructor - Ptr(); - //! take ownership of the pointer. The associated reference counter is allocated and set to 1 - Ptr(_Tp* _obj); - //! calls release() - ~Ptr(); - //! copy constructor. Copies the members and calls addref() - Ptr(const Ptr& ptr); - template Ptr(const Ptr<_Tp2>& ptr); - //! copy operator. Calls ptr.addref() and release() before copying the members - Ptr& operator = (const Ptr& ptr); - //! increments the reference counter - void addref(); - //! decrements the reference counter. If it reaches 0, delete_obj() is called - void release(); - //! deletes the object. Override if needed - void delete_obj(); - //! returns true iff obj==NULL - bool empty() const; - - //! cast pointer to another type - template Ptr<_Tp2> ptr(); - template const Ptr<_Tp2> ptr() const; - - //! helper operators making "Ptr ptr" use very similar to "T* ptr". - _Tp* operator -> (); - const _Tp* operator -> () const; - - operator _Tp* (); - operator const _Tp*() const; - - _Tp* obj; //< the object pointer. - int* refcount; //< the associated reference counter -}; - -template bool operator==(Ptr const & a, Ptr const & b); -template bool operator!=(Ptr const & a, Ptr const & b); - - -//////////////////////// Input/Output Array Arguments ///////////////////////////////// - -/*! - Proxy datatype for passing Mat's and vector<>'s as input parameters - */ -class CV_EXPORTS _InputArray -{ -public: - enum { - KIND_SHIFT = 16, - FIXED_TYPE = 0x8000 << KIND_SHIFT, - FIXED_SIZE = 0x4000 << KIND_SHIFT, - KIND_MASK = ~(FIXED_TYPE|FIXED_SIZE) - (1 << KIND_SHIFT) + 1, - - NONE = 0 << KIND_SHIFT, - MAT = 1 << KIND_SHIFT, - MATX = 2 << KIND_SHIFT, - STD_VECTOR = 3 << KIND_SHIFT, - STD_VECTOR_VECTOR = 4 << KIND_SHIFT, - STD_VECTOR_MAT = 5 << KIND_SHIFT, - EXPR = 6 << KIND_SHIFT, - OPENGL_BUFFER = 7 << KIND_SHIFT, - OPENGL_TEXTURE = 8 << KIND_SHIFT, - GPU_MAT = 9 << KIND_SHIFT - }; - _InputArray(); - - _InputArray(const Mat& m); - _InputArray(const MatExpr& expr); - template _InputArray(const _Tp* vec, int n); - template _InputArray(const std::vector<_Tp>& vec); - template _InputArray(const std::vector >& vec); - _InputArray(const std::vector& vec); - template _InputArray(const std::vector >& vec); - template _InputArray(const Mat_<_Tp>& m); - template _InputArray(const Matx<_Tp, m, n>& matx); - _InputArray(const Scalar& s); - _InputArray(const double& val); - _InputArray(const gpu::GpuMat& d_mat); - _InputArray(const ogl::Buffer& buf); - _InputArray(const ogl::Texture2D& tex); - - virtual Mat getMat(int i=-1) const; - virtual void getMatVector(std::vector& mv) const; - virtual gpu::GpuMat getGpuMat() const; - virtual ogl::Buffer getOGlBuffer() const; - virtual ogl::Texture2D getOGlTexture2D() const; - - virtual int kind() const; - virtual Size size(int i=-1) const; - virtual size_t total(int i=-1) const; - virtual int type(int i=-1) const; - virtual int depth(int i=-1) const; - virtual int channels(int i=-1) const; - virtual bool empty() const; - - virtual ~_InputArray(); - - int flags; - void* obj; - Size sz; -}; - - -enum -{ - DEPTH_MASK_8U = 1 << CV_8U, - DEPTH_MASK_8S = 1 << CV_8S, - DEPTH_MASK_16U = 1 << CV_16U, - DEPTH_MASK_16S = 1 << CV_16S, - DEPTH_MASK_32S = 1 << CV_32S, - DEPTH_MASK_32F = 1 << CV_32F, - DEPTH_MASK_64F = 1 << CV_64F, - DEPTH_MASK_ALL = (DEPTH_MASK_64F<<1)-1, - DEPTH_MASK_ALL_BUT_8S = DEPTH_MASK_ALL & ~DEPTH_MASK_8S, - DEPTH_MASK_FLT = DEPTH_MASK_32F + DEPTH_MASK_64F -}; - - -/*! - Proxy datatype for passing Mat's and vector<>'s as input parameters - */ -class CV_EXPORTS _OutputArray : public _InputArray -{ -public: - _OutputArray(); - - _OutputArray(Mat& m); - template _OutputArray(std::vector<_Tp>& vec); - template _OutputArray(std::vector >& vec); - _OutputArray(std::vector& vec); - template _OutputArray(std::vector >& vec); - template _OutputArray(Mat_<_Tp>& m); - template _OutputArray(Matx<_Tp, m, n>& matx); - template _OutputArray(_Tp* vec, int n); - _OutputArray(gpu::GpuMat& d_mat); - _OutputArray(ogl::Buffer& buf); - _OutputArray(ogl::Texture2D& tex); - - _OutputArray(const Mat& m); - template _OutputArray(const std::vector<_Tp>& vec); - template _OutputArray(const std::vector >& vec); - _OutputArray(const std::vector& vec); - template _OutputArray(const std::vector >& vec); - template _OutputArray(const Mat_<_Tp>& m); - template _OutputArray(const Matx<_Tp, m, n>& matx); - template _OutputArray(const _Tp* vec, int n); - _OutputArray(const gpu::GpuMat& d_mat); - _OutputArray(const ogl::Buffer& buf); - _OutputArray(const ogl::Texture2D& tex); - - virtual bool fixedSize() const; - virtual bool fixedType() const; - virtual bool needed() const; - virtual Mat& getMatRef(int i=-1) const; - virtual gpu::GpuMat& getGpuMatRef() const; - virtual ogl::Buffer& getOGlBufferRef() const; - virtual ogl::Texture2D& getOGlTexture2DRef() const; - virtual void create(Size sz, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; - virtual void create(int rows, int cols, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; - virtual void create(int dims, const int* size, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; - virtual void release() const; - virtual void clear() const; - - virtual ~_OutputArray(); -}; - -typedef const _InputArray& InputArray; -typedef InputArray InputArrayOfArrays; -typedef const _OutputArray& OutputArray; -typedef OutputArray OutputArrayOfArrays; -typedef OutputArray InputOutputArray; -typedef OutputArray InputOutputArrayOfArrays; - -CV_EXPORTS OutputArray noArray(); - -/////////////////////////////////////// Mat /////////////////////////////////////////// - -enum { MAGIC_MASK=0xFFFF0000, TYPE_MASK=0x00000FFF, DEPTH_MASK=7 }; - -static inline size_t getElemSize(int type) { return CV_ELEM_SIZE(type); } - -/*! - Custom array allocator - -*/ -class CV_EXPORTS MatAllocator -{ -public: - MatAllocator() {} - virtual ~MatAllocator() {} - virtual void allocate(int dims, const int* sizes, int type, int*& refcount, - uchar*& datastart, uchar*& data, size_t* step) = 0; - virtual void deallocate(int* refcount, uchar* datastart, uchar* data) = 0; -}; - -/*! - The n-dimensional matrix class. - - The class represents an n-dimensional dense numerical array that can act as - a matrix, image, optical flow map, 3-focal tensor etc. - It is very similar to CvMat and CvMatND types from earlier versions of OpenCV, - and similarly to those types, the matrix can be multi-channel. It also fully supports ROI mechanism. - - There are many different ways to create cv::Mat object. Here are the some popular ones: -
      -
    • using cv::Mat::create(nrows, ncols, type) method or - the similar constructor cv::Mat::Mat(nrows, ncols, type[, fill_value]) constructor. - A new matrix of the specified size and specifed type will be allocated. - "type" has the same meaning as in cvCreateMat function, - e.g. CV_8UC1 means 8-bit single-channel matrix, CV_32FC2 means 2-channel (i.e. complex) - floating-point matrix etc: - - \code - // make 7x7 complex matrix filled with 1+3j. - cv::Mat M(7,7,CV_32FC2,Scalar(1,3)); - // and now turn M to 100x60 15-channel 8-bit matrix. - // The old content will be deallocated - M.create(100,60,CV_8UC(15)); - \endcode - - As noted in the introduction of this chapter, Mat::create() - will only allocate a new matrix when the current matrix dimensionality - or type are different from the specified. - -
    • by using a copy constructor or assignment operator, where on the right side it can - be a matrix or expression, see below. Again, as noted in the introduction, - matrix assignment is O(1) operation because it only copies the header - and increases the reference counter. cv::Mat::clone() method can be used to get a full - (a.k.a. deep) copy of the matrix when you need it. - -
    • by constructing a header for a part of another matrix. It can be a single row, single column, - several rows, several columns, rectangular region in the matrix (called a minor in algebra) or - a diagonal. Such operations are also O(1), because the new header will reference the same data. - You can actually modify a part of the matrix using this feature, e.g. - - \code - // add 5-th row, multiplied by 3 to the 3rd row - M.row(3) = M.row(3) + M.row(5)*3; - - // now copy 7-th column to the 1-st column - // M.col(1) = M.col(7); // this will not work - Mat M1 = M.col(1); - M.col(7).copyTo(M1); - - // create new 320x240 image - cv::Mat img(Size(320,240),CV_8UC3); - // select a roi - cv::Mat roi(img, Rect(10,10,100,100)); - // fill the ROI with (0,255,0) (which is green in RGB space); - // the original 320x240 image will be modified - roi = Scalar(0,255,0); - \endcode - - Thanks to the additional cv::Mat::datastart and cv::Mat::dataend members, it is possible to - compute the relative sub-matrix position in the main "container" matrix using cv::Mat::locateROI(): - - \code - Mat A = Mat::eye(10, 10, CV_32S); - // extracts A columns, 1 (inclusive) to 3 (exclusive). - Mat B = A(Range::all(), Range(1, 3)); - // extracts B rows, 5 (inclusive) to 9 (exclusive). - // that is, C ~ A(Range(5, 9), Range(1, 3)) - Mat C = B(Range(5, 9), Range::all()); - Size size; Point ofs; - C.locateROI(size, ofs); - // size will be (width=10,height=10) and the ofs will be (x=1, y=5) - \endcode - - As in the case of whole matrices, if you need a deep copy, use cv::Mat::clone() method - of the extracted sub-matrices. - -
    • by making a header for user-allocated-data. It can be useful for -
        -
      1. processing "foreign" data using OpenCV (e.g. when you implement - a DirectShow filter or a processing module for gstreamer etc.), e.g. - - \code - void process_video_frame(const unsigned char* pixels, - int width, int height, int step) - { - cv::Mat img(height, width, CV_8UC3, pixels, step); - cv::GaussianBlur(img, img, cv::Size(7,7), 1.5, 1.5); - } - \endcode - -
      2. for quick initialization of small matrices and/or super-fast element access - - \code - double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}}; - cv::Mat M = cv::Mat(3, 3, CV_64F, m).inv(); - \endcode -
      - - partial yet very common cases of this "user-allocated data" case are conversions - from CvMat and IplImage to cv::Mat. For this purpose there are special constructors - taking pointers to CvMat or IplImage and the optional - flag indicating whether to copy the data or not. - - Backward conversion from cv::Mat to CvMat or IplImage is provided via cast operators - cv::Mat::operator CvMat() an cv::Mat::operator IplImage(). - The operators do not copy the data. - - - \code - IplImage* img = cvLoadImage("greatwave.jpg", 1); - Mat mtx(img); // convert IplImage* -> cv::Mat - CvMat oldmat = mtx; // convert cv::Mat -> CvMat - CV_Assert(oldmat.cols == img->width && oldmat.rows == img->height && - oldmat.data.ptr == (uchar*)img->imageData && oldmat.step == img->widthStep); - \endcode - -
    • by using MATLAB-style matrix initializers, cv::Mat::zeros(), cv::Mat::ones(), cv::Mat::eye(), e.g.: - - \code - // create a double-precision identity martix and add it to M. - M += Mat::eye(M.rows, M.cols, CV_64F); - \endcode - -
    • by using comma-separated initializer: - - \code - // create 3x3 double-precision identity matrix - Mat M = (Mat_(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1); - \endcode - - here we first call constructor of cv::Mat_ class (that we describe further) with the proper matrix, - and then we just put "<<" operator followed by comma-separated values that can be constants, - variables, expressions etc. Also, note the extra parentheses that are needed to avoid compiler errors. - -
    - - Once matrix is created, it will be automatically managed by using reference-counting mechanism - (unless the matrix header is built on top of user-allocated data, - in which case you should handle the data by yourself). - The matrix data will be deallocated when no one points to it; - if you want to release the data pointed by a matrix header before the matrix destructor is called, - use cv::Mat::release(). - - The next important thing to learn about the matrix class is element access. Here is how the matrix is stored. - The elements are stored in row-major order (row by row). The cv::Mat::data member points to the first element of the first row, - cv::Mat::rows contains the number of matrix rows and cv::Mat::cols - the number of matrix columns. There is yet another member, - cv::Mat::step that is used to actually compute address of a matrix element. cv::Mat::step is needed because the matrix can be - a part of another matrix or because there can some padding space in the end of each row for a proper alignment. - - \image html roi.png - - Given these parameters, address of the matrix element M_{ij} is computed as following: - - addr(M_{ij})=M.data + M.step*i + j*M.elemSize() - - if you know the matrix element type, e.g. it is float, then you can use cv::Mat::at() method: - - addr(M_{ij})=&M.at(i,j) - - (where & is used to convert the reference returned by cv::Mat::at() to a pointer). - if you need to process a whole row of matrix, the most efficient way is to get - the pointer to the row first, and then just use plain C operator []: - - \code - // compute sum of positive matrix elements - // (assuming that M is double-precision matrix) - double sum=0; - for(int i = 0; i < M.rows; i++) - { - const double* Mi = M.ptr(i); - for(int j = 0; j < M.cols; j++) - sum += std::max(Mi[j], 0.); - } - \endcode - - Some operations, like the above one, do not actually depend on the matrix shape, - they just process elements of a matrix one by one (or elements from multiple matrices - that are sitting in the same place, e.g. matrix addition). Such operations are called - element-wise and it makes sense to check whether all the input/output matrices are continuous, - i.e. have no gaps in the end of each row, and if yes, process them as a single long row: - - \code - // compute sum of positive matrix elements, optimized variant - double sum=0; - int cols = M.cols, rows = M.rows; - if(M.isContinuous()) - { - cols *= rows; - rows = 1; - } - for(int i = 0; i < rows; i++) - { - const double* Mi = M.ptr(i); - for(int j = 0; j < cols; j++) - sum += std::max(Mi[j], 0.); - } - \endcode - in the case of continuous matrix the outer loop body will be executed just once, - so the overhead will be smaller, which will be especially noticeable in the case of small matrices. - - Finally, there are STL-style iterators that are smart enough to skip gaps between successive rows: - \code - // compute sum of positive matrix elements, iterator-based variant - double sum=0; - MatConstIterator_ it = M.begin(), it_end = M.end(); - for(; it != it_end; ++it) - sum += std::max(*it, 0.); - \endcode - - The matrix iterators are random-access iterators, so they can be passed - to any STL algorithm, including std::sort(). -*/ -class CV_EXPORTS Mat -{ -public: - //! default constructor - Mat(); - //! constructs 2D matrix of the specified size and type - // (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.) - Mat(int rows, int cols, int type); - Mat(Size size, int type); - //! constucts 2D matrix and fills it with the specified value _s. - Mat(int rows, int cols, int type, const Scalar& s); - Mat(Size size, int type, const Scalar& s); - - //! constructs n-dimensional matrix - Mat(int ndims, const int* sizes, int type); - Mat(int ndims, const int* sizes, int type, const Scalar& s); - - //! copy constructor - Mat(const Mat& m); - //! constructor for matrix headers pointing to user-allocated data - Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP); - Mat(Size size, int type, void* data, size_t step=AUTO_STEP); - Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0); - - //! creates a matrix header for a part of the bigger matrix - Mat(const Mat& m, const Range& rowRange, const Range& colRange=Range::all()); - Mat(const Mat& m, const Rect& roi); - Mat(const Mat& m, const Range* ranges); - //! converts old-style CvMat to the new matrix; the data is not copied by default - Mat(const CvMat* m, bool copyData=false); - //! converts old-style CvMatND to the new matrix; the data is not copied by default - Mat(const CvMatND* m, bool copyData=false); - //! converts old-style IplImage to the new matrix; the data is not copied by default - Mat(const IplImage* img, bool copyData=false); - //! builds matrix from std::vector with or without copying the data - template explicit Mat(const std::vector<_Tp>& vec, bool copyData=false); - //! builds matrix from cv::Vec; the data is copied by default - template explicit Mat(const Vec<_Tp, n>& vec, bool copyData=true); - //! builds matrix from cv::Matx; the data is copied by default - template explicit Mat(const Matx<_Tp, m, n>& mtx, bool copyData=true); - //! builds matrix from a 2D point - template explicit Mat(const Point_<_Tp>& pt, bool copyData=true); - //! builds matrix from a 3D point - template explicit Mat(const Point3_<_Tp>& pt, bool copyData=true); - //! builds matrix from comma initializer - template explicit Mat(const MatCommaInitializer_<_Tp>& commaInitializer); - - //! download data from GpuMat - explicit Mat(const gpu::GpuMat& m); - - //! destructor - calls release() - ~Mat(); - //! assignment operators - Mat& operator = (const Mat& m); - Mat& operator = (const MatExpr& expr); - - //! returns a new matrix header for the specified row - Mat row(int y) const; - //! returns a new matrix header for the specified column - Mat col(int x) const; - //! ... for the specified row span - Mat rowRange(int startrow, int endrow) const; - Mat rowRange(const Range& r) const; - //! ... for the specified column span - Mat colRange(int startcol, int endcol) const; - Mat colRange(const Range& r) const; - //! ... for the specified diagonal - // (d=0 - the main diagonal, - // >0 - a diagonal from the lower half, - // <0 - a diagonal from the upper half) - Mat diag(int d=0) const; - //! constructs a square diagonal matrix which main diagonal is vector "d" - static Mat diag(const Mat& d); - - //! returns deep copy of the matrix, i.e. the data is copied - Mat clone() const; - //! copies the matrix content to "m". - // It calls m.create(this->size(), this->type()). - void copyTo( OutputArray m ) const; - //! copies those matrix elements to "m" that are marked with non-zero mask elements. - void copyTo( OutputArray m, InputArray mask ) const; - //! converts matrix to another datatype with optional scalng. See cvConvertScale. - void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const; - - void assignTo( Mat& m, int type=-1 ) const; - - //! sets every matrix element to s - Mat& operator = (const Scalar& s); - //! sets some of the matrix elements to s, according to the mask - Mat& setTo(InputArray value, InputArray mask=noArray()); - //! creates alternative matrix header for the same data, with different - // number of channels and/or different number of rows. see cvReshape. - Mat reshape(int cn, int rows=0) const; - Mat reshape(int cn, int newndims, const int* newsz) const; - - //! matrix transposition by means of matrix expressions - MatExpr t() const; - //! matrix inversion by means of matrix expressions - MatExpr inv(int method=DECOMP_LU) const; - //! per-element matrix multiplication by means of matrix expressions - MatExpr mul(InputArray m, double scale=1) const; - - //! computes cross-product of 2 3D vectors - Mat cross(InputArray m) const; - //! computes dot-product - double dot(InputArray m) const; - - //! Matlab-style matrix initialization - static MatExpr zeros(int rows, int cols, int type); - static MatExpr zeros(Size size, int type); - static MatExpr zeros(int ndims, const int* sz, int type); - static MatExpr ones(int rows, int cols, int type); - static MatExpr ones(Size size, int type); - static MatExpr ones(int ndims, const int* sz, int type); - static MatExpr eye(int rows, int cols, int type); - static MatExpr eye(Size size, int type); - - //! allocates new matrix data unless the matrix already has specified size and type. - // previous data is unreferenced if needed. - void create(int rows, int cols, int type); - void create(Size size, int type); - void create(int ndims, const int* sizes, int type); - - //! increases the reference counter; use with care to avoid memleaks - void addref(); - //! decreases reference counter; - // deallocates the data when reference counter reaches 0. - void release(); - - //! deallocates the matrix data - void deallocate(); - //! internal use function; properly re-allocates _size, _step arrays - void copySize(const Mat& m); - - //! reserves enough space to fit sz hyper-planes - void reserve(size_t sz); - //! resizes matrix to the specified number of hyper-planes - void resize(size_t sz); - //! resizes matrix to the specified number of hyper-planes; initializes the newly added elements - void resize(size_t sz, const Scalar& s); - //! internal function - void push_back_(const void* elem); - //! adds element to the end of 1d matrix (or possibly multiple elements when _Tp=Mat) - template void push_back(const _Tp& elem); - template void push_back(const Mat_<_Tp>& elem); - void push_back(const Mat& m); - //! removes several hyper-planes from bottom of the matrix - void pop_back(size_t nelems=1); - - //! locates matrix header within a parent matrix. See below - void locateROI( Size& wholeSize, Point& ofs ) const; - //! moves/resizes the current matrix ROI inside the parent matrix. - Mat& adjustROI( int dtop, int dbottom, int dleft, int dright ); - //! extracts a rectangular sub-matrix - // (this is a generalized form of row, rowRange etc.) - Mat operator()( Range rowRange, Range colRange ) const; - Mat operator()( const Rect& roi ) const; - Mat operator()( const Range* ranges ) const; - - //! converts header to CvMat; no data is copied - operator CvMat() const; - //! converts header to CvMatND; no data is copied - operator CvMatND() const; - //! converts header to IplImage; no data is copied - operator IplImage() const; - - template operator std::vector<_Tp>() const; - template operator Vec<_Tp, n>() const; - template operator Matx<_Tp, m, n>() const; - - //! returns true iff the matrix data is continuous - // (i.e. when there are no gaps between successive rows). - // similar to CV_IS_MAT_CONT(cvmat->type) - bool isContinuous() const; - - //! returns true if the matrix is a submatrix of another matrix - bool isSubmatrix() const; - - //! returns element size in bytes, - // similar to CV_ELEM_SIZE(cvmat->type) - size_t elemSize() const; - //! returns the size of element channel in bytes. - size_t elemSize1() const; - //! returns element type, similar to CV_MAT_TYPE(cvmat->type) - int type() const; - //! returns element type, similar to CV_MAT_DEPTH(cvmat->type) - int depth() const; - //! returns element type, similar to CV_MAT_CN(cvmat->type) - int channels() const; - //! returns step/elemSize1() - size_t step1(int i=0) const; - //! returns true if matrix data is NULL - bool empty() const; - //! returns the total number of matrix elements - size_t total() const; - - //! returns N if the matrix is 1-channel (N x ptdim) or ptdim-channel (1 x N) or (N x 1); negative number otherwise - int checkVector(int elemChannels, int depth=-1, bool requireContinuous=true) const; - - //! returns pointer to i0-th submatrix along the dimension #0 - uchar* ptr(int i0=0); - const uchar* ptr(int i0=0) const; - - //! returns pointer to (i0,i1) submatrix along the dimensions #0 and #1 - uchar* ptr(int i0, int i1); - const uchar* ptr(int i0, int i1) const; - - //! returns pointer to (i0,i1,i3) submatrix along the dimensions #0, #1, #2 - uchar* ptr(int i0, int i1, int i2); - const uchar* ptr(int i0, int i1, int i2) const; - - //! returns pointer to the matrix element - uchar* ptr(const int* idx); - //! returns read-only pointer to the matrix element - const uchar* ptr(const int* idx) const; - - template uchar* ptr(const Vec& idx); - template const uchar* ptr(const Vec& idx) const; - - //! template version of the above method - template _Tp* ptr(int i0=0); - template const _Tp* ptr(int i0=0) const; - - template _Tp* ptr(int i0, int i1); - template const _Tp* ptr(int i0, int i1) const; - - template _Tp* ptr(int i0, int i1, int i2); - template const _Tp* ptr(int i0, int i1, int i2) const; - - template _Tp* ptr(const int* idx); - template const _Tp* ptr(const int* idx) const; - - template _Tp* ptr(const Vec& idx); - template const _Tp* ptr(const Vec& idx) const; - - //! the same as above, with the pointer dereferencing - template _Tp& at(int i0=0); - template const _Tp& at(int i0=0) const; - - template _Tp& at(int i0, int i1); - template const _Tp& at(int i0, int i1) const; - - template _Tp& at(int i0, int i1, int i2); - template const _Tp& at(int i0, int i1, int i2) const; - - template _Tp& at(const int* idx); - template const _Tp& at(const int* idx) const; - - template _Tp& at(const Vec& idx); - template const _Tp& at(const Vec& idx) const; - - //! special versions for 2D arrays (especially convenient for referencing image pixels) - template _Tp& at(Point pt); - template const _Tp& at(Point pt) const; - - //! template methods for iteration over matrix elements. - // the iterators take care of skipping gaps in the end of rows (if any) - template MatIterator_<_Tp> begin(); - template MatIterator_<_Tp> end(); - template MatConstIterator_<_Tp> begin() const; - template MatConstIterator_<_Tp> end() const; - - enum { MAGIC_VAL=0x42FF0000, AUTO_STEP=0, CONTINUOUS_FLAG=CV_MAT_CONT_FLAG, SUBMATRIX_FLAG=CV_SUBMAT_FLAG }; - - /*! includes several bit-fields: - - the magic signature - - continuity flag - - depth - - number of channels - */ - int flags; - //! the matrix dimensionality, >= 2 - int dims; - //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions - int rows, cols; - //! pointer to the data - uchar* data; - - //! pointer to the reference counter; - // when matrix points to user-allocated data, the pointer is NULL - int* refcount; - - //! helper fields used in locateROI and adjustROI - uchar* datastart; - uchar* dataend; - uchar* datalimit; - - //! custom allocator - MatAllocator* allocator; - - struct CV_EXPORTS MSize - { - MSize(int* _p); - Size operator()() const; - const int& operator[](int i) const; - int& operator[](int i); - operator const int*() const; - bool operator == (const MSize& sz) const; - bool operator != (const MSize& sz) const; - - int* p; - }; - - struct CV_EXPORTS MStep - { - MStep(); - MStep(size_t s); - const size_t& operator[](int i) const; - size_t& operator[](int i); - operator size_t() const; - MStep& operator = (size_t s); - - size_t* p; - size_t buf[2]; - protected: - MStep& operator = (const MStep&); - }; - - MSize size; - MStep step; - -protected: - void initEmpty(); -}; - - -/*! - Random Number Generator - - The class implements RNG using Multiply-with-Carry algorithm -*/ -class CV_EXPORTS RNG -{ -public: - enum { UNIFORM=0, NORMAL=1 }; - - RNG(); - RNG(uint64 state); - //! updates the state and returns the next 32-bit unsigned integer random number - unsigned next(); - - operator uchar(); - operator schar(); - operator ushort(); - operator short(); - operator unsigned(); - //! returns a random integer sampled uniformly from [0, N). - unsigned operator ()(unsigned N); - unsigned operator ()(); - operator int(); - operator float(); - operator double(); - //! returns uniformly distributed integer random number from [a,b) range - int uniform(int a, int b); - //! returns uniformly distributed floating-point random number from [a,b) range - float uniform(float a, float b); - //! returns uniformly distributed double-precision floating-point random number from [a,b) range - double uniform(double a, double b); - void fill( InputOutputArray mat, int distType, InputArray a, InputArray b, bool saturateRange=false ); - //! returns Gaussian random variate with mean zero. - double gaussian(double sigma); - - uint64 state; -}; - -class CV_EXPORTS RNG_MT19937 -{ -public: - RNG_MT19937(); - RNG_MT19937(unsigned s); - void seed(unsigned s); - - unsigned next(); - - operator int(); - operator unsigned(); - operator float(); - operator double(); - - unsigned operator ()(unsigned N); - unsigned operator ()(); - - // returns uniformly distributed integer random number from [a,b) range - int uniform(int a, int b); - // returns uniformly distributed floating-point random number from [a,b) range - float uniform(float a, float b); - // returns uniformly distributed double-precision floating-point random number from [a,b) range - double uniform(double a, double b); - -private: - enum PeriodParameters {N = 624, M = 397}; - unsigned state[N]; - int mti; -}; - -/*! - Termination criteria in iterative algorithms - */ -class CV_EXPORTS TermCriteria -{ -public: - enum - { - COUNT=1, //!< the maximum number of iterations or elements to compute - MAX_ITER=COUNT, //!< ditto - EPS=2 //!< the desired accuracy or change in parameters at which the iterative algorithm stops - }; - - //! default constructor - TermCriteria(); - //! full constructor - TermCriteria(int type, int maxCount, double epsilon); - //! conversion from CvTermCriteria - TermCriteria(const CvTermCriteria& criteria); - //! conversion to CvTermCriteria - operator CvTermCriteria() const; - - int type; //!< the type of termination criteria: COUNT, EPS or COUNT + EPS - int maxCount; // the maximum number of iterations/elements - double epsilon; // the desired accuracy -}; - - -typedef void (*BinaryFunc)(const uchar* src1, size_t step1, - const uchar* src2, size_t step2, - uchar* dst, size_t step, Size sz, - void*); - -CV_EXPORTS BinaryFunc getConvertFunc(int sdepth, int ddepth); -CV_EXPORTS BinaryFunc getConvertScaleFunc(int sdepth, int ddepth); -CV_EXPORTS BinaryFunc getCopyMaskFunc(size_t esz); //! swaps two matrices CV_EXPORTS void swap(Mat& a, Mat& b); -//! converts array (CvMat or IplImage) to cv::Mat -CV_EXPORTS Mat cvarrToMat(const CvArr* arr, bool copyData=false, - bool allowND=true, int coiMode=0, - AutoBuffer* buf=0); -//! extracts Channel of Interest from CvMat or IplImage and makes cv::Mat out of it. -CV_EXPORTS void extractImageCOI(const CvArr* arr, OutputArray coiimg, int coi=-1); -//! inserts single-channel cv::Mat into a multi-channel CvMat or IplImage -CV_EXPORTS void insertImageCOI(InputArray coiimg, CvArr* arr, int coi=-1); +//! 1D interpolation function: returns coordinate of the "donor" pixel for the specified location p. +CV_EXPORTS_W int borderInterpolate(int p, int len, int borderType); + +//! copies 2D array to a larger destination array with extrapolation of the outer part of src using the specified border mode +CV_EXPORTS_W void copyMakeBorder(InputArray src, OutputArray dst, + int top, int bottom, int left, int right, + int borderType, const Scalar& value = Scalar() ); //! adds one matrix to another (dst = src1 + src2) CV_EXPORTS_W void add(InputArray src1, InputArray src2, OutputArray dst, - InputArray mask=noArray(), int dtype=-1); + InputArray mask = noArray(), int dtype = -1); + //! subtracts one matrix from another (dst = src1 - src2) CV_EXPORTS_W void subtract(InputArray src1, InputArray src2, OutputArray dst, - InputArray mask=noArray(), int dtype=-1); + InputArray mask = noArray(), int dtype = -1); //! computes element-wise weighted product of the two arrays (dst = scale*src1*src2) CV_EXPORTS_W void multiply(InputArray src1, InputArray src2, - OutputArray dst, double scale=1, int dtype=-1); + OutputArray dst, double scale = 1, int dtype = -1); -//! computes element-wise weighted quotient of the two arrays (dst = scale*src1/src2) +//! computes element-wise weighted quotient of the two arrays (dst = scale * src1 / src2) CV_EXPORTS_W void divide(InputArray src1, InputArray src2, OutputArray dst, - double scale=1, int dtype=-1); + double scale = 1, int dtype = -1); //! computes element-wise weighted reciprocal of an array (dst = scale/src2) CV_EXPORTS_W void divide(double scale, InputArray src2, - OutputArray dst, int dtype=-1); + OutputArray dst, int dtype = -1); //! adds scaled array to another one (dst = alpha*src1 + src2) CV_EXPORTS_W void scaleAdd(InputArray src1, double alpha, InputArray src2, OutputArray dst); //! computes weighted sum of two arrays (dst = alpha*src1 + beta*src2 + gamma) CV_EXPORTS_W void addWeighted(InputArray src1, double alpha, InputArray src2, - double beta, double gamma, OutputArray dst, int dtype=-1); + double beta, double gamma, OutputArray dst, int dtype = -1); //! scales array elements, computes absolute values and converts the results to 8-bit unsigned integers: dst(i)=saturate_castabs(src(i)*alpha+beta) CV_EXPORTS_W void convertScaleAbs(InputArray src, OutputArray dst, - double alpha=1, double beta=0); + double alpha = 1, double beta = 0); + //! transforms array of numbers using a lookup table: dst(i)=lut(src(i)) -CV_EXPORTS_W void LUT(InputArray src, InputArray lut, OutputArray dst, - int interpolation=0); +CV_EXPORTS_W void LUT(InputArray src, InputArray lut, OutputArray dst); //! computes sum of array elements CV_EXPORTS_AS(sumElems) Scalar sum(InputArray src); + //! computes the number of nonzero array elements CV_EXPORTS_W int countNonZero( InputArray src ); + //! returns the list of locations of non-zero pixels CV_EXPORTS_W void findNonZero( InputArray src, OutputArray idx ); //! computes mean value of selected array elements -CV_EXPORTS_W Scalar mean(InputArray src, InputArray mask=noArray()); +CV_EXPORTS_W Scalar mean(InputArray src, InputArray mask = noArray()); + //! computes mean value and standard deviation of all or selected array elements CV_EXPORTS_W void meanStdDev(InputArray src, OutputArray mean, OutputArray stddev, InputArray mask=noArray()); + //! computes norm of the selected array part -CV_EXPORTS_W double norm(InputArray src1, int normType=NORM_L2, InputArray mask=noArray()); +CV_EXPORTS_W double norm(InputArray src1, int normType = NORM_L2, InputArray mask = noArray()); + //! computes norm of selected part of the difference between two arrays CV_EXPORTS_W double norm(InputArray src1, InputArray src2, - int normType=NORM_L2, InputArray mask=noArray()); + int normType = NORM_L2, InputArray mask = noArray()); + +//! computes PSNR image/video quality metric +CV_EXPORTS_W double PSNR(InputArray src1, InputArray src2); + +//! computes norm of a sparse matrix +CV_EXPORTS double norm( const SparseMat& src, int normType ); //! naive nearest neighbor finder CV_EXPORTS_W void batchDistance(InputArray src1, InputArray src2, OutputArray dist, int dtype, OutputArray nidx, - int normType=NORM_L2, int K=0, - InputArray mask=noArray(), int update=0, - bool crosscheck=false); + int normType = NORM_L2, int K = 0, + InputArray mask = noArray(), int update = 0, + bool crosscheck = false); //! scales and shifts array elements so that either the specified norm (alpha) or the minimum (alpha) and maximum (beta) array values get the specified values -CV_EXPORTS_W void normalize( InputArray src, OutputArray dst, double alpha=1, double beta=0, - int norm_type=NORM_L2, int dtype=-1, InputArray mask=noArray()); +CV_EXPORTS_W void normalize( InputArray src, OutputArray dst, double alpha = 1, double beta = 0, + int norm_type = NORM_L2, int dtype = -1, InputArray mask = noArray()); + +//! scales and shifts array elements so that either the specified norm (alpha) or the minimum (alpha) and maximum (beta) array values get the specified values +CV_EXPORTS void normalize( const SparseMat& src, SparseMat& dst, double alpha, int normType ); //! finds global minimum and maximum array elements and returns their values and their locations CV_EXPORTS_W void minMaxLoc(InputArray src, CV_OUT double* minVal, - CV_OUT double* maxVal=0, CV_OUT Point* minLoc=0, - CV_OUT Point* maxLoc=0, InputArray mask=noArray()); -CV_EXPORTS void minMaxIdx(InputArray src, double* minVal, double* maxVal, - int* minIdx=0, int* maxIdx=0, InputArray mask=noArray()); + CV_OUT double* maxVal = 0, CV_OUT Point* minLoc = 0, + CV_OUT Point* maxLoc = 0, InputArray mask = noArray()); + +CV_EXPORTS void minMaxIdx(InputArray src, double* minVal, double* maxVal = 0, + int* minIdx = 0, int* maxIdx = 0, InputArray mask = noArray()); + +//! finds global minimum and maximum sparse array elements and returns their values and their locations +CV_EXPORTS void minMaxLoc(const SparseMat& a, double* minVal, + double* maxVal, int* minIdx = 0, int* maxIdx = 0); //! transforms 2D matrix to 1D row or column vector by taking sum, minimum, maximum or mean value over all the rows -CV_EXPORTS_W void reduce(InputArray src, OutputArray dst, int dim, int rtype, int dtype=-1); +CV_EXPORTS_W void reduce(InputArray src, OutputArray dst, int dim, int rtype, int dtype = -1); //! makes multi-channel array out of several single-channel arrays CV_EXPORTS void merge(const Mat* mv, size_t count, OutputArray dst); + //! makes multi-channel array out of several single-channel arrays CV_EXPORTS_W void merge(InputArrayOfArrays mv, OutputArray dst); //! copies each plane of a multi-channel array to a dedicated array CV_EXPORTS void split(const Mat& src, Mat* mvbegin); + //! copies each plane of a multi-channel array to a dedicated array CV_EXPORTS_W void split(InputArray m, OutputArrayOfArrays mv); //! copies selected channels from the input arrays to the selected channels of the output arrays CV_EXPORTS void mixChannels(const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, const int* fromTo, size_t npairs); -CV_EXPORTS void mixChannels(const std::vector& src, std::vector& dst, + +CV_EXPORTS void mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, const int* fromTo, size_t npairs); -CV_EXPORTS_W void mixChannels(InputArrayOfArrays src, InputArrayOfArrays dst, + +CV_EXPORTS_W void mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, const std::vector& fromTo); //! extracts a single channel from src (coi is 0-based index) @@ -2194,155 +291,299 @@ CV_EXPORTS_W void flip(InputArray src, OutputArray dst, int flipCode); //! replicates the input matrix the specified number of times in the horizontal and/or vertical direction CV_EXPORTS_W void repeat(InputArray src, int ny, int nx, OutputArray dst); + CV_EXPORTS Mat repeat(const Mat& src, int ny, int nx); CV_EXPORTS void hconcat(const Mat* src, size_t nsrc, OutputArray dst); + CV_EXPORTS void hconcat(InputArray src1, InputArray src2, OutputArray dst); + CV_EXPORTS_W void hconcat(InputArrayOfArrays src, OutputArray dst); CV_EXPORTS void vconcat(const Mat* src, size_t nsrc, OutputArray dst); + CV_EXPORTS void vconcat(InputArray src1, InputArray src2, OutputArray dst); + CV_EXPORTS_W void vconcat(InputArrayOfArrays src, OutputArray dst); //! computes bitwise conjunction of the two arrays (dst = src1 & src2) CV_EXPORTS_W void bitwise_and(InputArray src1, InputArray src2, - OutputArray dst, InputArray mask=noArray()); + OutputArray dst, InputArray mask = noArray()); + //! computes bitwise disjunction of the two arrays (dst = src1 | src2) CV_EXPORTS_W void bitwise_or(InputArray src1, InputArray src2, - OutputArray dst, InputArray mask=noArray()); + OutputArray dst, InputArray mask = noArray()); + //! computes bitwise exclusive-or of the two arrays (dst = src1 ^ src2) CV_EXPORTS_W void bitwise_xor(InputArray src1, InputArray src2, - OutputArray dst, InputArray mask=noArray()); + OutputArray dst, InputArray mask = noArray()); + //! inverts each bit of array (dst = ~src) CV_EXPORTS_W void bitwise_not(InputArray src, OutputArray dst, - InputArray mask=noArray()); + InputArray mask = noArray()); + //! computes element-wise absolute difference of two arrays (dst = abs(src1 - src2)) CV_EXPORTS_W void absdiff(InputArray src1, InputArray src2, OutputArray dst); + //! set mask elements for those array elements which are within the element-specific bounding box (dst = lowerb <= src && src < upperb) CV_EXPORTS_W void inRange(InputArray src, InputArray lowerb, InputArray upperb, OutputArray dst); + //! compares elements of two arrays (dst = src1 src2) CV_EXPORTS_W void compare(InputArray src1, InputArray src2, OutputArray dst, int cmpop); + //! computes per-element minimum of two arrays (dst = min(src1, src2)) CV_EXPORTS_W void min(InputArray src1, InputArray src2, OutputArray dst); + //! computes per-element maximum of two arrays (dst = max(src1, src2)) CV_EXPORTS_W void max(InputArray src1, InputArray src2, OutputArray dst); +// the following overloads are needed to avoid conflicts with +// const _Tp& std::min(const _Tp&, const _Tp&, _Compare) //! computes per-element minimum of two arrays (dst = min(src1, src2)) CV_EXPORTS void min(const Mat& src1, const Mat& src2, Mat& dst); -//! computes per-element minimum of array and scalar (dst = min(src1, src2)) -CV_EXPORTS void min(const Mat& src1, double src2, Mat& dst); //! computes per-element maximum of two arrays (dst = max(src1, src2)) CV_EXPORTS void max(const Mat& src1, const Mat& src2, Mat& dst); -//! computes per-element maximum of array and scalar (dst = max(src1, src2)) -CV_EXPORTS void max(const Mat& src1, double src2, Mat& dst); //! computes square root of each matrix element (dst = src**0.5) CV_EXPORTS_W void sqrt(InputArray src, OutputArray dst); + //! raises the input matrix elements to the specified power (b = a**power) CV_EXPORTS_W void pow(InputArray src, double power, OutputArray dst); + //! computes exponent of each matrix element (dst = e**src) CV_EXPORTS_W void exp(InputArray src, OutputArray dst); + //! computes natural logarithm of absolute value of each matrix element: dst = log(abs(src)) CV_EXPORTS_W void log(InputArray src, OutputArray dst); -//! computes cube root of the argument -CV_EXPORTS_W float cubeRoot(float val); -//! computes the angle in degrees (0..360) of the vector (x,y) -CV_EXPORTS_W float fastAtan2(float y, float x); - -CV_EXPORTS void exp(const float* src, float* dst, int n); -CV_EXPORTS void log(const float* src, float* dst, int n); -CV_EXPORTS void fastAtan2(const float* y, const float* x, float* dst, int n, bool angleInDegrees); -CV_EXPORTS void magnitude(const float* x, const float* y, float* dst, int n); //! converts polar coordinates to Cartesian CV_EXPORTS_W void polarToCart(InputArray magnitude, InputArray angle, - OutputArray x, OutputArray y, bool angleInDegrees=false); + OutputArray x, OutputArray y, bool angleInDegrees = false); + //! converts Cartesian coordinates to polar CV_EXPORTS_W void cartToPolar(InputArray x, InputArray y, OutputArray magnitude, OutputArray angle, - bool angleInDegrees=false); + bool angleInDegrees = false); + //! computes angle (angle(i)) of each (x(i), y(i)) vector CV_EXPORTS_W void phase(InputArray x, InputArray y, OutputArray angle, - bool angleInDegrees=false); + bool angleInDegrees = false); + //! computes magnitude (magnitude(i)) of each (x(i), y(i)) vector CV_EXPORTS_W void magnitude(InputArray x, InputArray y, OutputArray magnitude); + //! checks that each matrix element is within the specified range. -CV_EXPORTS_W bool checkRange(InputArray a, bool quiet=true, CV_OUT Point* pos=0, - double minVal=-DBL_MAX, double maxVal=DBL_MAX); +CV_EXPORTS_W bool checkRange(InputArray a, bool quiet = true, CV_OUT Point* pos = 0, + double minVal = -DBL_MAX, double maxVal = DBL_MAX); + //! converts NaN's to the given number -CV_EXPORTS_W void patchNaNs(InputOutputArray a, double val=0); +CV_EXPORTS_W void patchNaNs(InputOutputArray a, double val = 0); //! implements generalized matrix product algorithm GEMM from BLAS CV_EXPORTS_W void gemm(InputArray src1, InputArray src2, double alpha, - InputArray src3, double gamma, OutputArray dst, int flags=0); + InputArray src3, double gamma, OutputArray dst, int flags = 0); + //! multiplies matrix by its transposition from the left or from the right CV_EXPORTS_W void mulTransposed( InputArray src, OutputArray dst, bool aTa, - InputArray delta=noArray(), - double scale=1, int dtype=-1 ); + InputArray delta = noArray(), + double scale = 1, int dtype = -1 ); + //! transposes the matrix CV_EXPORTS_W void transpose(InputArray src, OutputArray dst); + //! performs affine transformation of each element of multi-channel input matrix CV_EXPORTS_W void transform(InputArray src, OutputArray dst, InputArray m ); + //! performs perspective transformation of each element of multi-channel input matrix CV_EXPORTS_W void perspectiveTransform(InputArray src, OutputArray dst, InputArray m ); //! extends the symmetrical matrix from the lower half or from the upper half -CV_EXPORTS_W void completeSymm(InputOutputArray mtx, bool lowerToUpper=false); +CV_EXPORTS_W void completeSymm(InputOutputArray mtx, bool lowerToUpper = false); + //! initializes scaled identity matrix -CV_EXPORTS_W void setIdentity(InputOutputArray mtx, const Scalar& s=Scalar(1)); +CV_EXPORTS_W void setIdentity(InputOutputArray mtx, const Scalar& s = Scalar(1)); + //! computes determinant of a square matrix CV_EXPORTS_W double determinant(InputArray mtx); + //! computes trace of a matrix CV_EXPORTS_W Scalar trace(InputArray mtx); + //! computes inverse or pseudo-inverse matrix -CV_EXPORTS_W double invert(InputArray src, OutputArray dst, int flags=DECOMP_LU); +CV_EXPORTS_W double invert(InputArray src, OutputArray dst, int flags = DECOMP_LU); + //! solves linear system or a least-square problem CV_EXPORTS_W bool solve(InputArray src1, InputArray src2, - OutputArray dst, int flags=DECOMP_LU); - -enum -{ - SORT_EVERY_ROW=0, - SORT_EVERY_COLUMN=1, - SORT_ASCENDING=0, - SORT_DESCENDING=16 -}; + OutputArray dst, int flags = DECOMP_LU); //! sorts independently each matrix row or each matrix column CV_EXPORTS_W void sort(InputArray src, OutputArray dst, int flags); + //! sorts independently each matrix row or each matrix column CV_EXPORTS_W void sortIdx(InputArray src, OutputArray dst, int flags); + //! finds real roots of a cubic polynomial CV_EXPORTS_W int solveCubic(InputArray coeffs, OutputArray roots); -//! finds real and complex roots of a polynomial -CV_EXPORTS_W double solvePoly(InputArray coeffs, OutputArray roots, int maxIters=300); -//! finds eigenvalues of a symmetric matrix -CV_EXPORTS bool eigen(InputArray src, OutputArray eigenvalues, int lowindex=-1, - int highindex=-1); -//! finds eigenvalues and eigenvectors of a symmetric matrix -CV_EXPORTS bool eigen(InputArray src, OutputArray eigenvalues, - OutputArray eigenvectors, - int lowindex=-1, int highindex=-1); -CV_EXPORTS_W bool eigen(InputArray src, bool computeEigenvectors, - OutputArray eigenvalues, OutputArray eigenvectors); -enum -{ - COVAR_SCRAMBLED=0, - COVAR_NORMAL=1, - COVAR_USE_AVG=2, - COVAR_SCALE=4, - COVAR_ROWS=8, - COVAR_COLS=16 -}; +//! finds real and complex roots of a polynomial +CV_EXPORTS_W double solvePoly(InputArray coeffs, OutputArray roots, int maxIters = 300); + +//! finds eigenvalues and eigenvectors of a symmetric matrix +CV_EXPORTS_W bool eigen(InputArray src, OutputArray eigenvalues, + OutputArray eigenvectors = noArray()); //! computes covariation matrix of a set of samples CV_EXPORTS void calcCovarMatrix( const Mat* samples, int nsamples, Mat& covar, Mat& mean, - int flags, int ctype=CV_64F); + int flags, int ctype = CV_64F); //TODO: InputArrayOfArrays + //! computes covariation matrix of a set of samples CV_EXPORTS_W void calcCovarMatrix( InputArray samples, OutputArray covar, - OutputArray mean, int flags, int ctype=CV_64F); + OutputArray mean, int flags, int ctype = CV_64F); + +CV_EXPORTS_W void PCACompute(InputArray data, InputOutputArray mean, + OutputArray eigenvectors, int maxComponents = 0); + +CV_EXPORTS_W void PCACompute(InputArray data, InputOutputArray mean, + OutputArray eigenvectors, double retainedVariance); + +CV_EXPORTS_W void PCAProject(InputArray data, InputArray mean, + InputArray eigenvectors, OutputArray result); + +CV_EXPORTS_W void PCABackProject(InputArray data, InputArray mean, + InputArray eigenvectors, OutputArray result); + +//! computes SVD of src +CV_EXPORTS_W void SVDecomp( InputArray src, OutputArray w, OutputArray u, OutputArray vt, int flags = 0 ); + +//! performs back substitution for the previously computed SVD +CV_EXPORTS_W void SVBackSubst( InputArray w, InputArray u, InputArray vt, + InputArray rhs, OutputArray dst ); + +//! computes Mahalanobis distance between two vectors: sqrt((v1-v2)'*icovar*(v1-v2)), where icovar is the inverse covariation matrix +CV_EXPORTS_W double Mahalanobis(InputArray v1, InputArray v2, InputArray icovar); + +//! performs forward or inverse 1D or 2D Discrete Fourier Transformation +CV_EXPORTS_W void dft(InputArray src, OutputArray dst, int flags = 0, int nonzeroRows = 0); + +//! performs inverse 1D or 2D Discrete Fourier Transformation +CV_EXPORTS_W void idft(InputArray src, OutputArray dst, int flags = 0, int nonzeroRows = 0); + +//! performs forward or inverse 1D or 2D Discrete Cosine Transformation +CV_EXPORTS_W void dct(InputArray src, OutputArray dst, int flags = 0); + +//! performs inverse 1D or 2D Discrete Cosine Transformation +CV_EXPORTS_W void idct(InputArray src, OutputArray dst, int flags = 0); + +//! computes element-wise product of the two Fourier spectrums. The second spectrum can optionally be conjugated before the multiplication +CV_EXPORTS_W void mulSpectrums(InputArray a, InputArray b, OutputArray c, + int flags, bool conjB = false); + +//! computes the minimal vector size vecsize1 >= vecsize so that the dft() of the vector of length vecsize1 can be computed efficiently +CV_EXPORTS_W int getOptimalDFTSize(int vecsize); + +//! clusters the input data using k-Means algorithm +CV_EXPORTS_W double kmeans( InputArray data, int K, InputOutputArray bestLabels, + TermCriteria criteria, int attempts, + int flags, OutputArray centers = noArray() ); + +//! returns the thread-local Random number generator +CV_EXPORTS RNG& theRNG(); + +//! fills array with uniformly-distributed random numbers from the range [low, high) +CV_EXPORTS_W void randu(InputOutputArray dst, InputArray low, InputArray high); + +//! fills array with normally-distributed random numbers with the specified mean and the standard deviation +CV_EXPORTS_W void randn(InputOutputArray dst, InputArray mean, InputArray stddev); + +//! shuffles the input array elements +CV_EXPORTS_W void randShuffle(InputOutputArray dst, double iterFactor = 1., RNG* rng = 0); + +//! draws the line segment (pt1, pt2) in the image +CV_EXPORTS_W void line(CV_IN_OUT Mat& img, Point pt1, Point pt2, const Scalar& color, + int thickness = 1, int lineType = LINE_8, int shift = 0); + +//! draws the rectangle outline or a solid rectangle with the opposite corners pt1 and pt2 in the image +CV_EXPORTS_W void rectangle(CV_IN_OUT Mat& img, Point pt1, Point pt2, + const Scalar& color, int thickness = 1, + int lineType = LINE_8, int shift = 0); + +//! draws the rectangle outline or a solid rectangle covering rec in the image +CV_EXPORTS void rectangle(CV_IN_OUT Mat& img, Rect rec, + const Scalar& color, int thickness = 1, + int lineType = LINE_8, int shift = 0); + +//! draws the circle outline or a solid circle in the image +CV_EXPORTS_W void circle(CV_IN_OUT Mat& img, Point center, int radius, + const Scalar& color, int thickness = 1, + int lineType = LINE_8, int shift = 0); + +//! draws an elliptic arc, ellipse sector or a rotated ellipse in the image +CV_EXPORTS_W void ellipse(CV_IN_OUT Mat& img, Point center, Size axes, + double angle, double startAngle, double endAngle, + const Scalar& color, int thickness = 1, + int lineType = LINE_8, int shift = 0); + +//! draws a rotated ellipse in the image +CV_EXPORTS_W void ellipse(CV_IN_OUT Mat& img, const RotatedRect& box, const Scalar& color, + int thickness = 1, int lineType = LINE_8); + +//! draws a filled convex polygon in the image +CV_EXPORTS void fillConvexPoly(Mat& img, const Point* pts, int npts, + const Scalar& color, int lineType = LINE_8, + int shift = 0); + +CV_EXPORTS_W void fillConvexPoly(InputOutputArray img, InputArray points, + const Scalar& color, int lineType = LINE_8, + int shift = 0); + +//! fills an area bounded by one or more polygons +CV_EXPORTS void fillPoly(Mat& img, const Point** pts, + const int* npts, int ncontours, + const Scalar& color, int lineType = LINE_8, int shift = 0, + Point offset = Point() ); + +CV_EXPORTS_W void fillPoly(InputOutputArray img, InputArrayOfArrays pts, + const Scalar& color, int lineType = LINE_8, int shift = 0, + Point offset = Point() ); + +//! draws one or more polygonal curves +CV_EXPORTS void polylines(Mat& img, const Point* const* pts, const int* npts, + int ncontours, bool isClosed, const Scalar& color, + int thickness = 1, int lineType = LINE_8, int shift = 0 ); + +CV_EXPORTS_W void polylines(InputOutputArray img, InputArrayOfArrays pts, + bool isClosed, const Scalar& color, + int thickness = 1, int lineType = LINE_8, int shift = 0 ); + +//! draws contours in the image +CV_EXPORTS_W void drawContours( InputOutputArray image, InputArrayOfArrays contours, + int contourIdx, const Scalar& color, + int thickness = 1, int lineType = LINE_8, + InputArray hierarchy = noArray(), + int maxLevel = INT_MAX, Point offset = Point() ); + +//! clips the line segment by the rectangle Rect(0, 0, imgSize.width, imgSize.height) +CV_EXPORTS bool clipLine(Size imgSize, CV_IN_OUT Point& pt1, CV_IN_OUT Point& pt2); + +//! clips the line segment by the rectangle imgRect +CV_EXPORTS_W bool clipLine(Rect imgRect, CV_OUT CV_IN_OUT Point& pt1, CV_OUT CV_IN_OUT Point& pt2); + +//! converts elliptic arc to a polygonal curve +CV_EXPORTS_W void ellipse2Poly( Point center, Size axes, int angle, + int arcStart, int arcEnd, int delta, + CV_OUT std::vector& pts ); + +//! renders text string in the image +CV_EXPORTS_W void putText( Mat& img, const String& text, Point org, + int fontFace, double fontScale, Scalar color, + int thickness = 1, int lineType = LINE_8, + bool bottomLeftOrigin = false ); + +//! returns bounding box of the text string +CV_EXPORTS_W Size getTextSize(const String& text, int fontFace, + double fontScale, int thickness, + CV_OUT int* baseLine); /*! Principal Component Analysis @@ -2369,9 +610,9 @@ CV_EXPORTS_W void calcCovarMatrix( InputArray samples, OutputArray covar, PCA pca(pcaset, // pass the data Mat(), // we do not have a pre-computed mean vector, // so let the PCA engine to compute it - CV_PCA_DATA_AS_ROW, // indicate that the vectors + PCA::DATA_AS_ROW, // indicate that the vectors // are stored as matrix rows - // (use CV_PCA_DATA_AS_COL if the vectors are + // (use PCA::DATA_AS_COL if the vectors are // the matrix columns) maxComponents // specify, how many principal components to retain ); @@ -2401,39 +642,43 @@ CV_EXPORTS_W void calcCovarMatrix( InputArray samples, OutputArray covar, class CV_EXPORTS PCA { public: + enum { DATA_AS_ROW = 0, + DATA_AS_COL = 1, + USE_AVG = 2 + }; + //! default constructor PCA(); + //! the constructor that performs PCA - PCA(InputArray data, InputArray mean, int flags, int maxComponents=0); + PCA(InputArray data, InputArray mean, int flags, int maxComponents = 0); PCA(InputArray data, InputArray mean, int flags, double retainedVariance); + //! operator that performs PCA. The previously stored data, if any, is released - PCA& operator()(InputArray data, InputArray mean, int flags, int maxComponents=0); + PCA& operator()(InputArray data, InputArray mean, int flags, int maxComponents = 0); PCA& operator()(InputArray data, InputArray mean, int flags, double retainedVariance); + //! projects vector from the original space to the principal components subspace Mat project(InputArray vec) const; + //! projects vector from the original space to the principal components subspace void project(InputArray vec, OutputArray result) const; + //! reconstructs the original vector from the projection Mat backProject(InputArray vec) const; + //! reconstructs the original vector from the projection void backProject(InputArray vec, OutputArray result) const; + //! write and load PCA matrix + void write(FileStorage& fs ) const; + void read(const FileNode& fs); + Mat eigenvectors; //!< eigenvectors of the covariation matrix Mat eigenvalues; //!< eigenvalues of the covariation matrix Mat mean; //!< mean value subtracted before the projection and added after the back projection }; -CV_EXPORTS_W void PCACompute(InputArray data, InputOutputArray mean, - OutputArray eigenvectors, int maxComponents=0); - -CV_EXPORTS_W void PCACompute(InputArray data, InputOutputArray mean, - OutputArray eigenvectors, double retainedVariance); - -CV_EXPORTS_W void PCAProject(InputArray data, InputArray mean, - InputArray eigenvectors, OutputArray result); - -CV_EXPORTS_W void PCABackProject(InputArray data, InputArray mean, - InputArray eigenvectors, OutputArray result); /*! @@ -2452,163 +697,51 @@ CV_EXPORTS_W void PCABackProject(InputArray data, InputArray mean, class CV_EXPORTS SVD { public: - enum { MODIFY_A=1, NO_UV=2, FULL_UV=4 }; + enum { MODIFY_A = 1, + NO_UV = 2, + FULL_UV = 4 + }; + //! the default constructor SVD(); + //! the constructor that performs SVD - SVD( InputArray src, int flags=0 ); + SVD( InputArray src, int flags = 0 ); + //! the operator that performs SVD. The previously allocated SVD::u, SVD::w are SVD::vt are released. - SVD& operator ()( InputArray src, int flags=0 ); + SVD& operator ()( InputArray src, int flags = 0 ); //! decomposes matrix and stores the results to user-provided matrices static void compute( InputArray src, OutputArray w, - OutputArray u, OutputArray vt, int flags=0 ); + OutputArray u, OutputArray vt, int flags = 0 ); + //! computes singular values of a matrix - static void compute( InputArray src, OutputArray w, int flags=0 ); + static void compute( InputArray src, OutputArray w, int flags = 0 ); + //! performs back substitution static void backSubst( InputArray w, InputArray u, InputArray vt, InputArray rhs, OutputArray dst ); - template static void compute( const Matx<_Tp, m, n>& a, - Matx<_Tp, nm, 1>& w, Matx<_Tp, m, nm>& u, Matx<_Tp, n, nm>& vt ); - template static void compute( const Matx<_Tp, m, n>& a, - Matx<_Tp, nm, 1>& w ); - template static void backSubst( const Matx<_Tp, nm, 1>& w, - const Matx<_Tp, m, nm>& u, const Matx<_Tp, n, nm>& vt, const Matx<_Tp, m, nb>& rhs, Matx<_Tp, n, nb>& dst ); - //! finds dst = arg min_{|dst|=1} |m*dst| static void solveZ( InputArray src, OutputArray dst ); + //! performs back substitution, so that dst is the solution or pseudo-solution of m*dst = rhs, where m is the decomposed matrix void backSubst( InputArray rhs, OutputArray dst ) const; + template static + void compute( const Matx<_Tp, m, n>& a, Matx<_Tp, nm, 1>& w, Matx<_Tp, m, nm>& u, Matx<_Tp, n, nm>& vt ); + + template static + void compute( const Matx<_Tp, m, n>& a, Matx<_Tp, nm, 1>& w ); + + template static + void backSubst( const Matx<_Tp, nm, 1>& w, const Matx<_Tp, m, nm>& u, const Matx<_Tp, n, nm>& vt, const Matx<_Tp, m, nb>& rhs, Matx<_Tp, n, nb>& dst ); + Mat u, w, vt; }; -//! computes SVD of src -CV_EXPORTS_W void SVDecomp( InputArray src, OutputArray w, OutputArray u, OutputArray vt, int flags=0 ); -//! performs back substitution for the previously computed SVD -CV_EXPORTS_W void SVBackSubst( InputArray w, InputArray u, InputArray vt, - InputArray rhs, OutputArray dst ); - -//! computes Mahalanobis distance between two vectors: sqrt((v1-v2)'*icovar*(v1-v2)), where icovar is the inverse covariation matrix -CV_EXPORTS_W double Mahalanobis(InputArray v1, InputArray v2, InputArray icovar); -//! a synonym for Mahalanobis -CV_EXPORTS double Mahalonobis(InputArray v1, InputArray v2, InputArray icovar); - -//! performs forward or inverse 1D or 2D Discrete Fourier Transformation -CV_EXPORTS_W void dft(InputArray src, OutputArray dst, int flags=0, int nonzeroRows=0); -//! performs inverse 1D or 2D Discrete Fourier Transformation -CV_EXPORTS_W void idft(InputArray src, OutputArray dst, int flags=0, int nonzeroRows=0); -//! performs forward or inverse 1D or 2D Discrete Cosine Transformation -CV_EXPORTS_W void dct(InputArray src, OutputArray dst, int flags=0); -//! performs inverse 1D or 2D Discrete Cosine Transformation -CV_EXPORTS_W void idct(InputArray src, OutputArray dst, int flags=0); -//! computes element-wise product of the two Fourier spectrums. The second spectrum can optionally be conjugated before the multiplication -CV_EXPORTS_W void mulSpectrums(InputArray a, InputArray b, OutputArray c, - int flags, bool conjB=false); -//! computes the minimal vector size vecsize1 >= vecsize so that the dft() of the vector of length vecsize1 can be computed efficiently -CV_EXPORTS_W int getOptimalDFTSize(int vecsize); - -/*! - Various k-Means flags -*/ -enum -{ - KMEANS_RANDOM_CENTERS=0, // Chooses random centers for k-Means initialization - KMEANS_PP_CENTERS=2, // Uses k-Means++ algorithm for initialization - KMEANS_USE_INITIAL_LABELS=1 // Uses the user-provided labels for K-Means initialization -}; -//! clusters the input data using k-Means algorithm -CV_EXPORTS_W double kmeans( InputArray data, int K, InputOutputArray bestLabels, - TermCriteria criteria, int attempts, - int flags, OutputArray centers=noArray() ); - -//! returns the thread-local Random number generator -CV_EXPORTS RNG& theRNG(); - -//! returns the next unifomly-distributed random number of the specified type -template static inline _Tp randu() { return (_Tp)theRNG(); } - -//! fills array with uniformly-distributed random numbers from the range [low, high) -CV_EXPORTS_W void randu(InputOutputArray dst, InputArray low, InputArray high); - -//! fills array with normally-distributed random numbers with the specified mean and the standard deviation -CV_EXPORTS_W void randn(InputOutputArray dst, InputArray mean, InputArray stddev); - -//! shuffles the input array elements -CV_EXPORTS void randShuffle(InputOutputArray dst, double iterFactor=1., RNG* rng=0); -CV_EXPORTS_AS(randShuffle) void randShuffle_(InputOutputArray dst, double iterFactor=1.); - -//! draws the line segment (pt1, pt2) in the image -CV_EXPORTS_W void line(CV_IN_OUT Mat& img, Point pt1, Point pt2, const Scalar& color, - int thickness=1, int lineType=8, int shift=0); - -//! draws the rectangle outline or a solid rectangle with the opposite corners pt1 and pt2 in the image -CV_EXPORTS_W void rectangle(CV_IN_OUT Mat& img, Point pt1, Point pt2, - const Scalar& color, int thickness=1, - int lineType=8, int shift=0); - -//! draws the rectangle outline or a solid rectangle covering rec in the image -CV_EXPORTS void rectangle(CV_IN_OUT Mat& img, Rect rec, - const Scalar& color, int thickness=1, - int lineType=8, int shift=0); - -//! draws the circle outline or a solid circle in the image -CV_EXPORTS_W void circle(CV_IN_OUT Mat& img, Point center, int radius, - const Scalar& color, int thickness=1, - int lineType=8, int shift=0); - -//! draws an elliptic arc, ellipse sector or a rotated ellipse in the image -CV_EXPORTS_W void ellipse(CV_IN_OUT Mat& img, Point center, Size axes, - double angle, double startAngle, double endAngle, - const Scalar& color, int thickness=1, - int lineType=8, int shift=0); - -//! draws a rotated ellipse in the image -CV_EXPORTS_W void ellipse(CV_IN_OUT Mat& img, const RotatedRect& box, const Scalar& color, - int thickness=1, int lineType=8); - -//! draws a filled convex polygon in the image -CV_EXPORTS void fillConvexPoly(Mat& img, const Point* pts, int npts, - const Scalar& color, int lineType=8, - int shift=0); -CV_EXPORTS_W void fillConvexPoly(InputOutputArray img, InputArray points, - const Scalar& color, int lineType=8, - int shift=0); - -//! fills an area bounded by one or more polygons -CV_EXPORTS void fillPoly(Mat& img, const Point** pts, - const int* npts, int ncontours, - const Scalar& color, int lineType=8, int shift=0, - Point offset=Point() ); - -CV_EXPORTS_W void fillPoly(InputOutputArray img, InputArrayOfArrays pts, - const Scalar& color, int lineType=8, int shift=0, - Point offset=Point() ); - -//! draws one or more polygonal curves -CV_EXPORTS void polylines(Mat& img, const Point* const* pts, const int* npts, - int ncontours, bool isClosed, const Scalar& color, - int thickness=1, int lineType=8, int shift=0 ); - -CV_EXPORTS_W void polylines(InputOutputArray img, InputArrayOfArrays pts, - bool isClosed, const Scalar& color, - int thickness=1, int lineType=8, int shift=0 ); - -//! draws contours in the image -CV_EXPORTS_W void drawContours( InputOutputArray image, InputArrayOfArrays contours, - int contourIdx, const Scalar& color, - int thickness=1, int lineType=8, - InputArray hierarchy=noArray(), - int maxLevel=INT_MAX, Point offset=Point() ); - -//! clips the line segment by the rectangle Rect(0, 0, imgSize.width, imgSize.height) -CV_EXPORTS bool clipLine(Size imgSize, CV_IN_OUT Point& pt1, CV_IN_OUT Point& pt2); - -//! clips the line segment by the rectangle imgRect -CV_EXPORTS_W bool clipLine(Rect imgRect, CV_OUT CV_IN_OUT Point& pt1, CV_OUT CV_IN_OUT Point& pt2); /*! Line iterator class @@ -2621,7 +754,7 @@ class CV_EXPORTS LineIterator public: //! intializes the iterator LineIterator( const Mat& img, Point pt1, Point pt2, - int connectivity=8, bool leftToRight=false ); + int connectivity = 8, bool leftToRight = false ); //! returns pointer to the current pixel uchar* operator *(); //! prefix increment operator (++it). shifts iterator to the next pixel @@ -2639,1191 +772,7 @@ public: int minusStep, plusStep; }; -//! converts elliptic arc to a polygonal curve -CV_EXPORTS_W void ellipse2Poly( Point center, Size axes, int angle, - int arcStart, int arcEnd, int delta, - CV_OUT std::vector& pts ); -enum -{ - FONT_HERSHEY_SIMPLEX = 0, - FONT_HERSHEY_PLAIN = 1, - FONT_HERSHEY_DUPLEX = 2, - FONT_HERSHEY_COMPLEX = 3, - FONT_HERSHEY_TRIPLEX = 4, - FONT_HERSHEY_COMPLEX_SMALL = 5, - FONT_HERSHEY_SCRIPT_SIMPLEX = 6, - FONT_HERSHEY_SCRIPT_COMPLEX = 7, - FONT_ITALIC = 16 -}; - -//! renders text string in the image -CV_EXPORTS_W void putText( Mat& img, const std::string& text, Point org, - int fontFace, double fontScale, Scalar color, - int thickness=1, int lineType=8, - bool bottomLeftOrigin=false ); - -//! returns bounding box of the text string -CV_EXPORTS_W Size getTextSize(const std::string& text, int fontFace, - double fontScale, int thickness, - CV_OUT int* baseLine); - -///////////////////////////////// Mat_<_Tp> //////////////////////////////////// - -/*! - Template matrix class derived from Mat - - The class Mat_ is a "thin" template wrapper on top of cv::Mat. It does not have any extra data fields, - nor it or cv::Mat have any virtual methods and thus references or pointers to these two classes - can be safely converted one to another. But do it with care, for example: - - \code - // create 100x100 8-bit matrix - Mat M(100,100,CV_8U); - // this will compile fine. no any data conversion will be done. - Mat_& M1 = (Mat_&)M; - // the program will likely crash at the statement below - M1(99,99) = 1.f; - \endcode - - While cv::Mat is sufficient in most cases, cv::Mat_ can be more convenient if you use a lot of element - access operations and if you know matrix type at compile time. - Note that cv::Mat::at<_Tp>(int y, int x) and cv::Mat_<_Tp>::operator ()(int y, int x) do absolutely the - same thing and run at the same speed, but the latter is certainly shorter: - - \code - Mat_ M(20,20); - for(int i = 0; i < M.rows; i++) - for(int j = 0; j < M.cols; j++) - M(i,j) = 1./(i+j+1); - Mat E, V; - eigen(M,E,V); - cout << E.at(0,0)/E.at(M.rows-1,0); - \endcode - - It is easy to use Mat_ for multi-channel images/matrices - just pass cv::Vec as cv::Mat_ template parameter: - - \code - // allocate 320x240 color image and fill it with green (in RGB space) - Mat_ img(240, 320, Vec3b(0,255,0)); - // now draw a diagonal white line - for(int i = 0; i < 100; i++) - img(i,i)=Vec3b(255,255,255); - // and now modify the 2nd (red) channel of each pixel - for(int i = 0; i < img.rows; i++) - for(int j = 0; j < img.cols; j++) - img(i,j)[2] ^= (uchar)(i ^ j); // img(y,x)[c] accesses c-th channel of the pixel (x,y) - \endcode -*/ -template class CV_EXPORTS Mat_ : public Mat -{ -public: - typedef _Tp value_type; - typedef typename DataType<_Tp>::channel_type channel_type; - typedef MatIterator_<_Tp> iterator; - typedef MatConstIterator_<_Tp> const_iterator; - - //! default constructor - Mat_(); - //! equivalent to Mat(_rows, _cols, DataType<_Tp>::type) - Mat_(int _rows, int _cols); - //! constructor that sets each matrix element to specified value - Mat_(int _rows, int _cols, const _Tp& value); - //! equivalent to Mat(_size, DataType<_Tp>::type) - explicit Mat_(Size _size); - //! constructor that sets each matrix element to specified value - Mat_(Size _size, const _Tp& value); - //! n-dim array constructor - Mat_(int _ndims, const int* _sizes); - //! n-dim array constructor that sets each matrix element to specified value - Mat_(int _ndims, const int* _sizes, const _Tp& value); - //! copy/conversion contructor. If m is of different type, it's converted - Mat_(const Mat& m); - //! copy constructor - Mat_(const Mat_& m); - //! constructs a matrix on top of user-allocated data. step is in bytes(!!!), regardless of the type - Mat_(int _rows, int _cols, _Tp* _data, size_t _step=AUTO_STEP); - //! constructs n-dim matrix on top of user-allocated data. steps are in bytes(!!!), regardless of the type - Mat_(int _ndims, const int* _sizes, _Tp* _data, const size_t* _steps=0); - //! selects a submatrix - Mat_(const Mat_& m, const Range& rowRange, const Range& colRange=Range::all()); - //! selects a submatrix - Mat_(const Mat_& m, const Rect& roi); - //! selects a submatrix, n-dim version - Mat_(const Mat_& m, const Range* ranges); - //! from a matrix expression - explicit Mat_(const MatExpr& e); - //! makes a matrix out of Vec, std::vector, Point_ or Point3_. The matrix will have a single column - explicit Mat_(const std::vector<_Tp>& vec, bool copyData=false); - template explicit Mat_(const Vec::channel_type, n>& vec, bool copyData=true); - template explicit Mat_(const Matx::channel_type, m, n>& mtx, bool copyData=true); - explicit Mat_(const Point_::channel_type>& pt, bool copyData=true); - explicit Mat_(const Point3_::channel_type>& pt, bool copyData=true); - explicit Mat_(const MatCommaInitializer_<_Tp>& commaInitializer); - - Mat_& operator = (const Mat& m); - Mat_& operator = (const Mat_& m); - //! set all the elements to s. - Mat_& operator = (const _Tp& s); - //! assign a matrix expression - Mat_& operator = (const MatExpr& e); - - //! iterators; they are smart enough to skip gaps in the end of rows - iterator begin(); - iterator end(); - const_iterator begin() const; - const_iterator end() const; - - //! equivalent to Mat::create(_rows, _cols, DataType<_Tp>::type) - void create(int _rows, int _cols); - //! equivalent to Mat::create(_size, DataType<_Tp>::type) - void create(Size _size); - //! equivalent to Mat::create(_ndims, _sizes, DatType<_Tp>::type) - void create(int _ndims, const int* _sizes); - //! cross-product - Mat_ cross(const Mat_& m) const; - //! data type conversion - template operator Mat_() const; - //! overridden forms of Mat::row() etc. - Mat_ row(int y) const; - Mat_ col(int x) const; - Mat_ diag(int d=0) const; - Mat_ clone() const; - - //! overridden forms of Mat::elemSize() etc. - size_t elemSize() const; - size_t elemSize1() const; - int type() const; - int depth() const; - int channels() const; - size_t step1(int i=0) const; - //! returns step()/sizeof(_Tp) - size_t stepT(int i=0) const; - - //! overridden forms of Mat::zeros() etc. Data type is omitted, of course - static MatExpr zeros(int rows, int cols); - static MatExpr zeros(Size size); - static MatExpr zeros(int _ndims, const int* _sizes); - static MatExpr ones(int rows, int cols); - static MatExpr ones(Size size); - static MatExpr ones(int _ndims, const int* _sizes); - static MatExpr eye(int rows, int cols); - static MatExpr eye(Size size); - - //! some more overriden methods - Mat_& adjustROI( int dtop, int dbottom, int dleft, int dright ); - Mat_ operator()( const Range& rowRange, const Range& colRange ) const; - Mat_ operator()( const Rect& roi ) const; - Mat_ operator()( const Range* ranges ) const; - - //! more convenient forms of row and element access operators - _Tp* operator [](int y); - const _Tp* operator [](int y) const; - - //! returns reference to the specified element - _Tp& operator ()(const int* idx); - //! returns read-only reference to the specified element - const _Tp& operator ()(const int* idx) const; - - //! returns reference to the specified element - template _Tp& operator ()(const Vec& idx); - //! returns read-only reference to the specified element - template const _Tp& operator ()(const Vec& idx) const; - - //! returns reference to the specified element (1D case) - _Tp& operator ()(int idx0); - //! returns read-only reference to the specified element (1D case) - const _Tp& operator ()(int idx0) const; - //! returns reference to the specified element (2D case) - _Tp& operator ()(int idx0, int idx1); - //! returns read-only reference to the specified element (2D case) - const _Tp& operator ()(int idx0, int idx1) const; - //! returns reference to the specified element (3D case) - _Tp& operator ()(int idx0, int idx1, int idx2); - //! returns read-only reference to the specified element (3D case) - const _Tp& operator ()(int idx0, int idx1, int idx2) const; - - _Tp& operator ()(Point pt); - const _Tp& operator ()(Point pt) const; - - //! conversion to vector. - operator std::vector<_Tp>() const; - //! conversion to Vec - template operator Vec::channel_type, n>() const; - //! conversion to Matx - template operator Matx::channel_type, m, n>() const; -}; - -typedef Mat_ Mat1b; -typedef Mat_ Mat2b; -typedef Mat_ Mat3b; -typedef Mat_ Mat4b; - -typedef Mat_ Mat1s; -typedef Mat_ Mat2s; -typedef Mat_ Mat3s; -typedef Mat_ Mat4s; - -typedef Mat_ Mat1w; -typedef Mat_ Mat2w; -typedef Mat_ Mat3w; -typedef Mat_ Mat4w; - -typedef Mat_ Mat1i; -typedef Mat_ Mat2i; -typedef Mat_ Mat3i; -typedef Mat_ Mat4i; - -typedef Mat_ Mat1f; -typedef Mat_ Mat2f; -typedef Mat_ Mat3f; -typedef Mat_ Mat4f; - -typedef Mat_ Mat1d; -typedef Mat_ Mat2d; -typedef Mat_ Mat3d; -typedef Mat_ Mat4d; - -//////////// Iterators & Comma initializers ////////////////// - -class CV_EXPORTS MatConstIterator -{ -public: - typedef uchar* value_type; - typedef ptrdiff_t difference_type; - typedef const uchar** pointer; - typedef uchar* reference; - typedef std::random_access_iterator_tag iterator_category; - - //! default constructor - MatConstIterator(); - //! constructor that sets the iterator to the beginning of the matrix - MatConstIterator(const Mat* _m); - //! constructor that sets the iterator to the specified element of the matrix - MatConstIterator(const Mat* _m, int _row, int _col=0); - //! constructor that sets the iterator to the specified element of the matrix - MatConstIterator(const Mat* _m, Point _pt); - //! constructor that sets the iterator to the specified element of the matrix - MatConstIterator(const Mat* _m, const int* _idx); - //! copy constructor - MatConstIterator(const MatConstIterator& it); - - //! copy operator - MatConstIterator& operator = (const MatConstIterator& it); - //! returns the current matrix element - uchar* operator *() const; - //! returns the i-th matrix element, relative to the current - uchar* operator [](ptrdiff_t i) const; - - //! shifts the iterator forward by the specified number of elements - MatConstIterator& operator += (ptrdiff_t ofs); - //! shifts the iterator backward by the specified number of elements - MatConstIterator& operator -= (ptrdiff_t ofs); - //! decrements the iterator - MatConstIterator& operator --(); - //! decrements the iterator - MatConstIterator operator --(int); - //! increments the iterator - MatConstIterator& operator ++(); - //! increments the iterator - MatConstIterator operator ++(int); - //! returns the current iterator position - Point pos() const; - //! returns the current iterator position - void pos(int* _idx) const; - ptrdiff_t lpos() const; - void seek(ptrdiff_t ofs, bool relative=false); - void seek(const int* _idx, bool relative=false); - - const Mat* m; - size_t elemSize; - uchar* ptr; - uchar* sliceStart; - uchar* sliceEnd; -}; - -/*! - Matrix read-only iterator - - */ -template -class CV_EXPORTS MatConstIterator_ : public MatConstIterator -{ -public: - typedef _Tp value_type; - typedef ptrdiff_t difference_type; - typedef const _Tp* pointer; - typedef const _Tp& reference; - typedef std::random_access_iterator_tag iterator_category; - - //! default constructor - MatConstIterator_(); - //! constructor that sets the iterator to the beginning of the matrix - MatConstIterator_(const Mat_<_Tp>* _m); - //! constructor that sets the iterator to the specified element of the matrix - MatConstIterator_(const Mat_<_Tp>* _m, int _row, int _col=0); - //! constructor that sets the iterator to the specified element of the matrix - MatConstIterator_(const Mat_<_Tp>* _m, Point _pt); - //! constructor that sets the iterator to the specified element of the matrix - MatConstIterator_(const Mat_<_Tp>* _m, const int* _idx); - //! copy constructor - MatConstIterator_(const MatConstIterator_& it); - - //! copy operator - MatConstIterator_& operator = (const MatConstIterator_& it); - //! returns the current matrix element - _Tp operator *() const; - //! returns the i-th matrix element, relative to the current - _Tp operator [](ptrdiff_t i) const; - - //! shifts the iterator forward by the specified number of elements - MatConstIterator_& operator += (ptrdiff_t ofs); - //! shifts the iterator backward by the specified number of elements - MatConstIterator_& operator -= (ptrdiff_t ofs); - //! decrements the iterator - MatConstIterator_& operator --(); - //! decrements the iterator - MatConstIterator_ operator --(int); - //! increments the iterator - MatConstIterator_& operator ++(); - //! increments the iterator - MatConstIterator_ operator ++(int); - //! returns the current iterator position - Point pos() const; -}; - - -/*! - Matrix read-write iterator - -*/ -template -class CV_EXPORTS MatIterator_ : public MatConstIterator_<_Tp> -{ -public: - typedef _Tp* pointer; - typedef _Tp& reference; - typedef std::random_access_iterator_tag iterator_category; - - //! the default constructor - MatIterator_(); - //! constructor that sets the iterator to the beginning of the matrix - MatIterator_(Mat_<_Tp>* _m); - //! constructor that sets the iterator to the specified element of the matrix - MatIterator_(Mat_<_Tp>* _m, int _row, int _col=0); - //! constructor that sets the iterator to the specified element of the matrix - MatIterator_(const Mat_<_Tp>* _m, Point _pt); - //! constructor that sets the iterator to the specified element of the matrix - MatIterator_(const Mat_<_Tp>* _m, const int* _idx); - //! copy constructor - MatIterator_(const MatIterator_& it); - //! copy operator - MatIterator_& operator = (const MatIterator_<_Tp>& it ); - - //! returns the current matrix element - _Tp& operator *() const; - //! returns the i-th matrix element, relative to the current - _Tp& operator [](ptrdiff_t i) const; - - //! shifts the iterator forward by the specified number of elements - MatIterator_& operator += (ptrdiff_t ofs); - //! shifts the iterator backward by the specified number of elements - MatIterator_& operator -= (ptrdiff_t ofs); - //! decrements the iterator - MatIterator_& operator --(); - //! decrements the iterator - MatIterator_ operator --(int); - //! increments the iterator - MatIterator_& operator ++(); - //! increments the iterator - MatIterator_ operator ++(int); -}; - -template class CV_EXPORTS MatOp_Iter_; - -/*! - Comma-separated Matrix Initializer - - The class instances are usually not created explicitly. - Instead, they are created on "matrix << firstValue" operator. - - The sample below initializes 2x2 rotation matrix: - - \code - double angle = 30, a = cos(angle*CV_PI/180), b = sin(angle*CV_PI/180); - Mat R = (Mat_(2,2) << a, -b, b, a); - \endcode -*/ -template class CV_EXPORTS MatCommaInitializer_ -{ -public: - //! the constructor, created by "matrix << firstValue" operator, where matrix is cv::Mat - MatCommaInitializer_(Mat_<_Tp>* _m); - //! the operator that takes the next value and put it to the matrix - template MatCommaInitializer_<_Tp>& operator , (T2 v); - //! another form of conversion operator - Mat_<_Tp> operator *() const; - operator Mat_<_Tp>() const; -protected: - MatIterator_<_Tp> it; -}; - - -template class CV_EXPORTS MatxCommaInitializer -{ -public: - MatxCommaInitializer(Matx<_Tp, m, n>* _mtx); - template MatxCommaInitializer<_Tp, m, n>& operator , (T2 val); - Matx<_Tp, m, n> operator *() const; - - Matx<_Tp, m, n>* dst; - int idx; -}; - -template class CV_EXPORTS VecCommaInitializer : public MatxCommaInitializer<_Tp, m, 1> -{ -public: - VecCommaInitializer(Vec<_Tp, m>* _vec); - template VecCommaInitializer<_Tp, m>& operator , (T2 val); - Vec<_Tp, m> operator *() const; -}; - -/*! - Automatically Allocated Buffer Class - - The class is used for temporary buffers in functions and methods. - If a temporary buffer is usually small (a few K's of memory), - but its size depends on the parameters, it makes sense to create a small - fixed-size array on stack and use it if it's large enough. If the required buffer size - is larger than the fixed size, another buffer of sufficient size is allocated dynamically - and released after the processing. Therefore, in typical cases, when the buffer size is small, - there is no overhead associated with malloc()/free(). - At the same time, there is no limit on the size of processed data. - - This is what AutoBuffer does. The template takes 2 parameters - type of the buffer elements and - the number of stack-allocated elements. Here is how the class is used: - - \code - void my_func(const cv::Mat& m) - { - cv::AutoBuffer buf; // create automatic buffer containing 1000 floats - - buf.allocate(m.rows); // if m.rows <= 1000, the pre-allocated buffer is used, - // otherwise the buffer of "m.rows" floats will be allocated - // dynamically and deallocated in cv::AutoBuffer destructor - ... - } - \endcode -*/ -template class CV_EXPORTS AutoBuffer -{ -public: - typedef _Tp value_type; - - //! the default contructor - AutoBuffer(); - //! constructor taking the real buffer size - AutoBuffer(size_t _size); - - //! the copy constructor - AutoBuffer(const AutoBuffer<_Tp, fixed_size>& buf); - //! the assignment operator - AutoBuffer<_Tp, fixed_size>& operator = (const AutoBuffer<_Tp, fixed_size>& buf); - - //! destructor. calls deallocate() - ~AutoBuffer(); - - //! allocates the new buffer of size _size. if the _size is small enough, stack-allocated buffer is used - void allocate(size_t _size); - //! deallocates the buffer if it was dynamically allocated - void deallocate(); - //! resizes the buffer and preserves the content - void resize(size_t _size); - //! returns the current buffer size - size_t size() const; - //! returns pointer to the real buffer, stack-allocated or head-allocated - operator _Tp* (); - //! returns read-only pointer to the real buffer, stack-allocated or head-allocated - operator const _Tp* () const; - -protected: - //! pointer to the real buffer, can point to buf if the buffer is small enough - _Tp* ptr; - //! size of the real buffer - size_t sz; - //! pre-allocated buffer - _Tp buf[fixed_size]; -}; - -/////////////////////////// multi-dimensional dense matrix ////////////////////////// - -/*! - n-Dimensional Dense Matrix Iterator Class. - - The class cv::NAryMatIterator is used for iterating over one or more n-dimensional dense arrays (cv::Mat's). - - The iterator is completely different from cv::Mat_ and cv::SparseMat_ iterators. - It iterates through the slices (or planes), not the elements, where "slice" is a continuous part of the arrays. - - Here is the example on how the iterator can be used to normalize 3D histogram: - - \code - void normalizeColorHist(Mat& hist) - { - #if 1 - // intialize iterator (the style is different from STL). - // after initialization the iterator will contain - // the number of slices or planes - // the iterator will go through - Mat* arrays[] = { &hist, 0 }; - Mat planes[1]; - NAryMatIterator it(arrays, planes); - double s = 0; - // iterate through the matrix. on each iteration - // it.planes[i] (of type Mat) will be set to the current plane of - // i-th n-dim matrix passed to the iterator constructor. - for(int p = 0; p < it.nplanes; p++, ++it) - s += sum(it.planes[0])[0]; - it = NAryMatIterator(hist); - s = 1./s; - for(int p = 0; p < it.nplanes; p++, ++it) - it.planes[0] *= s; - #elif 1 - // this is a shorter implementation of the above - // using built-in operations on Mat - double s = sum(hist)[0]; - hist.convertTo(hist, hist.type(), 1./s, 0); - #else - // and this is even shorter one - // (assuming that the histogram elements are non-negative) - normalize(hist, hist, 1, 0, NORM_L1); - #endif - } - \endcode - - You can iterate through several matrices simultaneously as long as they have the same geometry - (dimensionality and all the dimension sizes are the same), which is useful for binary - and n-ary operations on such matrices. Just pass those matrices to cv::MatNDIterator. - Then, during the iteration it.planes[0], it.planes[1], ... will - be the slices of the corresponding matrices -*/ -class CV_EXPORTS NAryMatIterator -{ -public: - //! the default constructor - NAryMatIterator(); - //! the full constructor taking arbitrary number of n-dim matrices - NAryMatIterator(const Mat** arrays, uchar** ptrs, int narrays=-1); - //! the full constructor taking arbitrary number of n-dim matrices - NAryMatIterator(const Mat** arrays, Mat* planes, int narrays=-1); - //! the separate iterator initialization method - void init(const Mat** arrays, Mat* planes, uchar** ptrs, int narrays=-1); - - //! proceeds to the next plane of every iterated matrix - NAryMatIterator& operator ++(); - //! proceeds to the next plane of every iterated matrix (postfix increment operator) - NAryMatIterator operator ++(int); - - //! the iterated arrays - const Mat** arrays; - //! the current planes - Mat* planes; - //! data pointers - uchar** ptrs; - //! the number of arrays - int narrays; - //! the number of hyper-planes that the iterator steps through - size_t nplanes; - //! the size of each segment (in elements) - size_t size; -protected: - int iterdepth; - size_t idx; -}; - -//typedef NAryMatIterator NAryMatNDIterator; - -typedef void (*ConvertData)(const void* from, void* to, int cn); -typedef void (*ConvertScaleData)(const void* from, void* to, int cn, double alpha, double beta); - -//! returns the function for converting pixels from one data type to another -CV_EXPORTS ConvertData getConvertElem(int fromType, int toType); -//! returns the function for converting pixels from one data type to another with the optional scaling -CV_EXPORTS ConvertScaleData getConvertScaleElem(int fromType, int toType); - - -/////////////////////////// multi-dimensional sparse matrix ////////////////////////// - -class SparseMatIterator; -class SparseMatConstIterator; -template class SparseMatIterator_; -template class SparseMatConstIterator_; - -/*! - Sparse matrix class. - - The class represents multi-dimensional sparse numerical arrays. Such a sparse array can store elements - of any type that cv::Mat is able to store. "Sparse" means that only non-zero elements - are stored (though, as a result of some operations on a sparse matrix, some of its stored elements - can actually become 0. It's user responsibility to detect such elements and delete them using cv::SparseMat::erase(). - The non-zero elements are stored in a hash table that grows when it's filled enough, - so that the search time remains O(1) in average. Elements can be accessed using the following methods: - -
      -
    1. Query operations: cv::SparseMat::ptr() and the higher-level cv::SparseMat::ref(), - cv::SparseMat::value() and cv::SparseMat::find, for example: - \code - const int dims = 5; - int size[] = {10, 10, 10, 10, 10}; - SparseMat sparse_mat(dims, size, CV_32F); - for(int i = 0; i < 1000; i++) - { - int idx[dims]; - for(int k = 0; k < dims; k++) - idx[k] = rand()%sparse_mat.size(k); - sparse_mat.ref(idx) += 1.f; - } - \endcode - -
    2. Sparse matrix iterators. Like cv::Mat iterators and unlike cv::Mat iterators, the sparse matrix iterators are STL-style, - that is, the iteration is done as following: - \code - // prints elements of a sparse floating-point matrix and the sum of elements. - SparseMatConstIterator_ - it = sparse_mat.begin(), - it_end = sparse_mat.end(); - double s = 0; - int dims = sparse_mat.dims(); - for(; it != it_end; ++it) - { - // print element indices and the element value - const Node* n = it.node(); - printf("(") - for(int i = 0; i < dims; i++) - printf("%3d%c", n->idx[i], i < dims-1 ? ',' : ')'); - printf(": %f\n", *it); - s += *it; - } - printf("Element sum is %g\n", s); - \endcode - If you run this loop, you will notice that elements are enumerated - in no any logical order (lexicographical etc.), - they come in the same order as they stored in the hash table, i.e. semi-randomly. - - You may collect pointers to the nodes and sort them to get the proper ordering. - Note, however, that pointers to the nodes may become invalid when you add more - elements to the matrix; this is because of possible buffer reallocation. - -
    3. A combination of the above 2 methods when you need to process 2 or more sparse - matrices simultaneously, e.g. this is how you can compute unnormalized - cross-correlation of the 2 floating-point sparse matrices: - \code - double crossCorr(const SparseMat& a, const SparseMat& b) - { - const SparseMat *_a = &a, *_b = &b; - // if b contains less elements than a, - // it's faster to iterate through b - if(_a->nzcount() > _b->nzcount()) - std::swap(_a, _b); - SparseMatConstIterator_ it = _a->begin(), - it_end = _a->end(); - double ccorr = 0; - for(; it != it_end; ++it) - { - // take the next element from the first matrix - float avalue = *it; - const Node* anode = it.node(); - // and try to find element with the same index in the second matrix. - // since the hash value depends only on the element index, - // we reuse hashvalue stored in the node - float bvalue = _b->value(anode->idx,&anode->hashval); - ccorr += avalue*bvalue; - } - return ccorr; - } - \endcode -
    -*/ -class CV_EXPORTS SparseMat -{ -public: - typedef SparseMatIterator iterator; - typedef SparseMatConstIterator const_iterator; - - //! the sparse matrix header - struct CV_EXPORTS Hdr - { - Hdr(int _dims, const int* _sizes, int _type); - void clear(); - int refcount; - int dims; - int valueOffset; - size_t nodeSize; - size_t nodeCount; - size_t freeList; - std::vector pool; - std::vector hashtab; - int size[CV_MAX_DIM]; - }; - - //! sparse matrix node - element of a hash table - struct CV_EXPORTS Node - { - //! hash value - size_t hashval; - //! index of the next node in the same hash table entry - size_t next; - //! index of the matrix element - int idx[CV_MAX_DIM]; - }; - - //! default constructor - SparseMat(); - //! creates matrix of the specified size and type - SparseMat(int dims, const int* _sizes, int _type); - //! copy constructor - SparseMat(const SparseMat& m); - //! converts dense 2d matrix to the sparse form - /*! - \param m the input matrix - \param try1d if true and m is a single-column matrix (Nx1), - then the sparse matrix will be 1-dimensional. - */ - explicit SparseMat(const Mat& m); - //! converts old-style sparse matrix to the new-style. All the data is copied - SparseMat(const CvSparseMat* m); - //! the destructor - ~SparseMat(); - - //! assignment operator. This is O(1) operation, i.e. no data is copied - SparseMat& operator = (const SparseMat& m); - //! equivalent to the corresponding constructor - SparseMat& operator = (const Mat& m); - - //! creates full copy of the matrix - SparseMat clone() const; - - //! copies all the data to the destination matrix. All the previous content of m is erased - void copyTo( SparseMat& m ) const; - //! converts sparse matrix to dense matrix. - void copyTo( Mat& m ) const; - //! multiplies all the matrix elements by the specified scale factor alpha and converts the results to the specified data type - void convertTo( SparseMat& m, int rtype, double alpha=1 ) const; - //! converts sparse matrix to dense n-dim matrix with optional type conversion and scaling. - /*! - \param rtype The output matrix data type. When it is =-1, the output array will have the same data type as (*this) - \param alpha The scale factor - \param beta The optional delta added to the scaled values before the conversion - */ - void convertTo( Mat& m, int rtype, double alpha=1, double beta=0 ) const; - - // not used now - void assignTo( SparseMat& m, int type=-1 ) const; - - //! reallocates sparse matrix. - /*! - If the matrix already had the proper size and type, - it is simply cleared with clear(), otherwise, - the old matrix is released (using release()) and the new one is allocated. - */ - void create(int dims, const int* _sizes, int _type); - //! sets all the sparse matrix elements to 0, which means clearing the hash table. - void clear(); - //! manually increments the reference counter to the header. - void addref(); - // decrements the header reference counter. When the counter reaches 0, the header and all the underlying data are deallocated. - void release(); - - //! converts sparse matrix to the old-style representation; all the elements are copied. - operator CvSparseMat*() const; - //! returns the size of each element in bytes (not including the overhead - the space occupied by SparseMat::Node elements) - size_t elemSize() const; - //! returns elemSize()/channels() - size_t elemSize1() const; - - //! returns type of sparse matrix elements - int type() const; - //! returns the depth of sparse matrix elements - int depth() const; - //! returns the number of channels - int channels() const; - - //! returns the array of sizes, or NULL if the matrix is not allocated - const int* size() const; - //! returns the size of i-th matrix dimension (or 0) - int size(int i) const; - //! returns the matrix dimensionality - int dims() const; - //! returns the number of non-zero elements (=the number of hash table nodes) - size_t nzcount() const; - - //! computes the element hash value (1D case) - size_t hash(int i0) const; - //! computes the element hash value (2D case) - size_t hash(int i0, int i1) const; - //! computes the element hash value (3D case) - size_t hash(int i0, int i1, int i2) const; - //! computes the element hash value (nD case) - size_t hash(const int* idx) const; - - //@{ - /*! - specialized variants for 1D, 2D, 3D cases and the generic_type one for n-D case. - - return pointer to the matrix element. -
      -
    • if the element is there (it's non-zero), the pointer to it is returned -
    • if it's not there and createMissing=false, NULL pointer is returned -
    • if it's not there and createMissing=true, then the new element - is created and initialized with 0. Pointer to it is returned -
    • if the optional hashval pointer is not NULL, the element hash value is - not computed, but *hashval is taken instead. -
    - */ - //! returns pointer to the specified element (1D case) - uchar* ptr(int i0, bool createMissing, size_t* hashval=0); - //! returns pointer to the specified element (2D case) - uchar* ptr(int i0, int i1, bool createMissing, size_t* hashval=0); - //! returns pointer to the specified element (3D case) - uchar* ptr(int i0, int i1, int i2, bool createMissing, size_t* hashval=0); - //! returns pointer to the specified element (nD case) - uchar* ptr(const int* idx, bool createMissing, size_t* hashval=0); - //@} - - //@{ - /*! - return read-write reference to the specified sparse matrix element. - - ref<_Tp>(i0,...[,hashval]) is equivalent to *(_Tp*)ptr(i0,...,true[,hashval]). - The methods always return a valid reference. - If the element did not exist, it is created and initialiazed with 0. - */ - //! returns reference to the specified element (1D case) - template _Tp& ref(int i0, size_t* hashval=0); - //! returns reference to the specified element (2D case) - template _Tp& ref(int i0, int i1, size_t* hashval=0); - //! returns reference to the specified element (3D case) - template _Tp& ref(int i0, int i1, int i2, size_t* hashval=0); - //! returns reference to the specified element (nD case) - template _Tp& ref(const int* idx, size_t* hashval=0); - //@} - - //@{ - /*! - return value of the specified sparse matrix element. - - value<_Tp>(i0,...[,hashval]) is equivalent - - \code - { const _Tp* p = find<_Tp>(i0,...[,hashval]); return p ? *p : _Tp(); } - \endcode - - That is, if the element did not exist, the methods return 0. - */ - //! returns value of the specified element (1D case) - template _Tp value(int i0, size_t* hashval=0) const; - //! returns value of the specified element (2D case) - template _Tp value(int i0, int i1, size_t* hashval=0) const; - //! returns value of the specified element (3D case) - template _Tp value(int i0, int i1, int i2, size_t* hashval=0) const; - //! returns value of the specified element (nD case) - template _Tp value(const int* idx, size_t* hashval=0) const; - //@} - - //@{ - /*! - Return pointer to the specified sparse matrix element if it exists - - find<_Tp>(i0,...[,hashval]) is equivalent to (_const Tp*)ptr(i0,...false[,hashval]). - - If the specified element does not exist, the methods return NULL. - */ - //! returns pointer to the specified element (1D case) - template const _Tp* find(int i0, size_t* hashval=0) const; - //! returns pointer to the specified element (2D case) - template const _Tp* find(int i0, int i1, size_t* hashval=0) const; - //! returns pointer to the specified element (3D case) - template const _Tp* find(int i0, int i1, int i2, size_t* hashval=0) const; - //! returns pointer to the specified element (nD case) - template const _Tp* find(const int* idx, size_t* hashval=0) const; - - //! erases the specified element (2D case) - void erase(int i0, int i1, size_t* hashval=0); - //! erases the specified element (3D case) - void erase(int i0, int i1, int i2, size_t* hashval=0); - //! erases the specified element (nD case) - void erase(const int* idx, size_t* hashval=0); - - //@{ - /*! - return the sparse matrix iterator pointing to the first sparse matrix element - */ - //! returns the sparse matrix iterator at the matrix beginning - SparseMatIterator begin(); - //! returns the sparse matrix iterator at the matrix beginning - template SparseMatIterator_<_Tp> begin(); - //! returns the read-only sparse matrix iterator at the matrix beginning - SparseMatConstIterator begin() const; - //! returns the read-only sparse matrix iterator at the matrix beginning - template SparseMatConstIterator_<_Tp> begin() const; - //@} - /*! - return the sparse matrix iterator pointing to the element following the last sparse matrix element - */ - //! returns the sparse matrix iterator at the matrix end - SparseMatIterator end(); - //! returns the read-only sparse matrix iterator at the matrix end - SparseMatConstIterator end() const; - //! returns the typed sparse matrix iterator at the matrix end - template SparseMatIterator_<_Tp> end(); - //! returns the typed read-only sparse matrix iterator at the matrix end - template SparseMatConstIterator_<_Tp> end() const; - - //! returns the value stored in the sparse martix node - template _Tp& value(Node* n); - //! returns the value stored in the sparse martix node - template const _Tp& value(const Node* n) const; - - ////////////// some internal-use methods /////////////// - Node* node(size_t nidx); - const Node* node(size_t nidx) const; - - uchar* newNode(const int* idx, size_t hashval); - void removeNode(size_t hidx, size_t nidx, size_t previdx); - void resizeHashTab(size_t newsize); - - enum { MAGIC_VAL=0x42FD0000, MAX_DIM=CV_MAX_DIM, HASH_SCALE=0x5bd1e995, HASH_BIT=0x80000000 }; - - int flags; - Hdr* hdr; -}; - -//! finds global minimum and maximum sparse array elements and returns their values and their locations -CV_EXPORTS void minMaxLoc(const SparseMat& a, double* minVal, - double* maxVal, int* minIdx=0, int* maxIdx=0); -//! computes norm of a sparse matrix -CV_EXPORTS double norm( const SparseMat& src, int normType ); -//! scales and shifts array elements so that either the specified norm (alpha) or the minimum (alpha) and maximum (beta) array values get the specified values -CV_EXPORTS void normalize( const SparseMat& src, SparseMat& dst, double alpha, int normType ); - -/*! - Read-Only Sparse Matrix Iterator. - Here is how to use the iterator to compute the sum of floating-point sparse matrix elements: - - \code - SparseMatConstIterator it = m.begin(), it_end = m.end(); - double s = 0; - CV_Assert( m.type() == CV_32F ); - for( ; it != it_end; ++it ) - s += it.value(); - \endcode -*/ -class CV_EXPORTS SparseMatConstIterator -{ -public: - //! the default constructor - SparseMatConstIterator(); - //! the full constructor setting the iterator to the first sparse matrix element - SparseMatConstIterator(const SparseMat* _m); - //! the copy constructor - SparseMatConstIterator(const SparseMatConstIterator& it); - - //! the assignment operator - SparseMatConstIterator& operator = (const SparseMatConstIterator& it); - - //! template method returning the current matrix element - template const _Tp& value() const; - //! returns the current node of the sparse matrix. it.node->idx is the current element index - const SparseMat::Node* node() const; - - //! moves iterator to the previous element - SparseMatConstIterator& operator --(); - //! moves iterator to the previous element - SparseMatConstIterator operator --(int); - //! moves iterator to the next element - SparseMatConstIterator& operator ++(); - //! moves iterator to the next element - SparseMatConstIterator operator ++(int); - - //! moves iterator to the element after the last element - void seekEnd(); - - const SparseMat* m; - size_t hashidx; - uchar* ptr; -}; - -/*! - Read-write Sparse Matrix Iterator - - The class is similar to cv::SparseMatConstIterator, - but can be used for in-place modification of the matrix elements. -*/ -class CV_EXPORTS SparseMatIterator : public SparseMatConstIterator -{ -public: - //! the default constructor - SparseMatIterator(); - //! the full constructor setting the iterator to the first sparse matrix element - SparseMatIterator(SparseMat* _m); - //! the full constructor setting the iterator to the specified sparse matrix element - SparseMatIterator(SparseMat* _m, const int* idx); - //! the copy constructor - SparseMatIterator(const SparseMatIterator& it); - - //! the assignment operator - SparseMatIterator& operator = (const SparseMatIterator& it); - //! returns read-write reference to the current sparse matrix element - template _Tp& value() const; - //! returns pointer to the current sparse matrix node. it.node->idx is the index of the current element (do not modify it!) - SparseMat::Node* node() const; - - //! moves iterator to the next element - SparseMatIterator& operator ++(); - //! moves iterator to the next element - SparseMatIterator operator ++(int); -}; - -/*! - The Template Sparse Matrix class derived from cv::SparseMat - - The class provides slightly more convenient operations for accessing elements. - - \code - SparseMat m; - ... - SparseMat_ m_ = (SparseMat_&)m; - m_.ref(1)++; // equivalent to m.ref(1)++; - m_.ref(2) += m_(3); // equivalent to m.ref(2) += m.value(3); - \endcode -*/ -template class CV_EXPORTS SparseMat_ : public SparseMat -{ -public: - typedef SparseMatIterator_<_Tp> iterator; - typedef SparseMatConstIterator_<_Tp> const_iterator; - - //! the default constructor - SparseMat_(); - //! the full constructor equivelent to SparseMat(dims, _sizes, DataType<_Tp>::type) - SparseMat_(int dims, const int* _sizes); - //! the copy constructor. If DataType<_Tp>.type != m.type(), the m elements are converted - SparseMat_(const SparseMat& m); - //! the copy constructor. This is O(1) operation - no data is copied - SparseMat_(const SparseMat_& m); - //! converts dense matrix to the sparse form - SparseMat_(const Mat& m); - //! converts the old-style sparse matrix to the C++ class. All the elements are copied - SparseMat_(const CvSparseMat* m); - //! the assignment operator. If DataType<_Tp>.type != m.type(), the m elements are converted - SparseMat_& operator = (const SparseMat& m); - //! the assignment operator. This is O(1) operation - no data is copied - SparseMat_& operator = (const SparseMat_& m); - //! converts dense matrix to the sparse form - SparseMat_& operator = (const Mat& m); - - //! makes full copy of the matrix. All the elements are duplicated - SparseMat_ clone() const; - //! equivalent to cv::SparseMat::create(dims, _sizes, DataType<_Tp>::type) - void create(int dims, const int* _sizes); - //! converts sparse matrix to the old-style CvSparseMat. All the elements are copied - operator CvSparseMat*() const; - - //! returns type of the matrix elements - int type() const; - //! returns depth of the matrix elements - int depth() const; - //! returns the number of channels in each matrix element - int channels() const; - - //! equivalent to SparseMat::ref<_Tp>(i0, hashval) - _Tp& ref(int i0, size_t* hashval=0); - //! equivalent to SparseMat::ref<_Tp>(i0, i1, hashval) - _Tp& ref(int i0, int i1, size_t* hashval=0); - //! equivalent to SparseMat::ref<_Tp>(i0, i1, i2, hashval) - _Tp& ref(int i0, int i1, int i2, size_t* hashval=0); - //! equivalent to SparseMat::ref<_Tp>(idx, hashval) - _Tp& ref(const int* idx, size_t* hashval=0); - - //! equivalent to SparseMat::value<_Tp>(i0, hashval) - _Tp operator()(int i0, size_t* hashval=0) const; - //! equivalent to SparseMat::value<_Tp>(i0, i1, hashval) - _Tp operator()(int i0, int i1, size_t* hashval=0) const; - //! equivalent to SparseMat::value<_Tp>(i0, i1, i2, hashval) - _Tp operator()(int i0, int i1, int i2, size_t* hashval=0) const; - //! equivalent to SparseMat::value<_Tp>(idx, hashval) - _Tp operator()(const int* idx, size_t* hashval=0) const; - - //! returns sparse matrix iterator pointing to the first sparse matrix element - SparseMatIterator_<_Tp> begin(); - //! returns read-only sparse matrix iterator pointing to the first sparse matrix element - SparseMatConstIterator_<_Tp> begin() const; - //! returns sparse matrix iterator pointing to the element following the last sparse matrix element - SparseMatIterator_<_Tp> end(); - //! returns read-only sparse matrix iterator pointing to the element following the last sparse matrix element - SparseMatConstIterator_<_Tp> end() const; -}; - - -/*! - Template Read-Only Sparse Matrix Iterator Class. - - This is the derived from SparseMatConstIterator class that - introduces more convenient operator *() for accessing the current element. -*/ -template class CV_EXPORTS SparseMatConstIterator_ : public SparseMatConstIterator -{ -public: - typedef std::forward_iterator_tag iterator_category; - - //! the default constructor - SparseMatConstIterator_(); - //! the full constructor setting the iterator to the first sparse matrix element - SparseMatConstIterator_(const SparseMat_<_Tp>* _m); - //! the copy constructor - SparseMatConstIterator_(const SparseMatConstIterator_& it); - - //! the assignment operator - SparseMatConstIterator_& operator = (const SparseMatConstIterator_& it); - //! the element access operator - const _Tp& operator *() const; - - //! moves iterator to the next element - SparseMatConstIterator_& operator ++(); - //! moves iterator to the next element - SparseMatConstIterator_ operator ++(int); -}; - -/*! - Template Read-Write Sparse Matrix Iterator Class. - - This is the derived from cv::SparseMatConstIterator_ class that - introduces more convenient operator *() for accessing the current element. -*/ -template class CV_EXPORTS SparseMatIterator_ : public SparseMatConstIterator_<_Tp> -{ -public: - typedef std::forward_iterator_tag iterator_category; - - //! the default constructor - SparseMatIterator_(); - //! the full constructor setting the iterator to the first sparse matrix element - SparseMatIterator_(SparseMat_<_Tp>* _m); - //! the copy constructor - SparseMatIterator_(const SparseMatIterator_& it); - - //! the assignment operator - SparseMatIterator_& operator = (const SparseMatIterator_& it); - //! returns the reference to the current element - _Tp& operator *() const; - - //! moves the iterator to the next element - SparseMatIterator_& operator ++(); - //! moves the iterator to the next element - SparseMatIterator_ operator ++(int); -}; - -//////////////////// Fast Nearest-Neighbor Search Structure //////////////////// /*! Fast Nearest Neighbor Search Class. @@ -3860,6 +809,7 @@ public: Node() : idx(-1), left(-1), right(-1), boundary(0.f) {} Node(int _idx, int _left, int _right, float _boundary) : idx(_idx), left(_left), right(_right), boundary(_boundary) {} + //! split dimension; >=0 for nodes (dim), < 0 for leaves (index of the point) int idx; //! node indices of the left and the right branches @@ -3871,32 +821,32 @@ public: //! the default constructor CV_WRAP KDTree(); //! the full constructor that builds the search tree - CV_WRAP KDTree(InputArray points, bool copyAndReorderPoints=false); + CV_WRAP KDTree(InputArray points, bool copyAndReorderPoints = false); //! the full constructor that builds the search tree CV_WRAP KDTree(InputArray points, InputArray _labels, - bool copyAndReorderPoints=false); + bool copyAndReorderPoints = false); //! builds the search tree - CV_WRAP void build(InputArray points, bool copyAndReorderPoints=false); + CV_WRAP void build(InputArray points, bool copyAndReorderPoints = false); //! builds the search tree CV_WRAP void build(InputArray points, InputArray labels, - bool copyAndReorderPoints=false); + bool copyAndReorderPoints = false); //! finds the K nearest neighbors of "vec" while looking at Emax (at most) leaves CV_WRAP int findNearest(InputArray vec, int K, int Emax, OutputArray neighborsIdx, - OutputArray neighbors=noArray(), - OutputArray dist=noArray(), - OutputArray labels=noArray()) const; + OutputArray neighbors = noArray(), + OutputArray dist = noArray(), + OutputArray labels = noArray()) const; //! finds all the points from the initial set that belong to the specified box CV_WRAP void findOrthoRange(InputArray minBounds, InputArray maxBounds, OutputArray neighborsIdx, - OutputArray neighbors=noArray(), - OutputArray labels=noArray()) const; + OutputArray neighbors = noArray(), + OutputArray labels = noArray()) const; //! returns vectors with the specified indices CV_WRAP void getPoints(InputArray idx, OutputArray pts, - OutputArray labels=noArray()) const; + OutputArray labels = noArray()) const; //! return a vector with the specified index - const float* getPoint(int ptidx, int* label=0) const; + const float* getPoint(int ptidx, int* label = 0) const; //! returns the search space dimensionality CV_WRAP int dims() const; @@ -3907,447 +857,119 @@ public: CV_PROP_RW int normType; //!< type of the distance (cv::NORM_L1 or cv::NORM_L2) used for search. Initially set to cv::NORM_L2, but you can modify it }; -//////////////////////////////////////// XML & YAML I/O //////////////////////////////////// -class CV_EXPORTS FileNode; /*! - XML/YAML File Storage Class. + Random Number Generator - The class describes an object associated with XML or YAML file. - It can be used to store data to such a file or read and decode the data. - - The storage is organized as a tree of nested sequences (or lists) and mappings. - Sequence is a heterogenious array, which elements are accessed by indices or sequentially using an iterator. - Mapping is analogue of std::map or C structure, which elements are accessed by names. - The most top level structure is a mapping. - Leaves of the file storage tree are integers, floating-point numbers and text strings. - - For example, the following code: - - \code - // open file storage for writing. Type of the file is determined from the extension - FileStorage fs("test.yml", FileStorage::WRITE); - fs << "test_int" << 5 << "test_real" << 3.1 << "test_string" << "ABCDEFGH"; - fs << "test_mat" << Mat::eye(3,3,CV_32F); - - fs << "test_list" << "[" << 0.0000000000001 << 2 << CV_PI << -3435345 << "2-502 2-029 3egegeg" << - "{:" << "month" << 12 << "day" << 31 << "year" << 1969 << "}" << "]"; - fs << "test_map" << "{" << "x" << 1 << "y" << 2 << "width" << 100 << "height" << 200 << "lbp" << "[:"; - - const uchar arr[] = {0, 1, 1, 0, 1, 1, 0, 1}; - fs.writeRaw("u", arr, (int)(sizeof(arr)/sizeof(arr[0]))); - - fs << "]" << "}"; - \endcode - - will produce the following file: - - \verbatim - %YAML:1.0 - test_int: 5 - test_real: 3.1000000000000001e+00 - test_string: ABCDEFGH - test_mat: !!opencv-matrix - rows: 3 - cols: 3 - dt: f - data: [ 1., 0., 0., 0., 1., 0., 0., 0., 1. ] - test_list: - - 1.0000000000000000e-13 - - 2 - - 3.1415926535897931e+00 - - -3435345 - - "2-502 2-029 3egegeg" - - { month:12, day:31, year:1969 } - test_map: - x: 1 - y: 2 - width: 100 - height: 200 - lbp: [ 0, 1, 1, 0, 1, 1, 0, 1 ] - \endverbatim - - and to read the file above, the following code can be used: - - \code - // open file storage for reading. - // Type of the file is determined from the content, not the extension - FileStorage fs("test.yml", FileStorage::READ); - int test_int = (int)fs["test_int"]; - double test_real = (double)fs["test_real"]; - std::string test_string = (std::string)fs["test_string"]; - - Mat M; - fs["test_mat"] >> M; - - FileNode tl = fs["test_list"]; - CV_Assert(tl.type() == FileNode::SEQ && tl.size() == 6); - double tl0 = (double)tl[0]; - int tl1 = (int)tl[1]; - double tl2 = (double)tl[2]; - int tl3 = (int)tl[3]; - std::string tl4 = (std::string)tl[4]; - CV_Assert(tl[5].type() == FileNode::MAP && tl[5].size() == 3); - - int month = (int)tl[5]["month"]; - int day = (int)tl[5]["day"]; - int year = (int)tl[5]["year"]; - - FileNode tm = fs["test_map"]; - - int x = (int)tm["x"]; - int y = (int)tm["y"]; - int width = (int)tm["width"]; - int height = (int)tm["height"]; - - int lbp_val = 0; - FileNodeIterator it = tm["lbp"].begin(); - - for(int k = 0; k < 8; k++, ++it) - lbp_val |= ((int)*it) << k; - \endcode + The class implements RNG using Multiply-with-Carry algorithm */ -class CV_EXPORTS_W FileStorage +class CV_EXPORTS RNG { public: - //! file storage mode - enum - { - READ=0, //! read mode - WRITE=1, //! write mode - APPEND=2, //! append mode - MEMORY=4, - FORMAT_MASK=(7<<3), - FORMAT_AUTO=0, - FORMAT_XML=(1<<3), - FORMAT_YAML=(2<<3) - }; - enum - { - UNDEFINED=0, - VALUE_EXPECTED=1, - NAME_EXPECTED=2, - INSIDE_MAP=4 - }; - //! the default constructor - CV_WRAP FileStorage(); - //! the full constructor that opens file storage for reading or writing - CV_WRAP FileStorage(const std::string& source, int flags, const std::string& encoding=std::string()); - //! the constructor that takes pointer to the C FileStorage structure - FileStorage(CvFileStorage* fs); - //! the destructor. calls release() - virtual ~FileStorage(); + enum { UNIFORM = 0, + NORMAL = 1 + }; - //! opens file storage for reading or writing. The previous storage is closed with release() - CV_WRAP virtual bool open(const std::string& filename, int flags, const std::string& encoding=std::string()); - //! returns true if the object is associated with currently opened file. - CV_WRAP virtual bool isOpened() const; - //! closes the file and releases all the memory buffers - CV_WRAP virtual void release(); - //! closes the file, releases all the memory buffers and returns the text string - CV_WRAP virtual std::string releaseAndGetString(); + RNG(); + RNG(uint64 state); + //! updates the state and returns the next 32-bit unsigned integer random number + unsigned next(); - //! returns the first element of the top-level mapping - CV_WRAP FileNode getFirstTopLevelNode() const; - //! returns the top-level mapping. YAML supports multiple streams - CV_WRAP FileNode root(int streamidx=0) const; - //! returns the specified element of the top-level mapping - FileNode operator[](const std::string& nodename) const; - //! returns the specified element of the top-level mapping - CV_WRAP FileNode operator[](const char* nodename) const; + operator uchar(); + operator schar(); + operator ushort(); + operator short(); + operator unsigned(); + //! returns a random integer sampled uniformly from [0, N). + unsigned operator ()(unsigned N); + unsigned operator ()(); + operator int(); + operator float(); + operator double(); + //! returns uniformly distributed integer random number from [a,b) range + int uniform(int a, int b); + //! returns uniformly distributed floating-point random number from [a,b) range + float uniform(float a, float b); + //! returns uniformly distributed double-precision floating-point random number from [a,b) range + double uniform(double a, double b); + void fill( InputOutputArray mat, int distType, InputArray a, InputArray b, bool saturateRange = false ); + //! returns Gaussian random variate with mean zero. + double gaussian(double sigma); - //! returns pointer to the underlying C FileStorage structure - CvFileStorage* operator *() { return fs; } - //! returns pointer to the underlying C FileStorage structure - const CvFileStorage* operator *() const { return fs; } - //! writes one or more numbers of the specified format to the currently written structure - void writeRaw( const std::string& fmt, const uchar* vec, size_t len ); - //! writes the registered C structure (CvMat, CvMatND, CvSeq). See cvWrite() - void writeObj( const std::string& name, const void* obj ); - - //! returns the normalized object name for the specified file name - static std::string getDefaultObjectName(const std::string& filename); - - Ptr fs; //!< the underlying C FileStorage structure - std::string elname; //!< the currently written element - std::vector structs; //!< the stack of written structures - int state; //!< the writer state + uint64 state; }; -class CV_EXPORTS FileNodeIterator; - -/*! - File Storage Node class - - The node is used to store each and every element of the file storage opened for reading - - from the primitive objects, such as numbers and text strings, to the complex nodes: - sequences, mappings and the registered objects. - - Note that file nodes are only used for navigating file storages opened for reading. - When a file storage is opened for writing, no data is stored in memory after it is written. -*/ -class CV_EXPORTS_W_SIMPLE FileNode +class CV_EXPORTS RNG_MT19937 { public: - //! type of the file storage node - enum - { - NONE=0, //!< empty node - INT=1, //!< an integer - REAL=2, //!< floating-point number - FLOAT=REAL, //!< synonym or REAL - STR=3, //!< text string in UTF-8 encoding - STRING=STR, //!< synonym for STR - REF=4, //!< integer of size size_t. Typically used for storing complex dynamic structures where some elements reference the others - SEQ=5, //!< sequence - MAP=6, //!< mapping - TYPE_MASK=7, - FLOW=8, //!< compact representation of a sequence or mapping. Used only by YAML writer - USER=16, //!< a registered object (e.g. a matrix) - EMPTY=32, //!< empty structure (sequence or mapping) - NAMED=64 //!< the node has a name (i.e. it is element of a mapping) - }; - //! the default constructor - CV_WRAP FileNode(); - //! the full constructor wrapping CvFileNode structure. - FileNode(const CvFileStorage* fs, const CvFileNode* node); - //! the copy constructor - FileNode(const FileNode& node); - //! returns element of a mapping node - FileNode operator[](const std::string& nodename) const; - //! returns element of a mapping node - CV_WRAP FileNode operator[](const char* nodename) const; - //! returns element of a sequence node - CV_WRAP FileNode operator[](int i) const; - //! returns type of the node - CV_WRAP int type() const; + RNG_MT19937(); + RNG_MT19937(unsigned s); + void seed(unsigned s); - //! returns true if the node is empty - CV_WRAP bool empty() const; - //! returns true if the node is a "none" object - CV_WRAP bool isNone() const; - //! returns true if the node is a sequence - CV_WRAP bool isSeq() const; - //! returns true if the node is a mapping - CV_WRAP bool isMap() const; - //! returns true if the node is an integer - CV_WRAP bool isInt() const; - //! returns true if the node is a floating-point number - CV_WRAP bool isReal() const; - //! returns true if the node is a text string - CV_WRAP bool isString() const; - //! returns true if the node has a name - CV_WRAP bool isNamed() const; - //! returns the node name or an empty string if the node is nameless - CV_WRAP std::string name() const; - //! returns the number of elements in the node, if it is a sequence or mapping, or 1 otherwise. - CV_WRAP size_t size() const; - //! returns the node content as an integer. If the node stores floating-point number, it is rounded. - operator int() const; - //! returns the node content as float - operator float() const; - //! returns the node content as double - operator double() const; - //! returns the node content as text string - operator std::string() const; + unsigned next(); - //! returns pointer to the underlying file node - CvFileNode* operator *(); - //! returns pointer to the underlying file node - const CvFileNode* operator* () const; + operator int(); + operator unsigned(); + operator float(); + operator double(); - //! returns iterator pointing to the first node element - FileNodeIterator begin() const; - //! returns iterator pointing to the element following the last node element - FileNodeIterator end() const; + unsigned operator ()(unsigned N); + unsigned operator ()(); - //! reads node elements to the buffer with the specified format - void readRaw( const std::string& fmt, uchar* vec, size_t len ) const; - //! reads the registered object and returns pointer to it - void* readObj() const; + // returns uniformly distributed integer random number from [a,b) range + int uniform(int a, int b); + // returns uniformly distributed floating-point random number from [a,b) range + float uniform(float a, float b); + // returns uniformly distributed double-precision floating-point random number from [a,b) range + double uniform(double a, double b); - // do not use wrapper pointer classes for better efficiency - const CvFileStorage* fs; - const CvFileNode* node; +private: + enum PeriodParameters {N = 624, M = 397}; + unsigned state[N]; + int mti; }; -/*! - File Node Iterator - The class is used for iterating sequences (usually) and mappings. - */ -class CV_EXPORTS FileNodeIterator +/////////////////////////////// Formatted output of cv::Mat /////////////////////////// + +class CV_EXPORTS Formatted { public: - //! the default constructor - FileNodeIterator(); - //! the full constructor set to the ofs-th element of the node - FileNodeIterator(const CvFileStorage* fs, const CvFileNode* node, size_t ofs=0); - //! the copy constructor - FileNodeIterator(const FileNodeIterator& it); - //! returns the currently observed element - FileNode operator *() const; - //! accesses the currently observed element methods - FileNode operator ->() const; - - //! moves iterator to the next node - FileNodeIterator& operator ++ (); - //! moves iterator to the next node - FileNodeIterator operator ++ (int); - //! moves iterator to the previous node - FileNodeIterator& operator -- (); - //! moves iterator to the previous node - FileNodeIterator operator -- (int); - //! moves iterator forward by the specified offset (possibly negative) - FileNodeIterator& operator += (int ofs); - //! moves iterator backward by the specified offset (possibly negative) - FileNodeIterator& operator -= (int ofs); - - //! reads the next maxCount elements (or less, if the sequence/mapping last element occurs earlier) to the buffer with the specified format - FileNodeIterator& readRaw( const std::string& fmt, uchar* vec, - size_t maxCount=(size_t)INT_MAX ); - - const CvFileStorage* fs; - const CvFileNode* container; - CvSeqReader reader; - size_t remaining; -}; - -////////////// convenient wrappers for operating old-style dynamic structures ////////////// - -template class SeqIterator; - -typedef Ptr MemStorage; - -/*! - Template Sequence Class derived from CvSeq - - The class provides more convenient access to sequence elements, - STL-style operations and iterators. - - \note The class is targeted for simple data types, - i.e. no constructors or destructors - are called for the sequence elements. -*/ -template class CV_EXPORTS Seq -{ -public: - typedef SeqIterator<_Tp> iterator; - typedef SeqIterator<_Tp> const_iterator; - - //! the default constructor - Seq(); - //! the constructor for wrapping CvSeq structure. The real element type in CvSeq should match _Tp. - Seq(const CvSeq* seq); - //! creates the empty sequence that resides in the specified storage - Seq(MemStorage& storage, int headerSize = sizeof(CvSeq)); - //! returns read-write reference to the specified element - _Tp& operator [](int idx); - //! returns read-only reference to the specified element - const _Tp& operator[](int idx) const; - //! returns iterator pointing to the beginning of the sequence - SeqIterator<_Tp> begin() const; - //! returns iterator pointing to the element following the last sequence element - SeqIterator<_Tp> end() const; - //! returns the number of elements in the sequence - size_t size() const; - //! returns the type of sequence elements (CV_8UC1 ... CV_64FC(CV_CN_MAX) ...) - int type() const; - //! returns the depth of sequence elements (CV_8U ... CV_64F) - int depth() const; - //! returns the number of channels in each sequence element - int channels() const; - //! returns the size of each sequence element - size_t elemSize() const; - //! returns index of the specified sequence element - size_t index(const _Tp& elem) const; - //! appends the specified element to the end of the sequence - void push_back(const _Tp& elem); - //! appends the specified element to the front of the sequence - void push_front(const _Tp& elem); - //! appends zero or more elements to the end of the sequence - void push_back(const _Tp* elems, size_t count); - //! appends zero or more elements to the front of the sequence - void push_front(const _Tp* elems, size_t count); - //! inserts the specified element to the specified position - void insert(int idx, const _Tp& elem); - //! inserts zero or more elements to the specified position - void insert(int idx, const _Tp* elems, size_t count); - //! removes element at the specified position - void remove(int idx); - //! removes the specified subsequence - void remove(const Range& r); - - //! returns reference to the first sequence element - _Tp& front(); - //! returns read-only reference to the first sequence element - const _Tp& front() const; - //! returns reference to the last sequence element - _Tp& back(); - //! returns read-only reference to the last sequence element - const _Tp& back() const; - //! returns true iff the sequence contains no elements - bool empty() const; - - //! removes all the elements from the sequence - void clear(); - //! removes the first element from the sequence - void pop_front(); - //! removes the last element from the sequence - void pop_back(); - //! removes zero or more elements from the beginning of the sequence - void pop_front(_Tp* elems, size_t count); - //! removes zero or more elements from the end of the sequence - void pop_back(_Tp* elems, size_t count); - - //! copies the whole sequence or the sequence slice to the specified vector - void copyTo(std::vector<_Tp>& vec, const Range& range=Range::all()) const; - //! returns the vector containing all the sequence elements - operator std::vector<_Tp>() const; - - CvSeq* seq; + virtual const char* next() = 0; + virtual void reset() = 0; + virtual ~Formatted(); }; -/*! - STL-style Sequence Iterator inherited from the CvSeqReader structure -*/ -template class CV_EXPORTS SeqIterator : public CvSeqReader +class CV_EXPORTS Formatter { public: - //! the default constructor - SeqIterator(); - //! the constructor setting the iterator to the beginning or to the end of the sequence - SeqIterator(const Seq<_Tp>& seq, bool seekEnd=false); - //! positions the iterator within the sequence - void seek(size_t pos); - //! reports the current iterator position - size_t tell() const; - //! returns reference to the current sequence element - _Tp& operator *(); - //! returns read-only reference to the current sequence element - const _Tp& operator *() const; - //! moves iterator to the next sequence element - SeqIterator& operator ++(); - //! moves iterator to the next sequence element - SeqIterator operator ++(int) const; - //! moves iterator to the previous sequence element - SeqIterator& operator --(); - //! moves iterator to the previous sequence element - SeqIterator operator --(int) const; + enum { FMT_MATLAB = 0, + FMT_CSV = 1, + FMT_PYTHON = 2, + FMT_NUMPY = 3, + FMT_C = 4, + FMT_DEFAULT = FMT_MATLAB + }; - //! moves iterator forward by the specified offset (possibly negative) - SeqIterator& operator +=(int); - //! moves iterator backward by the specified offset (possibly negative) - SeqIterator& operator -=(int); + virtual ~Formatter(); + + virtual Ptr format(const Mat& mtx) const = 0; + + virtual void set32fPrecision(int p = 8) = 0; + virtual void set64fPrecision(int p = 16) = 0; + virtual void setMultiline(bool ml = true) = 0; + + static Ptr get(int fmt = FMT_DEFAULT); - // this is index of the current element module seq->total*2 - // (to distinguish between 0 and seq->total) - int index; }; + + +//////////////////////////////////////// Algorithm //////////////////////////////////// + class CV_EXPORTS Algorithm; class CV_EXPORTS AlgorithmInfo; struct CV_EXPORTS AlgorithmInfoData; @@ -4362,41 +984,41 @@ class CV_EXPORTS_W Algorithm public: Algorithm(); virtual ~Algorithm(); - std::string name() const; + String name() const; - template typename ParamType<_Tp>::member_type get(const std::string& name) const; + template typename ParamType<_Tp>::member_type get(const String& name) const; template typename ParamType<_Tp>::member_type get(const char* name) const; - CV_WRAP int getInt(const std::string& name) const; - CV_WRAP double getDouble(const std::string& name) const; - CV_WRAP bool getBool(const std::string& name) const; - CV_WRAP std::string getString(const std::string& name) const; - CV_WRAP Mat getMat(const std::string& name) const; - CV_WRAP std::vector getMatVector(const std::string& name) const; - CV_WRAP Ptr getAlgorithm(const std::string& name) const; + CV_WRAP int getInt(const String& name) const; + CV_WRAP double getDouble(const String& name) const; + CV_WRAP bool getBool(const String& name) const; + CV_WRAP String getString(const String& name) const; + CV_WRAP Mat getMat(const String& name) const; + CV_WRAP std::vector getMatVector(const String& name) const; + CV_WRAP Ptr getAlgorithm(const String& name) const; - void set(const std::string& name, int value); - void set(const std::string& name, double value); - void set(const std::string& name, bool value); - void set(const std::string& name, const std::string& value); - void set(const std::string& name, const Mat& value); - void set(const std::string& name, const std::vector& value); - void set(const std::string& name, const Ptr& value); - template void set(const std::string& name, const Ptr<_Tp>& value); + void set(const String& name, int value); + void set(const String& name, double value); + void set(const String& name, bool value); + void set(const String& name, const String& value); + void set(const String& name, const Mat& value); + void set(const String& name, const std::vector& value); + void set(const String& name, const Ptr& value); + template void set(const String& name, const Ptr<_Tp>& value); - CV_WRAP void setInt(const std::string& name, int value); - CV_WRAP void setDouble(const std::string& name, double value); - CV_WRAP void setBool(const std::string& name, bool value); - CV_WRAP void setString(const std::string& name, const std::string& value); - CV_WRAP void setMat(const std::string& name, const Mat& value); - CV_WRAP void setMatVector(const std::string& name, const std::vector& value); - CV_WRAP void setAlgorithm(const std::string& name, const Ptr& value); - template void setAlgorithm(const std::string& name, const Ptr<_Tp>& value); + CV_WRAP void setInt(const String& name, int value); + CV_WRAP void setDouble(const String& name, double value); + CV_WRAP void setBool(const String& name, bool value); + CV_WRAP void setString(const String& name, const String& value); + CV_WRAP void setMat(const String& name, const Mat& value); + CV_WRAP void setMatVector(const String& name, const std::vector& value); + CV_WRAP void setAlgorithm(const String& name, const Ptr& value); + template void setAlgorithm(const String& name, const Ptr<_Tp>& value); void set(const char* name, int value); void set(const char* name, double value); void set(const char* name, bool value); - void set(const char* name, const std::string& value); + void set(const char* name, const String& value); void set(const char* name, const Mat& value); void set(const char* name, const std::vector& value); void set(const char* name, const Ptr& value); @@ -4405,16 +1027,16 @@ public: void setInt(const char* name, int value); void setDouble(const char* name, double value); void setBool(const char* name, bool value); - void setString(const char* name, const std::string& value); + void setString(const char* name, const String& value); void setMat(const char* name, const Mat& value); void setMatVector(const char* name, const std::vector& value); void setAlgorithm(const char* name, const Ptr& value); template void setAlgorithm(const char* name, const Ptr<_Tp>& value); - CV_WRAP std::string paramHelp(const std::string& name) const; + CV_WRAP String paramHelp(const String& name) const; int paramType(const char* name) const; - CV_WRAP int paramType(const std::string& name) const; - CV_WRAP void getParams(CV_OUT std::vector& names) const; + CV_WRAP int paramType(const String& name) const; + CV_WRAP void getParams(CV_OUT std::vector& names) const; virtual void write(FileStorage& fs) const; @@ -4424,9 +1046,9 @@ public: typedef int (Algorithm::*Getter)() const; typedef void (Algorithm::*Setter)(int); - CV_WRAP static void getList(CV_OUT std::vector& algorithms); - CV_WRAP static Ptr _create(const std::string& name); - template static Ptr<_Tp> create(const std::string& name); + CV_WRAP static void getList(CV_OUT std::vector& algorithms); + CV_WRAP static Ptr _create(const String& name); + template static Ptr<_Tp> create(const String& name); virtual AlgorithmInfo* info() const /* TODO: make it = 0;*/ { return 0; } }; @@ -4436,86 +1058,86 @@ class CV_EXPORTS AlgorithmInfo { public: friend class Algorithm; - AlgorithmInfo(const std::string& name, Algorithm::Constructor create); + AlgorithmInfo(const String& name, Algorithm::Constructor create); ~AlgorithmInfo(); void get(const Algorithm* algo, const char* name, int argType, void* value) const; void addParam_(Algorithm& algo, const char* name, int argType, void* value, bool readOnly, Algorithm::Getter getter, Algorithm::Setter setter, - const std::string& help=std::string()); - std::string paramHelp(const char* name) const; + const String& help=String()); + String paramHelp(const char* name) const; int paramType(const char* name) const; - void getParams(std::vector& names) const; + void getParams(std::vector& names) const; void write(const Algorithm* algo, FileStorage& fs) const; void read(Algorithm* algo, const FileNode& fn) const; - std::string name() const; + String name() const; void addParam(Algorithm& algo, const char* name, int& value, bool readOnly=false, int (Algorithm::*getter)()=0, void (Algorithm::*setter)(int)=0, - const std::string& help=std::string()); + const String& help=String()); void addParam(Algorithm& algo, const char* name, bool& value, bool readOnly=false, int (Algorithm::*getter)()=0, void (Algorithm::*setter)(int)=0, - const std::string& help=std::string()); + const String& help=String()); void addParam(Algorithm& algo, const char* name, double& value, bool readOnly=false, double (Algorithm::*getter)()=0, void (Algorithm::*setter)(double)=0, - const std::string& help=std::string()); + const String& help=String()); void addParam(Algorithm& algo, const char* name, - std::string& value, bool readOnly=false, - std::string (Algorithm::*getter)()=0, - void (Algorithm::*setter)(const std::string&)=0, - const std::string& help=std::string()); + String& value, bool readOnly=false, + String (Algorithm::*getter)()=0, + void (Algorithm::*setter)(const String&)=0, + const String& help=String()); void addParam(Algorithm& algo, const char* name, Mat& value, bool readOnly=false, Mat (Algorithm::*getter)()=0, void (Algorithm::*setter)(const Mat&)=0, - const std::string& help=std::string()); + const String& help=String()); void addParam(Algorithm& algo, const char* name, std::vector& value, bool readOnly=false, std::vector (Algorithm::*getter)()=0, void (Algorithm::*setter)(const std::vector&)=0, - const std::string& help=std::string()); + const String& help=String()); void addParam(Algorithm& algo, const char* name, Ptr& value, bool readOnly=false, Ptr (Algorithm::*getter)()=0, void (Algorithm::*setter)(const Ptr&)=0, - const std::string& help=std::string()); + const String& help=String()); void addParam(Algorithm& algo, const char* name, float& value, bool readOnly=false, float (Algorithm::*getter)()=0, void (Algorithm::*setter)(float)=0, - const std::string& help=std::string()); + const String& help=String()); void addParam(Algorithm& algo, const char* name, unsigned int& value, bool readOnly=false, unsigned int (Algorithm::*getter)()=0, void (Algorithm::*setter)(unsigned int)=0, - const std::string& help=std::string()); + const String& help=String()); void addParam(Algorithm& algo, const char* name, uint64& value, bool readOnly=false, uint64 (Algorithm::*getter)()=0, void (Algorithm::*setter)(uint64)=0, - const std::string& help=std::string()); + const String& help=String()); void addParam(Algorithm& algo, const char* name, uchar& value, bool readOnly=false, uchar (Algorithm::*getter)()=0, void (Algorithm::*setter)(uchar)=0, - const std::string& help=std::string()); + const String& help=String()); template void addParam(Algorithm& algo, const char* name, Ptr<_Tp>& value, bool readOnly=false, Ptr<_Tp> (Algorithm::*getter)()=0, void (Algorithm::*setter)(const Ptr<_Tp>&)=0, - const std::string& help=std::string()); + const String& help=String()); template void addParam(Algorithm& algo, const char* name, Ptr<_Tp>& value, bool readOnly=false, Ptr<_Tp> (Algorithm::*getter)()=0, void (Algorithm::*setter)(const Ptr<_Tp>&)=0, - const std::string& help=std::string()); + const String& help=String()); protected: AlgorithmInfoData* data; void set(Algorithm* algo, const char* name, int argType, @@ -4531,13 +1153,13 @@ struct CV_EXPORTS Param Param(int _type, bool _readonly, int _offset, Algorithm::Getter _getter=0, Algorithm::Setter _setter=0, - const std::string& _help=std::string()); + const String& _help=String()); int type; int offset; bool readonly; Algorithm::Getter getter; Algorithm::Setter setter; - std::string help; + String help; }; template<> struct ParamType @@ -4564,10 +1186,10 @@ template<> struct ParamType enum { type = Param::REAL }; }; -template<> struct ParamType +template<> struct ParamType { - typedef const std::string& const_param_type; - typedef std::string member_type; + typedef const String& const_param_type; + typedef String member_type; enum { type = Param::STRING }; }; @@ -4628,95 +1250,10 @@ template<> struct ParamType enum { type = Param::UCHAR }; }; -// The CommandLineParser class is designed for command line arguments parsing - -class CV_EXPORTS CommandLineParser -{ - public: - CommandLineParser(int argc, const char* const argv[], const std::string& keys); - CommandLineParser(const CommandLineParser& parser); - CommandLineParser& operator = (const CommandLineParser& parser); - - std::string getPathToApplication() const; - - template - T get(const std::string& name, bool space_delete = true) const - { - T val = T(); - getByName(name, space_delete, ParamType::type, (void*)&val); - return val; - } - - template - T get(int index, bool space_delete = true) const - { - T val = T(); - getByIndex(index, space_delete, ParamType::type, (void*)&val); - return val; - } - - bool has(const std::string& name) const; - - bool check() const; - - void about(const std::string& message); - - void printMessage() const; - void printErrors() const; - -protected: - void getByName(const std::string& name, bool space_delete, int type, void* dst) const; - void getByIndex(int index, bool space_delete, int type, void* dst) const; - - struct Impl; - Impl* impl; -}; - -/////////////////////////////// Parallel Primitives ////////////////////////////////// - -// a base body class -class CV_EXPORTS ParallelLoopBody -{ -public: - virtual ~ParallelLoopBody(); - virtual void operator() (const Range& range) const = 0; -}; - -CV_EXPORTS void parallel_for_(const Range& range, const ParallelLoopBody& body, double nstripes=-1.); - -/////////////////////////// Synchronization Primitives /////////////////////////////// - -class CV_EXPORTS Mutex -{ -public: - Mutex(); - ~Mutex(); - Mutex(const Mutex& m); - Mutex& operator = (const Mutex& m); - - void lock(); - bool trylock(); - void unlock(); - - struct Impl; -protected: - Impl* impl; -}; - -class CV_EXPORTS AutoLock -{ -public: - AutoLock(Mutex& m) : mutex(&m) { mutex->lock(); } - ~AutoLock() { mutex->unlock(); } -protected: - Mutex* mutex; -}; - -} - -#endif // __cplusplus +} //namespace cv #include "opencv2/core/operations.hpp" -#include "opencv2/core/mat.hpp" +#include "opencv2/core/cvstd.inl.hpp" + #endif /*__OPENCV_CORE_HPP__*/ diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index c9329c9b64..ed8bd29a18 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -1,44 +1,45 @@ /*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) 2008-2013, 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*/ +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ #ifndef __OPENCV_CORE_AFFINE3_HPP__ #define __OPENCV_CORE_AFFINE3_HPP__ @@ -68,7 +69,7 @@ namespace cv //Rodrigues vector Affine3(const Vec3& rvec, const Vec3& t = Vec3::all(0)); - + //Combines all contructors above. Supports 4x4, 3x3, 1x3, 3x1 sizes of data matrix explicit Affine3(const cv::Mat& data, const Vec3& t = Vec3::all(0)); @@ -79,13 +80,13 @@ namespace cv //Rotation matrix void rotation(const Mat3& R); - + //Rodrigues vector void rotation(const Vec3& rvec); - + //Combines rotation methods above. Suports 3x3, 1x3, 3x1 sizes of data matrix; void rotation(const Mat& data); - + //Euler angles void rotation(float_type alpha, float_type beta, float_type gamma); @@ -109,8 +110,6 @@ namespace cv template operator Affine3() const; - operator cv::Mat(); - Mat4 matrix; #if defined EIGEN_WORLD_VERSION && defined EIGEN_GEOMETRY_MODULE_H @@ -121,24 +120,36 @@ namespace cv #endif }; - template Affine3 operator*(const Affine3& affine1, const Affine3& affine2); - template V operator*(const Affine3& affine, const V& vector); + template static + Affine3 operator*(const Affine3& affine1, const Affine3& affine2); + + template static + V operator*(const Affine3& affine, const V& vector); typedef Affine3 Affine3f; typedef Affine3 Affine3d; - cv::Vec3f operator*(const cv::Affine3f& affine, const cv::Vec3f& vector); - cv::Vec3d operator*(const cv::Affine3d& affine, const cv::Vec3d& vector); + static cv::Vec3f operator*(const cv::Affine3f& affine, const cv::Vec3f& vector); + static cv::Vec3d operator*(const cv::Affine3d& affine, const cv::Vec3d& vector); } + /////////////////////////////////////////////////////////////////////////////////// /// Implementaiton -template inline cv::Affine3::Affine3() : matrix(Mat4::eye()) {} -template inline cv::Affine3::Affine3(const Mat4& affine) : matrix(affine) {} +template inline +cv::Affine3::Affine3() + : matrix(Mat4::eye()) +{} -template inline cv::Affine3::Affine3(const Mat3& R, const Vec3& t) +template inline +cv::Affine3::Affine3(const Mat4& affine) + : matrix(affine) +{} + +template inline +cv::Affine3::Affine3(const Mat3& R, const Vec3& t) { rotation(R); translation(t); @@ -146,7 +157,8 @@ template inline cv::Affine3::Affine3(const Mat3& R, const Vec3& t matrix.val[15] = 1; } -template inline cv::Affine3::Affine3(const Vec3& rvec, const Vec3& t) +template inline +cv::Affine3::Affine3(const Vec3& rvec, const Vec3& t) { rotation(rvec); translation(t); @@ -154,7 +166,8 @@ template inline cv::Affine3::Affine3(const Vec3& rvec, const Vec3 matrix.val[15] = 1; } -template inline cv::Affine3::Affine3(const cv::Mat& data, const Vec3& t) +template inline +cv::Affine3::Affine3(const cv::Mat& data, const Vec3& t) { CV_Assert(data.type() == cv::DataType::type); @@ -170,7 +183,8 @@ template inline cv::Affine3::Affine3(const cv::Mat& data, const V matrix.val[15] = 1; } -template inline cv::Affine3::Affine3(float_type alpha, float_type beta, float_type gamma, const Vec3& t) +template inline +cv::Affine3::Affine3(float_type alpha, float_type beta, float_type gamma, const Vec3& t) { rotation(alpha, beta, gamma); translation(t); @@ -178,14 +192,20 @@ template inline cv::Affine3::Affine3(float_type alpha, float_type matrix.val[15] = 1; } -template inline cv::Affine3 cv::Affine3::Identity() +template inline +cv::Affine3 cv::Affine3::Identity() { return Affine3(cv::Affine3::Mat4::eye()); } -template inline void cv::Affine3::rotation(const Mat3& R) { linear(R); } +template inline +void cv::Affine3::rotation(const Mat3& R) +{ + linear(R); +} -template inline void cv::Affine3::rotation(const Vec3& rvec) +template inline +void cv::Affine3::rotation(const Vec3& rvec) { double rx = rvec[0], ry = rvec[1], rz = rvec[2]; double theta = std::sqrt(rx*rx + ry*ry + rz*rz); @@ -217,10 +237,11 @@ template inline void cv::Affine3::rotation(const Vec3& rvec) } //Combines rotation methods above. Suports 3x3, 1x3, 3x1 sizes of data matrix; -template inline void cv::Affine3::rotation(const cv::Mat& data) +template inline +void cv::Affine3::rotation(const cv::Mat& data) { CV_Assert(data.type() == cv::DataType::type); - + if (data.cols == 3 && data.rows == 3) { Mat3 R; @@ -237,44 +258,56 @@ template inline void cv::Affine3::rotation(const cv::Mat& data) CV_Assert(!"Input marix can be 3x3, 1x3 or 3x1"); } -template inline void cv::Affine3::rotation(float_type alpha, float_type beta, float_type gamma) +template inline +void cv::Affine3::rotation(float_type alpha, float_type beta, float_type gamma) { rotation(Vec3(alpha, beta, gamma)); } -template inline void cv::Affine3::linear(const Mat3& L) +template inline +void cv::Affine3::linear(const Mat3& L) { matrix.val[0] = L.val[0]; matrix.val[1] = L.val[1]; matrix.val[ 2] = L.val[2]; matrix.val[4] = L.val[3]; matrix.val[5] = L.val[4]; matrix.val[ 6] = L.val[5]; matrix.val[8] = L.val[6]; matrix.val[9] = L.val[7]; matrix.val[10] = L.val[8]; } -template inline void cv::Affine3::translation(const Vec3& t) +template inline +void cv::Affine3::translation(const Vec3& t) { matrix.val[3] = t[0]; matrix.val[7] = t[1]; matrix.val[11] = t[2]; } -template inline typename cv::Affine3::Mat3 cv::Affine3::rotation() const { return linear(); } -template inline typename cv::Affine3::Mat3 cv::Affine3::linear() const +template inline +typename cv::Affine3::Mat3 cv::Affine3::rotation() const { - cv::Affine3::Mat3 R; + return linear(); +} + +template inline +typename cv::Affine3::Mat3 cv::Affine3::linear() const +{ + typename cv::Affine3::Mat3 R; R.val[0] = matrix.val[0]; R.val[1] = matrix.val[1]; R.val[2] = matrix.val[ 2]; R.val[3] = matrix.val[4]; R.val[4] = matrix.val[5]; R.val[5] = matrix.val[ 6]; R.val[6] = matrix.val[8]; R.val[7] = matrix.val[9]; R.val[8] = matrix.val[10]; return R; } -template inline typename cv::Affine3::Vec3 cv::Affine3::translation() const +template inline +typename cv::Affine3::Vec3 cv::Affine3::translation() const { return Vec3(matrix.val[3], matrix.val[7], matrix.val[11]); } -template inline cv::Affine3 cv::Affine3::inv(int method) const +template inline +cv::Affine3 cv::Affine3::inv(int method) const { return matrix.inv(method); } -template inline cv::Affine3 cv::Affine3::rotate(const Mat3& R) const +template inline +cv::Affine3 cv::Affine3::rotate(const Mat3& R) const { Mat3 Lc = linear(); Vec3 tc = translation(); @@ -297,7 +330,8 @@ template inline cv::Affine3 cv::Affine3::rotate(const Mat3& R) return result; } -template inline cv::Affine3 cv::Affine3::translate(const Vec3& t) const +template inline +cv::Affine3 cv::Affine3::translate(const Vec3& t) const { Mat4 m = matrix; m.val[ 3] += t[0]; @@ -306,24 +340,26 @@ template inline cv::Affine3 cv::Affine3::translate(const Vec3& return m; } -template inline cv::Affine3 cv::Affine3::concatenate(const Affine3& affine) const +template inline +cv::Affine3 cv::Affine3::concatenate(const Affine3& affine) const { return (*this).rotate(affine.rotation()).translate(affine.translation()); } -template template inline cv::Affine3::operator Affine3() const +template template inline +cv::Affine3::operator Affine3() const { return Affine3(matrix); } -template inline cv::Affine3::operator cv::Mat() { return cv::Mat(matrix, false); } - -template inline cv::Affine3 cv::operator*(const cv::Affine3& affine1, const cv::Affine3& affine2) +template inline +cv::Affine3 cv::operator*(const cv::Affine3& affine1, const cv::Affine3& affine2) { return affine2.concatenate(affine1); } -template inline V cv::operator*(const cv::Affine3& affine, const V& v) +template inline +V cv::operator*(const cv::Affine3& affine, const V& v) { const typename Affine3::Mat4& m = affine.matrix; @@ -334,7 +370,8 @@ template inline V cv::operator*(const cv::Affine3& af return r; } -inline cv::Vec3f cv::operator*(const cv::Affine3f& affine, const cv::Vec3f& v) +static inline +cv::Vec3f cv::operator*(const cv::Affine3f& affine, const cv::Vec3f& v) { const cv::Matx44f& m = affine.matrix; cv::Vec3f r; @@ -344,7 +381,8 @@ inline cv::Vec3f cv::operator*(const cv::Affine3f& affine, const cv::Vec3f& v) return r; } -inline cv::Vec3d cv::operator*(const cv::Affine3d& affine, const cv::Vec3d& v) +static inline +cv::Vec3d cv::operator*(const cv::Affine3d& affine, const cv::Vec3d& v) { const cv::Matx44d& m = affine.matrix; cv::Vec3d r; @@ -354,20 +392,25 @@ inline cv::Vec3d cv::operator*(const cv::Affine3d& affine, const cv::Vec3d& v) return r; } -#if (defined EIGEN_WORLD_VERSION && defined EIGEN_GEOMETRY_MODULE_H) || defined CV_AFFINE_FORCE_EIGEN_PLUGIN -template inline cv::Affine3::Affine3(const Eigen::Transform& affine) + +#if defined EIGEN_WORLD_VERSION && defined EIGEN_GEOMETRY_MODULE_H + +template inline +cv::Affine3::Affine3(const Eigen::Transform& affine) { cv::Mat(4, 4, cv::DataType::type, affine.matrix().data()).copyTo(matrix); } -template inline cv::Affine3::Affine3(const Eigen::Transform& affine) +template inline +cv::Affine3::Affine3(const Eigen::Transform& affine) { Eigen::Transform a = affine; cv::Mat(4, 4, cv::DataType::type, a.matrix().data()).copyTo(matrix); } -template inline cv::Affine3::operator Eigen::Transform() const +template inline +cv::Affine3::operator Eigen::Transform() const { Eigen::Transform r; cv::Mat hdr(4, 4, cv::DataType::type, r.matrix().data()); @@ -375,7 +418,8 @@ template inline cv::Affine3::operator Eigen::Transform inline cv::Affine3::operator Eigen::Transform() const +template inline +cv::Affine3::operator Eigen::Transform() const { return this->operator Eigen::Transform(); } @@ -386,5 +430,3 @@ template inline cv::Affine3::operator Eigen::Transform + +#include "opencv2/core/cvdef.h" +#include "opencv2/core/cvstd.hpp" + +namespace cv +{ + +// error codes +namespace Error { +enum { + StsOk= 0, /* everithing is ok */ + StsBackTrace= -1, /* pseudo error for back trace */ + StsError= -2, /* unknown /unspecified error */ + StsInternal= -3, /* internal error (bad state) */ + StsNoMem= -4, /* insufficient memory */ + StsBadArg= -5, /* function arg/param is bad */ + StsBadFunc= -6, /* unsupported function */ + StsNoConv= -7, /* iter. didn't converge */ + StsAutoTrace= -8, /* tracing */ + HeaderIsNull= -9, /* image header is NULL */ + BadImageSize= -10, /* image size is invalid */ + BadOffset= -11, /* offset is invalid */ + BadDataPtr= -12, /**/ + BadStep= -13, /**/ + BadModelOrChSeq= -14, /**/ + BadNumChannels= -15, /**/ + BadNumChannel1U= -16, /**/ + BadDepth= -17, /**/ + BadAlphaChannel= -18, /**/ + BadOrder= -19, /**/ + BadOrigin= -20, /**/ + BadAlign= -21, /**/ + BadCallBack= -22, /**/ + BadTileSize= -23, /**/ + BadCOI= -24, /**/ + BadROISize= -25, /**/ + MaskIsTiled= -26, /**/ + StsNullPtr= -27, /* null pointer */ + StsVecLengthErr= -28, /* incorrect vector length */ + StsFilterStructContentErr= -29, /* incorr. filter structure content */ + StsKernelStructContentErr= -30, /* incorr. transform kernel content */ + StsFilterOffsetErr= -31, /* incorrect filter ofset value */ + StsBadSize= -201, /* the input/output structure size is incorrect */ + StsDivByZero= -202, /* division by zero */ + StsInplaceNotSupported= -203, /* in-place operation is not supported */ + StsObjectNotFound= -204, /* request can't be completed */ + StsUnmatchedFormats= -205, /* formats of input/output arrays differ */ + StsBadFlag= -206, /* flag is wrong or not supported */ + StsBadPoint= -207, /* bad CvPoint */ + StsBadMask= -208, /* bad format of mask (neither 8uC1 nor 8sC1)*/ + StsUnmatchedSizes= -209, /* sizes of input/output structures do not match */ + StsUnsupportedFormat= -210, /* the data format/type is not supported by the function*/ + StsOutOfRange= -211, /* some of parameters are out of range */ + StsParseError= -212, /* invalid syntax/structure of the parsed file */ + StsNotImplemented= -213, /* the requested function/feature is not implemented */ + StsBadMemBlock= -214, /* an allocated block has been corrupted */ + StsAssert= -215, /* assertion failed */ + GpuNotSupported= -216, + GpuApiCallError= -217, + OpenGlNotSupported= -218, + OpenGlApiCallError= -219, + OpenCLApiCallError= -220 +}; +} //Error + +// matrix decomposition types +enum { DECOMP_LU = 0, + DECOMP_SVD = 1, + DECOMP_EIG = 2, + DECOMP_CHOLESKY = 3, + DECOMP_QR = 4, + DECOMP_NORMAL = 16 + }; + +// norm types +enum { NORM_INF = 1, + NORM_L1 = 2, + NORM_L2 = 4, + NORM_L2SQR = 5, + NORM_HAMMING = 6, + NORM_HAMMING2 = 7, + NORM_TYPE_MASK = 7, + NORM_RELATIVE = 8, + NORM_MINMAX = 32 + }; + +// comparison types +enum { CMP_EQ = 0, + CMP_GT = 1, + CMP_GE = 2, + CMP_LT = 3, + CMP_LE = 4, + CMP_NE = 5 + }; + +enum { GEMM_1_T = 1, + GEMM_2_T = 2, + GEMM_3_T = 4 + }; + +enum { DFT_INVERSE = 1, + DFT_SCALE = 2, + DFT_ROWS = 4, + DFT_COMPLEX_OUTPUT = 16, + DFT_REAL_OUTPUT = 32, + DCT_INVERSE = DFT_INVERSE, + DCT_ROWS = DFT_ROWS + }; + +//! Various border types, image boundaries are denoted with '|' +enum { + BORDER_CONSTANT = 0, // iiiiii|abcdefgh|iiiiiii with some specified 'i' + BORDER_REPLICATE = 1, // aaaaaa|abcdefgh|hhhhhhh + BORDER_REFLECT = 2, // fedcba|abcdefgh|hgfedcb + BORDER_WRAP = 3, // cdefgh|abcdefgh|abcdefg + BORDER_REFLECT_101 = 4, // gfedcb|abcdefgh|gfedcba + BORDER_TRANSPARENT = 5, // uvwxyz|absdefgh|ijklmno + + BORDER_REFLECT101 = BORDER_REFLECT_101, + BORDER_DEFAULT = BORDER_REFLECT_101, + BORDER_ISOLATED = 16 // do not look outside of ROI + }; + + + +//////////////// static assert ///////////////// + +#define CVAUX_CONCAT_EXP(a, b) a##b +#define CVAUX_CONCAT(a, b) CVAUX_CONCAT_EXP(a,b) + +#if defined(__clang__) +# ifndef __has_extension +# define __has_extension __has_feature /* compatibility, for older versions of clang */ +# endif +# if __has_extension(cxx_static_assert) +# define CV_StaticAssert(condition, reason) static_assert((condition), reason " " #condition) +# endif +#elif defined(__GNUC__) +# if (defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L) +# define CV_StaticAssert(condition, reason) static_assert((condition), reason " " #condition) +# endif +#elif defined(_MSC_VER) +# if _MSC_VER >= 1600 /* MSVC 10 */ +# define CV_StaticAssert(condition, reason) static_assert((condition), reason " " #condition) +# endif +#endif +#ifndef CV_StaticAssert +# if defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 2) +# define CV_StaticAssert(condition, reason) ({ extern int __attribute__((error("CV_StaticAssert: " reason " " #condition))) CV_StaticAssert(); ((condition) ? 0 : CV_StaticAssert()); }) +# else + template struct CV_StaticAssert_failed; + template <> struct CV_StaticAssert_failed { enum { val = 1 }; }; + template struct CV_StaticAssert_test {}; +# define CV_StaticAssert(condition, reason)\ + typedef cv::CV_StaticAssert_test< sizeof(cv::CV_StaticAssert_failed< static_cast(condition) >) > CVAUX_CONCAT(CV_StaticAssert_failed_at_, __LINE__) +# endif +#endif + + + +//! Signals an error and raises the exception. +/*! + By default the function prints information about the error to stderr, + then it either stops if setBreakOnError() had been called before or raises the exception. + It is possible to alternate error processing by using redirectError(). + + \param exc the exception raisen. + */ +CV_EXPORTS void error(int _code, const String& _err, const char* _func, const char* _file, int _line); + +#ifdef __GNUC__ +# define CV_Error( code, msg ) cv::error( code, msg, __func__, __FILE__, __LINE__ ) +# define CV_Error_( code, args ) cv::error( code, cv::format args, __func__, __FILE__, __LINE__ ) +# define CV_Assert( expr ) if(!!(expr)) ; else cv::error( cv::Error::StsAssert, #expr, __func__, __FILE__, __LINE__ ) +#else +# define CV_Error( code, msg ) cv::error( code, msg, "", __FILE__, __LINE__ ) +# define CV_Error_( code, args ) cv::error( code, cv::format args, "", __FILE__, __LINE__ ) +# define CV_Assert( expr ) if(!!(expr)) ; else cv::error( cv::Error::StsAssert, #expr, "", __FILE__, __LINE__ ) +#endif + +#ifdef _DEBUG +# define CV_DbgAssert(expr) CV_Assert(expr) +#else +# define CV_DbgAssert(expr) +#endif + + + +/////////////// saturate_cast (used in image & signal processing) /////////////////// + +template static inline _Tp saturate_cast(uchar v) { return _Tp(v); } +template static inline _Tp saturate_cast(schar v) { return _Tp(v); } +template static inline _Tp saturate_cast(ushort v) { return _Tp(v); } +template static inline _Tp saturate_cast(short v) { return _Tp(v); } +template static inline _Tp saturate_cast(unsigned v) { return _Tp(v); } +template static inline _Tp saturate_cast(int v) { return _Tp(v); } +template static inline _Tp saturate_cast(float v) { return _Tp(v); } +template static inline _Tp saturate_cast(double v) { return _Tp(v); } + +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); } +template<> inline uchar saturate_cast(short v) { return saturate_cast((int)v); } +template<> inline uchar saturate_cast(unsigned v) { return (uchar)std::min(v, (unsigned)UCHAR_MAX); } +template<> inline uchar saturate_cast(float v) { int iv = cvRound(v); return saturate_cast(iv); } +template<> inline uchar saturate_cast(double v) { int iv = cvRound(v); return saturate_cast(iv); } + +template<> inline schar saturate_cast(uchar v) { return (schar)std::min((int)v, SCHAR_MAX); } +template<> inline schar saturate_cast(ushort v) { return (schar)std::min((unsigned)v, (unsigned)SCHAR_MAX); } +template<> inline schar saturate_cast(int v) { return (schar)((unsigned)(v-SCHAR_MIN) <= (unsigned)UCHAR_MAX ? v : v > 0 ? SCHAR_MAX : SCHAR_MIN); } +template<> inline schar saturate_cast(short v) { return saturate_cast((int)v); } +template<> inline schar saturate_cast(unsigned v) { return (schar)std::min(v, (unsigned)SCHAR_MAX); } +template<> inline schar saturate_cast(float v) { int iv = cvRound(v); return saturate_cast(iv); } +template<> inline schar saturate_cast(double v) { int iv = cvRound(v); return saturate_cast(iv); } + +template<> inline ushort saturate_cast(schar v) { return (ushort)std::max((int)v, 0); } +template<> inline ushort saturate_cast(short v) { return (ushort)std::max((int)v, 0); } +template<> inline ushort saturate_cast(int v) { return (ushort)((unsigned)v <= (unsigned)USHRT_MAX ? v : v > 0 ? USHRT_MAX : 0); } +template<> inline ushort saturate_cast(unsigned v) { return (ushort)std::min(v, (unsigned)USHRT_MAX); } +template<> inline ushort saturate_cast(float v) { int iv = cvRound(v); return saturate_cast(iv); } +template<> inline ushort saturate_cast(double v) { int iv = cvRound(v); return saturate_cast(iv); } + +template<> inline short saturate_cast(ushort v) { return (short)std::min((int)v, SHRT_MAX); } +template<> inline short saturate_cast(int v) { return (short)((unsigned)(v - SHRT_MIN) <= (unsigned)USHRT_MAX ? v : v > 0 ? SHRT_MAX : SHRT_MIN); } +template<> inline short saturate_cast(unsigned v) { return (short)std::min(v, (unsigned)SHRT_MAX); } +template<> inline short saturate_cast(float v) { int iv = cvRound(v); return saturate_cast(iv); } +template<> inline short saturate_cast(double v) { int iv = cvRound(v); return saturate_cast(iv); } + +template<> inline int saturate_cast(float v) { return cvRound(v); } +template<> inline int saturate_cast(double v) { return cvRound(v); } + +// we intentionally do not clip negative numbers, to make -1 become 0xffffffff etc. +template<> inline unsigned saturate_cast(float v) { return cvRound(v); } +template<> inline unsigned saturate_cast(double v) { return cvRound(v); } + + + +//////////////////////////////// low-level functions //////////////////////////////// + +CV_EXPORTS int LU(float* A, size_t astep, int m, float* b, size_t bstep, int n); +CV_EXPORTS int LU(double* A, size_t astep, int m, double* b, size_t bstep, int n); +CV_EXPORTS bool Cholesky(float* A, size_t astep, int m, float* b, size_t bstep, int n); +CV_EXPORTS bool Cholesky(double* A, size_t astep, int m, double* b, size_t bstep, int n); + +CV_EXPORTS int normL1_(const uchar* a, const uchar* b, int n); +CV_EXPORTS int normHamming(const uchar* a, const uchar* b, int n); +CV_EXPORTS int normHamming(const uchar* a, const uchar* b, int n, int cellSize); +CV_EXPORTS float normL1_(const float* a, const float* b, int n); +CV_EXPORTS float normL2Sqr_(const float* a, const float* b, int n); + +CV_EXPORTS void exp(const float* src, float* dst, int n); +CV_EXPORTS void log(const float* src, float* dst, int n); +CV_EXPORTS void fastAtan2(const float* y, const float* x, float* dst, int n, bool angleInDegrees); +CV_EXPORTS void magnitude(const float* x, const float* y, float* dst, int n); + +//! computes cube root of the argument +CV_EXPORTS_W float cubeRoot(float val); +//! computes the angle in degrees (0..360) of the vector (x,y) +CV_EXPORTS_W float fastAtan2(float y, float x); + + + +/////////////////////////////////// inline norms //////////////////////////////////// + +template static inline +_AccTp normL2Sqr(const _Tp* a, int n) +{ + _AccTp s = 0; + int i=0; +#if CV_ENABLE_UNROLLED + for( ; i <= n - 4; i += 4 ) + { + _AccTp v0 = a[i], v1 = a[i+1], v2 = a[i+2], v3 = a[i+3]; + s += v0*v0 + v1*v1 + v2*v2 + v3*v3; + } +#endif + for( ; i < n; i++ ) + { + _AccTp v = a[i]; + s += v*v; + } + return s; +} + +template static inline +_AccTp normL1(const _Tp* a, int n) +{ + _AccTp s = 0; + int i = 0; +#if CV_ENABLE_UNROLLED + for(; i <= n - 4; i += 4 ) + { + s += (_AccTp)std::abs(a[i]) + (_AccTp)std::abs(a[i+1]) + + (_AccTp)std::abs(a[i+2]) + (_AccTp)std::abs(a[i+3]); + } +#endif + for( ; i < n; i++ ) + s += std::abs(a[i]); + return s; +} + +template static inline +_AccTp normInf(const _Tp* a, int n) +{ + _AccTp s = 0; + for( int i = 0; i < n; i++ ) + s = std::max(s, (_AccTp)std::abs(a[i])); + return s; +} + +template static inline +_AccTp normL2Sqr(const _Tp* a, const _Tp* b, int n) +{ + _AccTp s = 0; + int i= 0; +#if CV_ENABLE_UNROLLED + for(; i <= n - 4; i += 4 ) + { + _AccTp v0 = _AccTp(a[i] - b[i]), v1 = _AccTp(a[i+1] - b[i+1]), v2 = _AccTp(a[i+2] - b[i+2]), v3 = _AccTp(a[i+3] - b[i+3]); + s += v0*v0 + v1*v1 + v2*v2 + v3*v3; + } +#endif + for( ; i < n; i++ ) + { + _AccTp v = _AccTp(a[i] - b[i]); + s += v*v; + } + return s; +} + +template<> inline +float normL2Sqr(const float* a, const float* b, int n) +{ + if( n >= 8 ) + return normL2Sqr_(a, b, n); + float s = 0; + for( int i = 0; i < n; i++ ) + { + float v = a[i] - b[i]; + s += v*v; + } + return s; +} + +template static inline +_AccTp normL1(const _Tp* a, const _Tp* b, int n) +{ + _AccTp s = 0; + int i= 0; +#if CV_ENABLE_UNROLLED + for(; i <= n - 4; i += 4 ) + { + _AccTp v0 = _AccTp(a[i] - b[i]), v1 = _AccTp(a[i+1] - b[i+1]), v2 = _AccTp(a[i+2] - b[i+2]), v3 = _AccTp(a[i+3] - b[i+3]); + s += std::abs(v0) + std::abs(v1) + std::abs(v2) + std::abs(v3); + } +#endif + for( ; i < n; i++ ) + { + _AccTp v = _AccTp(a[i] - b[i]); + s += std::abs(v); + } + return s; +} + +template<> inline +float normL1(const float* a, const float* b, int n) +{ + if( n >= 8 ) + return normL1_(a, b, n); + float s = 0; + for( int i = 0; i < n; i++ ) + { + float v = a[i] - b[i]; + s += std::abs(v); + } + return s; +} + +template<> inline +int normL1(const uchar* a, const uchar* b, int n) +{ + return normL1_(a, b, n); +} + +template static inline +_AccTp normInf(const _Tp* a, const _Tp* b, int n) +{ + _AccTp s = 0; + for( int i = 0; i < n; i++ ) + { + _AccTp v0 = a[i] - b[i]; + s = std::max(s, std::abs(v0)); + } + return s; +} + + + +////////////////// forward declarations for important OpenCV types ////////////////// + +template class Vec; +template class Matx; + +template class Complex; +template class Point_; +template class Point3_; +template class Size_; +template class Rect_; +template class Scalar_; + +class CV_EXPORTS RotatedRect; +class CV_EXPORTS Range; +class CV_EXPORTS TermCriteria; +class CV_EXPORTS KeyPoint; +class CV_EXPORTS DMatch; +class CV_EXPORTS RNG; + +class CV_EXPORTS Mat; +class CV_EXPORTS MatExpr; + +class CV_EXPORTS SparseMat; +typedef Mat MatND; + +template class Mat_; +template class SparseMat_; + +class CV_EXPORTS MatConstIterator; +class CV_EXPORTS SparseMatIterator; +class CV_EXPORTS SparseMatConstIterator; +template class MatIterator_; +template class MatConstIterator_; +template class SparseMatIterator_; +template class SparseMatConstIterator_; + +namespace ogl +{ + class CV_EXPORTS Buffer; + class CV_EXPORTS Texture2D; + class CV_EXPORTS Arrays; +} + +namespace gpu +{ + class CV_EXPORTS GpuMat; + class CV_EXPORTS CudaMem; + class CV_EXPORTS Stream; + class CV_EXPORTS Event; +} + +namespace cudev +{ + template class GpuMat_; +} + +} // cv + +#endif //__OPENCV_CORE_BASE_HPP__ diff --git a/modules/core/include/opencv2/core/core.hpp b/modules/core/include/opencv2/core/core.hpp index 5ceb8ff96c..438918359b 100644 --- a/modules/core/include/opencv2/core/core.hpp +++ b/modules/core/include/opencv2/core/core.hpp @@ -45,4 +45,4 @@ #error this is a compatibility header which should not be used inside the OpenCV library #endif -#include "opencv2/core.hpp" \ No newline at end of file +#include "opencv2/core.hpp" diff --git a/modules/core/include/opencv2/core/core_c.h b/modules/core/include/opencv2/core/core_c.h index df763ab9a4..ca8413ee23 100644 --- a/modules/core/include/opencv2/core/core_c.h +++ b/modules/core/include/opencv2/core/core_c.h @@ -7,11 +7,12 @@ // copy or use the software. // // -// License Agreement +// License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -46,6 +47,20 @@ #include "opencv2/core/types_c.h" +#ifdef __cplusplus +# ifdef _MSC_VER +/* disable warning C4190: 'function' has C-linkage specified, but returns UDT 'typename' + which is incompatible with C + + It is OK to disable it because we only extend few plain structures with + C++ construrtors for simpler interoperability with C++ API of the library +*/ +# pragma warning(disable:4190) +# elif defined __clang__ && __clang_major__ >= 3 +# pragma GCC diagnostic ignored "-Wreturn-type-c-linkage" +# endif +#endif + #ifdef __cplusplus extern "C" { #endif @@ -1478,27 +1493,9 @@ CVAPI(int) cvKMeans2( const CvArr* samples, int cluster_count, CvArr* labels, * System functions * \****************************************************************************************/ -/* Add the function pointers table with associated information to the IPP primitives list */ -CVAPI(int) cvRegisterModule( const CvModuleInfo* module_info ); - /* Loads optimized functions from IPP, MKL etc. or switches back to pure C code */ CVAPI(int) cvUseOptimized( int on_off ); -/* Retrieves information about the registered modules and loaded optimized plugins */ -CVAPI(void) cvGetModuleInfo( const char* module_name, - const char** version, - const char** loaded_addon_plugins ); - -typedef void* (CV_CDECL *CvAllocFunc)(size_t size, void* userdata); -typedef int (CV_CDECL *CvFreeFunc)(void* pptr, void* userdata); - -/* Set user-defined memory managment functions (substitutors for malloc and free) that - will be called by cvAlloc, cvFree and higher-level functions (e.g. cvCreateImage) */ -CVAPI(void) cvSetMemoryManager( CvAllocFunc alloc_func CV_DEFAULT(NULL), - CvFreeFunc free_func CV_DEFAULT(NULL), - void* userdata CV_DEFAULT(NULL)); - - typedef IplImage* (CV_STDCALL* Cv_iplCreateImageHeader) (int,int,int,char*,char*,int,int,int,int,int, IplROI*,IplImage*,void*,IplTileInfo*); @@ -1696,18 +1693,6 @@ CVAPI(double) cvGetTickFrequency( void ); /*********************************** CPU capabilities ***********************************/ -#define CV_CPU_NONE 0 -#define CV_CPU_MMX 1 -#define CV_CPU_SSE 2 -#define CV_CPU_SSE2 3 -#define CV_CPU_SSE3 4 -#define CV_CPU_SSSE3 5 -#define CV_CPU_SSE4_1 6 -#define CV_CPU_SSE4_2 7 -#define CV_CPU_POPCNT 8 -#define CV_CPU_AVX 10 -#define CV_HARDWARE_MAX_FEATURE 255 - CVAPI(int) cvCheckHardwareSupport(int feature); /*********************************** Multi-Threading ************************************/ @@ -1855,19 +1840,11 @@ static char cvFuncName[] = Name #define __CV_EXIT__ goto exit #ifdef __cplusplus -} - -// classes for automatic module/RTTI data registration/unregistration -struct CV_EXPORTS CvModule -{ - CvModule( CvModuleInfo* _info ); - ~CvModule(); - CvModuleInfo* info; - - static CvModuleInfo* first; - static CvModuleInfo* last; -}; +} // extern "C" +#endif +#ifdef __cplusplus +// class for automatic module/RTTI data registration/unregistration struct CV_EXPORTS CvType { CvType( const char* type_name, @@ -1880,6 +1857,396 @@ struct CV_EXPORTS CvType static CvTypeInfo* last; }; +#include "opencv2/core/utility.hpp" + +namespace cv +{ + +/////////////////////////////////////////// glue /////////////////////////////////////////// + +//! converts array (CvMat or IplImage) to cv::Mat +CV_EXPORTS Mat cvarrToMat(const CvArr* arr, bool copyData=false, + bool allowND=true, int coiMode=0, + AutoBuffer* buf=0); + +static inline Mat cvarrToMatND(const CvArr* arr, bool copyData=false, int coiMode=0) +{ + return cvarrToMat(arr, copyData, true, coiMode); +} + + +//! extracts Channel of Interest from CvMat or IplImage and makes cv::Mat out of it. +CV_EXPORTS void extractImageCOI(const CvArr* arr, OutputArray coiimg, int coi=-1); +//! inserts single-channel cv::Mat into a multi-channel CvMat or IplImage +CV_EXPORTS void insertImageCOI(InputArray coiimg, CvArr* arr, int coi=-1); + + + +////// specialized implementations of DefaultDeleter::operator() for classic OpenCV types ////// + +template<> CV_EXPORTS void DefaultDeleter::operator ()(CvMat* obj) const; +template<> CV_EXPORTS void DefaultDeleter::operator ()(IplImage* obj) const; +template<> CV_EXPORTS void DefaultDeleter::operator ()(CvMatND* obj) const; +template<> CV_EXPORTS void DefaultDeleter::operator ()(CvSparseMat* obj) const; +template<> CV_EXPORTS void DefaultDeleter::operator ()(CvMemStorage* obj) const; + +////////////// convenient wrappers for operating old-style dynamic structures ////////////// + +template class SeqIterator; + +typedef Ptr MemStorage; + +/*! + Template Sequence Class derived from CvSeq + + The class provides more convenient access to sequence elements, + STL-style operations and iterators. + + \note The class is targeted for simple data types, + i.e. no constructors or destructors + are called for the sequence elements. +*/ +template class Seq +{ +public: + typedef SeqIterator<_Tp> iterator; + typedef SeqIterator<_Tp> const_iterator; + + //! the default constructor + Seq(); + //! the constructor for wrapping CvSeq structure. The real element type in CvSeq should match _Tp. + Seq(const CvSeq* seq); + //! creates the empty sequence that resides in the specified storage + Seq(MemStorage& storage, int headerSize = sizeof(CvSeq)); + //! returns read-write reference to the specified element + _Tp& operator [](int idx); + //! returns read-only reference to the specified element + const _Tp& operator[](int idx) const; + //! returns iterator pointing to the beginning of the sequence + SeqIterator<_Tp> begin() const; + //! returns iterator pointing to the element following the last sequence element + SeqIterator<_Tp> end() const; + //! returns the number of elements in the sequence + size_t size() const; + //! returns the type of sequence elements (CV_8UC1 ... CV_64FC(CV_CN_MAX) ...) + int type() const; + //! returns the depth of sequence elements (CV_8U ... CV_64F) + int depth() const; + //! returns the number of channels in each sequence element + int channels() const; + //! returns the size of each sequence element + size_t elemSize() const; + //! returns index of the specified sequence element + size_t index(const _Tp& elem) const; + //! appends the specified element to the end of the sequence + void push_back(const _Tp& elem); + //! appends the specified element to the front of the sequence + void push_front(const _Tp& elem); + //! appends zero or more elements to the end of the sequence + void push_back(const _Tp* elems, size_t count); + //! appends zero or more elements to the front of the sequence + void push_front(const _Tp* elems, size_t count); + //! inserts the specified element to the specified position + void insert(int idx, const _Tp& elem); + //! inserts zero or more elements to the specified position + void insert(int idx, const _Tp* elems, size_t count); + //! removes element at the specified position + void remove(int idx); + //! removes the specified subsequence + void remove(const Range& r); + + //! returns reference to the first sequence element + _Tp& front(); + //! returns read-only reference to the first sequence element + const _Tp& front() const; + //! returns reference to the last sequence element + _Tp& back(); + //! returns read-only reference to the last sequence element + const _Tp& back() const; + //! returns true iff the sequence contains no elements + bool empty() const; + + //! removes all the elements from the sequence + void clear(); + //! removes the first element from the sequence + void pop_front(); + //! removes the last element from the sequence + void pop_back(); + //! removes zero or more elements from the beginning of the sequence + void pop_front(_Tp* elems, size_t count); + //! removes zero or more elements from the end of the sequence + void pop_back(_Tp* elems, size_t count); + + //! copies the whole sequence or the sequence slice to the specified vector + void copyTo(std::vector<_Tp>& vec, const Range& range=Range::all()) const; + //! returns the vector containing all the sequence elements + operator std::vector<_Tp>() const; + + CvSeq* seq; +}; + + +/*! + STL-style Sequence Iterator inherited from the CvSeqReader structure +*/ +template class SeqIterator : public CvSeqReader +{ +public: + //! the default constructor + SeqIterator(); + //! the constructor setting the iterator to the beginning or to the end of the sequence + SeqIterator(const Seq<_Tp>& seq, bool seekEnd=false); + //! positions the iterator within the sequence + void seek(size_t pos); + //! reports the current iterator position + size_t tell() const; + //! returns reference to the current sequence element + _Tp& operator *(); + //! returns read-only reference to the current sequence element + const _Tp& operator *() const; + //! moves iterator to the next sequence element + SeqIterator& operator ++(); + //! moves iterator to the next sequence element + SeqIterator operator ++(int) const; + //! moves iterator to the previous sequence element + SeqIterator& operator --(); + //! moves iterator to the previous sequence element + SeqIterator operator --(int) const; + + //! moves iterator forward by the specified offset (possibly negative) + SeqIterator& operator +=(int); + //! moves iterator backward by the specified offset (possibly negative) + SeqIterator& operator -=(int); + + // this is index of the current element module seq->total*2 + // (to distinguish between 0 and seq->total) + int index; +}; + + + +// bridge C++ => C Seq API +CV_EXPORTS schar* seqPush( CvSeq* seq, const void* element=0); +CV_EXPORTS schar* seqPushFront( CvSeq* seq, const void* element=0); +CV_EXPORTS void seqPop( CvSeq* seq, void* element=0); +CV_EXPORTS void seqPopFront( CvSeq* seq, void* element=0); +CV_EXPORTS void seqPopMulti( CvSeq* seq, void* elements, + int count, int in_front=0 ); +CV_EXPORTS void seqRemove( CvSeq* seq, int index ); +CV_EXPORTS void clearSeq( CvSeq* seq ); +CV_EXPORTS schar* getSeqElem( const CvSeq* seq, int index ); +CV_EXPORTS void seqRemoveSlice( CvSeq* seq, CvSlice slice ); +CV_EXPORTS void seqInsertSlice( CvSeq* seq, int before_index, const CvArr* from_arr ); + +template inline Seq<_Tp>::Seq() : seq(0) {} +template inline Seq<_Tp>::Seq( const CvSeq* _seq ) : seq((CvSeq*)_seq) +{ + CV_Assert(!_seq || _seq->elem_size == sizeof(_Tp)); +} + +template inline Seq<_Tp>::Seq( MemStorage& storage, + int headerSize ) +{ + CV_Assert(headerSize >= (int)sizeof(CvSeq)); + seq = cvCreateSeq(DataType<_Tp>::type, headerSize, sizeof(_Tp), storage); +} + +template inline _Tp& Seq<_Tp>::operator [](int idx) +{ return *(_Tp*)getSeqElem(seq, idx); } + +template inline const _Tp& Seq<_Tp>::operator [](int idx) const +{ return *(_Tp*)getSeqElem(seq, idx); } + +template inline SeqIterator<_Tp> Seq<_Tp>::begin() const +{ return SeqIterator<_Tp>(*this); } + +template inline SeqIterator<_Tp> Seq<_Tp>::end() const +{ return SeqIterator<_Tp>(*this, true); } + +template inline size_t Seq<_Tp>::size() const +{ return seq ? seq->total : 0; } + +template inline int Seq<_Tp>::type() const +{ return seq ? CV_MAT_TYPE(seq->flags) : 0; } + +template inline int Seq<_Tp>::depth() const +{ return seq ? CV_MAT_DEPTH(seq->flags) : 0; } + +template inline int Seq<_Tp>::channels() const +{ return seq ? CV_MAT_CN(seq->flags) : 0; } + +template inline size_t Seq<_Tp>::elemSize() const +{ return seq ? seq->elem_size : 0; } + +template inline size_t Seq<_Tp>::index(const _Tp& elem) const +{ return cvSeqElemIdx(seq, &elem); } + +template inline void Seq<_Tp>::push_back(const _Tp& elem) +{ cvSeqPush(seq, &elem); } + +template inline void Seq<_Tp>::push_front(const _Tp& elem) +{ cvSeqPushFront(seq, &elem); } + +template inline void Seq<_Tp>::push_back(const _Tp* elem, size_t count) +{ cvSeqPushMulti(seq, elem, (int)count, 0); } + +template inline void Seq<_Tp>::push_front(const _Tp* elem, size_t count) +{ cvSeqPushMulti(seq, elem, (int)count, 1); } + +template inline _Tp& Seq<_Tp>::back() +{ return *(_Tp*)getSeqElem(seq, -1); } + +template inline const _Tp& Seq<_Tp>::back() const +{ return *(const _Tp*)getSeqElem(seq, -1); } + +template inline _Tp& Seq<_Tp>::front() +{ return *(_Tp*)getSeqElem(seq, 0); } + +template inline const _Tp& Seq<_Tp>::front() const +{ return *(const _Tp*)getSeqElem(seq, 0); } + +template inline bool Seq<_Tp>::empty() const +{ return !seq || seq->total == 0; } + +template inline void Seq<_Tp>::clear() +{ if(seq) clearSeq(seq); } + +template inline void Seq<_Tp>::pop_back() +{ seqPop(seq); } + +template inline void Seq<_Tp>::pop_front() +{ seqPopFront(seq); } + +template inline void Seq<_Tp>::pop_back(_Tp* elem, size_t count) +{ seqPopMulti(seq, elem, (int)count, 0); } + +template inline void Seq<_Tp>::pop_front(_Tp* elem, size_t count) +{ seqPopMulti(seq, elem, (int)count, 1); } + +template inline void Seq<_Tp>::insert(int idx, const _Tp& elem) +{ seqInsert(seq, idx, &elem); } + +template inline void Seq<_Tp>::insert(int idx, const _Tp* elems, size_t count) +{ + CvMat m = cvMat(1, count, DataType<_Tp>::type, elems); + seqInsertSlice(seq, idx, &m); +} + +template inline void Seq<_Tp>::remove(int idx) +{ seqRemove(seq, idx); } + +template inline void Seq<_Tp>::remove(const Range& r) +{ seqRemoveSlice(seq, cvSlice(r.start, r.end)); } + +template inline void Seq<_Tp>::copyTo(std::vector<_Tp>& vec, const Range& range) const +{ + size_t len = !seq ? 0 : range == Range::all() ? seq->total : range.end - range.start; + vec.resize(len); + if( seq && len ) + cvCvtSeqToArray(seq, &vec[0], range); +} + +template inline Seq<_Tp>::operator std::vector<_Tp>() const +{ + std::vector<_Tp> vec; + copyTo(vec); + return vec; +} + +template inline SeqIterator<_Tp>::SeqIterator() +{ memset(this, 0, sizeof(*this)); } + +template inline SeqIterator<_Tp>::SeqIterator(const Seq<_Tp>& _seq, bool seekEnd) +{ + cvStartReadSeq(_seq.seq, this); + index = seekEnd ? _seq.seq->total : 0; +} + +template inline void SeqIterator<_Tp>::seek(size_t pos) +{ + cvSetSeqReaderPos(this, (int)pos, false); + index = pos; +} + +template inline size_t SeqIterator<_Tp>::tell() const +{ return index; } + +template inline _Tp& SeqIterator<_Tp>::operator *() +{ return *(_Tp*)ptr; } + +template inline const _Tp& SeqIterator<_Tp>::operator *() const +{ return *(const _Tp*)ptr; } + +template inline SeqIterator<_Tp>& SeqIterator<_Tp>::operator ++() +{ + CV_NEXT_SEQ_ELEM(sizeof(_Tp), *this); + if( ++index >= seq->total*2 ) + index = 0; + return *this; +} + +template inline SeqIterator<_Tp> SeqIterator<_Tp>::operator ++(int) const +{ + SeqIterator<_Tp> it = *this; + ++*this; + return it; +} + +template inline SeqIterator<_Tp>& SeqIterator<_Tp>::operator --() +{ + CV_PREV_SEQ_ELEM(sizeof(_Tp), *this); + if( --index < 0 ) + index = seq->total*2-1; + return *this; +} + +template inline SeqIterator<_Tp> SeqIterator<_Tp>::operator --(int) const +{ + SeqIterator<_Tp> it = *this; + --*this; + return it; +} + +template inline SeqIterator<_Tp>& SeqIterator<_Tp>::operator +=(int delta) +{ + cvSetSeqReaderPos(this, delta, 1); + index += delta; + int n = seq->total*2; + if( index < 0 ) + index += n; + if( index >= n ) + index -= n; + return *this; +} + +template inline SeqIterator<_Tp>& SeqIterator<_Tp>::operator -=(int delta) +{ + return (*this += -delta); +} + +template inline ptrdiff_t operator - (const SeqIterator<_Tp>& a, + const SeqIterator<_Tp>& b) +{ + ptrdiff_t delta = a.index - b.index, n = a.seq->total; + if( delta > n || delta < -n ) + delta += delta < 0 ? n : -n; + return delta; +} + +template inline bool operator == (const SeqIterator<_Tp>& a, + const SeqIterator<_Tp>& b) +{ + return a.seq == b.seq && a.index == b.index; +} + +template inline bool operator != (const SeqIterator<_Tp>& a, + const SeqIterator<_Tp>& b) +{ + return !(a == b); +} + +} // cv + #endif #endif diff --git a/modules/gpu/include/opencv2/gpu/device/block.hpp b/modules/core/include/opencv2/core/cuda/block.hpp similarity index 99% rename from modules/gpu/include/opencv2/gpu/device/block.hpp rename to modules/core/include/opencv2/core/cuda/block.hpp index 86ce205bc7..04bfdba714 100644 --- a/modules/gpu/include/opencv2/gpu/device/block.hpp +++ b/modules/core/include/opencv2/core/cuda/block.hpp @@ -43,7 +43,7 @@ #ifndef __OPENCV_GPU_DEVICE_BLOCK_HPP__ #define __OPENCV_GPU_DEVICE_BLOCK_HPP__ -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { struct Block { @@ -201,5 +201,3 @@ namespace cv { namespace gpu { namespace device }}} #endif /* __OPENCV_GPU_DEVICE_BLOCK_HPP__ */ - - diff --git a/modules/gpu/include/opencv2/gpu/device/border_interpolate.hpp b/modules/core/include/opencv2/core/cuda/border_interpolate.hpp similarity index 96% rename from modules/gpu/include/opencv2/gpu/device/border_interpolate.hpp rename to modules/core/include/opencv2/core/cuda/border_interpolate.hpp index 2343ccab2a..6c53f09eee 100644 --- a/modules/gpu/include/opencv2/gpu/device/border_interpolate.hpp +++ b/modules/core/include/opencv2/core/cuda/border_interpolate.hpp @@ -28,7 +28,7 @@ // 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 bpied warranties, including, but not limited to, the bpied +// 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 @@ -47,7 +47,7 @@ #include "vec_traits.hpp" #include "vec_math.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { ////////////////////////////////////////////////////////////// // BrdConstant @@ -73,8 +73,8 @@ namespace cv { namespace gpu { namespace device return (x >= 0 && x < width) ? saturate_cast(data[x]) : val; } - const int width; - const D val; + int width; + D val; }; template struct BrdColConstant @@ -98,8 +98,8 @@ namespace cv { namespace gpu { namespace device return (y >= 0 && y < height) ? saturate_cast(*(const T*)((const char*)data + y * step)) : val; } - const int height; - const D val; + int height; + D val; }; template struct BrdConstant @@ -120,9 +120,9 @@ namespace cv { namespace gpu { namespace device return (x >= 0 && x < width && y >= 0 && y < height) ? saturate_cast(src(y, x)) : val; } - const int height; - const int width; - const D val; + int height; + int width; + D val; }; ////////////////////////////////////////////////////////////// @@ -165,7 +165,7 @@ namespace cv { namespace gpu { namespace device return saturate_cast(data[idx_col(x)]); } - const int last_col; + int last_col; }; template struct BrdColReplicate @@ -205,7 +205,7 @@ namespace cv { namespace gpu { namespace device return saturate_cast(*(const T*)((const char*)data + idx_row(y) * step)); } - const int last_row; + int last_row; }; template struct BrdReplicate @@ -255,8 +255,8 @@ namespace cv { namespace gpu { namespace device return saturate_cast(src(idx_row(y), idx_col(x))); } - const int last_row; - const int last_col; + int last_row; + int last_col; }; ////////////////////////////////////////////////////////////// @@ -299,7 +299,7 @@ namespace cv { namespace gpu { namespace device return saturate_cast(data[idx_col(x)]); } - const int last_col; + int last_col; }; template struct BrdColReflect101 @@ -339,7 +339,7 @@ namespace cv { namespace gpu { namespace device return saturate_cast(*(const D*)((const char*)data + idx_row(y) * step)); } - const int last_row; + int last_row; }; template struct BrdReflect101 @@ -389,8 +389,8 @@ namespace cv { namespace gpu { namespace device return saturate_cast(src(idx_row(y), idx_col(x))); } - const int last_row; - const int last_col; + int last_row; + int last_col; }; ////////////////////////////////////////////////////////////// @@ -433,7 +433,7 @@ namespace cv { namespace gpu { namespace device return saturate_cast(data[idx_col(x)]); } - const int last_col; + int last_col; }; template struct BrdColReflect @@ -473,7 +473,7 @@ namespace cv { namespace gpu { namespace device return saturate_cast(*(const D*)((const char*)data + idx_row(y) * step)); } - const int last_row; + int last_row; }; template struct BrdReflect @@ -523,8 +523,8 @@ namespace cv { namespace gpu { namespace device return saturate_cast(src(idx_row(y), idx_col(x))); } - const int last_row; - const int last_col; + int last_row; + int last_col; }; ////////////////////////////////////////////////////////////// @@ -567,7 +567,7 @@ namespace cv { namespace gpu { namespace device return saturate_cast(data[idx_col(x)]); } - const int width; + int width; }; template struct BrdColWrap @@ -607,7 +607,7 @@ namespace cv { namespace gpu { namespace device return saturate_cast(*(const D*)((const char*)data + idx_row(y) * step)); } - const int height; + int height; }; template struct BrdWrap @@ -664,8 +664,8 @@ namespace cv { namespace gpu { namespace device return saturate_cast(src(idx_row(y), idx_col(x))); } - const int height; - const int width; + int height; + int width; }; ////////////////////////////////////////////////////////////// @@ -683,8 +683,8 @@ namespace cv { namespace gpu { namespace device return b.at(y, x, ptr); } - const Ptr2D ptr; - const B b; + Ptr2D ptr; + B b; }; // under win32 there is some bug with templated types that passed as kernel parameters @@ -704,11 +704,11 @@ namespace cv { namespace gpu { namespace device return (x >= 0 && x < width && y >= 0 && y < height) ? saturate_cast(src(y, x)) : val; } - const Ptr2D src; - const int height; - const int width; - const D val; + Ptr2D src; + int height; + int width; + D val; }; -}}} // namespace cv { namespace gpu { namespace device +}}} // namespace cv { namespace gpu { namespace cudev #endif // __OPENCV_GPU_BORDER_INTERPOLATE_HPP__ diff --git a/modules/gpu/include/opencv2/gpu/device/color.hpp b/modules/core/include/opencv2/core/cuda/color.hpp similarity index 92% rename from modules/gpu/include/opencv2/gpu/device/color.hpp rename to modules/core/include/opencv2/core/cuda/color.hpp index 53d3d6b086..d5f94c92a4 100644 --- a/modules/gpu/include/opencv2/gpu/device/color.hpp +++ b/modules/core/include/opencv2/core/cuda/color.hpp @@ -28,7 +28,7 @@ // 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 bpied warranties, including, but not limited to, the bpied +// 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 @@ -45,7 +45,7 @@ #include "detail/color_detail.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { // All OPENCV_GPU_IMPLEMENT_*_TRAITS(ColorSpace1_to_ColorSpace2, ...) macros implements // template class ColorSpace1_to_ColorSpace2_traits @@ -107,25 +107,25 @@ namespace cv { namespace gpu { namespace device #undef OPENCV_GPU_IMPLEMENT_RGB2GRAY_TRAITS - OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(rgb_to_yuv, 3, 3, 0) - OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(rgba_to_yuv, 4, 3, 0) - OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(rgb_to_yuv4, 3, 4, 0) - OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(rgba_to_yuv4, 4, 4, 0) - OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(bgr_to_yuv, 3, 3, 2) - OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(bgra_to_yuv, 4, 3, 2) - OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(bgr_to_yuv4, 3, 4, 2) - OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(bgra_to_yuv4, 4, 4, 2) + OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(rgb_to_yuv, 3, 3, 2) + OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(rgba_to_yuv, 4, 3, 2) + OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(rgb_to_yuv4, 3, 4, 2) + OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(rgba_to_yuv4, 4, 4, 2) + OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(bgr_to_yuv, 3, 3, 0) + OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(bgra_to_yuv, 4, 3, 0) + OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(bgr_to_yuv4, 3, 4, 0) + OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(bgra_to_yuv4, 4, 4, 0) #undef OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS - OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv_to_rgb, 3, 3, 0) - OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv_to_rgba, 3, 4, 0) - OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv4_to_rgb, 4, 3, 0) - OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv4_to_rgba, 4, 4, 0) - OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv_to_bgr, 3, 3, 2) - OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv_to_bgra, 3, 4, 2) - OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv4_to_bgr, 4, 3, 2) - OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv4_to_bgra, 4, 4, 2) + OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv_to_rgb, 3, 3, 2) + OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv_to_rgba, 3, 4, 2) + OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv4_to_rgb, 4, 3, 2) + OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv4_to_rgba, 4, 4, 2) + OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv_to_bgr, 3, 3, 0) + OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv_to_bgra, 3, 4, 0) + OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv4_to_bgr, 4, 3, 0) + OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv4_to_bgra, 4, 4, 0) #undef OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS @@ -296,6 +296,6 @@ namespace cv { namespace gpu { namespace device OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(luv4_to_lbgra, 4, 4, false, 0) #undef OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS -}}} // namespace cv { namespace gpu { namespace device +}}} // namespace cv { namespace gpu { namespace cudev #endif // __OPENCV_GPU_BORDER_INTERPOLATE_HPP__ diff --git a/modules/gpu/include/opencv2/gpu/device/common.hpp b/modules/core/include/opencv2/core/cuda/common.hpp similarity index 74% rename from modules/gpu/include/opencv2/gpu/device/common.hpp rename to modules/core/include/opencv2/core/cuda/common.hpp index 64d82c83b0..6b3fef19a4 100644 --- a/modules/gpu/include/opencv2/gpu/device/common.hpp +++ b/modules/core/include/opencv2/core/cuda/common.hpp @@ -44,11 +44,9 @@ #define __OPENCV_GPU_COMMON_HPP__ #include -#include "opencv2/core/cuda_devptrs.hpp" - -#ifndef CV_PI - #define CV_PI 3.1415926535897932384626433832795 -#endif +#include "opencv2/core/gpu_types.hpp" +#include "opencv2/core/cvdef.h" +#include "opencv2/core/base.hpp" #ifndef CV_PI_F #ifndef CV_PI @@ -58,16 +56,24 @@ #endif #endif -#if defined(__GNUC__) - #define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__, __func__) -#else /* defined(__CUDACC__) || defined(__MSVC__) */ - #define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__) +namespace cv { namespace gpu { + static inline void checkCudaError(cudaError_t err, const char* file, const int line, const char* func) + { + if (cudaSuccess != err) + cv::error(cv::Error::GpuApiCallError, cudaGetErrorString(err), func, file, line); + } +}} + +#ifndef cudaSafeCall + #if defined(__GNUC__) + #define cudaSafeCall(expr) cv::gpu::checkCudaError(expr, __FILE__, __LINE__, __func__) + #else /* defined(__CUDACC__) || defined(__MSVC__) */ + #define cudaSafeCall(expr) cv::gpu::checkCudaError(expr, __FILE__, __LINE__, "") + #endif #endif namespace cv { namespace gpu { - void error(const char *error_string, const char *file, const int line, const char *func); - template static inline bool isAligned(const T* ptr, size_t size) { return reinterpret_cast(ptr) % size == 0; @@ -79,37 +85,20 @@ namespace cv { namespace gpu } }} -static inline void ___cudaSafeCall(cudaError_t err, const char *file, const int line, const char *func = "") -{ - if (cudaSuccess != err) - cv::gpu::error(cudaGetErrorString(err), file, line, func); -} - namespace cv { namespace gpu { - __host__ __device__ __forceinline__ int divUp(int total, int grain) + namespace cudev { - return (total + grain - 1) / grain; - } - - namespace device - { - using cv::gpu::divUp; - -#ifdef __CUDACC__ - typedef unsigned char uchar; - typedef unsigned short ushort; - typedef signed char schar; - #if defined (_WIN32) || defined (__APPLE__) - typedef unsigned int uint; - #endif + __host__ __device__ __forceinline__ int divUp(int total, int grain) + { + return (total + grain - 1) / grain; + } template inline void bindTexture(const textureReference* tex, const PtrStepSz& img) { cudaChannelFormatDesc desc = cudaCreateChannelDesc(); cudaSafeCall( cudaBindTexture2D(0, tex, img.ptr(), &desc, img.cols, img.rows, img.step) ); } -#endif // __CUDACC__ } }} diff --git a/modules/gpu/include/opencv2/gpu/device/datamov_utils.hpp b/modules/core/include/opencv2/core/cuda/datamov_utils.hpp similarity index 96% rename from modules/gpu/include/opencv2/gpu/device/datamov_utils.hpp rename to modules/core/include/opencv2/core/cuda/datamov_utils.hpp index e05a22477c..10df540936 100644 --- a/modules/gpu/include/opencv2/gpu/device/datamov_utils.hpp +++ b/modules/core/include/opencv2/core/cuda/datamov_utils.hpp @@ -28,7 +28,7 @@ // 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 bpied warranties, including, but not limited to, the bpied +// 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 @@ -45,7 +45,7 @@ #include "common.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { #if defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 200 @@ -100,6 +100,6 @@ namespace cv { namespace gpu { namespace device #undef OPENCV_GPU_ASM_PTR #endif // __CUDA_ARCH__ >= 200 -}}} // namespace cv { namespace gpu { namespace device +}}} // namespace cv { namespace gpu { namespace cudev #endif // __OPENCV_GPU_DATAMOV_UTILS_HPP__ diff --git a/modules/gpu/include/opencv2/gpu/device/detail/color_detail.hpp b/modules/core/include/opencv2/core/cuda/detail/color_detail.hpp similarity index 94% rename from modules/gpu/include/opencv2/gpu/device/detail/color_detail.hpp rename to modules/core/include/opencv2/core/cuda/detail/color_detail.hpp index 0d9c08620d..a0a673410a 100644 --- a/modules/gpu/include/opencv2/gpu/device/detail/color_detail.hpp +++ b/modules/core/include/opencv2/core/cuda/detail/color_detail.hpp @@ -28,7 +28,7 @@ // 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 bpied warranties, including, but not limited to, the bpied +// 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 @@ -49,7 +49,7 @@ #include "../limits.hpp" #include "../functional.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { #ifndef CV_DESCALE #define CV_DESCALE(x, n) (((x) + (1 << ((n)-1))) >> (n)) @@ -120,11 +120,8 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ RGB2RGB() - : unary_function::vec_type, typename TypeVec::vec_type>(){} - - __device__ __forceinline__ RGB2RGB(const RGB2RGB& other_) - :unary_function::vec_type, typename TypeVec::vec_type>(){} + __host__ __device__ __forceinline__ RGB2RGB() {} + __host__ __device__ __forceinline__ RGB2RGB(const RGB2RGB&) {} }; template <> struct RGB2RGB : unary_function @@ -141,15 +138,15 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ RGB2RGB():unary_function(){} - __device__ __forceinline__ RGB2RGB(const RGB2RGB& other_):unary_function(){} + __host__ __device__ __forceinline__ RGB2RGB() {} + __host__ __device__ __forceinline__ RGB2RGB(const RGB2RGB&) {} }; } #define OPENCV_GPU_IMPLEMENT_RGB2RGB_TRAITS(name, scn, dcn, bidx) \ template struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB2RGB functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB2RGB functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -203,8 +200,8 @@ namespace cv { namespace gpu { namespace device return RGB2RGB5x5Converter::cvt(src); } - __device__ __forceinline__ RGB2RGB5x5():unary_function(){} - __device__ __forceinline__ RGB2RGB5x5(const RGB2RGB5x5& other_):unary_function(){} + __host__ __device__ __forceinline__ RGB2RGB5x5() {} + __host__ __device__ __forceinline__ RGB2RGB5x5(const RGB2RGB5x5&) {} }; template struct RGB2RGB5x5<4, bidx,green_bits> : unary_function @@ -214,15 +211,15 @@ namespace cv { namespace gpu { namespace device return RGB2RGB5x5Converter::cvt(src); } - __device__ __forceinline__ RGB2RGB5x5():unary_function(){} - __device__ __forceinline__ RGB2RGB5x5(const RGB2RGB5x5& other_):unary_function(){} + __host__ __device__ __forceinline__ RGB2RGB5x5() {} + __host__ __device__ __forceinline__ RGB2RGB5x5(const RGB2RGB5x5&) {} }; } #define OPENCV_GPU_IMPLEMENT_RGB2RGB5x5_TRAITS(name, scn, bidx, green_bits) \ struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB2RGB5x5 functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB2RGB5x5 functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -282,8 +279,8 @@ namespace cv { namespace gpu { namespace device RGB5x52RGBConverter::cvt(src, dst); return dst; } - __device__ __forceinline__ RGB5x52RGB():unary_function(){} - __device__ __forceinline__ RGB5x52RGB(const RGB5x52RGB& other_):unary_function(){} + __host__ __device__ __forceinline__ RGB5x52RGB() {} + __host__ __device__ __forceinline__ RGB5x52RGB(const RGB5x52RGB&) {} }; @@ -295,15 +292,15 @@ namespace cv { namespace gpu { namespace device RGB5x52RGBConverter::cvt(src, dst); return dst; } - __device__ __forceinline__ RGB5x52RGB():unary_function(){} - __device__ __forceinline__ RGB5x52RGB(const RGB5x52RGB& other_):unary_function(){} + __host__ __device__ __forceinline__ RGB5x52RGB() {} + __host__ __device__ __forceinline__ RGB5x52RGB(const RGB5x52RGB&) {} }; } #define OPENCV_GPU_IMPLEMENT_RGB5x52RGB_TRAITS(name, dcn, bidx, green_bits) \ struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB5x52RGB functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB5x52RGB functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -325,9 +322,8 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ Gray2RGB():unary_function::vec_type>(){} - __device__ __forceinline__ Gray2RGB(const Gray2RGB& other_) - : unary_function::vec_type>(){} + __host__ __device__ __forceinline__ Gray2RGB() {} + __host__ __device__ __forceinline__ Gray2RGB(const Gray2RGB&) {} }; template <> struct Gray2RGB : unary_function @@ -342,15 +338,15 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ Gray2RGB():unary_function(){} - __device__ __forceinline__ Gray2RGB(const Gray2RGB& other_):unary_function(){} + __host__ __device__ __forceinline__ Gray2RGB() {} + __host__ __device__ __forceinline__ Gray2RGB(const Gray2RGB&) {} }; } #define OPENCV_GPU_IMPLEMENT_GRAY2RGB_TRAITS(name, dcn) \ template struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::Gray2RGB functor_type; \ + typedef ::cv::gpu::cudev::color_detail::Gray2RGB functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -384,15 +380,15 @@ namespace cv { namespace gpu { namespace device return Gray2RGB5x5Converter::cvt(src); } - __device__ __forceinline__ Gray2RGB5x5():unary_function(){} - __device__ __forceinline__ Gray2RGB5x5(const Gray2RGB5x5& other_):unary_function(){} + __host__ __device__ __forceinline__ Gray2RGB5x5() {} + __host__ __device__ __forceinline__ Gray2RGB5x5(const Gray2RGB5x5&) {} }; } #define OPENCV_GPU_IMPLEMENT_GRAY2RGB5x5_TRAITS(name, green_bits) \ struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::Gray2RGB5x5 functor_type; \ + typedef ::cv::gpu::cudev::color_detail::Gray2RGB5x5 functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -426,15 +422,15 @@ namespace cv { namespace gpu { namespace device { return RGB5x52GrayConverter::cvt(src); } - __device__ __forceinline__ RGB5x52Gray() : unary_function(){} - __device__ __forceinline__ RGB5x52Gray(const RGB5x52Gray& other_) : unary_function(){} + __host__ __device__ __forceinline__ RGB5x52Gray() {} + __host__ __device__ __forceinline__ RGB5x52Gray(const RGB5x52Gray&) {} }; } #define OPENCV_GPU_IMPLEMENT_RGB5x52GRAY_TRAITS(name, green_bits) \ struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB5x52Gray functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB5x52Gray functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -467,9 +463,8 @@ namespace cv { namespace gpu { namespace device { return RGB2GrayConvert(&src.x); } - __device__ __forceinline__ RGB2Gray() : unary_function::vec_type, T>(){} - __device__ __forceinline__ RGB2Gray(const RGB2Gray& other_) - : unary_function::vec_type, T>(){} + __host__ __device__ __forceinline__ RGB2Gray() {} + __host__ __device__ __forceinline__ RGB2Gray(const RGB2Gray&) {} }; template struct RGB2Gray : unary_function @@ -478,15 +473,15 @@ namespace cv { namespace gpu { namespace device { return RGB2GrayConvert(src); } - __device__ __forceinline__ RGB2Gray() : unary_function(){} - __device__ __forceinline__ RGB2Gray(const RGB2Gray& other_) : unary_function(){} + __host__ __device__ __forceinline__ RGB2Gray() {} + __host__ __device__ __forceinline__ RGB2Gray(const RGB2Gray&) {} }; } #define OPENCV_GPU_IMPLEMENT_RGB2GRAY_TRAITS(name, scn, bidx) \ template struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB2Gray functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB2Gray functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -529,17 +524,15 @@ namespace cv { namespace gpu { namespace device RGB2YUVConvert(&src.x, dst); return dst; } - __device__ __forceinline__ RGB2YUV() - : unary_function::vec_type, typename TypeVec::vec_type>(){} - __device__ __forceinline__ RGB2YUV(const RGB2YUV& other_) - : unary_function::vec_type, typename TypeVec::vec_type>(){} + __host__ __device__ __forceinline__ RGB2YUV() {} + __host__ __device__ __forceinline__ RGB2YUV(const RGB2YUV&) {} }; } #define OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(name, scn, dcn, bidx) \ template struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB2YUV functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB2YUV functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -609,10 +602,8 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ YUV2RGB() - : unary_function::vec_type, typename TypeVec::vec_type>(){} - __device__ __forceinline__ YUV2RGB(const YUV2RGB& other_) - : unary_function::vec_type, typename TypeVec::vec_type>(){} + __host__ __device__ __forceinline__ YUV2RGB() {} + __host__ __device__ __forceinline__ YUV2RGB(const YUV2RGB&) {} }; template struct YUV2RGB : unary_function @@ -621,15 +612,15 @@ namespace cv { namespace gpu { namespace device { return YUV2RGBConvert(src); } - __device__ __forceinline__ YUV2RGB() : unary_function(){} - __device__ __forceinline__ YUV2RGB(const YUV2RGB& other_) : unary_function(){} + __host__ __device__ __forceinline__ YUV2RGB() {} + __host__ __device__ __forceinline__ YUV2RGB(const YUV2RGB&) {} }; } #define OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(name, scn, dcn, bidx) \ template struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::YUV2RGB functor_type; \ + typedef ::cv::gpu::cudev::color_detail::YUV2RGB functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -689,10 +680,8 @@ namespace cv { namespace gpu { namespace device RGB2YCrCbConvert(&src.x, dst); return dst; } - __device__ __forceinline__ RGB2YCrCb() - : unary_function::vec_type, typename TypeVec::vec_type>(){} - __device__ __forceinline__ RGB2YCrCb(const RGB2YCrCb& other_) - : unary_function::vec_type, typename TypeVec::vec_type>(){} + __host__ __device__ __forceinline__ RGB2YCrCb() {} + __host__ __device__ __forceinline__ RGB2YCrCb(const RGB2YCrCb&) {} }; template struct RGB2YCrCb : unary_function @@ -702,15 +691,15 @@ namespace cv { namespace gpu { namespace device return RGB2YCrCbConvert(src); } - __device__ __forceinline__ RGB2YCrCb() : unary_function(){} - __device__ __forceinline__ RGB2YCrCb(const RGB2YCrCb& other_) : unary_function(){} + __host__ __device__ __forceinline__ RGB2YCrCb() {} + __host__ __device__ __forceinline__ RGB2YCrCb(const RGB2YCrCb&) {} }; } #define OPENCV_GPU_IMPLEMENT_RGB2YCrCb_TRAITS(name, scn, dcn, bidx) \ template struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB2YCrCb functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB2YCrCb functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -771,10 +760,8 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ YCrCb2RGB() - : unary_function::vec_type, typename TypeVec::vec_type>(){} - __device__ __forceinline__ YCrCb2RGB(const YCrCb2RGB& other_) - : unary_function::vec_type, typename TypeVec::vec_type>(){} + __host__ __device__ __forceinline__ YCrCb2RGB() {} + __host__ __device__ __forceinline__ YCrCb2RGB(const YCrCb2RGB&) {} }; template struct YCrCb2RGB : unary_function @@ -783,15 +770,15 @@ namespace cv { namespace gpu { namespace device { return YCrCb2RGBConvert(src); } - __device__ __forceinline__ YCrCb2RGB() : unary_function(){} - __device__ __forceinline__ YCrCb2RGB(const YCrCb2RGB& other_) : unary_function(){} + __host__ __device__ __forceinline__ YCrCb2RGB() {} + __host__ __device__ __forceinline__ YCrCb2RGB(const YCrCb2RGB&) {} }; } #define OPENCV_GPU_IMPLEMENT_YCrCb2RGB_TRAITS(name, scn, dcn, bidx) \ template struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::YCrCb2RGB functor_type; \ + typedef ::cv::gpu::cudev::color_detail::YCrCb2RGB functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -849,10 +836,8 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ RGB2XYZ() - : unary_function::vec_type, typename TypeVec::vec_type>(){} - __device__ __forceinline__ RGB2XYZ(const RGB2XYZ& other_) - : unary_function::vec_type, typename TypeVec::vec_type>(){} + __host__ __device__ __forceinline__ RGB2XYZ() {} + __host__ __device__ __forceinline__ RGB2XYZ(const RGB2XYZ&) {} }; template struct RGB2XYZ : unary_function @@ -861,15 +846,15 @@ namespace cv { namespace gpu { namespace device { return RGB2XYZConvert(src); } - __device__ __forceinline__ RGB2XYZ() : unary_function(){} - __device__ __forceinline__ RGB2XYZ(const RGB2XYZ& other_) : unary_function(){} + __host__ __device__ __forceinline__ RGB2XYZ() {} + __host__ __device__ __forceinline__ RGB2XYZ(const RGB2XYZ&) {} }; } #define OPENCV_GPU_IMPLEMENT_RGB2XYZ_TRAITS(name, scn, dcn, bidx) \ template struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB2XYZ functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB2XYZ functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -926,10 +911,8 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ XYZ2RGB() - : unary_function::vec_type, typename TypeVec::vec_type>(){} - __device__ __forceinline__ XYZ2RGB(const XYZ2RGB& other_) - : unary_function::vec_type, typename TypeVec::vec_type>(){} + __host__ __device__ __forceinline__ XYZ2RGB() {} + __host__ __device__ __forceinline__ XYZ2RGB(const XYZ2RGB&) {} }; template struct XYZ2RGB : unary_function @@ -938,15 +921,15 @@ namespace cv { namespace gpu { namespace device { return XYZ2RGBConvert(src); } - __device__ __forceinline__ XYZ2RGB() : unary_function(){} - __device__ __forceinline__ XYZ2RGB(const XYZ2RGB& other_) : unary_function(){} + __host__ __device__ __forceinline__ XYZ2RGB() {} + __host__ __device__ __forceinline__ XYZ2RGB(const XYZ2RGB&) {} }; } #define OPENCV_GPU_IMPLEMENT_XYZ2RGB_TRAITS(name, scn, dcn, bidx) \ template struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::XYZ2RGB functor_type; \ + typedef ::cv::gpu::cudev::color_detail::XYZ2RGB functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1066,10 +1049,8 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ RGB2HSV() - : unary_function::vec_type, typename TypeVec::vec_type>(){} - __device__ __forceinline__ RGB2HSV(const RGB2HSV& other_) - : unary_function::vec_type, typename TypeVec::vec_type>(){} + __host__ __device__ __forceinline__ RGB2HSV() {} + __host__ __device__ __forceinline__ RGB2HSV(const RGB2HSV&) {} }; template struct RGB2HSV : unary_function @@ -1078,15 +1059,15 @@ namespace cv { namespace gpu { namespace device { return RGB2HSVConvert(src); } - __device__ __forceinline__ RGB2HSV():unary_function(){} - __device__ __forceinline__ RGB2HSV(const RGB2HSV& other_):unary_function(){} + __host__ __device__ __forceinline__ RGB2HSV() {} + __host__ __device__ __forceinline__ RGB2HSV(const RGB2HSV&) {} }; } #define OPENCV_GPU_IMPLEMENT_RGB2HSV_TRAITS(name, scn, dcn, bidx) \ template struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB2HSV functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB2HSV functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1094,7 +1075,7 @@ namespace cv { namespace gpu { namespace device }; \ template struct name ## _full_traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB2HSV functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB2HSV functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1102,7 +1083,7 @@ namespace cv { namespace gpu { namespace device }; \ template <> struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB2HSV functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB2HSV functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1110,7 +1091,7 @@ namespace cv { namespace gpu { namespace device }; \ template <> struct name ## _full_traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB2HSV functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB2HSV functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1208,10 +1189,8 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ HSV2RGB() - : unary_function::vec_type, typename TypeVec::vec_type>(){} - __device__ __forceinline__ HSV2RGB(const HSV2RGB& other_) - : unary_function::vec_type, typename TypeVec::vec_type>(){} + __host__ __device__ __forceinline__ HSV2RGB() {} + __host__ __device__ __forceinline__ HSV2RGB(const HSV2RGB&) {} }; template struct HSV2RGB : unary_function @@ -1220,15 +1199,15 @@ namespace cv { namespace gpu { namespace device { return HSV2RGBConvert(src); } - __device__ __forceinline__ HSV2RGB():unary_function(){} - __device__ __forceinline__ HSV2RGB(const HSV2RGB& other_):unary_function(){} + __host__ __device__ __forceinline__ HSV2RGB() {} + __host__ __device__ __forceinline__ HSV2RGB(const HSV2RGB&) {} }; } #define OPENCV_GPU_IMPLEMENT_HSV2RGB_TRAITS(name, scn, dcn, bidx) \ template struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::HSV2RGB functor_type; \ + typedef ::cv::gpu::cudev::color_detail::HSV2RGB functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1236,7 +1215,7 @@ namespace cv { namespace gpu { namespace device }; \ template struct name ## _full_traits \ { \ - typedef ::cv::gpu::device::color_detail::HSV2RGB functor_type; \ + typedef ::cv::gpu::cudev::color_detail::HSV2RGB functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1244,7 +1223,7 @@ namespace cv { namespace gpu { namespace device }; \ template <> struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::HSV2RGB functor_type; \ + typedef ::cv::gpu::cudev::color_detail::HSV2RGB functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1252,7 +1231,7 @@ namespace cv { namespace gpu { namespace device }; \ template <> struct name ## _full_traits \ { \ - typedef ::cv::gpu::device::color_detail::HSV2RGB functor_type; \ + typedef ::cv::gpu::cudev::color_detail::HSV2RGB functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1343,10 +1322,8 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ RGB2HLS() - : unary_function::vec_type, typename TypeVec::vec_type>(){} - __device__ __forceinline__ RGB2HLS(const RGB2HLS& other_) - : unary_function::vec_type, typename TypeVec::vec_type>(){} + __host__ __device__ __forceinline__ RGB2HLS() {} + __host__ __device__ __forceinline__ RGB2HLS(const RGB2HLS&) {} }; template struct RGB2HLS : unary_function @@ -1355,15 +1332,15 @@ namespace cv { namespace gpu { namespace device { return RGB2HLSConvert(src); } - __device__ __forceinline__ RGB2HLS() : unary_function(){} - __device__ __forceinline__ RGB2HLS(const RGB2HLS& other_) : unary_function(){} + __host__ __device__ __forceinline__ RGB2HLS() {} + __host__ __device__ __forceinline__ RGB2HLS(const RGB2HLS&) {} }; } #define OPENCV_GPU_IMPLEMENT_RGB2HLS_TRAITS(name, scn, dcn, bidx) \ template struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB2HLS functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB2HLS functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1371,7 +1348,7 @@ namespace cv { namespace gpu { namespace device }; \ template struct name ## _full_traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB2HLS functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB2HLS functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1379,7 +1356,7 @@ namespace cv { namespace gpu { namespace device }; \ template <> struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB2HLS functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB2HLS functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1387,7 +1364,7 @@ namespace cv { namespace gpu { namespace device }; \ template <> struct name ## _full_traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB2HLS functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB2HLS functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1485,10 +1462,8 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ HLS2RGB() - : unary_function::vec_type, typename TypeVec::vec_type>(){} - __device__ __forceinline__ HLS2RGB(const HLS2RGB& other_) - : unary_function::vec_type, typename TypeVec::vec_type>(){} + __host__ __device__ __forceinline__ HLS2RGB() {} + __host__ __device__ __forceinline__ HLS2RGB(const HLS2RGB&) {} }; template struct HLS2RGB : unary_function @@ -1497,15 +1472,15 @@ namespace cv { namespace gpu { namespace device { return HLS2RGBConvert(src); } - __device__ __forceinline__ HLS2RGB() : unary_function(){} - __device__ __forceinline__ HLS2RGB(const HLS2RGB& other_) : unary_function(){} + __host__ __device__ __forceinline__ HLS2RGB() {} + __host__ __device__ __forceinline__ HLS2RGB(const HLS2RGB&) {} }; } #define OPENCV_GPU_IMPLEMENT_HLS2RGB_TRAITS(name, scn, dcn, bidx) \ template struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::HLS2RGB functor_type; \ + typedef ::cv::gpu::cudev::color_detail::HLS2RGB functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1513,7 +1488,7 @@ namespace cv { namespace gpu { namespace device }; \ template struct name ## _full_traits \ { \ - typedef ::cv::gpu::device::color_detail::HLS2RGB functor_type; \ + typedef ::cv::gpu::cudev::color_detail::HLS2RGB functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1521,7 +1496,7 @@ namespace cv { namespace gpu { namespace device }; \ template <> struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::HLS2RGB functor_type; \ + typedef ::cv::gpu::cudev::color_detail::HLS2RGB functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1529,7 +1504,7 @@ namespace cv { namespace gpu { namespace device }; \ template <> struct name ## _full_traits \ { \ - typedef ::cv::gpu::device::color_detail::HLS2RGB functor_type; \ + typedef ::cv::gpu::cudev::color_detail::HLS2RGB functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1651,8 +1626,8 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ RGB2Lab() {} - __device__ __forceinline__ RGB2Lab(const RGB2Lab& other_) {} + __host__ __device__ __forceinline__ RGB2Lab() {} + __host__ __device__ __forceinline__ RGB2Lab(const RGB2Lab&) {} }; template struct RGB2Lab @@ -1666,15 +1641,15 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ RGB2Lab() {} - __device__ __forceinline__ RGB2Lab(const RGB2Lab& other_) {} + __host__ __device__ __forceinline__ RGB2Lab() {} + __host__ __device__ __forceinline__ RGB2Lab(const RGB2Lab&) {} }; } #define OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS(name, scn, dcn, srgb, blueIdx) \ template struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB2Lab functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB2Lab functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1764,8 +1739,8 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ Lab2RGB() {} - __device__ __forceinline__ Lab2RGB(const Lab2RGB& other_) {} + __host__ __device__ __forceinline__ Lab2RGB() {} + __host__ __device__ __forceinline__ Lab2RGB(const Lab2RGB&) {} }; template struct Lab2RGB @@ -1779,15 +1754,15 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ Lab2RGB() {} - __device__ __forceinline__ Lab2RGB(const Lab2RGB& other_) {} + __host__ __device__ __forceinline__ Lab2RGB() {} + __host__ __device__ __forceinline__ Lab2RGB(const Lab2RGB&) {} }; } #define OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS(name, scn, dcn, srgb, blueIdx) \ template struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::Lab2RGB functor_type; \ + typedef ::cv::gpu::cudev::color_detail::Lab2RGB functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1863,8 +1838,8 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ RGB2Luv() {} - __device__ __forceinline__ RGB2Luv(const RGB2Luv& other_) {} + __host__ __device__ __forceinline__ RGB2Luv() {} + __host__ __device__ __forceinline__ RGB2Luv(const RGB2Luv&) {} }; template struct RGB2Luv @@ -1878,15 +1853,15 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ RGB2Luv() {} - __device__ __forceinline__ RGB2Luv(const RGB2Luv& other_) {} + __host__ __device__ __forceinline__ RGB2Luv() {} + __host__ __device__ __forceinline__ RGB2Luv(const RGB2Luv&) {} }; } #define OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS(name, scn, dcn, srgb, blueIdx) \ template struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::RGB2Luv functor_type; \ + typedef ::cv::gpu::cudev::color_detail::RGB2Luv functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1964,8 +1939,8 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ Luv2RGB() {} - __device__ __forceinline__ Luv2RGB(const Luv2RGB& other_) {} + __host__ __device__ __forceinline__ Luv2RGB() {} + __host__ __device__ __forceinline__ Luv2RGB(const Luv2RGB&) {} }; template struct Luv2RGB @@ -1979,15 +1954,15 @@ namespace cv { namespace gpu { namespace device return dst; } - __device__ __forceinline__ Luv2RGB() {} - __device__ __forceinline__ Luv2RGB(const Luv2RGB& other_) {} + __host__ __device__ __forceinline__ Luv2RGB() {} + __host__ __device__ __forceinline__ Luv2RGB(const Luv2RGB&) {} }; } #define OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(name, scn, dcn, srgb, blueIdx) \ template struct name ## _traits \ { \ - typedef ::cv::gpu::device::color_detail::Luv2RGB functor_type; \ + typedef ::cv::gpu::cudev::color_detail::Luv2RGB functor_type; \ static __host__ __device__ __forceinline__ functor_type create_functor() \ { \ return functor_type(); \ @@ -1996,6 +1971,6 @@ namespace cv { namespace gpu { namespace device #undef CV_DESCALE -}}} // namespace cv { namespace gpu { namespace device +}}} // namespace cv { namespace gpu { namespace cudev #endif // __OPENCV_GPU_COLOR_DETAIL_HPP__ diff --git a/modules/gpu/include/opencv2/gpu/device/detail/reduce.hpp b/modules/core/include/opencv2/core/cuda/detail/reduce.hpp similarity index 99% rename from modules/gpu/include/opencv2/gpu/device/detail/reduce.hpp rename to modules/core/include/opencv2/core/cuda/detail/reduce.hpp index 091a160e31..eba9b41a78 100644 --- a/modules/gpu/include/opencv2/gpu/device/detail/reduce.hpp +++ b/modules/core/include/opencv2/core/cuda/detail/reduce.hpp @@ -47,7 +47,7 @@ #include "../warp.hpp" #include "../warp_shuffle.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { namespace reduce_detail { diff --git a/modules/gpu/include/opencv2/gpu/device/detail/reduce_key_val.hpp b/modules/core/include/opencv2/core/cuda/detail/reduce_key_val.hpp similarity index 99% rename from modules/gpu/include/opencv2/gpu/device/detail/reduce_key_val.hpp rename to modules/core/include/opencv2/core/cuda/detail/reduce_key_val.hpp index a84e0c2fd0..1049e6714c 100644 --- a/modules/gpu/include/opencv2/gpu/device/detail/reduce_key_val.hpp +++ b/modules/core/include/opencv2/core/cuda/detail/reduce_key_val.hpp @@ -47,7 +47,7 @@ #include "../warp.hpp" #include "../warp_shuffle.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { namespace reduce_key_val_detail { diff --git a/modules/gpu/include/opencv2/gpu/device/detail/transform_detail.hpp b/modules/core/include/opencv2/core/cuda/detail/transform_detail.hpp similarity index 98% rename from modules/gpu/include/opencv2/gpu/device/detail/transform_detail.hpp rename to modules/core/include/opencv2/core/cuda/detail/transform_detail.hpp index 10da5938c5..2ac309b0c6 100644 --- a/modules/gpu/include/opencv2/gpu/device/detail/transform_detail.hpp +++ b/modules/core/include/opencv2/core/cuda/detail/transform_detail.hpp @@ -47,7 +47,7 @@ #include "../vec_traits.hpp" #include "../functional.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { namespace transform_detail { @@ -345,7 +345,7 @@ namespace cv { namespace gpu { namespace device { typedef TransformFunctorTraits ft; - StaticAssert::check(); + CV_StaticAssert(ft::smart_shift != 1, ""); if (!isAligned(src.data, ft::smart_shift * sizeof(T)) || !isAligned(src.step, ft::smart_shift * sizeof(T)) || !isAligned(dst.data, ft::smart_shift * sizeof(D)) || !isAligned(dst.step, ft::smart_shift * sizeof(D))) @@ -369,7 +369,7 @@ namespace cv { namespace gpu { namespace device { typedef TransformFunctorTraits ft; - StaticAssert::check(); + CV_StaticAssert(ft::smart_shift != 1, ""); if (!isAligned(src1.data, ft::smart_shift * sizeof(T1)) || !isAligned(src1.step, ft::smart_shift * sizeof(T1)) || !isAligned(src2.data, ft::smart_shift * sizeof(T2)) || !isAligned(src2.step, ft::smart_shift * sizeof(T2)) || @@ -390,6 +390,6 @@ namespace cv { namespace gpu { namespace device } }; } // namespace transform_detail -}}} // namespace cv { namespace gpu { namespace device +}}} // namespace cv { namespace gpu { namespace cudev #endif // __OPENCV_GPU_TRANSFORM_DETAIL_HPP__ diff --git a/modules/gpu/include/opencv2/gpu/device/detail/type_traits_detail.hpp b/modules/core/include/opencv2/core/cuda/detail/type_traits_detail.hpp similarity index 98% rename from modules/gpu/include/opencv2/gpu/device/detail/type_traits_detail.hpp rename to modules/core/include/opencv2/core/cuda/detail/type_traits_detail.hpp index 97ff00d8f6..4292d88003 100644 --- a/modules/gpu/include/opencv2/gpu/device/detail/type_traits_detail.hpp +++ b/modules/core/include/opencv2/core/cuda/detail/type_traits_detail.hpp @@ -46,7 +46,7 @@ #include "../common.hpp" #include "../vec_traits.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { namespace type_traits_detail { @@ -182,6 +182,6 @@ namespace cv { namespace gpu { namespace device enum { value = 1 }; }; } // namespace type_traits_detail -}}} // namespace cv { namespace gpu { namespace device +}}} // namespace cv { namespace gpu { namespace cudev #endif // __OPENCV_GPU_TYPE_TRAITS_DETAIL_HPP__ diff --git a/modules/gpu/include/opencv2/gpu/device/detail/vec_distance_detail.hpp b/modules/core/include/opencv2/core/cuda/detail/vec_distance_detail.hpp similarity index 98% rename from modules/gpu/include/opencv2/gpu/device/detail/vec_distance_detail.hpp rename to modules/core/include/opencv2/core/cuda/detail/vec_distance_detail.hpp index 78ab5565cb..a2a31a703c 100644 --- a/modules/gpu/include/opencv2/gpu/device/detail/vec_distance_detail.hpp +++ b/modules/core/include/opencv2/core/cuda/detail/vec_distance_detail.hpp @@ -45,7 +45,7 @@ #include "../datamov_utils.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { namespace vec_distance_detail { @@ -112,6 +112,6 @@ namespace cv { namespace gpu { namespace device } }; } // namespace vec_distance_detail -}}} // namespace cv { namespace gpu { namespace device +}}} // namespace cv { namespace gpu { namespace cudev #endif // __OPENCV_GPU_VEC_DISTANCE_DETAIL_HPP__ diff --git a/modules/gpu/include/opencv2/gpu/device/dynamic_smem.hpp b/modules/core/include/opencv2/core/cuda/dynamic_smem.hpp similarity index 98% rename from modules/gpu/include/opencv2/gpu/device/dynamic_smem.hpp rename to modules/core/include/opencv2/core/cuda/dynamic_smem.hpp index cf431d9524..aa20e53b82 100644 --- a/modules/gpu/include/opencv2/gpu/device/dynamic_smem.hpp +++ b/modules/core/include/opencv2/core/cuda/dynamic_smem.hpp @@ -43,7 +43,7 @@ #ifndef __OPENCV_GPU_DYNAMIC_SMEM_HPP__ #define __OPENCV_GPU_DYNAMIC_SMEM_HPP__ -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { template struct DynamicSharedMem { diff --git a/modules/core/include/opencv2/core/cuda/emulation.hpp b/modules/core/include/opencv2/core/cuda/emulation.hpp new file mode 100644 index 0000000000..b484f2378e --- /dev/null +++ b/modules/core/include/opencv2/core/cuda/emulation.hpp @@ -0,0 +1,261 @@ +/*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_GPU_EMULATION_HPP_ +#define OPENCV_GPU_EMULATION_HPP_ + +#include "common.hpp" +#include "warp_reduce.hpp" + +namespace cv { namespace gpu { namespace cudev +{ + struct Emulation + { + + static __device__ __forceinline__ int syncthreadsOr(int pred) + { +#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ < 200) + // just campilation stab + return 0; +#else + return __syncthreads_or(pred); +#endif + } + + template + static __forceinline__ __device__ int Ballot(int predicate) + { +#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ >= 200) + return __ballot(predicate); +#else + __shared__ volatile int cta_buffer[CTA_SIZE]; + + int tid = threadIdx.x; + cta_buffer[tid] = predicate ? (1 << (tid & 31)) : 0; + return warp_reduce(cta_buffer); +#endif + } + + struct smem + { + enum { TAG_MASK = (1U << ( (sizeof(unsigned int) << 3) - 5U)) - 1U }; + + template + static __device__ __forceinline__ T atomicInc(T* address, T val) + { +#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ < 120) + T count; + unsigned int tag = threadIdx.x << ( (sizeof(unsigned int) << 3) - 5U); + do + { + count = *address & TAG_MASK; + count = tag | (count + 1); + *address = count; + } while (*address != count); + + return (count & TAG_MASK) - 1; +#else + return ::atomicInc(address, val); +#endif + } + + template + static __device__ __forceinline__ T atomicAdd(T* address, T val) + { +#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ < 120) + T count; + unsigned int tag = threadIdx.x << ( (sizeof(unsigned int) << 3) - 5U); + do + { + count = *address & TAG_MASK; + count = tag | (count + val); + *address = count; + } while (*address != count); + + return (count & TAG_MASK) - val; +#else + return ::atomicAdd(address, val); +#endif + } + + template + static __device__ __forceinline__ T atomicMin(T* address, T val) + { +#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ < 120) + T count = ::min(*address, val); + do + { + *address = count; + } while (*address > count); + + return count; +#else + return ::atomicMin(address, val); +#endif + } + }; // struct cmem + + struct glob + { + static __device__ __forceinline__ int atomicAdd(int* address, int val) + { + return ::atomicAdd(address, val); + } + static __device__ __forceinline__ unsigned int atomicAdd(unsigned int* address, unsigned int val) + { + return ::atomicAdd(address, val); + } + static __device__ __forceinline__ float atomicAdd(float* address, float val) + { + #if __CUDA_ARCH__ >= 200 + return ::atomicAdd(address, val); + #else + int* address_as_i = (int*) address; + int old = *address_as_i, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_i, assumed, + __float_as_int(val + __int_as_float(assumed))); + } while (assumed != old); + return __int_as_float(old); + #endif + } + static __device__ __forceinline__ double atomicAdd(double* address, double val) + { + #if __CUDA_ARCH__ >= 130 + unsigned long long int* address_as_ull = (unsigned long long int*) address; + unsigned long long int old = *address_as_ull, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_ull, assumed, + __double_as_longlong(val + __longlong_as_double(assumed))); + } while (assumed != old); + return __longlong_as_double(old); + #else + (void) address; + (void) val; + return 0.0; + #endif + } + + static __device__ __forceinline__ int atomicMin(int* address, int val) + { + return ::atomicMin(address, val); + } + static __device__ __forceinline__ float atomicMin(float* address, float val) + { + #if __CUDA_ARCH__ >= 120 + int* address_as_i = (int*) address; + int old = *address_as_i, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_i, assumed, + __float_as_int(::fminf(val, __int_as_float(assumed)))); + } while (assumed != old); + return __int_as_float(old); + #else + (void) address; + (void) val; + return 0.0f; + #endif + } + static __device__ __forceinline__ double atomicMin(double* address, double val) + { + #if __CUDA_ARCH__ >= 130 + unsigned long long int* address_as_ull = (unsigned long long int*) address; + unsigned long long int old = *address_as_ull, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_ull, assumed, + __double_as_longlong(::fmin(val, __longlong_as_double(assumed)))); + } while (assumed != old); + return __longlong_as_double(old); + #else + (void) address; + (void) val; + return 0.0; + #endif + } + + static __device__ __forceinline__ int atomicMax(int* address, int val) + { + return ::atomicMax(address, val); + } + static __device__ __forceinline__ float atomicMax(float* address, float val) + { + #if __CUDA_ARCH__ >= 120 + int* address_as_i = (int*) address; + int old = *address_as_i, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_i, assumed, + __float_as_int(::fmaxf(val, __int_as_float(assumed)))); + } while (assumed != old); + return __int_as_float(old); + #else + (void) address; + (void) val; + return 0.0f; + #endif + } + static __device__ __forceinline__ double atomicMax(double* address, double val) + { + #if __CUDA_ARCH__ >= 130 + unsigned long long int* address_as_ull = (unsigned long long int*) address; + unsigned long long int old = *address_as_ull, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_ull, assumed, + __double_as_longlong(::fmax(val, __longlong_as_double(assumed)))); + } while (assumed != old); + return __longlong_as_double(old); + #else + (void) address; + (void) val; + return 0.0; + #endif + } + }; + }; //struct Emulation +}}} // namespace cv { namespace gpu { namespace cudev + +#endif /* OPENCV_GPU_EMULATION_HPP_ */ diff --git a/modules/gpu/include/opencv2/gpu/device/filters.hpp b/modules/core/include/opencv2/core/cuda/filters.hpp similarity index 97% rename from modules/gpu/include/opencv2/gpu/device/filters.hpp rename to modules/core/include/opencv2/core/cuda/filters.hpp index d193969a79..f35f662e8b 100644 --- a/modules/gpu/include/opencv2/gpu/device/filters.hpp +++ b/modules/core/include/opencv2/core/cuda/filters.hpp @@ -48,7 +48,7 @@ #include "vec_math.hpp" #include "type_traits.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { template struct PointFilter { @@ -67,7 +67,7 @@ namespace cv { namespace gpu { namespace device return src(__float2int_rz(y), __float2int_rz(x)); } - const Ptr2D src; + Ptr2D src; }; template struct LinearFilter @@ -107,7 +107,7 @@ namespace cv { namespace gpu { namespace device return saturate_cast(out); } - const Ptr2D src; + Ptr2D src; }; template struct CubicFilter @@ -166,7 +166,7 @@ namespace cv { namespace gpu { namespace device return saturate_cast(res); } - const Ptr2D src; + Ptr2D src; }; // for integer scaling template struct IntegerAreaFilter @@ -203,7 +203,7 @@ namespace cv { namespace gpu { namespace device return saturate_cast(out); } - const Ptr2D src; + Ptr2D src; float scale_x, scale_y ,scale; }; @@ -269,10 +269,10 @@ namespace cv { namespace gpu { namespace device return saturate_cast(out); } - const Ptr2D src; + Ptr2D src; float scale_x, scale_y; int width, haight; }; -}}} // namespace cv { namespace gpu { namespace device +}}} // namespace cv { namespace gpu { namespace cudev #endif // __OPENCV_GPU_FILTERS_HPP__ diff --git a/modules/gpu/include/opencv2/gpu/device/funcattrib.hpp b/modules/core/include/opencv2/core/cuda/funcattrib.hpp similarity index 95% rename from modules/gpu/include/opencv2/gpu/device/funcattrib.hpp rename to modules/core/include/opencv2/core/cuda/funcattrib.hpp index 05df4d10b4..46ef81926c 100644 --- a/modules/gpu/include/opencv2/gpu/device/funcattrib.hpp +++ b/modules/core/include/opencv2/core/cuda/funcattrib.hpp @@ -40,13 +40,12 @@ // //M*/ - #ifndef __OPENCV_GPU_DEVICE_FUNCATTRIB_HPP_ #define __OPENCV_GPU_DEVICE_FUNCATTRIB_HPP_ #include -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { template void printFuncAttrib(Func& func) @@ -67,6 +66,6 @@ namespace cv { namespace gpu { namespace device printf("\n"); fflush(stdout); } -}}} // namespace cv { namespace gpu { namespace device +}}} // namespace cv { namespace gpu { namespace cudev -#endif /* __OPENCV_GPU_DEVICE_FUNCATTRIB_HPP_ */ \ No newline at end of file +#endif /* __OPENCV_GPU_DEVICE_FUNCATTRIB_HPP_ */ diff --git a/modules/gpu/include/opencv2/gpu/device/functional.hpp b/modules/core/include/opencv2/core/cuda/functional.hpp similarity index 73% rename from modules/gpu/include/opencv2/gpu/device/functional.hpp rename to modules/core/include/opencv2/core/cuda/functional.hpp index 6064e8e99c..d6c019236a 100644 --- a/modules/gpu/include/opencv2/gpu/device/functional.hpp +++ b/modules/core/include/opencv2/core/cuda/functional.hpp @@ -49,7 +49,7 @@ #include "type_traits.hpp" #include "device_functions.h" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { // Function Objects template struct unary_function : public std::unary_function {}; @@ -63,8 +63,8 @@ namespace cv { namespace gpu { namespace device { return a + b; } - __device__ __forceinline__ plus(const plus& other):binary_function(){} - __device__ __forceinline__ plus():binary_function(){} + __host__ __device__ __forceinline__ plus() {} + __host__ __device__ __forceinline__ plus(const plus&) {} }; template struct minus : binary_function @@ -74,8 +74,8 @@ namespace cv { namespace gpu { namespace device { return a - b; } - __device__ __forceinline__ minus(const minus& other):binary_function(){} - __device__ __forceinline__ minus():binary_function(){} + __host__ __device__ __forceinline__ minus() {} + __host__ __device__ __forceinline__ minus(const minus&) {} }; template struct multiplies : binary_function @@ -85,8 +85,8 @@ namespace cv { namespace gpu { namespace device { return a * b; } - __device__ __forceinline__ multiplies(const multiplies& other):binary_function(){} - __device__ __forceinline__ multiplies():binary_function(){} + __host__ __device__ __forceinline__ multiplies() {} + __host__ __device__ __forceinline__ multiplies(const multiplies&) {} }; template struct divides : binary_function @@ -96,8 +96,8 @@ namespace cv { namespace gpu { namespace device { return a / b; } - __device__ __forceinline__ divides(const divides& other):binary_function(){} - __device__ __forceinline__ divides():binary_function(){} + __host__ __device__ __forceinline__ divides() {} + __host__ __device__ __forceinline__ divides(const divides&) {} }; template struct modulus : binary_function @@ -107,8 +107,8 @@ namespace cv { namespace gpu { namespace device { return a % b; } - __device__ __forceinline__ modulus(const modulus& other):binary_function(){} - __device__ __forceinline__ modulus():binary_function(){} + __host__ __device__ __forceinline__ modulus() {} + __host__ __device__ __forceinline__ modulus(const modulus&) {} }; template struct negate : unary_function @@ -117,8 +117,8 @@ namespace cv { namespace gpu { namespace device { return -a; } - __device__ __forceinline__ negate(const negate& other):unary_function(){} - __device__ __forceinline__ negate():unary_function(){} + __host__ __device__ __forceinline__ negate() {} + __host__ __device__ __forceinline__ negate(const negate&) {} }; // Comparison Operations @@ -129,8 +129,8 @@ namespace cv { namespace gpu { namespace device { return a == b; } - __device__ __forceinline__ equal_to(const equal_to& other):binary_function(){} - __device__ __forceinline__ equal_to():binary_function(){} + __host__ __device__ __forceinline__ equal_to() {} + __host__ __device__ __forceinline__ equal_to(const equal_to&) {} }; template struct not_equal_to : binary_function @@ -140,8 +140,8 @@ namespace cv { namespace gpu { namespace device { return a != b; } - __device__ __forceinline__ not_equal_to(const not_equal_to& other):binary_function(){} - __device__ __forceinline__ not_equal_to():binary_function(){} + __host__ __device__ __forceinline__ not_equal_to() {} + __host__ __device__ __forceinline__ not_equal_to(const not_equal_to&) {} }; template struct greater : binary_function @@ -151,8 +151,8 @@ namespace cv { namespace gpu { namespace device { return a > b; } - __device__ __forceinline__ greater(const greater& other):binary_function(){} - __device__ __forceinline__ greater():binary_function(){} + __host__ __device__ __forceinline__ greater() {} + __host__ __device__ __forceinline__ greater(const greater&) {} }; template struct less : binary_function @@ -162,8 +162,8 @@ namespace cv { namespace gpu { namespace device { return a < b; } - __device__ __forceinline__ less(const less& other):binary_function(){} - __device__ __forceinline__ less():binary_function(){} + __host__ __device__ __forceinline__ less() {} + __host__ __device__ __forceinline__ less(const less&) {} }; template struct greater_equal : binary_function @@ -173,8 +173,8 @@ namespace cv { namespace gpu { namespace device { return a >= b; } - __device__ __forceinline__ greater_equal(const greater_equal& other):binary_function(){} - __device__ __forceinline__ greater_equal():binary_function(){} + __host__ __device__ __forceinline__ greater_equal() {} + __host__ __device__ __forceinline__ greater_equal(const greater_equal&) {} }; template struct less_equal : binary_function @@ -184,8 +184,8 @@ namespace cv { namespace gpu { namespace device { return a <= b; } - __device__ __forceinline__ less_equal(const less_equal& other):binary_function(){} - __device__ __forceinline__ less_equal():binary_function(){} + __host__ __device__ __forceinline__ less_equal() {} + __host__ __device__ __forceinline__ less_equal(const less_equal&) {} }; // Logical Operations @@ -196,8 +196,8 @@ namespace cv { namespace gpu { namespace device { return a && b; } - __device__ __forceinline__ logical_and(const logical_and& other):binary_function(){} - __device__ __forceinline__ logical_and():binary_function(){} + __host__ __device__ __forceinline__ logical_and() {} + __host__ __device__ __forceinline__ logical_and(const logical_and&) {} }; template struct logical_or : binary_function @@ -207,8 +207,8 @@ namespace cv { namespace gpu { namespace device { return a || b; } - __device__ __forceinline__ logical_or(const logical_or& other):binary_function(){} - __device__ __forceinline__ logical_or():binary_function(){} + __host__ __device__ __forceinline__ logical_or() {} + __host__ __device__ __forceinline__ logical_or(const logical_or&) {} }; template struct logical_not : unary_function @@ -217,8 +217,8 @@ namespace cv { namespace gpu { namespace device { return !a; } - __device__ __forceinline__ logical_not(const logical_not& other):unary_function(){} - __device__ __forceinline__ logical_not():unary_function(){} + __host__ __device__ __forceinline__ logical_not() {} + __host__ __device__ __forceinline__ logical_not(const logical_not&) {} }; // Bitwise Operations @@ -229,8 +229,8 @@ namespace cv { namespace gpu { namespace device { return a & b; } - __device__ __forceinline__ bit_and(const bit_and& other):binary_function(){} - __device__ __forceinline__ bit_and():binary_function(){} + __host__ __device__ __forceinline__ bit_and() {} + __host__ __device__ __forceinline__ bit_and(const bit_and&) {} }; template struct bit_or : binary_function @@ -240,8 +240,8 @@ namespace cv { namespace gpu { namespace device { return a | b; } - __device__ __forceinline__ bit_or(const bit_or& other):binary_function(){} - __device__ __forceinline__ bit_or():binary_function(){} + __host__ __device__ __forceinline__ bit_or() {} + __host__ __device__ __forceinline__ bit_or(const bit_or&) {} }; template struct bit_xor : binary_function @@ -251,8 +251,8 @@ namespace cv { namespace gpu { namespace device { return a ^ b; } - __device__ __forceinline__ bit_xor(const bit_xor& other):binary_function(){} - __device__ __forceinline__ bit_xor():binary_function(){} + __host__ __device__ __forceinline__ bit_xor() {} + __host__ __device__ __forceinline__ bit_xor(const bit_xor&) {} }; template struct bit_not : unary_function @@ -261,8 +261,8 @@ namespace cv { namespace gpu { namespace device { return ~v; } - __device__ __forceinline__ bit_not(const bit_not& other):unary_function(){} - __device__ __forceinline__ bit_not():unary_function(){} + __host__ __device__ __forceinline__ bit_not() {} + __host__ __device__ __forceinline__ bit_not(const bit_not&) {} }; // Generalized Identity Operations @@ -272,8 +272,8 @@ namespace cv { namespace gpu { namespace device { return x; } - __device__ __forceinline__ identity(const identity& other):unary_function(){} - __device__ __forceinline__ identity():unary_function(){} + __host__ __device__ __forceinline__ identity() {} + __host__ __device__ __forceinline__ identity(const identity&) {} }; template struct project1st : binary_function @@ -282,8 +282,8 @@ namespace cv { namespace gpu { namespace device { return lhs; } - __device__ __forceinline__ project1st(const project1st& other):binary_function(){} - __device__ __forceinline__ project1st():binary_function(){} + __host__ __device__ __forceinline__ project1st() {} + __host__ __device__ __forceinline__ project1st(const project1st&) {} }; template struct project2nd : binary_function @@ -292,8 +292,8 @@ namespace cv { namespace gpu { namespace device { return rhs; } - __device__ __forceinline__ project2nd(const project2nd& other):binary_function(){} - __device__ __forceinline__ project2nd():binary_function(){} + __host__ __device__ __forceinline__ project2nd() {} + __host__ __device__ __forceinline__ project2nd(const project2nd&) {} }; // Min/Max Operations @@ -302,8 +302,8 @@ namespace cv { namespace gpu { namespace device template <> struct name : binary_function \ { \ __device__ __forceinline__ type operator()(type lhs, type rhs) const {return op(lhs, rhs);} \ - __device__ __forceinline__ name() {}\ - __device__ __forceinline__ name(const name&) {}\ + __host__ __device__ __forceinline__ name() {}\ + __host__ __device__ __forceinline__ name(const name&) {}\ }; template struct maximum : binary_function @@ -312,8 +312,8 @@ namespace cv { namespace gpu { namespace device { return max(lhs, rhs); } - __device__ __forceinline__ maximum() {} - __device__ __forceinline__ maximum(const maximum&) {} + __host__ __device__ __forceinline__ maximum() {} + __host__ __device__ __forceinline__ maximum(const maximum&) {} }; OPENCV_GPU_IMPLEMENT_MINMAX(maximum, uchar, ::max) @@ -332,8 +332,8 @@ namespace cv { namespace gpu { namespace device { return min(lhs, rhs); } - __device__ __forceinline__ minimum() {} - __device__ __forceinline__ minimum(const minimum&) {} + __host__ __device__ __forceinline__ minimum() {} + __host__ __device__ __forceinline__ minimum(const minimum&) {} }; OPENCV_GPU_IMPLEMENT_MINMAX(minimum, uchar, ::min) @@ -349,7 +349,6 @@ namespace cv { namespace gpu { namespace device #undef OPENCV_GPU_IMPLEMENT_MINMAX // Math functions -///bound========================================= template struct abs_func : unary_function { @@ -358,8 +357,8 @@ namespace cv { namespace gpu { namespace device return abs(x); } - __device__ __forceinline__ abs_func() {} - __device__ __forceinline__ abs_func(const abs_func&) {} + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} }; template <> struct abs_func : unary_function { @@ -368,8 +367,8 @@ namespace cv { namespace gpu { namespace device return x; } - __device__ __forceinline__ abs_func() {} - __device__ __forceinline__ abs_func(const abs_func&) {} + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} }; template <> struct abs_func : unary_function { @@ -378,8 +377,8 @@ namespace cv { namespace gpu { namespace device return ::abs((int)x); } - __device__ __forceinline__ abs_func() {} - __device__ __forceinline__ abs_func(const abs_func&) {} + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} }; template <> struct abs_func : unary_function { @@ -388,8 +387,8 @@ namespace cv { namespace gpu { namespace device return ::abs((int)x); } - __device__ __forceinline__ abs_func() {} - __device__ __forceinline__ abs_func(const abs_func&) {} + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} }; template <> struct abs_func : unary_function { @@ -398,8 +397,8 @@ namespace cv { namespace gpu { namespace device return x; } - __device__ __forceinline__ abs_func() {} - __device__ __forceinline__ abs_func(const abs_func&) {} + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} }; template <> struct abs_func : unary_function { @@ -408,8 +407,8 @@ namespace cv { namespace gpu { namespace device return ::abs((int)x); } - __device__ __forceinline__ abs_func() {} - __device__ __forceinline__ abs_func(const abs_func&) {} + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} }; template <> struct abs_func : unary_function { @@ -418,8 +417,8 @@ namespace cv { namespace gpu { namespace device return x; } - __device__ __forceinline__ abs_func() {} - __device__ __forceinline__ abs_func(const abs_func&) {} + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} }; template <> struct abs_func : unary_function { @@ -428,8 +427,8 @@ namespace cv { namespace gpu { namespace device return ::abs(x); } - __device__ __forceinline__ abs_func() {} - __device__ __forceinline__ abs_func(const abs_func&) {} + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} }; template <> struct abs_func : unary_function { @@ -438,8 +437,8 @@ namespace cv { namespace gpu { namespace device return ::fabsf(x); } - __device__ __forceinline__ abs_func() {} - __device__ __forceinline__ abs_func(const abs_func&) {} + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} }; template <> struct abs_func : unary_function { @@ -448,8 +447,8 @@ namespace cv { namespace gpu { namespace device return ::fabs(x); } - __device__ __forceinline__ abs_func() {} - __device__ __forceinline__ abs_func(const abs_func&) {} + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} }; #define OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(name, func) \ @@ -459,8 +458,8 @@ namespace cv { namespace gpu { namespace device { \ return func ## f(v); \ } \ - __device__ __forceinline__ name ## _func() {} \ - __device__ __forceinline__ name ## _func(const name ## _func&) {} \ + __host__ __device__ __forceinline__ name ## _func() {} \ + __host__ __device__ __forceinline__ name ## _func(const name ## _func&) {} \ }; \ template <> struct name ## _func : unary_function \ { \ @@ -468,8 +467,8 @@ namespace cv { namespace gpu { namespace device { \ return func(v); \ } \ - __device__ __forceinline__ name ## _func() {} \ - __device__ __forceinline__ name ## _func(const name ## _func&) {} \ + __host__ __device__ __forceinline__ name ## _func() {} \ + __host__ __device__ __forceinline__ name ## _func(const name ## _func&) {} \ }; #define OPENCV_GPU_IMPLEMENT_BIN_FUNCTOR(name, func) \ @@ -479,6 +478,8 @@ namespace cv { namespace gpu { namespace device { \ return func ## f(v1, v2); \ } \ + __host__ __device__ __forceinline__ name ## _func() {} \ + __host__ __device__ __forceinline__ name ## _func(const name ## _func&) {} \ }; \ template <> struct name ## _func : binary_function \ { \ @@ -486,6 +487,8 @@ namespace cv { namespace gpu { namespace device { \ return func(v1, v2); \ } \ + __host__ __device__ __forceinline__ name ## _func() {} \ + __host__ __device__ __forceinline__ name ## _func(const name ## _func&) {} \ }; OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(sqrt, ::sqrt) @@ -522,8 +525,8 @@ namespace cv { namespace gpu { namespace device { return src1 * src1 + src2 * src2; } - __device__ __forceinline__ hypot_sqr_func(const hypot_sqr_func& other) : binary_function(){} - __device__ __forceinline__ hypot_sqr_func() : binary_function(){} + __host__ __device__ __forceinline__ hypot_sqr_func() {} + __host__ __device__ __forceinline__ hypot_sqr_func(const hypot_sqr_func&) {} }; // Saturate Cast Functor @@ -533,8 +536,8 @@ namespace cv { namespace gpu { namespace device { return saturate_cast(v); } - __device__ __forceinline__ saturate_cast_func(const saturate_cast_func& other):unary_function(){} - __device__ __forceinline__ saturate_cast_func():unary_function(){} + __host__ __device__ __forceinline__ saturate_cast_func() {} + __host__ __device__ __forceinline__ saturate_cast_func(const saturate_cast_func&) {} }; // Threshold Functors @@ -547,13 +550,12 @@ namespace cv { namespace gpu { namespace device return (src > thresh) * maxVal; } - __device__ __forceinline__ thresh_binary_func(const thresh_binary_func& other) - : unary_function(), thresh(other.thresh), maxVal(other.maxVal){} + __host__ __device__ __forceinline__ thresh_binary_func() {} + __host__ __device__ __forceinline__ thresh_binary_func(const thresh_binary_func& other) + : thresh(other.thresh), maxVal(other.maxVal) {} - __device__ __forceinline__ thresh_binary_func():unary_function(){} - - const T thresh; - const T maxVal; + T thresh; + T maxVal; }; template struct thresh_binary_inv_func : unary_function @@ -565,13 +567,12 @@ namespace cv { namespace gpu { namespace device return (src <= thresh) * maxVal; } - __device__ __forceinline__ thresh_binary_inv_func(const thresh_binary_inv_func& other) - : unary_function(), thresh(other.thresh), maxVal(other.maxVal){} + __host__ __device__ __forceinline__ thresh_binary_inv_func() {} + __host__ __device__ __forceinline__ thresh_binary_inv_func(const thresh_binary_inv_func& other) + : thresh(other.thresh), maxVal(other.maxVal) {} - __device__ __forceinline__ thresh_binary_inv_func():unary_function(){} - - const T thresh; - const T maxVal; + T thresh; + T maxVal; }; template struct thresh_trunc_func : unary_function @@ -583,12 +584,11 @@ namespace cv { namespace gpu { namespace device return minimum()(src, thresh); } - __device__ __forceinline__ thresh_trunc_func(const thresh_trunc_func& other) - : unary_function(), thresh(other.thresh){} + __host__ __device__ __forceinline__ thresh_trunc_func() {} + __host__ __device__ __forceinline__ thresh_trunc_func(const thresh_trunc_func& other) + : thresh(other.thresh) {} - __device__ __forceinline__ thresh_trunc_func():unary_function(){} - - const T thresh; + T thresh; }; template struct thresh_to_zero_func : unary_function @@ -599,12 +599,12 @@ namespace cv { namespace gpu { namespace device { return (src > thresh) * src; } - __device__ __forceinline__ thresh_to_zero_func(const thresh_to_zero_func& other) - : unary_function(), thresh(other.thresh){} - __device__ __forceinline__ thresh_to_zero_func():unary_function(){} + __host__ __device__ __forceinline__ thresh_to_zero_func() {} + __host__ __device__ __forceinline__ thresh_to_zero_func(const thresh_to_zero_func& other) + : thresh(other.thresh) {} - const T thresh; + T thresh; }; template struct thresh_to_zero_inv_func : unary_function @@ -615,14 +615,14 @@ namespace cv { namespace gpu { namespace device { return (src <= thresh) * src; } - __device__ __forceinline__ thresh_to_zero_inv_func(const thresh_to_zero_inv_func& other) - : unary_function(), thresh(other.thresh){} - __device__ __forceinline__ thresh_to_zero_inv_func():unary_function(){} + __host__ __device__ __forceinline__ thresh_to_zero_inv_func() {} + __host__ __device__ __forceinline__ thresh_to_zero_inv_func(const thresh_to_zero_inv_func& other) + : thresh(other.thresh) {} - const T thresh; + T thresh; }; -//bound!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ============> + // Function Object Adaptors template struct unary_negate : unary_function { @@ -633,10 +633,10 @@ namespace cv { namespace gpu { namespace device return !pred(x); } - __device__ __forceinline__ unary_negate(const unary_negate& other) : unary_function(){} - __device__ __forceinline__ unary_negate() : unary_function(){} + __host__ __device__ __forceinline__ unary_negate() {} + __host__ __device__ __forceinline__ unary_negate(const unary_negate& other) : pred(other.pred) {} - const Predicate pred; + Predicate pred; }; template __host__ __device__ __forceinline__ unary_negate not1(const Predicate& pred) @@ -653,13 +653,11 @@ namespace cv { namespace gpu { namespace device { return !pred(x,y); } - __device__ __forceinline__ binary_negate(const binary_negate& other) - : binary_function(){} - __device__ __forceinline__ binary_negate() : - binary_function(){} + __host__ __device__ __forceinline__ binary_negate() {} + __host__ __device__ __forceinline__ binary_negate(const binary_negate& other) : pred(other.pred) {} - const Predicate pred; + Predicate pred; }; template __host__ __device__ __forceinline__ binary_negate not2(const BinaryPredicate& pred) @@ -676,11 +674,11 @@ namespace cv { namespace gpu { namespace device return op(arg1, a); } - __device__ __forceinline__ binder1st(const binder1st& other) : - unary_function(){} + __host__ __device__ __forceinline__ binder1st() {} + __host__ __device__ __forceinline__ binder1st(const binder1st& other) : op(other.op), arg1(other.arg1) {} - const Op op; - const typename Op::first_argument_type arg1; + Op op; + typename Op::first_argument_type arg1; }; template __host__ __device__ __forceinline__ binder1st bind1st(const Op& op, const T& x) @@ -697,11 +695,11 @@ namespace cv { namespace gpu { namespace device return op(a, arg2); } - __device__ __forceinline__ binder2nd(const binder2nd& other) : - unary_function(), op(other.op), arg2(other.arg2){} + __host__ __device__ __forceinline__ binder2nd() {} + __host__ __device__ __forceinline__ binder2nd(const binder2nd& other) : op(other.op), arg2(other.arg2) {} - const Op op; - const typename Op::second_argument_type arg2; + Op op; + typename Op::second_argument_type arg2; }; template __host__ __device__ __forceinline__ binder2nd bind2nd(const Op& op, const T& x) @@ -786,6 +784,6 @@ namespace cv { namespace gpu { namespace device #define OPENCV_GPU_TRANSFORM_FUNCTOR_TRAITS(type) \ template <> struct TransformFunctorTraits< type > : DefaultTransformFunctorTraits< type > -}}} // namespace cv { namespace gpu { namespace device +}}} // namespace cv { namespace gpu { namespace cudev #endif // __OPENCV_GPU_FUNCTIONAL_HPP__ diff --git a/modules/core/include/opencv2/core/cuda/limits.hpp b/modules/core/include/opencv2/core/cuda/limits.hpp new file mode 100644 index 0000000000..0439de795c --- /dev/null +++ b/modules/core/include/opencv2/core/cuda/limits.hpp @@ -0,0 +1,122 @@ +/*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_GPU_LIMITS_GPU_HPP__ +#define __OPENCV_GPU_LIMITS_GPU_HPP__ + +#include +#include +#include "common.hpp" + +namespace cv { namespace gpu { namespace cudev +{ + +template struct numeric_limits; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static bool min() { return false; } + __device__ __forceinline__ static bool max() { return true; } + static const bool is_signed = false; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static signed char min() { return SCHAR_MIN; } + __device__ __forceinline__ static signed char max() { return SCHAR_MAX; } + static const bool is_signed = true; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static unsigned char min() { return 0; } + __device__ __forceinline__ static unsigned char max() { return UCHAR_MAX; } + static const bool is_signed = false; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static short min() { return SHRT_MIN; } + __device__ __forceinline__ static short max() { return SHRT_MAX; } + static const bool is_signed = true; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static unsigned short min() { return 0; } + __device__ __forceinline__ static unsigned short max() { return USHRT_MAX; } + static const bool is_signed = false; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static int min() { return INT_MIN; } + __device__ __forceinline__ static int max() { return INT_MAX; } + static const bool is_signed = true; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static unsigned int min() { return 0; } + __device__ __forceinline__ static unsigned int max() { return UINT_MAX; } + static const bool is_signed = false; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static float min() { return FLT_MIN; } + __device__ __forceinline__ static float max() { return FLT_MAX; } + __device__ __forceinline__ static float epsilon() { return FLT_EPSILON; } + static const bool is_signed = true; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static double min() { return DBL_MIN; } + __device__ __forceinline__ static double max() { return DBL_MAX; } + __device__ __forceinline__ static double epsilon() { return DBL_EPSILON; } + static const bool is_signed = true; +}; + +}}} // namespace cv { namespace gpu { namespace cudev { + +#endif // __OPENCV_GPU_LIMITS_GPU_HPP__ diff --git a/modules/gpu/include/opencv2/gpu/device/reduce.hpp b/modules/core/include/opencv2/core/cuda/reduce.hpp similarity index 99% rename from modules/gpu/include/opencv2/gpu/device/reduce.hpp rename to modules/core/include/opencv2/core/cuda/reduce.hpp index 2161b06495..722e2bbeb6 100644 --- a/modules/gpu/include/opencv2/gpu/device/reduce.hpp +++ b/modules/core/include/opencv2/core/cuda/reduce.hpp @@ -47,7 +47,7 @@ #include "detail/reduce.hpp" #include "detail/reduce_key_val.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { template __device__ __forceinline__ void reduce(volatile T* smem, T& val, unsigned int tid, const Op& op) diff --git a/modules/gpu/include/opencv2/gpu/device/saturate_cast.hpp b/modules/core/include/opencv2/core/cuda/saturate_cast.hpp similarity index 99% rename from modules/gpu/include/opencv2/gpu/device/saturate_cast.hpp rename to modules/core/include/opencv2/core/cuda/saturate_cast.hpp index 7a2799fa37..b30f5e7ce0 100644 --- a/modules/gpu/include/opencv2/gpu/device/saturate_cast.hpp +++ b/modules/core/include/opencv2/core/cuda/saturate_cast.hpp @@ -45,7 +45,7 @@ #include "common.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { template __device__ __forceinline__ _Tp saturate_cast(uchar v) { return _Tp(v); } template __device__ __forceinline__ _Tp saturate_cast(schar v) { return _Tp(v); } diff --git a/modules/gpu/include/opencv2/gpu/device/scan.hpp b/modules/core/include/opencv2/core/cuda/scan.hpp similarity index 69% rename from modules/gpu/include/opencv2/gpu/device/scan.hpp rename to modules/core/include/opencv2/core/cuda/scan.hpp index f6dc6937fb..ecde123bb3 100644 --- a/modules/gpu/include/opencv2/gpu/device/scan.hpp +++ b/modules/core/include/opencv2/core/cuda/scan.hpp @@ -43,9 +43,12 @@ #ifndef __OPENCV_GPU_SCAN_HPP__ #define __OPENCV_GPU_SCAN_HPP__ -#include "common.hpp" +#include "opencv2/core/cuda/common.hpp" +#include "opencv2/core/cuda/utility.hpp" +#include "opencv2/core/cuda/warp.hpp" +#include "opencv2/core/cuda/warp_shuffle.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { enum ScanKind { EXCLUSIVE = 0, INCLUSIVE = 1 }; @@ -166,6 +169,82 @@ namespace cv { namespace gpu { namespace device static const int warp_log = 5; static const int warp_mask = 31; }; + + template + __device__ T warpScanInclusive(T idata, volatile T* s_Data, unsigned int tid) + { + #if __CUDA_ARCH__ >= 300 + const unsigned int laneId = cv::gpu::cudev::Warp::laneId(); + + // scan on shuffl functions + #pragma unroll + for (int i = 1; i <= (OPENCV_GPU_WARP_SIZE / 2); i *= 2) + { + const T n = cv::gpu::cudev::shfl_up(idata, i); + if (laneId >= i) + idata += n; + } + + return idata; + #else + unsigned int pos = 2 * tid - (tid & (OPENCV_GPU_WARP_SIZE - 1)); + s_Data[pos] = 0; + pos += OPENCV_GPU_WARP_SIZE; + s_Data[pos] = idata; + + s_Data[pos] += s_Data[pos - 1]; + s_Data[pos] += s_Data[pos - 2]; + s_Data[pos] += s_Data[pos - 4]; + s_Data[pos] += s_Data[pos - 8]; + s_Data[pos] += s_Data[pos - 16]; + + return s_Data[pos]; + #endif + } + + template + __device__ __forceinline__ T warpScanExclusive(T idata, volatile T* s_Data, unsigned int tid) + { + return warpScanInclusive(idata, s_Data, tid) - idata; + } + + template + __device__ T blockScanInclusive(T idata, volatile T* s_Data, unsigned int tid) + { + if (tiNumScanThreads > OPENCV_GPU_WARP_SIZE) + { + //Bottom-level inclusive warp scan + T warpResult = warpScanInclusive(idata, s_Data, tid); + + //Save top elements of each warp for exclusive warp scan + //sync to wait for warp scans to complete (because s_Data is being overwritten) + __syncthreads(); + if ((tid & (OPENCV_GPU_WARP_SIZE - 1)) == (OPENCV_GPU_WARP_SIZE - 1)) + { + s_Data[tid >> OPENCV_GPU_LOG_WARP_SIZE] = warpResult; + } + + //wait for warp scans to complete + __syncthreads(); + + if (tid < (tiNumScanThreads / OPENCV_GPU_WARP_SIZE) ) + { + //grab top warp elements + T val = s_Data[tid]; + //calculate exclusive scan and write back to shared memory + s_Data[tid] = warpScanExclusive(val, s_Data, tid); + } + + //return updated warp scans with exclusive scan results + __syncthreads(); + + return warpResult + s_Data[tid >> OPENCV_GPU_LOG_WARP_SIZE]; + } + else + { + return warpScanInclusive(idata, s_Data, tid); + } + } }}} #endif // __OPENCV_GPU_SCAN_HPP__ diff --git a/modules/core/include/opencv2/core/cuda/simd_functions.hpp b/modules/core/include/opencv2/core/cuda/simd_functions.hpp new file mode 100644 index 0000000000..aedd5632f2 --- /dev/null +++ b/modules/core/include/opencv2/core/cuda/simd_functions.hpp @@ -0,0 +1,909 @@ +/*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*/ + +/* + * Copyright (c) 2013 NVIDIA Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions 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. + * + * Neither the name of NVIDIA Corporation nor the names of its contributors + * may 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 COPYRIGHT HOLDER 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. + */ + +#ifndef __OPENCV_GPU_SIMD_FUNCTIONS_HPP__ +#define __OPENCV_GPU_SIMD_FUNCTIONS_HPP__ + +#include "common.hpp" + +/* + This header file contains inline functions that implement intra-word SIMD + operations, that are hardware accelerated on sm_3x (Kepler) GPUs. Efficient + emulation code paths are provided for earlier architectures (sm_1x, sm_2x) + to make the code portable across all GPUs supported by CUDA. The following + functions are currently implemented: + + vadd2(a,b) per-halfword unsigned addition, with wrap-around: a + b + vsub2(a,b) per-halfword unsigned subtraction, with wrap-around: a - b + vabsdiff2(a,b) per-halfword unsigned absolute difference: |a - b| + vavg2(a,b) per-halfword unsigned average: (a + b) / 2 + vavrg2(a,b) per-halfword unsigned rounded average: (a + b + 1) / 2 + vseteq2(a,b) per-halfword unsigned comparison: a == b ? 1 : 0 + vcmpeq2(a,b) per-halfword unsigned comparison: a == b ? 0xffff : 0 + vsetge2(a,b) per-halfword unsigned comparison: a >= b ? 1 : 0 + vcmpge2(a,b) per-halfword unsigned comparison: a >= b ? 0xffff : 0 + vsetgt2(a,b) per-halfword unsigned comparison: a > b ? 1 : 0 + vcmpgt2(a,b) per-halfword unsigned comparison: a > b ? 0xffff : 0 + vsetle2(a,b) per-halfword unsigned comparison: a <= b ? 1 : 0 + vcmple2(a,b) per-halfword unsigned comparison: a <= b ? 0xffff : 0 + vsetlt2(a,b) per-halfword unsigned comparison: a < b ? 1 : 0 + vcmplt2(a,b) per-halfword unsigned comparison: a < b ? 0xffff : 0 + vsetne2(a,b) per-halfword unsigned comparison: a != b ? 1 : 0 + vcmpne2(a,b) per-halfword unsigned comparison: a != b ? 0xffff : 0 + vmax2(a,b) per-halfword unsigned maximum: max(a, b) + vmin2(a,b) per-halfword unsigned minimum: min(a, b) + + vadd4(a,b) per-byte unsigned addition, with wrap-around: a + b + vsub4(a,b) per-byte unsigned subtraction, with wrap-around: a - b + vabsdiff4(a,b) per-byte unsigned absolute difference: |a - b| + vavg4(a,b) per-byte unsigned average: (a + b) / 2 + vavrg4(a,b) per-byte unsigned rounded average: (a + b + 1) / 2 + vseteq4(a,b) per-byte unsigned comparison: a == b ? 1 : 0 + vcmpeq4(a,b) per-byte unsigned comparison: a == b ? 0xff : 0 + vsetge4(a,b) per-byte unsigned comparison: a >= b ? 1 : 0 + vcmpge4(a,b) per-byte unsigned comparison: a >= b ? 0xff : 0 + vsetgt4(a,b) per-byte unsigned comparison: a > b ? 1 : 0 + vcmpgt4(a,b) per-byte unsigned comparison: a > b ? 0xff : 0 + vsetle4(a,b) per-byte unsigned comparison: a <= b ? 1 : 0 + vcmple4(a,b) per-byte unsigned comparison: a <= b ? 0xff : 0 + vsetlt4(a,b) per-byte unsigned comparison: a < b ? 1 : 0 + vcmplt4(a,b) per-byte unsigned comparison: a < b ? 0xff : 0 + vsetne4(a,b) per-byte unsigned comparison: a != b ? 1: 0 + vcmpne4(a,b) per-byte unsigned comparison: a != b ? 0xff: 0 + vmax4(a,b) per-byte unsigned maximum: max(a, b) + vmin4(a,b) per-byte unsigned minimum: min(a, b) +*/ + +namespace cv { namespace gpu { namespace cudev +{ + // 2 + + static __device__ __forceinline__ unsigned int vadd2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vadd2.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vadd.u32.u32.u32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vadd.u32.u32.u32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s; + s = a ^ b; // sum bits + r = a + b; // actual sum + s = s ^ r; // determine carry-ins for each bit position + s = s & 0x00010000; // carry-in to high word (= carry-out from low word) + r = r - s; // subtract out carry-out from low word + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsub2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vsub2.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vsub.u32.u32.u32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vsub.u32.u32.u32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s; + s = a ^ b; // sum bits + r = a - b; // actual sum + s = s ^ r; // determine carry-ins for each bit position + s = s & 0x00010000; // borrow to high word + r = r + s; // compensate for borrow from low word + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vabsdiff2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vabsdiff2.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vabsdiff.u32.u32.u32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vabsdiff.u32.u32.u32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s, t, u, v; + s = a & 0x0000ffff; // extract low halfword + r = b & 0x0000ffff; // extract low halfword + u = ::max(r, s); // maximum of low halfwords + v = ::min(r, s); // minimum of low halfwords + s = a & 0xffff0000; // extract high halfword + r = b & 0xffff0000; // extract high halfword + t = ::max(r, s); // maximum of high halfwords + s = ::min(r, s); // minimum of high halfwords + r = u | t; // maximum of both halfwords + s = v | s; // minimum of both halfwords + r = r - s; // |a - b| = max(a,b) - min(a,b); + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vavg2(unsigned int a, unsigned int b) + { + unsigned int r, s; + + // HAKMEM #23: a + b = 2 * (a & b) + (a ^ b) ==> + // (a + b) / 2 = (a & b) + ((a ^ b) >> 1) + s = a ^ b; + r = a & b; + s = s & 0xfffefffe; // ensure shift doesn't cross halfword boundaries + s = s >> 1; + s = r + s; + + return s; + } + + static __device__ __forceinline__ unsigned int vavrg2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vavrg2.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + // HAKMEM #23: a + b = 2 * (a | b) - (a ^ b) ==> + // (a + b + 1) / 2 = (a | b) - ((a ^ b) >> 1) + unsigned int s; + s = a ^ b; + r = a | b; + s = s & 0xfffefffe; // ensure shift doesn't cross half-word boundaries + s = s >> 1; + r = r - s; + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vseteq2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset2.u32.u32.eq %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + unsigned int c; + r = a ^ b; // 0x0000 if a == b + c = r | 0x80008000; // set msbs, to catch carry out + r = r ^ c; // extract msbs, msb = 1 if r < 0x8000 + c = c - 0x00010001; // msb = 0, if r was 0x0000 or 0x8000 + c = r & ~c; // msb = 1, if r was 0x0000 + r = c >> 15; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmpeq2(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vseteq2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask + #else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + r = a ^ b; // 0x0000 if a == b + c = r | 0x80008000; // set msbs, to catch carry out + r = r ^ c; // extract msbs, msb = 1 if r < 0x8000 + c = c - 0x00010001; // msb = 0, if r was 0x0000 or 0x8000 + c = r & ~c; // msb = 1, if r was 0x0000 + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetge2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset2.u32.u32.ge %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int c; + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavrg2(a, b); // (a + ~b + 1) / 2 = (a - b) / 2 + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmpge2(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetge2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask + #else + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavrg2(a, b); // (a + ~b + 1) / 2 = (a - b) / 2 + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetgt2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset2.u32.u32.gt %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int c; + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavg2(a, b); // (a + ~b) / 2 = (a - b) / 2 [rounded down] + c = c & 0x80008000; // msbs = carry-outs + r = c >> 15; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmpgt2(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetgt2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask + #else + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavg2(a, b); // (a + ~b) / 2 = (a - b) / 2 [rounded down] + c = c & 0x80008000; // msbs = carry-outs + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetle2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset2.u32.u32.le %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int c; + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavrg2(a, b); // (b + ~a + 1) / 2 = (b - a) / 2 + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmple2(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetle2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask + #else + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavrg2(a, b); // (b + ~a + 1) / 2 = (b - a) / 2 + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetlt2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset2.u32.u32.lt %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int c; + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavg2(a, b); // (b + ~a) / 2 = (b - a) / 2 [rounded down] + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmplt2(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetlt2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask + #else + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavg2(a, b); // (b + ~a) / 2 = (b - a) / 2 [rounded down] + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetne2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm ("vset2.u32.u32.ne %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + unsigned int c; + r = a ^ b; // 0x0000 if a == b + c = r | 0x80008000; // set msbs, to catch carry out + c = c - 0x00010001; // msb = 0, if r was 0x0000 or 0x8000 + c = r | c; // msb = 1, if r was not 0x0000 + c = c & 0x80008000; // extract msbs + r = c >> 15; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmpne2(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetne2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask + #else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + r = a ^ b; // 0x0000 if a == b + c = r | 0x80008000; // set msbs, to catch carry out + c = c - 0x00010001; // msb = 0, if r was 0x0000 or 0x8000 + c = r | c; // msb = 1, if r was not 0x0000 + c = c & 0x80008000; // extract msbs + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vmax2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vmax2.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vmax.u32.u32.u32 %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmax.u32.u32.u32 %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s, t, u; + r = a & 0x0000ffff; // extract low halfword + s = b & 0x0000ffff; // extract low halfword + t = ::max(r, s); // maximum of low halfwords + r = a & 0xffff0000; // extract high halfword + s = b & 0xffff0000; // extract high halfword + u = ::max(r, s); // maximum of high halfwords + r = t | u; // combine halfword maximums + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vmin2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vmin2.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vmin.u32.u32.u32 %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmin.u32.u32.u32 %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s, t, u; + r = a & 0x0000ffff; // extract low halfword + s = b & 0x0000ffff; // extract low halfword + t = ::min(r, s); // minimum of low halfwords + r = a & 0xffff0000; // extract high halfword + s = b & 0xffff0000; // extract high halfword + u = ::min(r, s); // minimum of high halfwords + r = t | u; // combine halfword minimums + #endif + + return r; + } + + // 4 + + static __device__ __forceinline__ unsigned int vadd4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vadd4.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vadd.u32.u32.u32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vadd.u32.u32.u32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vadd.u32.u32.u32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vadd.u32.u32.u32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s, t; + s = a ^ b; // sum bits + r = a & 0x7f7f7f7f; // clear msbs + t = b & 0x7f7f7f7f; // clear msbs + s = s & 0x80808080; // msb sum bits + r = r + t; // add without msbs, record carry-out in msbs + r = r ^ s; // sum of msb sum and carry-in bits, w/o carry-out + #endif /* __CUDA_ARCH__ >= 300 */ + + return r; + } + + static __device__ __forceinline__ unsigned int vsub4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vsub4.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vsub.u32.u32.u32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vsub.u32.u32.u32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vsub.u32.u32.u32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vsub.u32.u32.u32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s, t; + s = a ^ ~b; // inverted sum bits + r = a | 0x80808080; // set msbs + t = b & 0x7f7f7f7f; // clear msbs + s = s & 0x80808080; // inverted msb sum bits + r = r - t; // subtract w/o msbs, record inverted borrows in msb + r = r ^ s; // combine inverted msb sum bits and borrows + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vavg4(unsigned int a, unsigned int b) + { + unsigned int r, s; + + // HAKMEM #23: a + b = 2 * (a & b) + (a ^ b) ==> + // (a + b) / 2 = (a & b) + ((a ^ b) >> 1) + s = a ^ b; + r = a & b; + s = s & 0xfefefefe; // ensure following shift doesn't cross byte boundaries + s = s >> 1; + s = r + s; + + return s; + } + + static __device__ __forceinline__ unsigned int vavrg4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vavrg4.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + // HAKMEM #23: a + b = 2 * (a | b) - (a ^ b) ==> + // (a + b + 1) / 2 = (a | b) - ((a ^ b) >> 1) + unsigned int c; + c = a ^ b; + r = a | b; + c = c & 0xfefefefe; // ensure following shift doesn't cross byte boundaries + c = c >> 1; + r = r - c; + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vseteq4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset4.u32.u32.eq %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + unsigned int c; + r = a ^ b; // 0x00 if a == b + c = r | 0x80808080; // set msbs, to catch carry out + r = r ^ c; // extract msbs, msb = 1 if r < 0x80 + c = c - 0x01010101; // msb = 0, if r was 0x00 or 0x80 + c = r & ~c; // msb = 1, if r was 0x00 + r = c >> 7; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmpeq4(unsigned int a, unsigned int b) + { + unsigned int r, t; + + #if __CUDA_ARCH__ >= 300 + r = vseteq4(a, b); + t = r << 8; // convert bool + r = t - r; // to mask + #else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + t = a ^ b; // 0x00 if a == b + r = t | 0x80808080; // set msbs, to catch carry out + t = t ^ r; // extract msbs, msb = 1 if t < 0x80 + r = r - 0x01010101; // msb = 0, if t was 0x00 or 0x80 + r = t & ~r; // msb = 1, if t was 0x00 + t = r >> 7; // build mask + t = r - t; // from + r = t | r; // msbs + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetle4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset4.u32.u32.le %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int c; + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavrg4(a, b); // (b + ~a + 1) / 2 = (b - a) / 2 + c = c & 0x80808080; // msb = carry-outs + r = c >> 7; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmple4(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetle4(a, b); + c = r << 8; // convert bool + r = c - r; // to mask + #else + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavrg4(a, b); // (b + ~a + 1) / 2 = (b - a) / 2 + c = c & 0x80808080; // msbs = carry-outs + r = c >> 7; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetlt4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset4.u32.u32.lt %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int c; + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavg4(a, b); // (b + ~a) / 2 = (b - a) / 2 [rounded down] + c = c & 0x80808080; // msb = carry-outs + r = c >> 7; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmplt4(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetlt4(a, b); + c = r << 8; // convert bool + r = c - r; // to mask + #else + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavg4(a, b); // (b + ~a) / 2 = (b - a) / 2 [rounded down] + c = c & 0x80808080; // msbs = carry-outs + r = c >> 7; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetge4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset4.u32.u32.ge %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int c; + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavrg4(a, b); // (a + ~b + 1) / 2 = (a - b) / 2 + c = c & 0x80808080; // msb = carry-outs + r = c >> 7; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmpge4(unsigned int a, unsigned int b) + { + unsigned int r, s; + + #if __CUDA_ARCH__ >= 300 + r = vsetge4(a, b); + s = r << 8; // convert bool + r = s - r; // to mask + #else + asm ("not.b32 %0,%0;" : "+r"(b)); + r = vavrg4 (a, b); // (a + ~b + 1) / 2 = (a - b) / 2 + r = r & 0x80808080; // msb = carry-outs + s = r >> 7; // build mask + s = r - s; // from + r = s | r; // msbs + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetgt4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset4.u32.u32.gt %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int c; + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavg4(a, b); // (a + ~b) / 2 = (a - b) / 2 [rounded down] + c = c & 0x80808080; // msb = carry-outs + r = c >> 7; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmpgt4(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetgt4(a, b); + c = r << 8; // convert bool + r = c - r; // to mask + #else + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavg4(a, b); // (a + ~b) / 2 = (a - b) / 2 [rounded down] + c = c & 0x80808080; // msb = carry-outs + r = c >> 7; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetne4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset4.u32.u32.ne %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + unsigned int c; + r = a ^ b; // 0x00 if a == b + c = r | 0x80808080; // set msbs, to catch carry out + c = c - 0x01010101; // msb = 0, if r was 0x00 or 0x80 + c = r | c; // msb = 1, if r was not 0x00 + c = c & 0x80808080; // extract msbs + r = c >> 7; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmpne4(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetne4(a, b); + c = r << 8; // convert bool + r = c - r; // to mask + #else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + r = a ^ b; // 0x00 if a == b + c = r | 0x80808080; // set msbs, to catch carry out + c = c - 0x01010101; // msb = 0, if r was 0x00 or 0x80 + c = r | c; // msb = 1, if r was not 0x00 + c = c & 0x80808080; // extract msbs + r = c >> 7; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vabsdiff4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vabsdiff4.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vabsdiff.u32.u32.u32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vabsdiff.u32.u32.u32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vabsdiff.u32.u32.u32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vabsdiff.u32.u32.u32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s; + s = vcmpge4(a, b); // mask = 0xff if a >= b + r = a ^ b; // + s = (r & s) ^ b; // select a when a >= b, else select b => max(a,b) + r = s ^ r; // select a when b >= a, else select b => min(a,b) + r = s - r; // |a - b| = max(a,b) - min(a,b); + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vmax4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vmax4.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vmax.u32.u32.u32 %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmax.u32.u32.u32 %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmax.u32.u32.u32 %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmax.u32.u32.u32 %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s; + s = vcmpge4(a, b); // mask = 0xff if a >= b + r = a & s; // select a when b >= a + s = b & ~s; // select b when b < a + r = r | s; // combine byte selections + #endif + + return r; // byte-wise unsigned maximum + } + + static __device__ __forceinline__ unsigned int vmin4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vmin4.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vmin.u32.u32.u32 %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmin.u32.u32.u32 %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmin.u32.u32.u32 %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmin.u32.u32.u32 %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s; + s = vcmpge4(b, a); // mask = 0xff if a >= b + r = a & s; // select a when b >= a + s = b & ~s; // select b when b < a + r = r | s; // combine byte selections + #endif + + return r; + } +}}} + +#endif // __OPENCV_GPU_SIMD_FUNCTIONS_HPP__ diff --git a/modules/gpu/include/opencv2/gpu/device/transform.hpp b/modules/core/include/opencv2/core/cuda/transform.hpp similarity index 98% rename from modules/gpu/include/opencv2/gpu/device/transform.hpp rename to modules/core/include/opencv2/core/cuda/transform.hpp index 636caac63f..7c82e36469 100644 --- a/modules/gpu/include/opencv2/gpu/device/transform.hpp +++ b/modules/core/include/opencv2/core/cuda/transform.hpp @@ -47,7 +47,7 @@ #include "utility.hpp" #include "detail/transform_detail.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { template static inline void transform(PtrStepSz src, PtrStepSz dst, UnOp op, const Mask& mask, cudaStream_t stream) diff --git a/modules/gpu/include/opencv2/gpu/device/type_traits.hpp b/modules/core/include/opencv2/core/cuda/type_traits.hpp similarity index 98% rename from modules/gpu/include/opencv2/gpu/device/type_traits.hpp rename to modules/core/include/opencv2/core/cuda/type_traits.hpp index 1b36acca5d..8a58264bfc 100644 --- a/modules/gpu/include/opencv2/gpu/device/type_traits.hpp +++ b/modules/core/include/opencv2/core/cuda/type_traits.hpp @@ -45,7 +45,7 @@ #include "detail/type_traits_detail.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { template struct IsSimpleParameter { diff --git a/modules/gpu/include/opencv2/gpu/device/utility.hpp b/modules/core/include/opencv2/core/cuda/utility.hpp similarity index 96% rename from modules/gpu/include/opencv2/gpu/device/utility.hpp rename to modules/core/include/opencv2/core/cuda/utility.hpp index 83eaaa21ce..82c61a2014 100644 --- a/modules/gpu/include/opencv2/gpu/device/utility.hpp +++ b/modules/core/include/opencv2/core/cuda/utility.hpp @@ -46,7 +46,7 @@ #include "saturate_cast.hpp" #include "datamov_utils.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { #define OPENCV_GPU_LOG_WARP_SIZE (5) #define OPENCV_GPU_WARP_SIZE (1 << OPENCV_GPU_LOG_WARP_SIZE) @@ -124,8 +124,8 @@ namespace cv { namespace gpu { namespace device struct WithOutMask { - __device__ __forceinline__ WithOutMask(){} - __device__ __forceinline__ WithOutMask(const WithOutMask& mask){} + __host__ __device__ __forceinline__ WithOutMask(){} + __host__ __device__ __forceinline__ WithOutMask(const WithOutMask&){} __device__ __forceinline__ void next() const { @@ -208,6 +208,6 @@ namespace cv { namespace gpu { namespace device return false; } -}}} // namespace cv { namespace gpu { namespace device +}}} // namespace cv { namespace gpu { namespace cudev #endif // __OPENCV_GPU_UTILITY_HPP__ diff --git a/modules/gpu/include/opencv2/gpu/device/vec_distance.hpp b/modules/core/include/opencv2/core/cuda/vec_distance.hpp similarity index 98% rename from modules/gpu/include/opencv2/gpu/device/vec_distance.hpp rename to modules/core/include/opencv2/core/cuda/vec_distance.hpp index d5b4bb202c..4b88410207 100644 --- a/modules/gpu/include/opencv2/gpu/device/vec_distance.hpp +++ b/modules/core/include/opencv2/core/cuda/vec_distance.hpp @@ -47,7 +47,7 @@ #include "functional.hpp" #include "detail/vec_distance_detail.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { template struct L1Dist { @@ -219,6 +219,6 @@ namespace cv { namespace gpu { namespace device U vec1Vals[MAX_LEN / THREAD_DIM]; }; -}}} // namespace cv { namespace gpu { namespace device +}}} // namespace cv { namespace gpu { namespace cudev #endif // __OPENCV_GPU_VEC_DISTANCE_HPP__ diff --git a/modules/core/include/opencv2/core/cuda/vec_math.hpp b/modules/core/include/opencv2/core/cuda/vec_math.hpp new file mode 100644 index 0000000000..0dc92c3ef6 --- /dev/null +++ b/modules/core/include/opencv2/core/cuda/vec_math.hpp @@ -0,0 +1,922 @@ +/*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_GPU_VECMATH_HPP__ +#define __OPENCV_GPU_VECMATH_HPP__ + +#include "vec_traits.hpp" +#include "saturate_cast.hpp" + +namespace cv { namespace gpu { namespace cudev +{ + +// saturate_cast + +namespace vec_math_detail +{ + template struct SatCastHelper; + template struct SatCastHelper<1, VecD> + { + template static __device__ __forceinline__ VecD cast(const VecS& v) + { + typedef typename VecTraits::elem_type D; + return VecTraits::make(saturate_cast(v.x)); + } + }; + template struct SatCastHelper<2, VecD> + { + template static __device__ __forceinline__ VecD cast(const VecS& v) + { + typedef typename VecTraits::elem_type D; + return VecTraits::make(saturate_cast(v.x), saturate_cast(v.y)); + } + }; + template struct SatCastHelper<3, VecD> + { + template static __device__ __forceinline__ VecD cast(const VecS& v) + { + typedef typename VecTraits::elem_type D; + return VecTraits::make(saturate_cast(v.x), saturate_cast(v.y), saturate_cast(v.z)); + } + }; + template struct SatCastHelper<4, VecD> + { + template static __device__ __forceinline__ VecD cast(const VecS& v) + { + typedef typename VecTraits::elem_type D; + return VecTraits::make(saturate_cast(v.x), saturate_cast(v.y), saturate_cast(v.z), saturate_cast(v.w)); + } + }; + + template static __device__ __forceinline__ VecD saturate_cast_helper(const VecS& v) + { + return SatCastHelper::cn, VecD>::cast(v); + } +} + +template static __device__ __forceinline__ T saturate_cast(const uchar1& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const char1& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const ushort1& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const short1& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const uint1& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const int1& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const float1& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const double1& v) {return vec_math_detail::saturate_cast_helper(v);} + +template static __device__ __forceinline__ T saturate_cast(const uchar2& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const char2& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const ushort2& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const short2& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const uint2& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const int2& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const float2& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const double2& v) {return vec_math_detail::saturate_cast_helper(v);} + +template static __device__ __forceinline__ T saturate_cast(const uchar3& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const char3& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const ushort3& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const short3& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const uint3& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const int3& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const float3& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const double3& v) {return vec_math_detail::saturate_cast_helper(v);} + +template static __device__ __forceinline__ T saturate_cast(const uchar4& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const char4& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const ushort4& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const short4& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const uint4& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const int4& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const float4& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const double4& v) {return vec_math_detail::saturate_cast_helper(v);} + +// unary operators + +#define CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(op, input_type, output_type) \ + __device__ __forceinline__ output_type ## 1 operator op(const input_type ## 1 & a) \ + { \ + return VecTraits::make(op (a.x)); \ + } \ + __device__ __forceinline__ output_type ## 2 operator op(const input_type ## 2 & a) \ + { \ + return VecTraits::make(op (a.x), op (a.y)); \ + } \ + __device__ __forceinline__ output_type ## 3 operator op(const input_type ## 3 & a) \ + { \ + return VecTraits::make(op (a.x), op (a.y), op (a.z)); \ + } \ + __device__ __forceinline__ output_type ## 4 operator op(const input_type ## 4 & a) \ + { \ + return VecTraits::make(op (a.x), op (a.y), op (a.z), op (a.w)); \ + } + +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(-, char, char) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(-, short, short) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(-, int, int) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(-, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(-, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, char, char) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, short, short) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, int, int) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, uint, uint) + +#undef CV_CUDEV_IMPLEMENT_VEC_UNARY_OP + +// unary functions + +#define CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(func_name, func, input_type, output_type) \ + __device__ __forceinline__ output_type ## 1 func_name(const input_type ## 1 & a) \ + { \ + return VecTraits::make(func (a.x)); \ + } \ + __device__ __forceinline__ output_type ## 2 func_name(const input_type ## 2 & a) \ + { \ + return VecTraits::make(func (a.x), func (a.y)); \ + } \ + __device__ __forceinline__ output_type ## 3 func_name(const input_type ## 3 & a) \ + { \ + return VecTraits::make(func (a.x), func (a.y), func (a.z)); \ + } \ + __device__ __forceinline__ output_type ## 4 func_name(const input_type ## 4 & a) \ + { \ + return VecTraits::make(func (a.x), func (a.y), func (a.z), func (a.w)); \ + } + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, /*::abs*/, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, ::abs, char, char) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, /*::abs*/, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, ::abs, short, short) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, ::abs, int, int) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, /*::abs*/, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, ::fabsf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, ::fabs, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrt, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::exp, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::log, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sin, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cos, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tan, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asin, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acos, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atan, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinh, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::cosh, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanh, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinh, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acosh, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanh, double, double) + +#undef CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC + +// binary operators (vec & vec) + +#define CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(op, input_type, output_type) \ + __device__ __forceinline__ output_type ## 1 operator op(const input_type ## 1 & a, const input_type ## 1 & b) \ + { \ + return VecTraits::make(a.x op b.x); \ + } \ + __device__ __forceinline__ output_type ## 2 operator op(const input_type ## 2 & a, const input_type ## 2 & b) \ + { \ + return VecTraits::make(a.x op b.x, a.y op b.y); \ + } \ + __device__ __forceinline__ output_type ## 3 operator op(const input_type ## 3 & a, const input_type ## 3 & b) \ + { \ + return VecTraits::make(a.x op b.x, a.y op b.y, a.z op b.z); \ + } \ + __device__ __forceinline__ output_type ## 4 operator op(const input_type ## 4 & a, const input_type ## 4 & b) \ + { \ + return VecTraits::make(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); \ + } + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, uchar, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, char, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, ushort, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, short, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, uchar, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, char, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, ushort, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, short, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, uchar, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, char, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, ushort, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, short, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, uchar, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, char, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, ushort, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, short, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, char, char) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, short, short) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, uint, uint) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, char, char) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, short, short) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, uint, uint) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, char, char) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, short, short) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, uint, uint) + +#undef CV_CUDEV_IMPLEMENT_VEC_BINARY_OP + +// binary operators (vec & scalar) + +#define CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(op, input_type, scalar_type, output_type) \ + __device__ __forceinline__ output_type ## 1 operator op(const input_type ## 1 & a, scalar_type s) \ + { \ + return VecTraits::make(a.x op s); \ + } \ + __device__ __forceinline__ output_type ## 1 operator op(scalar_type s, const input_type ## 1 & b) \ + { \ + return VecTraits::make(s op b.x); \ + } \ + __device__ __forceinline__ output_type ## 2 operator op(const input_type ## 2 & a, scalar_type s) \ + { \ + return VecTraits::make(a.x op s, a.y op s); \ + } \ + __device__ __forceinline__ output_type ## 2 operator op(scalar_type s, const input_type ## 2 & b) \ + { \ + return VecTraits::make(s op b.x, s op b.y); \ + } \ + __device__ __forceinline__ output_type ## 3 operator op(const input_type ## 3 & a, scalar_type s) \ + { \ + return VecTraits::make(a.x op s, a.y op s, a.z op s); \ + } \ + __device__ __forceinline__ output_type ## 3 operator op(scalar_type s, const input_type ## 3 & b) \ + { \ + return VecTraits::make(s op b.x, s op b.y, s op b.z); \ + } \ + __device__ __forceinline__ output_type ## 4 operator op(const input_type ## 4 & a, scalar_type s) \ + { \ + return VecTraits::make(a.x op s, a.y op s, a.z op s, a.w op s); \ + } \ + __device__ __forceinline__ output_type ## 4 operator op(scalar_type s, const input_type ## 4 & b) \ + { \ + return VecTraits::make(s op b.x, s op b.y, s op b.z, s op b.w); \ + } + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uchar, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, char, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, ushort, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, short, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uchar, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, char, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, ushort, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, short, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uchar, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, char, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, ushort, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, short, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uchar, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, char, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, ushort, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, short, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, char, char, char) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, ushort, ushort, ushort) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, short, short, short) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, uint, uint, uint) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, char, char, char) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, ushort, ushort, ushort) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, short, short, short) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, uint, uint, uint) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, char, char, char) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, ushort, ushort, ushort) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, short, short, short) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, uint, uint, uint) + +#undef CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP + +// binary function (vec & vec) + +#define CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(func_name, func, input_type, output_type) \ + __device__ __forceinline__ output_type ## 1 func_name(const input_type ## 1 & a, const input_type ## 1 & b) \ + { \ + return VecTraits::make(func (a.x, b.x)); \ + } \ + __device__ __forceinline__ output_type ## 2 func_name(const input_type ## 2 & a, const input_type ## 2 & b) \ + { \ + return VecTraits::make(func (a.x, b.x), func (a.y, b.y)); \ + } \ + __device__ __forceinline__ output_type ## 3 func_name(const input_type ## 3 & a, const input_type ## 3 & b) \ + { \ + return VecTraits::make(func (a.x, b.x), func (a.y, b.y), func (a.z, b.z)); \ + } \ + __device__ __forceinline__ output_type ## 4 func_name(const input_type ## 4 & a, const input_type ## 4 & b) \ + { \ + return VecTraits::make(func (a.x, b.x), func (a.y, b.y), func (a.z, b.z), func (a.w, b.w)); \ + } + +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, char, char) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, short, short) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::fmaxf, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::fmax, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, char, char) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, short, short) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::fminf, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::fmin, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, char, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, short, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, int, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypot, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, char, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, short, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, uint, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, int, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2, double, double) + +#undef CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC + +// binary function (vec & scalar) + +#define CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(func_name, func, input_type, scalar_type, output_type) \ + __device__ __forceinline__ output_type ## 1 func_name(const input_type ## 1 & a, scalar_type s) \ + { \ + return VecTraits::make(func ((output_type) a.x, (output_type) s)); \ + } \ + __device__ __forceinline__ output_type ## 1 func_name(scalar_type s, const input_type ## 1 & b) \ + { \ + return VecTraits::make(func ((output_type) s, (output_type) b.x)); \ + } \ + __device__ __forceinline__ output_type ## 2 func_name(const input_type ## 2 & a, scalar_type s) \ + { \ + return VecTraits::make(func ((output_type) a.x, (output_type) s), func ((output_type) a.y, (output_type) s)); \ + } \ + __device__ __forceinline__ output_type ## 2 func_name(scalar_type s, const input_type ## 2 & b) \ + { \ + return VecTraits::make(func ((output_type) s, (output_type) b.x), func ((output_type) s, (output_type) b.y)); \ + } \ + __device__ __forceinline__ output_type ## 3 func_name(const input_type ## 3 & a, scalar_type s) \ + { \ + return VecTraits::make(func ((output_type) a.x, (output_type) s), func ((output_type) a.y, (output_type) s), func ((output_type) a.z, (output_type) s)); \ + } \ + __device__ __forceinline__ output_type ## 3 func_name(scalar_type s, const input_type ## 3 & b) \ + { \ + return VecTraits::make(func ((output_type) s, (output_type) b.x), func ((output_type) s, (output_type) b.y), func ((output_type) s, (output_type) b.z)); \ + } \ + __device__ __forceinline__ output_type ## 4 func_name(const input_type ## 4 & a, scalar_type s) \ + { \ + return VecTraits::make(func ((output_type) a.x, (output_type) s), func ((output_type) a.y, (output_type) s), func ((output_type) a.z, (output_type) s), func ((output_type) a.w, (output_type) s)); \ + } \ + __device__ __forceinline__ output_type ## 4 func_name(scalar_type s, const input_type ## 4 & b) \ + { \ + return VecTraits::make(func ((output_type) s, (output_type) b.x), func ((output_type) s, (output_type) b.y), func ((output_type) s, (output_type) b.z), func ((output_type) s, (output_type) b.w)); \ + } + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, char, char, char) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, ushort, ushort, ushort) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, short, short, short) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, char, char, char) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, ushort, ushort, ushort) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, short, short, short) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, double, double, double) + +#undef CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC + +}}} // namespace cv { namespace gpu { namespace device + +#endif // __OPENCV_GPU_VECMATH_HPP__ diff --git a/modules/gpu/include/opencv2/gpu/device/vec_traits.hpp b/modules/core/include/opencv2/core/cuda/vec_traits.hpp similarity index 99% rename from modules/gpu/include/opencv2/gpu/device/vec_traits.hpp rename to modules/core/include/opencv2/core/cuda/vec_traits.hpp index 8d179c83f5..304b05c919 100644 --- a/modules/gpu/include/opencv2/gpu/device/vec_traits.hpp +++ b/modules/core/include/opencv2/core/cuda/vec_traits.hpp @@ -45,7 +45,7 @@ #include "common.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { template struct TypeVec; @@ -275,6 +275,6 @@ namespace cv { namespace gpu { namespace device static __device__ __host__ __forceinline__ char8 make(schar a0, schar a1, schar a2, schar a3, schar a4, schar a5, schar a6, schar a7) {return make_char8(a0, a1, a2, a3, a4, a5, a6, a7);} static __device__ __host__ __forceinline__ char8 make(const schar* v) {return make_char8(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);} }; -}}} // namespace cv { namespace gpu { namespace device +}}} // namespace cv { namespace gpu { namespace cudev #endif // __OPENCV_GPU_VEC_TRAITS_HPP__ diff --git a/modules/gpu/include/opencv2/gpu/device/warp.hpp b/modules/core/include/opencv2/core/cuda/warp.hpp similarity index 97% rename from modules/gpu/include/opencv2/gpu/device/warp.hpp rename to modules/core/include/opencv2/core/cuda/warp.hpp index 0f1dc794ab..6d2b7745f1 100644 --- a/modules/gpu/include/opencv2/gpu/device/warp.hpp +++ b/modules/core/include/opencv2/core/cuda/warp.hpp @@ -43,7 +43,7 @@ #ifndef __OPENCV_GPU_DEVICE_WARP_HPP__ #define __OPENCV_GPU_DEVICE_WARP_HPP__ -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { struct Warp { @@ -126,6 +126,6 @@ namespace cv { namespace gpu { namespace device *t = value; } }; -}}} // namespace cv { namespace gpu { namespace device +}}} // namespace cv { namespace gpu { namespace cudev #endif /* __OPENCV_GPU_DEVICE_WARP_HPP__ */ diff --git a/modules/gpu/include/opencv2/gpu/device/warp_reduce.hpp b/modules/core/include/opencv2/core/cuda/warp_reduce.hpp similarity index 92% rename from modules/gpu/include/opencv2/gpu/device/warp_reduce.hpp rename to modules/core/include/opencv2/core/cuda/warp_reduce.hpp index 7ac85b095d..82185e8c0c 100644 --- a/modules/gpu/include/opencv2/gpu/device/warp_reduce.hpp +++ b/modules/core/include/opencv2/core/cuda/warp_reduce.hpp @@ -28,7 +28,7 @@ // 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 bpied warranties, including, but not limited to, the bpied +// 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 @@ -40,11 +40,10 @@ // //M*/ - #ifndef OPENCV_GPU_WARP_REDUCE_HPP__ #define OPENCV_GPU_WARP_REDUCE_HPP__ -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { template __device__ __forceinline__ T warp_reduce(volatile T *ptr , const unsigned int tid = threadIdx.x) @@ -64,6 +63,6 @@ namespace cv { namespace gpu { namespace device return ptr[tid - lane]; } -}}} // namespace cv { namespace gpu { namespace device { +}}} // namespace cv { namespace gpu { namespace cudev { -#endif /* OPENCV_GPU_WARP_REDUCE_HPP__ */ \ No newline at end of file +#endif /* OPENCV_GPU_WARP_REDUCE_HPP__ */ diff --git a/modules/gpu/include/opencv2/gpu/device/warp_shuffle.hpp b/modules/core/include/opencv2/core/cuda/warp_shuffle.hpp similarity index 99% rename from modules/gpu/include/opencv2/gpu/device/warp_shuffle.hpp rename to modules/core/include/opencv2/core/cuda/warp_shuffle.hpp index 8b4479a79b..aabcacfa4b 100644 --- a/modules/gpu/include/opencv2/gpu/device/warp_shuffle.hpp +++ b/modules/core/include/opencv2/core/cuda/warp_shuffle.hpp @@ -43,7 +43,7 @@ #ifndef __OPENCV_GPU_WARP_SHUFFLE_HPP__ #define __OPENCV_GPU_WARP_SHUFFLE_HPP__ -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { template __device__ __forceinline__ T shfl(T val, int srcLane, int width = warpSize) diff --git a/modules/core/include/opencv2/core/cvdef.h b/modules/core/include/opencv2/core/cvdef.h index 06b2b5f255..46f294962d 100644 --- a/modules/core/include/opencv2/core/cvdef.h +++ b/modules/core/include/opencv2/core/cvdef.h @@ -73,8 +73,10 @@ # define CV_ENABLE_UNROLLED 1 #endif -#if (defined WIN32 || defined _WIN32 || defined WINCE) && defined CVAPI_EXPORTS +#if (defined WIN32 || defined _WIN32 || defined WINCE || defined __CYGWIN__) && defined CVAPI_EXPORTS # define CV_EXPORTS __declspec(dllexport) +#elif defined __GNUC__ && __GNUC__ >= 4 +# define CV_EXPORTS __attribute__ ((visibility ("default"))) #else # define CV_EXPORTS #endif @@ -82,7 +84,7 @@ #ifndef CV_INLINE # if defined __cplusplus # define CV_INLINE static inline -# elif (defined WIN32 || defined _WIN32 || defined WINCE) && !defined __GNUC__ +# elif defined _MSC_VER # define CV_INLINE __inline # else # define CV_INLINE static @@ -97,17 +99,33 @@ # endif #endif -/* intrinsics support */ +/* CPU features and intrinsics support */ +#define CV_CPU_NONE 0 +#define CV_CPU_MMX 1 +#define CV_CPU_SSE 2 +#define CV_CPU_SSE2 3 +#define CV_CPU_SSE3 4 +#define CV_CPU_SSSE3 5 +#define CV_CPU_SSE4_1 6 +#define CV_CPU_SSE4_2 7 +#define CV_CPU_POPCNT 8 +#define CV_CPU_AVX 10 +#define CV_CPU_NEON 11 +#define CV_HARDWARE_MAX_FEATURE 255 + +// do not include SSE/AVX/NEON headers for NVCC compiler +#ifndef __CUDACC__ + #if defined __SSE2__ || defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP >= 2) -# include "emmintrin.h" +# include # define CV_SSE 1 # define CV_SSE2 1 # if defined __SSE3__ || (defined _MSC_VER && _MSC_VER >= 1500) -# include "pmmintrin.h" +# include # define CV_SSE3 1 # endif # if defined __SSSE3__ || (defined _MSC_VER && _MSC_VER >= 1500) -# include "tmmintrin.h" +# include # define CV_SSSE3 1 # endif # if defined __SSE4_1__ || (defined _MSC_VER && _MSC_VER >= 1500) @@ -131,11 +149,18 @@ # endif #endif -#ifdef __ARM_NEON__ +#if (defined WIN32 || defined _WIN32) && defined(_M_ARM) +# include +# include "arm_neon.h" +# define CV_NEON 1 +# define CPU_HAS_NEON_FEATURE (true) +#elif defined(__ARM_NEON__) # include # define CV_NEON 1 #endif +#endif // __CUDACC__ + #ifndef CV_SSE # define CV_SSE 0 #endif @@ -174,7 +199,15 @@ */ #if !defined _MSC_VER && !defined __BORLANDC__ -# include +# if defined __cplusplus && __cplusplus >= 201103L +# include + typedef std::uint32_t uint; +# else +# include + typedef uint32_t uint; +# endif +#else + typedef unsigned uint; #endif typedef signed char schar; @@ -305,17 +338,27 @@ typedef signed char schar; #if defined __BORLANDC__ # include +#elif defined __cplusplus +# include #else # include #endif +#ifndef MIN +# define MIN(a,b) ((a) > (b) ? (b) : (a)) +#endif + +#ifndef MAX +# define MAX(a,b) ((a) < (b) ? (b) : (a)) +#endif + #ifdef HAVE_TEGRA_OPTIMIZATION # include "tegra_round.hpp" #endif CV_INLINE int cvRound( double value ) { -#if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__ && defined __SSE2__ && !defined __APPLE__) +#if ((defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__ && defined __SSE2__ && !defined __APPLE__)) && !defined(__CUDACC__) __m128d t = _mm_set_sd( value ); return _mm_cvtsd_si32(t); #elif defined _MSC_VER && defined _M_IX86 @@ -326,21 +369,27 @@ CV_INLINE int cvRound( double value ) fistp t; } return t; -#elif defined HAVE_LRINT || defined CV_ICC || defined __GNUC__ +#elif defined _MSC_VER && defined _M_ARM && defined HAVE_TEGRA_OPTIMIZATION + TEGRA_ROUND(value); +#elif defined CV_ICC || defined __GNUC__ # ifdef HAVE_TEGRA_OPTIMIZATION TEGRA_ROUND(value); # else return (int)lrint(value); # endif #else - // while this is not IEEE754-compliant rounding, it's usually a good enough approximation - return (int)(value + (value >= 0 ? 0.5 : -0.5)); + double intpart, fractpart; + fractpart = modf(value, &intpart); + if ((fabs(fractpart) != 0.5) || ((((int)intpart) % 2) != 0)) + return (int)(value + (value >= 0 ? 0.5 : -0.5)); + else + return (int)intpart; #endif } CV_INLINE int cvFloor( double value ) { -#if defined _MSC_VER && defined _M_X64 || (defined __GNUC__ && defined __SSE2__ && !defined __APPLE__) +#if (defined _MSC_VER && defined _M_X64 || (defined __GNUC__ && defined __SSE2__ && !defined __APPLE__)) && !defined(__CUDACC__) __m128d t = _mm_set_sd( value ); int i = _mm_cvtsd_si32(t); return i - _mm_movemask_pd(_mm_cmplt_sd(t, _mm_cvtsi32_sd(t,i))); @@ -356,7 +405,7 @@ CV_INLINE int cvFloor( double value ) CV_INLINE int cvCeil( double value ) { -#if defined _MSC_VER && defined _M_X64 || (defined __GNUC__ && defined __SSE2__&& !defined __APPLE__) +#if (defined _MSC_VER && defined _M_X64 || (defined __GNUC__ && defined __SSE2__&& !defined __APPLE__)) && !defined(__CUDACC__) __m128d t = _mm_set_sd( value ); int i = _mm_cvtsd_si32(t); return i + _mm_movemask_pd(_mm_cmplt_sd(_mm_cvtsi32_sd(t,i), t)); @@ -401,11 +450,11 @@ CV_INLINE int cvIsInf( double value ) # define CV_XADD(addr, delta) __atomic_fetch_add((_Atomic(int)*)(addr), delta, 4) # endif # else -# ifdef __ATOMIC_ACQ_REL +# if defined __ATOMIC_ACQ_REL && !defined __clang__ // version for gcc >= 4.7 -# define CV_XADD(addr, delta) __atomic_fetch_add(addr, delta, __ATOMIC_ACQ_REL) +# define CV_XADD(addr, delta) (int)__atomic_fetch_add((unsigned*)(addr), (unsigned)(delta), __ATOMIC_ACQ_REL) # else -# define CV_XADD(addr, delta) __sync_fetch_and_add(addr, delta) +# define CV_XADD(addr, delta) (int)__sync_fetch_and_add((unsigned*)(addr), (unsigned)(delta)) # endif # endif #elif (defined WIN32 || defined _WIN32 || defined WINCE) && (!defined RC_INVOKED) @@ -421,4 +470,4 @@ CV_INLINE int cvIsInf( double value ) CV_INLINE CV_XADD(int* addr, int delta) { int tmp = *addr; *addr += delta; return tmp; } #endif -#endif // __OPENCV_CORE_CVDEF_H__ \ No newline at end of file +#endif // __OPENCV_CORE_CVDEF_H__ diff --git a/modules/core/include/opencv2/core/cvstd.hpp b/modules/core/include/opencv2/core/cvstd.hpp new file mode 100644 index 0000000000..afdeb2549a --- /dev/null +++ b/modules/core/include/opencv2/core/cvstd.hpp @@ -0,0 +1,882 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_CVSTD_HPP__ +#define __OPENCV_CORE_CVSTD_HPP__ + +#ifndef __cplusplus +# error cvstd.hpp header must be compiled as C++ +#endif + +#include "opencv2/core/cvdef.h" + +#include +#include +#include + +#ifndef OPENCV_NOSTL +# include +#endif + +// import useful primitives from stl +#ifndef OPENCV_NOSTL_TRANSITIONAL +# include +# include +# include //for abs(int) +# include + +namespace cv +{ + using std::min; + using std::max; + using std::abs; + using std::swap; + using std::sqrt; + using std::exp; + using std::pow; + using std::log; +} + +namespace std +{ + static inline uchar abs(uchar a) { return a; } + static inline ushort abs(ushort a) { return a; } + static inline unsigned abs(unsigned a) { return a; } + static inline uint64 abs(uint64 a) { return a; } +} + +#else +namespace cv +{ + template static inline T min(T a, T b) { return a < b ? a : b; } + template static inline T max(T a, T b) { return a > b ? a : b; } + template static inline T abs(T a) { return a < 0 ? -a : a; } + template static inline void swap(T& a, T& b) { T tmp = a; a = b; b = tmp; } + + template<> inline uchar abs(uchar a) { return a; } + template<> inline ushort abs(ushort a) { return a; } + template<> inline unsigned abs(unsigned a) { return a; } + template<> inline uint64 abs(uint64 a) { return a; } +} +#endif + +namespace cv { + +//////////////////////////// memory management functions //////////////////////////// + +/*! + Allocates memory buffer + + This is specialized OpenCV memory allocation function that returns properly aligned memory buffers. + The usage is identical to malloc(). The allocated buffers must be freed with cv::fastFree(). + If there is not enough memory, the function calls cv::error(), which raises an exception. + + \param bufSize buffer size in bytes + \return the allocated memory buffer. +*/ +CV_EXPORTS void* fastMalloc(size_t bufSize); + +/*! + Frees the memory allocated with cv::fastMalloc + + This is the corresponding deallocation function for cv::fastMalloc(). + When ptr==NULL, the function has no effect. +*/ +CV_EXPORTS void fastFree(void* ptr); + +/*! + The STL-compilant memory Allocator based on cv::fastMalloc() and cv::fastFree() +*/ +template class Allocator +{ +public: + typedef _Tp value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + template class rebind { typedef Allocator other; }; + + explicit Allocator() {} + ~Allocator() {} + explicit Allocator(Allocator const&) {} + template + explicit Allocator(Allocator const&) {} + + // address + pointer address(reference r) { return &r; } + const_pointer address(const_reference r) { return &r; } + + pointer allocate(size_type count, const void* =0) { return reinterpret_cast(fastMalloc(count * sizeof (_Tp))); } + void deallocate(pointer p, size_type) { fastFree(p); } + + void construct(pointer p, const _Tp& v) { new(static_cast(p)) _Tp(v); } + void destroy(pointer p) { p->~_Tp(); } + + size_type max_size() const { return cv::max(static_cast<_Tp>(-1)/sizeof(_Tp), 1); } +}; + +namespace detail +{ + +// Metafunction to avoid taking a reference to void. +template +struct RefOrVoid { typedef T& type; }; + +template<> +struct RefOrVoid{ typedef void type; }; + +template<> +struct RefOrVoid{ typedef const void type; }; + +template<> +struct RefOrVoid{ typedef volatile void type; }; + +template<> +struct RefOrVoid{ typedef const volatile void type; }; + +// This class would be private to Ptr, if it didn't have to be a non-template. +struct PtrOwner; + +} + +template +struct DefaultDeleter +{ + void operator () (Y* p) const; +}; + +/* + A smart shared pointer class with reference counting. + + A Ptr stores a pointer and owns a (potentially different) pointer. + The stored pointer has type T and is the one returned by get() et al, + while the owned pointer can have any type and is the one deleted + when there are no more Ptrs that own it. You can't directly obtain the + owned pointer. + + The interface of this class is mostly a subset of that of C++11's + std::shared_ptr. +*/ +template +struct Ptr +{ + /* Generic programming support. */ + typedef T element_type; + + /* Ptr that owns NULL and stores NULL. */ + Ptr(); + + /* Ptr that owns p and stores p. The owned pointer will be deleted with + DefaultDeleter. Y must be a complete type and Y* must be + convertible to T*. */ + template + explicit Ptr(Y* p); + + /* Ptr that owns p and stores p. The owned pointer will be deleted by + calling d(p). Y* must be convertible to T*. */ + template + Ptr(Y* p, D d); + + /* Same as the constructor below; it exists to suppress the generation + of the implicit copy constructor. */ + Ptr(const Ptr& o); + + /* Ptr that owns the same pointer as o and stores the same pointer as o, + converted to T*. Naturally, Y* must be convertible to T*. */ + template + Ptr(const Ptr& o); + + /* Ptr that owns same pointer as o, and stores p. Useful for casts and + creating non-owning Ptrs. */ + template + Ptr(const Ptr& o, T* p); + + /* Equivalent to release(). */ + ~Ptr(); + + /* Same as assignment below; exists to suppress the generation of the + implicit assignment operator. */ + Ptr& operator = (const Ptr& o); + + template + Ptr& operator = (const Ptr& o); + + /* Resets both the owned and stored pointers to NULL. Deletes the owned + pointer with the associated deleter if it's not owned by any other + Ptr and is non-zero. It's called reset() in std::shared_ptr; here + it is release() for compatibility with old OpenCV versions. */ + void release(); + + /* Equivalent to assigning from Ptr(p). */ + template + void reset(Y* p); + + /* Equivalent to assigning from Ptr(p, d). */ + template + void reset(Y* p, D d); + + /* Swaps the stored and owned pointers of this and o. */ + void swap(Ptr& o); + + /* Returns the stored pointer. */ + T* get() const; + + /* Ordinary pointer emulation. */ + typename detail::RefOrVoid::type operator * () const; + T* operator -> () const; + + /* Equivalent to get(). */ + operator T* () const; + + /* Equivalent to !*this. */ + bool empty() const; + + /* Returns a Ptr that owns the same pointer as this, and stores the same + pointer as this, except converted via static_cast to Y*. */ + template + Ptr staticCast() const; + + /* Ditto for const_cast. */ + template + Ptr constCast() const; + + /* Ditto for dynamic_cast. */ + template + Ptr dynamicCast() const; + +private: + detail::PtrOwner* owner; + T* stored; + + template + friend struct Ptr; // have to do this for the cross-type copy constructor +}; + +/* Overload of the generic swap. */ +template +void swap(Ptr& ptr1, Ptr& ptr2); + +/* Obvious comparisons. */ +template +bool operator == (const Ptr& ptr1, const Ptr& ptr2); +template +bool operator != (const Ptr& ptr1, const Ptr& ptr2); + +/* Convenience creation functions. In the far future, there may be variadic templates here. */ +template +Ptr makePtr(); +template +Ptr makePtr(const A1& a1); +template +Ptr makePtr(const A1& a1, const A2& a2); +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3); +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4); +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5); +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6); +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7); +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8); +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9); +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10); + + +//////////////////////////////// string class //////////////////////////////// + +class CV_EXPORTS FileNode; //for string constructor from FileNode + +class CV_EXPORTS String +{ +public: + typedef char value_type; + typedef char& reference; + typedef const char& const_reference; + typedef char* pointer; + typedef const char* const_pointer; + typedef ptrdiff_t difference_type; + typedef size_t size_type; + typedef char* iterator; + typedef const char* const_iterator; + + static const size_t npos = size_t(-1); + + explicit String(); + String(const String& str); + String(const String& str, size_t pos, size_t len = npos); + String(const char* s); + String(const char* s, size_t n); + String(size_t n, char c); + String(const char* first, const char* last); + template String(Iterator first, Iterator last); + explicit String(const FileNode& fn); + ~String(); + + String& operator=(const String& str); + String& operator=(const char* s); + String& operator=(char c); + + size_t size() const; + size_t length() const; + + char operator[](size_t idx) const; + char operator[](int idx) const; + + const char* begin() const; + const char* end() const; + + const char* c_str() const; + + bool empty() const; + void clear(); + + int compare(const char* s) const; + int compare(const String& str) const; + + void swap(String& str); + String substr(size_t pos = 0, size_t len = npos) const; + + size_t find(const char* s, size_t pos, size_t n) const; + size_t find(char c, size_t pos = 0) const; + size_t find(const String& str, size_t pos = 0) const; + size_t find(const char* s, size_t pos = 0) const; + + size_t rfind(const char* s, size_t pos, size_t n) const; + size_t rfind(char c, size_t pos = npos) const; + size_t rfind(const String& str, size_t pos = npos) const; + size_t rfind(const char* s, size_t pos = npos) const; + + size_t find_first_of(const char* s, size_t pos, size_t n) const; + size_t find_first_of(char c, size_t pos = 0) const; + size_t find_first_of(const String& str, size_t pos = 0) const; + size_t find_first_of(const char* s, size_t pos = 0) const; + + size_t find_last_of(const char* s, size_t pos, size_t n) const; + size_t find_last_of(char c, size_t pos = npos) const; + size_t find_last_of(const String& str, size_t pos = npos) const; + size_t find_last_of(const char* s, size_t pos = npos) const; + + friend String operator+ (const String& lhs, const String& rhs); + friend String operator+ (const String& lhs, const char* rhs); + friend String operator+ (const char* lhs, const String& rhs); + friend String operator+ (const String& lhs, char rhs); + friend String operator+ (char lhs, const String& rhs); + + String toLowerCase() const; + +#ifndef OPENCV_NOSTL + String(const std::string& str); + String(const std::string& str, size_t pos, size_t len = npos); + String& operator=(const std::string& str); + operator std::string() const; + + friend String operator+ (const String& lhs, const std::string& rhs); + friend String operator+ (const std::string& lhs, const String& rhs); +#endif + +private: + char* cstr_; + size_t len_; + + char* allocate(size_t len); // len without trailing 0 + void deallocate(); +}; + + +////////////////////////// cv::String implementation ///////////////////////// + +inline +String::String() + : cstr_(0), len_(0) +{} + +inline +String::String(const String& str) + : cstr_(str.cstr_), len_(str.len_) +{ + if (cstr_) + CV_XADD(((int*)cstr_)-1, 1); +} + +inline +String::String(const String& str, size_t pos, size_t len) + : cstr_(0), len_(0) +{ + pos = min(pos, str.len_); + len = min(str.len_ - pos, len); + if (!len) return; + if (len == str.len_) + { + CV_XADD(((int*)str.cstr_)-1, 1); + cstr_ = str.cstr_; + len_ = str.len_; + return; + } + memcpy(allocate(len), str.cstr_ + pos, len); +} + +inline +String::String(const char* s) + : cstr_(0), len_(0) +{ + if (!s) return; + size_t len = strlen(s); + memcpy(allocate(len), s, len); +} + +inline +String::String(const char* s, size_t n) + : cstr_(0), len_(0) +{ + if (!n) return; + memcpy(allocate(n), s, n); +} + +inline +String::String(size_t n, char c) + : cstr_(0), len_(0) +{ + memset(allocate(n), c, n); +} + +inline +String::String(const char* first, const char* last) + : cstr_(0), len_(0) +{ + size_t len = (size_t)(last - first); + memcpy(allocate(len), first, len); +} + +template inline +String::String(Iterator first, Iterator last) + : cstr_(0), len_(0) +{ + size_t len = (size_t)(last - first); + char* str = allocate(len); + while (first != last) + { + *str++ = *first; + ++first; + } +} + +inline +String::~String() +{ + deallocate(); +} + +inline +String& String::operator=(const String& str) +{ + if (&str == this) return *this; + + deallocate(); + if (str.cstr_) CV_XADD(((int*)str.cstr_)-1, 1); + cstr_ = str.cstr_; + len_ = str.len_; + return *this; +} + +inline +String& String::operator=(const char* s) +{ + deallocate(); + if (!s) return *this; + size_t len = strlen(s); + memcpy(allocate(len), s, len); + return *this; +} + +inline +String& String::operator=(char c) +{ + deallocate(); + allocate(1)[0] = c; + return *this; +} + +inline +size_t String::size() const +{ + return len_; +} + +inline +size_t String::length() const +{ + return len_; +} + +inline +char String::operator[](size_t idx) const +{ + return cstr_[idx]; +} + +inline +char String::operator[](int idx) const +{ + return cstr_[idx]; +} + +inline +const char* String::begin() const +{ + return cstr_; +} + +inline +const char* String::end() const +{ + return len_ ? cstr_ + 1 : 0; +} + +inline +bool String::empty() const +{ + return len_ == 0; +} + +inline +const char* String::c_str() const +{ + return cstr_ ? cstr_ : ""; +} + +inline +void String::swap(String& str) +{ + cv::swap(cstr_, str.cstr_); + cv::swap(len_, str.len_); +} + +inline +void String::clear() +{ + deallocate(); +} + +inline +int String::compare(const char* s) const +{ + if (cstr_ == s) return 0; + return strcmp(c_str(), s); +} + +inline +int String::compare(const String& str) const +{ + if (cstr_ == str.cstr_) return 0; + return strcmp(c_str(), str.c_str()); +} + +inline +String String::substr(size_t pos, size_t len) const +{ + return String(*this, pos, len); +} + +inline +size_t String::find(const char* s, size_t pos, size_t n) const +{ + if (n == 0 || pos + n > len_) return npos; + const char* lmax = cstr_ + len_ - n; + for (const char* i = cstr_ + pos; i <= lmax; ++i) + { + size_t j = 0; + while (j < n && s[j] == i[j]) ++j; + if (j == n) return (size_t)(i - cstr_); + } + return npos; +} + +inline +size_t String::find(char c, size_t pos) const +{ + return find(&c, pos, 1); +} + +inline +size_t String::find(const String& str, size_t pos) const +{ + return find(str.c_str(), pos, str.len_); +} + +inline +size_t String::find(const char* s, size_t pos) const +{ + if (pos >= len_ || !s[0]) return npos; + const char* lmax = cstr_ + len_; + for (const char* i = cstr_ + pos; i < lmax; ++i) + { + size_t j = 0; + while (s[j] && s[j] == i[j]) + { if(i + j >= lmax) return npos; + ++j; + } + if (!s[j]) return (size_t)(i - cstr_); + } + return npos; +} + +inline +size_t String::rfind(const char* s, size_t pos, size_t n) const +{ + if (n > len_) return npos; + if (pos > len_ - n) pos = len_ - n; + for (const char* i = cstr_ + pos; i >= cstr_; --i) + { + size_t j = 0; + while (j < n && s[j] == i[j]) ++j; + if (j == n) return (size_t)(i - cstr_); + } + return npos; +} + +inline +size_t String::rfind(char c, size_t pos) const +{ + return rfind(&c, pos, 1); +} + +inline +size_t String::rfind(const String& str, size_t pos) const +{ + return rfind(str.c_str(), pos, str.len_); +} + +inline +size_t String::rfind(const char* s, size_t pos) const +{ + return rfind(s, pos, strlen(s)); +} + +inline +size_t String::find_first_of(const char* s, size_t pos, size_t n) const +{ + if (n == 0 || pos + n > len_) return npos; + const char* lmax = cstr_ + len_; + for (const char* i = cstr_ + pos; i < lmax; ++i) + { + for (size_t j = 0; j < n; ++j) + if (s[j] == *i) + return (size_t)(i - cstr_); + } + return npos; +} + +inline +size_t String::find_first_of(char c, size_t pos) const +{ + return find_first_of(&c, pos, 1); +} + +inline +size_t String::find_first_of(const String& str, size_t pos) const +{ + return find_first_of(str.c_str(), pos, str.len_); +} + +inline +size_t String::find_first_of(const char* s, size_t pos) const +{ + if (pos >= len_ || !s[0]) return npos; + const char* lmax = cstr_ + len_; + for (const char* i = cstr_ + pos; i < lmax; ++i) + { + for (size_t j = 0; s[j]; ++j) + if (s[j] == *i) + return (size_t)(i - cstr_); + } + return npos; +} + +inline +size_t String::find_last_of(const char* s, size_t pos, size_t n) const +{ + if (pos >= len_) pos = len_ - 1; + for (const char* i = cstr_ + pos; i >= cstr_; --i) + { + for (size_t j = 0; j < n; ++j) + if (s[j] == *i) + return (size_t)(i - cstr_); + } + return npos; +} + +inline +size_t String::find_last_of(char c, size_t pos) const +{ + return find_last_of(&c, pos, 1); +} + +inline +size_t String::find_last_of(const String& str, size_t pos) const +{ + return find_last_of(str.c_str(), pos, str.len_); +} + +inline +size_t String::find_last_of(const char* s, size_t pos) const +{ + if (pos >= len_) pos = len_ - 1; + for (const char* i = cstr_ + pos; i >= cstr_; --i) + { + for (size_t j = 0; s[j]; ++j) + if (s[j] == *i) + return (size_t)(i - cstr_); + } + return npos; +} + +inline +String String::toLowerCase() const +{ + String res(cstr_, len_); + + for (size_t i = 0; i < len_; ++i) + res.cstr_[i] = (char) ::tolower(cstr_[i]); + + return res; +} + +// ************************* cv::String non-member functions ************************* + +inline +String operator + (const String& lhs, const String& rhs) +{ + String s; + s.allocate(lhs.len_ + rhs.len_); + memcpy(s.cstr_, lhs.cstr_, lhs.len_); + memcpy(s.cstr_ + lhs.len_, rhs.cstr_, rhs.len_); + return s; +} + +inline +String operator + (const String& lhs, const char* rhs) +{ + String s; + size_t rhslen = strlen(rhs); + s.allocate(lhs.len_ + rhslen); + memcpy(s.cstr_, lhs.cstr_, lhs.len_); + memcpy(s.cstr_ + lhs.len_, rhs, rhslen); + return s; +} + +inline +String operator + (const char* lhs, const String& rhs) +{ + String s; + size_t lhslen = strlen(lhs); + s.allocate(lhslen + rhs.len_); + memcpy(s.cstr_, lhs, lhslen); + memcpy(s.cstr_ + lhslen, rhs.cstr_, rhs.len_); + return s; +} + +inline +String operator + (const String& lhs, char rhs) +{ + String s; + s.allocate(lhs.len_ + 1); + memcpy(s.cstr_, lhs.cstr_, lhs.len_); + s.cstr_[lhs.len_] = rhs; + return s; +} + +inline +String operator + (char lhs, const String& rhs) +{ + String s; + s.allocate(rhs.len_ + 1); + s.cstr_[0] = lhs; + memcpy(s.cstr_ + 1, rhs.cstr_, rhs.len_); + return s; +} + +static inline bool operator== (const String& lhs, const String& rhs) { return 0 == lhs.compare(rhs); } +static inline bool operator== (const char* lhs, const String& rhs) { return 0 == rhs.compare(lhs); } +static inline bool operator== (const String& lhs, const char* rhs) { return 0 == lhs.compare(rhs); } +static inline bool operator!= (const String& lhs, const String& rhs) { return 0 != lhs.compare(rhs); } +static inline bool operator!= (const char* lhs, const String& rhs) { return 0 != rhs.compare(lhs); } +static inline bool operator!= (const String& lhs, const char* rhs) { return 0 != lhs.compare(rhs); } +static inline bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; } +static inline bool operator< (const char* lhs, const String& rhs) { return rhs.compare(lhs) > 0; } +static inline bool operator< (const String& lhs, const char* rhs) { return lhs.compare(rhs) < 0; } +static inline bool operator<= (const String& lhs, const String& rhs) { return lhs.compare(rhs) <= 0; } +static inline bool operator<= (const char* lhs, const String& rhs) { return rhs.compare(lhs) >= 0; } +static inline bool operator<= (const String& lhs, const char* rhs) { return lhs.compare(rhs) <= 0; } +static inline bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; } +static inline bool operator> (const char* lhs, const String& rhs) { return rhs.compare(lhs) < 0; } +static inline bool operator> (const String& lhs, const char* rhs) { return lhs.compare(rhs) > 0; } +static inline bool operator>= (const String& lhs, const String& rhs) { return lhs.compare(rhs) >= 0; } +static inline bool operator>= (const char* lhs, const String& rhs) { return rhs.compare(lhs) <= 0; } +static inline bool operator>= (const String& lhs, const char* rhs) { return lhs.compare(rhs) >= 0; } + +} // cv + +#ifndef OPENCV_NOSTL_TRANSITIONAL +namespace std +#else +namespace cv +#endif +{ + template<> inline + void swap(cv::String& a, cv::String& b) + { + a.swap(b); + } +} + +#include "opencv2/core/ptr.inl.hpp" + +#endif //__OPENCV_CORE_CVSTD_HPP__ diff --git a/modules/core/include/opencv2/core/cvstd.inl.hpp b/modules/core/include/opencv2/core/cvstd.inl.hpp new file mode 100644 index 0000000000..8642b7442e --- /dev/null +++ b/modules/core/include/opencv2/core/cvstd.inl.hpp @@ -0,0 +1,250 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_CVSTDINL_HPP__ +#define __OPENCV_CORE_CVSTDINL_HPP__ + +#ifndef OPENCV_NOSTL +# include +# include +#endif + +namespace cv +{ +#ifndef OPENCV_NOSTL + +template class DataType< std::complex<_Tp> > +{ +public: + typedef std::complex<_Tp> value_type; + typedef value_type work_type; + typedef _Tp channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 2, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) }; + + typedef Vec vec_type; +}; + +inline +String::String(const std::string& str) + : cstr_(0), len_(0) +{ + if (!str.empty()) + { + size_t len = str.size(); + memcpy(allocate(len), str.c_str(), len); + } +} + +inline +String::String(const std::string& str, size_t pos, size_t len) + : cstr_(0), len_(0) +{ + size_t strlen = str.size(); + pos = max(pos, strlen); + len = min(strlen - pos, len); + if (!len) return; + memcpy(allocate(len), str.c_str() + pos, len); +} + +inline +String& String::operator = (const std::string& str) +{ + deallocate(); + if (!str.empty()) + { + size_t len = str.size(); + memcpy(allocate(len), str.c_str(), len); + } + return *this; +} + +inline +String::operator std::string() const +{ + return std::string(cstr_, len_); +} + +inline +String operator + (const String& lhs, const std::string& rhs) +{ + String s; + size_t rhslen = rhs.size(); + s.allocate(lhs.len_ + rhslen); + memcpy(s.cstr_, lhs.cstr_, lhs.len_); + memcpy(s.cstr_ + lhs.len_, rhs.c_str(), rhslen); + return s; +} + +inline +String operator + (const std::string& lhs, const String& rhs) +{ + String s; + size_t lhslen = lhs.size(); + s.allocate(lhslen + rhs.len_); + memcpy(s.cstr_, lhs.c_str(), lhslen); + memcpy(s.cstr_ + lhslen, rhs.cstr_, rhs.len_); + return s; +} + +inline +FileNode::operator std::string() const +{ + String value; + read(*this, value, value); + return value; +} + +template<> inline +void operator >> (const FileNode& n, std::string& value) +{ + String val; + read(n, val, val); + value = val; +} + +template<> inline +FileStorage& operator << (FileStorage& fs, const std::string& value) +{ + return fs << cv::String(value); +} + +static inline +std::ostream& operator << (std::ostream& os, const String& str) +{ + return os << str.c_str(); +} + +static inline +std::ostream& operator << (std::ostream& out, Ptr fmtd) +{ + fmtd->reset(); + for(const char* str = fmtd->next(); str; str = fmtd->next()) + out << str; + return out; +} + +static inline +std::ostream& operator << (std::ostream& out, const Mat& mtx) +{ + return out << Formatter::get()->format(mtx); +} + +template static inline +std::ostream& operator << (std::ostream& out, const std::vector >& vec) +{ + return out << Formatter::get()->format(Mat(vec)); +} + + +template static inline +std::ostream& operator << (std::ostream& out, const std::vector >& vec) +{ + return out << Formatter::get()->format(Mat(vec)); +} + + +template static inline +std::ostream& operator << (std::ostream& out, const Matx<_Tp, m, n>& matx) +{ + return out << Formatter::get()->format(matx); +} + +template static inline +std::ostream& operator << (std::ostream& out, const Point_<_Tp>& p) +{ + out << "[" << p.x << ", " << p.y << "]"; + return out; +} + +template static inline +std::ostream& operator << (std::ostream& out, const Point3_<_Tp>& p) +{ + out << "[" << p.x << ", " << p.y << ", " << p.z << "]"; + return out; +} + +template static inline +std::ostream& operator << (std::ostream& out, const Vec<_Tp, n>& vec) +{ + out << "["; + + if(Vec<_Tp, n>::depth < CV_32F) + { + for (int i = 0; i < n - 1; ++i) { + out << (int)vec[i] << ", "; + } + out << (int)vec[n-1] << "]"; + } + else + { + for (int i = 0; i < n - 1; ++i) { + out << vec[i] << ", "; + } + out << vec[n-1] << "]"; + } + + return out; +} + +template static inline +std::ostream& operator << (std::ostream& out, const Size_<_Tp>& size) +{ + return out << "[" << size.width << " x " << size.height << "]"; +} + +template static inline +std::ostream& operator << (std::ostream& out, const Rect_<_Tp>& rect) +{ + return out << "[" << rect.width << " x " << rect.height << " from (" << rect.x << ", " << rect.y << ")]"; +} + + +#endif // OPENCV_NOSTL +} // cv + +#endif // __OPENCV_CORE_CVSTDINL_HPP__ diff --git a/modules/core/include/opencv2/core/eigen.hpp b/modules/core/include/opencv2/core/eigen.hpp index 6e47206c54..3005bfbfd4 100644 --- a/modules/core/include/opencv2/core/eigen.hpp +++ b/modules/core/include/opencv2/core/eigen.hpp @@ -12,6 +12,7 @@ // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -40,12 +41,10 @@ // //M*/ + #ifndef __OPENCV_CORE_EIGEN_HPP__ #define __OPENCV_CORE_EIGEN_HPP__ -#ifdef __cplusplus - -#include "opencv2/core/core_c.h" #include "opencv2/core.hpp" #if defined _MSC_VER && _MSC_VER >= 1200 @@ -57,7 +56,7 @@ namespace cv { -template +template static inline void eigen2cv( const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& src, Mat& dst ) { if( !(src.Flags & Eigen::RowMajorBit) ) @@ -75,7 +74,7 @@ void eigen2cv( const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCo } // Matx case -template +template static inline void eigen2cv( const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& src, Matx<_Tp, _rows, _cols>& dst ) { @@ -89,14 +88,14 @@ void eigen2cv( const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCo } } -template +template static inline void cv2eigen( const Mat& src, Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& dst ) { CV_DbgAssert(src.rows == _rows && src.cols == _cols); if( !(dst.Flags & Eigen::RowMajorBit) ) { - Mat _dst(src.cols, src.rows, DataType<_Tp>::type, + const Mat _dst(src.cols, src.rows, DataType<_Tp>::type, dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); if( src.type() == _dst.type() ) transpose(src, _dst); @@ -107,46 +106,42 @@ void cv2eigen( const Mat& src, } else Mat(src.t()).convertTo(_dst, _dst.type()); - CV_DbgAssert(_dst.data == (uchar*)dst.data()); } else { - Mat _dst(src.rows, src.cols, DataType<_Tp>::type, + const Mat _dst(src.rows, src.cols, DataType<_Tp>::type, dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); src.convertTo(_dst, _dst.type()); - CV_DbgAssert(_dst.data == (uchar*)dst.data()); } } // Matx case -template +template static inline void cv2eigen( const Matx<_Tp, _rows, _cols>& src, Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& dst ) { if( !(dst.Flags & Eigen::RowMajorBit) ) { - Mat _dst(_cols, _rows, DataType<_Tp>::type, + const Mat _dst(_cols, _rows, DataType<_Tp>::type, dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); transpose(src, _dst); - CV_DbgAssert(_dst.data == (uchar*)dst.data()); } else { - Mat _dst(_rows, _cols, DataType<_Tp>::type, + const Mat _dst(_rows, _cols, DataType<_Tp>::type, dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); Mat(src).copyTo(_dst); - CV_DbgAssert(_dst.data == (uchar*)dst.data()); } } -template +template static inline void cv2eigen( const Mat& src, Eigen::Matrix<_Tp, Eigen::Dynamic, Eigen::Dynamic>& dst ) { dst.resize(src.rows, src.cols); if( !(dst.Flags & Eigen::RowMajorBit) ) { - Mat _dst(src.cols, src.rows, DataType<_Tp>::type, + const Mat _dst(src.cols, src.rows, DataType<_Tp>::type, dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); if( src.type() == _dst.type() ) transpose(src, _dst); @@ -157,40 +152,36 @@ void cv2eigen( const Mat& src, } else Mat(src.t()).convertTo(_dst, _dst.type()); - CV_DbgAssert(_dst.data == (uchar*)dst.data()); } else { - Mat _dst(src.rows, src.cols, DataType<_Tp>::type, + const Mat _dst(src.rows, src.cols, DataType<_Tp>::type, dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); src.convertTo(_dst, _dst.type()); - CV_DbgAssert(_dst.data == (uchar*)dst.data()); } } // Matx case -template +template static inline void cv2eigen( const Matx<_Tp, _rows, _cols>& src, Eigen::Matrix<_Tp, Eigen::Dynamic, Eigen::Dynamic>& dst ) { dst.resize(_rows, _cols); if( !(dst.Flags & Eigen::RowMajorBit) ) { - Mat _dst(_cols, _rows, DataType<_Tp>::type, + const Mat _dst(_cols, _rows, DataType<_Tp>::type, dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); transpose(src, _dst); - CV_DbgAssert(_dst.data == (uchar*)dst.data()); } else { - Mat _dst(_rows, _cols, DataType<_Tp>::type, + const Mat _dst(_rows, _cols, DataType<_Tp>::type, dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); Mat(src).copyTo(_dst); - CV_DbgAssert(_dst.data == (uchar*)dst.data()); } } -template +template static inline void cv2eigen( const Mat& src, Eigen::Matrix<_Tp, Eigen::Dynamic, 1>& dst ) { @@ -199,25 +190,23 @@ void cv2eigen( const Mat& src, if( !(dst.Flags & Eigen::RowMajorBit) ) { - Mat _dst(src.cols, src.rows, DataType<_Tp>::type, + const Mat _dst(src.cols, src.rows, DataType<_Tp>::type, dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); if( src.type() == _dst.type() ) transpose(src, _dst); else Mat(src.t()).convertTo(_dst, _dst.type()); - CV_DbgAssert(_dst.data == (uchar*)dst.data()); } else { - Mat _dst(src.rows, src.cols, DataType<_Tp>::type, + const Mat _dst(src.rows, src.cols, DataType<_Tp>::type, dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); src.convertTo(_dst, _dst.type()); - CV_DbgAssert(_dst.data == (uchar*)dst.data()); } } // Matx case -template +template static inline void cv2eigen( const Matx<_Tp, _rows, 1>& src, Eigen::Matrix<_Tp, Eigen::Dynamic, 1>& dst ) { @@ -225,22 +214,20 @@ void cv2eigen( const Matx<_Tp, _rows, 1>& src, if( !(dst.Flags & Eigen::RowMajorBit) ) { - Mat _dst(1, _rows, DataType<_Tp>::type, + const Mat _dst(1, _rows, DataType<_Tp>::type, dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); transpose(src, _dst); - CV_DbgAssert(_dst.data == (uchar*)dst.data()); } else { - Mat _dst(_rows, 1, DataType<_Tp>::type, + const Mat _dst(_rows, 1, DataType<_Tp>::type, dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); src.copyTo(_dst); - CV_DbgAssert(_dst.data == (uchar*)dst.data()); } } -template +template static inline void cv2eigen( const Mat& src, Eigen::Matrix<_Tp, 1, Eigen::Dynamic>& dst ) { @@ -248,49 +235,41 @@ void cv2eigen( const Mat& src, dst.resize(src.cols); if( !(dst.Flags & Eigen::RowMajorBit) ) { - Mat _dst(src.cols, src.rows, DataType<_Tp>::type, + const Mat _dst(src.cols, src.rows, DataType<_Tp>::type, dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); if( src.type() == _dst.type() ) transpose(src, _dst); else Mat(src.t()).convertTo(_dst, _dst.type()); - CV_DbgAssert(_dst.data == (uchar*)dst.data()); } else { - Mat _dst(src.rows, src.cols, DataType<_Tp>::type, + const Mat _dst(src.rows, src.cols, DataType<_Tp>::type, dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); src.convertTo(_dst, _dst.type()); - CV_DbgAssert(_dst.data == (uchar*)dst.data()); } } //Matx -template +template static inline void cv2eigen( const Matx<_Tp, 1, _cols>& src, Eigen::Matrix<_Tp, 1, Eigen::Dynamic>& dst ) { dst.resize(_cols); if( !(dst.Flags & Eigen::RowMajorBit) ) { - Mat _dst(_cols, 1, DataType<_Tp>::type, + const Mat _dst(_cols, 1, DataType<_Tp>::type, dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); transpose(src, _dst); - CV_DbgAssert(_dst.data == (uchar*)dst.data()); } else { - Mat _dst(1, _cols, DataType<_Tp>::type, + const Mat _dst(1, _cols, DataType<_Tp>::type, dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); Mat(src).copyTo(_dst); - CV_DbgAssert(_dst.data == (uchar*)dst.data()); } } - -} +} // cv #endif - -#endif - diff --git a/modules/core/include/opencv2/core/gpu.hpp b/modules/core/include/opencv2/core/gpu.hpp new file mode 100644 index 0000000000..dfd4dd92ac --- /dev/null +++ b/modules/core/include/opencv2/core/gpu.hpp @@ -0,0 +1,672 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_GPU_HPP__ +#define __OPENCV_CORE_GPU_HPP__ + +#ifndef __cplusplus +# error gpu.hpp header must be compiled as C++ +#endif + +#include "opencv2/core.hpp" +#include "opencv2/core/gpu_types.hpp" + +namespace cv { namespace gpu { + +//////////////////////////////// GpuMat /////////////////////////////// + +// Smart pointer for GPU memory with reference counting. +// Its interface is mostly similar with cv::Mat. + +class CV_EXPORTS GpuMat +{ +public: + //! default constructor + GpuMat(); + + //! constructs GpuMat of the specified size and type + GpuMat(int rows, int cols, int type); + GpuMat(Size size, int type); + + //! constucts GpuMat and fills it with the specified value _s + GpuMat(int rows, int cols, int type, Scalar s); + GpuMat(Size size, int type, Scalar s); + + //! copy constructor + GpuMat(const GpuMat& m); + + //! constructor for GpuMat headers pointing to user-allocated data + GpuMat(int rows, int cols, int type, void* data, size_t step = Mat::AUTO_STEP); + GpuMat(Size size, int type, void* data, size_t step = Mat::AUTO_STEP); + + //! creates a GpuMat header for a part of the bigger matrix + GpuMat(const GpuMat& m, Range rowRange, Range colRange); + GpuMat(const GpuMat& m, Rect roi); + + //! builds GpuMat from host memory (Blocking call) + explicit GpuMat(InputArray arr); + + //! destructor - calls release() + ~GpuMat(); + + //! assignment operators + GpuMat& operator =(const GpuMat& m); + + //! allocates new GpuMat data unless the GpuMat already has specified size and type + void create(int rows, int cols, int type); + void create(Size size, int type); + + //! decreases reference counter, deallocate the data when reference counter reaches 0 + void release(); + + //! swaps with other smart pointer + void swap(GpuMat& mat); + + //! pefroms upload data to GpuMat (Blocking call) + void upload(InputArray arr); + + //! pefroms upload data to GpuMat (Non-Blocking call) + void upload(InputArray arr, Stream& stream); + + //! pefroms download data from device to host memory (Blocking call) + void download(OutputArray dst) const; + + //! pefroms download data from device to host memory (Non-Blocking call) + void download(OutputArray dst, Stream& stream) const; + + //! returns deep copy of the GpuMat, i.e. the data is copied + GpuMat clone() const; + + //! copies the GpuMat content to device memory (Blocking call) + void copyTo(OutputArray dst) const; + + //! copies the GpuMat content to device memory (Non-Blocking call) + void copyTo(OutputArray dst, Stream& stream) const; + + //! copies those GpuMat elements to "m" that are marked with non-zero mask elements (Blocking call) + void copyTo(OutputArray dst, InputArray mask) const; + + //! copies those GpuMat elements to "m" that are marked with non-zero mask elements (Non-Blocking call) + void copyTo(OutputArray dst, InputArray mask, Stream& stream) const; + + //! sets some of the GpuMat elements to s (Blocking call) + GpuMat& setTo(Scalar s); + + //! sets some of the GpuMat elements to s (Non-Blocking call) + GpuMat& setTo(Scalar s, Stream& stream); + + //! sets some of the GpuMat elements to s, according to the mask (Blocking call) + GpuMat& setTo(Scalar s, InputArray mask); + + //! sets some of the GpuMat elements to s, according to the mask (Non-Blocking call) + GpuMat& setTo(Scalar s, InputArray mask, Stream& stream); + + //! converts GpuMat to another datatype (Blocking call) + void convertTo(OutputArray dst, int rtype) const; + + //! converts GpuMat to another datatype (Non-Blocking call) + void convertTo(OutputArray dst, int rtype, Stream& stream) const; + + //! converts GpuMat to another datatype with scaling (Blocking call) + void convertTo(OutputArray dst, int rtype, double alpha, double beta = 0.0) const; + + //! converts GpuMat to another datatype with scaling (Non-Blocking call) + void convertTo(OutputArray dst, int rtype, double alpha, Stream& stream) const; + + //! converts GpuMat to another datatype with scaling (Non-Blocking call) + void convertTo(OutputArray dst, int rtype, double alpha, double beta, Stream& stream) const; + + void assignTo(GpuMat& m, int type=-1) const; + + //! returns pointer to y-th row + uchar* ptr(int y = 0); + const uchar* ptr(int y = 0) const; + + //! template version of the above method + template _Tp* ptr(int y = 0); + template const _Tp* ptr(int y = 0) const; + + template operator PtrStepSz<_Tp>() const; + template operator PtrStep<_Tp>() const; + + //! returns a new GpuMat header for the specified row + GpuMat row(int y) const; + + //! returns a new GpuMat header for the specified column + GpuMat col(int x) const; + + //! ... for the specified row span + GpuMat rowRange(int startrow, int endrow) const; + GpuMat rowRange(Range r) const; + + //! ... for the specified column span + GpuMat colRange(int startcol, int endcol) const; + GpuMat colRange(Range r) const; + + //! extracts a rectangular sub-GpuMat (this is a generalized form of row, rowRange etc.) + GpuMat operator ()(Range rowRange, Range colRange) const; + GpuMat operator ()(Rect roi) const; + + //! creates alternative GpuMat header for the same data, with different + //! number of channels and/or different number of rows + GpuMat reshape(int cn, int rows = 0) const; + + //! locates GpuMat header within a parent GpuMat + void locateROI(Size& wholeSize, Point& ofs) const; + + //! moves/resizes the current GpuMat ROI inside the parent GpuMat + GpuMat& adjustROI(int dtop, int dbottom, int dleft, int dright); + + //! returns true iff the GpuMat data is continuous + //! (i.e. when there are no gaps between successive rows) + bool isContinuous() const; + + //! returns element size in bytes + size_t elemSize() const; + + //! returns the size of element channel in bytes + size_t elemSize1() const; + + //! returns element type + int type() const; + + //! returns element type + int depth() const; + + //! returns number of channels + int channels() const; + + //! returns step/elemSize1() + size_t step1() const; + + //! returns GpuMat size : width == number of columns, height == number of rows + Size size() const; + + //! returns true if GpuMat data is NULL + bool empty() const; + + /*! includes several bit-fields: + - the magic signature + - continuity flag + - depth + - number of channels + */ + int flags; + + //! the number of rows and columns + int rows, cols; + + //! a distance between successive rows in bytes; includes the gap if any + size_t step; + + //! pointer to the data + uchar* data; + + //! pointer to the reference counter; + //! when GpuMat points to user-allocated data, the pointer is NULL + int* refcount; + + //! helper fields used in locateROI and adjustROI + uchar* datastart; + uchar* dataend; +}; + +//! creates continuous matrix +CV_EXPORTS void createContinuous(int rows, int cols, int type, OutputArray arr); + +//! ensures that size of the given matrix is not less than (rows, cols) size +//! and matrix type is match specified one too +CV_EXPORTS void ensureSizeIsEnough(int rows, int cols, int type, OutputArray arr); + +CV_EXPORTS GpuMat allocMatFromBuf(int rows, int cols, int type, GpuMat& mat); + +//////////////////////////////// CudaMem //////////////////////////////// + +// CudaMem is limited cv::Mat with page locked memory allocation. +// Page locked memory is only needed for async and faster coping to GPU. +// It is convertable to cv::Mat header without reference counting +// so you can use it with other opencv functions. + +class CV_EXPORTS CudaMem +{ +public: + enum AllocType { PAGE_LOCKED = 1, SHARED = 2, WRITE_COMBINED = 4 }; + + explicit CudaMem(AllocType alloc_type = PAGE_LOCKED); + + CudaMem(const CudaMem& m); + + CudaMem(int rows, int cols, int type, AllocType alloc_type = PAGE_LOCKED); + CudaMem(Size size, int type, AllocType alloc_type = PAGE_LOCKED); + + //! creates from host memory with coping data + explicit CudaMem(InputArray arr, AllocType alloc_type = PAGE_LOCKED); + + ~CudaMem(); + + CudaMem& operator =(const CudaMem& m); + + //! swaps with other smart pointer + void swap(CudaMem& b); + + //! returns deep copy of the matrix, i.e. the data is copied + CudaMem clone() const; + + //! allocates new matrix data unless the matrix already has specified size and type. + void create(int rows, int cols, int type); + void create(Size size, int type); + + //! creates alternative CudaMem header for the same data, with different + //! number of channels and/or different number of rows + CudaMem reshape(int cn, int rows = 0) const; + + //! decrements reference counter and released memory if needed. + void release(); + + //! returns matrix header with disabled reference counting for CudaMem data. + Mat createMatHeader() const; + + //! maps host memory into device address space and returns GpuMat header for it. Throws exception if not supported by hardware. + GpuMat createGpuMatHeader() const; + + // Please see cv::Mat for descriptions + bool isContinuous() const; + size_t elemSize() const; + size_t elemSize1() const; + int type() const; + int depth() const; + int channels() const; + size_t step1() const; + Size size() const; + bool empty() const; + + // Please see cv::Mat for descriptions + int flags; + int rows, cols; + size_t step; + + uchar* data; + int* refcount; + + uchar* datastart; + uchar* dataend; + + AllocType alloc_type; +}; + +//! page-locks the matrix m memory and maps it for the device(s) +CV_EXPORTS void registerPageLocked(Mat& m); + +//! unmaps the memory of matrix m, and makes it pageable again +CV_EXPORTS void unregisterPageLocked(Mat& m); + +///////////////////////////////// Stream ////////////////////////////////// + +// Encapculates Cuda Stream. Provides interface for async coping. +// Passed to each function that supports async kernel execution. +// Reference counting is enabled. + +class CV_EXPORTS Stream +{ + typedef void (Stream::*bool_type)() const; + void this_type_does_not_support_comparisons() const {} + +public: + typedef void (*StreamCallback)(int status, void* userData); + + //! creates a new asynchronous stream + Stream(); + + //! queries an asynchronous stream for completion status + bool queryIfComplete() const; + + //! waits for stream tasks to complete + void waitForCompletion(); + + //! makes a compute stream wait on an event + void waitEvent(const Event& event); + + //! adds a callback to be called on the host after all currently enqueued items in the stream have completed + void enqueueHostCallback(StreamCallback callback, void* userData); + + //! return Stream object for default CUDA stream + static Stream& Null(); + + //! returns true if stream object is not default (!= 0) + operator bool_type() const; + + class Impl; + +private: + Ptr impl_; + Stream(const Ptr& impl); + + friend struct StreamAccessor; +}; + +class CV_EXPORTS Event +{ +public: + enum CreateFlags + { + DEFAULT = 0x00, /**< Default event flag */ + BLOCKING_SYNC = 0x01, /**< Event uses blocking synchronization */ + DISABLE_TIMING = 0x02, /**< Event will not record timing data */ + INTERPROCESS = 0x04 /**< Event is suitable for interprocess use. DisableTiming must be set */ + }; + + explicit Event(CreateFlags flags = DEFAULT); + + //! records an event + void record(Stream& stream = Stream::Null()); + + //! queries an event's status + bool queryIfComplete() const; + + //! waits for an event to complete + void waitForCompletion(); + + //! computes the elapsed time between events + static float elapsedTime(const Event& start, const Event& end); + + class Impl; + +private: + Ptr impl_; + + friend struct EventAccessor; +}; + +//////////////////////////////// Initialization & Info //////////////////////// + +//! this is the only function that do not throw exceptions if the library is compiled without CUDA +CV_EXPORTS int getCudaEnabledDeviceCount(); + +//! set device to be used for GPU executions for the calling host thread +CV_EXPORTS void setDevice(int device); + +//! returns which device is currently being used for the calling host thread +CV_EXPORTS int getDevice(); + +//! explicitly destroys and cleans up all resources associated with the current device in the current process +//! any subsequent API call to this device will reinitialize the device +CV_EXPORTS void resetDevice(); + +enum FeatureSet +{ + FEATURE_SET_COMPUTE_10 = 10, + FEATURE_SET_COMPUTE_11 = 11, + FEATURE_SET_COMPUTE_12 = 12, + FEATURE_SET_COMPUTE_13 = 13, + FEATURE_SET_COMPUTE_20 = 20, + FEATURE_SET_COMPUTE_21 = 21, + FEATURE_SET_COMPUTE_30 = 30, + FEATURE_SET_COMPUTE_35 = 35, + + GLOBAL_ATOMICS = FEATURE_SET_COMPUTE_11, + SHARED_ATOMICS = FEATURE_SET_COMPUTE_12, + NATIVE_DOUBLE = FEATURE_SET_COMPUTE_13, + WARP_SHUFFLE_FUNCTIONS = FEATURE_SET_COMPUTE_30, + DYNAMIC_PARALLELISM = FEATURE_SET_COMPUTE_35 +}; + +//! checks whether current device supports the given feature +CV_EXPORTS bool deviceSupports(FeatureSet feature_set); + +//! information about what GPU archs this OpenCV GPU module was compiled for +class CV_EXPORTS TargetArchs +{ +public: + static bool builtWith(FeatureSet feature_set); + + static bool has(int major, int minor); + static bool hasPtx(int major, int minor); + static bool hasBin(int major, int minor); + + static bool hasEqualOrLessPtx(int major, int minor); + static bool hasEqualOrGreater(int major, int minor); + static bool hasEqualOrGreaterPtx(int major, int minor); + static bool hasEqualOrGreaterBin(int major, int minor); +}; + +//! information about the given GPU. +class CV_EXPORTS DeviceInfo +{ +public: + //! creates DeviceInfo object for the current GPU + DeviceInfo(); + + //! creates DeviceInfo object for the given GPU + DeviceInfo(int device_id); + + //! device number. + int deviceID() const; + + //! ASCII string identifying device + const char* name() const; + + //! global memory available on device in bytes + size_t totalGlobalMem() const; + + //! shared memory available per block in bytes + size_t sharedMemPerBlock() const; + + //! 32-bit registers available per block + int regsPerBlock() const; + + //! warp size in threads + int warpSize() const; + + //! maximum pitch in bytes allowed by memory copies + size_t memPitch() const; + + //! maximum number of threads per block + int maxThreadsPerBlock() const; + + //! maximum size of each dimension of a block + Vec3i maxThreadsDim() const; + + //! maximum size of each dimension of a grid + Vec3i maxGridSize() const; + + //! clock frequency in kilohertz + int clockRate() const; + + //! constant memory available on device in bytes + size_t totalConstMem() const; + + //! major compute capability + int majorVersion() const; + + //! minor compute capability + int minorVersion() const; + + //! alignment requirement for textures + size_t textureAlignment() const; + + //! pitch alignment requirement for texture references bound to pitched memory + size_t texturePitchAlignment() const; + + //! number of multiprocessors on device + int multiProcessorCount() const; + + //! specified whether there is a run time limit on kernels + bool kernelExecTimeoutEnabled() const; + + //! device is integrated as opposed to discrete + bool integrated() const; + + //! device can map host memory with cudaHostAlloc/cudaHostGetDevicePointer + bool canMapHostMemory() const; + + enum ComputeMode + { + ComputeModeDefault, /**< default compute mode (Multiple threads can use ::cudaSetDevice() with this device) */ + ComputeModeExclusive, /**< compute-exclusive-thread mode (Only one thread in one process will be able to use ::cudaSetDevice() with this device) */ + ComputeModeProhibited, /**< compute-prohibited mode (No threads can use ::cudaSetDevice() with this device) */ + ComputeModeExclusiveProcess /**< compute-exclusive-process mode (Many threads in one process will be able to use ::cudaSetDevice() with this device) */ + }; + + //! compute mode + ComputeMode computeMode() const; + + //! maximum 1D texture size + int maxTexture1D() const; + + //! maximum 1D mipmapped texture size + int maxTexture1DMipmap() const; + + //! maximum size for 1D textures bound to linear memory + int maxTexture1DLinear() const; + + //! maximum 2D texture dimensions + Vec2i maxTexture2D() const; + + //! maximum 2D mipmapped texture dimensions + Vec2i maxTexture2DMipmap() const; + + //! maximum dimensions (width, height, pitch) for 2D textures bound to pitched memory + Vec3i maxTexture2DLinear() const; + + //! maximum 2D texture dimensions if texture gather operations have to be performed + Vec2i maxTexture2DGather() const; + + //! maximum 3D texture dimensions + Vec3i maxTexture3D() const; + + //! maximum Cubemap texture dimensions + int maxTextureCubemap() const; + + //! maximum 1D layered texture dimensions + Vec2i maxTexture1DLayered() const; + + //! maximum 2D layered texture dimensions + Vec3i maxTexture2DLayered() const; + + //! maximum Cubemap layered texture dimensions + Vec2i maxTextureCubemapLayered() const; + + //! maximum 1D surface size + int maxSurface1D() const; + + //! maximum 2D surface dimensions + Vec2i maxSurface2D() const; + + //! maximum 3D surface dimensions + Vec3i maxSurface3D() const; + + //! maximum 1D layered surface dimensions + Vec2i maxSurface1DLayered() const; + + //! maximum 2D layered surface dimensions + Vec3i maxSurface2DLayered() const; + + //! maximum Cubemap surface dimensions + int maxSurfaceCubemap() const; + + //! maximum Cubemap layered surface dimensions + Vec2i maxSurfaceCubemapLayered() const; + + //! alignment requirements for surfaces + size_t surfaceAlignment() const; + + //! device can possibly execute multiple kernels concurrently + bool concurrentKernels() const; + + //! device has ECC support enabled + bool ECCEnabled() const; + + //! PCI bus ID of the device + int pciBusID() const; + + //! PCI device ID of the device + int pciDeviceID() const; + + //! PCI domain ID of the device + int pciDomainID() const; + + //! true if device is a Tesla device using TCC driver, false otherwise + bool tccDriver() const; + + //! number of asynchronous engines + int asyncEngineCount() const; + + //! device shares a unified address space with the host + bool unifiedAddressing() const; + + //! peak memory clock frequency in kilohertz + int memoryClockRate() const; + + //! global memory bus width in bits + int memoryBusWidth() const; + + //! size of L2 cache in bytes + int l2CacheSize() const; + + //! maximum resident threads per multiprocessor + int maxThreadsPerMultiProcessor() const; + + //! gets free and total device memory + void queryMemory(size_t& totalMemory, size_t& freeMemory) const; + size_t freeMemory() const; + size_t totalMemory() const; + + //! checks whether device supports the given feature + bool supports(FeatureSet feature_set) const; + + //! checks whether the GPU module can be run on the given device + bool isCompatible() const; + +private: + int device_id_; +}; + +CV_EXPORTS void printCudaDeviceInfo(int device); +CV_EXPORTS void printShortCudaDeviceInfo(int device); + +}} // namespace cv { namespace gpu { + + +#include "opencv2/core/gpu.inl.hpp" + +#endif /* __OPENCV_CORE_GPU_HPP__ */ diff --git a/modules/core/include/opencv2/core/gpu.inl.hpp b/modules/core/include/opencv2/core/gpu.inl.hpp new file mode 100644 index 0000000000..13861170cb --- /dev/null +++ b/modules/core/include/opencv2/core/gpu.inl.hpp @@ -0,0 +1,605 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_GPUINL_HPP__ +#define __OPENCV_CORE_GPUINL_HPP__ + +#include "opencv2/core/gpu.hpp" + +namespace cv { namespace gpu { + +//////////////////////////////// GpuMat /////////////////////////////// + +inline +GpuMat::GpuMat() + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0) +{} + +inline +GpuMat::GpuMat(int rows_, int cols_, int type_) + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0) +{ + if (rows_ > 0 && cols_ > 0) + create(rows_, cols_, type_); +} + +inline +GpuMat::GpuMat(Size size_, int type_) + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0) +{ + if (size_.height > 0 && size_.width > 0) + create(size_.height, size_.width, type_); +} + +inline +GpuMat::GpuMat(int rows_, int cols_, int type_, Scalar s_) + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0) +{ + if (rows_ > 0 && cols_ > 0) + { + create(rows_, cols_, type_); + setTo(s_); + } +} + +inline +GpuMat::GpuMat(Size size_, int type_, Scalar s_) + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0) +{ + if (size_.height > 0 && size_.width > 0) + { + create(size_.height, size_.width, type_); + setTo(s_); + } +} + +inline +GpuMat::GpuMat(const GpuMat& m) + : flags(m.flags), rows(m.rows), cols(m.cols), step(m.step), data(m.data), refcount(m.refcount), datastart(m.datastart), dataend(m.dataend) +{ + if (refcount) + CV_XADD(refcount, 1); +} + +inline +GpuMat::GpuMat(InputArray arr) : + flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0) +{ + upload(arr); +} + +inline +GpuMat::~GpuMat() +{ + release(); +} + +inline +GpuMat& GpuMat::operator =(const GpuMat& m) +{ + if (this != &m) + { + GpuMat temp(m); + swap(temp); + } + + return *this; +} + +inline +void GpuMat::create(Size size_, int type_) +{ + create(size_.height, size_.width, type_); +} + +inline +void GpuMat::swap(GpuMat& b) +{ + std::swap(flags, b.flags); + std::swap(rows, b.rows); + std::swap(cols, b.cols); + std::swap(step, b.step); + std::swap(data, b.data); + std::swap(datastart, b.datastart); + std::swap(dataend, b.dataend); + std::swap(refcount, b.refcount); +} + +inline +GpuMat GpuMat::clone() const +{ + GpuMat m; + copyTo(m); + return m; +} + +inline +void GpuMat::copyTo(OutputArray dst, InputArray mask) const +{ + copyTo(dst, mask, Stream::Null()); +} + +inline +GpuMat& GpuMat::setTo(Scalar s) +{ + return setTo(s, Stream::Null()); +} + +inline +GpuMat& GpuMat::setTo(Scalar s, InputArray mask) +{ + return setTo(s, mask, Stream::Null()); +} + +inline +void GpuMat::convertTo(OutputArray dst, int rtype) const +{ + convertTo(dst, rtype, Stream::Null()); +} + +inline +void GpuMat::convertTo(OutputArray dst, int rtype, double alpha, double beta) const +{ + convertTo(dst, rtype, alpha, beta, Stream::Null()); +} + +inline +void GpuMat::convertTo(OutputArray dst, int rtype, double alpha, Stream& stream) const +{ + convertTo(dst, rtype, alpha, 0.0, stream); +} + +inline +void GpuMat::assignTo(GpuMat& m, int _type) const +{ + if (_type < 0) + m = *this; + else + convertTo(m, _type); +} + +inline +uchar* GpuMat::ptr(int y) +{ + CV_DbgAssert( (unsigned)y < (unsigned)rows ); + return data + step * y; +} + +inline +const uchar* GpuMat::ptr(int y) const +{ + CV_DbgAssert( (unsigned)y < (unsigned)rows ); + return data + step * y; +} + +template inline +_Tp* GpuMat::ptr(int y) +{ + return (_Tp*)ptr(y); +} + +template inline +const _Tp* GpuMat::ptr(int y) const +{ + return (const _Tp*)ptr(y); +} + +template inline +GpuMat::operator PtrStepSz() const +{ + return PtrStepSz(rows, cols, (T*)data, step); +} + +template inline +GpuMat::operator PtrStep() const +{ + return PtrStep((T*)data, step); +} + +inline +GpuMat GpuMat::row(int y) const +{ + return GpuMat(*this, Range(y, y+1), Range::all()); +} + +inline +GpuMat GpuMat::col(int x) const +{ + return GpuMat(*this, Range::all(), Range(x, x+1)); +} + +inline +GpuMat GpuMat::rowRange(int startrow, int endrow) const +{ + return GpuMat(*this, Range(startrow, endrow), Range::all()); +} + +inline +GpuMat GpuMat::rowRange(Range r) const +{ + return GpuMat(*this, r, Range::all()); +} + +inline +GpuMat GpuMat::colRange(int startcol, int endcol) const +{ + return GpuMat(*this, Range::all(), Range(startcol, endcol)); +} + +inline +GpuMat GpuMat::colRange(Range r) const +{ + return GpuMat(*this, Range::all(), r); +} + +inline +GpuMat GpuMat::operator ()(Range rowRange_, Range colRange_) const +{ + return GpuMat(*this, rowRange_, colRange_); +} + +inline +GpuMat GpuMat::operator ()(Rect roi) const +{ + return GpuMat(*this, roi); +} + +inline +bool GpuMat::isContinuous() const +{ + return (flags & Mat::CONTINUOUS_FLAG) != 0; +} + +inline +size_t GpuMat::elemSize() const +{ + return CV_ELEM_SIZE(flags); +} + +inline +size_t GpuMat::elemSize1() const +{ + return CV_ELEM_SIZE1(flags); +} + +inline +int GpuMat::type() const +{ + return CV_MAT_TYPE(flags); +} + +inline +int GpuMat::depth() const +{ + return CV_MAT_DEPTH(flags); +} + +inline +int GpuMat::channels() const +{ + return CV_MAT_CN(flags); +} + +inline +size_t GpuMat::step1() const +{ + return step / elemSize1(); +} + +inline +Size GpuMat::size() const +{ + return Size(cols, rows); +} + +inline +bool GpuMat::empty() const +{ + return data == 0; +} + +static inline +GpuMat createContinuous(int rows, int cols, int type) +{ + GpuMat m; + createContinuous(rows, cols, type, m); + return m; +} + +static inline +void createContinuous(Size size, int type, OutputArray arr) +{ + createContinuous(size.height, size.width, type, arr); +} + +static inline +GpuMat createContinuous(Size size, int type) +{ + GpuMat m; + createContinuous(size, type, m); + return m; +} + +static inline +void ensureSizeIsEnough(Size size, int type, OutputArray arr) +{ + ensureSizeIsEnough(size.height, size.width, type, arr); +} + +static inline +void swap(GpuMat& a, GpuMat& b) +{ + a.swap(b); +} + +//////////////////////////////// CudaMem //////////////////////////////// + +inline +CudaMem::CudaMem(AllocType alloc_type_) + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), alloc_type(alloc_type_) +{ +} + +inline +CudaMem::CudaMem(const CudaMem& m) + : flags(m.flags), rows(m.rows), cols(m.cols), step(m.step), data(m.data), refcount(m.refcount), datastart(m.datastart), dataend(m.dataend), alloc_type(m.alloc_type) +{ + if( refcount ) + CV_XADD(refcount, 1); +} + +inline +CudaMem::CudaMem(int rows_, int cols_, int type_, AllocType alloc_type_) + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), alloc_type(alloc_type_) +{ + if (rows_ > 0 && cols_ > 0) + create(rows_, cols_, type_); +} + +inline +CudaMem::CudaMem(Size size_, int type_, AllocType alloc_type_) + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), alloc_type(alloc_type_) +{ + if (size_.height > 0 && size_.width > 0) + create(size_.height, size_.width, type_); +} + +inline +CudaMem::CudaMem(InputArray arr, AllocType alloc_type_) + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), alloc_type(alloc_type_) +{ + arr.getMat().copyTo(*this); +} + +inline +CudaMem::~CudaMem() +{ + release(); +} + +inline +CudaMem& CudaMem::operator =(const CudaMem& m) +{ + if (this != &m) + { + CudaMem temp(m); + swap(temp); + } + + return *this; +} + +inline +void CudaMem::swap(CudaMem& b) +{ + std::swap(flags, b.flags); + std::swap(rows, b.rows); + std::swap(cols, b.cols); + std::swap(step, b.step); + std::swap(data, b.data); + std::swap(datastart, b.datastart); + std::swap(dataend, b.dataend); + std::swap(refcount, b.refcount); + std::swap(alloc_type, b.alloc_type); +} + +inline +CudaMem CudaMem::clone() const +{ + CudaMem m(size(), type(), alloc_type); + createMatHeader().copyTo(m); + return m; +} + +inline +void CudaMem::create(Size size_, int type_) +{ + create(size_.height, size_.width, type_); +} + +inline +Mat CudaMem::createMatHeader() const +{ + return Mat(size(), type(), data, step); +} + +inline +bool CudaMem::isContinuous() const +{ + return (flags & Mat::CONTINUOUS_FLAG) != 0; +} + +inline +size_t CudaMem::elemSize() const +{ + return CV_ELEM_SIZE(flags); +} + +inline +size_t CudaMem::elemSize1() const +{ + return CV_ELEM_SIZE1(flags); +} + +inline +int CudaMem::type() const +{ + return CV_MAT_TYPE(flags); +} + +inline +int CudaMem::depth() const +{ + return CV_MAT_DEPTH(flags); +} + +inline +int CudaMem::channels() const +{ + return CV_MAT_CN(flags); +} + +inline +size_t CudaMem::step1() const +{ + return step / elemSize1(); +} + +inline +Size CudaMem::size() const +{ + return Size(cols, rows); +} + +inline +bool CudaMem::empty() const +{ + return data == 0; +} + +static inline +void swap(CudaMem& a, CudaMem& b) +{ + a.swap(b); +} + +//////////////////////////////// Stream /////////////////////////////// + +inline +Stream::Stream(const Ptr& impl) + : impl_(impl) +{ +} + +//////////////////////////////// Initialization & Info //////////////////////// + +inline +bool TargetArchs::has(int major, int minor) +{ + return hasPtx(major, minor) || hasBin(major, minor); +} + +inline +bool TargetArchs::hasEqualOrGreater(int major, int minor) +{ + return hasEqualOrGreaterPtx(major, minor) || hasEqualOrGreaterBin(major, minor); +} + +inline +DeviceInfo::DeviceInfo() +{ + device_id_ = getDevice(); +} + +inline +DeviceInfo::DeviceInfo(int device_id) +{ + CV_Assert( device_id >= 0 && device_id < getCudaEnabledDeviceCount() ); + device_id_ = device_id; +} + +inline +int DeviceInfo::deviceID() const +{ + return device_id_; +} + +inline +size_t DeviceInfo::freeMemory() const +{ + size_t _totalMemory, _freeMemory; + queryMemory(_totalMemory, _freeMemory); + return _freeMemory; +} + +inline +size_t DeviceInfo::totalMemory() const +{ + size_t _totalMemory, _freeMemory; + queryMemory(_totalMemory, _freeMemory); + return _totalMemory; +} + +inline +bool DeviceInfo::supports(FeatureSet feature_set) const +{ + int version = majorVersion() * 10 + minorVersion(); + return version >= feature_set; +} + +}} // namespace cv { namespace gpu { + +//////////////////////////////// Mat //////////////////////////////// + +namespace cv { + +inline +Mat::Mat(const gpu::GpuMat& m) + : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0), datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows) +{ + m.download(*this); +} + +} + +#endif // __OPENCV_CORE_GPUINL_HPP__ diff --git a/modules/core/include/opencv2/core/stream_accessor.hpp b/modules/core/include/opencv2/core/gpu_stream_accessor.hpp similarity index 73% rename from modules/core/include/opencv2/core/stream_accessor.hpp rename to modules/core/include/opencv2/core/gpu_stream_accessor.hpp index 9748bef80c..cf7d3c4316 100644 --- a/modules/core/include/opencv2/core/stream_accessor.hpp +++ b/modules/core/include/opencv2/core/gpu_stream_accessor.hpp @@ -22,7 +22,7 @@ // // * 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 GpuMaterials provided with the distribution. +// 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. @@ -40,25 +40,38 @@ // //M*/ -#ifndef __OPENCV_CUDA_STREAM_ACCESSOR_HPP__ -#define __OPENCV_CUDA_STREAM_ACCESSOR_HPP__ +#ifndef __OPENCV_CORE_GPU_STREAM_ACCESSOR_HPP__ +#define __OPENCV_CORE_GPU_STREAM_ACCESSOR_HPP__ -#include "opencv2/core/gpumat.hpp" -#include "cuda_runtime_api.h" +#ifndef __cplusplus +# error gpu_stream_accessor.hpp header must be compiled as C++ +#endif + +// This is only header file that depends on Cuda. All other headers are independent. +// So if you use OpenCV binaries you do noot need to install Cuda Toolkit. +// But of you wanna use GPU by yourself, may get cuda stream instance using the class below. +// In this case you have to install Cuda Toolkit. + +#include +#include "opencv2/core/cvdef.h" namespace cv { namespace gpu { - // This is only header file that depends on Cuda. All other headers are independent. - // So if you use OpenCV binaries you do noot need to install Cuda Toolkit. - // But of you wanna use GPU by yourself, may get cuda stream instance using the class below. - // In this case you have to install Cuda Toolkit. + class Stream; + class Event; + struct StreamAccessor { CV_EXPORTS static cudaStream_t getStream(const Stream& stream); }; + + struct EventAccessor + { + CV_EXPORTS static cudaEvent_t getEvent(const Event& event); + }; } } -#endif /* __OPENCV_CUDA_STREAM_ACCESSOR_HPP__ */ \ No newline at end of file +#endif /* __OPENCV_CORE_GPU_STREAM_ACCESSOR_HPP__ */ diff --git a/modules/core/include/opencv2/core/cuda_devptrs.hpp b/modules/core/include/opencv2/core/gpu_types.hpp similarity index 69% rename from modules/core/include/opencv2/core/cuda_devptrs.hpp rename to modules/core/include/opencv2/core/gpu_types.hpp index 26fc2403f9..4997034cca 100644 --- a/modules/core/include/opencv2/core/cuda_devptrs.hpp +++ b/modules/core/include/opencv2/core/gpu_types.hpp @@ -22,7 +22,7 @@ // // * 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 GpuMaterials provided with the distribution. +// 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. @@ -40,10 +40,12 @@ // //M*/ -#ifndef __OPENCV_CORE_DEVPTRS_HPP__ -#define __OPENCV_CORE_DEVPTRS_HPP__ +#ifndef __OPENCV_CORE_GPU_TYPES_HPP__ +#define __OPENCV_CORE_GPU_TYPES_HPP__ -#ifdef __cplusplus +#ifndef __cplusplus +# error gpu_types.hpp header must be compiled as C++ +#endif #ifdef __CUDACC__ #define __CV_GPU_HOST_DEVICE__ __host__ __device__ __forceinline__ @@ -58,10 +60,7 @@ namespace cv // Simple lightweight structures that encapsulates information about an image on device. // It is intended to pass to nvcc-compiled code. GpuMat depends on headers that nvcc can't compile - template struct StaticAssert; - template <> struct StaticAssert {static __CV_GPU_HOST_DEVICE__ void check(){}}; - - template struct DevPtr + template struct DevPtr { typedef T elem_type; typedef int index_type; @@ -78,7 +77,7 @@ namespace cv __CV_GPU_HOST_DEVICE__ operator const T*() const { return data; } }; - template struct PtrSz : public DevPtr + template struct PtrSz : public DevPtr { __CV_GPU_HOST_DEVICE__ PtrSz() : size(0) {} __CV_GPU_HOST_DEVICE__ PtrSz(T* data_, size_t size_) : DevPtr(data_), size(size_) {} @@ -86,12 +85,12 @@ namespace cv size_t size; }; - template struct PtrStep : public DevPtr + template struct PtrStep : public DevPtr { __CV_GPU_HOST_DEVICE__ PtrStep() : step(0) {} __CV_GPU_HOST_DEVICE__ PtrStep(T* data_, size_t step_) : DevPtr(data_), step(step_) {} - /** \brief stride between two consecutive rows in bytes. Step is stored always and everywhere in bytes!!! */ + //! stride between two consecutive rows in bytes. Step is stored always and everywhere in bytes!!! size_t step; __CV_GPU_HOST_DEVICE__ T* ptr(int y = 0) { return ( T*)( ( char*)DevPtr::data + y * step); } @@ -121,54 +120,7 @@ namespace cv typedef PtrStep PtrStepb; typedef PtrStep PtrStepf; typedef PtrStep PtrStepi; - - -#if defined __GNUC__ - #define __CV_GPU_DEPR_BEFORE__ - #define __CV_GPU_DEPR_AFTER__ __attribute__ ((deprecated)) -#elif defined(__MSVC__) //|| defined(__CUDACC__) - #pragma deprecated(DevMem2D_) - #define __CV_GPU_DEPR_BEFORE__ __declspec(deprecated) - #define __CV_GPU_DEPR_AFTER__ -#else - #define __CV_GPU_DEPR_BEFORE__ - #define __CV_GPU_DEPR_AFTER__ -#endif - - template struct __CV_GPU_DEPR_BEFORE__ DevMem2D_ : public PtrStepSz - { - DevMem2D_() {} - DevMem2D_(int rows_, int cols_, T* data_, size_t step_) : PtrStepSz(rows_, cols_, data_, step_) {} - - template - explicit __CV_GPU_DEPR_BEFORE__ DevMem2D_(const DevMem2D_& d) : PtrStepSz(d.rows, d.cols, (T*)d.data, d.step) {} - } __CV_GPU_DEPR_AFTER__ ; - - typedef DevMem2D_ DevMem2Db; - typedef DevMem2Db DevMem2D; - typedef DevMem2D_ DevMem2Df; - typedef DevMem2D_ DevMem2Di; - -//#undef __CV_GPU_DEPR_BEFORE__ -//#undef __CV_GPU_DEPR_AFTER__ - - namespace device - { - using cv::gpu::PtrSz; - using cv::gpu::PtrStep; - using cv::gpu::PtrStepSz; - - using cv::gpu::PtrStepSzb; - using cv::gpu::PtrStepSzf; - using cv::gpu::PtrStepSzi; - - using cv::gpu::PtrStepb; - using cv::gpu::PtrStepf; - using cv::gpu::PtrStepi; - } } } -#endif // __cplusplus - -#endif /* __OPENCV_CORE_DEVPTRS_HPP__ */ +#endif /* __OPENCV_CORE_GPU_TYPES_HPP__ */ diff --git a/modules/core/include/opencv2/core/gpumat.hpp b/modules/core/include/opencv2/core/gpumat.hpp deleted file mode 100644 index bb436ec553..0000000000 --- a/modules/core/include/opencv2/core/gpumat.hpp +++ /dev/null @@ -1,691 +0,0 @@ -/*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 GpuMaterials 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_GPUMAT_HPP__ -#define __OPENCV_GPUMAT_HPP__ - -#ifdef __cplusplus - -#include "opencv2/core.hpp" -#include "opencv2/core/cuda_devptrs.hpp" - -namespace cv { namespace gpu -{ - //////////////////////////////// CudaMem //////////////////////////////// - // CudaMem is limited cv::Mat with page locked memory allocation. - // Page locked memory is only needed for async and faster coping to GPU. - // It is convertable to cv::Mat header without reference counting - // so you can use it with other opencv functions. - - // Page-locks the matrix m memory and maps it for the device(s) - CV_EXPORTS void registerPageLocked(Mat& m); - // Unmaps the memory of matrix m, and makes it pageable again. - CV_EXPORTS void unregisterPageLocked(Mat& m); - - class CV_EXPORTS CudaMem - { - public: - enum { ALLOC_PAGE_LOCKED = 1, ALLOC_ZEROCOPY = 2, ALLOC_WRITE_COMBINED = 4 }; - - CudaMem(); - CudaMem(const CudaMem& m); - - CudaMem(int rows, int cols, int type, int _alloc_type = ALLOC_PAGE_LOCKED); - CudaMem(Size size, int type, int alloc_type = ALLOC_PAGE_LOCKED); - - - //! creates from cv::Mat with coping data - explicit CudaMem(const Mat& m, int alloc_type = ALLOC_PAGE_LOCKED); - - ~CudaMem(); - - CudaMem& operator = (const CudaMem& m); - - //! returns deep copy of the matrix, i.e. the data is copied - CudaMem clone() const; - - //! allocates new matrix data unless the matrix already has specified size and type. - void create(int rows, int cols, int type, int alloc_type = ALLOC_PAGE_LOCKED); - void create(Size size, int type, int alloc_type = ALLOC_PAGE_LOCKED); - - //! decrements reference counter and released memory if needed. - void release(); - - //! returns matrix header with disabled reference counting for CudaMem data. - Mat createMatHeader() const; - operator Mat() const; - - //! maps host memory into device address space and returns GpuMat header for it. Throws exception if not supported by hardware. - GpuMat createGpuMatHeader() const; - operator GpuMat() const; - - //returns if host memory can be mapperd to gpu address space; - static bool canMapHostMemory(); - - // Please see cv::Mat for descriptions - bool isContinuous() const; - size_t elemSize() const; - size_t elemSize1() const; - int type() const; - int depth() const; - int channels() const; - size_t step1() const; - Size size() const; - bool empty() const; - - - // Please see cv::Mat for descriptions - int flags; - int rows, cols; - size_t step; - - uchar* data; - int* refcount; - - uchar* datastart; - uchar* dataend; - - int alloc_type; - }; - - - //////////////////////////////// CudaStream //////////////////////////////// - // Encapculates Cuda Stream. Provides interface for async coping. - // Passed to each function that supports async kernel execution. - // Reference counting is enabled - - class CV_EXPORTS Stream - { - public: - Stream(); - ~Stream(); - - Stream(const Stream&); - Stream& operator =(const Stream&); - - bool queryIfComplete(); - void waitForCompletion(); - - //! downloads asynchronously - // Warning! cv::Mat must point to page locked memory (i.e. to CudaMem data or to its subMat) - void enqueueDownload(const GpuMat& src, CudaMem& dst); - void enqueueDownload(const GpuMat& src, Mat& dst); - - //! uploads asynchronously - // Warning! cv::Mat must point to page locked memory (i.e. to CudaMem data or to its ROI) - void enqueueUpload(const CudaMem& src, GpuMat& dst); - void enqueueUpload(const Mat& src, GpuMat& dst); - - //! copy asynchronously - void enqueueCopy(const GpuMat& src, GpuMat& dst); - - //! memory set asynchronously - void enqueueMemSet(GpuMat& src, Scalar val); - void enqueueMemSet(GpuMat& src, Scalar val, const GpuMat& mask); - - //! converts matrix type, ex from float to uchar depending on type - void enqueueConvert(const GpuMat& src, GpuMat& dst, int dtype, double a = 1, double b = 0); - - //! adds a callback to be called on the host after all currently enqueued items in the stream have completed - typedef void (*StreamCallback)(Stream& stream, int status, void* userData); - void enqueueHostCallback(StreamCallback callback, void* userData); - - static Stream& Null(); - - operator bool() const; - - private: - struct Impl; - - explicit Stream(Impl* impl); - void create(); - void release(); - - Impl *impl; - - friend struct StreamAccessor; - }; - - //////////////////////////////// Initialization & Info //////////////////////// - - //! This is the only function that do not throw exceptions if the library is compiled without Cuda. - CV_EXPORTS int getCudaEnabledDeviceCount(); - - //! Functions below throw cv::Expception if the library is compiled without Cuda. - - CV_EXPORTS void setDevice(int device); - CV_EXPORTS int getDevice(); - - //! Explicitly destroys and cleans up all resources associated with the current device in the current process. - //! Any subsequent API call to this device will reinitialize the device. - CV_EXPORTS void resetDevice(); - - enum FeatureSet - { - FEATURE_SET_COMPUTE_10 = 10, - FEATURE_SET_COMPUTE_11 = 11, - FEATURE_SET_COMPUTE_12 = 12, - FEATURE_SET_COMPUTE_13 = 13, - FEATURE_SET_COMPUTE_20 = 20, - FEATURE_SET_COMPUTE_21 = 21, - FEATURE_SET_COMPUTE_30 = 30, - FEATURE_SET_COMPUTE_35 = 35, - - GLOBAL_ATOMICS = FEATURE_SET_COMPUTE_11, - SHARED_ATOMICS = FEATURE_SET_COMPUTE_12, - NATIVE_DOUBLE = FEATURE_SET_COMPUTE_13, - WARP_SHUFFLE_FUNCTIONS = FEATURE_SET_COMPUTE_30, - DYNAMIC_PARALLELISM = FEATURE_SET_COMPUTE_35 - }; - - // Checks whether current device supports the given feature - CV_EXPORTS bool deviceSupports(FeatureSet feature_set); - - // Gives information about what GPU archs this OpenCV GPU module was - // compiled for - class CV_EXPORTS TargetArchs - { - public: - static bool builtWith(FeatureSet feature_set); - static bool has(int major, int minor); - static bool hasPtx(int major, int minor); - static bool hasBin(int major, int minor); - static bool hasEqualOrLessPtx(int major, int minor); - static bool hasEqualOrGreater(int major, int minor); - static bool hasEqualOrGreaterPtx(int major, int minor); - static bool hasEqualOrGreaterBin(int major, int minor); - private: - TargetArchs(); - }; - - // Gives information about the given GPU - class CV_EXPORTS DeviceInfo - { - public: - // Creates DeviceInfo object for the current GPU - DeviceInfo() : device_id_(getDevice()) { query(); } - - // Creates DeviceInfo object for the given GPU - DeviceInfo(int device_id) : device_id_(device_id) { query(); } - - std::string name() const { return name_; } - - // Return compute capability versions - int majorVersion() const { return majorVersion_; } - int minorVersion() const { return minorVersion_; } - - int multiProcessorCount() const { return multi_processor_count_; } - - size_t sharedMemPerBlock() const; - - void queryMemory(size_t& totalMemory, size_t& freeMemory) const; - size_t freeMemory() const; - size_t totalMemory() const; - - // Checks whether device supports the given feature - bool supports(FeatureSet feature_set) const; - - // Checks whether the GPU module can be run on the given device - bool isCompatible() const; - - int deviceID() const { return device_id_; } - - private: - void query(); - - int device_id_; - - std::string name_; - int multi_processor_count_; - int majorVersion_; - int minorVersion_; - }; - - CV_EXPORTS void printCudaDeviceInfo(int device); - CV_EXPORTS void printShortCudaDeviceInfo(int device); - - //////////////////////////////// GpuMat /////////////////////////////// - - //! Smart pointer for GPU memory with reference counting. Its interface is mostly similar with cv::Mat. - class CV_EXPORTS GpuMat - { - public: - //! default constructor - GpuMat(); - - //! constructs GpuMatrix of the specified size and type (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.) - GpuMat(int rows, int cols, int type); - GpuMat(Size size, int type); - - //! constucts GpuMatrix and fills it with the specified value _s. - GpuMat(int rows, int cols, int type, Scalar s); - GpuMat(Size size, int type, Scalar s); - - //! copy constructor - GpuMat(const GpuMat& m); - - //! constructor for GpuMatrix headers pointing to user-allocated data - GpuMat(int rows, int cols, int type, void* data, size_t step = Mat::AUTO_STEP); - GpuMat(Size size, int type, void* data, size_t step = Mat::AUTO_STEP); - - //! creates a matrix header for a part of the bigger matrix - GpuMat(const GpuMat& m, Range rowRange, Range colRange); - GpuMat(const GpuMat& m, Rect roi); - - //! builds GpuMat from Mat. Perfom blocking upload to device. - explicit GpuMat(const Mat& m); - - //! destructor - calls release() - ~GpuMat(); - - //! assignment operators - GpuMat& operator = (const GpuMat& m); - - //! pefroms blocking upload data to GpuMat. - void upload(const Mat& m); - - //! downloads data from device to host memory. Blocking calls. - void download(Mat& m) const; - - //! returns a new GpuMatrix header for the specified row - GpuMat row(int y) const; - //! returns a new GpuMatrix header for the specified column - GpuMat col(int x) const; - //! ... for the specified row span - GpuMat rowRange(int startrow, int endrow) const; - GpuMat rowRange(Range r) const; - //! ... for the specified column span - GpuMat colRange(int startcol, int endcol) const; - GpuMat colRange(Range r) const; - - //! returns deep copy of the GpuMatrix, i.e. the data is copied - GpuMat clone() const; - //! copies the GpuMatrix content to "m". - // It calls m.create(this->size(), this->type()). - void copyTo(GpuMat& m) const; - //! copies those GpuMatrix elements to "m" that are marked with non-zero mask elements. - void copyTo(GpuMat& m, const GpuMat& mask) const; - //! converts GpuMatrix to another datatype with optional scalng. See cvConvertScale. - void convertTo(GpuMat& m, int rtype, double alpha = 1, double beta = 0) const; - - void assignTo(GpuMat& m, int type=-1) const; - - //! sets every GpuMatrix element to s - GpuMat& operator = (Scalar s); - //! sets some of the GpuMatrix elements to s, according to the mask - GpuMat& setTo(Scalar s, const GpuMat& mask = GpuMat()); - //! creates alternative GpuMatrix header for the same data, with different - // number of channels and/or different number of rows. see cvReshape. - GpuMat reshape(int cn, int rows = 0) const; - - //! allocates new GpuMatrix data unless the GpuMatrix already has specified size and type. - // previous data is unreferenced if needed. - void create(int rows, int cols, int type); - void create(Size size, int type); - //! decreases reference counter; - // deallocate the data when reference counter reaches 0. - void release(); - - //! swaps with other smart pointer - void swap(GpuMat& mat); - - //! locates GpuMatrix header within a parent GpuMatrix. See below - void locateROI(Size& wholeSize, Point& ofs) const; - //! moves/resizes the current GpuMatrix ROI inside the parent GpuMatrix. - GpuMat& adjustROI(int dtop, int dbottom, int dleft, int dright); - //! extracts a rectangular sub-GpuMatrix - // (this is a generalized form of row, rowRange etc.) - GpuMat operator()(Range rowRange, Range colRange) const; - GpuMat operator()(Rect roi) const; - - //! returns true iff the GpuMatrix data is continuous - // (i.e. when there are no gaps between successive rows). - // similar to CV_IS_GpuMat_CONT(cvGpuMat->type) - bool isContinuous() const; - //! returns element size in bytes, - // similar to CV_ELEM_SIZE(cvMat->type) - size_t elemSize() const; - //! returns the size of element channel in bytes. - size_t elemSize1() const; - //! returns element type, similar to CV_MAT_TYPE(cvMat->type) - int type() const; - //! returns element type, similar to CV_MAT_DEPTH(cvMat->type) - int depth() const; - //! returns element type, similar to CV_MAT_CN(cvMat->type) - int channels() const; - //! returns step/elemSize1() - size_t step1() const; - //! returns GpuMatrix size: - // width == number of columns, height == number of rows - Size size() const; - //! returns true if GpuMatrix data is NULL - bool empty() const; - - //! returns pointer to y-th row - uchar* ptr(int y = 0); - const uchar* ptr(int y = 0) const; - - //! template version of the above method - template _Tp* ptr(int y = 0); - template const _Tp* ptr(int y = 0) const; - - template operator PtrStepSz<_Tp>() const; - template operator PtrStep<_Tp>() const; - - // Deprecated function - __CV_GPU_DEPR_BEFORE__ template operator DevMem2D_<_Tp>() const __CV_GPU_DEPR_AFTER__; - #undef __CV_GPU_DEPR_BEFORE__ - #undef __CV_GPU_DEPR_AFTER__ - - /*! includes several bit-fields: - - the magic signature - - continuity flag - - depth - - number of channels - */ - int flags; - - //! the number of rows and columns - int rows, cols; - - //! a distance between successive rows in bytes; includes the gap if any - size_t step; - - //! pointer to the data - uchar* data; - - //! pointer to the reference counter; - // when GpuMatrix points to user-allocated data, the pointer is NULL - int* refcount; - - //! helper fields used in locateROI and adjustROI - uchar* datastart; - uchar* dataend; - }; - - //! Creates continuous GPU matrix - CV_EXPORTS void createContinuous(int rows, int cols, int type, GpuMat& m); - CV_EXPORTS GpuMat createContinuous(int rows, int cols, int type); - CV_EXPORTS void createContinuous(Size size, int type, GpuMat& m); - CV_EXPORTS GpuMat createContinuous(Size size, int type); - - //! Ensures that size of the given matrix is not less than (rows, cols) size - //! and matrix type is match specified one too - CV_EXPORTS void ensureSizeIsEnough(int rows, int cols, int type, GpuMat& m); - CV_EXPORTS void ensureSizeIsEnough(Size size, int type, GpuMat& m); - - CV_EXPORTS GpuMat allocMatFromBuf(int rows, int cols, int type, GpuMat &mat); - - //////////////////////////////////////////////////////////////////////// - // Error handling - - CV_EXPORTS void error(const char* error_string, const char* file, const int line, const char* func = ""); - - //////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////// - - inline GpuMat::GpuMat() - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0) - { - } - - inline GpuMat::GpuMat(int rows_, int cols_, int type_) - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0) - { - if (rows_ > 0 && cols_ > 0) - create(rows_, cols_, type_); - } - - inline GpuMat::GpuMat(Size size_, int type_) - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0) - { - if (size_.height > 0 && size_.width > 0) - create(size_.height, size_.width, type_); - } - - inline GpuMat::GpuMat(int rows_, int cols_, int type_, Scalar s_) - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0) - { - if (rows_ > 0 && cols_ > 0) - { - create(rows_, cols_, type_); - setTo(s_); - } - } - - inline GpuMat::GpuMat(Size size_, int type_, Scalar s_) - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0) - { - if (size_.height > 0 && size_.width > 0) - { - create(size_.height, size_.width, type_); - setTo(s_); - } - } - - inline GpuMat::~GpuMat() - { - release(); - } - - inline GpuMat GpuMat::clone() const - { - GpuMat m; - copyTo(m); - return m; - } - - inline void GpuMat::assignTo(GpuMat& m, int _type) const - { - if (_type < 0) - m = *this; - else - convertTo(m, _type); - } - - inline size_t GpuMat::step1() const - { - return step / elemSize1(); - } - - inline bool GpuMat::empty() const - { - return data == 0; - } - - template inline _Tp* GpuMat::ptr(int y) - { - return (_Tp*)ptr(y); - } - - template inline const _Tp* GpuMat::ptr(int y) const - { - return (const _Tp*)ptr(y); - } - - inline void swap(GpuMat& a, GpuMat& b) - { - a.swap(b); - } - - inline GpuMat GpuMat::row(int y) const - { - return GpuMat(*this, Range(y, y+1), Range::all()); - } - - inline GpuMat GpuMat::col(int x) const - { - return GpuMat(*this, Range::all(), Range(x, x+1)); - } - - inline GpuMat GpuMat::rowRange(int startrow, int endrow) const - { - return GpuMat(*this, Range(startrow, endrow), Range::all()); - } - - inline GpuMat GpuMat::rowRange(Range r) const - { - return GpuMat(*this, r, Range::all()); - } - - inline GpuMat GpuMat::colRange(int startcol, int endcol) const - { - return GpuMat(*this, Range::all(), Range(startcol, endcol)); - } - - inline GpuMat GpuMat::colRange(Range r) const - { - return GpuMat(*this, Range::all(), r); - } - - inline void GpuMat::create(Size size_, int type_) - { - create(size_.height, size_.width, type_); - } - - inline GpuMat GpuMat::operator()(Range _rowRange, Range _colRange) const - { - return GpuMat(*this, _rowRange, _colRange); - } - - inline GpuMat GpuMat::operator()(Rect roi) const - { - return GpuMat(*this, roi); - } - - inline bool GpuMat::isContinuous() const - { - return (flags & Mat::CONTINUOUS_FLAG) != 0; - } - - inline size_t GpuMat::elemSize() const - { - return CV_ELEM_SIZE(flags); - } - - inline size_t GpuMat::elemSize1() const - { - return CV_ELEM_SIZE1(flags); - } - - inline int GpuMat::type() const - { - return CV_MAT_TYPE(flags); - } - - inline int GpuMat::depth() const - { - return CV_MAT_DEPTH(flags); - } - - inline int GpuMat::channels() const - { - return CV_MAT_CN(flags); - } - - inline Size GpuMat::size() const - { - return Size(cols, rows); - } - - inline uchar* GpuMat::ptr(int y) - { - CV_DbgAssert((unsigned)y < (unsigned)rows); - return data + step * y; - } - - inline const uchar* GpuMat::ptr(int y) const - { - CV_DbgAssert((unsigned)y < (unsigned)rows); - return data + step * y; - } - - inline GpuMat& GpuMat::operator = (Scalar s) - { - setTo(s); - return *this; - } - - template inline GpuMat::operator PtrStepSz() const - { - return PtrStepSz(rows, cols, (T*)data, step); - } - - template inline GpuMat::operator PtrStep() const - { - return PtrStep((T*)data, step); - } - - template inline GpuMat::operator DevMem2D_() const - { - return DevMem2D_(rows, cols, (T*)data, step); - } - - inline GpuMat createContinuous(int rows, int cols, int type) - { - GpuMat m; - createContinuous(rows, cols, type, m); - return m; - } - - inline void createContinuous(Size size, int type, GpuMat& m) - { - createContinuous(size.height, size.width, type, m); - } - - inline GpuMat createContinuous(Size size, int type) - { - GpuMat m; - createContinuous(size, type, m); - return m; - } - - inline void ensureSizeIsEnough(Size size, int type, GpuMat& m) - { - ensureSizeIsEnough(size.height, size.width, type, m); - } -}} - -#endif // __cplusplus - -#endif // __OPENCV_GPUMAT_HPP__ diff --git a/modules/core/include/opencv2/core/internal.hpp b/modules/core/include/opencv2/core/internal.hpp deleted file mode 100644 index 1faa0944a5..0000000000 --- a/modules/core/include/opencv2/core/internal.hpp +++ /dev/null @@ -1,763 +0,0 @@ -/*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*/ - -/* The header is for internal use and it is likely to change. - It contains some macro definitions that are used in cxcore, cv, cvaux - and, probably, other libraries. If you need some of this functionality, - the safe way is to copy it into your code and rename the macros. -*/ -#ifndef __OPENCV_CORE_INTERNAL_HPP__ -#define __OPENCV_CORE_INTERNAL_HPP__ - -#include - -#if defined WIN32 || defined _WIN32 -# ifndef WIN32 -# define WIN32 -# endif -# ifndef _WIN32 -# define _WIN32 -# endif -#endif - -#if !defined WIN32 && !defined WINCE -# include -#endif - -#ifdef __BORLANDC__ -# ifndef WIN32 -# define WIN32 -# endif -# ifndef _WIN32 -# define _WIN32 -# endif -# define CV_DLL -# undef _CV_ALWAYS_PROFILE_ -# define _CV_ALWAYS_NO_PROFILE_ -#endif - -#ifndef FALSE -# define FALSE 0 -#endif -#ifndef TRUE -# define TRUE 1 -#endif - -#define __BEGIN__ __CV_BEGIN__ -#define __END__ __CV_END__ -#define EXIT __CV_EXIT__ - -#ifdef HAVE_IPP -# include "ipp.h" - -CV_INLINE IppiSize ippiSize(int width, int height) -{ - IppiSize size = { width, height }; - return size; -} -#endif - -#ifndef IPPI_CALL -# define IPPI_CALL(func) CV_Assert((func) >= 0) -#endif - -#if defined __SSE2__ || defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP >= 2) -# include "emmintrin.h" -# define CV_SSE 1 -# define CV_SSE2 1 -# if defined __SSE3__ || (defined _MSC_VER && _MSC_VER >= 1500) -# include "pmmintrin.h" -# define CV_SSE3 1 -# endif -# if defined __SSSE3__ || (defined _MSC_VER && _MSC_VER >= 1500) -# include "tmmintrin.h" -# define CV_SSSE3 1 -# endif -# if defined __SSE4_1__ || (defined _MSC_VER && _MSC_VER >= 1500) -# include -# define CV_SSE4_1 1 -# endif -# if defined __SSE4_2__ || (defined _MSC_VER && _MSC_VER >= 1500) -# include -# define CV_SSE4_2 1 -# endif -# if defined __AVX__ || (defined _MSC_FULL_VER && _MSC_FULL_VER >= 160040219) -// MS Visual Studio 2010 (2012?) has no macro pre-defined to identify the use of /arch:AVX -// See: http://connect.microsoft.com/VisualStudio/feedback/details/605858/arch-avx-should-define-a-predefined-macro-in-x64-and-set-a-unique-value-for-m-ix86-fp-in-win32 -# include -# define CV_AVX 1 -# if defined(_XCR_XFEATURE_ENABLED_MASK) -# define __xgetbv() _xgetbv(_XCR_XFEATURE_ENABLED_MASK) -# else -# define __xgetbv() 0 -# endif -# endif -#endif - -#ifdef __ARM_NEON__ -# include -# define CV_NEON 1 -# define CPU_HAS_NEON_FEATURE (true) -#endif - -#ifndef CV_SSE -# define CV_SSE 0 -#endif -#ifndef CV_SSE2 -# define CV_SSE2 0 -#endif -#ifndef CV_SSE3 -# define CV_SSE3 0 -#endif -#ifndef CV_SSSE3 -# define CV_SSSE3 0 -#endif -#ifndef CV_SSE4_1 -# define CV_SSE4_1 0 -#endif -#ifndef CV_SSE4_2 -# define CV_SSE4_2 0 -#endif -#ifndef CV_AVX -# define CV_AVX 0 -#endif -#ifndef CV_NEON -# define CV_NEON 0 -#endif - -#ifdef HAVE_TBB -# include "tbb/tbb_stddef.h" -# if TBB_VERSION_MAJOR*100 + TBB_VERSION_MINOR >= 202 -# include "tbb/tbb.h" -# include "tbb/task.h" -# undef min -# undef max -# else -# undef HAVE_TBB -# endif -#endif - -#ifdef HAVE_EIGEN -# if defined __GNUC__ && defined __APPLE__ -# pragma GCC diagnostic ignored "-Wshadow" -# endif -# include -# include "opencv2/core/eigen.hpp" -#endif - -#ifdef __cplusplus - -namespace cv -{ -#ifdef HAVE_TBB - - typedef tbb::blocked_range BlockedRange; - - template static inline - void parallel_for( const BlockedRange& range, const Body& body ) - { - tbb::parallel_for(range, body); - } - - template static inline - void parallel_do( Iterator first, Iterator last, const Body& body ) - { - tbb::parallel_do(first, last, body); - } - - typedef tbb::split Split; - - template static inline - void parallel_reduce( const BlockedRange& range, Body& body ) - { - tbb::parallel_reduce(range, body); - } - - typedef tbb::concurrent_vector ConcurrentRectVector; - typedef tbb::concurrent_vector ConcurrentDoubleVector; -#else - class BlockedRange - { - public: - BlockedRange() : _begin(0), _end(0), _grainsize(0) {} - BlockedRange(int b, int e, int g=1) : _begin(b), _end(e), _grainsize(g) {} - int begin() const { return _begin; } - int end() const { return _end; } - int grainsize() const { return _grainsize; } - - protected: - int _begin, _end, _grainsize; - }; - - template static inline - void parallel_for( const BlockedRange& range, const Body& body ) - { - body(range); - } - typedef std::vector ConcurrentRectVector; - typedef std::vector ConcurrentDoubleVector; - - template static inline - void parallel_do( Iterator first, Iterator last, const Body& body ) - { - for( ; first != last; ++first ) - body(*first); - } - - class Split {}; - - template static inline - void parallel_reduce( const BlockedRange& range, Body& body ) - { - body(range); - } -#endif -} //namespace cv - -#define CV_INIT_ALGORITHM(classname, algname, memberinit) \ - static ::cv::Algorithm* create##classname() \ - { \ - return new classname; \ - } \ - \ - static ::cv::AlgorithmInfo& classname##_info() \ - { \ - static ::cv::AlgorithmInfo classname##_info_var(algname, create##classname); \ - return classname##_info_var; \ - } \ - \ - static ::cv::AlgorithmInfo& classname##_info_auto = classname##_info(); \ - \ - ::cv::AlgorithmInfo* classname::info() const \ - { \ - static volatile bool initialized = false; \ - \ - if( !initialized ) \ - { \ - initialized = true; \ - classname obj; \ - memberinit; \ - } \ - return &classname##_info(); \ - } - -#endif //__cplusplus - -/* maximal size of vector to run matrix operations on it inline (i.e. w/o ipp calls) */ -#define CV_MAX_INLINE_MAT_OP_SIZE 10 - -/* maximal linear size of matrix to allocate it on stack. */ -#define CV_MAX_LOCAL_MAT_SIZE 32 - -/* maximal size of local memory storage */ -#define CV_MAX_LOCAL_SIZE \ - (CV_MAX_LOCAL_MAT_SIZE*CV_MAX_LOCAL_MAT_SIZE*(int)sizeof(double)) - -/* default image row align (in bytes) */ -#define CV_DEFAULT_IMAGE_ROW_ALIGN 4 - -/* matrices are continuous by default */ -#define CV_DEFAULT_MAT_ROW_ALIGN 1 - -/* maximum size of dynamic memory buffer. - cvAlloc reports an error if a larger block is requested. */ -#define CV_MAX_ALLOC_SIZE (((size_t)1 << (sizeof(size_t)*8-2))) - -/* the alignment of all the allocated buffers */ -#define CV_MALLOC_ALIGN 16 - -/* default alignment for dynamic data strucutures, resided in storages. */ -#define CV_STRUCT_ALIGN ((int)sizeof(double)) - -/* default storage block size */ -#define CV_STORAGE_BLOCK_SIZE ((1<<16) - 128) - -/* default memory block for sparse array elements */ -#define CV_SPARSE_MAT_BLOCK (1<<12) - -/* initial hash table size */ -#define CV_SPARSE_HASH_SIZE0 (1<<10) - -/* maximal average node_count/hash_size ratio beyond which hash table is resized */ -#define CV_SPARSE_HASH_RATIO 3 - -/* max length of strings */ -#define CV_MAX_STRLEN 1024 - -#if 0 /*def CV_CHECK_FOR_NANS*/ -# define CV_CHECK_NANS( arr ) cvCheckArray((arr)) -#else -# define CV_CHECK_NANS( arr ) -#endif - -/****************************************************************************************\ -* Common declarations * -\****************************************************************************************/ - -/* get alloca declaration */ -#ifdef __GNUC__ -# undef alloca -# define alloca __builtin_alloca -# define CV_HAVE_ALLOCA 1 -#elif defined WIN32 || defined _WIN32 || \ - defined WINCE || defined _MSC_VER || defined __BORLANDC__ -# include -# define CV_HAVE_ALLOCA 1 -#elif defined HAVE_ALLOCA_H -# include -# define CV_HAVE_ALLOCA 1 -#elif defined HAVE_ALLOCA -# include -# define CV_HAVE_ALLOCA 1 -#else -# undef CV_HAVE_ALLOCA -#endif - -#ifdef __GNUC__ -# define CV_DECL_ALIGNED(x) __attribute__ ((aligned (x))) -#elif defined _MSC_VER -# define CV_DECL_ALIGNED(x) __declspec(align(x)) -#else -# define CV_DECL_ALIGNED(x) -#endif - -#if CV_HAVE_ALLOCA -/* ! DO NOT make it an inline function */ -# define cvStackAlloc(size) cvAlignPtr( alloca((size) + CV_MALLOC_ALIGN), CV_MALLOC_ALIGN ) -#endif - -#ifndef CV_IMPL -# define CV_IMPL CV_EXTERN_C -#endif - -#define CV_DBG_BREAK() { volatile int* crashMe = 0; *crashMe = 0; } - -/* default step, set in case of continuous data - to work around checks for valid step in some ipp functions */ -#define CV_STUB_STEP (1 << 30) - -#define CV_SIZEOF_FLOAT ((int)sizeof(float)) -#define CV_SIZEOF_SHORT ((int)sizeof(short)) - -#define CV_ORIGIN_TL 0 -#define CV_ORIGIN_BL 1 - -/* IEEE754 constants and macros */ -#define CV_POS_INF 0x7f800000 -#define CV_NEG_INF 0x807fffff /* CV_TOGGLE_FLT(0xff800000) */ -#define CV_1F 0x3f800000 -#define CV_TOGGLE_FLT(x) ((x)^((int)(x) < 0 ? 0x7fffffff : 0)) -#define CV_TOGGLE_DBL(x) \ - ((x)^((int64)(x) < 0 ? CV_BIG_INT(0x7fffffffffffffff) : 0)) - -#define CV_NOP(a) (a) -#define CV_ADD(a, b) ((a) + (b)) -#define CV_SUB(a, b) ((a) - (b)) -#define CV_MUL(a, b) ((a) * (b)) -#define CV_AND(a, b) ((a) & (b)) -#define CV_OR(a, b) ((a) | (b)) -#define CV_XOR(a, b) ((a) ^ (b)) -#define CV_ANDN(a, b) (~(a) & (b)) -#define CV_ORN(a, b) (~(a) | (b)) -#define CV_SQR(a) ((a) * (a)) - -#define CV_LT(a, b) ((a) < (b)) -#define CV_LE(a, b) ((a) <= (b)) -#define CV_EQ(a, b) ((a) == (b)) -#define CV_NE(a, b) ((a) != (b)) -#define CV_GT(a, b) ((a) > (b)) -#define CV_GE(a, b) ((a) >= (b)) - -#define CV_NONZERO(a) ((a) != 0) -#define CV_NONZERO_FLT(a) (((a)+(a)) != 0) - -/* general-purpose saturation macros */ -#define CV_CAST_8U(t) (uchar)(!((t) & ~255) ? (t) : (t) > 0 ? 255 : 0) -#define CV_CAST_8S(t) (schar)(!(((t)+128) & ~255) ? (t) : (t) > 0 ? 127 : -128) -#define CV_CAST_16U(t) (ushort)(!((t) & ~65535) ? (t) : (t) > 0 ? 65535 : 0) -#define CV_CAST_16S(t) (short)(!(((t)+32768) & ~65535) ? (t) : (t) > 0 ? 32767 : -32768) -#define CV_CAST_32S(t) (int)(t) -#define CV_CAST_64S(t) (int64)(t) -#define CV_CAST_32F(t) (float)(t) -#define CV_CAST_64F(t) (double)(t) - -#define CV_PASTE2(a,b) a##b -#define CV_PASTE(a,b) CV_PASTE2(a,b) - -#define CV_EMPTY -#define CV_MAKE_STR(a) #a - -#define CV_ZERO_OBJ(x) memset((x), 0, sizeof(*(x))) - -#define CV_DIM(static_array) ((int)(sizeof(static_array)/sizeof((static_array)[0]))) - -#define cvUnsupportedFormat "Unsupported format" - -CV_INLINE void* cvAlignPtr( const void* ptr, int align CV_DEFAULT(32) ) -{ - assert( (align & (align-1)) == 0 ); - return (void*)( ((size_t)ptr + align - 1) & ~(size_t)(align-1) ); -} - -CV_INLINE int cvAlign( int size, int align ) -{ - assert( (align & (align-1)) == 0 && size < INT_MAX ); - return (size + align - 1) & -align; -} - -CV_INLINE CvSize cvGetMatSize( const CvMat* mat ) -{ - CvSize size; - size.width = mat->cols; - size.height = mat->rows; - return size; -} - -#define CV_DESCALE(x,n) (((x) + (1 << ((n)-1))) >> (n)) -#define CV_FLT_TO_FIX(x,n) cvRound((x)*(1<<(n))) - -/****************************************************************************************\ - - Generic implementation of QuickSort algorithm. - ---------------------------------------------- - Using this macro user can declare customized sort function that can be much faster - than built-in qsort function because of lower overhead on elements - comparison and exchange. The macro takes less_than (or LT) argument - a macro or function - that takes 2 arguments returns non-zero if the first argument should be before the second - one in the sorted sequence and zero otherwise. - - Example: - - Suppose that the task is to sort points by ascending of y coordinates and if - y's are equal x's should ascend. - - The code is: - ------------------------------------------------------------------------------ - #define cmp_pts( pt1, pt2 ) \ - ((pt1).y < (pt2).y || ((pt1).y < (pt2).y && (pt1).x < (pt2).x)) - - [static] CV_IMPLEMENT_QSORT( icvSortPoints, CvPoint, cmp_pts ) - ------------------------------------------------------------------------------ - - After that the function "void icvSortPoints( CvPoint* array, size_t total, int aux );" - is available to user. - - aux is an additional parameter, which can be used when comparing elements. - The current implementation was derived from *BSD system qsort(): - - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - -\****************************************************************************************/ - -#define CV_IMPLEMENT_QSORT_EX( func_name, T, LT, user_data_type ) \ -void func_name( T *array, size_t total, user_data_type aux ) \ -{ \ - int isort_thresh = 7; \ - T t; \ - int sp = 0; \ - \ - struct \ - { \ - T *lb; \ - T *ub; \ - } \ - stack[48]; \ - \ - aux = aux; \ - \ - if( total <= 1 ) \ - return; \ - \ - stack[0].lb = array; \ - stack[0].ub = array + (total - 1); \ - \ - while( sp >= 0 ) \ - { \ - T* left = stack[sp].lb; \ - T* right = stack[sp--].ub; \ - \ - for(;;) \ - { \ - int i, n = (int)(right - left) + 1, m; \ - T* ptr; \ - T* ptr2; \ - \ - if( n <= isort_thresh ) \ - { \ - insert_sort: \ - for( ptr = left + 1; ptr <= right; ptr++ ) \ - { \ - for( ptr2 = ptr; ptr2 > left && LT(ptr2[0],ptr2[-1]); ptr2--) \ - CV_SWAP( ptr2[0], ptr2[-1], t ); \ - } \ - break; \ - } \ - else \ - { \ - T* left0; \ - T* left1; \ - T* right0; \ - T* right1; \ - T* pivot; \ - T* a; \ - T* b; \ - T* c; \ - int swap_cnt = 0; \ - \ - left0 = left; \ - right0 = right; \ - pivot = left + (n/2); \ - \ - if( n > 40 ) \ - { \ - int d = n / 8; \ - a = left, b = left + d, c = left + 2*d; \ - left = LT(*a, *b) ? (LT(*b, *c) ? b : (LT(*a, *c) ? c : a)) \ - : (LT(*c, *b) ? b : (LT(*a, *c) ? a : c)); \ - \ - a = pivot - d, b = pivot, c = pivot + d; \ - pivot = LT(*a, *b) ? (LT(*b, *c) ? b : (LT(*a, *c) ? c : a)) \ - : (LT(*c, *b) ? b : (LT(*a, *c) ? a : c)); \ - \ - a = right - 2*d, b = right - d, c = right; \ - right = LT(*a, *b) ? (LT(*b, *c) ? b : (LT(*a, *c) ? c : a)) \ - : (LT(*c, *b) ? b : (LT(*a, *c) ? a : c)); \ - } \ - \ - a = left, b = pivot, c = right; \ - pivot = LT(*a, *b) ? (LT(*b, *c) ? b : (LT(*a, *c) ? c : a)) \ - : (LT(*c, *b) ? b : (LT(*a, *c) ? a : c)); \ - if( pivot != left0 ) \ - { \ - CV_SWAP( *pivot, *left0, t ); \ - pivot = left0; \ - } \ - left = left1 = left0 + 1; \ - right = right1 = right0; \ - \ - for(;;) \ - { \ - while( left <= right && !LT(*pivot, *left) ) \ - { \ - if( !LT(*left, *pivot) ) \ - { \ - if( left > left1 ) \ - CV_SWAP( *left1, *left, t ); \ - swap_cnt = 1; \ - left1++; \ - } \ - left++; \ - } \ - \ - while( left <= right && !LT(*right, *pivot) ) \ - { \ - if( !LT(*pivot, *right) ) \ - { \ - if( right < right1 ) \ - CV_SWAP( *right1, *right, t ); \ - swap_cnt = 1; \ - right1--; \ - } \ - right--; \ - } \ - \ - if( left > right ) \ - break; \ - CV_SWAP( *left, *right, t ); \ - swap_cnt = 1; \ - left++; \ - right--; \ - } \ - \ - if( swap_cnt == 0 ) \ - { \ - left = left0, right = right0; \ - goto insert_sort; \ - } \ - \ - n = MIN( (int)(left1 - left0), (int)(left - left1) ); \ - for( i = 0; i < n; i++ ) \ - CV_SWAP( left0[i], left[i-n], t ); \ - \ - n = MIN( (int)(right0 - right1), (int)(right1 - right) ); \ - for( i = 0; i < n; i++ ) \ - CV_SWAP( left[i], right0[i-n+1], t ); \ - n = (int)(left - left1); \ - m = (int)(right1 - right); \ - if( n > 1 ) \ - { \ - if( m > 1 ) \ - { \ - if( n > m ) \ - { \ - stack[++sp].lb = left0; \ - stack[sp].ub = left0 + n - 1; \ - left = right0 - m + 1, right = right0; \ - } \ - else \ - { \ - stack[++sp].lb = right0 - m + 1; \ - stack[sp].ub = right0; \ - left = left0, right = left0 + n - 1; \ - } \ - } \ - else \ - left = left0, right = left0 + n - 1; \ - } \ - else if( m > 1 ) \ - left = right0 - m + 1, right = right0; \ - else \ - break; \ - } \ - } \ - } \ -} - -#define CV_IMPLEMENT_QSORT( func_name, T, cmp ) \ - CV_IMPLEMENT_QSORT_EX( func_name, T, cmp, int ) - -/****************************************************************************************\ -* Structures and macros for integration with IPP * -\****************************************************************************************/ - -/* IPP-compatible return codes */ -typedef enum CvStatus -{ - CV_BADMEMBLOCK_ERR = -113, - CV_INPLACE_NOT_SUPPORTED_ERR= -112, - CV_UNMATCHED_ROI_ERR = -111, - CV_NOTFOUND_ERR = -110, - CV_BADCONVERGENCE_ERR = -109, - - CV_BADDEPTH_ERR = -107, - CV_BADROI_ERR = -106, - CV_BADHEADER_ERR = -105, - CV_UNMATCHED_FORMATS_ERR = -104, - CV_UNSUPPORTED_COI_ERR = -103, - CV_UNSUPPORTED_CHANNELS_ERR = -102, - CV_UNSUPPORTED_DEPTH_ERR = -101, - CV_UNSUPPORTED_FORMAT_ERR = -100, - - CV_BADARG_ERR = -49, //ipp comp - CV_NOTDEFINED_ERR = -48, //ipp comp - - CV_BADCHANNELS_ERR = -47, //ipp comp - CV_BADRANGE_ERR = -44, //ipp comp - CV_BADSTEP_ERR = -29, //ipp comp - - CV_BADFLAG_ERR = -12, - CV_DIV_BY_ZERO_ERR = -11, //ipp comp - CV_BADCOEF_ERR = -10, - - CV_BADFACTOR_ERR = -7, - CV_BADPOINT_ERR = -6, - CV_BADSCALE_ERR = -4, - CV_OUTOFMEM_ERR = -3, - CV_NULLPTR_ERR = -2, - CV_BADSIZE_ERR = -1, - CV_NO_ERR = 0, - CV_OK = CV_NO_ERR -} -CvStatus; - -#define CV_NOTHROW throw() - -typedef struct CvFuncTable -{ - void* fn_2d[CV_DEPTH_MAX]; -} -CvFuncTable; - -typedef struct CvBigFuncTable -{ - void* fn_2d[CV_DEPTH_MAX*4]; -} CvBigFuncTable; - -#define CV_INIT_FUNC_TAB( tab, FUNCNAME, FLAG ) \ - (tab).fn_2d[CV_8U] = (void*)FUNCNAME##_8u##FLAG; \ - (tab).fn_2d[CV_8S] = 0; \ - (tab).fn_2d[CV_16U] = (void*)FUNCNAME##_16u##FLAG; \ - (tab).fn_2d[CV_16S] = (void*)FUNCNAME##_16s##FLAG; \ - (tab).fn_2d[CV_32S] = (void*)FUNCNAME##_32s##FLAG; \ - (tab).fn_2d[CV_32F] = (void*)FUNCNAME##_32f##FLAG; \ - (tab).fn_2d[CV_64F] = (void*)FUNCNAME##_64f##FLAG - -namespace cv { namespace ogl { -CV_EXPORTS bool checkError(const char* file, const int line, const char* func = ""); -}} - -#if defined(__GNUC__) - #define CV_CheckGlError() CV_DbgAssert( (cv::ogl::checkError(__FILE__, __LINE__, __func__)) ) -#else - #define CV_CheckGlError() CV_DbgAssert( (cv::ogl::checkError(__FILE__, __LINE__)) ) -#endif - -#endif // __OPENCV_CORE_INTERNAL_HPP__ diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index 8e7890568c..c132be9456 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -7,11 +7,12 @@ // copy or use the software. // // -// License Agreement +// License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -40,1137 +41,1819 @@ // //M*/ -#ifndef __OPENCV_CORE_MATRIX_OPERATIONS_HPP__ -#define __OPENCV_CORE_MATRIX_OPERATIONS_HPP__ +#ifndef __OPENCV_CORE_MAT_HPP__ +#define __OPENCV_CORE_MAT_HPP__ -#ifndef SKIP_INCLUDES -#include -#include -#endif // SKIP_INCLUDES +#ifndef __cplusplus +# error mat.hpp header must be compiled as C++ +#endif + +#include "opencv2/core/matx.hpp" +#include "opencv2/core/types.hpp" -#ifdef __cplusplus namespace cv { -//////////////////////////////// Mat //////////////////////////////// +//////////////////////// Input/Output Array Arguments ///////////////////////////////// -inline void Mat::initEmpty() +/*! + Proxy datatype for passing Mat's and vector<>'s as input parameters + */ +class CV_EXPORTS _InputArray { - flags = MAGIC_VAL; - dims = rows = cols = 0; - data = datastart = dataend = datalimit = 0; - refcount = 0; - allocator = 0; -} +public: + enum { + KIND_SHIFT = 16, + FIXED_TYPE = 0x8000 << KIND_SHIFT, + FIXED_SIZE = 0x4000 << KIND_SHIFT, + KIND_MASK = ~(FIXED_TYPE|FIXED_SIZE) - (1 << KIND_SHIFT) + 1, -inline Mat::Mat() : size(&rows) -{ - initEmpty(); -} + NONE = 0 << KIND_SHIFT, + MAT = 1 << KIND_SHIFT, + MATX = 2 << KIND_SHIFT, + STD_VECTOR = 3 << KIND_SHIFT, + STD_VECTOR_VECTOR = 4 << KIND_SHIFT, + STD_VECTOR_MAT = 5 << KIND_SHIFT, + EXPR = 6 << KIND_SHIFT, + OPENGL_BUFFER = 7 << KIND_SHIFT, + CUDA_MEM = 8 << KIND_SHIFT, + GPU_MAT = 9 << KIND_SHIFT, + OCL_MAT =10 << KIND_SHIFT + }; -inline Mat::Mat(int _rows, int _cols, int _type) : size(&rows) -{ - initEmpty(); - create(_rows, _cols, _type); -} + _InputArray(); + _InputArray(const Mat& m); + _InputArray(const MatExpr& expr); + _InputArray(const std::vector& vec); + template _InputArray(const Mat_<_Tp>& m); + template _InputArray(const std::vector<_Tp>& vec); + template _InputArray(const std::vector >& vec); + template _InputArray(const std::vector >& vec); + template _InputArray(const _Tp* vec, int n); + template _InputArray(const Matx<_Tp, m, n>& matx); + _InputArray(const double& val); + _InputArray(const gpu::GpuMat& d_mat); + _InputArray(const ogl::Buffer& buf); + _InputArray(const gpu::CudaMem& cuda_mem); + template _InputArray(const cudev::GpuMat_<_Tp>& m); -inline Mat::Mat(int _rows, int _cols, int _type, const Scalar& _s) : size(&rows) -{ - initEmpty(); - create(_rows, _cols, _type); - *this = _s; -} + virtual Mat getMat(int i=-1) const; + virtual void getMatVector(std::vector& mv) const; + virtual gpu::GpuMat getGpuMat() const; + virtual ogl::Buffer getOGlBuffer() const; -inline Mat::Mat(Size _sz, int _type) : size(&rows) -{ - initEmpty(); - create( _sz.height, _sz.width, _type ); -} + virtual int kind() const; + virtual Size size(int i=-1) const; + virtual size_t total(int i=-1) const; + virtual int type(int i=-1) const; + virtual int depth(int i=-1) const; + virtual int channels(int i=-1) const; + virtual bool empty() const; -inline Mat::Mat(Size _sz, int _type, const Scalar& _s) : size(&rows) -{ - initEmpty(); - create(_sz.height, _sz.width, _type); - *this = _s; -} + virtual ~_InputArray(); -inline Mat::Mat(int _dims, const int* _sz, int _type) : size(&rows) -{ - initEmpty(); - create(_dims, _sz, _type); -} + int flags; + void* obj; + Size sz; +}; -inline Mat::Mat(int _dims, const int* _sz, int _type, const Scalar& _s) : size(&rows) -{ - initEmpty(); - create(_dims, _sz, _type); - *this = _s; -} -inline Mat::Mat(const Mat& m) - : flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), data(m.data), - refcount(m.refcount), datastart(m.datastart), dataend(m.dataend), - datalimit(m.datalimit), allocator(m.allocator), size(&rows) +/*! + Proxy datatype for passing Mat's and vector<>'s as input parameters + */ +class CV_EXPORTS _OutputArray : public _InputArray { - if( refcount ) - CV_XADD(refcount, 1); - if( m.dims <= 2 ) +public: + enum { - step[0] = m.step[0]; step[1] = m.step[1]; - } - else + DEPTH_MASK_8U = 1 << CV_8U, + DEPTH_MASK_8S = 1 << CV_8S, + DEPTH_MASK_16U = 1 << CV_16U, + DEPTH_MASK_16S = 1 << CV_16S, + DEPTH_MASK_32S = 1 << CV_32S, + DEPTH_MASK_32F = 1 << CV_32F, + DEPTH_MASK_64F = 1 << CV_64F, + DEPTH_MASK_ALL = (DEPTH_MASK_64F<<1)-1, + DEPTH_MASK_ALL_BUT_8S = DEPTH_MASK_ALL & ~DEPTH_MASK_8S, + DEPTH_MASK_FLT = DEPTH_MASK_32F + DEPTH_MASK_64F + }; + + _OutputArray(); + _OutputArray(Mat& m); + _OutputArray(std::vector& vec); + _OutputArray(gpu::GpuMat& d_mat); + _OutputArray(ogl::Buffer& buf); + _OutputArray(gpu::CudaMem& cuda_mem); + template _OutputArray(cudev::GpuMat_<_Tp>& m); + template _OutputArray(std::vector<_Tp>& vec); + template _OutputArray(std::vector >& vec); + template _OutputArray(std::vector >& vec); + template _OutputArray(Mat_<_Tp>& m); + template _OutputArray(_Tp* vec, int n); + template _OutputArray(Matx<_Tp, m, n>& matx); + + _OutputArray(const Mat& m); + _OutputArray(const std::vector& vec); + _OutputArray(const gpu::GpuMat& d_mat); + _OutputArray(const ogl::Buffer& buf); + _OutputArray(const gpu::CudaMem& cuda_mem); + template _OutputArray(const cudev::GpuMat_<_Tp>& m); + template _OutputArray(const std::vector<_Tp>& vec); + template _OutputArray(const std::vector >& vec); + template _OutputArray(const std::vector >& vec); + template _OutputArray(const Mat_<_Tp>& m); + template _OutputArray(const _Tp* vec, int n); + template _OutputArray(const Matx<_Tp, m, n>& matx); + + virtual bool fixedSize() const; + virtual bool fixedType() const; + virtual bool needed() const; + virtual Mat& getMatRef(int i=-1) const; + virtual gpu::GpuMat& getGpuMatRef() const; + virtual ogl::Buffer& getOGlBufferRef() const; + virtual gpu::CudaMem& getCudaMemRef() const; + virtual void create(Size sz, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; + virtual void create(int rows, int cols, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; + virtual void create(int dims, const int* size, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; + virtual void release() const; + virtual void clear() const; + + virtual ~_OutputArray(); +}; + +typedef const _InputArray& InputArray; +typedef InputArray InputArrayOfArrays; +typedef const _OutputArray& OutputArray; +typedef OutputArray OutputArrayOfArrays; +typedef OutputArray InputOutputArray; +typedef OutputArray InputOutputArrayOfArrays; + +CV_EXPORTS OutputArray noArray(); + + + +/////////////////////////////////// MatAllocator ////////////////////////////////////// + +/*! + Custom array allocator + +*/ +class CV_EXPORTS MatAllocator +{ +public: + MatAllocator() {} + virtual ~MatAllocator() {} + virtual void allocate(int dims, const int* sizes, int type, int*& refcount, + uchar*& datastart, uchar*& data, size_t* step) = 0; + virtual void deallocate(int* refcount, uchar* datastart, uchar* data) = 0; +}; + + + +//////////////////////////////// MatCommaInitializer ////////////////////////////////// + +/*! + Comma-separated Matrix Initializer + + The class instances are usually not created explicitly. + Instead, they are created on "matrix << firstValue" operator. + + The sample below initializes 2x2 rotation matrix: + + \code + double angle = 30, a = cos(angle*CV_PI/180), b = sin(angle*CV_PI/180); + Mat R = (Mat_(2,2) << a, -b, b, a); + \endcode +*/ +template class MatCommaInitializer_ +{ +public: + //! the constructor, created by "matrix << firstValue" operator, where matrix is cv::Mat + MatCommaInitializer_(Mat_<_Tp>* _m); + //! the operator that takes the next value and put it to the matrix + template MatCommaInitializer_<_Tp>& operator , (T2 v); + //! another form of conversion operator + operator Mat_<_Tp>() const; +protected: + MatIterator_<_Tp> it; +}; + + + + +/////////////////////////////////////// Mat /////////////////////////////////////////// + +/*! + The n-dimensional matrix class. + + The class represents an n-dimensional dense numerical array that can act as + a matrix, image, optical flow map, 3-focal tensor etc. + It is very similar to CvMat and CvMatND types from earlier versions of OpenCV, + and similarly to those types, the matrix can be multi-channel. It also fully supports ROI mechanism. + + There are many different ways to create cv::Mat object. Here are the some popular ones: +
      +
    • using cv::Mat::create(nrows, ncols, type) method or + the similar constructor cv::Mat::Mat(nrows, ncols, type[, fill_value]) constructor. + A new matrix of the specified size and specifed type will be allocated. + "type" has the same meaning as in cvCreateMat function, + e.g. CV_8UC1 means 8-bit single-channel matrix, CV_32FC2 means 2-channel (i.e. complex) + floating-point matrix etc: + + \code + // make 7x7 complex matrix filled with 1+3j. + cv::Mat M(7,7,CV_32FC2,Scalar(1,3)); + // and now turn M to 100x60 15-channel 8-bit matrix. + // The old content will be deallocated + M.create(100,60,CV_8UC(15)); + \endcode + + As noted in the introduction of this chapter, Mat::create() + will only allocate a new matrix when the current matrix dimensionality + or type are different from the specified. + +
    • by using a copy constructor or assignment operator, where on the right side it can + be a matrix or expression, see below. Again, as noted in the introduction, + matrix assignment is O(1) operation because it only copies the header + and increases the reference counter. cv::Mat::clone() method can be used to get a full + (a.k.a. deep) copy of the matrix when you need it. + +
    • by constructing a header for a part of another matrix. It can be a single row, single column, + several rows, several columns, rectangular region in the matrix (called a minor in algebra) or + a diagonal. Such operations are also O(1), because the new header will reference the same data. + You can actually modify a part of the matrix using this feature, e.g. + + \code + // add 5-th row, multiplied by 3 to the 3rd row + M.row(3) = M.row(3) + M.row(5)*3; + + // now copy 7-th column to the 1-st column + // M.col(1) = M.col(7); // this will not work + Mat M1 = M.col(1); + M.col(7).copyTo(M1); + + // create new 320x240 image + cv::Mat img(Size(320,240),CV_8UC3); + // select a roi + cv::Mat roi(img, Rect(10,10,100,100)); + // fill the ROI with (0,255,0) (which is green in RGB space); + // the original 320x240 image will be modified + roi = Scalar(0,255,0); + \endcode + + Thanks to the additional cv::Mat::datastart and cv::Mat::dataend members, it is possible to + compute the relative sub-matrix position in the main "container" matrix using cv::Mat::locateROI(): + + \code + Mat A = Mat::eye(10, 10, CV_32S); + // extracts A columns, 1 (inclusive) to 3 (exclusive). + Mat B = A(Range::all(), Range(1, 3)); + // extracts B rows, 5 (inclusive) to 9 (exclusive). + // that is, C ~ A(Range(5, 9), Range(1, 3)) + Mat C = B(Range(5, 9), Range::all()); + Size size; Point ofs; + C.locateROI(size, ofs); + // size will be (width=10,height=10) and the ofs will be (x=1, y=5) + \endcode + + As in the case of whole matrices, if you need a deep copy, use cv::Mat::clone() method + of the extracted sub-matrices. + +
    • by making a header for user-allocated-data. It can be useful for +
        +
      1. processing "foreign" data using OpenCV (e.g. when you implement + a DirectShow filter or a processing module for gstreamer etc.), e.g. + + \code + void process_video_frame(const unsigned char* pixels, + int width, int height, int step) + { + cv::Mat img(height, width, CV_8UC3, pixels, step); + cv::GaussianBlur(img, img, cv::Size(7,7), 1.5, 1.5); + } + \endcode + +
      2. for quick initialization of small matrices and/or super-fast element access + + \code + double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}}; + cv::Mat M = cv::Mat(3, 3, CV_64F, m).inv(); + \endcode +
      + + partial yet very common cases of this "user-allocated data" case are conversions + from CvMat and IplImage to cv::Mat. For this purpose there are special constructors + taking pointers to CvMat or IplImage and the optional + flag indicating whether to copy the data or not. + + Backward conversion from cv::Mat to CvMat or IplImage is provided via cast operators + cv::Mat::operator CvMat() an cv::Mat::operator IplImage(). + The operators do not copy the data. + + + \code + IplImage* img = cvLoadImage("greatwave.jpg", 1); + Mat mtx(img); // convert IplImage* -> cv::Mat + CvMat oldmat = mtx; // convert cv::Mat -> CvMat + CV_Assert(oldmat.cols == img->width && oldmat.rows == img->height && + oldmat.data.ptr == (uchar*)img->imageData && oldmat.step == img->widthStep); + \endcode + +
    • by using MATLAB-style matrix initializers, cv::Mat::zeros(), cv::Mat::ones(), cv::Mat::eye(), e.g.: + + \code + // create a double-precision identity martix and add it to M. + M += Mat::eye(M.rows, M.cols, CV_64F); + \endcode + +
    • by using comma-separated initializer: + + \code + // create 3x3 double-precision identity matrix + Mat M = (Mat_(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1); + \endcode + + here we first call constructor of cv::Mat_ class (that we describe further) with the proper matrix, + and then we just put "<<" operator followed by comma-separated values that can be constants, + variables, expressions etc. Also, note the extra parentheses that are needed to avoid compiler errors. + +
    + + Once matrix is created, it will be automatically managed by using reference-counting mechanism + (unless the matrix header is built on top of user-allocated data, + in which case you should handle the data by yourself). + The matrix data will be deallocated when no one points to it; + if you want to release the data pointed by a matrix header before the matrix destructor is called, + use cv::Mat::release(). + + The next important thing to learn about the matrix class is element access. Here is how the matrix is stored. + The elements are stored in row-major order (row by row). The cv::Mat::data member points to the first element of the first row, + cv::Mat::rows contains the number of matrix rows and cv::Mat::cols - the number of matrix columns. There is yet another member, + cv::Mat::step that is used to actually compute address of a matrix element. cv::Mat::step is needed because the matrix can be + a part of another matrix or because there can some padding space in the end of each row for a proper alignment. + + \image html roi.png + + Given these parameters, address of the matrix element M_{ij} is computed as following: + + addr(M_{ij})=M.data + M.step*i + j*M.elemSize() + + if you know the matrix element type, e.g. it is float, then you can use cv::Mat::at() method: + + addr(M_{ij})=&M.at(i,j) + + (where & is used to convert the reference returned by cv::Mat::at() to a pointer). + if you need to process a whole row of matrix, the most efficient way is to get + the pointer to the row first, and then just use plain C operator []: + + \code + // compute sum of positive matrix elements + // (assuming that M is double-precision matrix) + double sum=0; + for(int i = 0; i < M.rows; i++) + { + const double* Mi = M.ptr(i); + for(int j = 0; j < M.cols; j++) + sum += std::max(Mi[j], 0.); + } + \endcode + + Some operations, like the above one, do not actually depend on the matrix shape, + they just process elements of a matrix one by one (or elements from multiple matrices + that are sitting in the same place, e.g. matrix addition). Such operations are called + element-wise and it makes sense to check whether all the input/output matrices are continuous, + i.e. have no gaps in the end of each row, and if yes, process them as a single long row: + + \code + // compute sum of positive matrix elements, optimized variant + double sum=0; + int cols = M.cols, rows = M.rows; + if(M.isContinuous()) + { + cols *= rows; + rows = 1; + } + for(int i = 0; i < rows; i++) + { + const double* Mi = M.ptr(i); + for(int j = 0; j < cols; j++) + sum += std::max(Mi[j], 0.); + } + \endcode + in the case of continuous matrix the outer loop body will be executed just once, + so the overhead will be smaller, which will be especially noticeable in the case of small matrices. + + Finally, there are STL-style iterators that are smart enough to skip gaps between successive rows: + \code + // compute sum of positive matrix elements, iterator-based variant + double sum=0; + MatConstIterator_ it = M.begin(), it_end = M.end(); + for(; it != it_end; ++it) + sum += std::max(*it, 0.); + \endcode + + The matrix iterators are random-access iterators, so they can be passed + to any STL algorithm, including std::sort(). +*/ +class CV_EXPORTS Mat +{ +public: + //! default constructor + Mat(); + //! constructs 2D matrix of the specified size and type + // (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.) + Mat(int rows, int cols, int type); + Mat(Size size, int type); + //! constucts 2D matrix and fills it with the specified value _s. + Mat(int rows, int cols, int type, const Scalar& s); + Mat(Size size, int type, const Scalar& s); + + //! constructs n-dimensional matrix + Mat(int ndims, const int* sizes, int type); + Mat(int ndims, const int* sizes, int type, const Scalar& s); + + //! copy constructor + Mat(const Mat& m); + //! constructor for matrix headers pointing to user-allocated data + Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP); + Mat(Size size, int type, void* data, size_t step=AUTO_STEP); + Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0); + + //! creates a matrix header for a part of the bigger matrix + Mat(const Mat& m, const Range& rowRange, const Range& colRange=Range::all()); + Mat(const Mat& m, const Rect& roi); + Mat(const Mat& m, const Range* ranges); + //! builds matrix from std::vector with or without copying the data + template explicit Mat(const std::vector<_Tp>& vec, bool copyData=false); + //! builds matrix from cv::Vec; the data is copied by default + template explicit Mat(const Vec<_Tp, n>& vec, bool copyData=true); + //! builds matrix from cv::Matx; the data is copied by default + template explicit Mat(const Matx<_Tp, m, n>& mtx, bool copyData=true); + //! builds matrix from a 2D point + template explicit Mat(const Point_<_Tp>& pt, bool copyData=true); + //! builds matrix from a 3D point + template explicit Mat(const Point3_<_Tp>& pt, bool copyData=true); + //! builds matrix from comma initializer + template explicit Mat(const MatCommaInitializer_<_Tp>& commaInitializer); + + // //! converts old-style CvMat to the new matrix; the data is not copied by default + // Mat(const CvMat* m, bool copyData=false); + // //! converts old-style CvMatND to the new matrix; the data is not copied by default + // Mat(const CvMatND* m, bool copyData=false); + // //! converts old-style IplImage to the new matrix; the data is not copied by default + // Mat(const IplImage* img, bool copyData=false); + //Mat(const void* img, bool copyData=false); + + //! download data from GpuMat + explicit Mat(const gpu::GpuMat& m); + + //! destructor - calls release() + ~Mat(); + //! assignment operators + Mat& operator = (const Mat& m); + Mat& operator = (const MatExpr& expr); + + //! returns a new matrix header for the specified row + Mat row(int y) const; + //! returns a new matrix header for the specified column + Mat col(int x) const; + //! ... for the specified row span + Mat rowRange(int startrow, int endrow) const; + Mat rowRange(const Range& r) const; + //! ... for the specified column span + Mat colRange(int startcol, int endcol) const; + Mat colRange(const Range& r) const; + //! ... for the specified diagonal + // (d=0 - the main diagonal, + // >0 - a diagonal from the lower half, + // <0 - a diagonal from the upper half) + Mat diag(int d=0) const; + //! constructs a square diagonal matrix which main diagonal is vector "d" + static Mat diag(const Mat& d); + + //! returns deep copy of the matrix, i.e. the data is copied + Mat clone() const; + //! copies the matrix content to "m". + // It calls m.create(this->size(), this->type()). + void copyTo( OutputArray m ) const; + //! copies those matrix elements to "m" that are marked with non-zero mask elements. + void copyTo( OutputArray m, InputArray mask ) const; + //! converts matrix to another datatype with optional scalng. See cvConvertScale. + void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const; + + void assignTo( Mat& m, int type=-1 ) const; + + //! sets every matrix element to s + Mat& operator = (const Scalar& s); + //! sets some of the matrix elements to s, according to the mask + Mat& setTo(InputArray value, InputArray mask=noArray()); + //! creates alternative matrix header for the same data, with different + // number of channels and/or different number of rows. see cvReshape. + Mat reshape(int cn, int rows=0) const; + Mat reshape(int cn, int newndims, const int* newsz) const; + + //! matrix transposition by means of matrix expressions + MatExpr t() const; + //! matrix inversion by means of matrix expressions + MatExpr inv(int method=DECOMP_LU) const; + //! per-element matrix multiplication by means of matrix expressions + MatExpr mul(InputArray m, double scale=1) const; + + //! computes cross-product of 2 3D vectors + Mat cross(InputArray m) const; + //! computes dot-product + double dot(InputArray m) const; + + //! Matlab-style matrix initialization + static MatExpr zeros(int rows, int cols, int type); + static MatExpr zeros(Size size, int type); + static MatExpr zeros(int ndims, const int* sz, int type); + static MatExpr ones(int rows, int cols, int type); + static MatExpr ones(Size size, int type); + static MatExpr ones(int ndims, const int* sz, int type); + static MatExpr eye(int rows, int cols, int type); + static MatExpr eye(Size size, int type); + + //! allocates new matrix data unless the matrix already has specified size and type. + // previous data is unreferenced if needed. + void create(int rows, int cols, int type); + void create(Size size, int type); + void create(int ndims, const int* sizes, int type); + + //! increases the reference counter; use with care to avoid memleaks + void addref(); + //! decreases reference counter; + // deallocates the data when reference counter reaches 0. + void release(); + + //! deallocates the matrix data + void deallocate(); + //! internal use function; properly re-allocates _size, _step arrays + void copySize(const Mat& m); + + //! reserves enough space to fit sz hyper-planes + void reserve(size_t sz); + //! resizes matrix to the specified number of hyper-planes + void resize(size_t sz); + //! resizes matrix to the specified number of hyper-planes; initializes the newly added elements + void resize(size_t sz, const Scalar& s); + //! internal function + void push_back_(const void* elem); + //! adds element to the end of 1d matrix (or possibly multiple elements when _Tp=Mat) + template void push_back(const _Tp& elem); + template void push_back(const Mat_<_Tp>& elem); + void push_back(const Mat& m); + //! removes several hyper-planes from bottom of the matrix + void pop_back(size_t nelems=1); + + //! locates matrix header within a parent matrix. See below + void locateROI( Size& wholeSize, Point& ofs ) const; + //! moves/resizes the current matrix ROI inside the parent matrix. + Mat& adjustROI( int dtop, int dbottom, int dleft, int dright ); + //! extracts a rectangular sub-matrix + // (this is a generalized form of row, rowRange etc.) + Mat operator()( Range rowRange, Range colRange ) const; + Mat operator()( const Rect& roi ) const; + Mat operator()( const Range* ranges ) const; + + // //! converts header to CvMat; no data is copied + // operator CvMat() const; + // //! converts header to CvMatND; no data is copied + // operator CvMatND() const; + // //! converts header to IplImage; no data is copied + // operator IplImage() const; + + template operator std::vector<_Tp>() const; + template operator Vec<_Tp, n>() const; + template operator Matx<_Tp, m, n>() const; + + //! returns true iff the matrix data is continuous + // (i.e. when there are no gaps between successive rows). + // similar to CV_IS_MAT_CONT(cvmat->type) + bool isContinuous() const; + + //! returns true if the matrix is a submatrix of another matrix + bool isSubmatrix() const; + + //! returns element size in bytes, + // similar to CV_ELEM_SIZE(cvmat->type) + size_t elemSize() const; + //! returns the size of element channel in bytes. + size_t elemSize1() const; + //! returns element type, similar to CV_MAT_TYPE(cvmat->type) + int type() const; + //! returns element type, similar to CV_MAT_DEPTH(cvmat->type) + int depth() const; + //! returns element type, similar to CV_MAT_CN(cvmat->type) + int channels() const; + //! returns step/elemSize1() + size_t step1(int i=0) const; + //! returns true if matrix data is NULL + bool empty() const; + //! returns the total number of matrix elements + size_t total() const; + + //! returns N if the matrix is 1-channel (N x ptdim) or ptdim-channel (1 x N) or (N x 1); negative number otherwise + int checkVector(int elemChannels, int depth=-1, bool requireContinuous=true) const; + + //! returns pointer to i0-th submatrix along the dimension #0 + uchar* ptr(int i0=0); + const uchar* ptr(int i0=0) const; + + //! returns pointer to (i0,i1) submatrix along the dimensions #0 and #1 + uchar* ptr(int i0, int i1); + const uchar* ptr(int i0, int i1) const; + + //! returns pointer to (i0,i1,i3) submatrix along the dimensions #0, #1, #2 + uchar* ptr(int i0, int i1, int i2); + const uchar* ptr(int i0, int i1, int i2) const; + + //! returns pointer to the matrix element + uchar* ptr(const int* idx); + //! returns read-only pointer to the matrix element + const uchar* ptr(const int* idx) const; + + template uchar* ptr(const Vec& idx); + template const uchar* ptr(const Vec& idx) const; + + //! template version of the above method + template _Tp* ptr(int i0=0); + template const _Tp* ptr(int i0=0) const; + + template _Tp* ptr(int i0, int i1); + template const _Tp* ptr(int i0, int i1) const; + + template _Tp* ptr(int i0, int i1, int i2); + template const _Tp* ptr(int i0, int i1, int i2) const; + + template _Tp* ptr(const int* idx); + template const _Tp* ptr(const int* idx) const; + + template _Tp* ptr(const Vec& idx); + template const _Tp* ptr(const Vec& idx) const; + + //! the same as above, with the pointer dereferencing + template _Tp& at(int i0=0); + template const _Tp& at(int i0=0) const; + + template _Tp& at(int i0, int i1); + template const _Tp& at(int i0, int i1) const; + + template _Tp& at(int i0, int i1, int i2); + template const _Tp& at(int i0, int i1, int i2) const; + + template _Tp& at(const int* idx); + template const _Tp& at(const int* idx) const; + + template _Tp& at(const Vec& idx); + template const _Tp& at(const Vec& idx) const; + + //! special versions for 2D arrays (especially convenient for referencing image pixels) + template _Tp& at(Point pt); + template const _Tp& at(Point pt) const; + + //! template methods for iteration over matrix elements. + // the iterators take care of skipping gaps in the end of rows (if any) + template MatIterator_<_Tp> begin(); + template MatIterator_<_Tp> end(); + template MatConstIterator_<_Tp> begin() const; + template MatConstIterator_<_Tp> end() const; + + enum { MAGIC_VAL = 0x42FF0000, AUTO_STEP = 0, CONTINUOUS_FLAG = CV_MAT_CONT_FLAG, SUBMATRIX_FLAG = CV_SUBMAT_FLAG }; + enum { MAGIC_MASK = 0xFFFF0000, TYPE_MASK = 0x00000FFF, DEPTH_MASK = 7 }; + + /*! includes several bit-fields: + - the magic signature + - continuity flag + - depth + - number of channels + */ + int flags; + //! the matrix dimensionality, >= 2 + int dims; + //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions + int rows, cols; + //! pointer to the data + uchar* data; + + //! pointer to the reference counter; + // when matrix points to user-allocated data, the pointer is NULL + int* refcount; + + //! helper fields used in locateROI and adjustROI + uchar* datastart; + uchar* dataend; + uchar* datalimit; + + //! custom allocator + MatAllocator* allocator; + + struct CV_EXPORTS MSize { - dims = 0; - copySize(m); - } -} + MSize(int* _p); + Size operator()() const; + const int& operator[](int i) const; + int& operator[](int i); + operator const int*() const; + bool operator == (const MSize& sz) const; + bool operator != (const MSize& sz) const; -inline Mat::Mat(int _rows, int _cols, int _type, void* _data, size_t _step) - : flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_rows), cols(_cols), - data((uchar*)_data), refcount(0), datastart((uchar*)_data), dataend(0), - datalimit(0), allocator(0), size(&rows) -{ - size_t esz = CV_ELEM_SIZE(_type), minstep = cols*esz; - if( _step == AUTO_STEP ) + int* p; + }; + + struct CV_EXPORTS MStep { - _step = minstep; - flags |= CONTINUOUS_FLAG; - } - else - { - if( rows == 1 ) _step = minstep; - CV_DbgAssert( _step >= minstep ); - flags |= _step == minstep ? CONTINUOUS_FLAG : 0; - } - step[0] = _step; step[1] = esz; - datalimit = datastart + _step*rows; - dataend = datalimit - _step + minstep; -} + MStep(); + MStep(size_t s); + const size_t& operator[](int i) const; + size_t& operator[](int i); + operator size_t() const; + MStep& operator = (size_t s); -inline Mat::Mat(Size _sz, int _type, void* _data, size_t _step) - : flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_sz.height), cols(_sz.width), - data((uchar*)_data), refcount(0), datastart((uchar*)_data), dataend(0), - datalimit(0), allocator(0), size(&rows) -{ - size_t esz = CV_ELEM_SIZE(_type), minstep = cols*esz; - if( _step == AUTO_STEP ) - { - _step = minstep; - flags |= CONTINUOUS_FLAG; - } - else - { - if( rows == 1 ) _step = minstep; - CV_DbgAssert( _step >= minstep ); - flags |= _step == minstep ? CONTINUOUS_FLAG : 0; - } - step[0] = _step; step[1] = esz; - datalimit = datastart + _step*rows; - dataend = datalimit - _step + minstep; -} + size_t* p; + size_t buf[2]; + protected: + MStep& operator = (const MStep&); + }; + MSize size; + MStep step; -template inline Mat::Mat(const std::vector<_Tp>& vec, bool copyData) - : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - dims(2), rows((int)vec.size()), cols(1), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) -{ - if(vec.empty()) - return; - if( !copyData ) - { - step[0] = step[1] = sizeof(_Tp); - data = datastart = (uchar*)&vec[0]; - datalimit = dataend = datastart + rows*step[0]; - } - else - Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this); -} +protected: +}; -template inline Mat::Mat(const Vec<_Tp, n>& vec, bool copyData) - : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - dims(2), rows(n), cols(1), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) -{ - if( !copyData ) - { - step[0] = step[1] = sizeof(_Tp); - data = datastart = (uchar*)vec.val; - datalimit = dataend = datastart + rows*step[0]; - } - else - Mat(n, 1, DataType<_Tp>::type, (void*)vec.val).copyTo(*this); -} - - -template inline Mat::Mat(const Matx<_Tp,m,n>& M, bool copyData) - : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - dims(2), rows(m), cols(n), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) -{ - if( !copyData ) - { - step[0] = cols*sizeof(_Tp); - step[1] = sizeof(_Tp); - data = datastart = (uchar*)M.val; - datalimit = dataend = datastart + rows*step[0]; - } - else - Mat(m, n, DataType<_Tp>::type, (uchar*)M.val).copyTo(*this); -} - - -template inline Mat::Mat(const Point_<_Tp>& pt, bool copyData) - : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - dims(2), rows(2), cols(1), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) -{ - if( !copyData ) - { - step[0] = step[1] = sizeof(_Tp); - data = datastart = (uchar*)&pt.x; - datalimit = dataend = datastart + rows*step[0]; - } - else - { - create(2, 1, DataType<_Tp>::type); - ((_Tp*)data)[0] = pt.x; - ((_Tp*)data)[1] = pt.y; - } -} - - -template inline Mat::Mat(const Point3_<_Tp>& pt, bool copyData) - : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - dims(2), rows(3), cols(1), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) -{ - if( !copyData ) - { - step[0] = step[1] = sizeof(_Tp); - data = datastart = (uchar*)&pt.x; - datalimit = dataend = datastart + rows*step[0]; - } - else - { - create(3, 1, DataType<_Tp>::type); - ((_Tp*)data)[0] = pt.x; - ((_Tp*)data)[1] = pt.y; - ((_Tp*)data)[2] = pt.z; - } -} - - -template inline Mat::Mat(const MatCommaInitializer_<_Tp>& commaInitializer) - : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - dims(0), rows(0), cols(0), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) -{ - *this = *commaInitializer; -} - -inline Mat::~Mat() -{ - release(); - if( step.p != step.buf ) - fastFree(step.p); -} - -inline Mat& Mat::operator = (const Mat& m) -{ - if( this != &m ) - { - if( m.refcount ) - CV_XADD(m.refcount, 1); - release(); - flags = m.flags; - if( dims <= 2 && m.dims <= 2 ) - { - dims = m.dims; - rows = m.rows; - cols = m.cols; - step[0] = m.step[0]; - step[1] = m.step[1]; - } - else - copySize(m); - data = m.data; - datastart = m.datastart; - dataend = m.dataend; - datalimit = m.datalimit; - refcount = m.refcount; - allocator = m.allocator; - } - return *this; -} - -inline Mat Mat::row(int y) const { return Mat(*this, Range(y, y+1), Range::all()); } -inline Mat Mat::col(int x) const { return Mat(*this, Range::all(), Range(x, x+1)); } -inline Mat Mat::rowRange(int startrow, int endrow) const - { return Mat(*this, Range(startrow, endrow), Range::all()); } -inline Mat Mat::rowRange(const Range& r) const - { return Mat(*this, r, Range::all()); } -inline Mat Mat::colRange(int startcol, int endcol) const - { return Mat(*this, Range::all(), Range(startcol, endcol)); } -inline Mat Mat::colRange(const Range& r) const - { return Mat(*this, Range::all(), r); } - -inline Mat Mat::diag(const Mat& d) -{ - CV_Assert( d.cols == 1 || d.rows == 1 ); - int len = d.rows + d.cols - 1; - Mat m(len, len, d.type(), Scalar(0)), md = m.diag(); - if( d.cols == 1 ) - d.copyTo(md); - else - transpose(d, md); - return m; -} - -inline Mat Mat::clone() const -{ - Mat m; - copyTo(m); - return m; -} - -inline void Mat::assignTo( Mat& m, int _type ) const -{ - if( _type < 0 ) - m = *this; - else - convertTo(m, _type); -} - -inline void Mat::create(int _rows, int _cols, int _type) -{ - _type &= TYPE_MASK; - if( dims <= 2 && rows == _rows && cols == _cols && type() == _type && data ) - return; - int sz[] = {_rows, _cols}; - create(2, sz, _type); -} - -inline void Mat::create(Size _sz, int _type) -{ - create(_sz.height, _sz.width, _type); -} - -inline void Mat::addref() -{ if( refcount ) CV_XADD(refcount, 1); } - -inline void Mat::release() -{ - if( refcount && CV_XADD(refcount, -1) == 1 ) - deallocate(); - data = datastart = dataend = datalimit = 0; - size.p[0] = 0; - refcount = 0; -} - -inline Mat Mat::operator()( Range _rowRange, Range _colRange ) const -{ - return Mat(*this, _rowRange, _colRange); -} - -inline Mat Mat::operator()( const Rect& roi ) const -{ return Mat(*this, roi); } - -inline Mat Mat::operator()(const Range* ranges) const -{ - return Mat(*this, ranges); -} - -inline Mat::operator CvMat() const -{ - CV_DbgAssert(dims <= 2); - CvMat m = cvMat(rows, dims == 1 ? 1 : cols, type(), data); - m.step = (int)step[0]; - m.type = (m.type & ~CONTINUOUS_FLAG) | (flags & CONTINUOUS_FLAG); - return m; -} - -inline bool Mat::isContinuous() const { return (flags & CONTINUOUS_FLAG) != 0; } -inline bool Mat::isSubmatrix() const { return (flags & SUBMATRIX_FLAG) != 0; } -inline size_t Mat::elemSize() const { return dims > 0 ? step.p[dims-1] : 0; } -inline size_t Mat::elemSize1() const { return CV_ELEM_SIZE1(flags); } -inline int Mat::type() const { return CV_MAT_TYPE(flags); } -inline int Mat::depth() const { return CV_MAT_DEPTH(flags); } -inline int Mat::channels() const { return CV_MAT_CN(flags); } -inline size_t Mat::step1(int i) const { return step.p[i]/elemSize1(); } -inline bool Mat::empty() const { return data == 0 || total() == 0; } -inline size_t Mat::total() const -{ - if( dims <= 2 ) - return (size_t)rows*cols; - size_t p = 1; - for( int i = 0; i < dims; i++ ) - p *= size[i]; - return p; -} - -inline uchar* Mat::ptr(int y) -{ - CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) ); - return data + step.p[0]*y; -} - -inline const uchar* Mat::ptr(int y) const -{ - CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) ); - return data + step.p[0]*y; -} - -template inline _Tp* Mat::ptr(int y) -{ - CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) ); - return (_Tp*)(data + step.p[0]*y); -} - -template inline const _Tp* Mat::ptr(int y) const -{ - CV_DbgAssert( y == 0 || (data && dims >= 1 && data && (unsigned)y < (unsigned)size.p[0]) ); - return (const _Tp*)(data + step.p[0]*y); -} - - -inline uchar* Mat::ptr(int i0, int i1) -{ - CV_DbgAssert( dims >= 2 && data && - (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)i1 < (unsigned)size.p[1] ); - return data + i0*step.p[0] + i1*step.p[1]; -} - -inline const uchar* Mat::ptr(int i0, int i1) const -{ - CV_DbgAssert( dims >= 2 && data && - (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)i1 < (unsigned)size.p[1] ); - return data + i0*step.p[0] + i1*step.p[1]; -} - -template inline _Tp* Mat::ptr(int i0, int i1) -{ - CV_DbgAssert( dims >= 2 && data && - (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)i1 < (unsigned)size.p[1] ); - return (_Tp*)(data + i0*step.p[0] + i1*step.p[1]); -} - -template inline const _Tp* Mat::ptr(int i0, int i1) const -{ - CV_DbgAssert( dims >= 2 && data && - (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)i1 < (unsigned)size.p[1] ); - return (const _Tp*)(data + i0*step.p[0] + i1*step.p[1]); -} - -inline uchar* Mat::ptr(int i0, int i1, int i2) -{ - CV_DbgAssert( dims >= 3 && data && - (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)i1 < (unsigned)size.p[1] && - (unsigned)i2 < (unsigned)size.p[2] ); - return data + i0*step.p[0] + i1*step.p[1] + i2*step.p[2]; -} - -inline const uchar* Mat::ptr(int i0, int i1, int i2) const -{ - CV_DbgAssert( dims >= 3 && data && - (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)i1 < (unsigned)size.p[1] && - (unsigned)i2 < (unsigned)size.p[2] ); - return data + i0*step.p[0] + i1*step.p[1] + i2*step.p[2]; -} - -template inline _Tp* Mat::ptr(int i0, int i1, int i2) -{ - CV_DbgAssert( dims >= 3 && data && - (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)i1 < (unsigned)size.p[1] && - (unsigned)i2 < (unsigned)size.p[2] ); - return (_Tp*)(data + i0*step.p[0] + i1*step.p[1] + i2*step.p[2]); -} - -template inline const _Tp* Mat::ptr(int i0, int i1, int i2) const -{ - CV_DbgAssert( dims >= 3 && data && - (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)i1 < (unsigned)size.p[1] && - (unsigned)i2 < (unsigned)size.p[2] ); - return (const _Tp*)(data + i0*step.p[0] + i1*step.p[1] + i2*step.p[2]); -} - -inline uchar* Mat::ptr(const int* idx) -{ - int i, d = dims; - uchar* p = data; - CV_DbgAssert( d >= 1 && p ); - for( i = 0; i < d; i++ ) - { - CV_DbgAssert( (unsigned)idx[i] < (unsigned)size.p[i] ); - p += idx[i]*step.p[i]; - } - return p; -} - -inline const uchar* Mat::ptr(const int* idx) const -{ - int i, d = dims; - uchar* p = data; - CV_DbgAssert( d >= 1 && p ); - for( i = 0; i < d; i++ ) - { - CV_DbgAssert( (unsigned)idx[i] < (unsigned)size.p[i] ); - p += idx[i]*step.p[i]; - } - return p; -} - -template inline _Tp& Mat::at(int i0, int i1) -{ - CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && - CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); - return ((_Tp*)(data + step.p[0]*i0))[i1]; -} - -template inline const _Tp& Mat::at(int i0, int i1) const -{ - CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && - CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); - return ((const _Tp*)(data + step.p[0]*i0))[i1]; -} - -template inline _Tp& Mat::at(Point pt) -{ - CV_DbgAssert( dims <= 2 && data && (unsigned)pt.y < (unsigned)size.p[0] && - (unsigned)(pt.x*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && - CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); - return ((_Tp*)(data + step.p[0]*pt.y))[pt.x]; -} - -template inline const _Tp& Mat::at(Point pt) const -{ - CV_DbgAssert( dims <= 2 && data && (unsigned)pt.y < (unsigned)size.p[0] && - (unsigned)(pt.x*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && - CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); - return ((const _Tp*)(data + step.p[0]*pt.y))[pt.x]; -} - -template inline _Tp& Mat::at(int i0) -{ - CV_DbgAssert( dims <= 2 && data && - (unsigned)i0 < (unsigned)(size.p[0]*size.p[1]) && - elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); - if( isContinuous() || size.p[0] == 1 ) - return ((_Tp*)data)[i0]; - if( size.p[1] == 1 ) - return *(_Tp*)(data + step.p[0]*i0); - int i = i0/cols, j = i0 - i*cols; - return ((_Tp*)(data + step.p[0]*i))[j]; -} - -template inline const _Tp& Mat::at(int i0) const -{ - CV_DbgAssert( dims <= 2 && data && - (unsigned)i0 < (unsigned)(size.p[0]*size.p[1]) && - elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); - if( isContinuous() || size.p[0] == 1 ) - return ((const _Tp*)data)[i0]; - if( size.p[1] == 1 ) - return *(const _Tp*)(data + step.p[0]*i0); - int i = i0/cols, j = i0 - i*cols; - return ((const _Tp*)(data + step.p[0]*i))[j]; -} - -template inline _Tp& Mat::at(int i0, int i1, int i2) -{ - CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); - return *(_Tp*)ptr(i0, i1, i2); -} -template inline const _Tp& Mat::at(int i0, int i1, int i2) const -{ - CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); - return *(const _Tp*)ptr(i0, i1, i2); -} -template inline _Tp& Mat::at(const int* idx) -{ - CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); - return *(_Tp*)ptr(idx); -} -template inline const _Tp& Mat::at(const int* idx) const -{ - CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); - return *(const _Tp*)ptr(idx); -} -template _Tp& Mat::at(const Vec& idx) -{ - CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); - return *(_Tp*)ptr(idx.val); -} -template inline const _Tp& Mat::at(const Vec& idx) const -{ - CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); - return *(const _Tp*)ptr(idx.val); -} - - -template inline MatConstIterator_<_Tp> Mat::begin() const -{ - CV_DbgAssert( elemSize() == sizeof(_Tp) ); - return MatConstIterator_<_Tp>((const Mat_<_Tp>*)this); -} - -template inline MatConstIterator_<_Tp> Mat::end() const -{ - CV_DbgAssert( elemSize() == sizeof(_Tp) ); - MatConstIterator_<_Tp> it((const Mat_<_Tp>*)this); - it += total(); - return it; -} - -template inline MatIterator_<_Tp> Mat::begin() -{ - CV_DbgAssert( elemSize() == sizeof(_Tp) ); - return MatIterator_<_Tp>((Mat_<_Tp>*)this); -} - -template inline MatIterator_<_Tp> Mat::end() -{ - CV_DbgAssert( elemSize() == sizeof(_Tp) ); - MatIterator_<_Tp> it((Mat_<_Tp>*)this); - it += total(); - return it; -} - -template inline Mat::operator std::vector<_Tp>() const -{ - std::vector<_Tp> v; - copyTo(v); - return v; -} - -template inline Mat::operator Vec<_Tp, n>() const -{ - CV_Assert( data && dims <= 2 && (rows == 1 || cols == 1) && - rows + cols - 1 == n && channels() == 1 ); - - if( isContinuous() && type() == DataType<_Tp>::type ) - return Vec<_Tp, n>((_Tp*)data); - Vec<_Tp, n> v; Mat tmp(rows, cols, DataType<_Tp>::type, v.val); - convertTo(tmp, tmp.type()); - return v; -} - -template inline Mat::operator Matx<_Tp, m, n>() const -{ - CV_Assert( data && dims <= 2 && rows == m && cols == n && channels() == 1 ); - - if( isContinuous() && type() == DataType<_Tp>::type ) - return Matx<_Tp, m, n>((_Tp*)data); - Matx<_Tp, m, n> mtx; Mat tmp(rows, cols, DataType<_Tp>::type, mtx.val); - convertTo(tmp, tmp.type()); - return mtx; -} - - -template inline void Mat::push_back(const _Tp& elem) -{ - if( !data ) - { - *this = Mat(1, 1, DataType<_Tp>::type, (void*)&elem).clone(); - return; - } - CV_Assert(DataType<_Tp>::type == type() && cols == 1 - /* && dims == 2 (cols == 1 implies dims == 2) */); - uchar* tmp = dataend + step[0]; - if( !isSubmatrix() && isContinuous() && tmp <= datalimit ) - { - *(_Tp*)(data + (size.p[0]++)*step.p[0]) = elem; - dataend = tmp; - } - else - push_back_(&elem); -} - -template inline void Mat::push_back(const Mat_<_Tp>& m) -{ - push_back((const Mat&)m); -} - -inline Mat::MSize::MSize(int* _p) : p(_p) {} -inline Size Mat::MSize::operator()() const -{ - CV_DbgAssert(p[-1] <= 2); - return Size(p[1], p[0]); -} -inline const int& Mat::MSize::operator[](int i) const { return p[i]; } -inline int& Mat::MSize::operator[](int i) { return p[i]; } -inline Mat::MSize::operator const int*() const { return p; } - -inline bool Mat::MSize::operator == (const MSize& sz) const -{ - int d = p[-1], dsz = sz.p[-1]; - if( d != dsz ) - return false; - if( d == 2 ) - return p[0] == sz.p[0] && p[1] == sz.p[1]; - - for( int i = 0; i < d; i++ ) - if( p[i] != sz.p[i] ) - return false; - return true; -} - -inline bool Mat::MSize::operator != (const MSize& sz) const -{ - return !(*this == sz); -} - -inline Mat::MStep::MStep() { p = buf; p[0] = p[1] = 0; } -inline Mat::MStep::MStep(size_t s) { p = buf; p[0] = s; p[1] = 0; } -inline const size_t& Mat::MStep::operator[](int i) const { return p[i]; } -inline size_t& Mat::MStep::operator[](int i) { return p[i]; } -inline Mat::MStep::operator size_t() const -{ - CV_DbgAssert( p == buf ); - return buf[0]; -} -inline Mat::MStep& Mat::MStep::operator = (size_t s) -{ - CV_DbgAssert( p == buf ); - buf[0] = s; - return *this; -} - -static inline Mat cvarrToMatND(const CvArr* arr, bool copyData=false, int coiMode=0) -{ - return cvarrToMat(arr, copyData, true, coiMode); -} - -///////////////////////////////////////////// SVD ////////////////////////////////////////////////////// - -inline SVD::SVD() {} -inline SVD::SVD( InputArray m, int flags ) { operator ()(m, flags); } -inline void SVD::solveZ( InputArray m, OutputArray _dst ) -{ - Mat mtx = m.getMat(); - SVD svd(mtx, (mtx.rows >= mtx.cols ? 0 : SVD::FULL_UV)); - _dst.create(svd.vt.cols, 1, svd.vt.type()); - Mat dst = _dst.getMat(); - svd.vt.row(svd.vt.rows-1).reshape(1,svd.vt.cols).copyTo(dst); -} - -template inline void - SVD::compute( const Matx<_Tp, m, n>& a, Matx<_Tp, nm, 1>& w, Matx<_Tp, m, nm>& u, Matx<_Tp, n, nm>& vt ) -{ - assert( nm == MIN(m, n)); - Mat _a(a, false), _u(u, false), _w(w, false), _vt(vt, false); - SVD::compute(_a, _w, _u, _vt); - CV_Assert(_w.data == (uchar*)&w.val[0] && _u.data == (uchar*)&u.val[0] && _vt.data == (uchar*)&vt.val[0]); -} - -template inline void -SVD::compute( const Matx<_Tp, m, n>& a, Matx<_Tp, nm, 1>& w ) -{ - assert( nm == MIN(m, n)); - Mat _a(a, false), _w(w, false); - SVD::compute(_a, _w); - CV_Assert(_w.data == (uchar*)&w.val[0]); -} - -template inline void -SVD::backSubst( const Matx<_Tp, nm, 1>& w, const Matx<_Tp, m, nm>& u, - const Matx<_Tp, n, nm>& vt, const Matx<_Tp, m, nb>& rhs, - Matx<_Tp, n, nb>& dst ) -{ - assert( nm == MIN(m, n)); - Mat _u(u, false), _w(w, false), _vt(vt, false), _rhs(rhs, false), _dst(dst, false); - SVD::backSubst(_w, _u, _vt, _rhs, _dst); - CV_Assert(_dst.data == (uchar*)&dst.val[0]); -} - ///////////////////////////////// Mat_<_Tp> //////////////////////////////////// -template inline Mat_<_Tp>::Mat_() - : Mat() { flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; } +/*! + Template matrix class derived from Mat -template inline Mat_<_Tp>::Mat_(int _rows, int _cols) - : Mat(_rows, _cols, DataType<_Tp>::type) {} + The class Mat_ is a "thin" template wrapper on top of cv::Mat. It does not have any extra data fields, + nor it or cv::Mat have any virtual methods and thus references or pointers to these two classes + can be safely converted one to another. But do it with care, for example: -template inline Mat_<_Tp>::Mat_(int _rows, int _cols, const _Tp& value) - : Mat(_rows, _cols, DataType<_Tp>::type) { *this = value; } + \code + // create 100x100 8-bit matrix + Mat M(100,100,CV_8U); + // this will compile fine. no any data conversion will be done. + Mat_& M1 = (Mat_&)M; + // the program will likely crash at the statement below + M1(99,99) = 1.f; + \endcode -template inline Mat_<_Tp>::Mat_(Size _sz) - : Mat(_sz.height, _sz.width, DataType<_Tp>::type) {} + While cv::Mat is sufficient in most cases, cv::Mat_ can be more convenient if you use a lot of element + access operations and if you know matrix type at compile time. + Note that cv::Mat::at<_Tp>(int y, int x) and cv::Mat_<_Tp>::operator ()(int y, int x) do absolutely the + same thing and run at the same speed, but the latter is certainly shorter: -template inline Mat_<_Tp>::Mat_(Size _sz, const _Tp& value) - : Mat(_sz.height, _sz.width, DataType<_Tp>::type) { *this = value; } + \code + Mat_ M(20,20); + for(int i = 0; i < M.rows; i++) + for(int j = 0; j < M.cols; j++) + M(i,j) = 1./(i+j+1); + Mat E, V; + eigen(M,E,V); + cout << E.at(0,0)/E.at(M.rows-1,0); + \endcode -template inline Mat_<_Tp>::Mat_(int _dims, const int* _sz) - : Mat(_dims, _sz, DataType<_Tp>::type) {} + It is easy to use Mat_ for multi-channel images/matrices - just pass cv::Vec as cv::Mat_ template parameter: -template inline Mat_<_Tp>::Mat_(int _dims, const int* _sz, const _Tp& _s) - : Mat(_dims, _sz, DataType<_Tp>::type, Scalar(_s)) {} - -template inline Mat_<_Tp>::Mat_(const Mat_<_Tp>& m, const Range* ranges) - : Mat(m, ranges) {} - -template inline Mat_<_Tp>::Mat_(const Mat& m) - : Mat() { flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; *this = m; } - -template inline Mat_<_Tp>::Mat_(const Mat_& m) - : Mat(m) {} - -template inline Mat_<_Tp>::Mat_(int _rows, int _cols, _Tp* _data, size_t steps) - : Mat(_rows, _cols, DataType<_Tp>::type, _data, steps) {} - -template inline Mat_<_Tp>::Mat_(const Mat_& m, const Range& _rowRange, const Range& _colRange) - : Mat(m, _rowRange, _colRange) {} - -template inline Mat_<_Tp>::Mat_(const Mat_& m, const Rect& roi) - : Mat(m, roi) {} - -template template inline - Mat_<_Tp>::Mat_(const Vec::channel_type, n>& vec, bool copyData) - : Mat(n/DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&vec) + \code + // allocate 320x240 color image and fill it with green (in RGB space) + Mat_ img(240, 320, Vec3b(0,255,0)); + // now draw a diagonal white line + for(int i = 0; i < 100; i++) + img(i,i)=Vec3b(255,255,255); + // and now modify the 2nd (red) channel of each pixel + for(int i = 0; i < img.rows; i++) + for(int j = 0; j < img.cols; j++) + img(i,j)[2] ^= (uchar)(i ^ j); // img(y,x)[c] accesses c-th channel of the pixel (x,y) + \endcode +*/ +template class Mat_ : public Mat { - CV_Assert(n%DataType<_Tp>::channels == 0); - if( copyData ) - *this = clone(); -} +public: + typedef _Tp value_type; + typedef typename DataType<_Tp>::channel_type channel_type; + typedef MatIterator_<_Tp> iterator; + typedef MatConstIterator_<_Tp> const_iterator; -template template inline - Mat_<_Tp>::Mat_(const Matx::channel_type,m,n>& M, bool copyData) - : Mat(m, n/DataType<_Tp>::channels, DataType<_Tp>::type, (void*)&M) + //! default constructor + Mat_(); + //! equivalent to Mat(_rows, _cols, DataType<_Tp>::type) + Mat_(int _rows, int _cols); + //! constructor that sets each matrix element to specified value + Mat_(int _rows, int _cols, const _Tp& value); + //! equivalent to Mat(_size, DataType<_Tp>::type) + explicit Mat_(Size _size); + //! constructor that sets each matrix element to specified value + Mat_(Size _size, const _Tp& value); + //! n-dim array constructor + Mat_(int _ndims, const int* _sizes); + //! n-dim array constructor that sets each matrix element to specified value + Mat_(int _ndims, const int* _sizes, const _Tp& value); + //! copy/conversion contructor. If m is of different type, it's converted + Mat_(const Mat& m); + //! copy constructor + Mat_(const Mat_& m); + //! constructs a matrix on top of user-allocated data. step is in bytes(!!!), regardless of the type + Mat_(int _rows, int _cols, _Tp* _data, size_t _step=AUTO_STEP); + //! constructs n-dim matrix on top of user-allocated data. steps are in bytes(!!!), regardless of the type + Mat_(int _ndims, const int* _sizes, _Tp* _data, const size_t* _steps=0); + //! selects a submatrix + Mat_(const Mat_& m, const Range& rowRange, const Range& colRange=Range::all()); + //! selects a submatrix + Mat_(const Mat_& m, const Rect& roi); + //! selects a submatrix, n-dim version + Mat_(const Mat_& m, const Range* ranges); + //! from a matrix expression + explicit Mat_(const MatExpr& e); + //! makes a matrix out of Vec, std::vector, Point_ or Point3_. The matrix will have a single column + explicit Mat_(const std::vector<_Tp>& vec, bool copyData=false); + template explicit Mat_(const Vec::channel_type, n>& vec, bool copyData=true); + template explicit Mat_(const Matx::channel_type, m, n>& mtx, bool copyData=true); + explicit Mat_(const Point_::channel_type>& pt, bool copyData=true); + explicit Mat_(const Point3_::channel_type>& pt, bool copyData=true); + explicit Mat_(const MatCommaInitializer_<_Tp>& commaInitializer); + + Mat_& operator = (const Mat& m); + Mat_& operator = (const Mat_& m); + //! set all the elements to s. + Mat_& operator = (const _Tp& s); + //! assign a matrix expression + Mat_& operator = (const MatExpr& e); + + //! iterators; they are smart enough to skip gaps in the end of rows + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + + //! equivalent to Mat::create(_rows, _cols, DataType<_Tp>::type) + void create(int _rows, int _cols); + //! equivalent to Mat::create(_size, DataType<_Tp>::type) + void create(Size _size); + //! equivalent to Mat::create(_ndims, _sizes, DatType<_Tp>::type) + void create(int _ndims, const int* _sizes); + //! cross-product + Mat_ cross(const Mat_& m) const; + //! data type conversion + template operator Mat_() const; + //! overridden forms of Mat::row() etc. + Mat_ row(int y) const; + Mat_ col(int x) const; + Mat_ diag(int d=0) const; + Mat_ clone() const; + + //! overridden forms of Mat::elemSize() etc. + size_t elemSize() const; + size_t elemSize1() const; + int type() const; + int depth() const; + int channels() const; + size_t step1(int i=0) const; + //! returns step()/sizeof(_Tp) + size_t stepT(int i=0) const; + + //! overridden forms of Mat::zeros() etc. Data type is omitted, of course + static MatExpr zeros(int rows, int cols); + static MatExpr zeros(Size size); + static MatExpr zeros(int _ndims, const int* _sizes); + static MatExpr ones(int rows, int cols); + static MatExpr ones(Size size); + static MatExpr ones(int _ndims, const int* _sizes); + static MatExpr eye(int rows, int cols); + static MatExpr eye(Size size); + + //! some more overriden methods + Mat_& adjustROI( int dtop, int dbottom, int dleft, int dright ); + Mat_ operator()( const Range& rowRange, const Range& colRange ) const; + Mat_ operator()( const Rect& roi ) const; + Mat_ operator()( const Range* ranges ) const; + + //! more convenient forms of row and element access operators + _Tp* operator [](int y); + const _Tp* operator [](int y) const; + + //! returns reference to the specified element + _Tp& operator ()(const int* idx); + //! returns read-only reference to the specified element + const _Tp& operator ()(const int* idx) const; + + //! returns reference to the specified element + template _Tp& operator ()(const Vec& idx); + //! returns read-only reference to the specified element + template const _Tp& operator ()(const Vec& idx) const; + + //! returns reference to the specified element (1D case) + _Tp& operator ()(int idx0); + //! returns read-only reference to the specified element (1D case) + const _Tp& operator ()(int idx0) const; + //! returns reference to the specified element (2D case) + _Tp& operator ()(int idx0, int idx1); + //! returns read-only reference to the specified element (2D case) + const _Tp& operator ()(int idx0, int idx1) const; + //! returns reference to the specified element (3D case) + _Tp& operator ()(int idx0, int idx1, int idx2); + //! returns read-only reference to the specified element (3D case) + const _Tp& operator ()(int idx0, int idx1, int idx2) const; + + _Tp& operator ()(Point pt); + const _Tp& operator ()(Point pt) const; + + //! conversion to vector. + operator std::vector<_Tp>() const; + //! conversion to Vec + template operator Vec::channel_type, n>() const; + //! conversion to Matx + template operator Matx::channel_type, m, n>() const; +}; + +typedef Mat_ Mat1b; +typedef Mat_ Mat2b; +typedef Mat_ Mat3b; +typedef Mat_ Mat4b; + +typedef Mat_ Mat1s; +typedef Mat_ Mat2s; +typedef Mat_ Mat3s; +typedef Mat_ Mat4s; + +typedef Mat_ Mat1w; +typedef Mat_ Mat2w; +typedef Mat_ Mat3w; +typedef Mat_ Mat4w; + +typedef Mat_ Mat1i; +typedef Mat_ Mat2i; +typedef Mat_ Mat3i; +typedef Mat_ Mat4i; + +typedef Mat_ Mat1f; +typedef Mat_ Mat2f; +typedef Mat_ Mat3f; +typedef Mat_ Mat4f; + +typedef Mat_ Mat1d; +typedef Mat_ Mat2d; +typedef Mat_ Mat3d; +typedef Mat_ Mat4d; + + + +/////////////////////////// multi-dimensional sparse matrix ////////////////////////// + +/*! + Sparse matrix class. + + The class represents multi-dimensional sparse numerical arrays. Such a sparse array can store elements + of any type that cv::Mat is able to store. "Sparse" means that only non-zero elements + are stored (though, as a result of some operations on a sparse matrix, some of its stored elements + can actually become 0. It's user responsibility to detect such elements and delete them using cv::SparseMat::erase(). + The non-zero elements are stored in a hash table that grows when it's filled enough, + so that the search time remains O(1) in average. Elements can be accessed using the following methods: + +
      +
    1. Query operations: cv::SparseMat::ptr() and the higher-level cv::SparseMat::ref(), + cv::SparseMat::value() and cv::SparseMat::find, for example: + \code + const int dims = 5; + int size[] = {10, 10, 10, 10, 10}; + SparseMat sparse_mat(dims, size, CV_32F); + for(int i = 0; i < 1000; i++) + { + int idx[dims]; + for(int k = 0; k < dims; k++) + idx[k] = rand()%sparse_mat.size(k); + sparse_mat.ref(idx) += 1.f; + } + \endcode + +
    2. Sparse matrix iterators. Like cv::Mat iterators and unlike cv::Mat iterators, the sparse matrix iterators are STL-style, + that is, the iteration is done as following: + \code + // prints elements of a sparse floating-point matrix and the sum of elements. + SparseMatConstIterator_ + it = sparse_mat.begin(), + it_end = sparse_mat.end(); + double s = 0; + int dims = sparse_mat.dims(); + for(; it != it_end; ++it) + { + // print element indices and the element value + const Node* n = it.node(); + printf("(") + for(int i = 0; i < dims; i++) + printf("%3d%c", n->idx[i], i < dims-1 ? ',' : ')'); + printf(": %f\n", *it); + s += *it; + } + printf("Element sum is %g\n", s); + \endcode + If you run this loop, you will notice that elements are enumerated + in no any logical order (lexicographical etc.), + they come in the same order as they stored in the hash table, i.e. semi-randomly. + + You may collect pointers to the nodes and sort them to get the proper ordering. + Note, however, that pointers to the nodes may become invalid when you add more + elements to the matrix; this is because of possible buffer reallocation. + +
    3. A combination of the above 2 methods when you need to process 2 or more sparse + matrices simultaneously, e.g. this is how you can compute unnormalized + cross-correlation of the 2 floating-point sparse matrices: + \code + double crossCorr(const SparseMat& a, const SparseMat& b) + { + const SparseMat *_a = &a, *_b = &b; + // if b contains less elements than a, + // it's faster to iterate through b + if(_a->nzcount() > _b->nzcount()) + std::swap(_a, _b); + SparseMatConstIterator_ it = _a->begin(), + it_end = _a->end(); + double ccorr = 0; + for(; it != it_end; ++it) + { + // take the next element from the first matrix + float avalue = *it; + const Node* anode = it.node(); + // and try to find element with the same index in the second matrix. + // since the hash value depends only on the element index, + // we reuse hashvalue stored in the node + float bvalue = _b->value(anode->idx,&anode->hashval); + ccorr += avalue*bvalue; + } + return ccorr; + } + \endcode +
    +*/ +class CV_EXPORTS SparseMat { - CV_Assert(n % DataType<_Tp>::channels == 0); - if( copyData ) - *this = clone(); -} +public: + typedef SparseMatIterator iterator; + typedef SparseMatConstIterator const_iterator; -template inline Mat_<_Tp>::Mat_(const Point_::channel_type>& pt, bool copyData) - : Mat(2/DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&pt) -{ - CV_Assert(2 % DataType<_Tp>::channels == 0); - if( copyData ) - *this = clone(); -} + enum { MAGIC_VAL=0x42FD0000, MAX_DIM=32, HASH_SCALE=0x5bd1e995, HASH_BIT=0x80000000 }; -template inline Mat_<_Tp>::Mat_(const Point3_::channel_type>& pt, bool copyData) - : Mat(3/DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&pt) -{ - CV_Assert(3 % DataType<_Tp>::channels == 0); - if( copyData ) - *this = clone(); -} - -template inline Mat_<_Tp>::Mat_(const MatCommaInitializer_<_Tp>& commaInitializer) - : Mat(commaInitializer) {} - -template inline Mat_<_Tp>::Mat_(const std::vector<_Tp>& vec, bool copyData) - : Mat(vec, copyData) {} - -template inline Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat& m) -{ - if( DataType<_Tp>::type == m.type() ) + //! the sparse matrix header + struct CV_EXPORTS Hdr { - Mat::operator = (m); - return *this; - } - if( DataType<_Tp>::depth == m.depth() ) + Hdr(int _dims, const int* _sizes, int _type); + void clear(); + int refcount; + int dims; + int valueOffset; + size_t nodeSize; + size_t nodeCount; + size_t freeList; + std::vector pool; + std::vector hashtab; + int size[MAX_DIM]; + }; + + //! sparse matrix node - element of a hash table + struct CV_EXPORTS Node { - return (*this = m.reshape(DataType<_Tp>::channels, m.dims, 0)); - } - CV_DbgAssert(DataType<_Tp>::channels == m.channels()); - m.convertTo(*this, type()); - return *this; -} + //! hash value + size_t hashval; + //! index of the next node in the same hash table entry + size_t next; + //! index of the matrix element + int idx[MAX_DIM]; + }; -template inline Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat_& m) + //! default constructor + SparseMat(); + //! creates matrix of the specified size and type + SparseMat(int dims, const int* _sizes, int _type); + //! copy constructor + SparseMat(const SparseMat& m); + //! converts dense 2d matrix to the sparse form + /*! + \param m the input matrix + */ + explicit SparseMat(const Mat& m); + //! converts old-style sparse matrix to the new-style. All the data is copied + //SparseMat(const CvSparseMat* m); + //! the destructor + ~SparseMat(); + + //! assignment operator. This is O(1) operation, i.e. no data is copied + SparseMat& operator = (const SparseMat& m); + //! equivalent to the corresponding constructor + SparseMat& operator = (const Mat& m); + + //! creates full copy of the matrix + SparseMat clone() const; + + //! copies all the data to the destination matrix. All the previous content of m is erased + void copyTo( SparseMat& m ) const; + //! converts sparse matrix to dense matrix. + void copyTo( Mat& m ) const; + //! multiplies all the matrix elements by the specified scale factor alpha and converts the results to the specified data type + void convertTo( SparseMat& m, int rtype, double alpha=1 ) const; + //! converts sparse matrix to dense n-dim matrix with optional type conversion and scaling. + /*! + \param rtype The output matrix data type. When it is =-1, the output array will have the same data type as (*this) + \param alpha The scale factor + \param beta The optional delta added to the scaled values before the conversion + */ + void convertTo( Mat& m, int rtype, double alpha=1, double beta=0 ) const; + + // not used now + void assignTo( SparseMat& m, int type=-1 ) const; + + //! reallocates sparse matrix. + /*! + If the matrix already had the proper size and type, + it is simply cleared with clear(), otherwise, + the old matrix is released (using release()) and the new one is allocated. + */ + void create(int dims, const int* _sizes, int _type); + //! sets all the sparse matrix elements to 0, which means clearing the hash table. + void clear(); + //! manually increments the reference counter to the header. + void addref(); + // decrements the header reference counter. When the counter reaches 0, the header and all the underlying data are deallocated. + void release(); + + //! converts sparse matrix to the old-style representation; all the elements are copied. + //operator CvSparseMat*() const; + //! returns the size of each element in bytes (not including the overhead - the space occupied by SparseMat::Node elements) + size_t elemSize() const; + //! returns elemSize()/channels() + size_t elemSize1() const; + + //! returns type of sparse matrix elements + int type() const; + //! returns the depth of sparse matrix elements + int depth() const; + //! returns the number of channels + int channels() const; + + //! returns the array of sizes, or NULL if the matrix is not allocated + const int* size() const; + //! returns the size of i-th matrix dimension (or 0) + int size(int i) const; + //! returns the matrix dimensionality + int dims() const; + //! returns the number of non-zero elements (=the number of hash table nodes) + size_t nzcount() const; + + //! computes the element hash value (1D case) + size_t hash(int i0) const; + //! computes the element hash value (2D case) + size_t hash(int i0, int i1) const; + //! computes the element hash value (3D case) + size_t hash(int i0, int i1, int i2) const; + //! computes the element hash value (nD case) + size_t hash(const int* idx) const; + + //@{ + /*! + specialized variants for 1D, 2D, 3D cases and the generic_type one for n-D case. + + return pointer to the matrix element. +
      +
    • if the element is there (it's non-zero), the pointer to it is returned +
    • if it's not there and createMissing=false, NULL pointer is returned +
    • if it's not there and createMissing=true, then the new element + is created and initialized with 0. Pointer to it is returned +
    • if the optional hashval pointer is not NULL, the element hash value is + not computed, but *hashval is taken instead. +
    + */ + //! returns pointer to the specified element (1D case) + uchar* ptr(int i0, bool createMissing, size_t* hashval=0); + //! returns pointer to the specified element (2D case) + uchar* ptr(int i0, int i1, bool createMissing, size_t* hashval=0); + //! returns pointer to the specified element (3D case) + uchar* ptr(int i0, int i1, int i2, bool createMissing, size_t* hashval=0); + //! returns pointer to the specified element (nD case) + uchar* ptr(const int* idx, bool createMissing, size_t* hashval=0); + //@} + + //@{ + /*! + return read-write reference to the specified sparse matrix element. + + ref<_Tp>(i0,...[,hashval]) is equivalent to *(_Tp*)ptr(i0,...,true[,hashval]). + The methods always return a valid reference. + If the element did not exist, it is created and initialiazed with 0. + */ + //! returns reference to the specified element (1D case) + template _Tp& ref(int i0, size_t* hashval=0); + //! returns reference to the specified element (2D case) + template _Tp& ref(int i0, int i1, size_t* hashval=0); + //! returns reference to the specified element (3D case) + template _Tp& ref(int i0, int i1, int i2, size_t* hashval=0); + //! returns reference to the specified element (nD case) + template _Tp& ref(const int* idx, size_t* hashval=0); + //@} + + //@{ + /*! + return value of the specified sparse matrix element. + + value<_Tp>(i0,...[,hashval]) is equivalent + + \code + { const _Tp* p = find<_Tp>(i0,...[,hashval]); return p ? *p : _Tp(); } + \endcode + + That is, if the element did not exist, the methods return 0. + */ + //! returns value of the specified element (1D case) + template _Tp value(int i0, size_t* hashval=0) const; + //! returns value of the specified element (2D case) + template _Tp value(int i0, int i1, size_t* hashval=0) const; + //! returns value of the specified element (3D case) + template _Tp value(int i0, int i1, int i2, size_t* hashval=0) const; + //! returns value of the specified element (nD case) + template _Tp value(const int* idx, size_t* hashval=0) const; + //@} + + //@{ + /*! + Return pointer to the specified sparse matrix element if it exists + + find<_Tp>(i0,...[,hashval]) is equivalent to (_const Tp*)ptr(i0,...false[,hashval]). + + If the specified element does not exist, the methods return NULL. + */ + //! returns pointer to the specified element (1D case) + template const _Tp* find(int i0, size_t* hashval=0) const; + //! returns pointer to the specified element (2D case) + template const _Tp* find(int i0, int i1, size_t* hashval=0) const; + //! returns pointer to the specified element (3D case) + template const _Tp* find(int i0, int i1, int i2, size_t* hashval=0) const; + //! returns pointer to the specified element (nD case) + template const _Tp* find(const int* idx, size_t* hashval=0) const; + + //! erases the specified element (2D case) + void erase(int i0, int i1, size_t* hashval=0); + //! erases the specified element (3D case) + void erase(int i0, int i1, int i2, size_t* hashval=0); + //! erases the specified element (nD case) + void erase(const int* idx, size_t* hashval=0); + + //@{ + /*! + return the sparse matrix iterator pointing to the first sparse matrix element + */ + //! returns the sparse matrix iterator at the matrix beginning + SparseMatIterator begin(); + //! returns the sparse matrix iterator at the matrix beginning + template SparseMatIterator_<_Tp> begin(); + //! returns the read-only sparse matrix iterator at the matrix beginning + SparseMatConstIterator begin() const; + //! returns the read-only sparse matrix iterator at the matrix beginning + template SparseMatConstIterator_<_Tp> begin() const; + //@} + /*! + return the sparse matrix iterator pointing to the element following the last sparse matrix element + */ + //! returns the sparse matrix iterator at the matrix end + SparseMatIterator end(); + //! returns the read-only sparse matrix iterator at the matrix end + SparseMatConstIterator end() const; + //! returns the typed sparse matrix iterator at the matrix end + template SparseMatIterator_<_Tp> end(); + //! returns the typed read-only sparse matrix iterator at the matrix end + template SparseMatConstIterator_<_Tp> end() const; + + //! returns the value stored in the sparse martix node + template _Tp& value(Node* n); + //! returns the value stored in the sparse martix node + template const _Tp& value(const Node* n) const; + + ////////////// some internal-use methods /////////////// + Node* node(size_t nidx); + const Node* node(size_t nidx) const; + + uchar* newNode(const int* idx, size_t hashval); + void removeNode(size_t hidx, size_t nidx, size_t previdx); + void resizeHashTab(size_t newsize); + + int flags; + Hdr* hdr; +}; + + + +///////////////////////////////// SparseMat_<_Tp> //////////////////////////////////// + +/*! + The Template Sparse Matrix class derived from cv::SparseMat + + The class provides slightly more convenient operations for accessing elements. + + \code + SparseMat m; + ... + SparseMat_ m_ = (SparseMat_&)m; + m_.ref(1)++; // equivalent to m.ref(1)++; + m_.ref(2) += m_(3); // equivalent to m.ref(2) += m.value(3); + \endcode +*/ +template class SparseMat_ : public SparseMat { - Mat::operator=(m); - return *this; -} +public: + typedef SparseMatIterator_<_Tp> iterator; + typedef SparseMatConstIterator_<_Tp> const_iterator; -template inline Mat_<_Tp>& Mat_<_Tp>::operator = (const _Tp& s) + //! the default constructor + SparseMat_(); + //! the full constructor equivelent to SparseMat(dims, _sizes, DataType<_Tp>::type) + SparseMat_(int dims, const int* _sizes); + //! the copy constructor. If DataType<_Tp>.type != m.type(), the m elements are converted + SparseMat_(const SparseMat& m); + //! the copy constructor. This is O(1) operation - no data is copied + SparseMat_(const SparseMat_& m); + //! converts dense matrix to the sparse form + SparseMat_(const Mat& m); + //! converts the old-style sparse matrix to the C++ class. All the elements are copied + //SparseMat_(const CvSparseMat* m); + //! the assignment operator. If DataType<_Tp>.type != m.type(), the m elements are converted + SparseMat_& operator = (const SparseMat& m); + //! the assignment operator. This is O(1) operation - no data is copied + SparseMat_& operator = (const SparseMat_& m); + //! converts dense matrix to the sparse form + SparseMat_& operator = (const Mat& m); + + //! makes full copy of the matrix. All the elements are duplicated + SparseMat_ clone() const; + //! equivalent to cv::SparseMat::create(dims, _sizes, DataType<_Tp>::type) + void create(int dims, const int* _sizes); + //! converts sparse matrix to the old-style CvSparseMat. All the elements are copied + //operator CvSparseMat*() const; + + //! returns type of the matrix elements + int type() const; + //! returns depth of the matrix elements + int depth() const; + //! returns the number of channels in each matrix element + int channels() const; + + //! equivalent to SparseMat::ref<_Tp>(i0, hashval) + _Tp& ref(int i0, size_t* hashval=0); + //! equivalent to SparseMat::ref<_Tp>(i0, i1, hashval) + _Tp& ref(int i0, int i1, size_t* hashval=0); + //! equivalent to SparseMat::ref<_Tp>(i0, i1, i2, hashval) + _Tp& ref(int i0, int i1, int i2, size_t* hashval=0); + //! equivalent to SparseMat::ref<_Tp>(idx, hashval) + _Tp& ref(const int* idx, size_t* hashval=0); + + //! equivalent to SparseMat::value<_Tp>(i0, hashval) + _Tp operator()(int i0, size_t* hashval=0) const; + //! equivalent to SparseMat::value<_Tp>(i0, i1, hashval) + _Tp operator()(int i0, int i1, size_t* hashval=0) const; + //! equivalent to SparseMat::value<_Tp>(i0, i1, i2, hashval) + _Tp operator()(int i0, int i1, int i2, size_t* hashval=0) const; + //! equivalent to SparseMat::value<_Tp>(idx, hashval) + _Tp operator()(const int* idx, size_t* hashval=0) const; + + //! returns sparse matrix iterator pointing to the first sparse matrix element + SparseMatIterator_<_Tp> begin(); + //! returns read-only sparse matrix iterator pointing to the first sparse matrix element + SparseMatConstIterator_<_Tp> begin() const; + //! returns sparse matrix iterator pointing to the element following the last sparse matrix element + SparseMatIterator_<_Tp> end(); + //! returns read-only sparse matrix iterator pointing to the element following the last sparse matrix element + SparseMatConstIterator_<_Tp> end() const; +}; + + + +////////////////////////////////// MatConstIterator ////////////////////////////////// + +class CV_EXPORTS MatConstIterator { - typedef typename DataType<_Tp>::vec_type VT; - Mat::operator=(Scalar((const VT&)s)); - return *this; -} +public: + typedef uchar* value_type; + typedef ptrdiff_t difference_type; + typedef const uchar** pointer; + typedef uchar* reference; -template inline void Mat_<_Tp>::create(int _rows, int _cols) +#ifndef OPENCV_NOSTL + typedef std::random_access_iterator_tag iterator_category; +#endif + + //! default constructor + MatConstIterator(); + //! constructor that sets the iterator to the beginning of the matrix + MatConstIterator(const Mat* _m); + //! constructor that sets the iterator to the specified element of the matrix + MatConstIterator(const Mat* _m, int _row, int _col=0); + //! constructor that sets the iterator to the specified element of the matrix + MatConstIterator(const Mat* _m, Point _pt); + //! constructor that sets the iterator to the specified element of the matrix + MatConstIterator(const Mat* _m, const int* _idx); + //! copy constructor + MatConstIterator(const MatConstIterator& it); + + //! copy operator + MatConstIterator& operator = (const MatConstIterator& it); + //! returns the current matrix element + uchar* operator *() const; + //! returns the i-th matrix element, relative to the current + uchar* operator [](ptrdiff_t i) const; + + //! shifts the iterator forward by the specified number of elements + MatConstIterator& operator += (ptrdiff_t ofs); + //! shifts the iterator backward by the specified number of elements + MatConstIterator& operator -= (ptrdiff_t ofs); + //! decrements the iterator + MatConstIterator& operator --(); + //! decrements the iterator + MatConstIterator operator --(int); + //! increments the iterator + MatConstIterator& operator ++(); + //! increments the iterator + MatConstIterator operator ++(int); + //! returns the current iterator position + Point pos() const; + //! returns the current iterator position + void pos(int* _idx) const; + + ptrdiff_t lpos() const; + void seek(ptrdiff_t ofs, bool relative = false); + void seek(const int* _idx, bool relative = false); + + const Mat* m; + size_t elemSize; + uchar* ptr; + uchar* sliceStart; + uchar* sliceEnd; +}; + + + +////////////////////////////////// MatConstIterator_ ///////////////////////////////// + +/*! + Matrix read-only iterator + */ +template +class MatConstIterator_ : public MatConstIterator { - Mat::create(_rows, _cols, DataType<_Tp>::type); -} +public: + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; -template inline void Mat_<_Tp>::create(Size _sz) +#ifndef OPENCV_NOSTL + typedef std::random_access_iterator_tag iterator_category; +#endif + + //! default constructor + MatConstIterator_(); + //! constructor that sets the iterator to the beginning of the matrix + MatConstIterator_(const Mat_<_Tp>* _m); + //! constructor that sets the iterator to the specified element of the matrix + MatConstIterator_(const Mat_<_Tp>* _m, int _row, int _col=0); + //! constructor that sets the iterator to the specified element of the matrix + MatConstIterator_(const Mat_<_Tp>* _m, Point _pt); + //! constructor that sets the iterator to the specified element of the matrix + MatConstIterator_(const Mat_<_Tp>* _m, const int* _idx); + //! copy constructor + MatConstIterator_(const MatConstIterator_& it); + + //! copy operator + MatConstIterator_& operator = (const MatConstIterator_& it); + //! returns the current matrix element + _Tp operator *() const; + //! returns the i-th matrix element, relative to the current + _Tp operator [](ptrdiff_t i) const; + + //! shifts the iterator forward by the specified number of elements + MatConstIterator_& operator += (ptrdiff_t ofs); + //! shifts the iterator backward by the specified number of elements + MatConstIterator_& operator -= (ptrdiff_t ofs); + //! decrements the iterator + MatConstIterator_& operator --(); + //! decrements the iterator + MatConstIterator_ operator --(int); + //! increments the iterator + MatConstIterator_& operator ++(); + //! increments the iterator + MatConstIterator_ operator ++(int); + //! returns the current iterator position + Point pos() const; +}; + + + +//////////////////////////////////// MatIterator_ //////////////////////////////////// + +/*! + Matrix read-write iterator +*/ +template +class MatIterator_ : public MatConstIterator_<_Tp> { - Mat::create(_sz, DataType<_Tp>::type); -} +public: + typedef _Tp* pointer; + typedef _Tp& reference; -template inline void Mat_<_Tp>::create(int _dims, const int* _sz) +#ifndef OPENCV_NOSTL + typedef std::random_access_iterator_tag iterator_category; +#endif + + //! the default constructor + MatIterator_(); + //! constructor that sets the iterator to the beginning of the matrix + MatIterator_(Mat_<_Tp>* _m); + //! constructor that sets the iterator to the specified element of the matrix + MatIterator_(Mat_<_Tp>* _m, int _row, int _col=0); + //! constructor that sets the iterator to the specified element of the matrix + MatIterator_(const Mat_<_Tp>* _m, Point _pt); + //! constructor that sets the iterator to the specified element of the matrix + MatIterator_(const Mat_<_Tp>* _m, const int* _idx); + //! copy constructor + MatIterator_(const MatIterator_& it); + //! copy operator + MatIterator_& operator = (const MatIterator_<_Tp>& it ); + + //! returns the current matrix element + _Tp& operator *() const; + //! returns the i-th matrix element, relative to the current + _Tp& operator [](ptrdiff_t i) const; + + //! shifts the iterator forward by the specified number of elements + MatIterator_& operator += (ptrdiff_t ofs); + //! shifts the iterator backward by the specified number of elements + MatIterator_& operator -= (ptrdiff_t ofs); + //! decrements the iterator + MatIterator_& operator --(); + //! decrements the iterator + MatIterator_ operator --(int); + //! increments the iterator + MatIterator_& operator ++(); + //! increments the iterator + MatIterator_ operator ++(int); +}; + + + +/////////////////////////////// SparseMatConstIterator /////////////////////////////// + +/*! + Read-Only Sparse Matrix Iterator. + Here is how to use the iterator to compute the sum of floating-point sparse matrix elements: + + \code + SparseMatConstIterator it = m.begin(), it_end = m.end(); + double s = 0; + CV_Assert( m.type() == CV_32F ); + for( ; it != it_end; ++it ) + s += it.value(); + \endcode +*/ +class CV_EXPORTS SparseMatConstIterator { - Mat::create(_dims, _sz, DataType<_Tp>::type); -} +public: + //! the default constructor + SparseMatConstIterator(); + //! the full constructor setting the iterator to the first sparse matrix element + SparseMatConstIterator(const SparseMat* _m); + //! the copy constructor + SparseMatConstIterator(const SparseMatConstIterator& it); + + //! the assignment operator + SparseMatConstIterator& operator = (const SparseMatConstIterator& it); + + //! template method returning the current matrix element + template const _Tp& value() const; + //! returns the current node of the sparse matrix. it.node->idx is the current element index + const SparseMat::Node* node() const; + + //! moves iterator to the previous element + SparseMatConstIterator& operator --(); + //! moves iterator to the previous element + SparseMatConstIterator operator --(int); + //! moves iterator to the next element + SparseMatConstIterator& operator ++(); + //! moves iterator to the next element + SparseMatConstIterator operator ++(int); + + //! moves iterator to the element after the last element + void seekEnd(); + + const SparseMat* m; + size_t hashidx; + uchar* ptr; +}; -template inline Mat_<_Tp> Mat_<_Tp>::cross(const Mat_& m) const -{ return Mat_<_Tp>(Mat::cross(m)); } -template template inline Mat_<_Tp>::operator Mat_() const -{ return Mat_(*this); } +////////////////////////////////// SparseMatIterator ///////////////////////////////// -template inline Mat_<_Tp> Mat_<_Tp>::row(int y) const -{ return Mat_(*this, Range(y, y+1), Range::all()); } -template inline Mat_<_Tp> Mat_<_Tp>::col(int x) const -{ return Mat_(*this, Range::all(), Range(x, x+1)); } -template inline Mat_<_Tp> Mat_<_Tp>::diag(int d) const -{ return Mat_(Mat::diag(d)); } -template inline Mat_<_Tp> Mat_<_Tp>::clone() const -{ return Mat_(Mat::clone()); } +/*! + Read-write Sparse Matrix Iterator -template inline size_t Mat_<_Tp>::elemSize() const + The class is similar to cv::SparseMatConstIterator, + but can be used for in-place modification of the matrix elements. +*/ +class CV_EXPORTS SparseMatIterator : public SparseMatConstIterator { - CV_DbgAssert( Mat::elemSize() == sizeof(_Tp) ); - return sizeof(_Tp); -} +public: + //! the default constructor + SparseMatIterator(); + //! the full constructor setting the iterator to the first sparse matrix element + SparseMatIterator(SparseMat* _m); + //! the full constructor setting the iterator to the specified sparse matrix element + SparseMatIterator(SparseMat* _m, const int* idx); + //! the copy constructor + SparseMatIterator(const SparseMatIterator& it); -template inline size_t Mat_<_Tp>::elemSize1() const + //! the assignment operator + SparseMatIterator& operator = (const SparseMatIterator& it); + //! returns read-write reference to the current sparse matrix element + template _Tp& value() const; + //! returns pointer to the current sparse matrix node. it.node->idx is the index of the current element (do not modify it!) + SparseMat::Node* node() const; + + //! moves iterator to the next element + SparseMatIterator& operator ++(); + //! moves iterator to the next element + SparseMatIterator operator ++(int); +}; + + + +/////////////////////////////// SparseMatConstIterator_ ////////////////////////////// + +/*! + Template Read-Only Sparse Matrix Iterator Class. + + This is the derived from SparseMatConstIterator class that + introduces more convenient operator *() for accessing the current element. +*/ +template class SparseMatConstIterator_ : public SparseMatConstIterator { - CV_DbgAssert( Mat::elemSize1() == sizeof(_Tp)/DataType<_Tp>::channels ); - return sizeof(_Tp)/DataType<_Tp>::channels; -} -template inline int Mat_<_Tp>::type() const +public: + +#ifndef OPENCV_NOSTL + typedef std::forward_iterator_tag iterator_category; +#endif + + //! the default constructor + SparseMatConstIterator_(); + //! the full constructor setting the iterator to the first sparse matrix element + SparseMatConstIterator_(const SparseMat_<_Tp>* _m); + SparseMatConstIterator_(const SparseMat* _m); + //! the copy constructor + SparseMatConstIterator_(const SparseMatConstIterator_& it); + + //! the assignment operator + SparseMatConstIterator_& operator = (const SparseMatConstIterator_& it); + //! the element access operator + const _Tp& operator *() const; + + //! moves iterator to the next element + SparseMatConstIterator_& operator ++(); + //! moves iterator to the next element + SparseMatConstIterator_ operator ++(int); +}; + + + +///////////////////////////////// SparseMatIterator_ ///////////////////////////////// + +/*! + Template Read-Write Sparse Matrix Iterator Class. + + This is the derived from cv::SparseMatConstIterator_ class that + introduces more convenient operator *() for accessing the current element. +*/ +template class SparseMatIterator_ : public SparseMatConstIterator_<_Tp> { - CV_DbgAssert( Mat::type() == DataType<_Tp>::type ); - return DataType<_Tp>::type; -} -template inline int Mat_<_Tp>::depth() const +public: + +#ifndef OPENCV_NOSTL + typedef std::forward_iterator_tag iterator_category; +#endif + + //! the default constructor + SparseMatIterator_(); + //! the full constructor setting the iterator to the first sparse matrix element + SparseMatIterator_(SparseMat_<_Tp>* _m); + SparseMatIterator_(SparseMat* _m); + //! the copy constructor + SparseMatIterator_(const SparseMatIterator_& it); + + //! the assignment operator + SparseMatIterator_& operator = (const SparseMatIterator_& it); + //! returns the reference to the current element + _Tp& operator *() const; + + //! moves the iterator to the next element + SparseMatIterator_& operator ++(); + //! moves the iterator to the next element + SparseMatIterator_ operator ++(int); +}; + + + +/////////////////////////////////// NAryMatIterator ////////////////////////////////// + +/*! + n-Dimensional Dense Matrix Iterator Class. + + The class cv::NAryMatIterator is used for iterating over one or more n-dimensional dense arrays (cv::Mat's). + + The iterator is completely different from cv::Mat_ and cv::SparseMat_ iterators. + It iterates through the slices (or planes), not the elements, where "slice" is a continuous part of the arrays. + + Here is the example on how the iterator can be used to normalize 3D histogram: + + \code + void normalizeColorHist(Mat& hist) + { + #if 1 + // intialize iterator (the style is different from STL). + // after initialization the iterator will contain + // the number of slices or planes + // the iterator will go through + Mat* arrays[] = { &hist, 0 }; + Mat planes[1]; + NAryMatIterator it(arrays, planes); + double s = 0; + // iterate through the matrix. on each iteration + // it.planes[i] (of type Mat) will be set to the current plane of + // i-th n-dim matrix passed to the iterator constructor. + for(int p = 0; p < it.nplanes; p++, ++it) + s += sum(it.planes[0])[0]; + it = NAryMatIterator(hist); + s = 1./s; + for(int p = 0; p < it.nplanes; p++, ++it) + it.planes[0] *= s; + #elif 1 + // this is a shorter implementation of the above + // using built-in operations on Mat + double s = sum(hist)[0]; + hist.convertTo(hist, hist.type(), 1./s, 0); + #else + // and this is even shorter one + // (assuming that the histogram elements are non-negative) + normalize(hist, hist, 1, 0, NORM_L1); + #endif + } + \endcode + + You can iterate through several matrices simultaneously as long as they have the same geometry + (dimensionality and all the dimension sizes are the same), which is useful for binary + and n-ary operations on such matrices. Just pass those matrices to cv::MatNDIterator. + Then, during the iteration it.planes[0], it.planes[1], ... will + be the slices of the corresponding matrices +*/ +class CV_EXPORTS NAryMatIterator { - CV_DbgAssert( Mat::depth() == DataType<_Tp>::depth ); - return DataType<_Tp>::depth; -} -template inline int Mat_<_Tp>::channels() const -{ - CV_DbgAssert( Mat::channels() == DataType<_Tp>::channels ); - return DataType<_Tp>::channels; -} -template inline size_t Mat_<_Tp>::stepT(int i) const { return step.p[i]/elemSize(); } -template inline size_t Mat_<_Tp>::step1(int i) const { return step.p[i]/elemSize1(); } +public: + //! the default constructor + NAryMatIterator(); + //! the full constructor taking arbitrary number of n-dim matrices + NAryMatIterator(const Mat** arrays, uchar** ptrs, int narrays=-1); + //! the full constructor taking arbitrary number of n-dim matrices + NAryMatIterator(const Mat** arrays, Mat* planes, int narrays=-1); + //! the separate iterator initialization method + void init(const Mat** arrays, Mat* planes, uchar** ptrs, int narrays=-1); -template inline Mat_<_Tp>& Mat_<_Tp>::adjustROI( int dtop, int dbottom, int dleft, int dright ) -{ return (Mat_<_Tp>&)(Mat::adjustROI(dtop, dbottom, dleft, dright)); } + //! proceeds to the next plane of every iterated matrix + NAryMatIterator& operator ++(); + //! proceeds to the next plane of every iterated matrix (postfix increment operator) + NAryMatIterator operator ++(int); -template inline Mat_<_Tp> Mat_<_Tp>::operator()( const Range& _rowRange, const Range& _colRange ) const -{ return Mat_<_Tp>(*this, _rowRange, _colRange); } - -template inline Mat_<_Tp> Mat_<_Tp>::operator()( const Rect& roi ) const -{ return Mat_<_Tp>(*this, roi); } - -template inline Mat_<_Tp> Mat_<_Tp>::operator()( const Range* ranges ) const -{ return Mat_<_Tp>(*this, ranges); } - -template inline _Tp* Mat_<_Tp>::operator [](int y) -{ return (_Tp*)ptr(y); } -template inline const _Tp* Mat_<_Tp>::operator [](int y) const -{ return (const _Tp*)ptr(y); } - -template inline _Tp& Mat_<_Tp>::operator ()(int i0, int i1) -{ - CV_DbgAssert( dims <= 2 && data && - (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)i1 < (unsigned)size.p[1] && - type() == DataType<_Tp>::type ); - return ((_Tp*)(data + step.p[0]*i0))[i1]; -} - -template inline const _Tp& Mat_<_Tp>::operator ()(int i0, int i1) const -{ - CV_DbgAssert( dims <= 2 && data && - (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)i1 < (unsigned)size.p[1] && - type() == DataType<_Tp>::type ); - return ((const _Tp*)(data + step.p[0]*i0))[i1]; -} - -template inline _Tp& Mat_<_Tp>::operator ()(Point pt) -{ - CV_DbgAssert( dims <= 2 && data && - (unsigned)pt.y < (unsigned)size.p[0] && - (unsigned)pt.x < (unsigned)size.p[1] && - type() == DataType<_Tp>::type ); - return ((_Tp*)(data + step.p[0]*pt.y))[pt.x]; -} - -template inline const _Tp& Mat_<_Tp>::operator ()(Point pt) const -{ - CV_DbgAssert( dims <= 2 && data && - (unsigned)pt.y < (unsigned)size.p[0] && - (unsigned)pt.x < (unsigned)size.p[1] && - type() == DataType<_Tp>::type ); - return ((const _Tp*)(data + step.p[0]*pt.y))[pt.x]; -} - -template inline _Tp& Mat_<_Tp>::operator ()(const int* idx) -{ - return Mat::at<_Tp>(idx); -} - -template inline const _Tp& Mat_<_Tp>::operator ()(const int* idx) const -{ - return Mat::at<_Tp>(idx); -} - -template template inline _Tp& Mat_<_Tp>::operator ()(const Vec& idx) -{ - return Mat::at<_Tp>(idx); -} - -template template inline const _Tp& Mat_<_Tp>::operator ()(const Vec& idx) const -{ - return Mat::at<_Tp>(idx); -} - -template inline _Tp& Mat_<_Tp>::operator ()(int i0) -{ - return this->at<_Tp>(i0); -} - -template inline const _Tp& Mat_<_Tp>::operator ()(int i0) const -{ - return this->at<_Tp>(i0); -} - -template inline _Tp& Mat_<_Tp>::operator ()(int i0, int i1, int i2) -{ - return this->at<_Tp>(i0, i1, i2); -} - -template inline const _Tp& Mat_<_Tp>::operator ()(int i0, int i1, int i2) const -{ - return this->at<_Tp>(i0, i1, i2); -} + //! the iterated arrays + const Mat** arrays; + //! the current planes + Mat* planes; + //! data pointers + uchar** ptrs; + //! the number of arrays + int narrays; + //! the number of hyper-planes that the iterator steps through + size_t nplanes; + //! the size of each segment (in elements) + size_t size; +protected: + int iterdepth; + size_t idx; +}; -template inline Mat_<_Tp>::operator std::vector<_Tp>() const -{ - std::vector<_Tp> v; - copyTo(v); - return v; -} -template template inline Mat_<_Tp>::operator Vec::channel_type, n>() const -{ - CV_Assert(n % DataType<_Tp>::channels == 0); - return this->Mat::operator Vec::channel_type, n>(); -} - -template template inline Mat_<_Tp>::operator Matx::channel_type, m, n>() const -{ - CV_Assert(n % DataType<_Tp>::channels == 0); - return this->Mat::operator Matx::channel_type, m, n>(); -} - -template inline void -process( const Mat_& m1, Mat_& m2, Op op ) -{ - int y, x, rows = m1.rows, cols = m1.cols; - - CV_DbgAssert( m1.size() == m2.size() ); - - for( y = 0; y < rows; y++ ) - { - const T1* src = m1[y]; - T2* dst = m2[y]; - - for( x = 0; x < cols; x++ ) - dst[x] = op(src[x]); - } -} - -template inline void -process( const Mat_& m1, const Mat_& m2, Mat_& m3, Op op ) -{ - int y, x, rows = m1.rows, cols = m1.cols; - - CV_DbgAssert( m1.size() == m2.size() ); - - for( y = 0; y < rows; y++ ) - { - const T1* src1 = m1[y]; - const T2* src2 = m2[y]; - T3* dst = m3[y]; - - for( x = 0; x < cols; x++ ) - dst[x] = op( src1[x], src2[x] ); - } -} - - -/////////////////////////////// Input/Output Arrays ///////////////////////////////// - -template inline _InputArray::_InputArray(const std::vector<_Tp>& vec) - : flags(FIXED_TYPE + STD_VECTOR + DataType<_Tp>::type), obj((void*)&vec) {} - -template inline _InputArray::_InputArray(const std::vector >& vec) - : flags(FIXED_TYPE + STD_VECTOR_VECTOR + DataType<_Tp>::type), obj((void*)&vec) {} - -template inline _InputArray::_InputArray(const std::vector >& vec) - : flags(FIXED_TYPE + STD_VECTOR_MAT + DataType<_Tp>::type), obj((void*)&vec) {} - -template inline _InputArray::_InputArray(const Matx<_Tp, m, n>& mtx) - : flags(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type), obj((void*)&mtx), sz(n, m) {} - -template inline _InputArray::_InputArray(const _Tp* vec, int n) - : flags(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type), obj((void*)vec), sz(n, 1) {} - -inline _InputArray::_InputArray(const Scalar& s) - : flags(FIXED_TYPE + FIXED_SIZE + MATX + CV_64F), obj((void*)&s), sz(1, 4) {} - -template inline _InputArray::_InputArray(const Mat_<_Tp>& m) - : flags(FIXED_TYPE + MAT + DataType<_Tp>::type), obj((void*)&m) {} - -template inline _OutputArray::_OutputArray(std::vector<_Tp>& vec) - : _InputArray(vec) {} -template inline _OutputArray::_OutputArray(std::vector >& vec) - : _InputArray(vec) {} -template inline _OutputArray::_OutputArray(std::vector >& vec) - : _InputArray(vec) {} -template inline _OutputArray::_OutputArray(Mat_<_Tp>& m) - : _InputArray(m) {} -template inline _OutputArray::_OutputArray(Matx<_Tp, m, n>& mtx) - : _InputArray(mtx) {} -template inline _OutputArray::_OutputArray(_Tp* vec, int n) - : _InputArray(vec, n) {} - -template inline _OutputArray::_OutputArray(const std::vector<_Tp>& vec) - : _InputArray(vec) {flags |= FIXED_SIZE;} -template inline _OutputArray::_OutputArray(const std::vector >& vec) - : _InputArray(vec) {flags |= FIXED_SIZE;} -template inline _OutputArray::_OutputArray(const std::vector >& vec) - : _InputArray(vec) {flags |= FIXED_SIZE;} - -template inline _OutputArray::_OutputArray(const Mat_<_Tp>& m) - : _InputArray(m) {flags |= FIXED_SIZE;} -template inline _OutputArray::_OutputArray(const Matx<_Tp, m, n>& mtx) - : _InputArray(mtx) {} -template inline _OutputArray::_OutputArray(const _Tp* vec, int n) - : _InputArray(vec, n) {} - -//////////////////////////////////// Matrix Expressions ///////////////////////////////////////// +///////////////////////////////// Matrix Expressions ///////////////////////////////// class CV_EXPORTS MatOp { public: - MatOp() {}; - virtual ~MatOp() {}; + MatOp(); + virtual ~MatOp(); virtual bool elementWise(const MatExpr& expr) const; virtual void assign(const MatExpr& expr, Mat& m, int type=-1) const = 0; @@ -1211,41 +1894,31 @@ public: class CV_EXPORTS MatExpr { public: - MatExpr() : op(0), flags(0), a(Mat()), b(Mat()), c(Mat()), alpha(0), beta(0), s(Scalar()) {} - MatExpr(const MatOp* _op, int _flags, const Mat& _a=Mat(), const Mat& _b=Mat(), - const Mat& _c=Mat(), double _alpha=1, double _beta=1, const Scalar& _s=Scalar()) - : op(_op), flags(_flags), a(_a), b(_b), c(_c), alpha(_alpha), beta(_beta), s(_s) {} + MatExpr(); explicit MatExpr(const Mat& m); - operator Mat() const - { - Mat m; - op->assign(*this, m); - return m; - } - template operator Mat_<_Tp>() const - { - Mat_<_Tp> m; - op->assign(*this, m, DataType<_Tp>::type); - return m; - } + MatExpr(const MatOp* _op, int _flags, const Mat& _a = Mat(), const Mat& _b = Mat(), + const Mat& _c = Mat(), double _alpha = 1, double _beta = 1, const Scalar& _s = Scalar()); + + operator Mat() const; + template operator Mat_<_Tp>() const; + + Size size() const; + int type() const; MatExpr row(int y) const; MatExpr col(int x) const; - MatExpr diag(int d=0) const; + MatExpr diag(int d = 0) const; MatExpr operator()( const Range& rowRange, const Range& colRange ) const; MatExpr operator()( const Rect& roi ) const; - Mat cross(const Mat& m) const; - double dot(const Mat& m) const; - MatExpr t() const; MatExpr inv(int method = DECOMP_LU) const; MatExpr mul(const MatExpr& e, double scale=1) const; MatExpr mul(const Mat& m, double scale=1) const; - Size size() const; - int type() const; + Mat cross(const Mat& m) const; + double dot(const Mat& m) const; const MatOp* op; int flags; @@ -1319,75 +1992,6 @@ CV_EXPORTS MatExpr operator > (const Mat& a, const Mat& b); CV_EXPORTS MatExpr operator > (const Mat& a, double s); CV_EXPORTS MatExpr operator > (double s, const Mat& a); -CV_EXPORTS MatExpr min(const Mat& a, const Mat& b); -CV_EXPORTS MatExpr min(const Mat& a, double s); -CV_EXPORTS MatExpr min(double s, const Mat& a); - -CV_EXPORTS MatExpr max(const Mat& a, const Mat& b); -CV_EXPORTS MatExpr max(const Mat& a, double s); -CV_EXPORTS MatExpr max(double s, const Mat& a); - -template static inline MatExpr min(const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - return cv::min((const Mat&)a, (const Mat&)b); -} - -template static inline MatExpr min(const Mat_<_Tp>& a, double s) -{ - return cv::min((const Mat&)a, s); -} - -template static inline MatExpr min(double s, const Mat_<_Tp>& a) -{ - return cv::min((const Mat&)a, s); -} - -template static inline MatExpr max(const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - return cv::max((const Mat&)a, (const Mat&)b); -} - -template static inline MatExpr max(const Mat_<_Tp>& a, double s) -{ - return cv::max((const Mat&)a, s); -} - -template static inline MatExpr max(double s, const Mat_<_Tp>& a) -{ - return cv::max((const Mat&)a, s); -} - -template static inline void min(const Mat_<_Tp>& a, const Mat_<_Tp>& b, Mat_<_Tp>& c) -{ - cv::min((const Mat&)a, (const Mat&)b, (Mat&)c); -} - -template static inline void min(const Mat_<_Tp>& a, double s, Mat_<_Tp>& c) -{ - cv::min((const Mat&)a, s, (Mat&)c); -} - -template static inline void min(double s, const Mat_<_Tp>& a, Mat_<_Tp>& c) -{ - cv::min((const Mat&)a, s, (Mat&)c); -} - -template static inline void max(const Mat_<_Tp>& a, const Mat_<_Tp>& b, Mat_<_Tp>& c) -{ - cv::max((const Mat&)a, (const Mat&)b, (Mat&)c); -} - -template static inline void max(const Mat_<_Tp>& a, double s, Mat_<_Tp>& c) -{ - cv::max((const Mat&)a, s, (Mat&)c); -} - -template static inline void max(double s, const Mat_<_Tp>& a, Mat_<_Tp>& c) -{ - cv::max((const Mat&)a, s, (Mat&)c); -} - - CV_EXPORTS MatExpr operator & (const Mat& a, const Mat& b); CV_EXPORTS MatExpr operator & (const Mat& a, const Scalar& s); CV_EXPORTS MatExpr operator & (const Scalar& s, const Mat& a); @@ -1402,1204 +2006,19 @@ CV_EXPORTS MatExpr operator ^ (const Scalar& s, const Mat& a); CV_EXPORTS MatExpr operator ~(const Mat& m); +CV_EXPORTS MatExpr min(const Mat& a, const Mat& b); +CV_EXPORTS MatExpr min(const Mat& a, double s); +CV_EXPORTS MatExpr min(double s, const Mat& a); + +CV_EXPORTS MatExpr max(const Mat& a, const Mat& b); +CV_EXPORTS MatExpr max(const Mat& a, double s); +CV_EXPORTS MatExpr max(double s, const Mat& a); + CV_EXPORTS MatExpr abs(const Mat& m); CV_EXPORTS MatExpr abs(const MatExpr& e); -template static inline MatExpr abs(const Mat_<_Tp>& m) -{ - return cv::abs((const Mat&)m); -} +} // cv -////////////////////////////// Augmenting algebraic operations ////////////////////////////////// +#include "opencv2/core/mat.inl.hpp" -inline Mat& Mat::operator = (const MatExpr& e) -{ - e.op->assign(e, *this); - return *this; -} - -template inline Mat_<_Tp>::Mat_(const MatExpr& e) -{ - e.op->assign(e, *this, DataType<_Tp>::type); -} - -template Mat_<_Tp>& Mat_<_Tp>::operator = (const MatExpr& e) -{ - e.op->assign(e, *this, DataType<_Tp>::type); - return *this; -} - -static inline Mat& operator += (const Mat& a, const Mat& b) -{ - add(a, b, (Mat&)a); - return (Mat&)a; -} - -static inline Mat& operator += (const Mat& a, const Scalar& s) -{ - add(a, s, (Mat&)a); - return (Mat&)a; -} - -template static inline -Mat_<_Tp>& operator += (const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - add(a, b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -template static inline -Mat_<_Tp>& operator += (const Mat_<_Tp>& a, const Scalar& s) -{ - add(a, s, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -static inline Mat& operator += (const Mat& a, const MatExpr& b) -{ - b.op->augAssignAdd(b, (Mat&)a); - return (Mat&)a; -} - -template static inline -Mat_<_Tp>& operator += (const Mat_<_Tp>& a, const MatExpr& b) -{ - b.op->augAssignAdd(b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -static inline Mat& operator -= (const Mat& a, const Mat& b) -{ - subtract(a, b, (Mat&)a); - return (Mat&)a; -} - -static inline Mat& operator -= (const Mat& a, const Scalar& s) -{ - subtract(a, s, (Mat&)a); - return (Mat&)a; -} - -template static inline -Mat_<_Tp>& operator -= (const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - subtract(a, b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -template static inline -Mat_<_Tp>& operator -= (const Mat_<_Tp>& a, const Scalar& s) -{ - subtract(a, s, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -static inline Mat& operator -= (const Mat& a, const MatExpr& b) -{ - b.op->augAssignSubtract(b, (Mat&)a); - return (Mat&)a; -} - -template static inline -Mat_<_Tp>& operator -= (const Mat_<_Tp>& a, const MatExpr& b) -{ - b.op->augAssignSubtract(b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -static inline Mat& operator *= (const Mat& a, const Mat& b) -{ - gemm(a, b, 1, Mat(), 0, (Mat&)a, 0); - return (Mat&)a; -} - -static inline Mat& operator *= (const Mat& a, double s) -{ - a.convertTo((Mat&)a, -1, s); - return (Mat&)a; -} - -template static inline -Mat_<_Tp>& operator *= (const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - gemm(a, b, 1, Mat(), 0, (Mat&)a, 0); - return (Mat_<_Tp>&)a; -} - -template static inline -Mat_<_Tp>& operator *= (const Mat_<_Tp>& a, double s) -{ - a.convertTo((Mat&)a, -1, s); - return (Mat_<_Tp>&)a; -} - -static inline Mat& operator *= (const Mat& a, const MatExpr& b) -{ - b.op->augAssignMultiply(b, (Mat&)a); - return (Mat&)a; -} - -template static inline -Mat_<_Tp>& operator *= (const Mat_<_Tp>& a, const MatExpr& b) -{ - b.op->augAssignMultiply(b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -static inline Mat& operator /= (const Mat& a, const Mat& b) -{ - divide(a, b, (Mat&)a); - return (Mat&)a; -} - -static inline Mat& operator /= (const Mat& a, double s) -{ - a.convertTo((Mat&)a, -1, 1./s); - return (Mat&)a; -} - -template static inline -Mat_<_Tp>& operator /= (const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - divide(a, b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -template static inline -Mat_<_Tp>& operator /= (const Mat_<_Tp>& a, double s) -{ - a.convertTo((Mat&)a, -1, 1./s); - return (Mat_<_Tp>&)a; -} - -static inline Mat& operator /= (const Mat& a, const MatExpr& b) -{ - b.op->augAssignDivide(b, (Mat&)a); - return (Mat&)a; -} - -template static inline -Mat_<_Tp>& operator /= (const Mat_<_Tp>& a, const MatExpr& b) -{ - b.op->augAssignDivide(b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -////////////////////////////// Logical operations /////////////////////////////// - -static inline Mat& operator &= (const Mat& a, const Mat& b) -{ - bitwise_and(a, b, (Mat&)a); - return (Mat&)a; -} - -static inline Mat& operator &= (const Mat& a, const Scalar& s) -{ - bitwise_and(a, s, (Mat&)a); - return (Mat&)a; -} - -template static inline Mat_<_Tp>& -operator &= (const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - bitwise_and(a, b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -template static inline Mat_<_Tp>& -operator &= (const Mat_<_Tp>& a, const Scalar& s) -{ - bitwise_and(a, s, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -static inline Mat& operator |= (const Mat& a, const Mat& b) -{ - bitwise_or(a, b, (Mat&)a); - return (Mat&)a; -} - -static inline Mat& operator |= (const Mat& a, const Scalar& s) -{ - bitwise_or(a, s, (Mat&)a); - return (Mat&)a; -} - -template static inline Mat_<_Tp>& -operator |= (const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - bitwise_or(a, b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -template static inline Mat_<_Tp>& -operator |= (const Mat_<_Tp>& a, const Scalar& s) -{ - bitwise_or(a, s, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -static inline Mat& operator ^= (const Mat& a, const Mat& b) -{ - bitwise_xor(a, b, (Mat&)a); - return (Mat&)a; -} - -static inline Mat& operator ^= (const Mat& a, const Scalar& s) -{ - bitwise_xor(a, s, (Mat&)a); - return (Mat&)a; -} - -template static inline Mat_<_Tp>& -operator ^= (const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - bitwise_xor(a, b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -template static inline Mat_<_Tp>& -operator ^= (const Mat_<_Tp>& a, const Scalar& s) -{ - bitwise_xor(a, s, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -/////////////////////////////// Miscellaneous operations ////////////////////////////// - -template void split(const Mat& src, std::vector >& mv) -{ split(src, (std::vector&)mv ); } - -////////////////////////////////////////////////////////////// - -template inline MatExpr Mat_<_Tp>::zeros(int rows, int cols) -{ - return Mat::zeros(rows, cols, DataType<_Tp>::type); -} - -template inline MatExpr Mat_<_Tp>::zeros(Size sz) -{ - return Mat::zeros(sz, DataType<_Tp>::type); -} - -template inline MatExpr Mat_<_Tp>::ones(int rows, int cols) -{ - return Mat::ones(rows, cols, DataType<_Tp>::type); -} - -template inline MatExpr Mat_<_Tp>::ones(Size sz) -{ - return Mat::ones(sz, DataType<_Tp>::type); -} - -template inline MatExpr Mat_<_Tp>::eye(int rows, int cols) -{ - return Mat::eye(rows, cols, DataType<_Tp>::type); -} - -template inline MatExpr Mat_<_Tp>::eye(Size sz) -{ - return Mat::eye(sz, DataType<_Tp>::type); -} - -//////////////////////////////// Iterators & Comma initializers ////////////////////////////////// - -inline MatConstIterator::MatConstIterator() - : m(0), elemSize(0), ptr(0), sliceStart(0), sliceEnd(0) {} - -inline MatConstIterator::MatConstIterator(const Mat* _m) - : m(_m), elemSize(_m->elemSize()), ptr(0), sliceStart(0), sliceEnd(0) -{ - if( m && m->isContinuous() ) - { - sliceStart = m->data; - sliceEnd = sliceStart + m->total()*elemSize; - } - seek((const int*)0); -} - -inline MatConstIterator::MatConstIterator(const Mat* _m, int _row, int _col) - : m(_m), elemSize(_m->elemSize()), ptr(0), sliceStart(0), sliceEnd(0) -{ - CV_Assert(m && m->dims <= 2); - if( m->isContinuous() ) - { - sliceStart = m->data; - sliceEnd = sliceStart + m->total()*elemSize; - } - int idx[]={_row, _col}; - seek(idx); -} - -inline MatConstIterator::MatConstIterator(const Mat* _m, Point _pt) - : m(_m), elemSize(_m->elemSize()), ptr(0), sliceStart(0), sliceEnd(0) -{ - CV_Assert(m && m->dims <= 2); - if( m->isContinuous() ) - { - sliceStart = m->data; - sliceEnd = sliceStart + m->total()*elemSize; - } - int idx[]={_pt.y, _pt.x}; - seek(idx); -} - -inline MatConstIterator::MatConstIterator(const MatConstIterator& it) - : m(it.m), elemSize(it.elemSize), ptr(it.ptr), sliceStart(it.sliceStart), sliceEnd(it.sliceEnd) -{} - -inline MatConstIterator& MatConstIterator::operator = (const MatConstIterator& it ) -{ - m = it.m; elemSize = it.elemSize; ptr = it.ptr; - sliceStart = it.sliceStart; sliceEnd = it.sliceEnd; - return *this; -} - -inline uchar* MatConstIterator::operator *() const { return ptr; } - -inline MatConstIterator& MatConstIterator::operator += (ptrdiff_t ofs) -{ - if( !m || ofs == 0 ) - return *this; - ptrdiff_t ofsb = ofs*elemSize; - ptr += ofsb; - if( ptr < sliceStart || sliceEnd <= ptr ) - { - ptr -= ofsb; - seek(ofs, true); - } - return *this; -} - -inline MatConstIterator& MatConstIterator::operator -= (ptrdiff_t ofs) -{ return (*this += -ofs); } - -inline MatConstIterator& MatConstIterator::operator --() -{ - if( m && (ptr -= elemSize) < sliceStart ) - { - ptr += elemSize; - seek(-1, true); - } - return *this; -} - -inline MatConstIterator MatConstIterator::operator --(int) -{ - MatConstIterator b = *this; - *this += -1; - return b; -} - -inline MatConstIterator& MatConstIterator::operator ++() -{ - if( m && (ptr += elemSize) >= sliceEnd ) - { - ptr -= elemSize; - seek(1, true); - } - return *this; -} - -inline MatConstIterator MatConstIterator::operator ++(int) -{ - MatConstIterator b = *this; - *this += 1; - return b; -} - -template inline MatConstIterator_<_Tp>::MatConstIterator_() {} - -template inline MatConstIterator_<_Tp>::MatConstIterator_(const Mat_<_Tp>* _m) - : MatConstIterator(_m) {} - -template inline MatConstIterator_<_Tp>:: - MatConstIterator_(const Mat_<_Tp>* _m, int _row, int _col) - : MatConstIterator(_m, _row, _col) {} - -template inline MatConstIterator_<_Tp>:: - MatConstIterator_(const Mat_<_Tp>* _m, Point _pt) - : MatConstIterator(_m, _pt) {} - -template inline MatConstIterator_<_Tp>:: - MatConstIterator_(const MatConstIterator_& it) - : MatConstIterator(it) {} - -template inline MatConstIterator_<_Tp>& - MatConstIterator_<_Tp>::operator = (const MatConstIterator_& it ) -{ - MatConstIterator::operator = (it); - return *this; -} - -template inline _Tp MatConstIterator_<_Tp>::operator *() const { return *(_Tp*)(this->ptr); } - -template inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator += (ptrdiff_t ofs) -{ - MatConstIterator::operator += (ofs); - return *this; -} - -template inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator -= (ptrdiff_t ofs) -{ return (*this += -ofs); } - -template inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator --() -{ - MatConstIterator::operator --(); - return *this; -} - -template inline MatConstIterator_<_Tp> MatConstIterator_<_Tp>::operator --(int) -{ - MatConstIterator_ b = *this; - MatConstIterator::operator --(); - return b; -} - -template inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator ++() -{ - MatConstIterator::operator ++(); - return *this; -} - -template inline MatConstIterator_<_Tp> MatConstIterator_<_Tp>::operator ++(int) -{ - MatConstIterator_ b = *this; - MatConstIterator::operator ++(); - return b; -} - -template inline MatIterator_<_Tp>::MatIterator_() : MatConstIterator_<_Tp>() {} - -template inline MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m) - : MatConstIterator_<_Tp>(_m) {} - -template inline MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m, int _row, int _col) - : MatConstIterator_<_Tp>(_m, _row, _col) {} - -template inline MatIterator_<_Tp>::MatIterator_(const Mat_<_Tp>* _m, Point _pt) - : MatConstIterator_<_Tp>(_m, _pt) {} - -template inline MatIterator_<_Tp>::MatIterator_(const Mat_<_Tp>* _m, const int* _idx) - : MatConstIterator_<_Tp>(_m, _idx) {} - -template inline MatIterator_<_Tp>::MatIterator_(const MatIterator_& it) - : MatConstIterator_<_Tp>(it) {} - -template inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator = (const MatIterator_<_Tp>& it ) -{ - MatConstIterator::operator = (it); - return *this; -} - -template inline _Tp& MatIterator_<_Tp>::operator *() const { return *(_Tp*)(this->ptr); } - -template inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator += (ptrdiff_t ofs) -{ - MatConstIterator::operator += (ofs); - return *this; -} - -template inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator -= (ptrdiff_t ofs) -{ - MatConstIterator::operator += (-ofs); - return *this; -} - -template inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator --() -{ - MatConstIterator::operator --(); - return *this; -} - -template inline MatIterator_<_Tp> MatIterator_<_Tp>::operator --(int) -{ - MatIterator_ b = *this; - MatConstIterator::operator --(); - return b; -} - -template inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator ++() -{ - MatConstIterator::operator ++(); - return *this; -} - -template inline MatIterator_<_Tp> MatIterator_<_Tp>::operator ++(int) -{ - MatIterator_ b = *this; - MatConstIterator::operator ++(); - return b; -} - -template inline Point MatConstIterator_<_Tp>::pos() const -{ - if( !m ) - return Point(); - CV_DbgAssert( m->dims <= 2 ); - if( m->isContinuous() ) - { - ptrdiff_t ofs = (const _Tp*)ptr - (const _Tp*)m->data; - int y = (int)(ofs / m->cols), x = (int)(ofs - (ptrdiff_t)y*m->cols); - return Point(x, y); - } - else - { - ptrdiff_t ofs = (uchar*)ptr - m->data; - int y = (int)(ofs / m->step), x = (int)((ofs - y*m->step)/sizeof(_Tp)); - return Point(x, y); - } -} - -static inline bool -operator == (const MatConstIterator& a, const MatConstIterator& b) -{ return a.m == b.m && a.ptr == b.ptr; } - -template static inline bool -operator != (const MatConstIterator& a, const MatConstIterator& b) -{ return !(a == b); } - -template static inline bool -operator == (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b) -{ return a.m == b.m && a.ptr == b.ptr; } - -template static inline bool -operator != (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b) -{ return a.m != b.m || a.ptr != b.ptr; } - -template static inline bool -operator == (const MatIterator_<_Tp>& a, const MatIterator_<_Tp>& b) -{ return a.m == b.m && a.ptr == b.ptr; } - -template static inline bool -operator != (const MatIterator_<_Tp>& a, const MatIterator_<_Tp>& b) -{ return a.m != b.m || a.ptr != b.ptr; } - -static inline bool -operator < (const MatConstIterator& a, const MatConstIterator& b) -{ return a.ptr < b.ptr; } - -static inline bool -operator > (const MatConstIterator& a, const MatConstIterator& b) -{ return a.ptr > b.ptr; } - -static inline bool -operator <= (const MatConstIterator& a, const MatConstIterator& b) -{ return a.ptr <= b.ptr; } - -static inline bool -operator >= (const MatConstIterator& a, const MatConstIterator& b) -{ return a.ptr >= b.ptr; } - -CV_EXPORTS ptrdiff_t operator - (const MatConstIterator& b, const MatConstIterator& a); - -static inline MatConstIterator operator + (const MatConstIterator& a, ptrdiff_t ofs) -{ MatConstIterator b = a; return b += ofs; } - -static inline MatConstIterator operator + (ptrdiff_t ofs, const MatConstIterator& a) -{ MatConstIterator b = a; return b += ofs; } - -static inline MatConstIterator operator - (const MatConstIterator& a, ptrdiff_t ofs) -{ MatConstIterator b = a; return b += -ofs; } - -template static inline MatConstIterator_<_Tp> -operator + (const MatConstIterator_<_Tp>& a, ptrdiff_t ofs) -{ MatConstIterator t = (const MatConstIterator&)a + ofs; return (MatConstIterator_<_Tp>&)t; } - -template static inline MatConstIterator_<_Tp> -operator + (ptrdiff_t ofs, const MatConstIterator_<_Tp>& a) -{ MatConstIterator t = (const MatConstIterator&)a + ofs; return (MatConstIterator_<_Tp>&)t; } - -template static inline MatConstIterator_<_Tp> -operator - (const MatConstIterator_<_Tp>& a, ptrdiff_t ofs) -{ MatConstIterator t = (const MatConstIterator&)a - ofs; return (MatConstIterator_<_Tp>&)t; } - -inline uchar* MatConstIterator::operator [](ptrdiff_t i) const -{ return *(*this + i); } - -template inline _Tp MatConstIterator_<_Tp>::operator [](ptrdiff_t i) const -{ return *(_Tp*)MatConstIterator::operator [](i); } - -template static inline MatIterator_<_Tp> -operator + (const MatIterator_<_Tp>& a, ptrdiff_t ofs) -{ MatConstIterator t = (const MatConstIterator&)a + ofs; return (MatIterator_<_Tp>&)t; } - -template static inline MatIterator_<_Tp> -operator + (ptrdiff_t ofs, const MatIterator_<_Tp>& a) -{ MatConstIterator t = (const MatConstIterator&)a + ofs; return (MatIterator_<_Tp>&)t; } - -template static inline MatIterator_<_Tp> -operator - (const MatIterator_<_Tp>& a, ptrdiff_t ofs) -{ MatConstIterator t = (const MatConstIterator&)a - ofs; return (MatIterator_<_Tp>&)t; } - -template inline _Tp& MatIterator_<_Tp>::operator [](ptrdiff_t i) const -{ return *(*this + i); } - -template inline MatConstIterator_<_Tp> Mat_<_Tp>::begin() const -{ return Mat::begin<_Tp>(); } - -template inline MatConstIterator_<_Tp> Mat_<_Tp>::end() const -{ return Mat::end<_Tp>(); } - -template inline MatIterator_<_Tp> Mat_<_Tp>::begin() -{ return Mat::begin<_Tp>(); } - -template inline MatIterator_<_Tp> Mat_<_Tp>::end() -{ return Mat::end<_Tp>(); } - -template inline MatCommaInitializer_<_Tp>::MatCommaInitializer_(Mat_<_Tp>* _m) : it(_m) {} - -template template inline MatCommaInitializer_<_Tp>& -MatCommaInitializer_<_Tp>::operator , (T2 v) -{ - CV_DbgAssert( this->it < ((const Mat_<_Tp>*)this->it.m)->end() ); - *this->it = _Tp(v); ++this->it; - return *this; -} - -template inline Mat_<_Tp> MatCommaInitializer_<_Tp>::operator *() const -{ - CV_DbgAssert( this->it == ((const Mat_<_Tp>*)this->it.m)->end() ); - return Mat_<_Tp>(*this->it.m); -} - -template inline MatCommaInitializer_<_Tp>::operator Mat_<_Tp>() const -{ - CV_DbgAssert( this->it == ((const Mat_<_Tp>*)this->it.m)->end() ); - return Mat_<_Tp>(*this->it.m); -} - -template static inline MatCommaInitializer_<_Tp> -operator << (const Mat_<_Tp>& m, T2 val) -{ - MatCommaInitializer_<_Tp> commaInitializer((Mat_<_Tp>*)&m); - return (commaInitializer, val); -} - -//////////////////////////////// SparseMat //////////////////////////////// - -inline SparseMat::SparseMat() -: flags(MAGIC_VAL), hdr(0) -{ -} - -inline SparseMat::SparseMat(int _dims, const int* _sizes, int _type) -: flags(MAGIC_VAL), hdr(0) -{ - create(_dims, _sizes, _type); -} - -inline SparseMat::SparseMat(const SparseMat& m) -: flags(m.flags), hdr(m.hdr) -{ - addref(); -} - -inline SparseMat::~SparseMat() -{ - release(); -} - -inline SparseMat& SparseMat::operator = (const SparseMat& m) -{ - if( this != &m ) - { - if( m.hdr ) - CV_XADD(&m.hdr->refcount, 1); - release(); - flags = m.flags; - hdr = m.hdr; - } - return *this; -} - -inline SparseMat& SparseMat::operator = (const Mat& m) -{ return (*this = SparseMat(m)); } - -inline SparseMat SparseMat::clone() const -{ - SparseMat temp; - this->copyTo(temp); - return temp; -} - - -inline void SparseMat::assignTo( SparseMat& m, int _type ) const -{ - if( _type < 0 ) - m = *this; - else - convertTo(m, _type); -} - -inline void SparseMat::addref() -{ if( hdr ) CV_XADD(&hdr->refcount, 1); } - -inline void SparseMat::release() -{ - if( hdr && CV_XADD(&hdr->refcount, -1) == 1 ) - delete hdr; - hdr = 0; -} - -inline size_t SparseMat::elemSize() const -{ return CV_ELEM_SIZE(flags); } - -inline size_t SparseMat::elemSize1() const -{ return CV_ELEM_SIZE1(flags); } - -inline int SparseMat::type() const -{ return CV_MAT_TYPE(flags); } - -inline int SparseMat::depth() const -{ return CV_MAT_DEPTH(flags); } - -inline int SparseMat::channels() const -{ return CV_MAT_CN(flags); } - -inline const int* SparseMat::size() const -{ - return hdr ? hdr->size : 0; -} - -inline int SparseMat::size(int i) const -{ - if( hdr ) - { - CV_DbgAssert((unsigned)i < (unsigned)hdr->dims); - return hdr->size[i]; - } - return 0; -} - -inline int SparseMat::dims() const -{ - return hdr ? hdr->dims : 0; -} - -inline size_t SparseMat::nzcount() const -{ - return hdr ? hdr->nodeCount : 0; -} - -inline size_t SparseMat::hash(int i0) const -{ - return (size_t)i0; -} - -inline size_t SparseMat::hash(int i0, int i1) const -{ - return (size_t)(unsigned)i0*HASH_SCALE + (unsigned)i1; -} - -inline size_t SparseMat::hash(int i0, int i1, int i2) const -{ - return ((size_t)(unsigned)i0*HASH_SCALE + (unsigned)i1)*HASH_SCALE + (unsigned)i2; -} - -inline size_t SparseMat::hash(const int* idx) const -{ - size_t h = (unsigned)idx[0]; - if( !hdr ) - return 0; - int i, d = hdr->dims; - for( i = 1; i < d; i++ ) - h = h*HASH_SCALE + (unsigned)idx[i]; - return h; -} - -template inline _Tp& SparseMat::ref(int i0, size_t* hashval) -{ return *(_Tp*)((SparseMat*)this)->ptr(i0, true, hashval); } - -template inline _Tp& SparseMat::ref(int i0, int i1, size_t* hashval) -{ return *(_Tp*)((SparseMat*)this)->ptr(i0, i1, true, hashval); } - -template inline _Tp& SparseMat::ref(int i0, int i1, int i2, size_t* hashval) -{ return *(_Tp*)((SparseMat*)this)->ptr(i0, i1, i2, true, hashval); } - -template inline _Tp& SparseMat::ref(const int* idx, size_t* hashval) -{ return *(_Tp*)((SparseMat*)this)->ptr(idx, true, hashval); } - -template inline _Tp SparseMat::value(int i0, size_t* hashval) const -{ - const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(i0, false, hashval); - return p ? *p : _Tp(); -} - -template inline _Tp SparseMat::value(int i0, int i1, size_t* hashval) const -{ - const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(i0, i1, false, hashval); - return p ? *p : _Tp(); -} - -template inline _Tp SparseMat::value(int i0, int i1, int i2, size_t* hashval) const -{ - const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(i0, i1, i2, false, hashval); - return p ? *p : _Tp(); -} - -template inline _Tp SparseMat::value(const int* idx, size_t* hashval) const -{ - const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(idx, false, hashval); - return p ? *p : _Tp(); -} - -template inline const _Tp* SparseMat::find(int i0, size_t* hashval) const -{ return (const _Tp*)((SparseMat*)this)->ptr(i0, false, hashval); } - -template inline const _Tp* SparseMat::find(int i0, int i1, size_t* hashval) const -{ return (const _Tp*)((SparseMat*)this)->ptr(i0, i1, false, hashval); } - -template inline const _Tp* SparseMat::find(int i0, int i1, int i2, size_t* hashval) const -{ return (const _Tp*)((SparseMat*)this)->ptr(i0, i1, i2, false, hashval); } - -template inline const _Tp* SparseMat::find(const int* idx, size_t* hashval) const -{ return (const _Tp*)((SparseMat*)this)->ptr(idx, false, hashval); } - -template inline _Tp& SparseMat::value(Node* n) -{ return *(_Tp*)((uchar*)n + hdr->valueOffset); } - -template inline const _Tp& SparseMat::value(const Node* n) const -{ return *(const _Tp*)((const uchar*)n + hdr->valueOffset); } - -inline SparseMat::Node* SparseMat::node(size_t nidx) -{ return (Node*)&hdr->pool[nidx]; } - -inline const SparseMat::Node* SparseMat::node(size_t nidx) const -{ return (const Node*)&hdr->pool[nidx]; } - -inline SparseMatIterator SparseMat::begin() -{ return SparseMatIterator(this); } - -inline SparseMatConstIterator SparseMat::begin() const -{ return SparseMatConstIterator(this); } - -inline SparseMatIterator SparseMat::end() -{ SparseMatIterator it(this); it.seekEnd(); return it; } - -inline SparseMatConstIterator SparseMat::end() const -{ SparseMatConstIterator it(this); it.seekEnd(); return it; } - -template inline SparseMatIterator_<_Tp> SparseMat::begin() -{ return SparseMatIterator_<_Tp>(this); } - -template inline SparseMatConstIterator_<_Tp> SparseMat::begin() const -{ return SparseMatConstIterator_<_Tp>(this); } - -template inline SparseMatIterator_<_Tp> SparseMat::end() -{ SparseMatIterator_<_Tp> it(this); it.seekEnd(); return it; } - -template inline SparseMatConstIterator_<_Tp> SparseMat::end() const -{ SparseMatConstIterator_<_Tp> it(this); it.seekEnd(); return it; } - - -inline SparseMatConstIterator::SparseMatConstIterator() -: m(0), hashidx(0), ptr(0) -{ -} - -inline SparseMatConstIterator::SparseMatConstIterator(const SparseMatConstIterator& it) -: m(it.m), hashidx(it.hashidx), ptr(it.ptr) -{ -} - -static inline bool operator == (const SparseMatConstIterator& it1, const SparseMatConstIterator& it2) -{ return it1.m == it2.m && it1.ptr == it2.ptr; } - -static inline bool operator != (const SparseMatConstIterator& it1, const SparseMatConstIterator& it2) -{ return !(it1 == it2); } - - -inline SparseMatConstIterator& SparseMatConstIterator::operator = (const SparseMatConstIterator& it) -{ - if( this != &it ) - { - m = it.m; - hashidx = it.hashidx; - ptr = it.ptr; - } - return *this; -} - -template inline const _Tp& SparseMatConstIterator::value() const -{ return *(_Tp*)ptr; } - -inline const SparseMat::Node* SparseMatConstIterator::node() const -{ - return ptr && m && m->hdr ? - (const SparseMat::Node*)(ptr - m->hdr->valueOffset) : 0; -} - -inline SparseMatConstIterator SparseMatConstIterator::operator ++(int) -{ - SparseMatConstIterator it = *this; - ++*this; - return it; -} - - -inline void SparseMatConstIterator::seekEnd() -{ - if( m && m->hdr ) - { - hashidx = m->hdr->hashtab.size(); - ptr = 0; - } -} - -inline SparseMatIterator::SparseMatIterator() -{} - -inline SparseMatIterator::SparseMatIterator(SparseMat* _m) -: SparseMatConstIterator(_m) -{} - -inline SparseMatIterator::SparseMatIterator(const SparseMatIterator& it) -: SparseMatConstIterator(it) -{ -} - -inline SparseMatIterator& SparseMatIterator::operator = (const SparseMatIterator& it) -{ - (SparseMatConstIterator&)*this = it; - return *this; -} - -template inline _Tp& SparseMatIterator::value() const -{ return *(_Tp*)ptr; } - -inline SparseMat::Node* SparseMatIterator::node() const -{ - return (SparseMat::Node*)SparseMatConstIterator::node(); -} - -inline SparseMatIterator& SparseMatIterator::operator ++() -{ - SparseMatConstIterator::operator ++(); - return *this; -} - -inline SparseMatIterator SparseMatIterator::operator ++(int) -{ - SparseMatIterator it = *this; - ++*this; - return it; -} - - -template inline SparseMat_<_Tp>::SparseMat_() -{ flags = MAGIC_VAL | DataType<_Tp>::type; } - -template inline SparseMat_<_Tp>::SparseMat_(int _dims, const int* _sizes) -: SparseMat(_dims, _sizes, DataType<_Tp>::type) -{} - -template inline SparseMat_<_Tp>::SparseMat_(const SparseMat& m) -{ - if( m.type() == DataType<_Tp>::type ) - *this = (const SparseMat_<_Tp>&)m; - else - m.convertTo(this, DataType<_Tp>::type); -} - -template inline SparseMat_<_Tp>::SparseMat_(const SparseMat_<_Tp>& m) -{ - this->flags = m.flags; - this->hdr = m.hdr; - if( this->hdr ) - CV_XADD(&this->hdr->refcount, 1); -} - -template inline SparseMat_<_Tp>::SparseMat_(const Mat& m) -{ - SparseMat sm(m); - *this = sm; -} - -template inline SparseMat_<_Tp>::SparseMat_(const CvSparseMat* m) -{ - SparseMat sm(m); - *this = sm; -} - -template inline SparseMat_<_Tp>& -SparseMat_<_Tp>::operator = (const SparseMat_<_Tp>& m) -{ - if( this != &m ) - { - if( m.hdr ) CV_XADD(&m.hdr->refcount, 1); - release(); - flags = m.flags; - hdr = m.hdr; - } - return *this; -} - -template inline SparseMat_<_Tp>& -SparseMat_<_Tp>::operator = (const SparseMat& m) -{ - if( m.type() == DataType<_Tp>::type ) - return (*this = (const SparseMat_<_Tp>&)m); - m.convertTo(*this, DataType<_Tp>::type); - return *this; -} - -template inline SparseMat_<_Tp>& -SparseMat_<_Tp>::operator = (const Mat& m) -{ return (*this = SparseMat(m)); } - -template inline SparseMat_<_Tp> -SparseMat_<_Tp>::clone() const -{ - SparseMat_<_Tp> m; - this->copyTo(m); - return m; -} - -template inline void -SparseMat_<_Tp>::create(int _dims, const int* _sizes) -{ - SparseMat::create(_dims, _sizes, DataType<_Tp>::type); -} - -template inline -SparseMat_<_Tp>::operator CvSparseMat*() const -{ - return SparseMat::operator CvSparseMat*(); -} - -template inline int SparseMat_<_Tp>::type() const -{ return DataType<_Tp>::type; } - -template inline int SparseMat_<_Tp>::depth() const -{ return DataType<_Tp>::depth; } - -template inline int SparseMat_<_Tp>::channels() const -{ return DataType<_Tp>::channels; } - -template inline _Tp& -SparseMat_<_Tp>::ref(int i0, size_t* hashval) -{ return SparseMat::ref<_Tp>(i0, hashval); } - -template inline _Tp -SparseMat_<_Tp>::operator()(int i0, size_t* hashval) const -{ return SparseMat::value<_Tp>(i0, hashval); } - -template inline _Tp& -SparseMat_<_Tp>::ref(int i0, int i1, size_t* hashval) -{ return SparseMat::ref<_Tp>(i0, i1, hashval); } - -template inline _Tp -SparseMat_<_Tp>::operator()(int i0, int i1, size_t* hashval) const -{ return SparseMat::value<_Tp>(i0, i1, hashval); } - -template inline _Tp& -SparseMat_<_Tp>::ref(int i0, int i1, int i2, size_t* hashval) -{ return SparseMat::ref<_Tp>(i0, i1, i2, hashval); } - -template inline _Tp -SparseMat_<_Tp>::operator()(int i0, int i1, int i2, size_t* hashval) const -{ return SparseMat::value<_Tp>(i0, i1, i2, hashval); } - -template inline _Tp& -SparseMat_<_Tp>::ref(const int* idx, size_t* hashval) -{ return SparseMat::ref<_Tp>(idx, hashval); } - -template inline _Tp -SparseMat_<_Tp>::operator()(const int* idx, size_t* hashval) const -{ return SparseMat::value<_Tp>(idx, hashval); } - -template inline SparseMatIterator_<_Tp> SparseMat_<_Tp>::begin() -{ return SparseMatIterator_<_Tp>(this); } - -template inline SparseMatConstIterator_<_Tp> SparseMat_<_Tp>::begin() const -{ return SparseMatConstIterator_<_Tp>(this); } - -template inline SparseMatIterator_<_Tp> SparseMat_<_Tp>::end() -{ SparseMatIterator_<_Tp> it(this); it.seekEnd(); return it; } - -template inline SparseMatConstIterator_<_Tp> SparseMat_<_Tp>::end() const -{ SparseMatConstIterator_<_Tp> it(this); it.seekEnd(); return it; } - -template inline -SparseMatConstIterator_<_Tp>::SparseMatConstIterator_() -{} - -template inline -SparseMatConstIterator_<_Tp>::SparseMatConstIterator_(const SparseMat_<_Tp>* _m) -: SparseMatConstIterator(_m) -{} - -template inline -SparseMatConstIterator_<_Tp>::SparseMatConstIterator_(const SparseMatConstIterator_<_Tp>& it) -: SparseMatConstIterator(it) -{} - -template inline SparseMatConstIterator_<_Tp>& -SparseMatConstIterator_<_Tp>::operator = (const SparseMatConstIterator_<_Tp>& it) -{ return reinterpret_cast&> - (*reinterpret_cast(this) = - reinterpret_cast(it)); } - -template inline const _Tp& -SparseMatConstIterator_<_Tp>::operator *() const -{ return *(const _Tp*)this->ptr; } - -template inline SparseMatConstIterator_<_Tp>& -SparseMatConstIterator_<_Tp>::operator ++() -{ - SparseMatConstIterator::operator ++(); - return *this; -} - -template inline SparseMatConstIterator_<_Tp> -SparseMatConstIterator_<_Tp>::operator ++(int) -{ - SparseMatConstIterator it = *this; - SparseMatConstIterator::operator ++(); - return it; -} - -template inline -SparseMatIterator_<_Tp>::SparseMatIterator_() -{} - -template inline -SparseMatIterator_<_Tp>::SparseMatIterator_(SparseMat_<_Tp>* _m) -: SparseMatConstIterator_<_Tp>(_m) -{} - -template inline -SparseMatIterator_<_Tp>::SparseMatIterator_(const SparseMatIterator_<_Tp>& it) -: SparseMatConstIterator_<_Tp>(it) -{} - -template inline SparseMatIterator_<_Tp>& -SparseMatIterator_<_Tp>::operator = (const SparseMatIterator_<_Tp>& it) -{ return reinterpret_cast&> - (*reinterpret_cast(this) = - reinterpret_cast(it)); } - -template inline _Tp& -SparseMatIterator_<_Tp>::operator *() const -{ return *(_Tp*)this->ptr; } - -template inline SparseMatIterator_<_Tp>& -SparseMatIterator_<_Tp>::operator ++() -{ - SparseMatConstIterator::operator ++(); - return *this; -} - -template inline SparseMatIterator_<_Tp> -SparseMatIterator_<_Tp>::operator ++(int) -{ - SparseMatIterator it = *this; - SparseMatConstIterator::operator ++(); - return it; -} - -} - -#endif -#endif +#endif // __OPENCV_CORE_MAT_HPP__ diff --git a/modules/core/include/opencv2/core/mat.inl.hpp b/modules/core/include/opencv2/core/mat.inl.hpp new file mode 100644 index 0000000000..026ab695d5 --- /dev/null +++ b/modules/core/include/opencv2/core/mat.inl.hpp @@ -0,0 +1,2961 @@ +/*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_CORE_MATRIX_OPERATIONS_HPP__ +#define __OPENCV_CORE_MATRIX_OPERATIONS_HPP__ + +#ifndef __cplusplus +# error mat.inl.hpp header must be compiled as C++ +#endif + +namespace cv +{ + +//////////////////////// Input/Output Arrays //////////////////////// + +template inline +_InputArray::_InputArray(const std::vector<_Tp>& vec) + : flags(FIXED_TYPE + STD_VECTOR + DataType<_Tp>::type), obj((void*)&vec) +{} + +template inline +_InputArray::_InputArray(const std::vector >& vec) + : flags(FIXED_TYPE + STD_VECTOR_VECTOR + DataType<_Tp>::type), obj((void*)&vec) +{} + +template inline +_InputArray::_InputArray(const std::vector >& vec) + : flags(FIXED_TYPE + STD_VECTOR_MAT + DataType<_Tp>::type), obj((void*)&vec) +{} + +template inline +_InputArray::_InputArray(const Matx<_Tp, m, n>& mtx) + : flags(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type), obj((void*)&mtx), sz(n, m) +{} + +template inline +_InputArray::_InputArray(const _Tp* vec, int n) + : flags(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type), obj((void*)vec), sz(n, 1) +{} + +template inline +_InputArray::_InputArray(const Mat_<_Tp>& m) + : flags(FIXED_TYPE + MAT + DataType<_Tp>::type), obj((void*)&m) +{} + + +template inline +_OutputArray::_OutputArray(std::vector<_Tp>& vec) + : _InputArray(vec) +{} + +template inline +_OutputArray::_OutputArray(std::vector >& vec) + : _InputArray(vec) +{} + +template inline +_OutputArray::_OutputArray(std::vector >& vec) + : _InputArray(vec) +{} + +template inline +_OutputArray::_OutputArray(Mat_<_Tp>& m) + : _InputArray(m) +{} + +template inline +_OutputArray::_OutputArray(Matx<_Tp, m, n>& mtx) + : _InputArray(mtx) +{} + +template inline +_OutputArray::_OutputArray(_Tp* vec, int n) + : _InputArray(vec, n) +{} + +template inline +_OutputArray::_OutputArray(const std::vector<_Tp>& vec) + : _InputArray(vec) +{ + flags |= FIXED_SIZE; +} + +template inline +_OutputArray::_OutputArray(const std::vector >& vec) + : _InputArray(vec) +{ + flags |= FIXED_SIZE; +} + +template inline +_OutputArray::_OutputArray(const std::vector >& vec) + : _InputArray(vec) +{ + flags |= FIXED_SIZE; +} + +template inline +_OutputArray::_OutputArray(const Mat_<_Tp>& m) + : _InputArray(m) +{ + flags |= FIXED_SIZE; +} + +template inline +_OutputArray::_OutputArray(const Matx<_Tp, m, n>& mtx) + : _InputArray(mtx) +{} + +template inline +_OutputArray::_OutputArray(const _Tp* vec, int n) + : _InputArray(vec, n) +{} + + + +//////////////////////////////// Mat //////////////////////////////// + +inline +Mat::Mat() + : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), refcount(0), datastart(0), dataend(0), + datalimit(0), allocator(0), size(&rows) +{} + +inline +Mat::Mat(int _rows, int _cols, int _type) + : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), refcount(0), datastart(0), dataend(0), + datalimit(0), allocator(0), size(&rows) +{ + create(_rows, _cols, _type); +} + +inline +Mat::Mat(int _rows, int _cols, int _type, const Scalar& _s) + : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), refcount(0), datastart(0), dataend(0), + datalimit(0), allocator(0), size(&rows) +{ + create(_rows, _cols, _type); + *this = _s; +} + +inline +Mat::Mat(Size _sz, int _type) + : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), refcount(0), datastart(0), dataend(0), + datalimit(0), allocator(0), size(&rows) +{ + create( _sz.height, _sz.width, _type ); +} + +inline +Mat::Mat(Size _sz, int _type, const Scalar& _s) + : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), refcount(0), datastart(0), dataend(0), + datalimit(0), allocator(0), size(&rows) +{ + create(_sz.height, _sz.width, _type); + *this = _s; +} + +inline +Mat::Mat(int _dims, const int* _sz, int _type) + : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), refcount(0), datastart(0), dataend(0), + datalimit(0), allocator(0), size(&rows) +{ + create(_dims, _sz, _type); +} + +inline +Mat::Mat(int _dims, const int* _sz, int _type, const Scalar& _s) + : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), refcount(0), datastart(0), dataend(0), + datalimit(0), allocator(0), size(&rows) +{ + create(_dims, _sz, _type); + *this = _s; +} + +inline +Mat::Mat(const Mat& m) + : flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), data(m.data), refcount(m.refcount), + datastart(m.datastart), dataend(m.dataend), datalimit(m.datalimit), allocator(m.allocator), + size(&rows) +{ + if( refcount ) + CV_XADD(refcount, 1); + if( m.dims <= 2 ) + { + step[0] = m.step[0]; step[1] = m.step[1]; + } + else + { + dims = 0; + copySize(m); + } +} + +inline +Mat::Mat(int _rows, int _cols, int _type, void* _data, size_t _step) + : flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_rows), cols(_cols), + data((uchar*)_data), refcount(0), datastart((uchar*)_data), dataend(0), datalimit(0), + allocator(0), size(&rows) +{ + size_t esz = CV_ELEM_SIZE(_type); + size_t minstep = cols * esz; + if( _step == AUTO_STEP ) + { + _step = minstep; + flags |= CONTINUOUS_FLAG; + } + else + { + if( rows == 1 ) _step = minstep; + CV_DbgAssert( _step >= minstep ); + flags |= _step == minstep ? CONTINUOUS_FLAG : 0; + } + step[0] = _step; + step[1] = esz; + datalimit = datastart + _step * rows; + dataend = datalimit - _step + minstep; +} + +inline +Mat::Mat(Size _sz, int _type, void* _data, size_t _step) + : flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_sz.height), cols(_sz.width), + data((uchar*)_data), refcount(0), datastart((uchar*)_data), dataend(0), datalimit(0), + allocator(0), size(&rows) +{ + size_t esz = CV_ELEM_SIZE(_type); + size_t minstep = cols*esz; + if( _step == AUTO_STEP ) + { + _step = minstep; + flags |= CONTINUOUS_FLAG; + } + else + { + if( rows == 1 ) _step = minstep; + CV_DbgAssert( _step >= minstep ); + flags |= _step == minstep ? CONTINUOUS_FLAG : 0; + } + step[0] = _step; + step[1] = esz; + datalimit = datastart + _step*rows; + dataend = datalimit - _step + minstep; +} + +template inline +Mat::Mat(const std::vector<_Tp>& vec, bool copyData) + : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows((int)vec.size()), + cols(1), data(0), refcount(0), datastart(0), dataend(0), allocator(0), size(&rows) +{ + if(vec.empty()) + return; + if( !copyData ) + { + step[0] = step[1] = sizeof(_Tp); + data = datastart = (uchar*)&vec[0]; + datalimit = dataend = datastart + rows * step[0]; + } + else + Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this); +} + +template inline +Mat::Mat(const Vec<_Tp, n>& vec, bool copyData) + : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows(n), cols(1), data(0), + refcount(0), datastart(0), dataend(0), allocator(0), size(&rows) +{ + if( !copyData ) + { + step[0] = step[1] = sizeof(_Tp); + data = datastart = (uchar*)vec.val; + datalimit = dataend = datastart + rows * step[0]; + } + else + Mat(n, 1, DataType<_Tp>::type, (void*)vec.val).copyTo(*this); +} + + +template inline +Mat::Mat(const Matx<_Tp,m,n>& M, bool copyData) + : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows(m), cols(n), data(0), + refcount(0), datastart(0), dataend(0), allocator(0), size(&rows) +{ + if( !copyData ) + { + step[0] = cols * sizeof(_Tp); + step[1] = sizeof(_Tp); + data = datastart = (uchar*)M.val; + datalimit = dataend = datastart + rows * step[0]; + } + else + Mat(m, n, DataType<_Tp>::type, (uchar*)M.val).copyTo(*this); +} + +template inline +Mat::Mat(const Point_<_Tp>& pt, bool copyData) + : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows(2), cols(1), data(0), + refcount(0), datastart(0), dataend(0), allocator(0), size(&rows) +{ + if( !copyData ) + { + step[0] = step[1] = sizeof(_Tp); + data = datastart = (uchar*)&pt.x; + datalimit = dataend = datastart + rows * step[0]; + } + else + { + create(2, 1, DataType<_Tp>::type); + ((_Tp*)data)[0] = pt.x; + ((_Tp*)data)[1] = pt.y; + } +} + +template inline +Mat::Mat(const Point3_<_Tp>& pt, bool copyData) + : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows(3), cols(1), data(0), + refcount(0), datastart(0), dataend(0), allocator(0), size(&rows) +{ + if( !copyData ) + { + step[0] = step[1] = sizeof(_Tp); + data = datastart = (uchar*)&pt.x; + datalimit = dataend = datastart + rows * step[0]; + } + else + { + create(3, 1, DataType<_Tp>::type); + ((_Tp*)data)[0] = pt.x; + ((_Tp*)data)[1] = pt.y; + ((_Tp*)data)[2] = pt.z; + } +} + +template inline +Mat::Mat(const MatCommaInitializer_<_Tp>& commaInitializer) + : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(0), rows(0), cols(0), data(0), + refcount(0), datastart(0), dataend(0), allocator(0), size(&rows) +{ + *this = commaInitializer.operator Mat_<_Tp>(); +} + +inline +Mat::~Mat() +{ + release(); + if( step.p != step.buf ) + fastFree(step.p); +} + +inline +Mat& Mat::operator = (const Mat& m) +{ + if( this != &m ) + { + if( m.refcount ) + CV_XADD(m.refcount, 1); + release(); + flags = m.flags; + if( dims <= 2 && m.dims <= 2 ) + { + dims = m.dims; + rows = m.rows; + cols = m.cols; + step[0] = m.step[0]; + step[1] = m.step[1]; + } + else + copySize(m); + data = m.data; + datastart = m.datastart; + dataend = m.dataend; + datalimit = m.datalimit; + refcount = m.refcount; + allocator = m.allocator; + } + return *this; +} + +inline +Mat Mat::row(int y) const +{ + return Mat(*this, Range(y, y + 1), Range::all()); +} + +inline +Mat Mat::col(int x) const +{ + return Mat(*this, Range::all(), Range(x, x + 1)); +} + +inline +Mat Mat::rowRange(int startrow, int endrow) const +{ + return Mat(*this, Range(startrow, endrow), Range::all()); +} + +inline +Mat Mat::rowRange(const Range& r) const +{ + return Mat(*this, r, Range::all()); +} + +inline +Mat Mat::colRange(int startcol, int endcol) const +{ + return Mat(*this, Range::all(), Range(startcol, endcol)); +} + +inline +Mat Mat::colRange(const Range& r) const +{ + return Mat(*this, Range::all(), r); +} + +inline +Mat Mat::clone() const +{ + Mat m; + copyTo(m); + return m; +} + +inline +void Mat::assignTo( Mat& m, int _type ) const +{ + if( _type < 0 ) + m = *this; + else + convertTo(m, _type); +} + +inline +void Mat::create(int _rows, int _cols, int _type) +{ + _type &= TYPE_MASK; + if( dims <= 2 && rows == _rows && cols == _cols && type() == _type && data ) + return; + int sz[] = {_rows, _cols}; + create(2, sz, _type); +} + +inline +void Mat::create(Size _sz, int _type) +{ + create(_sz.height, _sz.width, _type); +} + +inline +void Mat::addref() +{ + if( refcount ) + CV_XADD(refcount, 1); +} + +inline void Mat::release() +{ + if( refcount && CV_XADD(refcount, -1) == 1 ) + deallocate(); + data = datastart = dataend = datalimit = 0; + size.p[0] = 0; + refcount = 0; +} + +inline +Mat Mat::operator()( Range _rowRange, Range _colRange ) const +{ + return Mat(*this, _rowRange, _colRange); +} + +inline +Mat Mat::operator()( const Rect& roi ) const +{ + return Mat(*this, roi); +} + +inline +Mat Mat::operator()(const Range* ranges) const +{ + return Mat(*this, ranges); +} + +inline +bool Mat::isContinuous() const +{ + return (flags & CONTINUOUS_FLAG) != 0; +} + +inline +bool Mat::isSubmatrix() const +{ + return (flags & SUBMATRIX_FLAG) != 0; +} + +inline +size_t Mat::elemSize() const +{ + return dims > 0 ? step.p[dims - 1] : 0; +} + +inline +size_t Mat::elemSize1() const +{ + return CV_ELEM_SIZE1(flags); +} + +inline +int Mat::type() const +{ + return CV_MAT_TYPE(flags); +} + +inline +int Mat::depth() const +{ + return CV_MAT_DEPTH(flags); +} + +inline +int Mat::channels() const +{ + return CV_MAT_CN(flags); +} + +inline +size_t Mat::step1(int i) const +{ + return step.p[i] / elemSize1(); +} + +inline +bool Mat::empty() const +{ + return data == 0 || total() == 0; +} + +inline +size_t Mat::total() const +{ + if( dims <= 2 ) + return (size_t)rows * cols; + size_t p = 1; + for( int i = 0; i < dims; i++ ) + p *= size[i]; + return p; +} + +inline +uchar* Mat::ptr(int y) +{ + CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) ); + return data + step.p[0] * y; +} + +inline +const uchar* Mat::ptr(int y) const +{ + CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) ); + return data + step.p[0] * y; +} + +template inline +_Tp* Mat::ptr(int y) +{ + CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) ); + return (_Tp*)(data + step.p[0] * y); +} + +template inline +const _Tp* Mat::ptr(int y) const +{ + CV_DbgAssert( y == 0 || (data && dims >= 1 && data && (unsigned)y < (unsigned)size.p[0]) ); + return (const _Tp*)(data + step.p[0] * y); +} + +inline +uchar* Mat::ptr(int i0, int i1) +{ + CV_DbgAssert( dims >= 2 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] ); + return data + i0 * step.p[0] + i1 * step.p[1]; +} + +inline +const uchar* Mat::ptr(int i0, int i1) const +{ + CV_DbgAssert( dims >= 2 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] ); + return data + i0 * step.p[0] + i1 * step.p[1]; +} + +template inline +_Tp* Mat::ptr(int i0, int i1) +{ + CV_DbgAssert( dims >= 2 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] ); + return (_Tp*)(data + i0 * step.p[0] + i1 * step.p[1]); +} + +template inline +const _Tp* Mat::ptr(int i0, int i1) const +{ + CV_DbgAssert( dims >= 2 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] ); + return (const _Tp*)(data + i0 * step.p[0] + i1 * step.p[1]); +} + +inline +uchar* Mat::ptr(int i0, int i1, int i2) +{ + CV_DbgAssert( dims >= 3 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] && + (unsigned)i2 < (unsigned)size.p[2] ); + return data + i0 * step.p[0] + i1 * step.p[1] + i2 * step.p[2]; +} + +inline +const uchar* Mat::ptr(int i0, int i1, int i2) const +{ + CV_DbgAssert( dims >= 3 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] && + (unsigned)i2 < (unsigned)size.p[2] ); + return data + i0 * step.p[0] + i1 * step.p[1] + i2 * step.p[2]; +} + +template inline +_Tp* Mat::ptr(int i0, int i1, int i2) +{ + CV_DbgAssert( dims >= 3 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] && + (unsigned)i2 < (unsigned)size.p[2] ); + return (_Tp*)(data + i0 * step.p[0] + i1 * step.p[1] + i2 * step.p[2]); +} + +template inline +const _Tp* Mat::ptr(int i0, int i1, int i2) const +{ + CV_DbgAssert( dims >= 3 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] && + (unsigned)i2 < (unsigned)size.p[2] ); + return (const _Tp*)(data + i0 * step.p[0] + i1 * step.p[1] + i2 * step.p[2]); +} + +inline +uchar* Mat::ptr(const int* idx) +{ + int i, d = dims; + uchar* p = data; + CV_DbgAssert( d >= 1 && p ); + for( i = 0; i < d; i++ ) + { + CV_DbgAssert( (unsigned)idx[i] < (unsigned)size.p[i] ); + p += idx[i] * step.p[i]; + } + return p; +} + +inline +const uchar* Mat::ptr(const int* idx) const +{ + int i, d = dims; + uchar* p = data; + CV_DbgAssert( d >= 1 && p ); + for( i = 0; i < d; i++ ) + { + CV_DbgAssert( (unsigned)idx[i] < (unsigned)size.p[i] ); + p += idx[i] * step.p[i]; + } + return p; +} + +template inline +_Tp& Mat::at(int i0, int i1) +{ + CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()) && + CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); + return ((_Tp*)(data + step.p[0] * i0))[i1]; +} + +template inline +const _Tp& Mat::at(int i0, int i1) const +{ + CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()) && + CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); + return ((const _Tp*)(data + step.p[0] * i0))[i1]; +} + +template inline +_Tp& Mat::at(Point pt) +{ + CV_DbgAssert( dims <= 2 && data && (unsigned)pt.y < (unsigned)size.p[0] && + (unsigned)(pt.x * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()) && + CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); + return ((_Tp*)(data + step.p[0] * pt.y))[pt.x]; +} + +template inline +const _Tp& Mat::at(Point pt) const +{ + CV_DbgAssert( dims <= 2 && data && (unsigned)pt.y < (unsigned)size.p[0] && + (unsigned)(pt.x * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()) && + CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); + return ((const _Tp*)(data + step.p[0] * pt.y))[pt.x]; +} + +template inline +_Tp& Mat::at(int i0) +{ + CV_DbgAssert( dims <= 2 && data && + (unsigned)i0 < (unsigned)(size.p[0] * size.p[1]) && + elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); + if( isContinuous() || size.p[0] == 1 ) + return ((_Tp*)data)[i0]; + if( size.p[1] == 1 ) + return *(_Tp*)(data + step.p[0] * i0); + int i = i0 / cols, j = i0 - i * cols; + return ((_Tp*)(data + step.p[0] * i))[j]; +} + +template inline +const _Tp& Mat::at(int i0) const +{ + CV_DbgAssert( dims <= 2 && data && + (unsigned)i0 < (unsigned)(size.p[0] * size.p[1]) && + elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); + if( isContinuous() || size.p[0] == 1 ) + return ((const _Tp*)data)[i0]; + if( size.p[1] == 1 ) + return *(const _Tp*)(data + step.p[0] * i0); + int i = i0 / cols, j = i0 - i * cols; + return ((const _Tp*)(data + step.p[0] * i))[j]; +} + +template inline +_Tp& Mat::at(int i0, int i1, int i2) +{ + CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); + return *(_Tp*)ptr(i0, i1, i2); +} + +template inline +const _Tp& Mat::at(int i0, int i1, int i2) const +{ + CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); + return *(const _Tp*)ptr(i0, i1, i2); +} + +template inline +_Tp& Mat::at(const int* idx) +{ + CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); + return *(_Tp*)ptr(idx); +} + +template inline +const _Tp& Mat::at(const int* idx) const +{ + CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); + return *(const _Tp*)ptr(idx); +} + +template inline +_Tp& Mat::at(const Vec& idx) +{ + CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); + return *(_Tp*)ptr(idx.val); +} + +template inline +const _Tp& Mat::at(const Vec& idx) const +{ + CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); + return *(const _Tp*)ptr(idx.val); +} + +template inline +MatConstIterator_<_Tp> Mat::begin() const +{ + CV_DbgAssert( elemSize() == sizeof(_Tp) ); + return MatConstIterator_<_Tp>((const Mat_<_Tp>*)this); +} + +template inline +MatConstIterator_<_Tp> Mat::end() const +{ + CV_DbgAssert( elemSize() == sizeof(_Tp) ); + MatConstIterator_<_Tp> it((const Mat_<_Tp>*)this); + it += total(); + return it; +} + +template inline +MatIterator_<_Tp> Mat::begin() +{ + CV_DbgAssert( elemSize() == sizeof(_Tp) ); + return MatIterator_<_Tp>((Mat_<_Tp>*)this); +} + +template inline +MatIterator_<_Tp> Mat::end() +{ + CV_DbgAssert( elemSize() == sizeof(_Tp) ); + MatIterator_<_Tp> it((Mat_<_Tp>*)this); + it += total(); + return it; +} + +template inline +Mat::operator std::vector<_Tp>() const +{ + std::vector<_Tp> v; + copyTo(v); + return v; +} + +template inline +Mat::operator Vec<_Tp, n>() const +{ + CV_Assert( data && dims <= 2 && (rows == 1 || cols == 1) && + rows + cols - 1 == n && channels() == 1 ); + + if( isContinuous() && type() == DataType<_Tp>::type ) + return Vec<_Tp, n>((_Tp*)data); + Vec<_Tp, n> v; + Mat tmp(rows, cols, DataType<_Tp>::type, v.val); + convertTo(tmp, tmp.type()); + return v; +} + +template inline +Mat::operator Matx<_Tp, m, n>() const +{ + CV_Assert( data && dims <= 2 && rows == m && cols == n && channels() == 1 ); + + if( isContinuous() && type() == DataType<_Tp>::type ) + return Matx<_Tp, m, n>((_Tp*)data); + Matx<_Tp, m, n> mtx; + Mat tmp(rows, cols, DataType<_Tp>::type, mtx.val); + convertTo(tmp, tmp.type()); + return mtx; +} + +template inline +void Mat::push_back(const _Tp& elem) +{ + if( !data ) + { + *this = Mat(1, 1, DataType<_Tp>::type, (void*)&elem).clone(); + return; + } + CV_Assert(DataType<_Tp>::type == type() && cols == 1 + /* && dims == 2 (cols == 1 implies dims == 2) */); + uchar* tmp = dataend + step[0]; + if( !isSubmatrix() && isContinuous() && tmp <= datalimit ) + { + *(_Tp*)(data + (size.p[0]++) * step.p[0]) = elem; + dataend = tmp; + } + else + push_back_(&elem); +} + +template inline +void Mat::push_back(const Mat_<_Tp>& m) +{ + push_back((const Mat&)m); +} + + + +///////////////////////////// Mat::MSize //////////////////////////// + +inline +Mat::MSize::MSize(int* _p) + : p(_p) {} + +inline +Size Mat::MSize::operator()() const +{ + CV_DbgAssert(p[-1] <= 2); + return Size(p[1], p[0]); +} + +inline +const int& Mat::MSize::operator[](int i) const +{ + return p[i]; +} + +inline +int& Mat::MSize::operator[](int i) +{ + return p[i]; +} + +inline +Mat::MSize::operator const int*() const +{ + return p; +} + +inline +bool Mat::MSize::operator == (const MSize& sz) const +{ + int d = p[-1]; + int dsz = sz.p[-1]; + if( d != dsz ) + return false; + if( d == 2 ) + return p[0] == sz.p[0] && p[1] == sz.p[1]; + + for( int i = 0; i < d; i++ ) + if( p[i] != sz.p[i] ) + return false; + return true; +} + +inline +bool Mat::MSize::operator != (const MSize& sz) const +{ + return !(*this == sz); +} + + + +///////////////////////////// Mat::MStep //////////////////////////// + +inline +Mat::MStep::MStep() +{ + p = buf; p[0] = p[1] = 0; +} + +inline +Mat::MStep::MStep(size_t s) +{ + p = buf; p[0] = s; p[1] = 0; +} + +inline +const size_t& Mat::MStep::operator[](int i) const +{ + return p[i]; +} + +inline +size_t& Mat::MStep::operator[](int i) +{ + return p[i]; +} + +inline Mat::MStep::operator size_t() const +{ + CV_DbgAssert( p == buf ); + return buf[0]; +} + +inline Mat::MStep& Mat::MStep::operator = (size_t s) +{ + CV_DbgAssert( p == buf ); + buf[0] = s; + return *this; +} + + + +////////////////////////////// Mat_<_Tp> //////////////////////////// + +template inline +Mat_<_Tp>::Mat_() + : Mat() +{ + flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; +} + +template inline +Mat_<_Tp>::Mat_(int _rows, int _cols) + : Mat(_rows, _cols, DataType<_Tp>::type) +{ +} + +template inline +Mat_<_Tp>::Mat_(int _rows, int _cols, const _Tp& value) + : Mat(_rows, _cols, DataType<_Tp>::type) +{ + *this = value; +} + +template inline +Mat_<_Tp>::Mat_(Size _sz) + : Mat(_sz.height, _sz.width, DataType<_Tp>::type) +{} + +template inline +Mat_<_Tp>::Mat_(Size _sz, const _Tp& value) + : Mat(_sz.height, _sz.width, DataType<_Tp>::type) +{ + *this = value; +} + +template inline +Mat_<_Tp>::Mat_(int _dims, const int* _sz) + : Mat(_dims, _sz, DataType<_Tp>::type) +{} + +template inline +Mat_<_Tp>::Mat_(int _dims, const int* _sz, const _Tp& _s) + : Mat(_dims, _sz, DataType<_Tp>::type, Scalar(_s)) +{} + +template inline +Mat_<_Tp>::Mat_(const Mat_<_Tp>& m, const Range* ranges) + : Mat(m, ranges) +{} + +template inline +Mat_<_Tp>::Mat_(const Mat& m) + : Mat() +{ + flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; + *this = m; +} + +template inline +Mat_<_Tp>::Mat_(const Mat_& m) + : Mat(m) +{} + +template inline +Mat_<_Tp>::Mat_(int _rows, int _cols, _Tp* _data, size_t steps) + : Mat(_rows, _cols, DataType<_Tp>::type, _data, steps) +{} + +template inline +Mat_<_Tp>::Mat_(const Mat_& m, const Range& _rowRange, const Range& _colRange) + : Mat(m, _rowRange, _colRange) +{} + +template inline +Mat_<_Tp>::Mat_(const Mat_& m, const Rect& roi) + : Mat(m, roi) +{} + +template template inline +Mat_<_Tp>::Mat_(const Vec::channel_type, n>& vec, bool copyData) + : Mat(n / DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&vec) +{ + CV_Assert(n%DataType<_Tp>::channels == 0); + if( copyData ) + *this = clone(); +} + +template template inline +Mat_<_Tp>::Mat_(const Matx::channel_type, m, n>& M, bool copyData) + : Mat(m, n / DataType<_Tp>::channels, DataType<_Tp>::type, (void*)&M) +{ + CV_Assert(n % DataType<_Tp>::channels == 0); + if( copyData ) + *this = clone(); +} + +template inline +Mat_<_Tp>::Mat_(const Point_::channel_type>& pt, bool copyData) + : Mat(2 / DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&pt) +{ + CV_Assert(2 % DataType<_Tp>::channels == 0); + if( copyData ) + *this = clone(); +} + +template inline +Mat_<_Tp>::Mat_(const Point3_::channel_type>& pt, bool copyData) + : Mat(3 / DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&pt) +{ + CV_Assert(3 % DataType<_Tp>::channels == 0); + if( copyData ) + *this = clone(); +} + +template inline +Mat_<_Tp>::Mat_(const MatCommaInitializer_<_Tp>& commaInitializer) + : Mat(commaInitializer) +{} + +template inline +Mat_<_Tp>::Mat_(const std::vector<_Tp>& vec, bool copyData) + : Mat(vec, copyData) +{} + +template inline +Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat& m) +{ + if( DataType<_Tp>::type == m.type() ) + { + Mat::operator = (m); + return *this; + } + if( DataType<_Tp>::depth == m.depth() ) + { + return (*this = m.reshape(DataType<_Tp>::channels, m.dims, 0)); + } + CV_DbgAssert(DataType<_Tp>::channels == m.channels()); + m.convertTo(*this, type()); + return *this; +} + +template inline +Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat_& m) +{ + Mat::operator=(m); + return *this; +} + +template inline +Mat_<_Tp>& Mat_<_Tp>::operator = (const _Tp& s) +{ + typedef typename DataType<_Tp>::vec_type VT; + Mat::operator=(Scalar((const VT&)s)); + return *this; +} + +template inline +void Mat_<_Tp>::create(int _rows, int _cols) +{ + Mat::create(_rows, _cols, DataType<_Tp>::type); +} + +template inline +void Mat_<_Tp>::create(Size _sz) +{ + Mat::create(_sz, DataType<_Tp>::type); +} + +template inline +void Mat_<_Tp>::create(int _dims, const int* _sz) +{ + Mat::create(_dims, _sz, DataType<_Tp>::type); +} + +template inline +Mat_<_Tp> Mat_<_Tp>::cross(const Mat_& m) const +{ + return Mat_<_Tp>(Mat::cross(m)); +} + +template template inline +Mat_<_Tp>::operator Mat_() const +{ + return Mat_(*this); +} + +template inline +Mat_<_Tp> Mat_<_Tp>::row(int y) const +{ + return Mat_(*this, Range(y, y+1), Range::all()); +} + +template inline +Mat_<_Tp> Mat_<_Tp>::col(int x) const +{ + return Mat_(*this, Range::all(), Range(x, x+1)); +} + +template inline +Mat_<_Tp> Mat_<_Tp>::diag(int d) const +{ + return Mat_(Mat::diag(d)); +} + +template inline +Mat_<_Tp> Mat_<_Tp>::clone() const +{ + return Mat_(Mat::clone()); +} + +template inline +size_t Mat_<_Tp>::elemSize() const +{ + CV_DbgAssert( Mat::elemSize() == sizeof(_Tp) ); + return sizeof(_Tp); +} + +template inline +size_t Mat_<_Tp>::elemSize1() const +{ + CV_DbgAssert( Mat::elemSize1() == sizeof(_Tp) / DataType<_Tp>::channels ); + return sizeof(_Tp) / DataType<_Tp>::channels; +} + +template inline +int Mat_<_Tp>::type() const +{ + CV_DbgAssert( Mat::type() == DataType<_Tp>::type ); + return DataType<_Tp>::type; +} + +template inline +int Mat_<_Tp>::depth() const +{ + CV_DbgAssert( Mat::depth() == DataType<_Tp>::depth ); + return DataType<_Tp>::depth; +} + +template inline +int Mat_<_Tp>::channels() const +{ + CV_DbgAssert( Mat::channels() == DataType<_Tp>::channels ); + return DataType<_Tp>::channels; +} + +template inline +size_t Mat_<_Tp>::stepT(int i) const +{ + return step.p[i] / elemSize(); +} + +template inline +size_t Mat_<_Tp>::step1(int i) const +{ + return step.p[i] / elemSize1(); +} + +template inline +Mat_<_Tp>& Mat_<_Tp>::adjustROI( int dtop, int dbottom, int dleft, int dright ) +{ + return (Mat_<_Tp>&)(Mat::adjustROI(dtop, dbottom, dleft, dright)); +} + +template inline +Mat_<_Tp> Mat_<_Tp>::operator()( const Range& _rowRange, const Range& _colRange ) const +{ + return Mat_<_Tp>(*this, _rowRange, _colRange); +} + +template inline +Mat_<_Tp> Mat_<_Tp>::operator()( const Rect& roi ) const +{ + return Mat_<_Tp>(*this, roi); +} + +template inline +Mat_<_Tp> Mat_<_Tp>::operator()( const Range* ranges ) const +{ + return Mat_<_Tp>(*this, ranges); +} + +template inline +_Tp* Mat_<_Tp>::operator [](int y) +{ + return (_Tp*)ptr(y); +} + +template inline +const _Tp* Mat_<_Tp>::operator [](int y) const +{ + return (const _Tp*)ptr(y); +} + +template inline +_Tp& Mat_<_Tp>::operator ()(int i0, int i1) +{ + CV_DbgAssert( dims <= 2 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] && + type() == DataType<_Tp>::type ); + return ((_Tp*)(data + step.p[0] * i0))[i1]; +} + +template inline +const _Tp& Mat_<_Tp>::operator ()(int i0, int i1) const +{ + CV_DbgAssert( dims <= 2 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] && + type() == DataType<_Tp>::type ); + return ((const _Tp*)(data + step.p[0] * i0))[i1]; +} + +template inline +_Tp& Mat_<_Tp>::operator ()(Point pt) +{ + CV_DbgAssert( dims <= 2 && data && + (unsigned)pt.y < (unsigned)size.p[0] && + (unsigned)pt.x < (unsigned)size.p[1] && + type() == DataType<_Tp>::type ); + return ((_Tp*)(data + step.p[0] * pt.y))[pt.x]; +} + +template inline +const _Tp& Mat_<_Tp>::operator ()(Point pt) const +{ + CV_DbgAssert( dims <= 2 && data && + (unsigned)pt.y < (unsigned)size.p[0] && + (unsigned)pt.x < (unsigned)size.p[1] && + type() == DataType<_Tp>::type ); + return ((const _Tp*)(data + step.p[0] * pt.y))[pt.x]; +} + +template inline +_Tp& Mat_<_Tp>::operator ()(const int* idx) +{ + return Mat::at<_Tp>(idx); +} + +template inline +const _Tp& Mat_<_Tp>::operator ()(const int* idx) const +{ + return Mat::at<_Tp>(idx); +} + +template template inline +_Tp& Mat_<_Tp>::operator ()(const Vec& idx) +{ + return Mat::at<_Tp>(idx); +} + +template template inline +const _Tp& Mat_<_Tp>::operator ()(const Vec& idx) const +{ + return Mat::at<_Tp>(idx); +} + +template inline +_Tp& Mat_<_Tp>::operator ()(int i0) +{ + return this->at<_Tp>(i0); +} + +template inline +const _Tp& Mat_<_Tp>::operator ()(int i0) const +{ + return this->at<_Tp>(i0); +} + +template inline +_Tp& Mat_<_Tp>::operator ()(int i0, int i1, int i2) +{ + return this->at<_Tp>(i0, i1, i2); +} + +template inline +const _Tp& Mat_<_Tp>::operator ()(int i0, int i1, int i2) const +{ + return this->at<_Tp>(i0, i1, i2); +} + +template inline +Mat_<_Tp>::operator std::vector<_Tp>() const +{ + std::vector<_Tp> v; + copyTo(v); + return v; +} + +template template inline +Mat_<_Tp>::operator Vec::channel_type, n>() const +{ + CV_Assert(n % DataType<_Tp>::channels == 0); + return this->Mat::operator Vec::channel_type, n>(); +} + +template template inline +Mat_<_Tp>::operator Matx::channel_type, m, n>() const +{ + CV_Assert(n % DataType<_Tp>::channels == 0); + return this->Mat::operator Matx::channel_type, m, n>(); +} + +template inline +MatConstIterator_<_Tp> Mat_<_Tp>::begin() const +{ + return Mat::begin<_Tp>(); +} + +template inline +MatConstIterator_<_Tp> Mat_<_Tp>::end() const +{ + return Mat::end<_Tp>(); +} + +template inline +MatIterator_<_Tp> Mat_<_Tp>::begin() +{ + return Mat::begin<_Tp>(); +} + +template inline +MatIterator_<_Tp> Mat_<_Tp>::end() +{ + return Mat::end<_Tp>(); +} + + +/*template inline +void process( const Mat_& m1, Mat_& m2, Op op ) +{ + int y, x, rows = m1.rows, cols = m1.cols; + + CV_DbgAssert( m1.size() == m2.size() ); + + for( y = 0; y < rows; y++ ) + { + const T1* src = m1[y]; + T2* dst = m2[y]; + + for( x = 0; x < cols; x++ ) + dst[x] = op(src[x]); + } +} + +template inline +void process( const Mat_& m1, const Mat_& m2, Mat_& m3, Op op ) +{ + int y, x, rows = m1.rows, cols = m1.cols; + + CV_DbgAssert( m1.size() == m2.size() ); + + for( y = 0; y < rows; y++ ) + { + const T1* src1 = m1[y]; + const T2* src2 = m2[y]; + T3* dst = m3[y]; + + for( x = 0; x < cols; x++ ) + dst[x] = op( src1[x], src2[x] ); + } +}*/ + + + +///////////////////////////// SparseMat ///////////////////////////// + +inline +SparseMat::SparseMat() + : flags(MAGIC_VAL), hdr(0) +{} + +inline +SparseMat::SparseMat(int _dims, const int* _sizes, int _type) + : flags(MAGIC_VAL), hdr(0) +{ + create(_dims, _sizes, _type); +} + +inline +SparseMat::SparseMat(const SparseMat& m) + : flags(m.flags), hdr(m.hdr) +{ + addref(); +} + +inline +SparseMat::~SparseMat() +{ + release(); +} + +inline +SparseMat& SparseMat::operator = (const SparseMat& m) +{ + if( this != &m ) + { + if( m.hdr ) + CV_XADD(&m.hdr->refcount, 1); + release(); + flags = m.flags; + hdr = m.hdr; + } + return *this; +} + +inline +SparseMat& SparseMat::operator = (const Mat& m) +{ + return (*this = SparseMat(m)); +} + +inline +SparseMat SparseMat::clone() const +{ + SparseMat temp; + this->copyTo(temp); + return temp; +} + +inline +void SparseMat::assignTo( SparseMat& m, int _type ) const +{ + if( _type < 0 ) + m = *this; + else + convertTo(m, _type); +} + +inline +void SparseMat::addref() +{ + if( hdr ) + CV_XADD(&hdr->refcount, 1); +} + +inline +void SparseMat::release() +{ + if( hdr && CV_XADD(&hdr->refcount, -1) == 1 ) + delete hdr; + hdr = 0; +} + +inline +size_t SparseMat::elemSize() const +{ + return CV_ELEM_SIZE(flags); +} + +inline +size_t SparseMat::elemSize1() const +{ + return CV_ELEM_SIZE1(flags); +} + +inline +int SparseMat::type() const +{ + return CV_MAT_TYPE(flags); +} + +inline +int SparseMat::depth() const +{ + return CV_MAT_DEPTH(flags); +} + +inline +int SparseMat::channels() const +{ + return CV_MAT_CN(flags); +} + +inline +const int* SparseMat::size() const +{ + return hdr ? hdr->size : 0; +} + +inline +int SparseMat::size(int i) const +{ + if( hdr ) + { + CV_DbgAssert((unsigned)i < (unsigned)hdr->dims); + return hdr->size[i]; + } + return 0; +} + +inline +int SparseMat::dims() const +{ + return hdr ? hdr->dims : 0; +} + +inline +size_t SparseMat::nzcount() const +{ + return hdr ? hdr->nodeCount : 0; +} + +inline +size_t SparseMat::hash(int i0) const +{ + return (size_t)i0; +} + +inline +size_t SparseMat::hash(int i0, int i1) const +{ + return (size_t)(unsigned)i0 * HASH_SCALE + (unsigned)i1; +} + +inline +size_t SparseMat::hash(int i0, int i1, int i2) const +{ + return ((size_t)(unsigned)i0 * HASH_SCALE + (unsigned)i1) * HASH_SCALE + (unsigned)i2; +} + +inline +size_t SparseMat::hash(const int* idx) const +{ + size_t h = (unsigned)idx[0]; + if( !hdr ) + return 0; + int d = hdr->dims; + for(int i = 1; i < d; i++ ) + h = h * HASH_SCALE + (unsigned)idx[i]; + return h; +} + +template inline +_Tp& SparseMat::ref(int i0, size_t* hashval) +{ + return *(_Tp*)((SparseMat*)this)->ptr(i0, true, hashval); +} + +template inline +_Tp& SparseMat::ref(int i0, int i1, size_t* hashval) +{ + return *(_Tp*)((SparseMat*)this)->ptr(i0, i1, true, hashval); +} + +template inline +_Tp& SparseMat::ref(int i0, int i1, int i2, size_t* hashval) +{ + return *(_Tp*)((SparseMat*)this)->ptr(i0, i1, i2, true, hashval); +} + +template inline +_Tp& SparseMat::ref(const int* idx, size_t* hashval) +{ + return *(_Tp*)((SparseMat*)this)->ptr(idx, true, hashval); +} + +template inline +_Tp SparseMat::value(int i0, size_t* hashval) const +{ + const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(i0, false, hashval); + return p ? *p : _Tp(); +} + +template inline +_Tp SparseMat::value(int i0, int i1, size_t* hashval) const +{ + const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(i0, i1, false, hashval); + return p ? *p : _Tp(); +} + +template inline +_Tp SparseMat::value(int i0, int i1, int i2, size_t* hashval) const +{ + const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(i0, i1, i2, false, hashval); + return p ? *p : _Tp(); +} + +template inline +_Tp SparseMat::value(const int* idx, size_t* hashval) const +{ + const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(idx, false, hashval); + return p ? *p : _Tp(); +} + +template inline +const _Tp* SparseMat::find(int i0, size_t* hashval) const +{ + return (const _Tp*)((SparseMat*)this)->ptr(i0, false, hashval); +} + +template inline +const _Tp* SparseMat::find(int i0, int i1, size_t* hashval) const +{ + return (const _Tp*)((SparseMat*)this)->ptr(i0, i1, false, hashval); +} + +template inline +const _Tp* SparseMat::find(int i0, int i1, int i2, size_t* hashval) const +{ + return (const _Tp*)((SparseMat*)this)->ptr(i0, i1, i2, false, hashval); +} + +template inline +const _Tp* SparseMat::find(const int* idx, size_t* hashval) const +{ + return (const _Tp*)((SparseMat*)this)->ptr(idx, false, hashval); +} + +template inline +_Tp& SparseMat::value(Node* n) +{ + return *(_Tp*)((uchar*)n + hdr->valueOffset); +} + +template inline +const _Tp& SparseMat::value(const Node* n) const +{ + return *(const _Tp*)((const uchar*)n + hdr->valueOffset); +} + +inline +SparseMat::Node* SparseMat::node(size_t nidx) +{ + return (Node*)&hdr->pool[nidx]; +} + +inline +const SparseMat::Node* SparseMat::node(size_t nidx) const +{ + return (const Node*)&hdr->pool[nidx]; +} + +inline +SparseMatIterator SparseMat::begin() +{ + return SparseMatIterator(this); +} + +inline +SparseMatConstIterator SparseMat::begin() const +{ + return SparseMatConstIterator(this); +} + +inline +SparseMatIterator SparseMat::end() +{ + SparseMatIterator it(this); + it.seekEnd(); + return it; +} + +inline +SparseMatConstIterator SparseMat::end() const +{ + SparseMatConstIterator it(this); + it.seekEnd(); + return it; +} + +template inline +SparseMatIterator_<_Tp> SparseMat::begin() +{ + return SparseMatIterator_<_Tp>(this); +} + +template inline +SparseMatConstIterator_<_Tp> SparseMat::begin() const +{ + return SparseMatConstIterator_<_Tp>(this); +} + +template inline +SparseMatIterator_<_Tp> SparseMat::end() +{ + SparseMatIterator_<_Tp> it(this); + it.seekEnd(); + return it; +} + +template inline +SparseMatConstIterator_<_Tp> SparseMat::end() const +{ + SparseMatConstIterator_<_Tp> it(this); + it.seekEnd(); + return it; +} + + + +///////////////////////////// SparseMat_ //////////////////////////// + +template inline +SparseMat_<_Tp>::SparseMat_() +{ + flags = MAGIC_VAL | DataType<_Tp>::type; +} + +template inline +SparseMat_<_Tp>::SparseMat_(int _dims, const int* _sizes) + : SparseMat(_dims, _sizes, DataType<_Tp>::type) +{} + +template inline +SparseMat_<_Tp>::SparseMat_(const SparseMat& m) +{ + if( m.type() == DataType<_Tp>::type ) + *this = (const SparseMat_<_Tp>&)m; + else + m.convertTo(this, DataType<_Tp>::type); +} + +template inline +SparseMat_<_Tp>::SparseMat_(const SparseMat_<_Tp>& m) +{ + this->flags = m.flags; + this->hdr = m.hdr; + if( this->hdr ) + CV_XADD(&this->hdr->refcount, 1); +} + +template inline +SparseMat_<_Tp>::SparseMat_(const Mat& m) +{ + SparseMat sm(m); + *this = sm; +} + +template inline +SparseMat_<_Tp>& SparseMat_<_Tp>::operator = (const SparseMat_<_Tp>& m) +{ + if( this != &m ) + { + if( m.hdr ) CV_XADD(&m.hdr->refcount, 1); + release(); + flags = m.flags; + hdr = m.hdr; + } + return *this; +} + +template inline +SparseMat_<_Tp>& SparseMat_<_Tp>::operator = (const SparseMat& m) +{ + if( m.type() == DataType<_Tp>::type ) + return (*this = (const SparseMat_<_Tp>&)m); + m.convertTo(*this, DataType<_Tp>::type); + return *this; +} + +template inline +SparseMat_<_Tp>& SparseMat_<_Tp>::operator = (const Mat& m) +{ + return (*this = SparseMat(m)); +} + +template inline +SparseMat_<_Tp> SparseMat_<_Tp>::clone() const +{ + SparseMat_<_Tp> m; + this->copyTo(m); + return m; +} + +template inline +void SparseMat_<_Tp>::create(int _dims, const int* _sizes) +{ + SparseMat::create(_dims, _sizes, DataType<_Tp>::type); +} + +template inline +int SparseMat_<_Tp>::type() const +{ + return DataType<_Tp>::type; +} + +template inline +int SparseMat_<_Tp>::depth() const +{ + return DataType<_Tp>::depth; +} + +template inline +int SparseMat_<_Tp>::channels() const +{ + return DataType<_Tp>::channels; +} + +template inline +_Tp& SparseMat_<_Tp>::ref(int i0, size_t* hashval) +{ + return SparseMat::ref<_Tp>(i0, hashval); +} + +template inline +_Tp SparseMat_<_Tp>::operator()(int i0, size_t* hashval) const +{ + return SparseMat::value<_Tp>(i0, hashval); +} + +template inline +_Tp& SparseMat_<_Tp>::ref(int i0, int i1, size_t* hashval) +{ + return SparseMat::ref<_Tp>(i0, i1, hashval); +} + +template inline +_Tp SparseMat_<_Tp>::operator()(int i0, int i1, size_t* hashval) const +{ + return SparseMat::value<_Tp>(i0, i1, hashval); +} + +template inline +_Tp& SparseMat_<_Tp>::ref(int i0, int i1, int i2, size_t* hashval) +{ + return SparseMat::ref<_Tp>(i0, i1, i2, hashval); +} + +template inline +_Tp SparseMat_<_Tp>::operator()(int i0, int i1, int i2, size_t* hashval) const +{ + return SparseMat::value<_Tp>(i0, i1, i2, hashval); +} + +template inline +_Tp& SparseMat_<_Tp>::ref(const int* idx, size_t* hashval) +{ + return SparseMat::ref<_Tp>(idx, hashval); +} + +template inline +_Tp SparseMat_<_Tp>::operator()(const int* idx, size_t* hashval) const +{ + return SparseMat::value<_Tp>(idx, hashval); +} + +template inline +SparseMatIterator_<_Tp> SparseMat_<_Tp>::begin() +{ + return SparseMatIterator_<_Tp>(this); +} + +template inline +SparseMatConstIterator_<_Tp> SparseMat_<_Tp>::begin() const +{ + return SparseMatConstIterator_<_Tp>(this); +} + +template inline +SparseMatIterator_<_Tp> SparseMat_<_Tp>::end() +{ + SparseMatIterator_<_Tp> it(this); + it.seekEnd(); + return it; +} + +template inline +SparseMatConstIterator_<_Tp> SparseMat_<_Tp>::end() const +{ + SparseMatConstIterator_<_Tp> it(this); + it.seekEnd(); + return it; +} + + + +////////////////////////// MatConstIterator ///////////////////////// + +inline +MatConstIterator::MatConstIterator() + : m(0), elemSize(0), ptr(0), sliceStart(0), sliceEnd(0) +{} + +inline +MatConstIterator::MatConstIterator(const Mat* _m) + : m(_m), elemSize(_m->elemSize()), ptr(0), sliceStart(0), sliceEnd(0) +{ + if( m && m->isContinuous() ) + { + sliceStart = m->data; + sliceEnd = sliceStart + m->total()*elemSize; + } + seek((const int*)0); +} + +inline +MatConstIterator::MatConstIterator(const Mat* _m, int _row, int _col) + : m(_m), elemSize(_m->elemSize()), ptr(0), sliceStart(0), sliceEnd(0) +{ + CV_Assert(m && m->dims <= 2); + if( m->isContinuous() ) + { + sliceStart = m->data; + sliceEnd = sliceStart + m->total()*elemSize; + } + int idx[] = {_row, _col}; + seek(idx); +} + +inline +MatConstIterator::MatConstIterator(const Mat* _m, Point _pt) + : m(_m), elemSize(_m->elemSize()), ptr(0), sliceStart(0), sliceEnd(0) +{ + CV_Assert(m && m->dims <= 2); + if( m->isContinuous() ) + { + sliceStart = m->data; + sliceEnd = sliceStart + m->total()*elemSize; + } + int idx[] = {_pt.y, _pt.x}; + seek(idx); +} + +inline +MatConstIterator::MatConstIterator(const MatConstIterator& it) + : m(it.m), elemSize(it.elemSize), ptr(it.ptr), sliceStart(it.sliceStart), sliceEnd(it.sliceEnd) +{} + +inline +MatConstIterator& MatConstIterator::operator = (const MatConstIterator& it ) +{ + m = it.m; elemSize = it.elemSize; ptr = it.ptr; + sliceStart = it.sliceStart; sliceEnd = it.sliceEnd; + return *this; +} + +inline +uchar* MatConstIterator::operator *() const +{ + return ptr; +} + +inline MatConstIterator& MatConstIterator::operator += (ptrdiff_t ofs) +{ + if( !m || ofs == 0 ) + return *this; + ptrdiff_t ofsb = ofs*elemSize; + ptr += ofsb; + if( ptr < sliceStart || sliceEnd <= ptr ) + { + ptr -= ofsb; + seek(ofs, true); + } + return *this; +} + +inline +MatConstIterator& MatConstIterator::operator -= (ptrdiff_t ofs) +{ + return (*this += -ofs); +} + +inline +MatConstIterator& MatConstIterator::operator --() +{ + if( m && (ptr -= elemSize) < sliceStart ) + { + ptr += elemSize; + seek(-1, true); + } + return *this; +} + +inline +MatConstIterator MatConstIterator::operator --(int) +{ + MatConstIterator b = *this; + *this += -1; + return b; +} + +inline +MatConstIterator& MatConstIterator::operator ++() +{ + if( m && (ptr += elemSize) >= sliceEnd ) + { + ptr -= elemSize; + seek(1, true); + } + return *this; +} + +inline MatConstIterator MatConstIterator::operator ++(int) +{ + MatConstIterator b = *this; + *this += 1; + return b; +} + + +static inline +bool operator == (const MatConstIterator& a, const MatConstIterator& b) +{ + return a.m == b.m && a.ptr == b.ptr; +} + +static inline +bool operator != (const MatConstIterator& a, const MatConstIterator& b) +{ + return !(a == b); +} + +static inline +bool operator < (const MatConstIterator& a, const MatConstIterator& b) +{ + return a.ptr < b.ptr; +} + +static inline +bool operator > (const MatConstIterator& a, const MatConstIterator& b) +{ + return a.ptr > b.ptr; +} + +static inline +bool operator <= (const MatConstIterator& a, const MatConstIterator& b) +{ + return a.ptr <= b.ptr; +} + +static inline +bool operator >= (const MatConstIterator& a, const MatConstIterator& b) +{ + return a.ptr >= b.ptr; +} + +static inline +ptrdiff_t operator - (const MatConstIterator& b, const MatConstIterator& a) +{ + if( a.m != b.m ) + return ((size_t)(-1) >> 1); + if( a.sliceEnd == b.sliceEnd ) + return (b.ptr - a.ptr)/b.elemSize; + + return b.lpos() - a.lpos(); +} + +static inline +MatConstIterator operator + (const MatConstIterator& a, ptrdiff_t ofs) +{ + MatConstIterator b = a; + return b += ofs; +} + +static inline +MatConstIterator operator + (ptrdiff_t ofs, const MatConstIterator& a) +{ + MatConstIterator b = a; + return b += ofs; +} + +static inline +MatConstIterator operator - (const MatConstIterator& a, ptrdiff_t ofs) +{ + MatConstIterator b = a; + return b += -ofs; +} + + +inline +uchar* MatConstIterator::operator [](ptrdiff_t i) const +{ + return *(*this + i); +} + + + +///////////////////////// MatConstIterator_ ///////////////////////// + +template inline +MatConstIterator_<_Tp>::MatConstIterator_() +{} + +template inline +MatConstIterator_<_Tp>::MatConstIterator_(const Mat_<_Tp>* _m) + : MatConstIterator(_m) +{} + +template inline +MatConstIterator_<_Tp>::MatConstIterator_(const Mat_<_Tp>* _m, int _row, int _col) + : MatConstIterator(_m, _row, _col) +{} + +template inline +MatConstIterator_<_Tp>::MatConstIterator_(const Mat_<_Tp>* _m, Point _pt) + : MatConstIterator(_m, _pt) +{} + +template inline +MatConstIterator_<_Tp>::MatConstIterator_(const MatConstIterator_& it) + : MatConstIterator(it) +{} + +template inline +MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator = (const MatConstIterator_& it ) +{ + MatConstIterator::operator = (it); + return *this; +} + +template inline +_Tp MatConstIterator_<_Tp>::operator *() const +{ + return *(_Tp*)(this->ptr); +} + +template inline +MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator += (ptrdiff_t ofs) +{ + MatConstIterator::operator += (ofs); + return *this; +} + +template inline +MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator -= (ptrdiff_t ofs) +{ + return (*this += -ofs); +} + +template inline +MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator --() +{ + MatConstIterator::operator --(); + return *this; +} + +template inline +MatConstIterator_<_Tp> MatConstIterator_<_Tp>::operator --(int) +{ + MatConstIterator_ b = *this; + MatConstIterator::operator --(); + return b; +} + +template inline +MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator ++() +{ + MatConstIterator::operator ++(); + return *this; +} + +template inline +MatConstIterator_<_Tp> MatConstIterator_<_Tp>::operator ++(int) +{ + MatConstIterator_ b = *this; + MatConstIterator::operator ++(); + return b; +} + + +template inline +Point MatConstIterator_<_Tp>::pos() const +{ + if( !m ) + return Point(); + CV_DbgAssert( m->dims <= 2 ); + if( m->isContinuous() ) + { + ptrdiff_t ofs = (const _Tp*)ptr - (const _Tp*)m->data; + int y = (int)(ofs / m->cols); + int x = (int)(ofs - (ptrdiff_t)y * m->cols); + return Point(x, y); + } + else + { + ptrdiff_t ofs = (uchar*)ptr - m->data; + int y = (int)(ofs / m->step); + int x = (int)((ofs - y * m->step)/sizeof(_Tp)); + return Point(x, y); + } +} + + +template static inline +bool operator == (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b) +{ + return a.m == b.m && a.ptr == b.ptr; +} + +template static inline +bool operator != (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b) +{ + return a.m != b.m || a.ptr != b.ptr; +} + +template static inline +MatConstIterator_<_Tp> operator + (const MatConstIterator_<_Tp>& a, ptrdiff_t ofs) +{ + MatConstIterator t = (const MatConstIterator&)a + ofs; + return (MatConstIterator_<_Tp>&)t; +} + +template static inline +MatConstIterator_<_Tp> operator + (ptrdiff_t ofs, const MatConstIterator_<_Tp>& a) +{ + MatConstIterator t = (const MatConstIterator&)a + ofs; + return (MatConstIterator_<_Tp>&)t; +} + +template static inline +MatConstIterator_<_Tp> operator - (const MatConstIterator_<_Tp>& a, ptrdiff_t ofs) +{ + MatConstIterator t = (const MatConstIterator&)a - ofs; + return (MatConstIterator_<_Tp>&)t; +} + +template inline +_Tp MatConstIterator_<_Tp>::operator [](ptrdiff_t i) const +{ + return *(_Tp*)MatConstIterator::operator [](i); +} + + + +//////////////////////////// MatIterator_ /////////////////////////// + +template inline +MatIterator_<_Tp>::MatIterator_() + : MatConstIterator_<_Tp>() +{} + +template inline +MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m) + : MatConstIterator_<_Tp>(_m) +{} + +template inline +MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m, int _row, int _col) + : MatConstIterator_<_Tp>(_m, _row, _col) +{} + +template inline +MatIterator_<_Tp>::MatIterator_(const Mat_<_Tp>* _m, Point _pt) + : MatConstIterator_<_Tp>(_m, _pt) +{} + +template inline +MatIterator_<_Tp>::MatIterator_(const Mat_<_Tp>* _m, const int* _idx) + : MatConstIterator_<_Tp>(_m, _idx) +{} + +template inline +MatIterator_<_Tp>::MatIterator_(const MatIterator_& it) + : MatConstIterator_<_Tp>(it) +{} + +template inline +MatIterator_<_Tp>& MatIterator_<_Tp>::operator = (const MatIterator_<_Tp>& it ) +{ + MatConstIterator::operator = (it); + return *this; +} + +template inline +_Tp& MatIterator_<_Tp>::operator *() const +{ + return *(_Tp*)(this->ptr); +} + +template inline +MatIterator_<_Tp>& MatIterator_<_Tp>::operator += (ptrdiff_t ofs) +{ + MatConstIterator::operator += (ofs); + return *this; +} + +template inline +MatIterator_<_Tp>& MatIterator_<_Tp>::operator -= (ptrdiff_t ofs) +{ + MatConstIterator::operator += (-ofs); + return *this; +} + +template inline +MatIterator_<_Tp>& MatIterator_<_Tp>::operator --() +{ + MatConstIterator::operator --(); + return *this; +} + +template inline +MatIterator_<_Tp> MatIterator_<_Tp>::operator --(int) +{ + MatIterator_ b = *this; + MatConstIterator::operator --(); + return b; +} + +template inline +MatIterator_<_Tp>& MatIterator_<_Tp>::operator ++() +{ + MatConstIterator::operator ++(); + return *this; +} + +template inline +MatIterator_<_Tp> MatIterator_<_Tp>::operator ++(int) +{ + MatIterator_ b = *this; + MatConstIterator::operator ++(); + return b; +} + +template inline +_Tp& MatIterator_<_Tp>::operator [](ptrdiff_t i) const +{ + return *(*this + i); +} + + +template static inline +bool operator == (const MatIterator_<_Tp>& a, const MatIterator_<_Tp>& b) +{ + return a.m == b.m && a.ptr == b.ptr; +} + +template static inline +bool operator != (const MatIterator_<_Tp>& a, const MatIterator_<_Tp>& b) +{ + return a.m != b.m || a.ptr != b.ptr; +} + +template static inline +MatIterator_<_Tp> operator + (const MatIterator_<_Tp>& a, ptrdiff_t ofs) +{ + MatConstIterator t = (const MatConstIterator&)a + ofs; + return (MatIterator_<_Tp>&)t; +} + +template static inline +MatIterator_<_Tp> operator + (ptrdiff_t ofs, const MatIterator_<_Tp>& a) +{ + MatConstIterator t = (const MatConstIterator&)a + ofs; + return (MatIterator_<_Tp>&)t; +} + +template static inline +MatIterator_<_Tp> operator - (const MatIterator_<_Tp>& a, ptrdiff_t ofs) +{ + MatConstIterator t = (const MatConstIterator&)a - ofs; + return (MatIterator_<_Tp>&)t; +} + + + +/////////////////////// SparseMatConstIterator ////////////////////// + +inline +SparseMatConstIterator::SparseMatConstIterator() + : m(0), hashidx(0), ptr(0) +{} + +inline +SparseMatConstIterator::SparseMatConstIterator(const SparseMatConstIterator& it) + : m(it.m), hashidx(it.hashidx), ptr(it.ptr) +{} + +inline SparseMatConstIterator& SparseMatConstIterator::operator = (const SparseMatConstIterator& it) +{ + if( this != &it ) + { + m = it.m; + hashidx = it.hashidx; + ptr = it.ptr; + } + return *this; +} + +template inline +const _Tp& SparseMatConstIterator::value() const +{ + return *(_Tp*)ptr; +} + +inline +const SparseMat::Node* SparseMatConstIterator::node() const +{ + return (ptr && m && m->hdr) ? (const SparseMat::Node*)(ptr - m->hdr->valueOffset) : 0; +} + +inline +SparseMatConstIterator SparseMatConstIterator::operator ++(int) +{ + SparseMatConstIterator it = *this; + ++*this; + return it; +} + +inline +void SparseMatConstIterator::seekEnd() +{ + if( m && m->hdr ) + { + hashidx = m->hdr->hashtab.size(); + ptr = 0; + } +} + + +static inline +bool operator == (const SparseMatConstIterator& it1, const SparseMatConstIterator& it2) +{ + return it1.m == it2.m && it1.ptr == it2.ptr; +} + +static inline +bool operator != (const SparseMatConstIterator& it1, const SparseMatConstIterator& it2) +{ + return !(it1 == it2); +} + + + +///////////////////////// SparseMatIterator ///////////////////////// + +inline +SparseMatIterator::SparseMatIterator() +{} + +inline +SparseMatIterator::SparseMatIterator(SparseMat* _m) + : SparseMatConstIterator(_m) +{} + +inline +SparseMatIterator::SparseMatIterator(const SparseMatIterator& it) + : SparseMatConstIterator(it) +{} + +inline +SparseMatIterator& SparseMatIterator::operator = (const SparseMatIterator& it) +{ + (SparseMatConstIterator&)*this = it; + return *this; +} + +template inline +_Tp& SparseMatIterator::value() const +{ + return *(_Tp*)ptr; +} + +inline +SparseMat::Node* SparseMatIterator::node() const +{ + return (SparseMat::Node*)SparseMatConstIterator::node(); +} + +inline +SparseMatIterator& SparseMatIterator::operator ++() +{ + SparseMatConstIterator::operator ++(); + return *this; +} + +inline +SparseMatIterator SparseMatIterator::operator ++(int) +{ + SparseMatIterator it = *this; + ++*this; + return it; +} + + + +////////////////////// SparseMatConstIterator_ ////////////////////// + +template inline +SparseMatConstIterator_<_Tp>::SparseMatConstIterator_() +{} + +template inline +SparseMatConstIterator_<_Tp>::SparseMatConstIterator_(const SparseMat_<_Tp>* _m) + : SparseMatConstIterator(_m) +{} + +template inline +SparseMatConstIterator_<_Tp>::SparseMatConstIterator_(const SparseMat* _m) + : SparseMatConstIterator(_m) +{ + CV_Assert( _m->type() == DataType<_Tp>::type ); +} + +template inline +SparseMatConstIterator_<_Tp>::SparseMatConstIterator_(const SparseMatConstIterator_<_Tp>& it) + : SparseMatConstIterator(it) +{} + +template inline +SparseMatConstIterator_<_Tp>& SparseMatConstIterator_<_Tp>::operator = (const SparseMatConstIterator_<_Tp>& it) +{ + return reinterpret_cast&> + (*reinterpret_cast(this) = + reinterpret_cast(it)); +} + +template inline +const _Tp& SparseMatConstIterator_<_Tp>::operator *() const +{ + return *(const _Tp*)this->ptr; +} + +template inline +SparseMatConstIterator_<_Tp>& SparseMatConstIterator_<_Tp>::operator ++() +{ + SparseMatConstIterator::operator ++(); + return *this; +} + +template inline +SparseMatConstIterator_<_Tp> SparseMatConstIterator_<_Tp>::operator ++(int) +{ + SparseMatConstIterator it = *this; + SparseMatConstIterator::operator ++(); + return it; +} + + + +///////////////////////// SparseMatIterator_ //////////////////////// + +template inline +SparseMatIterator_<_Tp>::SparseMatIterator_() +{} + +template inline +SparseMatIterator_<_Tp>::SparseMatIterator_(SparseMat_<_Tp>* _m) + : SparseMatConstIterator_<_Tp>(_m) +{} + +template inline +SparseMatIterator_<_Tp>::SparseMatIterator_(SparseMat* _m) + : SparseMatConstIterator_<_Tp>(_m) +{} + +template inline +SparseMatIterator_<_Tp>::SparseMatIterator_(const SparseMatIterator_<_Tp>& it) + : SparseMatConstIterator_<_Tp>(it) +{} + +template inline +SparseMatIterator_<_Tp>& SparseMatIterator_<_Tp>::operator = (const SparseMatIterator_<_Tp>& it) +{ + return reinterpret_cast&> + (*reinterpret_cast(this) = + reinterpret_cast(it)); +} + +template inline +_Tp& SparseMatIterator_<_Tp>::operator *() const +{ + return *(_Tp*)this->ptr; +} + +template inline +SparseMatIterator_<_Tp>& SparseMatIterator_<_Tp>::operator ++() +{ + SparseMatConstIterator::operator ++(); + return *this; +} + +template inline +SparseMatIterator_<_Tp> SparseMatIterator_<_Tp>::operator ++(int) +{ + SparseMatIterator it = *this; + SparseMatConstIterator::operator ++(); + return it; +} + + + +//////////////////////// MatCommaInitializer_ /////////////////////// + +template inline +MatCommaInitializer_<_Tp>::MatCommaInitializer_(Mat_<_Tp>* _m) + : it(_m) +{} + +template template inline +MatCommaInitializer_<_Tp>& MatCommaInitializer_<_Tp>::operator , (T2 v) +{ + CV_DbgAssert( this->it < ((const Mat_<_Tp>*)this->it.m)->end() ); + *this->it = _Tp(v); + ++this->it; + return *this; +} + +template inline +MatCommaInitializer_<_Tp>::operator Mat_<_Tp>() const +{ + CV_DbgAssert( this->it == ((const Mat_<_Tp>*)this->it.m)->end() ); + return Mat_<_Tp>(*this->it.m); +} + + +template static inline +MatCommaInitializer_<_Tp> operator << (const Mat_<_Tp>& m, T2 val) +{ + MatCommaInitializer_<_Tp> commaInitializer((Mat_<_Tp>*)&m); + return (commaInitializer, val); +} + + + +///////////////////////// Matrix Expressions //////////////////////// + +inline +Mat& Mat::operator = (const MatExpr& e) +{ + e.op->assign(e, *this); + return *this; +} + +template inline +Mat_<_Tp>::Mat_(const MatExpr& e) +{ + e.op->assign(e, *this, DataType<_Tp>::type); +} + +template inline +Mat_<_Tp>& Mat_<_Tp>::operator = (const MatExpr& e) +{ + e.op->assign(e, *this, DataType<_Tp>::type); + return *this; +} + +template inline +MatExpr Mat_<_Tp>::zeros(int rows, int cols) +{ + return Mat::zeros(rows, cols, DataType<_Tp>::type); +} + +template inline +MatExpr Mat_<_Tp>::zeros(Size sz) +{ + return Mat::zeros(sz, DataType<_Tp>::type); +} + +template inline +MatExpr Mat_<_Tp>::ones(int rows, int cols) +{ + return Mat::ones(rows, cols, DataType<_Tp>::type); +} + +template inline +MatExpr Mat_<_Tp>::ones(Size sz) +{ + return Mat::ones(sz, DataType<_Tp>::type); +} + +template inline +MatExpr Mat_<_Tp>::eye(int rows, int cols) +{ + return Mat::eye(rows, cols, DataType<_Tp>::type); +} + +template inline +MatExpr Mat_<_Tp>::eye(Size sz) +{ + return Mat::eye(sz, DataType<_Tp>::type); +} + +inline +MatExpr::MatExpr() + : op(0), flags(0), a(Mat()), b(Mat()), c(Mat()), alpha(0), beta(0), s() +{} + +inline +MatExpr::MatExpr(const MatOp* _op, int _flags, const Mat& _a, const Mat& _b, + const Mat& _c, double _alpha, double _beta, const Scalar& _s) + : op(_op), flags(_flags), a(_a), b(_b), c(_c), alpha(_alpha), beta(_beta), s(_s) +{} + +inline +MatExpr::operator Mat() const +{ + Mat m; + op->assign(*this, m); + return m; +} + +template inline +MatExpr::operator Mat_<_Tp>() const +{ + Mat_<_Tp> m; + op->assign(*this, m, DataType<_Tp>::type); + return m; +} + + +template static inline +MatExpr min(const Mat_<_Tp>& a, const Mat_<_Tp>& b) +{ + return cv::min((const Mat&)a, (const Mat&)b); +} + +template static inline +MatExpr min(const Mat_<_Tp>& a, double s) +{ + return cv::min((const Mat&)a, s); +} + +template static inline +MatExpr min(double s, const Mat_<_Tp>& a) +{ + return cv::min((const Mat&)a, s); +} + +template static inline +MatExpr max(const Mat_<_Tp>& a, const Mat_<_Tp>& b) +{ + return cv::max((const Mat&)a, (const Mat&)b); +} + +template static inline +MatExpr max(const Mat_<_Tp>& a, double s) +{ + return cv::max((const Mat&)a, s); +} + +template static inline +MatExpr max(double s, const Mat_<_Tp>& a) +{ + return cv::max((const Mat&)a, s); +} + +template static inline +MatExpr abs(const Mat_<_Tp>& m) +{ + return cv::abs((const Mat&)m); +} + + +static inline +Mat& operator += (Mat& a, const MatExpr& b) +{ + b.op->augAssignAdd(b, a); + return a; +} + +static inline +const Mat& operator += (const Mat& a, const MatExpr& b) +{ + b.op->augAssignAdd(b, (Mat&)a); + return a; +} + +template static inline +Mat_<_Tp>& operator += (Mat_<_Tp>& a, const MatExpr& b) +{ + b.op->augAssignAdd(b, a); + return a; +} + +template static inline +const Mat_<_Tp>& operator += (const Mat_<_Tp>& a, const MatExpr& b) +{ + b.op->augAssignAdd(b, (Mat&)a); + return a; +} + +static inline +Mat& operator -= (Mat& a, const MatExpr& b) +{ + b.op->augAssignSubtract(b, a); + return a; +} + +static inline +const Mat& operator -= (const Mat& a, const MatExpr& b) +{ + b.op->augAssignSubtract(b, (Mat&)a); + return a; +} + +template static inline +Mat_<_Tp>& operator -= (Mat_<_Tp>& a, const MatExpr& b) +{ + b.op->augAssignSubtract(b, a); + return a; +} + +template static inline +const Mat_<_Tp>& operator -= (const Mat_<_Tp>& a, const MatExpr& b) +{ + b.op->augAssignSubtract(b, (Mat&)a); + return a; +} + +static inline +Mat& operator *= (Mat& a, const MatExpr& b) +{ + b.op->augAssignMultiply(b, a); + return a; +} + +static inline +const Mat& operator *= (const Mat& a, const MatExpr& b) +{ + b.op->augAssignMultiply(b, (Mat&)a); + return a; +} + +template static inline +Mat_<_Tp>& operator *= (Mat_<_Tp>& a, const MatExpr& b) +{ + b.op->augAssignMultiply(b, a); + return a; +} + +template static inline +const Mat_<_Tp>& operator *= (const Mat_<_Tp>& a, const MatExpr& b) +{ + b.op->augAssignMultiply(b, (Mat&)a); + return a; +} + +static inline +Mat& operator /= (Mat& a, const MatExpr& b) +{ + b.op->augAssignDivide(b, a); + return a; +} + +static inline +const Mat& operator /= (const Mat& a, const MatExpr& b) +{ + b.op->augAssignDivide(b, (Mat&)a); + return a; +} + +template static inline +Mat_<_Tp>& operator /= (Mat_<_Tp>& a, const MatExpr& b) +{ + b.op->augAssignDivide(b, a); + return a; +} + +template static inline +const Mat_<_Tp>& operator /= (const Mat_<_Tp>& a, const MatExpr& b) +{ + b.op->augAssignDivide(b, (Mat&)a); + return a; +} + +} //cv + +#endif diff --git a/modules/core/include/opencv2/core/matx.hpp b/modules/core/include/opencv2/core/matx.hpp new file mode 100644 index 0000000000..86a35cd756 --- /dev/null +++ b/modules/core/include/opencv2/core/matx.hpp @@ -0,0 +1,1358 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_MATX_HPP__ +#define __OPENCV_CORE_MATX_HPP__ + +#ifndef __cplusplus +# error matx.hpp header must be compiled as C++ +#endif + +#include "opencv2/core/cvdef.h" +#include "opencv2/core/base.hpp" +#include "opencv2/core/traits.hpp" + +namespace cv +{ + +////////////////////////////// Small Matrix /////////////////////////// + +/*! + A short numerical vector. + + This template class represents short numerical vectors (of 1, 2, 3, 4 ... elements) + on which you can perform basic arithmetical operations, access individual elements using [] operator etc. + The vectors are allocated on stack, as opposite to std::valarray, std::vector, cv::Mat etc., + which elements are dynamically allocated in the heap. + + The template takes 2 parameters: + -# _Tp element type + -# cn the number of elements + + In addition to the universal notation like Vec, you can use shorter aliases + for the most popular specialized variants of Vec, e.g. Vec3f ~ Vec. + */ + +struct CV_EXPORTS Matx_AddOp {}; +struct CV_EXPORTS Matx_SubOp {}; +struct CV_EXPORTS Matx_ScaleOp {}; +struct CV_EXPORTS Matx_MulOp {}; +struct CV_EXPORTS Matx_DivOp {}; +struct CV_EXPORTS Matx_MatMulOp {}; +struct CV_EXPORTS Matx_TOp {}; + +template class Matx +{ +public: + enum { depth = DataType<_Tp>::depth, + rows = m, + cols = n, + channels = rows*cols, + type = CV_MAKETYPE(depth, channels), + shortdim = (m < n ? m : n) + }; + + typedef _Tp value_type; + typedef Matx<_Tp, m, n> mat_type; + typedef Matx<_Tp, shortdim, 1> diag_type; + + //! default constructor + Matx(); + + Matx(_Tp v0); //!< 1x1 matrix + Matx(_Tp v0, _Tp v1); //!< 1x2 or 2x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2); //!< 1x3 or 3x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3); //!< 1x4, 2x2 or 4x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4); //!< 1x5 or 5x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5); //!< 1x6, 2x3, 3x2 or 6x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6); //!< 1x7 or 7x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7); //!< 1x8, 2x4, 4x2 or 8x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8); //!< 1x9, 3x3 or 9x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9); //!< 1x10, 2x5 or 5x2 or 10x1 matrix + 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); //!< 1x12, 2x6, 3x4, 4x3, 6x2 or 12x1 matrix + 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); //!< 1x16, 4x4 or 16x1 matrix + explicit Matx(const _Tp* vals); //!< initialize from a plain array + + static Matx all(_Tp alpha); + static Matx zeros(); + static Matx ones(); + static Matx eye(); + static Matx diag(const diag_type& d); + static Matx randu(_Tp a, _Tp b); + static Matx randn(_Tp a, _Tp b); + + //! dot product computed with the default precision + _Tp dot(const Matx<_Tp, m, n>& v) const; + + //! dot product computed in double-precision arithmetics + double ddot(const Matx<_Tp, m, n>& v) const; + + //! convertion to another data type + template operator Matx() const; + + //! change the matrix shape + template Matx<_Tp, m1, n1> reshape() const; + + //! extract part of the matrix + template Matx<_Tp, m1, n1> get_minor(int i, int j) const; + + //! extract the matrix row + Matx<_Tp, 1, n> row(int i) const; + + //! extract the matrix column + Matx<_Tp, m, 1> col(int i) const; + + //! extract the matrix diagonal + diag_type diag() const; + + //! transpose the matrix + Matx<_Tp, n, m> t() const; + + //! invert matrix the matrix + Matx<_Tp, n, m> inv(int method=DECOMP_LU) const; + + //! solve linear system + template Matx<_Tp, n, l> solve(const Matx<_Tp, m, l>& rhs, int flags=DECOMP_LU) const; + Vec<_Tp, n> solve(const Vec<_Tp, m>& rhs, int method) const; + + //! multiply two matrices element-wise + Matx<_Tp, m, n> mul(const Matx<_Tp, m, n>& a) const; + + //! divide two matrices element-wise + Matx<_Tp, m, n> div(const Matx<_Tp, m, n>& a) const; + + //! element access + const _Tp& operator ()(int i, int j) const; + _Tp& operator ()(int i, int j); + + //! 1D element access + const _Tp& operator ()(int i) const; + _Tp& operator ()(int i); + + Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_AddOp); + Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_SubOp); + template Matx(const Matx<_Tp, m, n>& a, _T2 alpha, Matx_ScaleOp); + Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_MulOp); + Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_DivOp); + template Matx(const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b, Matx_MatMulOp); + Matx(const Matx<_Tp, n, m>& a, Matx_TOp); + + _Tp val[m*n]; //< matrix elements +}; + +/*! + \typedef +*/ +typedef Matx Matx12f; +typedef Matx Matx12d; +typedef Matx Matx13f; +typedef Matx Matx13d; +typedef Matx Matx14f; +typedef Matx Matx14d; +typedef Matx Matx16f; +typedef Matx Matx16d; + +typedef Matx Matx21f; +typedef Matx Matx21d; +typedef Matx Matx31f; +typedef Matx Matx31d; +typedef Matx Matx41f; +typedef Matx Matx41d; +typedef Matx Matx61f; +typedef Matx Matx61d; + +typedef Matx Matx22f; +typedef Matx Matx22d; +typedef Matx Matx23f; +typedef Matx Matx23d; +typedef Matx Matx32f; +typedef Matx Matx32d; + +typedef Matx Matx33f; +typedef Matx Matx33d; + +typedef Matx Matx34f; +typedef Matx Matx34d; +typedef Matx Matx43f; +typedef Matx Matx43d; + +typedef Matx Matx44f; +typedef Matx Matx44d; +typedef Matx Matx66f; +typedef Matx Matx66d; + +/*! + traits +*/ +template class DataType< Matx<_Tp, m, n> > +{ +public: + typedef Matx<_Tp, m, n> value_type; + typedef Matx::work_type, m, n> work_type; + typedef _Tp channel_type; + typedef value_type vec_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = m * n, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; +}; + +/*! + Comma-separated Matrix Initializer +*/ +template class MatxCommaInitializer +{ +public: + MatxCommaInitializer(Matx<_Tp, m, n>* _mtx); + template MatxCommaInitializer<_Tp, m, n>& operator , (T2 val); + Matx<_Tp, m, n> operator *() const; + + Matx<_Tp, m, n>* dst; + int idx; +}; + +/*! + Utility methods +*/ +template static double determinant(const Matx<_Tp, m, m>& a); +template static double trace(const Matx<_Tp, m, n>& a); +template static double norm(const Matx<_Tp, m, n>& M); +template static double norm(const Matx<_Tp, m, n>& M, int normType); + + + +/////////////////////// Vec (used as element of multi-channel images ///////////////////// + +/*! + A short numerical vector. + + This template class represents short numerical vectors (of 1, 2, 3, 4 ... elements) + on which you can perform basic arithmetical operations, access individual elements using [] operator etc. + The vectors are allocated on stack, as opposite to std::valarray, std::vector, cv::Mat etc., + which elements are dynamically allocated in the heap. + + The template takes 2 parameters: + -# _Tp element type + -# cn the number of elements + + In addition to the universal notation like Vec, you can use shorter aliases + for the most popular specialized variants of Vec, e.g. Vec3f ~ Vec. +*/ +template class Vec : public Matx<_Tp, cn, 1> +{ +public: + typedef _Tp value_type; + enum { depth = Matx<_Tp, cn, 1>::depth, + channels = cn, + type = CV_MAKETYPE(depth, channels) + }; + + //! default constructor + Vec(); + + Vec(_Tp v0); //!< 1-element vector constructor + Vec(_Tp v0, _Tp v1); //!< 2-element vector constructor + Vec(_Tp v0, _Tp v1, _Tp v2); //!< 3-element vector constructor + Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3); //!< 4-element vector constructor + Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4); //!< 5-element vector constructor + Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5); //!< 6-element vector constructor + Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6); //!< 7-element vector constructor + Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7); //!< 8-element vector constructor + Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8); //!< 9-element vector constructor + Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9); //!< 10-element vector constructor + explicit Vec(const _Tp* values); + + Vec(const Vec<_Tp, cn>& v); + + static Vec all(_Tp alpha); + + //! per-element multiplication + Vec mul(const Vec<_Tp, cn>& v) const; + + //! conjugation (makes sense for complex numbers and quaternions) + Vec conj() const; + + /*! + cross product of the two 3D vectors. + + For other dimensionalities the exception is raised + */ + Vec cross(const Vec& v) const; + //! convertion to another data type + template operator Vec() const; + + /*! element access */ + const _Tp& operator [](int i) const; + _Tp& operator[](int i); + const _Tp& operator ()(int i) const; + _Tp& operator ()(int i); + + Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_AddOp); + Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_SubOp); + template Vec(const Matx<_Tp, cn, 1>& a, _T2 alpha, Matx_ScaleOp); +}; + +/* \typedef + Shorter aliases for the most popular specializations of Vec +*/ +typedef Vec Vec2b; +typedef Vec Vec3b; +typedef Vec Vec4b; + +typedef Vec Vec2s; +typedef Vec Vec3s; +typedef Vec Vec4s; + +typedef Vec Vec2w; +typedef Vec Vec3w; +typedef Vec Vec4w; + +typedef Vec Vec2i; +typedef Vec Vec3i; +typedef Vec Vec4i; +typedef Vec Vec6i; +typedef Vec Vec8i; + +typedef Vec Vec2f; +typedef Vec Vec3f; +typedef Vec Vec4f; +typedef Vec Vec6f; + +typedef Vec Vec2d; +typedef Vec Vec3d; +typedef Vec Vec4d; +typedef Vec Vec6d; + +/*! + traits +*/ +template class DataType< Vec<_Tp, cn> > +{ +public: + typedef Vec<_Tp, cn> value_type; + typedef Vec::work_type, cn> work_type; + typedef _Tp channel_type; + typedef value_type vec_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = cn, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; +}; + +/*! + Comma-separated Vec Initializer +*/ +template class VecCommaInitializer : public MatxCommaInitializer<_Tp, m, 1> +{ +public: + VecCommaInitializer(Vec<_Tp, m>* _vec); + template VecCommaInitializer<_Tp, m>& operator , (T2 val); + Vec<_Tp, m> operator *() const; +}; + +/*! + Utility methods +*/ +template static Vec<_Tp, cn> normalize(const Vec<_Tp, cn>& v); + + + +///////////////////////////////////// helper classes ///////////////////////////////////// +namespace internal +{ + +template struct Matx_DetOp +{ + double operator ()(const Matx<_Tp, m, m>& a) const + { + Matx<_Tp, m, m> temp = a; + double p = LU(temp.val, m*sizeof(_Tp), m, 0, 0, 0); + if( p == 0 ) + return p; + for( int i = 0; i < m; i++ ) + p *= temp(i, i); + return 1./p; + } +}; + +template struct Matx_DetOp<_Tp, 1> +{ + double operator ()(const Matx<_Tp, 1, 1>& a) const + { + return a(0,0); + } +}; + +template struct Matx_DetOp<_Tp, 2> +{ + double operator ()(const Matx<_Tp, 2, 2>& a) const + { + return a(0,0)*a(1,1) - a(0,1)*a(1,0); + } +}; + +template struct Matx_DetOp<_Tp, 3> +{ + double operator ()(const Matx<_Tp, 3, 3>& a) const + { + return a(0,0)*(a(1,1)*a(2,2) - a(2,1)*a(1,2)) - + a(0,1)*(a(1,0)*a(2,2) - a(2,0)*a(1,2)) + + a(0,2)*(a(1,0)*a(2,1) - a(2,0)*a(1,1)); + } +}; + +template Vec<_Tp, 2> inline conjugate(const Vec<_Tp, 2>& v) +{ + return Vec<_Tp, 2>(v[0], -v[1]); +} + +template Vec<_Tp, 4> inline conjugate(const Vec<_Tp, 4>& v) +{ + return Vec<_Tp, 4>(v[0], -v[1], -v[2], -v[3]); +} + +} // internal + + + +////////////////////////////////// Matx Implementation /////////////////////////////////// + +template inline +Matx<_Tp, m, n>::Matx() +{ + for(int i = 0; i < channels; i++) val[i] = _Tp(0); +} + +template inline +Matx<_Tp, m, n>::Matx(_Tp v0) +{ + val[0] = v0; + for(int i = 1; i < channels; i++) val[i] = _Tp(0); +} + +template inline +Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1) +{ + CV_StaticAssert(channels >= 2, "Matx should have at least 2 elaments."); + val[0] = v0; val[1] = v1; + for(int i = 2; i < channels; i++) val[i] = _Tp(0); +} + +template inline +Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2) +{ + CV_StaticAssert(channels >= 3, "Matx should have at least 3 elaments."); + val[0] = v0; val[1] = v1; val[2] = v2; + for(int i = 3; i < channels; i++) val[i] = _Tp(0); +} + +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."); + val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; + for(int i = 4; i < channels; i++) val[i] = _Tp(0); +} + +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."); + 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); +} + +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."); + 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); +} + +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."); + 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); +} + +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."); + 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); +} + +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."); + 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; + for(int i = 9; 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) +{ + CV_StaticAssert(channels >= 10, "Matx should have at least 10 elaments."); + 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; + for(int i = 10; 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) +{ + CV_StaticAssert(channels == 12, "Matx should have at least 12 elaments."); + 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; +} + +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."); + 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; +} + +template inline +Matx<_Tp, m, n>::Matx(const _Tp* values) +{ + for( int i = 0; i < channels; i++ ) val[i] = values[i]; +} + +template inline +Matx<_Tp, m, n> Matx<_Tp, m, n>::all(_Tp alpha) +{ + Matx<_Tp, m, n> M; + for( int i = 0; i < m*n; i++ ) M.val[i] = alpha; + return M; +} + +template inline +Matx<_Tp,m,n> Matx<_Tp,m,n>::zeros() +{ + return all(0); +} + +template inline +Matx<_Tp,m,n> Matx<_Tp,m,n>::ones() +{ + return all(1); +} + +template inline +Matx<_Tp,m,n> Matx<_Tp,m,n>::eye() +{ + Matx<_Tp,m,n> M; + for(int i = 0; i < shortdim; i++) + M(i,i) = 1; + return M; +} + +template inline +_Tp Matx<_Tp, m, n>::dot(const Matx<_Tp, m, n>& M) const +{ + _Tp s = 0; + for( int i = 0; i < channels; i++ ) s += val[i]*M.val[i]; + return s; +} + +template inline +double Matx<_Tp, m, n>::ddot(const Matx<_Tp, m, n>& M) const +{ + double s = 0; + for( int i = 0; i < channels; i++ ) s += (double)val[i]*M.val[i]; + return s; +} + +template inline +Matx<_Tp,m,n> Matx<_Tp,m,n>::diag(const typename Matx<_Tp,m,n>::diag_type& d) +{ + Matx<_Tp,m,n> M; + for(int i = 0; i < shortdim; i++) + M(i,i) = d(i, 0); + return M; +} + +template template +inline Matx<_Tp, m, n>::operator Matx() const +{ + Matx M; + for( int i = 0; i < m*n; i++ ) M.val[i] = saturate_cast(val[i]); + return M; +} + +template template inline +Matx<_Tp, m1, n1> Matx<_Tp, m, n>::reshape() const +{ + CV_StaticAssert(m1*n1 == m*n, "Input and destnarion matrices must have the same number of elements"); + return (const Matx<_Tp, m1, n1>&)*this; +} + +template +template inline +Matx<_Tp, m1, n1> Matx<_Tp, m, n>::get_minor(int i, int j) const +{ + CV_DbgAssert(0 <= i && i+m1 <= m && 0 <= j && j+n1 <= n); + Matx<_Tp, m1, n1> s; + for( int di = 0; di < m1; di++ ) + for( int dj = 0; dj < n1; dj++ ) + s(di, dj) = (*this)(i+di, j+dj); + return s; +} + +template inline +Matx<_Tp, 1, n> Matx<_Tp, m, n>::row(int i) const +{ + CV_DbgAssert((unsigned)i < (unsigned)m); + return Matx<_Tp, 1, n>(&val[i*n]); +} + +template inline +Matx<_Tp, m, 1> Matx<_Tp, m, n>::col(int j) const +{ + CV_DbgAssert((unsigned)j < (unsigned)n); + Matx<_Tp, m, 1> v; + for( int i = 0; i < m; i++ ) + v.val[i] = val[i*n + j]; + return v; +} + +template inline +typename Matx<_Tp, m, n>::diag_type Matx<_Tp, m, n>::diag() const +{ + diag_type d; + for( int i = 0; i < shortdim; i++ ) + d.val[i] = val[i*n + i]; + return d; +} + +template inline +const _Tp& Matx<_Tp, m, n>::operator()(int i, int j) const +{ + CV_DbgAssert( (unsigned)i < (unsigned)m && (unsigned)j < (unsigned)n ); + return this->val[i*n + j]; +} + +template inline +_Tp& Matx<_Tp, m, n>::operator ()(int i, int j) +{ + CV_DbgAssert( (unsigned)i < (unsigned)m && (unsigned)j < (unsigned)n ); + return val[i*n + j]; +} + +template inline +const _Tp& Matx<_Tp, m, n>::operator ()(int i) const +{ + CV_StaticAssert(m == 1 || n == 1, "Single index indexation requires matrix to be a column or a row"); + CV_DbgAssert( (unsigned)i < (unsigned)(m+n-1) ); + return val[i]; +} + +template inline +_Tp& Matx<_Tp, m, n>::operator ()(int i) +{ + CV_StaticAssert(m == 1 || n == 1, "Single index indexation requires matrix to be a column or a row"); + CV_DbgAssert( (unsigned)i < (unsigned)(m+n-1) ); + return val[i]; +} + +template inline +Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_AddOp) +{ + for( int i = 0; i < channels; i++ ) + val[i] = saturate_cast<_Tp>(a.val[i] + b.val[i]); +} + +template inline +Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_SubOp) +{ + for( int i = 0; i < channels; i++ ) + val[i] = saturate_cast<_Tp>(a.val[i] - b.val[i]); +} + +template template inline +Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, _T2 alpha, Matx_ScaleOp) +{ + for( int i = 0; i < channels; i++ ) + val[i] = saturate_cast<_Tp>(a.val[i] * alpha); +} + +template inline +Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_MulOp) +{ + for( int i = 0; i < channels; i++ ) + val[i] = saturate_cast<_Tp>(a.val[i] * b.val[i]); +} + +template inline +Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_DivOp) +{ + for( int i = 0; i < channels; i++ ) + val[i] = saturate_cast<_Tp>(a.val[i] / b.val[i]); +} + +template template inline +Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b, Matx_MatMulOp) +{ + for( int i = 0; i < m; i++ ) + for( int j = 0; j < n; j++ ) + { + _Tp s = 0; + for( int k = 0; k < l; k++ ) + s += a(i, k) * b(k, j); + val[i*n + j] = s; + } +} + +template inline +Matx<_Tp,m,n>::Matx(const Matx<_Tp, n, m>& a, Matx_TOp) +{ + for( int i = 0; i < m; i++ ) + for( int j = 0; j < n; j++ ) + val[i*n + j] = a(j, i); +} + +template inline +Matx<_Tp, m, n> Matx<_Tp, m, n>::mul(const Matx<_Tp, m, n>& a) const +{ + return Matx<_Tp, m, n>(*this, a, Matx_MulOp()); +} + +template inline +Matx<_Tp, m, n> Matx<_Tp, m, n>::div(const Matx<_Tp, m, n>& a) const +{ + return Matx<_Tp, m, n>(*this, a, Matx_DivOp()); +} + +template inline +Matx<_Tp, n, m> Matx<_Tp, m, n>::t() const +{ + return Matx<_Tp, n, m>(*this, Matx_TOp()); +} + +template inline +Vec<_Tp, n> Matx<_Tp, m, n>::solve(const Vec<_Tp, m>& rhs, int method) const +{ + Matx<_Tp, n, 1> x = solve((const Matx<_Tp, m, 1>&)(rhs), method); + return (Vec<_Tp, n>&)(x); +} + +template static inline +double determinant(const Matx<_Tp, m, m>& a) +{ + return internal::Matx_DetOp<_Tp, m>()(a); +} + +template static inline +double trace(const Matx<_Tp, m, n>& a) +{ + _Tp s = 0; + for( int i = 0; i < std::min(m, n); i++ ) + s += a(i,i); + return s; +} + +template static inline +double norm(const Matx<_Tp, m, n>& M) +{ + return std::sqrt(normL2Sqr<_Tp, double>(M.val, m*n)); +} + +template static inline +double norm(const Matx<_Tp, m, n>& M, int normType) +{ + return normType == NORM_INF ? (double)normInf<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n) : + normType == NORM_L1 ? (double)normL1<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n) : + std::sqrt((double)normL2Sqr<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n)); +} + + + +//////////////////////////////// matx comma initializer ////////////////////////////////// + +template static inline +MatxCommaInitializer<_Tp, m, n> operator << (const Matx<_Tp, m, n>& mtx, _T2 val) +{ + MatxCommaInitializer<_Tp, m, n> commaInitializer((Matx<_Tp, m, n>*)&mtx); + return (commaInitializer, val); +} + +template inline +MatxCommaInitializer<_Tp, m, n>::MatxCommaInitializer(Matx<_Tp, m, n>* _mtx) + : dst(_mtx), idx(0) +{} + +template template inline +MatxCommaInitializer<_Tp, m, n>& MatxCommaInitializer<_Tp, m, n>::operator , (_T2 value) +{ + CV_DbgAssert( idx < m*n ); + dst->val[idx++] = saturate_cast<_Tp>(value); + return *this; +} + +template inline +Matx<_Tp, m, n> MatxCommaInitializer<_Tp, m, n>::operator *() const +{ + CV_DbgAssert( idx == n*m ); + return *dst; +} + + + +/////////////////////////////////// Vec Implementation /////////////////////////////////// + +template inline +Vec<_Tp, cn>::Vec() {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0) + : Matx<_Tp, cn, 1>(v0) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1) + : Matx<_Tp, cn, 1>(v0, v1) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2) + : Matx<_Tp, cn, 1>(v0, v1, v2) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3) + : Matx<_Tp, cn, 1>(v0, v1, v2, v3) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4) + : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5) + : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6) + : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7) + : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6, v7) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8) + : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6, v7, v8) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9) + : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {} + +template inline +Vec<_Tp, cn>::Vec(const _Tp* values) + : Matx<_Tp, cn, 1>(values) {} + +template inline +Vec<_Tp, cn>::Vec(const Vec<_Tp, cn>& m) + : Matx<_Tp, cn, 1>(m.val) {} + +template inline +Vec<_Tp, cn>::Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_AddOp op) + : Matx<_Tp, cn, 1>(a, b, op) {} + +template inline +Vec<_Tp, cn>::Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_SubOp op) + : Matx<_Tp, cn, 1>(a, b, op) {} + +template template inline +Vec<_Tp, cn>::Vec(const Matx<_Tp, cn, 1>& a, _T2 alpha, Matx_ScaleOp op) + : Matx<_Tp, cn, 1>(a, alpha, op) {} + +template inline +Vec<_Tp, cn> Vec<_Tp, cn>::all(_Tp alpha) +{ + Vec v; + for( int i = 0; i < cn; i++ ) v.val[i] = alpha; + return v; +} + +template inline +Vec<_Tp, cn> Vec<_Tp, cn>::mul(const Vec<_Tp, cn>& v) const +{ + Vec<_Tp, cn> w; + for( int i = 0; i < cn; i++ ) w.val[i] = saturate_cast<_Tp>(this->val[i]*v.val[i]); + return w; +} + +template<> inline +Vec Vec::conj() const +{ + return internal::conjugate(*this); +} + +template<> inline +Vec Vec::conj() const +{ + return internal::conjugate(*this); +} + +template<> inline +Vec Vec::conj() const +{ + return internal::conjugate(*this); +} + +template<> inline +Vec Vec::conj() const +{ + return internal::conjugate(*this); +} + +template inline +Vec<_Tp, cn> Vec<_Tp, cn>::cross(const Vec<_Tp, cn>&) const +{ + CV_StaticAssert(cn == 3, "for arbitrary-size vector there is no cross-product defined"); + return Vec<_Tp, cn>(); +} + +template<> inline +Vec Vec::cross(const Vec& v) const +{ + return Vec(val[1]*v.val[2] - val[2]*v.val[1], + val[2]*v.val[0] - val[0]*v.val[2], + val[0]*v.val[1] - val[1]*v.val[0]); +} + +template<> inline +Vec Vec::cross(const Vec& v) const +{ + return Vec(val[1]*v.val[2] - val[2]*v.val[1], + val[2]*v.val[0] - val[0]*v.val[2], + val[0]*v.val[1] - val[1]*v.val[0]); +} + +template template inline +Vec<_Tp, cn>::operator Vec() const +{ + Vec v; + for( int i = 0; i < cn; i++ ) v.val[i] = saturate_cast(this->val[i]); + return v; +} + +template inline +const _Tp& Vec<_Tp, cn>::operator [](int i) const +{ + CV_DbgAssert( (unsigned)i < (unsigned)cn ); + return this->val[i]; +} + +template inline +_Tp& Vec<_Tp, cn>::operator [](int i) +{ + CV_DbgAssert( (unsigned)i < (unsigned)cn ); + return this->val[i]; +} + +template inline +const _Tp& Vec<_Tp, cn>::operator ()(int i) const +{ + CV_DbgAssert( (unsigned)i < (unsigned)cn ); + return this->val[i]; +} + +template inline +_Tp& Vec<_Tp, cn>::operator ()(int i) +{ + CV_DbgAssert( (unsigned)i < (unsigned)cn ); + return this->val[i]; +} + +template inline +Vec<_Tp, cn> normalize(const Vec<_Tp, cn>& v) +{ + double nv = norm(v); + return v * (nv ? 1./nv : 0.); +} + + + +//////////////////////////////// matx comma initializer ////////////////////////////////// + + +template static inline +VecCommaInitializer<_Tp, cn> operator << (const Vec<_Tp, cn>& vec, _T2 val) +{ + VecCommaInitializer<_Tp, cn> commaInitializer((Vec<_Tp, cn>*)&vec); + return (commaInitializer, val); +} + +template inline +VecCommaInitializer<_Tp, cn>::VecCommaInitializer(Vec<_Tp, cn>* _vec) + : MatxCommaInitializer<_Tp, cn, 1>(_vec) +{} + +template template inline +VecCommaInitializer<_Tp, cn>& VecCommaInitializer<_Tp, cn>::operator , (_T2 value) +{ + CV_DbgAssert( this->idx < cn ); + this->dst->val[this->idx++] = saturate_cast<_Tp>(value); + return *this; +} + +template inline +Vec<_Tp, cn> VecCommaInitializer<_Tp, cn>::operator *() const +{ + CV_DbgAssert( this->idx == cn ); + return *this->dst; +} + + + +///////////////////////////// Matx out-of-class operators //////////////////////////////// + +template static inline +Matx<_Tp1, m, n>& operator += (Matx<_Tp1, m, n>& a, const Matx<_Tp2, m, n>& b) +{ + for( int i = 0; i < m*n; i++ ) + a.val[i] = saturate_cast<_Tp1>(a.val[i] + b.val[i]); + return a; +} + +template static inline +Matx<_Tp1, m, n>& operator -= (Matx<_Tp1, m, n>& a, const Matx<_Tp2, m, n>& b) +{ + for( int i = 0; i < m*n; i++ ) + a.val[i] = saturate_cast<_Tp1>(a.val[i] - b.val[i]); + return a; +} + +template static inline +Matx<_Tp, m, n> operator + (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b) +{ + return Matx<_Tp, m, n>(a, b, Matx_AddOp()); +} + +template static inline +Matx<_Tp, m, n> operator - (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b) +{ + return Matx<_Tp, m, n>(a, b, Matx_SubOp()); +} + +template static inline +Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, int alpha) +{ + for( int i = 0; i < m*n; i++ ) + a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); + return a; +} + +template static inline +Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, float alpha) +{ + for( int i = 0; i < m*n; i++ ) + a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); + return a; +} + +template static inline +Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, double alpha) +{ + for( int i = 0; i < m*n; i++ ) + a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); + return a; +} + +template static inline +Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, int alpha) +{ + return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, float alpha) +{ + return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, double alpha) +{ + return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Matx<_Tp, m, n> operator * (int alpha, const Matx<_Tp, m, n>& a) +{ + return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Matx<_Tp, m, n> operator * (float alpha, const Matx<_Tp, m, n>& a) +{ + return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Matx<_Tp, m, n> operator * (double alpha, const Matx<_Tp, m, n>& a) +{ + return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Matx<_Tp, m, n> operator - (const Matx<_Tp, m, n>& a) +{ + return Matx<_Tp, m, n>(a, -1, Matx_ScaleOp()); +} + +template static inline +Matx<_Tp, m, n> operator * (const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b) +{ + return Matx<_Tp, m, n>(a, b, Matx_MatMulOp()); +} + +template static inline +Vec<_Tp, m> operator * (const Matx<_Tp, m, n>& a, const Vec<_Tp, n>& b) +{ + Matx<_Tp, m, 1> c(a, b, Matx_MatMulOp()); + return (const Vec<_Tp, m>&)(c); +} + +template static inline +bool operator == (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b) +{ + for( int i = 0; i < m*n; i++ ) + if( a.val[i] != b.val[i] ) return false; + return true; +} + +template static inline +bool operator != (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b) +{ + return !(a == b); +} + + + +////////////////////////////// Vec out-of-class operators //////////////////////////////// + +template static inline +Vec<_Tp1, cn>& operator += (Vec<_Tp1, cn>& a, const Vec<_Tp2, cn>& b) +{ + for( int i = 0; i < cn; i++ ) + a.val[i] = saturate_cast<_Tp1>(a.val[i] + b.val[i]); + return a; +} + +template static inline +Vec<_Tp1, cn>& operator -= (Vec<_Tp1, cn>& a, const Vec<_Tp2, cn>& b) +{ + for( int i = 0; i < cn; i++ ) + a.val[i] = saturate_cast<_Tp1>(a.val[i] - b.val[i]); + return a; +} + +template static inline +Vec<_Tp, cn> operator + (const Vec<_Tp, cn>& a, const Vec<_Tp, cn>& b) +{ + return Vec<_Tp, cn>(a, b, Matx_AddOp()); +} + +template static inline +Vec<_Tp, cn> operator - (const Vec<_Tp, cn>& a, const Vec<_Tp, cn>& b) +{ + return Vec<_Tp, cn>(a, b, Matx_SubOp()); +} + +template static inline +Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, int alpha) +{ + for( int i = 0; i < cn; i++ ) + a[i] = saturate_cast<_Tp>(a[i]*alpha); + return a; +} + +template static inline +Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, float alpha) +{ + for( int i = 0; i < cn; i++ ) + a[i] = saturate_cast<_Tp>(a[i]*alpha); + return a; +} + +template static inline +Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, double alpha) +{ + for( int i = 0; i < cn; i++ ) + a[i] = saturate_cast<_Tp>(a[i]*alpha); + return a; +} + +template static inline +Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, int alpha) +{ + double ialpha = 1./alpha; + for( int i = 0; i < cn; i++ ) + a[i] = saturate_cast<_Tp>(a[i]*ialpha); + return a; +} + +template static inline +Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, float alpha) +{ + float ialpha = 1.f/alpha; + for( int i = 0; i < cn; i++ ) + a[i] = saturate_cast<_Tp>(a[i]*ialpha); + return a; +} + +template static inline +Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, double alpha) +{ + double ialpha = 1./alpha; + for( int i = 0; i < cn; i++ ) + a[i] = saturate_cast<_Tp>(a[i]*ialpha); + return a; +} + +template static inline +Vec<_Tp, cn> operator * (const Vec<_Tp, cn>& a, int alpha) +{ + return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator * (int alpha, const Vec<_Tp, cn>& a) +{ + return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator * (const Vec<_Tp, cn>& a, float alpha) +{ + return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator * (float alpha, const Vec<_Tp, cn>& a) +{ + return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator * (const Vec<_Tp, cn>& a, double alpha) +{ + return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator * (double alpha, const Vec<_Tp, cn>& a) +{ + return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator / (const Vec<_Tp, cn>& a, int alpha) +{ + return Vec<_Tp, cn>(a, 1./alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator / (const Vec<_Tp, cn>& a, float alpha) +{ + return Vec<_Tp, cn>(a, 1.f/alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator / (const Vec<_Tp, cn>& a, double alpha) +{ + return Vec<_Tp, cn>(a, 1./alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator - (const Vec<_Tp, cn>& a) +{ + Vec<_Tp,cn> t; + for( int i = 0; i < cn; i++ ) t.val[i] = saturate_cast<_Tp>(-a.val[i]); + return t; +} + +template inline Vec<_Tp, 4> operator * (const Vec<_Tp, 4>& v1, const Vec<_Tp, 4>& v2) +{ + return Vec<_Tp, 4>(saturate_cast<_Tp>(v1[0]*v2[0] - v1[1]*v2[1] - v1[2]*v2[2] - v1[3]*v2[3]), + saturate_cast<_Tp>(v1[0]*v2[1] + v1[1]*v2[0] + v1[2]*v2[3] - v1[3]*v2[2]), + saturate_cast<_Tp>(v1[0]*v2[2] - v1[1]*v2[3] + v1[2]*v2[0] + v1[3]*v2[1]), + saturate_cast<_Tp>(v1[0]*v2[3] + v1[1]*v2[2] - v1[2]*v2[1] + v1[3]*v2[0])); +} + +template inline Vec<_Tp, 4>& operator *= (Vec<_Tp, 4>& v1, const Vec<_Tp, 4>& v2) +{ + v1 = v1 * v2; + return v1; +} + +} // cv + +#endif // __OPENCV_CORE_MATX_HPP__ diff --git a/modules/core/include/opencv2/core/opengl.hpp b/modules/core/include/opencv2/core/opengl.hpp index 1643d39e0c..0a4b454c8a 100644 --- a/modules/core/include/opencv2/core/opengl.hpp +++ b/modules/core/include/opencv2/core/opengl.hpp @@ -22,7 +22,7 @@ // // * 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 GpuMaterials provided with the distribution. +// 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. @@ -40,10 +40,12 @@ // //M*/ -#ifndef __OPENCV_OPENGL_INTEROP_HPP__ -#define __OPENCV_OPENGL_INTEROP_HPP__ +#ifndef __OPENCV_CORE_OPENGL_HPP__ +#define __OPENCV_CORE_OPENGL_HPP__ -#ifdef __cplusplus +#ifndef __cplusplus +# error opengl.hpp header must be compiled as C++ +#endif #include "opencv2/core.hpp" @@ -86,7 +88,7 @@ public: //! create buffer void create(int arows, int acols, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false); - void create(Size asize, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false) { create(asize.height, asize.width, atype, target, autoRelease); } + void create(Size asize, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false); //! release memory and delete buffer object void release(); @@ -94,11 +96,15 @@ public: //! set auto release mode (if true, release will be called in object's destructor) void setAutoRelease(bool flag); - //! copy from host/device memory + //! copy from host/device memory (blocking) void copyFrom(InputArray arr, Target target = ARRAY_BUFFER, bool autoRelease = false); + //! copy from device memory (non blocking) + void copyFrom(InputArray arr, gpu::Stream& stream, Target target = ARRAY_BUFFER, bool autoRelease = false); - //! copy to host/device memory - void copyTo(OutputArray arr, Target target = ARRAY_BUFFER, bool autoRelease = false) const; + //! copy to host/device memory (blocking) + void copyTo(OutputArray arr) const; + //! copy to device memory (non blocking) + void copyTo(OutputArray arr, gpu::Stream& stream) const; //! create copy of current buffer Buffer clone(Target target = ARRAY_BUFFER, bool autoRelease = false) const; @@ -113,21 +119,26 @@ public: Mat mapHost(Access access); void unmapHost(); - //! map to device memory + //! map to device memory (blocking) gpu::GpuMat mapDevice(); void unmapDevice(); - int rows() const { return rows_; } - int cols() const { return cols_; } - Size size() const { return Size(cols_, rows_); } - bool empty() const { return rows_ == 0 || cols_ == 0; } + //! map to device memory (non blocking) + gpu::GpuMat mapDevice(gpu::Stream& stream); + void unmapDevice(gpu::Stream& stream); - int type() const { return type_; } - int depth() const { return CV_MAT_DEPTH(type_); } - int channels() const { return CV_MAT_CN(type_); } - int elemSize() const { return CV_ELEM_SIZE(type_); } - int elemSize1() const { return CV_ELEM_SIZE1(type_); } + int rows() const; + int cols() const; + Size size() const; + bool empty() const; + int type() const; + int depth() const; + int channels() const; + int elemSize() const; + int elemSize1() const; + + //! get OpenGL opject id unsigned int bufId() const; class Impl; @@ -167,7 +178,7 @@ public: //! create texture void create(int arows, int acols, Format aformat, bool autoRelease = false); - void create(Size asize, Format aformat, bool autoRelease = false) { create(asize.height, asize.width, aformat, autoRelease); } + void create(Size asize, Format aformat, bool autoRelease = false); //! release memory and delete texture object void release(); @@ -184,13 +195,14 @@ public: //! bind texture to current active texture unit for GL_TEXTURE_2D target void bind() const; - int rows() const { return rows_; } - int cols() const { return cols_; } - Size size() const { return Size(cols_, rows_); } - bool empty() const { return rows_ == 0 || cols_ == 0; } + int rows() const; + int cols() const; + Size size() const; + bool empty() const; - Format format() const { return format_; } + Format format() const; + //! get OpenGL opject id unsigned int texId() const; class Impl; @@ -226,8 +238,8 @@ public: void bind() const; - int size() const { return size_; } - bool empty() const { return size_ == 0; } + int size() const; + bool empty() const; private: int size_; @@ -262,7 +274,7 @@ enum { CV_EXPORTS void render(const Arrays& arr, int mode = POINTS, Scalar color = Scalar::all(255)); CV_EXPORTS void render(const Arrays& arr, InputArray indices, int mode = POINTS, Scalar color = Scalar::all(255)); -}} // namespace cv::gl +}} // namespace cv::ogl namespace cv { namespace gpu { @@ -271,13 +283,150 @@ CV_EXPORTS void setGlDevice(int device = 0); }} -namespace cv { -template <> CV_EXPORTS void Ptr::delete_obj(); -template <> CV_EXPORTS void Ptr::delete_obj(); +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +inline +cv::ogl::Buffer::Buffer(int arows, int acols, int atype, Target target, bool autoRelease) : rows_(0), cols_(0), type_(0) +{ + create(arows, acols, atype, target, autoRelease); } -#endif // __cplusplus +inline +cv::ogl::Buffer::Buffer(Size asize, int atype, Target target, bool autoRelease) : rows_(0), cols_(0), type_(0) +{ + create(asize, atype, target, autoRelease); +} -#endif // __OPENCV_OPENGL_INTEROP_HPP__ +inline +void cv::ogl::Buffer::create(Size asize, int atype, Target target, bool autoRelease) +{ + create(asize.height, asize.width, atype, target, autoRelease); +} + +inline +int cv::ogl::Buffer::rows() const +{ + return rows_; +} + +inline +int cv::ogl::Buffer::cols() const +{ + return cols_; +} + +inline +cv::Size cv::ogl::Buffer::size() const +{ + return Size(cols_, rows_); +} + +inline +bool cv::ogl::Buffer::empty() const +{ + return rows_ == 0 || cols_ == 0; +} + +inline +int cv::ogl::Buffer::type() const +{ + return type_; +} + +inline +int cv::ogl::Buffer::depth() const +{ + return CV_MAT_DEPTH(type_); +} + +inline +int cv::ogl::Buffer::channels() const +{ + return CV_MAT_CN(type_); +} + +inline +int cv::ogl::Buffer::elemSize() const +{ + return CV_ELEM_SIZE(type_); +} + +inline +int cv::ogl::Buffer::elemSize1() const +{ + return CV_ELEM_SIZE1(type_); +} + +/////// + +inline +cv::ogl::Texture2D::Texture2D(int arows, int acols, Format aformat, bool autoRelease) : rows_(0), cols_(0), format_(NONE) +{ + create(arows, acols, aformat, autoRelease); +} + +inline +cv::ogl::Texture2D::Texture2D(Size asize, Format aformat, bool autoRelease) : rows_(0), cols_(0), format_(NONE) +{ + create(asize, aformat, autoRelease); +} + +inline +void cv::ogl::Texture2D::create(Size asize, Format aformat, bool autoRelease) +{ + create(asize.height, asize.width, aformat, autoRelease); +} + +inline +int cv::ogl::Texture2D::rows() const +{ + return rows_; +} + +inline +int cv::ogl::Texture2D::cols() const +{ + return cols_; +} + +inline +cv::Size cv::ogl::Texture2D::size() const +{ + return Size(cols_, rows_); +} + +inline +bool cv::ogl::Texture2D::empty() const +{ + return rows_ == 0 || cols_ == 0; +} + +inline +cv::ogl::Texture2D::Format cv::ogl::Texture2D::format() const +{ + return format_; +} + +/////// + +inline +cv::ogl::Arrays::Arrays() : size_(0) +{ +} + +inline +int cv::ogl::Arrays::size() const +{ + return size_; +} + +inline +bool cv::ogl::Arrays::empty() const +{ + return size_ == 0; +} + +#endif /* __OPENCV_CORE_OPENGL_HPP__ */ diff --git a/modules/core/include/opencv2/core/operations.hpp b/modules/core/include/opencv2/core/operations.hpp index c259b892bc..f8aeddfb11 100644 --- a/modules/core/include/opencv2/core/operations.hpp +++ b/modules/core/include/opencv2/core/operations.hpp @@ -43,692 +43,21 @@ #ifndef __OPENCV_CORE_OPERATIONS_HPP__ #define __OPENCV_CORE_OPERATIONS_HPP__ -#ifndef SKIP_INCLUDES - #include - #include -#endif // SKIP_INCLUDES - - -#ifdef __cplusplus - -#include - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable:4127) //conditional expression is constant +#ifndef __cplusplus +# error operations.hpp header must be compiled as C++ #endif +#include + namespace cv { -/////////////// saturate_cast (used in image & signal processing) /////////////////// +////////////////////////////// Matx methods depending on core API ///////////////////////////// -template static inline _Tp saturate_cast(uchar v) { return _Tp(v); } -template static inline _Tp saturate_cast(schar v) { return _Tp(v); } -template static inline _Tp saturate_cast(ushort v) { return _Tp(v); } -template static inline _Tp saturate_cast(short v) { return _Tp(v); } -template static inline _Tp saturate_cast(unsigned v) { return _Tp(v); } -template static inline _Tp saturate_cast(int v) { return _Tp(v); } -template static inline _Tp saturate_cast(float v) { return _Tp(v); } -template static inline _Tp saturate_cast(double v) { return _Tp(v); } - -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); } -template<> inline uchar saturate_cast(short v) -{ return saturate_cast((int)v); } -template<> inline uchar saturate_cast(unsigned v) -{ return (uchar)std::min(v, (unsigned)UCHAR_MAX); } -template<> inline uchar saturate_cast(float v) -{ int iv = cvRound(v); return saturate_cast(iv); } -template<> inline uchar saturate_cast(double v) -{ int iv = cvRound(v); return saturate_cast(iv); } - -template<> inline schar saturate_cast(uchar v) -{ return (schar)std::min((int)v, SCHAR_MAX); } -template<> inline schar saturate_cast(ushort v) -{ return (schar)std::min((unsigned)v, (unsigned)SCHAR_MAX); } -template<> inline schar saturate_cast(int v) -{ - return (schar)((unsigned)(v-SCHAR_MIN) <= (unsigned)UCHAR_MAX ? - v : v > 0 ? SCHAR_MAX : SCHAR_MIN); -} -template<> inline schar saturate_cast(short v) -{ return saturate_cast((int)v); } -template<> inline schar saturate_cast(unsigned v) -{ return (schar)std::min(v, (unsigned)SCHAR_MAX); } - -template<> inline schar saturate_cast(float v) -{ int iv = cvRound(v); return saturate_cast(iv); } -template<> inline schar saturate_cast(double v) -{ int iv = cvRound(v); return saturate_cast(iv); } - -template<> inline ushort saturate_cast(schar v) -{ return (ushort)std::max((int)v, 0); } -template<> inline ushort saturate_cast(short v) -{ return (ushort)std::max((int)v, 0); } -template<> inline ushort saturate_cast(int v) -{ return (ushort)((unsigned)v <= (unsigned)USHRT_MAX ? v : v > 0 ? USHRT_MAX : 0); } -template<> inline ushort saturate_cast(unsigned v) -{ return (ushort)std::min(v, (unsigned)USHRT_MAX); } -template<> inline ushort saturate_cast(float v) -{ int iv = cvRound(v); return saturate_cast(iv); } -template<> inline ushort saturate_cast(double v) -{ int iv = cvRound(v); return saturate_cast(iv); } - -template<> inline short saturate_cast(ushort v) -{ return (short)std::min((int)v, SHRT_MAX); } -template<> inline short saturate_cast(int v) -{ - return (short)((unsigned)(v - SHRT_MIN) <= (unsigned)USHRT_MAX ? - v : v > 0 ? SHRT_MAX : SHRT_MIN); -} -template<> inline short saturate_cast(unsigned v) -{ return (short)std::min(v, (unsigned)SHRT_MAX); } -template<> inline short saturate_cast(float v) -{ int iv = cvRound(v); return saturate_cast(iv); } -template<> inline short saturate_cast(double v) -{ int iv = cvRound(v); return saturate_cast(iv); } - -template<> inline int saturate_cast(float v) { return cvRound(v); } -template<> inline int saturate_cast(double v) { return cvRound(v); } - -// we intentionally do not clip negative numbers, to make -1 become 0xffffffff etc. -template<> inline unsigned saturate_cast(float v){ return cvRound(v); } -template<> inline unsigned saturate_cast(double v) { return cvRound(v); } - -inline int fast_abs(uchar v) { return v; } -inline int fast_abs(schar v) { return std::abs((int)v); } -inline int fast_abs(ushort v) { return v; } -inline int fast_abs(short v) { return std::abs((int)v); } -inline int fast_abs(int v) { return std::abs(v); } -inline float fast_abs(float v) { return std::abs(v); } -inline double fast_abs(double v) { return std::abs(v); } - -//////////////////////////////// Matx ///////////////////////////////// - - -template inline Matx<_Tp, m, n>::Matx() -{ - for(int i = 0; i < channels; i++) val[i] = _Tp(0); -} - -template inline Matx<_Tp, m, n>::Matx(_Tp v0) -{ - val[0] = v0; - for(int i = 1; i < channels; i++) val[i] = _Tp(0); -} - -template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1) -{ - assert(channels >= 2); - val[0] = v0; val[1] = v1; - for(int i = 2; i < channels; i++) val[i] = _Tp(0); -} - -template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2) -{ - assert(channels >= 3); - val[0] = v0; val[1] = v1; val[2] = v2; - for(int i = 3; i < channels; i++) val[i] = _Tp(0); -} - -template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3) -{ - assert(channels >= 4); - val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; - for(int i = 4; i < channels; i++) val[i] = _Tp(0); -} - -template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4) -{ - assert(channels >= 5); - 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); -} - -template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, - _Tp v4, _Tp v5) -{ - assert(channels >= 6); - 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); -} - -template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, - _Tp v4, _Tp v5, _Tp v6) -{ - assert(channels >= 7); - 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); -} - -template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, - _Tp v4, _Tp v5, _Tp v6, _Tp v7) -{ - assert(channels >= 8); - 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); -} - -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) -{ - assert(channels >= 9); - 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; - for(int i = 9; 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) -{ - assert(channels >= 10); - 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; - for(int i = 10; 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) -{ - assert(channels == 12); - 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; -} - -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) -{ - assert(channels == 16); - 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; -} - -template inline Matx<_Tp, m, n>::Matx(const _Tp* values) -{ - for( int i = 0; i < channels; i++ ) val[i] = values[i]; -} - -template inline Matx<_Tp, m, n> Matx<_Tp, m, n>::all(_Tp alpha) -{ - Matx<_Tp, m, n> M; - for( int i = 0; i < m*n; i++ ) M.val[i] = alpha; - return M; -} - -template inline -Matx<_Tp,m,n> Matx<_Tp,m,n>::zeros() -{ - return all(0); -} - -template inline -Matx<_Tp,m,n> Matx<_Tp,m,n>::ones() -{ - return all(1); -} - -template inline -Matx<_Tp,m,n> Matx<_Tp,m,n>::eye() -{ - Matx<_Tp,m,n> M; - for(int i = 0; i < MIN(m,n); i++) - M(i,i) = 1; - return M; -} - -template inline _Tp Matx<_Tp, m, n>::dot(const Matx<_Tp, m, n>& M) const -{ - _Tp s = 0; - for( int i = 0; i < m*n; i++ ) s += val[i]*M.val[i]; - return s; -} - - -template inline double Matx<_Tp, m, n>::ddot(const Matx<_Tp, m, n>& M) const -{ - double s = 0; - for( int i = 0; i < m*n; i++ ) s += (double)val[i]*M.val[i]; - return s; -} - - - -template inline -Matx<_Tp,m,n> Matx<_Tp,m,n>::diag(const typename Matx<_Tp,m,n>::diag_type& d) -{ - Matx<_Tp,m,n> M; - for(int i = 0; i < MIN(m,n); i++) - M(i,i) = d(i, 0); - return M; -} - -template inline -Matx<_Tp,m,n> Matx<_Tp,m,n>::randu(_Tp a, _Tp b) -{ - Matx<_Tp,m,n> M; - Mat matM(M, false); - cv::randu(matM, Scalar(a), Scalar(b)); - return M; -} - -template inline -Matx<_Tp,m,n> Matx<_Tp,m,n>::randn(_Tp a, _Tp b) -{ - Matx<_Tp,m,n> M; - Mat matM(M, false); - cv::randn(matM, Scalar(a), Scalar(b)); - return M; -} - -template template -inline Matx<_Tp, m, n>::operator Matx() const -{ - Matx M; - for( int i = 0; i < m*n; i++ ) M.val[i] = saturate_cast(val[i]); - return M; -} - - -template template inline -Matx<_Tp, m1, n1> Matx<_Tp, m, n>::reshape() const -{ - CV_DbgAssert(m1*n1 == m*n); - return (const Matx<_Tp, m1, n1>&)*this; -} - - -template -template inline -Matx<_Tp, m1, n1> Matx<_Tp, m, n>::get_minor(int i, int j) const -{ - CV_DbgAssert(0 <= i && i+m1 <= m && 0 <= j && j+n1 <= n); - Matx<_Tp, m1, n1> s; - for( int di = 0; di < m1; di++ ) - for( int dj = 0; dj < n1; dj++ ) - s(di, dj) = (*this)(i+di, j+dj); - return s; -} - - -template inline -Matx<_Tp, 1, n> Matx<_Tp, m, n>::row(int i) const -{ - CV_DbgAssert((unsigned)i < (unsigned)m); - return Matx<_Tp, 1, n>(&val[i*n]); -} - - -template inline -Matx<_Tp, m, 1> Matx<_Tp, m, n>::col(int j) const -{ - CV_DbgAssert((unsigned)j < (unsigned)n); - Matx<_Tp, m, 1> v; - for( int i = 0; i < m; i++ ) - v.val[i] = val[i*n + j]; - return v; -} - - -template inline -typename Matx<_Tp, m, n>::diag_type Matx<_Tp, m, n>::diag() const -{ - diag_type d; - for( int i = 0; i < MIN(m, n); i++ ) - d.val[i] = val[i*n + i]; - return d; -} - - -template inline -const _Tp& Matx<_Tp, m, n>::operator ()(int i, int j) const -{ - CV_DbgAssert( (unsigned)i < (unsigned)m && (unsigned)j < (unsigned)n ); - return this->val[i*n + j]; -} - - -template inline -_Tp& Matx<_Tp, m, n>::operator ()(int i, int j) -{ - CV_DbgAssert( (unsigned)i < (unsigned)m && (unsigned)j < (unsigned)n ); - return val[i*n + j]; -} - - -template inline -const _Tp& Matx<_Tp, m, n>::operator ()(int i) const -{ - CV_DbgAssert( (m == 1 || n == 1) && (unsigned)i < (unsigned)(m+n-1) ); - return val[i]; -} - - -template inline -_Tp& Matx<_Tp, m, n>::operator ()(int i) -{ - CV_DbgAssert( (m == 1 || n == 1) && (unsigned)i < (unsigned)(m+n-1) ); - return val[i]; -} - - -template static inline -Matx<_Tp1, m, n>& operator += (Matx<_Tp1, m, n>& a, const Matx<_Tp2, m, n>& b) -{ - for( int i = 0; i < m*n; i++ ) - a.val[i] = saturate_cast<_Tp1>(a.val[i] + b.val[i]); - return a; -} - - -template static inline -Matx<_Tp1, m, n>& operator -= (Matx<_Tp1, m, n>& a, const Matx<_Tp2, m, n>& b) +namespace internal { - for( int i = 0; i < m*n; i++ ) - a.val[i] = saturate_cast<_Tp1>(a.val[i] - b.val[i]); - return a; -} - - -template inline -Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_AddOp) -{ - for( int i = 0; i < m*n; i++ ) - val[i] = saturate_cast<_Tp>(a.val[i] + b.val[i]); -} - - -template inline -Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_SubOp) -{ - for( int i = 0; i < m*n; i++ ) - val[i] = saturate_cast<_Tp>(a.val[i] - b.val[i]); -} - - -template template inline -Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, _T2 alpha, Matx_ScaleOp) -{ - for( int i = 0; i < m*n; i++ ) - val[i] = saturate_cast<_Tp>(a.val[i] * alpha); -} - - -template inline -Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_MulOp) -{ - for( int i = 0; i < m*n; i++ ) - val[i] = saturate_cast<_Tp>(a.val[i] * b.val[i]); -} - - -template template inline -Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b, Matx_MatMulOp) -{ - for( int i = 0; i < m; i++ ) - for( int j = 0; j < n; j++ ) - { - _Tp s = 0; - for( int k = 0; k < l; k++ ) - s += a(i, k) * b(k, j); - val[i*n + j] = s; - } -} - - -template inline -Matx<_Tp,m,n>::Matx(const Matx<_Tp, n, m>& a, Matx_TOp) -{ - for( int i = 0; i < m; i++ ) - for( int j = 0; j < n; j++ ) - val[i*n + j] = a(j, i); -} - - -template static inline -Matx<_Tp, m, n> operator + (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b) -{ - return Matx<_Tp, m, n>(a, b, Matx_AddOp()); -} - - -template static inline -Matx<_Tp, m, n> operator - (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b) -{ - return Matx<_Tp, m, n>(a, b, Matx_SubOp()); -} - - -template static inline -Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, int alpha) -{ - for( int i = 0; i < m*n; i++ ) - a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); - return a; -} - -template static inline -Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, float alpha) -{ - for( int i = 0; i < m*n; i++ ) - a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); - return a; -} - -template static inline -Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, double alpha) -{ - for( int i = 0; i < m*n; i++ ) - a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); - return a; -} - -template static inline -Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, int alpha) -{ - return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); -} - -template static inline -Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, float alpha) -{ - return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); -} - -template static inline -Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, double alpha) -{ - return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); -} - -template static inline -Matx<_Tp, m, n> operator * (int alpha, const Matx<_Tp, m, n>& a) -{ - return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); -} - -template static inline -Matx<_Tp, m, n> operator * (float alpha, const Matx<_Tp, m, n>& a) -{ - return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); -} - -template static inline -Matx<_Tp, m, n> operator * (double alpha, const Matx<_Tp, m, n>& a) -{ - return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); -} - -template static inline -Matx<_Tp, m, n> operator - (const Matx<_Tp, m, n>& a) -{ - return Matx<_Tp, m, n>(a, -1, Matx_ScaleOp()); -} - - -template static inline -Matx<_Tp, m, n> operator * (const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b) -{ - return Matx<_Tp, m, n>(a, b, Matx_MatMulOp()); -} - - -template static inline -Vec<_Tp, m> operator * (const Matx<_Tp, m, n>& a, const Vec<_Tp, n>& b) -{ - Matx<_Tp, m, 1> c(a, b, Matx_MatMulOp()); - return reinterpret_cast&>(c); -} - - -template static inline -Point_<_Tp> operator * (const Matx<_Tp, 2, 2>& a, const Point_<_Tp>& b) -{ - Matx<_Tp, 2, 1> tmp = a*Vec<_Tp,2>(b.x, b.y); - return Point_<_Tp>(tmp.val[0], tmp.val[1]); -} - - -template static inline -Point3_<_Tp> operator * (const Matx<_Tp, 3, 3>& a, const Point3_<_Tp>& b) -{ - Matx<_Tp, 3, 1> tmp = a*Vec<_Tp,3>(b.x, b.y, b.z); - return Point3_<_Tp>(tmp.val[0], tmp.val[1], tmp.val[2]); -} - - -template static inline -Point3_<_Tp> operator * (const Matx<_Tp, 3, 3>& a, const Point_<_Tp>& b) -{ - Matx<_Tp, 3, 1> tmp = a*Vec<_Tp,3>(b.x, b.y, 1); - return Point3_<_Tp>(tmp.val[0], tmp.val[1], tmp.val[2]); -} - - -template static inline -Matx<_Tp, 4, 1> operator * (const Matx<_Tp, 4, 4>& a, const Point3_<_Tp>& b) -{ - return a*Matx<_Tp, 4, 1>(b.x, b.y, b.z, 1); -} - - -template static inline -Scalar operator * (const Matx<_Tp, 4, 4>& a, const Scalar& b) -{ - Matx c(Matx(a), b, Matx_MatMulOp()); - return reinterpret_cast(c); -} - - -static inline -Scalar operator * (const Matx& a, const Scalar& b) -{ - Matx c(a, b, Matx_MatMulOp()); - return reinterpret_cast(c); -} - - -template inline -Matx<_Tp, m, n> Matx<_Tp, m, n>::mul(const Matx<_Tp, m, n>& a) const -{ - return Matx<_Tp, m, n>(*this, a, Matx_MulOp()); -} - - -CV_EXPORTS int LU(float* A, size_t astep, int m, float* b, size_t bstep, int n); -CV_EXPORTS int LU(double* A, size_t astep, int m, double* b, size_t bstep, int n); -CV_EXPORTS bool Cholesky(float* A, size_t astep, int m, float* b, size_t bstep, int n); -CV_EXPORTS bool Cholesky(double* A, size_t astep, int m, double* b, size_t bstep, int n); - - -template struct CV_EXPORTS Matx_DetOp -{ - double operator ()(const Matx<_Tp, m, m>& a) const - { - Matx<_Tp, m, m> temp = a; - double p = LU(temp.val, m*sizeof(_Tp), m, 0, 0, 0); - if( p == 0 ) - return p; - for( int i = 0; i < m; i++ ) - p *= temp(i, i); - return 1./p; - } -}; - - -template struct CV_EXPORTS Matx_DetOp<_Tp, 1> -{ - double operator ()(const Matx<_Tp, 1, 1>& a) const - { - return a(0,0); - } -}; - - -template struct CV_EXPORTS Matx_DetOp<_Tp, 2> -{ - double operator ()(const Matx<_Tp, 2, 2>& a) const - { - return a(0,0)*a(1,1) - a(0,1)*a(1,0); - } -}; - - -template struct CV_EXPORTS Matx_DetOp<_Tp, 3> -{ - double operator ()(const Matx<_Tp, 3, 3>& a) const - { - return a(0,0)*(a(1,1)*a(2,2) - a(2,1)*a(1,2)) - - a(0,1)*(a(1,0)*a(2,2) - a(2,0)*a(1,2)) + - a(0,2)*(a(1,0)*a(2,1) - a(2,0)*a(1,1)); - } -}; - -template static inline -double determinant(const Matx<_Tp, m, m>& a) -{ - return Matx_DetOp<_Tp, m>()(a); -} - - -template static inline -double trace(const Matx<_Tp, m, n>& a) -{ - _Tp s = 0; - for( int i = 0; i < std::min(m, n); i++ ) - s += a(i,i); - return s; -} - - -template inline -Matx<_Tp, n, m> Matx<_Tp, m, n>::t() const -{ - return Matx<_Tp, n, m>(*this, Matx_TOp()); -} - -template struct CV_EXPORTS Matx_FastInvOp +template struct Matx_FastInvOp { bool operator()(const Matx<_Tp, m, m>& a, Matx<_Tp, m, m>& b, int method) const { @@ -745,8 +74,7 @@ template struct CV_EXPORTS Matx_FastInvOp } }; - -template struct CV_EXPORTS Matx_FastInvOp<_Tp, 2> +template struct Matx_FastInvOp<_Tp, 2> { bool operator()(const Matx<_Tp, 2, 2>& a, Matx<_Tp, 2, 2>& b, int) const { @@ -762,8 +90,7 @@ template struct CV_EXPORTS Matx_FastInvOp<_Tp, 2> } }; - -template struct CV_EXPORTS Matx_FastInvOp<_Tp, 3> +template struct Matx_FastInvOp<_Tp, 3> { bool operator()(const Matx<_Tp, 3, 3>& a, Matx<_Tp, 3, 3>& b, int) const { @@ -787,23 +114,7 @@ template struct CV_EXPORTS Matx_FastInvOp<_Tp, 3> }; -template inline -Matx<_Tp, n, m> Matx<_Tp, m, n>::inv(int method) const -{ - Matx<_Tp, n, m> b; - bool ok; - if( method == DECOMP_LU || method == DECOMP_CHOLESKY ) - ok = Matx_FastInvOp<_Tp, m>()(*this, b, method); - else - { - Mat A(*this, false), B(b, false); - ok = (invert(A, B, method) != 0); - } - return ok ? b : Matx<_Tp, n, m>::zeros(); -} - - -template struct CV_EXPORTS Matx_FastSolveOp +template struct Matx_FastSolveOp { bool operator()(const Matx<_Tp, m, m>& a, const Matx<_Tp, m, n>& b, Matx<_Tp, m, n>& x, int method) const @@ -817,8 +128,7 @@ template struct CV_EXPORTS Matx_FastSolveOp } }; - -template struct CV_EXPORTS Matx_FastSolveOp<_Tp, 2, 1> +template struct Matx_FastSolveOp<_Tp, 2, 1> { bool operator()(const Matx<_Tp, 2, 2>& a, const Matx<_Tp, 2, 1>& b, Matx<_Tp, 2, 1>& x, int) const @@ -833,8 +143,7 @@ template struct CV_EXPORTS Matx_FastSolveOp<_Tp, 2, 1> } }; - -template struct CV_EXPORTS Matx_FastSolveOp<_Tp, 3, 1> +template struct Matx_FastSolveOp<_Tp, 3, 1> { bool operator()(const Matx<_Tp, 3, 3>& a, const Matx<_Tp, 3, 1>& b, Matx<_Tp, 3, 1>& x, int) const @@ -858,6 +167,38 @@ template struct CV_EXPORTS Matx_FastSolveOp<_Tp, 3, 1> } }; +} // internal + +template inline +Matx<_Tp,m,n> Matx<_Tp,m,n>::randu(_Tp a, _Tp b) +{ + Matx<_Tp,m,n> M; + cv::randu(M, Scalar(a), Scalar(b)); + return M; +} + +template inline +Matx<_Tp,m,n> Matx<_Tp,m,n>::randn(_Tp a, _Tp b) +{ + Matx<_Tp,m,n> M; + cv::randn(M, Scalar(a), Scalar(b)); + return M; +} + +template inline +Matx<_Tp, n, m> Matx<_Tp, m, n>::inv(int method) const +{ + Matx<_Tp, n, m> b; + bool ok; + if( method == DECOMP_LU || method == DECOMP_CHOLESKY ) + ok = internal::Matx_FastInvOp<_Tp, m>()(*this, b, method); + else + { + Mat A(*this, false), B(b, false); + ok = (invert(A, B, method) != 0); + } + return ok ? b : Matx<_Tp, n, m>::zeros(); +} template template inline Matx<_Tp, n, l> Matx<_Tp, m, n>::solve(const Matx<_Tp, m, l>& rhs, int method) const @@ -865,7 +206,7 @@ Matx<_Tp, n, l> Matx<_Tp, m, n>::solve(const Matx<_Tp, m, l>& rhs, int method) c Matx<_Tp, n, l> x; bool ok; if( method == DECOMP_LU || method == DECOMP_CHOLESKY ) - ok = Matx_FastSolveOp<_Tp, m, l>()(*this, rhs, x, method); + ok = internal::Matx_FastSolveOp<_Tp, m, l>()(*this, rhs, x, method); else { Mat A(*this, false), B(rhs, false), X(x, false); @@ -875,1606 +216,169 @@ Matx<_Tp, n, l> Matx<_Tp, m, n>::solve(const Matx<_Tp, m, l>& rhs, int method) c return ok ? x : Matx<_Tp, n, l>::zeros(); } -template inline -Vec<_Tp, n> Matx<_Tp, m, n>::solve(const Vec<_Tp, m>& rhs, int method) const -{ - Matx<_Tp, n, 1> x = solve(reinterpret_cast&>(rhs), method); - return reinterpret_cast&>(x); -} - -template static inline -_AccTp normL2Sqr(const _Tp* a, int n) -{ - _AccTp s = 0; - int i=0; - #if CV_ENABLE_UNROLLED - for( ; i <= n - 4; i += 4 ) - { - _AccTp v0 = a[i], v1 = a[i+1], v2 = a[i+2], v3 = a[i+3]; - s += v0*v0 + v1*v1 + v2*v2 + v3*v3; - } -#endif - for( ; i < n; i++ ) - { - _AccTp v = a[i]; - s += v*v; - } - return s; -} - - -template static inline -_AccTp normL1(const _Tp* a, int n) -{ - _AccTp s = 0; - int i = 0; -#if CV_ENABLE_UNROLLED - for(; i <= n - 4; i += 4 ) - { - s += (_AccTp)fast_abs(a[i]) + (_AccTp)fast_abs(a[i+1]) + - (_AccTp)fast_abs(a[i+2]) + (_AccTp)fast_abs(a[i+3]); - } -#endif - for( ; i < n; i++ ) - s += fast_abs(a[i]); - return s; -} - - -template static inline -_AccTp normInf(const _Tp* a, int n) -{ - _AccTp s = 0; - for( int i = 0; i < n; i++ ) - s = std::max(s, (_AccTp)fast_abs(a[i])); - return s; -} - - -template static inline -_AccTp normL2Sqr(const _Tp* a, const _Tp* b, int n) -{ - _AccTp s = 0; - int i= 0; -#if CV_ENABLE_UNROLLED - for(; i <= n - 4; i += 4 ) - { - _AccTp v0 = _AccTp(a[i] - b[i]), v1 = _AccTp(a[i+1] - b[i+1]), v2 = _AccTp(a[i+2] - b[i+2]), v3 = _AccTp(a[i+3] - b[i+3]); - s += v0*v0 + v1*v1 + v2*v2 + v3*v3; - } -#endif - for( ; i < n; i++ ) - { - _AccTp v = _AccTp(a[i] - b[i]); - s += v*v; - } - return s; -} - -CV_EXPORTS float normL2Sqr_(const float* a, const float* b, int n); -CV_EXPORTS float normL1_(const float* a, const float* b, int n); -CV_EXPORTS int normL1_(const uchar* a, const uchar* b, int n); -CV_EXPORTS int normHamming(const uchar* a, const uchar* b, int n); -CV_EXPORTS int normHamming(const uchar* a, const uchar* b, int n, int cellSize); - -template<> inline float normL2Sqr(const float* a, const float* b, int n) -{ - if( n >= 8 ) - return normL2Sqr_(a, b, n); - float s = 0; - for( int i = 0; i < n; i++ ) - { - float v = a[i] - b[i]; - s += v*v; - } - return s; -} - - -template static inline -_AccTp normL1(const _Tp* a, const _Tp* b, int n) -{ - _AccTp s = 0; - int i= 0; -#if CV_ENABLE_UNROLLED - for(; i <= n - 4; i += 4 ) - { - _AccTp v0 = _AccTp(a[i] - b[i]), v1 = _AccTp(a[i+1] - b[i+1]), v2 = _AccTp(a[i+2] - b[i+2]), v3 = _AccTp(a[i+3] - b[i+3]); - s += std::abs(v0) + std::abs(v1) + std::abs(v2) + std::abs(v3); - } -#endif - for( ; i < n; i++ ) - { - _AccTp v = _AccTp(a[i] - b[i]); - s += std::abs(v); - } - return s; -} - -template<> inline float normL1(const float* a, const float* b, int n) -{ - if( n >= 8 ) - return normL1_(a, b, n); - float s = 0; - for( int i = 0; i < n; i++ ) - { - float v = a[i] - b[i]; - s += std::abs(v); - } - return s; -} - -template<> inline int normL1(const uchar* a, const uchar* b, int n) -{ - return normL1_(a, b, n); -} - -template static inline -_AccTp normInf(const _Tp* a, const _Tp* b, int n) -{ - _AccTp s = 0; - for( int i = 0; i < n; i++ ) - { - _AccTp v0 = a[i] - b[i]; - s = std::max(s, std::abs(v0)); - } - return s; -} - - -template static inline -double norm(const Matx<_Tp, m, n>& M) -{ - return std::sqrt(normL2Sqr<_Tp, double>(M.val, m*n)); -} - - -template static inline -double norm(const Matx<_Tp, m, n>& M, int normType) -{ - return normType == NORM_INF ? (double)normInf<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n) : - normType == NORM_L1 ? (double)normL1<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n) : - std::sqrt((double)normL2Sqr<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n)); -} - - -template static inline -bool operator == (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b) -{ - for( int i = 0; i < m*n; i++ ) - if( a.val[i] != b.val[i] ) return false; - return true; -} - -template static inline -bool operator != (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b) -{ - return !(a == b); -} - - -template static inline -MatxCommaInitializer<_Tp, m, n> operator << (const Matx<_Tp, m, n>& mtx, _T2 val) -{ - MatxCommaInitializer<_Tp, m, n> commaInitializer((Matx<_Tp, m, n>*)&mtx); - return (commaInitializer, val); -} - -template inline -MatxCommaInitializer<_Tp, m, n>::MatxCommaInitializer(Matx<_Tp, m, n>* _mtx) - : dst(_mtx), idx(0) -{} - -template template inline -MatxCommaInitializer<_Tp, m, n>& MatxCommaInitializer<_Tp, m, n>::operator , (_T2 value) -{ - CV_DbgAssert( idx < m*n ); - dst->val[idx++] = saturate_cast<_Tp>(value); - return *this; -} - -template inline -Matx<_Tp, m, n> MatxCommaInitializer<_Tp, m, n>::operator *() const -{ - CV_DbgAssert( idx == n*m ); - return *dst; -} - -/////////////////////////// short vector (Vec) ///////////////////////////// - -template inline Vec<_Tp, cn>::Vec() -{} - -template inline Vec<_Tp, cn>::Vec(_Tp v0) - : Matx<_Tp, cn, 1>(v0) -{} - -template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1) - : Matx<_Tp, cn, 1>(v0, v1) -{} - -template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2) - : Matx<_Tp, cn, 1>(v0, v1, v2) -{} - -template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3) - : Matx<_Tp, cn, 1>(v0, v1, v2, v3) -{} - -template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4) - : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4) -{} - -template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5) - : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5) -{} - -template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, - _Tp v4, _Tp v5, _Tp v6) - : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6) -{} - -template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, - _Tp v4, _Tp v5, _Tp v6, _Tp v7) - : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6, v7) -{} - -template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, - _Tp v4, _Tp v5, _Tp v6, _Tp v7, - _Tp v8) - : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6, v7, v8) -{} - -template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, - _Tp v4, _Tp v5, _Tp v6, _Tp v7, - _Tp v8, _Tp v9) - : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) -{} - -template inline Vec<_Tp, cn>::Vec(const _Tp* values) - : Matx<_Tp, cn, 1>(values) -{} - - -template inline Vec<_Tp, cn>::Vec(const Vec<_Tp, cn>& m) - : Matx<_Tp, cn, 1>(m.val) -{} - -template inline -Vec<_Tp, cn>::Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_AddOp op) -: Matx<_Tp, cn, 1>(a, b, op) -{} - -template inline -Vec<_Tp, cn>::Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_SubOp op) -: Matx<_Tp, cn, 1>(a, b, op) -{} - -template template inline -Vec<_Tp, cn>::Vec(const Matx<_Tp, cn, 1>& a, _T2 alpha, Matx_ScaleOp op) -: Matx<_Tp, cn, 1>(a, alpha, op) -{} - -template inline Vec<_Tp, cn> Vec<_Tp, cn>::all(_Tp alpha) -{ - Vec v; - for( int i = 0; i < cn; i++ ) v.val[i] = alpha; - return v; -} - -template inline Vec<_Tp, cn> Vec<_Tp, cn>::mul(const Vec<_Tp, cn>& v) const -{ - Vec<_Tp, cn> w; - for( int i = 0; i < cn; i++ ) w.val[i] = saturate_cast<_Tp>(this->val[i]*v.val[i]); - return w; -} - -template Vec<_Tp, 2> conjugate(const Vec<_Tp, 2>& v) -{ - return Vec<_Tp, 2>(v[0], -v[1]); -} - -template Vec<_Tp, 4> conjugate(const Vec<_Tp, 4>& v) -{ - return Vec<_Tp, 4>(v[0], -v[1], -v[2], -v[3]); -} - -template<> inline Vec Vec::conj() const -{ - return conjugate(*this); -} - -template<> inline Vec Vec::conj() const -{ - return conjugate(*this); -} - -template<> inline Vec Vec::conj() const -{ - return conjugate(*this); -} - -template<> inline Vec Vec::conj() const -{ - return conjugate(*this); -} - -template inline Vec<_Tp, cn> Vec<_Tp, cn>::cross(const Vec<_Tp, cn>&) const -{ - CV_Error(CV_StsError, "for arbitrary-size vector there is no cross-product defined"); - return Vec<_Tp, cn>(); -} - -template template -inline Vec<_Tp, cn>::operator Vec() const -{ - Vec v; - for( int i = 0; i < cn; i++ ) v.val[i] = saturate_cast(this->val[i]); - return v; -} - -template inline Vec<_Tp, cn>::operator CvScalar() const -{ - CvScalar s = {{0,0,0,0}}; - int i; - for( i = 0; i < std::min(cn, 4); i++ ) s.val[i] = this->val[i]; - for( ; i < 4; i++ ) s.val[i] = 0; - return s; -} - -template inline const _Tp& Vec<_Tp, cn>::operator [](int i) const -{ - CV_DbgAssert( (unsigned)i < (unsigned)cn ); - return this->val[i]; -} - -template inline _Tp& Vec<_Tp, cn>::operator [](int i) -{ - CV_DbgAssert( (unsigned)i < (unsigned)cn ); - return this->val[i]; -} -template inline const _Tp& Vec<_Tp, cn>::operator ()(int i) const -{ - CV_DbgAssert( (unsigned)i < (unsigned)cn ); - return this->val[i]; -} -template inline _Tp& Vec<_Tp, cn>::operator ()(int i) -{ - CV_DbgAssert( (unsigned)i < (unsigned)cn ); - return this->val[i]; -} +////////////////////////// Augmenting algebraic & logical operations ////////////////////////// -template static inline Vec<_Tp1, cn>& -operator += (Vec<_Tp1, cn>& a, const Vec<_Tp2, cn>& b) -{ - for( int i = 0; i < cn; i++ ) - a.val[i] = saturate_cast<_Tp1>(a.val[i] + b.val[i]); - return a; -} +#define CV_MAT_AUG_OPERATOR1(op, cvop, A, B) \ + static inline A& operator op (A& a, const B& b) { cvop; return a; } -template static inline Vec<_Tp1, cn>& -operator -= (Vec<_Tp1, cn>& a, const Vec<_Tp2, cn>& b) -{ - for( int i = 0; i < cn; i++ ) - a.val[i] = saturate_cast<_Tp1>(a.val[i] - b.val[i]); - return a; -} +#define CV_MAT_AUG_OPERATOR(op, cvop, A, B) \ + CV_MAT_AUG_OPERATOR1(op, cvop, A, B) \ + CV_MAT_AUG_OPERATOR1(op, cvop, const A, B) -template static inline Vec<_Tp, cn> -operator + (const Vec<_Tp, cn>& a, const Vec<_Tp, cn>& b) -{ - return Vec<_Tp, cn>(a, b, Matx_AddOp()); -} +#define CV_MAT_AUG_OPERATOR_T(op, cvop, A, B) \ + template CV_MAT_AUG_OPERATOR1(op, cvop, A, B) \ + template CV_MAT_AUG_OPERATOR1(op, cvop, const A, B) -template static inline Vec<_Tp, cn> -operator - (const Vec<_Tp, cn>& a, const Vec<_Tp, cn>& b) -{ - return Vec<_Tp, cn>(a, b, Matx_SubOp()); -} +CV_MAT_AUG_OPERATOR (+=, cv::add(a,b,a), Mat, Mat) +CV_MAT_AUG_OPERATOR (+=, cv::add(a,b,a), Mat, Scalar) +CV_MAT_AUG_OPERATOR_T(+=, cv::add(a,b,a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(+=, cv::add(a,b,a), Mat_<_Tp>, Scalar) +CV_MAT_AUG_OPERATOR_T(+=, cv::add(a,b,a), Mat_<_Tp>, Mat_<_Tp>) -template static inline -Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, int alpha) -{ - for( int i = 0; i < cn; i++ ) - a[i] = saturate_cast<_Tp>(a[i]*alpha); - return a; -} +CV_MAT_AUG_OPERATOR (-=, cv::subtract(a,b,a), Mat, Mat) +CV_MAT_AUG_OPERATOR (-=, cv::subtract(a,b,a), Mat, Scalar) +CV_MAT_AUG_OPERATOR_T(-=, cv::subtract(a,b,a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(-=, cv::subtract(a,b,a), Mat_<_Tp>, Scalar) +CV_MAT_AUG_OPERATOR_T(-=, cv::subtract(a,b,a), Mat_<_Tp>, Mat_<_Tp>) -template static inline -Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, float alpha) -{ - for( int i = 0; i < cn; i++ ) - a[i] = saturate_cast<_Tp>(a[i]*alpha); - return a; -} +CV_MAT_AUG_OPERATOR (*=, cv::gemm(a, b, 1, Mat(), 0, a, 0), Mat, Mat) +CV_MAT_AUG_OPERATOR_T(*=, cv::gemm(a, b, 1, Mat(), 0, a, 0), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(*=, cv::gemm(a, b, 1, Mat(), 0, a, 0), Mat_<_Tp>, Mat_<_Tp>) +CV_MAT_AUG_OPERATOR (*=, a.convertTo(a, -1, b), Mat, double) +CV_MAT_AUG_OPERATOR_T(*=, a.convertTo(a, -1, b), Mat_<_Tp>, double) -template static inline -Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, double alpha) -{ - for( int i = 0; i < cn; i++ ) - a[i] = saturate_cast<_Tp>(a[i]*alpha); - return a; -} +CV_MAT_AUG_OPERATOR (/=, cv::divide(a,b,a), Mat, Mat) +CV_MAT_AUG_OPERATOR_T(/=, cv::divide(a,b,a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(/=, cv::divide(a,b,a), Mat_<_Tp>, Mat_<_Tp>) +CV_MAT_AUG_OPERATOR (/=, a.convertTo((Mat&)a, -1, 1./b), Mat, double) +CV_MAT_AUG_OPERATOR_T(/=, a.convertTo((Mat&)a, -1, 1./b), Mat_<_Tp>, double) -template static inline -Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, int alpha) -{ - double ialpha = 1./alpha; - for( int i = 0; i < cn; i++ ) - a[i] = saturate_cast<_Tp>(a[i]*ialpha); - return a; -} +CV_MAT_AUG_OPERATOR (&=, cv::bitwise_and(a,b,a), Mat, Mat) +CV_MAT_AUG_OPERATOR (&=, cv::bitwise_and(a,b,a), Mat, Scalar) +CV_MAT_AUG_OPERATOR_T(&=, cv::bitwise_and(a,b,a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(&=, cv::bitwise_and(a,b,a), Mat_<_Tp>, Scalar) +CV_MAT_AUG_OPERATOR_T(&=, cv::bitwise_and(a,b,a), Mat_<_Tp>, Mat_<_Tp>) -template static inline -Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, float alpha) -{ - float ialpha = 1.f/alpha; - for( int i = 0; i < cn; i++ ) - a[i] = saturate_cast<_Tp>(a[i]*ialpha); - return a; -} +CV_MAT_AUG_OPERATOR (|=, cv::bitwise_or(a,b,a), Mat, Mat) +CV_MAT_AUG_OPERATOR (|=, cv::bitwise_or(a,b,a), Mat, Scalar) +CV_MAT_AUG_OPERATOR_T(|=, cv::bitwise_or(a,b,a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(|=, cv::bitwise_or(a,b,a), Mat_<_Tp>, Scalar) +CV_MAT_AUG_OPERATOR_T(|=, cv::bitwise_or(a,b,a), Mat_<_Tp>, Mat_<_Tp>) -template static inline -Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, double alpha) -{ - double ialpha = 1./alpha; - for( int i = 0; i < cn; i++ ) - a[i] = saturate_cast<_Tp>(a[i]*ialpha); - return a; -} +CV_MAT_AUG_OPERATOR (^=, cv::bitwise_xor(a,b,a), Mat, Mat) +CV_MAT_AUG_OPERATOR (^=, cv::bitwise_xor(a,b,a), Mat, Scalar) +CV_MAT_AUG_OPERATOR_T(^=, cv::bitwise_xor(a,b,a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(^=, cv::bitwise_xor(a,b,a), Mat_<_Tp>, Scalar) +CV_MAT_AUG_OPERATOR_T(^=, cv::bitwise_xor(a,b,a), Mat_<_Tp>, Mat_<_Tp>) -template static inline Vec<_Tp, cn> -operator * (const Vec<_Tp, cn>& a, int alpha) -{ - return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); -} +#undef CV_MAT_AUG_OPERATOR_T +#undef CV_MAT_AUG_OPERATOR +#undef CV_MAT_AUG_OPERATOR1 -template static inline Vec<_Tp, cn> -operator * (int alpha, const Vec<_Tp, cn>& a) -{ - return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); -} -template static inline Vec<_Tp, cn> -operator * (const Vec<_Tp, cn>& a, float alpha) -{ - return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); -} -template static inline Vec<_Tp, cn> -operator * (float alpha, const Vec<_Tp, cn>& a) -{ - return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); -} - -template static inline Vec<_Tp, cn> -operator * (const Vec<_Tp, cn>& a, double alpha) -{ - return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); -} - -template static inline Vec<_Tp, cn> -operator * (double alpha, const Vec<_Tp, cn>& a) -{ - return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); -} +///////////////////////////////////////////// SVD ///////////////////////////////////////////// -template static inline Vec<_Tp, cn> -operator / (const Vec<_Tp, cn>& a, int alpha) +inline SVD::SVD() {} +inline SVD::SVD( InputArray m, int flags ) { operator ()(m, flags); } +inline void SVD::solveZ( InputArray m, OutputArray _dst ) { - return Vec<_Tp, cn>(a, 1./alpha, Matx_ScaleOp()); + Mat mtx = m.getMat(); + SVD svd(mtx, (mtx.rows >= mtx.cols ? 0 : SVD::FULL_UV)); + _dst.create(svd.vt.cols, 1, svd.vt.type()); + Mat dst = _dst.getMat(); + svd.vt.row(svd.vt.rows-1).reshape(1,svd.vt.cols).copyTo(dst); } -template static inline Vec<_Tp, cn> -operator / (const Vec<_Tp, cn>& a, float alpha) +template inline void + SVD::compute( const Matx<_Tp, m, n>& a, Matx<_Tp, nm, 1>& w, Matx<_Tp, m, nm>& u, Matx<_Tp, n, nm>& vt ) { - return Vec<_Tp, cn>(a, 1.f/alpha, Matx_ScaleOp()); + CV_StaticAssert( nm == MIN(m, n), "Invalid size of output vector."); + Mat _a(a, false), _u(u, false), _w(w, false), _vt(vt, false); + SVD::compute(_a, _w, _u, _vt); + CV_Assert(_w.data == (uchar*)&w.val[0] && _u.data == (uchar*)&u.val[0] && _vt.data == (uchar*)&vt.val[0]); } -template static inline Vec<_Tp, cn> -operator / (const Vec<_Tp, cn>& a, double alpha) +template inline void +SVD::compute( const Matx<_Tp, m, n>& a, Matx<_Tp, nm, 1>& w ) { - return Vec<_Tp, cn>(a, 1./alpha, Matx_ScaleOp()); + CV_StaticAssert( nm == MIN(m, n), "Invalid size of output vector."); + Mat _a(a, false), _w(w, false); + SVD::compute(_a, _w); + CV_Assert(_w.data == (uchar*)&w.val[0]); } -template static inline Vec<_Tp, cn> -operator - (const Vec<_Tp, cn>& a) +template inline void +SVD::backSubst( const Matx<_Tp, nm, 1>& w, const Matx<_Tp, m, nm>& u, + const Matx<_Tp, n, nm>& vt, const Matx<_Tp, m, nb>& rhs, + Matx<_Tp, n, nb>& dst ) { - Vec<_Tp,cn> t; - for( int i = 0; i < cn; i++ ) t.val[i] = saturate_cast<_Tp>(-a.val[i]); - return t; + CV_StaticAssert( nm == MIN(m, n), "Invalid size of output vector."); + Mat _u(u, false), _w(w, false), _vt(vt, false), _rhs(rhs, false), _dst(dst, false); + SVD::backSubst(_w, _u, _vt, _rhs, _dst); + CV_Assert(_dst.data == (uchar*)&dst.val[0]); } -template inline Vec<_Tp, 4> operator * (const Vec<_Tp, 4>& v1, const Vec<_Tp, 4>& v2) -{ - return Vec<_Tp, 4>(saturate_cast<_Tp>(v1[0]*v2[0] - v1[1]*v2[1] - v1[2]*v2[2] - v1[3]*v2[3]), - saturate_cast<_Tp>(v1[0]*v2[1] + v1[1]*v2[0] + v1[2]*v2[3] - v1[3]*v2[2]), - saturate_cast<_Tp>(v1[0]*v2[2] - v1[1]*v2[3] + v1[2]*v2[0] + v1[3]*v2[1]), - saturate_cast<_Tp>(v1[0]*v2[3] + v1[1]*v2[2] - v1[2]*v2[1] + v1[3]*v2[0])); -} - -template inline Vec<_Tp, 4>& operator *= (Vec<_Tp, 4>& v1, const Vec<_Tp, 4>& v2) -{ - v1 = v1 * v2; - return v1; -} - -template<> inline Vec Vec::cross(const Vec& v) const -{ - return Vec(val[1]*v.val[2] - val[2]*v.val[1], - val[2]*v.val[0] - val[0]*v.val[2], - val[0]*v.val[1] - val[1]*v.val[0]); -} - -template<> inline Vec Vec::cross(const Vec& v) const -{ - return Vec(val[1]*v.val[2] - val[2]*v.val[1], - val[2]*v.val[0] - val[0]*v.val[2], - val[0]*v.val[1] - val[1]*v.val[0]); -} - -template inline Vec<_Tp, cn> normalize(const Vec<_Tp, cn>& v) -{ - double nv = norm(v); - return v * (nv ? 1./nv : 0.); -} - -template static inline -VecCommaInitializer<_Tp, cn> operator << (const Vec<_Tp, cn>& vec, _T2 val) -{ - VecCommaInitializer<_Tp, cn> commaInitializer((Vec<_Tp, cn>*)&vec); - return (commaInitializer, val); -} - -template inline -VecCommaInitializer<_Tp, cn>::VecCommaInitializer(Vec<_Tp, cn>* _vec) - : MatxCommaInitializer<_Tp, cn, 1>(_vec) -{} - -template template inline -VecCommaInitializer<_Tp, cn>& VecCommaInitializer<_Tp, cn>::operator , (_T2 value) -{ - CV_DbgAssert( this->idx < cn ); - this->dst->val[this->idx++] = saturate_cast<_Tp>(value); - return *this; -} - -template inline -Vec<_Tp, cn> VecCommaInitializer<_Tp, cn>::operator *() const -{ - CV_DbgAssert( this->idx == cn ); - return *this->dst; -} - -//////////////////////////////// Complex ////////////////////////////// - -template inline Complex<_Tp>::Complex() : re(0), im(0) {} -template inline Complex<_Tp>::Complex( _Tp _re, _Tp _im ) : re(_re), im(_im) {} -template template inline Complex<_Tp>::operator Complex() const -{ return Complex(saturate_cast(re), saturate_cast(im)); } -template inline Complex<_Tp> Complex<_Tp>::conj() const -{ return Complex<_Tp>(re, -im); } - -template static inline -bool operator == (const Complex<_Tp>& a, const Complex<_Tp>& b) -{ return a.re == b.re && a.im == b.im; } - -template static inline -bool operator != (const Complex<_Tp>& a, const Complex<_Tp>& b) -{ return a.re != b.re || a.im != b.im; } - -template static inline -Complex<_Tp> operator + (const Complex<_Tp>& a, const Complex<_Tp>& b) -{ return Complex<_Tp>( a.re + b.re, a.im + b.im ); } - -template static inline -Complex<_Tp>& operator += (Complex<_Tp>& a, const Complex<_Tp>& b) -{ a.re += b.re; a.im += b.im; return a; } - -template static inline -Complex<_Tp> operator - (const Complex<_Tp>& a, const Complex<_Tp>& b) -{ return Complex<_Tp>( a.re - b.re, a.im - b.im ); } - -template static inline -Complex<_Tp>& operator -= (Complex<_Tp>& a, const Complex<_Tp>& b) -{ a.re -= b.re; a.im -= b.im; return a; } - -template static inline -Complex<_Tp> operator - (const Complex<_Tp>& a) -{ return Complex<_Tp>(-a.re, -a.im); } - -template static inline -Complex<_Tp> operator * (const Complex<_Tp>& a, const Complex<_Tp>& b) -{ return Complex<_Tp>( a.re*b.re - a.im*b.im, a.re*b.im + a.im*b.re ); } - -template static inline -Complex<_Tp> operator * (const Complex<_Tp>& a, _Tp b) -{ return Complex<_Tp>( a.re*b, a.im*b ); } - -template static inline -Complex<_Tp> operator * (_Tp b, const Complex<_Tp>& a) -{ return Complex<_Tp>( a.re*b, a.im*b ); } - -template static inline -Complex<_Tp> operator + (const Complex<_Tp>& a, _Tp b) -{ return Complex<_Tp>( a.re + b, a.im ); } - -template static inline -Complex<_Tp> operator - (const Complex<_Tp>& a, _Tp b) -{ return Complex<_Tp>( a.re - b, a.im ); } - -template static inline -Complex<_Tp> operator + (_Tp b, const Complex<_Tp>& a) -{ return Complex<_Tp>( a.re + b, a.im ); } - -template static inline -Complex<_Tp> operator - (_Tp b, const Complex<_Tp>& a) -{ return Complex<_Tp>( b - a.re, -a.im ); } - -template static inline -Complex<_Tp>& operator += (Complex<_Tp>& a, _Tp b) -{ a.re += b; return a; } - -template static inline -Complex<_Tp>& operator -= (Complex<_Tp>& a, _Tp b) -{ a.re -= b; return a; } - -template static inline -Complex<_Tp>& operator *= (Complex<_Tp>& a, _Tp b) -{ a.re *= b; a.im *= b; return a; } - -template static inline -double abs(const Complex<_Tp>& a) -{ return std::sqrt( (double)a.re*a.re + (double)a.im*a.im); } - -template static inline -Complex<_Tp> operator / (const Complex<_Tp>& a, const Complex<_Tp>& b) -{ - double t = 1./((double)b.re*b.re + (double)b.im*b.im); - return Complex<_Tp>( (_Tp)((a.re*b.re + a.im*b.im)*t), - (_Tp)((-a.re*b.im + a.im*b.re)*t) ); -} - -template static inline -Complex<_Tp>& operator /= (Complex<_Tp>& a, const Complex<_Tp>& b) -{ - return (a = a / b); -} - -template static inline -Complex<_Tp> operator / (const Complex<_Tp>& a, _Tp b) -{ - _Tp t = (_Tp)1/b; - return Complex<_Tp>( a.re*t, a.im*t ); -} - -template static inline -Complex<_Tp> operator / (_Tp b, const Complex<_Tp>& a) -{ - return Complex<_Tp>(b)/a; -} - -template static inline -Complex<_Tp> operator /= (const Complex<_Tp>& a, _Tp b) -{ - _Tp t = (_Tp)1/b; - a.re *= t; a.im *= t; return a; -} - -//////////////////////////////// 2D Point //////////////////////////////// - -template inline Point_<_Tp>::Point_() : x(0), y(0) {} -template inline Point_<_Tp>::Point_(_Tp _x, _Tp _y) : x(_x), y(_y) {} -template inline Point_<_Tp>::Point_(const Point_& pt) : x(pt.x), y(pt.y) {} -template inline Point_<_Tp>::Point_(const CvPoint& pt) : x((_Tp)pt.x), y((_Tp)pt.y) {} -template inline Point_<_Tp>::Point_(const CvPoint2D32f& pt) - : x(saturate_cast<_Tp>(pt.x)), y(saturate_cast<_Tp>(pt.y)) {} -template inline Point_<_Tp>::Point_(const Size_<_Tp>& sz) : x(sz.width), y(sz.height) {} -template inline Point_<_Tp>::Point_(const Vec<_Tp,2>& v) : x(v[0]), y(v[1]) {} -template inline Point_<_Tp>& Point_<_Tp>::operator = (const Point_& pt) -{ x = pt.x; y = pt.y; return *this; } - -template template inline Point_<_Tp>::operator Point_<_Tp2>() const -{ return Point_<_Tp2>(saturate_cast<_Tp2>(x), saturate_cast<_Tp2>(y)); } -template inline Point_<_Tp>::operator CvPoint() const -{ return cvPoint(saturate_cast(x), saturate_cast(y)); } -template inline Point_<_Tp>::operator CvPoint2D32f() const -{ return cvPoint2D32f((float)x, (float)y); } -template inline Point_<_Tp>::operator Vec<_Tp, 2>() const -{ return Vec<_Tp, 2>(x, y); } - -template inline _Tp Point_<_Tp>::dot(const Point_& pt) const -{ return saturate_cast<_Tp>(x*pt.x + y*pt.y); } -template inline double Point_<_Tp>::ddot(const Point_& pt) const -{ return (double)x*pt.x + (double)y*pt.y; } - -template inline double Point_<_Tp>::cross(const Point_& pt) const -{ return (double)x*pt.y - (double)y*pt.x; } - -template static inline Point_<_Tp>& -operator += (Point_<_Tp>& a, const Point_<_Tp>& b) -{ - a.x = saturate_cast<_Tp>(a.x + b.x); - a.y = saturate_cast<_Tp>(a.y + b.y); - return a; -} - -template static inline Point_<_Tp>& -operator -= (Point_<_Tp>& a, const Point_<_Tp>& b) -{ - a.x = saturate_cast<_Tp>(a.x - b.x); - a.y = saturate_cast<_Tp>(a.y - b.y); - return a; -} - -template static inline Point_<_Tp>& -operator *= (Point_<_Tp>& a, int b) -{ - a.x = saturate_cast<_Tp>(a.x*b); - a.y = saturate_cast<_Tp>(a.y*b); - return a; -} - -template static inline Point_<_Tp>& -operator *= (Point_<_Tp>& a, float b) -{ - a.x = saturate_cast<_Tp>(a.x*b); - a.y = saturate_cast<_Tp>(a.y*b); - return a; -} - -template static inline Point_<_Tp>& -operator *= (Point_<_Tp>& a, double b) -{ - a.x = saturate_cast<_Tp>(a.x*b); - a.y = saturate_cast<_Tp>(a.y*b); - return a; -} -template static inline double norm(const Point_<_Tp>& pt) -{ return std::sqrt((double)pt.x*pt.x + (double)pt.y*pt.y); } -template static inline bool operator == (const Point_<_Tp>& a, const Point_<_Tp>& b) -{ return a.x == b.x && a.y == b.y; } - -template static inline bool operator != (const Point_<_Tp>& a, const Point_<_Tp>& b) -{ return a.x != b.x || a.y != b.y; } - -template static inline Point_<_Tp> operator + (const Point_<_Tp>& a, const Point_<_Tp>& b) -{ return Point_<_Tp>( saturate_cast<_Tp>(a.x + b.x), saturate_cast<_Tp>(a.y + b.y) ); } - -template static inline Point_<_Tp> operator - (const Point_<_Tp>& a, const Point_<_Tp>& b) -{ return Point_<_Tp>( saturate_cast<_Tp>(a.x - b.x), saturate_cast<_Tp>(a.y - b.y) ); } - -template static inline Point_<_Tp> operator - (const Point_<_Tp>& a) -{ return Point_<_Tp>( saturate_cast<_Tp>(-a.x), saturate_cast<_Tp>(-a.y) ); } - -template static inline Point_<_Tp> operator * (const Point_<_Tp>& a, int b) -{ return Point_<_Tp>( saturate_cast<_Tp>(a.x*b), saturate_cast<_Tp>(a.y*b) ); } - -template static inline Point_<_Tp> operator * (int a, const Point_<_Tp>& b) -{ return Point_<_Tp>( saturate_cast<_Tp>(b.x*a), saturate_cast<_Tp>(b.y*a) ); } - -template static inline Point_<_Tp> operator * (const Point_<_Tp>& a, float b) -{ return Point_<_Tp>( saturate_cast<_Tp>(a.x*b), saturate_cast<_Tp>(a.y*b) ); } - -template static inline Point_<_Tp> operator * (float a, const Point_<_Tp>& b) -{ return Point_<_Tp>( saturate_cast<_Tp>(b.x*a), saturate_cast<_Tp>(b.y*a) ); } - -template static inline Point_<_Tp> operator * (const Point_<_Tp>& a, double b) -{ return Point_<_Tp>( saturate_cast<_Tp>(a.x*b), saturate_cast<_Tp>(a.y*b) ); } - -template static inline Point_<_Tp> operator * (double a, const Point_<_Tp>& b) -{ return Point_<_Tp>( saturate_cast<_Tp>(b.x*a), saturate_cast<_Tp>(b.y*a) ); } - -//////////////////////////////// 3D Point //////////////////////////////// - -template inline Point3_<_Tp>::Point3_() : x(0), y(0), z(0) {} -template inline Point3_<_Tp>::Point3_(_Tp _x, _Tp _y, _Tp _z) : x(_x), y(_y), z(_z) {} -template inline Point3_<_Tp>::Point3_(const Point3_& pt) : x(pt.x), y(pt.y), z(pt.z) {} -template inline Point3_<_Tp>::Point3_(const Point_<_Tp>& pt) : x(pt.x), y(pt.y), z(_Tp()) {} -template inline Point3_<_Tp>::Point3_(const CvPoint3D32f& pt) : - x(saturate_cast<_Tp>(pt.x)), y(saturate_cast<_Tp>(pt.y)), z(saturate_cast<_Tp>(pt.z)) {} -template inline Point3_<_Tp>::Point3_(const Vec<_Tp, 3>& v) : x(v[0]), y(v[1]), z(v[2]) {} - -template template inline Point3_<_Tp>::operator Point3_<_Tp2>() const -{ return Point3_<_Tp2>(saturate_cast<_Tp2>(x), saturate_cast<_Tp2>(y), saturate_cast<_Tp2>(z)); } - -template inline Point3_<_Tp>::operator CvPoint3D32f() const -{ return cvPoint3D32f((float)x, (float)y, (float)z); } - -template inline Point3_<_Tp>::operator Vec<_Tp, 3>() const -{ return Vec<_Tp, 3>(x, y, z); } - -template inline Point3_<_Tp>& Point3_<_Tp>::operator = (const Point3_& pt) -{ x = pt.x; y = pt.y; z = pt.z; return *this; } - -template inline _Tp Point3_<_Tp>::dot(const Point3_& pt) const -{ return saturate_cast<_Tp>(x*pt.x + y*pt.y + z*pt.z); } -template inline double Point3_<_Tp>::ddot(const Point3_& pt) const -{ return (double)x*pt.x + (double)y*pt.y + (double)z*pt.z; } - -template inline Point3_<_Tp> Point3_<_Tp>::cross(const Point3_<_Tp>& pt) const -{ - return Point3_<_Tp>(y*pt.z - z*pt.y, z*pt.x - x*pt.z, x*pt.y - y*pt.x); -} - -template static inline Point3_<_Tp>& -operator += (Point3_<_Tp>& a, const Point3_<_Tp>& b) -{ - a.x = saturate_cast<_Tp>(a.x + b.x); - a.y = saturate_cast<_Tp>(a.y + b.y); - a.z = saturate_cast<_Tp>(a.z + b.z); - return a; -} - -template static inline Point3_<_Tp>& -operator -= (Point3_<_Tp>& a, const Point3_<_Tp>& b) -{ - a.x = saturate_cast<_Tp>(a.x - b.x); - a.y = saturate_cast<_Tp>(a.y - b.y); - a.z = saturate_cast<_Tp>(a.z - b.z); - return a; -} - -template static inline Point3_<_Tp>& -operator *= (Point3_<_Tp>& a, int b) -{ - a.x = saturate_cast<_Tp>(a.x*b); - a.y = saturate_cast<_Tp>(a.y*b); - a.z = saturate_cast<_Tp>(a.z*b); - return a; -} - -template static inline Point3_<_Tp>& -operator *= (Point3_<_Tp>& a, float b) -{ - a.x = saturate_cast<_Tp>(a.x*b); - a.y = saturate_cast<_Tp>(a.y*b); - a.z = saturate_cast<_Tp>(a.z*b); - return a; -} - -template static inline Point3_<_Tp>& -operator *= (Point3_<_Tp>& a, double b) -{ - a.x = saturate_cast<_Tp>(a.x*b); - a.y = saturate_cast<_Tp>(a.y*b); - a.z = saturate_cast<_Tp>(a.z*b); - return a; -} - -template static inline double norm(const Point3_<_Tp>& pt) -{ return std::sqrt((double)pt.x*pt.x + (double)pt.y*pt.y + (double)pt.z*pt.z); } - -template static inline bool operator == (const Point3_<_Tp>& a, const Point3_<_Tp>& b) -{ return a.x == b.x && a.y == b.y && a.z == b.z; } - -template static inline bool operator != (const Point3_<_Tp>& a, const Point3_<_Tp>& b) -{ return a.x != b.x || a.y != b.y || a.z != b.z; } - -template static inline Point3_<_Tp> operator + (const Point3_<_Tp>& a, const Point3_<_Tp>& b) -{ return Point3_<_Tp>( saturate_cast<_Tp>(a.x + b.x), - saturate_cast<_Tp>(a.y + b.y), - saturate_cast<_Tp>(a.z + b.z)); } - -template static inline Point3_<_Tp> operator - (const Point3_<_Tp>& a, const Point3_<_Tp>& b) -{ return Point3_<_Tp>( saturate_cast<_Tp>(a.x - b.x), - saturate_cast<_Tp>(a.y - b.y), - saturate_cast<_Tp>(a.z - b.z)); } - -template static inline Point3_<_Tp> operator - (const Point3_<_Tp>& a) -{ return Point3_<_Tp>( saturate_cast<_Tp>(-a.x), - saturate_cast<_Tp>(-a.y), - saturate_cast<_Tp>(-a.z) ); } - -template static inline Point3_<_Tp> operator * (const Point3_<_Tp>& a, int b) -{ return Point3_<_Tp>( saturate_cast<_Tp>(a.x*b), - saturate_cast<_Tp>(a.y*b), - saturate_cast<_Tp>(a.z*b) ); } - -template static inline Point3_<_Tp> operator * (int a, const Point3_<_Tp>& b) -{ return Point3_<_Tp>( saturate_cast<_Tp>(b.x*a), - saturate_cast<_Tp>(b.y*a), - saturate_cast<_Tp>(b.z*a) ); } - -template static inline Point3_<_Tp> operator * (const Point3_<_Tp>& a, float b) -{ return Point3_<_Tp>( saturate_cast<_Tp>(a.x*b), - saturate_cast<_Tp>(a.y*b), - saturate_cast<_Tp>(a.z*b) ); } - -template static inline Point3_<_Tp> operator * (float a, const Point3_<_Tp>& b) -{ return Point3_<_Tp>( saturate_cast<_Tp>(b.x*a), - saturate_cast<_Tp>(b.y*a), - saturate_cast<_Tp>(b.z*a) ); } - -template static inline Point3_<_Tp> operator * (const Point3_<_Tp>& a, double b) -{ return Point3_<_Tp>( saturate_cast<_Tp>(a.x*b), - saturate_cast<_Tp>(a.y*b), - saturate_cast<_Tp>(a.z*b) ); } - -template static inline Point3_<_Tp> operator * (double a, const Point3_<_Tp>& b) -{ return Point3_<_Tp>( saturate_cast<_Tp>(b.x*a), - saturate_cast<_Tp>(b.y*a), - saturate_cast<_Tp>(b.z*a) ); } - -//////////////////////////////// Size //////////////////////////////// - -template inline Size_<_Tp>::Size_() - : width(0), height(0) {} -template inline Size_<_Tp>::Size_(_Tp _width, _Tp _height) - : width(_width), height(_height) {} -template inline Size_<_Tp>::Size_(const Size_& sz) - : width(sz.width), height(sz.height) {} -template inline Size_<_Tp>::Size_(const CvSize& sz) - : width(saturate_cast<_Tp>(sz.width)), height(saturate_cast<_Tp>(sz.height)) {} -template inline Size_<_Tp>::Size_(const CvSize2D32f& sz) - : width(saturate_cast<_Tp>(sz.width)), height(saturate_cast<_Tp>(sz.height)) {} -template inline Size_<_Tp>::Size_(const Point_<_Tp>& pt) : width(pt.x), height(pt.y) {} - -template template inline Size_<_Tp>::operator Size_<_Tp2>() const -{ return Size_<_Tp2>(saturate_cast<_Tp2>(width), saturate_cast<_Tp2>(height)); } -template inline Size_<_Tp>::operator CvSize() const -{ return cvSize(saturate_cast(width), saturate_cast(height)); } -template inline Size_<_Tp>::operator CvSize2D32f() const -{ return cvSize2D32f((float)width, (float)height); } - -template inline Size_<_Tp>& Size_<_Tp>::operator = (const Size_<_Tp>& sz) -{ width = sz.width; height = sz.height; return *this; } -template static inline Size_<_Tp> operator * (const Size_<_Tp>& a, _Tp b) -{ return Size_<_Tp>(a.width * b, a.height * b); } -template static inline Size_<_Tp> operator + (const Size_<_Tp>& a, const Size_<_Tp>& b) -{ return Size_<_Tp>(a.width + b.width, a.height + b.height); } -template static inline Size_<_Tp> operator - (const Size_<_Tp>& a, const Size_<_Tp>& b) -{ return Size_<_Tp>(a.width - b.width, a.height - b.height); } -template inline _Tp Size_<_Tp>::area() const { return width*height; } - -template static inline Size_<_Tp>& operator += (Size_<_Tp>& a, const Size_<_Tp>& b) -{ a.width += b.width; a.height += b.height; return a; } -template static inline Size_<_Tp>& operator -= (Size_<_Tp>& a, const Size_<_Tp>& b) -{ a.width -= b.width; a.height -= b.height; return a; } - -template static inline bool operator == (const Size_<_Tp>& a, const Size_<_Tp>& b) -{ return a.width == b.width && a.height == b.height; } -template static inline bool operator != (const Size_<_Tp>& a, const Size_<_Tp>& b) -{ return a.width != b.width || a.height != b.height; } - -//////////////////////////////// Rect //////////////////////////////// - - -template inline Rect_<_Tp>::Rect_() : x(0), y(0), width(0), height(0) {} -template inline Rect_<_Tp>::Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height) : x(_x), y(_y), width(_width), height(_height) {} -template inline Rect_<_Tp>::Rect_(const Rect_<_Tp>& r) : x(r.x), y(r.y), width(r.width), height(r.height) {} -template inline Rect_<_Tp>::Rect_(const CvRect& r) : x((_Tp)r.x), y((_Tp)r.y), width((_Tp)r.width), height((_Tp)r.height) {} -template inline Rect_<_Tp>::Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz) : - x(org.x), y(org.y), width(sz.width), height(sz.height) {} -template inline Rect_<_Tp>::Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2) -{ - x = std::min(pt1.x, pt2.x); y = std::min(pt1.y, pt2.y); - width = std::max(pt1.x, pt2.x) - x; height = std::max(pt1.y, pt2.y) - y; -} -template inline Rect_<_Tp>& Rect_<_Tp>::operator = ( const Rect_<_Tp>& r ) -{ x = r.x; y = r.y; width = r.width; height = r.height; return *this; } - -template inline Point_<_Tp> Rect_<_Tp>::tl() const { return Point_<_Tp>(x,y); } -template inline Point_<_Tp> Rect_<_Tp>::br() const { return Point_<_Tp>(x+width, y+height); } - -template static inline Rect_<_Tp>& operator += ( Rect_<_Tp>& a, const Point_<_Tp>& b ) -{ a.x += b.x; a.y += b.y; return a; } -template static inline Rect_<_Tp>& operator -= ( Rect_<_Tp>& a, const Point_<_Tp>& b ) -{ a.x -= b.x; a.y -= b.y; return a; } - -template static inline Rect_<_Tp>& operator += ( Rect_<_Tp>& a, const Size_<_Tp>& b ) -{ a.width += b.width; a.height += b.height; return a; } - -template static inline Rect_<_Tp>& operator -= ( Rect_<_Tp>& a, const Size_<_Tp>& b ) -{ a.width -= b.width; a.height -= b.height; return a; } - -template static inline Rect_<_Tp>& operator &= ( Rect_<_Tp>& a, const Rect_<_Tp>& b ) -{ - _Tp x1 = std::max(a.x, b.x), y1 = std::max(a.y, b.y); - a.width = std::min(a.x + a.width, b.x + b.width) - x1; - a.height = std::min(a.y + a.height, b.y + b.height) - y1; - a.x = x1; a.y = y1; - if( a.width <= 0 || a.height <= 0 ) - a = Rect(); - return a; -} - -template static inline Rect_<_Tp>& operator |= ( Rect_<_Tp>& a, const Rect_<_Tp>& b ) -{ - _Tp x1 = std::min(a.x, b.x), y1 = std::min(a.y, b.y); - a.width = std::max(a.x + a.width, b.x + b.width) - x1; - a.height = std::max(a.y + a.height, b.y + b.height) - y1; - a.x = x1; a.y = y1; - return a; -} - -template inline Size_<_Tp> Rect_<_Tp>::size() const { return Size_<_Tp>(width, height); } -template inline _Tp Rect_<_Tp>::area() const { return width*height; } - -template template inline Rect_<_Tp>::operator Rect_<_Tp2>() const -{ return Rect_<_Tp2>(saturate_cast<_Tp2>(x), saturate_cast<_Tp2>(y), - saturate_cast<_Tp2>(width), saturate_cast<_Tp2>(height)); } -template inline Rect_<_Tp>::operator CvRect() const -{ return cvRect(saturate_cast(x), saturate_cast(y), - saturate_cast(width), saturate_cast(height)); } - -template inline bool Rect_<_Tp>::contains(const Point_<_Tp>& pt) const -{ return x <= pt.x && pt.x < x + width && y <= pt.y && pt.y < y + height; } - -template static inline bool operator == (const Rect_<_Tp>& a, const Rect_<_Tp>& b) -{ - return a.x == b.x && a.y == b.y && a.width == b.width && a.height == b.height; -} - -template static inline bool operator != (const Rect_<_Tp>& a, const Rect_<_Tp>& b) -{ - return a.x != b.x || a.y != b.y || a.width != b.width || a.height != b.height; -} - -template static inline Rect_<_Tp> operator + (const Rect_<_Tp>& a, const Point_<_Tp>& b) -{ - return Rect_<_Tp>( a.x + b.x, a.y + b.y, a.width, a.height ); -} - -template static inline Rect_<_Tp> operator - (const Rect_<_Tp>& a, const Point_<_Tp>& b) -{ - return Rect_<_Tp>( a.x - b.x, a.y - b.y, a.width, a.height ); -} - -template static inline Rect_<_Tp> operator + (const Rect_<_Tp>& a, const Size_<_Tp>& b) -{ - return Rect_<_Tp>( a.x, a.y, a.width + b.width, a.height + b.height ); -} - -template static inline Rect_<_Tp> operator & (const Rect_<_Tp>& a, const Rect_<_Tp>& b) -{ - Rect_<_Tp> c = a; - return c &= b; -} - -template static inline Rect_<_Tp> operator | (const Rect_<_Tp>& a, const Rect_<_Tp>& b) -{ - Rect_<_Tp> c = a; - return c |= b; -} - -template inline bool Point_<_Tp>::inside( const Rect_<_Tp>& r ) const -{ - return r.contains(*this); -} - -inline RotatedRect::RotatedRect() { angle = 0; } -inline RotatedRect::RotatedRect(const Point2f& _center, const Size2f& _size, float _angle) - : center(_center), size(_size), angle(_angle) {} -inline RotatedRect::RotatedRect(const CvBox2D& box) - : center(box.center), size(box.size), angle(box.angle) {} -inline RotatedRect::operator CvBox2D() const -{ - CvBox2D box; box.center = center; box.size = size; box.angle = angle; - return box; -} - -//////////////////////////////// Scalar_ /////////////////////////////// - -template inline Scalar_<_Tp>::Scalar_() -{ this->val[0] = this->val[1] = this->val[2] = this->val[3] = 0; } - -template inline Scalar_<_Tp>::Scalar_(_Tp v0, _Tp v1, _Tp v2, _Tp v3) -{ this->val[0] = v0; this->val[1] = v1; this->val[2] = v2; this->val[3] = v3; } - -template inline Scalar_<_Tp>::Scalar_(const CvScalar& s) -{ - this->val[0] = saturate_cast<_Tp>(s.val[0]); - this->val[1] = saturate_cast<_Tp>(s.val[1]); - this->val[2] = saturate_cast<_Tp>(s.val[2]); - this->val[3] = saturate_cast<_Tp>(s.val[3]); -} - -template inline Scalar_<_Tp>::Scalar_(_Tp v0) -{ this->val[0] = v0; this->val[1] = this->val[2] = this->val[3] = 0; } - -template inline Scalar_<_Tp> Scalar_<_Tp>::all(_Tp v0) -{ return Scalar_<_Tp>(v0, v0, v0, v0); } -template inline Scalar_<_Tp>::operator CvScalar() const -{ return cvScalar(this->val[0], this->val[1], this->val[2], this->val[3]); } - -template template inline Scalar_<_Tp>::operator Scalar_() const -{ - return Scalar_(saturate_cast(this->val[0]), - saturate_cast(this->val[1]), - saturate_cast(this->val[2]), - saturate_cast(this->val[3])); -} - -template static inline Scalar_<_Tp>& operator += (Scalar_<_Tp>& a, const Scalar_<_Tp>& b) -{ - a.val[0] = saturate_cast<_Tp>(a.val[0] + b.val[0]); - a.val[1] = saturate_cast<_Tp>(a.val[1] + b.val[1]); - a.val[2] = saturate_cast<_Tp>(a.val[2] + b.val[2]); - a.val[3] = saturate_cast<_Tp>(a.val[3] + b.val[3]); - return a; -} - -template static inline Scalar_<_Tp>& operator -= (Scalar_<_Tp>& a, const Scalar_<_Tp>& b) -{ - a.val[0] = saturate_cast<_Tp>(a.val[0] - b.val[0]); - a.val[1] = saturate_cast<_Tp>(a.val[1] - b.val[1]); - a.val[2] = saturate_cast<_Tp>(a.val[2] - b.val[2]); - a.val[3] = saturate_cast<_Tp>(a.val[3] - b.val[3]); - return a; -} - -template static inline Scalar_<_Tp>& operator *= ( Scalar_<_Tp>& a, _Tp v ) -{ - a.val[0] = saturate_cast<_Tp>(a.val[0] * v); - a.val[1] = saturate_cast<_Tp>(a.val[1] * v); - a.val[2] = saturate_cast<_Tp>(a.val[2] * v); - a.val[3] = saturate_cast<_Tp>(a.val[3] * v); - return a; -} - -template inline Scalar_<_Tp> Scalar_<_Tp>::mul(const Scalar_<_Tp>& t, double scale ) const -{ - return Scalar_<_Tp>( saturate_cast<_Tp>(this->val[0]*t.val[0]*scale), - saturate_cast<_Tp>(this->val[1]*t.val[1]*scale), - saturate_cast<_Tp>(this->val[2]*t.val[2]*scale), - saturate_cast<_Tp>(this->val[3]*t.val[3]*scale)); -} - -template static inline bool operator == ( const Scalar_<_Tp>& a, const Scalar_<_Tp>& b ) -{ - return a.val[0] == b.val[0] && a.val[1] == b.val[1] && - a.val[2] == b.val[2] && a.val[3] == b.val[3]; -} - -template static inline bool operator != ( const Scalar_<_Tp>& a, const Scalar_<_Tp>& b ) -{ - return a.val[0] != b.val[0] || a.val[1] != b.val[1] || - a.val[2] != b.val[2] || a.val[3] != b.val[3]; -} - -template static inline Scalar_<_Tp> operator + (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b) -{ - return Scalar_<_Tp>(saturate_cast<_Tp>(a.val[0] + b.val[0]), - saturate_cast<_Tp>(a.val[1] + b.val[1]), - saturate_cast<_Tp>(a.val[2] + b.val[2]), - saturate_cast<_Tp>(a.val[3] + b.val[3])); -} - -template static inline Scalar_<_Tp> operator - (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b) -{ - return Scalar_<_Tp>(saturate_cast<_Tp>(a.val[0] - b.val[0]), - saturate_cast<_Tp>(a.val[1] - b.val[1]), - saturate_cast<_Tp>(a.val[2] - b.val[2]), - saturate_cast<_Tp>(a.val[3] - b.val[3])); -} - -template static inline Scalar_<_Tp> operator * (const Scalar_<_Tp>& a, _Tp alpha) -{ - return Scalar_<_Tp>(saturate_cast<_Tp>(a.val[0] * alpha), - saturate_cast<_Tp>(a.val[1] * alpha), - saturate_cast<_Tp>(a.val[2] * alpha), - saturate_cast<_Tp>(a.val[3] * alpha)); -} - -template static inline Scalar_<_Tp> operator * (_Tp alpha, const Scalar_<_Tp>& a) -{ - return a*alpha; -} - -template static inline Scalar_<_Tp> operator - (const Scalar_<_Tp>& a) -{ - return Scalar_<_Tp>(saturate_cast<_Tp>(-a.val[0]), saturate_cast<_Tp>(-a.val[1]), - saturate_cast<_Tp>(-a.val[2]), saturate_cast<_Tp>(-a.val[3])); -} - - -template static inline Scalar_<_Tp> -operator * (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b) -{ - return Scalar_<_Tp>(saturate_cast<_Tp>(a[0]*b[0] - a[1]*b[1] - a[2]*b[2] - a[3]*b[3]), - saturate_cast<_Tp>(a[0]*b[1] + a[1]*b[0] + a[2]*b[3] - a[3]*b[2]), - saturate_cast<_Tp>(a[0]*b[2] - a[1]*b[3] + a[2]*b[0] + a[3]*b[1]), - saturate_cast<_Tp>(a[0]*b[3] + a[1]*b[2] - a[2]*b[1] + a[3]*b[0])); -} - -template static inline Scalar_<_Tp>& -operator *= (Scalar_<_Tp>& a, const Scalar_<_Tp>& b) -{ - a = a*b; - return a; -} - -template inline Scalar_<_Tp> Scalar_<_Tp>::conj() const -{ - return Scalar_<_Tp>(saturate_cast<_Tp>(this->val[0]), - saturate_cast<_Tp>(-this->val[1]), - saturate_cast<_Tp>(-this->val[2]), - saturate_cast<_Tp>(-this->val[3])); -} - -template inline bool Scalar_<_Tp>::isReal() const -{ - return this->val[1] == 0 && this->val[2] == 0 && this->val[3] == 0; -} - -template static inline -Scalar_<_Tp> operator / (const Scalar_<_Tp>& a, _Tp alpha) -{ - return Scalar_<_Tp>(saturate_cast<_Tp>(a.val[0] / alpha), - saturate_cast<_Tp>(a.val[1] / alpha), - saturate_cast<_Tp>(a.val[2] / alpha), - saturate_cast<_Tp>(a.val[3] / alpha)); -} - -template static inline -Scalar_ operator / (const Scalar_& a, float alpha) -{ - float s = 1/alpha; - return Scalar_(a.val[0]*s, a.val[1]*s, a.val[2]*s, a.val[3]*s); -} - -template static inline -Scalar_ operator / (const Scalar_& a, double alpha) -{ - double s = 1/alpha; - return Scalar_(a.val[0]*s, a.val[1]*s, a.val[2]*s, a.val[3]*s); -} - -template static inline -Scalar_<_Tp>& operator /= (Scalar_<_Tp>& a, _Tp alpha) -{ - a = a/alpha; - return a; -} - -template static inline -Scalar_<_Tp> operator / (_Tp a, const Scalar_<_Tp>& b) -{ - _Tp s = a/(b[0]*b[0] + b[1]*b[1] + b[2]*b[2] + b[3]*b[3]); - return b.conj()*s; -} - -template static inline -Scalar_<_Tp> operator / (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b) -{ - return a*((_Tp)1/b); -} - -template static inline -Scalar_<_Tp>& operator /= (Scalar_<_Tp>& a, const Scalar_<_Tp>& b) -{ - a = a/b; - return a; -} - -//////////////////////////////// Range ///////////////////////////////// - -inline Range::Range() : start(0), end(0) {} -inline Range::Range(int _start, int _end) : start(_start), end(_end) {} -inline Range::Range(const CvSlice& slice) : start(slice.start_index), end(slice.end_index) -{ - if( start == 0 && end == CV_WHOLE_SEQ_END_INDEX ) - *this = Range::all(); -} - -inline int Range::size() const { return end - start; } -inline bool Range::empty() const { return start == end; } -inline Range Range::all() { return Range(INT_MIN, INT_MAX); } - -static inline bool operator == (const Range& r1, const Range& r2) -{ return r1.start == r2.start && r1.end == r2.end; } - -static inline bool operator != (const Range& r1, const Range& r2) -{ return !(r1 == r2); } - -static inline bool operator !(const Range& r) -{ return r.start == r.end; } - -static inline Range operator & (const Range& r1, const Range& r2) -{ - Range r(std::max(r1.start, r2.start), std::min(r1.end, r2.end)); - r.end = std::max(r.end, r.start); - return r; -} - -static inline Range& operator &= (Range& r1, const Range& r2) -{ - r1 = r1 & r2; - return r1; -} - -static inline Range operator + (const Range& r1, int delta) -{ - return Range(r1.start + delta, r1.end + delta); -} - -static inline Range operator + (int delta, const Range& r1) -{ - return Range(r1.start + delta, r1.end + delta); -} - -static inline Range operator - (const Range& r1, int delta) -{ - return r1 + (-delta); -} - -inline Range::operator CvSlice() const -{ return *this != Range::all() ? cvSlice(start, end) : CV_WHOLE_SEQ; } - - - -//////////////////////////////// Vector //////////////////////////////// - -// template vector class. It is similar to STL's vector, -// with a few important differences: -// 1) it can be created on top of user-allocated data w/o copying it -// 2) vector b = a means copying the header, -// not the underlying data (use clone() to make a deep copy) -template class CV_EXPORTS Vector -{ -public: - typedef _Tp value_type; - typedef _Tp* iterator; - typedef const _Tp* const_iterator; - typedef _Tp& reference; - typedef const _Tp& const_reference; - - struct CV_EXPORTS Hdr - { - Hdr() : data(0), datastart(0), refcount(0), size(0), capacity(0) {}; - _Tp* data; - _Tp* datastart; - int* refcount; - size_t size; - size_t capacity; - }; - - Vector() {} - Vector(size_t _size) { resize(_size); } - Vector(size_t _size, const _Tp& val) - { - resize(_size); - for(size_t i = 0; i < _size; i++) - hdr.data[i] = val; - } - Vector(_Tp* _data, size_t _size, bool _copyData=false) - { set(_data, _size, _copyData); } - - template Vector(const Vec<_Tp, n>& vec) - { set((_Tp*)&vec.val[0], n, true); } - - Vector(const std::vector<_Tp>& vec, bool _copyData=false) - { set(!vec.empty() ? (_Tp*)&vec[0] : 0, vec.size(), _copyData); } - - Vector(const Vector& d) { *this = d; } - - Vector(const Vector& d, const Range& r_) - { - Range r = r_ == Range::all() ? Range(0, d.size()) : r_; - /*if( r == Range::all() ) - r = Range(0, d.size());*/ - if( r.size() > 0 && r.start >= 0 && r.end <= d.size() ) - { - if( d.hdr.refcount ) - CV_XADD(d.hdr.refcount, 1); - hdr.refcount = d.hdr.refcount; - hdr.datastart = d.hdr.datastart; - hdr.data = d.hdr.data + r.start; - hdr.capacity = hdr.size = r.size(); - } - } - - Vector<_Tp>& operator = (const Vector& d) - { - if( this != &d ) - { - if( d.hdr.refcount ) - CV_XADD(d.hdr.refcount, 1); - release(); - hdr = d.hdr; - } - return *this; - } - - ~Vector() { release(); } - - Vector<_Tp> clone() const - { return hdr.data ? Vector<_Tp>(hdr.data, hdr.size, true) : Vector<_Tp>(); } - - void copyTo(Vector<_Tp>& vec) const - { - size_t i, sz = size(); - vec.resize(sz); - const _Tp* src = hdr.data; - _Tp* dst = vec.hdr.data; - for( i = 0; i < sz; i++ ) - dst[i] = src[i]; - } - - void copyTo(std::vector<_Tp>& vec) const - { - size_t i, sz = size(); - vec.resize(sz); - const _Tp* src = hdr.data; - _Tp* dst = sz ? &vec[0] : 0; - for( i = 0; i < sz; i++ ) - dst[i] = src[i]; - } - - operator CvMat() const - { return cvMat((int)size(), 1, type(), (void*)hdr.data); } - - _Tp& operator [] (size_t i) { CV_DbgAssert( i < size() ); return hdr.data[i]; } - const _Tp& operator [] (size_t i) const { CV_DbgAssert( i < size() ); return hdr.data[i]; } - Vector operator() (const Range& r) const { return Vector(*this, r); } - _Tp& back() { CV_DbgAssert(!empty()); return hdr.data[hdr.size-1]; } - const _Tp& back() const { CV_DbgAssert(!empty()); return hdr.data[hdr.size-1]; } - _Tp& front() { CV_DbgAssert(!empty()); return hdr.data[0]; } - const _Tp& front() const { CV_DbgAssert(!empty()); return hdr.data[0]; } - - _Tp* begin() { return hdr.data; } - _Tp* end() { return hdr.data + hdr.size; } - const _Tp* begin() const { return hdr.data; } - const _Tp* end() const { return hdr.data + hdr.size; } - - void addref() { if( hdr.refcount ) CV_XADD(hdr.refcount, 1); } - void release() - { - if( hdr.refcount && CV_XADD(hdr.refcount, -1) == 1 ) - { - delete[] hdr.datastart; - delete hdr.refcount; - } - hdr = Hdr(); - } - - void set(_Tp* _data, size_t _size, bool _copyData=false) - { - if( !_copyData ) - { - release(); - hdr.data = hdr.datastart = _data; - hdr.size = hdr.capacity = _size; - hdr.refcount = 0; - } - else - { - reserve(_size); - for( size_t i = 0; i < _size; i++ ) - hdr.data[i] = _data[i]; - hdr.size = _size; - } - } - - void reserve(size_t newCapacity) - { - _Tp* newData; - int* newRefcount; - size_t i, oldSize = hdr.size; - if( (!hdr.refcount || *hdr.refcount == 1) && hdr.capacity >= newCapacity ) - return; - newCapacity = std::max(newCapacity, oldSize); - newData = new _Tp[newCapacity]; - newRefcount = new int(1); - for( i = 0; i < oldSize; i++ ) - newData[i] = hdr.data[i]; - release(); - hdr.data = hdr.datastart = newData; - hdr.capacity = newCapacity; - hdr.size = oldSize; - hdr.refcount = newRefcount; - } - - void resize(size_t newSize) - { - size_t i; - newSize = std::max(newSize, (size_t)0); - if( (!hdr.refcount || *hdr.refcount == 1) && hdr.size == newSize ) - return; - if( newSize > hdr.capacity ) - reserve(std::max(newSize, std::max((size_t)4, hdr.capacity*2))); - for( i = hdr.size; i < newSize; i++ ) - hdr.data[i] = _Tp(); - hdr.size = newSize; - } - - Vector<_Tp>& push_back(const _Tp& elem) - { - if( hdr.size == hdr.capacity ) - reserve( std::max((size_t)4, hdr.capacity*2) ); - hdr.data[hdr.size++] = elem; - return *this; - } - - Vector<_Tp>& pop_back() - { - if( hdr.size > 0 ) - --hdr.size; - return *this; - } - - size_t size() const { return hdr.size; } - size_t capacity() const { return hdr.capacity; } - bool empty() const { return hdr.size == 0; } - void clear() { resize(0); } - int type() const { return DataType<_Tp>::type; } - -protected: - Hdr hdr; -}; - - -template inline typename DataType<_Tp>::work_type -dot(const Vector<_Tp>& v1, const Vector<_Tp>& v2) -{ - typedef typename DataType<_Tp>::work_type _Tw; - size_t i = 0, n = v1.size(); - assert(v1.size() == v2.size()); - - _Tw s = 0; - const _Tp *ptr1 = &v1[0], *ptr2 = &v2[0]; - for( ; i < n; i++ ) - s += (_Tw)ptr1[i]*ptr2[i]; - - return s; -} +/////////////////////////////////// Multiply-with-Carry RNG /////////////////////////////////// -// Multiply-with-Carry RNG -inline RNG::RNG() { state = 0xffffffff; } +inline RNG::RNG() { state = 0xffffffff; } inline RNG::RNG(uint64 _state) { state = _state ? _state : 0xffffffff; } + +inline RNG::operator uchar() { return (uchar)next(); } +inline RNG::operator schar() { return (schar)next(); } +inline RNG::operator ushort() { return (ushort)next(); } +inline RNG::operator short() { return (short)next(); } +inline RNG::operator int() { return (int)next(); } +inline RNG::operator unsigned() { return next(); } +inline RNG::operator float() { return next()*2.3283064365386962890625e-10f; } +inline RNG::operator double() { unsigned t = next(); return (((uint64)t << 32) | next()) * 5.4210108624275221700372640043497e-20; } + +inline unsigned RNG::operator ()(unsigned N) { return (unsigned)uniform(0,N); } +inline unsigned RNG::operator ()() { return next(); } + +inline int RNG::uniform(int a, int b) { return a == b ? a : (int)(next() % (b - a) + a); } +inline float RNG::uniform(float a, float b) { return ((float)*this)*(b - a) + a; } +inline double RNG::uniform(double a, double b) { return ((double)*this)*(b - a) + a; } + inline unsigned RNG::next() { - state = (uint64)(unsigned)state*CV_RNG_COEFF + (unsigned)(state >> 32); + state = (uint64)(unsigned)state* /*CV_RNG_COEFF*/ 4164903690U + (unsigned)(state >> 32); return (unsigned)state; } -inline RNG::operator uchar() { return (uchar)next(); } -inline RNG::operator schar() { return (schar)next(); } -inline RNG::operator ushort() { return (ushort)next(); } -inline RNG::operator short() { return (short)next(); } -inline RNG::operator unsigned() { return next(); } -inline unsigned RNG::operator ()(unsigned N) {return (unsigned)uniform(0,N);} -inline unsigned RNG::operator ()() {return next();} -inline RNG::operator int() { return (int)next(); } -// * (2^32-1)^-1 -inline RNG::operator float() { return next()*2.3283064365386962890625e-10f; } -inline RNG::operator double() + + +///////////////////////////////////////// LineIterator //////////////////////////////////////// + +inline +uchar* LineIterator::operator *() { - unsigned t = next(); - return (((uint64)t << 32) | next())*5.4210108624275221700372640043497e-20; + return ptr; } -inline int RNG::uniform(int a, int b) { return a == b ? a : (int)(next()%(b - a) + a); } -inline float RNG::uniform(float a, float b) { return ((float)*this)*(b - a) + a; } -inline double RNG::uniform(double a, double b) { return ((double)*this)*(b - a) + a; } -inline TermCriteria::TermCriteria() : type(0), maxCount(0), epsilon(0) {} -inline TermCriteria::TermCriteria(int _type, int _maxCount, double _epsilon) - : type(_type), maxCount(_maxCount), epsilon(_epsilon) {} -inline TermCriteria::TermCriteria(const CvTermCriteria& criteria) - : type(criteria.type), maxCount(criteria.max_iter), epsilon(criteria.epsilon) {} -inline TermCriteria::operator CvTermCriteria() const -{ return cvTermCriteria(type, maxCount, epsilon); } - -inline uchar* LineIterator::operator *() { return ptr; } -inline LineIterator& LineIterator::operator ++() +inline +LineIterator& LineIterator::operator ++() { int mask = err < 0 ? -1 : 0; err += minusDelta + (plusDelta & mask); ptr += minusStep + (plusStep & mask); return *this; } -inline LineIterator LineIterator::operator ++(int) + +inline +LineIterator LineIterator::operator ++(int) { LineIterator it = *this; ++(*this); return it; } -inline Point LineIterator::pos() const + +inline +Point LineIterator::pos() const { Point p; p.y = (int)((ptr - ptr0)/step); @@ -2482,1525 +386,138 @@ inline Point LineIterator::pos() const return p; } -/////////////////////////////// AutoBuffer //////////////////////////////////////// -template inline -AutoBuffer<_Tp, fixed_size>::AutoBuffer() +//! returns the next unifomly-distributed random number of the specified type +template static inline _Tp randu() { - ptr = buf; - sz = fixed_size; + return (_Tp)theRNG(); } -template inline -AutoBuffer<_Tp, fixed_size>::AutoBuffer(size_t _size) + + +///////////////////////////////// Formatted output of cv::Mat ///////////////////////////////// + +static inline +Ptr format(InputArray mtx, int fmt) { - ptr = buf; - sz = fixed_size; - allocate(_size); + return Formatter::get(fmt)->format(mtx.getMat()); } -template inline -AutoBuffer<_Tp, fixed_size>::AutoBuffer(const AutoBuffer<_Tp, fixed_size>& abuf ) +static inline +int print(Ptr fmtd, FILE* stream = stdout) { - ptr = buf; - sz = fixed_size; - allocate(abuf.size); - for( size_t i = 0; i < sz; i++ ) - ptr[i] = abuf.ptr[i]; + int written = 0; + fmtd->reset(); + for(const char* str = fmtd->next(); str; str = fmtd->next()) + written += fputs(str, stream); + + return written; } -template inline AutoBuffer<_Tp, fixed_size>& -AutoBuffer<_Tp, fixed_size>::operator = (const AutoBuffer<_Tp, fixed_size>& abuf) +static inline +int print(const Mat& mtx, FILE* stream = stdout) { - if( this != &abuf ) - { - deallocate(); - allocate(abuf.size); - for( size_t i = 0; i < sz; i++ ) - ptr[i] = abuf.ptr[i]; - } - return *this; + return print(Formatter::get()->format(mtx), stream); } -template inline -AutoBuffer<_Tp, fixed_size>::~AutoBuffer() -{ deallocate(); } - -template inline void -AutoBuffer<_Tp, fixed_size>::allocate(size_t _size) -{ - if(_size <= sz) - { - sz = _size; - return; - } - deallocate(); - if(_size > fixed_size) - { - ptr = new _Tp[_size]; - sz = _size; - } -} - -template inline void -AutoBuffer<_Tp, fixed_size>::deallocate() -{ - if( ptr != buf ) - { - delete[] ptr; - ptr = buf; - sz = fixed_size; - } -} - -template inline void -AutoBuffer<_Tp, fixed_size>::resize(size_t _size) -{ - if(_size <= sz) - { - sz = _size; - return; - } - size_t i, prevsize = sz, minsize = MIN(prevsize, _size); - _Tp* prevptr = ptr; - - ptr = _size > fixed_size ? new _Tp[_size] : buf; - sz = _size; - - if( ptr != prevptr ) - for( i = 0; i < minsize; i++ ) - ptr[i] = prevptr[i]; - for( i = prevsize; i < _size; i++ ) - ptr[i] = _Tp(); - - if( prevptr != buf ) - delete[] prevptr; -} - -template inline size_t -AutoBuffer<_Tp, fixed_size>::size() const -{ return sz; } - -template inline -AutoBuffer<_Tp, fixed_size>::operator _Tp* () -{ return ptr; } - -template inline -AutoBuffer<_Tp, fixed_size>::operator const _Tp* () const -{ return ptr; } - - -/////////////////////////////////// Ptr //////////////////////////////////////// - -template inline Ptr<_Tp>::Ptr() : obj(0), refcount(0) {} -template inline Ptr<_Tp>::Ptr(_Tp* _obj) : obj(_obj) -{ - if(obj) - { - refcount = (int*)fastMalloc(sizeof(*refcount)); - *refcount = 1; - } - else - refcount = 0; -} - -template inline void Ptr<_Tp>::addref() -{ if( refcount ) CV_XADD(refcount, 1); } - -template inline void Ptr<_Tp>::release() -{ - if( refcount && CV_XADD(refcount, -1) == 1 ) - { - delete_obj(); - fastFree(refcount); - } - refcount = 0; - obj = 0; -} - -template inline void Ptr<_Tp>::delete_obj() -{ - if( obj ) delete obj; -} - -template inline Ptr<_Tp>::~Ptr() { release(); } - -template inline Ptr<_Tp>::Ptr(const Ptr<_Tp>& _ptr) -{ - obj = _ptr.obj; - refcount = _ptr.refcount; - addref(); -} - -template inline Ptr<_Tp>& Ptr<_Tp>::operator = (const Ptr<_Tp>& _ptr) -{ - int* _refcount = _ptr.refcount; - if( _refcount ) - CV_XADD(_refcount, 1); - release(); - obj = _ptr.obj; - refcount = _refcount; - return *this; -} - -template inline _Tp* Ptr<_Tp>::operator -> () { return obj; } -template inline const _Tp* Ptr<_Tp>::operator -> () const { return obj; } - -template inline Ptr<_Tp>::operator _Tp* () { return obj; } -template inline Ptr<_Tp>::operator const _Tp*() const { return obj; } - -template inline bool Ptr<_Tp>::empty() const { return obj == 0; } - -template template Ptr<_Tp>::Ptr(const Ptr<_Tp2>& p) - : obj(0), refcount(0) -{ - if (p.empty()) - return; - - _Tp* p_casted = dynamic_cast<_Tp*>(p.obj); - if (!p_casted) - return; - - obj = p_casted; - refcount = p.refcount; - addref(); -} - -template template inline Ptr<_Tp2> Ptr<_Tp>::ptr() -{ - Ptr<_Tp2> p; - if( !obj ) - return p; - - _Tp2* obj_casted = dynamic_cast<_Tp2*>(obj); - if (!obj_casted) - return p; - - if( refcount ) - CV_XADD(refcount, 1); - - p.obj = obj_casted; - p.refcount = refcount; - return p; -} - -template template inline const Ptr<_Tp2> Ptr<_Tp>::ptr() const -{ - Ptr<_Tp2> p; - if( !obj ) - return p; - - _Tp2* obj_casted = dynamic_cast<_Tp2*>(obj); - if (!obj_casted) - return p; - - if( refcount ) - CV_XADD(refcount, 1); - - p.obj = obj_casted; - p.refcount = refcount; - return p; -} - -template inline bool operator==(const Ptr<_Tp>& a, const Ptr<_Tp2>& b) { return a.refcount == b.refcount; } -template inline bool operator!=(const Ptr<_Tp>& a, const Ptr<_Tp2>& b) { return a.refcount != b.refcount; } - - - - -//// specializied implementations of Ptr::delete_obj() for classic OpenCV types - -template<> CV_EXPORTS void Ptr::delete_obj(); -template<> CV_EXPORTS void Ptr::delete_obj(); -template<> CV_EXPORTS void Ptr::delete_obj(); -template<> CV_EXPORTS void Ptr::delete_obj(); -template<> CV_EXPORTS void Ptr::delete_obj(); -template<> CV_EXPORTS void Ptr::delete_obj(); - -//////////////////////////////////////// XML & YAML I/O //////////////////////////////////// - -CV_EXPORTS_W void write( FileStorage& fs, const std::string& name, int value ); -CV_EXPORTS_W void write( FileStorage& fs, const std::string& name, float value ); -CV_EXPORTS_W void write( FileStorage& fs, const std::string& name, double value ); -CV_EXPORTS_W void write( FileStorage& fs, const std::string& name, const std::string& value ); - -template inline void write(FileStorage& fs, const _Tp& value) -{ write(fs, std::string(), value); } - -CV_EXPORTS void writeScalar( FileStorage& fs, int value ); -CV_EXPORTS void writeScalar( FileStorage& fs, float value ); -CV_EXPORTS void writeScalar( FileStorage& fs, double value ); -CV_EXPORTS void writeScalar( FileStorage& fs, const std::string& value ); - -template<> inline void write( FileStorage& fs, const int& value ) -{ - writeScalar(fs, value); -} - -template<> inline void write( FileStorage& fs, const float& value ) -{ - writeScalar(fs, value); -} - -template<> inline void write( FileStorage& fs, const double& value ) -{ - writeScalar(fs, value); -} - -template<> inline void write( FileStorage& fs, const std::string& value ) -{ - writeScalar(fs, value); -} - -template inline void write(FileStorage& fs, const Point_<_Tp>& pt ) -{ - write(fs, pt.x); - write(fs, pt.y); -} - -template inline void write(FileStorage& fs, const Point3_<_Tp>& pt ) -{ - write(fs, pt.x); - write(fs, pt.y); - write(fs, pt.z); -} - -template inline void write(FileStorage& fs, const Size_<_Tp>& sz ) -{ - write(fs, sz.width); - write(fs, sz.height); -} - -template inline void write(FileStorage& fs, const Complex<_Tp>& c ) -{ - write(fs, c.re); - write(fs, c.im); -} - -template inline void write(FileStorage& fs, const Rect_<_Tp>& r ) -{ - write(fs, r.x); - write(fs, r.y); - write(fs, r.width); - write(fs, r.height); -} - -template inline void write(FileStorage& fs, const Vec<_Tp, cn>& v ) -{ - for(int i = 0; i < cn; i++) - write(fs, v.val[i]); -} - -template inline void write(FileStorage& fs, const Scalar_<_Tp>& s ) -{ - write(fs, s.val[0]); - write(fs, s.val[1]); - write(fs, s.val[2]); - write(fs, s.val[3]); -} - -inline void write(FileStorage& fs, const Range& r ) -{ - write(fs, r.start); - write(fs, r.end); -} - -class CV_EXPORTS WriteStructContext -{ -public: - WriteStructContext(FileStorage& _fs, const std::string& name, - int flags, const std::string& typeName=std::string()); - ~WriteStructContext(); - FileStorage* fs; -}; - -template inline void write(FileStorage& fs, const std::string& name, const Point_<_Tp>& pt ) -{ - WriteStructContext ws(fs, name, CV_NODE_SEQ+CV_NODE_FLOW); - write(fs, pt.x); - write(fs, pt.y); -} - -template inline void write(FileStorage& fs, const std::string& name, const Point3_<_Tp>& pt ) -{ - WriteStructContext ws(fs, name, CV_NODE_SEQ+CV_NODE_FLOW); - write(fs, pt.x); - write(fs, pt.y); - write(fs, pt.z); -} - -template inline void write(FileStorage& fs, const std::string& name, const Size_<_Tp>& sz ) -{ - WriteStructContext ws(fs, name, CV_NODE_SEQ+CV_NODE_FLOW); - write(fs, sz.width); - write(fs, sz.height); -} - -template inline void write(FileStorage& fs, const std::string& name, const Complex<_Tp>& c ) -{ - WriteStructContext ws(fs, name, CV_NODE_SEQ+CV_NODE_FLOW); - write(fs, c.re); - write(fs, c.im); -} - -template inline void write(FileStorage& fs, const std::string& name, const Rect_<_Tp>& r ) -{ - WriteStructContext ws(fs, name, CV_NODE_SEQ+CV_NODE_FLOW); - write(fs, r.x); - write(fs, r.y); - write(fs, r.width); - write(fs, r.height); -} - -template inline void write(FileStorage& fs, const std::string& name, const Vec<_Tp, cn>& v ) -{ - WriteStructContext ws(fs, name, CV_NODE_SEQ+CV_NODE_FLOW); - for(int i = 0; i < cn; i++) - write(fs, v.val[i]); -} - -template inline void write(FileStorage& fs, const std::string& name, const Scalar_<_Tp>& s ) -{ - WriteStructContext ws(fs, name, CV_NODE_SEQ+CV_NODE_FLOW); - write(fs, s.val[0]); - write(fs, s.val[1]); - write(fs, s.val[2]); - write(fs, s.val[3]); -} - -inline void write(FileStorage& fs, const std::string& name, const Range& r ) -{ - WriteStructContext ws(fs, name, CV_NODE_SEQ+CV_NODE_FLOW); - write(fs, r.start); - write(fs, r.end); -} - -template class CV_EXPORTS VecWriterProxy -{ -public: - VecWriterProxy( FileStorage* _fs ) : fs(_fs) {} - void operator()(const std::vector<_Tp>& vec) const - { - size_t i, count = vec.size(); - for( i = 0; i < count; i++ ) - write( *fs, vec[i] ); - } - FileStorage* fs; -}; - -template class CV_EXPORTS VecWriterProxy<_Tp,1> -{ -public: - VecWriterProxy( FileStorage* _fs ) : fs(_fs) {} - void operator()(const std::vector<_Tp>& vec) const - { - int _fmt = DataType<_Tp>::fmt; - char fmt[] = { (char)((_fmt>>8)+'1'), (char)_fmt, '\0' }; - fs->writeRaw( std::string(fmt), !vec.empty() ? (uchar*)&vec[0] : 0, vec.size()*sizeof(_Tp) ); - } - FileStorage* fs; -}; - -template static inline void write( FileStorage& fs, const std::vector<_Tp>& vec ) -{ - VecWriterProxy<_Tp, DataType<_Tp>::fmt != 0> w(&fs); - w(vec); -} - -template static inline void write( FileStorage& fs, const std::string& name, - const std::vector<_Tp>& vec ) -{ - WriteStructContext ws(fs, name, CV_NODE_SEQ+(DataType<_Tp>::fmt != 0 ? CV_NODE_FLOW : 0)); - write(fs, vec); -} - -CV_EXPORTS_W void write( FileStorage& fs, const std::string& name, const Mat& value ); -CV_EXPORTS void write( FileStorage& fs, const std::string& name, const SparseMat& value ); - -template static inline FileStorage& operator << (FileStorage& fs, const _Tp& value) -{ - if( !fs.isOpened() ) - return fs; - if( fs.state == FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP ) - CV_Error( CV_StsError, "No element name has been given" ); - write( fs, fs.elname, value ); - if( fs.state & FileStorage::INSIDE_MAP ) - fs.state = FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP; - return fs; -} - -CV_EXPORTS FileStorage& operator << (FileStorage& fs, const std::string& str); - -static inline FileStorage& operator << (FileStorage& fs, const char* str) -{ return (fs << std::string(str)); } - -inline FileNode::FileNode() : fs(0), node(0) {} -inline FileNode::FileNode(const CvFileStorage* _fs, const CvFileNode* _node) - : fs(_fs), node(_node) {} - -inline FileNode::FileNode(const FileNode& _node) : fs(_node.fs), node(_node.node) {} - -inline int FileNode::type() const { return !node ? NONE : (node->tag & TYPE_MASK); } -inline bool FileNode::empty() const { return node == 0; } -inline bool FileNode::isNone() const { return type() == NONE; } -inline bool FileNode::isSeq() const { return type() == SEQ; } -inline bool FileNode::isMap() const { return type() == MAP; } -inline bool FileNode::isInt() const { return type() == INT; } -inline bool FileNode::isReal() const { return type() == REAL; } -inline bool FileNode::isString() const { return type() == STR; } -inline bool FileNode::isNamed() const { return !node ? false : (node->tag & NAMED) != 0; } -inline size_t FileNode::size() const -{ - int t = type(); - return t == MAP ? (size_t)((CvSet*)node->data.map)->active_count : - t == SEQ ? (size_t)node->data.seq->total : (size_t)!isNone(); -} - -inline CvFileNode* FileNode::operator *() { return (CvFileNode*)node; } -inline const CvFileNode* FileNode::operator* () const { return node; } - -static inline void read(const FileNode& node, int& value, int default_value) -{ - value = !node.node ? default_value : - CV_NODE_IS_INT(node.node->tag) ? node.node->data.i : - CV_NODE_IS_REAL(node.node->tag) ? cvRound(node.node->data.f) : 0x7fffffff; -} - -static inline void read(const FileNode& node, bool& value, bool default_value) -{ - int temp; read(node, temp, (int)default_value); - value = temp != 0; -} - -static inline void read(const FileNode& node, uchar& value, uchar default_value) -{ - int temp; read(node, temp, (int)default_value); - value = saturate_cast(temp); -} - -static inline void read(const FileNode& node, schar& value, schar default_value) -{ - int temp; read(node, temp, (int)default_value); - value = saturate_cast(temp); -} - -static inline void read(const FileNode& node, ushort& value, ushort default_value) -{ - int temp; read(node, temp, (int)default_value); - value = saturate_cast(temp); -} - -static inline void read(const FileNode& node, short& value, short default_value) -{ - int temp; read(node, temp, (int)default_value); - value = saturate_cast(temp); -} - -static inline void read(const FileNode& node, float& value, float default_value) -{ - value = !node.node ? default_value : - CV_NODE_IS_INT(node.node->tag) ? (float)node.node->data.i : - CV_NODE_IS_REAL(node.node->tag) ? (float)node.node->data.f : 1e30f; -} - -static inline void read(const FileNode& node, double& value, double default_value) -{ - value = !node.node ? default_value : - CV_NODE_IS_INT(node.node->tag) ? (double)node.node->data.i : - CV_NODE_IS_REAL(node.node->tag) ? node.node->data.f : 1e300; -} - -static inline void read(const FileNode& node, std::string& value, const std::string& default_value) -{ - value = !node.node ? default_value : CV_NODE_IS_STRING(node.node->tag) ? std::string(node.node->data.str.ptr) : std::string(""); -} - -CV_EXPORTS_W void read(const FileNode& node, Mat& mat, const Mat& default_mat=Mat() ); -CV_EXPORTS void read(const FileNode& node, SparseMat& mat, const SparseMat& default_mat=SparseMat() ); - -inline FileNode::operator int() const -{ - int value; - read(*this, value, 0); - return value; -} -inline FileNode::operator float() const -{ - float value; - read(*this, value, 0.f); - return value; -} -inline FileNode::operator double() const -{ - double value; - read(*this, value, 0.); - return value; -} -inline FileNode::operator std::string() const -{ - std::string value; - read(*this, value, value); - return value; -} - -inline void FileNode::readRaw( const std::string& fmt, uchar* vec, size_t len ) const -{ - begin().readRaw( fmt, vec, len ); -} - -template class CV_EXPORTS VecReaderProxy -{ -public: - VecReaderProxy( FileNodeIterator* _it ) : it(_it) {} - void operator()(std::vector<_Tp>& vec, size_t count) const - { - count = std::min(count, it->remaining); - vec.resize(count); - for( size_t i = 0; i < count; i++, ++(*it) ) - read(**it, vec[i], _Tp()); - } - FileNodeIterator* it; -}; - -template class CV_EXPORTS VecReaderProxy<_Tp,1> -{ -public: - VecReaderProxy( FileNodeIterator* _it ) : it(_it) {} - void operator()(std::vector<_Tp>& vec, size_t count) const - { - size_t remaining = it->remaining, cn = DataType<_Tp>::channels; - int _fmt = DataType<_Tp>::fmt; - char fmt[] = { (char)((_fmt>>8)+'1'), (char)_fmt, '\0' }; - size_t remaining1 = remaining/cn; - count = count < remaining1 ? count : remaining1; - vec.resize(count); - it->readRaw( std::string(fmt), !vec.empty() ? (uchar*)&vec[0] : 0, count*sizeof(_Tp) ); - } - FileNodeIterator* it; -}; - -template static inline void -read( FileNodeIterator& it, std::vector<_Tp>& vec, size_t maxCount=(size_t)INT_MAX ) -{ - VecReaderProxy<_Tp, DataType<_Tp>::fmt != 0> r(&it); - r(vec, maxCount); -} - -template static inline void -read( const FileNode& node, std::vector<_Tp>& vec, const std::vector<_Tp>& default_value=std::vector<_Tp>() ) -{ - if(!node.node) - vec = default_value; - else - { - FileNodeIterator it = node.begin(); - read( it, vec ); - } -} - -inline FileNodeIterator FileNode::begin() const -{ - return FileNodeIterator(fs, node); -} - -inline FileNodeIterator FileNode::end() const -{ - return FileNodeIterator(fs, node, size()); -} - -inline FileNode FileNodeIterator::operator *() const -{ return FileNode(fs, (const CvFileNode*)reader.ptr); } - -inline FileNode FileNodeIterator::operator ->() const -{ return FileNode(fs, (const CvFileNode*)reader.ptr); } - -template static inline FileNodeIterator& operator >> (FileNodeIterator& it, _Tp& value) -{ read( *it, value, _Tp()); return ++it; } - template static inline -FileNodeIterator& operator >> (FileNodeIterator& it, std::vector<_Tp>& vec) +int print(const std::vector >& vec, FILE* stream = stdout) { - VecReaderProxy<_Tp, DataType<_Tp>::fmt != 0> r(&it); - r(vec, (size_t)INT_MAX); - return it; + return print(Formatter::get()->format(Mat(vec)), stream); } -template static inline void operator >> (const FileNode& n, _Tp& value) -{ read( n, value, _Tp()); } - -template static inline void operator >> (const FileNode& n, std::vector<_Tp>& vec) -{ FileNodeIterator it = n.begin(); it >> vec; } - -static inline bool operator == (const FileNodeIterator& it1, const FileNodeIterator& it2) +template static inline +int print(const std::vector >& vec, FILE* stream = stdout) { - return it1.fs == it2.fs && it1.container == it2.container && - it1.reader.ptr == it2.reader.ptr && it1.remaining == it2.remaining; + return print(Formatter::get()->format(Mat(vec)), stream); } -static inline bool operator != (const FileNodeIterator& it1, const FileNodeIterator& it2) +template static inline +int print(const Matx<_Tp, m, n>& matx, FILE* stream = stdout) { - return !(it1 == it2); -} - -static inline ptrdiff_t operator - (const FileNodeIterator& it1, const FileNodeIterator& it2) -{ - return it2.remaining - it1.remaining; -} - -static inline bool operator < (const FileNodeIterator& it1, const FileNodeIterator& it2) -{ - return it1.remaining > it2.remaining; -} - -inline FileNode FileStorage::getFirstTopLevelNode() const -{ - FileNode r = root(); - FileNodeIterator it = r.begin(); - return it != r.end() ? *it : FileNode(); -} - -//////////////////////////////////////// Various algorithms //////////////////////////////////// - -template static inline _Tp gcd(_Tp a, _Tp b) -{ - if( a < b ) - std::swap(a, b); - while( b > 0 ) - { - _Tp r = a % b; - a = b; - b = r; - } - return a; -} - -/****************************************************************************************\ - - Generic implementation of QuickSort algorithm - Use it as: vector<_Tp> a; ... sort(a,); - - The current implementation was derived from *BSD system qsort(): - - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - -\****************************************************************************************/ - -template void sort( std::vector<_Tp>& vec, _LT LT=_LT() ) -{ - int isort_thresh = 7; - int sp = 0; - - struct - { - _Tp *lb; - _Tp *ub; - } stack[48]; - - size_t total = vec.size(); - - if( total <= 1 ) - return; - - _Tp* arr = &vec[0]; - stack[0].lb = arr; - stack[0].ub = arr + (total - 1); - - while( sp >= 0 ) - { - _Tp* left = stack[sp].lb; - _Tp* right = stack[sp--].ub; - - for(;;) - { - int i, n = (int)(right - left) + 1, m; - _Tp* ptr; - _Tp* ptr2; - - if( n <= isort_thresh ) - { - insert_sort: - for( ptr = left + 1; ptr <= right; ptr++ ) - { - for( ptr2 = ptr; ptr2 > left && LT(ptr2[0],ptr2[-1]); ptr2--) - std::swap( ptr2[0], ptr2[-1] ); - } - break; - } - else - { - _Tp* left0; - _Tp* left1; - _Tp* right0; - _Tp* right1; - _Tp* pivot; - _Tp* a; - _Tp* b; - _Tp* c; - int swap_cnt = 0; - - left0 = left; - right0 = right; - pivot = left + (n/2); - - if( n > 40 ) - { - int d = n / 8; - a = left, b = left + d, c = left + 2*d; - left = LT(*a, *b) ? (LT(*b, *c) ? b : (LT(*a, *c) ? c : a)) - : (LT(*c, *b) ? b : (LT(*a, *c) ? a : c)); - - a = pivot - d, b = pivot, c = pivot + d; - pivot = LT(*a, *b) ? (LT(*b, *c) ? b : (LT(*a, *c) ? c : a)) - : (LT(*c, *b) ? b : (LT(*a, *c) ? a : c)); - - a = right - 2*d, b = right - d, c = right; - right = LT(*a, *b) ? (LT(*b, *c) ? b : (LT(*a, *c) ? c : a)) - : (LT(*c, *b) ? b : (LT(*a, *c) ? a : c)); - } - - a = left, b = pivot, c = right; - pivot = LT(*a, *b) ? (LT(*b, *c) ? b : (LT(*a, *c) ? c : a)) - : (LT(*c, *b) ? b : (LT(*a, *c) ? a : c)); - if( pivot != left0 ) - { - std::swap( *pivot, *left0 ); - pivot = left0; - } - left = left1 = left0 + 1; - right = right1 = right0; - - for(;;) - { - while( left <= right && !LT(*pivot, *left) ) - { - if( !LT(*left, *pivot) ) - { - if( left > left1 ) - std::swap( *left1, *left ); - swap_cnt = 1; - left1++; - } - left++; - } - - while( left <= right && !LT(*right, *pivot) ) - { - if( !LT(*pivot, *right) ) - { - if( right < right1 ) - std::swap( *right1, *right ); - swap_cnt = 1; - right1--; - } - right--; - } - - if( left > right ) - break; - std::swap( *left, *right ); - swap_cnt = 1; - left++; - right--; - } - - if( swap_cnt == 0 ) - { - left = left0, right = right0; - goto insert_sort; - } - - n = std::min( (int)(left1 - left0), (int)(left - left1) ); - for( i = 0; i < n; i++ ) - std::swap( left0[i], left[i-n] ); - - n = std::min( (int)(right0 - right1), (int)(right1 - right) ); - for( i = 0; i < n; i++ ) - std::swap( left[i], right0[i-n+1] ); - n = (int)(left - left1); - m = (int)(right1 - right); - if( n > 1 ) - { - if( m > 1 ) - { - if( n > m ) - { - stack[++sp].lb = left0; - stack[sp].ub = left0 + n - 1; - left = right0 - m + 1, right = right0; - } - else - { - stack[++sp].lb = right0 - m + 1; - stack[sp].ub = right0; - left = left0, right = left0 + n - 1; - } - } - else - left = left0, right = left0 + n - 1; - } - else if( m > 1 ) - left = right0 - m + 1, right = right0; - else - break; - } - } - } -} - -template class CV_EXPORTS LessThan -{ -public: - bool operator()(const _Tp& a, const _Tp& b) const { return a < b; } -}; - -template class CV_EXPORTS GreaterEq -{ -public: - bool operator()(const _Tp& a, const _Tp& b) const { return a >= b; } -}; - -template class CV_EXPORTS LessThanIdx -{ -public: - LessThanIdx( const _Tp* _arr ) : arr(_arr) {} - bool operator()(int a, int b) const { return arr[a] < arr[b]; } - const _Tp* arr; -}; - -template class CV_EXPORTS GreaterEqIdx -{ -public: - GreaterEqIdx( const _Tp* _arr ) : arr(_arr) {} - bool operator()(int a, int b) const { return arr[a] >= arr[b]; } - const _Tp* arr; -}; - - -// This function splits the input sequence or set into one or more equivalence classes and -// returns the vector of labels - 0-based class indexes for each element. -// predicate(a,b) returns true if the two sequence elements certainly belong to the same class. -// -// The algorithm is described in "Introduction to Algorithms" -// by Cormen, Leiserson and Rivest, the chapter "Data structures for disjoint sets" -template int -partition( const std::vector<_Tp>& _vec, std::vector& labels, - _EqPredicate predicate=_EqPredicate()) -{ - int i, j, N = (int)_vec.size(); - const _Tp* vec = &_vec[0]; - - const int PARENT=0; - const int RANK=1; - - std::vector _nodes(N*2); - int (*nodes)[2] = (int(*)[2])&_nodes[0]; - - // The first O(N) pass: create N single-vertex trees - for(i = 0; i < N; i++) - { - nodes[i][PARENT]=-1; - nodes[i][RANK] = 0; - } - - // The main O(N^2) pass: merge connected components - for( i = 0; i < N; i++ ) - { - int root = i; - - // find root - while( nodes[root][PARENT] >= 0 ) - root = nodes[root][PARENT]; - - for( j = 0; j < N; j++ ) - { - if( i == j || !predicate(vec[i], vec[j])) - continue; - int root2 = j; - - while( nodes[root2][PARENT] >= 0 ) - root2 = nodes[root2][PARENT]; - - if( root2 != root ) - { - // unite both trees - int rank = nodes[root][RANK], rank2 = nodes[root2][RANK]; - if( rank > rank2 ) - nodes[root2][PARENT] = root; - else - { - nodes[root][PARENT] = root2; - nodes[root2][RANK] += rank == rank2; - root = root2; - } - assert( nodes[root][PARENT] < 0 ); - - int k = j, parent; - - // compress the path from node2 to root - while( (parent = nodes[k][PARENT]) >= 0 ) - { - nodes[k][PARENT] = root; - k = parent; - } - - // compress the path from node to root - k = i; - while( (parent = nodes[k][PARENT]) >= 0 ) - { - nodes[k][PARENT] = root; - k = parent; - } - } - } - } - - // Final O(N) pass: enumerate classes - labels.resize(N); - int nclasses = 0; - - for( i = 0; i < N; i++ ) - { - int root = i; - while( nodes[root][PARENT] >= 0 ) - root = nodes[root][PARENT]; - // re-use the rank as the class label - if( nodes[root][RANK] >= 0 ) - nodes[root][RANK] = ~nclasses++; - labels[i] = ~nodes[root][RANK]; - } - - return nclasses; + return print(Formatter::get()->format(matx), stream); } -////////////////////////////////////////////////////////////////////////////// -// bridge C++ => C Seq API -CV_EXPORTS schar* seqPush( CvSeq* seq, const void* element=0); -CV_EXPORTS schar* seqPushFront( CvSeq* seq, const void* element=0); -CV_EXPORTS void seqPop( CvSeq* seq, void* element=0); -CV_EXPORTS void seqPopFront( CvSeq* seq, void* element=0); -CV_EXPORTS void seqPopMulti( CvSeq* seq, void* elements, - int count, int in_front=0 ); -CV_EXPORTS void seqRemove( CvSeq* seq, int index ); -CV_EXPORTS void clearSeq( CvSeq* seq ); -CV_EXPORTS schar* getSeqElem( const CvSeq* seq, int index ); -CV_EXPORTS void seqRemoveSlice( CvSeq* seq, CvSlice slice ); -CV_EXPORTS void seqInsertSlice( CvSeq* seq, int before_index, const CvArr* from_arr ); +////////////////////////////////////////// Algorithm ////////////////////////////////////////// -template inline Seq<_Tp>::Seq() : seq(0) {} -template inline Seq<_Tp>::Seq( const CvSeq* _seq ) : seq((CvSeq*)_seq) +template inline +Ptr<_Tp> Algorithm::create(const String& name) { - CV_Assert(!_seq || _seq->elem_size == sizeof(_Tp)); + return _create(name).dynamicCast<_Tp>(); } -template inline Seq<_Tp>::Seq( MemStorage& storage, - int headerSize ) +template inline +void Algorithm::set(const char* _name, const Ptr<_Tp>& value) { - CV_Assert(headerSize >= (int)sizeof(CvSeq)); - seq = cvCreateSeq(DataType<_Tp>::type, headerSize, sizeof(_Tp), storage); -} - -template inline _Tp& Seq<_Tp>::operator [](int idx) -{ return *(_Tp*)getSeqElem(seq, idx); } - -template inline const _Tp& Seq<_Tp>::operator [](int idx) const -{ return *(_Tp*)getSeqElem(seq, idx); } - -template inline SeqIterator<_Tp> Seq<_Tp>::begin() const -{ return SeqIterator<_Tp>(*this); } - -template inline SeqIterator<_Tp> Seq<_Tp>::end() const -{ return SeqIterator<_Tp>(*this, true); } - -template inline size_t Seq<_Tp>::size() const -{ return seq ? seq->total : 0; } - -template inline int Seq<_Tp>::type() const -{ return seq ? CV_MAT_TYPE(seq->flags) : 0; } - -template inline int Seq<_Tp>::depth() const -{ return seq ? CV_MAT_DEPTH(seq->flags) : 0; } - -template inline int Seq<_Tp>::channels() const -{ return seq ? CV_MAT_CN(seq->flags) : 0; } - -template inline size_t Seq<_Tp>::elemSize() const -{ return seq ? seq->elem_size : 0; } - -template inline size_t Seq<_Tp>::index(const _Tp& elem) const -{ return cvSeqElemIdx(seq, &elem); } - -template inline void Seq<_Tp>::push_back(const _Tp& elem) -{ cvSeqPush(seq, &elem); } - -template inline void Seq<_Tp>::push_front(const _Tp& elem) -{ cvSeqPushFront(seq, &elem); } - -template inline void Seq<_Tp>::push_back(const _Tp* elem, size_t count) -{ cvSeqPushMulti(seq, elem, (int)count, 0); } - -template inline void Seq<_Tp>::push_front(const _Tp* elem, size_t count) -{ cvSeqPushMulti(seq, elem, (int)count, 1); } - -template inline _Tp& Seq<_Tp>::back() -{ return *(_Tp*)getSeqElem(seq, -1); } - -template inline const _Tp& Seq<_Tp>::back() const -{ return *(const _Tp*)getSeqElem(seq, -1); } - -template inline _Tp& Seq<_Tp>::front() -{ return *(_Tp*)getSeqElem(seq, 0); } - -template inline const _Tp& Seq<_Tp>::front() const -{ return *(const _Tp*)getSeqElem(seq, 0); } - -template inline bool Seq<_Tp>::empty() const -{ return !seq || seq->total == 0; } - -template inline void Seq<_Tp>::clear() -{ if(seq) clearSeq(seq); } - -template inline void Seq<_Tp>::pop_back() -{ seqPop(seq); } - -template inline void Seq<_Tp>::pop_front() -{ seqPopFront(seq); } - -template inline void Seq<_Tp>::pop_back(_Tp* elem, size_t count) -{ seqPopMulti(seq, elem, (int)count, 0); } - -template inline void Seq<_Tp>::pop_front(_Tp* elem, size_t count) -{ seqPopMulti(seq, elem, (int)count, 1); } - -template inline void Seq<_Tp>::insert(int idx, const _Tp& elem) -{ seqInsert(seq, idx, &elem); } - -template inline void Seq<_Tp>::insert(int idx, const _Tp* elems, size_t count) -{ - CvMat m = cvMat(1, count, DataType<_Tp>::type, elems); - seqInsertSlice(seq, idx, &m); -} - -template inline void Seq<_Tp>::remove(int idx) -{ seqRemove(seq, idx); } - -template inline void Seq<_Tp>::remove(const Range& r) -{ seqRemoveSlice(seq, r); } - -template inline void Seq<_Tp>::copyTo(std::vector<_Tp>& vec, const Range& range) const -{ - size_t len = !seq ? 0 : range == Range::all() ? seq->total : range.end - range.start; - vec.resize(len); - if( seq && len ) - cvCvtSeqToArray(seq, &vec[0], range); -} - -template inline Seq<_Tp>::operator std::vector<_Tp>() const -{ - std::vector<_Tp> vec; - copyTo(vec); - return vec; -} - -template inline SeqIterator<_Tp>::SeqIterator() -{ memset(this, 0, sizeof(*this)); } - -template inline SeqIterator<_Tp>::SeqIterator(const Seq<_Tp>& _seq, bool seekEnd) -{ - cvStartReadSeq(_seq.seq, this); - index = seekEnd ? _seq.seq->total : 0; -} - -template inline void SeqIterator<_Tp>::seek(size_t pos) -{ - cvSetSeqReaderPos(this, (int)pos, false); - index = pos; -} - -template inline size_t SeqIterator<_Tp>::tell() const -{ return index; } - -template inline _Tp& SeqIterator<_Tp>::operator *() -{ return *(_Tp*)ptr; } - -template inline const _Tp& SeqIterator<_Tp>::operator *() const -{ return *(const _Tp*)ptr; } - -template inline SeqIterator<_Tp>& SeqIterator<_Tp>::operator ++() -{ - CV_NEXT_SEQ_ELEM(sizeof(_Tp), *this); - if( ++index >= seq->total*2 ) - index = 0; - return *this; -} - -template inline SeqIterator<_Tp> SeqIterator<_Tp>::operator ++(int) const -{ - SeqIterator<_Tp> it = *this; - ++*this; - return it; -} - -template inline SeqIterator<_Tp>& SeqIterator<_Tp>::operator --() -{ - CV_PREV_SEQ_ELEM(sizeof(_Tp), *this); - if( --index < 0 ) - index = seq->total*2-1; - return *this; -} - -template inline SeqIterator<_Tp> SeqIterator<_Tp>::operator --(int) const -{ - SeqIterator<_Tp> it = *this; - --*this; - return it; -} - -template inline SeqIterator<_Tp>& SeqIterator<_Tp>::operator +=(int delta) -{ - cvSetSeqReaderPos(this, delta, 1); - index += delta; - int n = seq->total*2; - if( index < 0 ) - index += n; - if( index >= n ) - index -= n; - return *this; -} - -template inline SeqIterator<_Tp>& SeqIterator<_Tp>::operator -=(int delta) -{ - return (*this += -delta); -} - -template inline ptrdiff_t operator - (const SeqIterator<_Tp>& a, - const SeqIterator<_Tp>& b) -{ - ptrdiff_t delta = a.index - b.index, n = a.seq->total; - if( std::abs(static_cast(delta)) > n ) - delta += delta < 0 ? n : -n; - return delta; -} - -template inline bool operator == (const SeqIterator<_Tp>& a, - const SeqIterator<_Tp>& b) -{ - return a.seq == b.seq && a.index == b.index; -} - -template inline bool operator != (const SeqIterator<_Tp>& a, - const SeqIterator<_Tp>& b) -{ - return !(a == b); -} - - -template struct CV_EXPORTS RTTIImpl -{ -public: - static int isInstance(const void* ptr) - { - static _ClsName dummy; - static void* dummyp = &dummy; - union - { - const void* p; - const void** pp; - } a, b; - a.p = dummyp; - b.p = ptr; - return *a.pp == *b.pp; - } - static void release(void** dbptr) - { - if(dbptr && *dbptr) - { - delete (_ClsName*)*dbptr; - *dbptr = 0; - } - } - static void* read(CvFileStorage* fs, CvFileNode* n) - { - FileNode fn(fs, n); - _ClsName* obj = new _ClsName; - if(obj->read(fn)) - return obj; - delete obj; - return 0; - } - - static void write(CvFileStorage* _fs, const char* name, const void* ptr, CvAttrList) - { - if(ptr && _fs) - { - FileStorage fs(_fs); - fs.fs.addref(); - ((const _ClsName*)ptr)->write(fs, std::string(name)); - } - } - - static void* clone(const void* ptr) - { - if(!ptr) - return 0; - return new _ClsName(*(const _ClsName*)ptr); - } -}; - - -class CV_EXPORTS Formatter -{ -public: - virtual ~Formatter() {} - virtual void write(std::ostream& out, const Mat& m, const int* params=0, int nparams=0) const = 0; - virtual void write(std::ostream& out, const void* data, int nelems, int type, - const int* params=0, int nparams=0) const = 0; - static const Formatter* get(const char* fmt=""); - static const Formatter* setDefault(const Formatter* fmt); -}; - - -struct CV_EXPORTS Formatted -{ - Formatted(const Mat& m, const Formatter* fmt, - const std::vector& params); - Formatted(const Mat& m, const Formatter* fmt, - const int* params=0); - Mat mtx; - const Formatter* fmt; - std::vector params; -}; - -static inline Formatted format(const Mat& mtx, const char* fmt, - const std::vector& params=std::vector()) -{ - return Formatted(mtx, Formatter::get(fmt), params); -} - -template static inline Formatted format(const std::vector >& vec, - const char* fmt, const std::vector& params=std::vector()) -{ - return Formatted(Mat(vec), Formatter::get(fmt), params); -} - -template static inline Formatted format(const std::vector >& vec, - const char* fmt, const std::vector& params=std::vector()) -{ - return Formatted(Mat(vec), Formatter::get(fmt), params); -} - -/** \brief prints Mat to the output stream in Matlab notation - * use like - @verbatim - Mat my_mat = Mat::eye(3,3,CV_32F); - std::cout << my_mat; - @endverbatim - */ -static inline std::ostream& operator << (std::ostream& out, const Mat& mtx) -{ - Formatter::get()->write(out, mtx); - return out; -} - -/** \brief prints Mat to the output stream allows in the specified notation (see format) - * use like - @verbatim - Mat my_mat = Mat::eye(3,3,CV_32F); - std::cout << my_mat; - @endverbatim - */ -static inline std::ostream& operator << (std::ostream& out, const Formatted& fmtd) -{ - fmtd.fmt->write(out, fmtd.mtx); - return out; -} - - -template static inline std::ostream& operator << (std::ostream& out, - const std::vector >& vec) -{ - Formatter::get()->write(out, Mat(vec)); - return out; -} - - -template static inline std::ostream& operator << (std::ostream& out, - const std::vector >& vec) -{ - Formatter::get()->write(out, Mat(vec)); - return out; -} - - -/** Writes a Matx to an output stream. - */ -template inline std::ostream& operator<<(std::ostream& out, const Matx<_Tp, m, n>& matx) -{ - out << cv::Mat(matx); - return out; -} - -/** Writes a point to an output stream in Matlab notation - */ -template inline std::ostream& operator<<(std::ostream& out, const Point_<_Tp>& p) -{ - out << "[" << p.x << ", " << p.y << "]"; - return out; -} - -/** Writes a point to an output stream in Matlab notation - */ -template inline std::ostream& operator<<(std::ostream& out, const Point3_<_Tp>& p) -{ - out << "[" << p.x << ", " << p.y << ", " << p.z << "]"; - return out; -} - -/** Writes a Vec to an output stream. Format example : [10, 20, 30] - */ -template inline std::ostream& operator<<(std::ostream& out, const Vec<_Tp, n>& vec) -{ - out << "["; - - if(Vec<_Tp, n>::depth < CV_32F) - { - for (int i = 0; i < n - 1; ++i) { - out << (int)vec[i] << ", "; - } - out << (int)vec[n-1] << "]"; - } - else - { - for (int i = 0; i < n - 1; ++i) { - out << vec[i] << ", "; - } - out << vec[n-1] << "]"; - } - - return out; -} - -/** Writes a Size_ to an output stream. Format example : [640 x 480] - */ -template inline std::ostream& operator<<(std::ostream& out, const Size_<_Tp>& size) -{ - out << "[" << size.width << " x " << size.height << "]"; - return out; -} - -/** Writes a Rect_ to an output stream. Format example : [640 x 480 from (10, 20)] - */ -template inline std::ostream& operator<<(std::ostream& out, const Rect_<_Tp>& rect) -{ - out << "[" << rect.width << " x " << rect.height << " from (" << rect.x << ", " << rect.y << ")]"; - return out; -} - - -template inline Ptr<_Tp> Algorithm::create(const std::string& name) -{ - return _create(name).ptr<_Tp>(); -} - -template -inline void Algorithm::set(const char* _name, const Ptr<_Tp>& value) -{ - Ptr algo_ptr = value. template ptr(); - if (algo_ptr.empty()) { - CV_Error( CV_StsUnsupportedFormat, "unknown/unsupported Ptr type of the second parameter of the method Algorithm::set"); + Ptr algo_ptr = value. template dynamicCast(); + if (!algo_ptr) { + CV_Error( Error::StsUnsupportedFormat, "unknown/unsupported Ptr type of the second parameter of the method Algorithm::set"); } info()->set(this, _name, ParamType::type, &algo_ptr); } -template -inline void Algorithm::set(const std::string& _name, const Ptr<_Tp>& value) +template inline +void Algorithm::set(const String& _name, const Ptr<_Tp>& value) { this->set<_Tp>(_name.c_str(), value); } -template -inline void Algorithm::setAlgorithm(const char* _name, const Ptr<_Tp>& value) +template inline +void Algorithm::setAlgorithm(const char* _name, const Ptr<_Tp>& value) { Ptr algo_ptr = value. template ptr(); - if (algo_ptr.empty()) { - CV_Error( CV_StsUnsupportedFormat, "unknown/unsupported Ptr type of the second parameter of the method Algorithm::set"); + if (!algo_ptr) { + CV_Error( Error::StsUnsupportedFormat, "unknown/unsupported Ptr type of the second parameter of the method Algorithm::set"); } info()->set(this, _name, ParamType::type, &algo_ptr); } -template -inline void Algorithm::setAlgorithm(const std::string& _name, const Ptr<_Tp>& value) +template inline +void Algorithm::setAlgorithm(const String& _name, const Ptr<_Tp>& value) { this->set<_Tp>(_name.c_str(), value); } -template inline typename ParamType<_Tp>::member_type Algorithm::get(const std::string& _name) const +template inline +typename ParamType<_Tp>::member_type Algorithm::get(const String& _name) const { typename ParamType<_Tp>::member_type value; info()->get(this, _name.c_str(), ParamType<_Tp>::type, &value); return value; } -template inline typename ParamType<_Tp>::member_type Algorithm::get(const char* _name) const +template inline +typename ParamType<_Tp>::member_type Algorithm::get(const char* _name) const { typename ParamType<_Tp>::member_type value; info()->get(this, _name, ParamType<_Tp>::type, &value); return value; } -template inline void AlgorithmInfo::addParam(Algorithm& algo, const char* parameter, - Ptr<_Tp>& value, bool readOnly, Ptr<_Tp> (Algorithm::*getter)(), void (Algorithm::*setter)(const Ptr<_Tp>&), - const std::string& help) +template inline +void AlgorithmInfo::addParam(Algorithm& algo, const char* parameter, Ptr<_Tp>& value, bool readOnly, + Ptr<_Tp> (Algorithm::*getter)(), void (Algorithm::*setter)(const Ptr<_Tp>&), + const String& help) { //TODO: static assert: _Tp inherits from _Base addParam_(algo, parameter, ParamType<_Base>::type, &value, readOnly, (Algorithm::Getter)getter, (Algorithm::Setter)setter, help); } -template inline void AlgorithmInfo::addParam(Algorithm& algo, const char* parameter, - Ptr<_Tp>& value, bool readOnly, Ptr<_Tp> (Algorithm::*getter)(), void (Algorithm::*setter)(const Ptr<_Tp>&), - const std::string& help) +template inline +void AlgorithmInfo::addParam(Algorithm& algo, const char* parameter, Ptr<_Tp>& value, bool readOnly, + Ptr<_Tp> (Algorithm::*getter)(), void (Algorithm::*setter)(const Ptr<_Tp>&), + const String& help) { //TODO: static assert: _Tp inherits from Algorithm addParam_(algo, parameter, ParamType::type, &value, readOnly, (Algorithm::Getter)getter, (Algorithm::Setter)setter, help); } -} -#ifdef _MSC_VER -# pragma warning(pop) -#endif -#endif // __cplusplus +} // cv + #endif diff --git a/modules/core/include/opencv2/core/persistence.hpp b/modules/core/include/opencv2/core/persistence.hpp new file mode 100644 index 0000000000..f5687614bb --- /dev/null +++ b/modules/core/include/opencv2/core/persistence.hpp @@ -0,0 +1,870 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_PERSISTENCE_HPP__ +#define __OPENCV_CORE_PERSISTENCE_HPP__ + +#ifndef __cplusplus +# error persistence.hpp header must be compiled as C++ +#endif + +// black-box structures used by FileStorage +typedef struct CvFileStorage CvFileStorage; +typedef struct CvFileNode CvFileNode; + +#include "opencv2/core/types.hpp" +#include "opencv2/core/mat.hpp" + +namespace cv { + +////////////////////////// XML & YAML I/O ////////////////////////// + +class CV_EXPORTS FileNode; +class CV_EXPORTS FileNodeIterator; + +/*! + XML/YAML File Storage Class. + + The class describes an object associated with XML or YAML file. + It can be used to store data to such a file or read and decode the data. + + The storage is organized as a tree of nested sequences (or lists) and mappings. + Sequence is a heterogenious array, which elements are accessed by indices or sequentially using an iterator. + Mapping is analogue of std::map or C structure, which elements are accessed by names. + The most top level structure is a mapping. + Leaves of the file storage tree are integers, floating-point numbers and text strings. + + For example, the following code: + + \code + // open file storage for writing. Type of the file is determined from the extension + FileStorage fs("test.yml", FileStorage::WRITE); + fs << "test_int" << 5 << "test_real" << 3.1 << "test_string" << "ABCDEFGH"; + fs << "test_mat" << Mat::eye(3,3,CV_32F); + + fs << "test_list" << "[" << 0.0000000000001 << 2 << CV_PI << -3435345 << "2-502 2-029 3egegeg" << + "{:" << "month" << 12 << "day" << 31 << "year" << 1969 << "}" << "]"; + fs << "test_map" << "{" << "x" << 1 << "y" << 2 << "width" << 100 << "height" << 200 << "lbp" << "[:"; + + const uchar arr[] = {0, 1, 1, 0, 1, 1, 0, 1}; + fs.writeRaw("u", arr, (int)(sizeof(arr)/sizeof(arr[0]))); + + fs << "]" << "}"; + \endcode + + will produce the following file: + + \verbatim + %YAML:1.0 + test_int: 5 + test_real: 3.1000000000000001e+00 + test_string: ABCDEFGH + test_mat: !!opencv-matrix + rows: 3 + cols: 3 + dt: f + data: [ 1., 0., 0., 0., 1., 0., 0., 0., 1. ] + test_list: + - 1.0000000000000000e-13 + - 2 + - 3.1415926535897931e+00 + - -3435345 + - "2-502 2-029 3egegeg" + - { month:12, day:31, year:1969 } + test_map: + x: 1 + y: 2 + width: 100 + height: 200 + lbp: [ 0, 1, 1, 0, 1, 1, 0, 1 ] + \endverbatim + + and to read the file above, the following code can be used: + + \code + // open file storage for reading. + // Type of the file is determined from the content, not the extension + FileStorage fs("test.yml", FileStorage::READ); + int test_int = (int)fs["test_int"]; + double test_real = (double)fs["test_real"]; + String test_string = (String)fs["test_string"]; + + Mat M; + fs["test_mat"] >> M; + + FileNode tl = fs["test_list"]; + CV_Assert(tl.type() == FileNode::SEQ && tl.size() == 6); + double tl0 = (double)tl[0]; + int tl1 = (int)tl[1]; + double tl2 = (double)tl[2]; + int tl3 = (int)tl[3]; + String tl4 = (String)tl[4]; + CV_Assert(tl[5].type() == FileNode::MAP && tl[5].size() == 3); + + int month = (int)tl[5]["month"]; + int day = (int)tl[5]["day"]; + int year = (int)tl[5]["year"]; + + FileNode tm = fs["test_map"]; + + int x = (int)tm["x"]; + int y = (int)tm["y"]; + int width = (int)tm["width"]; + int height = (int)tm["height"]; + + int lbp_val = 0; + FileNodeIterator it = tm["lbp"].begin(); + + for(int k = 0; k < 8; k++, ++it) + lbp_val |= ((int)*it) << k; + \endcode +*/ +class CV_EXPORTS_W FileStorage +{ +public: + //! file storage mode + enum + { + READ = 0, //! read mode + WRITE = 1, //! write mode + APPEND = 2, //! append mode + MEMORY = 4, + FORMAT_MASK = (7<<3), + FORMAT_AUTO = 0, + FORMAT_XML = (1<<3), + FORMAT_YAML = (2<<3) + }; + enum + { + UNDEFINED = 0, + VALUE_EXPECTED = 1, + NAME_EXPECTED = 2, + INSIDE_MAP = 4 + }; + //! the default constructor + CV_WRAP FileStorage(); + //! the full constructor that opens file storage for reading or writing + CV_WRAP FileStorage(const String& source, int flags, const String& encoding=String()); + //! the constructor that takes pointer to the C FileStorage structure + FileStorage(CvFileStorage* fs, bool owning=true); + //! the destructor. calls release() + virtual ~FileStorage(); + + //! opens file storage for reading or writing. The previous storage is closed with release() + CV_WRAP virtual bool open(const String& filename, int flags, const String& encoding=String()); + //! returns true if the object is associated with currently opened file. + CV_WRAP virtual bool isOpened() const; + //! closes the file and releases all the memory buffers + CV_WRAP virtual void release(); + //! closes the file, releases all the memory buffers and returns the text string + CV_WRAP virtual String releaseAndGetString(); + + //! returns the first element of the top-level mapping + CV_WRAP FileNode getFirstTopLevelNode() const; + //! returns the top-level mapping. YAML supports multiple streams + CV_WRAP FileNode root(int streamidx=0) const; + //! returns the specified element of the top-level mapping + FileNode operator[](const String& nodename) const; + //! returns the specified element of the top-level mapping + CV_WRAP FileNode operator[](const char* nodename) const; + + //! returns pointer to the underlying C FileStorage structure + CvFileStorage* operator *() { return fs.get(); } + //! returns pointer to the underlying C FileStorage structure + const CvFileStorage* operator *() const { return fs.get(); } + //! writes one or more numbers of the specified format to the currently written structure + void writeRaw( const String& fmt, const uchar* vec, size_t len ); + //! writes the registered C structure (CvMat, CvMatND, CvSeq). See cvWrite() + void writeObj( const String& name, const void* obj ); + + //! returns the normalized object name for the specified file name + static String getDefaultObjectName(const String& filename); + + Ptr fs; //!< the underlying C FileStorage structure + String elname; //!< the currently written element + std::vector structs; //!< the stack of written structures + int state; //!< the writer state +}; + +template<> CV_EXPORTS void DefaultDeleter::operator ()(CvFileStorage* obj) const; + +/*! + File Storage Node class + + The node is used to store each and every element of the file storage opened for reading - + from the primitive objects, such as numbers and text strings, to the complex nodes: + sequences, mappings and the registered objects. + + Note that file nodes are only used for navigating file storages opened for reading. + When a file storage is opened for writing, no data is stored in memory after it is written. +*/ +class CV_EXPORTS_W_SIMPLE FileNode +{ +public: + //! type of the file storage node + enum + { + NONE = 0, //!< empty node + INT = 1, //!< an integer + REAL = 2, //!< floating-point number + FLOAT = REAL, //!< synonym or REAL + STR = 3, //!< text string in UTF-8 encoding + STRING = STR, //!< synonym for STR + REF = 4, //!< integer of size size_t. Typically used for storing complex dynamic structures where some elements reference the others + SEQ = 5, //!< sequence + MAP = 6, //!< mapping + TYPE_MASK = 7, + FLOW = 8, //!< compact representation of a sequence or mapping. Used only by YAML writer + USER = 16, //!< a registered object (e.g. a matrix) + EMPTY = 32, //!< empty structure (sequence or mapping) + NAMED = 64 //!< the node has a name (i.e. it is element of a mapping) + }; + //! the default constructor + CV_WRAP FileNode(); + //! the full constructor wrapping CvFileNode structure. + FileNode(const CvFileStorage* fs, const CvFileNode* node); + //! the copy constructor + FileNode(const FileNode& node); + //! returns element of a mapping node + FileNode operator[](const String& nodename) const; + //! returns element of a mapping node + CV_WRAP FileNode operator[](const char* nodename) const; + //! returns element of a sequence node + CV_WRAP FileNode operator[](int i) const; + //! returns type of the node + CV_WRAP int type() const; + + //! returns true if the node is empty + CV_WRAP bool empty() const; + //! returns true if the node is a "none" object + CV_WRAP bool isNone() const; + //! returns true if the node is a sequence + CV_WRAP bool isSeq() const; + //! returns true if the node is a mapping + CV_WRAP bool isMap() const; + //! returns true if the node is an integer + CV_WRAP bool isInt() const; + //! returns true if the node is a floating-point number + CV_WRAP bool isReal() const; + //! returns true if the node is a text string + CV_WRAP bool isString() const; + //! returns true if the node has a name + CV_WRAP bool isNamed() const; + //! returns the node name or an empty string if the node is nameless + CV_WRAP String name() const; + //! returns the number of elements in the node, if it is a sequence or mapping, or 1 otherwise. + CV_WRAP size_t size() const; + //! returns the node content as an integer. If the node stores floating-point number, it is rounded. + operator int() const; + //! returns the node content as float + operator float() const; + //! returns the node content as double + operator double() const; + //! returns the node content as text string + operator String() const; +#ifndef OPENCV_NOSTL + operator std::string() const; +#endif + + //! returns pointer to the underlying file node + CvFileNode* operator *(); + //! returns pointer to the underlying file node + const CvFileNode* operator* () const; + + //! returns iterator pointing to the first node element + FileNodeIterator begin() const; + //! returns iterator pointing to the element following the last node element + FileNodeIterator end() const; + + //! reads node elements to the buffer with the specified format + void readRaw( const String& fmt, uchar* vec, size_t len ) const; + //! reads the registered object and returns pointer to it + void* readObj() const; + + // do not use wrapper pointer classes for better efficiency + const CvFileStorage* fs; + const CvFileNode* node; +}; + + +/*! + File Node Iterator + + The class is used for iterating sequences (usually) and mappings. + */ +class CV_EXPORTS FileNodeIterator +{ +public: + //! the default constructor + FileNodeIterator(); + //! the full constructor set to the ofs-th element of the node + FileNodeIterator(const CvFileStorage* fs, const CvFileNode* node, size_t ofs=0); + //! the copy constructor + FileNodeIterator(const FileNodeIterator& it); + //! returns the currently observed element + FileNode operator *() const; + //! accesses the currently observed element methods + FileNode operator ->() const; + + //! moves iterator to the next node + FileNodeIterator& operator ++ (); + //! moves iterator to the next node + FileNodeIterator operator ++ (int); + //! moves iterator to the previous node + FileNodeIterator& operator -- (); + //! moves iterator to the previous node + FileNodeIterator operator -- (int); + //! moves iterator forward by the specified offset (possibly negative) + FileNodeIterator& operator += (int ofs); + //! moves iterator backward by the specified offset (possibly negative) + FileNodeIterator& operator -= (int ofs); + + //! reads the next maxCount elements (or less, if the sequence/mapping last element occurs earlier) to the buffer with the specified format + FileNodeIterator& readRaw( const String& fmt, uchar* vec, + size_t maxCount=(size_t)INT_MAX ); + + struct SeqReader + { + int header_size; + void* seq; /* sequence, beign read; CvSeq */ + void* block; /* current block; CvSeqBlock */ + schar* ptr; /* pointer to element be read next */ + schar* block_min; /* pointer to the beginning of block */ + schar* block_max; /* pointer to the end of block */ + int delta_index;/* = seq->first->start_index */ + schar* prev_elem; /* pointer to previous element */ + }; + + const CvFileStorage* fs; + const CvFileNode* container; + SeqReader reader; + size_t remaining; +}; + + + +/////////////////// XML & YAML I/O implementation ////////////////// + +CV_EXPORTS void write( FileStorage& fs, const String& name, int value ); +CV_EXPORTS void write( FileStorage& fs, const String& name, float value ); +CV_EXPORTS void write( FileStorage& fs, const String& name, double value ); +CV_EXPORTS void write( FileStorage& fs, const String& name, const String& value ); +CV_EXPORTS void write( FileStorage& fs, const String& name, const Mat& value ); +CV_EXPORTS void write( FileStorage& fs, const String& name, const SparseMat& value ); +CV_EXPORTS void write( FileStorage& fs, const String& name, const std::vector& value); + +CV_EXPORTS void writeScalar( FileStorage& fs, int value ); +CV_EXPORTS void writeScalar( FileStorage& fs, float value ); +CV_EXPORTS void writeScalar( FileStorage& fs, double value ); +CV_EXPORTS void writeScalar( FileStorage& fs, const String& value ); + +CV_EXPORTS void read(const FileNode& node, int& value, int default_value); +CV_EXPORTS void read(const FileNode& node, float& value, float default_value); +CV_EXPORTS void read(const FileNode& node, double& value, double default_value); +CV_EXPORTS void read(const FileNode& node, String& value, const String& default_value); +CV_EXPORTS void read(const FileNode& node, Mat& mat, const Mat& default_mat = Mat() ); +CV_EXPORTS void read(const FileNode& node, SparseMat& mat, const SparseMat& default_mat = SparseMat() ); +CV_EXPORTS void read(const FileNode& node, std::vector& keypoints); + +template static inline void read(const FileNode& node, Point_<_Tp>& value, const Point_<_Tp>& default_value) +{ + std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; + value = temp.size() != 2 ? default_value : Point_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1])); +} + +template static inline void read(const FileNode& node, Point3_<_Tp>& value, const Point3_<_Tp>& default_value) +{ + std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; + value = temp.size() != 3 ? default_value : Point3_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]), + saturate_cast<_Tp>(temp[2])); +} + +template static inline void read(const FileNode& node, Size_<_Tp>& value, const Size_<_Tp>& default_value) +{ + std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; + value = temp.size() != 2 ? default_value : Size_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1])); +} + +template static inline void read(const FileNode& node, Complex<_Tp>& value, const Complex<_Tp>& default_value) +{ + std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; + value = temp.size() != 2 ? default_value : Complex<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1])); +} + +template static inline void read(const FileNode& node, Rect_<_Tp>& value, const Rect_<_Tp>& default_value) +{ + std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; + value = temp.size() != 4 ? default_value : Rect_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]), + saturate_cast<_Tp>(temp[2]), saturate_cast<_Tp>(temp[3])); +} + +template static inline void read(const FileNode& node, Vec<_Tp, cn>& value, const Vec<_Tp, cn>& default_value) +{ + std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; + value = temp.size() != cn ? default_value : Vec<_Tp, cn>(&temp[0]); +} + +template static inline void read(const FileNode& node, Scalar_<_Tp>& value, const Scalar_<_Tp>& default_value) +{ + std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; + value = temp.size() != 4 ? default_value : Scalar_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]), + saturate_cast<_Tp>(temp[2]), saturate_cast<_Tp>(temp[3])); +} + +static inline void read(const FileNode& node, Range& value, const Range& default_value) +{ + Point2i temp(value.start, value.end); const Point2i default_temp = Point2i(default_value.start, default_value.end); + read(node, temp, default_temp); + value.start = temp.x; value.end = temp.y; +} + + +CV_EXPORTS FileStorage& operator << (FileStorage& fs, const String& str); + + +namespace internal +{ + class CV_EXPORTS WriteStructContext + { + public: + WriteStructContext(FileStorage& _fs, const String& name, int flags, const String& typeName = String()); + ~WriteStructContext(); + private: + FileStorage* fs; + }; + + template class VecWriterProxy + { + public: + VecWriterProxy( FileStorage* _fs ) : fs(_fs) {} + void operator()(const std::vector<_Tp>& vec) const + { + size_t count = vec.size(); + for (size_t i = 0; i < count; i++) + write(*fs, vec[i]); + } + private: + FileStorage* fs; + }; + + template class VecWriterProxy<_Tp, 1> + { + public: + VecWriterProxy( FileStorage* _fs ) : fs(_fs) {} + void operator()(const std::vector<_Tp>& vec) const + { + int _fmt = DataType<_Tp>::fmt; + char fmt[] = { (char)((_fmt >> 8) + '1'), (char)_fmt, '\0' }; + fs->writeRaw(fmt, !vec.empty() ? (uchar*)&vec[0] : 0, vec.size() * sizeof(_Tp)); + } + private: + FileStorage* fs; + }; + + template class VecReaderProxy + { + public: + VecReaderProxy( FileNodeIterator* _it ) : it(_it) {} + void operator()(std::vector<_Tp>& vec, size_t count) const + { + count = std::min(count, it->remaining); + vec.resize(count); + for (size_t i = 0; i < count; i++, ++(*it)) + read(**it, vec[i], _Tp()); + } + private: + FileNodeIterator* it; + }; + + template class VecReaderProxy<_Tp, 1> + { + public: + VecReaderProxy( FileNodeIterator* _it ) : it(_it) {} + void operator()(std::vector<_Tp>& vec, size_t count) const + { + size_t remaining = it->remaining; + size_t cn = DataType<_Tp>::channels; + int _fmt = DataType<_Tp>::fmt; + char fmt[] = { (char)((_fmt >> 8)+'1'), (char)_fmt, '\0' }; + size_t remaining1 = remaining / cn; + count = count < remaining1 ? count : remaining1; + vec.resize(count); + it->readRaw(fmt, !vec.empty() ? (uchar*)&vec[0] : 0, count*sizeof(_Tp)); + } + private: + FileNodeIterator* it; + }; + +} // internal + + + +template static inline +void write(FileStorage& fs, const _Tp& value) +{ + write(fs, String(), value); +} + +template<> inline +void write( FileStorage& fs, const int& value ) +{ + writeScalar(fs, value); +} + +template<> inline +void write( FileStorage& fs, const float& value ) +{ + writeScalar(fs, value); +} + +template<> inline +void write( FileStorage& fs, const double& value ) +{ + writeScalar(fs, value); +} + +template<> inline +void write( FileStorage& fs, const String& value ) +{ + writeScalar(fs, value); +} + +template static inline +void write(FileStorage& fs, const Point_<_Tp>& pt ) +{ + write(fs, pt.x); + write(fs, pt.y); +} + +template static inline +void write(FileStorage& fs, const Point3_<_Tp>& pt ) +{ + write(fs, pt.x); + write(fs, pt.y); + write(fs, pt.z); +} + +template static inline +void write(FileStorage& fs, const Size_<_Tp>& sz ) +{ + write(fs, sz.width); + write(fs, sz.height); +} + +template static inline +void write(FileStorage& fs, const Complex<_Tp>& c ) +{ + write(fs, c.re); + write(fs, c.im); +} + +template static inline +void write(FileStorage& fs, const Rect_<_Tp>& r ) +{ + write(fs, r.x); + write(fs, r.y); + write(fs, r.width); + write(fs, r.height); +} + +template static inline +void write(FileStorage& fs, const Vec<_Tp, cn>& v ) +{ + for(int i = 0; i < cn; i++) + write(fs, v.val[i]); +} + +template static inline +void write(FileStorage& fs, const Scalar_<_Tp>& s ) +{ + write(fs, s.val[0]); + write(fs, s.val[1]); + write(fs, s.val[2]); + write(fs, s.val[3]); +} + +static inline +void write(FileStorage& fs, const Range& r ) +{ + write(fs, r.start); + write(fs, r.end); +} + +template static inline +void write( FileStorage& fs, const std::vector<_Tp>& vec ) +{ + internal::VecWriterProxy<_Tp, DataType<_Tp>::fmt != 0> w(&fs); + w(vec); +} + + +template static inline +void write(FileStorage& fs, const String& name, const Point_<_Tp>& pt ) +{ + internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); + write(fs, pt); +} + +template static inline +void write(FileStorage& fs, const String& name, const Point3_<_Tp>& pt ) +{ + internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); + write(fs, pt); +} + +template static inline +void write(FileStorage& fs, const String& name, const Size_<_Tp>& sz ) +{ + internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); + write(fs, sz); +} + +template static inline +void write(FileStorage& fs, const String& name, const Complex<_Tp>& c ) +{ + internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); + write(fs, c); +} + +template static inline +void write(FileStorage& fs, const String& name, const Rect_<_Tp>& r ) +{ + internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); + write(fs, r); +} + +template static inline +void write(FileStorage& fs, const String& name, const Vec<_Tp, cn>& v ) +{ + internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); + write(fs, v); +} + +template static inline +void write(FileStorage& fs, const String& name, const Scalar_<_Tp>& s ) +{ + internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); + write(fs, s); +} + +static inline +void write(FileStorage& fs, const String& name, const Range& r ) +{ + internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); + write(fs, r); +} + +template static inline +void write( FileStorage& fs, const String& name, const std::vector<_Tp>& vec ) +{ + internal::WriteStructContext ws(fs, name, FileNode::SEQ+(DataType<_Tp>::fmt != 0 ? FileNode::FLOW : 0)); + write(fs, vec); +} + + +static inline +void read(const FileNode& node, bool& value, bool default_value) +{ + int temp; + read(node, temp, (int)default_value); + value = temp != 0; +} + +static inline +void read(const FileNode& node, uchar& value, uchar default_value) +{ + int temp; + read(node, temp, (int)default_value); + value = saturate_cast(temp); +} + +static inline +void read(const FileNode& node, schar& value, schar default_value) +{ + int temp; + read(node, temp, (int)default_value); + value = saturate_cast(temp); +} + +static inline +void read(const FileNode& node, ushort& value, ushort default_value) +{ + int temp; + read(node, temp, (int)default_value); + value = saturate_cast(temp); +} + +static inline +void read(const FileNode& node, short& value, short default_value) +{ + int temp; + read(node, temp, (int)default_value); + value = saturate_cast(temp); +} + +template static inline +void read( FileNodeIterator& it, std::vector<_Tp>& vec, size_t maxCount = (size_t)INT_MAX ) +{ + internal::VecReaderProxy<_Tp, DataType<_Tp>::fmt != 0> r(&it); + r(vec, maxCount); +} + +template static inline +void read( const FileNode& node, std::vector<_Tp>& vec, const std::vector<_Tp>& default_value = std::vector<_Tp>() ) +{ + if(!node.node) + vec = default_value; + else + { + FileNodeIterator it = node.begin(); + read( it, vec ); + } +} + + +template static inline +FileStorage& operator << (FileStorage& fs, const _Tp& value) +{ + if( !fs.isOpened() ) + return fs; + if( fs.state == FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP ) + CV_Error( Error::StsError, "No element name has been given" ); + write( fs, fs.elname, value ); + if( fs.state & FileStorage::INSIDE_MAP ) + fs.state = FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP; + return fs; +} + +static inline +FileStorage& operator << (FileStorage& fs, const char* str) +{ + return (fs << String(str)); +} + +static inline +FileStorage& operator << (FileStorage& fs, char* value) +{ + return (fs << String(value)); +} + +template static inline +FileNodeIterator& operator >> (FileNodeIterator& it, _Tp& value) +{ + read( *it, value, _Tp()); + return ++it; +} + +template static inline +FileNodeIterator& operator >> (FileNodeIterator& it, std::vector<_Tp>& vec) +{ + internal::VecReaderProxy<_Tp, DataType<_Tp>::fmt != 0> r(&it); + r(vec, (size_t)INT_MAX); + return it; +} + +template static inline +void operator >> (const FileNode& n, _Tp& value) +{ + read( n, value, _Tp()); +} + +template static inline +void operator >> (const FileNode& n, std::vector<_Tp>& vec) +{ + FileNodeIterator it = n.begin(); + it >> vec; +} + + +static inline +bool operator == (const FileNodeIterator& it1, const FileNodeIterator& it2) +{ + return it1.fs == it2.fs && it1.container == it2.container && + it1.reader.ptr == it2.reader.ptr && it1.remaining == it2.remaining; +} + +static inline +bool operator != (const FileNodeIterator& it1, const FileNodeIterator& it2) +{ + return !(it1 == it2); +} + +static inline +ptrdiff_t operator - (const FileNodeIterator& it1, const FileNodeIterator& it2) +{ + return it2.remaining - it1.remaining; +} + +static inline +bool operator < (const FileNodeIterator& it1, const FileNodeIterator& it2) +{ + return it1.remaining > it2.remaining; +} + +inline FileNode FileStorage::getFirstTopLevelNode() const { FileNode r = root(); FileNodeIterator it = r.begin(); return it != r.end() ? *it : FileNode(); } +inline FileNode::FileNode() : fs(0), node(0) {} +inline FileNode::FileNode(const CvFileStorage* _fs, const CvFileNode* _node) : fs(_fs), node(_node) {} +inline FileNode::FileNode(const FileNode& _node) : fs(_node.fs), node(_node.node) {} +inline bool FileNode::empty() const { return node == 0; } +inline bool FileNode::isNone() const { return type() == NONE; } +inline bool FileNode::isSeq() const { return type() == SEQ; } +inline bool FileNode::isMap() const { return type() == MAP; } +inline bool FileNode::isInt() const { return type() == INT; } +inline bool FileNode::isReal() const { return type() == REAL; } +inline bool FileNode::isString() const { return type() == STR; } +inline CvFileNode* FileNode::operator *() { return (CvFileNode*)node; } +inline const CvFileNode* FileNode::operator* () const { return node; } +inline FileNode::operator int() const { int value; read(*this, value, 0); return value; } +inline FileNode::operator float() const { float value; read(*this, value, 0.f); return value; } +inline FileNode::operator double() const { double value; read(*this, value, 0.); return value; } +inline FileNode::operator String() const { String value; read(*this, value, value); return value; } +inline FileNodeIterator FileNode::begin() const { return FileNodeIterator(fs, node); } +inline FileNodeIterator FileNode::end() const { return FileNodeIterator(fs, node, size()); } +inline void FileNode::readRaw( const String& fmt, uchar* vec, size_t len ) const { begin().readRaw( fmt, vec, len ); } +inline FileNode FileNodeIterator::operator *() const { return FileNode(fs, (const CvFileNode*)reader.ptr); } +inline FileNode FileNodeIterator::operator ->() const { return FileNode(fs, (const CvFileNode*)reader.ptr); } +inline String::String(const FileNode& fn): cstr_(0), len_(0) { read(fn, *this, *this); } + +} // cv + +#endif // __OPENCV_CORE_PERSISTENCE_HPP__ diff --git a/modules/core/include/opencv2/core/private.gpu.hpp b/modules/core/include/opencv2/core/private.gpu.hpp new file mode 100644 index 0000000000..d26cd0017f --- /dev/null +++ b/modules/core/include/opencv2/core/private.gpu.hpp @@ -0,0 +1,143 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_PRIVATE_GPU_HPP__ +#define __OPENCV_CORE_PRIVATE_GPU_HPP__ + +#ifndef __OPENCV_BUILD +# error this is a private header which should not be used from outside of the OpenCV library +#endif + +#include "cvconfig.h" + +#include "opencv2/core/cvdef.h" +#include "opencv2/core/base.hpp" + +#include "opencv2/core/gpu.hpp" + +#ifdef HAVE_CUDA +# include +# include +# include +# include "opencv2/core/gpu_stream_accessor.hpp" +# include "opencv2/core/cuda/common.hpp" + +# define NPP_VERSION (NPP_VERSION_MAJOR * 1000 + NPP_VERSION_MINOR * 100 + NPP_VERSION_BUILD) + +# define CUDART_MINIMUM_REQUIRED_VERSION 4020 + +# if (CUDART_VERSION < CUDART_MINIMUM_REQUIRED_VERSION) +# error "Insufficient Cuda Runtime library version, please update it." +# endif + +# if defined(CUDA_ARCH_BIN_OR_PTX_10) +# error "OpenCV GPU module doesn't support NVIDIA compute capability 1.0" +# endif +#endif + +namespace cv { namespace gpu { + CV_EXPORTS cv::String getNppErrorMessage(int code); + CV_EXPORTS cv::String getCudaDriverApiErrorMessage(int code); +}} + +#ifndef HAVE_CUDA + +static inline void throw_no_cuda() { CV_Error(cv::Error::GpuNotSupported, "The library is compiled without GPU support"); } + +#else // HAVE_CUDA + +static inline void throw_no_cuda() { CV_Error(cv::Error::StsNotImplemented, "The called functionality is disabled for current build or platform"); } + +namespace cv { namespace gpu +{ + static inline void checkNppError(int code, const char* file, const int line, const char* func) + { + if (code < 0) + cv::error(cv::Error::GpuApiCallError, getNppErrorMessage(code), func, file, line); + } + + static inline void checkCudaDriverApiError(int code, const char* file, const int line, const char* func) + { + if (code != CUDA_SUCCESS) + cv::error(cv::Error::GpuApiCallError, getCudaDriverApiErrorMessage(code), func, file, line); + } + + template struct NPPTypeTraits; + template<> struct NPPTypeTraits { typedef Npp8u npp_type; }; + template<> struct NPPTypeTraits { typedef Npp8s npp_type; }; + template<> struct NPPTypeTraits { typedef Npp16u npp_type; }; + template<> struct NPPTypeTraits { typedef Npp16s npp_type; }; + template<> struct NPPTypeTraits { typedef Npp32s npp_type; }; + template<> struct NPPTypeTraits { typedef Npp32f npp_type; }; + template<> struct NPPTypeTraits { typedef Npp64f npp_type; }; + + class NppStreamHandler + { + public: + inline explicit NppStreamHandler(cudaStream_t newStream) + { + oldStream = nppGetStream(); + nppSetStream(newStream); + } + + inline ~NppStreamHandler() + { + nppSetStream(oldStream); + } + + private: + cudaStream_t oldStream; + }; +}} + +#if defined(__GNUC__) + #define nppSafeCall(expr) cv::gpu::checkNppError(expr, __FILE__, __LINE__, __func__) + #define cuSafeCall(expr) cv::gpu::checkCudaDriverApiError(expr, __FILE__, __LINE__, __func__) +#else /* defined(__CUDACC__) || defined(__MSVC__) */ + #define nppSafeCall(expr) cv::gpu::checkNppError(expr, __FILE__, __LINE__, "") + #define cuSafeCall(expr) cv::gpu::checkCudaDriverApiError(expr, __FILE__, __LINE__, "") +#endif + +#endif // HAVE_CUDA + +#endif // __OPENCV_CORE_GPU_PRIVATE_HPP__ diff --git a/modules/core/include/opencv2/core/private.hpp b/modules/core/include/opencv2/core/private.hpp new file mode 100644 index 0000000000..a1cc0e5c89 --- /dev/null +++ b/modules/core/include/opencv2/core/private.hpp @@ -0,0 +1,373 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_PRIVATE_HPP__ +#define __OPENCV_CORE_PRIVATE_HPP__ + +#ifndef __OPENCV_BUILD +# error this is a private header which should not be used from outside of the OpenCV library +#endif + +#include "opencv2/core.hpp" +#include "cvconfig.h" + +#ifdef HAVE_EIGEN +# if defined __GNUC__ && defined __APPLE__ +# pragma GCC diagnostic ignored "-Wshadow" +# endif +# include +# include "opencv2/core/eigen.hpp" +#endif + +#ifdef HAVE_TBB +# include "tbb/tbb_stddef.h" +# if TBB_VERSION_MAJOR*100 + TBB_VERSION_MINOR >= 202 +# include "tbb/tbb.h" +# include "tbb/task.h" +# undef min +# undef max +# else +# undef HAVE_TBB +# endif +#endif + +namespace cv +{ +#ifdef HAVE_TBB + + typedef tbb::blocked_range BlockedRange; + + template static inline + void parallel_for( const BlockedRange& range, const Body& body ) + { + tbb::parallel_for(range, body); + } + + typedef tbb::split Split; + + template static inline + void parallel_reduce( const BlockedRange& range, Body& body ) + { + tbb::parallel_reduce(range, body); + } + + typedef tbb::concurrent_vector ConcurrentRectVector; +#else + class BlockedRange + { + public: + BlockedRange() : _begin(0), _end(0), _grainsize(0) {} + BlockedRange(int b, int e, int g=1) : _begin(b), _end(e), _grainsize(g) {} + int begin() const { return _begin; } + int end() const { return _end; } + int grainsize() const { return _grainsize; } + + protected: + int _begin, _end, _grainsize; + }; + + template static inline + void parallel_for( const BlockedRange& range, const Body& body ) + { + body(range); + } + typedef std::vector ConcurrentRectVector; + + class Split {}; + + template static inline + void parallel_reduce( const BlockedRange& range, Body& body ) + { + body(range); + } +#endif + + // Returns a static string if there is a parallel framework, + // NULL otherwise. + CV_EXPORTS const char* currentParallelFramework(); +} //namespace cv + +#define CV_INIT_ALGORITHM(classname, algname, memberinit) \ + static inline ::cv::Algorithm* create##classname##_hidden() \ + { \ + return new classname; \ + } \ + \ + static inline ::cv::Ptr< ::cv::Algorithm> create##classname##_ptr_hidden() \ + { \ + return ::cv::makePtr(); \ + } \ + \ + static inline ::cv::AlgorithmInfo& classname##_info() \ + { \ + static ::cv::AlgorithmInfo classname##_info_var(algname, create##classname##_hidden); \ + return classname##_info_var; \ + } \ + \ + static ::cv::AlgorithmInfo& classname##_info_auto = classname##_info(); \ + \ + ::cv::AlgorithmInfo* classname::info() const \ + { \ + static volatile bool initialized = false; \ + \ + if( !initialized ) \ + { \ + initialized = true; \ + classname obj; \ + memberinit; \ + } \ + return &classname##_info(); \ + } + + + +/****************************************************************************************\ +* Common declarations * +\****************************************************************************************/ + +/* the alignment of all the allocated buffers */ +#define CV_MALLOC_ALIGN 16 + +#ifdef __GNUC__ +# define CV_DECL_ALIGNED(x) __attribute__ ((aligned (x))) +#elif defined _MSC_VER +# define CV_DECL_ALIGNED(x) __declspec(align(x)) +#else +# define CV_DECL_ALIGNED(x) +#endif + +/* IEEE754 constants and macros */ +#define CV_TOGGLE_FLT(x) ((x)^((int)(x) < 0 ? 0x7fffffff : 0)) +#define CV_TOGGLE_DBL(x) ((x)^((int64)(x) < 0 ? CV_BIG_INT(0x7fffffffffffffff) : 0)) + +static inline void* cvAlignPtr( const void* ptr, int align = 32 ) +{ + CV_DbgAssert ( (align & (align-1)) == 0 ); + return (void*)( ((size_t)ptr + align - 1) & ~(size_t)(align-1) ); +} + +static inline int cvAlign( int size, int align ) +{ + CV_DbgAssert( (align & (align-1)) == 0 && size < INT_MAX ); + return (size + align - 1) & -align; +} + +#ifdef IPL_DEPTH_8U +static inline cv::Size cvGetMatSize( const CvMat* mat ) +{ + return cv::Size(mat->cols, mat->rows); +} +#endif + +namespace cv +{ +CV_EXPORTS void scalarToRawData(const cv::Scalar& s, void* buf, int type, int unroll_to = 0); +} + + +/****************************************************************************************\ +* Structures and macros for integration with IPP * +\****************************************************************************************/ + +#ifdef HAVE_IPP +# include "ipp.h" + +static inline IppiSize ippiSize(int width, int height) +{ + IppiSize size = { width, height }; + return size; +} +#endif + +#ifndef IPPI_CALL +# define IPPI_CALL(func) CV_Assert((func) >= 0) +#endif + +/* IPP-compatible return codes */ +typedef enum CvStatus +{ + CV_BADMEMBLOCK_ERR = -113, + CV_INPLACE_NOT_SUPPORTED_ERR= -112, + CV_UNMATCHED_ROI_ERR = -111, + CV_NOTFOUND_ERR = -110, + CV_BADCONVERGENCE_ERR = -109, + + CV_BADDEPTH_ERR = -107, + CV_BADROI_ERR = -106, + CV_BADHEADER_ERR = -105, + CV_UNMATCHED_FORMATS_ERR = -104, + CV_UNSUPPORTED_COI_ERR = -103, + CV_UNSUPPORTED_CHANNELS_ERR = -102, + CV_UNSUPPORTED_DEPTH_ERR = -101, + CV_UNSUPPORTED_FORMAT_ERR = -100, + + CV_BADARG_ERR = -49, //ipp comp + CV_NOTDEFINED_ERR = -48, //ipp comp + + CV_BADCHANNELS_ERR = -47, //ipp comp + CV_BADRANGE_ERR = -44, //ipp comp + CV_BADSTEP_ERR = -29, //ipp comp + + CV_BADFLAG_ERR = -12, + CV_DIV_BY_ZERO_ERR = -11, //ipp comp + CV_BADCOEF_ERR = -10, + + CV_BADFACTOR_ERR = -7, + CV_BADPOINT_ERR = -6, + CV_BADSCALE_ERR = -4, + CV_OUTOFMEM_ERR = -3, + CV_NULLPTR_ERR = -2, + CV_BADSIZE_ERR = -1, + CV_NO_ERR = 0, + CV_OK = CV_NO_ERR +} +CvStatus; + + + +/****************************************************************************************\ +* Auxiliary algorithms * +\****************************************************************************************/ + +namespace cv +{ + +// This function splits the input sequence or set into one or more equivalence classes and +// returns the vector of labels - 0-based class indexes for each element. +// predicate(a,b) returns true if the two sequence elements certainly belong to the same class. +// +// The algorithm is described in "Introduction to Algorithms" +// by Cormen, Leiserson and Rivest, the chapter "Data structures for disjoint sets" +template int +partition( const std::vector<_Tp>& _vec, std::vector& labels, + _EqPredicate predicate=_EqPredicate()) +{ + int i, j, N = (int)_vec.size(); + const _Tp* vec = &_vec[0]; + + const int PARENT=0; + const int RANK=1; + + std::vector _nodes(N*2); + int (*nodes)[2] = (int(*)[2])&_nodes[0]; + + // The first O(N) pass: create N single-vertex trees + for(i = 0; i < N; i++) + { + nodes[i][PARENT]=-1; + nodes[i][RANK] = 0; + } + + // The main O(N^2) pass: merge connected components + for( i = 0; i < N; i++ ) + { + int root = i; + + // find root + while( nodes[root][PARENT] >= 0 ) + root = nodes[root][PARENT]; + + for( j = 0; j < N; j++ ) + { + if( i == j || !predicate(vec[i], vec[j])) + continue; + int root2 = j; + + while( nodes[root2][PARENT] >= 0 ) + root2 = nodes[root2][PARENT]; + + if( root2 != root ) + { + // unite both trees + int rank = nodes[root][RANK], rank2 = nodes[root2][RANK]; + if( rank > rank2 ) + nodes[root2][PARENT] = root; + else + { + nodes[root][PARENT] = root2; + nodes[root2][RANK] += rank == rank2; + root = root2; + } + CV_Assert( nodes[root][PARENT] < 0 ); + + int k = j, parent; + + // compress the path from node2 to root + while( (parent = nodes[k][PARENT]) >= 0 ) + { + nodes[k][PARENT] = root; + k = parent; + } + + // compress the path from node to root + k = i; + while( (parent = nodes[k][PARENT]) >= 0 ) + { + nodes[k][PARENT] = root; + k = parent; + } + } + } + } + + // Final O(N) pass: enumerate classes + labels.resize(N); + int nclasses = 0; + + for( i = 0; i < N; i++ ) + { + int root = i; + while( nodes[root][PARENT] >= 0 ) + root = nodes[root][PARENT]; + // re-use the rank as the class label + if( nodes[root][RANK] >= 0 ) + nodes[root][RANK] = ~nclasses++; + labels[i] = ~nodes[root][RANK]; + } + + return nclasses; +} + +} // namespace cv + +#endif // __OPENCV_CORE_PRIVATE_HPP__ diff --git a/modules/core/include/opencv2/core/ptr.inl.hpp b/modules/core/include/opencv2/core/ptr.inl.hpp new file mode 100644 index 0000000000..989724281f --- /dev/null +++ b/modules/core/include/opencv2/core/ptr.inl.hpp @@ -0,0 +1,338 @@ +/*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) 2013, NVIDIA Corporation, 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 copyright holders or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_PTR_INL_HPP__ +#define __OPENCV_CORE_PTR_INL_HPP__ + +#include + +namespace cv { + +template +void DefaultDeleter::operator () (Y* p) const +{ + delete p; +} + +namespace detail +{ + +struct PtrOwner +{ + PtrOwner() : refCount(1) + {} + + void incRef() + { + CV_XADD(&refCount, 1); + } + + void decRef() + { + if (CV_XADD(&refCount, -1) == 1) deleteSelf(); + } + +protected: + /* This doesn't really need to be virtual, since PtrOwner is never deleted + directly, but it doesn't hurt and it helps avoid warnings. */ + virtual ~PtrOwner() + {} + + virtual void deleteSelf() = 0; + +private: + unsigned int refCount; + + // noncopyable + PtrOwner(const PtrOwner&); + PtrOwner& operator = (const PtrOwner&); +}; + +template +struct PtrOwnerImpl : PtrOwner +{ + PtrOwnerImpl(Y* p, D d) : owned(p), deleter(d) + {} + + void deleteSelf() + { + deleter(owned); + delete this; + } + +private: + Y* owned; + D deleter; +}; + + +} + +template +Ptr::Ptr() : owner(NULL), stored(NULL) +{} + +template +template +Ptr::Ptr(Y* p) + : owner(p + ? new detail::PtrOwnerImpl >(p, DefaultDeleter()) + : NULL), + stored(p) +{} + +template +template +Ptr::Ptr(Y* p, D d) + : owner(p + ? new detail::PtrOwnerImpl(p, d) + : NULL), + stored(p) +{} + +template +Ptr::Ptr(const Ptr& o) : owner(o.owner), stored(o.stored) +{ + if (owner) owner->incRef(); +} + +template +template +Ptr::Ptr(const Ptr& o) : owner(o.owner), stored(o.stored) +{ + if (owner) owner->incRef(); +} + +template +template +Ptr::Ptr(const Ptr& o, T* p) : owner(o.owner), stored(p) +{ + if (owner) owner->incRef(); +} + +template +Ptr::~Ptr() +{ + release(); +} + +template +Ptr& Ptr::operator = (const Ptr& o) +{ + Ptr(o).swap(*this); + return *this; +} + +template +template +Ptr& Ptr::operator = (const Ptr& o) +{ + Ptr(o).swap(*this); + return *this; +} + +template +void Ptr::release() +{ + if (owner) owner->decRef(); + owner = NULL; + stored = NULL; +} + +template +template +void Ptr::reset(Y* p) +{ + Ptr(p).swap(*this); +} + +template +template +void Ptr::reset(Y* p, D d) +{ + Ptr(p, d).swap(*this); +} + +template +void Ptr::swap(Ptr& o) +{ + std::swap(owner, o.owner); + std::swap(stored, o.stored); +} + +template +T* Ptr::get() const +{ + return stored; +} + +template +typename detail::RefOrVoid::type Ptr::operator * () const +{ + return *stored; +} + +template +T* Ptr::operator -> () const +{ + return stored; +} + +template +Ptr::operator T* () const +{ + return stored; +} + + +template +bool Ptr::empty() const +{ + return !stored; +} + +template +template +Ptr Ptr::staticCast() const +{ + return Ptr(*this, static_cast(stored)); +} + +template +template +Ptr Ptr::constCast() const +{ + return Ptr(*this, const_cast(stored)); +} + +template +template +Ptr Ptr::dynamicCast() const +{ + return Ptr(*this, dynamic_cast(stored)); +} + +template +void swap(Ptr& ptr1, Ptr& ptr2){ + ptr1.swap(ptr2); +} + +template +bool operator == (const Ptr& ptr1, const Ptr& ptr2) +{ + return ptr1.get() == ptr2.get(); +} + +template +bool operator != (const Ptr& ptr1, const Ptr& ptr2) +{ + return ptr1.get() != ptr2.get(); +} + +template +Ptr makePtr() +{ + return Ptr(new T()); +} + +template +Ptr makePtr(const A1& a1) +{ + return Ptr(new T(a1)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2) +{ + return Ptr(new T(a1, a2)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3) +{ + return Ptr(new T(a1, a2, a3)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4) +{ + return Ptr(new T(a1, a2, a3, a4)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) +{ + return Ptr(new T(a1, a2, a3, a4, a5)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) +{ + return Ptr(new T(a1, a2, a3, a4, a5, a6)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) +{ + return Ptr(new T(a1, a2, a3, a4, a5, a6, a7)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) +{ + return Ptr(new T(a1, a2, a3, a4, a5, a6, a7, a8)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9) +{ + return Ptr(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10) +{ + return Ptr(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)); +} + +} // namespace cv + +#endif // __OPENCV_CORE_PTR_INL_HPP__ diff --git a/modules/core/include/opencv2/core/traits.hpp b/modules/core/include/opencv2/core/traits.hpp new file mode 100644 index 0000000000..85a5132f0e --- /dev/null +++ b/modules/core/include/opencv2/core/traits.hpp @@ -0,0 +1,282 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_TRAITS_HPP__ +#define __OPENCV_CORE_TRAITS_HPP__ + +#include "opencv2/core/cvdef.h" + +namespace cv +{ + +/*! + Informative template class for OpenCV "scalars". + + The class is specialized for each primitive numerical type supported by OpenCV (such as unsigned char or float), + as well as for more complex types, like cv::Complex<>, std::complex<>, cv::Vec<> etc. + The common property of all such types (called "scalars", do not confuse it with cv::Scalar_) + is that each of them is basically a tuple of numbers of the same type. Each "scalar" can be represented + by the depth id (CV_8U ... CV_64F) and the number of channels. + OpenCV matrices, 2D or nD, dense or sparse, can store "scalars", + as long as the number of channels does not exceed CV_CN_MAX. +*/ +template class DataType +{ +public: + typedef _Tp value_type; + typedef value_type work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 1, + depth = -1, + channels = 1, + fmt = 0, + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef bool value_type; + typedef int work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_8U, + channels = 1, + fmt = (int)'u', + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef uchar value_type; + typedef int work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_8U, + channels = 1, + fmt = (int)'u', + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef schar value_type; + typedef int work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_8S, + channels = 1, + fmt = (int)'c', + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef schar value_type; + typedef int work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_8S, + channels = 1, + fmt = (int)'c', + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef ushort value_type; + typedef int work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_16U, + channels = 1, + fmt = (int)'w', + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef short value_type; + typedef int work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_16S, + channels = 1, + fmt = (int)'s', + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef int value_type; + typedef value_type work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_32S, + channels = 1, + fmt = (int)'i', + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef float value_type; + typedef value_type work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_32F, + channels = 1, + fmt = (int)'f', + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef double value_type; + typedef value_type work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_64F, + channels = 1, + fmt = (int)'d', + type = CV_MAKETYPE(depth, channels) + }; +}; + + +/*! + A helper class for cv::DataType + + The class is specialized for each fundamental numerical data type supported by OpenCV. + It provides DataDepth::value constant. +*/ +template class DataDepth +{ +public: + enum + { + value = DataType<_Tp>::depth, + fmt = DataType<_Tp>::fmt + }; +}; + + + +template class TypeDepth +{ + enum { depth = CV_USRTYPE1 }; + typedef void value_type; +}; + +template<> class TypeDepth +{ + enum { depth = CV_8U }; + typedef uchar value_type; +}; + +template<> class TypeDepth +{ + enum { depth = CV_8S }; + typedef schar value_type; +}; + +template<> class TypeDepth +{ + enum { depth = CV_16U }; + typedef ushort value_type; +}; + +template<> class TypeDepth +{ + enum { depth = CV_16S }; + typedef short value_type; +}; + +template<> class TypeDepth +{ + enum { depth = CV_32S }; + typedef int value_type; +}; + +template<> class TypeDepth +{ + enum { depth = CV_32F }; + typedef float value_type; +}; + +template<> class TypeDepth +{ + enum { depth = CV_64F }; + typedef double value_type; +}; + +} // cv + +#endif // __OPENCV_CORE_TRAITS_HPP__ diff --git a/modules/core/include/opencv2/core/types.hpp b/modules/core/include/opencv2/core/types.hpp new file mode 100644 index 0000000000..9252cad14a --- /dev/null +++ b/modules/core/include/opencv2/core/types.hpp @@ -0,0 +1,1925 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_TYPES_HPP__ +#define __OPENCV_CORE_TYPES_HPP__ + +#ifndef __cplusplus +# error types.hpp header must be compiled as C++ +#endif + +#include +#include +#include + +#include "opencv2/core/cvdef.h" +#include "opencv2/core/cvstd.hpp" +#include "opencv2/core/matx.hpp" + +namespace cv +{ + +//////////////////////////////// Complex ////////////////////////////// + +/*! + A complex number class. + + The template class is similar and compatible with std::complex, however it provides slightly + more convenient access to the real and imaginary parts using through the simple field access, as opposite + to std::complex::real() and std::complex::imag(). +*/ +template class Complex +{ +public: + + //! constructors + Complex(); + Complex( _Tp _re, _Tp _im = 0 ); + + //! conversion to another data type + template operator Complex() const; + //! conjugation + Complex conj() const; + + _Tp re, im; //< the real and the imaginary parts +}; + +/*! + \typedef +*/ +typedef Complex Complexf; +typedef Complex Complexd; + +/*! + traits +*/ +template class DataType< Complex<_Tp> > +{ +public: + typedef Complex<_Tp> value_type; + typedef value_type work_type; + typedef _Tp channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 2, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) }; + + typedef Vec vec_type; +}; + + + +//////////////////////////////// Point_ //////////////////////////////// + +/*! + template 2D point class. + + The class defines a point in 2D space. Data type of the point coordinates is specified + as a template parameter. There are a few shorter aliases available for user convenience. + See cv::Point, cv::Point2i, cv::Point2f and cv::Point2d. +*/ +template class Point_ +{ +public: + typedef _Tp value_type; + + // various constructors + Point_(); + Point_(_Tp _x, _Tp _y); + Point_(const Point_& pt); + Point_(const Size_<_Tp>& sz); + Point_(const Vec<_Tp, 2>& v); + + Point_& operator = (const Point_& pt); + //! conversion to another data type + template operator Point_<_Tp2>() const; + + //! conversion to the old-style C structures + operator Vec<_Tp, 2>() const; + + //! dot product + _Tp dot(const Point_& pt) const; + //! dot product computed in double-precision arithmetics + double ddot(const Point_& pt) const; + //! cross-product + double cross(const Point_& pt) const; + //! checks whether the point is inside the specified rectangle + bool inside(const Rect_<_Tp>& r) const; + + _Tp x, y; //< the point coordinates +}; + +/*! + \typedef +*/ +typedef Point_ Point2i; +typedef Point_ Point2f; +typedef Point_ Point2d; +typedef Point2i Point; + +/*! + traits +*/ +template class DataType< Point_<_Tp> > +{ +public: + typedef Point_<_Tp> value_type; + typedef Point_::work_type> work_type; + typedef _Tp channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 2, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +//////////////////////////////// Point3_ //////////////////////////////// + +/*! + template 3D point class. + + The class defines a point in 3D space. Data type of the point coordinates is specified + as a template parameter. + + \see cv::Point3i, cv::Point3f and cv::Point3d +*/ +template class Point3_ +{ +public: + typedef _Tp value_type; + + // various constructors + Point3_(); + Point3_(_Tp _x, _Tp _y, _Tp _z); + Point3_(const Point3_& pt); + explicit Point3_(const Point_<_Tp>& pt); + Point3_(const Vec<_Tp, 3>& v); + + Point3_& operator = (const Point3_& pt); + //! conversion to another data type + template operator Point3_<_Tp2>() const; + //! conversion to cv::Vec<> + operator Vec<_Tp, 3>() const; + + //! dot product + _Tp dot(const Point3_& pt) const; + //! dot product computed in double-precision arithmetics + double ddot(const Point3_& pt) const; + //! cross product of the 2 3D points + Point3_ cross(const Point3_& pt) const; + + _Tp x, y, z; //< the point coordinates +}; + +/*! + \typedef +*/ +typedef Point3_ Point3i; +typedef Point3_ Point3f; +typedef Point3_ Point3d; + +/*! + traits +*/ +template class DataType< Point3_<_Tp> > +{ +public: + typedef Point3_<_Tp> value_type; + typedef Point3_::work_type> work_type; + typedef _Tp channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 3, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +//////////////////////////////// Size_ //////////////////////////////// + +/*! + The 2D size class + + The class represents the size of a 2D rectangle, image size, matrix size etc. + Normally, cv::Size ~ cv::Size_ is used. +*/ +template class Size_ +{ +public: + typedef _Tp value_type; + + //! various constructors + Size_(); + Size_(_Tp _width, _Tp _height); + Size_(const Size_& sz); + Size_(const Point_<_Tp>& pt); + + Size_& operator = (const Size_& sz); + //! the area (width*height) + _Tp area() const; + + //! conversion of another data type. + template operator Size_<_Tp2>() const; + + _Tp width, height; // the width and the height +}; + +/*! + \typedef +*/ +typedef Size_ Size2i; +typedef Size_ Size2f; +typedef Size2i Size; + +/*! + traits +*/ +template class DataType< Size_<_Tp> > +{ +public: + typedef Size_<_Tp> value_type; + typedef Size_::work_type> work_type; + typedef _Tp channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 2, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +//////////////////////////////// Rect_ //////////////////////////////// + +/*! + The 2D up-right rectangle class + + The class represents a 2D rectangle with coordinates of the specified data type. + Normally, cv::Rect ~ cv::Rect_ is used. +*/ +template class Rect_ +{ +public: + typedef _Tp value_type; + + //! various constructors + Rect_(); + Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height); + Rect_(const Rect_& r); + Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz); + Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2); + + Rect_& operator = ( const Rect_& r ); + //! the top-left corner + Point_<_Tp> tl() const; + //! the bottom-right corner + Point_<_Tp> br() const; + + //! size (width, height) of the rectangle + Size_<_Tp> size() const; + //! area (width*height) of the rectangle + _Tp area() const; + + //! conversion to another data type + template operator Rect_<_Tp2>() const; + + //! checks whether the rectangle contains the point + bool contains(const Point_<_Tp>& pt) const; + + _Tp x, y, width, height; //< the top-left corner, as well as width and height of the rectangle +}; + +/*! + \typedef +*/ +typedef Rect_ Rect; + +/*! + traits +*/ +template class DataType< Rect_<_Tp> > +{ +public: + typedef Rect_<_Tp> value_type; + typedef Rect_::work_type> work_type; + typedef _Tp channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 4, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +///////////////////////////// RotatedRect ///////////////////////////// + +/*! + The rotated 2D rectangle. + + The class represents rotated (i.e. not up-right) rectangles on a plane. + Each rectangle is described by the center point (mass center), length of each side + (represented by cv::Size2f structure) and the rotation angle in degrees. +*/ +class CV_EXPORTS RotatedRect +{ +public: + //! various constructors + RotatedRect(); + RotatedRect(const Point2f& center, const Size2f& size, float angle); + + //! returns 4 vertices of the rectangle + void points(Point2f pts[]) const; + //! returns the minimal up-right rectangle containing the rotated rectangle + Rect boundingRect() const; + + Point2f center; //< the rectangle mass center + Size2f size; //< width and height of the rectangle + float angle; //< the rotation angle. When the angle is 0, 90, 180, 270 etc., the rectangle becomes an up-right rectangle. +}; + +/*! + traits +*/ +template<> class DataType< RotatedRect > +{ +public: + typedef RotatedRect value_type; + typedef value_type work_type; + typedef float channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = (int)sizeof(value_type)/sizeof(channel_type), // 5 + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +//////////////////////////////// Range ///////////////////////////////// + +/*! + The 2D range class + + This is the class used to specify a continuous subsequence, i.e. part of a contour, or a column span in a matrix. +*/ +class CV_EXPORTS Range +{ +public: + Range(); + Range(int _start, int _end); + int size() const; + bool empty() const; + static Range all(); + + int start, end; +}; + +/*! + traits +*/ +template<> class DataType +{ +public: + typedef Range value_type; + typedef value_type work_type; + typedef int channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 2, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +//////////////////////////////// Scalar_ /////////////////////////////// + +/*! + The template scalar class. + + This is partially specialized cv::Vec class with the number of elements = 4, i.e. a short vector of four elements. + Normally, cv::Scalar ~ cv::Scalar_ is used. +*/ +template class Scalar_ : public Vec<_Tp, 4> +{ +public: + //! various constructors + Scalar_(); + Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0); + Scalar_(_Tp v0); + + template + Scalar_(const Vec<_Tp2, cn>& v); + + //! returns a scalar with all elements set to v0 + static Scalar_<_Tp> all(_Tp v0); + + //! conversion to another data type + template operator Scalar_() const; + + //! per-element product + Scalar_<_Tp> mul(const Scalar_<_Tp>& t, double scale=1 ) const; + + // returns (v0, -v1, -v2, -v3) + Scalar_<_Tp> conj() const; + + // returns true iff v1 == v2 == v3 == 0 + bool isReal() const; +}; + +/*! + \typedef +*/ +typedef Scalar_ Scalar; + +/*! + traits +*/ +template class DataType< Scalar_<_Tp> > +{ +public: + typedef Scalar_<_Tp> value_type; + typedef Scalar_::work_type> work_type; + typedef _Tp channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 4, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +/////////////////////////////// KeyPoint //////////////////////////////// + +/*! + The Keypoint Class + + The class instance stores a keypoint, i.e. a point feature found by one of many available keypoint detectors, such as + Harris corner detector, cv::FAST, cv::StarDetector, cv::SURF, cv::SIFT, cv::LDetector etc. + + The keypoint is characterized by the 2D position, scale + (proportional to the diameter of the neighborhood that needs to be taken into account), + orientation and some other parameters. The keypoint neighborhood is then analyzed by another algorithm that builds a descriptor + (usually represented as a feature vector). The keypoints representing the same object in different images can then be matched using + cv::KDTree or another method. +*/ +class CV_EXPORTS_W_SIMPLE KeyPoint +{ +public: + //! the default constructor + CV_WRAP KeyPoint(); + //! the full constructor + KeyPoint(Point2f _pt, float _size, float _angle=-1, float _response=0, int _octave=0, int _class_id=-1); + //! another form of the full constructor + CV_WRAP KeyPoint(float x, float y, float _size, float _angle=-1, float _response=0, int _octave=0, int _class_id=-1); + + size_t hash() const; + + //! converts vector of keypoints to vector of points + CV_WRAP static void convert(const std::vector& keypoints, + CV_OUT std::vector& points2f, + const std::vector& keypointIndexes=std::vector()); + //! converts vector of points to the vector of keypoints, where each keypoint is assigned the same size and the same orientation + CV_WRAP static void convert(const std::vector& points2f, + CV_OUT std::vector& keypoints, + float size=1, float response=1, int octave=0, int class_id=-1); + + //! computes overlap for pair of keypoints; + //! overlap is a ratio between area of keypoint regions intersection and + //! area of keypoint regions union (now keypoint region is circle) + CV_WRAP static float overlap(const KeyPoint& kp1, const KeyPoint& kp2); + + CV_PROP_RW Point2f pt; //!< coordinates of the keypoints + CV_PROP_RW float size; //!< diameter of the meaningful keypoint neighborhood + CV_PROP_RW float angle; //!< computed orientation of the keypoint (-1 if not applicable); + //!< it's in [0,360) degrees and measured relative to + //!< image coordinate system, ie in clockwise. + CV_PROP_RW float response; //!< the response by which the most strong keypoints have been selected. Can be used for the further sorting or subsampling + CV_PROP_RW int octave; //!< octave (pyramid layer) from which the keypoint has been extracted + CV_PROP_RW int class_id; //!< object class (if the keypoints need to be clustered by an object they belong to) +}; + +/*! + traits +*/ +template<> class DataType +{ +public: + typedef KeyPoint value_type; + typedef float work_type; + typedef float channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = (int)(sizeof(value_type)/sizeof(channel_type)), // 7 + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +//////////////////////////////// DMatch ///////////////////////////////// + +/* + * Struct for matching: query descriptor index, train descriptor index, train image index and distance between descriptors. + */ +class CV_EXPORTS_W_SIMPLE DMatch +{ +public: + CV_WRAP DMatch(); + CV_WRAP DMatch(int _queryIdx, int _trainIdx, float _distance); + CV_WRAP DMatch(int _queryIdx, int _trainIdx, int _imgIdx, float _distance); + + CV_PROP_RW int queryIdx; // query descriptor index + CV_PROP_RW int trainIdx; // train descriptor index + CV_PROP_RW int imgIdx; // train image index + + CV_PROP_RW float distance; + + // less is better + bool operator<(const DMatch &m) const; +}; + +/*! + traits +*/ +template<> class DataType +{ +public: + typedef DMatch value_type; + typedef int work_type; + typedef int channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = (int)(sizeof(value_type)/sizeof(channel_type)), // 4 + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +///////////////////////////// TermCriteria ////////////////////////////// + +/*! + Termination criteria in iterative algorithms + */ +class CV_EXPORTS TermCriteria +{ +public: + enum + { + COUNT=1, //!< the maximum number of iterations or elements to compute + MAX_ITER=COUNT, //!< ditto + EPS=2 //!< the desired accuracy or change in parameters at which the iterative algorithm stops + }; + + //! default constructor + TermCriteria(); + //! full constructor + TermCriteria(int type, int maxCount, double epsilon); + + int type; //!< the type of termination criteria: COUNT, EPS or COUNT + EPS + int maxCount; // the maximum number of iterations/elements + double epsilon; // the desired accuracy +}; + + + +///////////////////////// raster image moments ////////////////////////// + +class CV_EXPORTS_W_MAP Moments +{ +public: + //! the default constructor + Moments(); + //! the full constructor + Moments(double m00, double m10, double m01, double m20, double m11, + double m02, double m30, double m21, double m12, double m03 ); + ////! the conversion from CvMoments + //Moments( const CvMoments& moments ); + ////! the conversion to CvMoments + //operator CvMoments() const; + + //! spatial moments + CV_PROP_RW double m00, m10, m01, m20, m11, m02, m30, m21, m12, m03; + //! central moments + CV_PROP_RW double mu20, mu11, mu02, mu30, mu21, mu12, mu03; + //! central normalized moments + CV_PROP_RW double nu20, nu11, nu02, nu30, nu21, nu12, nu03; +}; + +/*! + traits +*/ +template<> class DataType +{ +public: + typedef Moments value_type; + typedef double work_type; + typedef double channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = (int)(sizeof(value_type)/sizeof(channel_type)), // 24 + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +///////////////////////////////////////////////////////////////////////// +///////////////////////////// Implementation //////////////////////////// +///////////////////////////////////////////////////////////////////////// + +//////////////////////////////// Complex //////////////////////////////// + +template inline +Complex<_Tp>::Complex() + : re(0), im(0) {} + +template inline +Complex<_Tp>::Complex( _Tp _re, _Tp _im ) + : re(_re), im(_im) {} + +template template inline +Complex<_Tp>::operator Complex() const +{ + return Complex(saturate_cast(re), saturate_cast(im)); +} + +template inline +Complex<_Tp> Complex<_Tp>::conj() const +{ + return Complex<_Tp>(re, -im); +} + + +template static inline +bool operator == (const Complex<_Tp>& a, const Complex<_Tp>& b) +{ + return a.re == b.re && a.im == b.im; +} + +template static inline +bool operator != (const Complex<_Tp>& a, const Complex<_Tp>& b) +{ + return a.re != b.re || a.im != b.im; +} + +template static inline +Complex<_Tp> operator + (const Complex<_Tp>& a, const Complex<_Tp>& b) +{ + return Complex<_Tp>( a.re + b.re, a.im + b.im ); +} + +template static inline +Complex<_Tp>& operator += (Complex<_Tp>& a, const Complex<_Tp>& b) +{ + a.re += b.re; a.im += b.im; + return a; +} + +template static inline +Complex<_Tp> operator - (const Complex<_Tp>& a, const Complex<_Tp>& b) +{ + return Complex<_Tp>( a.re - b.re, a.im - b.im ); +} + +template static inline +Complex<_Tp>& operator -= (Complex<_Tp>& a, const Complex<_Tp>& b) +{ + a.re -= b.re; a.im -= b.im; + return a; +} + +template static inline +Complex<_Tp> operator - (const Complex<_Tp>& a) +{ + return Complex<_Tp>(-a.re, -a.im); +} + +template static inline +Complex<_Tp> operator * (const Complex<_Tp>& a, const Complex<_Tp>& b) +{ + return Complex<_Tp>( a.re*b.re - a.im*b.im, a.re*b.im + a.im*b.re ); +} + +template static inline +Complex<_Tp> operator * (const Complex<_Tp>& a, _Tp b) +{ + return Complex<_Tp>( a.re*b, a.im*b ); +} + +template static inline +Complex<_Tp> operator * (_Tp b, const Complex<_Tp>& a) +{ + return Complex<_Tp>( a.re*b, a.im*b ); +} + +template static inline +Complex<_Tp> operator + (const Complex<_Tp>& a, _Tp b) +{ + return Complex<_Tp>( a.re + b, a.im ); +} + +template static inline +Complex<_Tp> operator - (const Complex<_Tp>& a, _Tp b) +{ return Complex<_Tp>( a.re - b, a.im ); } + +template static inline +Complex<_Tp> operator + (_Tp b, const Complex<_Tp>& a) +{ + return Complex<_Tp>( a.re + b, a.im ); +} + +template static inline +Complex<_Tp> operator - (_Tp b, const Complex<_Tp>& a) +{ + return Complex<_Tp>( b - a.re, -a.im ); +} + +template static inline +Complex<_Tp>& operator += (Complex<_Tp>& a, _Tp b) +{ + a.re += b; return a; +} + +template static inline +Complex<_Tp>& operator -= (Complex<_Tp>& a, _Tp b) +{ + a.re -= b; return a; +} + +template static inline +Complex<_Tp>& operator *= (Complex<_Tp>& a, _Tp b) +{ + a.re *= b; a.im *= b; return a; +} + +template static inline +double abs(const Complex<_Tp>& a) +{ + return std::sqrt( (double)a.re*a.re + (double)a.im*a.im); +} + +template static inline +Complex<_Tp> operator / (const Complex<_Tp>& a, const Complex<_Tp>& b) +{ + double t = 1./((double)b.re*b.re + (double)b.im*b.im); + return Complex<_Tp>( (_Tp)((a.re*b.re + a.im*b.im)*t), + (_Tp)((-a.re*b.im + a.im*b.re)*t) ); +} + +template static inline +Complex<_Tp>& operator /= (Complex<_Tp>& a, const Complex<_Tp>& b) +{ + return (a = a / b); +} + +template static inline +Complex<_Tp> operator / (const Complex<_Tp>& a, _Tp b) +{ + _Tp t = (_Tp)1/b; + return Complex<_Tp>( a.re*t, a.im*t ); +} + +template static inline +Complex<_Tp> operator / (_Tp b, const Complex<_Tp>& a) +{ + return Complex<_Tp>(b)/a; +} + +template static inline +Complex<_Tp> operator /= (const Complex<_Tp>& a, _Tp b) +{ + _Tp t = (_Tp)1/b; + a.re *= t; a.im *= t; return a; +} + + + +//////////////////////////////// 2D Point /////////////////////////////// + +template inline +Point_<_Tp>::Point_() + : x(0), y(0) {} + +template inline +Point_<_Tp>::Point_(_Tp _x, _Tp _y) + : x(_x), y(_y) {} + +template inline +Point_<_Tp>::Point_(const Point_& pt) + : x(pt.x), y(pt.y) {} + +template inline +Point_<_Tp>::Point_(const Size_<_Tp>& sz) + : x(sz.width), y(sz.height) {} + +template inline +Point_<_Tp>::Point_(const Vec<_Tp,2>& v) + : x(v[0]), y(v[1]) {} + +template inline +Point_<_Tp>& Point_<_Tp>::operator = (const Point_& pt) +{ + x = pt.x; y = pt.y; + return *this; +} + +template template inline +Point_<_Tp>::operator Point_<_Tp2>() const +{ + return Point_<_Tp2>(saturate_cast<_Tp2>(x), saturate_cast<_Tp2>(y)); +} + +template inline +Point_<_Tp>::operator Vec<_Tp, 2>() const +{ + return Vec<_Tp, 2>(x, y); +} + +template inline +_Tp Point_<_Tp>::dot(const Point_& pt) const +{ + return saturate_cast<_Tp>(x*pt.x + y*pt.y); +} + +template inline +double Point_<_Tp>::ddot(const Point_& pt) const +{ + return (double)x*pt.x + (double)y*pt.y; +} + +template inline +double Point_<_Tp>::cross(const Point_& pt) const +{ + return (double)x*pt.y - (double)y*pt.x; +} + +template inline bool +Point_<_Tp>::inside( const Rect_<_Tp>& r ) const +{ + return r.contains(*this); +} + + +template static inline +Point_<_Tp>& operator += (Point_<_Tp>& a, const Point_<_Tp>& b) +{ + a.x += b.x; + a.y += b.y; + return a; +} + +template static inline +Point_<_Tp>& operator -= (Point_<_Tp>& a, const Point_<_Tp>& b) +{ + a.x -= b.x; + a.y -= b.y; + return a; +} + +template static inline +Point_<_Tp>& operator *= (Point_<_Tp>& a, int b) +{ + a.x = saturate_cast<_Tp>(a.x * b); + a.y = saturate_cast<_Tp>(a.y * b); + return a; +} + +template static inline +Point_<_Tp>& operator *= (Point_<_Tp>& a, float b) +{ + a.x = saturate_cast<_Tp>(a.x * b); + a.y = saturate_cast<_Tp>(a.y * b); + return a; +} + +template static inline +Point_<_Tp>& operator *= (Point_<_Tp>& a, double b) +{ + a.x = saturate_cast<_Tp>(a.x * b); + a.y = saturate_cast<_Tp>(a.y * b); + return a; +} + +template static inline +double norm(const Point_<_Tp>& pt) +{ + return std::sqrt((double)pt.x*pt.x + (double)pt.y*pt.y); +} + +template static inline +bool operator == (const Point_<_Tp>& a, const Point_<_Tp>& b) +{ + return a.x == b.x && a.y == b.y; +} + +template static inline +bool operator != (const Point_<_Tp>& a, const Point_<_Tp>& b) +{ + return a.x != b.x || a.y != b.y; +} + +template static inline +Point_<_Tp> operator + (const Point_<_Tp>& a, const Point_<_Tp>& b) +{ + return Point_<_Tp>( saturate_cast<_Tp>(a.x + b.x), saturate_cast<_Tp>(a.y + b.y) ); +} + +template static inline +Point_<_Tp> operator - (const Point_<_Tp>& a, const Point_<_Tp>& b) +{ + return Point_<_Tp>( saturate_cast<_Tp>(a.x - b.x), saturate_cast<_Tp>(a.y - b.y) ); +} + +template static inline +Point_<_Tp> operator - (const Point_<_Tp>& a) +{ + return Point_<_Tp>( saturate_cast<_Tp>(-a.x), saturate_cast<_Tp>(-a.y) ); +} + +template static inline +Point_<_Tp> operator * (const Point_<_Tp>& a, int b) +{ + return Point_<_Tp>( saturate_cast<_Tp>(a.x*b), saturate_cast<_Tp>(a.y*b) ); +} + +template static inline +Point_<_Tp> operator * (int a, const Point_<_Tp>& b) +{ + return Point_<_Tp>( saturate_cast<_Tp>(b.x*a), saturate_cast<_Tp>(b.y*a) ); +} + +template static inline +Point_<_Tp> operator * (const Point_<_Tp>& a, float b) +{ + return Point_<_Tp>( saturate_cast<_Tp>(a.x*b), saturate_cast<_Tp>(a.y*b) ); +} + +template static inline +Point_<_Tp> operator * (float a, const Point_<_Tp>& b) +{ + return Point_<_Tp>( saturate_cast<_Tp>(b.x*a), saturate_cast<_Tp>(b.y*a) ); +} + +template static inline +Point_<_Tp> operator * (const Point_<_Tp>& a, double b) +{ + return Point_<_Tp>( saturate_cast<_Tp>(a.x*b), saturate_cast<_Tp>(a.y*b) ); +} + +template static inline +Point_<_Tp> operator * (double a, const Point_<_Tp>& b) +{ + return Point_<_Tp>( saturate_cast<_Tp>(b.x*a), saturate_cast<_Tp>(b.y*a) ); +} + +template static inline +Point_<_Tp> operator * (const Matx<_Tp, 2, 2>& a, const Point_<_Tp>& b) +{ + Matx<_Tp, 2, 1> tmp = a * Vec<_Tp,2>(b.x, b.y); + return Point_<_Tp>(tmp.val[0], tmp.val[1]); +} + +template static inline +Point3_<_Tp> operator * (const Matx<_Tp, 3, 3>& a, const Point_<_Tp>& b) +{ + Matx<_Tp, 3, 1> tmp = a * Vec<_Tp,3>(b.x, b.y, 1); + return Point3_<_Tp>(tmp.val[0], tmp.val[1], tmp.val[2]); +} + + + +//////////////////////////////// 3D Point /////////////////////////////// + +template inline +Point3_<_Tp>::Point3_() + : x(0), y(0), z(0) {} + +template inline +Point3_<_Tp>::Point3_(_Tp _x, _Tp _y, _Tp _z) + : x(_x), y(_y), z(_z) {} + +template inline +Point3_<_Tp>::Point3_(const Point3_& pt) + : x(pt.x), y(pt.y), z(pt.z) {} + +template inline +Point3_<_Tp>::Point3_(const Point_<_Tp>& pt) + : x(pt.x), y(pt.y), z(_Tp()) {} + +template inline +Point3_<_Tp>::Point3_(const Vec<_Tp, 3>& v) + : x(v[0]), y(v[1]), z(v[2]) {} + +template template inline +Point3_<_Tp>::operator Point3_<_Tp2>() const +{ + return Point3_<_Tp2>(saturate_cast<_Tp2>(x), saturate_cast<_Tp2>(y), saturate_cast<_Tp2>(z)); +} + +template inline +Point3_<_Tp>::operator Vec<_Tp, 3>() const +{ + return Vec<_Tp, 3>(x, y, z); +} + +template inline +Point3_<_Tp>& Point3_<_Tp>::operator = (const Point3_& pt) +{ + x = pt.x; y = pt.y; z = pt.z; + return *this; +} + +template inline +_Tp Point3_<_Tp>::dot(const Point3_& pt) const +{ + return saturate_cast<_Tp>(x*pt.x + y*pt.y + z*pt.z); +} + +template inline +double Point3_<_Tp>::ddot(const Point3_& pt) const +{ + return (double)x*pt.x + (double)y*pt.y + (double)z*pt.z; +} + +template inline +Point3_<_Tp> Point3_<_Tp>::cross(const Point3_<_Tp>& pt) const +{ + return Point3_<_Tp>(y*pt.z - z*pt.y, z*pt.x - x*pt.z, x*pt.y - y*pt.x); +} + + +template static inline +Point3_<_Tp>& operator += (Point3_<_Tp>& a, const Point3_<_Tp>& b) +{ + a.x += b.x; + a.y += b.y; + a.z += b.z; + return a; +} + +template static inline +Point3_<_Tp>& operator -= (Point3_<_Tp>& a, const Point3_<_Tp>& b) +{ + a.x -= b.x; + a.y -= b.y; + a.z -= b.z; + return a; +} + +template static inline +Point3_<_Tp>& operator *= (Point3_<_Tp>& a, int b) +{ + a.x = saturate_cast<_Tp>(a.x * b); + a.y = saturate_cast<_Tp>(a.y * b); + a.z = saturate_cast<_Tp>(a.z * b); + return a; +} + +template static inline +Point3_<_Tp>& operator *= (Point3_<_Tp>& a, float b) +{ + a.x = saturate_cast<_Tp>(a.x * b); + a.y = saturate_cast<_Tp>(a.y * b); + a.z = saturate_cast<_Tp>(a.z * b); + return a; +} + +template static inline +Point3_<_Tp>& operator *= (Point3_<_Tp>& a, double b) +{ + a.x = saturate_cast<_Tp>(a.x * b); + a.y = saturate_cast<_Tp>(a.y * b); + a.z = saturate_cast<_Tp>(a.z * b); + return a; +} + +template static inline +double norm(const Point3_<_Tp>& pt) +{ + return std::sqrt((double)pt.x*pt.x + (double)pt.y*pt.y + (double)pt.z*pt.z); +} + +template static inline +bool operator == (const Point3_<_Tp>& a, const Point3_<_Tp>& b) +{ + return a.x == b.x && a.y == b.y && a.z == b.z; +} + +template static inline +bool operator != (const Point3_<_Tp>& a, const Point3_<_Tp>& b) +{ + return a.x != b.x || a.y != b.y || a.z != b.z; +} + +template static inline +Point3_<_Tp> operator + (const Point3_<_Tp>& a, const Point3_<_Tp>& b) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(a.x + b.x), saturate_cast<_Tp>(a.y + b.y), saturate_cast<_Tp>(a.z + b.z)); +} + +template static inline +Point3_<_Tp> operator - (const Point3_<_Tp>& a, const Point3_<_Tp>& b) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(a.x - b.x), saturate_cast<_Tp>(a.y - b.y), saturate_cast<_Tp>(a.z - b.z)); +} + +template static inline +Point3_<_Tp> operator - (const Point3_<_Tp>& a) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(-a.x), saturate_cast<_Tp>(-a.y), saturate_cast<_Tp>(-a.z) ); +} + +template static inline +Point3_<_Tp> operator * (const Point3_<_Tp>& a, int b) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(a.x*b), saturate_cast<_Tp>(a.y*b), saturate_cast<_Tp>(a.z*b) ); +} + +template static inline +Point3_<_Tp> operator * (int a, const Point3_<_Tp>& b) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(b.x * a), saturate_cast<_Tp>(b.y * a), saturate_cast<_Tp>(b.z * a) ); +} + +template static inline +Point3_<_Tp> operator * (const Point3_<_Tp>& a, float b) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(a.x * b), saturate_cast<_Tp>(a.y * b), saturate_cast<_Tp>(a.z * b) ); +} + +template static inline +Point3_<_Tp> operator * (float a, const Point3_<_Tp>& b) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(b.x * a), saturate_cast<_Tp>(b.y * a), saturate_cast<_Tp>(b.z * a) ); +} + +template static inline +Point3_<_Tp> operator * (const Point3_<_Tp>& a, double b) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(a.x * b), saturate_cast<_Tp>(a.y * b), saturate_cast<_Tp>(a.z * b) ); +} + +template static inline +Point3_<_Tp> operator * (double a, const Point3_<_Tp>& b) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(b.x * a), saturate_cast<_Tp>(b.y * a), saturate_cast<_Tp>(b.z * a) ); +} + +template static inline +Point3_<_Tp> operator * (const Matx<_Tp, 3, 3>& a, const Point3_<_Tp>& b) +{ + Matx<_Tp, 3, 1> tmp = a * Vec<_Tp,3>(b.x, b.y, b.z); + return Point3_<_Tp>(tmp.val[0], tmp.val[1], tmp.val[2]); +} + +template static inline +Matx<_Tp, 4, 1> operator * (const Matx<_Tp, 4, 4>& a, const Point3_<_Tp>& b) +{ + return a * Matx<_Tp, 4, 1>(b.x, b.y, b.z, 1); +} + + + +////////////////////////////////// Size ///////////////////////////////// + +template inline +Size_<_Tp>::Size_() + : width(0), height(0) {} + +template inline +Size_<_Tp>::Size_(_Tp _width, _Tp _height) + : width(_width), height(_height) {} + +template inline +Size_<_Tp>::Size_(const Size_& sz) + : width(sz.width), height(sz.height) {} + +template inline +Size_<_Tp>::Size_(const Point_<_Tp>& pt) + : width(pt.x), height(pt.y) {} + +template template inline +Size_<_Tp>::operator Size_<_Tp2>() const +{ + return Size_<_Tp2>(saturate_cast<_Tp2>(width), saturate_cast<_Tp2>(height)); +} + +template inline +Size_<_Tp>& Size_<_Tp>::operator = (const Size_<_Tp>& sz) +{ + width = sz.width; height = sz.height; + return *this; +} + +template inline +_Tp Size_<_Tp>::area() const +{ + return width * height; +} + + +template static inline +Size_<_Tp> operator * (const Size_<_Tp>& a, _Tp b) +{ + return Size_<_Tp>(a.width * b, a.height * b); +} + +template static inline +Size_<_Tp> operator + (const Size_<_Tp>& a, const Size_<_Tp>& b) +{ + return Size_<_Tp>(a.width + b.width, a.height + b.height); +} + +template static inline +Size_<_Tp> operator - (const Size_<_Tp>& a, const Size_<_Tp>& b) +{ + return Size_<_Tp>(a.width - b.width, a.height - b.height); +} + +template static inline +Size_<_Tp>& operator += (Size_<_Tp>& a, const Size_<_Tp>& b) +{ + a.width += b.width; + a.height += b.height; + return a; +} + +template static inline +Size_<_Tp>& operator -= (Size_<_Tp>& a, const Size_<_Tp>& b) +{ + a.width -= b.width; + a.height -= b.height; + return a; +} + +template static inline +bool operator == (const Size_<_Tp>& a, const Size_<_Tp>& b) +{ + return a.width == b.width && a.height == b.height; +} + +template static inline +bool operator != (const Size_<_Tp>& a, const Size_<_Tp>& b) +{ + return a.width != b.width || a.height != b.height; +} + + + +////////////////////////////////// Rect ///////////////////////////////// + +template inline +Rect_<_Tp>::Rect_() + : x(0), y(0), width(0), height(0) {} + +template inline +Rect_<_Tp>::Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height) + : x(_x), y(_y), width(_width), height(_height) {} + +template inline +Rect_<_Tp>::Rect_(const Rect_<_Tp>& r) + : x(r.x), y(r.y), width(r.width), height(r.height) {} + +template inline +Rect_<_Tp>::Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz) + : x(org.x), y(org.y), width(sz.width), height(sz.height) {} + +template inline +Rect_<_Tp>::Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2) +{ + x = std::min(pt1.x, pt2.x); + y = std::min(pt1.y, pt2.y); + width = std::max(pt1.x, pt2.x) - x; + height = std::max(pt1.y, pt2.y) - y; +} + +template inline +Rect_<_Tp>& Rect_<_Tp>::operator = ( const Rect_<_Tp>& r ) +{ + x = r.x; + y = r.y; + width = r.width; + height = r.height; + return *this; +} + +template inline +Point_<_Tp> Rect_<_Tp>::tl() const +{ + return Point_<_Tp>(x,y); +} + +template inline +Point_<_Tp> Rect_<_Tp>::br() const +{ + return Point_<_Tp>(x + width, y + height); +} + +template inline +Size_<_Tp> Rect_<_Tp>::size() const +{ + return Size_<_Tp>(width, height); +} + +template inline +_Tp Rect_<_Tp>::area() const +{ + return width * height; +} + +template template inline +Rect_<_Tp>::operator Rect_<_Tp2>() const +{ + return Rect_<_Tp2>(saturate_cast<_Tp2>(x), saturate_cast<_Tp2>(y), saturate_cast<_Tp2>(width), saturate_cast<_Tp2>(height)); +} + +template inline +bool Rect_<_Tp>::contains(const Point_<_Tp>& pt) const +{ + return x <= pt.x && pt.x < x + width && y <= pt.y && pt.y < y + height; +} + + +template static inline +Rect_<_Tp>& operator += ( Rect_<_Tp>& a, const Point_<_Tp>& b ) +{ + a.x += b.x; + a.y += b.y; + return a; +} + +template static inline +Rect_<_Tp>& operator -= ( Rect_<_Tp>& a, const Point_<_Tp>& b ) +{ + a.x -= b.x; + a.y -= b.y; + return a; +} + +template static inline +Rect_<_Tp>& operator += ( Rect_<_Tp>& a, const Size_<_Tp>& b ) +{ + a.width += b.width; + a.height += b.height; + return a; +} + +template static inline +Rect_<_Tp>& operator -= ( Rect_<_Tp>& a, const Size_<_Tp>& b ) +{ + a.width -= b.width; + a.height -= b.height; + return a; +} + +template static inline +Rect_<_Tp>& operator &= ( Rect_<_Tp>& a, const Rect_<_Tp>& b ) +{ + _Tp x1 = std::max(a.x, b.x); + _Tp y1 = std::max(a.y, b.y); + a.width = std::min(a.x + a.width, b.x + b.width) - x1; + a.height = std::min(a.y + a.height, b.y + b.height) - y1; + a.x = x1; + a.y = y1; + if( a.width <= 0 || a.height <= 0 ) + a = Rect(); + return a; +} + +template static inline +Rect_<_Tp>& operator |= ( Rect_<_Tp>& a, const Rect_<_Tp>& b ) +{ + _Tp x1 = std::min(a.x, b.x); + _Tp y1 = std::min(a.y, b.y); + a.width = std::max(a.x + a.width, b.x + b.width) - x1; + a.height = std::max(a.y + a.height, b.y + b.height) - y1; + a.x = x1; + a.y = y1; + return a; +} + +template static inline +bool operator == (const Rect_<_Tp>& a, const Rect_<_Tp>& b) +{ + return a.x == b.x && a.y == b.y && a.width == b.width && a.height == b.height; +} + +template static inline +bool operator != (const Rect_<_Tp>& a, const Rect_<_Tp>& b) +{ + return a.x != b.x || a.y != b.y || a.width != b.width || a.height != b.height; +} + +template static inline +Rect_<_Tp> operator + (const Rect_<_Tp>& a, const Point_<_Tp>& b) +{ + return Rect_<_Tp>( a.x + b.x, a.y + b.y, a.width, a.height ); +} + +template static inline +Rect_<_Tp> operator - (const Rect_<_Tp>& a, const Point_<_Tp>& b) +{ + return Rect_<_Tp>( a.x - b.x, a.y - b.y, a.width, a.height ); +} + +template static inline +Rect_<_Tp> operator + (const Rect_<_Tp>& a, const Size_<_Tp>& b) +{ + return Rect_<_Tp>( a.x, a.y, a.width + b.width, a.height + b.height ); +} + +template static inline +Rect_<_Tp> operator & (const Rect_<_Tp>& a, const Rect_<_Tp>& b) +{ + Rect_<_Tp> c = a; + return c &= b; +} + +template static inline +Rect_<_Tp> operator | (const Rect_<_Tp>& a, const Rect_<_Tp>& b) +{ + Rect_<_Tp> c = a; + return c |= b; +} + + + +////////////////////////////// RotatedRect ////////////////////////////// + +inline +RotatedRect::RotatedRect() + : center(), size(), angle(0) {} + +inline +RotatedRect::RotatedRect(const Point2f& _center, const Size2f& _size, float _angle) + : center(_center), size(_size), angle(_angle) {} + + + +///////////////////////////////// Range ///////////////////////////////// + +inline +Range::Range() + : start(0), end(0) {} + +inline +Range::Range(int _start, int _end) + : start(_start), end(_end) {} + +inline +int Range::size() const +{ + return end - start; +} + +inline +bool Range::empty() const +{ + return start == end; +} + +inline +Range Range::all() +{ + return Range(INT_MIN, INT_MAX); +} + + +static inline +bool operator == (const Range& r1, const Range& r2) +{ + return r1.start == r2.start && r1.end == r2.end; +} + +static inline +bool operator != (const Range& r1, const Range& r2) +{ + return !(r1 == r2); +} + +static inline +bool operator !(const Range& r) +{ + return r.start == r.end; +} + +static inline +Range operator & (const Range& r1, const Range& r2) +{ + Range r(std::max(r1.start, r2.start), std::min(r1.end, r2.end)); + r.end = std::max(r.end, r.start); + return r; +} + +static inline +Range& operator &= (Range& r1, const Range& r2) +{ + r1 = r1 & r2; + return r1; +} + +static inline +Range operator + (const Range& r1, int delta) +{ + return Range(r1.start + delta, r1.end + delta); +} + +static inline +Range operator + (int delta, const Range& r1) +{ + return Range(r1.start + delta, r1.end + delta); +} + +static inline +Range operator - (const Range& r1, int delta) +{ + return r1 + (-delta); +} + + + +///////////////////////////////// Scalar //////////////////////////////// + +template inline +Scalar_<_Tp>::Scalar_() +{ + this->val[0] = this->val[1] = this->val[2] = this->val[3] = 0; +} + +template inline +Scalar_<_Tp>::Scalar_(_Tp v0, _Tp v1, _Tp v2, _Tp v3) +{ + this->val[0] = v0; + this->val[1] = v1; + this->val[2] = v2; + this->val[3] = v3; +} + +template template inline +Scalar_<_Tp>::Scalar_(const Vec<_Tp2, cn>& v) +{ + int i; + for( i = 0; i < (cn < 4 ? cn : 4); i++ ) + this->val[i] = cv::saturate_cast<_Tp>(v.val[i]); + for( ; i < 4; i++ ) + this->val[i] = 0; +} + +template inline +Scalar_<_Tp>::Scalar_(_Tp v0) +{ + this->val[0] = v0; + this->val[1] = this->val[2] = this->val[3] = 0; +} + +template inline +Scalar_<_Tp> Scalar_<_Tp>::all(_Tp v0) +{ + return Scalar_<_Tp>(v0, v0, v0, v0); +} + + +template inline +Scalar_<_Tp> Scalar_<_Tp>::mul(const Scalar_<_Tp>& t, double scale ) const +{ + return Scalar_<_Tp>(saturate_cast<_Tp>(this->val[0] * t.val[0] * scale), + saturate_cast<_Tp>(this->val[1] * t.val[1] * scale), + saturate_cast<_Tp>(this->val[2] * t.val[2] * scale), + saturate_cast<_Tp>(this->val[3] * t.val[3] * scale)); +} + +template inline +Scalar_<_Tp> Scalar_<_Tp>::conj() const +{ + return Scalar_<_Tp>(saturate_cast<_Tp>( this->val[0]), + saturate_cast<_Tp>(-this->val[1]), + saturate_cast<_Tp>(-this->val[2]), + saturate_cast<_Tp>(-this->val[3])); +} + +template inline +bool Scalar_<_Tp>::isReal() const +{ + return this->val[1] == 0 && this->val[2] == 0 && this->val[3] == 0; +} + + +template template inline +Scalar_<_Tp>::operator Scalar_() const +{ + return Scalar_(saturate_cast(this->val[0]), + saturate_cast(this->val[1]), + saturate_cast(this->val[2]), + saturate_cast(this->val[3])); +} + + +template static inline +Scalar_<_Tp>& operator += (Scalar_<_Tp>& a, const Scalar_<_Tp>& b) +{ + a.val[0] += b.val[0]; + a.val[1] += b.val[1]; + a.val[2] += b.val[2]; + a.val[3] += b.val[3]; + return a; +} + +template static inline +Scalar_<_Tp>& operator -= (Scalar_<_Tp>& a, const Scalar_<_Tp>& b) +{ + a.val[0] -= b.val[0]; + a.val[1] -= b.val[1]; + a.val[2] -= b.val[2]; + a.val[3] -= b.val[3]; + return a; +} + +template static inline +Scalar_<_Tp>& operator *= ( Scalar_<_Tp>& a, _Tp v ) +{ + a.val[0] *= v; + a.val[1] *= v; + a.val[2] *= v; + a.val[3] *= v; + return a; +} + +template static inline +bool operator == ( const Scalar_<_Tp>& a, const Scalar_<_Tp>& b ) +{ + return a.val[0] == b.val[0] && a.val[1] == b.val[1] && + a.val[2] == b.val[2] && a.val[3] == b.val[3]; +} + +template static inline +bool operator != ( const Scalar_<_Tp>& a, const Scalar_<_Tp>& b ) +{ + return a.val[0] != b.val[0] || a.val[1] != b.val[1] || + a.val[2] != b.val[2] || a.val[3] != b.val[3]; +} + +template static inline +Scalar_<_Tp> operator + (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b) +{ + return Scalar_<_Tp>(a.val[0] + b.val[0], + a.val[1] + b.val[1], + a.val[2] + b.val[2], + a.val[3] + b.val[3]); +} + +template static inline +Scalar_<_Tp> operator - (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b) +{ + return Scalar_<_Tp>(saturate_cast<_Tp>(a.val[0] - b.val[0]), + saturate_cast<_Tp>(a.val[1] - b.val[1]), + saturate_cast<_Tp>(a.val[2] - b.val[2]), + saturate_cast<_Tp>(a.val[3] - b.val[3])); +} + +template static inline +Scalar_<_Tp> operator * (const Scalar_<_Tp>& a, _Tp alpha) +{ + return Scalar_<_Tp>(a.val[0] * alpha, + a.val[1] * alpha, + a.val[2] * alpha, + a.val[3] * alpha); +} + +template static inline +Scalar_<_Tp> operator * (_Tp alpha, const Scalar_<_Tp>& a) +{ + return a*alpha; +} + +template static inline +Scalar_<_Tp> operator - (const Scalar_<_Tp>& a) +{ + return Scalar_<_Tp>(saturate_cast<_Tp>(-a.val[0]), + saturate_cast<_Tp>(-a.val[1]), + saturate_cast<_Tp>(-a.val[2]), + saturate_cast<_Tp>(-a.val[3])); +} + + +template static inline +Scalar_<_Tp> operator * (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b) +{ + return Scalar_<_Tp>(saturate_cast<_Tp>(a[0]*b[0] - a[1]*b[1] - a[2]*b[2] - a[3]*b[3]), + saturate_cast<_Tp>(a[0]*b[1] + a[1]*b[0] + a[2]*b[3] - a[3]*b[2]), + saturate_cast<_Tp>(a[0]*b[2] - a[1]*b[3] + a[2]*b[0] + a[3]*b[1]), + saturate_cast<_Tp>(a[0]*b[3] + a[1]*b[2] - a[2]*b[1] + a[3]*b[0])); +} + +template static inline +Scalar_<_Tp>& operator *= (Scalar_<_Tp>& a, const Scalar_<_Tp>& b) +{ + a = a * b; + return a; +} + +template static inline +Scalar_<_Tp> operator / (const Scalar_<_Tp>& a, _Tp alpha) +{ + return Scalar_<_Tp>(a.val[0] / alpha, + a.val[1] / alpha, + a.val[2] / alpha, + a.val[3] / alpha); +} + +template static inline +Scalar_ operator / (const Scalar_& a, float alpha) +{ + float s = 1 / alpha; + return Scalar_(a.val[0] * s, a.val[1] * s, a.val[2] * s, a.val[3] * s); +} + +template static inline +Scalar_ operator / (const Scalar_& a, double alpha) +{ + double s = 1 / alpha; + return Scalar_(a.val[0] * s, a.val[1] * s, a.val[2] * s, a.val[3] * s); +} + +template static inline +Scalar_<_Tp>& operator /= (Scalar_<_Tp>& a, _Tp alpha) +{ + a = a / alpha; + return a; +} + +template static inline +Scalar_<_Tp> operator / (_Tp a, const Scalar_<_Tp>& b) +{ + _Tp s = a / (b[0]*b[0] + b[1]*b[1] + b[2]*b[2] + b[3]*b[3]); + return b.conj() * s; +} + +template static inline +Scalar_<_Tp> operator / (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b) +{ + return a * ((_Tp)1 / b); +} + +template static inline +Scalar_<_Tp>& operator /= (Scalar_<_Tp>& a, const Scalar_<_Tp>& b) +{ + a = a / b; + return a; +} + +template static inline +Scalar operator * (const Matx<_Tp, 4, 4>& a, const Scalar& b) +{ + Matx c((Matx)a, b, Matx_MatMulOp()); + return reinterpret_cast(c); +} + +template<> inline +Scalar operator * (const Matx& a, const Scalar& b) +{ + Matx c(a, b, Matx_MatMulOp()); + return reinterpret_cast(c); +} + + + +//////////////////////////////// KeyPoint /////////////////////////////// + +inline +KeyPoint::KeyPoint() + : pt(0,0), size(0), angle(-1), response(0), octave(0), class_id(-1) {} + +inline +KeyPoint::KeyPoint(Point2f _pt, float _size, float _angle, float _response, int _octave, int _class_id) + : pt(_pt), size(_size), angle(_angle), response(_response), octave(_octave), class_id(_class_id) {} + +inline +KeyPoint::KeyPoint(float x, float y, float _size, float _angle, float _response, int _octave, int _class_id) + : pt(x, y), size(_size), angle(_angle), response(_response), octave(_octave), class_id(_class_id) {} + + + +///////////////////////////////// DMatch //////////////////////////////// + +inline +DMatch::DMatch() + : queryIdx(-1), trainIdx(-1), imgIdx(-1), distance(FLT_MAX) {} + +inline +DMatch::DMatch(int _queryIdx, int _trainIdx, float _distance) + : queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(-1), distance(_distance) {} + +inline +DMatch::DMatch(int _queryIdx, int _trainIdx, int _imgIdx, float _distance) + : queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(_imgIdx), distance(_distance) {} + +inline +bool DMatch::operator < (const DMatch &m) const +{ + return distance < m.distance; +} + + + +////////////////////////////// TermCriteria ///////////////////////////// + +inline +TermCriteria::TermCriteria() + : type(0), maxCount(0), epsilon(0) {} + +inline +TermCriteria::TermCriteria(int _type, int _maxCount, double _epsilon) + : type(_type), maxCount(_maxCount), epsilon(_epsilon) {} + +} // cv + +#endif //__OPENCV_CORE_TYPES_HPP__ diff --git a/modules/core/include/opencv2/core/types_c.h b/modules/core/include/opencv2/core/types_c.h index 5838c0415d..e4c8cb5a6a 100644 --- a/modules/core/include/opencv2/core/types_c.h +++ b/modules/core/include/opencv2/core/types_c.h @@ -12,6 +12,7 @@ // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -92,6 +93,14 @@ # define CVAPI(rettype) CV_EXTERN_C CV_EXPORTS rettype CV_CDECL #endif +#ifndef CV_IMPL +# define CV_IMPL CV_EXTERN_C +#endif + +#ifdef __cplusplus +# include "opencv2/core.hpp" +#endif + /* CvArr* is used to pass arbitrary * array-like data structures * into functions where the particular @@ -177,14 +186,6 @@ enum { #define CV_SWAP(a,b,t) ((t) = (a), (a) = (b), (b) = (t)) -#ifndef MIN -# define MIN(a,b) ((a) > (b) ? (b) : (a)) -#endif - -#ifndef MAX -# define MAX(a,b) ((a) < (b) ? (b) : (a)) -#endif - /* min & max without jumps */ #define CV_IMIN(a, b) ((a) ^ (((a)^(b)) & (((a) < (b)) - 1))) @@ -271,7 +272,11 @@ CV_INLINE double cvRandReal( CvRNG* rng ) #define IPL_BORDER_REFLECT 2 #define IPL_BORDER_WRAP 3 -typedef struct _IplImage +typedef struct +#ifdef __cplusplus + CV_EXPORTS +#endif +_IplImage { int nSize; /* sizeof(IplImage) */ int ID; /* version (=0)*/ @@ -303,6 +308,11 @@ typedef struct _IplImage char *imageDataOrigin; /* Pointer to very origin of image data (not necessarily aligned) - needed for correct deallocation */ + +#ifdef __cplusplus + _IplImage() {} + _IplImage(const cv::Mat& m); +#endif } IplImage; @@ -413,6 +423,13 @@ typedef struct CvMat int cols; #endif + +#ifdef __cplusplus + CvMat() {} + CvMat(const CvMat& m) { memcpy(this, &m, sizeof(CvMat));} + CvMat(const cv::Mat& m); +#endif + } CvMat; @@ -474,6 +491,16 @@ CV_INLINE CvMat cvMat( int rows, int cols, int type, void* data CV_DEFAULT(NULL) return m; } +#ifdef __cplusplus +inline CvMat::CvMat(const cv::Mat& m) +{ + CV_DbgAssert(m.dims <= 2); + *this = cvMat(m.rows, m.dims == 1 ? 1 : m.cols, m.type(), m.data); + step = (int)m.step[0]; + type = (type & ~cv::Mat::CONTINUOUS_FLAG) | (m.flags & cv::Mat::CONTINUOUS_FLAG); +} +#endif + #define CV_MAT_ELEM_PTR_FAST( mat, row, col, pix_size ) \ (assert( (unsigned)(row) < (unsigned)(mat).rows && \ @@ -540,7 +567,11 @@ CV_INLINE int cvIplDepth( int type ) #define CV_MAX_DIM 32 #define CV_MAX_DIM_HEAP 1024 -typedef struct CvMatND +typedef struct +#ifdef __cplusplus + CV_EXPORTS +#endif +CvMatND { int type; int dims; @@ -563,6 +594,11 @@ typedef struct CvMatND int step; } dim[CV_MAX_DIM]; + +#ifdef __cplusplus + CvMatND() {} + CvMatND(const cv::Mat& m); +#endif } CvMatND; @@ -582,7 +618,11 @@ CvMatND; struct CvSet; -typedef struct CvSparseMat +typedef struct +#ifdef __cplusplus + CV_EXPORTS +#endif +CvSparseMat { int type; int dims; @@ -595,9 +635,17 @@ typedef struct CvSparseMat int valoffset; int idxoffset; int size[CV_MAX_DIM]; + +#ifdef __cplusplus + void copyToSparseMat(cv::SparseMat& m) const; +#endif } CvSparseMat; +#ifdef __cplusplus + CV_EXPORTS CvSparseMat* cvCreateSparseMat(const cv::SparseMat& m); +#endif + #define CV_IS_SPARSE_MAT_HDR(mat) \ ((mat) != NULL && \ (((const CvSparseMat*)(mat))->type & CV_MAGIC_MASK) == CV_SPARSE_MAT_MAGIC_VAL) @@ -681,6 +729,14 @@ typedef struct CvRect int y; int width; int height; + +#ifdef __cplusplus + CvRect(int _x = 0, int _y = 0, int w = 0, int h = 0): x(_x), y(_y), width(w), height(h) {} + template + CvRect(const cv::Rect_<_Tp>& r): x(cv::saturate_cast(r.x)), y(cv::saturate_cast(r.y)), width(cv::saturate_cast(r.width)), height(cv::saturate_cast(r.height)) {} + template + operator cv::Rect_<_Tp>() const { return cv::Rect_<_Tp>((_Tp)x, (_Tp)y, (_Tp)width, (_Tp)height); } +#endif } CvRect; @@ -728,6 +784,13 @@ typedef struct CvTermCriteria CV_TERMCRIT_EPS */ int max_iter; double epsilon; + +#ifdef __cplusplus + CvTermCriteria(int _type = 0, int _iter = 0, double _eps = 0) : type(_type), max_iter(_iter), epsilon(_eps) {} + CvTermCriteria(const cv::TermCriteria& t) : type(t.type), max_iter(t.maxCount), epsilon(t.epsilon) {} + operator cv::TermCriteria() const { return cv::TermCriteria(type, max_iter, epsilon); } +#endif + } CvTermCriteria; @@ -749,6 +812,14 @@ typedef struct CvPoint { int x; int y; + +#ifdef __cplusplus + CvPoint(int _x = 0, int _y = 0): x(_x), y(_y) {} + template + CvPoint(const cv::Point_<_Tp>& pt): x((int)pt.x), y((int)pt.y) {} + template + operator cv::Point_<_Tp>() const { return cv::Point_<_Tp>(cv::saturate_cast<_Tp>(x), cv::saturate_cast<_Tp>(y)); } +#endif } CvPoint; @@ -768,6 +839,14 @@ typedef struct CvPoint2D32f { float x; float y; + +#ifdef __cplusplus + CvPoint2D32f(float _x = 0, float _y = 0): x(_x), y(_y) {} + template + CvPoint2D32f(const cv::Point_<_Tp>& pt): x((float)pt.x), y((float)pt.y) {} + template + operator cv::Point_<_Tp>() const { return cv::Point_<_Tp>(cv::saturate_cast<_Tp>(x), cv::saturate_cast<_Tp>(y)); } +#endif } CvPoint2D32f; @@ -804,6 +883,14 @@ typedef struct CvPoint3D32f float x; float y; float z; + +#ifdef __cplusplus + CvPoint3D32f(float _x = 0, float _y = 0, float _z = 0): x(_x), y(_y), z(_z) {} + template + CvPoint3D32f(const cv::Point3_<_Tp>& pt): x((float)pt.x), y((float)pt.y), z((float)pt.z) {} + template + operator cv::Point3_<_Tp>() const { return cv::Point3_<_Tp>(cv::saturate_cast<_Tp>(x), cv::saturate_cast<_Tp>(y), cv::saturate_cast<_Tp>(z)); } +#endif } CvPoint3D32f; @@ -866,6 +953,14 @@ typedef struct CvSize { int width; int height; + +#ifdef __cplusplus + CvSize(int w = 0, int h = 0): width(w), height(h) {} + template + CvSize(const cv::Size_<_Tp>& sz): width(cv::saturate_cast(sz.width)), height(cv::saturate_cast(sz.height)) {} + template + operator cv::Size_<_Tp>() const { return cv::Size_<_Tp>(cv::saturate_cast<_Tp>(width), cv::saturate_cast<_Tp>(height)); } +#endif } CvSize; @@ -883,6 +978,14 @@ typedef struct CvSize2D32f { float width; float height; + +#ifdef __cplusplus + CvSize2D32f(float w = 0, float h = 0): width(w), height(h) {} + template + CvSize2D32f(const cv::Size_<_Tp>& sz): width(cv::saturate_cast(sz.width)), height(cv::saturate_cast(sz.height)) {} + template + operator cv::Size_<_Tp>() const { return cv::Size_<_Tp>(cv::saturate_cast<_Tp>(width), cv::saturate_cast<_Tp>(height)); } +#endif } CvSize2D32f; @@ -903,6 +1006,12 @@ typedef struct CvBox2D CvSize2D32f size; /* Box width and length. */ float angle; /* Angle between the horizontal axis */ /* and the first side (i.e. length) in degrees */ + +#ifdef __cplusplus + CvBox2D(CvPoint2D32f c = CvPoint2D32f(), CvSize2D32f s = CvSize2D32f(), float a = 0) : center(c), size(s), angle(a) {} + CvBox2D(const cv::RotatedRect& rr) : center(rr.center), size(rr.size), angle(rr.angle) {} + operator cv::RotatedRect() const { return cv::RotatedRect(center, size, angle); } +#endif } CvBox2D; @@ -925,10 +1034,18 @@ CvLineIterator; /************************************* CvSlice ******************************************/ +#define CV_WHOLE_SEQ_END_INDEX 0x3fffffff +#define CV_WHOLE_SEQ cvSlice(0, CV_WHOLE_SEQ_END_INDEX) typedef struct CvSlice { int start_index, end_index; + +#if defined(__cplusplus) && !defined(__CUDACC__) + CvSlice(int start = 0, int end = 0) : start_index(start), end_index(end) {} + CvSlice(const cv::Range& r) { *this = (r.start != INT_MIN && r.end != INT_MAX) ? CvSlice(r.start, r.end) : CvSlice(0, CV_WHOLE_SEQ_END_INDEX); } + operator cv::Range() const { return (start_index == 0 && end_index == CV_WHOLE_SEQ_END_INDEX ) ? cv::Range::all() : cv::Range(start_index, end_index); } +#endif } CvSlice; @@ -941,8 +1058,6 @@ CV_INLINE CvSlice cvSlice( int start, int end ) return slice; } -#define CV_WHOLE_SEQ_END_INDEX 0x3fffffff -#define CV_WHOLE_SEQ cvSlice(0, CV_WHOLE_SEQ_END_INDEX) /************************************* CvScalar *****************************************/ @@ -950,6 +1065,22 @@ CV_INLINE CvSlice cvSlice( int start, int end ) typedef struct CvScalar { double val[4]; + +#ifdef __cplusplus + CvScalar() {} + CvScalar(double d0, double d1 = 0, double d2 = 0, double d3 = 0) { val[0] = d0; val[1] = d1; val[2] = d2; val[3] = d3; } + template + CvScalar(const cv::Scalar_<_Tp>& s) { val[0] = s.val[0]; val[1] = s.val[1]; val[2] = s.val[2]; val[3] = s.val[3]; } + template + operator cv::Scalar_<_Tp>() const { return cv::Scalar_<_Tp>(cv::saturate_cast<_Tp>(val[0]), cv::saturate_cast<_Tp>(val[1]), cv::saturate_cast<_Tp>(val[2]), cv::saturate_cast<_Tp>(val[3])); } + template + CvScalar(const cv::Vec<_Tp, cn>& v) + { + int i; + for( i = 0; i < (cn < 4 ? cn : 4); i++ ) val[i] = v.val[i]; + for( ; i < 4; i++ ) val[i] = 0; + } +#endif } CvScalar; @@ -1343,7 +1474,6 @@ CvSeqWriter; int delta_index;/* = seq->first->start_index */ \ schar* prev_elem; /* pointer to previous element */ - typedef struct CvSeqReader { CV_SEQ_READER_FIELDS() diff --git a/modules/core/include/opencv2/core/utility.hpp b/modules/core/include/opencv2/core/utility.hpp new file mode 100644 index 0000000000..c96a0aaf93 --- /dev/null +++ b/modules/core/include/opencv2/core/utility.hpp @@ -0,0 +1,466 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_UTILITY_H__ +#define __OPENCV_CORE_UTILITY_H__ + +#ifndef __cplusplus +# error utility.hpp header must be compiled as C++ +#endif + +#include "opencv2/core.hpp" + +namespace cv +{ + +/*! + Automatically Allocated Buffer Class + + The class is used for temporary buffers in functions and methods. + If a temporary buffer is usually small (a few K's of memory), + but its size depends on the parameters, it makes sense to create a small + fixed-size array on stack and use it if it's large enough. If the required buffer size + is larger than the fixed size, another buffer of sufficient size is allocated dynamically + and released after the processing. Therefore, in typical cases, when the buffer size is small, + there is no overhead associated with malloc()/free(). + At the same time, there is no limit on the size of processed data. + + This is what AutoBuffer does. The template takes 2 parameters - type of the buffer elements and + the number of stack-allocated elements. Here is how the class is used: + + \code + void my_func(const cv::Mat& m) + { + cv::AutoBuffer buf; // create automatic buffer containing 1000 floats + + buf.allocate(m.rows); // if m.rows <= 1000, the pre-allocated buffer is used, + // otherwise the buffer of "m.rows" floats will be allocated + // dynamically and deallocated in cv::AutoBuffer destructor + ... + } + \endcode +*/ +template class AutoBuffer +{ +public: + typedef _Tp value_type; + + //! the default contructor + AutoBuffer(); + //! constructor taking the real buffer size + AutoBuffer(size_t _size); + + //! the copy constructor + AutoBuffer(const AutoBuffer<_Tp, fixed_size>& buf); + //! the assignment operator + AutoBuffer<_Tp, fixed_size>& operator = (const AutoBuffer<_Tp, fixed_size>& buf); + + //! destructor. calls deallocate() + ~AutoBuffer(); + + //! allocates the new buffer of size _size. if the _size is small enough, stack-allocated buffer is used + void allocate(size_t _size); + //! deallocates the buffer if it was dynamically allocated + void deallocate(); + //! resizes the buffer and preserves the content + void resize(size_t _size); + //! returns the current buffer size + size_t size() const; + //! returns pointer to the real buffer, stack-allocated or head-allocated + operator _Tp* (); + //! returns read-only pointer to the real buffer, stack-allocated or head-allocated + operator const _Tp* () const; + +protected: + //! pointer to the real buffer, can point to buf if the buffer is small enough + _Tp* ptr; + //! size of the real buffer + size_t sz; + //! pre-allocated buffer. At least 1 element to confirm C++ standard reqirements + _Tp buf[(fixed_size > 0) ? fixed_size : 1]; +}; + +//! Sets/resets the break-on-error mode. + +/*! + When the break-on-error mode is set, the default error handler + issues a hardware exception, which can make debugging more convenient. + + \return the previous state + */ +CV_EXPORTS bool setBreakOnError(bool flag); + +extern "C" typedef int (*ErrorCallback)( int status, const char* func_name, + const char* err_msg, const char* file_name, + int line, void* userdata ); + +//! Sets the new error handler and the optional user data. + +/*! + The function sets the new error handler, called from cv::error(). + + \param errCallback the new error handler. If NULL, the default error handler is used. + \param userdata the optional user data pointer, passed to the callback. + \param prevUserdata the optional output parameter where the previous user data pointer is stored + + \return the previous error handler +*/ +CV_EXPORTS ErrorCallback redirectError( ErrorCallback errCallback, void* userdata=0, void** prevUserdata=0); + +CV_EXPORTS String format( const char* fmt, ... ); +CV_EXPORTS String tempfile( const char* suffix = 0); +CV_EXPORTS void glob(String pattern, std::vector& result, bool recursive = false); +CV_EXPORTS void setNumThreads(int nthreads); +CV_EXPORTS int getNumThreads(); +CV_EXPORTS int getThreadNum(); + +CV_EXPORTS_W const String& getBuildInformation(); + +//! Returns the number of ticks. + +/*! + The function returns the number of ticks since the certain event (e.g. when the machine was turned on). + It can be used to initialize cv::RNG or to measure a function execution time by reading the tick count + before and after the function call. The granularity of ticks depends on the hardware and OS used. Use + cv::getTickFrequency() to convert ticks to seconds. +*/ +CV_EXPORTS_W int64 getTickCount(); + +/*! + Returns the number of ticks per seconds. + + The function returns the number of ticks (as returned by cv::getTickCount()) per second. + The following code computes the execution time in milliseconds: + + \code + double exec_time = (double)getTickCount(); + // do something ... + exec_time = ((double)getTickCount() - exec_time)*1000./getTickFrequency(); + \endcode +*/ +CV_EXPORTS_W double getTickFrequency(); + +/*! + Returns the number of CPU ticks. + + On platforms where the feature is available, the function returns the number of CPU ticks + since the certain event (normally, the system power-on moment). Using this function + one can accurately measure the execution time of very small code fragments, + for which cv::getTickCount() granularity is not enough. +*/ +CV_EXPORTS_W int64 getCPUTickCount(); + +/*! + Returns SSE etc. support status + + The function returns true if certain hardware features are available. + Currently, the following features are recognized: + - CV_CPU_MMX - MMX + - CV_CPU_SSE - SSE + - CV_CPU_SSE2 - SSE 2 + - CV_CPU_SSE3 - SSE 3 + - CV_CPU_SSSE3 - SSSE 3 + - CV_CPU_SSE4_1 - SSE 4.1 + - CV_CPU_SSE4_2 - SSE 4.2 + - CV_CPU_POPCNT - POPCOUNT + - CV_CPU_AVX - AVX + + \note {Note that the function output is not static. Once you called cv::useOptimized(false), + most of the hardware acceleration is disabled and thus the function will returns false, + until you call cv::useOptimized(true)} +*/ +CV_EXPORTS_W bool checkHardwareSupport(int feature); + +//! returns the number of CPUs (including hyper-threading) +CV_EXPORTS_W int getNumberOfCPUs(); + + +/*! + Aligns pointer by the certain number of bytes + + This small inline function aligns the pointer by the certian number of bytes by shifting + it forward by 0 or a positive offset. +*/ +template static inline _Tp* alignPtr(_Tp* ptr, int n=(int)sizeof(_Tp)) +{ + return (_Tp*)(((size_t)ptr + n-1) & -n); +} + +/*! + Aligns buffer size by the certain number of bytes + + This small inline function aligns a buffer size by the certian number of bytes by enlarging it. +*/ +static inline size_t alignSize(size_t sz, int n) +{ + return (sz + n-1) & -n; +} + +/*! + Turns on/off available optimization + + The function turns on or off the optimized code in OpenCV. Some optimization can not be enabled + or disabled, but, for example, most of SSE code in OpenCV can be temporarily turned on or off this way. + + \note{Since optimization may imply using special data structures, it may be unsafe + to call this function anywhere in the code. Instead, call it somewhere at the top level.} +*/ +CV_EXPORTS_W void setUseOptimized(bool onoff); + +/*! + Returns the current optimization status + + The function returns the current optimization status, which is controlled by cv::setUseOptimized(). +*/ +CV_EXPORTS_W bool useOptimized(); + +static inline size_t getElemSize(int type) { return CV_ELEM_SIZE(type); } + +/////////////////////////////// Parallel Primitives ////////////////////////////////// + +// a base body class +class CV_EXPORTS ParallelLoopBody +{ +public: + virtual ~ParallelLoopBody(); + virtual void operator() (const Range& range) const = 0; +}; + +CV_EXPORTS void parallel_for_(const Range& range, const ParallelLoopBody& body, double nstripes=-1.); + +/////////////////////////// Synchronization Primitives /////////////////////////////// + +class CV_EXPORTS Mutex +{ +public: + Mutex(); + ~Mutex(); + Mutex(const Mutex& m); + Mutex& operator = (const Mutex& m); + + void lock(); + bool trylock(); + void unlock(); + + struct Impl; +protected: + Impl* impl; +}; + +class CV_EXPORTS AutoLock +{ +public: + AutoLock(Mutex& m) : mutex(&m) { mutex->lock(); } + ~AutoLock() { mutex->unlock(); } +protected: + Mutex* mutex; +private: + AutoLock(const AutoLock&); + AutoLock& operator = (const AutoLock&); +}; + +// The CommandLineParser class is designed for command line arguments parsing + +class CV_EXPORTS CommandLineParser +{ + public: + CommandLineParser(int argc, const char* const argv[], const String& keys); + CommandLineParser(const CommandLineParser& parser); + CommandLineParser& operator = (const CommandLineParser& parser); + + String getPathToApplication() const; + + template + T get(const String& name, bool space_delete = true) const + { + T val = T(); + getByName(name, space_delete, ParamType::type, (void*)&val); + return val; + } + + template + T get(int index, bool space_delete = true) const + { + T val = T(); + getByIndex(index, space_delete, ParamType::type, (void*)&val); + return val; + } + + bool has(const String& name) const; + + bool check() const; + + void about(const String& message); + + void printMessage() const; + void printErrors() const; + +protected: + void getByName(const String& name, bool space_delete, int type, void* dst) const; + void getByIndex(int index, bool space_delete, int type, void* dst) const; + + struct Impl; + Impl* impl; +}; + +/////////////////////////////// AutoBuffer implementation //////////////////////////////////////// + +template inline +AutoBuffer<_Tp, fixed_size>::AutoBuffer() +{ + ptr = buf; + sz = fixed_size; +} + +template inline +AutoBuffer<_Tp, fixed_size>::AutoBuffer(size_t _size) +{ + ptr = buf; + sz = fixed_size; + allocate(_size); +} + +template inline +AutoBuffer<_Tp, fixed_size>::AutoBuffer(const AutoBuffer<_Tp, fixed_size>& abuf ) +{ + ptr = buf; + sz = fixed_size; + allocate(abuf.size()); + for( size_t i = 0; i < sz; i++ ) + ptr[i] = abuf.ptr[i]; +} + +template inline AutoBuffer<_Tp, fixed_size>& +AutoBuffer<_Tp, fixed_size>::operator = (const AutoBuffer<_Tp, fixed_size>& abuf) +{ + if( this != &abuf ) + { + deallocate(); + allocate(abuf.size()); + for( size_t i = 0; i < sz; i++ ) + ptr[i] = abuf.ptr[i]; + } + return *this; +} + +template inline +AutoBuffer<_Tp, fixed_size>::~AutoBuffer() +{ deallocate(); } + +template inline void +AutoBuffer<_Tp, fixed_size>::allocate(size_t _size) +{ + if(_size <= sz) + { + sz = _size; + return; + } + deallocate(); + if(_size > fixed_size) + { + ptr = new _Tp[_size]; + sz = _size; + } +} + +template inline void +AutoBuffer<_Tp, fixed_size>::deallocate() +{ + if( ptr != buf ) + { + delete[] ptr; + ptr = buf; + sz = fixed_size; + } +} + +template inline void +AutoBuffer<_Tp, fixed_size>::resize(size_t _size) +{ + if(_size <= sz) + { + sz = _size; + return; + } + size_t i, prevsize = sz, minsize = MIN(prevsize, _size); + _Tp* prevptr = ptr; + + ptr = _size > fixed_size ? new _Tp[_size] : buf; + sz = _size; + + if( ptr != prevptr ) + for( i = 0; i < minsize; i++ ) + ptr[i] = prevptr[i]; + for( i = prevsize; i < _size; i++ ) + ptr[i] = _Tp(); + + if( prevptr != buf ) + delete[] prevptr; +} + +template inline size_t +AutoBuffer<_Tp, fixed_size>::size() const +{ return sz; } + +template inline +AutoBuffer<_Tp, fixed_size>::operator _Tp* () +{ return ptr; } + +template inline +AutoBuffer<_Tp, fixed_size>::operator const _Tp* () const +{ return ptr; } + +#ifndef OPENCV_NOSTL +template<> inline std::string CommandLineParser::get(int index, bool space_delete) const +{ + return get(index, space_delete); +} +template<> inline std::string CommandLineParser::get(const String& name, bool space_delete) const +{ + return get(name, space_delete); +} +#endif // OPENCV_NOSTL + +} //namespace cv + +#endif //__OPENCV_CORE_UTILITY_H__ diff --git a/modules/core/include/opencv2/core/version.hpp b/modules/core/include/opencv2/core/version.hpp index 916d173bac..203503ecad 100644 --- a/modules/core/include/opencv2/core/version.hpp +++ b/modules/core/include/opencv2/core/version.hpp @@ -11,6 +11,7 @@ // For Open Source Computer Vision Library // // Copyright( C) 2000, Intel Corporation, all rights reserved. +// Copyright (C) 2011-2013, NVIDIA Corporation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -47,18 +48,22 @@ #ifndef __OPENCV_VERSION_HPP__ #define __OPENCV_VERSION_HPP__ -#define CV_VERSION_EPOCH 2 -#define CV_VERSION_MAJOR 4 -#define CV_VERSION_MINOR 9 +#define CV_VERSION_EPOCH 3 +#define CV_VERSION_MAJOR 0 +#define CV_VERSION_MINOR 0 #define CV_VERSION_REVISION 0 +#define CV_VERSION_STATUS "-dev" #define CVAUX_STR_EXP(__A) #__A #define CVAUX_STR(__A) CVAUX_STR_EXP(__A) +#define CVAUX_STRW_EXP(__A) L#__A +#define CVAUX_STRW(__A) CVAUX_STRW_EXP(__A) + #if CV_VERSION_REVISION -# define CV_VERSION CVAUX_STR(CV_VERSION_EPOCH) "." CVAUX_STR(CV_VERSION_MAJOR) "." CVAUX_STR(CV_VERSION_MINOR) "." CVAUX_STR(CV_VERSION_REVISION) +# define CV_VERSION CVAUX_STR(CV_VERSION_EPOCH) "." CVAUX_STR(CV_VERSION_MAJOR) "." CVAUX_STR(CV_VERSION_MINOR) "." CVAUX_STR(CV_VERSION_REVISION) CV_VERSION_STATUS #else -# define CV_VERSION CVAUX_STR(CV_VERSION_EPOCH) "." CVAUX_STR(CV_VERSION_MAJOR) "." CVAUX_STR(CV_VERSION_MINOR) +# define CV_VERSION CVAUX_STR(CV_VERSION_EPOCH) "." CVAUX_STR(CV_VERSION_MAJOR) "." CVAUX_STR(CV_VERSION_MINOR) CV_VERSION_STATUS #endif /* old style version constants*/ diff --git a/modules/core/perf/perf_abs.cpp b/modules/core/perf/perf_abs.cpp index 691c6f7c4b..63cb06b638 100644 --- a/modules/core/perf/perf_abs.cpp +++ b/modules/core/perf/perf_abs.cpp @@ -24,4 +24,3 @@ PERF_TEST_P(Size_MatType, abs, TYPICAL_MATS_ABS) SANITY_CHECK(c); } - diff --git a/modules/core/perf/perf_bitwise.cpp b/modules/core/perf/perf_bitwise.cpp index 64a8dd8bd9..1308b7bf3e 100644 --- a/modules/core/perf/perf_bitwise.cpp +++ b/modules/core/perf/perf_bitwise.cpp @@ -73,4 +73,3 @@ PERF_TEST_P(Size_MatType, bitwise_xor, TYPICAL_MATS_BITW_ARITHM) SANITY_CHECK(c); } - diff --git a/modules/core/perf/perf_compare.cpp b/modules/core/perf/perf_compare.cpp index 5fb755d956..86d07d9c0a 100644 --- a/modules/core/perf/perf_compare.cpp +++ b/modules/core/perf/perf_compare.cpp @@ -15,7 +15,7 @@ PERF_TEST_P( Size_MatType_CmpType, compare, testing::Combine( testing::Values(::perf::szVGA, ::perf::sz1080p), testing::Values(CV_8UC1, CV_8UC4, CV_8SC1, CV_16UC1, CV_16SC1, CV_32SC1, CV_32FC1), - testing::ValuesIn(CmpType::all()) + CmpType::all() ) ) { @@ -38,7 +38,7 @@ PERF_TEST_P( Size_MatType_CmpType, compareScalar, testing::Combine( testing::Values(TYPICAL_MAT_SIZES), testing::Values(TYPICAL_MAT_TYPES), - testing::ValuesIn(CmpType::all()) + CmpType::all() ) ) { diff --git a/modules/core/perf/perf_main.cpp b/modules/core/perf/perf_main.cpp index 79c28a645c..7c899c2446 100644 --- a/modules/core/perf/perf_main.cpp +++ b/modules/core/perf/perf_main.cpp @@ -1,3 +1,8 @@ #include "perf_precomp.hpp" +#ifdef _MSC_VER +# if _MSC_VER >= 1700 +# pragma warning(disable:4447) // Disable warning 'main' signature found without threading model +# endif +#endif CV_PERF_TEST_MAIN(core) diff --git a/modules/core/perf/perf_merge.cpp b/modules/core/perf/perf_merge.cpp index d82941a92b..e7e8d2fe3f 100644 --- a/modules/core/perf/perf_merge.cpp +++ b/modules/core/perf/perf_merge.cpp @@ -34,4 +34,4 @@ PERF_TEST_P( Size_SrcDepth_DstChannels, merge, TEST_CYCLE_MULTIRUN(runs) merge( (vector &)mv, dst ); SANITY_CHECK(dst, 1e-12); -} \ No newline at end of file +} diff --git a/modules/core/perf/perf_precomp.cpp b/modules/core/perf/perf_precomp.cpp deleted file mode 100644 index 8552ac3d42..0000000000 --- a/modules/core/perf/perf_precomp.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "perf_precomp.hpp" diff --git a/modules/core/perf/perf_reduce.cpp b/modules/core/perf/perf_reduce.cpp index 81cdb5db57..7b74b0e7e3 100644 --- a/modules/core/perf/perf_reduce.cpp +++ b/modules/core/perf/perf_reduce.cpp @@ -16,7 +16,7 @@ PERF_TEST_P(Size_MatType_ROp, reduceR, testing::Combine( testing::Values(TYPICAL_MAT_SIZES), testing::Values(TYPICAL_MAT_TYPES), - testing::ValuesIn(ROp::all()) + ROp::all() ) ) { @@ -34,7 +34,8 @@ PERF_TEST_P(Size_MatType_ROp, reduceR, declare.in(src, WARMUP_RNG).out(vec); declare.time(100); - TEST_CYCLE() reduce(src, vec, 0, reduceOp, ddepth); + int runs = 15; + TEST_CYCLE_MULTIRUN(runs) reduce(src, vec, 0, reduceOp, ddepth); SANITY_CHECK(vec, 1); } @@ -43,7 +44,7 @@ PERF_TEST_P(Size_MatType_ROp, reduceC, testing::Combine( testing::Values(TYPICAL_MAT_SIZES), testing::Values(TYPICAL_MAT_TYPES), - testing::ValuesIn(ROp::all()) + ROp::all() ) ) { @@ -65,4 +66,3 @@ PERF_TEST_P(Size_MatType_ROp, reduceC, SANITY_CHECK(vec, 1); } - diff --git a/modules/core/perf/perf_stat.cpp b/modules/core/perf/perf_stat.cpp index b7fc43d120..6b5f0ff524 100644 --- a/modules/core/perf/perf_stat.cpp +++ b/modules/core/perf/perf_stat.cpp @@ -33,7 +33,7 @@ PERF_TEST_P(Size_MatType, mean, TYPICAL_MATS) TEST_CYCLE() s = mean(src); - SANITY_CHECK(s, 1e-6); + SANITY_CHECK(s, 1e-5); } PERF_TEST_P(Size_MatType, mean_mask, TYPICAL_MATS) @@ -49,7 +49,7 @@ PERF_TEST_P(Size_MatType, mean_mask, TYPICAL_MATS) TEST_CYCLE() s = mean(src, mask); - SANITY_CHECK(s, 1e-6); + SANITY_CHECK(s, 5e-5); } PERF_TEST_P(Size_MatType, meanStdDev, TYPICAL_MATS) @@ -83,8 +83,8 @@ PERF_TEST_P(Size_MatType, meanStdDev_mask, TYPICAL_MATS) TEST_CYCLE() meanStdDev(src, mean, dev, mask); - SANITY_CHECK(mean, 1e-6); - SANITY_CHECK(dev, 1e-6); + SANITY_CHECK(mean, 1e-5); + SANITY_CHECK(dev, 1e-5); } PERF_TEST_P(Size_MatType, countNonZero, testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( CV_8UC1, CV_8SC1, CV_16UC1, CV_16SC1, CV_32SC1, CV_32FC1, CV_64FC1 ) )) diff --git a/modules/core/src/algorithm.cpp b/modules/core/src/algorithm.cpp index 67c71443c5..ff67a5df1e 100644 --- a/modules/core/src/algorithm.cpp +++ b/modules/core/src/algorithm.cpp @@ -96,7 +96,7 @@ template struct sorted_vector }; -template inline const _ValueTp* findstr(const sorted_vector& vec, +template inline const _ValueTp* findstr(const sorted_vector& vec, const char* key) { if( !key ) @@ -130,7 +130,7 @@ Param::Param() Param::Param(int _type, bool _readonly, int _offset, Algorithm::Getter _getter, Algorithm::Setter _setter, - const std::string& _help) + const String& _help) { type = _type; readonly = _readonly; @@ -142,28 +142,28 @@ Param::Param(int _type, bool _readonly, int _offset, struct CV_EXPORTS AlgorithmInfoData { - sorted_vector params; - std::string _name; + sorted_vector params; + String _name; }; -static sorted_vector& alglist() +static sorted_vector& alglist() { - static sorted_vector alglist_var; + static sorted_vector alglist_var; return alglist_var; } -void Algorithm::getList(std::vector& algorithms) +void Algorithm::getList(std::vector& algorithms) { alglist().get_keys(algorithms); } -Ptr Algorithm::_create(const std::string& name) +Ptr Algorithm::_create(const String& name) { Algorithm::Constructor c = 0; if( !alglist().find(name, c) ) return Ptr(); - return c(); + return Ptr(c()); } Algorithm::Algorithm() @@ -174,42 +174,42 @@ Algorithm::~Algorithm() { } -std::string Algorithm::name() const +String Algorithm::name() const { return info()->name(); } -void Algorithm::set(const std::string& parameter, int value) +void Algorithm::set(const String& parameter, int value) { info()->set(this, parameter.c_str(), ParamType::type, &value); } -void Algorithm::set(const std::string& parameter, double value) +void Algorithm::set(const String& parameter, double value) { info()->set(this, parameter.c_str(), ParamType::type, &value); } -void Algorithm::set(const std::string& parameter, bool value) +void Algorithm::set(const String& parameter, bool value) { info()->set(this, parameter.c_str(), ParamType::type, &value); } -void Algorithm::set(const std::string& parameter, const std::string& value) +void Algorithm::set(const String& parameter, const String& value) { - info()->set(this, parameter.c_str(), ParamType::type, &value); + info()->set(this, parameter.c_str(), ParamType::type, &value); } -void Algorithm::set(const std::string& parameter, const Mat& value) +void Algorithm::set(const String& parameter, const Mat& value) { info()->set(this, parameter.c_str(), ParamType::type, &value); } -void Algorithm::set(const std::string& parameter, const std::vector& value) +void Algorithm::set(const String& parameter, const std::vector& value) { info()->set(this, parameter.c_str(), ParamType >::type, &value); } -void Algorithm::set(const std::string& parameter, const Ptr& value) +void Algorithm::set(const String& parameter, const Ptr& value) { info()->set(this, parameter.c_str(), ParamType::type, &value); } @@ -229,9 +229,9 @@ void Algorithm::set(const char* parameter, bool value) info()->set(this, parameter, ParamType::type, &value); } -void Algorithm::set(const char* parameter, const std::string& value) +void Algorithm::set(const char* parameter, const String& value) { - info()->set(this, parameter, ParamType::type, &value); + info()->set(this, parameter, ParamType::type, &value); } void Algorithm::set(const char* parameter, const Mat& value) @@ -250,37 +250,37 @@ void Algorithm::set(const char* parameter, const Ptr& value) } -void Algorithm::setInt(const std::string& parameter, int value) +void Algorithm::setInt(const String& parameter, int value) { info()->set(this, parameter.c_str(), ParamType::type, &value); } -void Algorithm::setDouble(const std::string& parameter, double value) +void Algorithm::setDouble(const String& parameter, double value) { info()->set(this, parameter.c_str(), ParamType::type, &value); } -void Algorithm::setBool(const std::string& parameter, bool value) +void Algorithm::setBool(const String& parameter, bool value) { info()->set(this, parameter.c_str(), ParamType::type, &value); } -void Algorithm::setString(const std::string& parameter, const std::string& value) +void Algorithm::setString(const String& parameter, const String& value) { - info()->set(this, parameter.c_str(), ParamType::type, &value); + info()->set(this, parameter.c_str(), ParamType::type, &value); } -void Algorithm::setMat(const std::string& parameter, const Mat& value) +void Algorithm::setMat(const String& parameter, const Mat& value) { info()->set(this, parameter.c_str(), ParamType::type, &value); } -void Algorithm::setMatVector(const std::string& parameter, const std::vector& value) +void Algorithm::setMatVector(const String& parameter, const std::vector& value) { info()->set(this, parameter.c_str(), ParamType >::type, &value); } -void Algorithm::setAlgorithm(const std::string& parameter, const Ptr& value) +void Algorithm::setAlgorithm(const String& parameter, const Ptr& value) { info()->set(this, parameter.c_str(), ParamType::type, &value); } @@ -300,9 +300,9 @@ void Algorithm::setBool(const char* parameter, bool value) info()->set(this, parameter, ParamType::type, &value); } -void Algorithm::setString(const char* parameter, const std::string& value) +void Algorithm::setString(const char* parameter, const String& value) { - info()->set(this, parameter, ParamType::type, &value); + info()->set(this, parameter, ParamType::type, &value); } void Algorithm::setMat(const char* parameter, const Mat& value) @@ -322,47 +322,47 @@ void Algorithm::setAlgorithm(const char* parameter, const Ptr& value) -int Algorithm::getInt(const std::string& parameter) const +int Algorithm::getInt(const String& parameter) const { return get(parameter); } -double Algorithm::getDouble(const std::string& parameter) const +double Algorithm::getDouble(const String& parameter) const { return get(parameter); } -bool Algorithm::getBool(const std::string& parameter) const +bool Algorithm::getBool(const String& parameter) const { return get(parameter); } -std::string Algorithm::getString(const std::string& parameter) const +String Algorithm::getString(const String& parameter) const { - return get(parameter); + return get(parameter); } -Mat Algorithm::getMat(const std::string& parameter) const +Mat Algorithm::getMat(const String& parameter) const { return get(parameter); } -std::vector Algorithm::getMatVector(const std::string& parameter) const +std::vector Algorithm::getMatVector(const String& parameter) const { return get >(parameter); } -Ptr Algorithm::getAlgorithm(const std::string& parameter) const +Ptr Algorithm::getAlgorithm(const String& parameter) const { return get(parameter); } -std::string Algorithm::paramHelp(const std::string& parameter) const +String Algorithm::paramHelp(const String& parameter) const { return info()->paramHelp(parameter.c_str()); } -int Algorithm::paramType(const std::string& parameter) const +int Algorithm::paramType(const String& parameter) const { return info()->paramType(parameter.c_str()); } @@ -372,7 +372,7 @@ int Algorithm::paramType(const char* parameter) const return info()->paramType(parameter); } -void Algorithm::getParams(std::vector& names) const +void Algorithm::getParams(std::vector& names) const { info()->getParams(names); } @@ -388,7 +388,7 @@ void Algorithm::read(const FileNode& fn) } -AlgorithmInfo::AlgorithmInfo(const std::string& _name, Algorithm::Constructor create) +AlgorithmInfo::AlgorithmInfo(const String& _name, Algorithm::Constructor create) { data = new AlgorithmInfoData; data->_name = _name; @@ -408,7 +408,7 @@ void AlgorithmInfo::write(const Algorithm* algo, FileStorage& fs) const for( i = 0; i < nparams; i++ ) { const Param& p = data->params.vec[i].second; - const std::string& pname = data->params.vec[i].first; + const String& pname = data->params.vec[i].first; if( p.type == Param::INT ) cv::write(fs, pname, algo->get(pname)); else if( p.type == Param::BOOLEAN ) @@ -416,14 +416,14 @@ void AlgorithmInfo::write(const Algorithm* algo, FileStorage& fs) const else if( p.type == Param::REAL ) cv::write(fs, pname, algo->get(pname)); else if( p.type == Param::STRING ) - cv::write(fs, pname, algo->get(pname)); + cv::write(fs, pname, algo->get(pname)); else if( p.type == Param::MAT ) cv::write(fs, pname, algo->get(pname)); else if( p.type == Param::MAT_VECTOR ) cv::write(fs, pname, algo->get >(pname)); else if( p.type == Param::ALGORITHM ) { - WriteStructContext ws(fs, pname, CV_NODE_MAP); + internal::WriteStructContext ws(fs, pname, CV_NODE_MAP); Ptr nestedAlgo = algo->get(pname); nestedAlgo->write(fs); } @@ -437,7 +437,7 @@ void AlgorithmInfo::write(const Algorithm* algo, FileStorage& fs) const cv::write(fs, pname, algo->getInt(pname)); else { - std::string msg = format("unknown/unsupported type of '%s' parameter == %d", pname.c_str(), p.type); + String msg = format("unknown/unsupported type of '%s' parameter == %d", pname.c_str(), p.type); CV_Error( CV_StsUnsupportedFormat, msg.c_str()); } } @@ -451,7 +451,7 @@ void AlgorithmInfo::read(Algorithm* algo, const FileNode& fn) const for( i = 0; i < nparams; i++ ) { const Param& p = data->params.vec[i].second; - const std::string& pname = data->params.vec[i].first; + const String& pname = data->params.vec[i].first; const FileNode n = fn[pname]; if( n.empty() ) continue; @@ -472,7 +472,7 @@ void AlgorithmInfo::read(Algorithm* algo, const FileNode& fn) const } else if( p.type == Param::STRING ) { - std::string val = (std::string)n; + String val = (String)n; info->set(algo, pname.c_str(), p.type, &val, true); } else if( p.type == Param::MAT ) @@ -489,8 +489,8 @@ void AlgorithmInfo::read(Algorithm* algo, const FileNode& fn) const } else if( p.type == Param::ALGORITHM ) { - Ptr nestedAlgo = Algorithm::_create((std::string)n["name"]); - CV_Assert( !nestedAlgo.empty() ); + Ptr nestedAlgo = Algorithm::_create((String)n["name"]); + CV_Assert( nestedAlgo ); nestedAlgo->read(n); info->set(algo, pname.c_str(), p.type, &nestedAlgo, true); } @@ -516,13 +516,13 @@ void AlgorithmInfo::read(Algorithm* algo, const FileNode& fn) const } else { - std::string msg = format("unknown/unsupported type of '%s' parameter == %d", pname.c_str(), p.type); + String msg = format("unknown/unsupported type of '%s' parameter == %d", pname.c_str(), p.type); CV_Error( CV_StsUnsupportedFormat, msg.c_str()); } } } -std::string AlgorithmInfo::name() const +String AlgorithmInfo::name() const { return data->_name; } @@ -532,7 +532,7 @@ union GetSetParam int (Algorithm::*get_int)() const; bool (Algorithm::*get_bool)() const; double (Algorithm::*get_double)() const; - std::string (Algorithm::*get_string)() const; + String (Algorithm::*get_string)() const; Mat (Algorithm::*get_mat)() const; std::vector (Algorithm::*get_mat_vector)() const; Ptr (Algorithm::*get_algo)() const; @@ -544,7 +544,7 @@ union GetSetParam void (Algorithm::*set_int)(int); void (Algorithm::*set_bool)(bool); void (Algorithm::*set_double)(double); - void (Algorithm::*set_string)(const std::string&); + void (Algorithm::*set_string)(const String&); void (Algorithm::*set_mat)(const Mat&); void (Algorithm::*set_mat_vector)(const std::vector&); void (Algorithm::*set_algo)(const Ptr&); @@ -554,9 +554,9 @@ union GetSetParam void (Algorithm::*set_uchar)(uchar); }; -static std::string getNameOfType(int argType); +static String getNameOfType(int argType); -static std::string getNameOfType(int argType) +static String getNameOfType(int argType) { switch(argType) { @@ -576,37 +576,37 @@ static std::string getNameOfType(int argType) return ""; } -static std::string getErrorMessageForWrongArgumentInSetter(std::string algoName, std::string paramName, int paramType, int argType) +static String getErrorMessageForWrongArgumentInSetter(String algoName, String paramName, int paramType, int argType) { - std::string message = std::string("Argument error: the setter") + String message = String("Argument error: the setter") + " method was called for the parameter '" + paramName + "' of the algorithm '" + algoName +"', the parameter has " + getNameOfType(paramType) + " type, "; if (paramType == Param::INT || paramType == Param::BOOLEAN || paramType == Param::REAL || paramType == Param::FLOAT || paramType == Param::UNSIGNED_INT || paramType == Param::UINT64 || paramType == Param::UCHAR) { - message += "so it should be set by integer, unsigned integer, uint64, unsigned char, boolean, float or double value, "; + message = message + "so it should be set by integer, unsigned integer, uint64, unsigned char, boolean, float or double value, "; } - message += "but the setter was called with " + getNameOfType(argType) + " value"; + message = message + "but the setter was called with " + getNameOfType(argType) + " value"; return message; } -static std::string getErrorMessageForWrongArgumentInGetter(std::string algoName, std::string paramName, int paramType, int argType) +static String getErrorMessageForWrongArgumentInGetter(String algoName, String paramName, int paramType, int argType) { - std::string message = std::string("Argument error: the getter") + String message = String("Argument error: the getter") + " method was called for the parameter '" + paramName + "' of the algorithm '" + algoName +"', the parameter has " + getNameOfType(paramType) + " type, "; if (paramType == Param::BOOLEAN) { - message += "so it should be get as integer, unsigned integer, uint64, boolean, unsigned char, float or double value, "; + message = message + "so it should be get as integer, unsigned integer, uint64, boolean, unsigned char, float or double value, "; } else if (paramType == Param::INT || paramType == Param::UNSIGNED_INT || paramType == Param::UINT64 || paramType == Param::UCHAR) { - message += "so it should be get as integer, unsigned integer, uint64, unsigned char, float or double value, "; + message = message + "so it should be get as integer, unsigned integer, uint64, unsigned char, float or double value, "; } - message += "but the getter was called to get a " + getNameOfType(argType) + " value"; + message = message + "but the getter was called to get a " + getNameOfType(argType) + " value"; return message; } @@ -630,7 +630,7 @@ void AlgorithmInfo::set(Algorithm* algo, const char* parameter, int argType, con if ( !( p->type == Param::INT || p->type == Param::REAL || p->type == Param::BOOLEAN || p->type == Param::UNSIGNED_INT || p->type == Param::UINT64 || p->type == Param::FLOAT || argType == Param::UCHAR) ) { - std::string message = getErrorMessageForWrongArgumentInSetter(algo->name(), parameter, p->type, argType); + String message = getErrorMessageForWrongArgumentInSetter(algo->name(), parameter, p->type, argType); CV_Error(CV_StsBadArg, message); } @@ -790,21 +790,21 @@ void AlgorithmInfo::set(Algorithm* algo, const char* parameter, int argType, con { if( p->type != Param::STRING ) { - std::string message = getErrorMessageForWrongArgumentInSetter(algo->name(), parameter, p->type, argType); + String message = getErrorMessageForWrongArgumentInSetter(algo->name(), parameter, p->type, argType); CV_Error(CV_StsBadArg, message); } - const std::string& val = *(const std::string*)value; + const String& val = *(const String*)value; if( p->setter ) (algo->*f.set_string)(val); else - *(std::string*)((uchar*)algo + p->offset) = val; + *(String*)((uchar*)algo + p->offset) = val; } else if( argType == Param::MAT ) { if( p->type != Param::MAT ) { - std::string message = getErrorMessageForWrongArgumentInSetter(algo->name(), parameter, p->type, argType); + String message = getErrorMessageForWrongArgumentInSetter(algo->name(), parameter, p->type, argType); CV_Error(CV_StsBadArg, message); } @@ -818,7 +818,7 @@ void AlgorithmInfo::set(Algorithm* algo, const char* parameter, int argType, con { if( p->type != Param::MAT_VECTOR ) { - std::string message = getErrorMessageForWrongArgumentInSetter(algo->name(), parameter, p->type, argType); + String message = getErrorMessageForWrongArgumentInSetter(algo->name(), parameter, p->type, argType); CV_Error(CV_StsBadArg, message); } @@ -832,7 +832,7 @@ void AlgorithmInfo::set(Algorithm* algo, const char* parameter, int argType, con { if( p->type != Param::ALGORITHM ) { - std::string message = getErrorMessageForWrongArgumentInSetter(algo->name(), parameter, p->type, argType); + String message = getErrorMessageForWrongArgumentInSetter(algo->name(), parameter, p->type, argType); CV_Error(CV_StsBadArg, message); } @@ -862,7 +862,7 @@ void AlgorithmInfo::get(const Algorithm* algo, const char* parameter, int argTyp { if (!( argType == Param::INT || argType == Param::REAL || argType == Param::FLOAT || argType == Param::UNSIGNED_INT || argType == Param::UINT64 || argType == Param::UCHAR)) { - std::string message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); + String message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); CV_Error(CV_StsBadArg, message); } int val = p->getter ? (algo->*f.get_int)() : *(int*)((uchar*)algo + p->offset); @@ -887,7 +887,7 @@ void AlgorithmInfo::get(const Algorithm* algo, const char* parameter, int argTyp { if (!( argType == Param::INT || argType == Param::BOOLEAN || argType == Param::REAL || argType == Param::FLOAT || argType == Param::UNSIGNED_INT || argType == Param::UINT64 || argType == Param::UCHAR)) { - std::string message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); + String message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); CV_Error(CV_StsBadArg, message); } bool val = p->getter ? (algo->*f.get_bool)() : *(bool*)((uchar*)algo + p->offset); @@ -913,7 +913,7 @@ void AlgorithmInfo::get(const Algorithm* algo, const char* parameter, int argTyp { if(!( argType == Param::REAL || argType == Param::FLOAT)) { - std::string message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); + String message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); CV_Error(CV_StsBadArg, message); } double val = p->getter ? (algo->*f.get_double)() : *(double*)((uchar*)algo + p->offset); @@ -929,7 +929,7 @@ void AlgorithmInfo::get(const Algorithm* algo, const char* parameter, int argTyp { if(!( argType == Param::REAL || argType == Param::FLOAT)) { - std::string message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); + String message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); CV_Error(CV_StsBadArg, message); } float val = p->getter ? (algo->*f.get_float)() : *(float*)((uchar*)algo + p->offset); @@ -945,7 +945,7 @@ void AlgorithmInfo::get(const Algorithm* algo, const char* parameter, int argTyp { if (!( argType == Param::INT || argType == Param::REAL || argType == Param::FLOAT || argType == Param::UNSIGNED_INT || argType == Param::UINT64 || argType == Param::UCHAR)) { - std::string message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); + String message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); CV_Error(CV_StsBadArg, message); } unsigned int val = p->getter ? (algo->*f.get_uint)() : *(unsigned int*)((uchar*)algo + p->offset); @@ -969,7 +969,7 @@ void AlgorithmInfo::get(const Algorithm* algo, const char* parameter, int argTyp { if (!( argType == Param::INT || argType == Param::REAL || argType == Param::FLOAT || argType == Param::UNSIGNED_INT || argType == Param::UINT64 || argType == Param::UCHAR)) { - std::string message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); + String message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); CV_Error(CV_StsBadArg, message); } uint64 val = p->getter ? (algo->*f.get_uint64)() : *(uint64*)((uchar*)algo + p->offset); @@ -993,7 +993,7 @@ void AlgorithmInfo::get(const Algorithm* algo, const char* parameter, int argTyp { if (!( argType == Param::INT || argType == Param::REAL || argType == Param::FLOAT || argType == Param::UNSIGNED_INT || argType == Param::UINT64 || argType == Param::UCHAR)) { - std::string message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); + String message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); CV_Error(CV_StsBadArg, message); } uchar val = p->getter ? (algo->*f.get_uchar)() : *(uchar*)((uchar*)algo + p->offset); @@ -1021,18 +1021,18 @@ void AlgorithmInfo::get(const Algorithm* algo, const char* parameter, int argTyp { if( p->type != Param::STRING ) { - std::string message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); + String message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); CV_Error(CV_StsBadArg, message); } - *(std::string*)value = p->getter ? (algo->*f.get_string)() : - *(std::string*)((uchar*)algo + p->offset); + *(String*)value = p->getter ? (algo->*f.get_string)() : + *(String*)((uchar*)algo + p->offset); } else if( argType == Param::MAT ) { if( p->type != Param::MAT ) { - std::string message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); + String message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); CV_Error(CV_StsBadArg, message); } @@ -1043,7 +1043,7 @@ void AlgorithmInfo::get(const Algorithm* algo, const char* parameter, int argTyp { if( p->type != Param::MAT_VECTOR ) { - std::string message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); + String message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); CV_Error(CV_StsBadArg, message); } @@ -1054,7 +1054,7 @@ void AlgorithmInfo::get(const Algorithm* algo, const char* parameter, int argTyp { if( p->type != Param::ALGORITHM ) { - std::string message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); + String message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); CV_Error(CV_StsBadArg, message); } @@ -1063,7 +1063,7 @@ void AlgorithmInfo::get(const Algorithm* algo, const char* parameter, int argTyp } else { - std::string message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); + String message = getErrorMessageForWrongArgumentInGetter(algo->name(), parameter, p->type, argType); CV_Error(CV_StsBadArg, message); } } @@ -1078,7 +1078,7 @@ int AlgorithmInfo::paramType(const char* parameter) const } -std::string AlgorithmInfo::paramHelp(const char* parameter) const +String AlgorithmInfo::paramHelp(const char* parameter) const { const Param* p = findstr(data->params, parameter); if( !p ) @@ -1087,7 +1087,7 @@ std::string AlgorithmInfo::paramHelp(const char* parameter) const } -void AlgorithmInfo::getParams(std::vector& names) const +void AlgorithmInfo::getParams(std::vector& names) const { data->params.get_keys(names); } @@ -1096,7 +1096,7 @@ void AlgorithmInfo::getParams(std::vector& names) const void AlgorithmInfo::addParam_(Algorithm& algo, const char* parameter, int argType, void* value, bool readOnly, Algorithm::Getter getter, Algorithm::Setter setter, - const std::string& help) + const String& help) { CV_Assert( argType == Param::INT || argType == Param::BOOLEAN || argType == Param::REAL || argType == Param::STRING || @@ -1104,7 +1104,7 @@ void AlgorithmInfo::addParam_(Algorithm& algo, const char* parameter, int argTyp argType == Param::ALGORITHM || argType == Param::FLOAT || argType == Param::UNSIGNED_INT || argType == Param::UINT64 || argType == Param::UCHAR); - data->params.add(std::string(parameter), Param(argType, readOnly, + data->params.add(String(parameter), Param(argType, readOnly, (int)((size_t)value - (size_t)(void*)&algo), getter, setter, help)); } @@ -1114,7 +1114,7 @@ void AlgorithmInfo::addParam(Algorithm& algo, const char* parameter, int& value, bool readOnly, int (Algorithm::*getter)(), void (Algorithm::*setter)(int), - const std::string& help) + const String& help) { addParam_(algo, parameter, ParamType::type, &value, readOnly, (Algorithm::Getter)getter, (Algorithm::Setter)setter, help); @@ -1124,7 +1124,7 @@ void AlgorithmInfo::addParam(Algorithm& algo, const char* parameter, bool& value, bool readOnly, int (Algorithm::*getter)(), void (Algorithm::*setter)(int), - const std::string& help) + const String& help) { addParam_(algo, parameter, ParamType::type, &value, readOnly, (Algorithm::Getter)getter, (Algorithm::Setter)setter, help); @@ -1134,19 +1134,19 @@ void AlgorithmInfo::addParam(Algorithm& algo, const char* parameter, double& value, bool readOnly, double (Algorithm::*getter)(), void (Algorithm::*setter)(double), - const std::string& help) + const String& help) { addParam_(algo, parameter, ParamType::type, &value, readOnly, (Algorithm::Getter)getter, (Algorithm::Setter)setter, help); } void AlgorithmInfo::addParam(Algorithm& algo, const char* parameter, - std::string& value, bool readOnly, - std::string (Algorithm::*getter)(), - void (Algorithm::*setter)(const std::string&), - const std::string& help) + String& value, bool readOnly, + String (Algorithm::*getter)(), + void (Algorithm::*setter)(const String&), + const String& help) { - addParam_(algo, parameter, ParamType::type, &value, readOnly, + addParam_(algo, parameter, ParamType::type, &value, readOnly, (Algorithm::Getter)getter, (Algorithm::Setter)setter, help); } @@ -1154,7 +1154,7 @@ void AlgorithmInfo::addParam(Algorithm& algo, const char* parameter, Mat& value, bool readOnly, Mat (Algorithm::*getter)(), void (Algorithm::*setter)(const Mat&), - const std::string& help) + const String& help) { addParam_(algo, parameter, ParamType::type, &value, readOnly, (Algorithm::Getter)getter, (Algorithm::Setter)setter, help); @@ -1164,7 +1164,7 @@ void AlgorithmInfo::addParam(Algorithm& algo, const char* parameter, std::vector& value, bool readOnly, std::vector (Algorithm::*getter)(), void (Algorithm::*setter)(const std::vector&), - const std::string& help) + const String& help) { addParam_(algo, parameter, ParamType >::type, &value, readOnly, (Algorithm::Getter)getter, (Algorithm::Setter)setter, help); @@ -1174,7 +1174,7 @@ void AlgorithmInfo::addParam(Algorithm& algo, const char* parameter, Ptr& value, bool readOnly, Ptr (Algorithm::*getter)(), void (Algorithm::*setter)(const Ptr&), - const std::string& help) + const String& help) { addParam_(algo, parameter, ParamType::type, &value, readOnly, (Algorithm::Getter)getter, (Algorithm::Setter)setter, help); @@ -1184,7 +1184,7 @@ void AlgorithmInfo::addParam(Algorithm& algo, const char* parameter, float& value, bool readOnly, float (Algorithm::*getter)(), void (Algorithm::*setter)(float), - const std::string& help) + const String& help) { addParam_(algo, parameter, ParamType::type, &value, readOnly, (Algorithm::Getter)getter, (Algorithm::Setter)setter, help); @@ -1194,7 +1194,7 @@ void AlgorithmInfo::addParam(Algorithm& algo, const char* parameter, unsigned int& value, bool readOnly, unsigned int (Algorithm::*getter)(), void (Algorithm::*setter)(unsigned int), - const std::string& help) + const String& help) { addParam_(algo, parameter, ParamType::type, &value, readOnly, (Algorithm::Getter)getter, (Algorithm::Setter)setter, help); @@ -1204,7 +1204,7 @@ void AlgorithmInfo::addParam(Algorithm& algo, const char* parameter, uint64& value, bool readOnly, uint64 (Algorithm::*getter)(), void (Algorithm::*setter)(uint64), - const std::string& help) + const String& help) { addParam_(algo, parameter, ParamType::type, &value, readOnly, (Algorithm::Getter)getter, (Algorithm::Setter)setter, help); @@ -1214,7 +1214,7 @@ void AlgorithmInfo::addParam(Algorithm& algo, const char* parameter, uchar& value, bool readOnly, uchar (Algorithm::*getter)(), void (Algorithm::*setter)(uchar), - const std::string& help) + const String& help) { addParam_(algo, parameter, ParamType::type, &value, readOnly, (Algorithm::Getter)getter, (Algorithm::Setter)setter, help); diff --git a/modules/core/src/alloc.cpp b/modules/core/src/alloc.cpp index 1944ed17de..8e218738b3 100644 --- a/modules/core/src/alloc.cpp +++ b/modules/core/src/alloc.cpp @@ -94,9 +94,20 @@ void fastFree(void* ptr) #define STAT(stmt) #ifdef WIN32 +#if (_WIN32_WINNT >= 0x0602) +#include +#endif + struct CriticalSection { - CriticalSection() { InitializeCriticalSection(&cs); } + CriticalSection() + { +#if (_WIN32_WINNT >= 0x0600) + InitializeCriticalSectionEx(&cs, 1000, 0); +#else + InitializeCriticalSection(&cs); +#endif + } ~CriticalSection() { DeleteCriticalSection(&cs); } void lock() { EnterCriticalSection(&cs); } void unlock() { LeaveCriticalSection(&cs); } @@ -683,11 +694,6 @@ void fastFree( void* ptr ) } -CV_IMPL void cvSetMemoryManager( CvAllocFunc, CvFreeFunc, void * ) -{ - CV_Error( -1, "Custom memory allocator is not supported" ); -} - CV_IMPL void* cvAlloc( size_t size ) { return cv::fastMalloc( size ); diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index b76dd7fd40..313d06d881 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -1131,23 +1131,33 @@ static void binary_op(InputArray _src1, InputArray _src2, OutputArray _dst, } } -static BinaryFunc maxTab[] = +static BinaryFunc* getMaxTab() { - (BinaryFunc)GET_OPTIMIZED(max8u), (BinaryFunc)GET_OPTIMIZED(max8s), - (BinaryFunc)GET_OPTIMIZED(max16u), (BinaryFunc)GET_OPTIMIZED(max16s), - (BinaryFunc)GET_OPTIMIZED(max32s), - (BinaryFunc)GET_OPTIMIZED(max32f), (BinaryFunc)max64f, - 0 -}; + static BinaryFunc maxTab[] = + { + (BinaryFunc)GET_OPTIMIZED(max8u), (BinaryFunc)GET_OPTIMIZED(max8s), + (BinaryFunc)GET_OPTIMIZED(max16u), (BinaryFunc)GET_OPTIMIZED(max16s), + (BinaryFunc)GET_OPTIMIZED(max32s), + (BinaryFunc)GET_OPTIMIZED(max32f), (BinaryFunc)max64f, + 0 + }; -static BinaryFunc minTab[] = + return maxTab; +} + +static BinaryFunc* getMinTab() { - (BinaryFunc)GET_OPTIMIZED(min8u), (BinaryFunc)GET_OPTIMIZED(min8s), - (BinaryFunc)GET_OPTIMIZED(min16u), (BinaryFunc)GET_OPTIMIZED(min16s), - (BinaryFunc)GET_OPTIMIZED(min32s), - (BinaryFunc)GET_OPTIMIZED(min32f), (BinaryFunc)min64f, - 0 -}; + static BinaryFunc minTab[] = + { + (BinaryFunc)GET_OPTIMIZED(min8u), (BinaryFunc)GET_OPTIMIZED(min8s), + (BinaryFunc)GET_OPTIMIZED(min16u), (BinaryFunc)GET_OPTIMIZED(min16s), + (BinaryFunc)GET_OPTIMIZED(min32s), + (BinaryFunc)GET_OPTIMIZED(min32f), (BinaryFunc)min64f, + 0 + }; + + return minTab; +} } @@ -1177,37 +1187,26 @@ void cv::bitwise_not(InputArray a, OutputArray c, InputArray mask) void cv::max( InputArray src1, InputArray src2, OutputArray dst ) { - binary_op(src1, src2, dst, noArray(), maxTab, false ); + binary_op(src1, src2, dst, noArray(), getMaxTab(), false ); } void cv::min( InputArray src1, InputArray src2, OutputArray dst ) { - binary_op(src1, src2, dst, noArray(), minTab, false ); + binary_op(src1, src2, dst, noArray(), getMinTab(), false ); } void cv::max(const Mat& src1, const Mat& src2, Mat& dst) { OutputArray _dst(dst); - binary_op(src1, src2, _dst, noArray(), maxTab, false ); + binary_op(src1, src2, _dst, noArray(), getMaxTab(), false ); } void cv::min(const Mat& src1, const Mat& src2, Mat& dst) { OutputArray _dst(dst); - binary_op(src1, src2, _dst, noArray(), minTab, false ); + binary_op(src1, src2, _dst, noArray(), getMinTab(), false ); } -void cv::max(const Mat& src1, double src2, Mat& dst) -{ - OutputArray _dst(dst); - binary_op(src1, src2, _dst, noArray(), maxTab, false ); -} - -void cv::min(const Mat& src1, double src2, Mat& dst) -{ - OutputArray _dst(dst); - binary_op(src1, src2, _dst, noArray(), minTab, false ); -} /****************************************************************************************\ * add/subtract * @@ -1493,39 +1492,54 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, } } -static BinaryFunc addTab[] = +static BinaryFunc* getAddTab() { - (BinaryFunc)GET_OPTIMIZED(add8u), (BinaryFunc)GET_OPTIMIZED(add8s), - (BinaryFunc)GET_OPTIMIZED(add16u), (BinaryFunc)GET_OPTIMIZED(add16s), - (BinaryFunc)GET_OPTIMIZED(add32s), - (BinaryFunc)GET_OPTIMIZED(add32f), (BinaryFunc)add64f, - 0 -}; + static BinaryFunc addTab[] = + { + (BinaryFunc)GET_OPTIMIZED(add8u), (BinaryFunc)GET_OPTIMIZED(add8s), + (BinaryFunc)GET_OPTIMIZED(add16u), (BinaryFunc)GET_OPTIMIZED(add16s), + (BinaryFunc)GET_OPTIMIZED(add32s), + (BinaryFunc)GET_OPTIMIZED(add32f), (BinaryFunc)add64f, + 0 + }; -static BinaryFunc subTab[] = -{ - (BinaryFunc)GET_OPTIMIZED(sub8u), (BinaryFunc)GET_OPTIMIZED(sub8s), - (BinaryFunc)GET_OPTIMIZED(sub16u), (BinaryFunc)GET_OPTIMIZED(sub16s), - (BinaryFunc)GET_OPTIMIZED(sub32s), - (BinaryFunc)GET_OPTIMIZED(sub32f), (BinaryFunc)sub64f, - 0 -}; + return addTab; +} -static BinaryFunc absdiffTab[] = +static BinaryFunc* getSubTab() { - (BinaryFunc)GET_OPTIMIZED(absdiff8u), (BinaryFunc)GET_OPTIMIZED(absdiff8s), - (BinaryFunc)GET_OPTIMIZED(absdiff16u), (BinaryFunc)GET_OPTIMIZED(absdiff16s), - (BinaryFunc)GET_OPTIMIZED(absdiff32s), - (BinaryFunc)GET_OPTIMIZED(absdiff32f), (BinaryFunc)absdiff64f, - 0 -}; + static BinaryFunc subTab[] = + { + (BinaryFunc)GET_OPTIMIZED(sub8u), (BinaryFunc)GET_OPTIMIZED(sub8s), + (BinaryFunc)GET_OPTIMIZED(sub16u), (BinaryFunc)GET_OPTIMIZED(sub16s), + (BinaryFunc)GET_OPTIMIZED(sub32s), + (BinaryFunc)GET_OPTIMIZED(sub32f), (BinaryFunc)sub64f, + 0 + }; + + return subTab; +} + +static BinaryFunc* getAbsDiffTab() +{ + static BinaryFunc absDiffTab[] = + { + (BinaryFunc)GET_OPTIMIZED(absdiff8u), (BinaryFunc)GET_OPTIMIZED(absdiff8s), + (BinaryFunc)GET_OPTIMIZED(absdiff16u), (BinaryFunc)GET_OPTIMIZED(absdiff16s), + (BinaryFunc)GET_OPTIMIZED(absdiff32s), + (BinaryFunc)GET_OPTIMIZED(absdiff32f), (BinaryFunc)absdiff64f, + 0 + }; + + return absDiffTab; +} } void cv::add( InputArray src1, InputArray src2, OutputArray dst, InputArray mask, int dtype ) { - arithm_op(src1, src2, dst, mask, dtype, addTab ); + arithm_op(src1, src2, dst, mask, dtype, getAddTab() ); } void cv::subtract( InputArray src1, InputArray src2, OutputArray dst, @@ -1560,12 +1574,12 @@ void cv::subtract( InputArray src1, InputArray src2, OutputArray dst, } } #endif - arithm_op(src1, src2, dst, mask, dtype, subTab ); + arithm_op(src1, src2, dst, mask, dtype, getSubTab() ); } void cv::absdiff( InputArray src1, InputArray src2, OutputArray dst ) { - arithm_op(src1, src2, dst, noArray(), -1, absdiffTab); + arithm_op(src1, src2, dst, noArray(), -1, getAbsDiffTab()); } /****************************************************************************************\ @@ -1855,46 +1869,60 @@ static void recip64f( const double* src1, size_t step1, const double* src2, size } -static BinaryFunc mulTab[] = +static BinaryFunc* getMulTab() { - (BinaryFunc)mul8u, (BinaryFunc)mul8s, (BinaryFunc)mul16u, - (BinaryFunc)mul16s, (BinaryFunc)mul32s, (BinaryFunc)mul32f, - (BinaryFunc)mul64f, 0 -}; + static BinaryFunc mulTab[] = + { + (BinaryFunc)mul8u, (BinaryFunc)mul8s, (BinaryFunc)mul16u, + (BinaryFunc)mul16s, (BinaryFunc)mul32s, (BinaryFunc)mul32f, + (BinaryFunc)mul64f, 0 + }; -static BinaryFunc divTab[] = + return mulTab; +} + +static BinaryFunc* getDivTab() { - (BinaryFunc)div8u, (BinaryFunc)div8s, (BinaryFunc)div16u, - (BinaryFunc)div16s, (BinaryFunc)div32s, (BinaryFunc)div32f, - (BinaryFunc)div64f, 0 -}; + static BinaryFunc divTab[] = + { + (BinaryFunc)div8u, (BinaryFunc)div8s, (BinaryFunc)div16u, + (BinaryFunc)div16s, (BinaryFunc)div32s, (BinaryFunc)div32f, + (BinaryFunc)div64f, 0 + }; -static BinaryFunc recipTab[] = + return divTab; +} + +static BinaryFunc* getRecipTab() { - (BinaryFunc)recip8u, (BinaryFunc)recip8s, (BinaryFunc)recip16u, - (BinaryFunc)recip16s, (BinaryFunc)recip32s, (BinaryFunc)recip32f, - (BinaryFunc)recip64f, 0 -}; + static BinaryFunc recipTab[] = + { + (BinaryFunc)recip8u, (BinaryFunc)recip8s, (BinaryFunc)recip16u, + (BinaryFunc)recip16s, (BinaryFunc)recip32s, (BinaryFunc)recip32f, + (BinaryFunc)recip64f, 0 + }; + return recipTab; +} } void cv::multiply(InputArray src1, InputArray src2, OutputArray dst, double scale, int dtype) { - arithm_op(src1, src2, dst, noArray(), dtype, mulTab, true, &scale); + arithm_op(src1, src2, dst, noArray(), dtype, getMulTab(), true, &scale); } void cv::divide(InputArray src1, InputArray src2, OutputArray dst, double scale, int dtype) { - arithm_op(src1, src2, dst, noArray(), dtype, divTab, true, &scale); + arithm_op(src1, src2, dst, noArray(), dtype, getDivTab(), true, &scale); } void cv::divide(double scale, InputArray src2, OutputArray dst, int dtype) { - arithm_op(src2, src2, dst, noArray(), dtype, recipTab, true, &scale); + arithm_op(src2, src2, dst, noArray(), dtype, getRecipTab(), true, &scale); } /****************************************************************************************\ @@ -2037,12 +2065,17 @@ static void addWeighted64f( const double* src1, size_t step1, const double* src2 addWeighted_(src1, step1, src2, step2, dst, step, sz, scalars); } -static BinaryFunc addWeightedTab[] = +static BinaryFunc* getAddWeightedTab() { - (BinaryFunc)GET_OPTIMIZED(addWeighted8u), (BinaryFunc)GET_OPTIMIZED(addWeighted8s), (BinaryFunc)GET_OPTIMIZED(addWeighted16u), - (BinaryFunc)GET_OPTIMIZED(addWeighted16s), (BinaryFunc)GET_OPTIMIZED(addWeighted32s), (BinaryFunc)addWeighted32f, - (BinaryFunc)addWeighted64f, 0 -}; + static BinaryFunc addWeightedTab[] = + { + (BinaryFunc)GET_OPTIMIZED(addWeighted8u), (BinaryFunc)GET_OPTIMIZED(addWeighted8s), (BinaryFunc)GET_OPTIMIZED(addWeighted16u), + (BinaryFunc)GET_OPTIMIZED(addWeighted16s), (BinaryFunc)GET_OPTIMIZED(addWeighted32s), (BinaryFunc)addWeighted32f, + (BinaryFunc)addWeighted64f, 0 + }; + + return addWeightedTab; +} } @@ -2050,7 +2083,7 @@ void cv::addWeighted( InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype ) { double scalars[] = {alpha, beta, gamma}; - arithm_op(src1, src2, dst, noArray(), dtype, addWeightedTab, true, scalars); + arithm_op(src1, src2, dst, noArray(), dtype, getAddWeightedTab(), true, scalars); } @@ -2120,10 +2153,30 @@ cmp_(const T* src1, size_t step1, const T* src2, size_t step2, } } +#if ARITHM_USE_IPP +inline static IppCmpOp convert_cmp(int _cmpop) +{ + return _cmpop == CMP_EQ ? ippCmpEq : + _cmpop == CMP_GT ? ippCmpGreater : + _cmpop == CMP_GE ? ippCmpGreaterEq : + _cmpop == CMP_LT ? ippCmpLess : + _cmpop == CMP_LE ? ippCmpLessEq : + (IppCmpOp)-1; +} +#endif static void cmp8u(const uchar* src1, size_t step1, const uchar* src2, size_t step2, uchar* dst, size_t step, Size size, void* _cmpop) { +#if ARITHM_USE_IPP + IppCmpOp op = convert_cmp(*(int *)_cmpop); + if( op >= 0 ) + { + fixSteps(size, sizeof(dst[0]), step1, step2, step); + if( ippiCompare_8u_C1R(src1, (int)step1, src2, (int)step2, dst, (int)step, (IppiSize&)size, op) >= 0 ) + return; + } +#endif //vz optimized cmp_(src1, step1, src2, step2, dst, step, size, *(int*)_cmpop); int code = *(int*)_cmpop; step1 /= sizeof(src1[0]); @@ -2198,12 +2251,30 @@ static void cmp8s(const schar* src1, size_t step1, const schar* src2, size_t ste static void cmp16u(const ushort* src1, size_t step1, const ushort* src2, size_t step2, uchar* dst, size_t step, Size size, void* _cmpop) { +#if ARITHM_USE_IPP + IppCmpOp op = convert_cmp(*(int *)_cmpop); + if( op >= 0 ) + { + fixSteps(size, sizeof(dst[0]), step1, step2, step); + if( ippiCompare_16u_C1R(src1, (int)step1, src2, (int)step2, dst, (int)step, (IppiSize&)size, op) >= 0 ) + return; + } +#endif cmp_(src1, step1, src2, step2, dst, step, size, *(int*)_cmpop); } static void cmp16s(const short* src1, size_t step1, const short* src2, size_t step2, uchar* dst, size_t step, Size size, void* _cmpop) { +#if ARITHM_USE_IPP + IppCmpOp op = convert_cmp(*(int *)_cmpop); + if( op > 0 ) + { + fixSteps(size, sizeof(dst[0]), step1, step2, step); + if( ippiCompare_16s_C1R(src1, (int)step1, src2, (int)step2, dst, (int)step, (IppiSize&)size, op) >= 0 ) + return; + } +#endif //vz optimized cmp_(src1, step1, src2, step2, dst, step, size, *(int*)_cmpop); int code = *(int*)_cmpop; @@ -2301,6 +2372,15 @@ static void cmp32s(const int* src1, size_t step1, const int* src2, size_t step2, static void cmp32f(const float* src1, size_t step1, const float* src2, size_t step2, uchar* dst, size_t step, Size size, void* _cmpop) { +#if ARITHM_USE_IPP + IppCmpOp op = convert_cmp(*(int *)_cmpop); + if( op >= 0 ) + { + fixSteps(size, sizeof(dst[0]), step1, step2, step); + if( ippiCompare_32f_C1R(src1, (int)step1, src2, (int)step2, dst, (int)step, (IppiSize&)size, op) >= 0 ) + return; + } +#endif cmp_(src1, step1, src2, step2, dst, step, size, *(int*)_cmpop); } @@ -2310,15 +2390,19 @@ static void cmp64f(const double* src1, size_t step1, const double* src2, size_t cmp_(src1, step1, src2, step2, dst, step, size, *(int*)_cmpop); } -static BinaryFunc cmpTab[] = +static BinaryFunc getCmpFunc(int depth) { - (BinaryFunc)GET_OPTIMIZED(cmp8u), (BinaryFunc)GET_OPTIMIZED(cmp8s), - (BinaryFunc)GET_OPTIMIZED(cmp16u), (BinaryFunc)GET_OPTIMIZED(cmp16s), - (BinaryFunc)GET_OPTIMIZED(cmp32s), - (BinaryFunc)GET_OPTIMIZED(cmp32f), (BinaryFunc)cmp64f, - 0 -}; + static BinaryFunc cmpTab[] = + { + (BinaryFunc)GET_OPTIMIZED(cmp8u), (BinaryFunc)GET_OPTIMIZED(cmp8s), + (BinaryFunc)GET_OPTIMIZED(cmp16u), (BinaryFunc)GET_OPTIMIZED(cmp16s), + (BinaryFunc)GET_OPTIMIZED(cmp32s), + (BinaryFunc)GET_OPTIMIZED(cmp32f), (BinaryFunc)cmp64f, + 0 + }; + return cmpTab[depth]; +} static double getMinVal(int depth) { @@ -2348,7 +2432,7 @@ void cv::compare(InputArray _src1, InputArray _src2, OutputArray _dst, int op) _dst.create(src1.size(), CV_8UC(cn)); Mat dst = _dst.getMat(); Size sz = getContinuousSize(src1, src2, dst, src1.channels()); - cmpTab[src1.depth()](src1.data, src1.step, src2.data, src2.step, dst.data, dst.step, sz, &op); + getCmpFunc(src1.depth())(src1.data, src1.step, src2.data, src2.step, dst.data, dst.step, sz, &op); return; } @@ -2380,7 +2464,7 @@ void cv::compare(InputArray _src1, InputArray _src2, OutputArray _dst, int op) size_t esz = src1.elemSize(); size_t blocksize0 = (size_t)(BLOCK_SIZE + esz-1)/esz; - BinaryFunc func = cmpTab[depth1]; + BinaryFunc func = getCmpFunc(depth1); if( !haveScalar ) { @@ -2557,12 +2641,17 @@ static void inRangeReduce(const uchar* src, uchar* dst, size_t len, int cn) typedef void (*InRangeFunc)( const uchar* src1, size_t step1, const uchar* src2, size_t step2, const uchar* src3, size_t step3, uchar* dst, size_t step, Size sz ); -static InRangeFunc inRangeTab[] = +static InRangeFunc getInRangeFunc(int depth) { - (InRangeFunc)GET_OPTIMIZED(inRange8u), (InRangeFunc)GET_OPTIMIZED(inRange8s), (InRangeFunc)GET_OPTIMIZED(inRange16u), - (InRangeFunc)GET_OPTIMIZED(inRange16s), (InRangeFunc)GET_OPTIMIZED(inRange32s), (InRangeFunc)GET_OPTIMIZED(inRange32f), - (InRangeFunc)inRange64f, 0 -}; + static InRangeFunc inRangeTab[] = + { + (InRangeFunc)GET_OPTIMIZED(inRange8u), (InRangeFunc)GET_OPTIMIZED(inRange8s), (InRangeFunc)GET_OPTIMIZED(inRange16u), + (InRangeFunc)GET_OPTIMIZED(inRange16s), (InRangeFunc)GET_OPTIMIZED(inRange32s), (InRangeFunc)GET_OPTIMIZED(inRange32f), + (InRangeFunc)inRange64f, 0 + }; + + return inRangeTab[depth]; +} } @@ -2601,7 +2690,7 @@ void cv::inRange(InputArray _src, InputArray _lowerb, _dst.create(src.dims, src.size, CV_8U); Mat dst = _dst.getMat(); - InRangeFunc func = inRangeTab[depth]; + InRangeFunc func = getInRangeFunc(depth); const Mat* arrays_sc[] = { &src, &dst, 0 }; const Mat* arrays_nosc[] = { &src, &dst, &lb, &ub, 0 }; diff --git a/modules/core/src/array.cpp b/modules/core/src/array.cpp index 9c024293eb..2ad7b1216c 100644 --- a/modules/core/src/array.cpp +++ b/modules/core/src/array.cpp @@ -48,6 +48,12 @@ #include "precomp.hpp" +#define CV_ORIGIN_TL 0 +#define CV_ORIGIN_BL 1 + +/* default image row align (in bytes) */ +#define CV_DEFAULT_IMAGE_ROW_ALIGN 4 + static struct { @@ -305,7 +311,8 @@ cvCloneMatND( const CvMatND* src ) if( src->data.ptr ) { cvCreateData( dst ); - cv::Mat _src(src), _dst(dst); + cv::Mat _src = cv::cvarrToMat(src); + cv::Mat _dst = cv::cvarrToMat(dst); uchar* data0 = dst->data.ptr; _src.copyTo(_dst); CV_Assert(_dst.data == data0); @@ -1210,7 +1217,7 @@ cvGetDimSize( const CvArr* arr, int index ) CV_IMPL CvSize cvGetSize( const CvArr* arr ) { - CvSize size = { 0, 0 }; + CvSize size; if( CV_IS_MAT_HDR_Z( arr )) { @@ -1463,28 +1470,28 @@ cvScalarToRawData( const CvScalar* scalar, void* data, int type, int extend_to_1 while( cn-- ) { int t = cvRound( scalar->val[cn] ); - ((uchar*)data)[cn] = CV_CAST_8U(t); + ((uchar*)data)[cn] = cv::saturate_cast(t); } break; case CV_8SC1: while( cn-- ) { int t = cvRound( scalar->val[cn] ); - ((char*)data)[cn] = CV_CAST_8S(t); + ((char*)data)[cn] = cv::saturate_cast(t); } break; case CV_16UC1: while( cn-- ) { int t = cvRound( scalar->val[cn] ); - ((ushort*)data)[cn] = CV_CAST_16U(t); + ((ushort*)data)[cn] = cv::saturate_cast(t); } break; case CV_16SC1: while( cn-- ) { int t = cvRound( scalar->val[cn] ); - ((short*)data)[cn] = CV_CAST_16S(t); + ((short*)data)[cn] = cv::saturate_cast(t); } break; case CV_32SC1: @@ -1601,19 +1608,19 @@ static void icvSetReal( double value, const void* data, int type ) switch( type ) { case CV_8U: - *(uchar*)data = CV_CAST_8U(ivalue); + *(uchar*)data = cv::saturate_cast(ivalue); break; case CV_8S: - *(char*)data = CV_CAST_8S(ivalue); + *(schar*)data = cv::saturate_cast(ivalue); break; case CV_16U: - *(ushort*)data = CV_CAST_16U(ivalue); + *(ushort*)data = cv::saturate_cast(ivalue); break; case CV_16S: - *(short*)data = CV_CAST_16S(ivalue); + *(short*)data = cv::saturate_cast(ivalue); break; case CV_32S: - *(int*)data = CV_CAST_32S(ivalue); + *(int*)data = cv::saturate_cast(ivalue); break; } } @@ -1910,7 +1917,7 @@ cvPtrND( const CvArr* arr, const int* idx, int* _type, CV_IMPL CvScalar cvGet1D( const CvArr* arr, int idx ) { - CvScalar scalar = {{0,0,0,0}}; + CvScalar scalar(0); int type = 0; uchar* ptr; @@ -1945,7 +1952,7 @@ cvGet1D( const CvArr* arr, int idx ) CV_IMPL CvScalar cvGet2D( const CvArr* arr, int y, int x ) { - CvScalar scalar = {{0,0,0,0}}; + CvScalar scalar(0); int type = 0; uchar* ptr; @@ -1979,7 +1986,7 @@ cvGet2D( const CvArr* arr, int y, int x ) CV_IMPL CvScalar cvGet3D( const CvArr* arr, int z, int y, int x ) { - CvScalar scalar = {{0,0,0,0}}; + CvScalar scalar(0); int type = 0; uchar* ptr; @@ -2001,7 +2008,7 @@ cvGet3D( const CvArr* arr, int z, int y, int x ) CV_IMPL CvScalar cvGetND( const CvArr* arr, const int* idx ) { - CvScalar scalar = {{0,0,0,0}}; + CvScalar scalar(0); int type = 0; uchar* ptr; @@ -3052,7 +3059,7 @@ cvResetImageROI( IplImage* image ) CV_IMPL CvRect cvGetImageROI( const IplImage* img ) { - CvRect rect = { 0, 0, 0, 0 }; + CvRect rect; if( !img ) CV_Error( CV_StsNullPtr, "Null pointer to image" ); @@ -3183,22 +3190,22 @@ cvCheckTermCriteria( CvTermCriteria criteria, double default_eps, namespace cv { -template<> void Ptr::delete_obj() +template<> void DefaultDeleter::operator ()(CvMat* obj) const { cvReleaseMat(&obj); } -template<> void Ptr::delete_obj() +template<> void DefaultDeleter::operator ()(IplImage* obj) const { cvReleaseImage(&obj); } -template<> void Ptr::delete_obj() +template<> void DefaultDeleter::operator ()(CvMatND* obj) const { cvReleaseMatND(&obj); } -template<> void Ptr::delete_obj() +template<> void DefaultDeleter::operator ()(CvSparseMat* obj) const { cvReleaseSparseMat(&obj); } -template<> void Ptr::delete_obj() +template<> void DefaultDeleter::operator ()(CvMemStorage* obj) const { cvReleaseMemStorage(&obj); } -template<> void Ptr::delete_obj() +template<> void DefaultDeleter::operator ()(CvFileStorage* obj) const { cvReleaseFileStorage(&obj); } } diff --git a/modules/core/src/command_line_parser.cpp b/modules/core/src/command_line_parser.cpp index 1bffe5af77..b082faee62 100644 --- a/modules/core/src/command_line_parser.cpp +++ b/modules/core/src/command_line_parser.cpp @@ -1,7 +1,5 @@ - #include "precomp.hpp" - -#include +#include namespace cv { @@ -9,9 +7,9 @@ namespace cv struct CommandLineParserParams { public: - std::string help_message; - std::string def_value; - std::vector keys; + String help_message; + String def_value; + std::vector keys; int number; }; @@ -19,27 +17,27 @@ public: struct CommandLineParser::Impl { bool error; - std::string error_message; - std::string about_message; + String error_message; + String about_message; - std::string path_to_app; - std::string app_name; + String path_to_app; + String app_name; std::vector data; - std::vector split_range_string(const std::string& str, char fs, char ss) const; - std::vector split_string(const std::string& str, char symbol = ' ', bool create_empty_item = false) const; - std::string cat_string(const std::string& str) const; + 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 std::string& key, const std::string& value); - void apply_params(int i, std::string value); + void apply_params(const String& key, const String& value); + void apply_params(int i, String value); void sort_params(); int refcount; }; -static std::string get_type_name(int type) +static String get_type_name(int type) { if( type == Param::INT ) return "int"; @@ -56,9 +54,9 @@ static std::string get_type_name(int type) return "unknown"; } -static void from_str(const std::string& str, int type, void* dst) +static void from_str(const String& str, int type, void* dst) { - std::stringstream ss(str); + std::stringstream ss(str.c_str()); if( type == Param::INT ) ss >> *(int*)dst; else if( type == Param::UNSIGNED_INT ) @@ -70,20 +68,20 @@ static void from_str(const std::string& str, int type, void* dst) else if( type == Param::REAL ) ss >> *(double*)dst; else if( type == Param::STRING ) - *(std::string*)dst = str; + *(String*)dst = str; else throw cv::Exception(CV_StsBadArg, "unknown/unsupported parameter type", "", __FILE__, __LINE__); if (ss.fail()) { - std::string err_msg = "can not convert: [" + str + + String err_msg = "can not convert: [" + str + + "] to [" + get_type_name(type) + "]"; throw cv::Exception(CV_StsBadArg, err_msg, "", __FILE__, __LINE__); } } -void CommandLineParser::getByName(const std::string& name, bool space_delete, int type, void* dst) const +void CommandLineParser::getByName(const String& name, bool space_delete, int type, void* dst) const { try { @@ -93,7 +91,7 @@ void CommandLineParser::getByName(const std::string& name, bool space_delete, in { if (name.compare(impl->data[i].keys[j]) == 0) { - std::string v = impl->data[i].def_value; + String v = impl->data[i].def_value; if (space_delete) v = impl->cat_string(v); from_str(v, type, dst); @@ -102,12 +100,12 @@ void CommandLineParser::getByName(const std::string& name, bool space_delete, in } } impl->error = true; - impl->error_message += "Unknown parametes " + name + "\n"; + impl->error_message = impl->error_message + "Unknown parametes " + name + "\n"; } catch (std::exception& e) { impl->error = true; - impl->error_message += "Exception: " + std::string(e.what()) + "\n"; + impl->error_message = impl->error_message + "Exception: " + String(e.what()) + "\n"; } } @@ -120,66 +118,61 @@ void CommandLineParser::getByIndex(int index, bool space_delete, int type, void* { if (impl->data[i].number == index) { - std::string v = impl->data[i].def_value; + String v = impl->data[i].def_value; if (space_delete == true) v = impl->cat_string(v); from_str(v, type, dst); return; } } impl->error = true; - impl->error_message += "Unknown parametes #" + format("%d", index) + "\n"; + impl->error_message = impl->error_message + "Unknown parametes #" + format("%d", index) + "\n"; } catch(std::exception & e) { impl->error = true; - impl->error_message += "Exception: " + std::string(e.what()) + "\n"; + impl->error_message = impl->error_message + "Exception: " + String(e.what()) + "\n"; } } static bool cmp_params(const CommandLineParserParams & p1, const CommandLineParserParams & p2) { + if (p1.number < p2.number) + return true; + if (p1.number > p2.number) return false; - if (p1.number == -1 && p2.number == -1) - { - if (p1.keys[0].compare(p2.keys[0]) > 0) - { - return false; - } - } - - return true; + return p1.keys[0].compare(p2.keys[0]) < 0; } -CommandLineParser::CommandLineParser(int argc, const char* const argv[], const std::string& keys) +CommandLineParser::CommandLineParser(int argc, const char* const argv[], const String& keys) { impl = new Impl; impl->refcount = 1; // path to application - size_t pos_s = std::string(argv[0]).find_last_of("/\\"); - if (pos_s == std::string::npos) + size_t pos_s = String(argv[0]).find_last_of("/\\"); + if (pos_s == String::npos) { impl->path_to_app = ""; - impl->app_name = std::string(argv[0]); + impl->app_name = String(argv[0]); } else { - impl->path_to_app = std::string(argv[0]).substr(0, pos_s); - impl->app_name = std::string(argv[0]).substr(pos_s + 1, std::string(argv[0]).length() - pos_s); + impl->path_to_app = String(argv[0]).substr(0, pos_s); + impl->app_name = String(argv[0]).substr(pos_s + 1, String(argv[0]).length() - pos_s); } impl->error = false; impl->error_message = ""; // parse keys - std::vector k = impl->split_range_string(keys, '{', '}'); + std::vector k = impl->split_range_string(keys, '{', '}'); int jj = 0; for (size_t i = 0; i < k.size(); i++) { - std::vector l = impl->split_string(k[i], '|', true); + std::vector l = impl->split_string(k[i], '|', true); CommandLineParserParams p; p.keys = impl->split_string(l[0]); p.def_value = l[1]; @@ -206,11 +199,11 @@ CommandLineParser::CommandLineParser(int argc, const char* const argv[], const s jj = 0; for (int i = 1; i < argc; i++) { - std::string s = std::string(argv[i]); + String s = String(argv[i]); - if (s.find('=') != std::string::npos && s.find('=') < s.length()) + if (s.find('=') != String::npos && s.find('=') < s.length()) { - std::vector k_v = impl->split_string(s, '=', true); + std::vector k_v = impl->split_string(s, '=', true); for (int h = 0; h < 2; h++) { if (k_v[0][0] == '-') @@ -256,12 +249,12 @@ CommandLineParser& CommandLineParser::operator = (const CommandLineParser& parse return *this; } -void CommandLineParser::about(const std::string& message) +void CommandLineParser::about(const String& message) { impl->about_message = message; } -void CommandLineParser::Impl::apply_params(const std::string& key, const std::string& value) +void CommandLineParser::Impl::apply_params(const String& key, const String& value) { for (size_t i = 0; i < data.size(); i++) { @@ -276,7 +269,7 @@ void CommandLineParser::Impl::apply_params(const std::string& key, const std::st } } -void CommandLineParser::Impl::apply_params(int i, std::string value) +void CommandLineParser::Impl::apply_params(int i, String value) { for (size_t j = 0; j < data.size(); j++) { @@ -292,34 +285,34 @@ void CommandLineParser::Impl::sort_params() { for (size_t i = 0; i < data.size(); i++) { - sort(data[i].keys.begin(), data[i].keys.end()); + std::sort(data[i].keys.begin(), data[i].keys.end()); } std::sort (data.begin(), data.end(), cmp_params); } -std::string CommandLineParser::Impl::cat_string(const std::string& str) const +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 ? std::string("") : str.substr(left, right-left); + return left >= right ? String("") : str.substr(left, right-left); } -std::string CommandLineParser::getPathToApplication() const +String CommandLineParser::getPathToApplication() const { return impl->path_to_app; } -bool CommandLineParser::has(const std::string& name) const +bool CommandLineParser::has(const String& name) const { for (size_t i = 0; i < impl->data.size(); i++) { for (size_t j = 0; j < impl->data[i].keys.size(); j++) { - if (name.compare(impl->data[i].keys[j]) == 0 && std::string("true").compare(impl->data[i].def_value) == 0) + if (name.compare(impl->data[i].keys[j]) == 0 && String("true").compare(impl->data[i].def_value) == 0) { return true; } @@ -337,86 +330,87 @@ void CommandLineParser::printErrors() const { if (impl->error) { - std::cout << std::endl << "ERRORS:" << std::endl << impl->error_message << std::endl; + printf("\nERRORS:\n%s\n", impl->error_message.c_str()); + fflush(stdout); } } void CommandLineParser::printMessage() const { if (impl->about_message != "") - std::cout << impl->about_message << std::endl; + printf("%s\n", impl->about_message.c_str()); - std::cout << "Usage: " << impl->app_name << " [params] "; + printf("Usage: %s [params] ", impl->app_name.c_str()); for (size_t i = 0; i < impl->data.size(); i++) { if (impl->data[i].number > -1) { - std::string name = impl->data[i].keys[0].substr(1, impl->data[i].keys[0].length() - 1); - std::cout << name << " "; + String name = impl->data[i].keys[0].substr(1, impl->data[i].keys[0].length() - 1); + printf("%s ", name.c_str()); } } - std::cout << std::endl << std::endl; + printf("\n\n"); for (size_t i = 0; i < impl->data.size(); i++) { if (impl->data[i].number == -1) { - std::cout << "\t"; + printf("\t"); for (size_t j = 0; j < impl->data[i].keys.size(); j++) { - std::string k = impl->data[i].keys[j]; + String k = impl->data[i].keys[j]; if (k.length() > 1) { - std::cout << "--"; + printf("--"); } else { - std::cout << "-"; + printf("-"); } - std::cout << k; + printf("%s", k.c_str()); if (j != impl->data[i].keys.size() - 1) { - std::cout << ", "; + printf(", "); } } - std::string dv = impl->cat_string(impl->data[i].def_value); + String dv = impl->cat_string(impl->data[i].def_value); if (dv.compare("") != 0) { - std::cout << " (value:" << dv << ")"; + printf(" (value:%s)", dv.c_str()); } - std::cout << std::endl << "\t\t" << impl->data[i].help_message << std::endl; + printf("\n\t\t%s\n", impl->data[i].help_message.c_str()); } } - std::cout << std::endl; + printf("\n"); for (size_t i = 0; i < impl->data.size(); i++) { if (impl->data[i].number != -1) { - std::cout << "\t"; - std::string k = impl->data[i].keys[0]; + printf("\t"); + String k = impl->data[i].keys[0]; k = k.substr(1, k.length() - 1); - std::cout << k; + printf("%s", k.c_str()); - std::string dv = impl->cat_string(impl->data[i].def_value); + String dv = impl->cat_string(impl->data[i].def_value); if (dv.compare("") != 0) { - std::cout << " (value:" << dv << ")"; + printf(" (value:%s)", dv.c_str()); } - std::cout << std::endl << "\t\t" << impl->data[i].help_message << std::endl; + printf("\n\t\t%s\n", impl->data[i].help_message.c_str()); } } } -std::vector CommandLineParser::Impl::split_range_string(const std::string& _str, char fs, char ss) const +std::vector CommandLineParser::Impl::split_range_string(const String& _str, char fs, char ss) const { - std::string str = _str; - std::vector vec; - std::string word = ""; + String str = _str; + std::vector vec; + String word = ""; bool begin = false; while (!str.empty()) @@ -426,13 +420,13 @@ std::vector CommandLineParser::Impl::split_range_string(const std:: if (begin == true) { throw cv::Exception(CV_StsParseError, - std::string("error in split_range_string(") + String("error in split_range_string(") + str - + std::string(", ") - + std::string(1, fs) - + std::string(", ") - + std::string(1, ss) - + std::string(")"), + + String(", ") + + String(1, fs) + + String(", ") + + String(1, ss) + + String(")"), "", __FILE__, __LINE__ ); } @@ -446,13 +440,13 @@ std::vector CommandLineParser::Impl::split_range_string(const std:: if (begin == false) { throw cv::Exception(CV_StsParseError, - std::string("error in split_range_string(") + String("error in split_range_string(") + str - + std::string(", ") - + std::string(1, fs) - + std::string(", ") - + std::string(1, ss) - + std::string(")"), + + String(", ") + + String(1, fs) + + String(", ") + + String(1, ss) + + String(")"), "", __FILE__, __LINE__ ); } @@ -462,7 +456,7 @@ std::vector CommandLineParser::Impl::split_range_string(const std:: if (begin == true) { - word += str[0]; + word = word + str[0]; } str = str.substr(1, str.length() - 1); } @@ -470,13 +464,13 @@ std::vector CommandLineParser::Impl::split_range_string(const std:: if (begin == true) { throw cv::Exception(CV_StsParseError, - std::string("error in split_range_string(") + String("error in split_range_string(") + str - + std::string(", ") - + std::string(1, fs) - + std::string(", ") - + std::string(1, ss) - + std::string(")"), + + String(", ") + + String(1, fs) + + String(", ") + + String(1, ss) + + String(")"), "", __FILE__, __LINE__ ); } @@ -484,11 +478,11 @@ std::vector CommandLineParser::Impl::split_range_string(const std:: return vec; } -std::vector CommandLineParser::Impl::split_string(const std::string& _str, char symbol, bool create_empty_item) const +std::vector CommandLineParser::Impl::split_string(const String& _str, char symbol, bool create_empty_item) const { - std::string str = _str; - std::vector vec; - std::string word = ""; + String str = _str; + std::vector vec; + String word = ""; while (!str.empty()) { @@ -502,7 +496,7 @@ std::vector CommandLineParser::Impl::split_string(const std::string } else { - word += str[0]; + word = word + str[0]; } str = str.substr(1, str.length() - 1); } diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index d8ef88151a..5cd6894600 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -194,17 +194,27 @@ static void merge64s(const int64** src, int64* dst, int len, int cn ) typedef void (*SplitFunc)(const uchar* src, uchar** dst, int len, int cn); typedef void (*MergeFunc)(const uchar** src, uchar* dst, int len, int cn); -static SplitFunc splitTab[] = +static SplitFunc getSplitFunc(int depth) { - (SplitFunc)GET_OPTIMIZED(split8u), (SplitFunc)GET_OPTIMIZED(split8u), (SplitFunc)GET_OPTIMIZED(split16u), (SplitFunc)GET_OPTIMIZED(split16u), - (SplitFunc)GET_OPTIMIZED(split32s), (SplitFunc)GET_OPTIMIZED(split32s), (SplitFunc)GET_OPTIMIZED(split64s), 0 -}; + static SplitFunc splitTab[] = + { + (SplitFunc)GET_OPTIMIZED(split8u), (SplitFunc)GET_OPTIMIZED(split8u), (SplitFunc)GET_OPTIMIZED(split16u), (SplitFunc)GET_OPTIMIZED(split16u), + (SplitFunc)GET_OPTIMIZED(split32s), (SplitFunc)GET_OPTIMIZED(split32s), (SplitFunc)GET_OPTIMIZED(split64s), 0 + }; -static MergeFunc mergeTab[] = + return splitTab[depth]; +} + +static MergeFunc getMergeFunc(int depth) { - (MergeFunc)GET_OPTIMIZED(merge8u), (MergeFunc)GET_OPTIMIZED(merge8u), (MergeFunc)GET_OPTIMIZED(merge16u), (MergeFunc)GET_OPTIMIZED(merge16u), - (MergeFunc)GET_OPTIMIZED(merge32s), (MergeFunc)GET_OPTIMIZED(merge32s), (MergeFunc)GET_OPTIMIZED(merge64s), 0 -}; + static MergeFunc mergeTab[] = + { + (MergeFunc)GET_OPTIMIZED(merge8u), (MergeFunc)GET_OPTIMIZED(merge8u), (MergeFunc)GET_OPTIMIZED(merge16u), (MergeFunc)GET_OPTIMIZED(merge16u), + (MergeFunc)GET_OPTIMIZED(merge32s), (MergeFunc)GET_OPTIMIZED(merge32s), (MergeFunc)GET_OPTIMIZED(merge64s), 0 + }; + + return mergeTab[depth]; +} } @@ -217,7 +227,7 @@ void cv::split(const Mat& src, Mat* mv) return; } - SplitFunc func = splitTab[depth]; + SplitFunc func = getSplitFunc(depth); CV_Assert( func != 0 ); int esz = (int)src.elemSize(), esz1 = (int)src.elemSize1(); @@ -323,7 +333,7 @@ void cv::merge(const Mat* mv, size_t n, OutputArray _dst) NAryMatIterator it(arrays, ptrs, cn+1); int total = (int)it.size, blocksize = cn <= 4 ? total : std::min(total, blocksize0); - MergeFunc func = mergeTab[depth]; + MergeFunc func = getMergeFunc(depth); for( i = 0; i < it.nplanes; i++, ++it ) { @@ -419,12 +429,17 @@ static void mixChannels64s( const int64** src, const int* sdelta, typedef void (*MixChannelsFunc)( const uchar** src, const int* sdelta, uchar** dst, const int* ddelta, int len, int npairs ); -static MixChannelsFunc mixchTab[] = +static MixChannelsFunc getMixchFunc(int depth) { - (MixChannelsFunc)mixChannels8u, (MixChannelsFunc)mixChannels8u, (MixChannelsFunc)mixChannels16u, - (MixChannelsFunc)mixChannels16u, (MixChannelsFunc)mixChannels32s, (MixChannelsFunc)mixChannels32s, - (MixChannelsFunc)mixChannels64s, 0 -}; + static MixChannelsFunc mixchTab[] = + { + (MixChannelsFunc)mixChannels8u, (MixChannelsFunc)mixChannels8u, (MixChannelsFunc)mixChannels16u, + (MixChannelsFunc)mixChannels16u, (MixChannelsFunc)mixChannels32s, (MixChannelsFunc)mixChannels32s, + (MixChannelsFunc)mixChannels64s, 0 + }; + + return mixchTab[depth]; +} } @@ -479,7 +494,7 @@ void cv::mixChannels( const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, cons NAryMatIterator it(arrays, ptrs, (int)(nsrcs + ndsts)); int total = (int)it.size, blocksize = std::min(total, (int)((BLOCK_SIZE + esz1-1)/esz1)); - MixChannelsFunc func = mixchTab[depth]; + MixChannelsFunc func = getMixchFunc(depth); for( i = 0; i < it.nplanes; i++, ++it ) { @@ -505,14 +520,30 @@ void cv::mixChannels( const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, cons } -void cv::mixChannels(const std::vector& src, std::vector& dst, +void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, const int* fromTo, size_t npairs) { - mixChannels(!src.empty() ? &src[0] : 0, src.size(), - !dst.empty() ? &dst[0] : 0, dst.size(), fromTo, npairs); + if(npairs == 0) + return; + bool src_is_mat = src.kind() != _InputArray::STD_VECTOR_MAT && + src.kind() != _InputArray::STD_VECTOR_VECTOR; + bool dst_is_mat = dst.kind() != _InputArray::STD_VECTOR_MAT && + dst.kind() != _InputArray::STD_VECTOR_VECTOR; + int i; + int nsrc = src_is_mat ? 1 : (int)src.total(); + int ndst = dst_is_mat ? 1 : (int)dst.total(); + + CV_Assert(nsrc > 0 && ndst > 0); + cv::AutoBuffer _buf(nsrc + ndst); + Mat* buf = _buf; + for( i = 0; i < nsrc; i++ ) + buf[i] = src.getMat(src_is_mat ? -1 : i); + for( i = 0; i < ndst; i++ ) + buf[nsrc + i] = dst.getMat(dst_is_mat ? -1 : i); + mixChannels(&buf[0], nsrc, &buf[nsrc], ndst, fromTo, npairs); } -void cv::mixChannels(InputArrayOfArrays src, InputArrayOfArrays dst, +void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, const std::vector& fromTo) { if(fromTo.empty()) @@ -931,104 +962,109 @@ DEF_CVT_FUNC(32s64f, int, double); DEF_CVT_FUNC(32f64f, float, double); DEF_CPY_FUNC(64s, int64); -static BinaryFunc cvtScaleAbsTab[] = +static BinaryFunc getCvtScaleAbsFunc(int depth) { - (BinaryFunc)cvtScaleAbs8u, (BinaryFunc)cvtScaleAbs8s8u, (BinaryFunc)cvtScaleAbs16u8u, - (BinaryFunc)cvtScaleAbs16s8u, (BinaryFunc)cvtScaleAbs32s8u, (BinaryFunc)cvtScaleAbs32f8u, - (BinaryFunc)cvtScaleAbs64f8u, 0 -}; + static BinaryFunc cvtScaleAbsTab[] = + { + (BinaryFunc)cvtScaleAbs8u, (BinaryFunc)cvtScaleAbs8s8u, (BinaryFunc)cvtScaleAbs16u8u, + (BinaryFunc)cvtScaleAbs16s8u, (BinaryFunc)cvtScaleAbs32s8u, (BinaryFunc)cvtScaleAbs32f8u, + (BinaryFunc)cvtScaleAbs64f8u, 0 + }; -static BinaryFunc cvtScaleTab[][8] = -{ - { - (BinaryFunc)GET_OPTIMIZED(cvtScale8u), (BinaryFunc)GET_OPTIMIZED(cvtScale8s8u), (BinaryFunc)GET_OPTIMIZED(cvtScale16u8u), - (BinaryFunc)GET_OPTIMIZED(cvtScale16s8u), (BinaryFunc)GET_OPTIMIZED(cvtScale32s8u), (BinaryFunc)GET_OPTIMIZED(cvtScale32f8u), - (BinaryFunc)cvtScale64f8u, 0 - }, - { - (BinaryFunc)GET_OPTIMIZED(cvtScale8u8s), (BinaryFunc)GET_OPTIMIZED(cvtScale8s), (BinaryFunc)GET_OPTIMIZED(cvtScale16u8s), - (BinaryFunc)GET_OPTIMIZED(cvtScale16s8s), (BinaryFunc)GET_OPTIMIZED(cvtScale32s8s), (BinaryFunc)GET_OPTIMIZED(cvtScale32f8s), - (BinaryFunc)cvtScale64f8s, 0 - }, - { - (BinaryFunc)GET_OPTIMIZED(cvtScale8u16u), (BinaryFunc)GET_OPTIMIZED(cvtScale8s16u), (BinaryFunc)GET_OPTIMIZED(cvtScale16u), - (BinaryFunc)GET_OPTIMIZED(cvtScale16s16u), (BinaryFunc)GET_OPTIMIZED(cvtScale32s16u), (BinaryFunc)GET_OPTIMIZED(cvtScale32f16u), - (BinaryFunc)cvtScale64f16u, 0 - }, - { - (BinaryFunc)GET_OPTIMIZED(cvtScale8u16s), (BinaryFunc)GET_OPTIMIZED(cvtScale8s16s), (BinaryFunc)GET_OPTIMIZED(cvtScale16u16s), - (BinaryFunc)GET_OPTIMIZED(cvtScale16s), (BinaryFunc)GET_OPTIMIZED(cvtScale32s16s), (BinaryFunc)GET_OPTIMIZED(cvtScale32f16s), - (BinaryFunc)cvtScale64f16s, 0 - }, - { - (BinaryFunc)GET_OPTIMIZED(cvtScale8u32s), (BinaryFunc)GET_OPTIMIZED(cvtScale8s32s), (BinaryFunc)GET_OPTIMIZED(cvtScale16u32s), - (BinaryFunc)GET_OPTIMIZED(cvtScale16s32s), (BinaryFunc)GET_OPTIMIZED(cvtScale32s), (BinaryFunc)GET_OPTIMIZED(cvtScale32f32s), - (BinaryFunc)cvtScale64f32s, 0 - }, - { - (BinaryFunc)GET_OPTIMIZED(cvtScale8u32f), (BinaryFunc)GET_OPTIMIZED(cvtScale8s32f), (BinaryFunc)GET_OPTIMIZED(cvtScale16u32f), - (BinaryFunc)GET_OPTIMIZED(cvtScale16s32f), (BinaryFunc)GET_OPTIMIZED(cvtScale32s32f), (BinaryFunc)GET_OPTIMIZED(cvtScale32f), - (BinaryFunc)cvtScale64f32f, 0 - }, - { - (BinaryFunc)cvtScale8u64f, (BinaryFunc)cvtScale8s64f, (BinaryFunc)cvtScale16u64f, - (BinaryFunc)cvtScale16s64f, (BinaryFunc)cvtScale32s64f, (BinaryFunc)cvtScale32f64f, - (BinaryFunc)cvtScale64f, 0 - }, - { - 0, 0, 0, 0, 0, 0, 0, 0 - } -}; - -static BinaryFunc cvtTab[][8] = -{ - { - (BinaryFunc)(cvt8u), (BinaryFunc)GET_OPTIMIZED(cvt8s8u), (BinaryFunc)GET_OPTIMIZED(cvt16u8u), - (BinaryFunc)GET_OPTIMIZED(cvt16s8u), (BinaryFunc)GET_OPTIMIZED(cvt32s8u), (BinaryFunc)GET_OPTIMIZED(cvt32f8u), - (BinaryFunc)GET_OPTIMIZED(cvt64f8u), 0 - }, - { - (BinaryFunc)GET_OPTIMIZED(cvt8u8s), (BinaryFunc)cvt8u, (BinaryFunc)GET_OPTIMIZED(cvt16u8s), - (BinaryFunc)GET_OPTIMIZED(cvt16s8s), (BinaryFunc)GET_OPTIMIZED(cvt32s8s), (BinaryFunc)GET_OPTIMIZED(cvt32f8s), - (BinaryFunc)GET_OPTIMIZED(cvt64f8s), 0 - }, - { - (BinaryFunc)GET_OPTIMIZED(cvt8u16u), (BinaryFunc)GET_OPTIMIZED(cvt8s16u), (BinaryFunc)cvt16u, - (BinaryFunc)GET_OPTIMIZED(cvt16s16u), (BinaryFunc)GET_OPTIMIZED(cvt32s16u), (BinaryFunc)GET_OPTIMIZED(cvt32f16u), - (BinaryFunc)GET_OPTIMIZED(cvt64f16u), 0 - }, - { - (BinaryFunc)GET_OPTIMIZED(cvt8u16s), (BinaryFunc)GET_OPTIMIZED(cvt8s16s), (BinaryFunc)GET_OPTIMIZED(cvt16u16s), - (BinaryFunc)cvt16u, (BinaryFunc)GET_OPTIMIZED(cvt32s16s), (BinaryFunc)GET_OPTIMIZED(cvt32f16s), - (BinaryFunc)GET_OPTIMIZED(cvt64f16s), 0 - }, - { - (BinaryFunc)GET_OPTIMIZED(cvt8u32s), (BinaryFunc)GET_OPTIMIZED(cvt8s32s), (BinaryFunc)GET_OPTIMIZED(cvt16u32s), - (BinaryFunc)GET_OPTIMIZED(cvt16s32s), (BinaryFunc)cvt32s, (BinaryFunc)GET_OPTIMIZED(cvt32f32s), - (BinaryFunc)GET_OPTIMIZED(cvt64f32s), 0 - }, - { - (BinaryFunc)GET_OPTIMIZED(cvt8u32f), (BinaryFunc)GET_OPTIMIZED(cvt8s32f), (BinaryFunc)GET_OPTIMIZED(cvt16u32f), - (BinaryFunc)GET_OPTIMIZED(cvt16s32f), (BinaryFunc)GET_OPTIMIZED(cvt32s32f), (BinaryFunc)cvt32s, - (BinaryFunc)GET_OPTIMIZED(cvt64f32f), 0 - }, - { - (BinaryFunc)GET_OPTIMIZED(cvt8u64f), (BinaryFunc)GET_OPTIMIZED(cvt8s64f), (BinaryFunc)GET_OPTIMIZED(cvt16u64f), - (BinaryFunc)GET_OPTIMIZED(cvt16s64f), (BinaryFunc)GET_OPTIMIZED(cvt32s64f), (BinaryFunc)GET_OPTIMIZED(cvt32f64f), - (BinaryFunc)(cvt64s), 0 - }, - { - 0, 0, 0, 0, 0, 0, 0, 0 - } -}; + return cvtScaleAbsTab[depth]; +} BinaryFunc getConvertFunc(int sdepth, int ddepth) { + static BinaryFunc cvtTab[][8] = + { + { + (BinaryFunc)(cvt8u), (BinaryFunc)GET_OPTIMIZED(cvt8s8u), (BinaryFunc)GET_OPTIMIZED(cvt16u8u), + (BinaryFunc)GET_OPTIMIZED(cvt16s8u), (BinaryFunc)GET_OPTIMIZED(cvt32s8u), (BinaryFunc)GET_OPTIMIZED(cvt32f8u), + (BinaryFunc)GET_OPTIMIZED(cvt64f8u), 0 + }, + { + (BinaryFunc)GET_OPTIMIZED(cvt8u8s), (BinaryFunc)cvt8u, (BinaryFunc)GET_OPTIMIZED(cvt16u8s), + (BinaryFunc)GET_OPTIMIZED(cvt16s8s), (BinaryFunc)GET_OPTIMIZED(cvt32s8s), (BinaryFunc)GET_OPTIMIZED(cvt32f8s), + (BinaryFunc)GET_OPTIMIZED(cvt64f8s), 0 + }, + { + (BinaryFunc)GET_OPTIMIZED(cvt8u16u), (BinaryFunc)GET_OPTIMIZED(cvt8s16u), (BinaryFunc)cvt16u, + (BinaryFunc)GET_OPTIMIZED(cvt16s16u), (BinaryFunc)GET_OPTIMIZED(cvt32s16u), (BinaryFunc)GET_OPTIMIZED(cvt32f16u), + (BinaryFunc)GET_OPTIMIZED(cvt64f16u), 0 + }, + { + (BinaryFunc)GET_OPTIMIZED(cvt8u16s), (BinaryFunc)GET_OPTIMIZED(cvt8s16s), (BinaryFunc)GET_OPTIMIZED(cvt16u16s), + (BinaryFunc)cvt16u, (BinaryFunc)GET_OPTIMIZED(cvt32s16s), (BinaryFunc)GET_OPTIMIZED(cvt32f16s), + (BinaryFunc)GET_OPTIMIZED(cvt64f16s), 0 + }, + { + (BinaryFunc)GET_OPTIMIZED(cvt8u32s), (BinaryFunc)GET_OPTIMIZED(cvt8s32s), (BinaryFunc)GET_OPTIMIZED(cvt16u32s), + (BinaryFunc)GET_OPTIMIZED(cvt16s32s), (BinaryFunc)cvt32s, (BinaryFunc)GET_OPTIMIZED(cvt32f32s), + (BinaryFunc)GET_OPTIMIZED(cvt64f32s), 0 + }, + { + (BinaryFunc)GET_OPTIMIZED(cvt8u32f), (BinaryFunc)GET_OPTIMIZED(cvt8s32f), (BinaryFunc)GET_OPTIMIZED(cvt16u32f), + (BinaryFunc)GET_OPTIMIZED(cvt16s32f), (BinaryFunc)GET_OPTIMIZED(cvt32s32f), (BinaryFunc)cvt32s, + (BinaryFunc)GET_OPTIMIZED(cvt64f32f), 0 + }, + { + (BinaryFunc)GET_OPTIMIZED(cvt8u64f), (BinaryFunc)GET_OPTIMIZED(cvt8s64f), (BinaryFunc)GET_OPTIMIZED(cvt16u64f), + (BinaryFunc)GET_OPTIMIZED(cvt16s64f), (BinaryFunc)GET_OPTIMIZED(cvt32s64f), (BinaryFunc)GET_OPTIMIZED(cvt32f64f), + (BinaryFunc)(cvt64s), 0 + }, + { + 0, 0, 0, 0, 0, 0, 0, 0 + } + }; + return cvtTab[CV_MAT_DEPTH(ddepth)][CV_MAT_DEPTH(sdepth)]; } -BinaryFunc getConvertScaleFunc(int sdepth, int ddepth) +static BinaryFunc getConvertScaleFunc(int sdepth, int ddepth) { + static BinaryFunc cvtScaleTab[][8] = + { + { + (BinaryFunc)GET_OPTIMIZED(cvtScale8u), (BinaryFunc)GET_OPTIMIZED(cvtScale8s8u), (BinaryFunc)GET_OPTIMIZED(cvtScale16u8u), + (BinaryFunc)GET_OPTIMIZED(cvtScale16s8u), (BinaryFunc)GET_OPTIMIZED(cvtScale32s8u), (BinaryFunc)GET_OPTIMIZED(cvtScale32f8u), + (BinaryFunc)cvtScale64f8u, 0 + }, + { + (BinaryFunc)GET_OPTIMIZED(cvtScale8u8s), (BinaryFunc)GET_OPTIMIZED(cvtScale8s), (BinaryFunc)GET_OPTIMIZED(cvtScale16u8s), + (BinaryFunc)GET_OPTIMIZED(cvtScale16s8s), (BinaryFunc)GET_OPTIMIZED(cvtScale32s8s), (BinaryFunc)GET_OPTIMIZED(cvtScale32f8s), + (BinaryFunc)cvtScale64f8s, 0 + }, + { + (BinaryFunc)GET_OPTIMIZED(cvtScale8u16u), (BinaryFunc)GET_OPTIMIZED(cvtScale8s16u), (BinaryFunc)GET_OPTIMIZED(cvtScale16u), + (BinaryFunc)GET_OPTIMIZED(cvtScale16s16u), (BinaryFunc)GET_OPTIMIZED(cvtScale32s16u), (BinaryFunc)GET_OPTIMIZED(cvtScale32f16u), + (BinaryFunc)cvtScale64f16u, 0 + }, + { + (BinaryFunc)GET_OPTIMIZED(cvtScale8u16s), (BinaryFunc)GET_OPTIMIZED(cvtScale8s16s), (BinaryFunc)GET_OPTIMIZED(cvtScale16u16s), + (BinaryFunc)GET_OPTIMIZED(cvtScale16s), (BinaryFunc)GET_OPTIMIZED(cvtScale32s16s), (BinaryFunc)GET_OPTIMIZED(cvtScale32f16s), + (BinaryFunc)cvtScale64f16s, 0 + }, + { + (BinaryFunc)GET_OPTIMIZED(cvtScale8u32s), (BinaryFunc)GET_OPTIMIZED(cvtScale8s32s), (BinaryFunc)GET_OPTIMIZED(cvtScale16u32s), + (BinaryFunc)GET_OPTIMIZED(cvtScale16s32s), (BinaryFunc)GET_OPTIMIZED(cvtScale32s), (BinaryFunc)GET_OPTIMIZED(cvtScale32f32s), + (BinaryFunc)cvtScale64f32s, 0 + }, + { + (BinaryFunc)GET_OPTIMIZED(cvtScale8u32f), (BinaryFunc)GET_OPTIMIZED(cvtScale8s32f), (BinaryFunc)GET_OPTIMIZED(cvtScale16u32f), + (BinaryFunc)GET_OPTIMIZED(cvtScale16s32f), (BinaryFunc)GET_OPTIMIZED(cvtScale32s32f), (BinaryFunc)GET_OPTIMIZED(cvtScale32f), + (BinaryFunc)cvtScale64f32f, 0 + }, + { + (BinaryFunc)cvtScale8u64f, (BinaryFunc)cvtScale8s64f, (BinaryFunc)cvtScale16u64f, + (BinaryFunc)cvtScale16s64f, (BinaryFunc)cvtScale32s64f, (BinaryFunc)cvtScale32f64f, + (BinaryFunc)cvtScale64f, 0 + }, + { + 0, 0, 0, 0, 0, 0, 0, 0 + } + }; + return cvtScaleTab[CV_MAT_DEPTH(ddepth)][CV_MAT_DEPTH(sdepth)]; } @@ -1041,7 +1077,7 @@ void cv::convertScaleAbs( InputArray _src, OutputArray _dst, double alpha, doubl double scale[] = {alpha, beta}; _dst.create( src.dims, src.size, CV_8UC(cn) ); Mat dst = _dst.getMat(); - BinaryFunc func = cvtScaleAbsTab[src.depth()]; + BinaryFunc func = getCvtScaleAbsFunc(src.depth()); CV_Assert( func != 0 ); if( src.dims <= 2 ) @@ -1173,10 +1209,9 @@ static LUTFunc lutTab[] = } -void cv::LUT( InputArray _src, InputArray _lut, OutputArray _dst, int interpolation ) +void cv::LUT( InputArray _src, InputArray _lut, OutputArray _dst ) { Mat src = _src.getMat(), lut = _lut.getMat(); - CV_Assert( interpolation == 0 ); int cn = src.channels(); int lutcn = lut.channels(); @@ -1361,4 +1396,4 @@ CV_IMPL void cvNormalize( const CvArr* srcarr, CvArr* dstarr, cv::normalize( src, dst, a, b, norm_type, dst.type(), mask ); } -/* End of file. */ \ No newline at end of file +/* End of file. */ diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index 8276ffddb6..3d58df7871 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -512,6 +512,231 @@ Mat repeat(const Mat& src, int ny, int nx) return dst; } + +} // cv + + +/* + Various border types, image boundaries are denoted with '|' + + * BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh + * BORDER_REFLECT: fedcba|abcdefgh|hgfedcb + * BORDER_REFLECT_101: gfedcb|abcdefgh|gfedcba + * BORDER_WRAP: cdefgh|abcdefgh|abcdefg + * BORDER_CONSTANT: iiiiii|abcdefgh|iiiiiii with some specified 'i' + */ +int cv::borderInterpolate( int p, int len, int borderType ) +{ + if( (unsigned)p < (unsigned)len ) + ; + else if( borderType == BORDER_REPLICATE ) + p = p < 0 ? 0 : len - 1; + else if( borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101 ) + { + int delta = borderType == BORDER_REFLECT_101; + if( len == 1 ) + return 0; + do + { + if( p < 0 ) + p = -p - 1 + delta; + else + p = len - 1 - (p - len) - delta; + } + while( (unsigned)p >= (unsigned)len ); + } + else if( borderType == BORDER_WRAP ) + { + if( p < 0 ) + p -= ((p-len+1)/len)*len; + if( p >= len ) + p %= len; + } + else if( borderType == BORDER_CONSTANT ) + p = -1; + else + CV_Error( CV_StsBadArg, "Unknown/unsupported border type" ); + return p; +} + +namespace +{ + +void copyMakeBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi, + uchar* dst, size_t dststep, cv::Size dstroi, + int top, int left, int cn, int borderType ) +{ + const int isz = (int)sizeof(int); + int i, j, k, elemSize = 1; + bool intMode = false; + + if( (cn | srcstep | dststep | (size_t)src | (size_t)dst) % isz == 0 ) + { + cn /= isz; + elemSize = isz; + intMode = true; + } + + cv::AutoBuffer _tab((dstroi.width - srcroi.width)*cn); + int* tab = _tab; + int right = dstroi.width - srcroi.width - left; + int bottom = dstroi.height - srcroi.height - top; + + for( i = 0; i < left; i++ ) + { + j = cv::borderInterpolate(i - left, srcroi.width, borderType)*cn; + for( k = 0; k < cn; k++ ) + tab[i*cn + k] = j + k; + } + + for( i = 0; i < right; i++ ) + { + j = cv::borderInterpolate(srcroi.width + i, srcroi.width, borderType)*cn; + for( k = 0; k < cn; k++ ) + tab[(i+left)*cn + k] = j + k; + } + + srcroi.width *= cn; + dstroi.width *= cn; + left *= cn; + right *= cn; + + uchar* dstInner = dst + dststep*top + left*elemSize; + + for( i = 0; i < srcroi.height; i++, dstInner += dststep, src += srcstep ) + { + if( dstInner != src ) + memcpy(dstInner, src, srcroi.width*elemSize); + + if( intMode ) + { + const int* isrc = (int*)src; + int* idstInner = (int*)dstInner; + for( j = 0; j < left; j++ ) + idstInner[j - left] = isrc[tab[j]]; + for( j = 0; j < right; j++ ) + idstInner[j + srcroi.width] = isrc[tab[j + left]]; + } + else + { + for( j = 0; j < left; j++ ) + dstInner[j - left] = src[tab[j]]; + for( j = 0; j < right; j++ ) + dstInner[j + srcroi.width] = src[tab[j + left]]; + } + } + + dstroi.width *= elemSize; + dst += dststep*top; + + for( i = 0; i < top; i++ ) + { + j = cv::borderInterpolate(i - top, srcroi.height, borderType); + memcpy(dst + (i - top)*dststep, dst + j*dststep, dstroi.width); + } + + for( i = 0; i < bottom; i++ ) + { + j = cv::borderInterpolate(i + srcroi.height, srcroi.height, borderType); + memcpy(dst + (i + srcroi.height)*dststep, dst + j*dststep, dstroi.width); + } +} + + +void copyMakeConstBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi, + uchar* dst, size_t dststep, cv::Size dstroi, + int top, int left, int cn, const uchar* value ) +{ + int i, j; + cv::AutoBuffer _constBuf(dstroi.width*cn); + uchar* constBuf = _constBuf; + int right = dstroi.width - srcroi.width - left; + int bottom = dstroi.height - srcroi.height - top; + + for( i = 0; i < dstroi.width; i++ ) + { + for( j = 0; j < cn; j++ ) + constBuf[i*cn + j] = value[j]; + } + + srcroi.width *= cn; + dstroi.width *= cn; + left *= cn; + right *= cn; + + uchar* dstInner = dst + dststep*top + left; + + for( i = 0; i < srcroi.height; i++, dstInner += dststep, src += srcstep ) + { + if( dstInner != src ) + memcpy( dstInner, src, srcroi.width ); + memcpy( dstInner - left, constBuf, left ); + memcpy( dstInner + srcroi.width, constBuf, right ); + } + + dst += dststep*top; + + for( i = 0; i < top; i++ ) + memcpy(dst + (i - top)*dststep, constBuf, dstroi.width); + + for( i = 0; i < bottom; i++ ) + memcpy(dst + (i + srcroi.height)*dststep, constBuf, dstroi.width); +} + +} + +void cv::copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom, + int left, int right, int borderType, const Scalar& value ) +{ + Mat src = _src.getMat(); + CV_Assert( top >= 0 && bottom >= 0 && left >= 0 && right >= 0 ); + + if( src.isSubmatrix() && (borderType & BORDER_ISOLATED) == 0 ) + { + Size wholeSize; + Point ofs; + src.locateROI(wholeSize, ofs); + int dtop = std::min(ofs.y, top); + int dbottom = std::min(wholeSize.height - src.rows - ofs.y, bottom); + int dleft = std::min(ofs.x, left); + int dright = std::min(wholeSize.width - src.cols - ofs.x, right); + src.adjustROI(dtop, dbottom, dleft, dright); + top -= dtop; + left -= dleft; + bottom -= dbottom; + right -= dright; + } + + _dst.create( src.rows + top + bottom, src.cols + left + right, src.type() ); + Mat dst = _dst.getMat(); + + if(top == 0 && left == 0 && bottom == 0 && right == 0) + { + if(src.data != dst.data || src.step != dst.step) + src.copyTo(dst); + return; + } + + borderType &= ~BORDER_ISOLATED; + + if( borderType != BORDER_CONSTANT ) + copyMakeBorder_8u( src.data, src.step, src.size(), + dst.data, dst.step, dst.size(), + top, left, (int)src.elemSize(), borderType ); + else + { + int cn = src.channels(), cn1 = cn; + AutoBuffer buf(cn); + if( cn > 4 ) + { + CV_Assert( value[0] == value[1] && value[0] == value[2] && value[0] == value[3] ); + cn1 = 1; + } + scalarToRawData(value, buf, CV_MAKETYPE(src.depth(), cn1), cn); + copyMakeConstBorder_8u( src.data, src.step, src.size(), + dst.data, dst.step, dst.size(), + top, left, (int)src.elemSize(), (uchar*)(double*)buf ); + } } /* dst = src */ diff --git a/modules/core/src/cuda/gpu_mat.cu b/modules/core/src/cuda/gpu_mat.cu new file mode 100644 index 0000000000..0db1584212 --- /dev/null +++ b/modules/core/src/cuda/gpu_mat.cu @@ -0,0 +1,486 @@ +/*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 "opencv2/opencv_modules.hpp" + +#ifndef HAVE_OPENCV_CUDEV + +#error "opencv_cudev is required" + +#else + +#include "opencv2/core/gpu.hpp" +#include "opencv2/cudev.hpp" + +using namespace cv; +using namespace cv::gpu; +using namespace cv::cudev; + +///////////////////////////////////////////////////// +/// create + +void cv::gpu::GpuMat::create(int _rows, int _cols, int _type) +{ + CV_DbgAssert( _rows >= 0 && _cols >= 0 ); + + _type &= Mat::TYPE_MASK; + + if (rows == _rows && cols == _cols && type() == _type && data) + return; + + if (data) + release(); + + if (_rows > 0 && _cols > 0) + { + flags = Mat::MAGIC_VAL + _type; + rows = _rows; + cols = _cols; + + size_t esz = elemSize(); + + void* devPtr; + + if (rows > 1 && cols > 1) + { + CV_CUDEV_SAFE_CALL( cudaMallocPitch(&devPtr, &step, esz * cols, rows) ); + } + else + { + // Single row or single column must be continuous + CV_CUDEV_SAFE_CALL( cudaMalloc(&devPtr, esz * cols * rows) ); + step = esz * cols; + } + + if (esz * cols == step) + flags |= Mat::CONTINUOUS_FLAG; + + int64 _nettosize = static_cast(step) * rows; + size_t nettosize = static_cast(_nettosize); + + datastart = data = static_cast(devPtr); + dataend = data + nettosize; + + refcount = static_cast(fastMalloc(sizeof(*refcount))); + *refcount = 1; + } +} + +///////////////////////////////////////////////////// +/// release + +void cv::gpu::GpuMat::release() +{ + if (refcount && CV_XADD(refcount, -1) == 1) + { + cudaFree(datastart); + fastFree(refcount); + } + + data = datastart = dataend = 0; + step = rows = cols = 0; + refcount = 0; +} + +///////////////////////////////////////////////////// +/// upload + +void cv::gpu::GpuMat::upload(InputArray arr) +{ + Mat mat = arr.getMat(); + + CV_DbgAssert( !mat.empty() ); + + create(mat.size(), mat.type()); + + CV_CUDEV_SAFE_CALL( cudaMemcpy2D(data, step, mat.data, mat.step, cols * elemSize(), rows, cudaMemcpyHostToDevice) ); +} + +void cv::gpu::GpuMat::upload(InputArray arr, Stream& _stream) +{ + Mat mat = arr.getMat(); + + CV_DbgAssert( !mat.empty() ); + + create(mat.size(), mat.type()); + + cudaStream_t stream = StreamAccessor::getStream(_stream); + CV_CUDEV_SAFE_CALL( cudaMemcpy2DAsync(data, step, mat.data, mat.step, cols * elemSize(), rows, cudaMemcpyHostToDevice, stream) ); +} + +///////////////////////////////////////////////////// +/// download + +void cv::gpu::GpuMat::download(OutputArray _dst) const +{ + CV_DbgAssert( !empty() ); + + _dst.create(size(), type()); + Mat dst = _dst.getMat(); + + CV_CUDEV_SAFE_CALL( cudaMemcpy2D(dst.data, dst.step, data, step, cols * elemSize(), rows, cudaMemcpyDeviceToHost) ); +} + +void cv::gpu::GpuMat::download(OutputArray _dst, Stream& _stream) const +{ + CV_DbgAssert( !empty() ); + + _dst.create(size(), type()); + Mat dst = _dst.getMat(); + + cudaStream_t stream = StreamAccessor::getStream(_stream); + CV_CUDEV_SAFE_CALL( cudaMemcpy2DAsync(dst.data, dst.step, data, step, cols * elemSize(), rows, cudaMemcpyDeviceToHost, stream) ); +} + +///////////////////////////////////////////////////// +/// copyTo + +void cv::gpu::GpuMat::copyTo(OutputArray _dst) const +{ + CV_DbgAssert( !empty() ); + + _dst.create(size(), type()); + GpuMat dst = _dst.getGpuMat(); + + CV_CUDEV_SAFE_CALL( cudaMemcpy2D(dst.data, dst.step, data, step, cols * elemSize(), rows, cudaMemcpyDeviceToDevice) ); +} + +void cv::gpu::GpuMat::copyTo(OutputArray _dst, Stream& _stream) const +{ + CV_DbgAssert( !empty() ); + + _dst.create(size(), type()); + GpuMat dst = _dst.getGpuMat(); + + cudaStream_t stream = StreamAccessor::getStream(_stream); + CV_CUDEV_SAFE_CALL( cudaMemcpy2DAsync(dst.data, dst.step, data, step, cols * elemSize(), rows, cudaMemcpyDeviceToDevice, stream) ); +} + +namespace +{ + template struct CopyToPolicy : DefaultTransformPolicy + { + }; + template <> struct CopyToPolicy<4> : DefaultTransformPolicy + { + enum { + shift = 2 + }; + }; + template <> struct CopyToPolicy<8> : DefaultTransformPolicy + { + enum { + shift = 1 + }; + }; + + template + void copyWithMask(const GpuMat& src, const GpuMat& dst, const GpuMat& mask, Stream& stream) + { + gridTransform_< CopyToPolicy::elem_type)> >(globPtr(src), globPtr(dst), identity(), globPtr(mask), stream); + } +} + +void cv::gpu::GpuMat::copyTo(OutputArray _dst, InputArray _mask, Stream& stream) const +{ + CV_DbgAssert( !empty() ); + CV_DbgAssert( depth() <= CV_64F && channels() <= 4 ); + + GpuMat mask = _mask.getGpuMat(); + CV_DbgAssert( size() == mask.size() && mask.depth() == CV_8U && (mask.channels() == 1 || mask.channels() == channels()) ); + + _dst.create(size(), type()); + GpuMat dst = _dst.getGpuMat(); + + typedef void (*func_t)(const GpuMat& src, const GpuMat& dst, const GpuMat& mask, Stream& stream); + static const func_t funcs[9][4] = + { + {0,0,0,0}, + {copyWithMask, copyWithMask, copyWithMask, copyWithMask}, + {copyWithMask, copyWithMask, copyWithMask, copyWithMask}, + {0,0,0,0}, + {copyWithMask, copyWithMask, copyWithMask, copyWithMask}, + {0,0,0,0}, + {0,0,0,0}, + {0,0,0,0}, + {copyWithMask, copyWithMask, copyWithMask, copyWithMask} + }; + + if (mask.channels() == channels()) + { + const func_t func = funcs[elemSize1()][0]; + CV_DbgAssert( func != 0 ); + func(reshape(1), dst.reshape(1), mask.reshape(1), stream); + } + else + { + const func_t func = funcs[elemSize1()][channels() - 1]; + CV_DbgAssert( func != 0 ); + func(*this, dst, mask, stream); + } +} + +///////////////////////////////////////////////////// +/// setTo + +namespace +{ + template + void setToWithOutMask(const GpuMat& mat, Scalar _scalar, Stream& stream) + { + Scalar_::elem_type> scalar = _scalar; + gridTransform(constantPtr(VecTraits::make(scalar.val), mat.rows, mat.cols), globPtr(mat), identity(), stream); + } + + template + void setToWithMask(const GpuMat& mat, const GpuMat& mask, Scalar _scalar, Stream& stream) + { + Scalar_::elem_type> scalar = _scalar; + gridTransform(constantPtr(VecTraits::make(scalar.val), mat.rows, mat.cols), globPtr(mat), identity(), globPtr(mask), stream); + } +} + +GpuMat& cv::gpu::GpuMat::setTo(Scalar value, Stream& stream) +{ + CV_DbgAssert( !empty() ); + CV_DbgAssert( depth() <= CV_64F && channels() <= 4 ); + + if (value[0] == 0.0 && value[1] == 0.0 && value[2] == 0.0 && value[3] == 0.0) + { + // Zero fill + + if (stream) + CV_CUDEV_SAFE_CALL( cudaMemset2DAsync(data, step, 0, cols * elemSize(), rows, StreamAccessor::getStream(stream)) ); + else + CV_CUDEV_SAFE_CALL( cudaMemset2D(data, step, 0, cols * elemSize(), rows) ); + + return *this; + } + + if (depth() == CV_8U) + { + const int cn = channels(); + + if (cn == 1 + || (cn == 2 && value[0] == value[1]) + || (cn == 3 && value[0] == value[1] && value[0] == value[2]) + || (cn == 4 && value[0] == value[1] && value[0] == value[2] && value[0] == value[3])) + { + const int val = cv::saturate_cast(value[0]); + + if (stream) + CV_CUDEV_SAFE_CALL( cudaMemset2DAsync(data, step, val, cols * elemSize(), rows, StreamAccessor::getStream(stream)) ); + else + CV_CUDEV_SAFE_CALL( cudaMemset2D(data, step, val, cols * elemSize(), rows) ); + + return *this; + } + } + + typedef void (*func_t)(const GpuMat& mat, Scalar scalar, Stream& stream); + static const func_t funcs[7][4] = + { + {setToWithOutMask,setToWithOutMask,setToWithOutMask,setToWithOutMask}, + {setToWithOutMask,setToWithOutMask,setToWithOutMask,setToWithOutMask}, + {setToWithOutMask,setToWithOutMask,setToWithOutMask,setToWithOutMask}, + {setToWithOutMask,setToWithOutMask,setToWithOutMask,setToWithOutMask}, + {setToWithOutMask,setToWithOutMask,setToWithOutMask,setToWithOutMask}, + {setToWithOutMask,setToWithOutMask,setToWithOutMask,setToWithOutMask}, + {setToWithOutMask,setToWithOutMask,setToWithOutMask,setToWithOutMask} + }; + + funcs[depth()][channels() - 1](*this, value, stream); + + return *this; +} + +GpuMat& cv::gpu::GpuMat::setTo(Scalar value, InputArray _mask, Stream& stream) +{ + CV_DbgAssert( !empty() ); + CV_DbgAssert( depth() <= CV_64F && channels() <= 4 ); + + GpuMat mask = _mask.getGpuMat(); + + CV_DbgAssert( size() == mask.size() && mask.type() == CV_8UC1 ); + + typedef void (*func_t)(const GpuMat& mat, const GpuMat& mask, Scalar scalar, Stream& stream); + static const func_t funcs[7][4] = + { + {setToWithMask,setToWithMask,setToWithMask,setToWithMask}, + {setToWithMask,setToWithMask,setToWithMask,setToWithMask}, + {setToWithMask,setToWithMask,setToWithMask,setToWithMask}, + {setToWithMask,setToWithMask,setToWithMask,setToWithMask}, + {setToWithMask,setToWithMask,setToWithMask,setToWithMask}, + {setToWithMask,setToWithMask,setToWithMask,setToWithMask}, + {setToWithMask,setToWithMask,setToWithMask,setToWithMask} + }; + + funcs[depth()][channels() - 1](*this, mask, value, stream); + + return *this; +} + +///////////////////////////////////////////////////// +/// convertTo + +namespace +{ + template struct ConvertToPolicy : DefaultTransformPolicy + { + }; + template <> struct ConvertToPolicy : DefaultTransformPolicy + { + enum { + shift = 1 + }; + }; + + template + void convertToNoScale(const GpuMat& src, const GpuMat& dst, Stream& stream) + { + typedef typename VecTraits::elem_type src_elem_type; + typedef typename VecTraits::elem_type dst_elem_type; + typedef typename LargerType::type larger_elem_type; + typedef typename LargerType::type scalar_type; + + gridTransform_< ConvertToPolicy >(globPtr(src), globPtr(dst), saturate_cast_func(), stream); + } + + template struct Convertor : unary_function + { + S alpha; + S beta; + + __device__ __forceinline__ D operator ()(typename TypeTraits::parameter_type src) const + { + return cudev::saturate_cast(alpha * src + beta); + } + }; + + template + void convertToScale(const GpuMat& src, const GpuMat& dst, double alpha, double beta, Stream& stream) + { + typedef typename VecTraits::elem_type src_elem_type; + typedef typename VecTraits::elem_type dst_elem_type; + typedef typename LargerType::type larger_elem_type; + typedef typename LargerType::type scalar_type; + + Convertor op; + op.alpha = cv::saturate_cast(alpha); + op.beta = cv::saturate_cast(beta); + + gridTransform_< ConvertToPolicy >(globPtr(src), globPtr(dst), op, stream); + } +} + +void cv::gpu::GpuMat::convertTo(OutputArray _dst, int rtype, Stream& stream) const +{ + if (rtype < 0) + rtype = type(); + else + rtype = CV_MAKE_TYPE(CV_MAT_DEPTH(rtype), channels()); + + const int sdepth = depth(); + const int ddepth = CV_MAT_DEPTH(rtype); + if (sdepth == ddepth) + { + if (stream) + copyTo(_dst, stream); + else + copyTo(_dst); + + return; + } + + CV_DbgAssert( sdepth <= CV_64F && ddepth <= CV_64F ); + + GpuMat src = *this; + + _dst.create(size(), rtype); + GpuMat dst = _dst.getGpuMat(); + + typedef void (*func_t)(const GpuMat& src, const GpuMat& dst, Stream& stream); + static const func_t funcs[7][7] = + { + {0, convertToNoScale, convertToNoScale, convertToNoScale, convertToNoScale, convertToNoScale, convertToNoScale}, + {convertToNoScale, 0, convertToNoScale, convertToNoScale, convertToNoScale, convertToNoScale, convertToNoScale}, + {convertToNoScale, convertToNoScale, 0, convertToNoScale, convertToNoScale, convertToNoScale, convertToNoScale}, + {convertToNoScale, convertToNoScale, convertToNoScale, 0, convertToNoScale, convertToNoScale, convertToNoScale}, + {convertToNoScale, convertToNoScale, convertToNoScale, convertToNoScale, 0, convertToNoScale, convertToNoScale}, + {convertToNoScale, convertToNoScale, convertToNoScale, convertToNoScale, convertToNoScale, 0, convertToNoScale}, + {convertToNoScale, convertToNoScale, convertToNoScale, convertToNoScale, convertToNoScale, convertToNoScale, 0} + }; + + funcs[sdepth][ddepth](reshape(1), dst.reshape(1), stream); +} + +void cv::gpu::GpuMat::convertTo(OutputArray _dst, int rtype, double alpha, double beta, Stream& stream) const +{ + if (rtype < 0) + rtype = type(); + else + rtype = CV_MAKETYPE(CV_MAT_DEPTH(rtype), channels()); + + const int sdepth = depth(); + const int ddepth = CV_MAT_DEPTH(rtype); + + GpuMat src = *this; + + _dst.create(size(), rtype); + GpuMat dst = _dst.getGpuMat(); + + typedef void (*func_t)(const GpuMat& src, const GpuMat& dst, double alpha, double beta, Stream& stream); + static const func_t funcs[7][7] = + { + {convertToScale, convertToScale, convertToScale, convertToScale, convertToScale, convertToScale, convertToScale}, + {convertToScale, convertToScale, convertToScale, convertToScale, convertToScale, convertToScale, convertToScale}, + {convertToScale, convertToScale, convertToScale, convertToScale, convertToScale, convertToScale, convertToScale}, + {convertToScale, convertToScale, convertToScale, convertToScale, convertToScale, convertToScale, convertToScale}, + {convertToScale, convertToScale, convertToScale, convertToScale, convertToScale, convertToScale, convertToScale}, + {convertToScale, convertToScale, convertToScale, convertToScale, convertToScale, convertToScale, convertToScale}, + {convertToScale, convertToScale, convertToScale, convertToScale, convertToScale, convertToScale, convertToScale} + }; + + funcs[sdepth][ddepth](reshape(1), dst.reshape(1), alpha, beta, stream); +} + +#endif diff --git a/modules/core/src/cuda/matrix_operations.cu b/modules/core/src/cuda/matrix_operations.cu deleted file mode 100644 index 60aa073406..0000000000 --- a/modules/core/src/cuda/matrix_operations.cu +++ /dev/null @@ -1,383 +0,0 @@ -/*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 "opencv2/gpu/device/saturate_cast.hpp" -#include "opencv2/gpu/device/transform.hpp" -#include "opencv2/gpu/device/functional.hpp" -#include "opencv2/gpu/device/type_traits.hpp" - -namespace cv { namespace gpu { namespace device -{ - void writeScalar(const uchar*); - void writeScalar(const schar*); - void writeScalar(const ushort*); - void writeScalar(const short int*); - void writeScalar(const int*); - void writeScalar(const float*); - void writeScalar(const double*); - void copyToWithMask_gpu(PtrStepSzb src, PtrStepSzb dst, size_t elemSize1, int cn, PtrStepSzb mask, bool colorMask, cudaStream_t stream); - void convert_gpu(PtrStepSzb, int, PtrStepSzb, int, double, double, cudaStream_t); -}}} - -namespace cv { namespace gpu { namespace device -{ - template struct shift_and_sizeof; - template <> struct shift_and_sizeof { enum { shift = 0 }; }; - template <> struct shift_and_sizeof { enum { shift = 0 }; }; - template <> struct shift_and_sizeof { enum { shift = 1 }; }; - template <> struct shift_and_sizeof { enum { shift = 1 }; }; - template <> struct shift_and_sizeof { enum { shift = 2 }; }; - template <> struct shift_and_sizeof { enum { shift = 2 }; }; - template <> struct shift_and_sizeof { enum { shift = 3 }; }; - - /////////////////////////////////////////////////////////////////////////// - ////////////////////////////////// CopyTo ///////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - template void copyToWithMask(PtrStepSzb src, PtrStepSzb dst, int cn, PtrStepSzb mask, bool colorMask, cudaStream_t stream) - { - if (colorMask) - cv::gpu::device::transform((PtrStepSz)src, (PtrStepSz)dst, identity(), SingleMask(mask), stream); - else - cv::gpu::device::transform((PtrStepSz)src, (PtrStepSz)dst, identity(), SingleMaskChannels(mask, cn), stream); - } - - void copyToWithMask_gpu(PtrStepSzb src, PtrStepSzb dst, size_t elemSize1, int cn, PtrStepSzb mask, bool colorMask, cudaStream_t stream) - { - typedef void (*func_t)(PtrStepSzb src, PtrStepSzb dst, int cn, PtrStepSzb mask, bool colorMask, cudaStream_t stream); - - static func_t tab[] = - { - 0, - copyToWithMask, - copyToWithMask, - 0, - copyToWithMask, - 0, - 0, - 0, - copyToWithMask - }; - - tab[elemSize1](src, dst, cn, mask, colorMask, stream); - } - - /////////////////////////////////////////////////////////////////////////// - ////////////////////////////////// SetTo ////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - __constant__ uchar scalar_8u[4]; - __constant__ schar scalar_8s[4]; - __constant__ ushort scalar_16u[4]; - __constant__ short scalar_16s[4]; - __constant__ int scalar_32s[4]; - __constant__ float scalar_32f[4]; - __constant__ double scalar_64f[4]; - - template __device__ __forceinline__ T readScalar(int i); - template <> __device__ __forceinline__ uchar readScalar(int i) {return scalar_8u[i];} - template <> __device__ __forceinline__ schar readScalar(int i) {return scalar_8s[i];} - template <> __device__ __forceinline__ ushort readScalar(int i) {return scalar_16u[i];} - template <> __device__ __forceinline__ short readScalar(int i) {return scalar_16s[i];} - template <> __device__ __forceinline__ int readScalar(int i) {return scalar_32s[i];} - template <> __device__ __forceinline__ float readScalar(int i) {return scalar_32f[i];} - template <> __device__ __forceinline__ double readScalar(int i) {return scalar_64f[i];} - - void writeScalar(const uchar* vals) - { - cudaSafeCall( cudaMemcpyToSymbol(scalar_8u, vals, sizeof(uchar) * 4) ); - } - void writeScalar(const schar* vals) - { - cudaSafeCall( cudaMemcpyToSymbol(scalar_8s, vals, sizeof(schar) * 4) ); - } - void writeScalar(const ushort* vals) - { - cudaSafeCall( cudaMemcpyToSymbol(scalar_16u, vals, sizeof(ushort) * 4) ); - } - void writeScalar(const short* vals) - { - cudaSafeCall( cudaMemcpyToSymbol(scalar_16s, vals, sizeof(short) * 4) ); - } - void writeScalar(const int* vals) - { - cudaSafeCall( cudaMemcpyToSymbol(scalar_32s, vals, sizeof(int) * 4) ); - } - void writeScalar(const float* vals) - { - cudaSafeCall( cudaMemcpyToSymbol(scalar_32f, vals, sizeof(float) * 4) ); - } - void writeScalar(const double* vals) - { - cudaSafeCall( cudaMemcpyToSymbol(scalar_64f, vals, sizeof(double) * 4) ); - } - - template - __global__ void set_to_without_mask(T* mat, int cols, int rows, size_t step, int channels) - { - size_t x = blockIdx.x * blockDim.x + threadIdx.x; - size_t y = blockIdx.y * blockDim.y + threadIdx.y; - - if ((x < cols * channels ) && (y < rows)) - { - size_t idx = y * ( step >> shift_and_sizeof::shift ) + x; - mat[idx] = readScalar(x % channels); - } - } - - template - __global__ void set_to_with_mask(T* mat, const uchar* mask, int cols, int rows, size_t step, int channels, size_t step_mask) - { - size_t x = blockIdx.x * blockDim.x + threadIdx.x; - size_t y = blockIdx.y * blockDim.y + threadIdx.y; - - if ((x < cols * channels ) && (y < rows)) - if (mask[y * step_mask + x / channels] != 0) - { - size_t idx = y * ( step >> shift_and_sizeof::shift ) + x; - mat[idx] = readScalar(x % channels); - } - } - template - void set_to_gpu(PtrStepSzb mat, const T* scalar, PtrStepSzb mask, int channels, cudaStream_t stream) - { - writeScalar(scalar); - - dim3 threadsPerBlock(32, 8, 1); - dim3 numBlocks (mat.cols * channels / threadsPerBlock.x + 1, mat.rows / threadsPerBlock.y + 1, 1); - - set_to_with_mask<<>>((T*)mat.data, (uchar*)mask.data, mat.cols, mat.rows, mat.step, channels, mask.step); - cudaSafeCall( cudaGetLastError() ); - - if (stream == 0) - cudaSafeCall ( cudaDeviceSynchronize() ); - } - - template void set_to_gpu(PtrStepSzb mat, const uchar* scalar, PtrStepSzb mask, int channels, cudaStream_t stream); - template void set_to_gpu(PtrStepSzb mat, const schar* scalar, PtrStepSzb mask, int channels, cudaStream_t stream); - template void set_to_gpu(PtrStepSzb mat, const ushort* scalar, PtrStepSzb mask, int channels, cudaStream_t stream); - template void set_to_gpu(PtrStepSzb mat, const short* scalar, PtrStepSzb mask, int channels, cudaStream_t stream); - template void set_to_gpu(PtrStepSzb mat, const int* scalar, PtrStepSzb mask, int channels, cudaStream_t stream); - template void set_to_gpu(PtrStepSzb mat, const float* scalar, PtrStepSzb mask, int channels, cudaStream_t stream); - template void set_to_gpu(PtrStepSzb mat, const double* scalar, PtrStepSzb mask, int channels, cudaStream_t stream); - - template - void set_to_gpu(PtrStepSzb mat, const T* scalar, int channels, cudaStream_t stream) - { - writeScalar(scalar); - - dim3 threadsPerBlock(32, 8, 1); - dim3 numBlocks (mat.cols * channels / threadsPerBlock.x + 1, mat.rows / threadsPerBlock.y + 1, 1); - - set_to_without_mask<<>>((T*)mat.data, mat.cols, mat.rows, mat.step, channels); - cudaSafeCall( cudaGetLastError() ); - - if (stream == 0) - cudaSafeCall ( cudaDeviceSynchronize() ); - } - - template void set_to_gpu(PtrStepSzb mat, const uchar* scalar, int channels, cudaStream_t stream); - template void set_to_gpu(PtrStepSzb mat, const schar* scalar, int channels, cudaStream_t stream); - template void set_to_gpu(PtrStepSzb mat, const ushort* scalar, int channels, cudaStream_t stream); - template void set_to_gpu(PtrStepSzb mat, const short* scalar, int channels, cudaStream_t stream); - template void set_to_gpu(PtrStepSzb mat, const int* scalar, int channels, cudaStream_t stream); - template void set_to_gpu(PtrStepSzb mat, const float* scalar, int channels, cudaStream_t stream); - template void set_to_gpu(PtrStepSzb mat, const double* scalar, int channels, cudaStream_t stream); - - /////////////////////////////////////////////////////////////////////////// - //////////////////////////////// ConvertTo //////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - template struct Convertor : unary_function - { - Convertor(S alpha_, S beta_) : alpha(alpha_), beta(beta_) {} - - __device__ __forceinline__ D operator()(typename TypeTraits::ParameterType src) const - { - return saturate_cast(alpha * src + beta); - } - - S alpha, beta; - }; - - namespace detail - { - template struct ConvertTraitsDispatcher : DefaultTransformFunctorTraits - { - }; - template struct ConvertTraitsDispatcher<1, 1, F> : DefaultTransformFunctorTraits - { - enum { smart_shift = 8 }; - }; - template struct ConvertTraitsDispatcher<1, 2, F> : DefaultTransformFunctorTraits - { - enum { smart_shift = 4 }; - }; - template struct ConvertTraitsDispatcher<1, 4, F> : DefaultTransformFunctorTraits - { - enum { smart_block_dim_y = 8 }; - enum { smart_shift = 4 }; - }; - - template struct ConvertTraitsDispatcher<2, 2, F> : DefaultTransformFunctorTraits - { - enum { smart_shift = 4 }; - }; - template struct ConvertTraitsDispatcher<2, 4, F> : DefaultTransformFunctorTraits - { - enum { smart_shift = 2 }; - }; - - template struct ConvertTraitsDispatcher<4, 2, F> : DefaultTransformFunctorTraits - { - enum { smart_block_dim_y = 8 }; - enum { smart_shift = 4 }; - }; - template struct ConvertTraitsDispatcher<4, 4, F> : DefaultTransformFunctorTraits - { - enum { smart_block_dim_y = 8 }; - enum { smart_shift = 2 }; - }; - - template struct ConvertTraits : ConvertTraitsDispatcher - { - }; - } - - template struct TransformFunctorTraits< Convertor > : detail::ConvertTraits< Convertor > - { - }; - - template - void cvt_(PtrStepSzb src, PtrStepSzb dst, double alpha, double beta, cudaStream_t stream) - { - cudaSafeCall( cudaSetDoubleForDevice(&alpha) ); - cudaSafeCall( cudaSetDoubleForDevice(&beta) ); - Convertor op(static_cast(alpha), static_cast(beta)); - cv::gpu::device::transform((PtrStepSz)src, (PtrStepSz)dst, op, WithOutMask(), stream); - } - -#if defined __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wmissing-declarations" -#endif - - void convert_gpu(PtrStepSzb src, int sdepth, PtrStepSzb dst, int ddepth, double alpha, double beta, cudaStream_t stream) - { - typedef void (*caller_t)(PtrStepSzb src, PtrStepSzb dst, double alpha, double beta, cudaStream_t stream); - - static const caller_t tab[7][7] = - { - { - cvt_, - cvt_, - cvt_, - cvt_, - cvt_, - cvt_, - cvt_ - }, - { - cvt_, - cvt_, - cvt_, - cvt_, - cvt_, - cvt_, - cvt_ - }, - { - cvt_, - cvt_, - cvt_, - cvt_, - cvt_, - cvt_, - cvt_ - }, - { - cvt_, - cvt_, - cvt_, - cvt_, - cvt_, - cvt_, - cvt_ - }, - { - cvt_, - cvt_, - cvt_, - cvt_, - cvt_, - cvt_, - cvt_ - }, - { - cvt_, - cvt_, - cvt_, - cvt_, - cvt_, - cvt_, - cvt_ - }, - { - cvt_, - cvt_, - cvt_, - cvt_, - cvt_, - cvt_, - cvt_ - } - }; - - caller_t func = tab[sdepth][ddepth]; - func(src, dst, alpha, beta, stream); - } - -#if defined __clang__ -# pragma clang diagnostic pop -#endif -}}} // namespace cv { namespace gpu { namespace device diff --git a/modules/core/src/cudastream.cpp b/modules/core/src/cudastream.cpp deleted file mode 100644 index 6244af9e5e..0000000000 --- a/modules/core/src/cudastream.cpp +++ /dev/null @@ -1,352 +0,0 @@ -/*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 "precomp.hpp" -#include "opencv2/core/gpumat.hpp" - -using namespace cv; -using namespace cv::gpu; - -#if !defined (HAVE_CUDA) -#define throw_nogpu() CV_Error(CV_GpuNotSupported, "The library is compiled without CUDA support") - -cv::gpu::Stream::Stream() { throw_nogpu(); } -cv::gpu::Stream::~Stream() {} -cv::gpu::Stream::Stream(const Stream&) { throw_nogpu(); } -Stream& cv::gpu::Stream::operator=(const Stream&) { throw_nogpu(); return *this; } -bool cv::gpu::Stream::queryIfComplete() { throw_nogpu(); return false; } -void cv::gpu::Stream::waitForCompletion() { throw_nogpu(); } -void cv::gpu::Stream::enqueueDownload(const GpuMat&, Mat&) { throw_nogpu(); } -void cv::gpu::Stream::enqueueDownload(const GpuMat&, CudaMem&) { throw_nogpu(); } -void cv::gpu::Stream::enqueueUpload(const CudaMem&, GpuMat&) { throw_nogpu(); } -void cv::gpu::Stream::enqueueUpload(const Mat&, GpuMat&) { throw_nogpu(); } -void cv::gpu::Stream::enqueueCopy(const GpuMat&, GpuMat&) { throw_nogpu(); } -void cv::gpu::Stream::enqueueMemSet(GpuMat&, Scalar) { throw_nogpu(); } -void cv::gpu::Stream::enqueueMemSet(GpuMat&, Scalar, const GpuMat&) { throw_nogpu(); } -void cv::gpu::Stream::enqueueConvert(const GpuMat&, GpuMat&, int, double, double) { throw_nogpu(); } -void cv::gpu::Stream::enqueueHostCallback(StreamCallback, void*) { throw_nogpu(); } -Stream& cv::gpu::Stream::Null() { throw_nogpu(); static Stream s; return s; } -cv::gpu::Stream::operator bool() const { throw_nogpu(); return false; } -cv::gpu::Stream::Stream(Impl*) { throw_nogpu(); } -void cv::gpu::Stream::create() { throw_nogpu(); } -void cv::gpu::Stream::release() { throw_nogpu(); } - -#else /* !defined (HAVE_CUDA) */ - -#include "opencv2/core/stream_accessor.hpp" - -namespace cv { namespace gpu -{ - void copyWithMask(const GpuMat& src, GpuMat& dst, const GpuMat& mask, cudaStream_t stream); - void convertTo(const GpuMat& src, GpuMat& dst, double alpha, double beta, cudaStream_t stream); - void setTo(GpuMat& src, Scalar s, cudaStream_t stream); - void setTo(GpuMat& src, Scalar s, const GpuMat& mask, cudaStream_t stream); -}} - -struct Stream::Impl -{ - static cudaStream_t getStream(const Impl* impl) - { - return impl ? impl->stream : 0; - } - - cudaStream_t stream; - int ref_counter; -}; - -cudaStream_t cv::gpu::StreamAccessor::getStream(const Stream& stream) -{ - return Stream::Impl::getStream(stream.impl); -} - -cv::gpu::Stream::Stream() : impl(0) -{ - create(); -} - -cv::gpu::Stream::~Stream() -{ - release(); -} - -cv::gpu::Stream::Stream(const Stream& stream) : impl(stream.impl) -{ - if (impl) - CV_XADD(&impl->ref_counter, 1); -} - -Stream& cv::gpu::Stream::operator =(const Stream& stream) -{ - if (this != &stream) - { - release(); - impl = stream.impl; - if (impl) - CV_XADD(&impl->ref_counter, 1); - } - - return *this; -} - -bool cv::gpu::Stream::queryIfComplete() -{ - cudaStream_t stream = Impl::getStream(impl); - cudaError_t err = cudaStreamQuery(stream); - - if (err == cudaErrorNotReady || err == cudaSuccess) - return err == cudaSuccess; - - cudaSafeCall(err); - return false; -} - -void cv::gpu::Stream::waitForCompletion() -{ - cudaStream_t stream = Impl::getStream(impl); - cudaSafeCall( cudaStreamSynchronize(stream) ); -} - -void cv::gpu::Stream::enqueueDownload(const GpuMat& src, Mat& dst) -{ - // if not -> allocation will be done, but after that dst will not point to page locked memory - CV_Assert( src.size() == dst.size() && src.type() == dst.type() ); - - cudaStream_t stream = Impl::getStream(impl); - size_t bwidth = src.cols * src.elemSize(); - cudaSafeCall( cudaMemcpy2DAsync(dst.data, dst.step, src.data, src.step, bwidth, src.rows, cudaMemcpyDeviceToHost, stream) ); -} - -void cv::gpu::Stream::enqueueDownload(const GpuMat& src, CudaMem& dst) -{ - dst.create(src.size(), src.type(), CudaMem::ALLOC_PAGE_LOCKED); - - cudaStream_t stream = Impl::getStream(impl); - size_t bwidth = src.cols * src.elemSize(); - cudaSafeCall( cudaMemcpy2DAsync(dst.data, dst.step, src.data, src.step, bwidth, src.rows, cudaMemcpyDeviceToHost, stream) ); -} - -void cv::gpu::Stream::enqueueUpload(const CudaMem& src, GpuMat& dst) -{ - dst.create(src.size(), src.type()); - - cudaStream_t stream = Impl::getStream(impl); - size_t bwidth = src.cols * src.elemSize(); - cudaSafeCall( cudaMemcpy2DAsync(dst.data, dst.step, src.data, src.step, bwidth, src.rows, cudaMemcpyHostToDevice, stream) ); -} - -void cv::gpu::Stream::enqueueUpload(const Mat& src, GpuMat& dst) -{ - dst.create(src.size(), src.type()); - - cudaStream_t stream = Impl::getStream(impl); - size_t bwidth = src.cols * src.elemSize(); - cudaSafeCall( cudaMemcpy2DAsync(dst.data, dst.step, src.data, src.step, bwidth, src.rows, cudaMemcpyHostToDevice, stream) ); -} - -void cv::gpu::Stream::enqueueCopy(const GpuMat& src, GpuMat& dst) -{ - dst.create(src.size(), src.type()); - - cudaStream_t stream = Impl::getStream(impl); - size_t bwidth = src.cols * src.elemSize(); - cudaSafeCall( cudaMemcpy2DAsync(dst.data, dst.step, src.data, src.step, bwidth, src.rows, cudaMemcpyDeviceToDevice, stream) ); -} - -void cv::gpu::Stream::enqueueMemSet(GpuMat& src, Scalar val) -{ - const int sdepth = src.depth(); - - if (sdepth == CV_64F) - { - if (!deviceSupports(NATIVE_DOUBLE)) - CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); - } - - cudaStream_t stream = Impl::getStream(impl); - - if (val[0] == 0.0 && val[1] == 0.0 && val[2] == 0.0 && val[3] == 0.0) - { - cudaSafeCall( cudaMemset2DAsync(src.data, src.step, 0, src.cols * src.elemSize(), src.rows, stream) ); - return; - } - - if (sdepth == CV_8U) - { - int cn = src.channels(); - - if (cn == 1 || (cn == 2 && val[0] == val[1]) || (cn == 3 && val[0] == val[1] && val[0] == val[2]) || (cn == 4 && val[0] == val[1] && val[0] == val[2] && val[0] == val[3])) - { - int ival = saturate_cast(val[0]); - cudaSafeCall( cudaMemset2DAsync(src.data, src.step, ival, src.cols * src.elemSize(), src.rows, stream) ); - return; - } - } - - setTo(src, val, stream); -} - -void cv::gpu::Stream::enqueueMemSet(GpuMat& src, Scalar val, const GpuMat& mask) -{ - const int sdepth = src.depth(); - - if (sdepth == CV_64F) - { - if (!deviceSupports(NATIVE_DOUBLE)) - CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); - } - - CV_Assert(mask.type() == CV_8UC1); - - cudaStream_t stream = Impl::getStream(impl); - - setTo(src, val, mask, stream); -} - -void cv::gpu::Stream::enqueueConvert(const GpuMat& src, GpuMat& dst, int dtype, double alpha, double beta) -{ - if (dtype < 0) - dtype = src.type(); - else - dtype = CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src.channels()); - - const int sdepth = src.depth(); - const int ddepth = CV_MAT_DEPTH(dtype); - - if (sdepth == CV_64F || ddepth == CV_64F) - { - if (!deviceSupports(NATIVE_DOUBLE)) - CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); - } - - bool noScale = fabs(alpha - 1) < std::numeric_limits::epsilon() - && fabs(beta) < std::numeric_limits::epsilon(); - - if (sdepth == ddepth && noScale) - { - enqueueCopy(src, dst); - return; - } - - dst.create(src.size(), dtype); - - cudaStream_t stream = Impl::getStream(impl); - convertTo(src, dst, alpha, beta, stream); -} - -#if CUDA_VERSION >= 5000 - -namespace -{ - struct CallbackData - { - cv::gpu::Stream::StreamCallback callback; - void* userData; - Stream stream; - }; - - void CUDART_CB cudaStreamCallback(cudaStream_t, cudaError_t status, void* userData) - { - CallbackData* data = reinterpret_cast(userData); - data->callback(data->stream, static_cast(status), data->userData); - delete data; - } -} - -#endif - -void cv::gpu::Stream::enqueueHostCallback(StreamCallback callback, void* userData) -{ -#if CUDA_VERSION >= 5000 - CallbackData* data = new CallbackData; - data->callback = callback; - data->userData = userData; - data->stream = *this; - - cudaStream_t stream = Impl::getStream(impl); - - cudaSafeCall( cudaStreamAddCallback(stream, cudaStreamCallback, data, 0) ); -#else - (void) callback; - (void) userData; - CV_Error(CV_StsNotImplemented, "This function requires CUDA 5.0"); -#endif -} - -cv::gpu::Stream& cv::gpu::Stream::Null() -{ - static Stream s((Impl*) 0); - return s; -} - -cv::gpu::Stream::operator bool() const -{ - return impl && impl->stream; -} - -cv::gpu::Stream::Stream(Impl* impl_) : impl(impl_) -{ -} - -void cv::gpu::Stream::create() -{ - if (impl) - release(); - - cudaStream_t stream; - cudaSafeCall( cudaStreamCreate( &stream ) ); - - impl = (Stream::Impl*) fastMalloc(sizeof(Stream::Impl)); - - impl->stream = stream; - impl->ref_counter = 1; -} - -void cv::gpu::Stream::release() -{ - if (impl && CV_XADD(&impl->ref_counter, -1) == 1) - { - cudaSafeCall( cudaStreamDestroy(impl->stream) ); - cv::fastFree(impl); - } -} - -#endif /* !defined (HAVE_CUDA) */ diff --git a/modules/core/src/datastructs.cpp b/modules/core/src/datastructs.cpp index c927c9e22f..ae2375ad6d 100644 --- a/modules/core/src/datastructs.cpp +++ b/modules/core/src/datastructs.cpp @@ -40,6 +40,12 @@ //M*/ #include "precomp.hpp" +/* default alignment for dynamic data strucutures, resided in storages. */ +#define CV_STRUCT_ALIGN ((int)sizeof(double)) + +/* default storage block size */ +#define CV_STORAGE_BLOCK_SIZE ((1<<16) - 128) + #define ICV_FREE_PTR(storage) \ ((schar*)(storage)->top + (storage)->block_size - (storage)->free_space) diff --git a/modules/core/src/drawing.cpp b/modules/core/src/drawing.cpp index 8850c6ec4c..5cc498256b 100644 --- a/modules/core/src/drawing.cpp +++ b/modules/core/src/drawing.cpp @@ -886,12 +886,16 @@ void ellipse2Poly( Point center, Size axes, int angle, Point pt; pt.x = cvRound( cx + x * alpha - y * beta ); pt.y = cvRound( cy + x * beta + y * alpha ); - if( pt != prevPt ) + if( pt != prevPt ){ pts.push_back(pt); + prevPt = pt; + } } - if( pts.size() < 2 ) - pts.push_back(pts[0]); + // If there are no points, it's a zero-size polygon + if( pts.size() == 1) { + pts.assign(2,center); + } } @@ -1914,7 +1918,7 @@ static const int* getFontData(int fontFace) } -void putText( Mat& img, const std::string& text, Point org, +void putText( Mat& img, const String& text, Point org, int fontFace, double fontScale, Scalar color, int thickness, int line_type, bool bottomLeftOrigin ) @@ -1976,7 +1980,7 @@ void putText( Mat& img, const std::string& text, Point org, } } -Size getTextSize( const std::string& text, int fontFace, double fontScale, int thickness, int* _base_line) +Size getTextSize( const String& text, int fontFace, double fontScale, int thickness, int* _base_line) { Size size; double view_x = 0; @@ -2341,7 +2345,7 @@ cvColorToScalar( double packed_color, int type ) } else { - scalar.val[0] = CV_CAST_8U( icolor ); + scalar.val[0] = cv::saturate_cast( icolor ); scalar.val[1] = scalar.val[2] = scalar.val[3] = 0; } } @@ -2357,7 +2361,7 @@ cvColorToScalar( double packed_color, int type ) } else { - scalar.val[0] = CV_CAST_8S( icolor ); + scalar.val[0] = cv::saturate_cast( icolor ); scalar.val[1] = scalar.val[2] = scalar.val[3] = 0; } } diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index b3c2b833b4..a802868df0 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -50,6 +50,13 @@ namespace cv # pragma warning(disable: 4748) #endif +#if defined HAVE_IPP && IPP_VERSION_MAJOR >= 7 +#define USE_IPP_DFT 1 +#else +#undef USE_IPP_DFT +#endif + + /****************************************************************************************\ Discrete Fourier Transform \****************************************************************************************/ @@ -455,7 +462,7 @@ template<> struct DFT_VecR4 #endif -#ifdef HAVE_IPP +#ifdef USE_IPP_DFT static void ippsDFTFwd_CToC( const Complex* src, Complex* dst, const void* spec, uchar* buf) { @@ -517,7 +524,7 @@ DFT( const Complex* src, Complex* dst, int n, int nf, const int* factors, const int* itab, const Complex* wave, int tab_size, const void* -#ifdef HAVE_IPP +#ifdef USE_IPP_DFT spec #endif , Complex* buf, @@ -537,7 +544,7 @@ DFT( const Complex* src, Complex* dst, int n, T scale = (T)_scale; int tab_step; -#ifdef HAVE_IPP +#ifdef USE_IPP_DFT if( spec ) { if( !inv ) @@ -957,7 +964,7 @@ DFT( const Complex* src, Complex* dst, int n, template static void RealDFT( const T* src, T* dst, int n, int nf, int* factors, const int* itab, const Complex* wave, int tab_size, const void* -#ifdef HAVE_IPP +#ifdef USE_IPP_DFT spec #endif , @@ -968,11 +975,18 @@ RealDFT( const T* src, T* dst, int n, int nf, int* factors, const int* itab, int j, n2 = n >> 1; dst += complex_output; -#ifdef HAVE_IPP +#ifdef USE_IPP_DFT if( spec ) { ippsDFTFwd_RToPack( src, dst, spec, (uchar*)buf ); - goto finalize; + if( complex_output ) + { + dst[-1] = dst[0]; + dst[0] = 0; + if( (n & 1) == 0 ) + dst[n] = 0; + } + return; } #endif assert( tab_size == n ); @@ -1056,15 +1070,11 @@ RealDFT( const T* src, T* dst, int n, int nf, int* factors, const int* itab, } } -#ifdef HAVE_IPP -finalize: -#endif if( complex_output && (n & 1) == 0 ) { dst[-1] = dst[0]; dst[0] = 0; - if( (n & 1) == 0 ) - dst[n] = 0; + dst[n] = 0; } } @@ -1076,7 +1086,7 @@ template static void CCSIDFT( const T* src, T* dst, int n, int nf, int* factors, const int* itab, const Complex* wave, int tab_size, const void* -#ifdef HAVE_IPP +#ifdef USE_IPP_DFT spec #endif , Complex* buf, @@ -1097,7 +1107,7 @@ CCSIDFT( const T* src, T* dst, int n, int nf, int* factors, const int* itab, ((T*)src)[1] = src[0]; src++; } -#ifdef HAVE_IPP +#ifdef USE_IPP_DFT if( spec ) { ippsDFTInv_PackToR( src, dst, spec, (uchar*)buf ); @@ -1225,7 +1235,7 @@ CCSIDFT( const T* src, T* dst, int n, int nf, int* factors, const int* itab, } } -#ifdef HAVE_IPP +#ifdef USE_IPP_DFT finalize: #endif if( complex_input ) @@ -1458,6 +1468,10 @@ static void CCSIDFT_64f( const double* src, double* dst, int n, int nf, int* fac } +#ifdef USE_IPP_DFT +typedef IppStatus (CV_STDCALL* IppDFTGetSizeFunc)(int, int, IppHintAlgorithm, int*, int*, int*); +typedef IppStatus (CV_STDCALL* IppDFTInitFunc)(int, int, IppHintAlgorithm, void*, uchar*); +#endif void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) { @@ -1482,8 +1496,8 @@ void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) int elem_size = (int)src.elemSize1(), complex_elem_size = elem_size*2; int factors[34]; bool inplace_transform = false; -#ifdef HAVE_IPP - void *spec_r = 0, *spec_c = 0; +#ifdef USE_IPP_DFT + AutoBuffer ippbuf; int ipp_norm_flag = !(flags & DFT_SCALE) ? 8 : inv ? 2 : 1; #endif @@ -1542,53 +1556,48 @@ void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) } spec = 0; -#ifdef HAVE_IPP +#ifdef USE_IPP_DFT if( len*count >= 64 ) // use IPP DFT if available { - int ipp_sz = 0; + int specsize=0, initsize=0, worksize=0; + IppDFTGetSizeFunc getSizeFunc = 0; + IppDFTInitFunc initFunc = 0; if( real_transform && stage == 0 ) { if( depth == CV_32F ) { - if( spec_r ) - IPPI_CALL( ippsDFTFree_R_32f( (IppsDFTSpec_R_32f*)spec_r )); - IPPI_CALL( ippsDFTInitAlloc_R_32f( - (IppsDFTSpec_R_32f**)&spec_r, len, ipp_norm_flag, ippAlgHintNone )); - IPPI_CALL( ippsDFTGetBufSize_R_32f( (IppsDFTSpec_R_32f*)spec_r, &ipp_sz )); + getSizeFunc = ippsDFTGetSize_R_32f; + initFunc = (IppDFTInitFunc)ippsDFTInit_R_32f; } else { - if( spec_r ) - IPPI_CALL( ippsDFTFree_R_64f( (IppsDFTSpec_R_64f*)spec_r )); - IPPI_CALL( ippsDFTInitAlloc_R_64f( - (IppsDFTSpec_R_64f**)&spec_r, len, ipp_norm_flag, ippAlgHintNone )); - IPPI_CALL( ippsDFTGetBufSize_R_64f( (IppsDFTSpec_R_64f*)spec_r, &ipp_sz )); + getSizeFunc = ippsDFTGetSize_R_64f; + initFunc = (IppDFTInitFunc)ippsDFTInit_R_64f; } - spec = spec_r; } else { if( depth == CV_32F ) { - if( spec_c ) - IPPI_CALL( ippsDFTFree_C_32fc( (IppsDFTSpec_C_32fc*)spec_c )); - IPPI_CALL( ippsDFTInitAlloc_C_32fc( - (IppsDFTSpec_C_32fc**)&spec_c, len, ipp_norm_flag, ippAlgHintNone )); - IPPI_CALL( ippsDFTGetBufSize_C_32fc( (IppsDFTSpec_C_32fc*)spec_c, &ipp_sz )); + getSizeFunc = ippsDFTGetSize_C_32fc; + initFunc = (IppDFTInitFunc)ippsDFTInit_C_32fc; } else { - if( spec_c ) - IPPI_CALL( ippsDFTFree_C_64fc( (IppsDFTSpec_C_64fc*)spec_c )); - IPPI_CALL( ippsDFTInitAlloc_C_64fc( - (IppsDFTSpec_C_64fc**)&spec_c, len, ipp_norm_flag, ippAlgHintNone )); - IPPI_CALL( ippsDFTGetBufSize_C_64fc( (IppsDFTSpec_C_64fc*)spec_c, &ipp_sz )); + getSizeFunc = ippsDFTGetSize_C_64fc; + initFunc = (IppDFTInitFunc)ippsDFTInit_C_64fc; } - spec = spec_c; } - - sz += ipp_sz; + if( getSizeFunc(len, ipp_norm_flag, ippAlgHintNone, &specsize, &initsize, &worksize) >= 0 ) + { + ippbuf.allocate(specsize + initsize + 64); + spec = alignPtr(&ippbuf[0], 32); + uchar* initbuf = alignPtr((uchar*)spec + specsize, 32); + if( initFunc(len, ipp_norm_flag, ippAlgHintNone, spec, initbuf) < 0 ) + spec = 0; + sz += worksize; + } } else #endif @@ -1862,24 +1871,6 @@ void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) src = dst; } } - -#ifdef HAVE_IPP - if( spec_c ) - { - if( depth == CV_32F ) - ippsDFTFree_C_32fc( (IppsDFTSpec_C_32fc*)spec_c ); - else - ippsDFTFree_C_64fc( (IppsDFTSpec_C_64fc*)spec_c ); - } - - if( spec_r ) - { - if( depth == CV_32F ) - ippsDFTFree_R_32f( (IppsDFTSpec_R_32f*)spec_r ); - else - ippsDFTFree_R_64f( (IppsDFTSpec_R_64f*)spec_r ); - } -#endif } diff --git a/modules/core/src/gl_core_3_1.cpp b/modules/core/src/gl_core_3_1.cpp index 61006f5cac..48201b4b76 100644 --- a/modules/core/src/gl_core_3_1.cpp +++ b/modules/core/src/gl_core_3_1.cpp @@ -1,7 +1,46 @@ -#include -#include -#include "cvconfig.h" -#include "opencv2/core.hpp" +/*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 "precomp.hpp" #include "gl_core_3_1.hpp" #ifdef HAVE_OPENGL @@ -15,8 +54,8 @@ image = NSAddImage("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", NSADDIMAGE_OPTION_RETURN_ON_ERROR); // prepend a '_' for the Unix C symbol mangling convention - std::string symbolName = "_"; - symbolName += std::string(name); + String symbolName = "_"; + symbolName += String(name); NSSymbol symbol = image ? NSLookupSymbolInImage(image, &symbolName[0], NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR) : 0; @@ -94,16 +133,14 @@ void* func = (void*) CV_GL_GET_PROC_ADDRESS(name); if (!func) { - std::ostringstream msg; - msg << "Can't load OpenGL extension [" << name << "]"; - CV_Error(CV_OpenGlApiCallError, msg.str()); + CV_Error(cv::Error::OpenGlApiCallError, cv::format("Can't load OpenGL extension [%s]", name) ); } return func; } #else static void* IntGetProcAddress(const char*) { - CV_Error(CV_OpenGlNotSupported, "The library is compiled without OpenGL support"); + CV_Error(cv::Error::OpenGlNotSupported, "The library is compiled without OpenGL support"); return 0; } #endif diff --git a/modules/core/src/gl_core_3_1.hpp b/modules/core/src/gl_core_3_1.hpp index 50dbee66c7..f86390169e 100644 --- a/modules/core/src/gl_core_3_1.hpp +++ b/modules/core/src/gl_core_3_1.hpp @@ -1,3 +1,45 @@ +/*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 OPENGL_NOLOAD_STYLE_HPP #define OPENGL_NOLOAD_STYLE_HPP diff --git a/modules/core/src/glob.cpp b/modules/core/src/glob.cpp index 4659c21d89..c75bd2e66b 100644 --- a/modules/core/src/glob.cpp +++ b/modules/core/src/glob.cpp @@ -56,19 +56,42 @@ namespace struct DIR { +#ifdef HAVE_WINRT + WIN32_FIND_DATAW data; +#else WIN32_FIND_DATA data; +#endif HANDLE handle; dirent ent; +#ifdef HAVE_WINRT + DIR() {}; + ~DIR() + { + if (ent.d_name) + delete[] ent.d_name; + } +#endif }; DIR* opendir(const char* path) { DIR* dir = new DIR; dir->ent.d_name = 0; - dir->handle = ::FindFirstFileA((std::string(path) + "\\*").c_str(), &dir->data); +#ifdef HAVE_WINRT + cv::String full_path = cv::String(path) + "\\*"; + wchar_t wfull_path[MAX_PATH]; + size_t copied = mbstowcs(wfull_path, full_path.c_str(), MAX_PATH); + CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1)); + dir->handle = ::FindFirstFileExW(wfull_path, FindExInfoStandard, + &dir->data, FindExSearchNameMatch, NULL, 0); +#else + dir->handle = ::FindFirstFileExA((cv::String(path) + "\\*").c_str(), + FindExInfoStandard, &dir->data, FindExSearchNameMatch, NULL, 0); +#endif if(dir->handle == INVALID_HANDLE_VALUE) { /*closedir will do all cleanup*/ + delete dir; return 0; } return dir; @@ -76,12 +99,26 @@ namespace dirent* readdir(DIR* dir) { +#ifdef HAVE_WINRT if (dir->ent.d_name != 0) { - if (::FindNextFile(dir->handle, &dir->data) != TRUE) + if (::FindNextFileW(dir->handle, &dir->data) != TRUE) + return 0; + } + size_t asize = wcstombs(NULL, dir->data.cFileName, 0); + CV_Assert((asize != 0) && (asize != (size_t)-1)); + char* aname = new char[asize+1]; + aname[asize] = 0; + wcstombs(aname, dir->data.cFileName, asize); + dir->ent.d_name = aname; +#else + if (dir->ent.d_name != 0) + { + if (::FindNextFileA(dir->handle, &dir->data) != TRUE) return 0; } dir->ent.d_name = dir->data.cFileName; +#endif return &dir->ent; } @@ -100,22 +137,34 @@ const char dir_separators[] = "/"; const char native_separator = '/'; #endif -static bool isDir(const std::string& path, DIR* dir) +static bool isDir(const cv::String& path, DIR* dir) { #if defined WIN32 || defined _WIN32 || defined WINCE DWORD attributes; + BOOL status = TRUE; if (dir) attributes = dir->data.dwFileAttributes; else - attributes = ::GetFileAttributes(path.c_str()); - - return (attributes != INVALID_FILE_ATTRIBUTES) && ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0); + { + WIN32_FILE_ATTRIBUTE_DATA all_attrs; +#ifdef HAVE_WINRT + wchar_t wpath[MAX_PATH]; + size_t copied = mbstowcs(wpath, path.c_str(), MAX_PATH); + CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1)); + status = ::GetFileAttributesExW(wpath, GetFileExInfoStandard, &all_attrs); #else - struct stat stat_buf; - stat( path.c_str(), &stat_buf); - int is_dir = S_ISDIR( stat_buf.st_mode); - (void)dir; + status = ::GetFileAttributesExA(path.c_str(), GetFileExInfoStandard, &all_attrs); +#endif + attributes = all_attrs.dwFileAttributes; + } + return status && ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0); +#else + (void)dir; + struct stat stat_buf; + if (0 != stat( path.c_str(), &stat_buf)) + return false; + int is_dir = S_ISDIR( stat_buf.st_mode); return is_dir != 0; #endif } @@ -168,10 +217,11 @@ static bool wildcmp(const char *string, const char *wild) return *wild == 0; } -static void glob_rec(const std::string& directory, const std::string& wildchart, std::vector& result, bool recursive) +static void glob_rec(const cv::String& directory, const cv::String& wildchart, std::vector& result, bool recursive) { DIR *dir; struct dirent *ent; + if ((dir = opendir (directory.c_str())) != 0) { /* find all the files and directories within directory */ @@ -183,7 +233,7 @@ static void glob_rec(const std::string& directory, const std::string& wildchart, if((name[0] == 0) || (name[0] == '.' && name[1] == 0) || (name[0] == '.' && name[1] == '.' && name[2] == 0)) continue; - std::string path = directory + native_separator + name; + cv::String path = directory + native_separator + name; if (isDir(path, dir)) { @@ -207,14 +257,13 @@ static void glob_rec(const std::string& directory, const std::string& wildchart, else CV_Error(CV_StsObjectNotFound, cv::format("could not open directory: %s", directory.c_str())); } -void cv::glob(std::string pattern, std::vector& result, bool recursive) +void cv::glob(String pattern, std::vector& result, bool recursive) { result.clear(); - std::string path, wildchart; + String path, wildchart; if (isDir(pattern, 0)) { - printf("WE ARE HERE: %s\n", pattern.c_str()); if(strchr(dir_separators, pattern[pattern.size() - 1]) != 0) { path = pattern.substr(0, pattern.size() - 1); @@ -227,7 +276,7 @@ void cv::glob(std::string pattern, std::vector& result, bool recurs else { size_t pos = pattern.find_last_of(dir_separators); - if (pos == std::string::npos) + if (pos == String::npos) { wildchart = pattern; path = "."; @@ -241,4 +290,4 @@ void cv::glob(std::string pattern, std::vector& result, bool recurs glob_rec(path, wildchart, result, recursive); std::sort(result.begin(), result.end()); -} \ No newline at end of file +} diff --git a/modules/core/src/gpu_cuda_mem.cpp b/modules/core/src/gpu_cuda_mem.cpp new file mode 100644 index 0000000000..52de069cbc --- /dev/null +++ b/modules/core/src/gpu_cuda_mem.cpp @@ -0,0 +1,215 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "precomp.hpp" + +using namespace cv; +using namespace cv::gpu; + +namespace +{ + size_t alignUpStep(size_t what, size_t alignment) + { + size_t alignMask = alignment - 1; + size_t inverseAlignMask = ~alignMask; + size_t res = (what + alignMask) & inverseAlignMask; + return res; + } +} + +void cv::gpu::CudaMem::create(int rows_, int cols_, int type_) +{ +#ifndef HAVE_CUDA + (void) rows_; + (void) cols_; + (void) type_; + throw_no_cuda(); +#else + if (alloc_type == SHARED) + { + DeviceInfo devInfo; + CV_Assert( devInfo.canMapHostMemory() ); + } + + type_ &= Mat::TYPE_MASK; + + if (rows == rows_ && cols == cols_ && type() == type_ && data) + return; + + if (data) + release(); + + CV_DbgAssert( rows_ >= 0 && cols_ >= 0 ); + + if (rows_ > 0 && cols_ > 0) + { + flags = Mat::MAGIC_VAL + Mat::CONTINUOUS_FLAG + type_; + rows = rows_; + cols = cols_; + step = elemSize() * cols; + + if (alloc_type == SHARED) + { + DeviceInfo devInfo; + step = alignUpStep(step, devInfo.textureAlignment()); + } + + int64 _nettosize = (int64)step*rows; + size_t nettosize = (size_t)_nettosize; + + if (_nettosize != (int64)nettosize) + CV_Error(cv::Error::StsNoMem, "Too big buffer is allocated"); + + size_t datasize = alignSize(nettosize, (int)sizeof(*refcount)); + + void* ptr = 0; + + switch (alloc_type) + { + case PAGE_LOCKED: cudaSafeCall( cudaHostAlloc(&ptr, datasize, cudaHostAllocDefault) ); break; + case SHARED: cudaSafeCall( cudaHostAlloc(&ptr, datasize, cudaHostAllocMapped) ); break; + case WRITE_COMBINED: cudaSafeCall( cudaHostAlloc(&ptr, datasize, cudaHostAllocWriteCombined) ); break; + default: CV_Error(cv::Error::StsBadFlag, "Invalid alloc type"); + } + + datastart = data = (uchar*)ptr; + dataend = data + nettosize; + + refcount = (int*)cv::fastMalloc(sizeof(*refcount)); + *refcount = 1; + } +#endif +} + +CudaMem cv::gpu::CudaMem::reshape(int new_cn, int new_rows) const +{ + CudaMem hdr = *this; + + int cn = channels(); + if (new_cn == 0) + new_cn = cn; + + int total_width = cols * cn; + + if ((new_cn > total_width || total_width % new_cn != 0) && new_rows == 0) + new_rows = rows * total_width / new_cn; + + if (new_rows != 0 && new_rows != rows) + { + int total_size = total_width * rows; + + if (!isContinuous()) + CV_Error(cv::Error::BadStep, "The matrix is not continuous, thus its number of rows can not be changed"); + + if ((unsigned)new_rows > (unsigned)total_size) + CV_Error(cv::Error::StsOutOfRange, "Bad new number of rows"); + + total_width = total_size / new_rows; + + if (total_width * new_rows != total_size) + CV_Error(cv::Error::StsBadArg, "The total number of matrix elements is not divisible by the new number of rows"); + + hdr.rows = new_rows; + hdr.step = total_width * elemSize1(); + } + + int new_width = total_width / new_cn; + + if (new_width * new_cn != total_width) + CV_Error(cv::Error::BadNumChannels, "The total width is not divisible by the new number of channels"); + + hdr.cols = new_width; + hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn - 1) << CV_CN_SHIFT); + + return hdr; +} + +void cv::gpu::CudaMem::release() +{ +#ifdef HAVE_CUDA + if (refcount && CV_XADD(refcount, -1) == 1) + { + cudaFreeHost(datastart); + fastFree(refcount); + } + + data = datastart = dataend = 0; + step = rows = cols = 0; + refcount = 0; +#endif +} + +GpuMat cv::gpu::CudaMem::createGpuMatHeader() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return GpuMat(); +#else + CV_Assert( alloc_type == SHARED ); + + void *pdev; + cudaSafeCall( cudaHostGetDevicePointer(&pdev, data, 0) ); + + return GpuMat(rows, cols, type(), pdev, step); +#endif +} + +void cv::gpu::registerPageLocked(Mat& m) +{ +#ifndef HAVE_CUDA + (void) m; + throw_no_cuda(); +#else + CV_Assert( m.isContinuous() ); + cudaSafeCall( cudaHostRegister(m.data, m.step * m.rows, cudaHostRegisterPortable) ); +#endif +} + +void cv::gpu::unregisterPageLocked(Mat& m) +{ +#ifndef HAVE_CUDA + (void) m; +#else + cudaSafeCall( cudaHostUnregister(m.data) ); +#endif +} diff --git a/modules/core/src/gpu_info.cpp b/modules/core/src/gpu_info.cpp new file mode 100644 index 0000000000..5a1e567463 --- /dev/null +++ b/modules/core/src/gpu_info.cpp @@ -0,0 +1,1272 @@ +/*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 "precomp.hpp" + +using namespace cv; +using namespace cv::gpu; + +int cv::gpu::getCudaEnabledDeviceCount() +{ +#ifndef HAVE_CUDA + return 0; +#else + int count; + cudaError_t error = cudaGetDeviceCount(&count); + + if (error == cudaErrorInsufficientDriver) + return -1; + + if (error == cudaErrorNoDevice) + return 0; + + cudaSafeCall( error ); + return count; +#endif +} + +void cv::gpu::setDevice(int device) +{ +#ifndef HAVE_CUDA + (void) device; + throw_no_cuda(); +#else + cudaSafeCall( cudaSetDevice(device) ); +#endif +} + +int cv::gpu::getDevice() +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + int device; + cudaSafeCall( cudaGetDevice(&device) ); + return device; +#endif +} + +void cv::gpu::resetDevice() +{ +#ifndef HAVE_CUDA + throw_no_cuda(); +#else + cudaSafeCall( cudaDeviceReset() ); +#endif +} + +bool cv::gpu::deviceSupports(FeatureSet feature_set) +{ +#ifndef HAVE_CUDA + (void) feature_set; + throw_no_cuda(); + return false; +#else + static int versions[] = + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; + static const int cache_size = static_cast(sizeof(versions) / sizeof(versions[0])); + + const int devId = getDevice(); + + int version; + + if (devId < cache_size && versions[devId] >= 0) + { + version = versions[devId]; + } + else + { + DeviceInfo dev(devId); + version = dev.majorVersion() * 10 + dev.minorVersion(); + if (devId < cache_size) + versions[devId] = version; + } + + return TargetArchs::builtWith(feature_set) && (version >= feature_set); +#endif +} + +//////////////////////////////////////////////////////////////////////// +// TargetArchs + +#ifdef HAVE_CUDA + +namespace +{ + class CudaArch + { + public: + CudaArch(); + + bool builtWith(FeatureSet feature_set) const; + bool hasPtx(int major, int minor) const; + bool hasBin(int major, int minor) const; + bool hasEqualOrLessPtx(int major, int minor) const; + bool hasEqualOrGreaterPtx(int major, int minor) const; + bool hasEqualOrGreaterBin(int major, int minor) const; + + private: + static void fromStr(const char* set_as_str, std::vector& arr); + + std::vector bin; + std::vector ptx; + std::vector features; + }; + + const CudaArch cudaArch; + + CudaArch::CudaArch() + { + fromStr(CUDA_ARCH_BIN, bin); + fromStr(CUDA_ARCH_PTX, ptx); + fromStr(CUDA_ARCH_FEATURES, features); + } + + bool CudaArch::builtWith(FeatureSet feature_set) const + { + return !features.empty() && (features.back() >= feature_set); + } + + bool CudaArch::hasPtx(int major, int minor) const + { + return std::find(ptx.begin(), ptx.end(), major * 10 + minor) != ptx.end(); + } + + bool CudaArch::hasBin(int major, int minor) const + { + return std::find(bin.begin(), bin.end(), major * 10 + minor) != bin.end(); + } + + bool CudaArch::hasEqualOrLessPtx(int major, int minor) const + { + return !ptx.empty() && (ptx.front() <= major * 10 + minor); + } + + bool CudaArch::hasEqualOrGreaterPtx(int major, int minor) const + { + return !ptx.empty() && (ptx.back() >= major * 10 + minor); + } + + bool CudaArch::hasEqualOrGreaterBin(int major, int minor) const + { + return !bin.empty() && (bin.back() >= major * 10 + minor); + } + + void CudaArch::fromStr(const char* set_as_str, std::vector& arr) + { + arr.clear(); + + const size_t len = strlen(set_as_str); + + size_t pos = 0; + while (pos < len) + { + if (isspace(set_as_str[pos])) + { + ++pos; + } + else + { + int cur_value; + int chars_read; + int args_read = sscanf(set_as_str + pos, "%d%n", &cur_value, &chars_read); + CV_Assert( args_read == 1 ); + + arr.push_back(cur_value); + pos += chars_read; + } + } + + std::sort(arr.begin(), arr.end()); + } +} + +#endif + +bool cv::gpu::TargetArchs::builtWith(cv::gpu::FeatureSet feature_set) +{ +#ifndef HAVE_CUDA + (void) feature_set; + throw_no_cuda(); + return false; +#else + return cudaArch.builtWith(feature_set); +#endif +} + +bool cv::gpu::TargetArchs::hasPtx(int major, int minor) +{ +#ifndef HAVE_CUDA + (void) major; + (void) minor; + throw_no_cuda(); + return false; +#else + return cudaArch.hasPtx(major, minor); +#endif +} + +bool cv::gpu::TargetArchs::hasBin(int major, int minor) +{ +#ifndef HAVE_CUDA + (void) major; + (void) minor; + throw_no_cuda(); + return false; +#else + return cudaArch.hasBin(major, minor); +#endif +} + +bool cv::gpu::TargetArchs::hasEqualOrLessPtx(int major, int minor) +{ +#ifndef HAVE_CUDA + (void) major; + (void) minor; + throw_no_cuda(); + return false; +#else + return cudaArch.hasEqualOrLessPtx(major, minor); +#endif +} + +bool cv::gpu::TargetArchs::hasEqualOrGreaterPtx(int major, int minor) +{ +#ifndef HAVE_CUDA + (void) major; + (void) minor; + throw_no_cuda(); + return false; +#else + return cudaArch.hasEqualOrGreaterPtx(major, minor); +#endif +} + +bool cv::gpu::TargetArchs::hasEqualOrGreaterBin(int major, int minor) +{ +#ifndef HAVE_CUDA + (void) major; + (void) minor; + throw_no_cuda(); + return false; +#else + return cudaArch.hasEqualOrGreaterBin(major, minor); +#endif +} + +//////////////////////////////////////////////////////////////////////// +// DeviceInfo + +#ifdef HAVE_CUDA + +namespace +{ + class DeviceProps + { + public: + DeviceProps(); + + const cudaDeviceProp* get(int devID) const; + + private: + std::vector props_; + }; + + DeviceProps::DeviceProps() + { + int count = getCudaEnabledDeviceCount(); + + if (count > 0) + { + props_.resize(count); + + for (int devID = 0; devID < count; ++devID) + { + cudaSafeCall( cudaGetDeviceProperties(&props_[devID], devID) ); + } + } + } + + const cudaDeviceProp* DeviceProps::get(int devID) const + { + CV_Assert( static_cast(devID) < props_.size() ); + + return &props_[devID]; + } + + DeviceProps& deviceProps() + { + static DeviceProps props; + return props; + } +} + +#endif + +const char* cv::gpu::DeviceInfo::name() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return ""; +#else + return deviceProps().get(device_id_)->name; +#endif +} + +size_t cv::gpu::DeviceInfo::totalGlobalMem() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->totalGlobalMem; +#endif +} + +size_t cv::gpu::DeviceInfo::sharedMemPerBlock() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->sharedMemPerBlock; +#endif +} + +int cv::gpu::DeviceInfo::regsPerBlock() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->regsPerBlock; +#endif +} + +int cv::gpu::DeviceInfo::warpSize() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->warpSize; +#endif +} + +size_t cv::gpu::DeviceInfo::memPitch() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->memPitch; +#endif +} + +int cv::gpu::DeviceInfo::maxThreadsPerBlock() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->maxThreadsPerBlock; +#endif +} + +Vec3i cv::gpu::DeviceInfo::maxThreadsDim() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return Vec3i(); +#else + return Vec3i(deviceProps().get(device_id_)->maxThreadsDim); +#endif +} + +Vec3i cv::gpu::DeviceInfo::maxGridSize() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return Vec3i(); +#else + return Vec3i(deviceProps().get(device_id_)->maxGridSize); +#endif +} + +int cv::gpu::DeviceInfo::clockRate() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->clockRate; +#endif +} + +size_t cv::gpu::DeviceInfo::totalConstMem() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->totalConstMem; +#endif +} + +int cv::gpu::DeviceInfo::majorVersion() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->major; +#endif +} + +int cv::gpu::DeviceInfo::minorVersion() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->minor; +#endif +} + +size_t cv::gpu::DeviceInfo::textureAlignment() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->textureAlignment; +#endif +} + +size_t cv::gpu::DeviceInfo::texturePitchAlignment() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->texturePitchAlignment; +#endif +} + +int cv::gpu::DeviceInfo::multiProcessorCount() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->multiProcessorCount; +#endif +} + +bool cv::gpu::DeviceInfo::kernelExecTimeoutEnabled() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return false; +#else + return deviceProps().get(device_id_)->kernelExecTimeoutEnabled != 0; +#endif +} + +bool cv::gpu::DeviceInfo::integrated() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return false; +#else + return deviceProps().get(device_id_)->integrated != 0; +#endif +} + +bool cv::gpu::DeviceInfo::canMapHostMemory() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return false; +#else + return deviceProps().get(device_id_)->canMapHostMemory != 0; +#endif +} + +DeviceInfo::ComputeMode cv::gpu::DeviceInfo::computeMode() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return ComputeModeDefault; +#else + static const ComputeMode tbl[] = + { + ComputeModeDefault, + ComputeModeExclusive, + ComputeModeProhibited, + ComputeModeExclusiveProcess + }; + + return tbl[deviceProps().get(device_id_)->computeMode]; +#endif +} + +int cv::gpu::DeviceInfo::maxTexture1D() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->maxTexture1D; +#endif +} + +int cv::gpu::DeviceInfo::maxTexture1DMipmap() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + #if CUDA_VERSION >= 5000 + return deviceProps().get(device_id_)->maxTexture1DMipmap; + #else + CV_Error(Error::StsNotImplemented, "This function requires CUDA 5.0"); + return 0; + #endif +#endif +} + +int cv::gpu::DeviceInfo::maxTexture1DLinear() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->maxTexture1DLinear; +#endif +} + +Vec2i cv::gpu::DeviceInfo::maxTexture2D() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return Vec2i(); +#else + return Vec2i(deviceProps().get(device_id_)->maxTexture2D); +#endif +} + +Vec2i cv::gpu::DeviceInfo::maxTexture2DMipmap() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return Vec2i(); +#else + #if CUDA_VERSION >= 5000 + return Vec2i(deviceProps().get(device_id_)->maxTexture2DMipmap); + #else + CV_Error(Error::StsNotImplemented, "This function requires CUDA 5.0"); + return Vec2i(); + #endif +#endif +} + +Vec3i cv::gpu::DeviceInfo::maxTexture2DLinear() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return Vec3i(); +#else + return Vec3i(deviceProps().get(device_id_)->maxTexture2DLinear); +#endif +} + +Vec2i cv::gpu::DeviceInfo::maxTexture2DGather() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return Vec2i(); +#else + return Vec2i(deviceProps().get(device_id_)->maxTexture2DGather); +#endif +} + +Vec3i cv::gpu::DeviceInfo::maxTexture3D() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return Vec3i(); +#else + return Vec3i(deviceProps().get(device_id_)->maxTexture3D); +#endif +} + +int cv::gpu::DeviceInfo::maxTextureCubemap() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->maxTextureCubemap; +#endif +} + +Vec2i cv::gpu::DeviceInfo::maxTexture1DLayered() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return Vec2i(); +#else + return Vec2i(deviceProps().get(device_id_)->maxTexture1DLayered); +#endif +} + +Vec3i cv::gpu::DeviceInfo::maxTexture2DLayered() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return Vec3i(); +#else + return Vec3i(deviceProps().get(device_id_)->maxTexture2DLayered); +#endif +} + +Vec2i cv::gpu::DeviceInfo::maxTextureCubemapLayered() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return Vec2i(); +#else + return Vec2i(deviceProps().get(device_id_)->maxTextureCubemapLayered); +#endif +} + +int cv::gpu::DeviceInfo::maxSurface1D() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->maxSurface1D; +#endif +} + +Vec2i cv::gpu::DeviceInfo::maxSurface2D() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return Vec2i(); +#else + return Vec2i(deviceProps().get(device_id_)->maxSurface2D); +#endif +} + +Vec3i cv::gpu::DeviceInfo::maxSurface3D() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return Vec3i(); +#else + return Vec3i(deviceProps().get(device_id_)->maxSurface3D); +#endif +} + +Vec2i cv::gpu::DeviceInfo::maxSurface1DLayered() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return Vec2i(); +#else + return Vec2i(deviceProps().get(device_id_)->maxSurface1DLayered); +#endif +} + +Vec3i cv::gpu::DeviceInfo::maxSurface2DLayered() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return Vec3i(); +#else + return Vec3i(deviceProps().get(device_id_)->maxSurface2DLayered); +#endif +} + +int cv::gpu::DeviceInfo::maxSurfaceCubemap() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->maxSurfaceCubemap; +#endif +} + +Vec2i cv::gpu::DeviceInfo::maxSurfaceCubemapLayered() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return Vec2i(); +#else + return Vec2i(deviceProps().get(device_id_)->maxSurfaceCubemapLayered); +#endif +} + +size_t cv::gpu::DeviceInfo::surfaceAlignment() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->surfaceAlignment; +#endif +} + +bool cv::gpu::DeviceInfo::concurrentKernels() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return false; +#else + return deviceProps().get(device_id_)->concurrentKernels != 0; +#endif +} + +bool cv::gpu::DeviceInfo::ECCEnabled() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return false; +#else + return deviceProps().get(device_id_)->ECCEnabled != 0; +#endif +} + +int cv::gpu::DeviceInfo::pciBusID() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->pciBusID; +#endif +} + +int cv::gpu::DeviceInfo::pciDeviceID() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->pciDeviceID; +#endif +} + +int cv::gpu::DeviceInfo::pciDomainID() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->pciDomainID; +#endif +} + +bool cv::gpu::DeviceInfo::tccDriver() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return false; +#else + return deviceProps().get(device_id_)->tccDriver != 0; +#endif +} + +int cv::gpu::DeviceInfo::asyncEngineCount() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->asyncEngineCount; +#endif +} + +bool cv::gpu::DeviceInfo::unifiedAddressing() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return false; +#else + return deviceProps().get(device_id_)->unifiedAddressing != 0; +#endif +} + +int cv::gpu::DeviceInfo::memoryClockRate() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->memoryClockRate; +#endif +} + +int cv::gpu::DeviceInfo::memoryBusWidth() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->memoryBusWidth; +#endif +} + +int cv::gpu::DeviceInfo::l2CacheSize() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->l2CacheSize; +#endif +} + +int cv::gpu::DeviceInfo::maxThreadsPerMultiProcessor() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return 0; +#else + return deviceProps().get(device_id_)->maxThreadsPerMultiProcessor; +#endif +} + +void cv::gpu::DeviceInfo::queryMemory(size_t& _totalMemory, size_t& _freeMemory) const +{ +#ifndef HAVE_CUDA + (void) _totalMemory; + (void) _freeMemory; + throw_no_cuda(); +#else + int prevDeviceID = getDevice(); + if (prevDeviceID != device_id_) + setDevice(device_id_); + + cudaSafeCall( cudaMemGetInfo(&_freeMemory, &_totalMemory) ); + + if (prevDeviceID != device_id_) + setDevice(prevDeviceID); +#endif +} + +bool cv::gpu::DeviceInfo::isCompatible() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return false; +#else + // Check PTX compatibility + if (TargetArchs::hasEqualOrLessPtx(majorVersion(), minorVersion())) + return true; + + // Check BIN compatibility + for (int i = minorVersion(); i >= 0; --i) + if (TargetArchs::hasBin(majorVersion(), i)) + return true; + + return false; +#endif +} + +//////////////////////////////////////////////////////////////////////// +// print info + +#ifdef HAVE_CUDA + +namespace +{ + int convertSMVer2Cores(int major, int minor) + { + // Defines for GPU Architecture types (using the SM version to determine the # of cores per SM + typedef struct { + int SM; // 0xMm (hexidecimal notation), M = SM Major version, and m = SM minor version + int Cores; + } SMtoCores; + + SMtoCores gpuArchCoresPerSM[] = { { 0x10, 8 }, { 0x11, 8 }, { 0x12, 8 }, { 0x13, 8 }, { 0x20, 32 }, { 0x21, 48 }, {0x30, 192}, {0x35, 192}, { -1, -1 } }; + + int index = 0; + while (gpuArchCoresPerSM[index].SM != -1) + { + if (gpuArchCoresPerSM[index].SM == ((major << 4) + minor) ) + return gpuArchCoresPerSM[index].Cores; + index++; + } + + return -1; + } +} + +#endif + +void cv::gpu::printCudaDeviceInfo(int device) +{ +#ifndef HAVE_CUDA + (void) device; + throw_no_cuda(); +#else + int count = getCudaEnabledDeviceCount(); + bool valid = (device >= 0) && (device < count); + + int beg = valid ? device : 0; + int end = valid ? device+1 : count; + + printf("*** CUDA Device Query (Runtime API) version (CUDART static linking) *** \n\n"); + printf("Device count: %d\n", count); + + int driverVersion = 0, runtimeVersion = 0; + cudaSafeCall( cudaDriverGetVersion(&driverVersion) ); + cudaSafeCall( cudaRuntimeGetVersion(&runtimeVersion) ); + + const char *computeMode[] = { + "Default (multiple host threads can use ::cudaSetDevice() with device simultaneously)", + "Exclusive (only one host thread in one process is able to use ::cudaSetDevice() with this device)", + "Prohibited (no host thread can use ::cudaSetDevice() with this device)", + "Exclusive Process (many threads in one process is able to use ::cudaSetDevice() with this device)", + "Unknown", + NULL + }; + + for(int dev = beg; dev < end; ++dev) + { + cudaDeviceProp prop; + cudaSafeCall( cudaGetDeviceProperties(&prop, dev) ); + + printf("\nDevice %d: \"%s\"\n", dev, prop.name); + printf(" CUDA Driver Version / Runtime Version %d.%d / %d.%d\n", driverVersion/1000, driverVersion%100, runtimeVersion/1000, runtimeVersion%100); + printf(" CUDA Capability Major/Minor version number: %d.%d\n", prop.major, prop.minor); + printf(" Total amount of global memory: %.0f MBytes (%llu bytes)\n", (float)prop.totalGlobalMem/1048576.0f, (unsigned long long) prop.totalGlobalMem); + + int cores = convertSMVer2Cores(prop.major, prop.minor); + if (cores > 0) + printf(" (%2d) Multiprocessors x (%2d) CUDA Cores/MP: %d CUDA Cores\n", prop.multiProcessorCount, cores, cores * prop.multiProcessorCount); + + printf(" GPU Clock Speed: %.2f GHz\n", prop.clockRate * 1e-6f); + + printf(" Max Texture Dimension Size (x,y,z) 1D=(%d), 2D=(%d,%d), 3D=(%d,%d,%d)\n", + prop.maxTexture1D, prop.maxTexture2D[0], prop.maxTexture2D[1], + prop.maxTexture3D[0], prop.maxTexture3D[1], prop.maxTexture3D[2]); + printf(" Max Layered Texture Size (dim) x layers 1D=(%d) x %d, 2D=(%d,%d) x %d\n", + prop.maxTexture1DLayered[0], prop.maxTexture1DLayered[1], + prop.maxTexture2DLayered[0], prop.maxTexture2DLayered[1], prop.maxTexture2DLayered[2]); + + printf(" Total amount of constant memory: %u bytes\n", (int)prop.totalConstMem); + printf(" Total amount of shared memory per block: %u bytes\n", (int)prop.sharedMemPerBlock); + printf(" Total number of registers available per block: %d\n", prop.regsPerBlock); + printf(" Warp size: %d\n", prop.warpSize); + printf(" Maximum number of threads per block: %d\n", prop.maxThreadsPerBlock); + printf(" Maximum sizes of each dimension of a block: %d x %d x %d\n", prop.maxThreadsDim[0], prop.maxThreadsDim[1], prop.maxThreadsDim[2]); + printf(" Maximum sizes of each dimension of a grid: %d x %d x %d\n", prop.maxGridSize[0], prop.maxGridSize[1], prop.maxGridSize[2]); + printf(" Maximum memory pitch: %u bytes\n", (int)prop.memPitch); + printf(" Texture alignment: %u bytes\n", (int)prop.textureAlignment); + + printf(" Concurrent copy and execution: %s with %d copy engine(s)\n", (prop.deviceOverlap ? "Yes" : "No"), prop.asyncEngineCount); + printf(" Run time limit on kernels: %s\n", prop.kernelExecTimeoutEnabled ? "Yes" : "No"); + printf(" Integrated GPU sharing Host Memory: %s\n", prop.integrated ? "Yes" : "No"); + printf(" Support host page-locked memory mapping: %s\n", prop.canMapHostMemory ? "Yes" : "No"); + + printf(" Concurrent kernel execution: %s\n", prop.concurrentKernels ? "Yes" : "No"); + printf(" Alignment requirement for Surfaces: %s\n", prop.surfaceAlignment ? "Yes" : "No"); + printf(" Device has ECC support enabled: %s\n", prop.ECCEnabled ? "Yes" : "No"); + printf(" Device is using TCC driver mode: %s\n", prop.tccDriver ? "Yes" : "No"); + printf(" Device supports Unified Addressing (UVA): %s\n", prop.unifiedAddressing ? "Yes" : "No"); + printf(" Device PCI Bus ID / PCI location ID: %d / %d\n", prop.pciBusID, prop.pciDeviceID ); + printf(" Compute Mode:\n"); + printf(" %s \n", computeMode[prop.computeMode]); + } + + printf("\n"); + printf("deviceQuery, CUDA Driver = CUDART"); + printf(", CUDA Driver Version = %d.%d", driverVersion / 1000, driverVersion % 100); + printf(", CUDA Runtime Version = %d.%d", runtimeVersion/1000, runtimeVersion%100); + printf(", NumDevs = %d\n\n", count); + + fflush(stdout); +#endif +} + +void cv::gpu::printShortCudaDeviceInfo(int device) +{ +#ifndef HAVE_CUDA + (void) device; + throw_no_cuda(); +#else + int count = getCudaEnabledDeviceCount(); + bool valid = (device >= 0) && (device < count); + + int beg = valid ? device : 0; + int end = valid ? device+1 : count; + + int driverVersion = 0, runtimeVersion = 0; + cudaSafeCall( cudaDriverGetVersion(&driverVersion) ); + cudaSafeCall( cudaRuntimeGetVersion(&runtimeVersion) ); + + for(int dev = beg; dev < end; ++dev) + { + cudaDeviceProp prop; + cudaSafeCall( cudaGetDeviceProperties(&prop, dev) ); + + const char *arch_str = prop.major < 2 ? " (not Fermi)" : ""; + printf("Device %d: \"%s\" %.0fMb", dev, prop.name, (float)prop.totalGlobalMem/1048576.0f); + printf(", sm_%d%d%s", prop.major, prop.minor, arch_str); + + int cores = convertSMVer2Cores(prop.major, prop.minor); + if (cores > 0) + printf(", %d cores", cores * prop.multiProcessorCount); + + printf(", Driver/Runtime ver.%d.%d/%d.%d\n", driverVersion/1000, driverVersion%100, runtimeVersion/1000, runtimeVersion%100); + } + + fflush(stdout); +#endif +} + +//////////////////////////////////////////////////////////////////////// +// Error handling + +#ifdef HAVE_CUDA + +namespace +{ + #define error_entry(entry) { entry, #entry } + + struct ErrorEntry + { + int code; + const char* str; + }; + + struct ErrorEntryComparer + { + int code; + ErrorEntryComparer(int code_) : code(code_) {} + bool operator()(const ErrorEntry& e) const { return e.code == code; } + }; + + const ErrorEntry npp_errors [] = + { + #if defined (_MSC_VER) + error_entry( NPP_NOT_SUFFICIENT_COMPUTE_CAPABILITY ), + #endif + + #if NPP_VERSION < 5500 + error_entry( NPP_BAD_ARG_ERROR ), + error_entry( NPP_COEFF_ERROR ), + error_entry( NPP_RECT_ERROR ), + error_entry( NPP_QUAD_ERROR ), + error_entry( NPP_MEMFREE_ERR ), + error_entry( NPP_MEMSET_ERR ), + error_entry( NPP_MEM_ALLOC_ERR ), + error_entry( NPP_HISTO_NUMBER_OF_LEVELS_ERROR ), + error_entry( NPP_MIRROR_FLIP_ERR ), + error_entry( NPP_INVALID_INPUT ), + error_entry( NPP_POINTER_ERROR ), + error_entry( NPP_WARNING ), + error_entry( NPP_ODD_ROI_WARNING ), + #else + error_entry( NPP_INVALID_HOST_POINTER_ERROR ), + error_entry( NPP_INVALID_DEVICE_POINTER_ERROR ), + error_entry( NPP_LUT_PALETTE_BITSIZE_ERROR ), + error_entry( NPP_ZC_MODE_NOT_SUPPORTED_ERROR ), + error_entry( NPP_MEMFREE_ERROR ), + error_entry( NPP_MEMSET_ERROR ), + error_entry( NPP_QUALITY_INDEX_ERROR ), + error_entry( NPP_HISTOGRAM_NUMBER_OF_LEVELS_ERROR ), + error_entry( NPP_CHANNEL_ORDER_ERROR ), + error_entry( NPP_ZERO_MASK_VALUE_ERROR ), + error_entry( NPP_QUADRANGLE_ERROR ), + error_entry( NPP_RECTANGLE_ERROR ), + error_entry( NPP_COEFFICIENT_ERROR ), + error_entry( NPP_NUMBER_OF_CHANNELS_ERROR ), + error_entry( NPP_COI_ERROR ), + error_entry( NPP_DIVISOR_ERROR ), + error_entry( NPP_CHANNEL_ERROR ), + error_entry( NPP_STRIDE_ERROR ), + error_entry( NPP_ANCHOR_ERROR ), + error_entry( NPP_MASK_SIZE_ERROR ), + error_entry( NPP_MIRROR_FLIP_ERROR ), + error_entry( NPP_MOMENT_00_ZERO_ERROR ), + error_entry( NPP_THRESHOLD_NEGATIVE_LEVEL_ERROR ), + error_entry( NPP_THRESHOLD_ERROR ), + error_entry( NPP_CONTEXT_MATCH_ERROR ), + error_entry( NPP_FFT_FLAG_ERROR ), + error_entry( NPP_FFT_ORDER_ERROR ), + error_entry( NPP_SCALE_RANGE_ERROR ), + error_entry( NPP_DATA_TYPE_ERROR ), + error_entry( NPP_OUT_OFF_RANGE_ERROR ), + error_entry( NPP_DIVIDE_BY_ZERO_ERROR ), + error_entry( NPP_MEMORY_ALLOCATION_ERR ), + error_entry( NPP_RANGE_ERROR ), + error_entry( NPP_BAD_ARGUMENT_ERROR ), + error_entry( NPP_NO_MEMORY_ERROR ), + error_entry( NPP_ERROR_RESERVED ), + error_entry( NPP_NO_OPERATION_WARNING ), + error_entry( NPP_DIVIDE_BY_ZERO_WARNING ), + error_entry( NPP_WRONG_INTERSECTION_ROI_WARNING ), + #endif + + error_entry( NPP_NOT_SUPPORTED_MODE_ERROR ), + error_entry( NPP_ROUND_MODE_NOT_SUPPORTED_ERROR ), + error_entry( NPP_RESIZE_NO_OPERATION_ERROR ), + error_entry( NPP_LUT_NUMBER_OF_LEVELS_ERROR ), + error_entry( NPP_TEXTURE_BIND_ERROR ), + error_entry( NPP_WRONG_INTERSECTION_ROI_ERROR ), + error_entry( NPP_NOT_EVEN_STEP_ERROR ), + error_entry( NPP_INTERPOLATION_ERROR ), + error_entry( NPP_RESIZE_FACTOR_ERROR ), + error_entry( NPP_HAAR_CLASSIFIER_PIXEL_MATCH_ERROR ), + error_entry( NPP_MEMCPY_ERROR ), + error_entry( NPP_ALIGNMENT_ERROR ), + error_entry( NPP_STEP_ERROR ), + error_entry( NPP_SIZE_ERROR ), + error_entry( NPP_NULL_POINTER_ERROR ), + error_entry( NPP_CUDA_KERNEL_EXECUTION_ERROR ), + error_entry( NPP_NOT_IMPLEMENTED_ERROR ), + error_entry( NPP_ERROR ), + error_entry( NPP_NO_ERROR ), + error_entry( NPP_SUCCESS ), + error_entry( NPP_WRONG_INTERSECTION_QUAD_WARNING ), + error_entry( NPP_MISALIGNED_DST_ROI_WARNING ), + error_entry( NPP_AFFINE_QUAD_INCORRECT_WARNING ), + error_entry( NPP_DOUBLE_SIZE_WARNING ) + }; + + const size_t npp_error_num = sizeof(npp_errors) / sizeof(npp_errors[0]); + + const ErrorEntry cu_errors [] = + { + error_entry( CUDA_SUCCESS ), + error_entry( CUDA_ERROR_INVALID_VALUE ), + error_entry( CUDA_ERROR_OUT_OF_MEMORY ), + error_entry( CUDA_ERROR_NOT_INITIALIZED ), + error_entry( CUDA_ERROR_DEINITIALIZED ), + error_entry( CUDA_ERROR_PROFILER_DISABLED ), + error_entry( CUDA_ERROR_PROFILER_NOT_INITIALIZED ), + error_entry( CUDA_ERROR_PROFILER_ALREADY_STARTED ), + error_entry( CUDA_ERROR_PROFILER_ALREADY_STOPPED ), + error_entry( CUDA_ERROR_NO_DEVICE ), + error_entry( CUDA_ERROR_INVALID_DEVICE ), + error_entry( CUDA_ERROR_INVALID_IMAGE ), + error_entry( CUDA_ERROR_INVALID_CONTEXT ), + error_entry( CUDA_ERROR_CONTEXT_ALREADY_CURRENT ), + error_entry( CUDA_ERROR_MAP_FAILED ), + error_entry( CUDA_ERROR_UNMAP_FAILED ), + error_entry( CUDA_ERROR_ARRAY_IS_MAPPED ), + error_entry( CUDA_ERROR_ALREADY_MAPPED ), + error_entry( CUDA_ERROR_NO_BINARY_FOR_GPU ), + error_entry( CUDA_ERROR_ALREADY_ACQUIRED ), + error_entry( CUDA_ERROR_NOT_MAPPED ), + error_entry( CUDA_ERROR_NOT_MAPPED_AS_ARRAY ), + error_entry( CUDA_ERROR_NOT_MAPPED_AS_POINTER ), + error_entry( CUDA_ERROR_ECC_UNCORRECTABLE ), + error_entry( CUDA_ERROR_UNSUPPORTED_LIMIT ), + error_entry( CUDA_ERROR_CONTEXT_ALREADY_IN_USE ), + error_entry( CUDA_ERROR_INVALID_SOURCE ), + error_entry( CUDA_ERROR_FILE_NOT_FOUND ), + error_entry( CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND ), + error_entry( CUDA_ERROR_SHARED_OBJECT_INIT_FAILED ), + error_entry( CUDA_ERROR_OPERATING_SYSTEM ), + error_entry( CUDA_ERROR_INVALID_HANDLE ), + error_entry( CUDA_ERROR_NOT_FOUND ), + error_entry( CUDA_ERROR_NOT_READY ), + error_entry( CUDA_ERROR_LAUNCH_FAILED ), + error_entry( CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES ), + error_entry( CUDA_ERROR_LAUNCH_TIMEOUT ), + error_entry( CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING ), + error_entry( CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED ), + error_entry( CUDA_ERROR_PEER_ACCESS_NOT_ENABLED ), + error_entry( CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE ), + error_entry( CUDA_ERROR_CONTEXT_IS_DESTROYED ), + error_entry( CUDA_ERROR_ASSERT ), + error_entry( CUDA_ERROR_TOO_MANY_PEERS ), + error_entry( CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED ), + error_entry( CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED ), + error_entry( CUDA_ERROR_UNKNOWN ) + }; + + const size_t cu_errors_num = sizeof(cu_errors) / sizeof(cu_errors[0]); + + cv::String getErrorString(int code, const ErrorEntry* errors, size_t n) + { + size_t idx = std::find_if(errors, errors + n, ErrorEntryComparer(code)) - errors; + + const char* msg = (idx != n) ? errors[idx].str : "Unknown error code"; + cv::String str = cv::format("%s [Code = %d]", msg, code); + + return str; + } +} + +#endif + +String cv::gpu::getNppErrorMessage(int code) +{ +#ifndef HAVE_CUDA + (void) code; + return String(); +#else + return getErrorString(code, npp_errors, npp_error_num); +#endif +} + +String cv::gpu::getCudaDriverApiErrorMessage(int code) +{ +#ifndef HAVE_CUDA + (void) code; + return String(); +#else + return getErrorString(code, cu_errors, cu_errors_num); +#endif +} diff --git a/modules/core/src/gpu_mat.cpp b/modules/core/src/gpu_mat.cpp new file mode 100644 index 0000000000..33a6046fed --- /dev/null +++ b/modules/core/src/gpu_mat.cpp @@ -0,0 +1,444 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "precomp.hpp" + +using namespace cv; +using namespace cv::gpu; + +cv::gpu::GpuMat::GpuMat(int rows_, int cols_, int type_, void* data_, size_t step_) : + flags(Mat::MAGIC_VAL + (type_ & Mat::TYPE_MASK)), rows(rows_), cols(cols_), + step(step_), data((uchar*)data_), refcount(0), + datastart((uchar*)data_), dataend((uchar*)data_) +{ + size_t minstep = cols * elemSize(); + + if (step == Mat::AUTO_STEP) + { + step = minstep; + flags |= Mat::CONTINUOUS_FLAG; + } + else + { + if (rows == 1) + step = minstep; + + CV_DbgAssert( step >= minstep ); + + flags |= step == minstep ? Mat::CONTINUOUS_FLAG : 0; + } + + dataend += step * (rows - 1) + minstep; +} + +cv::gpu::GpuMat::GpuMat(Size size_, int type_, void* data_, size_t step_) : + flags(Mat::MAGIC_VAL + (type_ & Mat::TYPE_MASK)), rows(size_.height), cols(size_.width), + step(step_), data((uchar*)data_), refcount(0), + datastart((uchar*)data_), dataend((uchar*)data_) +{ + size_t minstep = cols * elemSize(); + + if (step == Mat::AUTO_STEP) + { + step = minstep; + flags |= Mat::CONTINUOUS_FLAG; + } + else + { + if (rows == 1) + step = minstep; + + CV_DbgAssert( step >= minstep ); + + flags |= step == minstep ? Mat::CONTINUOUS_FLAG : 0; + } + dataend += step * (rows - 1) + minstep; +} + +cv::gpu::GpuMat::GpuMat(const GpuMat& m, Range rowRange_, Range colRange_) +{ + flags = m.flags; + step = m.step; refcount = m.refcount; + data = m.data; datastart = m.datastart; dataend = m.dataend; + + if (rowRange_ == Range::all()) + { + rows = m.rows; + } + else + { + CV_Assert( 0 <= rowRange_.start && rowRange_.start <= rowRange_.end && rowRange_.end <= m.rows ); + + rows = rowRange_.size(); + data += step*rowRange_.start; + } + + if (colRange_ == Range::all()) + { + cols = m.cols; + } + else + { + CV_Assert( 0 <= colRange_.start && colRange_.start <= colRange_.end && colRange_.end <= m.cols ); + + cols = colRange_.size(); + data += colRange_.start*elemSize(); + flags &= cols < m.cols ? ~Mat::CONTINUOUS_FLAG : -1; + } + + if (rows == 1) + flags |= Mat::CONTINUOUS_FLAG; + + if (refcount) + CV_XADD(refcount, 1); + + if (rows <= 0 || cols <= 0) + rows = cols = 0; +} + +cv::gpu::GpuMat::GpuMat(const GpuMat& m, Rect roi) : + flags(m.flags), rows(roi.height), cols(roi.width), + step(m.step), data(m.data + roi.y*step), refcount(m.refcount), + datastart(m.datastart), dataend(m.dataend) +{ + flags &= roi.width < m.cols ? ~Mat::CONTINUOUS_FLAG : -1; + data += roi.x * elemSize(); + + CV_Assert( 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows ); + + if (refcount) + CV_XADD(refcount, 1); + + if (rows <= 0 || cols <= 0) + rows = cols = 0; +} + +GpuMat cv::gpu::GpuMat::reshape(int new_cn, int new_rows) const +{ + GpuMat hdr = *this; + + int cn = channels(); + if (new_cn == 0) + new_cn = cn; + + int total_width = cols * cn; + + if ((new_cn > total_width || total_width % new_cn != 0) && new_rows == 0) + new_rows = rows * total_width / new_cn; + + if (new_rows != 0 && new_rows != rows) + { + int total_size = total_width * rows; + + if (!isContinuous()) + CV_Error(cv::Error::BadStep, "The matrix is not continuous, thus its number of rows can not be changed"); + + if ((unsigned)new_rows > (unsigned)total_size) + CV_Error(cv::Error::StsOutOfRange, "Bad new number of rows"); + + total_width = total_size / new_rows; + + if (total_width * new_rows != total_size) + CV_Error(cv::Error::StsBadArg, "The total number of matrix elements is not divisible by the new number of rows"); + + hdr.rows = new_rows; + hdr.step = total_width * elemSize1(); + } + + int new_width = total_width / new_cn; + + if (new_width * new_cn != total_width) + CV_Error(cv::Error::BadNumChannels, "The total width is not divisible by the new number of channels"); + + hdr.cols = new_width; + hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn - 1) << CV_CN_SHIFT); + + return hdr; +} + +void cv::gpu::GpuMat::locateROI(Size& wholeSize, Point& ofs) const +{ + CV_DbgAssert( step > 0 ); + + size_t esz = elemSize(); + ptrdiff_t delta1 = data - datastart; + ptrdiff_t delta2 = dataend - datastart; + + if (delta1 == 0) + { + ofs.x = ofs.y = 0; + } + else + { + ofs.y = static_cast(delta1 / step); + ofs.x = static_cast((delta1 - step * ofs.y) / esz); + + CV_DbgAssert( data == datastart + ofs.y * step + ofs.x * esz ); + } + + size_t minstep = (ofs.x + cols) * esz; + + wholeSize.height = std::max(static_cast((delta2 - minstep) / step + 1), ofs.y + rows); + wholeSize.width = std::max(static_cast((delta2 - step * (wholeSize.height - 1)) / esz), ofs.x + cols); +} + +GpuMat& cv::gpu::GpuMat::adjustROI(int dtop, int dbottom, int dleft, int dright) +{ + Size wholeSize; + Point ofs; + locateROI(wholeSize, ofs); + + size_t esz = elemSize(); + + int row1 = std::max(ofs.y - dtop, 0); + int row2 = std::min(ofs.y + rows + dbottom, wholeSize.height); + + int col1 = std::max(ofs.x - dleft, 0); + int col2 = std::min(ofs.x + cols + dright, wholeSize.width); + + data += (row1 - ofs.y) * step + (col1 - ofs.x) * esz; + rows = row2 - row1; + cols = col2 - col1; + + if (esz * cols == step || rows == 1) + flags |= Mat::CONTINUOUS_FLAG; + else + flags &= ~Mat::CONTINUOUS_FLAG; + + return *this; +} + +namespace +{ + template + void createContinuousImpl(int rows, int cols, int type, ObjType& obj) + { + const int area = rows * cols; + + if (obj.empty() || obj.type() != type || !obj.isContinuous() || obj.size().area() < area) + obj.create(1, area, type); + + obj = obj.reshape(obj.channels(), rows); + } +} + +void cv::gpu::createContinuous(int rows, int cols, int type, OutputArray arr) +{ + switch (arr.kind()) + { + case _InputArray::MAT: + ::createContinuousImpl(rows, cols, type, arr.getMatRef()); + break; + + case _InputArray::GPU_MAT: + ::createContinuousImpl(rows, cols, type, arr.getGpuMatRef()); + break; + + case _InputArray::CUDA_MEM: + ::createContinuousImpl(rows, cols, type, arr.getCudaMemRef()); + break; + + default: + arr.create(rows, cols, type); + } +} + +namespace +{ + template + void ensureSizeIsEnoughImpl(int rows, int cols, int type, ObjType& obj) + { + if (obj.empty() || obj.type() != type || obj.data != obj.datastart) + { + obj.create(rows, cols, type); + } + else + { + const size_t esz = obj.elemSize(); + const ptrdiff_t delta2 = obj.dataend - obj.datastart; + + const size_t minstep = obj.cols * esz; + + Size wholeSize; + wholeSize.height = std::max(static_cast((delta2 - minstep) / static_cast(obj.step) + 1), obj.rows); + wholeSize.width = std::max(static_cast((delta2 - static_cast(obj.step) * (wholeSize.height - 1)) / esz), obj.cols); + + if (wholeSize.height < rows || wholeSize.width < cols) + { + obj.create(rows, cols, type); + } + else + { + obj.cols = cols; + obj.rows = rows; + } + } + } +} + +void cv::gpu::ensureSizeIsEnough(int rows, int cols, int type, OutputArray arr) +{ + switch (arr.kind()) + { + case _InputArray::MAT: + ::ensureSizeIsEnoughImpl(rows, cols, type, arr.getMatRef()); + break; + + case _InputArray::GPU_MAT: + ::ensureSizeIsEnoughImpl(rows, cols, type, arr.getGpuMatRef()); + break; + + case _InputArray::CUDA_MEM: + ::ensureSizeIsEnoughImpl(rows, cols, type, arr.getCudaMemRef()); + break; + + default: + arr.create(rows, cols, type); + } +} + +GpuMat cv::gpu::allocMatFromBuf(int rows, int cols, int type, GpuMat& mat) +{ + if (!mat.empty() && mat.type() == type && mat.rows >= rows && mat.cols >= cols) + return mat(Rect(0, 0, cols, rows)); + + return mat = GpuMat(rows, cols, type); +} + +#ifndef HAVE_CUDA + +void cv::gpu::GpuMat::create(int _rows, int _cols, int _type) +{ + (void) _rows; + (void) _cols; + (void) _type; + throw_no_cuda(); +} + +void cv::gpu::GpuMat::release() +{ +} + +void cv::gpu::GpuMat::upload(InputArray arr) +{ + (void) arr; + throw_no_cuda(); +} + +void cv::gpu::GpuMat::upload(InputArray arr, Stream& _stream) +{ + (void) arr; + (void) _stream; + throw_no_cuda(); +} + +void cv::gpu::GpuMat::download(OutputArray _dst) const +{ + (void) _dst; + throw_no_cuda(); +} + +void cv::gpu::GpuMat::download(OutputArray _dst, Stream& _stream) const +{ + (void) _dst; + (void) _stream; + throw_no_cuda(); +} + +void cv::gpu::GpuMat::copyTo(OutputArray _dst) const +{ + (void) _dst; + throw_no_cuda(); +} + +void cv::gpu::GpuMat::copyTo(OutputArray _dst, Stream& _stream) const +{ + (void) _dst; + (void) _stream; + throw_no_cuda(); +} + +void cv::gpu::GpuMat::copyTo(OutputArray _dst, InputArray _mask, Stream& _stream) const +{ + (void) _dst; + (void) _mask; + (void) _stream; + throw_no_cuda(); +} + +GpuMat& cv::gpu::GpuMat::setTo(Scalar s, Stream& _stream) +{ + (void) s; + (void) _stream; + throw_no_cuda(); + return *this; +} + +GpuMat& cv::gpu::GpuMat::setTo(Scalar s, InputArray _mask, Stream& _stream) +{ + (void) s; + (void) _mask; + (void) _stream; + throw_no_cuda(); + return *this; +} + +void cv::gpu::GpuMat::convertTo(OutputArray _dst, int rtype, Stream& _stream) const +{ + (void) _dst; + (void) rtype; + (void) _stream; + throw_no_cuda(); +} + +void cv::gpu::GpuMat::convertTo(OutputArray _dst, int rtype, double alpha, double beta, Stream& _stream) const +{ + (void) _dst; + (void) rtype; + (void) alpha; + (void) beta; + (void) _stream; + throw_no_cuda(); +} + +#endif diff --git a/modules/core/src/gpu_stream.cpp b/modules/core/src/gpu_stream.cpp new file mode 100644 index 0000000000..fcdf480a91 --- /dev/null +++ b/modules/core/src/gpu_stream.cpp @@ -0,0 +1,299 @@ +/*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 "precomp.hpp" + +using namespace cv; +using namespace cv::gpu; + +//////////////////////////////////////////////////////////////// +// Stream + +#ifndef HAVE_CUDA + +class cv::gpu::Stream::Impl +{ +public: + Impl(void* ptr = 0) + { + (void) ptr; + throw_no_cuda(); + } +}; + +#else + +class cv::gpu::Stream::Impl +{ +public: + cudaStream_t stream; + + Impl(); + Impl(cudaStream_t stream); + + ~Impl(); +}; + +cv::gpu::Stream::Impl::Impl() : stream(0) +{ + cudaSafeCall( cudaStreamCreate(&stream) ); +} + +cv::gpu::Stream::Impl::Impl(cudaStream_t stream_) : stream(stream_) +{ +} + +cv::gpu::Stream::Impl::~Impl() +{ + if (stream) + cudaStreamDestroy(stream); +} + +cudaStream_t cv::gpu::StreamAccessor::getStream(const Stream& stream) +{ + return stream.impl_->stream; +} + +#endif + +cv::gpu::Stream::Stream() +{ +#ifndef HAVE_CUDA + throw_no_cuda(); +#else + impl_ = makePtr(); +#endif +} + +bool cv::gpu::Stream::queryIfComplete() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return false; +#else + cudaError_t err = cudaStreamQuery(impl_->stream); + + if (err == cudaErrorNotReady || err == cudaSuccess) + return err == cudaSuccess; + + cudaSafeCall(err); + return false; +#endif +} + +void cv::gpu::Stream::waitForCompletion() +{ +#ifndef HAVE_CUDA + throw_no_cuda(); +#else + cudaSafeCall( cudaStreamSynchronize(impl_->stream) ); +#endif +} + +void cv::gpu::Stream::waitEvent(const Event& event) +{ +#ifndef HAVE_CUDA + (void) event; + throw_no_cuda(); +#else + cudaSafeCall( cudaStreamWaitEvent(impl_->stream, EventAccessor::getEvent(event), 0) ); +#endif +} + +#if defined(HAVE_CUDA) && (CUDART_VERSION >= 5000) + +namespace +{ + struct CallbackData + { + Stream::StreamCallback callback; + void* userData; + + CallbackData(Stream::StreamCallback callback_, void* userData_) : callback(callback_), userData(userData_) {} + }; + + void CUDART_CB cudaStreamCallback(cudaStream_t, cudaError_t status, void* userData) + { + CallbackData* data = reinterpret_cast(userData); + data->callback(static_cast(status), data->userData); + delete data; + } +} + +#endif + +void cv::gpu::Stream::enqueueHostCallback(StreamCallback callback, void* userData) +{ +#ifndef HAVE_CUDA + (void) callback; + (void) userData; + throw_no_cuda(); +#else + #if CUDART_VERSION < 5000 + (void) callback; + (void) userData; + CV_Error(cv::Error::StsNotImplemented, "This function requires CUDA 5.0"); + #else + CallbackData* data = new CallbackData(callback, userData); + + cudaSafeCall( cudaStreamAddCallback(impl_->stream, cudaStreamCallback, data, 0) ); + #endif +#endif +} + +Stream& cv::gpu::Stream::Null() +{ + static Stream s(Ptr(new Impl(0))); + return s; +} + +cv::gpu::Stream::operator bool_type() const +{ +#ifndef HAVE_CUDA + return 0; +#else + return (impl_->stream != 0) ? &Stream::this_type_does_not_support_comparisons : 0; +#endif +} + + +//////////////////////////////////////////////////////////////// +// Stream + +#ifndef HAVE_CUDA + +class cv::gpu::Event::Impl +{ +public: + Impl(unsigned int) + { + throw_no_cuda(); + } +}; + +#else + +class cv::gpu::Event::Impl +{ +public: + cudaEvent_t event; + + Impl(unsigned int flags); + ~Impl(); +}; + +cv::gpu::Event::Impl::Impl(unsigned int flags) : event(0) +{ + cudaSafeCall( cudaEventCreateWithFlags(&event, flags) ); +} + +cv::gpu::Event::Impl::~Impl() +{ + if (event) + cudaEventDestroy(event); +} + +cudaEvent_t cv::gpu::EventAccessor::getEvent(const Event& event) +{ + return event.impl_->event; +} + +#endif + +cv::gpu::Event::Event(CreateFlags flags) +{ +#ifndef HAVE_CUDA + (void) flags; + throw_no_cuda(); +#else + impl_ = makePtr(flags); +#endif +} + +void cv::gpu::Event::record(Stream& stream) +{ +#ifndef HAVE_CUDA + (void) stream; + throw_no_cuda(); +#else + cudaSafeCall( cudaEventRecord(impl_->event, StreamAccessor::getStream(stream)) ); +#endif +} + +bool cv::gpu::Event::queryIfComplete() const +{ +#ifndef HAVE_CUDA + throw_no_cuda(); + return false; +#else + cudaError_t err = cudaEventQuery(impl_->event); + + if (err == cudaErrorNotReady || err == cudaSuccess) + return err == cudaSuccess; + + cudaSafeCall(err); + return false; +#endif +} + +void cv::gpu::Event::waitForCompletion() +{ +#ifndef HAVE_CUDA + throw_no_cuda(); +#else + cudaSafeCall( cudaEventSynchronize(impl_->event) ); +#endif +} + +float cv::gpu::Event::elapsedTime(const Event& start, const Event& end) +{ +#ifndef HAVE_CUDA + (void) start; + (void) end; + throw_no_cuda(); + return 0.0f; +#else + float ms; + cudaSafeCall( cudaEventElapsedTime(&ms, start.impl_->event, end.impl_->event) ); + return ms; +#endif +} diff --git a/modules/core/src/gpumat.cpp b/modules/core/src/gpumat.cpp deleted file mode 100644 index cc7442a664..0000000000 --- a/modules/core/src/gpumat.cpp +++ /dev/null @@ -1,1578 +0,0 @@ -/*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 "precomp.hpp" -#include "opencv2/core/gpumat.hpp" -#include - -#ifdef HAVE_CUDA - #include - #include - - #define CUDART_MINIMUM_REQUIRED_VERSION 4020 - #define NPP_MINIMUM_REQUIRED_VERSION 4200 - - #if (CUDART_VERSION < CUDART_MINIMUM_REQUIRED_VERSION) - #error "Insufficient Cuda Runtime library version, please update it." - #endif - - #if (NPP_VERSION_MAJOR * 1000 + NPP_VERSION_MINOR * 100 + NPP_VERSION_BUILD < NPP_MINIMUM_REQUIRED_VERSION) - #error "Insufficient NPP version, please update it." - #endif -#endif - -using namespace cv; -using namespace cv::gpu; - -#ifndef HAVE_CUDA - -#define throw_nogpu CV_Error(CV_GpuNotSupported, "The library is compiled without CUDA support") - -#else // HAVE_CUDA - -namespace -{ -#if defined(__GNUC__) - #define nppSafeCall(expr) ___nppSafeCall(expr, __FILE__, __LINE__, __func__) -#else /* defined(__CUDACC__) || defined(__MSVC__) */ - #define nppSafeCall(expr) ___nppSafeCall(expr, __FILE__, __LINE__) -#endif - - inline void ___nppSafeCall(int err, const char *file, const int line, const char *func = "") - { - if (err < 0) - { - std::ostringstream msg; - msg << "NPP API Call Error: " << err; - cv::gpu::error(msg.str().c_str(), file, line, func); - } - } -} - -#endif // HAVE_CUDA - -//////////////////////////////// Initialization & Info //////////////////////// - -#ifndef HAVE_CUDA - -int cv::gpu::getCudaEnabledDeviceCount() { return 0; } - -void cv::gpu::setDevice(int) { throw_nogpu; } -int cv::gpu::getDevice() { throw_nogpu; return 0; } - -void cv::gpu::resetDevice() { throw_nogpu; } - -bool cv::gpu::deviceSupports(FeatureSet) { throw_nogpu; return false; } - -bool cv::gpu::TargetArchs::builtWith(FeatureSet) { throw_nogpu; return false; } -bool cv::gpu::TargetArchs::has(int, int) { throw_nogpu; return false; } -bool cv::gpu::TargetArchs::hasPtx(int, int) { throw_nogpu; return false; } -bool cv::gpu::TargetArchs::hasBin(int, int) { throw_nogpu; return false; } -bool cv::gpu::TargetArchs::hasEqualOrLessPtx(int, int) { throw_nogpu; return false; } -bool cv::gpu::TargetArchs::hasEqualOrGreater(int, int) { throw_nogpu; return false; } -bool cv::gpu::TargetArchs::hasEqualOrGreaterPtx(int, int) { throw_nogpu; return false; } -bool cv::gpu::TargetArchs::hasEqualOrGreaterBin(int, int) { throw_nogpu; return false; } - -size_t cv::gpu::DeviceInfo::sharedMemPerBlock() const { throw_nogpu; return 0; } -void cv::gpu::DeviceInfo::queryMemory(size_t&, size_t&) const { throw_nogpu; } -size_t cv::gpu::DeviceInfo::freeMemory() const { throw_nogpu; return 0; } -size_t cv::gpu::DeviceInfo::totalMemory() const { throw_nogpu; return 0; } -bool cv::gpu::DeviceInfo::supports(FeatureSet) const { throw_nogpu; return false; } -bool cv::gpu::DeviceInfo::isCompatible() const { throw_nogpu; return false; } -void cv::gpu::DeviceInfo::query() { throw_nogpu; } - -void cv::gpu::printCudaDeviceInfo(int) { throw_nogpu; } -void cv::gpu::printShortCudaDeviceInfo(int) { throw_nogpu; } - -#else // HAVE_CUDA - -int cv::gpu::getCudaEnabledDeviceCount() -{ - int count; - cudaError_t error = cudaGetDeviceCount( &count ); - - if (error == cudaErrorInsufficientDriver) - return -1; - - if (error == cudaErrorNoDevice) - return 0; - - cudaSafeCall( error ); - return count; -} - -void cv::gpu::setDevice(int device) -{ - cudaSafeCall( cudaSetDevice( device ) ); -} - -int cv::gpu::getDevice() -{ - int device; - cudaSafeCall( cudaGetDevice( &device ) ); - return device; -} - -void cv::gpu::resetDevice() -{ - cudaSafeCall( cudaDeviceReset() ); -} - -namespace -{ - class CudaArch - { - public: - CudaArch(); - - bool builtWith(FeatureSet feature_set) const; - bool hasPtx(int major, int minor) const; - bool hasBin(int major, int minor) const; - bool hasEqualOrLessPtx(int major, int minor) const; - bool hasEqualOrGreaterPtx(int major, int minor) const; - bool hasEqualOrGreaterBin(int major, int minor) const; - - private: - static void fromStr(const std::string& set_as_str, std::vector& arr); - - std::vector bin; - std::vector ptx; - std::vector features; - }; - - const CudaArch cudaArch; - - CudaArch::CudaArch() - { - fromStr(CUDA_ARCH_BIN, bin); - fromStr(CUDA_ARCH_PTX, ptx); - fromStr(CUDA_ARCH_FEATURES, features); - } - - bool CudaArch::builtWith(FeatureSet feature_set) const - { - return !features.empty() && (features.back() >= feature_set); - } - - bool CudaArch::hasPtx(int major, int minor) const - { - return std::find(ptx.begin(), ptx.end(), major * 10 + minor) != ptx.end(); - } - - bool CudaArch::hasBin(int major, int minor) const - { - return std::find(bin.begin(), bin.end(), major * 10 + minor) != bin.end(); - } - - bool CudaArch::hasEqualOrLessPtx(int major, int minor) const - { - return !ptx.empty() && (ptx.front() <= major * 10 + minor); - } - - bool CudaArch::hasEqualOrGreaterPtx(int major, int minor) const - { - return !ptx.empty() && (ptx.back() >= major * 10 + minor); - } - - bool CudaArch::hasEqualOrGreaterBin(int major, int minor) const - { - return !bin.empty() && (bin.back() >= major * 10 + minor); - } - - void CudaArch::fromStr(const std::string& set_as_str, std::vector& arr) - { - if (set_as_str.find_first_not_of(" ") == std::string::npos) - return; - - std::istringstream stream(set_as_str); - int cur_value; - - while (!stream.eof()) - { - stream >> cur_value; - arr.push_back(cur_value); - } - - std::sort(arr.begin(), arr.end()); - } -} - -bool cv::gpu::TargetArchs::builtWith(cv::gpu::FeatureSet feature_set) -{ - return cudaArch.builtWith(feature_set); -} - -bool cv::gpu::TargetArchs::has(int major, int minor) -{ - return hasPtx(major, minor) || hasBin(major, minor); -} - -bool cv::gpu::TargetArchs::hasPtx(int major, int minor) -{ - return cudaArch.hasPtx(major, minor); -} - -bool cv::gpu::TargetArchs::hasBin(int major, int minor) -{ - return cudaArch.hasBin(major, minor); -} - -bool cv::gpu::TargetArchs::hasEqualOrLessPtx(int major, int minor) -{ - return cudaArch.hasEqualOrLessPtx(major, minor); -} - -bool cv::gpu::TargetArchs::hasEqualOrGreater(int major, int minor) -{ - return hasEqualOrGreaterPtx(major, minor) || hasEqualOrGreaterBin(major, minor); -} - -bool cv::gpu::TargetArchs::hasEqualOrGreaterPtx(int major, int minor) -{ - return cudaArch.hasEqualOrGreaterPtx(major, minor); -} - -bool cv::gpu::TargetArchs::hasEqualOrGreaterBin(int major, int minor) -{ - return cudaArch.hasEqualOrGreaterBin(major, minor); -} - -bool cv::gpu::deviceSupports(FeatureSet feature_set) -{ - static int versions[] = - { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - }; - static const int cache_size = static_cast(sizeof(versions) / sizeof(versions[0])); - - const int devId = getDevice(); - - int version; - - if (devId < cache_size && versions[devId] >= 0) - version = versions[devId]; - else - { - DeviceInfo dev(devId); - version = dev.majorVersion() * 10 + dev.minorVersion(); - if (devId < cache_size) - versions[devId] = version; - } - - return TargetArchs::builtWith(feature_set) && (version >= feature_set); -} - -namespace -{ - class DeviceProps - { - public: - DeviceProps(); - ~DeviceProps(); - - cudaDeviceProp* get(int devID); - - private: - std::vector props_; - }; - - DeviceProps::DeviceProps() - { - props_.resize(10, 0); - } - - DeviceProps::~DeviceProps() - { - for (size_t i = 0; i < props_.size(); ++i) - { - if (props_[i]) - delete props_[i]; - } - props_.clear(); - } - - cudaDeviceProp* DeviceProps::get(int devID) - { - if (devID >= (int) props_.size()) - props_.resize(devID + 5, 0); - - if (!props_[devID]) - { - props_[devID] = new cudaDeviceProp; - cudaSafeCall( cudaGetDeviceProperties(props_[devID], devID) ); - } - - return props_[devID]; - } - - DeviceProps deviceProps; -} - -size_t cv::gpu::DeviceInfo::sharedMemPerBlock() const -{ - return deviceProps.get(device_id_)->sharedMemPerBlock; -} - -void cv::gpu::DeviceInfo::queryMemory(size_t& _totalMemory, size_t& _freeMemory) const -{ - int prevDeviceID = getDevice(); - if (prevDeviceID != device_id_) - setDevice(device_id_); - - cudaSafeCall( cudaMemGetInfo(&_freeMemory, &_totalMemory) ); - - if (prevDeviceID != device_id_) - setDevice(prevDeviceID); -} - -size_t cv::gpu::DeviceInfo::freeMemory() const -{ - size_t _totalMemory, _freeMemory; - queryMemory(_totalMemory, _freeMemory); - return _freeMemory; -} - -size_t cv::gpu::DeviceInfo::totalMemory() const -{ - size_t _totalMemory, _freeMemory; - queryMemory(_totalMemory, _freeMemory); - return _totalMemory; -} - -bool cv::gpu::DeviceInfo::supports(FeatureSet feature_set) const -{ - int version = majorVersion() * 10 + minorVersion(); - return version >= feature_set; -} - -bool cv::gpu::DeviceInfo::isCompatible() const -{ - // Check PTX compatibility - if (TargetArchs::hasEqualOrLessPtx(majorVersion(), minorVersion())) - return true; - - // Check BIN compatibility - for (int i = minorVersion(); i >= 0; --i) - if (TargetArchs::hasBin(majorVersion(), i)) - return true; - - return false; -} - -void cv::gpu::DeviceInfo::query() -{ - const cudaDeviceProp* prop = deviceProps.get(device_id_); - - name_ = prop->name; - multi_processor_count_ = prop->multiProcessorCount; - majorVersion_ = prop->major; - minorVersion_ = prop->minor; -} - -namespace -{ - int convertSMVer2Cores(int major, int minor) - { - // Defines for GPU Architecture types (using the SM version to determine the # of cores per SM - typedef struct { - int SM; // 0xMm (hexidecimal notation), M = SM Major version, and m = SM minor version - int Cores; - } SMtoCores; - - SMtoCores gpuArchCoresPerSM[] = { { 0x10, 8 }, { 0x11, 8 }, { 0x12, 8 }, { 0x13, 8 }, { 0x20, 32 }, { 0x21, 48 }, {0x30, 192}, {0x35, 192}, { -1, -1 } }; - - int index = 0; - while (gpuArchCoresPerSM[index].SM != -1) - { - if (gpuArchCoresPerSM[index].SM == ((major << 4) + minor) ) - return gpuArchCoresPerSM[index].Cores; - index++; - } - - return -1; - } -} - -void cv::gpu::printCudaDeviceInfo(int device) -{ - int count = getCudaEnabledDeviceCount(); - bool valid = (device >= 0) && (device < count); - - int beg = valid ? device : 0; - int end = valid ? device+1 : count; - - printf("*** CUDA Device Query (Runtime API) version (CUDART static linking) *** \n\n"); - printf("Device count: %d\n", count); - - int driverVersion = 0, runtimeVersion = 0; - cudaSafeCall( cudaDriverGetVersion(&driverVersion) ); - cudaSafeCall( cudaRuntimeGetVersion(&runtimeVersion) ); - - const char *computeMode[] = { - "Default (multiple host threads can use ::cudaSetDevice() with device simultaneously)", - "Exclusive (only one host thread in one process is able to use ::cudaSetDevice() with this device)", - "Prohibited (no host thread can use ::cudaSetDevice() with this device)", - "Exclusive Process (many threads in one process is able to use ::cudaSetDevice() with this device)", - "Unknown", - NULL - }; - - for(int dev = beg; dev < end; ++dev) - { - cudaDeviceProp prop; - cudaSafeCall( cudaGetDeviceProperties(&prop, dev) ); - - printf("\nDevice %d: \"%s\"\n", dev, prop.name); - printf(" CUDA Driver Version / Runtime Version %d.%d / %d.%d\n", driverVersion/1000, driverVersion%100, runtimeVersion/1000, runtimeVersion%100); - printf(" CUDA Capability Major/Minor version number: %d.%d\n", prop.major, prop.minor); - printf(" Total amount of global memory: %.0f MBytes (%llu bytes)\n", (float)prop.totalGlobalMem/1048576.0f, (unsigned long long) prop.totalGlobalMem); - - int cores = convertSMVer2Cores(prop.major, prop.minor); - if (cores > 0) - printf(" (%2d) Multiprocessors x (%2d) CUDA Cores/MP: %d CUDA Cores\n", prop.multiProcessorCount, cores, cores * prop.multiProcessorCount); - - printf(" GPU Clock Speed: %.2f GHz\n", prop.clockRate * 1e-6f); - - printf(" Max Texture Dimension Size (x,y,z) 1D=(%d), 2D=(%d,%d), 3D=(%d,%d,%d)\n", - prop.maxTexture1D, prop.maxTexture2D[0], prop.maxTexture2D[1], - prop.maxTexture3D[0], prop.maxTexture3D[1], prop.maxTexture3D[2]); - printf(" Max Layered Texture Size (dim) x layers 1D=(%d) x %d, 2D=(%d,%d) x %d\n", - prop.maxTexture1DLayered[0], prop.maxTexture1DLayered[1], - prop.maxTexture2DLayered[0], prop.maxTexture2DLayered[1], prop.maxTexture2DLayered[2]); - - printf(" Total amount of constant memory: %u bytes\n", (int)prop.totalConstMem); - printf(" Total amount of shared memory per block: %u bytes\n", (int)prop.sharedMemPerBlock); - printf(" Total number of registers available per block: %d\n", prop.regsPerBlock); - printf(" Warp size: %d\n", prop.warpSize); - printf(" Maximum number of threads per block: %d\n", prop.maxThreadsPerBlock); - printf(" Maximum sizes of each dimension of a block: %d x %d x %d\n", prop.maxThreadsDim[0], prop.maxThreadsDim[1], prop.maxThreadsDim[2]); - printf(" Maximum sizes of each dimension of a grid: %d x %d x %d\n", prop.maxGridSize[0], prop.maxGridSize[1], prop.maxGridSize[2]); - printf(" Maximum memory pitch: %u bytes\n", (int)prop.memPitch); - printf(" Texture alignment: %u bytes\n", (int)prop.textureAlignment); - - printf(" Concurrent copy and execution: %s with %d copy engine(s)\n", (prop.deviceOverlap ? "Yes" : "No"), prop.asyncEngineCount); - printf(" Run time limit on kernels: %s\n", prop.kernelExecTimeoutEnabled ? "Yes" : "No"); - printf(" Integrated GPU sharing Host Memory: %s\n", prop.integrated ? "Yes" : "No"); - printf(" Support host page-locked memory mapping: %s\n", prop.canMapHostMemory ? "Yes" : "No"); - - printf(" Concurrent kernel execution: %s\n", prop.concurrentKernels ? "Yes" : "No"); - printf(" Alignment requirement for Surfaces: %s\n", prop.surfaceAlignment ? "Yes" : "No"); - printf(" Device has ECC support enabled: %s\n", prop.ECCEnabled ? "Yes" : "No"); - printf(" Device is using TCC driver mode: %s\n", prop.tccDriver ? "Yes" : "No"); - printf(" Device supports Unified Addressing (UVA): %s\n", prop.unifiedAddressing ? "Yes" : "No"); - printf(" Device PCI Bus ID / PCI location ID: %d / %d\n", prop.pciBusID, prop.pciDeviceID ); - printf(" Compute Mode:\n"); - printf(" %s \n", computeMode[prop.computeMode]); - } - - printf("\n"); - printf("deviceQuery, CUDA Driver = CUDART"); - printf(", CUDA Driver Version = %d.%d", driverVersion / 1000, driverVersion % 100); - printf(", CUDA Runtime Version = %d.%d", runtimeVersion/1000, runtimeVersion%100); - printf(", NumDevs = %d\n\n", count); - fflush(stdout); -} - -void cv::gpu::printShortCudaDeviceInfo(int device) -{ - int count = getCudaEnabledDeviceCount(); - bool valid = (device >= 0) && (device < count); - - int beg = valid ? device : 0; - int end = valid ? device+1 : count; - - int driverVersion = 0, runtimeVersion = 0; - cudaSafeCall( cudaDriverGetVersion(&driverVersion) ); - cudaSafeCall( cudaRuntimeGetVersion(&runtimeVersion) ); - - for(int dev = beg; dev < end; ++dev) - { - cudaDeviceProp prop; - cudaSafeCall( cudaGetDeviceProperties(&prop, dev) ); - - const char *arch_str = prop.major < 2 ? " (not Fermi)" : ""; - printf("Device %d: \"%s\" %.0fMb", dev, prop.name, (float)prop.totalGlobalMem/1048576.0f); - printf(", sm_%d%d%s", prop.major, prop.minor, arch_str); - - int cores = convertSMVer2Cores(prop.major, prop.minor); - if (cores > 0) - printf(", %d cores", cores * prop.multiProcessorCount); - - printf(", Driver/Runtime ver.%d.%d/%d.%d\n", driverVersion/1000, driverVersion%100, runtimeVersion/1000, runtimeVersion%100); - } - fflush(stdout); -} - -#endif // HAVE_CUDA - -//////////////////////////////// GpuMat /////////////////////////////// - -cv::gpu::GpuMat::GpuMat(const GpuMat& m) - : flags(m.flags), rows(m.rows), cols(m.cols), step(m.step), data(m.data), refcount(m.refcount), datastart(m.datastart), dataend(m.dataend) -{ - if (refcount) - CV_XADD(refcount, 1); -} - -cv::gpu::GpuMat::GpuMat(int rows_, int cols_, int type_, void* data_, size_t step_) : - flags(Mat::MAGIC_VAL + (type_ & TYPE_MASK)), rows(rows_), cols(cols_), - step(step_), data((uchar*)data_), refcount(0), - datastart((uchar*)data_), dataend((uchar*)data_) -{ - size_t minstep = cols * elemSize(); - - if (step == Mat::AUTO_STEP) - { - step = minstep; - flags |= Mat::CONTINUOUS_FLAG; - } - else - { - if (rows == 1) - step = minstep; - - CV_DbgAssert(step >= minstep); - - flags |= step == minstep ? Mat::CONTINUOUS_FLAG : 0; - } - dataend += step * (rows - 1) + minstep; -} - -cv::gpu::GpuMat::GpuMat(Size size_, int type_, void* data_, size_t step_) : - flags(Mat::MAGIC_VAL + (type_ & TYPE_MASK)), rows(size_.height), cols(size_.width), - step(step_), data((uchar*)data_), refcount(0), - datastart((uchar*)data_), dataend((uchar*)data_) -{ - size_t minstep = cols * elemSize(); - - if (step == Mat::AUTO_STEP) - { - step = minstep; - flags |= Mat::CONTINUOUS_FLAG; - } - else - { - if (rows == 1) - step = minstep; - - CV_DbgAssert(step >= minstep); - - flags |= step == minstep ? Mat::CONTINUOUS_FLAG : 0; - } - dataend += step * (rows - 1) + minstep; -} - -cv::gpu::GpuMat::GpuMat(const GpuMat& m, Range _rowRange, Range _colRange) -{ - flags = m.flags; - step = m.step; refcount = m.refcount; - data = m.data; datastart = m.datastart; dataend = m.dataend; - - if (_rowRange == Range::all()) - rows = m.rows; - else - { - CV_Assert(0 <= _rowRange.start && _rowRange.start <= _rowRange.end && _rowRange.end <= m.rows); - - rows = _rowRange.size(); - data += step*_rowRange.start; - } - - if (_colRange == Range::all()) - cols = m.cols; - else - { - CV_Assert(0 <= _colRange.start && _colRange.start <= _colRange.end && _colRange.end <= m.cols); - - cols = _colRange.size(); - data += _colRange.start*elemSize(); - flags &= cols < m.cols ? ~Mat::CONTINUOUS_FLAG : -1; - } - - if (rows == 1) - flags |= Mat::CONTINUOUS_FLAG; - - if (refcount) - CV_XADD(refcount, 1); - - if (rows <= 0 || cols <= 0) - rows = cols = 0; -} - -cv::gpu::GpuMat::GpuMat(const GpuMat& m, Rect roi) : - flags(m.flags), rows(roi.height), cols(roi.width), - step(m.step), data(m.data + roi.y*step), refcount(m.refcount), - datastart(m.datastart), dataend(m.dataend) -{ - flags &= roi.width < m.cols ? ~Mat::CONTINUOUS_FLAG : -1; - data += roi.x * elemSize(); - - CV_Assert(0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows); - - if (refcount) - CV_XADD(refcount, 1); - - if (rows <= 0 || cols <= 0) - rows = cols = 0; -} - -cv::gpu::GpuMat::GpuMat(const Mat& m) : - flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0) -{ - upload(m); -} - -GpuMat& cv::gpu::GpuMat::operator = (const GpuMat& m) -{ - if (this != &m) - { - GpuMat temp(m); - swap(temp); - } - - return *this; -} - -void cv::gpu::GpuMat::swap(GpuMat& b) -{ - std::swap(flags, b.flags); - std::swap(rows, b.rows); - std::swap(cols, b.cols); - std::swap(step, b.step); - std::swap(data, b.data); - std::swap(datastart, b.datastart); - std::swap(dataend, b.dataend); - std::swap(refcount, b.refcount); -} - -void cv::gpu::GpuMat::locateROI(Size& wholeSize, Point& ofs) const -{ - size_t esz = elemSize(); - ptrdiff_t delta1 = data - datastart; - ptrdiff_t delta2 = dataend - datastart; - - CV_DbgAssert(step > 0); - - if (delta1 == 0) - ofs.x = ofs.y = 0; - else - { - ofs.y = static_cast(delta1 / step); - ofs.x = static_cast((delta1 - step * ofs.y) / esz); - - CV_DbgAssert(data == datastart + ofs.y * step + ofs.x * esz); - } - - size_t minstep = (ofs.x + cols) * esz; - - wholeSize.height = std::max(static_cast((delta2 - minstep) / step + 1), ofs.y + rows); - wholeSize.width = std::max(static_cast((delta2 - step * (wholeSize.height - 1)) / esz), ofs.x + cols); -} - -GpuMat& cv::gpu::GpuMat::adjustROI(int dtop, int dbottom, int dleft, int dright) -{ - Size wholeSize; - Point ofs; - locateROI(wholeSize, ofs); - - size_t esz = elemSize(); - - int row1 = std::max(ofs.y - dtop, 0); - int row2 = std::min(ofs.y + rows + dbottom, wholeSize.height); - - int col1 = std::max(ofs.x - dleft, 0); - int col2 = std::min(ofs.x + cols + dright, wholeSize.width); - - data += (row1 - ofs.y) * step + (col1 - ofs.x) * esz; - rows = row2 - row1; - cols = col2 - col1; - - if (esz * cols == step || rows == 1) - flags |= Mat::CONTINUOUS_FLAG; - else - flags &= ~Mat::CONTINUOUS_FLAG; - - return *this; -} - -GpuMat cv::gpu::GpuMat::reshape(int new_cn, int new_rows) const -{ - GpuMat hdr = *this; - - int cn = channels(); - if (new_cn == 0) - new_cn = cn; - - int total_width = cols * cn; - - if ((new_cn > total_width || total_width % new_cn != 0) && new_rows == 0) - new_rows = rows * total_width / new_cn; - - if (new_rows != 0 && new_rows != rows) - { - int total_size = total_width * rows; - - if (!isContinuous()) - CV_Error(CV_BadStep, "The matrix is not continuous, thus its number of rows can not be changed"); - - if ((unsigned)new_rows > (unsigned)total_size) - CV_Error(CV_StsOutOfRange, "Bad new number of rows"); - - total_width = total_size / new_rows; - - if (total_width * new_rows != total_size) - CV_Error(CV_StsBadArg, "The total number of matrix elements is not divisible by the new number of rows"); - - hdr.rows = new_rows; - hdr.step = total_width * elemSize1(); - } - - int new_width = total_width / new_cn; - - if (new_width * new_cn != total_width) - CV_Error(CV_BadNumChannels, "The total width is not divisible by the new number of channels"); - - hdr.cols = new_width; - hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn - 1) << CV_CN_SHIFT); - - return hdr; -} - -cv::Mat::Mat(const GpuMat& m) : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0), datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows) -{ - m.download(*this); -} - -void cv::gpu::createContinuous(int rows, int cols, int type, GpuMat& m) -{ - int area = rows * cols; - if (m.empty() || m.type() != type || !m.isContinuous() || m.size().area() < area) - m.create(1, area, type); - - m.cols = cols; - m.rows = rows; - m.step = m.elemSize() * cols; - m.flags |= Mat::CONTINUOUS_FLAG; -} - -void cv::gpu::ensureSizeIsEnough(int rows, int cols, int type, GpuMat& m) -{ - if (m.empty() || m.type() != type || m.data != m.datastart) - m.create(rows, cols, type); - else - { - const size_t esz = m.elemSize(); - const ptrdiff_t delta2 = m.dataend - m.datastart; - - const size_t minstep = m.cols * esz; - - Size wholeSize; - wholeSize.height = std::max(static_cast((delta2 - minstep) / m.step + 1), m.rows); - wholeSize.width = std::max(static_cast((delta2 - m.step * (wholeSize.height - 1)) / esz), m.cols); - - if (wholeSize.height < rows || wholeSize.width < cols) - m.create(rows, cols, type); - else - { - m.cols = cols; - m.rows = rows; - } - } -} - -GpuMat cv::gpu::allocMatFromBuf(int rows, int cols, int type, GpuMat &mat) -{ - if (!mat.empty() && mat.type() == type && mat.rows >= rows && mat.cols >= cols) - return mat(Rect(0, 0, cols, rows)); - return mat = GpuMat(rows, cols, type); -} - -namespace -{ - class GpuFuncTable - { - public: - virtual ~GpuFuncTable() {} - - virtual void copy(const Mat& src, GpuMat& dst) const = 0; - virtual void copy(const GpuMat& src, Mat& dst) const = 0; - virtual void copy(const GpuMat& src, GpuMat& dst) const = 0; - - virtual void copyWithMask(const GpuMat& src, GpuMat& dst, const GpuMat& mask) const = 0; - - virtual void convert(const GpuMat& src, GpuMat& dst) const = 0; - virtual void convert(const GpuMat& src, GpuMat& dst, double alpha, double beta) const = 0; - - virtual void setTo(GpuMat& m, Scalar s, const GpuMat& mask) const = 0; - - virtual void mallocPitch(void** devPtr, size_t* step, size_t width, size_t height) const = 0; - virtual void free(void* devPtr) const = 0; - }; -} - -#ifndef HAVE_CUDA - -namespace -{ - class EmptyFuncTable : public GpuFuncTable - { - public: - void copy(const Mat&, GpuMat&) const { throw_nogpu; } - void copy(const GpuMat&, Mat&) const { throw_nogpu; } - void copy(const GpuMat&, GpuMat&) const { throw_nogpu; } - - void copyWithMask(const GpuMat&, GpuMat&, const GpuMat&) const { throw_nogpu; } - - void convert(const GpuMat&, GpuMat&) const { throw_nogpu; } - void convert(const GpuMat&, GpuMat&, double, double) const { throw_nogpu; } - - void setTo(GpuMat&, Scalar, const GpuMat&) const { throw_nogpu; } - - void mallocPitch(void**, size_t*, size_t, size_t) const { throw_nogpu; } - void free(void*) const {} - }; - - const GpuFuncTable* gpuFuncTable() - { - static EmptyFuncTable empty; - return ∅ - } -} - -#else // HAVE_CUDA - -namespace cv { namespace gpu { namespace device -{ - void copyToWithMask_gpu(PtrStepSzb src, PtrStepSzb dst, size_t elemSize1, int cn, PtrStepSzb mask, bool colorMask, cudaStream_t stream); - - template - void set_to_gpu(PtrStepSzb mat, const T* scalar, int channels, cudaStream_t stream); - - template - void set_to_gpu(PtrStepSzb mat, const T* scalar, PtrStepSzb mask, int channels, cudaStream_t stream); - - void convert_gpu(PtrStepSzb src, int sdepth, PtrStepSzb dst, int ddepth, double alpha, double beta, cudaStream_t stream); -}}} - -namespace -{ - template void kernelSetCaller(GpuMat& src, Scalar s, cudaStream_t stream) - { - Scalar_ sf = s; - cv::gpu::device::set_to_gpu(src, sf.val, src.channels(), stream); - } - - template void kernelSetCaller(GpuMat& src, Scalar s, const GpuMat& mask, cudaStream_t stream) - { - Scalar_ sf = s; - cv::gpu::device::set_to_gpu(src, sf.val, mask, src.channels(), stream); - } -} - - -namespace cv { namespace gpu -{ - CV_EXPORTS void copyWithMask(const cv::gpu::GpuMat&, cv::gpu::GpuMat&, const cv::gpu::GpuMat&, CUstream_st*); - CV_EXPORTS void convertTo(const cv::gpu::GpuMat&, cv::gpu::GpuMat&); - CV_EXPORTS void convertTo(const cv::gpu::GpuMat&, cv::gpu::GpuMat&, double, double, CUstream_st*); - CV_EXPORTS void setTo(cv::gpu::GpuMat&, cv::Scalar, CUstream_st*); - CV_EXPORTS void setTo(cv::gpu::GpuMat&, cv::Scalar, const cv::gpu::GpuMat&, CUstream_st*); - CV_EXPORTS void setTo(cv::gpu::GpuMat&, cv::Scalar); - CV_EXPORTS void setTo(cv::gpu::GpuMat&, cv::Scalar, const cv::gpu::GpuMat&); -}} - - -namespace cv { namespace gpu -{ - void copyWithMask(const GpuMat& src, GpuMat& dst, const GpuMat& mask, cudaStream_t stream = 0) - { - CV_Assert(src.size() == dst.size() && src.type() == dst.type()); - CV_Assert(src.size() == mask.size() && mask.depth() == CV_8U && (mask.channels() == 1 || mask.channels() == src.channels())); - - cv::gpu::device::copyToWithMask_gpu(src.reshape(1), dst.reshape(1), src.elemSize1(), src.channels(), mask.reshape(1), mask.channels() != 1, stream); - } - - void convertTo(const GpuMat& src, GpuMat& dst) - { - cv::gpu::device::convert_gpu(src.reshape(1), src.depth(), dst.reshape(1), dst.depth(), 1.0, 0.0, 0); - } - - void convertTo(const GpuMat& src, GpuMat& dst, double alpha, double beta, cudaStream_t stream = 0) - { - cv::gpu::device::convert_gpu(src.reshape(1), src.depth(), dst.reshape(1), dst.depth(), alpha, beta, stream); - } - - void setTo(GpuMat& src, Scalar s, cudaStream_t stream) - { - typedef void (*caller_t)(GpuMat& src, Scalar s, cudaStream_t stream); - - static const caller_t callers[] = - { - kernelSetCaller, kernelSetCaller, kernelSetCaller, kernelSetCaller, kernelSetCaller, - kernelSetCaller, kernelSetCaller - }; - - callers[src.depth()](src, s, stream); - } - - void setTo(GpuMat& src, Scalar s, const GpuMat& mask, cudaStream_t stream) - { - typedef void (*caller_t)(GpuMat& src, Scalar s, const GpuMat& mask, cudaStream_t stream); - - static const caller_t callers[] = - { - kernelSetCaller, kernelSetCaller, kernelSetCaller, kernelSetCaller, kernelSetCaller, - kernelSetCaller, kernelSetCaller - }; - - callers[src.depth()](src, s, mask, stream); - } - - void setTo(GpuMat& src, Scalar s) - { - setTo(src, s, 0); - } - - void setTo(GpuMat& src, Scalar s, const GpuMat& mask) - { - setTo(src, s, mask, 0); - } -}} - -namespace -{ - template struct NPPTypeTraits; - template<> struct NPPTypeTraits { typedef Npp8u npp_type; }; - template<> struct NPPTypeTraits { typedef Npp8s npp_type; }; - template<> struct NPPTypeTraits { typedef Npp16u npp_type; }; - template<> struct NPPTypeTraits { typedef Npp16s npp_type; }; - template<> struct NPPTypeTraits { typedef Npp32s npp_type; }; - template<> struct NPPTypeTraits { typedef Npp32f npp_type; }; - template<> struct NPPTypeTraits { typedef Npp64f npp_type; }; - - ////////////////////////////////////////////////////////////////////////// - // Convert - - template struct NppConvertFunc - { - typedef typename NPPTypeTraits::npp_type src_t; - typedef typename NPPTypeTraits::npp_type dst_t; - - typedef NppStatus (*func_ptr)(const src_t* pSrc, int nSrcStep, dst_t* pDst, int nDstStep, NppiSize oSizeROI); - }; - template struct NppConvertFunc - { - typedef typename NPPTypeTraits::npp_type dst_t; - - typedef NppStatus (*func_ptr)(const Npp32f* pSrc, int nSrcStep, dst_t* pDst, int nDstStep, NppiSize oSizeROI, NppRoundMode eRoundMode); - }; - - template::func_ptr func> struct NppCvt - { - typedef typename NPPTypeTraits::npp_type src_t; - typedef typename NPPTypeTraits::npp_type dst_t; - - static void call(const GpuMat& src, GpuMat& dst) - { - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - nppSafeCall( func(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), sz) ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - }; - template::func_ptr func> struct NppCvt - { - typedef typename NPPTypeTraits::npp_type dst_t; - - static void call(const GpuMat& src, GpuMat& dst) - { - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - nppSafeCall( func(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), sz, NPP_RND_NEAR) ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - }; - - ////////////////////////////////////////////////////////////////////////// - // Set - - template struct NppSetFunc - { - typedef typename NPPTypeTraits::npp_type src_t; - - typedef NppStatus (*func_ptr)(const src_t values[], src_t* pSrc, int nSrcStep, NppiSize oSizeROI); - }; - template struct NppSetFunc - { - typedef typename NPPTypeTraits::npp_type src_t; - - typedef NppStatus (*func_ptr)(src_t val, src_t* pSrc, int nSrcStep, NppiSize oSizeROI); - }; - template struct NppSetFunc - { - typedef NppStatus (*func_ptr)(Npp8s values[], Npp8s* pSrc, int nSrcStep, NppiSize oSizeROI); - }; - template<> struct NppSetFunc - { - typedef NppStatus (*func_ptr)(Npp8s val, Npp8s* pSrc, int nSrcStep, NppiSize oSizeROI); - }; - - template::func_ptr func> struct NppSet - { - typedef typename NPPTypeTraits::npp_type src_t; - - static void call(GpuMat& src, Scalar s) - { - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - Scalar_ nppS = s; - - nppSafeCall( func(nppS.val, src.ptr(), static_cast(src.step), sz) ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - }; - template::func_ptr func> struct NppSet - { - typedef typename NPPTypeTraits::npp_type src_t; - - static void call(GpuMat& src, Scalar s) - { - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - Scalar_ nppS = s; - - nppSafeCall( func(nppS[0], src.ptr(), static_cast(src.step), sz) ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - }; - - template struct NppSetMaskFunc - { - typedef typename NPPTypeTraits::npp_type src_t; - - typedef NppStatus (*func_ptr)(const src_t values[], src_t* pSrc, int nSrcStep, NppiSize oSizeROI, const Npp8u* pMask, int nMaskStep); - }; - template struct NppSetMaskFunc - { - typedef typename NPPTypeTraits::npp_type src_t; - - typedef NppStatus (*func_ptr)(src_t val, src_t* pSrc, int nSrcStep, NppiSize oSizeROI, const Npp8u* pMask, int nMaskStep); - }; - - template::func_ptr func> struct NppSetMask - { - typedef typename NPPTypeTraits::npp_type src_t; - - static void call(GpuMat& src, Scalar s, const GpuMat& mask) - { - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - Scalar_ nppS = s; - - nppSafeCall( func(nppS.val, src.ptr(), static_cast(src.step), sz, mask.ptr(), static_cast(mask.step)) ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - }; - template::func_ptr func> struct NppSetMask - { - typedef typename NPPTypeTraits::npp_type src_t; - - static void call(GpuMat& src, Scalar s, const GpuMat& mask) - { - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - Scalar_ nppS = s; - - nppSafeCall( func(nppS[0], src.ptr(), static_cast(src.step), sz, mask.ptr(), static_cast(mask.step)) ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - }; - - ////////////////////////////////////////////////////////////////////////// - // CopyMasked - - template struct NppCopyMaskedFunc - { - typedef typename NPPTypeTraits::npp_type src_t; - - typedef NppStatus (*func_ptr)(const src_t* pSrc, int nSrcStep, src_t* pDst, int nDstStep, NppiSize oSizeROI, const Npp8u* pMask, int nMaskStep); - }; - - template::func_ptr func> struct NppCopyMasked - { - typedef typename NPPTypeTraits::npp_type src_t; - - static void call(const GpuMat& src, GpuMat& dst, const GpuMat& mask, cudaStream_t /*stream*/) - { - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - nppSafeCall( func(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), sz, mask.ptr(), static_cast(mask.step)) ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - }; - - template static inline bool isAligned(const T* ptr, size_t size) - { - return reinterpret_cast(ptr) % size == 0; - } - - ////////////////////////////////////////////////////////////////////////// - // CudaFuncTable - - class CudaFuncTable : public GpuFuncTable - { - public: - void copy(const Mat& src, GpuMat& dst) const - { - cudaSafeCall( cudaMemcpy2D(dst.data, dst.step, src.data, src.step, src.cols * src.elemSize(), src.rows, cudaMemcpyHostToDevice) ); - } - void copy(const GpuMat& src, Mat& dst) const - { - cudaSafeCall( cudaMemcpy2D(dst.data, dst.step, src.data, src.step, src.cols * src.elemSize(), src.rows, cudaMemcpyDeviceToHost) ); - } - void copy(const GpuMat& src, GpuMat& dst) const - { - cudaSafeCall( cudaMemcpy2D(dst.data, dst.step, src.data, src.step, src.cols * src.elemSize(), src.rows, cudaMemcpyDeviceToDevice) ); - } - - void copyWithMask(const GpuMat& src, GpuMat& dst, const GpuMat& mask) const - { - CV_Assert(src.depth() <= CV_64F && src.channels() <= 4); - CV_Assert(src.size() == dst.size() && src.type() == dst.type()); - CV_Assert(src.size() == mask.size() && mask.depth() == CV_8U && (mask.channels() == 1 || mask.channels() == src.channels())); - - if (src.depth() == CV_64F) - { - if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) - CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); - } - - typedef void (*func_t)(const GpuMat& src, GpuMat& dst, const GpuMat& mask, cudaStream_t stream); - static const func_t funcs[7][4] = - { - /* 8U */ {NppCopyMasked::call, cv::gpu::copyWithMask, NppCopyMasked::call, NppCopyMasked::call}, - /* 8S */ {cv::gpu::copyWithMask , cv::gpu::copyWithMask, cv::gpu::copyWithMask , cv::gpu::copyWithMask }, - /* 16U */ {NppCopyMasked::call, cv::gpu::copyWithMask, NppCopyMasked::call, NppCopyMasked::call}, - /* 16S */ {NppCopyMasked::call, cv::gpu::copyWithMask, NppCopyMasked::call, NppCopyMasked::call}, - /* 32S */ {NppCopyMasked::call, cv::gpu::copyWithMask, NppCopyMasked::call, NppCopyMasked::call}, - /* 32F */ {NppCopyMasked::call, cv::gpu::copyWithMask, NppCopyMasked::call, NppCopyMasked::call}, - /* 64F */ {cv::gpu::copyWithMask , cv::gpu::copyWithMask, cv::gpu::copyWithMask , cv::gpu::copyWithMask } - }; - - const func_t func = mask.channels() == src.channels() ? funcs[src.depth()][src.channels() - 1] : cv::gpu::copyWithMask; - - func(src, dst, mask, 0); - } - - void convert(const GpuMat& src, GpuMat& dst) const - { - typedef void (*func_t)(const GpuMat& src, GpuMat& dst); - static const func_t funcs[7][7][4] = - { - { - /* 8U -> 8U */ {0, 0, 0, 0}, - /* 8U -> 8S */ {cv::gpu::convertTo , cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo }, - /* 8U -> 16U */ {NppCvt::call, cv::gpu::convertTo, cv::gpu::convertTo, NppCvt::call}, - /* 8U -> 16S */ {NppCvt::call, cv::gpu::convertTo, cv::gpu::convertTo, NppCvt::call}, - /* 8U -> 32S */ {cv::gpu::convertTo , cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo }, - /* 8U -> 32F */ {NppCvt::call, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo }, - /* 8U -> 64F */ {cv::gpu::convertTo , cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo } - }, - { - /* 8S -> 8U */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 8S -> 8S */ {0,0,0,0}, - /* 8S -> 16U */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 8S -> 16S */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 8S -> 32S */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 8S -> 32F */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 8S -> 64F */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo} - }, - { - /* 16U -> 8U */ {NppCvt::call, cv::gpu::convertTo, cv::gpu::convertTo, NppCvt::call}, - /* 16U -> 8S */ {cv::gpu::convertTo , cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo }, - /* 16U -> 16U */ {0,0,0,0}, - /* 16U -> 16S */ {cv::gpu::convertTo , cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo }, - /* 16U -> 32S */ {NppCvt::call, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo }, - /* 16U -> 32F */ {NppCvt::call, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo }, - /* 16U -> 64F */ {cv::gpu::convertTo , cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo } - }, - { - /* 16S -> 8U */ {NppCvt::call, cv::gpu::convertTo, cv::gpu::convertTo, NppCvt::call}, - /* 16S -> 8S */ {cv::gpu::convertTo , cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo }, - /* 16S -> 16U */ {cv::gpu::convertTo , cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo }, - /* 16S -> 16S */ {0,0,0,0}, - /* 16S -> 32S */ {NppCvt::call, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo }, - /* 16S -> 32F */ {NppCvt::call, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo }, - /* 16S -> 64F */ {cv::gpu::convertTo , cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo } - }, - { - /* 32S -> 8U */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 32S -> 8S */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 32S -> 16U */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 32S -> 16S */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 32S -> 32S */ {0,0,0,0}, - /* 32S -> 32F */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 32S -> 64F */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo} - }, - { - /* 32F -> 8U */ {NppCvt::call, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 32F -> 8S */ {cv::gpu::convertTo , cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 32F -> 16U */ {NppCvt::call, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 32F -> 16S */ {NppCvt::call, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 32F -> 32S */ {cv::gpu::convertTo , cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 32F -> 32F */ {0,0,0,0}, - /* 32F -> 64F */ {cv::gpu::convertTo , cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo} - }, - { - /* 64F -> 8U */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 64F -> 8S */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 64F -> 16U */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 64F -> 16S */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 64F -> 32S */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 64F -> 32F */ {cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo, cv::gpu::convertTo}, - /* 64F -> 64F */ {0,0,0,0} - } - }; - - CV_Assert(src.depth() <= CV_64F && src.channels() <= 4); - CV_Assert(dst.depth() <= CV_64F); - CV_Assert(src.size() == dst.size() && src.channels() == dst.channels()); - - if (src.depth() == CV_64F || dst.depth() == CV_64F) - { - if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) - CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); - } - - bool aligned = isAligned(src.data, 16) && isAligned(dst.data, 16); - if (!aligned) - { - cv::gpu::convertTo(src, dst); - return; - } - - const func_t func = funcs[src.depth()][dst.depth()][src.channels() - 1]; - CV_DbgAssert(func != 0); - - func(src, dst); - } - - void convert(const GpuMat& src, GpuMat& dst, double alpha, double beta) const - { - CV_Assert(src.depth() <= CV_64F && src.channels() <= 4); - CV_Assert(dst.depth() <= CV_64F); - - if (src.depth() == CV_64F || dst.depth() == CV_64F) - { - if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) - CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); - } - - cv::gpu::convertTo(src, dst, alpha, beta); - } - - void setTo(GpuMat& m, Scalar s, const GpuMat& mask) const - { - if (mask.empty()) - { - if (s[0] == 0.0 && s[1] == 0.0 && s[2] == 0.0 && s[3] == 0.0) - { - cudaSafeCall( cudaMemset2D(m.data, m.step, 0, m.cols * m.elemSize(), m.rows) ); - return; - } - - if (m.depth() == CV_8U) - { - int cn = m.channels(); - - if (cn == 1 || (cn == 2 && s[0] == s[1]) || (cn == 3 && s[0] == s[1] && s[0] == s[2]) || (cn == 4 && s[0] == s[1] && s[0] == s[2] && s[0] == s[3])) - { - int val = saturate_cast(s[0]); - cudaSafeCall( cudaMemset2D(m.data, m.step, val, m.cols * m.elemSize(), m.rows) ); - return; - } - } - - typedef void (*func_t)(GpuMat& src, Scalar s); - static const func_t funcs[7][4] = - { - {NppSet::call, cv::gpu::setTo , cv::gpu::setTo , NppSet::call}, - {NppSet::call, NppSet::call, NppSet::call, NppSet::call}, - {NppSet::call, NppSet::call, cv::gpu::setTo , NppSet::call}, - {NppSet::call, NppSet::call, cv::gpu::setTo , NppSet::call}, - {NppSet::call, cv::gpu::setTo , cv::gpu::setTo , NppSet::call}, - {NppSet::call, cv::gpu::setTo , cv::gpu::setTo , NppSet::call}, - {cv::gpu::setTo , cv::gpu::setTo , cv::gpu::setTo , cv::gpu::setTo } - }; - - CV_Assert(m.depth() <= CV_64F && m.channels() <= 4); - - if (m.depth() == CV_64F) - { - if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) - CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); - } - - funcs[m.depth()][m.channels() - 1](m, s); - } - else - { - typedef void (*func_t)(GpuMat& src, Scalar s, const GpuMat& mask); - static const func_t funcs[7][4] = - { - {NppSetMask::call, cv::gpu::setTo, cv::gpu::setTo, NppSetMask::call}, - {cv::gpu::setTo , cv::gpu::setTo, cv::gpu::setTo, cv::gpu::setTo }, - {NppSetMask::call, cv::gpu::setTo, cv::gpu::setTo, NppSetMask::call}, - {NppSetMask::call, cv::gpu::setTo, cv::gpu::setTo, NppSetMask::call}, - {NppSetMask::call, cv::gpu::setTo, cv::gpu::setTo, NppSetMask::call}, - {NppSetMask::call, cv::gpu::setTo, cv::gpu::setTo, NppSetMask::call}, - {cv::gpu::setTo , cv::gpu::setTo, cv::gpu::setTo, cv::gpu::setTo } - }; - - CV_Assert(m.depth() <= CV_64F && m.channels() <= 4); - - if (m.depth() == CV_64F) - { - if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) - CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); - } - - funcs[m.depth()][m.channels() - 1](m, s, mask); - } - } - - void mallocPitch(void** devPtr, size_t* step, size_t width, size_t height) const - { - cudaSafeCall( cudaMallocPitch(devPtr, step, width, height) ); - } - - void free(void* devPtr) const - { - cudaFree(devPtr); - } - }; - - const GpuFuncTable* gpuFuncTable() - { - static CudaFuncTable funcTable; - return &funcTable; - } -} - -#endif // HAVE_CUDA - -void cv::gpu::GpuMat::upload(const Mat& m) -{ - CV_DbgAssert(!m.empty()); - - create(m.size(), m.type()); - - gpuFuncTable()->copy(m, *this); -} - -void cv::gpu::GpuMat::download(Mat& m) const -{ - CV_DbgAssert(!empty()); - - m.create(size(), type()); - - gpuFuncTable()->copy(*this, m); -} - -void cv::gpu::GpuMat::copyTo(GpuMat& m) const -{ - CV_DbgAssert(!empty()); - - m.create(size(), type()); - - gpuFuncTable()->copy(*this, m); -} - -void cv::gpu::GpuMat::copyTo(GpuMat& mat, const GpuMat& mask) const -{ - if (mask.empty()) - copyTo(mat); - else - { - mat.create(size(), type()); - - gpuFuncTable()->copyWithMask(*this, mat, mask); - } -} - -void cv::gpu::GpuMat::convertTo(GpuMat& dst, int rtype, double alpha, double beta) const -{ - bool noScale = fabs(alpha - 1) < std::numeric_limits::epsilon() && fabs(beta) < std::numeric_limits::epsilon(); - - if (rtype < 0) - rtype = type(); - else - rtype = CV_MAKETYPE(CV_MAT_DEPTH(rtype), channels()); - - int sdepth = depth(); - int ddepth = CV_MAT_DEPTH(rtype); - if (sdepth == ddepth && noScale) - { - copyTo(dst); - return; - } - - GpuMat temp; - const GpuMat* psrc = this; - if (sdepth != ddepth && psrc == &dst) - { - temp = *this; - psrc = &temp; - } - - dst.create(size(), rtype); - - if (noScale) - gpuFuncTable()->convert(*psrc, dst); - else - gpuFuncTable()->convert(*psrc, dst, alpha, beta); -} - -GpuMat& cv::gpu::GpuMat::setTo(Scalar s, const GpuMat& mask) -{ - CV_Assert(mask.empty() || mask.type() == CV_8UC1); - CV_DbgAssert(!empty()); - - gpuFuncTable()->setTo(*this, s, mask); - - return *this; -} - -void cv::gpu::GpuMat::create(int _rows, int _cols, int _type) -{ - _type &= TYPE_MASK; - - if (rows == _rows && cols == _cols && type() == _type && data) - return; - - if (data) - release(); - - CV_DbgAssert(_rows >= 0 && _cols >= 0); - - if (_rows > 0 && _cols > 0) - { - flags = Mat::MAGIC_VAL + _type; - rows = _rows; - cols = _cols; - - size_t esz = elemSize(); - - void* devPtr; - gpuFuncTable()->mallocPitch(&devPtr, &step, esz * cols, rows); - - // Single row must be continuous - if (rows == 1) - step = esz * cols; - - if (esz * cols == step) - flags |= Mat::CONTINUOUS_FLAG; - - int64 _nettosize = static_cast(step) * rows; - size_t nettosize = static_cast(_nettosize); - - datastart = data = static_cast(devPtr); - dataend = data + nettosize; - - refcount = static_cast(fastMalloc(sizeof(*refcount))); - *refcount = 1; - } -} - -void cv::gpu::GpuMat::release() -{ - if (refcount && CV_XADD(refcount, -1) == 1) - { - fastFree(refcount); - - gpuFuncTable()->free(datastart); - } - - data = datastart = dataend = 0; - step = rows = cols = 0; - refcount = 0; -} - -//////////////////////////////////////////////////////////////////////// -// Error handling - -void cv::gpu::error(const char *error_string, const char *file, const int line, const char *func) -{ - int code = CV_GpuApiCallError; - - if (std::uncaught_exception()) - { - const char* errorStr = cvErrorStr(code); - const char* function = func ? func : "unknown function"; - - std::cerr << "OpenCV Error: " << errorStr << "(" << error_string << ") in " << function << ", file " << file << ", line " << line; - std::cerr.flush(); - } - else - cv::error( cv::Exception(code, error_string, func, file, line) ); -} diff --git a/modules/core/src/lapack.cpp b/modules/core/src/lapack.cpp index bf376c8753..f6bc7c88c9 100644 --- a/modules/core/src/lapack.cpp +++ b/modules/core/src/lapack.cpp @@ -41,6 +41,7 @@ //M*/ #include "precomp.hpp" +#include #if defined _M_IX86 && defined _MSC_VER && _MSC_VER < 1700 #pragma float_control(precise, on) @@ -531,12 +532,12 @@ template<> inline int VBLAS::givensx(double* a, double* b, int n, double #endif template void -JacobiSVDImpl_(_Tp* At, size_t astep, _Tp* _W, _Tp* Vt, size_t vstep, int m, int n, int n1, double minval) +JacobiSVDImpl_(_Tp* At, size_t astep, _Tp* _W, _Tp* Vt, size_t vstep, + int m, int n, int n1, double minval, _Tp eps) { VBLAS<_Tp> vblas; AutoBuffer Wbuf(n); double* W = Wbuf; - _Tp eps = DBL_EPSILON*10; int i, j, k, iter, max_iter = std::max(m, 30); _Tp c, s; double sd; @@ -577,10 +578,10 @@ JacobiSVDImpl_(_Tp* At, size_t astep, _Tp* _W, _Tp* Vt, size_t vstep, int m, int continue; p *= 2; - double beta = a - b, gamma = hypot((double)p, beta), delta; + double beta = a - b, gamma = hypot((double)p, beta); if( beta < 0 ) { - delta = (gamma - beta)*0.5; + double delta = (gamma - beta)*0.5; s = (_Tp)std::sqrt(delta/gamma); c = (_Tp)(p/(gamma*s*2)); } @@ -588,36 +589,18 @@ JacobiSVDImpl_(_Tp* At, size_t astep, _Tp* _W, _Tp* Vt, size_t vstep, int m, int { c = (_Tp)std::sqrt((gamma + beta)/(gamma*2)); s = (_Tp)(p/(gamma*c*2)); - delta = p*p*0.5/(gamma + beta); } - W[i] += delta; - W[j] -= delta; - - if( iter % 2 != 0 && W[i] > 0 && W[j] > 0 ) + a = b = 0; + for( k = 0; k < m; k++ ) { - k = vblas.givens(Ai, Aj, m, c, s); + _Tp t0 = c*Ai[k] + s*Aj[k]; + _Tp t1 = -s*Ai[k] + c*Aj[k]; + Ai[k] = t0; Aj[k] = t1; - for( ; k < m; k++ ) - { - _Tp t0 = c*Ai[k] + s*Aj[k]; - _Tp t1 = -s*Ai[k] + c*Aj[k]; - Ai[k] = t0; Aj[k] = t1; - } - } - else - { - a = b = 0; - for( k = 0; k < m; k++ ) - { - _Tp t0 = c*Ai[k] + s*Aj[k]; - _Tp t1 = -s*Ai[k] + c*Aj[k]; - Ai[k] = t0; Aj[k] = t1; - - a += (double)t0*t0; b += (double)t1*t1; - } - W[i] = a; W[j] = b; + a += (double)t0*t0; b += (double)t1*t1; } + W[i] = a; W[j] = b; changed = true; @@ -729,12 +712,12 @@ JacobiSVDImpl_(_Tp* At, size_t astep, _Tp* _W, _Tp* Vt, size_t vstep, int m, int static void JacobiSVD(float* At, size_t astep, float* W, float* Vt, size_t vstep, int m, int n, int n1=-1) { - JacobiSVDImpl_(At, astep, W, Vt, vstep, m, n, !Vt ? 0 : n1 < 0 ? n : n1, FLT_MIN); + JacobiSVDImpl_(At, astep, W, Vt, vstep, m, n, !Vt ? 0 : n1 < 0 ? n : n1, FLT_MIN, FLT_EPSILON*2); } static void JacobiSVD(double* At, size_t astep, double* W, double* Vt, size_t vstep, int m, int n, int n1=-1) { - JacobiSVDImpl_(At, astep, W, Vt, vstep, m, n, !Vt ? 0 : n1 < 0 ? n : n1, DBL_MIN); + JacobiSVDImpl_(At, astep, W, Vt, vstep, m, n, !Vt ? 0 : n1 < 0 ? n : n1, DBL_MIN, DBL_EPSILON*10); } /* y[0:m,0:n] += diag(a[0:1,0:m]) * x[0:m,0:n] */ @@ -1482,7 +1465,7 @@ bool cv::solve( InputArray _src, InputArray _src2arg, OutputArray _dst, int meth /////////////////// finding eigenvalues and eigenvectors of a symmetric matrix /////////////// -bool cv::eigen( InputArray _src, bool computeEvects, OutputArray _evals, OutputArray _evects ) +bool cv::eigen( InputArray _src, OutputArray _evals, OutputArray _evects ) { Mat src = _src.getMat(); int type = src.type(); @@ -1492,7 +1475,7 @@ bool cv::eigen( InputArray _src, bool computeEvects, OutputArray _evals, OutputA CV_Assert (type == CV_32F || type == CV_64F); Mat v; - if( computeEvects ) + if( _evects.needed() ) { _evects.create(n, n, type); v = _evects.getMat(); @@ -1512,16 +1495,6 @@ bool cv::eigen( InputArray _src, bool computeEvects, OutputArray _evals, OutputA return ok; } -bool cv::eigen( InputArray src, OutputArray evals, int, int ) -{ - return eigen(src, false, evals, noArray()); -} - -bool cv::eigen( InputArray src, OutputArray evals, OutputArray evects, int, int) -{ - return eigen(src, true, evals, evects); -} - namespace cv { @@ -1689,7 +1662,6 @@ cvDet( const CvArr* arr ) if( rows == 3 ) return det3(Md); } - return cv::determinant(cv::Mat(mat)); } return cv::determinant(cv::cvarrToMat(arr)); } @@ -1724,13 +1696,13 @@ cvSolve( const CvArr* Aarr, const CvArr* barr, CvArr* xarr, int method ) CV_IMPL void cvEigenVV( CvArr* srcarr, CvArr* evectsarr, CvArr* evalsarr, double, - int lowindex, int highindex) + int, int ) { cv::Mat src = cv::cvarrToMat(srcarr), evals0 = cv::cvarrToMat(evalsarr), evals = evals0; if( evectsarr ) { cv::Mat evects0 = cv::cvarrToMat(evectsarr), evects = evects0; - eigen(src, evals, evects, lowindex, highindex); + eigen(src, evals, evects); if( evects0.data != evects.data ) { uchar* p = evects0.data; @@ -1739,7 +1711,7 @@ cvEigenVV( CvArr* srcarr, CvArr* evectsarr, CvArr* evalsarr, double, } } else - eigen(src, evals, lowindex, highindex); + eigen(src, evals); if( evals0.data != evals.data ) { uchar* p = evals0.data; @@ -1851,4 +1823,4 @@ cvSVBkSb( const CvArr* warr, const CvArr* uarr, cv::SVD::backSubst(w, u, v, rhs, dst); CV_Assert( dst.data == dst0.data ); -} \ No newline at end of file +} diff --git a/modules/core/src/mathfuncs.cpp b/modules/core/src/mathfuncs.cpp index 8e76d72355..2df111f0db 100644 --- a/modules/core/src/mathfuncs.cpp +++ b/modules/core/src/mathfuncs.cpp @@ -2350,7 +2350,7 @@ int cv::solveCubic( InputArray _coeffs, OutputArray _roots ) coeffs.size() == Size(1, n0) || coeffs.size() == Size(1, n0+1)) ); - _roots.create(n0, 1, ctype, -1, true, DEPTH_MASK_FLT); + _roots.create(n0, 1, ctype, -1, true, _OutputArray::DEPTH_MASK_FLT); Mat roots = _roots.getMat(); int i = -1, n = 0; @@ -2482,7 +2482,7 @@ double cv::solvePoly( InputArray _coeffs0, OutputArray _roots0, int maxIters ) int n = coeffs0.cols + coeffs0.rows - 2; - _roots0.create(n, 1, CV_MAKETYPE(cdepth, 2), -1, true, DEPTH_MASK_FLT); + _roots0.create(n, 1, CV_MAKETYPE(cdepth, 2), -1, true, _OutputArray::DEPTH_MASK_FLT); Mat roots0 = _roots0.getMat(); AutoBuffer buf(n*2+2); @@ -2550,7 +2550,9 @@ cvSolveCubic( const CvMat* coeffs, CvMat* roots ) void cvSolvePoly(const CvMat* a, CvMat *r, int maxiter, int) { - cv::Mat _a = cv::cvarrToMat(a), _r = cv::cvarrToMat(r), _r0 = r; + cv::Mat _a = cv::cvarrToMat(a); + cv::Mat _r = cv::cvarrToMat(r); + cv::Mat _r0 = _r; cv::solvePoly(_a, _r, maxiter); CV_Assert( _r.data == _r0.data ); // check that the array of roots was not reallocated } diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.cpp index 6b075a5b8e..7d832cb0fa 100644 --- a/modules/core/src/matmul.cpp +++ b/modules/core/src/matmul.cpp @@ -1725,19 +1725,29 @@ diagtransform_64f(const double* src, double* dst, const double* m, int len, int typedef void (*TransformFunc)( const uchar* src, uchar* dst, const uchar* m, int, int, int ); -static TransformFunc transformTab[] = +static TransformFunc getTransformFunc(int depth) { - (TransformFunc)transform_8u, (TransformFunc)transform_8s, (TransformFunc)transform_16u, - (TransformFunc)transform_16s, (TransformFunc)transform_32s, (TransformFunc)transform_32f, - (TransformFunc)transform_64f, 0 -}; + static TransformFunc transformTab[] = + { + (TransformFunc)transform_8u, (TransformFunc)transform_8s, (TransformFunc)transform_16u, + (TransformFunc)transform_16s, (TransformFunc)transform_32s, (TransformFunc)transform_32f, + (TransformFunc)transform_64f, 0 + }; -static TransformFunc diagTransformTab[] = + return transformTab[depth]; +} + +static TransformFunc getDiagTransformFunc(int depth) { - (TransformFunc)diagtransform_8u, (TransformFunc)diagtransform_8s, (TransformFunc)diagtransform_16u, - (TransformFunc)diagtransform_16s, (TransformFunc)diagtransform_32s, (TransformFunc)diagtransform_32f, - (TransformFunc)diagtransform_64f, 0 -}; + static TransformFunc diagTransformTab[] = + { + (TransformFunc)diagtransform_8u, (TransformFunc)diagtransform_8s, (TransformFunc)diagtransform_16u, + (TransformFunc)diagtransform_16s, (TransformFunc)diagtransform_32s, (TransformFunc)diagtransform_32f, + (TransformFunc)diagtransform_64f, 0 + }; + + return diagTransformTab[depth]; +} } @@ -1800,7 +1810,7 @@ void cv::transform( InputArray _src, OutputArray _dst, InputArray _mtx ) } } - TransformFunc func = isDiag ? diagTransformTab[depth] : transformTab[depth]; + TransformFunc func = isDiag ? getDiagTransformFunc(depth): getTransformFunc(depth); CV_Assert( func != 0 ); const Mat* arrays[] = {&src, &dst, 0}; @@ -2308,11 +2318,6 @@ double cv::Mahalanobis( InputArray _v1, InputArray _v2, InputArray _icovar ) return std::sqrt(result); } -double cv::Mahalonobis( InputArray _v1, InputArray _v2, InputArray _icovar ) -{ - return Mahalanobis(_v1, _v2, _icovar); -} - /****************************************************************************************\ * MulTransposed * \****************************************************************************************/ @@ -2766,19 +2771,24 @@ static double dotProd_64f(const double* src1, const double* src2, int len) typedef double (*DotProdFunc)(const uchar* src1, const uchar* src2, int len); -static DotProdFunc dotProdTab[] = +static DotProdFunc getDotProdFunc(int depth) { - (DotProdFunc)GET_OPTIMIZED(dotProd_8u), (DotProdFunc)GET_OPTIMIZED(dotProd_8s), - (DotProdFunc)dotProd_16u, (DotProdFunc)dotProd_16s, - (DotProdFunc)dotProd_32s, (DotProdFunc)GET_OPTIMIZED(dotProd_32f), - (DotProdFunc)dotProd_64f, 0 -}; + static DotProdFunc dotProdTab[] = + { + (DotProdFunc)GET_OPTIMIZED(dotProd_8u), (DotProdFunc)GET_OPTIMIZED(dotProd_8s), + (DotProdFunc)dotProd_16u, (DotProdFunc)dotProd_16s, + (DotProdFunc)dotProd_32s, (DotProdFunc)GET_OPTIMIZED(dotProd_32f), + (DotProdFunc)dotProd_64f, 0 + }; + + return dotProdTab[depth]; +} double Mat::dot(InputArray _mat) const { Mat mat = _mat.getMat(); int cn = channels(); - DotProdFunc func = dotProdTab[depth()]; + DotProdFunc func = getDotProdFunc(depth()); CV_Assert( mat.type() == type() && mat.size == size && func != 0 ); if( isContinuous() && mat.isContinuous() ) @@ -2857,6 +2867,7 @@ PCA& PCA::operator()(InputArray _data, InputArray __mean, int flags, int maxComp { CV_Assert( _mean.size() == mean_sz ); _mean.convertTo(mean, ctype); + covar_flags |= CV_COVAR_USE_AVG; } calcCovarMatrix( data, covar, mean, covar_flags, ctype ); @@ -2900,6 +2911,57 @@ PCA& PCA::operator()(InputArray _data, InputArray __mean, int flags, int maxComp return *this; } +void PCA::write(FileStorage& fs ) const +{ + CV_Assert( fs.isOpened() ); + + fs << "name" << "PCA"; + fs << "vectors" << eigenvectors; + fs << "values" << eigenvalues; + fs << "mean" << mean; +} + +void PCA::read(const FileNode& fs) +{ + CV_Assert( !fs.empty() ); + String name = (String)fs["name"]; + CV_Assert( name == "PCA" ); + + cv::read(fs["vectors"], eigenvectors); + cv::read(fs["values"], eigenvalues); + cv::read(fs["mean"], mean); +} + +template +int computeCumulativeEnergy(const Mat& eigenvalues, double retainedVariance) +{ + CV_DbgAssert( eigenvalues.type() == DataType::type ); + + Mat g(eigenvalues.size(), DataType::type); + + for(int ig = 0; ig < g.rows; ig++) + { + g.at(ig, 0) = 0; + for(int im = 0; im <= ig; im++) + { + g.at(ig,0) += eigenvalues.at(im,0); + } + } + + int L; + + for(L = 0; L < eigenvalues.rows; L++) + { + double energy = g.at(L, 0) / g.at(g.rows - 1, 0); + if(energy > retainedVariance) + break; + } + + L = std::max(2, L); + + return L; +} + PCA& PCA::operator()(InputArray _data, InputArray __mean, int flags, double retainedVariance) { Mat data = _data.getMat(), _mean = __mean.getMat(); @@ -2976,26 +3038,11 @@ PCA& PCA::operator()(InputArray _data, InputArray __mean, int flags, double reta } // compute the cumulative energy content for each eigenvector - Mat g(eigenvalues.size(), ctype); - - for(int ig = 0; ig < g.rows; ig++) - { - g.at(ig,0) = 0; - for(int im = 0; im <= ig; im++) - { - g.at(ig,0) += eigenvalues.at(im,0); - } - } - int L; - for(L = 0; L < eigenvalues.rows; L++) - { - double energy = g.at(L, 0) / g.at(g.rows - 1, 0); - if(energy > retainedVariance) - break; - } - - L = std::max(2, L); + if (ctype == CV_32F) + L = computeCumulativeEnergy(eigenvalues, retainedVariance); + else + L = computeCumulativeEnergy(eigenvalues, retainedVariance); // use clone() to physically copy the data and thus deallocate the original matrices eigenvalues = eigenvalues.rowRange(0,L).clone(); diff --git a/modules/core/src/matop.cpp b/modules/core/src/matop.cpp index 7d43a8f029..016435650a 100644 --- a/modules/core/src/matop.cpp +++ b/modules/core/src/matop.cpp @@ -220,6 +220,10 @@ static inline bool isInitializer(const MatExpr& e) { return e.op == &g_MatOp_Ini ///////////////////////////////////////////////////////////////////////////////////////////////////// +MatOp::MatOp() {} +MatOp::~MatOp() {} + + bool MatOp::elementWise(const MatExpr& /*expr*/) const { return false; @@ -320,7 +324,7 @@ void MatOp::augAssignXor(const MatExpr& expr, Mat& m) const { Mat temp; expr.op->assign(expr, temp); - m /= temp; + m ^= temp; } diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 8336a28683..d2032b2e5c 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -41,8 +41,6 @@ //M*/ #include "precomp.hpp" -#include "opencv2/core/gpumat.hpp" -#include "opencv2/core/opengl.hpp" /****************************************************************************************\ * [scaled] Identity matrix initialization * @@ -183,7 +181,7 @@ static void finalizeHdr(Mat& m) void Mat::create(int d, const int* _sizes, int _type) { int i; - CV_Assert(0 <= d && _sizes && d <= CV_MAX_DIM && _sizes); + CV_Assert(0 <= d && d <= CV_MAX_DIM && _sizes); _type = CV_MAT_TYPE(_type); if( data && (d == dims || (d == 1 && dims <= 2)) && _type == type() ) @@ -262,9 +260,10 @@ void Mat::deallocate() } -Mat::Mat(const Mat& m, const Range& _rowRange, const Range& _colRange) : size(&rows) +Mat::Mat(const Mat& m, const Range& _rowRange, const Range& _colRange) + : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), refcount(0), datastart(0), dataend(0), + datalimit(0), allocator(0), size(&rows) { - initEmpty(); CV_Assert( m.dims >= 2 ); if( m.dims > 2 ) { @@ -335,9 +334,10 @@ Mat::Mat(const Mat& m, const Rect& roi) } -Mat::Mat(int _dims, const int* _sizes, int _type, void* _data, const size_t* _steps) : size(&rows) +Mat::Mat(int _dims, const int* _sizes, int _type, void* _data, const size_t* _steps) + : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), refcount(0), datastart(0), dataend(0), + datalimit(0), allocator(0), size(&rows) { - initEmpty(); flags |= CV_MAT_TYPE(_type); data = datastart = (uchar*)_data; setSize(*this, _dims, _sizes, _steps, true); @@ -345,9 +345,10 @@ Mat::Mat(int _dims, const int* _sizes, int _type, void* _data, const size_t* _st } -Mat::Mat(const Mat& m, const Range* ranges) : size(&rows) +Mat::Mat(const Mat& m, const Range* ranges) + : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), refcount(0), datastart(0), dataend(0), + datalimit(0), allocator(0), size(&rows) { - initEmpty(); int i, d = m.dims; CV_Assert(ranges); @@ -371,13 +372,14 @@ Mat::Mat(const Mat& m, const Range* ranges) : size(&rows) } -Mat::Mat(const CvMatND* m, bool copyData) : size(&rows) +static Mat cvMatNDToMat(const CvMatND* m, bool copyData) { - initEmpty(); + Mat thiz; + if( !m ) - return; - data = datastart = m->data.ptr; - flags |= CV_MAT_TYPE(m->type); + return thiz; + thiz.data = thiz.datastart = m->data.ptr; + thiz.flags |= CV_MAT_TYPE(m->type); int _sizes[CV_MAX_DIM]; size_t _steps[CV_MAX_DIM]; @@ -388,16 +390,107 @@ Mat::Mat(const CvMatND* m, bool copyData) : size(&rows) _steps[i] = m->dim[i].step; } - setSize(*this, d, _sizes, _steps); - finalizeHdr(*this); + setSize(thiz, d, _sizes, _steps); + finalizeHdr(thiz); if( copyData ) { - Mat temp(*this); - temp.copyTo(*this); + Mat temp(thiz); + thiz.release(); + temp.copyTo(thiz); } + + return thiz; } +static Mat cvMatToMat(const CvMat* m, bool copyData) +{ + Mat thiz; + + if( !m ) + return thiz; + + if( !copyData ) + { + thiz.flags = Mat::MAGIC_VAL + (m->type & (CV_MAT_TYPE_MASK|CV_MAT_CONT_FLAG)); + thiz.dims = 2; + thiz.rows = m->rows; + thiz.cols = m->cols; + thiz.data = thiz.datastart = m->data.ptr; + size_t esz = CV_ELEM_SIZE(m->type), minstep = thiz.cols*esz, _step = m->step; + if( _step == 0 ) + _step = minstep; + thiz.datalimit = thiz.datastart + _step*thiz.rows; + thiz.dataend = thiz.datalimit - _step + minstep; + thiz.step[0] = _step; thiz.step[1] = esz; + } + else + { + thiz.data = thiz.datastart = thiz.dataend = 0; + Mat(m->rows, m->cols, m->type, m->data.ptr, m->step).copyTo(thiz); + } + + return thiz; +} + + +static Mat iplImageToMat(const IplImage* img, bool copyData) +{ + Mat m; + + if( !img ) + return m; + + m.dims = 2; + CV_DbgAssert(CV_IS_IMAGE(img) && img->imageData != 0); + + int imgdepth = IPL2CV_DEPTH(img->depth); + size_t esz; + m.step[0] = img->widthStep; + + if(!img->roi) + { + CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL); + m.flags = Mat::MAGIC_VAL + CV_MAKETYPE(imgdepth, img->nChannels); + m.rows = img->height; + m.cols = img->width; + m.datastart = m.data = (uchar*)img->imageData; + esz = CV_ELEM_SIZE(m.flags); + } + else + { + CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL || img->roi->coi != 0); + bool selectedPlane = img->roi->coi && img->dataOrder == IPL_DATA_ORDER_PLANE; + m.flags = Mat::MAGIC_VAL + CV_MAKETYPE(imgdepth, selectedPlane ? 1 : img->nChannels); + m.rows = img->roi->height; + m.cols = img->roi->width; + esz = CV_ELEM_SIZE(m.flags); + m.data = m.datastart = (uchar*)img->imageData + + (selectedPlane ? (img->roi->coi - 1)*m.step*img->height : 0) + + img->roi->yOffset*m.step[0] + img->roi->xOffset*esz; + } + m.datalimit = m.datastart + m.step.p[0]*m.rows; + m.dataend = m.datastart + m.step.p[0]*(m.rows-1) + esz*m.cols; + m.flags |= (m.cols*esz == m.step.p[0] || m.rows == 1 ? Mat::CONTINUOUS_FLAG : 0); + m.step[1] = esz; + + if( copyData ) + { + Mat m2 = m; + m.release(); + if( !img->roi || !img->roi->coi || + img->dataOrder == IPL_DATA_ORDER_PLANE) + m2.copyTo(m); + else + { + int ch[] = {img->roi->coi - 1, 0}; + m.create(m2.rows, m2.cols, m2.type()); + mixChannels(&m2, 1, &m, 1, ch, 1); + } + } + + return m; +} Mat Mat::diag(int d) const { @@ -433,101 +526,6 @@ Mat Mat::diag(int d) const return m; } - -Mat::Mat(const CvMat* m, bool copyData) : size(&rows) -{ - initEmpty(); - - if( !m ) - return; - - if( !copyData ) - { - flags = MAGIC_VAL + (m->type & (CV_MAT_TYPE_MASK|CV_MAT_CONT_FLAG)); - dims = 2; - rows = m->rows; - cols = m->cols; - data = datastart = m->data.ptr; - size_t esz = CV_ELEM_SIZE(m->type), minstep = cols*esz, _step = m->step; - if( _step == 0 ) - _step = minstep; - datalimit = datastart + _step*rows; - dataend = datalimit - _step + minstep; - step[0] = _step; step[1] = esz; - } - else - { - data = datastart = dataend = 0; - Mat(m->rows, m->cols, m->type, m->data.ptr, m->step).copyTo(*this); - } -} - - -Mat::Mat(const IplImage* img, bool copyData) : size(&rows) -{ - initEmpty(); - - if( !img ) - return; - - dims = 2; - CV_DbgAssert(CV_IS_IMAGE(img) && img->imageData != 0); - - int imgdepth = IPL2CV_DEPTH(img->depth); - size_t esz; - step[0] = img->widthStep; - - if(!img->roi) - { - CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL); - flags = MAGIC_VAL + CV_MAKETYPE(imgdepth, img->nChannels); - rows = img->height; cols = img->width; - datastart = data = (uchar*)img->imageData; - esz = CV_ELEM_SIZE(flags); - } - else - { - CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL || img->roi->coi != 0); - bool selectedPlane = img->roi->coi && img->dataOrder == IPL_DATA_ORDER_PLANE; - flags = MAGIC_VAL + CV_MAKETYPE(imgdepth, selectedPlane ? 1 : img->nChannels); - rows = img->roi->height; cols = img->roi->width; - esz = CV_ELEM_SIZE(flags); - data = datastart = (uchar*)img->imageData + - (selectedPlane ? (img->roi->coi - 1)*step*img->height : 0) + - img->roi->yOffset*step[0] + img->roi->xOffset*esz; - } - datalimit = datastart + step.p[0]*rows; - dataend = datastart + step.p[0]*(rows-1) + esz*cols; - flags |= (cols*esz == step.p[0] || rows == 1 ? CONTINUOUS_FLAG : 0); - step[1] = esz; - - if( copyData ) - { - Mat m = *this; - release(); - if( !img->roi || !img->roi->coi || - img->dataOrder == IPL_DATA_ORDER_PLANE) - m.copyTo(*this); - else - { - int ch[] = {img->roi->coi - 1, 0}; - create(m.rows, m.cols, m.type()); - mixChannels(&m, 1, this, 1, ch, 1); - } - } -} - - -Mat::operator IplImage() const -{ - CV_Assert( dims <= 2 ); - IplImage img; - cvInitImageHeader(&img, size(), cvIplDepth(flags), channels()); - cvSetData(&img, data, (int)step[0]); - return img; -} - - void Mat::pop_back(size_t nelems) { CV_Assert( nelems <= (size_t)size.p[0] ); @@ -673,16 +671,16 @@ Mat cvarrToMat(const CvArr* arr, bool copyData, { if( !arr ) return Mat(); - if( CV_IS_MAT(arr) ) - return Mat((const CvMat*)arr, copyData ); + if( CV_IS_MAT_HDR_Z(arr) ) + return cvMatToMat((const CvMat*)arr, copyData); if( CV_IS_MATND(arr) ) - return Mat((const CvMatND*)arr, copyData ); + return cvMatNDToMat((const CvMatND*)arr, copyData ); if( CV_IS_IMAGE(arr) ) { const IplImage* iplimg = (const IplImage*)arr; if( coiMode == 0 && iplimg->roi && iplimg->roi->coi > 0 ) CV_Error(CV_BadCOI, "COI is not supported by the function"); - return Mat(iplimg, copyData); + return iplImageToMat(iplimg, copyData); } if( CV_IS_SEQ(arr) ) { @@ -836,6 +834,18 @@ Mat Mat::reshape(int new_cn, int new_rows) const return hdr; } +Mat Mat::diag(const Mat& d) +{ + CV_Assert( d.cols == 1 || d.rows == 1 ); + int len = d.rows + d.cols - 1; + Mat m(len, len, d.type(), Scalar(0)); + Mat md = m.diag(); + if( d.cols == 1 ) + d.copyTo(md); + else + transpose(d, md); + return m; +} int Mat::checkVector(int _elemChannels, int _depth, bool _requireContinuous) const { @@ -929,14 +939,15 @@ void scalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to) \*************************************************************************************************/ _InputArray::_InputArray() : flags(0), obj(0) {} -_InputArray::~_InputArray() {} _InputArray::_InputArray(const Mat& m) : flags(MAT), obj((void*)&m) {} _InputArray::_InputArray(const std::vector& vec) : flags(STD_VECTOR_MAT), obj((void*)&vec) {} _InputArray::_InputArray(const double& val) : flags(FIXED_TYPE + FIXED_SIZE + MATX + CV_64F), obj((void*)&val), sz(Size(1,1)) {} _InputArray::_InputArray(const MatExpr& expr) : flags(FIXED_TYPE + FIXED_SIZE + EXPR), obj((void*)&expr) {} _InputArray::_InputArray(const gpu::GpuMat& d_mat) : flags(GPU_MAT), obj((void*)&d_mat) {} _InputArray::_InputArray(const ogl::Buffer& buf) : flags(OPENGL_BUFFER), obj((void*)&buf) {} -_InputArray::_InputArray(const ogl::Texture2D& tex) : flags(OPENGL_TEXTURE), obj((void*)&tex) {} +_InputArray::_InputArray(const gpu::CudaMem& cuda_mem) : flags(CUDA_MEM), obj((void*)&cuda_mem) {} + +_InputArray::~_InputArray() {} Mat _InputArray::getMat(int i) const { @@ -984,14 +995,42 @@ Mat _InputArray::getMat(int i) const return !v.empty() ? Mat(size(i), t, (void*)&v[0]) : Mat(); } - CV_Assert( k == STD_VECTOR_MAT ); - //if( k == STD_VECTOR_MAT ) + if( k == OCL_MAT ) + { + CV_Error(CV_StsNotImplemented, "This method is not implemented for oclMat yet"); + } + + if( k == STD_VECTOR_MAT ) { const std::vector& v = *(const std::vector*)obj; CV_Assert( 0 <= i && i < (int)v.size() ); return v[i]; } + + if( k == OPENGL_BUFFER ) + { + CV_Assert( i < 0 ); + CV_Error(cv::Error::StsNotImplemented, "You should explicitly call mapHost/unmapHost methods for ogl::Buffer object"); + return Mat(); + } + + if( k == GPU_MAT ) + { + CV_Assert( i < 0 ); + CV_Error(cv::Error::StsNotImplemented, "You should explicitly call download method for gpu::GpuMat object"); + return Mat(); + } + + CV_Assert( k == CUDA_MEM ); + //if( k == CUDA_MEM ) + { + CV_Assert( i < 0 ); + + const gpu::CudaMem* cuda_mem = (const gpu::CudaMem*)obj; + + return cuda_mem->createMatHeader(); + } } @@ -1066,6 +1105,11 @@ void _InputArray::getMatVector(std::vector& mv) const return; } + if( k == OCL_MAT ) + { + CV_Error(CV_StsNotImplemented, "This method is not implemented for oclMat yet"); + } + CV_Assert( k == STD_VECTOR_MAT ); //if( k == STD_VECTOR_MAT ) { @@ -1080,10 +1124,29 @@ gpu::GpuMat _InputArray::getGpuMat() const { int k = kind(); - CV_Assert(k == GPU_MAT); + if (k == GPU_MAT) + { + const gpu::GpuMat* d_mat = (const gpu::GpuMat*)obj; + return *d_mat; + } - const gpu::GpuMat* d_mat = (const gpu::GpuMat*)obj; - return *d_mat; + if (k == CUDA_MEM) + { + const gpu::CudaMem* cuda_mem = (const gpu::CudaMem*)obj; + return cuda_mem->createGpuMatHeader(); + } + + if (k == OPENGL_BUFFER) + { + CV_Error(cv::Error::StsNotImplemented, "You should explicitly call mapDevice/unmapDevice methods for ogl::Buffer object"); + return gpu::GpuMat(); + } + + if (k == NONE) + return gpu::GpuMat(); + + CV_Error(cv::Error::StsNotImplemented, "getGpuMat is available only for gpu::GpuMat and gpu::CudaMem"); + return gpu::GpuMat(); } ogl::Buffer _InputArray::getOGlBuffer() const @@ -1096,16 +1159,6 @@ ogl::Buffer _InputArray::getOGlBuffer() const return *gl_buf; } -ogl::Texture2D _InputArray::getOGlTexture2D() const -{ - int k = kind(); - - CV_Assert(k == OPENGL_TEXTURE); - - const ogl::Texture2D* gl_tex = (const ogl::Texture2D*)obj; - return *gl_tex; -} - int _InputArray::kind() const { return flags & KIND_MASK; @@ -1174,20 +1227,25 @@ Size _InputArray::size(int i) const return buf->size(); } - if( k == OPENGL_TEXTURE ) - { - CV_Assert( i < 0 ); - const ogl::Texture2D* tex = (const ogl::Texture2D*)obj; - return tex->size(); - } - - CV_Assert( k == GPU_MAT ); - //if( k == GPU_MAT ) + if( k == GPU_MAT ) { CV_Assert( i < 0 ); const gpu::GpuMat* d_mat = (const gpu::GpuMat*)obj; return d_mat->size(); } + + if( k == OCL_MAT ) + { + CV_Error(CV_StsNotImplemented, "This method is not implemented for oclMat yet"); + } + + CV_Assert( k == CUDA_MEM ); + //if( k == CUDA_MEM ) + { + CV_Assert( i < 0 ); + const gpu::CudaMem* cuda_mem = (const gpu::CudaMem*)obj; + return cuda_mem->size(); + } } size_t _InputArray::total(int i) const @@ -1240,9 +1298,12 @@ int _InputArray::type(int i) const if( k == OPENGL_BUFFER ) return ((const ogl::Buffer*)obj)->type(); - CV_Assert( k == GPU_MAT ); - //if( k == GPU_MAT ) + if( k == GPU_MAT ) return ((const gpu::GpuMat*)obj)->type(); + + CV_Assert( k == CUDA_MEM ); + //if( k == CUDA_MEM ) + return ((const gpu::CudaMem*)obj)->type(); } int _InputArray::depth(int i) const @@ -1292,29 +1353,34 @@ bool _InputArray::empty() const if( k == OPENGL_BUFFER ) return ((const ogl::Buffer*)obj)->empty(); - if( k == OPENGL_TEXTURE ) - return ((const ogl::Texture2D*)obj)->empty(); + if( k == OCL_MAT ) + { + CV_Error(CV_StsNotImplemented, "This method is not implemented for oclMat yet"); + } - CV_Assert( k == GPU_MAT ); - //if( k == GPU_MAT ) + if( k == GPU_MAT ) return ((const gpu::GpuMat*)obj)->empty(); + + CV_Assert( k == CUDA_MEM ); + //if( k == CUDA_MEM ) + return ((const gpu::CudaMem*)obj)->empty(); } _OutputArray::_OutputArray() {} -_OutputArray::~_OutputArray() {} _OutputArray::_OutputArray(Mat& m) : _InputArray(m) {} _OutputArray::_OutputArray(std::vector& vec) : _InputArray(vec) {} _OutputArray::_OutputArray(gpu::GpuMat& d_mat) : _InputArray(d_mat) {} _OutputArray::_OutputArray(ogl::Buffer& buf) : _InputArray(buf) {} -_OutputArray::_OutputArray(ogl::Texture2D& tex) : _InputArray(tex) {} +_OutputArray::_OutputArray(gpu::CudaMem& cuda_mem) : _InputArray(cuda_mem) {} _OutputArray::_OutputArray(const Mat& m) : _InputArray(m) {flags |= FIXED_SIZE|FIXED_TYPE;} _OutputArray::_OutputArray(const std::vector& vec) : _InputArray(vec) {flags |= FIXED_SIZE;} _OutputArray::_OutputArray(const gpu::GpuMat& d_mat) : _InputArray(d_mat) {flags |= FIXED_SIZE|FIXED_TYPE;} _OutputArray::_OutputArray(const ogl::Buffer& buf) : _InputArray(buf) {flags |= FIXED_SIZE|FIXED_TYPE;} -_OutputArray::_OutputArray(const ogl::Texture2D& tex) : _InputArray(tex) {flags |= FIXED_SIZE|FIXED_TYPE;} +_OutputArray::_OutputArray(const gpu::CudaMem& cuda_mem) : _InputArray(cuda_mem) {flags |= FIXED_SIZE|FIXED_TYPE;} +_OutputArray::~_OutputArray() {} bool _OutputArray::fixedSize() const { @@ -1350,6 +1416,13 @@ void _OutputArray::create(Size _sz, int mtype, int i, bool allowTransposed, int ((ogl::Buffer*)obj)->create(_sz, mtype); return; } + if( k == CUDA_MEM && i < 0 && !allowTransposed && fixedDepthMask == 0 ) + { + CV_Assert(!fixedSize() || ((gpu::CudaMem*)obj)->size() == _sz); + CV_Assert(!fixedType() || ((gpu::CudaMem*)obj)->type() == mtype); + ((gpu::CudaMem*)obj)->create(_sz, mtype); + return; + } int sizes[] = {_sz.height, _sz.width}; create(2, sizes, mtype, i, allowTransposed, fixedDepthMask); } @@ -1378,6 +1451,13 @@ void _OutputArray::create(int rows, int cols, int mtype, int i, bool allowTransp ((ogl::Buffer*)obj)->create(rows, cols, mtype); return; } + if( k == CUDA_MEM && i < 0 && !allowTransposed && fixedDepthMask == 0 ) + { + CV_Assert(!fixedSize() || ((gpu::CudaMem*)obj)->size() == Size(cols, rows)); + CV_Assert(!fixedType() || ((gpu::CudaMem*)obj)->type() == mtype); + ((gpu::CudaMem*)obj)->create(rows, cols, mtype); + return; + } int sizes[] = {rows, cols}; create(2, sizes, mtype, i, allowTransposed, fixedDepthMask); } @@ -1513,6 +1593,11 @@ void _OutputArray::create(int dims, const int* sizes, int mtype, int i, bool all return; } + if( k == OCL_MAT ) + { + CV_Error(CV_StsNotImplemented, "This method is not implemented for oclMat yet"); + } + if( k == NONE ) { CV_Error(CV_StsNullPtr, "create() called for the missing output array" ); @@ -1536,10 +1621,10 @@ void _OutputArray::create(int dims, const int* sizes, int mtype, int i, bool all int _type = CV_MAT_TYPE(flags); for( size_t j = len0; j < len; j++ ) { - if( v[i].type() == _type ) + if( v[j].type() == _type ) continue; - CV_Assert( v[i].empty() ); - v[i].flags = (v[i].flags & ~CV_MAT_TYPE_MASK) | _type; + CV_Assert( v[j].empty() ); + v[j].flags = (v[j].flags & ~CV_MAT_TYPE_MASK) | _type; } } return; @@ -1597,15 +1682,15 @@ void _OutputArray::release() const return; } - if( k == OPENGL_BUFFER ) + if( k == CUDA_MEM ) { - ((ogl::Buffer*)obj)->release(); + ((gpu::CudaMem*)obj)->release(); return; } - if( k == OPENGL_TEXTURE ) + if( k == OPENGL_BUFFER ) { - ((ogl::Texture2D*)obj)->release(); + ((ogl::Buffer*)obj)->release(); return; } @@ -1624,6 +1709,11 @@ void _OutputArray::release() const return; } + if( k == OCL_MAT ) + { + CV_Error(CV_StsNotImplemented, "This method is not implemented for oclMat yet"); + } + CV_Assert( k == STD_VECTOR_MAT ); //if( k == STD_VECTOR_MAT ) { @@ -1681,11 +1771,11 @@ ogl::Buffer& _OutputArray::getOGlBufferRef() const return *(ogl::Buffer*)obj; } -ogl::Texture2D& _OutputArray::getOGlTexture2DRef() const +gpu::CudaMem& _OutputArray::getCudaMemRef() const { int k = kind(); - CV_Assert( k == OPENGL_TEXTURE ); - return *(ogl::Texture2D*)obj; + CV_Assert( k == CUDA_MEM ); + return *(gpu::CudaMem*)obj; } static _OutputArray _none; @@ -2393,7 +2483,7 @@ template static void sort_( const Mat& src, Mat& dst, int flags ) for( j = 0; j < len; j++ ) ptr[j] = ((const T*)(src.data + src.step*j))[i]; } - std::sort( ptr, ptr + len, LessThan() ); + std::sort( ptr, ptr + len ); if( sortDescending ) for( j = 0; j < len/2; j++ ) std::swap(ptr[j], ptr[len-1-j]); @@ -2403,6 +2493,15 @@ template static void sort_( const Mat& src, Mat& dst, int flags ) } } +template class LessThanIdx +{ +public: + LessThanIdx( const _Tp* _arr ) : arr(_arr) {} + bool operator()(int a, int b) const { return arr[a] < arr[b]; } + const _Tp* arr; +}; + + template static void sortIdx_( const Mat& src, Mat& dst, int flags ) { @@ -2929,7 +3028,7 @@ CV_IMPL void cvTranspose( const CvArr* srcarr, CvArr* dstarr ) CV_IMPL void cvCompleteSymm( CvMat* matrix, int LtoR ) { - cv::Mat m(matrix); + cv::Mat m = cv::cvarrToMat(matrix); cv::completeSymm( m, LtoR != 0 ); } @@ -3100,17 +3199,6 @@ Mat Mat::reshape(int _cn, int _newndims, const int* _newsz) const return Mat(); } -Mat::operator CvMatND() const -{ - CvMatND mat; - cvInitMatNDHeader( &mat, dims, size, type(), data ); - int i, d = dims; - for( i = 0; i < d; i++ ) - mat.dim[i].step = (int)step[i]; - mat.type |= flags & CONTINUOUS_FLAG; - return mat; -} - NAryMatIterator::NAryMatIterator() : arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0) { @@ -3412,16 +3500,6 @@ void MatConstIterator::seek(const int* _idx, bool relative) seek(ofs, relative); } -ptrdiff_t operator - (const MatConstIterator& b, const MatConstIterator& a) -{ - if( a.m != b.m ) - return INT_MAX; - if( a.sliceEnd == b.sliceEnd ) - return (b.ptr - a.ptr)/b.elemSize; - - return b.lpos() - a.lpos(); -} - //////////////////////////////// SparseMat //////////////////////////////// template void @@ -3448,7 +3526,10 @@ convertScaleData_(const void* _from, void* _to, int cn, double alpha, double bet to[i] = saturate_cast(from[i]*alpha + beta); } -ConvertData getConvertElem(int fromType, int toType) +typedef void (*ConvertData)(const void* from, void* to, int cn); +typedef void (*ConvertScaleData)(const void* from, void* to, int cn, double alpha, double beta); + +static ConvertData getConvertElem(int fromType, int toType) { static ConvertData tab[][8] = {{ convertData_, convertData_, @@ -3493,7 +3574,7 @@ ConvertData getConvertElem(int fromType, int toType) return func; } -ConvertScaleData getConvertScaleElem(int fromType, int toType) +static ConvertScaleData getConvertScaleElem(int fromType, int toType) { static ConvertScaleData tab[][8] = {{ convertScaleData_, convertScaleData_, @@ -3621,24 +3702,6 @@ SparseMat::SparseMat(const Mat& m) } } -SparseMat::SparseMat(const CvSparseMat* m) -: flags(MAGIC_VAL), hdr(0) -{ - CV_Assert(m); - create( m->dims, &m->size[0], m->type ); - - CvSparseMatIterator it; - CvSparseNode* n = cvInitSparseMatIterator(m, &it); - size_t esz = elemSize(); - - for( ; n != 0; n = cvGetNextSparseNode(&it) ) - { - const int* idx = CV_NODE_IDX(m, n); - uchar* to = newNode(idx, hash(idx)); - copyElem((const uchar*)CV_NODE_VAL(m, n), to, esz); - } -} - void SparseMat::create(int d, const int* _sizes, int _type) { int i; @@ -3786,24 +3849,6 @@ void SparseMat::clear() hdr->clear(); } -SparseMat::operator CvSparseMat*() const -{ - if( !hdr ) - return 0; - CvSparseMat* m = cvCreateSparseMat(hdr->dims, hdr->size, type()); - - SparseMatConstIterator from = begin(); - size_t i, N = nzcount(), esz = elemSize(); - - for( i = 0; i < N; i++, ++from ) - { - const Node* n = from.node(); - uchar* to = cvPtrND(m, n->idx, 0, -2, 0); - copyElem(from.ptr, to, esz); - } - return m; -} - uchar* SparseMat::ptr(int i0, bool createMissing, size_t* hashval) { CV_Assert( hdr && hdr->dims == 1 ); @@ -4257,4 +4302,58 @@ Rect RotatedRect::boundingRect() const } +// glue + +CvMatND::CvMatND(const cv::Mat& m) +{ + cvInitMatNDHeader(this, m.dims, m.size, m.type(), m.data ); + int i, d = m.dims; + for( i = 0; i < d; i++ ) + dim[i].step = (int)m.step[i]; + type |= m.flags & cv::Mat::CONTINUOUS_FLAG; +} + +_IplImage::_IplImage(const cv::Mat& m) +{ + CV_Assert( m.dims <= 2 ); + cvInitImageHeader(this, m.size(), cvIplDepth(m.flags), m.channels()); + cvSetData(this, m.data, (int)m.step[0]); +} + +CvSparseMat* cvCreateSparseMat(const cv::SparseMat& sm) +{ + if( !sm.hdr ) + return 0; + + CvSparseMat* m = cvCreateSparseMat(sm.hdr->dims, sm.hdr->size, sm.type()); + + cv::SparseMatConstIterator from = sm.begin(); + size_t i, N = sm.nzcount(), esz = sm.elemSize(); + + for( i = 0; i < N; i++, ++from ) + { + const cv::SparseMat::Node* n = from.node(); + uchar* to = cvPtrND(m, n->idx, 0, -2, 0); + cv::copyElem(from.ptr, to, esz); + } + return m; +} + +void CvSparseMat::copyToSparseMat(cv::SparseMat& m) const +{ + m.create( dims, &size[0], type ); + + CvSparseMatIterator it; + CvSparseNode* n = cvInitSparseMatIterator(this, &it); + size_t esz = m.elemSize(); + + for( ; n != 0; n = cvGetNextSparseNode(&it) ) + { + const int* idx = CV_NODE_IDX(this, n); + uchar* to = m.newNode(idx, m.hash(idx)); + cv::copyElem((const uchar*)CV_NODE_VAL(this, n), to, esz); + } +} + + /* End of file. */ diff --git a/modules/core/src/matrix_operations.cpp b/modules/core/src/matrix_operations.cpp deleted file mode 100644 index 243d56e22a..0000000000 --- a/modules/core/src/matrix_operations.cpp +++ /dev/null @@ -1,298 +0,0 @@ -/*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 "precomp.hpp" -#include "opencv2/core/gpumat.hpp" - -using namespace cv; -using namespace cv::gpu; - -cv::gpu::CudaMem::CudaMem() - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), alloc_type(0) -{ -} - -cv::gpu::CudaMem::CudaMem(int _rows, int _cols, int _type, int _alloc_type) - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), alloc_type(0) -{ - if( _rows > 0 && _cols > 0 ) - create( _rows, _cols, _type, _alloc_type); -} - -cv::gpu::CudaMem::CudaMem(Size _size, int _type, int _alloc_type) - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), alloc_type(0) -{ - if( _size.height > 0 && _size.width > 0 ) - create( _size.height, _size.width, _type, _alloc_type); -} - -cv::gpu::CudaMem::CudaMem(const CudaMem& m) - : flags(m.flags), rows(m.rows), cols(m.cols), step(m.step), data(m.data), refcount(m.refcount), datastart(m.datastart), dataend(m.dataend), alloc_type(m.alloc_type) -{ - if( refcount ) - CV_XADD(refcount, 1); -} - -cv::gpu::CudaMem::CudaMem(const Mat& m, int _alloc_type) - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), alloc_type(0) -{ - if( m.rows > 0 && m.cols > 0 ) - create( m.size(), m.type(), _alloc_type); - - Mat tmp = createMatHeader(); - m.copyTo(tmp); -} - -cv::gpu::CudaMem::~CudaMem() -{ - release(); -} - -CudaMem& cv::gpu::CudaMem::operator = (const CudaMem& m) -{ - if( this != &m ) - { - if( m.refcount ) - CV_XADD(m.refcount, 1); - release(); - flags = m.flags; - rows = m.rows; cols = m.cols; - step = m.step; data = m.data; - datastart = m.datastart; - dataend = m.dataend; - refcount = m.refcount; - alloc_type = m.alloc_type; - } - return *this; -} - -CudaMem cv::gpu::CudaMem::clone() const -{ - CudaMem m(size(), type(), alloc_type); - Mat to = m; - Mat from = *this; - from.copyTo(to); - return m; -} - -void cv::gpu::CudaMem::create(Size _size, int _type, int _alloc_type) -{ - create(_size.height, _size.width, _type, _alloc_type); -} - -Mat cv::gpu::CudaMem::createMatHeader() const -{ - return Mat(size(), type(), data, step); -} - -cv::gpu::CudaMem::operator Mat() const -{ - return createMatHeader(); -} - -cv::gpu::CudaMem::operator GpuMat() const -{ - return createGpuMatHeader(); -} - -bool cv::gpu::CudaMem::isContinuous() const -{ - return (flags & Mat::CONTINUOUS_FLAG) != 0; -} - -size_t cv::gpu::CudaMem::elemSize() const -{ - return CV_ELEM_SIZE(flags); -} - -size_t cv::gpu::CudaMem::elemSize1() const -{ - return CV_ELEM_SIZE1(flags); -} - -int cv::gpu::CudaMem::type() const -{ - return CV_MAT_TYPE(flags); -} - -int cv::gpu::CudaMem::depth() const -{ - return CV_MAT_DEPTH(flags); -} - -int cv::gpu::CudaMem::channels() const -{ - return CV_MAT_CN(flags); -} - -size_t cv::gpu::CudaMem::step1() const -{ - return step/elemSize1(); -} - -Size cv::gpu::CudaMem::size() const -{ - return Size(cols, rows); -} - -bool cv::gpu::CudaMem::empty() const -{ - return data == 0; -} - -#if !defined (HAVE_CUDA) - -void cv::gpu::registerPageLocked(Mat&) { CV_Error(CV_GpuNotSupported, "The library is compiled without CUDA support"); } -void cv::gpu::unregisterPageLocked(Mat&) { CV_Error(CV_GpuNotSupported, "The library is compiled without CUDA support"); } -void cv::gpu::CudaMem::create(int /*_rows*/, int /*_cols*/, int /*_type*/, int /*type_alloc*/) -{ CV_Error(CV_GpuNotSupported, "The library is compiled without CUDA support"); } -bool cv::gpu::CudaMem::canMapHostMemory() { CV_Error(CV_GpuNotSupported, "The library is compiled without CUDA support"); return false; } -void cv::gpu::CudaMem::release() { CV_Error(CV_GpuNotSupported, "The library is compiled without CUDA support"); } -GpuMat cv::gpu::CudaMem::createGpuMatHeader () const { CV_Error(CV_GpuNotSupported, "The library is compiled without CUDA support"); return GpuMat(); } - -#else /* !defined (HAVE_CUDA) */ - -void cv::gpu::registerPageLocked(Mat& m) -{ - cudaSafeCall( cudaHostRegister(m.ptr(), m.step * m.rows, cudaHostRegisterPortable) ); -} - -void cv::gpu::unregisterPageLocked(Mat& m) -{ - cudaSafeCall( cudaHostUnregister(m.ptr()) ); -} - -bool cv::gpu::CudaMem::canMapHostMemory() -{ - cudaDeviceProp prop; - cudaSafeCall( cudaGetDeviceProperties(&prop, getDevice()) ); - return (prop.canMapHostMemory != 0) ? true : false; -} - -namespace -{ - size_t alignUpStep(size_t what, size_t alignment) - { - size_t alignMask = alignment-1; - size_t inverseAlignMask = ~alignMask; - size_t res = (what + alignMask) & inverseAlignMask; - return res; - } -} - -void cv::gpu::CudaMem::create(int _rows, int _cols, int _type, int _alloc_type) -{ - if (_alloc_type == ALLOC_ZEROCOPY && !canMapHostMemory()) - cv::gpu::error("ZeroCopy is not supported by current device", __FILE__, __LINE__); - - _type &= TYPE_MASK; - if( rows == _rows && cols == _cols && type() == _type && data ) - return; - if( data ) - release(); - CV_DbgAssert( _rows >= 0 && _cols >= 0 ); - if( _rows > 0 && _cols > 0 ) - { - flags = Mat::MAGIC_VAL + Mat::CONTINUOUS_FLAG + _type; - rows = _rows; - cols = _cols; - step = elemSize()*cols; - if (_alloc_type == ALLOC_ZEROCOPY) - { - cudaDeviceProp prop; - cudaSafeCall( cudaGetDeviceProperties(&prop, getDevice()) ); - step = alignUpStep(step, prop.textureAlignment); - } - int64 _nettosize = (int64)step*rows; - size_t nettosize = (size_t)_nettosize; - if( _nettosize != (int64)nettosize ) - CV_Error(CV_StsNoMem, "Too big buffer is allocated"); - size_t datasize = alignSize(nettosize, (int)sizeof(*refcount)); - - //datastart = data = (uchar*)fastMalloc(datasize + sizeof(*refcount)); - alloc_type = _alloc_type; - void *ptr = 0; - - switch (alloc_type) - { - case ALLOC_PAGE_LOCKED: cudaSafeCall( cudaHostAlloc( &ptr, datasize, cudaHostAllocDefault) ); break; - case ALLOC_ZEROCOPY: cudaSafeCall( cudaHostAlloc( &ptr, datasize, cudaHostAllocMapped) ); break; - case ALLOC_WRITE_COMBINED: cudaSafeCall( cudaHostAlloc( &ptr, datasize, cudaHostAllocWriteCombined) ); break; - default: cv::gpu::error("Invalid alloc type", __FILE__, __LINE__); - } - - datastart = data = (uchar*)ptr; - dataend = data + nettosize; - - refcount = (int*)cv::fastMalloc(sizeof(*refcount)); - *refcount = 1; - } -} - -GpuMat cv::gpu::CudaMem::createGpuMatHeader () const -{ - GpuMat res; - if (alloc_type == ALLOC_ZEROCOPY) - { - void *pdev; - cudaSafeCall( cudaHostGetDevicePointer( &pdev, data, 0 ) ); - res = GpuMat(rows, cols, type(), pdev, step); - } - else - cv::gpu::error("Zero-copy is not supported or memory was allocated without zero-copy flag", __FILE__, __LINE__); - - return res; -} - -void cv::gpu::CudaMem::release() -{ - if( refcount && CV_XADD(refcount, -1) == 1 ) - { - cudaSafeCall( cudaFreeHost(datastart ) ); - fastFree(refcount); - } - data = datastart = dataend = 0; - step = rows = cols = 0; - refcount = 0; -} - -#endif /* !defined (HAVE_CUDA) */ diff --git a/modules/core/src/opengl_interop.cpp b/modules/core/src/opengl.cpp similarity index 83% rename from modules/core/src/opengl_interop.cpp rename to modules/core/src/opengl.cpp index fb4c53f629..36a437a2d6 100644 --- a/modules/core/src/opengl_interop.cpp +++ b/modules/core/src/opengl.cpp @@ -41,16 +41,12 @@ //M*/ #include "precomp.hpp" -#include "opencv2/core/opengl.hpp" -#include "opencv2/core/gpumat.hpp" #ifdef HAVE_OPENGL - #include "gl_core_3_1.hpp" - - #ifdef HAVE_CUDA - #include - #include - #endif +# include "gl_core_3_1.hpp" +# ifdef HAVE_CUDA +# include +# endif #endif using namespace cv; @@ -59,62 +55,62 @@ using namespace cv::gpu; namespace { #ifndef HAVE_OPENGL - void throw_nogl() { CV_Error(CV_OpenGlNotSupported, "The library is compiled without OpenGL support"); } + inline void throw_no_ogl() { CV_Error(cv::Error::OpenGlNotSupported, "The library is compiled without OpenGL support"); } #else - void throw_nogl() { CV_Error(CV_OpenGlApiCallError, "OpenGL context doesn't exist"); } - - #ifndef HAVE_CUDA - void throw_nocuda() { CV_Error(CV_GpuNotSupported, "The library is compiled without GPU support"); } - #else - void throw_nocuda() { CV_Error(CV_StsNotImplemented, "The called functionality is disabled for current build or platform"); } - #endif + inline void throw_no_ogl() { CV_Error(cv::Error::OpenGlApiCallError, "OpenGL context doesn't exist"); } #endif -} -bool cv::ogl::checkError(const char* file, const int line, const char* func) -{ -#ifndef HAVE_OPENGL - (void) file; - (void) line; - (void) func; - return true; -#else - GLenum err = gl::GetError(); - - if (err != gl::NO_ERROR_) + bool checkError(const char* file, const int line, const char* func = 0) { - const char* msg; + #ifndef HAVE_OPENGL + (void) file; + (void) line; + (void) func; + return true; + #else + GLenum err = gl::GetError(); - switch (err) + if (err != gl::NO_ERROR_) { - case gl::INVALID_ENUM: - msg = "An unacceptable value is specified for an enumerated argument"; - break; + const char* msg; - case gl::INVALID_VALUE: - msg = "A numeric argument is out of range"; - break; + switch (err) + { + case gl::INVALID_ENUM: + msg = "An unacceptable value is specified for an enumerated argument"; + break; - case gl::INVALID_OPERATION: - msg = "The specified operation is not allowed in the current state"; - break; + case gl::INVALID_VALUE: + msg = "A numeric argument is out of range"; + break; - case gl::OUT_OF_MEMORY: - msg = "There is not enough memory left to execute the command"; - break; + case gl::INVALID_OPERATION: + msg = "The specified operation is not allowed in the current state"; + break; - default: - msg = "Unknown error"; - }; + case gl::OUT_OF_MEMORY: + msg = "There is not enough memory left to execute the command"; + break; - cvError(CV_OpenGlApiCallError, func, msg, file, line); + default: + msg = "Unknown error"; + }; - return false; + cvError(CV_OpenGlApiCallError, func, msg, file, line); + + return false; + } + + return true; + #endif } - return true; -#endif -} + #if defined(__GNUC__) + #define CV_CheckGlError() CV_DbgAssert( (checkError(__FILE__, __LINE__, __func__)) ) + #else + #define CV_CheckGlError() CV_DbgAssert( (checkError(__FILE__, __LINE__)) ) + #endif +} // namespace #ifdef HAVE_OPENGL namespace @@ -130,11 +126,11 @@ void cv::gpu::setGlDevice(int device) { #ifndef HAVE_OPENGL (void) device; - throw_nogl(); + throw_no_ogl(); #else - #if !defined(HAVE_CUDA) || defined(CUDA_DISABLER) + #ifndef HAVE_CUDA (void) device; - throw_nocuda(); + throw_no_cuda(); #else cudaSafeCall( cudaGLSetGLDevice(device) ); #endif @@ -144,7 +140,7 @@ void cv::gpu::setGlDevice(int device) //////////////////////////////////////////////////////////////////////// // CudaResource -#if defined(HAVE_OPENGL) && defined(HAVE_CUDA) && !defined(CUDA_DISABLER) +#if defined(HAVE_OPENGL) && defined(HAVE_CUDA) namespace { @@ -356,12 +352,13 @@ const Ptr& cv::ogl::Buffer::Impl::empty() return p; } -cv::ogl::Buffer::Impl::Impl() : bufId_(0), autoRelease_(true) +cv::ogl::Buffer::Impl::Impl() : bufId_(0), autoRelease_(false) { } cv::ogl::Buffer::Impl::Impl(GLuint abufId, bool autoRelease) : bufId_(abufId), autoRelease_(autoRelease) { + CV_Assert( gl::IsBuffer(abufId) == gl::TRUE_ ); } cv::ogl::Buffer::Impl::Impl(GLsizeiptr size, const GLvoid* data, GLenum target, bool autoRelease) : bufId_(0), autoRelease_(autoRelease) @@ -440,36 +437,38 @@ void cv::ogl::Buffer::Impl::unmapHost() } #ifdef HAVE_CUDA - void cv::ogl::Buffer::Impl::copyFrom(const void* src, size_t spitch, size_t width, size_t height, cudaStream_t stream) - { - cudaResource_.registerBuffer(bufId_); - cudaResource_.copyFrom(src, spitch, width, height, stream); - } - void cv::ogl::Buffer::Impl::copyTo(void* dst, size_t dpitch, size_t width, size_t height, cudaStream_t stream) const - { - cudaResource_.registerBuffer(bufId_); - cudaResource_.copyTo(dst, dpitch, width, height, stream); - } +void cv::ogl::Buffer::Impl::copyFrom(const void* src, size_t spitch, size_t width, size_t height, cudaStream_t stream) +{ + cudaResource_.registerBuffer(bufId_); + cudaResource_.copyFrom(src, spitch, width, height, stream); +} - void* cv::ogl::Buffer::Impl::mapDevice(cudaStream_t stream) - { - cudaResource_.registerBuffer(bufId_); - return cudaResource_.map(stream); - } +void cv::ogl::Buffer::Impl::copyTo(void* dst, size_t dpitch, size_t width, size_t height, cudaStream_t stream) const +{ + cudaResource_.registerBuffer(bufId_); + cudaResource_.copyTo(dst, dpitch, width, height, stream); +} - void cv::ogl::Buffer::Impl::unmapDevice(cudaStream_t stream) - { - cudaResource_.unmap(stream); - } -#endif +void* cv::ogl::Buffer::Impl::mapDevice(cudaStream_t stream) +{ + cudaResource_.registerBuffer(bufId_); + return cudaResource_.map(stream); +} + +void cv::ogl::Buffer::Impl::unmapDevice(cudaStream_t stream) +{ + cudaResource_.unmap(stream); +} + +#endif // HAVE_CUDA #endif // HAVE_OPENGL cv::ogl::Buffer::Buffer() : rows_(0), cols_(0), type_(0) { #ifndef HAVE_OPENGL - throw_nogl(); + throw_no_ogl(); #else impl_ = Impl::empty(); #endif @@ -483,9 +482,9 @@ cv::ogl::Buffer::Buffer(int arows, int acols, int atype, unsigned int abufId, bo (void) atype; (void) abufId; (void) autoRelease; - throw_nogl(); + throw_no_ogl(); #else - impl_ = new Impl(abufId, autoRelease); + impl_.reset(new Impl(abufId, autoRelease)); rows_ = arows; cols_ = acols; type_ = atype; @@ -499,61 +498,38 @@ cv::ogl::Buffer::Buffer(Size asize, int atype, unsigned int abufId, bool autoRel (void) atype; (void) abufId; (void) autoRelease; - throw_nogl(); + throw_no_ogl(); #else - impl_ = new Impl(abufId, autoRelease); + impl_.reset(new Impl(abufId, autoRelease)); rows_ = asize.height; cols_ = asize.width; type_ = atype; #endif } -cv::ogl::Buffer::Buffer(int arows, int acols, int atype, Target target, bool autoRelease) : rows_(0), cols_(0), type_(0) -{ - create(arows, acols, atype, target, autoRelease); -} - -cv::ogl::Buffer::Buffer(Size asize, int atype, Target target, bool autoRelease) : rows_(0), cols_(0), type_(0) -{ - create(asize, atype, target, autoRelease); -} - cv::ogl::Buffer::Buffer(InputArray arr, Target target, bool autoRelease) : rows_(0), cols_(0), type_(0) { #ifndef HAVE_OPENGL (void) arr; (void) target; (void) autoRelease; - throw_nogl(); + throw_no_ogl(); #else const int kind = arr.kind(); switch (kind) { case _InputArray::OPENGL_BUFFER: - { - copyFrom(arr, target, autoRelease); - break; - } - - case _InputArray::OPENGL_TEXTURE: - { - copyFrom(arr, target, autoRelease); - break; - } - case _InputArray::GPU_MAT: - { - copyFrom(arr, target, autoRelease); - break; - } + copyFrom(arr, target, autoRelease); + break; default: { Mat mat = arr.getMat(); CV_Assert( mat.isContinuous() ); const GLsizeiptr asize = mat.rows * mat.cols * mat.elemSize(); - impl_ = new Impl(asize, mat.data, target, autoRelease); + impl_.reset(new Impl(asize, mat.data, target, autoRelease)); rows_ = mat.rows; cols_ = mat.cols; type_ = mat.type(); @@ -571,12 +547,12 @@ void cv::ogl::Buffer::create(int arows, int acols, int atype, Target target, boo (void) atype; (void) target; (void) autoRelease; - throw_nogl(); + throw_no_ogl(); #else if (rows_ != arows || cols_ != acols || type_ != atype) { const GLsizeiptr asize = arows * acols * CV_ELEM_SIZE(atype); - impl_ = new Impl(asize, 0, target, autoRelease); + impl_.reset(new Impl(asize, 0, target, autoRelease)); rows_ = arows; cols_ = acols; type_ = atype; @@ -587,7 +563,7 @@ void cv::ogl::Buffer::create(int arows, int acols, int atype, Target target, boo void cv::ogl::Buffer::release() { #ifdef HAVE_OPENGL - if (*impl_.refcount == 1) + if (impl_) impl_->setAutoRelease(true); impl_ = Impl::empty(); rows_ = 0; @@ -600,7 +576,7 @@ void cv::ogl::Buffer::setAutoRelease(bool flag) { #ifndef HAVE_OPENGL (void) flag; - throw_nogl(); + throw_no_ogl(); #else impl_->setAutoRelease(flag); #endif @@ -612,18 +588,10 @@ void cv::ogl::Buffer::copyFrom(InputArray arr, Target target, bool autoRelease) (void) arr; (void) target; (void) autoRelease; - throw_nogl(); + throw_no_ogl(); #else const int kind = arr.kind(); - if (kind == _InputArray::OPENGL_TEXTURE) - { - ogl::Texture2D tex = arr.getOGlTexture2D(); - tex.copyTo(*this); - setAutoRelease(autoRelease); - return; - } - const Size asize = arr.size(); const int atype = arr.type(); create(asize, atype, target, autoRelease); @@ -639,8 +607,8 @@ void cv::ogl::Buffer::copyFrom(InputArray arr, Target target, bool autoRelease) case _InputArray::GPU_MAT: { - #if !defined HAVE_CUDA || defined(CUDA_DISABLER) - throw_nocuda(); + #ifndef HAVE_CUDA + throw_no_cuda(); #else GpuMat dmat = arr.getGpuMat(); impl_->copyFrom(dmat.data, dmat.step, dmat.cols * dmat.elemSize(), dmat.rows); @@ -659,13 +627,36 @@ void cv::ogl::Buffer::copyFrom(InputArray arr, Target target, bool autoRelease) #endif } -void cv::ogl::Buffer::copyTo(OutputArray arr, Target target, bool autoRelease) const +void cv::ogl::Buffer::copyFrom(InputArray arr, gpu::Stream& stream, Target target, bool autoRelease) { #ifndef HAVE_OPENGL (void) arr; + (void) stream; (void) target; (void) autoRelease; - throw_nogl(); + throw_no_ogl(); +#else + #ifndef HAVE_CUDA + (void) arr; + (void) stream; + (void) target; + (void) autoRelease; + throw_no_cuda(); + #else + GpuMat dmat = arr.getGpuMat(); + + create(dmat.size(), dmat.type(), target, autoRelease); + + impl_->copyFrom(dmat.data, dmat.step, dmat.cols * dmat.elemSize(), dmat.rows, gpu::StreamAccessor::getStream(stream)); + #endif +#endif +} + +void cv::ogl::Buffer::copyTo(OutputArray arr) const +{ +#ifndef HAVE_OPENGL + (void) arr; + throw_no_ogl(); #else const int kind = arr.kind(); @@ -673,20 +664,14 @@ void cv::ogl::Buffer::copyTo(OutputArray arr, Target target, bool autoRelease) c { case _InputArray::OPENGL_BUFFER: { - arr.getOGlBufferRef().copyFrom(*this, target, autoRelease); - break; - } - - case _InputArray::OPENGL_TEXTURE: - { - arr.getOGlTexture2DRef().copyFrom(*this, autoRelease); + arr.getOGlBufferRef().copyFrom(*this); break; } case _InputArray::GPU_MAT: { - #if !defined HAVE_CUDA || defined(CUDA_DISABLER) - throw_nocuda(); + #ifndef HAVE_CUDA + throw_no_cuda(); #else GpuMat& dmat = arr.getGpuMatRef(); dmat.create(rows_, cols_, type_); @@ -707,12 +692,31 @@ void cv::ogl::Buffer::copyTo(OutputArray arr, Target target, bool autoRelease) c #endif } +void cv::ogl::Buffer::copyTo(OutputArray arr, gpu::Stream& stream) const +{ +#ifndef HAVE_OPENGL + (void) arr; + (void) stream; + throw_no_ogl(); +#else + #ifndef HAVE_CUDA + (void) arr; + (void) stream; + throw_no_cuda(); + #else + arr.create(rows_, cols_, type_); + GpuMat dmat = arr.getGpuMat(); + impl_->copyTo(dmat.data, dmat.step, dmat.cols * dmat.elemSize(), dmat.rows, gpu::StreamAccessor::getStream(stream)); + #endif +#endif +} + cv::ogl::Buffer cv::ogl::Buffer::clone(Target target, bool autoRelease) const { #ifndef HAVE_OPENGL (void) target; (void) autoRelease; - throw_nogl(); + throw_no_ogl(); return cv::ogl::Buffer(); #else ogl::Buffer buf; @@ -725,7 +729,7 @@ void cv::ogl::Buffer::bind(Target target) const { #ifndef HAVE_OPENGL (void) target; - throw_nogl(); + throw_no_ogl(); #else impl_->bind(target); #endif @@ -735,7 +739,7 @@ void cv::ogl::Buffer::unbind(Target target) { #ifndef HAVE_OPENGL (void) target; - throw_nogl(); + throw_no_ogl(); #else gl::BindBuffer(target, 0); CV_CheckGlError(); @@ -746,7 +750,7 @@ Mat cv::ogl::Buffer::mapHost(Access access) { #ifndef HAVE_OPENGL (void) access; - throw_nogl(); + throw_no_ogl(); return Mat(); #else return Mat(rows_, cols_, type_, impl_->mapHost(access)); @@ -756,7 +760,7 @@ Mat cv::ogl::Buffer::mapHost(Access access) void cv::ogl::Buffer::unmapHost() { #ifndef HAVE_OPENGL - throw_nogl(); + throw_no_ogl(); #else return impl_->unmapHost(); #endif @@ -765,11 +769,11 @@ void cv::ogl::Buffer::unmapHost() GpuMat cv::ogl::Buffer::mapDevice() { #ifndef HAVE_OPENGL - throw_nogl(); + throw_no_ogl(); return GpuMat(); #else - #if !defined HAVE_CUDA || defined(CUDA_DISABLER) - throw_nocuda(); + #ifndef HAVE_CUDA + throw_no_cuda(); return GpuMat(); #else return GpuMat(rows_, cols_, type_, impl_->mapDevice()); @@ -780,30 +784,58 @@ GpuMat cv::ogl::Buffer::mapDevice() void cv::ogl::Buffer::unmapDevice() { #ifndef HAVE_OPENGL - throw_nogl(); + throw_no_ogl(); #else - #if !defined HAVE_CUDA || defined(CUDA_DISABLER) - throw_nocuda(); + #ifndef HAVE_CUDA + throw_no_cuda(); #else impl_->unmapDevice(); #endif #endif } +gpu::GpuMat cv::ogl::Buffer::mapDevice(gpu::Stream& stream) +{ +#ifndef HAVE_OPENGL + (void) stream; + throw_no_ogl(); + return GpuMat(); +#else + #ifndef HAVE_CUDA + (void) stream; + throw_no_cuda(); + return GpuMat(); + #else + return GpuMat(rows_, cols_, type_, impl_->mapDevice(gpu::StreamAccessor::getStream(stream))); + #endif +#endif +} + +void cv::ogl::Buffer::unmapDevice(gpu::Stream& stream) +{ +#ifndef HAVE_OPENGL + (void) stream; + throw_no_ogl(); +#else + #ifndef HAVE_CUDA + (void) stream; + throw_no_cuda(); + #else + impl_->unmapDevice(gpu::StreamAccessor::getStream(stream)); + #endif +#endif +} + unsigned int cv::ogl::Buffer::bufId() const { #ifndef HAVE_OPENGL - throw_nogl(); + throw_no_ogl(); return 0; #else return impl_->bufId(); #endif } -template <> void cv::Ptr::delete_obj() -{ - if (obj) delete obj; -} ////////////////////////////////////////////////////////////////////////////////////////// // ogl::Texture @@ -847,12 +879,13 @@ const Ptr cv::ogl::Texture2D::Impl::empty() return p; } -cv::ogl::Texture2D::Impl::Impl() : texId_(0), autoRelease_(true) +cv::ogl::Texture2D::Impl::Impl() : texId_(0), autoRelease_(false) { } cv::ogl::Texture2D::Impl::Impl(GLuint atexId, bool autoRelease) : texId_(atexId), autoRelease_(autoRelease) { + CV_Assert( gl::IsTexture(atexId) == gl::TRUE_ ); } cv::ogl::Texture2D::Impl::Impl(GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels, bool autoRelease) : texId_(0), autoRelease_(autoRelease) @@ -919,7 +952,7 @@ void cv::ogl::Texture2D::Impl::bind() const cv::ogl::Texture2D::Texture2D() : rows_(0), cols_(0), format_(NONE) { #ifndef HAVE_OPENGL - throw_nogl(); + throw_no_ogl(); #else impl_ = Impl::empty(); #endif @@ -933,9 +966,9 @@ cv::ogl::Texture2D::Texture2D(int arows, int acols, Format aformat, unsigned int (void) aformat; (void) atexId; (void) autoRelease; - throw_nogl(); + throw_no_ogl(); #else - impl_ = new Impl(atexId, autoRelease); + impl_.reset(new Impl(atexId, autoRelease)); rows_ = arows; cols_ = acols; format_ = aformat; @@ -949,31 +982,21 @@ cv::ogl::Texture2D::Texture2D(Size asize, Format aformat, unsigned int atexId, b (void) aformat; (void) atexId; (void) autoRelease; - throw_nogl(); + throw_no_ogl(); #else - impl_ = new Impl(atexId, autoRelease); + impl_.reset(new Impl(atexId, autoRelease)); rows_ = asize.height; cols_ = asize.width; format_ = aformat; #endif } -cv::ogl::Texture2D::Texture2D(int arows, int acols, Format aformat, bool autoRelease) : rows_(0), cols_(0), format_(NONE) -{ - create(arows, acols, aformat, autoRelease); -} - -cv::ogl::Texture2D::Texture2D(Size asize, Format aformat, bool autoRelease) : rows_(0), cols_(0), format_(NONE) -{ - create(asize, aformat, autoRelease); -} - cv::ogl::Texture2D::Texture2D(InputArray arr, bool autoRelease) : rows_(0), cols_(0), format_(NONE) { #ifndef HAVE_OPENGL (void) arr; (void) autoRelease; - throw_nogl(); + throw_no_ogl(); #else const int kind = arr.kind(); @@ -1001,20 +1024,20 @@ cv::ogl::Texture2D::Texture2D(InputArray arr, bool autoRelease) : rows_(0), cols { ogl::Buffer buf = arr.getOGlBuffer(); buf.bind(ogl::Buffer::PIXEL_UNPACK_BUFFER); - impl_ = new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], 0, autoRelease); + impl_.reset(new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], 0, autoRelease)); ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER); break; } case _InputArray::GPU_MAT: { - #if !defined HAVE_CUDA || defined(CUDA_DISABLER) - throw_nocuda(); + #ifndef HAVE_CUDA + throw_no_cuda(); #else GpuMat dmat = arr.getGpuMat(); ogl::Buffer buf(dmat, ogl::Buffer::PIXEL_UNPACK_BUFFER); buf.bind(ogl::Buffer::PIXEL_UNPACK_BUFFER); - impl_ = new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], 0, autoRelease); + impl_.reset(new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], 0, autoRelease)); ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER); #endif @@ -1026,7 +1049,7 @@ cv::ogl::Texture2D::Texture2D(InputArray arr, bool autoRelease) : rows_(0), cols Mat mat = arr.getMat(); CV_Assert( mat.isContinuous() ); ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER); - impl_ = new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], mat.data, autoRelease); + impl_.reset(new Impl(internalFormats[cn], asize.width, asize.height, srcFormats[cn], gl_types[depth], mat.data, autoRelease)); break; } } @@ -1044,12 +1067,12 @@ void cv::ogl::Texture2D::create(int arows, int acols, Format aformat, bool autoR (void) acols; (void) aformat; (void) autoRelease; - throw_nogl(); + throw_no_ogl(); #else if (rows_ != arows || cols_ != acols || format_ != aformat) { ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER); - impl_ = new Impl(aformat, acols, arows, aformat, gl::FLOAT, 0, autoRelease); + impl_.reset(new Impl(aformat, acols, arows, aformat, gl::FLOAT, 0, autoRelease)); rows_ = arows; cols_ = acols; format_ = aformat; @@ -1060,7 +1083,7 @@ void cv::ogl::Texture2D::create(int arows, int acols, Format aformat, bool autoR void cv::ogl::Texture2D::release() { #ifdef HAVE_OPENGL - if (*impl_.refcount == 1) + if (impl_) impl_->setAutoRelease(true); impl_ = Impl::empty(); rows_ = 0; @@ -1073,7 +1096,7 @@ void cv::ogl::Texture2D::setAutoRelease(bool flag) { #ifndef HAVE_OPENGL (void) flag; - throw_nogl(); + throw_no_ogl(); #else impl_->setAutoRelease(flag); #endif @@ -1084,7 +1107,7 @@ void cv::ogl::Texture2D::copyFrom(InputArray arr, bool autoRelease) #ifndef HAVE_OPENGL (void) arr; (void) autoRelease; - throw_nogl(); + throw_no_ogl(); #else const int kind = arr.kind(); @@ -1121,8 +1144,8 @@ void cv::ogl::Texture2D::copyFrom(InputArray arr, bool autoRelease) case _InputArray::GPU_MAT: { - #if !defined HAVE_CUDA || defined(CUDA_DISABLER) - throw_nocuda(); + #ifndef HAVE_CUDA + throw_no_cuda(); #else GpuMat dmat = arr.getGpuMat(); ogl::Buffer buf(dmat, ogl::Buffer::PIXEL_UNPACK_BUFFER); @@ -1151,7 +1174,7 @@ void cv::ogl::Texture2D::copyTo(OutputArray arr, int ddepth, bool autoRelease) c (void) arr; (void) ddepth; (void) autoRelease; - throw_nogl(); + throw_no_ogl(); #else const int kind = arr.kind(); @@ -1172,8 +1195,8 @@ void cv::ogl::Texture2D::copyTo(OutputArray arr, int ddepth, bool autoRelease) c case _InputArray::GPU_MAT: { - #if !defined HAVE_CUDA || defined(CUDA_DISABLER) - throw_nocuda(); + #ifndef HAVE_CUDA + throw_no_cuda(); #else ogl::Buffer buf(rows_, cols_, CV_MAKE_TYPE(ddepth, cn), ogl::Buffer::PIXEL_PACK_BUFFER); buf.bind(ogl::Buffer::PIXEL_PACK_BUFFER); @@ -1200,7 +1223,7 @@ void cv::ogl::Texture2D::copyTo(OutputArray arr, int ddepth, bool autoRelease) c void cv::ogl::Texture2D::bind() const { #ifndef HAVE_OPENGL - throw_nogl(); + throw_no_ogl(); #else impl_->bind(); #endif @@ -1209,25 +1232,17 @@ void cv::ogl::Texture2D::bind() const unsigned int cv::ogl::Texture2D::texId() const { #ifndef HAVE_OPENGL - throw_nogl(); + throw_no_ogl(); return 0; #else return impl_->texId(); #endif } -template <> void cv::Ptr::delete_obj() -{ - if (obj) delete obj; -} //////////////////////////////////////////////////////////////////////// // ogl::Arrays -cv::ogl::Arrays::Arrays() : size_(0) -{ -} - void cv::ogl::Arrays::setVertexArray(InputArray vertex) { const int cn = vertex.channels(); @@ -1324,7 +1339,7 @@ void cv::ogl::Arrays::setAutoRelease(bool flag) void cv::ogl::Arrays::bind() const { #ifndef HAVE_OPENGL - throw_nogl(); + throw_no_ogl(); #else CV_Assert( texCoord_.empty() || texCoord_.size().area() == size_ ); CV_Assert( normal_.empty() || normal_.size().area() == size_ ); @@ -1409,7 +1424,7 @@ void cv::ogl::render(const ogl::Texture2D& tex, Rect_ wndRect, Rect_ + +namespace +{ + class FormattedImpl : public cv::Formatted + { + enum { STATE_PROLOGUE, STATE_EPILOGUE, STATE_ROW_OPEN, STATE_ROW_CLOSE, STATE_CN_OPEN, STATE_CN_CLOSE, STATE_VALUE, STATE_FINISHED, + STATE_LINE_SEPARATOR, STATE_CN_SEPARATOR, STATE_VALUE_SEPARATOR }; + enum {BRACE_ROW_OPEN = 0, BRACE_ROW_CLOSE = 1, BRACE_ROW_SEP=2, BRACE_CN_OPEN=3, BRACE_CN_CLOSE=4 }; + + char floatFormat[8]; + char buf[32]; // enough for double with precision up to 20 + + cv::Mat mtx; + int mcn; // == mtx.channels() + bool singleLine; + + int state; + int row; + int col; + int cn; + + cv::String prologue; + cv::String epilogue; + char braces[5]; + + void (FormattedImpl::*valueToStr)(); + void valueToStr8u() { sprintf(buf, "%3d", (int)mtx.ptr(row, col)[cn]); } + void valueToStr8s() { sprintf(buf, "%3d", (int)mtx.ptr(row, col)[cn]); } + void valueToStr16u() { sprintf(buf, "%d", (int)mtx.ptr(row, col)[cn]); } + void valueToStr16s() { sprintf(buf, "%d", (int)mtx.ptr(row, col)[cn]); } + void valueToStr32s() { sprintf(buf, "%d", mtx.ptr(row, col)[cn]); } + void valueToStr32f() { sprintf(buf, floatFormat, mtx.ptr(row, col)[cn]); } + void valueToStr64f() { sprintf(buf, floatFormat, mtx.ptr(row, col)[cn]); } + void valueToStrOther() { buf[0] = 0; } + + public: + + FormattedImpl(cv::String pl, cv::String el, cv::Mat m, char br[5], bool sLine, int precision) + { + prologue = pl; + epilogue = el; + mtx = m; + mcn = m.channels(); + memcpy(braces, br, 5); + state = STATE_PROLOGUE; + singleLine = sLine; + + if (precision < 0) + { + floatFormat[0] = '%'; + floatFormat[1] = 'a'; + floatFormat[2] = 0; + } + else + { + sprintf(floatFormat, "%%.%dg", std::min(precision, 20)); + } + + switch(mtx.depth()) + { + case CV_8U: valueToStr = &FormattedImpl::valueToStr8u; break; + case CV_8S: valueToStr = &FormattedImpl::valueToStr8s; break; + case CV_16U: valueToStr = &FormattedImpl::valueToStr16u; break; + case CV_16S: valueToStr = &FormattedImpl::valueToStr16s; break; + case CV_32S: valueToStr = &FormattedImpl::valueToStr32s; break; + case CV_32F: valueToStr = &FormattedImpl::valueToStr32f; break; + case CV_64F: valueToStr = &FormattedImpl::valueToStr64f; break; + default: valueToStr = &FormattedImpl::valueToStrOther; break; + } + } + + void reset() + { + state = STATE_PROLOGUE; + } + + const char* next() + { + switch(state) + { + case STATE_PROLOGUE: + row = 0; + if (mtx.empty()) + state = STATE_EPILOGUE; + else + state = STATE_ROW_OPEN; + return prologue.c_str(); + case STATE_EPILOGUE: + state = STATE_FINISHED; + return epilogue.c_str(); + case STATE_ROW_OPEN: + col = 0; + state = STATE_CN_OPEN; + { + size_t pos = 0; + if (row > 0) + while(pos < prologue.size() && pos < sizeof(buf) - 2) + buf[pos++] = ' '; + if (braces[BRACE_ROW_OPEN]) + buf[pos++] = braces[BRACE_ROW_OPEN]; + if(!pos) + return next(); + buf[pos] = 0; + } + return buf; + case STATE_ROW_CLOSE: + state = STATE_LINE_SEPARATOR; + ++row; + if (braces[BRACE_ROW_CLOSE]) + { + buf[0] = braces[BRACE_ROW_CLOSE]; + buf[1] = row < mtx.rows ? ',' : '\0'; + buf[2] = 0; + return buf; + } + else if(braces[BRACE_ROW_SEP] && row < mtx.rows) + { + buf[0] = braces[BRACE_ROW_SEP]; + buf[1] = 0; + return buf; + } + return next(); + case STATE_CN_OPEN: + cn = 0; + state = STATE_VALUE; + if (mcn > 1 && braces[BRACE_CN_OPEN]) + { + buf[0] = braces[BRACE_CN_OPEN]; + buf[1] = 0; + return buf; + } + return next(); + case STATE_CN_CLOSE: + ++col; + if (col >= mtx.cols) + state = STATE_ROW_CLOSE; + else + state = STATE_CN_SEPARATOR; + if (mcn > 1 && braces[BRACE_CN_CLOSE]) + { + buf[0] = braces[BRACE_CN_CLOSE]; + buf[1] = 0; + return buf; + } + return next(); + case STATE_VALUE: + (this->*valueToStr)(); + if (++cn >= mcn) + state = STATE_CN_CLOSE; + else + state = STATE_VALUE_SEPARATOR; + return buf; + case STATE_FINISHED: + return 0; + case STATE_LINE_SEPARATOR: + if (row >= mtx.rows) + { + state = STATE_EPILOGUE; + return next(); + } + state = STATE_ROW_OPEN; + buf[0] = singleLine ? ' ' : '\n'; + buf[1] = 0; + return buf; + case STATE_CN_SEPARATOR: + state = STATE_CN_OPEN; + buf[0] = ','; + buf[1] = ' '; + buf[2] = 0; + return buf; + case STATE_VALUE_SEPARATOR: + state = STATE_VALUE; + buf[0] = ','; + buf[1] = ' '; + buf[2] = 0; + return buf; + } + return 0; + } + }; + + class FormatterBase : public cv::Formatter + { + public: + FormatterBase() : prec32f(8), prec64f(16), multiline(true) {} + + void set32fPrecision(int p) + { + prec32f = p; + } + + void set64fPrecision(int p) + { + prec64f = p; + } + + void setMultiline(bool ml) + { + multiline = ml; + } + + protected: + int prec32f; + int prec64f; + int multiline; + }; + + class MatlabFormatter : public FormatterBase + { + public: + + cv::Ptr format(const cv::Mat& mtx) const + { + char braces[5] = {'\0', '\0', ';', '\0', '\0'}; + return cv::makePtr("[", "]", mtx, &*braces, + mtx.cols == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f ); + } + }; + + class PythonFormatter : public FormatterBase + { + public: + + cv::Ptr format(const cv::Mat& mtx) const + { + char braces[5] = {'[', ']', '\0', '[', ']'}; + if (mtx.cols == 1) + braces[0] = braces[1] = '\0'; + return cv::makePtr("[", "]", mtx, &*braces, + mtx.cols*mtx.channels() == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f ); + } + }; + + class NumpyFormatter : public FormatterBase + { + public: + + cv::Ptr format(const cv::Mat& mtx) const + { + static const char* numpyTypes[] = + { + "uint8", "int8", "uint16", "int16", "int32", "float32", "float64", "uint64" + }; + char braces[5] = {'[', ']', '\0', '[', ']'}; + if (mtx.cols == 1) + braces[0] = braces[1] = '\0'; + return cv::makePtr("array([", + cv::format("], type='%s')", numpyTypes[mtx.depth()]), mtx, &*braces, + mtx.cols*mtx.channels() == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f ); + } + }; + + class CSVFormatter : public FormatterBase + { + public: + + cv::Ptr format(const cv::Mat& mtx) const + { + char braces[5] = {'\0', '\0', '\0', '\0', '\0'}; + return cv::makePtr(cv::String(), + mtx.rows > 1 ? cv::String("\n") : cv::String(), mtx, &*braces, + mtx.cols*mtx.channels() == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f ); + } + }; + + class CFormatter : public FormatterBase + { + public: + + cv::Ptr format(const cv::Mat& mtx) const + { + char braces[5] = {'\0', '\0', ',', '\0', '\0'}; + return cv::makePtr("{", "}", mtx, &*braces, + mtx.cols == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f ); + } + }; + +} // namespace + namespace cv { + Formatted::~Formatted() {} + Formatter::~Formatter() {} -static inline char getCloseBrace(char c) -{ - return c == '[' ? ']' : c == '(' ? ')' : c == '{' ? '}' : '\0'; -} - - -template static void writeElems(std::ostream& out, const _Tp* data, - int nelems, int cn, char obrace, char cbrace) -{ - typedef typename DataType<_Tp>::work_type _WTp; - nelems *= cn; - for(int i = 0; i < nelems; i += cn) + Ptr Formatter::get(int fmt) { - if(cn == 1) + switch(fmt) { - out << (_WTp)data[i] << (i+1 < nelems ? ", " : ""); - continue; + case FMT_MATLAB: + return makePtr(); + case FMT_CSV: + return makePtr(); + case FMT_PYTHON: + return makePtr(); + case FMT_NUMPY: + return makePtr(); + case FMT_C: + return makePtr(); } - out << obrace; - for(int j = 0; j < cn; j++) - out << (_WTp)data[i + j] << (j+1 < cn ? ", " : ""); - out << cbrace << (i+cn < nelems ? ", " : ""); + return makePtr(); } -} - - -static void writeElems(std::ostream& out, const void* data, int nelems, int type, char brace) -{ - int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); - char cbrace = ' '; - if(!brace || isspace(brace)) - { - nelems *= cn; - cn = 1; - } - else - cbrace = getCloseBrace(brace); - if(depth == CV_8U) - writeElems(out, (const uchar*)data, nelems, cn, brace, cbrace); - else if(depth == CV_8S) - writeElems(out, (const schar*)data, nelems, cn, brace, cbrace); - else if(depth == CV_16U) - writeElems(out, (const ushort*)data, nelems, cn, brace, cbrace); - else if(depth == CV_16S) - writeElems(out, (const short*)data, nelems, cn, brace, cbrace); - else if(depth == CV_32S) - writeElems(out, (const int*)data, nelems, cn, brace, cbrace); - else if(depth == CV_32F) - { - std::streamsize pp = out.precision(); - out.precision(8); - writeElems(out, (const float*)data, nelems, cn, brace, cbrace); - out.precision(pp); - } - else if(depth == CV_64F) - { - std::streamsize pp = out.precision(); - out.precision(16); - writeElems(out, (const double*)data, nelems, cn, brace, cbrace); - out.precision(pp); - } - else - CV_Error(CV_StsUnsupportedFormat, ""); -} - - -static void writeMat(std::ostream& out, const Mat& m, char rowsep, char elembrace, bool singleLine) -{ - CV_Assert(m.dims <= 2); - int type = m.type(); - - char crowbrace = getCloseBrace(rowsep); - char orowbrace = crowbrace ? rowsep : '\0'; - - if( orowbrace || isspace(rowsep) ) - rowsep = '\0'; - - for( int i = 0; i < m.rows; i++ ) - { - if(orowbrace) - out << orowbrace; - if( m.data ) - writeElems(out, m.ptr(i), m.cols, type, elembrace); - if(orowbrace) - out << crowbrace << (i+1 < m.rows ? ", " : ""); - if(i+1 < m.rows) - { - if(rowsep) - out << rowsep << (singleLine ? " " : ""); - if(!singleLine) - out << "\n "; - } - } -} - -class MatlabFormatter : public Formatter -{ -public: - virtual ~MatlabFormatter() {} - void write(std::ostream& out, const Mat& m, const int*, int) const - { - out << "["; - writeMat(out, m, ';', ' ', m.cols == 1); - out << "]"; - } - - void write(std::ostream& out, const void* data, int nelems, int type, const int*, int) const - { - writeElems(out, data, nelems, type, ' '); - } -}; - -class PythonFormatter : public Formatter -{ -public: - virtual ~PythonFormatter() {} - void write(std::ostream& out, const Mat& m, const int*, int) const - { - out << "["; - writeMat(out, m, m.cols > 1 ? '[' : ' ', '[', m.cols*m.channels() == 1); - out << "]"; - } - - void write(std::ostream& out, const void* data, int nelems, int type, const int*, int) const - { - writeElems(out, data, nelems, type, '['); - } -}; - - -class NumpyFormatter : public Formatter -{ -public: - virtual ~NumpyFormatter() {} - void write(std::ostream& out, const Mat& m, const int*, int) const - { - static const char* numpyTypes[] = - { - "uint8", "int8", "uint16", "int16", "int32", "float32", "float64", "uint64" - }; - out << "array(["; - writeMat(out, m, m.cols > 1 ? '[' : ' ', '[', m.cols*m.channels() == 1); - out << "], type='" << numpyTypes[m.depth()] << "')"; - } - - void write(std::ostream& out, const void* data, int nelems, int type, const int*, int) const - { - writeElems(out, data, nelems, type, '['); - } -}; - - -class CSVFormatter : public Formatter -{ -public: - virtual ~CSVFormatter() {} - void write(std::ostream& out, const Mat& m, const int*, int) const - { - writeMat(out, m, ' ', ' ', m.cols*m.channels() == 1); - if(m.rows > 1) - out << "\n"; - } - - void write(std::ostream& out, const void* data, int nelems, int type, const int*, int) const - { - writeElems(out, data, nelems, type, ' '); - } -}; - - -class CFormatter : public Formatter -{ -public: - virtual ~CFormatter() {} - void write(std::ostream& out, const Mat& m, const int*, int) const - { - out << "{"; - writeMat(out, m, ',', ' ', m.cols==1); - out << "}"; - } - - void write(std::ostream& out, const void* data, int nelems, int type, const int*, int) const - { - writeElems(out, data, nelems, type, ' '); - } -}; - - -static MatlabFormatter matlabFormatter; -static PythonFormatter pythonFormatter; -static NumpyFormatter numpyFormatter; -static CSVFormatter csvFormatter; -static CFormatter cFormatter; - -static const Formatter* g_defaultFormatter0 = &matlabFormatter; -static const Formatter* g_defaultFormatter = &matlabFormatter; - -static bool my_streq(const char* a, const char* b) -{ - size_t i, alen = strlen(a), blen = strlen(b); - if( alen != blen ) - return false; - for( i = 0; i < alen; i++ ) - if( a[i] != b[i] && a[i] - 32 != b[i] ) - return false; - return true; -} - -const Formatter* Formatter::get(const char* fmt) -{ - if(!fmt || my_streq(fmt, "")) - return g_defaultFormatter; - if( my_streq(fmt, "MATLAB")) - return &matlabFormatter; - if( my_streq(fmt, "CSV")) - return &csvFormatter; - if( my_streq(fmt, "PYTHON")) - return &pythonFormatter; - if( my_streq(fmt, "NUMPY")) - return &numpyFormatter; - if( my_streq(fmt, "C")) - return &cFormatter; - CV_Error(CV_StsBadArg, "Unknown formatter"); - return g_defaultFormatter; -} - -const Formatter* Formatter::setDefault(const Formatter* fmt) -{ - const Formatter* prevFmt = g_defaultFormatter; - if(!fmt) - fmt = g_defaultFormatter0; - g_defaultFormatter = fmt; - return prevFmt; -} - -Formatted::Formatted(const Mat& _m, const Formatter* _fmt, - const std::vector& _params) -{ - mtx = _m; - fmt = _fmt ? _fmt : Formatter::get(); - std::copy(_params.begin(), _params.end(), back_inserter(params)); -} - -Formatted::Formatted(const Mat& _m, const Formatter* _fmt, const int* _params) -{ - mtx = _m; - fmt = _fmt ? _fmt : Formatter::get(); - - if( _params ) - { - int i, maxParams = 100; - for(i = 0; i < maxParams && _params[i] != 0; i+=2) - ; - std::copy(_params, _params + i, back_inserter(params)); - } -} - -} - +} // cv diff --git a/modules/core/src/parallel.cpp b/modules/core/src/parallel.cpp index 0b2a845ac1..27d7ecc038 100644 --- a/modules/core/src/parallel.cpp +++ b/modules/core/src/parallel.cpp @@ -110,8 +110,16 @@ #endif #endif -#if defined HAVE_TBB || defined HAVE_CSTRIPES || defined HAVE_OPENMP || defined HAVE_GCD || defined HAVE_CONCURRENCY - #define HAVE_PARALLEL_FRAMEWORK +#if defined HAVE_TBB && TBB_VERSION_MAJOR*100 + TBB_VERSION_MINOR >= 202 +# define CV_PARALLEL_FRAMEWORK "tbb" +#elif defined HAVE_CSTRIPES +# define CV_PARALLEL_FRAMEWORK "cstripes" +#elif defined HAVE_OPENMP +# define CV_PARALLEL_FRAMEWORK "openmp" +#elif defined HAVE_GCD +# define CV_PARALLEL_FRAMEWORK "gcd" +#elif defined HAVE_CONCURRENCY +# define CV_PARALLEL_FRAMEWORK "ms-concurrency" #endif namespace cv @@ -121,7 +129,7 @@ namespace cv namespace { -#ifdef HAVE_PARALLEL_FRAMEWORK +#ifdef CV_PARALLEL_FRAMEWORK class ParallelLoopBodyWrapper { public: @@ -136,9 +144,9 @@ namespace { cv::Range r; r.start = (int)(wholeRange.start + - ((size_t)sr.start*(wholeRange.end - wholeRange.start) + nstripes/2)/nstripes); + ((uint64)sr.start*(wholeRange.end - wholeRange.start) + nstripes/2)/nstripes); r.end = sr.end >= nstripes ? wholeRange.end : (int)(wholeRange.start + - ((size_t)sr.end*(wholeRange.end - wholeRange.start) + nstripes/2)/nstripes); + ((uint64)sr.end*(wholeRange.end - wholeRange.start) + nstripes/2)/nstripes); (*body)(r); } cv::Range stripeRange() const { return cv::Range(0, nstripes); } @@ -218,7 +226,7 @@ public: static SchedPtr pplScheduler; #endif -#endif // HAVE_PARALLEL_FRAMEWORK +#endif // CV_PARALLEL_FRAMEWORK } //namespace @@ -226,7 +234,7 @@ static SchedPtr pplScheduler; void cv::parallel_for_(const cv::Range& range, const cv::ParallelLoopBody& body, double nstripes) { -#ifdef HAVE_PARALLEL_FRAMEWORK +#ifdef CV_PARALLEL_FRAMEWORK if(numThreads != 0) { @@ -281,7 +289,7 @@ void cv::parallel_for_(const cv::Range& range, const cv::ParallelLoopBody& body, } else -#endif // HAVE_PARALLEL_FRAMEWORK +#endif // CV_PARALLEL_FRAMEWORK { (void)nstripes; body(range); @@ -290,7 +298,7 @@ void cv::parallel_for_(const cv::Range& range, const cv::ParallelLoopBody& body, int cv::getNumThreads(void) { -#ifdef HAVE_PARALLEL_FRAMEWORK +#ifdef CV_PARALLEL_FRAMEWORK if(numThreads == 0) return 1; @@ -333,7 +341,7 @@ int cv::getNumThreads(void) void cv::setNumThreads( int threads ) { (void)threads; -#ifdef HAVE_PARALLEL_FRAMEWORK +#ifdef CV_PARALLEL_FRAMEWORK numThreads = threads; #endif @@ -445,7 +453,11 @@ int cv::getNumberOfCPUs(void) { #if defined WIN32 || defined _WIN32 SYSTEM_INFO sysinfo; +#if defined(_M_ARM) || defined(_M_X64) || defined(HAVE_WINRT) + GetNativeSystemInfo( &sysinfo ); +#else GetSystemInfo( &sysinfo ); +#endif return (int)sysinfo.dwNumberOfProcessors; #elif defined ANDROID @@ -480,6 +492,14 @@ int cv::getNumberOfCPUs(void) #endif } +const char* cv::currentParallelFramework() { +#ifdef CV_PARALLEL_FRAMEWORK + return CV_PARALLEL_FRAMEWORK; +#else + return NULL; +#endif +} + CV_IMPL void cvSetNumThreads(int nt) { cv::setNumThreads(nt); diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 1ee511910c..39ce633139 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -58,7 +58,6 @@ #endif #if USE_ZLIB -# undef HAVE_UNISTD_H //to avoid redefinition # ifndef _LFS64_LARGEFILE # define _LFS64_LARGEFILE 0 # endif @@ -116,7 +115,7 @@ static char* icv_itoa( int _val, char* buffer, int /*radix*/ ) return ptr; } -std::string cv::FileStorage::getDefaultObjectName(const std::string& _filename) +cv::String cv::FileStorage::getDefaultObjectName(const cv::String& _filename) { static const char* stubname = "unnamed"; const char* filename = _filename.c_str(); @@ -152,7 +151,7 @@ std::string cv::FileStorage::getDefaultObjectName(const std::string& _filename) name = name_buf; if( strcmp( name, "_" ) == 0 ) strcpy( name, stubname ); - return std::string(name); + return String(name); } typedef struct CvGenericHash @@ -516,7 +515,7 @@ icvFSFlush( CvFileStorage* fs ) static void -icvClose( CvFileStorage* fs, std::string* out ) +icvClose( CvFileStorage* fs, cv::String* out ) { if( out ) out->clear(); @@ -543,8 +542,7 @@ icvClose( CvFileStorage* fs, std::string* out ) if( fs->outbuf && out ) { - out->resize(fs->outbuf->size()); - std::copy(fs->outbuf->begin(), fs->outbuf->end(), out->begin()); + *out = cv::String(fs->outbuf->begin(), fs->outbuf->end()); } } @@ -3247,19 +3245,19 @@ cvReadRawDataSlice( const CvFileStorage* fs, CvSeqReader* reader, switch( elem_type ) { case CV_8U: - *(uchar*)data = CV_CAST_8U(ival); + *(uchar*)data = cv::saturate_cast(ival); data++; break; case CV_8S: - *(char*)data = CV_CAST_8S(ival); + *(char*)data = cv::saturate_cast(ival); data++; break; case CV_16U: - *(ushort*)data = CV_CAST_16U(ival); + *(ushort*)data = cv::saturate_cast(ival); data += sizeof(ushort); break; case CV_16S: - *(short*)data = CV_CAST_16S(ival); + *(short*)data = cv::saturate_cast(ival); data += sizeof(short); break; case CV_32S: @@ -3292,22 +3290,22 @@ cvReadRawDataSlice( const CvFileStorage* fs, CvSeqReader* reader, { case CV_8U: ival = cvRound(fval); - *(uchar*)data = CV_CAST_8U(ival); + *(uchar*)data = cv::saturate_cast(ival); data++; break; case CV_8S: ival = cvRound(fval); - *(char*)data = CV_CAST_8S(ival); + *(char*)data = cv::saturate_cast(ival); data++; break; case CV_16U: ival = cvRound(fval); - *(ushort*)data = CV_CAST_16U(ival); + *(ushort*)data = cv::saturate_cast(ival); data += sizeof(ushort); break; case CV_16S: ival = cvRound(fval); - *(short*)data = CV_CAST_16S(ival); + *(short*)data = cv::saturate_cast(ival); data += sizeof(short); break; case CV_32S: @@ -5011,7 +5009,7 @@ cvSave( const char* filename, const void* struct_ptr, if( !fs ) CV_Error( CV_StsError, "Could not open the file storage. Check the path and permissions" ); - std::string name = _name ? std::string(_name) : cv::FileStorage::getDefaultObjectName(filename); + cv::String name = _name ? cv::String(_name) : cv::FileStorage::getDefaultObjectName(filename); if( comment ) cvWriteComment( fs, comment, 0 ); @@ -5105,7 +5103,7 @@ stop_search: namespace cv { -static void getElemSize( const std::string& fmt, size_t& elemSize, size_t& cn ) +static void getElemSize( const String& fmt, size_t& elemSize, size_t& cn ) { const char* dt = fmt.c_str(); cn = 1; @@ -5125,15 +5123,17 @@ FileStorage::FileStorage() state = UNDEFINED; } -FileStorage::FileStorage(const std::string& filename, int flags, const std::string& encoding) +FileStorage::FileStorage(const String& filename, int flags, const String& encoding) { state = UNDEFINED; open( filename, flags, encoding ); } -FileStorage::FileStorage(CvFileStorage* _fs) +FileStorage::FileStorage(CvFileStorage* _fs, bool owning) { - fs = Ptr(_fs); + if (owning) fs.reset(_fs); + else fs = Ptr(Ptr(), _fs); + state = _fs ? NAME_EXPECTED + INSIDE_MAP : UNDEFINED; } @@ -5146,11 +5146,11 @@ FileStorage::~FileStorage() } } -bool FileStorage::open(const std::string& filename, int flags, const std::string& encoding) +bool FileStorage::open(const String& filename, int flags, const String& encoding) { release(); - fs = Ptr(cvOpenFileStorage( filename.c_str(), 0, flags, - !encoding.empty() ? encoding.c_str() : 0)); + fs.reset(cvOpenFileStorage( filename.c_str(), 0, flags, + !encoding.empty() ? encoding.c_str() : 0)); bool ok = isOpened(); state = ok ? NAME_EXPECTED + INSIDE_MAP : UNDEFINED; return ok; @@ -5158,7 +5158,7 @@ bool FileStorage::open(const std::string& filename, int flags, const std::string bool FileStorage::isOpened() const { - return !fs.empty() && fs.obj->is_opened; + return fs && fs->is_opened; } void FileStorage::release() @@ -5168,12 +5168,11 @@ void FileStorage::release() state = UNDEFINED; } -std::string FileStorage::releaseAndGetString() +String FileStorage::releaseAndGetString() { - std::string buf; - buf.reserve(16); // HACK: Work around for compiler bug - if( fs.obj && fs.obj->outbuf ) - icvClose(fs.obj, &buf); + String buf; + if( fs && fs->outbuf ) + icvClose(fs, &buf); release(); return buf; @@ -5184,7 +5183,7 @@ FileNode FileStorage::root(int streamidx) const return isOpened() ? FileNode(fs, cvGetRootFileNode(fs, streamidx)) : FileNode(); } -FileStorage& operator << (FileStorage& fs, const std::string& str) +FileStorage& operator << (FileStorage& fs, const String& str) { enum { NAME_EXPECTED = FileStorage::NAME_EXPECTED, VALUE_EXPECTED = FileStorage::VALUE_EXPECTED, @@ -5203,7 +5202,7 @@ FileStorage& operator << (FileStorage& fs, const std::string& str) fs.state = fs.structs.empty() || fs.structs.back() == '{' ? INSIDE_MAP + NAME_EXPECTED : VALUE_EXPECTED; cvEndWriteStruct( *fs ); - fs.elname = std::string(); + fs.elname = String(); } else if( fs.state == NAME_EXPECTED + INSIDE_MAP ) { @@ -5227,12 +5226,12 @@ FileStorage& operator << (FileStorage& fs, const std::string& str) } cvStartWriteStruct( *fs, fs.elname.size() > 0 ? fs.elname.c_str() : 0, flags, *_str ? _str : 0 ); - fs.elname = std::string(); + fs.elname = String(); } else { write( fs, fs.elname, (_str[0] == '\\' && (_str[1] == '{' || _str[1] == '}' || - _str[1] == '[' || _str[1] == ']')) ? std::string(_str+1) : str ); + _str[1] == '[' || _str[1] == ']')) ? String(_str+1) : str ); if( fs.state == INSIDE_MAP + VALUE_EXPECTED ) fs.state = INSIDE_MAP + NAME_EXPECTED; } @@ -5243,7 +5242,7 @@ FileStorage& operator << (FileStorage& fs, const std::string& str) } -void FileStorage::writeRaw( const std::string& fmt, const uchar* vec, size_t len ) +void FileStorage::writeRaw( const String& fmt, const uchar* vec, size_t len ) { if( !isOpened() ) return; @@ -5254,7 +5253,7 @@ void FileStorage::writeRaw( const std::string& fmt, const uchar* vec, size_t len } -void FileStorage::writeObj( const std::string& name, const void* obj ) +void FileStorage::writeObj( const String& name, const void* obj ) { if( !isOpened() ) return; @@ -5262,7 +5261,7 @@ void FileStorage::writeObj( const std::string& name, const void* obj ) } -FileNode FileStorage::operator[](const std::string& nodename) const +FileNode FileStorage::operator[](const String& nodename) const { return FileNode(fs, cvGetFileNodeByName(fs, 0, nodename.c_str())); } @@ -5272,7 +5271,7 @@ FileNode FileStorage::operator[](const char* nodename) const return FileNode(fs, cvGetFileNodeByName(fs, 0, nodename)); } -FileNode FileNode::operator[](const std::string& nodename) const +FileNode FileNode::operator[](const String& nodename) const { return FileNode(fs, cvGetFileNodeByName(fs, node, nodename.c_str())); } @@ -5288,10 +5287,10 @@ FileNode FileNode::operator[](int i) const i == 0 ? *this : FileNode(); } -std::string FileNode::name() const +String FileNode::name() const { const char* str; - return !node || (str = cvGetFileNodeName(node)) == 0 ? std::string() : std::string(str); + return !node || (str = cvGetFileNodeName(node)) == 0 ? String() : String(str); } void* FileNode::readObj() const @@ -5319,7 +5318,7 @@ FileNodeIterator::FileNodeIterator(const CvFileStorage* _fs, container = _node; if( !(_node->tag & FileNode::USER) && (node_type == FileNode::SEQ || node_type == FileNode::MAP) ) { - cvStartReadSeq( _node->data.seq, &reader ); + cvStartReadSeq( _node->data.seq, (CvSeqReader*)&reader ); remaining = FileNode(_fs, _node).size(); } else @@ -5352,7 +5351,12 @@ FileNodeIterator& FileNodeIterator::operator ++() if( remaining > 0 ) { if( reader.seq ) - CV_NEXT_SEQ_ELEM( reader.seq->elem_size, reader ); + { + if( ((reader).ptr += (((CvSeq*)reader.seq)->elem_size)) >= (reader).block_max ) + { + cvChangeSeqBlock( (CvSeqReader*)&(reader), 1 ); + } + } remaining--; } return *this; @@ -5370,7 +5374,12 @@ FileNodeIterator& FileNodeIterator::operator --() if( remaining < FileNode(fs, container).size() ) { if( reader.seq ) - CV_PREV_SEQ_ELEM( reader.seq->elem_size, reader ); + { + if( ((reader).ptr -= (((CvSeq*)reader.seq)->elem_size)) < (reader).block_min ) + { + cvChangeSeqBlock( (CvSeqReader*)&(reader), -1 ); + } + } remaining++; } return *this; @@ -5396,7 +5405,7 @@ FileNodeIterator& FileNodeIterator::operator += (int ofs) } remaining -= ofs; if( reader.seq ) - cvSetSeqReaderPos( &reader, ofs, 1 ); + cvSetSeqReaderPos( (CvSeqReader*)&reader, ofs, 1 ); return *this; } @@ -5406,7 +5415,7 @@ FileNodeIterator& FileNodeIterator::operator -= (int ofs) } -FileNodeIterator& FileNodeIterator::readRaw( const std::string& fmt, uchar* vec, size_t maxCount ) +FileNodeIterator& FileNodeIterator::readRaw( const String& fmt, uchar* vec, size_t maxCount ) { if( fs && container && remaining > 0 ) { @@ -5417,7 +5426,7 @@ FileNodeIterator& FileNodeIterator::readRaw( const std::string& fmt, uchar* vec, if( reader.seq ) { - cvReadRawDataSlice( fs, &reader, (int)count, vec, fmt.c_str() ); + cvReadRawDataSlice( fs, (CvSeqReader*)&reader, (int)count, vec, fmt.c_str() ); remaining -= count*cn; } else @@ -5430,16 +5439,16 @@ FileNodeIterator& FileNodeIterator::readRaw( const std::string& fmt, uchar* vec, } -void write( FileStorage& fs, const std::string& name, int value ) +void write( FileStorage& fs, const String& name, int value ) { cvWriteInt( *fs, name.size() ? name.c_str() : 0, value ); } -void write( FileStorage& fs, const std::string& name, float value ) +void write( FileStorage& fs, const String& name, float value ) { cvWriteReal( *fs, name.size() ? name.c_str() : 0, value ); } -void write( FileStorage& fs, const std::string& name, double value ) +void write( FileStorage& fs, const String& name, double value ) { cvWriteReal( *fs, name.size() ? name.c_str() : 0, value ); } -void write( FileStorage& fs, const std::string& name, const std::string& value ) +void write( FileStorage& fs, const String& name, const String& value ) { cvWriteString( *fs, name.size() ? name.c_str() : 0, value.c_str() ); } void writeScalar(FileStorage& fs, int value ) @@ -5451,11 +5460,11 @@ void writeScalar(FileStorage& fs, float value ) void writeScalar(FileStorage& fs, double value ) { cvWriteReal( *fs, 0, value ); } -void writeScalar(FileStorage& fs, const std::string& value ) +void writeScalar(FileStorage& fs, const String& value ) { cvWriteString( *fs, 0, value.c_str() ); } -void write( FileStorage& fs, const std::string& name, const Mat& value ) +void write( FileStorage& fs, const String& name, const Mat& value ) { if( value.dims <= 2 ) { @@ -5470,21 +5479,24 @@ void write( FileStorage& fs, const std::string& name, const Mat& value ) } // TODO: the 4 functions below need to be implemented more efficiently -void write( FileStorage& fs, const std::string& name, const SparseMat& value ) +void write( FileStorage& fs, const String& name, const SparseMat& value ) { - Ptr mat = (CvSparseMat*)value; + Ptr mat(cvCreateSparseMat(value)); cvWrite( *fs, name.size() ? name.c_str() : 0, mat ); } -WriteStructContext::WriteStructContext(FileStorage& _fs, const std::string& name, - int flags, const std::string& typeName) : fs(&_fs) +internal::WriteStructContext::WriteStructContext(FileStorage& _fs, + const String& name, int flags, const String& typeName) : fs(&_fs) { cvStartWriteStruct(**fs, !name.empty() ? name.c_str() : 0, flags, !typeName.empty() ? typeName.c_str() : 0); } -WriteStructContext::~WriteStructContext() { cvEndWriteStruct(**fs); } +internal::WriteStructContext::~WriteStructContext() +{ + cvEndWriteStruct(**fs); +} void read( const FileNode& node, Mat& mat, const Mat& default_mat ) @@ -5497,12 +5509,12 @@ void read( const FileNode& node, Mat& mat, const Mat& default_mat ) void* obj = cvRead((CvFileStorage*)node.fs, (CvFileNode*)*node); if(CV_IS_MAT_HDR_Z(obj)) { - Mat((const CvMat*)obj).copyTo(mat); + cvarrToMat(obj).copyTo(mat); cvReleaseMat((CvMat**)&obj); } else if(CV_IS_MATND_HDR(obj)) { - Mat((const CvMatND*)obj).copyTo(mat); + cvarrToMat(obj).copyTo(mat); cvReleaseMatND((CvMatND**)&obj); } else @@ -5519,9 +5531,76 @@ void read( const FileNode& node, SparseMat& mat, const SparseMat& default_mat ) default_mat.copyTo(mat); return; } - Ptr m = (CvSparseMat*)cvRead((CvFileStorage*)node.fs, (CvFileNode*)*node); - CV_Assert(CV_IS_SPARSE_MAT(m.obj)); - SparseMat(m).copyTo(mat); + Ptr m((CvSparseMat*)cvRead((CvFileStorage*)node.fs, (CvFileNode*)*node)); + CV_Assert(CV_IS_SPARSE_MAT(m)); + m->copyToSparseMat(mat); +} + +void write(FileStorage& fs, const String& objname, const std::vector& keypoints) +{ + internal::WriteStructContext ws(fs, objname, CV_NODE_SEQ + CV_NODE_FLOW); + + int i, npoints = (int)keypoints.size(); + for( i = 0; i < npoints; i++ ) + { + const KeyPoint& kpt = keypoints[i]; + cv::write(fs, kpt.pt.x); + cv::write(fs, kpt.pt.y); + cv::write(fs, kpt.size); + cv::write(fs, kpt.angle); + cv::write(fs, kpt.response); + cv::write(fs, kpt.octave); + cv::write(fs, kpt.class_id); + } +} + + +void read(const FileNode& node, std::vector& keypoints) +{ + keypoints.resize(0); + FileNodeIterator it = node.begin(), it_end = node.end(); + for( ; it != it_end; ) + { + KeyPoint kpt; + it >> kpt.pt.x >> kpt.pt.y >> kpt.size >> kpt.angle >> kpt.response >> kpt.octave >> kpt.class_id; + keypoints.push_back(kpt); + } +} + +int FileNode::type() const { return !node ? NONE : (node->tag & TYPE_MASK); } +bool FileNode::isNamed() const { return !node ? false : (node->tag & NAMED) != 0; } + +size_t FileNode::size() const +{ + int t = type(); + return t == MAP ? (size_t)((CvSet*)node->data.map)->active_count : + t == SEQ ? (size_t)node->data.seq->total : (size_t)!isNone(); +} + +void read(const FileNode& node, int& value, int default_value) +{ + value = !node.node ? default_value : + CV_NODE_IS_INT(node.node->tag) ? node.node->data.i : + CV_NODE_IS_REAL(node.node->tag) ? cvRound(node.node->data.f) : 0x7fffffff; +} + +void read(const FileNode& node, float& value, float default_value) +{ + value = !node.node ? default_value : + CV_NODE_IS_INT(node.node->tag) ? (float)node.node->data.i : + CV_NODE_IS_REAL(node.node->tag) ? (float)node.node->data.f : 1e30f; +} + +void read(const FileNode& node, double& value, double default_value) +{ + value = !node.node ? default_value : + CV_NODE_IS_INT(node.node->tag) ? (double)node.node->data.i : + CV_NODE_IS_REAL(node.node->tag) ? node.node->data.f : 1e300; +} + +void read(const FileNode& node, String& value, const String& default_value) +{ + value = !node.node ? default_value : CV_NODE_IS_STRING(node.node->tag) ? String(node.node->data.str.ptr) : String(); } } diff --git a/modules/core/src/precomp.hpp b/modules/core/src/precomp.hpp index 30ce3d17b1..1a59f6e7bd 100644 --- a/modules/core/src/precomp.hpp +++ b/modules/core/src/precomp.hpp @@ -43,13 +43,13 @@ #ifndef __OPENCV_PRECOMP_H__ #define __OPENCV_PRECOMP_H__ -#ifdef HAVE_CVCONFIG_H -#include "cvconfig.h" -#endif - -#include "opencv2/core.hpp" +#include "opencv2/core/utility.hpp" #include "opencv2/core/core_c.h" -#include "opencv2/core/internal.hpp" +#include "opencv2/core/gpu.hpp" +#include "opencv2/core/opengl.hpp" + +#include "opencv2/core/private.hpp" +#include "opencv2/core/private.gpu.hpp" #include #include @@ -66,28 +66,28 @@ #define GET_OPTIMIZED(func) (func) #endif -#ifdef HAVE_CUDA -# include -# include "opencv2/core/gpumat.hpp" - -# if defined(__GNUC__) -# define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__, __func__) -# else -# define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__) -# endif - -static inline void ___cudaSafeCall(cudaError_t err, const char *file, const int line, const char *func = "") -{ - if (cudaSuccess != err) cv::gpu::error(cudaGetErrorString(err), file, line, func); -} - -#else -# define cudaSafeCall(expr) -#endif - namespace cv { +typedef void (*BinaryFunc)(const uchar* src1, size_t step1, + const uchar* src2, size_t step2, + uchar* dst, size_t step, Size sz, + void*); + +BinaryFunc getConvertFunc(int sdepth, int ddepth); +BinaryFunc getCopyMaskFunc(size_t esz); + +/* default memory block for sparse array elements */ +#define CV_SPARSE_MAT_BLOCK (1<<12) + +/* initial hash table size */ +#define CV_SPARSE_HASH_SIZE0 (1<<10) + +/* maximal average node_count/hash_size ratio beyond which hash table is resized */ +#define CV_SPARSE_HASH_RATIO 3 + + + // -128.f ... 255.f extern const float g_8x32fTab[]; #define CV_8TO32F(x) cv::g_8x32fTab[(x)+128] @@ -194,11 +194,6 @@ extern volatile bool USE_AVX; enum { BLOCK_SIZE = 1024 }; -#ifdef HAVE_IPP -static inline IppiSize ippiSize(int width, int height) { IppiSize sz = { width, height}; return sz; } -static inline IppiSize ippiSize(Size _sz) { IppiSize sz = { _sz.width, _sz.height}; return sz; } -#endif - #if defined HAVE_IPP && (IPP_VERSION_MAJOR >= 7) #define ARITHM_USE_IPP 1 #define IF_IPP(then_call, else_call) then_call diff --git a/modules/core/src/rand.cpp b/modules/core/src/rand.cpp index 3ba7fd684d..ffce63484a 100644 --- a/modules/core/src/rand.cpp +++ b/modules/core/src/rand.cpp @@ -54,6 +54,8 @@ #undef min #undef max #undef abs +#else + #include #endif #if defined __SSE2__ || (defined _M_IX86_FP && 2 == _M_IX86_FP) @@ -726,33 +728,54 @@ void RNG::fill( InputOutputArray _mat, int disttype, } #ifdef WIN32 + + +#ifdef HAVE_WINRT +// using C++11 thread attribute for local thread data +__declspec( thread ) RNG* rng = NULL; + + void deleteThreadRNGData() + { + if (rng) + delete rng; +} + +RNG& theRNG() +{ + if (!rng) + { + rng = new RNG; + } + return *rng; +} +#else #ifdef WINCE # define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF) #endif static DWORD tlsRNGKey = TLS_OUT_OF_INDEXES; -void deleteThreadRNGData() -{ - if( tlsRNGKey != TLS_OUT_OF_INDEXES ) - delete (RNG*)TlsGetValue( tlsRNGKey ); + void deleteThreadRNGData() + { + if( tlsRNGKey != TLS_OUT_OF_INDEXES ) + delete (RNG*)TlsGetValue( tlsRNGKey ); } RNG& theRNG() { if( tlsRNGKey == TLS_OUT_OF_INDEXES ) { - tlsRNGKey = TlsAlloc(); - CV_Assert(tlsRNGKey != TLS_OUT_OF_INDEXES); + tlsRNGKey = TlsAlloc(); + CV_Assert(tlsRNGKey != TLS_OUT_OF_INDEXES); } RNG* rng = (RNG*)TlsGetValue( tlsRNGKey ); if( !rng ) { - rng = new RNG; - TlsSetValue( tlsRNGKey, rng ); + rng = new RNG; + TlsSetValue( tlsRNGKey, rng ); } return *rng; } - +#endif //HAVE_WINRT #else static pthread_key_t tlsRNGKey = 0; @@ -861,11 +884,6 @@ void cv::randShuffle( InputOutputArray _dst, double iterFactor, RNG* _rng ) func( dst, rng, iterFactor ); } -void cv::randShuffle_( InputOutputArray _dst, double iterFactor ) -{ - randShuffle(_dst, iterFactor); -} - CV_IMPL void cvRandArr( CvRNG* _rng, CvArr* arr, int disttype, CvScalar param1, CvScalar param2 ) { diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index b62f10a2a8..86555fcc3b 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -42,6 +42,7 @@ #include "precomp.hpp" #include +#include namespace cv { @@ -199,14 +200,19 @@ static int sum64f( const double* src, const uchar* mask, double* dst, int len, i typedef int (*SumFunc)(const uchar*, const uchar* mask, uchar*, int, int); -static SumFunc sumTab[] = +static SumFunc getSumFunc(int depth) { - (SumFunc)GET_OPTIMIZED(sum8u), (SumFunc)sum8s, - (SumFunc)sum16u, (SumFunc)sum16s, - (SumFunc)sum32s, - (SumFunc)GET_OPTIMIZED(sum32f), (SumFunc)sum64f, - 0 -}; + static SumFunc sumTab[] = + { + (SumFunc)GET_OPTIMIZED(sum8u), (SumFunc)sum8s, + (SumFunc)sum16u, (SumFunc)sum16s, + (SumFunc)sum32s, + (SumFunc)GET_OPTIMIZED(sum32f), (SumFunc)sum64f, + 0 + }; + + return sumTab[depth]; +} template static int countNonZero_(const T* src, int len ) @@ -271,14 +277,18 @@ static int countNonZero64f( const double* src, int len ) typedef int (*CountNonZeroFunc)(const uchar*, int); -static CountNonZeroFunc countNonZeroTab[] = +static CountNonZeroFunc getCountNonZeroTab(int depth) { - (CountNonZeroFunc)GET_OPTIMIZED(countNonZero8u), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero8u), - (CountNonZeroFunc)GET_OPTIMIZED(countNonZero16u), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero16u), - (CountNonZeroFunc)GET_OPTIMIZED(countNonZero32s), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero32f), - (CountNonZeroFunc)GET_OPTIMIZED(countNonZero64f), 0 -}; + static CountNonZeroFunc countNonZeroTab[] = + { + (CountNonZeroFunc)GET_OPTIMIZED(countNonZero8u), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero8u), + (CountNonZeroFunc)GET_OPTIMIZED(countNonZero16u), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero16u), + (CountNonZeroFunc)GET_OPTIMIZED(countNonZero32s), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero32f), + (CountNonZeroFunc)GET_OPTIMIZED(countNonZero64f), 0 + }; + return countNonZeroTab[depth]; +} template static int sumsqr_(const T* src0, const uchar* mask, ST* sum, SQT* sqsum, int len, int cn ) @@ -427,11 +437,16 @@ static int sqsum64f( const double* src, const uchar* mask, double* sum, double* typedef int (*SumSqrFunc)(const uchar*, const uchar* mask, uchar*, uchar*, int, int); -static SumSqrFunc sumSqrTab[] = +static SumSqrFunc getSumSqrTab(int depth) { - (SumSqrFunc)GET_OPTIMIZED(sqsum8u), (SumSqrFunc)sqsum8s, (SumSqrFunc)sqsum16u, (SumSqrFunc)sqsum16s, - (SumSqrFunc)sqsum32s, (SumSqrFunc)GET_OPTIMIZED(sqsum32f), (SumSqrFunc)sqsum64f, 0 -}; + static SumSqrFunc sumSqrTab[] = + { + (SumSqrFunc)GET_OPTIMIZED(sqsum8u), (SumSqrFunc)sqsum8s, (SumSqrFunc)sqsum16u, (SumSqrFunc)sqsum16s, + (SumSqrFunc)sqsum32s, (SumSqrFunc)GET_OPTIMIZED(sqsum32f), (SumSqrFunc)sqsum64f, 0 + }; + + return sumSqrTab[depth]; +} } @@ -439,7 +454,46 @@ cv::Scalar cv::sum( InputArray _src ) { Mat src = _src.getMat(); int k, cn = src.channels(), depth = src.depth(); - SumFunc func = sumTab[depth]; + +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) + size_t total_size = src.total(); + int rows = src.size[0], cols = (int)(total_size/rows); + if( src.dims == 2 || (src.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) ) + { + IppiSize sz = { cols, rows }; + int type = src.type(); + typedef IppStatus (CV_STDCALL* ippiSumFunc)(const void*, int, IppiSize, double *, int); + ippiSumFunc ippFunc = + type == CV_8UC1 ? (ippiSumFunc)ippiSum_8u_C1R : + type == CV_8UC3 ? (ippiSumFunc)ippiSum_8u_C3R : + type == CV_8UC4 ? (ippiSumFunc)ippiSum_8u_C4R : + type == CV_16UC1 ? (ippiSumFunc)ippiSum_16u_C1R : + type == CV_16UC3 ? (ippiSumFunc)ippiSum_16u_C3R : + type == CV_16UC4 ? (ippiSumFunc)ippiSum_16u_C4R : + type == CV_16SC1 ? (ippiSumFunc)ippiSum_16s_C1R : + type == CV_16SC3 ? (ippiSumFunc)ippiSum_16s_C3R : + type == CV_16SC4 ? (ippiSumFunc)ippiSum_16s_C4R : + type == CV_32FC1 ? (ippiSumFunc)ippiSum_32f_C1R : + type == CV_32FC3 ? (ippiSumFunc)ippiSum_32f_C3R : + type == CV_32FC4 ? (ippiSumFunc)ippiSum_32f_C4R : + 0; + if( ippFunc ) + { + Ipp64f res[4]; + if( ippFunc(src.data, src.step[0], sz, res, ippAlgHintAccurate) >= 0 ) + { + Scalar sc; + for( int i = 0; i < cn; i++ ) + { + sc[i] = res[i]; + } + return sc; + } + } + } +#endif + + SumFunc func = getSumFunc(depth); CV_Assert( cn <= 4 && func != 0 ); @@ -491,7 +545,7 @@ cv::Scalar cv::sum( InputArray _src ) int cv::countNonZero( InputArray _src ) { Mat src = _src.getMat(); - CountNonZeroFunc func = countNonZeroTab[src.depth()]; + CountNonZeroFunc func = getCountNonZeroTab(src.depth()); CV_Assert( src.channels() == 1 && func != 0 ); @@ -512,7 +566,82 @@ cv::Scalar cv::mean( InputArray _src, InputArray _mask ) CV_Assert( mask.empty() || mask.type() == CV_8U ); int k, cn = src.channels(), depth = src.depth(); - SumFunc func = sumTab[depth]; + +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) + size_t total_size = src.total(); + int rows = src.size[0], cols = (int)(total_size/rows); + 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, 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.data, src.step[0], mask.data, mask.step[0], sz, &res) >= 0 ) + { + return Scalar(res); + } + } + typedef IppStatus (CV_STDCALL* ippiMaskMeanFuncC3)(const void *, int, 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.data, src.step[0], mask.data, mask.step[0], sz, 1, &res1) >= 0 && + ippFuncC3(src.data, src.step[0], mask.data, mask.step[0], sz, 2, &res2) >= 0 && + ippFuncC3(src.data, src.step[0], mask.data, mask.step[0], sz, 3, &res3) >= 0 ) + { + return Scalar(res1, res2, res3); + } + } + } + else + { + typedef IppStatus (CV_STDCALL* ippiMeanFunc)(const void*, int, IppiSize, double *, int); + ippiMeanFunc ippFunc = + type == CV_8UC1 ? (ippiMeanFunc)ippiMean_8u_C1R : + type == CV_8UC3 ? (ippiMeanFunc)ippiMean_8u_C3R : + type == CV_8UC4 ? (ippiMeanFunc)ippiMean_8u_C4R : + type == CV_16UC1 ? (ippiMeanFunc)ippiMean_16u_C1R : + type == CV_16UC3 ? (ippiMeanFunc)ippiMean_16u_C3R : + type == CV_16UC4 ? (ippiMeanFunc)ippiMean_16u_C4R : + type == CV_16SC1 ? (ippiMeanFunc)ippiMean_16s_C1R : + type == CV_16SC3 ? (ippiMeanFunc)ippiMean_16s_C3R : + type == CV_16SC4 ? (ippiMeanFunc)ippiMean_16s_C4R : + type == CV_32FC1 ? (ippiMeanFunc)ippiMean_32f_C1R : + type == CV_32FC3 ? (ippiMeanFunc)ippiMean_32f_C3R : + type == CV_32FC4 ? (ippiMeanFunc)ippiMean_32f_C4R : + 0; + if( ippFunc ) + { + Ipp64f res[4]; + if( ippFunc(src.data, src.step[0], sz, res, ippAlgHintAccurate) >= 0 ) + { + Scalar sc; + for( int i = 0; i < cn; i++ ) + { + sc[i] = res[i]; + } + return sc; + } + } + } + } +#endif + + SumFunc func = getSumFunc(depth); CV_Assert( cn <= 4 && func != 0 ); @@ -571,7 +700,100 @@ void cv::meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv, Input CV_Assert( mask.empty() || mask.type() == CV_8U ); int k, cn = src.channels(), depth = src.depth(); - SumSqrFunc func = sumSqrTab[depth]; + +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) + size_t total_size = src.total(); + int rows = src.size[0], cols = (int)(total_size/rows); + if( src.dims == 2 || (src.isContinuous() && mask.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) ) + { + Ipp64f mean_temp[3]; + Ipp64f stddev_temp[3]; + Ipp64f *pmean = &mean_temp[0]; + Ipp64f *pstddev = &stddev_temp[0]; + Mat mean, stddev; + int dcn_mean = -1; + if( _mean.needed() ) + { + if( !_mean.fixedSize() ) + _mean.create(cn, 1, CV_64F, -1, true); + mean = _mean.getMat(); + dcn_mean = (int)mean.total(); + pmean = (Ipp64f *)mean.data; + } + int dcn_stddev = -1; + if( _sdv.needed() ) + { + if( !_sdv.fixedSize() ) + _sdv.create(cn, 1, CV_64F, -1, true); + stddev = _sdv.getMat(); + dcn_stddev = (int)stddev.total(); + pstddev = (Ipp64f *)stddev.data; + } + for( int k = cn; k < dcn_mean; k++ ) + pmean[k] = 0; + for( int k = cn; k < dcn_stddev; k++ ) + pstddev[k] = 0; + IppiSize sz = { cols, rows }; + int type = src.type(); + if( !mask.empty() ) + { + typedef IppStatus (CV_STDCALL* ippiMaskMeanStdDevFuncC1)(const void *, int, void *, int, IppiSize, Ipp64f *, Ipp64f *); + ippiMaskMeanStdDevFuncC1 ippFuncC1 = + type == CV_8UC1 ? (ippiMaskMeanStdDevFuncC1)ippiMean_StdDev_8u_C1MR : + type == CV_16UC1 ? (ippiMaskMeanStdDevFuncC1)ippiMean_StdDev_16u_C1MR : + type == CV_32FC1 ? (ippiMaskMeanStdDevFuncC1)ippiMean_StdDev_32f_C1MR : + 0; + if( ippFuncC1 ) + { + if( ippFuncC1(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, pmean, pstddev) >= 0 ) + return; + } + typedef IppStatus (CV_STDCALL* ippiMaskMeanStdDevFuncC3)(const void *, int, void *, int, IppiSize, int, Ipp64f *, Ipp64f *); + ippiMaskMeanStdDevFuncC3 ippFuncC3 = + type == CV_8UC3 ? (ippiMaskMeanStdDevFuncC3)ippiMean_StdDev_8u_C3CMR : + type == CV_16UC3 ? (ippiMaskMeanStdDevFuncC3)ippiMean_StdDev_16u_C3CMR : + type == CV_32FC3 ? (ippiMaskMeanStdDevFuncC3)ippiMean_StdDev_32f_C3CMR : + 0; + if( ippFuncC3 ) + { + if( ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 1, &pmean[0], &pstddev[0]) >= 0 && + ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 2, &pmean[1], &pstddev[1]) >= 0 && + ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 3, &pmean[2], &pstddev[2]) >= 0 ) + return; + } + } + else + { + typedef IppStatus (CV_STDCALL* ippiMeanStdDevFuncC1)(const void *, int, IppiSize, Ipp64f *, Ipp64f *); + ippiMeanStdDevFuncC1 ippFuncC1 = + type == CV_8UC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_8u_C1R : + type == CV_16UC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_16u_C1R : + //type == CV_32FC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_32f_C1R ://Aug 2013: bug in IPP 7.1, 8.0 + 0; + if( ippFuncC1 ) + { + if( ippFuncC1(src.data, (int)src.step[0], sz, pmean, pstddev) >= 0 ) + return; + } + typedef IppStatus (CV_STDCALL* ippiMeanStdDevFuncC3)(const void *, int, IppiSize, int, Ipp64f *, Ipp64f *); + ippiMeanStdDevFuncC3 ippFuncC3 = + type == CV_8UC3 ? (ippiMeanStdDevFuncC3)ippiMean_StdDev_8u_C3CR : + type == CV_16UC3 ? (ippiMeanStdDevFuncC3)ippiMean_StdDev_16u_C3CR : + type == CV_32FC3 ? (ippiMeanStdDevFuncC3)ippiMean_StdDev_32f_C3CR : + 0; + if( ippFuncC3 ) + { + if( ippFuncC3(src.data, (int)src.step[0], sz, 1, &pmean[0], &pstddev[0]) >= 0 && + ippFuncC3(src.data, (int)src.step[0], sz, 2, &pmean[1], &pstddev[1]) >= 0 && + ippFuncC3(src.data, (int)src.step[0], sz, 3, &pmean[2], &pstddev[2]) >= 0 ) + return; + } + } + } +#endif + + + SumSqrFunc func = getSumSqrTab(depth); CV_Assert( func != 0 ); @@ -745,14 +967,19 @@ static void minMaxIdx_64f(const double* src, const uchar* mask, double* minval, typedef void (*MinMaxIdxFunc)(const uchar*, const uchar*, int*, int*, size_t*, size_t*, int, size_t); -static MinMaxIdxFunc minmaxTab[] = +static MinMaxIdxFunc getMinmaxTab(int depth) { - (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_8u), (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_8s), - (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_16u), (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_16s), - (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_32s), - (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_32f), (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_64f), - 0 -}; + static MinMaxIdxFunc minmaxTab[] = + { + (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_8u), (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_8s), + (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_16u), (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_16s), + (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_32s), + (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_32f), (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_64f), + 0 + }; + + return minmaxTab[depth]; +} static void ofs2idx(const Mat& a, size_t ofs, int* idx) { @@ -785,7 +1012,84 @@ void cv::minMaxIdx(InputArray _src, double* minVal, CV_Assert( (cn == 1 && (mask.empty() || mask.type() == CV_8U)) || (cn >= 1 && mask.empty() && !minIdx && !maxIdx) ); - MinMaxIdxFunc func = minmaxTab[depth]; + +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) + size_t total_size = src.total(); + int rows = src.size[0], cols = (int)(total_size/rows); + if( cn == 1 && ( 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* ippiMaskMinMaxIndxFuncC1)(const void *, int, const void *, int, IppiSize, Ipp32f *, Ipp32f *, IppiPoint *, IppiPoint *); + ippiMaskMinMaxIndxFuncC1 ippFuncC1 = + type == CV_8UC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_8u_C1MR : + type == CV_16UC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_16u_C1MR : + type == CV_32FC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_32f_C1MR : + 0; + if( ippFuncC1 ) + { + Ipp32f min, max; + IppiPoint minp, maxp; + if( ippFuncC1(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, &min, &max, &minp, &maxp) >= 0 ) + { + if( minVal ) + *minVal = (double)min; + if( maxVal ) + *maxVal = (double)max; + if( !minp.x && !minp.y && !maxp.x && !maxp.y && !mask.data[0] ) + minp.x = maxp.x = -1; + if( minIdx ) + { + size_t minidx = minp.y * cols + minp.x + 1; + ofs2idx(src, minidx, minIdx); + } + if( maxIdx ) + { + size_t maxidx = maxp.y * cols + maxp.x + 1; + ofs2idx(src, maxidx, maxIdx); + } + return; + } + } + } + else + { + typedef IppStatus (CV_STDCALL* ippiMinMaxIndxFuncC1)(const void *, int, IppiSize, Ipp32f *, Ipp32f *, IppiPoint *, IppiPoint *); + ippiMinMaxIndxFuncC1 ippFuncC1 = + type == CV_8UC1 ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_8u_C1R : + type == CV_16UC1 ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_16u_C1R : + type == CV_32FC1 ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_32f_C1R : + 0; + if( ippFuncC1 ) + { + Ipp32f min, max; + IppiPoint minp, maxp; + if( ippFuncC1(src.data, (int)src.step[0], sz, &min, &max, &minp, &maxp) >= 0 ) + { + if( minVal ) + *minVal = (double)min; + if( maxVal ) + *maxVal = (double)max; + if( minIdx ) + { + size_t minidx = minp.y * cols + minp.x + 1; + ofs2idx(src, minidx, minIdx); + } + if( maxIdx ) + { + size_t maxidx = maxp.y * cols + maxp.x + 1; + ofs2idx(src, maxidx, maxIdx); + } + return; + } + } + } + } +#endif + + MinMaxIdxFunc func = getMinmaxTab(depth); CV_Assert( func != 0 ); const Mat* arrays[] = {&src, &mask, 0}; @@ -999,7 +1303,6 @@ static int normHamming(const uchar* a, int n) { int i = 0, result = 0; #if CV_NEON - if (CPU_HAS_NEON_FEATURE) { uint32x4_t bits = vmovq_n_u32(0); for (; i <= n - 16; i += 16) { @@ -1013,7 +1316,6 @@ static int normHamming(const uchar* a, int n) result = vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),0); result += vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),2); } - else #endif for( ; i <= n - 4; i += 4 ) result += popCountTable[a[i]] + popCountTable[a[i+1]] + @@ -1027,7 +1329,6 @@ int normHamming(const uchar* a, const uchar* b, int n) { int i = 0, result = 0; #if CV_NEON - if (CPU_HAS_NEON_FEATURE) { uint32x4_t bits = vmovq_n_u32(0); for (; i <= n - 16; i += 16) { @@ -1043,7 +1344,6 @@ int normHamming(const uchar* a, const uchar* b, int n) result = vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),0); result += vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),2); } - else #endif for( ; i <= n - 4; i += 4 ) result += popCountTable[a[i] ^ b[i]] + popCountTable[a[i+1] ^ b[i+1]] + @@ -1111,7 +1411,7 @@ normInf_(const T* src, const uchar* mask, ST* _result, int len, int cn) if( mask[i] ) { for( int k = 0; k < cn; k++ ) - result = std::max(result, ST(fast_abs(src[k]))); + result = std::max(result, ST(std::abs(src[k]))); } } *_result = result; @@ -1132,7 +1432,7 @@ normL1_(const T* src, const uchar* mask, ST* _result, int len, int cn) if( mask[i] ) { for( int k = 0; k < cn; k++ ) - result += fast_abs(src[k]); + result += std::abs(src[k]); } } *_result = result; @@ -1254,43 +1554,53 @@ CV_DEF_NORM_ALL(64f, double, double, double, double) typedef int (*NormFunc)(const uchar*, const uchar*, uchar*, int, int); typedef int (*NormDiffFunc)(const uchar*, const uchar*, const uchar*, uchar*, int, int); -static NormFunc normTab[3][8] = +static NormFunc getNormFunc(int normType, int depth) { + static NormFunc normTab[3][8] = { - (NormFunc)GET_OPTIMIZED(normInf_8u), (NormFunc)GET_OPTIMIZED(normInf_8s), (NormFunc)GET_OPTIMIZED(normInf_16u), (NormFunc)GET_OPTIMIZED(normInf_16s), - (NormFunc)GET_OPTIMIZED(normInf_32s), (NormFunc)GET_OPTIMIZED(normInf_32f), (NormFunc)normInf_64f, 0 - }, - { - (NormFunc)GET_OPTIMIZED(normL1_8u), (NormFunc)GET_OPTIMIZED(normL1_8s), (NormFunc)GET_OPTIMIZED(normL1_16u), (NormFunc)GET_OPTIMIZED(normL1_16s), - (NormFunc)GET_OPTIMIZED(normL1_32s), (NormFunc)GET_OPTIMIZED(normL1_32f), (NormFunc)normL1_64f, 0 - }, - { - (NormFunc)GET_OPTIMIZED(normL2_8u), (NormFunc)GET_OPTIMIZED(normL2_8s), (NormFunc)GET_OPTIMIZED(normL2_16u), (NormFunc)GET_OPTIMIZED(normL2_16s), - (NormFunc)GET_OPTIMIZED(normL2_32s), (NormFunc)GET_OPTIMIZED(normL2_32f), (NormFunc)normL2_64f, 0 - } -}; + { + (NormFunc)GET_OPTIMIZED(normInf_8u), (NormFunc)GET_OPTIMIZED(normInf_8s), (NormFunc)GET_OPTIMIZED(normInf_16u), (NormFunc)GET_OPTIMIZED(normInf_16s), + (NormFunc)GET_OPTIMIZED(normInf_32s), (NormFunc)GET_OPTIMIZED(normInf_32f), (NormFunc)normInf_64f, 0 + }, + { + (NormFunc)GET_OPTIMIZED(normL1_8u), (NormFunc)GET_OPTIMIZED(normL1_8s), (NormFunc)GET_OPTIMIZED(normL1_16u), (NormFunc)GET_OPTIMIZED(normL1_16s), + (NormFunc)GET_OPTIMIZED(normL1_32s), (NormFunc)GET_OPTIMIZED(normL1_32f), (NormFunc)normL1_64f, 0 + }, + { + (NormFunc)GET_OPTIMIZED(normL2_8u), (NormFunc)GET_OPTIMIZED(normL2_8s), (NormFunc)GET_OPTIMIZED(normL2_16u), (NormFunc)GET_OPTIMIZED(normL2_16s), + (NormFunc)GET_OPTIMIZED(normL2_32s), (NormFunc)GET_OPTIMIZED(normL2_32f), (NormFunc)normL2_64f, 0 + } + }; -static NormDiffFunc normDiffTab[3][8] = + return normTab[normType][depth]; +} + +static NormDiffFunc getNormDiffFunc(int normType, int depth) { + static NormDiffFunc normDiffTab[3][8] = { - (NormDiffFunc)GET_OPTIMIZED(normDiffInf_8u), (NormDiffFunc)normDiffInf_8s, - (NormDiffFunc)normDiffInf_16u, (NormDiffFunc)normDiffInf_16s, - (NormDiffFunc)normDiffInf_32s, (NormDiffFunc)GET_OPTIMIZED(normDiffInf_32f), - (NormDiffFunc)normDiffInf_64f, 0 - }, - { - (NormDiffFunc)GET_OPTIMIZED(normDiffL1_8u), (NormDiffFunc)normDiffL1_8s, - (NormDiffFunc)normDiffL1_16u, (NormDiffFunc)normDiffL1_16s, - (NormDiffFunc)normDiffL1_32s, (NormDiffFunc)GET_OPTIMIZED(normDiffL1_32f), - (NormDiffFunc)normDiffL1_64f, 0 - }, - { - (NormDiffFunc)GET_OPTIMIZED(normDiffL2_8u), (NormDiffFunc)normDiffL2_8s, - (NormDiffFunc)normDiffL2_16u, (NormDiffFunc)normDiffL2_16s, - (NormDiffFunc)normDiffL2_32s, (NormDiffFunc)GET_OPTIMIZED(normDiffL2_32f), - (NormDiffFunc)normDiffL2_64f, 0 - } -}; + { + (NormDiffFunc)GET_OPTIMIZED(normDiffInf_8u), (NormDiffFunc)normDiffInf_8s, + (NormDiffFunc)normDiffInf_16u, (NormDiffFunc)normDiffInf_16s, + (NormDiffFunc)normDiffInf_32s, (NormDiffFunc)GET_OPTIMIZED(normDiffInf_32f), + (NormDiffFunc)normDiffInf_64f, 0 + }, + { + (NormDiffFunc)GET_OPTIMIZED(normDiffL1_8u), (NormDiffFunc)normDiffL1_8s, + (NormDiffFunc)normDiffL1_16u, (NormDiffFunc)normDiffL1_16s, + (NormDiffFunc)normDiffL1_32s, (NormDiffFunc)GET_OPTIMIZED(normDiffL1_32f), + (NormDiffFunc)normDiffL1_64f, 0 + }, + { + (NormDiffFunc)GET_OPTIMIZED(normDiffL2_8u), (NormDiffFunc)normDiffL2_8s, + (NormDiffFunc)normDiffL2_16u, (NormDiffFunc)normDiffL2_16s, + (NormDiffFunc)normDiffL2_32s, (NormDiffFunc)GET_OPTIMIZED(normDiffL2_32f), + (NormDiffFunc)normDiffL2_64f, 0 + } + }; + + return normDiffTab[normType][depth]; +} } @@ -1303,6 +1613,147 @@ double cv::norm( InputArray _src, int normType, InputArray _mask ) CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 || normType == NORM_L2SQR || ((normType == NORM_HAMMING || normType == NORM_HAMMING2) && src.type() == CV_8U) ); +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) + size_t total_size = src.total(); + int rows = src.size[0], cols = (int)(total_size/rows); + if( src.dims == 2 || (src.isContinuous() && mask.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) + && (normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 || normType == NORM_L2SQR) ) + { + IppiSize sz = { cols, rows }; + int type = src.type(); + if( !mask.empty() ) + { + typedef IppStatus (CV_STDCALL* ippiMaskNormFuncC1)(const void *, int, const void *, int, IppiSize, Ipp64f *); + ippiMaskNormFuncC1 ippFuncC1 = + normType == NORM_INF ? + (type == CV_8UC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_8u_C1MR : + type == CV_8SC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_8s_C1MR : + 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 : + type == CV_8SC1 ? (ippiMaskNormFuncC1)ippiNorm_L1_8s_C1MR : + 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 : + type == CV_8SC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_8s_C1MR : + type == CV_16UC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_16u_C1MR : + type == CV_32FC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_32f_C1MR : + 0) : 0; + if( ippFuncC1 ) + { + Ipp64f norm; + if( ippFuncC1(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, &norm) >= 0 ) + { + return normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm; + } + } + 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 : + type == CV_8SC3 ? (ippiMaskNormFuncC3)ippiNorm_Inf_8s_C3CMR : + type == CV_16UC3 ? (ippiMaskNormFuncC3)ippiNorm_Inf_16u_C3CMR : + type == CV_32FC3 ? (ippiMaskNormFuncC3)ippiNorm_Inf_32f_C3CMR : + 0) : + normType == NORM_L1 ? + (type == CV_8UC3 ? (ippiMaskNormFuncC3)ippiNorm_L1_8u_C3CMR : + type == CV_8SC3 ? (ippiMaskNormFuncC3)ippiNorm_L1_8s_C3CMR : + type == CV_16UC3 ? (ippiMaskNormFuncC3)ippiNorm_L1_16u_C3CMR : + type == CV_32FC3 ? (ippiMaskNormFuncC3)ippiNorm_L1_32f_C3CMR : + 0) : + normType == NORM_L2 || normType == NORM_L2SQR ? + (type == CV_8UC3 ? (ippiMaskNormFuncC3)ippiNorm_L2_8u_C3CMR : + type == CV_8SC3 ? (ippiMaskNormFuncC3)ippiNorm_L2_8s_C3CMR : + type == CV_16UC3 ? (ippiMaskNormFuncC3)ippiNorm_L2_16u_C3CMR : + type == CV_32FC3 ? (ippiMaskNormFuncC3)ippiNorm_L2_32f_C3CMR : + 0) : 0; + if( ippFuncC3 ) + { + Ipp64f norm1, norm2, norm3; + if( ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 1, &norm1) >= 0 && + ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 2, &norm2) >= 0 && + ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 3, &norm3) >= 0) + { + Ipp64f norm = + normType == NORM_INF ? std::max(std::max(norm1, norm2), norm3) : + normType == NORM_L1 ? norm1 + norm2 + norm3 : + normType == NORM_L2 || normType == NORM_L2SQR ? std::sqrt(norm1 * norm1 + norm2 * norm2 + norm3 * norm3) : + 0; + return normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm; + } + } + } + else + { + typedef IppStatus (CV_STDCALL* ippiNormFunc)(const void *, int, IppiSize, Ipp64f *, IppHintAlgorithm hint); + ippiNormFunc ippFunc = + normType == NORM_INF ? + (type == CV_8UC1 ? (ippiNormFunc)ippiNorm_Inf_8u_C1R : + type == CV_8UC3 ? (ippiNormFunc)ippiNorm_Inf_8u_C3R : + type == CV_8UC4 ? (ippiNormFunc)ippiNorm_Inf_8u_C4R : + type == CV_16UC1 ? (ippiNormFunc)ippiNorm_Inf_16u_C1R : + type == CV_16UC3 ? (ippiNormFunc)ippiNorm_Inf_16u_C3R : + type == CV_16UC4 ? (ippiNormFunc)ippiNorm_Inf_16u_C4R : + type == CV_16SC1 ? (ippiNormFunc)ippiNorm_Inf_16s_C1R : + //type == CV_16SC3 ? (ippiNormFunc)ippiNorm_Inf_16s_C3R : //Aug 2013: problem in IPP 7.1, 8.0 : -32768 + //type == CV_16SC4 ? (ippiNormFunc)ippiNorm_Inf_16s_C4R : //Aug 2013: problem in IPP 7.1, 8.0 : -32768 + type == CV_32FC1 ? (ippiNormFunc)ippiNorm_Inf_32f_C1R : + type == CV_32FC3 ? (ippiNormFunc)ippiNorm_Inf_32f_C3R : + type == CV_32FC4 ? (ippiNormFunc)ippiNorm_Inf_32f_C4R : + 0) : + normType == NORM_L1 ? + (type == CV_8UC1 ? (ippiNormFunc)ippiNorm_L1_8u_C1R : + type == CV_8UC3 ? (ippiNormFunc)ippiNorm_L1_8u_C3R : + type == CV_8UC4 ? (ippiNormFunc)ippiNorm_L1_8u_C4R : + type == CV_16UC1 ? (ippiNormFunc)ippiNorm_L1_16u_C1R : + type == CV_16UC3 ? (ippiNormFunc)ippiNorm_L1_16u_C3R : + type == CV_16UC4 ? (ippiNormFunc)ippiNorm_L1_16u_C4R : + type == CV_16SC1 ? (ippiNormFunc)ippiNorm_L1_16s_C1R : + type == CV_16SC3 ? (ippiNormFunc)ippiNorm_L1_16s_C3R : + type == CV_16SC4 ? (ippiNormFunc)ippiNorm_L1_16s_C4R : + type == CV_32FC1 ? (ippiNormFunc)ippiNorm_L1_32f_C1R : + type == CV_32FC3 ? (ippiNormFunc)ippiNorm_L1_32f_C3R : + type == CV_32FC4 ? (ippiNormFunc)ippiNorm_L1_32f_C4R : + 0) : + normType == NORM_L2 || normType == NORM_L2SQR ? + (type == CV_8UC1 ? (ippiNormFunc)ippiNorm_L2_8u_C1R : + type == CV_8UC3 ? (ippiNormFunc)ippiNorm_L2_8u_C3R : + type == CV_8UC4 ? (ippiNormFunc)ippiNorm_L2_8u_C4R : + type == CV_16UC1 ? (ippiNormFunc)ippiNorm_L2_16u_C1R : + type == CV_16UC3 ? (ippiNormFunc)ippiNorm_L2_16u_C3R : + type == CV_16UC4 ? (ippiNormFunc)ippiNorm_L2_16u_C4R : + type == CV_16SC1 ? (ippiNormFunc)ippiNorm_L2_16s_C1R : + type == CV_16SC3 ? (ippiNormFunc)ippiNorm_L2_16s_C3R : + type == CV_16SC4 ? (ippiNormFunc)ippiNorm_L2_16s_C4R : + type == CV_32FC1 ? (ippiNormFunc)ippiNorm_L2_32f_C1R : + type == CV_32FC3 ? (ippiNormFunc)ippiNorm_L2_32f_C3R : + type == CV_32FC4 ? (ippiNormFunc)ippiNorm_L2_32f_C4R : + 0) : 0; + if( ippFunc ) + { + Ipp64f norm_array[4]; + if( ippFunc(src.data, (int)src.step[0], sz, norm_array, ippAlgHintAccurate) >= 0 ) + { + Ipp64f norm = (normType == NORM_L2 || normType == NORM_L2SQR) ? norm_array[0] * norm_array[0] : norm_array[0]; + for( int i = 1; i < cn; i++ ) + { + norm = + normType == NORM_INF ? std::max(norm, norm_array[i]) : + normType == NORM_L1 ? norm + norm_array[i] : + normType == NORM_L2 || normType == NORM_L2SQR ? norm + norm_array[i] * norm_array[i] : + 0; + } + return normType == NORM_L2 ? (double)std::sqrt(norm) : (double)norm; + } + } + } + } +#endif + if( src.isContinuous() && mask.empty() ) { size_t len = src.total()*cn; @@ -1374,7 +1825,7 @@ double cv::norm( InputArray _src, int normType, InputArray _mask ) return result; } - NormFunc func = normTab[normType >> 1][depth]; + NormFunc func = getNormFunc(normType >> 1, depth); CV_Assert( func != 0 ); const Mat* arrays[] = {&src, &mask, 0}; @@ -1441,7 +1892,84 @@ double cv::norm( InputArray _src, int normType, InputArray _mask ) double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask ) { if( normType & CV_RELATIVE ) + { +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) + Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat(); + + CV_Assert( src1.size == src2.size && src1.type() == src2.type() ); + + normType &= 7; + CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 || normType == NORM_L2SQR || + ((normType == NORM_HAMMING || normType == NORM_HAMMING2) && src1.type() == CV_8U) ); + size_t total_size = src1.total(); + int rows = src1.size[0], cols = (int)(total_size/rows); + if( src1.dims == 2 || (src1.isContinuous() && src2.isContinuous() && mask.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) + && (normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 || normType == NORM_L2SQR) ) + { + IppiSize sz = { cols, rows }; + int type = src1.type(); + if( !mask.empty() ) + { + typedef IppStatus (CV_STDCALL* ippiMaskNormRelFuncC1)(const void *, int, const void *, int, const void *, int, IppiSize, Ipp64f *); + ippiMaskNormRelFuncC1 ippFuncC1 = + normType == NORM_INF ? + (type == CV_8UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_Inf_8u_C1MR : + type == CV_8SC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_Inf_8s_C1MR : + 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 : + type == CV_8SC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L1_8s_C1MR : + 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 : + type == CV_8SC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L2_8s_C1MR : + type == CV_16UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L2_16u_C1MR : + type == CV_32FC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L2_32f_C1MR : + 0) : 0; + if( ippFuncC1 ) + { + Ipp64f norm; + if( ippFuncC1(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, &norm) >= 0 ) + return normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm; + } + } + else + { + typedef IppStatus (CV_STDCALL* ippiNormRelFunc)(const void *, int, const void *, int, IppiSize, Ipp64f *, IppHintAlgorithm hint); + ippiNormRelFunc ippFunc = + normType == NORM_INF ? + (type == CV_8UC1 ? (ippiNormRelFunc)ippiNormRel_Inf_8u_C1R : + type == CV_16UC1 ? (ippiNormRelFunc)ippiNormRel_Inf_16u_C1R : + type == CV_16SC1 ? (ippiNormRelFunc)ippiNormRel_Inf_16s_C1R : + type == CV_32FC1 ? (ippiNormRelFunc)ippiNormRel_Inf_32f_C1R : + 0) : + normType == NORM_L1 ? + (type == CV_8UC1 ? (ippiNormRelFunc)ippiNormRel_L1_8u_C1R : + type == CV_16UC1 ? (ippiNormRelFunc)ippiNormRel_L1_16u_C1R : + type == CV_16SC1 ? (ippiNormRelFunc)ippiNormRel_L1_16s_C1R : + type == CV_32FC1 ? (ippiNormRelFunc)ippiNormRel_L1_32f_C1R : + 0) : + normType == NORM_L2 || normType == NORM_L2SQR ? + (type == CV_8UC1 ? (ippiNormRelFunc)ippiNormRel_L2_8u_C1R : + type == CV_16UC1 ? (ippiNormRelFunc)ippiNormRel_L2_16u_C1R : + type == CV_16SC1 ? (ippiNormRelFunc)ippiNormRel_L2_16s_C1R : + type == CV_32FC1 ? (ippiNormRelFunc)ippiNormRel_L2_32f_C1R : + 0) : 0; + if( ippFunc ) + { + Ipp64f norm; + if( ippFunc(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], sz, &norm, ippAlgHintAccurate) >= 0 ) + return (double)norm; + } + } + } +#endif return norm(_src1, _src2, normType & ~CV_RELATIVE, _mask)/(norm(_src2, normType, _mask) + DBL_EPSILON); + } Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat(); int depth = src1.depth(), cn = src1.channels(); @@ -1452,6 +1980,145 @@ double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _m CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 || normType == NORM_L2SQR || ((normType == NORM_HAMMING || normType == NORM_HAMMING2) && src1.type() == CV_8U) ); +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) + size_t total_size = src1.total(); + int rows = src1.size[0], cols = (int)(total_size/rows); + if( src1.dims == 2 || (src1.isContinuous() && src2.isContinuous() && mask.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) + && (normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 || normType == NORM_L2SQR) ) + { + IppiSize sz = { cols, rows }; + int type = src1.type(); + if( !mask.empty() ) + { + typedef IppStatus (CV_STDCALL* ippiMaskNormDiffFuncC1)(const void *, int, const void *, int, const void *, int, IppiSize, Ipp64f *); + ippiMaskNormDiffFuncC1 ippFuncC1 = + normType == NORM_INF ? + (type == CV_8UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_8u_C1MR : + type == CV_8SC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_8s_C1MR : + 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 : + type == CV_8SC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L1_8s_C1MR : + 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 : + type == CV_8SC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_8s_C1MR : + type == CV_16UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_16u_C1MR : + type == CV_32FC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_32f_C1MR : + 0) : 0; + if( ippFuncC1 ) + { + Ipp64f norm; + if( ippFuncC1(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, &norm) >= 0 ) + return normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm; + } + typedef IppStatus (CV_STDCALL* ippiMaskNormDiffFuncC3)(const void *, int, const void *, int, const void *, int, IppiSize, int, Ipp64f *); + ippiMaskNormDiffFuncC3 ippFuncC3 = + normType == NORM_INF ? + (type == CV_8UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_8u_C3CMR : + type == CV_8SC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_8s_C3CMR : + 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 : + type == CV_8SC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L1_8s_C3CMR : + 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 : + type == CV_8SC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_8s_C3CMR : + type == CV_16UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_16u_C3CMR : + type == CV_32FC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_32f_C3CMR : + 0) : 0; + if( ippFuncC3 ) + { + Ipp64f norm1, norm2, norm3; + if( ippFuncC3(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, 1, &norm1) >= 0 && + ippFuncC3(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, 2, &norm2) >= 0 && + ippFuncC3(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, 3, &norm3) >= 0) + { + Ipp64f norm = + normType == NORM_INF ? std::max(std::max(norm1, norm2), norm3) : + normType == NORM_L1 ? norm1 + norm2 + norm3 : + normType == NORM_L2 || normType == NORM_L2SQR ? std::sqrt(norm1 * norm1 + norm2 * norm2 + norm3 * norm3) : + 0; + return normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm; + } + } + } + else + { + typedef IppStatus (CV_STDCALL* ippiNormDiffFunc)(const void *, int, const void *, int, IppiSize, Ipp64f *, IppHintAlgorithm hint); + ippiNormDiffFunc ippFunc = + normType == NORM_INF ? + (type == CV_8UC1 ? (ippiNormDiffFunc)ippiNormDiff_Inf_8u_C1R : + type == CV_8UC3 ? (ippiNormDiffFunc)ippiNormDiff_Inf_8u_C3R : + type == CV_8UC4 ? (ippiNormDiffFunc)ippiNormDiff_Inf_8u_C4R : + type == CV_16UC1 ? (ippiNormDiffFunc)ippiNormDiff_Inf_16u_C1R : + type == CV_16UC3 ? (ippiNormDiffFunc)ippiNormDiff_Inf_16u_C3R : + type == CV_16UC4 ? (ippiNormDiffFunc)ippiNormDiff_Inf_16u_C4R : + type == CV_16SC1 ? (ippiNormDiffFunc)ippiNormDiff_Inf_16s_C1R : + //type == CV_16SC3 ? (ippiNormDiffFunc)ippiNormDiff_Inf_16s_C3R : //Aug 2013: problem in IPP 7.1, 8.0 : -32768 + //type == CV_16SC4 ? (ippiNormDiffFunc)ippiNormDiff_Inf_16s_C4R : //Aug 2013: problem in IPP 7.1, 8.0 : -32768 + type == CV_32FC1 ? (ippiNormDiffFunc)ippiNormDiff_Inf_32f_C1R : + type == CV_32FC3 ? (ippiNormDiffFunc)ippiNormDiff_Inf_32f_C3R : + type == CV_32FC4 ? (ippiNormDiffFunc)ippiNormDiff_Inf_32f_C4R : + 0) : + normType == NORM_L1 ? + (type == CV_8UC1 ? (ippiNormDiffFunc)ippiNormDiff_L1_8u_C1R : + type == CV_8UC3 ? (ippiNormDiffFunc)ippiNormDiff_L1_8u_C3R : + type == CV_8UC4 ? (ippiNormDiffFunc)ippiNormDiff_L1_8u_C4R : + type == CV_16UC1 ? (ippiNormDiffFunc)ippiNormDiff_L1_16u_C1R : + type == CV_16UC3 ? (ippiNormDiffFunc)ippiNormDiff_L1_16u_C3R : + type == CV_16UC4 ? (ippiNormDiffFunc)ippiNormDiff_L1_16u_C4R : + type == CV_16SC1 ? (ippiNormDiffFunc)ippiNormDiff_L1_16s_C1R : + type == CV_16SC3 ? (ippiNormDiffFunc)ippiNormDiff_L1_16s_C3R : + type == CV_16SC4 ? (ippiNormDiffFunc)ippiNormDiff_L1_16s_C4R : + type == CV_32FC1 ? (ippiNormDiffFunc)ippiNormDiff_L1_32f_C1R : + type == CV_32FC3 ? (ippiNormDiffFunc)ippiNormDiff_L1_32f_C3R : + type == CV_32FC4 ? (ippiNormDiffFunc)ippiNormDiff_L1_32f_C4R : + 0) : + normType == NORM_L2 || normType == NORM_L2SQR ? + (type == CV_8UC1 ? (ippiNormDiffFunc)ippiNormDiff_L2_8u_C1R : + type == CV_8UC3 ? (ippiNormDiffFunc)ippiNormDiff_L2_8u_C3R : + type == CV_8UC4 ? (ippiNormDiffFunc)ippiNormDiff_L2_8u_C4R : + type == CV_16UC1 ? (ippiNormDiffFunc)ippiNormDiff_L2_16u_C1R : + type == CV_16UC3 ? (ippiNormDiffFunc)ippiNormDiff_L2_16u_C3R : + type == CV_16UC4 ? (ippiNormDiffFunc)ippiNormDiff_L2_16u_C4R : + type == CV_16SC1 ? (ippiNormDiffFunc)ippiNormDiff_L2_16s_C1R : + type == CV_16SC3 ? (ippiNormDiffFunc)ippiNormDiff_L2_16s_C3R : + type == CV_16SC4 ? (ippiNormDiffFunc)ippiNormDiff_L2_16s_C4R : + type == CV_32FC1 ? (ippiNormDiffFunc)ippiNormDiff_L2_32f_C1R : + type == CV_32FC3 ? (ippiNormDiffFunc)ippiNormDiff_L2_32f_C3R : + type == CV_32FC4 ? (ippiNormDiffFunc)ippiNormDiff_L2_32f_C4R : + 0) : 0; + if( ippFunc ) + { + Ipp64f norm_array[4]; + if( ippFunc(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], sz, norm_array, ippAlgHintAccurate) >= 0 ) + { + Ipp64f norm = (normType == NORM_L2 || normType == NORM_L2SQR) ? norm_array[0] * norm_array[0] : norm_array[0]; + for( int i = 1; i < src1.channels(); i++ ) + { + norm = + normType == NORM_INF ? std::max(norm, norm_array[i]) : + normType == NORM_L1 ? norm + norm_array[i] : + normType == NORM_L2 || normType == NORM_L2SQR ? norm + norm_array[i] * norm_array[i] : + 0; + } + return normType == NORM_L2 ? (double)std::sqrt(norm) : (double)norm; + } + } + } + } +#endif + if( src1.isContinuous() && src2.isContinuous() && mask.empty() ) { size_t len = src1.total()*src1.channels(); @@ -1515,7 +2182,7 @@ double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _m return result; } - NormDiffFunc func = normDiffTab[normType >> 1][depth]; + NormDiffFunc func = getNormDiffFunc(normType >> 1, depth); CV_Assert( func != 0 ); const Mat* arrays[] = {&src1, &src2, &mask, 0}; @@ -1925,6 +2592,14 @@ void cv::findNonZero( InputArray _src, OutputArray _idx ) } } +double cv::PSNR(InputArray _src1, InputArray _src2) +{ + Mat src1 = _src1.getMat(), src2 = _src2.getMat(); + CV_Assert( src1.depth() == CV_8U ); + double diff = std::sqrt(norm(src1, src2, NORM_L2SQR)/(src1.total()*src1.channels())); + return 20*log10(255./(diff+DBL_EPSILON)); +} + CV_IMPL CvScalar cvSum( const CvArr* srcarr ) { diff --git a/modules/gpu/src/cu_safe_call.h b/modules/core/src/stl.cpp similarity index 79% rename from modules/gpu/src/cu_safe_call.h rename to modules/core/src/stl.cpp index 6f93adc760..f03c1a2d79 100644 --- a/modules/gpu/src/cu_safe_call.h +++ b/modules/core/src/stl.cpp @@ -12,6 +12,7 @@ // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -40,28 +41,29 @@ // //M*/ -#ifndef __CU_SAFE_CALL_H__ -#define __CU_SAFE_CALL_H__ #include "precomp.hpp" -#ifdef HAVE_CUDA +char* cv::String::allocate(size_t len) +{ + size_t totalsize = alignSize(len + 1, (int)sizeof(int)); + int* data = (int*)cv::fastMalloc(totalsize + sizeof(int)); + data[0] = 1; + cstr_ = (char*)(data + 1); + len_ = len; + cstr_[len] = 0; + return cstr_; +} -namespace cv { namespace gpu { - namespace detail + +void cv::String::deallocate() +{ + int* data = (int*)cstr_; + len_ = 0; + cstr_ = 0; + + if(data && 1 == CV_XADD(data-1, -1)) { - std::string cuGetErrString(CUresult res); - - inline void cuSafeCall_impl(CUresult res, const char* file, int line) - { - if (res != CUDA_SUCCESS) - cv::error( cv::Exception(CV_GpuApiCallError, cuGetErrString(res), "unknown function", file, line) ); - } + cv::fastFree(data-1); } -}} - -#define cuSafeCall( op ) cv::gpu::detail::cuSafeCall_impl( (op), __FILE__, __LINE__ ) - -#endif // HAVE_CUDA - -#endif // __CU_SAFE_CALL_H__ +} diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index 668b868b32..738e863d76 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -42,11 +42,20 @@ #include "precomp.hpp" +#ifdef _MSC_VER +# if _MSC_VER >= 1700 +# pragma warning(disable:4447) // Disable warning 'main' signature found without threading model +# endif +#endif + #if defined WIN32 || defined _WIN32 || defined WINCE #ifndef _WIN32_WINNT // This is needed for the declaration of TryEnterCriticalSection in winbase.h with Visual Studio 2005 (and older?) #define _WIN32_WINNT 0x0400 // http://msdn.microsoft.com/en-us/library/ms686857(VS.85).aspx #endif #include +#if (_WIN32_WINNT >= 0x0602) + #include +#endif #undef small #undef min #undef max @@ -75,6 +84,30 @@ } #endif #endif + +#ifdef HAVE_WINRT +#include + +std::wstring GetTempPathWinRT() +{ + return std::wstring(Windows::Storage::ApplicationData::Current->TemporaryFolder->Path->Data()); +} + +std::wstring GetTempFileNameWinRT(std::wstring prefix) +{ + wchar_t guidStr[40]; + GUID g; + CoCreateGuid(&g); + wchar_t* mask = L"%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x"; + swprintf(&guidStr[0], sizeof(guidStr)/sizeof(wchar_t), mask, + g.Data1, g.Data2, g.Data3, UINT(g.Data4[0]), UINT(g.Data4[1]), + UINT(g.Data4[2]), UINT(g.Data4[3]), UINT(g.Data4[4]), + UINT(g.Data4[5]), UINT(g.Data4[6]), UINT(g.Data4[7])); + + return prefix + std::wstring(guidStr); +} + +#endif #else #include #include @@ -113,7 +146,7 @@ namespace cv Exception::Exception() { code = 0; line = 0; } -Exception::Exception(int _code, const std::string& _err, const std::string& _func, const std::string& _file, int _line) +Exception::Exception(int _code, const String& _err, const String& _func, const String& _file, int _line) : code(_code), err(_err), func(_func), file(_file), line(_line) { formatMessage(); @@ -340,31 +373,70 @@ int64 getCPUTickCount(void) #endif -const std::string& getBuildInformation() +const String& getBuildInformation() { - static std::string build_info = + static String build_info = #include "version_string.inc" ; return build_info; } -std::string format( const char* fmt, ... ) +String format( const char* fmt, ... ) { - char buf[1 << 16]; - va_list args; - va_start( args, fmt ); - vsprintf( buf, fmt, args ); - return std::string(buf); + char buf[1024]; + + va_list va; + va_start(va, fmt); + int len = vsnprintf(buf, sizeof(buf), fmt, va); + va_end(va); + + if (len >= (int)sizeof(buf)) + { + String s(len, '\0'); + va_start(va, fmt); + len = vsnprintf((char*)s.c_str(), len + 1, fmt, va); + va_end(va); + return s; + } + + return String(buf, len); } -std::string tempfile( const char* suffix ) +String tempfile( const char* suffix ) { +#ifdef HAVE_WINRT + std::wstring temp_dir = L""; + const wchar_t* opencv_temp_dir = _wgetenv(L"OPENCV_TEMP_PATH"); + if (opencv_temp_dir) + temp_dir = std::wstring(opencv_temp_dir); +#else const char *temp_dir = getenv("OPENCV_TEMP_PATH"); - std::string fname; + String fname; +#endif #if defined WIN32 || defined _WIN32 - char temp_dir2[MAX_PATH + 1] = { 0 }; - char temp_file[MAX_PATH + 1] = { 0 }; +#ifdef HAVE_WINRT + RoInitialize(RO_INIT_MULTITHREADED); + std::wstring temp_dir2; + if (temp_dir.empty()) + temp_dir = GetTempPathWinRT(); + + std::wstring temp_file; + temp_file = GetTempFileNameWinRT(L"ocv"); + if (temp_file.empty()) + return std::string(); + + temp_file = temp_dir + std::wstring(L"\\") + temp_file; + DeleteFileW(temp_file.c_str()); + + char aname[MAX_PATH]; + size_t copied = wcstombs(aname, temp_file.c_str(), MAX_PATH); + CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1)); + fname = std::string(aname); + RoUninitialize(); +#else + char temp_dir2[MAX_PATH] = { 0 }; + char temp_file[MAX_PATH] = { 0 }; if (temp_dir == 0 || temp_dir[0] == 0) { @@ -372,11 +444,12 @@ std::string tempfile( const char* suffix ) temp_dir = temp_dir2; } if(0 == ::GetTempFileNameA(temp_dir, "ocv", 0, temp_file)) - return std::string(); + return String(); DeleteFileA(temp_file); fname = temp_file; +#endif # else # ifdef ANDROID //char defaultTemplate[] = "/mnt/sdcard/__opencv_temp.XXXXXX"; @@ -392,12 +465,12 @@ std::string tempfile( const char* suffix ) fname = temp_dir; char ech = fname[fname.size() - 1]; if(ech != '/' && ech != '\\') - fname += "/"; - fname += "__opencv_temp.XXXXXX"; + fname = fname + "/"; + fname = fname + "__opencv_temp.XXXXXX"; } const int fd = mkstemp((char*)fname.c_str()); - if (fd == -1) return std::string(); + if (fd == -1) return String(); close(fd); remove(fname.c_str()); @@ -453,6 +526,11 @@ void error( const Exception& exc ) throw exc; } +void error(int _code, const String& _err, const char* _func, const char* _file, int _line) +{ + error(cv::Exception(_code, _err, _func, _file, _line)); +} + CvErrorCallback redirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata) { @@ -469,40 +547,6 @@ redirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata) } -/*CV_IMPL int -cvGuiBoxReport( int code, const char *func_name, const char *err_msg, - const char *file, int line, void* ) -{ -#if (!defined WIN32 && !defined _WIN32) || defined WINCE - return cvStdErrReport( code, func_name, err_msg, file, line, 0 ); -#else - if( code != CV_StsBackTrace && code != CV_StsAutoTrace ) - { - size_t msg_len = strlen(err_msg ? err_msg : "") + 1024; - char* message = (char*)alloca(msg_len); - char title[100]; - - wsprintf( message, "%s (%s)\nin function %s, %s(%d)\n\n" - "Press \"Abort\" to terminate application.\n" - "Press \"Retry\" to debug (if the app is running under debugger).\n" - "Press \"Ignore\" to continue (this is not safe).\n", - cvErrorStr(code), err_msg ? err_msg : "no description", - func_name, file, line ); - - wsprintf( title, "OpenCV GUI Error Handler" ); - - int answer = MessageBox( NULL, message, title, MB_ICONERROR|MB_ABORTRETRYIGNORE|MB_SYSTEMMODAL ); - - if( answer == IDRETRY ) - { - CV_DBG_BREAK(); - } - return answer != IDIGNORE; - } - return 0; -#endif -}*/ - CV_IMPL int cvCheckHardwareSupport(int feature) { CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE ); @@ -659,127 +703,12 @@ cvErrorFromIppStatus( int status ) } } -static CvModuleInfo cxcore_info = { 0, "cxcore", CV_VERSION, 0 }; -CvModuleInfo* CvModule::first = 0, *CvModule::last = 0; +#if defined CVAPI_EXPORTS && defined WIN32 && !defined WINCE +#ifdef HAVE_WINRT + #pragma warning(disable:4447) // Disable warning 'main' signature found without threading model +#endif -CvModule::CvModule( CvModuleInfo* _info ) -{ - cvRegisterModule( _info ); - info = last; -} - -CvModule::~CvModule(void) -{ - if( info ) - { - CvModuleInfo* p = first; - for( ; p != 0 && p->next != info; p = p->next ) - ; - - if( p ) - p->next = info->next; - - if( first == info ) - first = info->next; - - if( last == info ) - last = p; - - free( info ); - info = 0; - } -} - -CV_IMPL int -cvRegisterModule( const CvModuleInfo* module ) -{ - CV_Assert( module != 0 && module->name != 0 && module->version != 0 ); - - size_t name_len = strlen(module->name); - size_t version_len = strlen(module->version); - - CvModuleInfo* module_copy = (CvModuleInfo*)malloc( sizeof(*module_copy) + - name_len + 1 + version_len + 1 ); - - *module_copy = *module; - module_copy->name = (char*)(module_copy + 1); - module_copy->version = (char*)(module_copy + 1) + name_len + 1; - - memcpy( (void*)module_copy->name, module->name, name_len + 1 ); - memcpy( (void*)module_copy->version, module->version, version_len + 1 ); - module_copy->next = 0; - - if( CvModule::first == 0 ) - CvModule::first = module_copy; - else - CvModule::last->next = module_copy; - - CvModule::last = module_copy; - - return 0; -} - -CvModule cxcore_module( &cxcore_info ); - -CV_IMPL void -cvGetModuleInfo( const char* name, const char **version, const char **plugin_list ) -{ - static char joint_verinfo[1024] = ""; - static char plugin_list_buf[1024] = ""; - - if( version ) - *version = 0; - - if( plugin_list ) - *plugin_list = 0; - - CvModuleInfo* module; - - if( version ) - { - if( name ) - { - size_t i, name_len = strlen(name); - - for( module = CvModule::first; module != 0; module = module->next ) - { - if( strlen(module->name) == name_len ) - { - for( i = 0; i < name_len; i++ ) - { - int c0 = toupper(module->name[i]), c1 = toupper(name[i]); - if( c0 != c1 ) - break; - } - if( i == name_len ) - break; - } - } - if( !module ) - CV_Error( CV_StsObjectNotFound, "The module is not found" ); - - *version = module->version; - } - else - { - char* ptr = joint_verinfo; - - for( module = CvModule::first; module != 0; module = module->next ) - { - sprintf( ptr, "%s: %s%s", module->name, module->version, module->next ? ", " : "" ); - ptr += strlen(ptr); - } - - *version = joint_verinfo; - } - } - - if( plugin_list ) - *plugin_list = plugin_list_buf; -} - -#if defined BUILD_SHARED_LIBS && defined CVAPI_EXPORTS && defined WIN32 && !defined WINCE BOOL WINAPI DllMain( HINSTANCE, DWORD fdwReason, LPVOID ); BOOL WINAPI DllMain( HINSTANCE, DWORD fdwReason, LPVOID ) @@ -800,7 +729,15 @@ namespace cv struct Mutex::Impl { - Impl() { InitializeCriticalSection(&cs); refcount = 1; } + Impl() + { +#if (_WIN32_WINNT >= 0x0600) + ::InitializeCriticalSectionEx(&cs, 1000, 0); +#else + ::InitializeCriticalSection(&cs); +#endif + refcount = 1; + } ~Impl() { DeleteCriticalSection(&cs); } void lock() { EnterCriticalSection(&cs); } @@ -893,4 +830,4 @@ bool Mutex::trylock() { return impl->trylock(); } } -/* End of file. */ \ No newline at end of file +/* End of file. */ diff --git a/modules/core/src/types.cpp b/modules/core/src/types.cpp new file mode 100644 index 0000000000..89e0042657 --- /dev/null +++ b/modules/core/src/types.cpp @@ -0,0 +1,139 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "precomp.hpp" + +namespace cv +{ + +size_t KeyPoint::hash() const +{ + size_t _Val = 2166136261U, scale = 16777619U; + Cv32suf u; + u.f = pt.x; _Val = (scale * _Val) ^ u.u; + u.f = pt.y; _Val = (scale * _Val) ^ u.u; + u.f = size; _Val = (scale * _Val) ^ u.u; + u.f = angle; _Val = (scale * _Val) ^ u.u; + u.f = response; _Val = (scale * _Val) ^ u.u; + _Val = (scale * _Val) ^ ((size_t) octave); + _Val = (scale * _Val) ^ ((size_t) class_id); + return _Val; +} + +void KeyPoint::convert(const std::vector& keypoints, std::vector& points2f, + const std::vector& keypointIndexes) +{ + if( keypointIndexes.empty() ) + { + points2f.resize( keypoints.size() ); + for( size_t i = 0; i < keypoints.size(); i++ ) + points2f[i] = keypoints[i].pt; + } + else + { + points2f.resize( keypointIndexes.size() ); + for( size_t i = 0; i < keypointIndexes.size(); i++ ) + { + int idx = keypointIndexes[i]; + if( idx >= 0 ) + points2f[i] = keypoints[idx].pt; + else + { + CV_Error( CV_StsBadArg, "keypointIndexes has element < 0. TODO: process this case" ); + //points2f[i] = Point2f(-1, -1); + } + } + } +} + +void KeyPoint::convert( const std::vector& points2f, std::vector& keypoints, + float size, float response, int octave, int class_id ) +{ + keypoints.resize(points2f.size()); + for( size_t i = 0; i < points2f.size(); i++ ) + keypoints[i] = KeyPoint(points2f[i], size, -1, response, octave, class_id); +} + +float KeyPoint::overlap( const KeyPoint& kp1, const KeyPoint& kp2 ) +{ + float a = kp1.size * 0.5f; + float b = kp2.size * 0.5f; + float a_2 = a * a; + float b_2 = b * b; + + Point2f p1 = kp1.pt; + Point2f p2 = kp2.pt; + float c = (float)norm( p1 - p2 ); + + float ovrl = 0.f; + + // one circle is completely encovered by the other => no intersection points! + if( std::min( a, b ) + c <= std::max( a, b ) ) + return std::min( a_2, b_2 ) / std::max( a_2, b_2 ); + + if( c < a + b ) // circles intersect + { + float c_2 = c * c; + float cosAlpha = ( b_2 + c_2 - a_2 ) / ( kp2.size * c ); + float cosBeta = ( a_2 + c_2 - b_2 ) / ( kp1.size * c ); + float alpha = acos( cosAlpha ); + float beta = acos( cosBeta ); + float sinAlpha = sin(alpha); + float sinBeta = sin(beta); + + float segmentAreaA = a_2 * beta; + float segmentAreaB = b_2 * alpha; + + float triangleAreaA = a_2 * sinBeta * cosBeta; + float triangleAreaB = b_2 * sinAlpha * cosAlpha; + + float intersectionArea = segmentAreaA + segmentAreaB - triangleAreaA - triangleAreaB; + float unionArea = (a_2 + b_2) * (float)CV_PI - intersectionArea; + + ovrl = intersectionArea / unionArea; + } + + return ovrl; +} + +} // cv diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index ebc9eae640..7486e134a7 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -35,7 +35,7 @@ struct BaseElemWiseOp virtual int getRandomType(RNG& rng) { - return cvtest::randomType(rng, DEPTH_MASK_ALL_BUT_8S, 1, + return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_BUT_8S, 1, ninputs > 1 ? ARITHM_MAX_CHANNELS : 4); } @@ -425,7 +425,7 @@ struct CmpOp : public BaseElemWiseOp } int getRandomType(RNG& rng) { - return cvtest::randomType(rng, DEPTH_MASK_ALL_BUT_8S, 1, 1); + return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_BUT_8S, 1, 1); } double getMaxErr(int) @@ -455,7 +455,7 @@ struct CmpSOp : public BaseElemWiseOp } int getRandomType(RNG& rng) { - return cvtest::randomType(rng, DEPTH_MASK_ALL_BUT_8S, 1, 1); + return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_BUT_8S, 1, 1); } double getMaxErr(int) { @@ -478,7 +478,7 @@ struct CopyOp : public BaseElemWiseOp } int getRandomType(RNG& rng) { - return cvtest::randomType(rng, DEPTH_MASK_ALL, 1, ARITHM_MAX_CHANNELS); + return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL, 1, ARITHM_MAX_CHANNELS); } double getMaxErr(int) { @@ -501,7 +501,7 @@ struct SetOp : public BaseElemWiseOp } int getRandomType(RNG& rng) { - return cvtest::randomType(rng, DEPTH_MASK_ALL, 1, ARITHM_MAX_CHANNELS); + return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL, 1, ARITHM_MAX_CHANNELS); } double getMaxErr(int) { @@ -718,8 +718,8 @@ struct ConvertScaleOp : public BaseElemWiseOp } int getRandomType(RNG& rng) { - int srctype = cvtest::randomType(rng, DEPTH_MASK_ALL, 1, ARITHM_MAX_CHANNELS); - ddepth = cvtest::randomType(rng, DEPTH_MASK_ALL, 1, 1); + int srctype = cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL, 1, ARITHM_MAX_CHANNELS); + ddepth = cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL, 1, 1); return srctype; } double getMaxErr(int) @@ -957,7 +957,7 @@ struct ExpOp : public BaseElemWiseOp ExpOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}; int getRandomType(RNG& rng) { - return cvtest::randomType(rng, DEPTH_MASK_FLT, 1, ARITHM_MAX_CHANNELS); + return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_FLT, 1, ARITHM_MAX_CHANNELS); } void getValueRange(int depth, double& minval, double& maxval) { @@ -984,7 +984,7 @@ struct LogOp : public BaseElemWiseOp LogOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}; int getRandomType(RNG& rng) { - return cvtest::randomType(rng, DEPTH_MASK_FLT, 1, ARITHM_MAX_CHANNELS); + return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_FLT, 1, ARITHM_MAX_CHANNELS); } void getValueRange(int depth, double& minval, double& maxval) { @@ -1070,7 +1070,7 @@ struct CartToPolarToCartOp : public BaseElemWiseOp } int getRandomType(RNG& rng) { - return cvtest::randomType(rng, DEPTH_MASK_FLT, 1, 1); + return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_FLT, 1, 1); } void op(const vector& src, Mat& dst, const Mat&) { @@ -1123,7 +1123,7 @@ struct MeanOp : public BaseElemWiseOp } double getMaxErr(int) { - return 1e-6; + return 1e-5; } }; @@ -1157,7 +1157,7 @@ struct CountNonZeroOp : public BaseElemWiseOp {} int getRandomType(RNG& rng) { - return cvtest::randomType(rng, DEPTH_MASK_ALL, 1, 1); + return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL, 1, 1); } void op(const vector& src, Mat& dst, const Mat& mask) { @@ -1237,7 +1237,7 @@ struct NormOp : public BaseElemWiseOp }; int getRandomType(RNG& rng) { - int type = cvtest::randomType(rng, DEPTH_MASK_ALL_BUT_8S, 1, 4); + int type = cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_BUT_8S, 1, 4); for(;;) { normType = rng.uniform(1, 8); @@ -1283,7 +1283,7 @@ struct MinMaxLocOp : public BaseElemWiseOp }; int getRandomType(RNG& rng) { - return cvtest::randomType(rng, DEPTH_MASK_ALL_BUT_8S, 1, 1); + return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_BUT_8S, 1, 1); } void saveOutput(const vector& minidx, const vector& maxidx, double minval, double maxval, Mat& dst) @@ -1551,3 +1551,16 @@ TEST(Core_Add, AddToColumnWhen4Rows) ASSERT_EQ(0, countNonZero(m1 - m2)); } + +TEST(Core_round, CvRound) +{ + ASSERT_EQ(2, cvRound(2.0)); + ASSERT_EQ(2, cvRound(2.1)); + ASSERT_EQ(-2, cvRound(-2.1)); + ASSERT_EQ(3, cvRound(2.8)); + ASSERT_EQ(-3, cvRound(-2.8)); + ASSERT_EQ(2, cvRound(2.5)); + ASSERT_EQ(4, cvRound(3.5)); + ASSERT_EQ(-2, cvRound(-2.5)); + ASSERT_EQ(-4, cvRound(-3.5)); +} diff --git a/modules/core/test/test_ds.cpp b/modules/core/test/test_ds.cpp index d79786054a..c71deed06f 100644 --- a/modules/core/test/test_ds.cpp +++ b/modules/core/test/test_ds.cpp @@ -358,8 +358,6 @@ Core_DynStructBaseTest::Core_DynStructBaseTest() iterations = max_struct_size*2; gen = struct_idx = iter = -1; test_progress = -1; - - storage = 0; } @@ -999,7 +997,7 @@ void Core_SeqBaseTest::run( int ) { t = cvtest::randReal(rng)*(max_log_storage_block_size - min_log_storage_block_size) + min_log_storage_block_size; - storage = cvCreateMemStorage( cvRound( exp(t * CV_LOG2) ) ); + storage.reset(cvCreateMemStorage( cvRound( exp(t * CV_LOG2) ) )); } iter = struct_idx = -1; @@ -1083,11 +1081,11 @@ void Core_SeqSortInvTest::run( int ) { struct_idx = iter = -1; - if( storage.empty() ) + if( !storage ) { t = cvtest::randReal(rng)*(max_log_storage_block_size - min_log_storage_block_size) + min_log_storage_block_size; - storage = cvCreateMemStorage( cvRound( exp(t * CV_LOG2) ) ); + storage.reset(cvCreateMemStorage( cvRound( exp(t * CV_LOG2) ) )); } for( iter = 0; iter < iterations/10; iter++ ) @@ -1384,7 +1382,7 @@ void Core_SetTest::run( int ) { struct_idx = iter = -1; t = cvtest::randReal(rng)*(max_log_storage_block_size - min_log_storage_block_size) + min_log_storage_block_size; - storage = cvCreateMemStorage( cvRound( exp(t * CV_LOG2) ) ); + storage.reset(cvCreateMemStorage( cvRound( exp(t * CV_LOG2) ) )); for( int i = 0; i < struct_count; i++ ) { @@ -1398,7 +1396,7 @@ void Core_SetTest::run( int ) cvTsReleaseSimpleSet( (CvTsSimpleSet**)&simple_struct[i] ); simple_struct[i] = cvTsCreateSimpleSet( max_struct_size, pure_elem_size ); - cxcore_struct[i] = cvCreateSet( 0, sizeof(CvSet), elem_size, storage ); + cxcore_struct[i] = cvCreateSet( 0, sizeof(CvSet), elem_size, storage ); } if( test_set_ops( iterations*100 ) < 0 ) @@ -1811,7 +1809,7 @@ void Core_GraphTest::run( int ) int block_size = cvRound( exp(t * CV_LOG2) ); block_size = MAX(block_size, (int)(sizeof(CvGraph) + sizeof(CvMemBlock) + sizeof(CvSeqBlock))); - storage = cvCreateMemStorage(block_size); + storage.reset(cvCreateMemStorage(block_size)); for( i = 0; i < struct_count; i++ ) { @@ -1929,7 +1927,7 @@ void Core_GraphScanTest::run( int ) storage_blocksize = MAX(storage_blocksize, (int)(sizeof(CvGraph) + sizeof(CvMemBlock) + sizeof(CvSeqBlock))); storage_blocksize = MAX(storage_blocksize, (int)(sizeof(CvGraphEdge) + sizeof(CvMemBlock) + sizeof(CvSeqBlock))); storage_blocksize = MAX(storage_blocksize, (int)(sizeof(CvGraphVtx) + sizeof(CvMemBlock) + sizeof(CvSeqBlock))); - storage = cvCreateMemStorage(storage_blocksize); + storage.reset(cvCreateMemStorage(storage_blocksize)); if( gen == 0 ) { @@ -2118,5 +2116,3 @@ TEST(Core_DS_Seq, sort_invert) { Core_SeqSortInvTest test; test.safe_run(); } TEST(Core_DS_Set, basic_operations) { Core_SetTest test; test.safe_run(); } TEST(Core_DS_Graph, basic_operations) { Core_GraphTest test; test.safe_run(); } TEST(Core_DS_Graph, scan) { Core_GraphScanTest test; test.safe_run(); } - - diff --git a/modules/core/test/test_dxt.cpp b/modules/core/test/test_dxt.cpp index 16025fa8f2..1c0c7b00bf 100644 --- a/modules/core/test/test_dxt.cpp +++ b/modules/core/test/test_dxt.cpp @@ -866,5 +866,3 @@ protected: }; TEST(Core_DFT, complex_output) { Core_DFTComplexOutputTest test; test.safe_run(); } - - diff --git a/modules/core/test/test_eigen.cpp b/modules/core/test/test_eigen.cpp index 046573d26d..21859e59b8 100644 --- a/modules/core/test/test_eigen.cpp +++ b/modules/core/test/test_eigen.cpp @@ -294,7 +294,7 @@ bool Core_EigenTest::test_pairs(const cv::Mat& src) cv::Mat eigen_values, eigen_vectors; - cv::eigen(src, true, eigen_values, eigen_vectors); + cv::eigen(src, eigen_values, eigen_vectors); if (!check_pair_count(src, eigen_values, eigen_vectors)) return false; @@ -362,8 +362,8 @@ bool Core_EigenTest::test_values(const cv::Mat& src) if (!test_pairs(src)) return false; - cv::eigen(src, true, eigen_values_1, eigen_vectors); - cv::eigen(src, false, eigen_values_2, eigen_vectors); + cv::eigen(src, eigen_values_1, eigen_vectors); + cv::eigen(src, eigen_values_2); if (!check_pair_count(src, eigen_values_2)) return false; diff --git a/modules/core/test/test_io.cpp b/modules/core/test/test_io.cpp index 7d4e7d9398..ba66567615 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -191,7 +191,7 @@ protected: int real_int = (int)fs["test_int"]; double real_real = (double)fs["test_real"]; - string real_string = (string)fs["test_string"]; + String real_string = (String)fs["test_string"]; if( real_int != test_int || fabs(real_real - test_real) > DBL_EPSILON*(fabs(test_real)+1) || @@ -211,7 +211,7 @@ protected: vector pt; if( !m || !CV_IS_MAT(m) || m->rows != test_mat.rows || m->cols != test_mat.cols || - cvtest::cmpEps( Mat(&stub1), Mat(&_test_stub1), &max_diff, 0, &pt, true) < 0 ) + cvtest::cmpEps( cv::cvarrToMat(&stub1), cv::cvarrToMat(&_test_stub1), &max_diff, 0, &pt, true) < 0 ) { ts->printf( cvtest::TS::LOG, "the read matrix is not correct: (%.20g vs %.20g) at (%d,%d)\n", cvGetReal2D(&stub1, pt[0], pt[1]), cvGetReal2D(&_test_stub1, pt[0], pt[1]), @@ -241,7 +241,7 @@ protected: if( !CV_ARE_TYPES_EQ(&stub, &_test_stub) || !CV_ARE_SIZES_EQ(&stub, &_test_stub) || //cvNorm(&stub, &_test_stub, CV_L2) != 0 ) - cvtest::cmpEps( Mat(&stub1), Mat(&_test_stub1), &max_diff, 0, &pt, true) < 0 ) + cvtest::cmpEps( cv::cvarrToMat(&stub1), cv::cvarrToMat(&_test_stub1), &max_diff, 0, &pt, true) < 0 ) { ts->printf( cvtest::TS::LOG, "readObj method: the read nd matrix is not correct: (%.20g vs %.20g) vs at (%d,%d)\n", cvGetReal2D(&stub1, pt[0], pt[1]), cvGetReal2D(&_test_stub1, pt[0], pt[1]), @@ -259,7 +259,7 @@ protected: if( !CV_ARE_TYPES_EQ(&stub, &_test_stub) || !CV_ARE_SIZES_EQ(&stub, &_test_stub) || //cvNorm(&stub, &_test_stub, CV_L2) != 0 ) - cvtest::cmpEps( Mat(&stub1), Mat(&_test_stub1), &max_diff, 0, &pt, true) < 0 ) + cvtest::cmpEps( cv::cvarrToMat(&stub1), cv::cvarrToMat(&_test_stub1), &max_diff, 0, &pt, true) < 0 ) { ts->printf( cvtest::TS::LOG, "C++ method: the read nd matrix is not correct: (%.20g vs %.20g) vs at (%d,%d)\n", cvGetReal2D(&stub1, pt[0], pt[1]), cvGetReal2D(&_test_stub1, pt[1], pt[0]), @@ -270,16 +270,16 @@ protected: cvRelease((void**)&m_nd); - Ptr m_s = (CvSparseMat*)fs["test_sparse_mat"].readObj(); - Ptr _test_sparse_ = (CvSparseMat*)test_sparse_mat; - Ptr _test_sparse = (CvSparseMat*)cvClone(_test_sparse_); + Ptr m_s((CvSparseMat*)fs["test_sparse_mat"].readObj()); + Ptr _test_sparse_(cvCreateSparseMat(test_sparse_mat)); + Ptr _test_sparse((CvSparseMat*)cvClone(_test_sparse_)); SparseMat m_s2; fs["test_sparse_mat"] >> m_s2; - Ptr _m_s2 = (CvSparseMat*)m_s2; + Ptr _m_s2(cvCreateSparseMat(m_s2)); if( !m_s || !CV_IS_SPARSE_MAT(m_s) || - !cvTsCheckSparse(m_s, _test_sparse,0) || - !cvTsCheckSparse(_m_s2, _test_sparse,0)) + !cvTsCheckSparse(m_s, _test_sparse, 0) || + !cvTsCheckSparse(_m_s2, _test_sparse, 0)) { ts->printf( cvtest::TS::LOG, "the read sparse matrix is not correct\n" ); ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); @@ -292,7 +292,7 @@ protected: (int)tl[1] != 2 || fabs((double)tl[2] - CV_PI) >= DBL_EPSILON || (int)tl[3] != -3435345 || - (string)tl[4] != "2-502 2-029 3egegeg" || + (String)tl[4] != "2-502 2-029 3egegeg" || tl[5].type() != FileNode::MAP || tl[5].size() != 3 || (int)tl[5]["month"] != 12 || (int)tl[5]["day"] != 31 || @@ -378,6 +378,7 @@ protected: TEST(Core_InputOutput, write_read_consistency) { Core_IOTest test; test.safe_run(); } +extern void testFormatter(); class CV_MiscIOTest : public cvtest::BaseTest { @@ -390,7 +391,6 @@ protected: try { string fname = cv::tempfile(".xml"); - FileStorage fs(fname, FileStorage::WRITE); vector mi, mi2, mi3, mi4; vector mv, mv2, mv3, mv4; Mat m(10, 9, CV_32F); @@ -398,24 +398,59 @@ protected: randu(m, 0, 1); mi3.push_back(5); mv3.push_back(m); + Point_ p1(1.1f, 2.2f), op1; + Point3i p2(3, 4, 5), op2; + Size s1(6, 7), os1; + Complex c1(9, 10), oc1; + Rect r1(11, 12, 13, 14), or1; + Vec v1(15, 16, 17, 18, 19), ov1; + Scalar sc1(20.0, 21.1, 22.2, 23.3), osc1; + Range g1(7, 8), og1; + + FileStorage fs(fname, FileStorage::WRITE); fs << "mi" << mi; fs << "mv" << mv; fs << "mi3" << mi3; fs << "mv3" << mv3; fs << "empty" << empty; + fs << "p1" << p1; + fs << "p2" << p2; + fs << "s1" << s1; + fs << "c1" << c1; + fs << "r1" << r1; + fs << "v1" << v1; + fs << "sc1" << sc1; + fs << "g1" << g1; fs.release(); + fs.open(fname, FileStorage::READ); fs["mi"] >> mi2; fs["mv"] >> mv2; fs["mi3"] >> mi4; fs["mv3"] >> mv4; fs["empty"] >> empty; + fs["p1"] >> op1; + fs["p2"] >> op2; + fs["s1"] >> os1; + fs["c1"] >> oc1; + fs["r1"] >> or1; + fs["v1"] >> ov1; + fs["sc1"] >> osc1; + fs["g1"] >> og1; CV_Assert( mi2.empty() ); CV_Assert( mv2.empty() ); CV_Assert( norm(mi3, mi4, CV_C) == 0 ); CV_Assert( mv4.size() == 1 ); double n = norm(mv3[0], mv4[0], CV_C); CV_Assert( n == 0 ); + CV_Assert( op1 == p1 ); + CV_Assert( op2 == p2 ); + CV_Assert( os1 == s1 ); + CV_Assert( oc1 == c1 ); + CV_Assert( or1 == r1 ); + CV_Assert( ov1 == v1 ); + CV_Assert( osc1 == sc1 ); + CV_Assert( og1 == g1 ); } catch(...) { @@ -454,12 +489,12 @@ protected: TEST(Core_InputOutput, huge) { CV_BigMatrixIOTest test; test.safe_run(); } */ -TEST(Core_globbing, accurasy) +TEST(Core_globbing, accuracy) { std::string patternLena = cvtest::TS::ptr()->get_data_path() + "lena*.*"; std::string patternLenaPng = cvtest::TS::ptr()->get_data_path() + "lena.png"; - std::vector lenas, pngLenas; + std::vector lenas, pngLenas; cv::glob(patternLena, lenas, true); cv::glob(patternLenaPng, pngLenas, true); @@ -469,4 +504,14 @@ TEST(Core_globbing, accurasy) { ASSERT_NE(std::find(lenas.begin(), lenas.end(), pngLenas[i]), lenas.end()); } -} \ No newline at end of file +} + +TEST(Core_InputOutput, FileStorage) +{ + std::string file = cv::tempfile(".xml"); + cv::FileStorage f(file, cv::FileStorage::WRITE); + + char arr[66]; + sprintf(arr, "sprintf is hell %d", 666); + EXPECT_NO_THROW(f << arr); +} diff --git a/modules/core/test/test_main.cpp b/modules/core/test/test_main.cpp index 6b24993447..d5400e20fd 100644 --- a/modules/core/test/test_main.cpp +++ b/modules/core/test/test_main.cpp @@ -1,3 +1,10 @@ +#ifdef _MSC_VER +# if _MSC_VER >= 1700 +# pragma warning(disable:4447) // Disable warning 'main' signature found without threading model +# endif +#endif + + #include "test_precomp.hpp" CV_TEST_MAIN("cv") diff --git a/modules/core/test/test_mat.cpp b/modules/core/test/test_mat.cpp index 3693c2dcb1..3c8ae8bf9f 100644 --- a/modules/core/test/test_mat.cpp +++ b/modules/core/test/test_mat.cpp @@ -1,5 +1,7 @@ #include "test_precomp.hpp" +#include + using namespace cv; using namespace std; @@ -508,6 +510,32 @@ protected: return; } #endif + // Test read and write + FileStorage fs( "PCA_store.yml", FileStorage::WRITE ); + rPCA.write( fs ); + fs.release(); + + PCA lPCA; + fs.open( "PCA_store.yml", FileStorage::READ ); + lPCA.read( fs.root() ); + err = norm( rPCA.eigenvectors, lPCA.eigenvectors, CV_RELATIVE_L2 ); + if( err > 0 ) + { + ts->printf( cvtest::TS::LOG, "bad accuracy of write/load functions (YML); err = %f\n", err ); + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + } + err = norm( rPCA.eigenvalues, lPCA.eigenvalues, CV_RELATIVE_L2 ); + if( err > 0 ) + { + ts->printf( cvtest::TS::LOG, "bad accuracy of write/load functions (YML); err = %f\n", err ); + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + } + err = norm( rPCA.mean, lPCA.mean, CV_RELATIVE_L2 ); + if( err > 0 ) + { + ts->printf( cvtest::TS::LOG, "bad accuracy of write/load functions (YML); err = %f\n", err ); + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + } } }; @@ -641,7 +669,7 @@ void Core_ArrayOpTest::run( int /* start_from */) cvSetReal3D(&matA, idx1[0], idx1[1], idx1[2], -val0); cvSetND(&matB, idx0, val1); cvSet3D(&matB, idx1[0], idx1[1], idx1[2], -val1); - Ptr matC = cvCloneMatND(&matB); + Ptr matC(cvCloneMatND(&matB)); if( A.at(idx0[0], idx0[1], idx0[2]) != val0 || A.at(idx1[0], idx1[1], idx1[2]) != -val0 || @@ -734,7 +762,7 @@ void Core_ArrayOpTest::run( int /* start_from */) } } - Ptr M2 = (CvSparseMat*)M; + Ptr M2(cvCreateSparseMat(M)); MatND Md; M.copyTo(Md); SparseMat M3; SparseMat(Md).convertTo(M3, Md.type(), 2); diff --git a/modules/core/test/test_math.cpp b/modules/core/test/test_math.cpp index e02f78c541..377742386f 100644 --- a/modules/core/test/test_math.cpp +++ b/modules/core/test/test_math.cpp @@ -545,7 +545,7 @@ void Core_CrossProductTest::run_func() void Core_CrossProductTest::prepare_to_validation( int ) { - CvScalar a = {{0,0,0,0}}, b = {{0,0,0,0}}, c = {{0,0,0,0}}; + CvScalar a(0), b(0), c(0); if( test_mat[INPUT][0].rows > 1 ) { @@ -2292,9 +2292,9 @@ void Core_SolvePolyTest::run( int ) cvFlip(&amat, &amat, 0); int nr2; if( cubic_case == 0 ) - nr2 = cv::solveCubic(cv::Mat(&amat),umat2); + nr2 = cv::solveCubic(cv::cvarrToMat(&amat),umat2); else - nr2 = cv::solveCubic(cv::Mat_(cv::Mat(&amat)), umat2); + nr2 = cv::solveCubic(cv::Mat_(cv::cvarrToMat(&amat)), umat2); cvFlip(&amat, &amat, 0); if(nr2 > 0) std::sort(ar2.begin(), ar2.begin()+nr2, pred_double()); @@ -2599,6 +2599,35 @@ TEST(Core_Trace, accuracy) { Core_TraceTest test; test.safe_run(); } TEST(Core_SolvePoly, accuracy) { Core_SolvePolyTest test; test.safe_run(); } TEST(Core_Phase, accuracy) { Core_PhaseTest test; test.safe_run(); } + +TEST(Core_SVD, flt) +{ + float a[] = { + 1.23377746e+011f, -7.05490125e+010f, -4.18380882e+010f, -11693456.f, + -39091328.f, 77492224.f, -7.05490125e+010f, 2.36211143e+011f, + -3.51093473e+010f, 70773408.f, -4.83386156e+005f, -129560368.f, + -4.18380882e+010f, -3.51093473e+010f, 9.25311222e+010f, -49052424.f, + 43922752.f, 12176842.f, -11693456.f, 70773408.f, -49052424.f, 8.40836094e+004f, + 5.17475293e+003f, -1.16122949e+004f, -39091328.f, -4.83386156e+005f, + 43922752.f, 5.17475293e+003f, 5.16047969e+004f, 5.68887842e+003f, 77492224.f, + -129560368.f, 12176842.f, -1.16122949e+004f, 5.68887842e+003f, + 1.28060578e+005f + }; + + float b[] = { + 283751232.f, 2.61604198e+009f, -745033216.f, 2.31125625e+005f, + -4.52429188e+005f, -1.37596525e+006f + }; + + Mat A(6, 6, CV_32F, a); + Mat B(6, 1, CV_32F, b); + Mat X, B1; + solve(A, B, X, DECOMP_SVD); + B1 = A*X; + EXPECT_LE(norm(B1, B, NORM_L2 + NORM_RELATIVE), FLT_EPSILON*10); +} + + // TODO: eigenvv, invsqrt, cbrt, fastarctan, (round, floor, ceil(?)), @@ -2726,4 +2755,3 @@ TEST(CovariationMatrixVectorOfMatWithMean, accuracy) } /* End of file. */ - diff --git a/modules/core/test/test_operations.cpp b/modules/core/test/test_operations.cpp index 6b36883cfe..8d3341e59d 100644 --- a/modules/core/test/test_operations.cpp +++ b/modules/core/test/test_operations.cpp @@ -75,6 +75,7 @@ protected: bool TestSparseMat(); bool TestVec(); bool TestMatxMultiplication(); + bool TestMatxElementwiseDivison(); bool TestSubMatAccess(); bool TestExp(); bool TestSVD(); @@ -891,6 +892,28 @@ bool CV_OperationsTest::TestMatxMultiplication() return true; } +bool CV_OperationsTest::TestMatxElementwiseDivison() +{ + try + { + Matx22f mat(2, 4, 6, 8); + Matx22f mat2(2, 2, 2, 2); + + Matx22f res = mat.div(mat2); + + if(res(0, 0) != 1.0) throw test_excep(); + if(res(0, 1) != 2.0) throw test_excep(); + if(res(1, 0) != 3.0) throw test_excep(); + if(res(1, 1) != 4.0) throw test_excep(); + } + catch(const test_excep&) + { + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return false; + } + return true; +} + bool CV_OperationsTest::TestVec() { @@ -1109,6 +1132,9 @@ void CV_OperationsTest::run( int /* start_from */) if (!TestMatxMultiplication()) return; + if (!TestMatxElementwiseDivison()) + return; + if (!TestSubMatAccess()) return; diff --git a/modules/core/test/test_precomp.cpp b/modules/core/test/test_precomp.cpp deleted file mode 100644 index 5956e13e3e..0000000000 --- a/modules/core/test/test_precomp.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "test_precomp.hpp" diff --git a/modules/core/test/test_precomp.hpp b/modules/core/test/test_precomp.hpp index 6c0f493d4e..d981cea066 100644 --- a/modules/core/test/test_precomp.hpp +++ b/modules/core/test/test_precomp.hpp @@ -9,8 +9,10 @@ #ifndef __OPENCV_TEST_PRECOMP_HPP__ #define __OPENCV_TEST_PRECOMP_HPP__ +#include #include "opencv2/ts.hpp" #include "opencv2/core/core_c.h" -#include + +#include "opencv2/core/private.hpp" #endif diff --git a/modules/core/test/test_ptr.cpp b/modules/core/test/test_ptr.cpp new file mode 100644 index 0000000000..c6f793ab16 --- /dev/null +++ b/modules/core/test/test_ptr.cpp @@ -0,0 +1,389 @@ +/*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) 2013, NVIDIA Corporation, 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 copyright holders 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 "test_precomp.hpp" + +using namespace cv; + +namespace { + +struct Reporter { + Reporter(bool* deleted) : deleted_(deleted) + { *deleted_ = false; } + + // the destructor is virtual, so that we can test dynamic_cast later + virtual ~Reporter() + { *deleted_ = true; } + +private: + bool* deleted_; + + Reporter(const Reporter&); + Reporter& operator = (const Reporter&); +}; + +struct ReportingDeleter { + ReportingDeleter(bool* deleted) : deleted_(deleted) + { *deleted_ = false; } + + void operator()(void*) + { *deleted_ = true; } + +private: + bool* deleted_; +}; + +int dummyObject; + +} + +TEST(Core_Ptr, default_ctor) +{ + Ptr p; + EXPECT_EQ(NULL, p.get()); +} + +TEST(Core_Ptr, owning_ctor) +{ + bool deleted = false; + + { + Reporter* r = new Reporter(&deleted); + Ptr p(r); + EXPECT_EQ(r, p.get()); + } + + EXPECT_TRUE(deleted); + + { + Ptr p(&dummyObject, ReportingDeleter(&deleted)); + EXPECT_EQ(&dummyObject, p.get()); + } + + EXPECT_TRUE(deleted); + + { + Ptr p((void*)0, ReportingDeleter(&deleted)); + EXPECT_EQ(NULL, p.get()); + } + + EXPECT_FALSE(deleted); +} + +TEST(Core_Ptr, sharing_ctor) +{ + bool deleted = false; + + { + Ptr p1(new Reporter(&deleted)); + Ptr p2(p1); + EXPECT_EQ(p1.get(), p2.get()); + p1.release(); + EXPECT_FALSE(deleted); + } + + EXPECT_TRUE(deleted); + + { + Ptr p1(new Reporter(&deleted)); + Ptr p2(p1); + EXPECT_EQ(p1.get(), p2.get()); + p1.release(); + EXPECT_FALSE(deleted); + } + + EXPECT_TRUE(deleted); + + { + Ptr p1(new Reporter(&deleted)); + Ptr p2(p1, &dummyObject); + EXPECT_EQ(&dummyObject, p2.get()); + p1.release(); + EXPECT_FALSE(deleted); + } + + EXPECT_TRUE(deleted); +} + +TEST(Core_Ptr, assignment) +{ + bool deleted1 = false, deleted2 = false; + + { + Ptr p1(new Reporter(&deleted1)); + p1 = p1; + EXPECT_FALSE(deleted1); + } + + EXPECT_TRUE(deleted1); + + { + Ptr p1(new Reporter(&deleted1)); + Ptr p2(new Reporter(&deleted2)); + p2 = p1; + EXPECT_TRUE(deleted2); + EXPECT_EQ(p1.get(), p2.get()); + p1.release(); + EXPECT_FALSE(deleted1); + } + + EXPECT_TRUE(deleted1); + + { + Ptr p1(new Reporter(&deleted1)); + Ptr p2(new Reporter(&deleted2)); + p2 = p1; + EXPECT_TRUE(deleted2); + EXPECT_EQ(p1.get(), p2.get()); + p1.release(); + EXPECT_FALSE(deleted1); + } + + EXPECT_TRUE(deleted1); +} + +TEST(Core_Ptr, release) +{ + bool deleted = false; + + Ptr p1(new Reporter(&deleted)); + p1.release(); + EXPECT_TRUE(deleted); + EXPECT_EQ(NULL, p1.get()); +} + +TEST(Core_Ptr, reset) +{ + bool deleted_old = false, deleted_new = false; + + { + Ptr p(new Reporter(&deleted_old)); + Reporter* r = new Reporter(&deleted_new); + p.reset(r); + EXPECT_TRUE(deleted_old); + EXPECT_EQ(r, p.get()); + } + + EXPECT_TRUE(deleted_new); + + { + Ptr p(new Reporter(&deleted_old)); + p.reset(&dummyObject, ReportingDeleter(&deleted_new)); + EXPECT_TRUE(deleted_old); + EXPECT_EQ(&dummyObject, p.get()); + } + + EXPECT_TRUE(deleted_new); +} + +TEST(Core_Ptr, swap) +{ + bool deleted1 = false, deleted2 = false; + + { + Reporter* r1 = new Reporter(&deleted1); + Reporter* r2 = new Reporter(&deleted2); + Ptr p1(r1), p2(r2); + p1.swap(p2); + EXPECT_EQ(r1, p2.get()); + EXPECT_EQ(r2, p1.get()); + EXPECT_FALSE(deleted1); + EXPECT_FALSE(deleted2); + p1.release(); + EXPECT_TRUE(deleted2); + } + + EXPECT_TRUE(deleted1); + + { + Reporter* r1 = new Reporter(&deleted1); + Reporter* r2 = new Reporter(&deleted2); + Ptr p1(r1), p2(r2); + swap(p1, p2); + EXPECT_EQ(r1, p2.get()); + EXPECT_EQ(r2, p1.get()); + EXPECT_FALSE(deleted1); + EXPECT_FALSE(deleted2); + p1.release(); + EXPECT_TRUE(deleted2); + } + + EXPECT_TRUE(deleted1); +} + +TEST(Core_Ptr, accessors) +{ + { + Ptr p; + EXPECT_EQ(NULL, static_cast(p)); + EXPECT_TRUE(p.empty()); + } + + { + Size* s = new Size(); + Ptr p(s); + EXPECT_EQ(s, static_cast(p)); + EXPECT_EQ(s, &*p); + EXPECT_EQ(&s->width, &p->width); + EXPECT_FALSE(p.empty()); + } +} + +namespace { + +struct SubReporterBase { + virtual ~SubReporterBase() {} + int padding; +}; + +/* multiple inheritance, so that casts do something interesting */ +struct SubReporter : SubReporterBase, Reporter +{ + SubReporter(bool* deleted) : Reporter(deleted) + {} +}; + +} + +TEST(Core_Ptr, casts) +{ + bool deleted = false; + + { + Ptr p1(new Reporter(&deleted)); + Ptr p2 = p1.constCast(); + EXPECT_EQ(p1.get(), p2.get()); + p1.release(); + EXPECT_FALSE(deleted); + } + + EXPECT_TRUE(deleted); + + { + SubReporter* sr = new SubReporter(&deleted); + Ptr p1(sr); + // This next check isn't really for Ptr itself; it checks that Reporter + // is at a non-zero offset within SubReporter, so that the next + // check will give us more confidence that the cast actually did something. + EXPECT_NE(static_cast(sr), static_cast(p1.get())); + Ptr p2 = p1.staticCast(); + EXPECT_EQ(sr, p2.get()); + p1.release(); + EXPECT_FALSE(deleted); + } + + EXPECT_TRUE(deleted); + + { + SubReporter* sr = new SubReporter(&deleted); + Ptr p1(sr); + EXPECT_NE(static_cast(sr), static_cast(p1.get())); + Ptr p2 = p1.dynamicCast(); + EXPECT_EQ(sr, p2.get()); + p1.release(); + EXPECT_FALSE(deleted); + } + + EXPECT_TRUE(deleted); + + { + Ptr p1(new Reporter(&deleted)); + Ptr p2 = p1.dynamicCast(); + EXPECT_EQ(NULL, p2.get()); + p1.release(); + EXPECT_FALSE(deleted); + } + + EXPECT_TRUE(deleted); +} + +TEST(Core_Ptr, comparisons) +{ + Ptr p1, p2(new int), p3(new int); + Ptr p4(p2, p3.get()); + + // Not using EXPECT_EQ here, since none of them are really "expected" or "actual". + EXPECT_TRUE(p1 == p1); + EXPECT_TRUE(p2 == p2); + EXPECT_TRUE(p2 != p3); + EXPECT_TRUE(p2 != p4); + EXPECT_TRUE(p3 == p4); +} + +TEST(Core_Ptr, make) +{ + bool deleted = true; + + { + Ptr p = makePtr(&deleted); + EXPECT_FALSE(deleted); + } + + EXPECT_TRUE(deleted); +} + +namespace { + +struct SpeciallyDeletable +{ + SpeciallyDeletable() : deleted(false) + {} + bool deleted; +}; + +} + +namespace cv { + +template<> +void DefaultDeleter::operator()(SpeciallyDeletable * obj) const +{ obj->deleted = true; } + +} + +TEST(Core_Ptr, specialized_deleter) +{ + SpeciallyDeletable sd; + + { Ptr p(&sd); } + + ASSERT_TRUE(sd.deleted); +} diff --git a/modules/cudev/CMakeLists.txt b/modules/cudev/CMakeLists.txt new file mode 100644 index 0000000000..3c7b0592c7 --- /dev/null +++ b/modules/cudev/CMakeLists.txt @@ -0,0 +1,22 @@ +if(NOT HAVE_CUDA) + ocv_module_disable(cudev) +endif() + +set(the_description "CUDA device layer") + +ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4189 /wd4505 -Wundef -Wmissing-declarations -Wunused-function -Wunused-variable) + +ocv_add_module(cudev) + +ocv_module_include_directories(opencv_core) + +file(GLOB_RECURSE lib_hdrs "include/opencv2/*.hpp") +file(GLOB lib_srcs "src/*.cpp") + +ocv_set_module_sources(HEADERS ${lib_hdrs} SOURCES ${lib_srcs}) + +ocv_create_module() + +if(BUILD_TESTS) + add_subdirectory(test) +endif() diff --git a/modules/cudev/include/opencv2/cudev.hpp b/modules/cudev/include/opencv2/cudev.hpp new file mode 100644 index 0000000000..63bfc95696 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev.hpp @@ -0,0 +1,112 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_HPP__ +#define __OPENCV_CUDEV_HPP__ + +#include "cudev/common.hpp" + +#include "cudev/util/atomic.hpp" +#include "cudev/util/limits.hpp" +#include "cudev/util/saturate_cast.hpp" +#include "cudev/util/simd_functions.hpp" +#include "cudev/util/tuple.hpp" +#include "cudev/util/type_traits.hpp" +#include "cudev/util/vec_math.hpp" +#include "cudev/util/vec_traits.hpp" + +#include "cudev/functional/color_cvt.hpp" +#include "cudev/functional/functional.hpp" +#include "cudev/functional/tuple_adapter.hpp" + +#include "cudev/warp/reduce.hpp" +#include "cudev/warp/scan.hpp" +#include "cudev/warp/shuffle.hpp" +#include "cudev/warp/warp.hpp" + +#include "cudev/block/block.hpp" +#include "cudev/block/dynamic_smem.hpp" +#include "cudev/block/reduce.hpp" +#include "cudev/block/scan.hpp" +#include "cudev/block/vec_distance.hpp" + +#include "cudev/grid/copy.hpp" +#include "cudev/grid/glob_reduce.hpp" +#include "cudev/grid/histogram.hpp" +#include "cudev/grid/integral.hpp" +#include "cudev/grid/pyramids.hpp" +#include "cudev/grid/reduce_to_vec.hpp" +#include "cudev/grid/split_merge.hpp" +#include "cudev/grid/transform.hpp" +#include "cudev/grid/transpose.hpp" + +#include "cudev/ptr2d/constant.hpp" +#include "cudev/ptr2d/deriv.hpp" +#include "cudev/ptr2d/extrapolation.hpp" +#include "cudev/ptr2d/glob.hpp" +#include "cudev/ptr2d/gpumat.hpp" +#include "cudev/ptr2d/interpolation.hpp" +#include "cudev/ptr2d/lut.hpp" +#include "cudev/ptr2d/mask.hpp" +#include "cudev/ptr2d/remap.hpp" +#include "cudev/ptr2d/resize.hpp" +#include "cudev/ptr2d/texture.hpp" +#include "cudev/ptr2d/traits.hpp" +#include "cudev/ptr2d/transform.hpp" +#include "cudev/ptr2d/warping.hpp" +#include "cudev/ptr2d/zip.hpp" + +#include "cudev/expr/binary_func.hpp" +#include "cudev/expr/binary_op.hpp" +#include "cudev/expr/color.hpp" +#include "cudev/expr/deriv.hpp" +#include "cudev/expr/expr.hpp" +#include "cudev/expr/per_element_func.hpp" +#include "cudev/expr/reduction.hpp" +#include "cudev/expr/unary_func.hpp" +#include "cudev/expr/unary_op.hpp" +#include "cudev/expr/warping.hpp" + +#endif diff --git a/modules/cudev/include/opencv2/cudev/block/block.hpp b/modules/cudev/include/opencv2/cudev/block/block.hpp new file mode 100644 index 0000000000..385e1713e5 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/block/block.hpp @@ -0,0 +1,127 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_BLOCK_BLOCK_HPP__ +#define __OPENCV_CUDEV_BLOCK_BLOCK_HPP__ + +#include "../common.hpp" + +namespace cv { namespace cudev { + +struct Block +{ + __device__ __forceinline__ static uint blockId() + { + return (blockIdx.z * gridDim.y + blockIdx.y) * gridDim.x + blockIdx.x; + } + + __device__ __forceinline__ static uint blockSize() + { + return blockDim.x * blockDim.y * blockDim.z; + } + + __device__ __forceinline__ static uint threadLineId() + { + return (threadIdx.z * blockDim.y + threadIdx.y) * blockDim.x + threadIdx.x; + } +}; + +template +__device__ __forceinline__ static void blockFill(It beg, It end, const T& value) +{ + uint STRIDE = Block::blockSize(); + It t = beg + Block::threadLineId(); + + for(; t < end; t += STRIDE) + *t = value; +} + +template +__device__ __forceinline__ static void blockYota(OutIt beg, OutIt end, T value) +{ + uint STRIDE = Block::blockSize(); + uint tid = Block::threadLineId(); + value += tid; + + for(OutIt t = beg + tid; t < end; t += STRIDE, value += STRIDE) + *t = value; +} + +template +__device__ __forceinline__ static void blockCopy(InIt beg, InIt end, OutIt out) +{ + uint STRIDE = Block::blockSize(); + InIt t = beg + Block::threadLineId(); + OutIt o = out + (t - beg); + + for(; t < end; t += STRIDE, o += STRIDE) + *o = *t; +} + +template +__device__ __forceinline__ static void blockTransfrom(InIt beg, InIt end, OutIt out, const UnOp& op) +{ + uint STRIDE = Block::blockSize(); + InIt t = beg + Block::threadLineId(); + OutIt o = out + (t - beg); + + for(; t < end; t += STRIDE, o += STRIDE) + *o = op(*t); +} + +template +__device__ __forceinline__ static void blockTransfrom(InIt1 beg1, InIt1 end1, InIt2 beg2, OutIt out, const BinOp& op) +{ + uint STRIDE = Block::blockSize(); + InIt1 t1 = beg1 + Block::threadLineId(); + InIt2 t2 = beg2 + Block::threadLineId(); + OutIt o = out + (t1 - beg1); + + for(; t1 < end1; t1 += STRIDE, t2 += STRIDE, o += STRIDE) + *o = op(*t1, *t2); +} +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/block/detail/reduce.hpp b/modules/cudev/include/opencv2/cudev/block/detail/reduce.hpp new file mode 100644 index 0000000000..02803b003a --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/block/detail/reduce.hpp @@ -0,0 +1,392 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_BLOCK_REDUCE_DETAIL_HPP__ +#define __OPENCV_CUDEV_BLOCK_REDUCE_DETAIL_HPP__ + +#include "../../common.hpp" +#include "../../util/tuple.hpp" +#include "../../util/type_traits.hpp" +#include "../../warp/warp.hpp" +#include "../../warp/shuffle.hpp" + +namespace cv { namespace cudev { + +namespace block_reduce_detail +{ + // GetType + + template struct GetType; + + template struct GetType + { + typedef T type; + }; + + template struct GetType + { + typedef T type; + }; + + template struct GetType + { + typedef T type; + }; + + // For + + template struct For + { + template + __device__ static void loadToSmem(const PointerTuple& smem, const ValTuple& val, uint tid) + { + get(smem)[tid] = get(val); + + For::loadToSmem(smem, val, tid); + } + + template + __device__ static void loadFromSmem(const PointerTuple& smem, const ValTuple& val, uint tid) + { + get(val) = get(smem)[tid]; + + For::loadFromSmem(smem, val, tid); + } + + template + __device__ static void merge(const PointerTuple& smem, const ValTuple& val, uint tid, uint delta, const OpTuple& op) + { + typename GetType::type>::type reg = get(smem)[tid + delta]; + get(smem)[tid] = get(val) = get(op)(get(val), reg); + + For::merge(smem, val, tid, delta, op); + } + +#if CV_CUDEV_ARCH >= 300 + template + __device__ static void mergeShfl(const ValTuple& val, uint delta, uint width, const OpTuple& op) + { + typename GetType::type>::type reg = shfl_down(get(val), delta, width); + get(val) = get(op)(get(val), reg); + + For::mergeShfl(val, delta, width, op); + } +#endif + }; + + template struct For + { + template + __device__ __forceinline__ static void loadToSmem(const PointerTuple&, const ValTuple&, uint) + { + } + template + __device__ __forceinline__ static void loadFromSmem(const PointerTuple&, const ValTuple&, uint) + { + } + + template + __device__ __forceinline__ static void merge(const PointerTuple&, const ValTuple&, uint, uint, const OpTuple&) + { + } + +#if CV_CUDEV_ARCH >= 300 + template + __device__ __forceinline__ static void mergeShfl(const ValTuple&, uint, uint, const OpTuple&) + { + } +#endif + }; + + // loadToSmem / loadFromSmem + + template + __device__ __forceinline__ void loadToSmem(volatile T* smem, T& val, uint tid) + { + smem[tid] = val; + } + + template + __device__ __forceinline__ void loadFromSmem(volatile T* smem, T& val, uint tid) + { + val = smem[tid]; + } + + template + __device__ __forceinline__ void loadToSmem(const tuple& smem, + const tuple& val, + uint tid) + { + For<0, tuple_size >::value>::loadToSmem(smem, val, tid); + } + + template + __device__ __forceinline__ void loadFromSmem(const tuple& smem, + const tuple& val, + uint tid) + { + For<0, tuple_size >::value>::loadFromSmem(smem, val, tid); + } + + // merge + + template + __device__ __forceinline__ void merge(volatile T* smem, T& val, uint tid, uint delta, const Op& op) + { + T reg = smem[tid + delta]; + smem[tid] = val = op(val, reg); + } + + template + __device__ __forceinline__ void merge(const tuple& smem, + const tuple& val, + uint tid, + uint delta, + const tuple& op) + { + For<0, tuple_size >::value>::merge(smem, val, tid, delta, op); + } + + // mergeShfl + +#if CV_CUDEV_ARCH >= 300 + template + __device__ __forceinline__ void mergeShfl(T& val, uint delta, uint width, const Op& op) + { + T reg = shfl_down(val, delta, width); + val = op(val, reg); + } + + template + __device__ __forceinline__ void mergeShfl(const tuple& val, + uint delta, + uint width, + const tuple& op) + { + For<0, tuple_size >::value>::mergeShfl(val, delta, width, op); + } +#endif + + // Generic + + template struct Generic + { + template + __device__ static void reduce(Pointer smem, Reference val, uint tid, Op op) + { + loadToSmem(smem, val, tid); + if (N >= 32) + __syncthreads(); + + if (N >= 2048) + { + if (tid < 1024) + merge(smem, val, tid, 1024, op); + + __syncthreads(); + } + if (N >= 1024) + { + if (tid < 512) + merge(smem, val, tid, 512, op); + + __syncthreads(); + } + if (N >= 512) + { + if (tid < 256) + merge(smem, val, tid, 256, op); + + __syncthreads(); + } + if (N >= 256) + { + if (tid < 128) + merge(smem, val, tid, 128, op); + + __syncthreads(); + } + if (N >= 128) + { + if (tid < 64) + merge(smem, val, tid, 64, op); + + __syncthreads(); + } + if (N >= 64) + { + if (tid < 32) + merge(smem, val, tid, 32, op); + } + + if (tid < 16) + { + merge(smem, val, tid, 16, op); + merge(smem, val, tid, 8, op); + merge(smem, val, tid, 4, op); + merge(smem, val, tid, 2, op); + merge(smem, val, tid, 1, op); + } + } + }; + + // Unroll + + template struct Unroll + { + __device__ static void loop(Pointer smem, Reference val, uint tid, Op op) + { + merge(smem, val, tid, I, op); + Unroll::loop(smem, val, tid, op); + } + +#if CV_CUDEV_ARCH >= 300 + __device__ static void loopShfl(Reference val, Op op, uint N) + { + mergeShfl(val, I, N, op); + Unroll::loopShfl(val, op, N); + } +#endif + }; + + template struct Unroll<0, Pointer, Reference, Op> + { + __device__ __forceinline__ static void loop(Pointer, Reference, uint, Op) + { + } + +#if CV_CUDEV_ARCH >= 300 + __device__ __forceinline__ static void loopShfl(Reference, Op, uint) + { + } +#endif + }; + + // WarpOptimized + + template struct WarpOptimized + { + template + __device__ static void reduce(Pointer smem, Reference val, uint tid, Op op) + { + #if CV_CUDEV_ARCH >= 300 + (void) smem; + (void) tid; + + Unroll::loopShfl(val, op, N); + #else + loadToSmem(smem, val, tid); + + if (tid < N / 2) + Unroll::loop(smem, val, tid, op); + #endif + } + }; + + // GenericOptimized32 + + template struct GenericOptimized32 + { + enum { M = N / 32 }; + + template + __device__ static void reduce(Pointer smem, Reference val, uint tid, Op op) + { + const uint laneId = Warp::laneId(); + + #if CV_CUDEV_ARCH >= 300 + Unroll<16, Pointer, Reference, Op>::loopShfl(val, op, warpSize); + + if (laneId == 0) + loadToSmem(smem, val, tid / 32); + #else + loadToSmem(smem, val, tid); + + if (laneId < 16) + Unroll<16, Pointer, Reference, Op>::loop(smem, val, tid, op); + + __syncthreads(); + + if (laneId == 0) + loadToSmem(smem, val, tid / 32); + #endif + + __syncthreads(); + + loadFromSmem(smem, val, tid); + + if (tid < 32) + { + #if CV_CUDEV_ARCH >= 300 + Unroll::loopShfl(val, op, M); + #else + Unroll::loop(smem, val, tid, op); + #endif + } + } + }; + + template struct Dispatcher + { + typedef typename SelectIf< + (N <= 32) && IsPowerOf2::value, + WarpOptimized, + typename SelectIf< + (N <= 1024) && IsPowerOf2::value, + GenericOptimized32, + Generic + >::type + >::type reductor; + }; +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/block/detail/reduce_key_val.hpp b/modules/cudev/include/opencv2/cudev/block/detail/reduce_key_val.hpp new file mode 100644 index 0000000000..edbe8a586b --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/block/detail/reduce_key_val.hpp @@ -0,0 +1,394 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_BLOCK_REDUCE_KEY_VAL_DETAIL_HPP__ +#define __OPENCV_CUDEV_BLOCK_REDUCE_KEY_VAL_DETAIL_HPP__ + +#include "../../common.hpp" +#include "../../util/tuple.hpp" +#include "../../util/type_traits.hpp" +#include "../../warp/warp.hpp" + +namespace cv { namespace cudev { + +namespace block_reduce_key_val_detail +{ + // GetType + + template struct GetType; + + template struct GetType + { + typedef T type; + }; + + template struct GetType + { + typedef T type; + }; + + template struct GetType + { + typedef T type; + }; + + // For + + template struct For + { + template + __device__ static void loadToSmem(const PointerTuple& smem, const ReferenceTuple& data, uint tid) + { + get(smem)[tid] = get(data); + + For::loadToSmem(smem, data, tid); + } + + template + __device__ static void loadFromSmem(const PointerTuple& smem, const ReferenceTuple& data, uint tid) + { + get(data) = get(smem)[tid]; + + For::loadFromSmem(smem, data, tid); + } + + template + __device__ static void copy(const PointerTuple& svals, const ReferenceTuple& val, uint tid, uint delta) + { + get(svals)[tid] = get(val) = get(svals)[tid + delta]; + + For::copy(svals, val, tid, delta); + } + + template + __device__ static void merge(const KeyPointerTuple& skeys, const KeyReferenceTuple& key, + const ValPointerTuple& svals, const ValReferenceTuple& val, + const CmpTuple& cmp, + uint tid, uint delta) + { + typename GetType::type>::type reg = get(skeys)[tid + delta]; + + if (get(cmp)(reg, get(key))) + { + get(skeys)[tid] = get(key) = reg; + get(svals)[tid] = get(val) = get(svals)[tid + delta]; + } + + For::merge(skeys, key, svals, val, cmp, tid, delta); + } + }; + + template struct For + { + template + __device__ static void loadToSmem(const PointerTuple&, const ReferenceTuple&, uint) + { + } + + template + __device__ static void loadFromSmem(const PointerTuple&, const ReferenceTuple&, uint) + { + } + + template + __device__ static void copy(const PointerTuple&, const ReferenceTuple&, uint, uint) + { + } + + template + __device__ static void merge(const KeyPointerTuple&, const KeyReferenceTuple&, + const ValPointerTuple&, const ValReferenceTuple&, + const CmpTuple&, + uint, uint) + { + } + }; + + // loadToSmem / loadFromSmem + + template + __device__ __forceinline__ void loadToSmem(volatile T* smem, T& data, uint tid) + { + smem[tid] = data; + } + + template + __device__ __forceinline__ void loadFromSmem(volatile T* smem, T& data, uint tid) + { + data = smem[tid]; + } + + template + __device__ __forceinline__ void loadToSmem(const tuple& smem, + const tuple& data, + uint tid) + { + For<0, tuple_size >::value>::loadToSmem(smem, data, tid); + } + + template + __device__ __forceinline__ void loadFromSmem(const tuple& smem, + const tuple& data, + uint tid) + { + For<0, tuple_size >::value>::loadFromSmem(smem, data, tid); + } + + // copyVals + + template + __device__ __forceinline__ void copyVals(volatile V* svals, V& val, uint tid, uint delta) + { + svals[tid] = val = svals[tid + delta]; + } + + template + __device__ __forceinline__ void copyVals(const tuple& svals, + const tuple& val, + uint tid, uint delta) + { + For<0, tuple_size >::value>::copy(svals, val, tid, delta); + } + + // merge + + template + __device__ void merge(volatile K* skeys, K& key, volatile V* svals, V& val, const Cmp& cmp, uint tid, uint delta) + { + K reg = skeys[tid + delta]; + + if (cmp(reg, key)) + { + skeys[tid] = key = reg; + copyVals(svals, val, tid, delta); + } + } + + template + __device__ void merge(volatile K* skeys, K& key, + const tuple& svals, + const tuple& val, + const Cmp& cmp, uint tid, uint delta) + { + K reg = skeys[tid + delta]; + + if (cmp(reg, key)) + { + skeys[tid] = key = reg; + copyVals(svals, val, tid, delta); + } + } + + template + __device__ __forceinline__ void merge(const tuple& skeys, + const tuple& key, + const tuple& svals, + const tuple& val, + const tuple& cmp, + uint tid, uint delta) + { + For<0, tuple_size >::value>::merge(skeys, key, svals, val, cmp, tid, delta); + } + + // Generic + + template struct Generic + { + template + __device__ static void reduce(KP skeys, KR key, VP svals, VR val, uint tid, Cmp cmp) + { + loadToSmem(skeys, key, tid); + loadValsToSmem(svals, val, tid); + if (N >= 32) + __syncthreads(); + + if (N >= 2048) + { + if (tid < 1024) + merge(skeys, key, svals, val, cmp, tid, 1024); + + __syncthreads(); + } + if (N >= 1024) + { + if (tid < 512) + merge(skeys, key, svals, val, cmp, tid, 512); + + __syncthreads(); + } + if (N >= 512) + { + if (tid < 256) + merge(skeys, key, svals, val, cmp, tid, 256); + + __syncthreads(); + } + if (N >= 256) + { + if (tid < 128) + merge(skeys, key, svals, val, cmp, tid, 128); + + __syncthreads(); + } + if (N >= 128) + { + if (tid < 64) + merge(skeys, key, svals, val, cmp, tid, 64); + + __syncthreads(); + } + if (N >= 64) + { + if (tid < 32) + merge(skeys, key, svals, val, cmp, tid, 32); + } + + if (tid < 16) + { + merge(skeys, key, svals, val, cmp, tid, 16); + merge(skeys, key, svals, val, cmp, tid, 8); + merge(skeys, key, svals, val, cmp, tid, 4); + merge(skeys, key, svals, val, cmp, tid, 2); + merge(skeys, key, svals, val, cmp, tid, 1); + } + } + }; + + // Unroll + + template struct Unroll + { + __device__ static void loop(KP skeys, KR key, VP svals, VR val, uint tid, Cmp cmp) + { + merge(skeys, key, svals, val, cmp, tid, I); + Unroll::loop(skeys, key, svals, val, tid, cmp); + } + }; + + template struct Unroll<0, KP, KR, VP, VR, Cmp> + { + __device__ __forceinline__ static void loop(KP, KR, VP, VR, uint, Cmp) + { + } + }; + + // WarpOptimized + + template struct WarpOptimized + { + template + __device__ static void reduce(KP skeys, KR key, VP svals, VR val, uint tid, Cmp cmp) + { + loadToSmem(skeys, key, tid); + loadToSmem(svals, val, tid); + + if (tid < N / 2) + Unroll::loop(skeys, key, svals, val, tid, cmp); + } + }; + + // GenericOptimized32 + + template struct GenericOptimized32 + { + enum { M = N / 32 }; + + template + __device__ static void reduce(KP skeys, KR key, VP svals, VR val, uint tid, Cmp cmp) + { + const uint laneId = Warp::laneId(); + + loadToSmem(skeys, key, tid); + loadToSmem(svals, val, tid); + + if (laneId < 16) + Unroll<16, KP, KR, VP, VR, Cmp>::loop(skeys, key, svals, val, tid, cmp); + + __syncthreads(); + + if (laneId == 0) + { + loadToSmem(skeys, key, tid / 32); + loadToSmem(svals, val, tid / 32); + } + + __syncthreads(); + + loadFromSmem(skeys, key, tid); + + if (tid < 32) + { + Unroll::loop(skeys, key, svals, val, tid, cmp); + } + } + }; + + template struct Dispatcher + { + typedef typename SelectIf< + (N <= 32) && IsPowerOf2::value, + WarpOptimized, + typename SelectIf< + (N <= 1024) && IsPowerOf2::value, + GenericOptimized32, + Generic + >::type + >::type reductor; + }; +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/block/dynamic_smem.hpp b/modules/cudev/include/opencv2/cudev/block/dynamic_smem.hpp new file mode 100644 index 0000000000..9f9ba60009 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/block/dynamic_smem.hpp @@ -0,0 +1,86 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_BLOCK_DYNAMIC_SMEM_HPP__ +#define __OPENCV_CUDEV_BLOCK_DYNAMIC_SMEM_HPP__ + +#include "../common.hpp" + +namespace cv { namespace cudev { + +template struct DynamicSharedMem +{ + __device__ __forceinline__ operator T*() + { + extern __shared__ int __smem[]; + return (T*) __smem; + } + + __device__ __forceinline__ operator const T*() const + { + extern __shared__ int __smem[]; + return (T*) __smem; + } +}; + +// specialize for double to avoid unaligned memory access compile errors +template <> struct DynamicSharedMem +{ + __device__ __forceinline__ operator double*() + { + extern __shared__ double __smem_d[]; + return (double*) __smem_d; + } + + __device__ __forceinline__ operator const double*() const + { + extern __shared__ double __smem_d[]; + return (double*) __smem_d; + } +}; + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/block/reduce.hpp b/modules/cudev/include/opencv2/cudev/block/reduce.hpp new file mode 100644 index 0000000000..4c9022631b --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/block/reduce.hpp @@ -0,0 +1,128 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_BLOCK_REDUCE_HPP__ +#define __OPENCV_CUDEV_BLOCK_REDUCE_HPP__ + +#include "../common.hpp" +#include "../util/tuple.hpp" +#include "../warp/reduce.hpp" +#include "detail/reduce.hpp" +#include "detail/reduce_key_val.hpp" + +namespace cv { namespace cudev { + +// blockReduce + +template +__device__ __forceinline__ void blockReduce(volatile T* smem, T& val, uint tid, const Op& op) +{ + block_reduce_detail::Dispatcher::reductor::template reduce(smem, val, tid, op); +} + +template +__device__ __forceinline__ void blockReduce(const tuple& smem, + const tuple& val, + uint tid, + const tuple& op) +{ + block_reduce_detail::Dispatcher::reductor::template reduce< + const tuple&, + const tuple&, + const tuple&>(smem, val, tid, op); +} + +// blockReduceKeyVal + +template +__device__ __forceinline__ void blockReduceKeyVal(volatile K* skeys, K& key, volatile V* svals, V& val, uint tid, const Cmp& cmp) +{ + block_reduce_key_val_detail::Dispatcher::reductor::template reduce(skeys, key, svals, val, tid, cmp); +} + +template +__device__ __forceinline__ void blockReduceKeyVal(volatile K* skeys, K& key, + const tuple& svals, + const tuple& val, + uint tid, const Cmp& cmp) +{ + block_reduce_key_val_detail::Dispatcher::reductor::template reduce&, + const tuple&, + const Cmp&>(skeys, key, svals, val, tid, cmp); +} + +template +__device__ __forceinline__ void blockReduceKeyVal(const tuple& skeys, + const tuple& key, + const tuple& svals, + const tuple& val, + uint tid, + const tuple& cmp) +{ + block_reduce_key_val_detail::Dispatcher::reductor::template reduce< + const tuple&, + const tuple&, + const tuple&, + const tuple&, + const tuple& + >(skeys, key, svals, val, tid, cmp); +} + +}} + +#endif diff --git a/modules/gpu/src/thread_wrappers.h b/modules/cudev/include/opencv2/cudev/block/scan.hpp similarity index 59% rename from modules/gpu/src/thread_wrappers.h rename to modules/cudev/include/opencv2/cudev/block/scan.hpp index 78e675216c..c54dfef9f3 100644 --- a/modules/gpu/src/thread_wrappers.h +++ b/modules/cudev/include/opencv2/cudev/block/scan.hpp @@ -12,6 +12,7 @@ // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -40,73 +41,61 @@ // //M*/ -#ifndef __THREAD_WRAPPERS_H__ -#define __THREAD_WRAPPERS_H__ +#pragma once -#include "precomp.hpp" +#ifndef __OPENCV_CUDEV_BLOCK_SCAN_HPP__ +#define __OPENCV_CUDEV_BLOCK_SCAN_HPP__ -#if defined(HAVE_CUDA) && defined(HAVE_NVCUVID) +#include "../common.hpp" +#include "../warp/scan.hpp" -namespace cv { namespace gpu +namespace cv { namespace cudev { + +template +__device__ T blockScanInclusive(T data, volatile T* smem, uint tid) { - namespace detail + if (THREADS_NUM > WARP_SIZE) { - class CriticalSection + // bottom-level inclusive warp scan + T warpResult = warpScanInclusive(data, smem, tid); + + __syncthreads(); + + // save top elements of each warp for exclusive warp scan + // sync to wait for warp scans to complete (because s_Data is being overwritten) + if ((tid & (WARP_SIZE - 1)) == (WARP_SIZE - 1)) { - public: - CriticalSection(); - ~CriticalSection(); + smem[tid >> LOG_WARP_SIZE] = warpResult; + } - void enter(); - void leave(); + __syncthreads(); - class AutoLock - { - public: - explicit AutoLock(CriticalSection& criticalSection) : - criticalSection_(criticalSection) - { - criticalSection_.enter(); - } - - ~AutoLock() - { - criticalSection_.leave(); - } - - private: - CriticalSection& criticalSection_; - }; - - private: - CriticalSection(const CriticalSection&); - CriticalSection& operator=(const CriticalSection&); - - class Impl; - std::auto_ptr impl_; - }; - - class Thread + if (tid < (THREADS_NUM / WARP_SIZE)) { - public: - explicit Thread(void (*func)(void* userData), void* userData = 0); - ~Thread(); + // grab top warp elements + T val = smem[tid]; - void wait(); + // calculate exclusive scan and write back to shared memory + smem[tid] = warpScanExclusive(val, smem, tid); + } - static void sleep(int ms); - - private: - Thread(const Thread&); - Thread& operator=(const Thread&); - - class Impl; - std::auto_ptr impl_; - }; + __syncthreads(); + // return updated warp scans with exclusive scan results + return warpResult + smem[tid >> LOG_WARP_SIZE]; } + else + { + return warpScanInclusive(data, smem, tid); + } +} + +template +__device__ __forceinline__ T blockScanExclusive(T data, volatile T* smem, uint tid) +{ + return blockScanInclusive(data, smem, tid) - data; +} + }} -#endif // HAVE_CUDA - -#endif // __THREAD_WRAPPERS_H__ +#endif diff --git a/modules/cudev/include/opencv2/cudev/block/vec_distance.hpp b/modules/cudev/include/opencv2/cudev/block/vec_distance.hpp new file mode 100644 index 0000000000..c48e9146ef --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/block/vec_distance.hpp @@ -0,0 +1,184 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_BLOCK_VEC_DISTANCE_HPP__ +#define __OPENCV_CUDEV_BLOCK_VEC_DISTANCE_HPP__ + +#include "../common.hpp" +#include "../functional/functional.hpp" +#include "../warp/reduce.hpp" +#include "reduce.hpp" + +namespace cv { namespace cudev { + +// NormL1 + +template struct NormL1 +{ + typedef int value_type; + typedef uint result_type; + + result_type mySum; + + __device__ __forceinline__ NormL1() : mySum(0) {} + + __device__ __forceinline__ void reduceThread(value_type val1, value_type val2) + { + mySum = __sad(val1, val2, mySum); + } + + __device__ __forceinline__ void reduceWarp(result_type* smem, uint tid) + { + warpReduce(smem, mySum, tid, plus()); + } + + template __device__ __forceinline__ void reduceBlock(result_type* smem, uint tid) + { + blockReduce(smem, mySum, tid, plus()); + } + + __device__ __forceinline__ operator result_type() const + { + return mySum; + } +}; +template <> struct NormL1 +{ + typedef float value_type; + typedef float result_type; + + result_type mySum; + + __device__ __forceinline__ NormL1() : mySum(0.0f) {} + + __device__ __forceinline__ void reduceThread(value_type val1, value_type val2) + { + mySum += ::fabsf(val1 - val2); + } + + __device__ __forceinline__ void reduceWarp(result_type* smem, uint tid) + { + warpReduce(smem, mySum, tid, plus()); + } + + template __device__ __forceinline__ void reduceBlock(result_type* smem, uint tid) + { + blockReduce(smem, mySum, tid, plus()); + } + + __device__ __forceinline__ operator result_type() const + { + return mySum; + } +}; + +// NormL2 + +struct NormL2 +{ + typedef float value_type; + typedef float result_type; + + result_type mySum; + + __device__ __forceinline__ NormL2() : mySum(0.0f) {} + + __device__ __forceinline__ void reduceThread(value_type val1, value_type val2) + { + const float diff = val1 - val2; + mySum += diff * diff; + } + + __device__ __forceinline__ void reduceWarp(result_type* smem, uint tid) + { + warpReduce(smem, mySum, tid, plus()); + } + + template __device__ __forceinline__ void reduceBlock(result_type* smem, uint tid) + { + blockReduce(smem, mySum, tid, plus()); + } + + __device__ __forceinline__ operator result_type() const + { + return ::sqrtf(mySum); + } +}; + +// NormHamming + +struct NormHamming +{ + typedef int value_type; + typedef int result_type; + + result_type mySum; + + __device__ __forceinline__ NormHamming() : mySum(0) {} + + __device__ __forceinline__ void reduceThread(value_type val1, value_type val2) + { + mySum += __popc(val1 ^ val2); + } + + __device__ __forceinline__ void reduceWarp(result_type* smem, uint tid) + { + warpReduce(smem, mySum, tid, plus()); + } + + template __device__ __forceinline__ void reduceBlock(result_type* smem, uint tid) + { + blockReduce(smem, mySum, tid, plus()); + } + + __device__ __forceinline__ operator result_type() const + { + return mySum; + } +}; + +}} + +#endif diff --git a/modules/gpu/src/ffmpeg_video_source.h b/modules/cudev/include/opencv2/cudev/common.hpp similarity index 65% rename from modules/gpu/src/ffmpeg_video_source.h rename to modules/cudev/include/opencv2/cudev/common.hpp index 41bf0cfd0e..be79901729 100644 --- a/modules/gpu/src/ffmpeg_video_source.h +++ b/modules/cudev/include/opencv2/cudev/common.hpp @@ -12,6 +12,7 @@ // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -40,49 +41,53 @@ // //M*/ -#ifndef __FFMPEG_VIDEO_SOURCE_H__ -#define __FFMPEG_VIDEO_SOURCE_H__ +#pragma once -#include "precomp.hpp" -#include "thread_wrappers.h" +#ifndef __OPENCV_CUDEV_COMMON_HPP__ +#define __OPENCV_CUDEV_COMMON_HPP__ -#if defined(HAVE_CUDA) && defined(HAVE_NVCUVID) +#include +#include "opencv2/core/gpu.hpp" +#include "opencv2/core/gpu_stream_accessor.hpp" -struct InputMediaStream_FFMPEG; +namespace cv { namespace cudev { -namespace cv { namespace gpu +using namespace cv::gpu; + +// CV_CUDEV_ARCH + +#ifndef __CUDA_ARCH__ +# define CV_CUDEV_ARCH 0 +#else +# define CV_CUDEV_ARCH __CUDA_ARCH__ +#endif + +// CV_CUDEV_SAFE_CALL + +__host__ __forceinline__ void checkCudaError(cudaError_t err, const char* file, const int line, const char* func) { - namespace detail - { - class FFmpegVideoSource : public VideoReader_GPU::VideoSource - { - public: - FFmpegVideoSource(const std::string& fname); - ~FFmpegVideoSource(); + if (cudaSuccess != err) + cv::error(cv::Error::GpuApiCallError, cudaGetErrorString(err), func, file, line); +} - VideoReader_GPU::FormatInfo format() const; - void start(); - void stop(); - bool isStarted() const; - bool hasError() const; +#ifdef __GNUC__ +# define CV_CUDEV_SAFE_CALL(expr) cv::cudev::checkCudaError((expr), __FILE__, __LINE__, __func__) +#else +# define CV_CUDEV_SAFE_CALL(expr) cv::cudev::checkCudaError((expr), __FILE__, __LINE__, "") +#endif - private: - FFmpegVideoSource(const FFmpegVideoSource&); - FFmpegVideoSource& operator =(const FFmpegVideoSource&); +// divUp - VideoReader_GPU::FormatInfo format_; +__host__ __device__ __forceinline__ int divUp(int total, int grain) +{ + return (total + grain - 1) / grain; +} - InputMediaStream_FFMPEG* stream_; +// math constants - std::auto_ptr thread_; - volatile bool stop_; - volatile bool hasError_; +#define CV_PI_F ((float)CV_PI) +#define CV_LOG2_F ((float)CV_LOG2) - static void readLoop(void* userData); - }; - } }} -#endif // HAVE_CUDA - -#endif // __CUVUD_VIDEO_SOURCE_H__ +#endif diff --git a/modules/cudev/include/opencv2/cudev/expr/binary_func.hpp b/modules/cudev/include/opencv2/cudev/expr/binary_func.hpp new file mode 100644 index 0000000000..f35ea2dc3c --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/expr/binary_func.hpp @@ -0,0 +1,75 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_EXPR_BINARY_FUNC_HPP__ +#define __OPENCV_CUDEV_EXPR_BINARY_FUNC_HPP__ + +#include "../common.hpp" +#include "../util/type_traits.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/transform.hpp" +#include "../functional/functional.hpp" +#include "expr.hpp" + +namespace cv { namespace cudev { + +#define CV_CUDEV_EXPR_BINARY_FUNC(name) \ + template \ + __host__ Expr::ptr_type, typename PtrTraits::ptr_type, name ## _func::value_type, typename PtrTraits::value_type>::type> > > \ + name ## _(const SrcPtr1& src1, const SrcPtr2& src2) \ + { \ + return makeExpr(transformPtr(src1, src2, name ## _func::value_type, typename PtrTraits::value_type>::type>())); \ + } + +CV_CUDEV_EXPR_BINARY_FUNC(hypot) +CV_CUDEV_EXPR_BINARY_FUNC(magnitude) +CV_CUDEV_EXPR_BINARY_FUNC(atan2) +CV_CUDEV_EXPR_BINARY_FUNC(absdiff) + +#undef CV_CUDEV_EXPR_BINARY_FUNC + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/expr/binary_op.hpp b/modules/cudev/include/opencv2/cudev/expr/binary_op.hpp new file mode 100644 index 0000000000..f7e9655720 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/expr/binary_op.hpp @@ -0,0 +1,235 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_EXPR_BINARY_OP_HPP__ +#define __OPENCV_CUDEV_EXPR_BINARY_OP_HPP__ + +#include "../common.hpp" +#include "../util/type_traits.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/transform.hpp" +#include "../ptr2d/gpumat.hpp" +#include "../ptr2d/texture.hpp" +#include "../ptr2d/glob.hpp" +#include "../functional/functional.hpp" +#include "expr.hpp" + +namespace cv { namespace cudev { + +// Binary Operations + +#define CV_CUDEV_EXPR_BINOP_INST(op, functor) \ + template \ + __host__ Expr >::ptr_type, typename PtrTraits >::ptr_type, functor > > \ + operator op(const GpuMat_& src1, const GpuMat_& src2) \ + { \ + return makeExpr(transformPtr(src1, src2, functor())); \ + } \ + template \ + __host__ Expr >::ptr_type, typename PtrTraits >::ptr_type, functor > > \ + operator op(const GpuMat_& src1, const GlobPtrSz& src2) \ + { \ + return makeExpr(transformPtr(src1, src2, functor())); \ + } \ + template \ + __host__ Expr >::ptr_type, typename PtrTraits >::ptr_type, functor > > \ + operator op(const GlobPtrSz& src1, const GpuMat_& src2) \ + { \ + return makeExpr(transformPtr(src1, src2, functor())); \ + } \ + template \ + __host__ Expr >::ptr_type, typename PtrTraits >::ptr_type, functor > > \ + operator op(const GpuMat_& src1, const Texture& src2) \ + { \ + return makeExpr(transformPtr(src1, src2, functor())); \ + } \ + template \ + __host__ Expr >::ptr_type, typename PtrTraits >::ptr_type, functor > > \ + operator op(const Texture& src1, const GpuMat_& src2) \ + { \ + return makeExpr(transformPtr(src1, src2, functor())); \ + } \ + template \ + __host__ Expr >::ptr_type, typename PtrTraits::ptr_type, functor::value_type>::type> > > \ + operator op(const GpuMat_& src1, const Expr& src2) \ + { \ + return makeExpr(transformPtr(src1, src2.body, functor::value_type>::type>())); \ + } \ + template \ + __host__ Expr::ptr_type, typename PtrTraits >::ptr_type, functor::value_type>::type> > > \ + operator op(const Expr& src1, const GpuMat_& src2) \ + { \ + return makeExpr(transformPtr(src1.body, src2, functor::value_type>::type>())); \ + } \ + template \ + __host__ Expr >::ptr_type, Binder2nd< functor > > > \ + operator op(const GpuMat_& src, T val) \ + { \ + return makeExpr(transformPtr(src, bind2nd(functor(), val))); \ + } \ + template \ + __host__ Expr >::ptr_type, Binder1st< functor > > > \ + operator op(T val, const GpuMat_& src) \ + { \ + return makeExpr(transformPtr(src, bind1st(functor(), val))); \ + } \ + template \ + __host__ Expr >::ptr_type, typename PtrTraits >::ptr_type, functor > > \ + operator op(const GlobPtrSz& src1, const GlobPtrSz& src2) \ + { \ + return makeExpr(transformPtr(src1, src2, functor())); \ + } \ + template \ + __host__ Expr >::ptr_type, typename PtrTraits >::ptr_type, functor > > \ + operator op(const GlobPtrSz& src1, const Texture& src2) \ + { \ + return makeExpr(transformPtr(src1, src2, functor())); \ + } \ + template \ + __host__ Expr >::ptr_type, typename PtrTraits >::ptr_type, functor > > \ + operator op(const Texture& src1, const GlobPtrSz& src2) \ + { \ + return makeExpr(transformPtr(src1, src2, functor())); \ + } \ + template \ + __host__ Expr >::ptr_type, typename PtrTraits::ptr_type, functor::value_type>::type> > > \ + operator op(const GlobPtrSz& src1, const Expr& src2) \ + { \ + return makeExpr(transformPtr(src1, src2.body, functor::value_type>::type>())); \ + } \ + template \ + __host__ Expr::ptr_type, typename PtrTraits >::ptr_type, functor::value_type>::type> > > \ + operator op(const Expr& src1, const GlobPtrSz& src2) \ + { \ + return makeExpr(transformPtr(src1.body, src2, functor::value_type>::type>())); \ + } \ + template \ + __host__ Expr >::ptr_type, Binder2nd< functor > > > \ + operator op(const GlobPtrSz& src, T val) \ + { \ + return makeExpr(transformPtr(src, bind2nd(functor(), val))); \ + } \ + template \ + __host__ Expr >::ptr_type, Binder1st< functor > > > \ + operator op(T val, const GlobPtrSz& src) \ + { \ + return makeExpr(transformPtr(src, bind1st(functor(), val))); \ + } \ + template \ + __host__ Expr >::ptr_type, typename PtrTraits >::ptr_type, functor > > \ + operator op(const Texture& src1, const Texture& src2) \ + { \ + return makeExpr(transformPtr(src1, src2, functor())); \ + } \ + template \ + __host__ Expr >::ptr_type, typename PtrTraits::ptr_type, functor::value_type>::type> > > \ + operator op(const Texture& src1, const Expr& src2) \ + { \ + return makeExpr(transformPtr(src1, src2.body, functor::value_type>::type>())); \ + } \ + template \ + __host__ Expr::ptr_type, typename PtrTraits >::ptr_type, functor::value_type>::type> > > \ + operator op(const Expr& src1, const Texture& src2) \ + { \ + return makeExpr(transformPtr(src1.body, src2, functor::value_type>::type>())); \ + } \ + template \ + __host__ Expr >::ptr_type, Binder2nd< functor > > > \ + operator op(const Texture& src, T val) \ + { \ + return makeExpr(transformPtr(src, bind2nd(functor(), val))); \ + } \ + template \ + __host__ Expr >::ptr_type, Binder1st< functor > > > \ + operator op(T val, const Texture& src) \ + { \ + return makeExpr(transformPtr(src, bind1st(functor(), val))); \ + } \ + template \ + __host__ Expr::ptr_type, typename PtrTraits::ptr_type, functor::value_type, typename PtrTraits::value_type>::type> > > \ + operator op(const Expr& a, const Expr& b) \ + { \ + return makeExpr(transformPtr(a.body, b.body, functor::value_type, typename PtrTraits::value_type>::type>())); \ + } \ + template \ + __host__ Expr::ptr_type, Binder2nd< functor > > > \ + operator op(const Expr& a, typename Body::value_type val) \ + { \ + return makeExpr(transformPtr(a.body, bind2nd(functor(), val))); \ + } \ + template \ + __host__ Expr::ptr_type, Binder1st< functor > > > \ + operator op(typename Body::value_type val, const Expr& a) \ + { \ + return makeExpr(transformPtr(a.body, bind1st(functor(), val))); \ + } + +CV_CUDEV_EXPR_BINOP_INST(+, plus) +CV_CUDEV_EXPR_BINOP_INST(-, minus) +CV_CUDEV_EXPR_BINOP_INST(*, multiplies) +CV_CUDEV_EXPR_BINOP_INST(/, divides) +CV_CUDEV_EXPR_BINOP_INST(%, modulus) + +CV_CUDEV_EXPR_BINOP_INST(==, equal_to) +CV_CUDEV_EXPR_BINOP_INST(!=, not_equal_to) +CV_CUDEV_EXPR_BINOP_INST(>, greater) +CV_CUDEV_EXPR_BINOP_INST(<, less) +CV_CUDEV_EXPR_BINOP_INST(>=, greater_equal) +CV_CUDEV_EXPR_BINOP_INST(<=, less_equal) + +CV_CUDEV_EXPR_BINOP_INST(&&, logical_and) +CV_CUDEV_EXPR_BINOP_INST(||, logical_or) + +CV_CUDEV_EXPR_BINOP_INST(&, bit_and) +CV_CUDEV_EXPR_BINOP_INST(|, bit_or) +CV_CUDEV_EXPR_BINOP_INST(^, bit_xor) +CV_CUDEV_EXPR_BINOP_INST(<<, bit_lshift) +CV_CUDEV_EXPR_BINOP_INST(>>, bit_rshift) + +#undef CV_CUDEV_EXPR_BINOP_INST + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/expr/color.hpp b/modules/cudev/include/opencv2/cudev/expr/color.hpp new file mode 100644 index 0000000000..13f07c15a4 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/expr/color.hpp @@ -0,0 +1,282 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_EXPR_COLOR_HPP__ +#define __OPENCV_CUDEV_EXPR_COLOR_HPP__ + +#include "../common.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/transform.hpp" +#include "../functional/color_cvt.hpp" +#include "expr.hpp" + +namespace cv { namespace cudev { + +#define CV_CUDEV_EXPR_CVTCOLOR_INST(name) \ + template \ + __host__ Expr::ptr_type, name ## _func::value_type>::elem_type> > > \ + name ## _(const SrcPtr& src) \ + { \ + return makeExpr(transformPtr(src, name ## _func::value_type>::elem_type>())); \ + } + +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_RGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_BGRA) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_RGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_BGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_RGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_RGBA) + +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_GRAY) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_GRAY) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_GRAY) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_GRAY) + +CV_CUDEV_EXPR_CVTCOLOR_INST(GRAY_to_BGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(GRAY_to_BGRA) + +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_YUV) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_YUV) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_YUV4) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_YUV4) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_YUV) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_YUV) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_YUV4) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_YUV4) + +CV_CUDEV_EXPR_CVTCOLOR_INST(YUV_to_RGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(YUV_to_RGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(YUV4_to_RGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(YUV4_to_RGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(YUV_to_BGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(YUV_to_BGRA) +CV_CUDEV_EXPR_CVTCOLOR_INST(YUV4_to_BGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(YUV4_to_BGRA) + +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_YCrCb) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_YCrCb) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_YCrCb4) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_YCrCb4) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_YCrCb) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_YCrCb) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_YCrCb4) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_YCrCb4) + +CV_CUDEV_EXPR_CVTCOLOR_INST(YCrCb_to_RGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(YCrCb_to_RGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(YCrCb4_to_RGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(YCrCb4_to_RGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(YCrCb_to_BGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(YCrCb_to_BGRA) +CV_CUDEV_EXPR_CVTCOLOR_INST(YCrCb4_to_BGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(YCrCb4_to_BGRA) + +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_XYZ) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_XYZ) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_XYZ4) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_XYZ4) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_XYZ) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_XYZ) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_XYZ4) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_XYZ4) + +CV_CUDEV_EXPR_CVTCOLOR_INST(XYZ_to_RGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(XYZ4_to_RGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(XYZ_to_RGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(XYZ4_to_RGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(XYZ_to_BGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(XYZ4_to_BGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(XYZ_to_BGRA) +CV_CUDEV_EXPR_CVTCOLOR_INST(XYZ4_to_BGRA) + +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_HSV) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_HSV) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_HSV4) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_HSV4) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_HSV) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_HSV) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_HSV4) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_HSV4) + +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_HSV_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_HSV_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_HSV4_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_HSV4_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_HSV_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_HSV_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_HSV4_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_HSV4_FULL) + +CV_CUDEV_EXPR_CVTCOLOR_INST(HSV_to_RGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(HSV_to_RGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(HSV4_to_RGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(HSV4_to_RGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(HSV_to_BGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(HSV_to_BGRA) +CV_CUDEV_EXPR_CVTCOLOR_INST(HSV4_to_BGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(HSV4_to_BGRA) + +CV_CUDEV_EXPR_CVTCOLOR_INST(HSV_to_RGB_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(HSV_to_RGBA_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(HSV4_to_RGB_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(HSV4_to_RGBA_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(HSV_to_BGR_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(HSV_to_BGRA_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(HSV4_to_BGR_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(HSV4_to_BGRA_FULL) + +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_HLS) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_HLS) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_HLS4) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_HLS4) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_HLS) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_HLS) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_HLS4) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_HLS4) + +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_HLS_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_HLS_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_HLS4_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_HLS4_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_HLS_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_HLS_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_HLS4_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_HLS4_FULL) + +CV_CUDEV_EXPR_CVTCOLOR_INST(HLS_to_RGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(HLS_to_RGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(HLS4_to_RGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(HLS4_to_RGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(HLS_to_BGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(HLS_to_BGRA) +CV_CUDEV_EXPR_CVTCOLOR_INST(HLS4_to_BGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(HLS4_to_BGRA) + +CV_CUDEV_EXPR_CVTCOLOR_INST(HLS_to_RGB_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(HLS_to_RGBA_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(HLS4_to_RGB_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(HLS4_to_RGBA_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(HLS_to_BGR_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(HLS_to_BGRA_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(HLS4_to_BGR_FULL) +CV_CUDEV_EXPR_CVTCOLOR_INST(HLS4_to_BGRA_FULL) + +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_Lab) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_Lab) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_Lab4) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_Lab4) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_Lab) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_Lab) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_Lab4) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_Lab4) + +CV_CUDEV_EXPR_CVTCOLOR_INST(LRGB_to_Lab) +CV_CUDEV_EXPR_CVTCOLOR_INST(LRGBA_to_Lab) +CV_CUDEV_EXPR_CVTCOLOR_INST(LRGB_to_Lab4) +CV_CUDEV_EXPR_CVTCOLOR_INST(LRGBA_to_Lab4) +CV_CUDEV_EXPR_CVTCOLOR_INST(LBGR_to_Lab) +CV_CUDEV_EXPR_CVTCOLOR_INST(LBGRA_to_Lab) +CV_CUDEV_EXPR_CVTCOLOR_INST(LBGR_to_Lab4) +CV_CUDEV_EXPR_CVTCOLOR_INST(LBGRA_to_Lab4) + +CV_CUDEV_EXPR_CVTCOLOR_INST(Lab_to_RGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(Lab4_to_RGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(Lab_to_RGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(Lab4_to_RGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(Lab_to_BGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(Lab4_to_BGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(Lab_to_BGRA) +CV_CUDEV_EXPR_CVTCOLOR_INST(Lab4_to_BGRA) + +CV_CUDEV_EXPR_CVTCOLOR_INST(Lab_to_LRGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(Lab4_to_LRGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(Lab_to_LRGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(Lab4_to_LRGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(Lab_to_LBGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(Lab4_to_LBGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(Lab_to_LBGRA) +CV_CUDEV_EXPR_CVTCOLOR_INST(Lab4_to_LBGRA) + +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_Luv) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_Luv) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGB_to_Luv4) +CV_CUDEV_EXPR_CVTCOLOR_INST(RGBA_to_Luv4) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_Luv) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_Luv) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGR_to_Luv4) +CV_CUDEV_EXPR_CVTCOLOR_INST(BGRA_to_Luv4) + +CV_CUDEV_EXPR_CVTCOLOR_INST(LRGB_to_Luv) +CV_CUDEV_EXPR_CVTCOLOR_INST(LRGBA_to_Luv) +CV_CUDEV_EXPR_CVTCOLOR_INST(LRGB_to_Luv4) +CV_CUDEV_EXPR_CVTCOLOR_INST(LRGBA_to_Luv4) +CV_CUDEV_EXPR_CVTCOLOR_INST(LBGR_to_Luv) +CV_CUDEV_EXPR_CVTCOLOR_INST(LBGRA_to_Luv) +CV_CUDEV_EXPR_CVTCOLOR_INST(LBGR_to_Luv4) +CV_CUDEV_EXPR_CVTCOLOR_INST(LBGRA_to_Luv4) + +CV_CUDEV_EXPR_CVTCOLOR_INST(Luv_to_RGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(Luv4_to_RGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(Luv_to_RGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(Luv4_to_RGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(Luv_to_BGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(Luv4_to_BGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(Luv_to_BGRA) +CV_CUDEV_EXPR_CVTCOLOR_INST(Luv4_to_BGRA) + +CV_CUDEV_EXPR_CVTCOLOR_INST(Luv_to_LRGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(Luv4_to_LRGB) +CV_CUDEV_EXPR_CVTCOLOR_INST(Luv_to_LRGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(Luv4_to_LRGBA) +CV_CUDEV_EXPR_CVTCOLOR_INST(Luv_to_LBGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(Luv4_to_LBGR) +CV_CUDEV_EXPR_CVTCOLOR_INST(Luv_to_LBGRA) +CV_CUDEV_EXPR_CVTCOLOR_INST(Luv4_to_LBGRA) + +#undef CV_CUDEV_EXPR_CVTCOLOR_INST + +}} + +#endif diff --git a/modules/gpu/src/cuvid_video_source.h b/modules/cudev/include/opencv2/cudev/expr/deriv.hpp similarity index 58% rename from modules/gpu/src/cuvid_video_source.h rename to modules/cudev/include/opencv2/cudev/expr/deriv.hpp index 1c4c0e5e00..822a86b9a3 100644 --- a/modules/gpu/src/cuvid_video_source.h +++ b/modules/cudev/include/opencv2/cudev/expr/deriv.hpp @@ -12,6 +12,7 @@ // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -40,51 +41,81 @@ // //M*/ -#ifndef __CUVUD_VIDEO_SOURCE_H__ -#define __CUVUD_VIDEO_SOURCE_H__ +#pragma once -#include "precomp.hpp" +#ifndef __OPENCV_CUDEV_EXPR_DERIV_HPP__ +#define __OPENCV_CUDEV_EXPR_DERIV_HPP__ -#if defined(HAVE_CUDA) && defined(HAVE_NVCUVID) +#include "../common.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/deriv.hpp" +#include "expr.hpp" -namespace cv { namespace gpu +namespace cv { namespace cudev { + +// derivX + +template +__host__ Expr::ptr_type> > +derivX_(const SrcPtr& src) { - namespace detail - { - class CuvidVideoSource : public VideoReader_GPU::VideoSource - { - public: - explicit CuvidVideoSource(const std::string& fname); - ~CuvidVideoSource() { cuvidDestroyVideoSource(videoSource_); } + return makeExpr(derivXPtr(src)); +} - VideoReader_GPU::FormatInfo format() const; - void start(); - void stop(); - bool isStarted() const; - bool hasError() const; +// derivY - private: - CuvidVideoSource(const CuvidVideoSource&); - CuvidVideoSource& operator =(const CuvidVideoSource&); +template +__host__ Expr::ptr_type> > +derivY_(const SrcPtr& src) +{ + return makeExpr(derivYPtr(src)); +} - // Callback for handling packages of demuxed video data. - // - // Parameters: - // pUserData - Pointer to user data. We must pass a pointer to a - // VideoSourceData struct here, that contains a valid CUvideoparser - // and FrameQueue. - // pPacket - video-source data packet. - // - // NOTE: called from a different thread that doesn't not have a cuda context - // - static int CUDAAPI HandleVideoData(void* pUserData, CUVIDSOURCEDATAPACKET* pPacket); +// sobelX + +template +__host__ Expr::ptr_type> > +sobelX_(const SrcPtr& src) +{ + return makeExpr(sobelXPtr(src)); +} + +// sobelY + +template +__host__ Expr::ptr_type> > +sobelY_(const SrcPtr& src) +{ + return makeExpr(sobelYPtr(src)); +} + +// scharrX + +template +__host__ Expr::ptr_type> > +scharrX_(const SrcPtr& src) +{ + return makeExpr(scharrXPtr(src)); +} + +// scharrY + +template +__host__ Expr::ptr_type> > +scharrY_(const SrcPtr& src) +{ + return makeExpr(scharrYPtr(src)); +} + +// laplacian + +template +__host__ Expr::ptr_type> > +laplacian_(const SrcPtr& src) +{ + return makeExpr(laplacianPtr(src)); +} - CUvideosource videoSource_; - VideoReader_GPU::FormatInfo format_; - }; - } }} -#endif // defined(HAVE_CUDA) && !defined(__APPLE__) - -#endif // __CUVUD_VIDEO_SOURCE_H__ +#endif diff --git a/modules/cudev/include/opencv2/cudev/expr/expr.hpp b/modules/cudev/include/opencv2/cudev/expr/expr.hpp new file mode 100644 index 0000000000..46c780b4a2 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/expr/expr.hpp @@ -0,0 +1,92 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_EXPR_EXPR_HPP__ +#define __OPENCV_CUDEV_EXPR_EXPR_HPP__ + +#include "../common.hpp" +#include "../ptr2d/traits.hpp" + +namespace cv { namespace cudev { + +template struct Expr +{ + Body body; +}; + +template +__host__ Expr makeExpr(const Body& body) +{ + Expr e; + e.body = body; + return e; +} + +template struct PtrTraits< Expr > +{ + typedef Expr ptr_sz_type; + typedef typename PtrTraits::ptr_type ptr_type; + + typedef typename ptr_type::value_type value_type; + + __host__ static ptr_type shrinkPtr(const Expr& expr) + { + return PtrTraits::shrinkPtr(expr.body); + } + + __host__ static int getRows(const Expr& expr) + { + return PtrTraits::getRows(expr.body); + } + + __host__ static int getCols(const Expr& expr) + { + return PtrTraits::getCols(expr.body); + } +}; + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/expr/per_element_func.hpp b/modules/cudev/include/opencv2/cudev/expr/per_element_func.hpp new file mode 100644 index 0000000000..56a067de9d --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/expr/per_element_func.hpp @@ -0,0 +1,132 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_EXPR_PER_ELEMENT_FUNC_HPP__ +#define __OPENCV_CUDEV_EXPR_PER_ELEMENT_FUNC_HPP__ + +#include "../common.hpp" +#include "../util/type_traits.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/transform.hpp" +#include "../ptr2d/lut.hpp" +#include "../functional/functional.hpp" +#include "expr.hpp" + +namespace cv { namespace cudev { + +// min/max + +template +__host__ Expr::ptr_type, typename PtrTraits::ptr_type, minimum::value_type, typename PtrTraits::value_type>::type> > > +min_(const SrcPtr1& src1, const SrcPtr2& src2) +{ + return makeExpr(transformPtr(src1, src2, minimum::value_type, typename PtrTraits::value_type>::type>())); +} + +template +__host__ Expr::ptr_type, typename PtrTraits::ptr_type, maximum::value_type, typename PtrTraits::value_type>::type> > > +max_(const SrcPtr1& src1, const SrcPtr2& src2) +{ + return makeExpr(transformPtr(src1, src2, maximum::value_type, typename PtrTraits::value_type>::type>())); +} + +// threshold + +template +__host__ Expr::ptr_type, ThreshBinaryFunc::value_type> > > +threshBinary_(const SrcPtr& src, typename PtrTraits::value_type thresh, typename PtrTraits::value_type maxVal) +{ + return makeExpr(transformPtr(src, thresh_binary_func(thresh, maxVal))); +} + +template +__host__ Expr::ptr_type, ThreshBinaryInvFunc::value_type> > > +threshBinaryInv_(const SrcPtr& src, typename PtrTraits::value_type thresh, typename PtrTraits::value_type maxVal) +{ + return makeExpr(transformPtr(src, thresh_binary_inv_func(thresh, maxVal))); +} + +template +__host__ Expr::ptr_type, ThreshTruncFunc::value_type> > > +threshTrunc_(const SrcPtr& src, typename PtrTraits::value_type thresh) +{ + return makeExpr(transformPtr(src, thresh_trunc_func(thresh))); +} + +template +__host__ Expr::ptr_type, ThreshToZeroFunc::value_type> > > +threshToZero_(const SrcPtr& src, typename PtrTraits::value_type thresh) +{ + return makeExpr(transformPtr(src, thresh_to_zero_func(thresh))); +} + +template +__host__ Expr::ptr_type, ThreshToZeroInvFunc::value_type> > > +threshToZeroInv_(const SrcPtr& src, typename PtrTraits::value_type thresh) +{ + return makeExpr(transformPtr(src, thresh_to_zero_inv_func(thresh))); +} + +// cvt + +template +__host__ Expr::ptr_type, saturate_cast_func::value_type, D> > > +cvt_(const SrcPtr& src) +{ + return makeExpr(transformPtr(src, saturate_cast_func::value_type, D>())); +} + +// lut + +template +__host__ Expr::ptr_type, typename PtrTraits::ptr_type> > +lut_(const SrcPtr& src, const TablePtr& tbl) +{ + return makeExpr(lutPtr(src, tbl)); +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/expr/reduction.hpp b/modules/cudev/include/opencv2/cudev/expr/reduction.hpp new file mode 100644 index 0000000000..0fdde02e53 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/expr/reduction.hpp @@ -0,0 +1,259 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_EXPR_REDUCTION_HPP__ +#define __OPENCV_CUDEV_EXPR_REDUCTION_HPP__ + +#include "../common.hpp" +#include "../grid/glob_reduce.hpp" +#include "../grid/histogram.hpp" +#include "../grid/integral.hpp" +#include "../grid/reduce_to_vec.hpp" +#include "../ptr2d/traits.hpp" +#include "expr.hpp" + +namespace cv { namespace cudev { + +// sum + +template struct SumExprBody +{ + SrcPtr src; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridCalcSum(src, dst, stream); + } +}; + +template +__host__ Expr > +sum_(const SrcPtr& src) +{ + SumExprBody body; + body.src = src; + return makeExpr(body); +} + +// minVal + +template struct FindMinValExprBody +{ + SrcPtr src; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridFindMinVal(src, dst, stream); + } +}; + +template +__host__ Expr > +minVal_(const SrcPtr& src) +{ + FindMinValExprBody body; + body.src = src; + return makeExpr(body); +} + +// maxVal + +template struct FindMaxValExprBody +{ + SrcPtr src; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridFindMaxVal(src, dst, stream); + } +}; + +template +__host__ Expr > +maxVal_(const SrcPtr& src) +{ + FindMaxValExprBody body; + body.src = src; + return makeExpr(body); +} + +// minMaxVal + +template struct FindMinMaxValExprBody +{ + SrcPtr src; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridFindMinMaxVal(src, dst, stream); + } +}; + +template +__host__ Expr > +minMaxVal_(const SrcPtr& src) +{ + FindMinMaxValExprBody body; + body.src = src; + return makeExpr(body); +} + +// countNonZero + +template struct CountNonZeroExprBody +{ + SrcPtr src; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridCountNonZero(src, dst, stream); + } +}; + +template +__host__ Expr > +countNonZero_(const SrcPtr& src) +{ + CountNonZeroExprBody body; + body.src = src; + return makeExpr(body); +} + +// reduceToRow + +template struct ReduceToRowBody +{ + SrcPtr src; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridReduceToRow(src, dst, stream); + } +}; + +template +__host__ Expr > +reduceToRow_(const SrcPtr& src) +{ + ReduceToRowBody body; + body.src = src; + return makeExpr(body); +} + +// reduceToColumn + +template struct ReduceToColumnBody +{ + SrcPtr src; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridReduceToColumn(src, dst, stream); + } +}; + +template +__host__ Expr > +reduceToColumn_(const SrcPtr& src) +{ + ReduceToColumnBody body; + body.src = src; + return makeExpr(body); +} + +// histogram + +template struct HistogramBody +{ + SrcPtr src; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridHistogram(src, dst, stream); + } +}; + +template +__host__ Expr > +histogram_(const SrcPtr& src) +{ + HistogramBody body; + body.src = src; + return makeExpr(body); +} + +// integral + +template struct IntegralBody +{ + SrcPtr src; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridIntegral(src, dst, stream); + } +}; + +template +__host__ Expr > +integral_(const SrcPtr& src) +{ + IntegralBody body; + body.src = src; + return makeExpr(body); +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/expr/unary_func.hpp b/modules/cudev/include/opencv2/cudev/expr/unary_func.hpp new file mode 100644 index 0000000000..a30f6a6f3c --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/expr/unary_func.hpp @@ -0,0 +1,98 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_EXPR_UNARY_FUNC_HPP__ +#define __OPENCV_CUDEV_EXPR_UNARY_FUNC_HPP__ + +#include "../common.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/transform.hpp" +#include "../functional/functional.hpp" +#include "expr.hpp" + +namespace cv { namespace cudev { + +#define CV_CUDEV_EXPR_UNARY_FUNC(name) \ + template \ + __host__ Expr::ptr_type, name ## _func::value_type> > > \ + name ## _(const SrcPtr& src) \ + { \ + return makeExpr(transformPtr(src, name ## _func::value_type>())); \ + } + +CV_CUDEV_EXPR_UNARY_FUNC(abs) +CV_CUDEV_EXPR_UNARY_FUNC(sqr) +CV_CUDEV_EXPR_UNARY_FUNC(sqrt) +CV_CUDEV_EXPR_UNARY_FUNC(exp) +CV_CUDEV_EXPR_UNARY_FUNC(exp2) +CV_CUDEV_EXPR_UNARY_FUNC(exp10) +CV_CUDEV_EXPR_UNARY_FUNC(log) +CV_CUDEV_EXPR_UNARY_FUNC(log2) +CV_CUDEV_EXPR_UNARY_FUNC(log10) +CV_CUDEV_EXPR_UNARY_FUNC(sin) +CV_CUDEV_EXPR_UNARY_FUNC(cos) +CV_CUDEV_EXPR_UNARY_FUNC(tan) +CV_CUDEV_EXPR_UNARY_FUNC(asin) +CV_CUDEV_EXPR_UNARY_FUNC(acos) +CV_CUDEV_EXPR_UNARY_FUNC(atan) +CV_CUDEV_EXPR_UNARY_FUNC(sinh) +CV_CUDEV_EXPR_UNARY_FUNC(cosh) +CV_CUDEV_EXPR_UNARY_FUNC(tanh) +CV_CUDEV_EXPR_UNARY_FUNC(asinh) +CV_CUDEV_EXPR_UNARY_FUNC(acosh) +CV_CUDEV_EXPR_UNARY_FUNC(atanh) + +#undef CV_CUDEV_EXPR_UNARY_FUNC + +template +__host__ Expr::ptr_type, Binder2nd::value_type> > > > +pow_(const SrcPtr& src, float power) +{ + return makeExpr(transformPtr(src, bind2nd(pow_func::value_type>(), power))); +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/expr/unary_op.hpp b/modules/cudev/include/opencv2/cudev/expr/unary_op.hpp new file mode 100644 index 0000000000..905013e42f --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/expr/unary_op.hpp @@ -0,0 +1,94 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_EXPR_UNARY_OP_HPP__ +#define __OPENCV_CUDEV_EXPR_UNARY_OP_HPP__ + +#include "../common.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/transform.hpp" +#include "../ptr2d/gpumat.hpp" +#include "../ptr2d/texture.hpp" +#include "../ptr2d/glob.hpp" +#include "../functional/functional.hpp" +#include "expr.hpp" + +namespace cv { namespace cudev { + +#define CV_CUDEV_EXPR_UNOP_INST(op, functor) \ + template \ + __host__ Expr >::ptr_type, functor > > \ + operator op(const GpuMat_& src) \ + { \ + return makeExpr(transformPtr(src, functor())); \ + } \ + template \ + __host__ Expr >::ptr_type, functor > > \ + operator op(const GlobPtrSz& src) \ + { \ + return makeExpr(transformPtr(src, functor())); \ + } \ + template \ + __host__ Expr >::ptr_type, functor > > \ + operator op(const Texture& src) \ + { \ + return makeExpr(transformPtr(src, functor())); \ + } \ + template \ + __host__ Expr::ptr_type, functor > > \ + operator op(const Expr& src) \ + { \ + return makeExpr(transformPtr(src.body, functor())); \ + } + +CV_CUDEV_EXPR_UNOP_INST(-, negate) +CV_CUDEV_EXPR_UNOP_INST(!, logical_not) +CV_CUDEV_EXPR_UNOP_INST(~, bit_not) + +#undef CV_CUDEV_EXPR_UNOP_INST + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/expr/warping.hpp b/modules/cudev/include/opencv2/cudev/expr/warping.hpp new file mode 100644 index 0000000000..f942a3fb6f --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/expr/warping.hpp @@ -0,0 +1,171 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_EXPR_WARPING_HPP__ +#define __OPENCV_CUDEV_EXPR_WARPING_HPP__ + +#include "../common.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/resize.hpp" +#include "../ptr2d/remap.hpp" +#include "../ptr2d/warping.hpp" +#include "../grid/pyramids.hpp" +#include "../grid/transpose.hpp" +#include "expr.hpp" + +namespace cv { namespace cudev { + +// resize + +template +__host__ Expr::ptr_type> > +resize_(const SrcPtr& src, float fx, float fy) +{ + return makeExpr(resizePtr(src, fx, fy)); +} + +// remap + +template +__host__ Expr::ptr_type, typename PtrTraits::ptr_type> > +remap_(const SrcPtr& src, const MapPtr& map) +{ + return makeExpr(remapPtr(src, map)); +} + +template +__host__ Expr::ptr_type, typename PtrTraits::ptr_type, typename PtrTraits::ptr_type> > +remap_(const SrcPtr& src, const MapXPtr& mapx, const MapYPtr& mapy) +{ + return makeExpr(remapPtr(src, mapx, mapy)); +} + +// warpAffine + +template +__host__ Expr::ptr_type, AffineMapPtr> > +warpAffine_(const SrcPtr& src, Size dstSize, const GpuMat_& warpMat) +{ + return makeExpr(warpAffinePtr(src, dstSize, warpMat)); +} + +// warpPerspective + +template +__host__ Expr::ptr_type, PerspectiveMapPtr> > +warpPerspective_(const SrcPtr& src, Size dstSize, const GpuMat_& warpMat) +{ + return makeExpr(warpPerspectivePtr(src, dstSize, warpMat)); +} + +// pyrDown + +template struct PyrDownBody +{ + SrcPtr src; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridPyrDown(src, dst, stream); + } +}; + +template +__host__ Expr > +pyrDown_(const SrcPtr& src) +{ + PyrDownBody body; + body.src = src; + return makeExpr(body); +} + +// pyrUp + +template struct PyrUpBody +{ + SrcPtr src; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridPyrUp(src, dst, stream); + } +}; + +template +__host__ Expr > +pyrUp_(const SrcPtr& src) +{ + PyrUpBody body; + body.src = src; + return makeExpr(body); +} + +// transpose + +template struct TransposeBody +{ + SrcPtr src; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridTranspose(src, dst, stream); + } +}; + +template +__host__ Expr > +transpose_(const SrcPtr& src) +{ + TransposeBody body; + body.src = src; + return makeExpr(body); +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/functional/color_cvt.hpp b/modules/cudev/include/opencv2/cudev/functional/color_cvt.hpp new file mode 100644 index 0000000000..8be854780a --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/functional/color_cvt.hpp @@ -0,0 +1,474 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_FUNCTIONAL_COLOR_CVT_HPP__ +#define __OPENCV_CUDEV_FUNCTIONAL_COLOR_CVT_HPP__ + +#include "../common.hpp" +#include "detail/color_cvt.hpp" + +namespace cv { namespace cudev { + +// Various 3/4-channel to 3/4-channel RGB transformations + +#define CV_CUDEV_RGB2RGB_INST(name, scn, dcn, bidx) \ + template struct name ## _func : cv::cudev::color_cvt_detail::RGB2RGB \ + { \ + }; + +CV_CUDEV_RGB2RGB_INST(BGR_to_RGB, 3, 3, 2) +CV_CUDEV_RGB2RGB_INST(BGR_to_BGRA, 3, 4, 0) +CV_CUDEV_RGB2RGB_INST(BGR_to_RGBA, 3, 4, 2) +CV_CUDEV_RGB2RGB_INST(BGRA_to_BGR, 4, 3, 0) +CV_CUDEV_RGB2RGB_INST(BGRA_to_RGB, 4, 3, 2) +CV_CUDEV_RGB2RGB_INST(BGRA_to_RGBA, 4, 4, 2) + +#undef CV_CUDEV_RGB2RGB_INST + +// RGB to Grayscale + +#define CV_CUDEV_RGB2GRAY_INST(name, scn, bidx) \ + template struct name ## _func : cv::cudev::color_cvt_detail::RGB2Gray \ + { \ + }; + +CV_CUDEV_RGB2GRAY_INST(RGB_to_GRAY, 3, 2) +CV_CUDEV_RGB2GRAY_INST(BGR_to_GRAY, 3, 0) +CV_CUDEV_RGB2GRAY_INST(RGBA_to_GRAY, 4, 2) +CV_CUDEV_RGB2GRAY_INST(BGRA_to_GRAY, 4, 0) + +#undef CV_CUDEV_RGB2GRAY_INST + +// Grayscale to RGB + +#define CV_CUDEV_GRAY2RGB_INST(name, dcn) \ + template struct name ## _func : cv::cudev::color_cvt_detail::Gray2RGB \ + { \ + }; + +CV_CUDEV_GRAY2RGB_INST(GRAY_to_BGR, 3) +CV_CUDEV_GRAY2RGB_INST(GRAY_to_BGRA, 4) + +#undef CV_CUDEV_GRAY2RGB_INST + +// RGB to YUV + +#define CV_CUDEV_RGB2YUV_INST(name, scn, dcn, bidx) \ + template struct name ## _func : cv::cudev::color_cvt_detail::RGB2YUV \ + { \ + }; + +CV_CUDEV_RGB2YUV_INST(RGB_to_YUV, 3, 3, 2) +CV_CUDEV_RGB2YUV_INST(RGBA_to_YUV, 4, 3, 2) +CV_CUDEV_RGB2YUV_INST(RGB_to_YUV4, 3, 4, 2) +CV_CUDEV_RGB2YUV_INST(RGBA_to_YUV4, 4, 4, 2) +CV_CUDEV_RGB2YUV_INST(BGR_to_YUV, 3, 3, 0) +CV_CUDEV_RGB2YUV_INST(BGRA_to_YUV, 4, 3, 0) +CV_CUDEV_RGB2YUV_INST(BGR_to_YUV4, 3, 4, 0) +CV_CUDEV_RGB2YUV_INST(BGRA_to_YUV4, 4, 4, 0) + +#undef CV_CUDEV_RGB2YUV_INST + +// YUV to RGB + +#define CV_CUDEV_YUV2RGB_INST(name, scn, dcn, bidx) \ + template struct name ## _func : cv::cudev::color_cvt_detail::YUV2RGB \ + { \ + }; + +CV_CUDEV_YUV2RGB_INST(YUV_to_RGB, 3, 3, 2) +CV_CUDEV_YUV2RGB_INST(YUV_to_RGBA, 3, 4, 2) +CV_CUDEV_YUV2RGB_INST(YUV4_to_RGB, 4, 3, 2) +CV_CUDEV_YUV2RGB_INST(YUV4_to_RGBA, 4, 4, 2) +CV_CUDEV_YUV2RGB_INST(YUV_to_BGR, 3, 3, 0) +CV_CUDEV_YUV2RGB_INST(YUV_to_BGRA, 3, 4, 0) +CV_CUDEV_YUV2RGB_INST(YUV4_to_BGR, 4, 3, 0) +CV_CUDEV_YUV2RGB_INST(YUV4_to_BGRA, 4, 4, 0) + +#undef CV_CUDEV_YUV2RGB_INST + +// RGB to YCrCb + +#define CV_CUDEV_RGB2YCrCb_INST(name, scn, dcn, bidx) \ + template struct name ## _func : cv::cudev::color_cvt_detail::RGB2YCrCb \ + { \ + }; + +CV_CUDEV_RGB2YCrCb_INST(RGB_to_YCrCb, 3, 3, 2) +CV_CUDEV_RGB2YCrCb_INST(RGBA_to_YCrCb, 4, 3, 2) +CV_CUDEV_RGB2YCrCb_INST(RGB_to_YCrCb4, 3, 4, 2) +CV_CUDEV_RGB2YCrCb_INST(RGBA_to_YCrCb4, 4, 4, 2) +CV_CUDEV_RGB2YCrCb_INST(BGR_to_YCrCb, 3, 3, 0) +CV_CUDEV_RGB2YCrCb_INST(BGRA_to_YCrCb, 4, 3, 0) +CV_CUDEV_RGB2YCrCb_INST(BGR_to_YCrCb4, 3, 4, 0) +CV_CUDEV_RGB2YCrCb_INST(BGRA_to_YCrCb4, 4, 4, 0) + +#undef CV_CUDEV_RGB2YCrCb_INST + +// YCrCb to RGB + +#define CV_CUDEV_YCrCb2RGB_INST(name, scn, dcn, bidx) \ + template struct name ## _func : cv::cudev::color_cvt_detail::YCrCb2RGB \ + { \ + }; + +CV_CUDEV_YCrCb2RGB_INST(YCrCb_to_RGB, 3, 3, 2) +CV_CUDEV_YCrCb2RGB_INST(YCrCb_to_RGBA, 3, 4, 2) +CV_CUDEV_YCrCb2RGB_INST(YCrCb4_to_RGB, 4, 3, 2) +CV_CUDEV_YCrCb2RGB_INST(YCrCb4_to_RGBA, 4, 4, 2) +CV_CUDEV_YCrCb2RGB_INST(YCrCb_to_BGR, 3, 3, 0) +CV_CUDEV_YCrCb2RGB_INST(YCrCb_to_BGRA, 3, 4, 0) +CV_CUDEV_YCrCb2RGB_INST(YCrCb4_to_BGR, 4, 3, 0) +CV_CUDEV_YCrCb2RGB_INST(YCrCb4_to_BGRA, 4, 4, 0) + +#undef CV_CUDEV_YCrCb2RGB_INST + +// RGB to XYZ + +#define CV_CUDEV_RGB2XYZ_INST(name, scn, dcn, bidx) \ + template struct name ## _func : cv::cudev::color_cvt_detail::RGB2XYZ \ + { \ + }; + +CV_CUDEV_RGB2XYZ_INST(RGB_to_XYZ, 3, 3, 2) +CV_CUDEV_RGB2XYZ_INST(RGBA_to_XYZ, 4, 3, 2) +CV_CUDEV_RGB2XYZ_INST(RGB_to_XYZ4, 3, 4, 2) +CV_CUDEV_RGB2XYZ_INST(RGBA_to_XYZ4, 4, 4, 2) +CV_CUDEV_RGB2XYZ_INST(BGR_to_XYZ, 3, 3, 0) +CV_CUDEV_RGB2XYZ_INST(BGRA_to_XYZ, 4, 3, 0) +CV_CUDEV_RGB2XYZ_INST(BGR_to_XYZ4, 3, 4, 0) +CV_CUDEV_RGB2XYZ_INST(BGRA_to_XYZ4, 4, 4, 0) + +#undef CV_CUDEV_RGB2XYZ_INST + +// XYZ to RGB + +#define CV_CUDEV_XYZ2RGB_INST(name, scn, dcn, bidx) \ + template struct name ## _func : cv::cudev::color_cvt_detail::XYZ2RGB \ + { \ + }; + +CV_CUDEV_XYZ2RGB_INST(XYZ_to_RGB, 3, 3, 2) +CV_CUDEV_XYZ2RGB_INST(XYZ4_to_RGB, 4, 3, 2) +CV_CUDEV_XYZ2RGB_INST(XYZ_to_RGBA, 3, 4, 2) +CV_CUDEV_XYZ2RGB_INST(XYZ4_to_RGBA, 4, 4, 2) +CV_CUDEV_XYZ2RGB_INST(XYZ_to_BGR, 3, 3, 0) +CV_CUDEV_XYZ2RGB_INST(XYZ4_to_BGR, 4, 3, 0) +CV_CUDEV_XYZ2RGB_INST(XYZ_to_BGRA, 3, 4, 0) +CV_CUDEV_XYZ2RGB_INST(XYZ4_to_BGRA, 4, 4, 0) + +#undef CV_CUDEV_XYZ2RGB_INST + +// RGB to HSV + +#define CV_CUDEV_RGB2HSV_INST(name, scn, dcn, bidx) \ + template struct name ## _func : cv::cudev::color_cvt_detail::RGB2HSV \ + { \ + }; \ + template struct name ## _FULL ## _func : cv::cudev::color_cvt_detail::RGB2HSV \ + { \ + }; \ + template <> struct name ## _func : cv::cudev::color_cvt_detail::RGB2HSV \ + { \ + }; \ + template <> struct name ## _FULL ## _func : cv::cudev::color_cvt_detail::RGB2HSV \ + { \ + }; + +CV_CUDEV_RGB2HSV_INST(RGB_to_HSV, 3, 3, 2) +CV_CUDEV_RGB2HSV_INST(RGBA_to_HSV, 4, 3, 2) +CV_CUDEV_RGB2HSV_INST(RGB_to_HSV4, 3, 4, 2) +CV_CUDEV_RGB2HSV_INST(RGBA_to_HSV4, 4, 4, 2) +CV_CUDEV_RGB2HSV_INST(BGR_to_HSV, 3, 3, 0) +CV_CUDEV_RGB2HSV_INST(BGRA_to_HSV, 4, 3, 0) +CV_CUDEV_RGB2HSV_INST(BGR_to_HSV4, 3, 4, 0) +CV_CUDEV_RGB2HSV_INST(BGRA_to_HSV4, 4, 4, 0) + +#undef CV_CUDEV_RGB2HSV_INST + +// HSV to RGB + +#define CV_CUDEV_HSV2RGB_INST(name, scn, dcn, bidx) \ + template struct name ## _func : cv::cudev::color_cvt_detail::HSV2RGB \ + { \ + }; \ + template struct name ## _FULL ## _func : cv::cudev::color_cvt_detail::HSV2RGB \ + { \ + }; \ + template <> struct name ## _func : cv::cudev::color_cvt_detail::HSV2RGB \ + { \ + }; \ + template <> struct name ## _FULL ## _func : cv::cudev::color_cvt_detail::HSV2RGB \ + { \ + }; + +CV_CUDEV_HSV2RGB_INST(HSV_to_RGB, 3, 3, 2) +CV_CUDEV_HSV2RGB_INST(HSV_to_RGBA, 3, 4, 2) +CV_CUDEV_HSV2RGB_INST(HSV4_to_RGB, 4, 3, 2) +CV_CUDEV_HSV2RGB_INST(HSV4_to_RGBA, 4, 4, 2) +CV_CUDEV_HSV2RGB_INST(HSV_to_BGR, 3, 3, 0) +CV_CUDEV_HSV2RGB_INST(HSV_to_BGRA, 3, 4, 0) +CV_CUDEV_HSV2RGB_INST(HSV4_to_BGR, 4, 3, 0) +CV_CUDEV_HSV2RGB_INST(HSV4_to_BGRA, 4, 4, 0) + +#undef CV_CUDEV_HSV2RGB_INST + +// RGB to HLS + +#define CV_CUDEV_RGB2HLS_INST(name, scn, dcn, bidx) \ + template struct name ## _func : cv::cudev::color_cvt_detail::RGB2HLS \ + { \ + }; \ + template struct name ## _FULL ## _func : cv::cudev::color_cvt_detail::RGB2HLS \ + { \ + }; \ + template <> struct name ## _func : cv::cudev::color_cvt_detail::RGB2HLS \ + { \ + }; \ + template <> struct name ## _FULL ## _func : cv::cudev::color_cvt_detail::RGB2HLS \ + { \ + }; + +CV_CUDEV_RGB2HLS_INST(RGB_to_HLS, 3, 3, 2) +CV_CUDEV_RGB2HLS_INST(RGBA_to_HLS, 4, 3, 2) +CV_CUDEV_RGB2HLS_INST(RGB_to_HLS4, 3, 4, 2) +CV_CUDEV_RGB2HLS_INST(RGBA_to_HLS4, 4, 4, 2) +CV_CUDEV_RGB2HLS_INST(BGR_to_HLS, 3, 3, 0) +CV_CUDEV_RGB2HLS_INST(BGRA_to_HLS, 4, 3, 0) +CV_CUDEV_RGB2HLS_INST(BGR_to_HLS4, 3, 4, 0) +CV_CUDEV_RGB2HLS_INST(BGRA_to_HLS4, 4, 4, 0) + +#undef CV_CUDEV_RGB2HLS_INST + +// HLS to RGB + +#define CV_CUDEV_HLS2RGB_INST(name, scn, dcn, bidx) \ + template struct name ## _func : cv::cudev::color_cvt_detail::HLS2RGB \ + { \ + }; \ + template struct name ## _FULL ## _func : cv::cudev::color_cvt_detail::HLS2RGB \ + { \ + }; \ + template <> struct name ## _func : cv::cudev::color_cvt_detail::HLS2RGB \ + { \ + }; \ + template <> struct name ## _FULL ## _func : cv::cudev::color_cvt_detail::HLS2RGB \ + { \ + }; + +CV_CUDEV_HLS2RGB_INST(HLS_to_RGB, 3, 3, 2) +CV_CUDEV_HLS2RGB_INST(HLS_to_RGBA, 3, 4, 2) +CV_CUDEV_HLS2RGB_INST(HLS4_to_RGB, 4, 3, 2) +CV_CUDEV_HLS2RGB_INST(HLS4_to_RGBA, 4, 4, 2) +CV_CUDEV_HLS2RGB_INST(HLS_to_BGR, 3, 3, 0) +CV_CUDEV_HLS2RGB_INST(HLS_to_BGRA, 3, 4, 0) +CV_CUDEV_HLS2RGB_INST(HLS4_to_BGR, 4, 3, 0) +CV_CUDEV_HLS2RGB_INST(HLS4_to_BGRA, 4, 4, 0) + +#undef CV_CUDEV_HLS2RGB_INST + +// RGB to Lab + +#define CV_CUDEV_RGB2Lab_INST(name, scn, dcn, sRGB, blueIdx) \ + template struct name ## _func : cv::cudev::color_cvt_detail::RGB2Lab \ + { \ + }; + +CV_CUDEV_RGB2Lab_INST(RGB_to_Lab, 3, 3, true, 2) +CV_CUDEV_RGB2Lab_INST(RGBA_to_Lab, 4, 3, true, 2) +CV_CUDEV_RGB2Lab_INST(RGB_to_Lab4, 3, 4, true, 2) +CV_CUDEV_RGB2Lab_INST(RGBA_to_Lab4, 4, 4, true, 2) +CV_CUDEV_RGB2Lab_INST(BGR_to_Lab, 3, 3, true, 0) +CV_CUDEV_RGB2Lab_INST(BGRA_to_Lab, 4, 3, true, 0) +CV_CUDEV_RGB2Lab_INST(BGR_to_Lab4, 3, 4, true, 0) +CV_CUDEV_RGB2Lab_INST(BGRA_to_Lab4, 4, 4, true, 0) + +CV_CUDEV_RGB2Lab_INST(LRGB_to_Lab, 3, 3, false, 2) +CV_CUDEV_RGB2Lab_INST(LRGBA_to_Lab, 4, 3, false, 2) +CV_CUDEV_RGB2Lab_INST(LRGB_to_Lab4, 3, 4, false, 2) +CV_CUDEV_RGB2Lab_INST(LRGBA_to_Lab4, 4, 4, false, 2) +CV_CUDEV_RGB2Lab_INST(LBGR_to_Lab, 3, 3, false, 0) +CV_CUDEV_RGB2Lab_INST(LBGRA_to_Lab, 4, 3, false, 0) +CV_CUDEV_RGB2Lab_INST(LBGR_to_Lab4, 3, 4, false, 0) +CV_CUDEV_RGB2Lab_INST(LBGRA_to_Lab4, 4, 4, false, 0) + +#undef CV_CUDEV_RGB2Lab_INST + +// Lab to RGB + +#define CV_CUDEV_Lab2RGB_INST(name, scn, dcn, sRGB, blueIdx) \ + template struct name ## _func : cv::cudev::color_cvt_detail::Lab2RGB \ + { \ + }; + +CV_CUDEV_Lab2RGB_INST(Lab_to_RGB, 3, 3, true, 2) +CV_CUDEV_Lab2RGB_INST(Lab4_to_RGB, 4, 3, true, 2) +CV_CUDEV_Lab2RGB_INST(Lab_to_RGBA, 3, 4, true, 2) +CV_CUDEV_Lab2RGB_INST(Lab4_to_RGBA, 4, 4, true, 2) +CV_CUDEV_Lab2RGB_INST(Lab_to_BGR, 3, 3, true, 0) +CV_CUDEV_Lab2RGB_INST(Lab4_to_BGR, 4, 3, true, 0) +CV_CUDEV_Lab2RGB_INST(Lab_to_BGRA, 3, 4, true, 0) +CV_CUDEV_Lab2RGB_INST(Lab4_to_BGRA, 4, 4, true, 0) + +CV_CUDEV_Lab2RGB_INST(Lab_to_LRGB, 3, 3, false, 2) +CV_CUDEV_Lab2RGB_INST(Lab4_to_LRGB, 4, 3, false, 2) +CV_CUDEV_Lab2RGB_INST(Lab_to_LRGBA, 3, 4, false, 2) +CV_CUDEV_Lab2RGB_INST(Lab4_to_LRGBA, 4, 4, false, 2) +CV_CUDEV_Lab2RGB_INST(Lab_to_LBGR, 3, 3, false, 0) +CV_CUDEV_Lab2RGB_INST(Lab4_to_LBGR, 4, 3, false, 0) +CV_CUDEV_Lab2RGB_INST(Lab_to_LBGRA, 3, 4, false, 0) +CV_CUDEV_Lab2RGB_INST(Lab4_to_LBGRA, 4, 4, false, 0) + +#undef CV_CUDEV_Lab2RGB_INST + +// RGB to Luv + +#define CV_CUDEV_RGB2Luv_INST(name, scn, dcn, sRGB, blueIdx) \ + template struct name ## _func : cv::cudev::color_cvt_detail::RGB2Luv \ + { \ + }; + +CV_CUDEV_RGB2Luv_INST(RGB_to_Luv, 3, 3, true, 2) +CV_CUDEV_RGB2Luv_INST(RGBA_to_Luv, 4, 3, true, 2) +CV_CUDEV_RGB2Luv_INST(RGB_to_Luv4, 3, 4, true, 2) +CV_CUDEV_RGB2Luv_INST(RGBA_to_Luv4, 4, 4, true, 2) +CV_CUDEV_RGB2Luv_INST(BGR_to_Luv, 3, 3, true, 0) +CV_CUDEV_RGB2Luv_INST(BGRA_to_Luv, 4, 3, true, 0) +CV_CUDEV_RGB2Luv_INST(BGR_to_Luv4, 3, 4, true, 0) +CV_CUDEV_RGB2Luv_INST(BGRA_to_Luv4, 4, 4, true, 0) + +CV_CUDEV_RGB2Luv_INST(LRGB_to_Luv, 3, 3, false, 2) +CV_CUDEV_RGB2Luv_INST(LRGBA_to_Luv, 4, 3, false, 2) +CV_CUDEV_RGB2Luv_INST(LRGB_to_Luv4, 3, 4, false, 2) +CV_CUDEV_RGB2Luv_INST(LRGBA_to_Luv4, 4, 4, false, 2) +CV_CUDEV_RGB2Luv_INST(LBGR_to_Luv, 3, 3, false, 0) +CV_CUDEV_RGB2Luv_INST(LBGRA_to_Luv, 4, 3, false, 0) +CV_CUDEV_RGB2Luv_INST(LBGR_to_Luv4, 3, 4, false, 0) +CV_CUDEV_RGB2Luv_INST(LBGRA_to_Luv4, 4, 4, false, 0) + +#undef CV_CUDEV_RGB2Luv_INST + +// Luv to RGB + +#define CV_CUDEV_Luv2RGB_INST(name, scn, dcn, sRGB, blueIdx) \ + template struct name ## _func : cv::cudev::color_cvt_detail::Luv2RGB \ + { \ + }; + +CV_CUDEV_Luv2RGB_INST(Luv_to_RGB, 3, 3, true, 2) +CV_CUDEV_Luv2RGB_INST(Luv4_to_RGB, 4, 3, true, 2) +CV_CUDEV_Luv2RGB_INST(Luv_to_RGBA, 3, 4, true, 2) +CV_CUDEV_Luv2RGB_INST(Luv4_to_RGBA, 4, 4, true, 2) +CV_CUDEV_Luv2RGB_INST(Luv_to_BGR, 3, 3, true, 0) +CV_CUDEV_Luv2RGB_INST(Luv4_to_BGR, 4, 3, true, 0) +CV_CUDEV_Luv2RGB_INST(Luv_to_BGRA, 3, 4, true, 0) +CV_CUDEV_Luv2RGB_INST(Luv4_to_BGRA, 4, 4, true, 0) + +CV_CUDEV_Luv2RGB_INST(Luv_to_LRGB, 3, 3, false, 2) +CV_CUDEV_Luv2RGB_INST(Luv4_to_LRGB, 4, 3, false, 2) +CV_CUDEV_Luv2RGB_INST(Luv_to_LRGBA, 3, 4, false, 2) +CV_CUDEV_Luv2RGB_INST(Luv4_to_LRGBA, 4, 4, false, 2) +CV_CUDEV_Luv2RGB_INST(Luv_to_LBGR, 3, 3, false, 0) +CV_CUDEV_Luv2RGB_INST(Luv4_to_LBGR, 4, 3, false, 0) +CV_CUDEV_Luv2RGB_INST(Luv_to_LBGRA, 3, 4, false, 0) +CV_CUDEV_Luv2RGB_INST(Luv4_to_LBGRA, 4, 4, false, 0) + +#undef CV_CUDEV_Luv2RGB_INST + +// 24/32-bit RGB to 16-bit (565 or 555) RGB + +#define CV_CUDEV_RGB2RGB5x5_INST(name, scn, bidx, green_bits) \ + typedef cv::cudev::color_cvt_detail::RGB2RGB5x5 name ## _func; + +CV_CUDEV_RGB2RGB5x5_INST(BGR_to_BGR555, 3, 0, 5) +CV_CUDEV_RGB2RGB5x5_INST(BGR_to_BGR565, 3, 0, 6) +CV_CUDEV_RGB2RGB5x5_INST(RGB_to_BGR555, 3, 2, 5) +CV_CUDEV_RGB2RGB5x5_INST(RGB_to_BGR565, 3, 2, 6) +CV_CUDEV_RGB2RGB5x5_INST(BGRA_to_BGR555, 4, 0, 5) +CV_CUDEV_RGB2RGB5x5_INST(BGRA_to_BGR565, 4, 0, 6) +CV_CUDEV_RGB2RGB5x5_INST(RGBA_to_BGR555, 4, 2, 5) +CV_CUDEV_RGB2RGB5x5_INST(RGBA_to_BGR565, 4, 2, 6) + +#undef CV_CUDEV_RGB2RGB5x5_INST + +// 16-bit (565 or 555) RGB to 24/32-bit RGB + +#define CV_CUDEV_RGB5x52RGB_INST(name, dcn, bidx, green_bits) \ + typedef cv::cudev::color_cvt_detail::RGB5x52RGB name ## _func; + +CV_CUDEV_RGB5x52RGB_INST(BGR555_to_RGB, 3, 2, 5) +CV_CUDEV_RGB5x52RGB_INST(BGR565_to_RGB, 3, 2, 6) +CV_CUDEV_RGB5x52RGB_INST(BGR555_to_BGR, 3, 0, 5) +CV_CUDEV_RGB5x52RGB_INST(BGR565_to_BGR, 3, 0, 6) +CV_CUDEV_RGB5x52RGB_INST(BGR555_to_RGBA, 4, 2, 5) +CV_CUDEV_RGB5x52RGB_INST(BGR565_to_RGBA, 4, 2, 6) +CV_CUDEV_RGB5x52RGB_INST(BGR555_to_BGRA, 4, 0, 5) +CV_CUDEV_RGB5x52RGB_INST(BGR565_to_BGRA, 4, 0, 6) + +#undef CV_CUDEV_RGB5x52RGB_INST + +// Grayscale to 16-bit (565 or 555) RGB + +#define CV_CUDEV_GRAY2RGB5x5_INST(name, green_bits) \ + typedef cv::cudev::color_cvt_detail::Gray2RGB5x5 name ## _func; + +CV_CUDEV_GRAY2RGB5x5_INST(GRAY_to_BGR555, 5) +CV_CUDEV_GRAY2RGB5x5_INST(GRAY_to_BGR565, 6) + +#undef CV_CUDEV_GRAY2RGB5x5_INST + +// 16-bit (565 or 555) RGB to Grayscale + +#define CV_CUDEV_RGB5x52GRAY_INST(name, green_bits) \ + typedef cv::cudev::color_cvt_detail::RGB5x52Gray name ## _func; + +CV_CUDEV_RGB5x52GRAY_INST(BGR555_to_GRAY, 5) +CV_CUDEV_RGB5x52GRAY_INST(BGR565_to_GRAY, 6) + +#undef CV_CUDEV_RGB5x52GRAY_INST + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/functional/detail/color_cvt.hpp b/modules/cudev/include/opencv2/cudev/functional/detail/color_cvt.hpp new file mode 100644 index 0000000000..9b20fcc2c6 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/functional/detail/color_cvt.hpp @@ -0,0 +1,1279 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_FUNCTIONAL_COLOR_CVT_DETAIL_HPP__ +#define __OPENCV_CUDEV_FUNCTIONAL_COLOR_CVT_DETAIL_HPP__ + +#include "../../common.hpp" +#include "../../util/vec_traits.hpp" +#include "../../util/saturate_cast.hpp" +#include "../../util/limits.hpp" +#include "../functional.hpp" + +namespace cv { namespace cudev { + +namespace color_cvt_detail +{ + // utility + + #define CV_CUDEV_DESCALE(x, n) (((x) + (1 << ((n)-1))) >> (n)) + + template struct ColorChannel + { + __device__ __forceinline__ static T max() { return numeric_limits::max(); } + __device__ __forceinline__ static T half() { return (T)(max()/2 + 1); } + }; + + template <> struct ColorChannel + { + __device__ __forceinline__ static float max() { return 1.f; } + __device__ __forceinline__ static float half() { return 0.5f; } + }; + + template __device__ __forceinline__ void setAlpha(typename MakeVec::type& vec, T val) + { + } + + template __device__ __forceinline__ void setAlpha(typename MakeVec::type& vec, T val) + { + vec.w = val; + } + + template __device__ __forceinline__ T getAlpha(const typename MakeVec::type& vec) + { + return ColorChannel::max(); + } + + template __device__ __forceinline__ T getAlpha(const typename MakeVec::type& vec) + { + return vec.w; + } + + enum + { + yuv_shift = 14, + xyz_shift = 12, + R2Y = 4899, + G2Y = 9617, + B2Y = 1868, + BLOCK_SIZE = 256 + }; + + // Various 3/4-channel to 3/4-channel RGB transformations + + template struct RGB2RGB + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + typename MakeVec::type dst; + + dst.x = bidx == 0 ? src.x : src.z; + dst.y = src.y; + dst.z = bidx == 0 ? src.z : src.x; + setAlpha(dst, getAlpha(src)); + + return dst; + } + }; + + // 24/32-bit RGB to 16-bit (565 or 555) RGB + + template struct RGB2RGB5x5; + + template struct RGB2RGB5x5 + : unary_function::type, ushort> + { + __device__ ushort operator ()(const typename MakeVec::type& src) const + { + const int b = bidx == 0 ? src.x : src.z; + const int g = src.y; + const int r = bidx == 0 ? src.z : src.x; + return (ushort) ((b >> 3) | ((g & ~3) << 3) | ((r & ~7) << 8)); + } + }; + + template struct RGB2RGB5x5<3, bidx, 5> + : unary_function + { + __device__ ushort operator ()(const uchar3& src) const + { + const int b = bidx == 0 ? src.x : src.z; + const int g = src.y; + const int r = bidx == 0 ? src.z : src.x; + return (ushort) ((b >> 3) | ((g & ~7) << 2) | ((r & ~7) << 7)); + } + }; + + template struct RGB2RGB5x5<4, bidx, 5> + : unary_function + { + __device__ ushort operator ()(const uchar4& src) const + { + const int b = bidx == 0 ? src.x : src.z; + const int g = src.y; + const int r = bidx == 0 ? src.z : src.x; + const int a = src.w; + return (ushort) ((b >> 3) | ((g & ~7) << 2) | ((r & ~7) << 7) | (a * 0x8000)); + } + }; + + // 16-bit (565 or 555) RGB to 24/32-bit RGB + + template struct RGB5x52RGB; + + template struct RGB5x52RGB<3, bidx, 5> + : unary_function + { + __device__ uchar3 operator ()(ushort src) const + { + const int b = src << 3; + const int r = (src >> 7) & ~7; + + uchar3 dst; + + dst.x = bidx == 0 ? b : r; + dst.y = (src >> 2) & ~7; + dst.z = bidx == 0 ? r : b; + + return dst; + } + }; + + template struct RGB5x52RGB<4, bidx, 5> + : unary_function + { + __device__ uchar4 operator ()(ushort src) const + { + const int b = src << 3; + const int r = (src >> 7) & ~7; + + uchar4 dst; + + dst.x = bidx == 0 ? b : r; + dst.y = (src >> 2) & ~7; + dst.z = bidx == 0 ? r : b; + dst.w = (src & 0x8000) * 0xffu; + + return dst; + } + }; + + template struct RGB5x52RGB<3, bidx, 6> + : unary_function + { + __device__ uchar3 operator ()(ushort src) const + { + const int b = src << 3; + const int r = (src >> 8) & ~7; + + uchar3 dst; + + dst.x = bidx == 0 ? b : r; + dst.y = (src >> 3) & ~3; + dst.z = bidx == 0 ? r : b; + + return dst; + } + }; + + template struct RGB5x52RGB<4, bidx, 6> + : unary_function + { + __device__ uchar4 operator ()(ushort src) const + { + const int b = src << 3; + const int r = (src >> 8) & ~7; + + uchar4 dst; + + dst.x = bidx == 0 ? b : r; + dst.y = (src >> 3) & ~3; + dst.z = bidx == 0 ? r : b; + dst.w = 255; + + return dst; + } + }; + + // Grayscale to RGB + + template struct Gray2RGB + : unary_function::type> + { + __device__ typename MakeVec::type operator ()(T src) const + { + typename MakeVec::type dst; + + dst.z = dst.y = dst.x = src; + setAlpha(dst, ColorChannel::max()); + + return dst; + } + }; + + // Grayscale to 16-bit (565 or 555) RGB + + template struct Gray2RGB5x5; + + template <> struct Gray2RGB5x5<5> + : unary_function + { + __device__ ushort operator ()(uchar src) const + { + return (ushort) (src | (src << 5) | (src << 10)); + } + }; + + template <> struct Gray2RGB5x5<6> + : unary_function + { + __device__ ushort operator ()(uchar src) const + { + return (ushort) ((src >> 3) | ((src & ~3) << 3) | ((src & ~7) << 8)); + } + }; + + // 16-bit (565 or 555) RGB to Grayscale + + template struct RGB5x52Gray; + + template <> struct RGB5x52Gray<5> + : unary_function + { + __device__ uchar operator ()(ushort src) const + { + return (uchar) CV_CUDEV_DESCALE(((src << 3) & 0xf8) * B2Y + ((src >> 2) & 0xf8) * G2Y + ((src >> 7) & 0xf8) * R2Y, yuv_shift); + } + }; + + template <> struct RGB5x52Gray<6> + : unary_function + { + __device__ uchar operator ()(ushort src) const + { + return (uchar) CV_CUDEV_DESCALE(((src << 3) & 0xf8) * B2Y + ((src >> 3) & 0xfc) * G2Y + ((src >> 8) & 0xf8) * R2Y, yuv_shift); + } + }; + + // RGB to Grayscale + + template struct RGB2Gray + : unary_function::type, T> + { + __device__ T operator ()(const typename MakeVec::type& src) const + { + const int b = bidx == 0 ? src.x : src.z; + const int g = src.y; + const int r = bidx == 0 ? src.z : src.x; + return (T) CV_CUDEV_DESCALE(b * B2Y + g * G2Y + r * R2Y, yuv_shift); + } + }; + + template struct RGB2Gray + : unary_function::type, float> + { + __device__ float operator ()(const typename MakeVec::type& src) const + { + const float b = bidx == 0 ? src.x : src.z; + const float g = src.y; + const float r = bidx == 0 ? src.z : src.x; + return b * 0.114f + g * 0.587f + r * 0.299f; + } + }; + + // RGB to YUV + + __constant__ float c_RGB2YUVCoeffs_f[5] = { 0.114f, 0.587f, 0.299f, 0.492f, 0.877f }; + __constant__ int c_RGB2YUVCoeffs_i[5] = { B2Y, G2Y, R2Y, 8061, 14369 }; + + template struct RGB2YUV + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const int b = bidx == 0 ? src.x : src.z; + const int g = src.y; + const int r = bidx == 0 ? src.z : src.x; + + const int delta = ColorChannel::half() * (1 << yuv_shift); + + const int Y = CV_CUDEV_DESCALE(b * c_RGB2YUVCoeffs_i[2] + g * c_RGB2YUVCoeffs_i[1] + r * c_RGB2YUVCoeffs_i[0], yuv_shift); + const int Cr = CV_CUDEV_DESCALE((r - Y) * c_RGB2YUVCoeffs_i[3] + delta, yuv_shift); + const int Cb = CV_CUDEV_DESCALE((b - Y) * c_RGB2YUVCoeffs_i[4] + delta, yuv_shift); + + typename MakeVec::type dst; + + dst.x = saturate_cast(Y); + dst.y = saturate_cast(Cr); + dst.z = saturate_cast(Cb); + + return dst; + } + }; + + template struct RGB2YUV + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const float b = bidx == 0 ? src.x : src.z; + const float g = src.y; + const float r = bidx == 0 ? src.z : src.x; + + typename MakeVec::type dst; + + dst.x = b * c_RGB2YUVCoeffs_f[2] + g * c_RGB2YUVCoeffs_f[1] + r * c_RGB2YUVCoeffs_f[0]; + dst.y = (r - dst.x) * c_RGB2YUVCoeffs_f[3] + ColorChannel::half(); + dst.z = (b - dst.x) * c_RGB2YUVCoeffs_f[4] + ColorChannel::half(); + + return dst; + } + }; + + // YUV to RGB + + __constant__ float c_YUV2RGBCoeffs_f[5] = { 2.032f, -0.395f, -0.581f, 1.140f }; + __constant__ int c_YUV2RGBCoeffs_i[5] = { 33292, -6472, -9519, 18678 }; + + template struct YUV2RGB + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const int b = src.x + CV_CUDEV_DESCALE((src.z - ColorChannel::half()) * c_YUV2RGBCoeffs_i[3], yuv_shift); + const int g = src.x + CV_CUDEV_DESCALE((src.z - ColorChannel::half()) * c_YUV2RGBCoeffs_i[2] + (src.y - ColorChannel::half()) * c_YUV2RGBCoeffs_i[1], yuv_shift); + const int r = src.x + CV_CUDEV_DESCALE((src.y - ColorChannel::half()) * c_YUV2RGBCoeffs_i[0], yuv_shift); + + typename MakeVec::type dst; + + dst.x = saturate_cast(bidx == 0 ? b : r); + dst.y = saturate_cast(g); + dst.z = saturate_cast(bidx == 0 ? r : b); + setAlpha(dst, ColorChannel::max()); + + return dst; + } + }; + + template struct YUV2RGB + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const float b = src.x + (src.z - ColorChannel::half()) * c_YUV2RGBCoeffs_f[3]; + const float g = src.x + (src.z - ColorChannel::half()) * c_YUV2RGBCoeffs_f[2] + (src.y - ColorChannel::half()) * c_YUV2RGBCoeffs_f[1]; + const float r = src.x + (src.y - ColorChannel::half()) * c_YUV2RGBCoeffs_f[0]; + + typename MakeVec::type dst; + + dst.x = bidx == 0 ? b : r; + dst.y = g; + dst.z = bidx == 0 ? r : b; + setAlpha(dst, ColorChannel::max()); + + return dst; + } + }; + + // RGB to YCrCb + + __constant__ float c_RGB2YCrCbCoeffs_f[5] = { 0.299f, 0.587f, 0.114f, 0.713f, 0.564f }; + __constant__ int c_RGB2YCrCbCoeffs_i[5] = { R2Y, G2Y, B2Y, 11682, 9241 }; + + template struct RGB2YCrCb + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const int b = bidx == 0 ? src.x : src.z; + const int g = src.y; + const int r = bidx == 0 ? src.z : src.x; + + const int delta = ColorChannel::half() * (1 << yuv_shift); + + const int Y = CV_CUDEV_DESCALE(b * c_RGB2YCrCbCoeffs_i[2] + g * c_RGB2YCrCbCoeffs_i[1] + r * c_RGB2YCrCbCoeffs_i[0], yuv_shift); + const int Cr = CV_CUDEV_DESCALE((r - Y) * c_RGB2YCrCbCoeffs_i[3] + delta, yuv_shift); + const int Cb = CV_CUDEV_DESCALE((b - Y) * c_RGB2YCrCbCoeffs_i[4] + delta, yuv_shift); + + typename MakeVec::type dst; + + dst.x = saturate_cast(Y); + dst.y = saturate_cast(Cr); + dst.z = saturate_cast(Cb); + + return dst; + } + }; + + template struct RGB2YCrCb + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const float b = bidx == 0 ? src.x : src.z; + const float g = src.y; + const float r = bidx == 0 ? src.z : src.x; + + typename MakeVec::type dst; + + dst.x = b * c_RGB2YCrCbCoeffs_f[2] + g * c_RGB2YCrCbCoeffs_f[1] + r * c_RGB2YCrCbCoeffs_f[0]; + dst.y = (r - dst.x) * c_RGB2YCrCbCoeffs_f[3] + ColorChannel::half(); + dst.z = (b - dst.x) * c_RGB2YCrCbCoeffs_f[4] + ColorChannel::half(); + + return dst; + } + }; + + // YCrCb to RGB + + __constant__ float c_YCrCb2RGBCoeffs_f[5] = {1.403f, -0.714f, -0.344f, 1.773f}; + __constant__ int c_YCrCb2RGBCoeffs_i[5] = {22987, -11698, -5636, 29049}; + + template struct YCrCb2RGB + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const int b = src.x + CV_CUDEV_DESCALE((src.z - ColorChannel::half()) * c_YCrCb2RGBCoeffs_i[3], yuv_shift); + const int g = src.x + CV_CUDEV_DESCALE((src.z - ColorChannel::half()) * c_YCrCb2RGBCoeffs_i[2] + (src.y - ColorChannel::half()) * c_YCrCb2RGBCoeffs_i[1], yuv_shift); + const int r = src.x + CV_CUDEV_DESCALE((src.y - ColorChannel::half()) * c_YCrCb2RGBCoeffs_i[0], yuv_shift); + + typename MakeVec::type dst; + + dst.x = saturate_cast(bidx == 0 ? b : r); + dst.y = saturate_cast(g); + dst.z = saturate_cast(bidx == 0 ? r : b); + setAlpha(dst, ColorChannel::max()); + + return dst; + } + }; + + template struct YCrCb2RGB + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const float b = src.x + (src.z - ColorChannel::half()) * c_YCrCb2RGBCoeffs_f[3]; + const float g = src.x + (src.z - ColorChannel::half()) * c_YCrCb2RGBCoeffs_f[2] + (src.y - ColorChannel::half()) * c_YCrCb2RGBCoeffs_f[1]; + const float r = src.x + (src.y - ColorChannel::half()) * c_YCrCb2RGBCoeffs_f[0]; + + typename MakeVec::type dst; + + dst.x = bidx == 0 ? b : r; + dst.y = g; + dst.z = bidx == 0 ? r : b; + setAlpha(dst, ColorChannel::max()); + + return dst; + } + }; + + // RGB to XYZ + + __constant__ float c_RGB2XYZ_D65f[9] = { 0.412453f, 0.357580f, 0.180423f, 0.212671f, 0.715160f, 0.072169f, 0.019334f, 0.119193f, 0.950227f }; + __constant__ int c_RGB2XYZ_D65i[9] = { 1689, 1465, 739, 871, 2929, 296, 79, 488, 3892 }; + + template struct RGB2XYZ + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const int b = bidx == 0 ? src.x : src.z; + const int g = src.y; + const int r = bidx == 0 ? src.z : src.x; + + typename MakeVec::type dst; + + dst.z = saturate_cast(CV_CUDEV_DESCALE(r * c_RGB2XYZ_D65i[6] + g * c_RGB2XYZ_D65i[7] + b * c_RGB2XYZ_D65i[8], xyz_shift)); + dst.x = saturate_cast(CV_CUDEV_DESCALE(r * c_RGB2XYZ_D65i[0] + g * c_RGB2XYZ_D65i[1] + b * c_RGB2XYZ_D65i[2], xyz_shift)); + dst.y = saturate_cast(CV_CUDEV_DESCALE(r * c_RGB2XYZ_D65i[3] + g * c_RGB2XYZ_D65i[4] + b * c_RGB2XYZ_D65i[5], xyz_shift)); + + return dst; + } + }; + + template struct RGB2XYZ + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const float b = bidx == 0 ? src.x : src.z; + const float g = src.y; + const float r = bidx == 0 ? src.z : src.x; + + typename MakeVec::type dst; + + dst.x = r * c_RGB2XYZ_D65f[0] + g * c_RGB2XYZ_D65f[1] + b * c_RGB2XYZ_D65f[2]; + dst.y = r * c_RGB2XYZ_D65f[3] + g * c_RGB2XYZ_D65f[4] + b * c_RGB2XYZ_D65f[5]; + dst.z = r * c_RGB2XYZ_D65f[6] + g * c_RGB2XYZ_D65f[7] + b * c_RGB2XYZ_D65f[8]; + + return dst; + } + }; + + // XYZ to RGB + + __constant__ float c_XYZ2sRGB_D65f[9] = { 3.240479f, -1.53715f, -0.498535f, -0.969256f, 1.875991f, 0.041556f, 0.055648f, -0.204043f, 1.057311f }; + __constant__ int c_XYZ2sRGB_D65i[9] = { 13273, -6296, -2042, -3970, 7684, 170, 228, -836, 4331 }; + + template struct XYZ2RGB + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const int b = CV_CUDEV_DESCALE(src.x * c_XYZ2sRGB_D65i[6] + src.y * c_XYZ2sRGB_D65i[7] + src.z * c_XYZ2sRGB_D65i[8], xyz_shift); + const int g = CV_CUDEV_DESCALE(src.x * c_XYZ2sRGB_D65i[3] + src.y * c_XYZ2sRGB_D65i[4] + src.z * c_XYZ2sRGB_D65i[5], xyz_shift); + const int r = CV_CUDEV_DESCALE(src.x * c_XYZ2sRGB_D65i[0] + src.y * c_XYZ2sRGB_D65i[1] + src.z * c_XYZ2sRGB_D65i[2], xyz_shift); + + typename MakeVec::type dst; + + dst.x = saturate_cast(bidx == 0 ? b : r); + dst.y = saturate_cast(g); + dst.z = saturate_cast(bidx == 0 ? r : b); + setAlpha(dst, ColorChannel::max()); + + return dst; + } + }; + + template struct XYZ2RGB + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const float b = src.x * c_XYZ2sRGB_D65f[6] + src.y * c_XYZ2sRGB_D65f[7] + src.z * c_XYZ2sRGB_D65f[8]; + const float g = src.x * c_XYZ2sRGB_D65f[3] + src.y * c_XYZ2sRGB_D65f[4] + src.z * c_XYZ2sRGB_D65f[5]; + const float r = src.x * c_XYZ2sRGB_D65f[0] + src.y * c_XYZ2sRGB_D65f[1] + src.z * c_XYZ2sRGB_D65f[2]; + + typename MakeVec::type dst; + + dst.x = bidx == 0 ? b : r; + dst.y = g; + dst.z = bidx == 0 ? r : b; + setAlpha(dst, ColorChannel::max()); + + return dst; + } + }; + + // RGB to HSV + + __constant__ int c_HsvDivTable [256] = {0, 1044480, 522240, 348160, 261120, 208896, 174080, 149211, 130560, 116053, 104448, 94953, 87040, 80345, 74606, 69632, 65280, 61440, 58027, 54973, 52224, 49737, 47476, 45412, 43520, 41779, 40172, 38684, 37303, 36017, 34816, 33693, 32640, 31651, 30720, 29842, 29013, 28229, 27486, 26782, 26112, 25475, 24869, 24290, 23738, 23211, 22706, 22223, 21760, 21316, 20890, 20480, 20086, 19707, 19342, 18991, 18651, 18324, 18008, 17703, 17408, 17123, 16846, 16579, 16320, 16069, 15825, 15589, 15360, 15137, 14921, 14711, 14507, 14308, 14115, 13926, 13743, 13565, 13391, 13221, 13056, 12895, 12738, 12584, 12434, 12288, 12145, 12006, 11869, 11736, 11605, 11478, 11353, 11231, 11111, 10995, 10880, 10768, 10658, 10550, 10445, 10341, 10240, 10141, 10043, 9947, 9854, 9761, 9671, 9582, 9495, 9410, 9326, 9243, 9162, 9082, 9004, 8927, 8852, 8777, 8704, 8632, 8561, 8492, 8423, 8356, 8290, 8224, 8160, 8097, 8034, 7973, 7913, 7853, 7795, 7737, 7680, 7624, 7569, 7514, 7461, 7408, 7355, 7304, 7253, 7203, 7154, 7105, 7057, 7010, 6963, 6917, 6872, 6827, 6782, 6739, 6695, 6653, 6611, 6569, 6528, 6487, 6447, 6408, 6369, 6330, 6292, 6254, 6217, 6180, 6144, 6108, 6073, 6037, 6003, 5968, 5935, 5901, 5868, 5835, 5803, 5771, 5739, 5708, 5677, 5646, 5615, 5585, 5556, 5526, 5497, 5468, 5440, 5412, 5384, 5356, 5329, 5302, 5275, 5249, 5222, 5196, 5171, 5145, 5120, 5095, 5070, 5046, 5022, 4998, 4974, 4950, 4927, 4904, 4881, 4858, 4836, 4813, 4791, 4769, 4748, 4726, 4705, 4684, 4663, 4642, 4622, 4601, 4581, 4561, 4541, 4522, 4502, 4483, 4464, 4445, 4426, 4407, 4389, 4370, 4352, 4334, 4316, 4298, 4281, 4263, 4246, 4229, 4212, 4195, 4178, 4161, 4145, 4128, 4112, 4096}; + __constant__ int c_HsvDivTable180[256] = {0, 122880, 61440, 40960, 30720, 24576, 20480, 17554, 15360, 13653, 12288, 11171, 10240, 9452, 8777, 8192, 7680, 7228, 6827, 6467, 6144, 5851, 5585, 5343, 5120, 4915, 4726, 4551, 4389, 4237, 4096, 3964, 3840, 3724, 3614, 3511, 3413, 3321, 3234, 3151, 3072, 2997, 2926, 2858, 2793, 2731, 2671, 2614, 2560, 2508, 2458, 2409, 2363, 2318, 2276, 2234, 2194, 2156, 2119, 2083, 2048, 2014, 1982, 1950, 1920, 1890, 1862, 1834, 1807, 1781, 1755, 1731, 1707, 1683, 1661, 1638, 1617, 1596, 1575, 1555, 1536, 1517, 1499, 1480, 1463, 1446, 1429, 1412, 1396, 1381, 1365, 1350, 1336, 1321, 1307, 1293, 1280, 1267, 1254, 1241, 1229, 1217, 1205, 1193, 1182, 1170, 1159, 1148, 1138, 1127, 1117, 1107, 1097, 1087, 1078, 1069, 1059, 1050, 1041, 1033, 1024, 1016, 1007, 999, 991, 983, 975, 968, 960, 953, 945, 938, 931, 924, 917, 910, 904, 897, 890, 884, 878, 871, 865, 859, 853, 847, 842, 836, 830, 825, 819, 814, 808, 803, 798, 793, 788, 783, 778, 773, 768, 763, 759, 754, 749, 745, 740, 736, 731, 727, 723, 719, 714, 710, 706, 702, 698, 694, 690, 686, 683, 679, 675, 671, 668, 664, 661, 657, 654, 650, 647, 643, 640, 637, 633, 630, 627, 624, 621, 617, 614, 611, 608, 605, 602, 599, 597, 594, 591, 588, 585, 582, 580, 577, 574, 572, 569, 566, 564, 561, 559, 556, 554, 551, 549, 546, 544, 541, 539, 537, 534, 532, 530, 527, 525, 523, 521, 518, 516, 514, 512, 510, 508, 506, 504, 502, 500, 497, 495, 493, 492, 490, 488, 486, 484, 482}; + __constant__ int c_HsvDivTable256[256] = {0, 174763, 87381, 58254, 43691, 34953, 29127, 24966, 21845, 19418, 17476, 15888, 14564, 13443, 12483, 11651, 10923, 10280, 9709, 9198, 8738, 8322, 7944, 7598, 7282, 6991, 6722, 6473, 6242, 6026, 5825, 5638, 5461, 5296, 5140, 4993, 4855, 4723, 4599, 4481, 4369, 4263, 4161, 4064, 3972, 3884, 3799, 3718, 3641, 3567, 3495, 3427, 3361, 3297, 3236, 3178, 3121, 3066, 3013, 2962, 2913, 2865, 2819, 2774, 2731, 2689, 2648, 2608, 2570, 2533, 2497, 2461, 2427, 2394, 2362, 2330, 2300, 2270, 2241, 2212, 2185, 2158, 2131, 2106, 2081, 2056, 2032, 2009, 1986, 1964, 1942, 1920, 1900, 1879, 1859, 1840, 1820, 1802, 1783, 1765, 1748, 1730, 1713, 1697, 1680, 1664, 1649, 1633, 1618, 1603, 1589, 1574, 1560, 1547, 1533, 1520, 1507, 1494, 1481, 1469, 1456, 1444, 1432, 1421, 1409, 1398, 1387, 1376, 1365, 1355, 1344, 1334, 1324, 1314, 1304, 1295, 1285, 1276, 1266, 1257, 1248, 1239, 1231, 1222, 1214, 1205, 1197, 1189, 1181, 1173, 1165, 1157, 1150, 1142, 1135, 1128, 1120, 1113, 1106, 1099, 1092, 1085, 1079, 1072, 1066, 1059, 1053, 1046, 1040, 1034, 1028, 1022, 1016, 1010, 1004, 999, 993, 987, 982, 976, 971, 966, 960, 955, 950, 945, 940, 935, 930, 925, 920, 915, 910, 906, 901, 896, 892, 887, 883, 878, 874, 869, 865, 861, 857, 853, 848, 844, 840, 836, 832, 828, 824, 820, 817, 813, 809, 805, 802, 798, 794, 791, 787, 784, 780, 777, 773, 770, 767, 763, 760, 757, 753, 750, 747, 744, 741, 737, 734, 731, 728, 725, 722, 719, 716, 713, 710, 708, 705, 702, 699, 696, 694, 691, 688, 685}; + + template struct RGB2HSV; + + template struct RGB2HSV + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const int hsv_shift = 12; + const int* hdiv_table = hr == 180 ? c_HsvDivTable180 : c_HsvDivTable256; + + const int b = bidx == 0 ? src.x : src.z; + const int g = src.y; + const int r = bidx == 0 ? src.z : src.x; + + int h, s, v = b; + int vmin = b, diff; + int vr, vg; + + v = ::max(v, g); + v = ::max(v, r); + vmin = ::min(vmin, g); + vmin = ::min(vmin, r); + + diff = v - vmin; + vr = (v == r) * -1; + vg = (v == g) * -1; + + s = (diff * c_HsvDivTable[v] + (1 << (hsv_shift-1))) >> hsv_shift; + h = (vr & (g - b)) + (~vr & ((vg & (b - r + 2 * diff)) + ((~vg) & (r - g + 4 * diff)))); + h = (h * hdiv_table[diff] + (1 << (hsv_shift-1))) >> hsv_shift; + h += (h < 0) * hr; + + typename MakeVec::type dst; + + dst.x = saturate_cast(h); + dst.y = saturate_cast(s); + dst.z = saturate_cast(v); + + return dst; + } + }; + + template struct RGB2HSV + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const float hscale = hr * (1.f / 360.f); + + const float b = bidx == 0 ? src.x : src.z; + const float g = src.y; + const float r = bidx == 0 ? src.z : src.x; + + float h, s, v; + float vmin, diff; + + v = vmin = r; + v = ::fmax(v, g); + v = ::fmax(v, b); + vmin = ::fmin(vmin, g); + vmin = ::fmin(vmin, b); + + diff = v - vmin; + s = diff / (float)(::fabs(v) + numeric_limits::epsilon()); + diff = (float)(60. / (diff + numeric_limits::epsilon())); + + h = (v == r) * (g - b) * diff; + h += (v != r && v == g) * ((b - r) * diff + 120.f); + h += (v != r && v != g) * ((r - g) * diff + 240.f); + h += (h < 0) * 360.f; + + typename MakeVec::type dst; + + dst.x = h * hscale; + dst.y = s; + dst.z = v; + + return dst; + } + }; + + // HSV to RGB + + __constant__ int c_HsvSectorData[6][3] = { {1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0} }; + + template struct HSV2RGB; + + template struct HSV2RGB + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const float hscale = 6.f / hr; + + float h = src.x, s = src.y, v = src.z; + float b = v, g = v, r = v; + + if (s != 0) + { + h *= hscale; + + if( h < 0 ) + do h += 6; while( h < 0 ); + else if( h >= 6 ) + do h -= 6; while( h >= 6 ); + + int sector = __float2int_rd(h); + h -= sector; + + if ( (unsigned)sector >= 6u ) + { + sector = 0; + h = 0.f; + } + + float tab[4]; + tab[0] = v; + tab[1] = v * (1.f - s); + tab[2] = v * (1.f - s * h); + tab[3] = v * (1.f - s * (1.f - h)); + + b = tab[c_HsvSectorData[sector][0]]; + g = tab[c_HsvSectorData[sector][1]]; + r = tab[c_HsvSectorData[sector][2]]; + } + + typename MakeVec::type dst; + + dst.x = bidx == 0 ? b : r; + dst.y = g; + dst.z = bidx == 0 ? r : b; + setAlpha(dst, ColorChannel::max()); + + return dst; + } + }; + + template struct HSV2RGB + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + float3 buf; + + buf.x = src.x; + buf.y = src.y * (1.f / 255.f); + buf.z = src.z * (1.f / 255.f); + + HSV2RGB cvtf; + buf = cvtf(buf); + + typename MakeVec::type dst; + + dst.x = saturate_cast(buf.x * 255.f); + dst.y = saturate_cast(buf.y * 255.f); + dst.z = saturate_cast(buf.z * 255.f); + setAlpha(dst, ColorChannel::max()); + + return dst; + } + }; + + // RGB to HLS + + template struct RGB2HLS; + + template struct RGB2HLS + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const float hscale = hr * (1.f / 360.f); + + const float b = bidx == 0 ? src.x : src.z; + const float g = src.y; + const float r = bidx == 0 ? src.z : src.x; + + float h = 0.f, s = 0.f, l; + float vmin, vmax, diff; + + vmax = vmin = r; + vmax = ::fmax(vmax, g); + vmax = ::fmax(vmax, b); + vmin = ::fmin(vmin, g); + vmin = ::fmin(vmin, b); + + diff = vmax - vmin; + l = (vmax + vmin) * 0.5f; + + if (diff > numeric_limits::epsilon()) + { + s = (l < 0.5f) * diff / (vmax + vmin); + s += (l >= 0.5f) * diff / (2.0f - vmax - vmin); + + diff = 60.f / diff; + + h = (vmax == r) * (g - b) * diff; + h += (vmax != r && vmax == g) * ((b - r) * diff + 120.f); + h += (vmax != r && vmax != g) * ((r - g) * diff + 240.f); + h += (h < 0.f) * 360.f; + } + + typename MakeVec::type dst; + + dst.x = h * hscale; + dst.y = l; + dst.z = s; + + return dst; + } + }; + + template struct RGB2HLS + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + float3 buf; + + buf.x = src.x * (1.f / 255.f); + buf.y = src.y * (1.f / 255.f); + buf.z = src.z * (1.f / 255.f); + + RGB2HLS cvtf; + buf = cvtf(buf); + + typename MakeVec::type dst; + + dst.x = saturate_cast(buf.x); + dst.y = saturate_cast(buf.y * 255.f); + dst.z = saturate_cast(buf.z * 255.f); + + return dst; + } + }; + + // HLS to RGB + + __constant__ int c_HlsSectorData[6][3] = { {1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0} }; + + template struct HLS2RGB; + + template struct HLS2RGB + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const float hscale = 6.0f / hr; + + float h = src.x, l = src.y, s = src.z; + float b = l, g = l, r = l; + + if (s != 0) + { + float p2 = (l <= 0.5f) * l * (1 + s); + p2 += (l > 0.5f) * (l + s - l * s); + float p1 = 2 * l - p2; + + h *= hscale; + + if( h < 0 ) + do h += 6; while( h < 0 ); + else if( h >= 6 ) + do h -= 6; while( h >= 6 ); + + int sector; + sector = __float2int_rd(h); + + h -= sector; + + float tab[4]; + tab[0] = p2; + tab[1] = p1; + tab[2] = p1 + (p2 - p1) * (1 - h); + tab[3] = p1 + (p2 - p1) * h; + + b = tab[c_HlsSectorData[sector][0]]; + g = tab[c_HlsSectorData[sector][1]]; + r = tab[c_HlsSectorData[sector][2]]; + } + + typename MakeVec::type dst; + + dst.x = bidx == 0 ? b : r; + dst.y = g; + dst.z = bidx == 0 ? r : b; + setAlpha(dst, ColorChannel::max()); + + return dst; + } + }; + + template struct HLS2RGB + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + float3 buf; + + buf.x = src.x; + buf.y = src.y * (1.f / 255.f); + buf.z = src.z * (1.f / 255.f); + + HLS2RGB cvtf; + buf = cvtf(buf); + + typename MakeVec::type dst; + + dst.x = saturate_cast(buf.x * 255.f); + dst.y = saturate_cast(buf.y * 255.f); + dst.z = saturate_cast(buf.z * 255.f); + setAlpha(dst, ColorChannel::max()); + + return dst; + } + }; + + // RGB to Lab + + enum + { + LAB_CBRT_TAB_SIZE = 1024, + GAMMA_TAB_SIZE = 1024, + lab_shift = xyz_shift, + gamma_shift = 3, + lab_shift2 = (lab_shift + gamma_shift), + LAB_CBRT_TAB_SIZE_B = (256 * 3 / 2 * (1 << gamma_shift)) + }; + + __constant__ ushort c_sRGBGammaTab_b[] = {0,1,1,2,2,3,4,4,5,6,6,7,8,8,9,10,11,11,12,13,14,15,16,17,19,20,21,22,24,25,26,28,29,31,33,34,36,38,40,41,43,45,47,49,51,54,56,58,60,63,65,68,70,73,75,78,81,83,86,89,92,95,98,101,105,108,111,115,118,121,125,129,132,136,140,144,147,151,155,160,164,168,172,176,181,185,190,194,199,204,209,213,218,223,228,233,239,244,249,255,260,265,271,277,282,288,294,300,306,312,318,324,331,337,343,350,356,363,370,376,383,390,397,404,411,418,426,433,440,448,455,463,471,478,486,494,502,510,518,527,535,543,552,560,569,578,586,595,604,613,622,631,641,650,659,669,678,688,698,707,717,727,737,747,757,768,778,788,799,809,820,831,842,852,863,875,886,897,908,920,931,943,954,966,978,990,1002,1014,1026,1038,1050,1063,1075,1088,1101,1113,1126,1139,1152,1165,1178,1192,1205,1218,1232,1245,1259,1273,1287,1301,1315,1329,1343,1357,1372,1386,1401,1415,1430,1445,1460,1475,1490,1505,1521,1536,1551,1567,1583,1598,1614,1630,1646,1662,1678,1695,1711,1728,1744,1761,1778,1794,1811,1828,1846,1863,1880,1897,1915,1933,1950,1968,1986,2004,2022,2040}; + __constant__ float c_sRGBGammaTab[] = {0,7.55853e-05,0.,-7.51331e-13,7.55853e-05,7.55853e-05,-2.25399e-12,3.75665e-12,0.000151171,7.55853e-05,9.01597e-12,-6.99932e-12,0.000226756,7.55853e-05,-1.1982e-11,2.41277e-12,0.000302341,7.55853e-05,-4.74369e-12,1.19001e-11,0.000377927,7.55853e-05,3.09568e-11,-2.09095e-11,0.000453512,7.55853e-05,-3.17718e-11,1.35303e-11,0.000529097,7.55853e-05,8.81905e-12,-4.10782e-12,0.000604683,7.55853e-05,-3.50439e-12,2.90097e-12,0.000680268,7.55853e-05,5.19852e-12,-7.49607e-12,0.000755853,7.55853e-05,-1.72897e-11,2.70833e-11,0.000831439,7.55854e-05,6.39602e-11,-4.26295e-11,0.000907024,7.55854e-05,-6.39282e-11,2.70193e-11,0.000982609,7.55853e-05,1.71298e-11,-7.24017e-12,0.00105819,7.55853e-05,-4.59077e-12,1.94137e-12,0.00113378,7.55853e-05,1.23333e-12,-5.25291e-13,0.00120937,7.55853e-05,-3.42545e-13,1.59799e-13,0.00128495,7.55853e-05,1.36852e-13,-1.13904e-13,0.00136054,7.55853e-05,-2.04861e-13,2.95818e-13,0.00143612,7.55853e-05,6.82594e-13,-1.06937e-12,0.00151171,7.55853e-05,-2.52551e-12,3.98166e-12,0.00158729,7.55853e-05,9.41946e-12,-1.48573e-11,0.00166288,7.55853e-05,-3.51523e-11,5.54474e-11,0.00173846,7.55854e-05,1.3119e-10,-9.0517e-11,0.00181405,7.55854e-05,-1.40361e-10,7.37899e-11,0.00188963,7.55853e-05,8.10085e-11,-8.82272e-11,0.00196522,7.55852e-05,-1.83673e-10,1.62704e-10,0.0020408,7.55853e-05,3.04438e-10,-2.13341e-10,0.00211639,7.55853e-05,-3.35586e-10,2.25e-10,0.00219197,7.55853e-05,3.39414e-10,-2.20997e-10,0.00226756,7.55853e-05,-3.23576e-10,1.93326e-10,0.00234315,7.55853e-05,2.564e-10,-8.66446e-11,0.00241873,7.55855e-05,-3.53328e-12,-7.9578e-11,0.00249432,7.55853e-05,-2.42267e-10,1.72126e-10,0.0025699,7.55853e-05,2.74111e-10,-1.43265e-10,0.00264549,7.55854e-05,-1.55683e-10,-6.47292e-11,0.00272107,7.55849e-05,-3.4987e-10,8.67842e-10,0.00279666,7.55868e-05,2.25366e-09,-3.8723e-09,0.00287224,7.55797e-05,-9.36325e-09,1.5087e-08,0.00294783,7.56063e-05,3.58978e-08,-5.69415e-08,0.00302341,7.55072e-05,-1.34927e-07,2.13144e-07,0.003099,7.58768e-05,5.04507e-07,1.38713e-07,0.00317552,7.7302e-05,9.20646e-07,-1.55186e-07,0.00325359,7.86777e-05,4.55087e-07,4.26813e-08,0.00333276,7.97159e-05,5.83131e-07,-1.06495e-08,0.00341305,8.08502e-05,5.51182e-07,3.87467e-09,0.00349446,8.19642e-05,5.62806e-07,-1.92586e-10,0.00357698,8.30892e-05,5.62228e-07,1.0866e-09,0.00366063,8.4217e-05,5.65488e-07,5.02818e-10,0.00374542,8.53494e-05,5.66997e-07,8.60211e-10,0.00383133,8.6486e-05,5.69577e-07,7.13044e-10,0.00391839,8.76273e-05,5.71716e-07,4.78527e-10,0.00400659,8.87722e-05,5.73152e-07,1.09818e-09,0.00409594,8.99218e-05,5.76447e-07,2.50964e-10,0.00418644,9.10754e-05,5.772e-07,1.15762e-09,0.00427809,9.22333e-05,5.80672e-07,2.40865e-10,0.0043709,9.33954e-05,5.81395e-07,1.13854e-09,0.00446488,9.45616e-05,5.84811e-07,3.27267e-10,0.00456003,9.57322e-05,5.85792e-07,8.1197e-10,0.00465635,9.69062e-05,5.88228e-07,6.15823e-10,0.00475384,9.80845e-05,5.90076e-07,9.15747e-10,0.00485252,9.92674e-05,5.92823e-07,3.778e-10,0.00495238,0.000100454,5.93956e-07,8.32623e-10,0.00505343,0.000101645,5.96454e-07,4.82695e-10,0.00515567,0.000102839,5.97902e-07,9.61904e-10,0.00525911,0.000104038,6.00788e-07,3.26281e-10,0.00536375,0.00010524,6.01767e-07,9.926e-10,0.00546959,0.000106447,6.04745e-07,3.59933e-10,0.00557664,0.000107657,6.05824e-07,8.2728e-10,0.0056849,0.000108871,6.08306e-07,5.21898e-10,0.00579438,0.00011009,6.09872e-07,8.10492e-10,0.00590508,0.000111312,6.12303e-07,4.27046e-10,0.00601701,0.000112538,6.13585e-07,7.40878e-10,0.00613016,0.000113767,6.15807e-07,8.00469e-10,0.00624454,0.000115001,6.18209e-07,2.48178e-10,0.00636016,0.000116238,6.18953e-07,1.00073e-09,0.00647702,0.000117479,6.21955e-07,4.05654e-10,0.00659512,0.000118724,6.23172e-07,6.36192e-10,0.00671447,0.000119973,6.25081e-07,7.74927e-10,0.00683507,0.000121225,6.27406e-07,4.54975e-10,0.00695692,0.000122481,6.28771e-07,6.64841e-10,0.00708003,0.000123741,6.30765e-07,6.10972e-10,0.00720441,0.000125004,6.32598e-07,6.16543e-10,0.00733004,0.000126271,6.34448e-07,6.48204e-10,0.00745695,0.000127542,6.36392e-07,5.15835e-10,0.00758513,0.000128816,6.3794e-07,5.48103e-10,0.00771458,0.000130094,6.39584e-07,1.01706e-09,0.00784532,0.000131376,6.42635e-07,4.0283e-11,0.00797734,0.000132661,6.42756e-07,6.84471e-10,0.00811064,0.000133949,6.4481e-07,9.47144e-10,0.00824524,0.000135241,6.47651e-07,1.83472e-10,0.00838112,0.000136537,6.48201e-07,1.11296e-09,0.00851831,0.000137837,6.5154e-07,2.13163e-11,0.0086568,0.00013914,6.51604e-07,6.64462e-10,0.00879659,0.000140445,6.53598e-07,1.04613e-09,0.00893769,0.000141756,6.56736e-07,-1.92377e-10,0.0090801,0.000143069,6.56159e-07,1.58601e-09,0.00922383,0.000144386,6.60917e-07,-5.63754e-10,0.00936888,0.000145706,6.59226e-07,1.60033e-09,0.00951524,0.000147029,6.64027e-07,-2.49543e-10,0.00966294,0.000148356,6.63278e-07,1.26043e-09,0.00981196,0.000149687,6.67059e-07,-1.35572e-10,0.00996231,0.00015102,6.66653e-07,1.14458e-09,0.010114,0.000152357,6.70086e-07,2.13864e-10,0.010267,0.000153698,6.70728e-07,7.93856e-10,0.0104214,0.000155042,6.73109e-07,3.36077e-10,0.0105771,0.000156389,6.74118e-07,6.55765e-10,0.0107342,0.000157739,6.76085e-07,7.66211e-10,0.0108926,0.000159094,6.78384e-07,4.66116e-12,0.0110524,0.000160451,6.78398e-07,1.07775e-09,0.0112135,0.000161811,6.81631e-07,3.41023e-10,0.011376,0.000163175,6.82654e-07,3.5205e-10,0.0115398,0.000164541,6.8371e-07,1.04473e-09,0.0117051,0.000165912,6.86844e-07,1.25757e-10,0.0118717,0.000167286,6.87222e-07,3.14818e-10,0.0120396,0.000168661,6.88166e-07,1.40886e-09,0.012209,0.000170042,6.92393e-07,-3.62244e-10,0.0123797,0.000171425,6.91306e-07,9.71397e-10,0.0125518,0.000172811,6.9422e-07,2.02003e-10,0.0127253,0.0001742,6.94826e-07,1.01448e-09,0.0129002,0.000175593,6.97869e-07,3.96653e-10,0.0130765,0.00017699,6.99059e-07,1.92927e-10,0.0132542,0.000178388,6.99638e-07,6.94305e-10,0.0134333,0.00017979,7.01721e-07,7.55108e-10,0.0136138,0.000181195,7.03986e-07,1.05918e-11,0.0137957,0.000182603,7.04018e-07,1.06513e-09,0.013979,0.000184015,7.07214e-07,3.85512e-10,0.0141637,0.00018543,7.0837e-07,1.86769e-10,0.0143499,0.000186848,7.0893e-07,7.30116e-10,0.0145374,0.000188268,7.11121e-07,6.17983e-10,0.0147264,0.000189692,7.12975e-07,5.23282e-10,0.0149168,0.000191119,7.14545e-07,8.28398e-11,0.0151087,0.000192549,7.14793e-07,1.0081e-09,0.0153019,0.000193981,7.17817e-07,5.41244e-10,0.0154966,0.000195418,7.19441e-07,-3.7907e-10,0.0156928,0.000196856,7.18304e-07,1.90641e-09,0.0158903,0.000198298,7.24023e-07,-7.27387e-10,0.0160893,0.000199744,7.21841e-07,1.00317e-09,0.0162898,0.000201191,7.24851e-07,4.39949e-10,0.0164917,0.000202642,7.2617e-07,9.6234e-10,0.0166951,0.000204097,7.29057e-07,-5.64019e-10,0.0168999,0.000205554,7.27365e-07,1.29374e-09,0.0171062,0.000207012,7.31247e-07,9.77025e-10,0.017314,0.000208478,7.34178e-07,-1.47651e-09,0.0175232,0.000209942,7.29748e-07,3.06636e-09,0.0177338,0.00021141,7.38947e-07,-1.47573e-09,0.017946,0.000212884,7.3452e-07,9.7386e-10,0.0181596,0.000214356,7.37442e-07,1.30562e-09,0.0183747,0.000215835,7.41358e-07,-6.08376e-10,0.0185913,0.000217315,7.39533e-07,1.12785e-09,0.0188093,0.000218798,7.42917e-07,-1.77711e-10,0.0190289,0.000220283,7.42384e-07,1.44562e-09,0.0192499,0.000221772,7.46721e-07,-1.68825e-11,0.0194724,0.000223266,7.4667e-07,4.84533e-10,0.0196964,0.000224761,7.48124e-07,-5.85298e-11,0.0199219,0.000226257,7.47948e-07,1.61217e-09,0.0201489,0.000227757,7.52785e-07,-8.02136e-10,0.0203775,0.00022926,7.50378e-07,1.59637e-09,0.0206075,0.000230766,7.55167e-07,4.47168e-12,0.020839,0.000232276,7.55181e-07,2.48387e-10,0.021072,0.000233787,7.55926e-07,8.6474e-10,0.0213066,0.000235302,7.5852e-07,1.78299e-11,0.0215426,0.000236819,7.58573e-07,9.26567e-10,0.0217802,0.000238339,7.61353e-07,1.34529e-12,0.0220193,0.000239862,7.61357e-07,9.30659e-10,0.0222599,0.000241387,7.64149e-07,1.34529e-12,0.0225021,0.000242915,7.64153e-07,9.26567e-10,0.0227458,0.000244447,7.66933e-07,1.76215e-11,0.022991,0.00024598,7.66986e-07,8.65536e-10,0.0232377,0.000247517,7.69582e-07,2.45677e-10,0.023486,0.000249057,7.70319e-07,1.44193e-11,0.0237358,0.000250598,7.70363e-07,1.55918e-09,0.0239872,0.000252143,7.7504e-07,-6.63173e-10,0.0242401,0.000253691,7.73051e-07,1.09357e-09,0.0244946,0.000255241,7.76331e-07,1.41919e-11,0.0247506,0.000256793,7.76374e-07,7.12248e-10,0.0250082,0.000258348,7.78511e-07,8.62049e-10,0.0252673,0.000259908,7.81097e-07,-4.35061e-10,0.025528,0.000261469,7.79792e-07,8.7825e-10,0.0257902,0.000263031,7.82426e-07,6.47181e-10,0.0260541,0.000264598,7.84368e-07,2.58448e-10,0.0263194,0.000266167,7.85143e-07,1.81558e-10,0.0265864,0.000267738,7.85688e-07,8.78041e-10,0.0268549,0.000269312,7.88322e-07,3.15102e-11,0.027125,0.000270889,7.88417e-07,8.58525e-10,0.0273967,0.000272468,7.90992e-07,2.59812e-10,0.02767,0.000274051,7.91772e-07,-3.5224e-11,0.0279448,0.000275634,7.91666e-07,1.74377e-09,0.0282212,0.000277223,7.96897e-07,-1.35196e-09,0.0284992,0.000278813,7.92841e-07,1.80141e-09,0.0287788,0.000280404,7.98246e-07,-2.65629e-10,0.0290601,0.000281999,7.97449e-07,1.12374e-09,0.0293428,0.000283598,8.0082e-07,-5.04106e-10,0.0296272,0.000285198,7.99308e-07,8.92764e-10,0.0299132,0.000286799,8.01986e-07,6.58379e-10,0.0302008,0.000288405,8.03961e-07,1.98971e-10,0.0304901,0.000290014,8.04558e-07,4.08382e-10,0.0307809,0.000291624,8.05783e-07,3.01839e-11,0.0310733,0.000293236,8.05874e-07,1.33343e-09,0.0313673,0.000294851,8.09874e-07,2.2419e-10,0.031663,0.000296472,8.10547e-07,-3.67606e-10,0.0319603,0.000298092,8.09444e-07,1.24624e-09,0.0322592,0.000299714,8.13182e-07,-8.92025e-10,0.0325597,0.000301338,8.10506e-07,2.32183e-09,0.0328619,0.000302966,8.17472e-07,-9.44719e-10,0.0331657,0.000304598,8.14638e-07,1.45703e-09,0.0334711,0.000306232,8.19009e-07,-1.15805e-09,0.0337781,0.000307866,8.15535e-07,3.17507e-09,0.0340868,0.000309507,8.2506e-07,-4.09161e-09,0.0343971,0.000311145,8.12785e-07,5.74079e-09,0.0347091,0.000312788,8.30007e-07,-3.97034e-09,0.0350227,0.000314436,8.18096e-07,2.68985e-09,0.035338,0.00031608,8.26166e-07,6.61676e-10,0.0356549,0.000317734,8.28151e-07,-1.61123e-09,0.0359734,0.000319386,8.23317e-07,2.05786e-09,0.0362936,0.000321038,8.29491e-07,8.30388e-10,0.0366155,0.0003227,8.31982e-07,-1.65424e-09,0.036939,0.000324359,8.27019e-07,2.06129e-09,0.0372642,0.000326019,8.33203e-07,8.59719e-10,0.0375911,0.000327688,8.35782e-07,-1.77488e-09,0.0379196,0.000329354,8.30458e-07,2.51464e-09,0.0382498,0.000331023,8.38002e-07,-8.33135e-10,0.0385817,0.000332696,8.35502e-07,8.17825e-10,0.0389152,0.00033437,8.37956e-07,1.28718e-09,0.0392504,0.00033605,8.41817e-07,-2.2413e-09,0.0395873,0.000337727,8.35093e-07,3.95265e-09,0.0399258,0.000339409,8.46951e-07,-2.39332e-09,0.0402661,0.000341095,8.39771e-07,1.89533e-09,0.040608,0.000342781,8.45457e-07,-1.46271e-09,0.0409517,0.000344467,8.41069e-07,3.95554e-09,0.041297,0.000346161,8.52936e-07,-3.18369e-09,0.041644,0.000347857,8.43385e-07,1.32873e-09,0.0419927,0.000349548,8.47371e-07,1.59402e-09,0.0423431,0.000351248,8.52153e-07,-2.54336e-10,0.0426952,0.000352951,8.5139e-07,-5.76676e-10,0.043049,0.000354652,8.4966e-07,2.56114e-09,0.0434045,0.000356359,8.57343e-07,-2.21744e-09,0.0437617,0.000358067,8.50691e-07,2.58344e-09,0.0441206,0.000359776,8.58441e-07,-6.65826e-10,0.0444813,0.000361491,8.56444e-07,7.99218e-11,0.0448436,0.000363204,8.56684e-07,3.46063e-10,0.0452077,0.000364919,8.57722e-07,2.26116e-09,0.0455734,0.000366641,8.64505e-07,-1.94005e-09,0.045941,0.000368364,8.58685e-07,1.77384e-09,0.0463102,0.000370087,8.64007e-07,-1.43005e-09,0.0466811,0.000371811,8.59717e-07,3.94634e-09,0.0470538,0.000373542,8.71556e-07,-3.17946e-09,0.0474282,0.000375276,8.62017e-07,1.32104e-09,0.0478043,0.000377003,8.6598e-07,1.62045e-09,0.0481822,0.00037874,8.70842e-07,-3.52297e-10,0.0485618,0.000380481,8.69785e-07,-2.11211e-10,0.0489432,0.00038222,8.69151e-07,1.19716e-09,0.0493263,0.000383962,8.72743e-07,-8.52026e-10,0.0497111,0.000385705,8.70187e-07,2.21092e-09,0.0500977,0.000387452,8.76819e-07,-5.41339e-10,0.050486,0.000389204,8.75195e-07,-4.5361e-11,0.0508761,0.000390954,8.75059e-07,7.22669e-10,0.0512679,0.000392706,8.77227e-07,8.79936e-10,0.0516615,0.000394463,8.79867e-07,-5.17048e-10,0.0520568,0.000396222,8.78316e-07,1.18833e-09,0.0524539,0.000397982,8.81881e-07,-5.11022e-10,0.0528528,0.000399744,8.80348e-07,8.55683e-10,0.0532534,0.000401507,8.82915e-07,8.13562e-10,0.0536558,0.000403276,8.85356e-07,-3.84603e-10,0.05406,0.000405045,8.84202e-07,7.24962e-10,0.0544659,0.000406816,8.86377e-07,1.20986e-09,0.0548736,0.000408592,8.90006e-07,-1.83896e-09,0.0552831,0.000410367,8.84489e-07,2.42071e-09,0.0556944,0.000412143,8.91751e-07,-3.93413e-10,0.0561074,0.000413925,8.90571e-07,-8.46967e-10,0.0565222,0.000415704,8.8803e-07,3.78122e-09,0.0569388,0.000417491,8.99374e-07,-3.1021e-09,0.0573572,0.000419281,8.90068e-07,1.17658e-09,0.0577774,0.000421064,8.93597e-07,2.12117e-09,0.0581993,0.000422858,8.99961e-07,-2.21068e-09,0.0586231,0.000424651,8.93329e-07,2.9961e-09,0.0590486,0.000426447,9.02317e-07,-2.32311e-09,0.059476,0.000428244,8.95348e-07,2.57122e-09,0.0599051,0.000430043,9.03062e-07,-5.11098e-10,0.0603361,0.000431847,9.01528e-07,-5.27166e-10,0.0607688,0.000433649,8.99947e-07,2.61984e-09,0.0612034,0.000435457,9.07806e-07,-2.50141e-09,0.0616397,0.000437265,9.00302e-07,3.66045e-09,0.0620779,0.000439076,9.11283e-07,-4.68977e-09,0.0625179,0.000440885,8.97214e-07,7.64783e-09,0.0629597,0.000442702,9.20158e-07,-7.27499e-09,0.0634033,0.000444521,8.98333e-07,6.55113e-09,0.0638487,0.000446337,9.17986e-07,-4.02844e-09,0.0642959,0.000448161,9.05901e-07,2.11196e-09,0.064745,0.000449979,9.12236e-07,3.03125e-09,0.0651959,0.000451813,9.2133e-07,-6.78648e-09,0.0656486,0.000453635,9.00971e-07,9.21375e-09,0.0661032,0.000455464,9.28612e-07,-7.71684e-09,0.0665596,0.000457299,9.05462e-07,6.7522e-09,0.0670178,0.00045913,9.25718e-07,-4.3907e-09,0.0674778,0.000460968,9.12546e-07,3.36e-09,0.0679397,0.000462803,9.22626e-07,-1.59876e-09,0.0684034,0.000464644,9.1783e-07,3.0351e-09,0.068869,0.000466488,9.26935e-07,-3.09101e-09,0.0693364,0.000468333,9.17662e-07,1.8785e-09,0.0698057,0.000470174,9.23298e-07,3.02733e-09,0.0702768,0.00047203,9.3238e-07,-6.53722e-09,0.0707497,0.000473875,9.12768e-07,8.22054e-09,0.0712245,0.000475725,9.37429e-07,-3.99325e-09,0.0717012,0.000477588,9.2545e-07,3.01839e-10,0.0721797,0.00047944,9.26355e-07,2.78597e-09,0.0726601,0.000481301,9.34713e-07,-3.99507e-09,0.0731423,0.000483158,9.22728e-07,5.7435e-09,0.0736264,0.000485021,9.39958e-07,-4.07776e-09,0.0741123,0.000486888,9.27725e-07,3.11695e-09,0.0746002,0.000488753,9.37076e-07,-9.39394e-10,0.0750898,0.000490625,9.34258e-07,6.4055e-10,0.0755814,0.000492495,9.3618e-07,-1.62265e-09,0.0760748,0.000494363,9.31312e-07,5.84995e-09,0.0765701,0.000496243,9.48861e-07,-6.87601e-09,0.0770673,0.00049812,9.28233e-07,6.75296e-09,0.0775664,0.000499997,9.48492e-07,-5.23467e-09,0.0780673,0.000501878,9.32788e-07,6.73523e-09,0.0785701,0.000503764,9.52994e-07,-6.80514e-09,0.0790748,0.000505649,9.32578e-07,5.5842e-09,0.0795814,0.000507531,9.49331e-07,-6.30583e-10,0.0800899,0.000509428,9.47439e-07,-3.0618e-09,0.0806003,0.000511314,9.38254e-07,5.4273e-09,0.0811125,0.000513206,9.54536e-07,-3.74627e-09,0.0816267,0.000515104,9.43297e-07,2.10713e-09,0.0821427,0.000516997,9.49618e-07,2.76839e-09,0.0826607,0.000518905,9.57924e-07,-5.73006e-09,0.0831805,0.000520803,9.40733e-07,5.25072e-09,0.0837023,0.0005227,9.56486e-07,-3.71718e-10,0.084226,0.000524612,9.5537e-07,-3.76404e-09,0.0847515,0.000526512,9.44078e-07,7.97735e-09,0.085279,0.000528424,9.6801e-07,-5.79367e-09,0.0858084,0.000530343,9.50629e-07,2.96268e-10,0.0863397,0.000532245,9.51518e-07,4.6086e-09,0.0868729,0.000534162,9.65344e-07,-3.82947e-09,0.087408,0.000536081,9.53856e-07,3.25861e-09,0.087945,0.000537998,9.63631e-07,-1.7543e-09,0.088484,0.00053992,9.58368e-07,3.75849e-09,0.0890249,0.000541848,9.69644e-07,-5.82891e-09,0.0895677,0.00054377,9.52157e-07,4.65593e-09,0.0901124,0.000545688,9.66125e-07,2.10643e-09,0.0906591,0.000547627,9.72444e-07,-5.63099e-09,0.0912077,0.000549555,9.55551e-07,5.51627e-09,0.0917582,0.000551483,9.721e-07,-1.53292e-09,0.0923106,0.000553422,9.67501e-07,6.15311e-10,0.092865,0.000555359,9.69347e-07,-9.28291e-10,0.0934213,0.000557295,9.66562e-07,3.09774e-09,0.0939796,0.000559237,9.75856e-07,-4.01186e-09,0.0945398,0.000561177,9.6382e-07,5.49892e-09,0.095102,0.000563121,9.80317e-07,-3.08258e-09,0.0956661,0.000565073,9.71069e-07,-6.19176e-10,0.0962321,0.000567013,9.69212e-07,5.55932e-09,0.0968001,0.000568968,9.8589e-07,-6.71704e-09,0.09737,0.00057092,9.65738e-07,6.40762e-09,0.0979419,0.00057287,9.84961e-07,-4.0122e-09,0.0985158,0.000574828,9.72925e-07,2.19059e-09,0.0990916,0.000576781,9.79496e-07,2.70048e-09,0.0996693,0.000578748,9.87598e-07,-5.54193e-09,0.100249,0.000580706,9.70972e-07,4.56597e-09,0.100831,0.000582662,9.8467e-07,2.17923e-09,0.101414,0.000584638,9.91208e-07,-5.83232e-09,0.102,0.000586603,9.73711e-07,6.24884e-09,0.102588,0.000588569,9.92457e-07,-4.26178e-09,0.103177,0.000590541,9.79672e-07,3.34781e-09,0.103769,0.00059251,9.89715e-07,-1.67904e-09,0.104362,0.000594485,9.84678e-07,3.36839e-09,0.104958,0.000596464,9.94783e-07,-4.34397e-09,0.105555,0.000598441,9.81751e-07,6.55696e-09,0.106155,0.000600424,1.00142e-06,-6.98272e-09,0.106756,0.000602406,9.80474e-07,6.4728e-09,0.107359,0.000604386,9.99893e-07,-4.00742e-09,0.107965,0.000606374,9.8787e-07,2.10654e-09,0.108572,0.000608356,9.9419e-07,3.0318e-09,0.109181,0.000610353,1.00329e-06,-6.7832e-09,0.109793,0.00061234,9.82936e-07,9.1998e-09,0.110406,0.000614333,1.01054e-06,-7.6642e-09,0.111021,0.000616331,9.87543e-07,6.55579e-09,0.111639,0.000618326,1.00721e-06,-3.65791e-09,0.112258,0.000620329,9.96236e-07,6.25467e-10,0.112879,0.000622324,9.98113e-07,1.15593e-09,0.113503,0.000624323,1.00158e-06,2.20158e-09,0.114128,0.000626333,1.00819e-06,-2.51191e-09,0.114755,0.000628342,1.00065e-06,3.95517e-10,0.115385,0.000630345,1.00184e-06,9.29807e-10,0.116016,0.000632351,1.00463e-06,3.33599e-09,0.116649,0.00063437,1.01463e-06,-6.82329e-09,0.117285,0.000636379,9.94163e-07,9.05595e-09,0.117922,0.000638395,1.02133e-06,-7.04862e-09,0.118562,0.000640416,1.00019e-06,4.23737e-09,0.119203,0.000642429,1.0129e-06,-2.45033e-09,0.119847,0.000644448,1.00555e-06,5.56395e-09,0.120492,0.000646475,1.02224e-06,-4.9043e-09,0.121139,0.000648505,1.00753e-06,-8.47952e-10,0.121789,0.000650518,1.00498e-06,8.29622e-09,0.122441,0.000652553,1.02987e-06,-9.98538e-09,0.123094,0.000654582,9.99914e-07,9.2936e-09,0.12375,0.00065661,1.02779e-06,-4.83707e-09,0.124407,0.000658651,1.01328e-06,2.60411e-09,0.125067,0.000660685,1.0211e-06,-5.57945e-09,0.125729,0.000662711,1.00436e-06,1.22631e-08,0.126392,0.000664756,1.04115e-06,-1.36704e-08,0.127058,0.000666798,1.00014e-06,1.26161e-08,0.127726,0.000668836,1.03798e-06,-6.99155e-09,0.128396,0.000670891,1.01701e-06,4.48836e-10,0.129068,0.000672926,1.01836e-06,5.19606e-09,0.129742,0.000674978,1.03394e-06,-6.3319e-09,0.130418,0.000677027,1.01495e-06,5.2305e-09,0.131096,0.000679073,1.03064e-06,3.11123e-10,0.131776,0.000681135,1.03157e-06,-6.47511e-09,0.132458,0.000683179,1.01215e-06,1.06882e-08,0.133142,0.000685235,1.04421e-06,-6.47519e-09,0.133829,0.000687304,1.02479e-06,3.11237e-10,0.134517,0.000689355,1.02572e-06,5.23035e-09,0.135207,0.000691422,1.04141e-06,-6.3316e-09,0.1359,0.000693486,1.02242e-06,5.19484e-09,0.136594,0.000695546,1.038e-06,4.53497e-10,0.137291,0.000697623,1.03936e-06,-7.00891e-09,0.137989,0.000699681,1.01834e-06,1.2681e-08,0.13869,0.000701756,1.05638e-06,-1.39128e-08,0.139393,0.000703827,1.01464e-06,1.31679e-08,0.140098,0.000705896,1.05414e-06,-8.95659e-09,0.140805,0.000707977,1.02727e-06,7.75742e-09,0.141514,0.000710055,1.05055e-06,-7.17182e-09,0.142225,0.000712135,1.02903e-06,6.02862e-09,0.142938,0.000714211,1.04712e-06,-2.04163e-09,0.143653,0.000716299,1.04099e-06,2.13792e-09,0.144371,0.000718387,1.04741e-06,-6.51009e-09,0.14509,0.000720462,1.02787e-06,9.00123e-09,0.145812,0.000722545,1.05488e-06,3.07523e-10,0.146535,0.000724656,1.0558e-06,-1.02312e-08,0.147261,0.000726737,1.02511e-06,1.0815e-08,0.147989,0.000728819,1.05755e-06,-3.22681e-09,0.148719,0.000730925,1.04787e-06,2.09244e-09,0.14945,0.000733027,1.05415e-06,-5.143e-09,0.150185,0.00073512,1.03872e-06,3.57844e-09,0.150921,0.000737208,1.04946e-06,5.73027e-09,0.151659,0.000739324,1.06665e-06,-1.15983e-08,0.152399,0.000741423,1.03185e-06,1.08605e-08,0.153142,0.000743519,1.06443e-06,-2.04106e-09,0.153886,0.000745642,1.05831e-06,-2.69642e-09,0.154633,0.00074775,1.05022e-06,-2.07425e-09,0.155382,0.000749844,1.044e-06,1.09934e-08,0.156133,0.000751965,1.07698e-06,-1.20972e-08,0.156886,0.000754083,1.04069e-06,7.59288e-09,0.157641,0.000756187,1.06347e-06,-3.37305e-09,0.158398,0.000758304,1.05335e-06,5.89921e-09,0.159158,0.000760428,1.07104e-06,-5.32248e-09,0.159919,0.000762554,1.05508e-06,4.8927e-10,0.160683,0.000764666,1.05654e-06,3.36547e-09,0.161448,0.000766789,1.06664e-06,9.50081e-10,0.162216,0.000768925,1.06949e-06,-7.16568e-09,0.162986,0.000771043,1.04799e-06,1.28114e-08,0.163758,0.000773177,1.08643e-06,-1.42774e-08,0.164533,0.000775307,1.0436e-06,1.44956e-08,0.165309,0.000777438,1.08708e-06,-1.39025e-08,0.166087,0.00077957,1.04538e-06,1.13118e-08,0.166868,0.000781695,1.07931e-06,-1.54224e-09,0.167651,0.000783849,1.07468e-06,-5.14312e-09,0.168436,0.000785983,1.05925e-06,7.21381e-09,0.169223,0.000788123,1.0809e-06,-8.81096e-09,0.170012,0.000790259,1.05446e-06,1.31289e-08,0.170803,0.000792407,1.09385e-06,-1.39022e-08,0.171597,0.000794553,1.05214e-06,1.26775e-08,0.172392,0.000796695,1.09018e-06,-7.00557e-09,0.17319,0.000798855,1.06916e-06,4.43796e-10,0.17399,0.000800994,1.07049e-06,5.23031e-09,0.174792,0.000803151,1.08618e-06,-6.46397e-09,0.175596,0.000805304,1.06679e-06,5.72444e-09,0.176403,0.000807455,1.08396e-06,-1.53254e-09,0.177211,0.000809618,1.07937e-06,4.05673e-10,0.178022,0.000811778,1.08058e-06,-9.01916e-11,0.178835,0.000813939,1.08031e-06,-4.49821e-11,0.17965,0.000816099,1.08018e-06,2.70234e-10,0.180467,0.00081826,1.08099e-06,-1.03603e-09,0.181286,0.000820419,1.07788e-06,3.87392e-09,0.182108,0.000822587,1.0895e-06,4.41522e-10,0.182932,0.000824767,1.09083e-06,-5.63997e-09,0.183758,0.000826932,1.07391e-06,7.21707e-09,0.184586,0.000829101,1.09556e-06,-8.32718e-09,0.185416,0.000831267,1.07058e-06,1.11907e-08,0.186248,0.000833442,1.10415e-06,-6.63336e-09,0.187083,0.00083563,1.08425e-06,4.41484e-10,0.187919,0.0008378,1.08557e-06,4.86754e-09,0.188758,0.000839986,1.10017e-06,-5.01041e-09,0.189599,0.000842171,1.08514e-06,2.72811e-10,0.190443,0.000844342,1.08596e-06,3.91916e-09,0.191288,0.000846526,1.09772e-06,-1.04819e-09,0.192136,0.000848718,1.09457e-06,2.73531e-10,0.192985,0.000850908,1.0954e-06,-4.58916e-11,0.193837,0.000853099,1.09526e-06,-9.01158e-11,0.194692,0.000855289,1.09499e-06,4.06506e-10,0.195548,0.00085748,1.09621e-06,-1.53595e-09,0.196407,0.000859668,1.0916e-06,5.73717e-09,0.197267,0.000861869,1.10881e-06,-6.51164e-09,0.19813,0.000864067,1.08928e-06,5.40831e-09,0.198995,0.000866261,1.1055e-06,-2.20401e-10,0.199863,0.000868472,1.10484e-06,-4.52652e-09,0.200732,0.000870668,1.09126e-06,3.42508e-09,0.201604,0.000872861,1.10153e-06,5.72762e-09,0.202478,0.000875081,1.11872e-06,-1.14344e-08,0.203354,0.000877284,1.08441e-06,1.02076e-08,0.204233,0.000879484,1.11504e-06,4.06355e-10,0.205113,0.000881715,1.11626e-06,-1.18329e-08,0.205996,0.000883912,1.08076e-06,1.71227e-08,0.206881,0.000886125,1.13213e-06,-1.19546e-08,0.207768,0.000888353,1.09626e-06,8.93465e-10,0.208658,0.000890548,1.09894e-06,8.38062e-09,0.209549,0.000892771,1.12408e-06,-4.61353e-09,0.210443,0.000895006,1.11024e-06,-4.82756e-09,0.211339,0.000897212,1.09576e-06,9.02245e-09,0.212238,0.00089943,1.12283e-06,-1.45997e-09,0.213138,0.000901672,1.11845e-06,-3.18255e-09,0.214041,0.000903899,1.1089e-06,-7.11073e-10,0.214946,0.000906115,1.10677e-06,6.02692e-09,0.215853,0.000908346,1.12485e-06,-8.49548e-09,0.216763,0.00091057,1.09936e-06,1.30537e-08,0.217675,0.000912808,1.13852e-06,-1.3917e-08,0.218588,0.000915044,1.09677e-06,1.28121e-08,0.219505,0.000917276,1.13521e-06,-7.5288e-09,0.220423,0.000919523,1.11262e-06,2.40205e-09,0.221344,0.000921756,1.11983e-06,-2.07941e-09,0.222267,0.000923989,1.11359e-06,5.91551e-09,0.223192,0.000926234,1.13134e-06,-6.68149e-09,0.224119,0.000928477,1.11129e-06,5.90929e-09,0.225049,0.000930717,1.12902e-06,-2.05436e-09,0.22598,0.000932969,1.12286e-06,2.30807e-09,0.226915,0.000935222,1.12978e-06,-7.17796e-09,0.227851,0.00093746,1.10825e-06,1.15028e-08,0.228789,0.000939711,1.14276e-06,-9.03083e-09,0.22973,0.000941969,1.11566e-06,9.71932e-09,0.230673,0.00094423,1.14482e-06,-1.49452e-08,0.231619,0.000946474,1.09998e-06,2.02591e-08,0.232566,0.000948735,1.16076e-06,-2.13879e-08,0.233516,0.000950993,1.0966e-06,2.05888e-08,0.234468,0.000953247,1.15837e-06,-1.62642e-08,0.235423,0.000955515,1.10957e-06,1.46658e-08,0.236379,0.000957779,1.15357e-06,-1.25966e-08,0.237338,0.000960048,1.11578e-06,5.91793e-09,0.238299,0.000962297,1.13353e-06,3.82602e-09,0.239263,0.000964576,1.14501e-06,-6.3208e-09,0.240229,0.000966847,1.12605e-06,6.55613e-09,0.241197,0.000969119,1.14572e-06,-5.00268e-09,0.242167,0.000971395,1.13071e-06,-1.44659e-09,0.243139,0.000973652,1.12637e-06,1.07891e-08,0.244114,0.000975937,1.15874e-06,-1.19073e-08,0.245091,0.000978219,1.12302e-06,7.03782e-09,0.246071,0.000980486,1.14413e-06,-1.34276e-09,0.247052,0.00098277,1.1401e-06,-1.66669e-09,0.248036,0.000985046,1.1351e-06,8.00935e-09,0.249022,0.00098734,1.15913e-06,-1.54694e-08,0.250011,0.000989612,1.11272e-06,2.4066e-08,0.251002,0.000991909,1.18492e-06,-2.11901e-08,0.251995,0.000994215,1.12135e-06,1.08973e-09,0.25299,0.000996461,1.12462e-06,1.68311e-08,0.253988,0.000998761,1.17511e-06,-8.8094e-09,0.254987,0.00100109,1.14868e-06,-1.13958e-08,0.25599,0.00100335,1.1145e-06,2.45902e-08,0.256994,0.00100565,1.18827e-06,-2.73603e-08,0.258001,0.00100795,1.10618e-06,2.52464e-08,0.25901,0.00101023,1.18192e-06,-1.40207e-08,0.260021,0.00101256,1.13986e-06,1.03387e-09,0.261035,0.00101484,1.14296e-06,9.8853e-09,0.262051,0.00101715,1.17262e-06,-1.07726e-08,0.263069,0.00101947,1.1403e-06,3.40272e-09,0.26409,0.00102176,1.15051e-06,-2.83827e-09,0.265113,0.00102405,1.142e-06,7.95039e-09,0.266138,0.00102636,1.16585e-06,8.39047e-10,0.267166,0.00102869,1.16836e-06,-1.13066e-08,0.268196,0.00103099,1.13444e-06,1.4585e-08,0.269228,0.00103331,1.1782e-06,-1.72314e-08,0.270262,0.00103561,1.1265e-06,2.45382e-08,0.271299,0.00103794,1.20012e-06,-2.13166e-08,0.272338,0.00104028,1.13617e-06,1.12364e-09,0.273379,0.00104255,1.13954e-06,1.68221e-08,0.274423,0.00104488,1.19001e-06,-8.80736e-09,0.275469,0.00104723,1.16358e-06,-1.13948e-08,0.276518,0.00104953,1.1294e-06,2.45839e-08,0.277568,0.00105186,1.20315e-06,-2.73361e-08,0.278621,0.00105418,1.12114e-06,2.51559e-08,0.279677,0.0010565,1.19661e-06,-1.36832e-08,0.280734,0.00105885,1.15556e-06,-2.25706e-10,0.281794,0.00106116,1.15488e-06,1.45862e-08,0.282857,0.00106352,1.19864e-06,-2.83167e-08,0.283921,0.00106583,1.11369e-06,3.90759e-08,0.284988,0.00106817,1.23092e-06,-3.85801e-08,0.286058,0.00107052,1.11518e-06,2.58375e-08,0.287129,0.00107283,1.19269e-06,-5.16498e-09,0.288203,0.0010752,1.1772e-06,-5.17768e-09,0.28928,0.00107754,1.16167e-06,-3.92671e-09,0.290358,0.00107985,1.14988e-06,2.08846e-08,0.29144,0.00108221,1.21254e-06,-2.00072e-08,0.292523,0.00108458,1.15252e-06,-4.60659e-10,0.293609,0.00108688,1.15114e-06,2.18499e-08,0.294697,0.00108925,1.21669e-06,-2.73343e-08,0.295787,0.0010916,1.13468e-06,2.78826e-08,0.29688,0.00109395,1.21833e-06,-2.45915e-08,0.297975,0.00109632,1.14456e-06,1.08787e-08,0.299073,0.00109864,1.17719e-06,1.08788e-08,0.300172,0.00110102,1.20983e-06,-2.45915e-08,0.301275,0.00110337,1.13605e-06,2.78828e-08,0.302379,0.00110573,1.2197e-06,-2.73348e-08,0.303486,0.00110808,1.1377e-06,2.18518e-08,0.304595,0.00111042,1.20325e-06,-4.67556e-10,0.305707,0.00111283,1.20185e-06,-1.99816e-08,0.306821,0.00111517,1.14191e-06,2.07891e-08,0.307937,0.00111752,1.20427e-06,-3.57026e-09,0.309056,0.00111992,1.19356e-06,-6.50797e-09,0.310177,0.00112228,1.17404e-06,-2.00165e-10,0.3113,0.00112463,1.17344e-06,7.30874e-09,0.312426,0.001127,1.19536e-06,7.67424e-10,0.313554,0.00112939,1.19767e-06,-1.03784e-08,0.314685,0.00113176,1.16653e-06,1.09437e-08,0.315818,0.00113412,1.19936e-06,-3.59406e-09,0.316953,0.00113651,1.18858e-06,3.43251e-09,0.318091,0.0011389,1.19888e-06,-1.0136e-08,0.319231,0.00114127,1.16847e-06,7.30915e-09,0.320374,0.00114363,1.1904e-06,1.07018e-08,0.321518,0.00114604,1.2225e-06,-2.03137e-08,0.322666,0.00114842,1.16156e-06,1.09484e-08,0.323815,0.00115078,1.19441e-06,6.32224e-09,0.324967,0.00115319,1.21337e-06,-6.43509e-09,0.326122,0.00115559,1.19407e-06,-1.03842e-08,0.327278,0.00115795,1.16291e-06,1.81697e-08,0.328438,0.00116033,1.21742e-06,-2.6901e-09,0.329599,0.00116276,1.20935e-06,-7.40939e-09,0.330763,0.00116515,1.18713e-06,2.52533e-09,0.331929,0.00116754,1.1947e-06,-2.69191e-09,0.333098,0.00116992,1.18663e-06,8.24218e-09,0.334269,0.00117232,1.21135e-06,-4.74377e-10,0.335443,0.00117474,1.20993e-06,-6.34471e-09,0.336619,0.00117714,1.1909e-06,-3.94922e-09,0.337797,0.00117951,1.17905e-06,2.21417e-08,0.338978,0.00118193,1.24547e-06,-2.50128e-08,0.340161,0.00118435,1.17043e-06,1.8305e-08,0.341346,0.00118674,1.22535e-06,-1.84048e-08,0.342534,0.00118914,1.17013e-06,2.55121e-08,0.343725,0.00119156,1.24667e-06,-2.40389e-08,0.344917,0.00119398,1.17455e-06,1.10389e-08,0.346113,0.00119636,1.20767e-06,9.68574e-09,0.34731,0.0011988,1.23673e-06,-1.99797e-08,0.34851,0.00120122,1.17679e-06,1.06284e-08,0.349713,0.0012036,1.20867e-06,7.26868e-09,0.350917,0.00120604,1.23048e-06,-9.90072e-09,0.352125,0.00120847,1.20078e-06,2.53177e-09,0.353334,0.00121088,1.20837e-06,-2.26199e-10,0.354546,0.0012133,1.20769e-06,-1.62705e-09,0.355761,0.00121571,1.20281e-06,6.73435e-09,0.356978,0.00121813,1.22302e-06,4.49207e-09,0.358197,0.00122059,1.23649e-06,-2.47027e-08,0.359419,0.00122299,1.16238e-06,3.47142e-08,0.360643,0.00122542,1.26653e-06,-2.47472e-08,0.36187,0.00122788,1.19229e-06,4.66965e-09,0.363099,0.00123028,1.20629e-06,6.06872e-09,0.36433,0.00123271,1.2245e-06,8.57729e-10,0.365564,0.00123516,1.22707e-06,-9.49952e-09,0.366801,0.00123759,1.19858e-06,7.33792e-09,0.36804,0.00124001,1.22059e-06,9.95025e-09,0.369281,0.00124248,1.25044e-06,-1.73366e-08,0.370525,0.00124493,1.19843e-06,-2.08464e-10,0.371771,0.00124732,1.1978e-06,1.81704e-08,0.373019,0.00124977,1.25232e-06,-1.28683e-08,0.37427,0.00125224,1.21371e-06,3.50042e-09,0.375524,0.00125468,1.22421e-06,-1.1335e-09,0.37678,0.00125712,1.22081e-06,1.03345e-09,0.378038,0.00125957,1.22391e-06,-3.00023e-09,0.379299,0.00126201,1.21491e-06,1.09676e-08,0.380562,0.00126447,1.24781e-06,-1.10676e-08,0.381828,0.00126693,1.21461e-06,3.50042e-09,0.383096,0.00126937,1.22511e-06,-2.93403e-09,0.384366,0.00127181,1.21631e-06,8.23574e-09,0.385639,0.00127427,1.24102e-06,-2.06607e-10,0.386915,0.00127675,1.2404e-06,-7.40935e-09,0.388193,0.00127921,1.21817e-06,4.1761e-11,0.389473,0.00128165,1.21829e-06,7.24223e-09,0.390756,0.0012841,1.24002e-06,7.91564e-10,0.392042,0.00128659,1.2424e-06,-1.04086e-08,0.393329,0.00128904,1.21117e-06,1.10405e-08,0.39462,0.0012915,1.24429e-06,-3.951e-09,0.395912,0.00129397,1.23244e-06,4.7634e-09,0.397208,0.00129645,1.24673e-06,-1.51025e-08,0.398505,0.0012989,1.20142e-06,2.58443e-08,0.399805,0.00130138,1.27895e-06,-2.86702e-08,0.401108,0.00130385,1.19294e-06,2.92318e-08,0.402413,0.00130632,1.28064e-06,-2.86524e-08,0.403721,0.0013088,1.19468e-06,2.57731e-08,0.405031,0.00131127,1.272e-06,-1.48355e-08,0.406343,0.00131377,1.2275e-06,3.76652e-09,0.407658,0.00131623,1.23879e-06,-2.30784e-10,0.408976,0.00131871,1.2381e-06,-2.84331e-09,0.410296,0.00132118,1.22957e-06,1.16041e-08,0.411618,0.00132367,1.26438e-06,-1.37708e-08,0.412943,0.00132616,1.22307e-06,1.36768e-08,0.41427,0.00132865,1.2641e-06,-1.1134e-08,0.4156,0.00133114,1.2307e-06,1.05714e-09,0.416933,0.00133361,1.23387e-06,6.90538e-09,0.418267,0.00133609,1.25459e-06,1.12372e-09,0.419605,0.00133861,1.25796e-06,-1.14002e-08,0.420945,0.00134109,1.22376e-06,1.46747e-08,0.422287,0.00134358,1.26778e-06,-1.7496e-08,0.423632,0.00134606,1.21529e-06,2.5507e-08,0.424979,0.00134857,1.29182e-06,-2.49272e-08,0.426329,0.00135108,1.21703e-06,1.45972e-08,0.427681,0.00135356,1.26083e-06,-3.65935e-09,0.429036,0.00135607,1.24985e-06,4.00178e-11,0.430393,0.00135857,1.24997e-06,3.49917e-09,0.431753,0.00136108,1.26047e-06,-1.40366e-08,0.433116,0.00136356,1.21836e-06,2.28448e-08,0.43448,0.00136606,1.28689e-06,-1.77378e-08,0.435848,0.00136858,1.23368e-06,1.83043e-08,0.437218,0.0013711,1.28859e-06,-2.56769e-08,0.43859,0.0013736,1.21156e-06,2.47987e-08,0.439965,0.0013761,1.28595e-06,-1.39133e-08,0.441342,0.00137863,1.24421e-06,1.05202e-09,0.442722,0.00138112,1.24737e-06,9.70507e-09,0.444104,0.00138365,1.27649e-06,-1.00698e-08,0.445489,0.00138617,1.24628e-06,7.72123e-10,0.446877,0.00138867,1.24859e-06,6.98132e-09,0.448267,0.00139118,1.26954e-06,1.10477e-09,0.449659,0.00139373,1.27285e-06,-1.14003e-08,0.451054,0.00139624,1.23865e-06,1.4694e-08,0.452452,0.00139876,1.28273e-06,-1.75734e-08,0.453852,0.00140127,1.23001e-06,2.5797e-08,0.455254,0.00140381,1.3074e-06,-2.60097e-08,0.456659,0.00140635,1.22937e-06,1.86371e-08,0.458067,0.00140886,1.28529e-06,-1.8736e-08,0.459477,0.00141137,1.22908e-06,2.65048e-08,0.46089,0.00141391,1.30859e-06,-2.76784e-08,0.462305,0.00141645,1.22556e-06,2.46043e-08,0.463722,0.00141897,1.29937e-06,-1.11341e-08,0.465143,0.00142154,1.26597e-06,-9.87033e-09,0.466565,0.00142404,1.23636e-06,2.08131e-08,0.467991,0.00142657,1.2988e-06,-1.37773e-08,0.469419,0.00142913,1.25746e-06,4.49378e-09,0.470849,0.00143166,1.27094e-06,-4.19781e-09,0.472282,0.00143419,1.25835e-06,1.22975e-08,0.473717,0.00143674,1.29524e-06,-1.51902e-08,0.475155,0.00143929,1.24967e-06,1.86608e-08,0.476596,0.00144184,1.30566e-06,-2.96506e-08,0.478039,0.00144436,1.2167e-06,4.03368e-08,0.479485,0.00144692,1.33771e-06,-4.22896e-08,0.480933,0.00144947,1.21085e-06,3.94148e-08,0.482384,0.00145201,1.32909e-06,-2.59626e-08,0.483837,0.00145459,1.2512e-06,4.83124e-09,0.485293,0.0014571,1.2657e-06,6.63757e-09,0.486751,0.00145966,1.28561e-06,-1.57911e-09,0.488212,0.00146222,1.28087e-06,-3.21468e-10,0.489676,0.00146478,1.27991e-06,2.86517e-09,0.491142,0.00146735,1.2885e-06,-1.11392e-08,0.49261,0.00146989,1.25508e-06,1.18893e-08,0.494081,0.00147244,1.29075e-06,-6.61574e-09,0.495555,0.001475,1.27091e-06,1.45736e-08,0.497031,0.00147759,1.31463e-06,-2.18759e-08,0.49851,0.00148015,1.249e-06,1.33252e-08,0.499992,0.00148269,1.28897e-06,-1.62277e-09,0.501476,0.00148526,1.28411e-06,-6.83421e-09,0.502962,0.00148781,1.2636e-06,2.89596e-08,0.504451,0.00149042,1.35048e-06,-4.93997e-08,0.505943,0.00149298,1.20228e-06,4.94299e-08,0.507437,0.00149553,1.35057e-06,-2.91107e-08,0.508934,0.00149814,1.26324e-06,7.40848e-09,0.510434,0.00150069,1.28547e-06,-5.23187e-10,0.511936,0.00150326,1.2839e-06,-5.31585e-09,0.51344,0.00150581,1.26795e-06,2.17866e-08,0.514947,0.00150841,1.33331e-06,-2.22257e-08,0.516457,0.00151101,1.26663e-06,7.51178e-09,0.517969,0.00151357,1.28917e-06,-7.82128e-09,0.519484,0.00151613,1.2657e-06,2.37733e-08,0.521002,0.00151873,1.33702e-06,-2.76674e-08,0.522522,0.00152132,1.25402e-06,2.72917e-08,0.524044,0.00152391,1.3359e-06,-2.18949e-08,0.525569,0.00152652,1.27021e-06,6.83372e-10,0.527097,0.00152906,1.27226e-06,1.91613e-08,0.528628,0.00153166,1.32974e-06,-1.77241e-08,0.53016,0.00153427,1.27657e-06,-7.86963e-09,0.531696,0.0015368,1.25296e-06,4.92027e-08,0.533234,0.00153945,1.40057e-06,-6.9732e-08,0.534775,0.00154204,1.19138e-06,5.09114e-08,0.536318,0.00154458,1.34411e-06,-1.4704e-08,0.537864,0.00154722,1.3e-06,7.9048e-09,0.539413,0.00154984,1.32371e-06,-1.69152e-08,0.540964,0.00155244,1.27297e-06,1.51355e-10,0.542517,0.00155499,1.27342e-06,1.63099e-08,0.544074,0.00155758,1.32235e-06,-5.78647e-09,0.545633,0.00156021,1.30499e-06,6.83599e-09,0.547194,0.00156284,1.3255e-06,-2.15575e-08,0.548758,0.00156543,1.26083e-06,1.97892e-08,0.550325,0.00156801,1.32019e-06,2.00525e-09,0.551894,0.00157065,1.32621e-06,-2.78103e-08,0.553466,0.00157322,1.24278e-06,4.96314e-08,0.555041,0.00157586,1.39167e-06,-5.1506e-08,0.556618,0.00157849,1.23716e-06,3.71835e-08,0.558198,0.00158107,1.34871e-06,-3.76233e-08,0.55978,0.00158366,1.23584e-06,5.37052e-08,0.561365,0.00158629,1.39695e-06,-5.79884e-08,0.562953,0.00158891,1.22299e-06,5.90392e-08,0.564543,0.00159153,1.4001e-06,-5.89592e-08,0.566136,0.00159416,1.22323e-06,5.7588e-08,0.567731,0.00159678,1.39599e-06,-5.21835e-08,0.569329,0.00159941,1.23944e-06,3.19369e-08,0.57093,0.00160199,1.33525e-06,-1.59594e-08,0.572533,0.00160461,1.28737e-06,3.19006e-08,0.574139,0.00160728,1.38307e-06,-5.20383e-08,0.575748,0.00160989,1.22696e-06,5.70431e-08,0.577359,0.00161251,1.39809e-06,-5.69247e-08,0.578973,0.00161514,1.22731e-06,5.14463e-08,0.580589,0.00161775,1.38165e-06,-2.9651e-08,0.582208,0.00162042,1.2927e-06,7.55339e-09,0.58383,0.00162303,1.31536e-06,-5.62636e-10,0.585455,0.00162566,1.31367e-06,-5.30281e-09,0.587081,0.00162827,1.29776e-06,2.17738e-08,0.588711,0.00163093,1.36309e-06,-2.21875e-08,0.590343,0.00163359,1.29652e-06,7.37164e-09,0.591978,0.00163621,1.31864e-06,-7.29907e-09,0.593616,0.00163882,1.29674e-06,2.18247e-08,0.595256,0.00164148,1.36221e-06,-2.03952e-08,0.596899,0.00164414,1.30103e-06,1.51241e-10,0.598544,0.00164675,1.30148e-06,1.97902e-08,0.600192,0.00164941,1.36085e-06,-1.97074e-08,0.601843,0.00165207,1.30173e-06,-5.65175e-10,0.603496,0.00165467,1.30004e-06,2.1968e-08,0.605152,0.00165734,1.36594e-06,-2.77024e-08,0.606811,0.00165999,1.28283e-06,2.92369e-08,0.608472,0.00166264,1.37054e-06,-2.96407e-08,0.610136,0.00166529,1.28162e-06,2.97215e-08,0.611803,0.00166795,1.37079e-06,-2.96408e-08,0.613472,0.0016706,1.28186e-06,2.92371e-08,0.615144,0.00167325,1.36957e-06,-2.77031e-08,0.616819,0.00167591,1.28647e-06,2.19708e-08,0.618496,0.00167855,1.35238e-06,-5.75407e-10,0.620176,0.00168125,1.35065e-06,-1.9669e-08,0.621858,0.00168389,1.29164e-06,1.96468e-08,0.623544,0.00168653,1.35058e-06,6.86403e-10,0.625232,0.00168924,1.35264e-06,-2.23924e-08,0.626922,0.00169187,1.28547e-06,2.92788e-08,0.628615,0.00169453,1.3733e-06,-3.51181e-08,0.630311,0.00169717,1.26795e-06,5.15889e-08,0.63201,0.00169987,1.42272e-06,-5.2028e-08,0.633711,0.00170255,1.26663e-06,3.73139e-08,0.635415,0.0017052,1.37857e-06,-3.76227e-08,0.637121,0.00170784,1.2657e-06,5.35722e-08,0.63883,0.00171054,1.42642e-06,-5.74567e-08,0.640542,0.00171322,1.25405e-06,5.70456e-08,0.642257,0.0017159,1.42519e-06,-5.15163e-08,0.643974,0.00171859,1.27064e-06,2.98103e-08,0.645694,0.00172122,1.36007e-06,-8.12016e-09,0.647417,0.00172392,1.33571e-06,2.67039e-09,0.649142,0.0017266,1.34372e-06,-2.56152e-09,0.65087,0.00172928,1.33604e-06,7.57571e-09,0.6526,0.00173197,1.35876e-06,-2.77413e-08,0.654334,0.00173461,1.27554e-06,4.3785e-08,0.65607,0.00173729,1.40689e-06,-2.81896e-08,0.657808,0.00174002,1.32233e-06,9.36893e-09,0.65955,0.00174269,1.35043e-06,-9.28617e-09,0.661294,0.00174536,1.32257e-06,2.77757e-08,0.66304,0.00174809,1.4059e-06,-4.2212e-08,0.66479,0.00175078,1.27926e-06,2.1863e-08,0.666542,0.0017534,1.34485e-06,1.43648e-08,0.668297,0.00175613,1.38795e-06,-1.97177e-08,0.670054,0.00175885,1.3288e-06,4.90115e-09,0.671814,0.00176152,1.3435e-06,1.13232e-10,0.673577,0.00176421,1.34384e-06,-5.3542e-09,0.675343,0.00176688,1.32778e-06,2.13035e-08,0.677111,0.0017696,1.39169e-06,-2.02553e-08,0.678882,0.00177232,1.33092e-06,1.13005e-10,0.680656,0.00177499,1.33126e-06,1.98031e-08,0.682432,0.00177771,1.39067e-06,-1.97211e-08,0.684211,0.00178043,1.33151e-06,-5.2349e-10,0.685993,0.00178309,1.32994e-06,2.18151e-08,0.687777,0.00178582,1.39538e-06,-2.71325e-08,0.689564,0.00178853,1.31398e-06,2.71101e-08,0.691354,0.00179124,1.39531e-06,-2.17035e-08,0.693147,0.00179396,1.3302e-06,9.92865e-11,0.694942,0.00179662,1.3305e-06,2.13063e-08,0.69674,0.00179935,1.39442e-06,-2.57198e-08,0.698541,0.00180206,1.31726e-06,2.19682e-08,0.700344,0.00180476,1.38317e-06,-2.54852e-09,0.70215,0.00180752,1.37552e-06,-1.17741e-08,0.703959,0.00181023,1.3402e-06,-9.95999e-09,0.705771,0.00181288,1.31032e-06,5.16141e-08,0.707585,0.00181566,1.46516e-06,-7.72869e-08,0.709402,0.00181836,1.2333e-06,7.87197e-08,0.711222,0.00182106,1.46946e-06,-5.87781e-08,0.713044,0.00182382,1.29312e-06,3.71834e-08,0.714869,0.00182652,1.40467e-06,-3.03511e-08,0.716697,0.00182924,1.31362e-06,2.46161e-08,0.718528,0.00183194,1.38747e-06,-8.5087e-09,0.720361,0.00183469,1.36194e-06,9.41892e-09,0.722197,0.00183744,1.3902e-06,-2.91671e-08,0.724036,0.00184014,1.3027e-06,4.76448e-08,0.725878,0.00184288,1.44563e-06,-4.22028e-08,0.727722,0.00184565,1.31902e-06,1.95682e-09,0.729569,0.00184829,1.3249e-06,3.43754e-08,0.731419,0.00185104,1.42802e-06,-2.0249e-08,0.733271,0.00185384,1.36727e-06,-1.29838e-08,0.735126,0.00185654,1.32832e-06,1.25794e-08,0.736984,0.00185923,1.36606e-06,2.22711e-08,0.738845,0.00186203,1.43287e-06,-4.20594e-08,0.740708,0.00186477,1.3067e-06,2.67571e-08,0.742574,0.00186746,1.38697e-06,-5.36424e-09,0.744443,0.00187022,1.37087e-06,-5.30023e-09,0.746315,0.00187295,1.35497e-06,2.65653e-08,0.748189,0.00187574,1.43467e-06,-4.13564e-08,0.750066,0.00187848,1.3106e-06,1.9651e-08,0.751946,0.00188116,1.36955e-06,2.23572e-08,0.753828,0.00188397,1.43663e-06,-4.9475e-08,0.755714,0.00188669,1.2882e-06,5.63335e-08,0.757602,0.00188944,1.4572e-06,-5.66499e-08,0.759493,0.00189218,1.28725e-06,5.10567e-08,0.761386,0.00189491,1.44042e-06,-2.83677e-08,0.763283,0.00189771,1.35532e-06,2.80962e-09,0.765182,0.00190042,1.36375e-06,1.71293e-08,0.767083,0.0019032,1.41513e-06,-1.17221e-08,0.768988,0.001906,1.37997e-06,-2.98453e-08,0.770895,0.00190867,1.29043e-06,7.14987e-08,0.772805,0.00191146,1.50493e-06,-7.73354e-08,0.774718,0.00191424,1.27292e-06,5.90292e-08,0.776634,0.00191697,1.45001e-06,-3.9572e-08,0.778552,0.00191975,1.33129e-06,3.9654e-08,0.780473,0.00192253,1.45026e-06,-5.94395e-08,0.782397,0.00192525,1.27194e-06,7.88945e-08,0.784324,0.00192803,1.50862e-06,-7.73249e-08,0.786253,0.00193082,1.27665e-06,5.15913e-08,0.788185,0.00193352,1.43142e-06,-9.83099e-09,0.79012,0.00193636,1.40193e-06,-1.22672e-08,0.792058,0.00193912,1.36513e-06,-7.05275e-10,0.793999,0.00194185,1.36301e-06,1.50883e-08,0.795942,0.00194462,1.40828e-06,-4.33147e-11,0.797888,0.00194744,1.40815e-06,-1.49151e-08,0.799837,0.00195021,1.3634e-06,9.93244e-11,0.801788,0.00195294,1.3637e-06,1.45179e-08,0.803743,0.00195571,1.40725e-06,1.43363e-09,0.8057,0.00195853,1.41155e-06,-2.02525e-08,0.80766,0.00196129,1.35079e-06,1.99718e-08,0.809622,0.00196405,1.41071e-06,-3.01649e-11,0.811588,0.00196687,1.41062e-06,-1.9851e-08,0.813556,0.00196964,1.35107e-06,1.98296e-08,0.815527,0.0019724,1.41056e-06,1.37485e-10,0.817501,0.00197522,1.41097e-06,-2.03796e-08,0.819477,0.00197798,1.34983e-06,2.17763e-08,0.821457,0.00198074,1.41516e-06,-7.12085e-09,0.823439,0.00198355,1.3938e-06,6.70707e-09,0.825424,0.00198636,1.41392e-06,-1.97074e-08,0.827412,0.00198913,1.35479e-06,1.25179e-08,0.829402,0.00199188,1.39235e-06,2.92405e-08,0.831396,0.00199475,1.48007e-06,-6.98755e-08,0.833392,0.0019975,1.27044e-06,7.14477e-08,0.835391,0.00200026,1.48479e-06,-3.71014e-08,0.837392,0.00200311,1.37348e-06,1.73533e-08,0.839397,0.00200591,1.42554e-06,-3.23118e-08,0.841404,0.00200867,1.32861e-06,5.2289e-08,0.843414,0.00201148,1.48547e-06,-5.76348e-08,0.845427,0.00201428,1.31257e-06,5.9041e-08,0.847443,0.00201708,1.48969e-06,-5.93197e-08,0.849461,0.00201988,1.31173e-06,5.90289e-08,0.851482,0.00202268,1.48882e-06,-5.75864e-08,0.853507,0.00202549,1.31606e-06,5.21075e-08,0.855533,0.00202828,1.47238e-06,-3.16344e-08,0.857563,0.00203113,1.37748e-06,1.48257e-08,0.859596,0.00203393,1.42196e-06,-2.76684e-08,0.861631,0.00203669,1.33895e-06,3.62433e-08,0.863669,0.00203947,1.44768e-06,1.90463e-09,0.86571,0.00204237,1.45339e-06,-4.38617e-08,0.867754,0.00204515,1.32181e-06,5.43328e-08,0.8698,0.00204796,1.48481e-06,-5.42603e-08,0.87185,0.00205076,1.32203e-06,4.34989e-08,0.873902,0.00205354,1.45252e-06,-5.26029e-10,0.875957,0.00205644,1.45095e-06,-4.13949e-08,0.878015,0.00205922,1.32676e-06,4.68962e-08,0.880075,0.00206201,1.46745e-06,-2.69807e-08,0.882139,0.00206487,1.38651e-06,1.42181e-09,0.884205,0.00206764,1.39077e-06,2.12935e-08,0.886274,0.00207049,1.45465e-06,-2.69912e-08,0.888346,0.00207332,1.37368e-06,2.70664e-08,0.890421,0.00207615,1.45488e-06,-2.16698e-08,0.892498,0.00207899,1.38987e-06,8.14756e-12,0.894579,0.00208177,1.38989e-06,2.16371e-08,0.896662,0.00208462,1.45481e-06,-2.6952e-08,0.898748,0.00208744,1.37395e-06,2.65663e-08,0.900837,0.00209027,1.45365e-06,-1.97084e-08,0.902928,0.00209312,1.39452e-06,-7.33731e-09,0.905023,0.00209589,1.37251e-06,4.90578e-08,0.90712,0.00209878,1.51968e-06,-6.96845e-08,0.90922,0.00210161,1.31063e-06,5.08664e-08,0.911323,0.00210438,1.46323e-06,-1.45717e-08,0.913429,0.00210727,1.41952e-06,7.42038e-09,0.915538,0.00211013,1.44178e-06,-1.51097e-08,0.917649,0.00211297,1.39645e-06,-6.58618e-09,0.919764,0.00211574,1.37669e-06,4.14545e-08,0.921881,0.00211862,1.50105e-06,-4.00222e-08,0.924001,0.0021215,1.38099e-06,-5.7518e-10,0.926124,0.00212426,1.37926e-06,4.23229e-08,0.92825,0.00212714,1.50623e-06,-4.9507e-08,0.930378,0.00213001,1.35771e-06,3.64958e-08,0.93251,0.00213283,1.4672e-06,-3.68713e-08,0.934644,0.00213566,1.35658e-06,5.13848e-08,0.936781,0.00213852,1.51074e-06,-4.94585e-08,0.938921,0.0021414,1.36236e-06,2.72399e-08,0.941064,0.0021442,1.44408e-06,1.0372e-10,0.943209,0.00214709,1.44439e-06,-2.76547e-08,0.945358,0.0021499,1.36143e-06,5.09106e-08,0.947509,0.00215277,1.51416e-06,-5.67784e-08,0.949663,0.00215563,1.34382e-06,5.69935e-08,0.95182,0.00215849,1.5148e-06,-5.19861e-08,0.95398,0.00216136,1.35885e-06,3.17417e-08,0.956143,0.00216418,1.45407e-06,-1.53758e-08,0.958309,0.00216704,1.40794e-06,2.97615e-08,0.960477,0.00216994,1.49723e-06,-4.40657e-08,0.962649,0.00217281,1.36503e-06,2.72919e-08,0.964823,0.00217562,1.44691e-06,-5.49729e-09,0.967,0.0021785,1.43041e-06,-5.30273e-09,0.96918,0.00218134,1.41451e-06,2.67084e-08,0.971363,0.00218425,1.49463e-06,-4.19265e-08,0.973548,0.00218711,1.36885e-06,2.17881e-08,0.975737,0.00218992,1.43422e-06,1.43789e-08,0.977928,0.00219283,1.47735e-06,-1.96989e-08,0.980122,0.00219572,1.41826e-06,4.81221e-09,0.98232,0.00219857,1.43269e-06,4.50048e-10,0.98452,0.00220144,1.43404e-06,-6.61237e-09,0.986722,0.00220429,1.41421e-06,2.59993e-08,0.988928,0.0022072,1.4922e-06,-3.77803e-08,0.991137,0.00221007,1.37886e-06,5.9127e-09,0.993348,0.00221284,1.3966e-06,1.33339e-07,0.995563,0.00221604,1.79662e-06,-5.98872e-07,0.99778,0.00222015,0.,0.}; + + __device__ static int LabCbrt_b(int i) + { + float x = i * (1.f / (255.f * (1 << gamma_shift))); + return (1 << lab_shift2) * (x < 0.008856f ? x * 7.787f + 0.13793103448275862f : ::cbrtf(x)); + } + + __device__ static float splineInterpolate(float x, const float* tab, int n) + { + int ix = ::min(::max(int(x), 0), n-1); + x -= ix; + tab += ix * 4; + return ((tab[3] * x + tab[2]) * x + tab[1]) * x + tab[0]; + } + + template struct RGB2Lab; + + template struct RGB2Lab + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const int Lscale = (116 * 255 + 50) / 100; + const int Lshift = -((16 * 255 * (1 << lab_shift2) + 50) / 100); + + int B = blueIdx == 0 ? src.x : src.z; + int G = src.y; + int R = blueIdx == 0 ? src.z : src.x; + + if (srgb) + { + B = c_sRGBGammaTab_b[B]; + G = c_sRGBGammaTab_b[G]; + R = c_sRGBGammaTab_b[R]; + } + else + { + B <<= 3; + G <<= 3; + R <<= 3; + } + + int fX = LabCbrt_b(CV_CUDEV_DESCALE(B * 778 + G * 1541 + R * 1777, lab_shift)); + int fY = LabCbrt_b(CV_CUDEV_DESCALE(B * 296 + G * 2929 + R * 871, lab_shift)); + int fZ = LabCbrt_b(CV_CUDEV_DESCALE(B * 3575 + G * 448 + R * 73, lab_shift)); + + int L = CV_CUDEV_DESCALE(Lscale * fY + Lshift, lab_shift2); + int a = CV_CUDEV_DESCALE(500 * (fX - fY) + 128 * (1 << lab_shift2), lab_shift2); + int b = CV_CUDEV_DESCALE(200 * (fY - fZ) + 128 * (1 << lab_shift2), lab_shift2); + + typename MakeVec::type dst; + + dst.x = saturate_cast(L); + dst.y = saturate_cast(a); + dst.z = saturate_cast(b); + + return dst; + } + }; + + template struct RGB2Lab + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const float _1_3 = 1.0f / 3.0f; + const float _a = 16.0f / 116.0f; + + float B = blueIdx == 0 ? src.x : src.z; + float G = src.y; + float R = blueIdx == 0 ? src.z : src.x; + + if (srgb) + { + B = splineInterpolate(B * GAMMA_TAB_SIZE, c_sRGBGammaTab, GAMMA_TAB_SIZE); + G = splineInterpolate(G * GAMMA_TAB_SIZE, c_sRGBGammaTab, GAMMA_TAB_SIZE); + R = splineInterpolate(R * GAMMA_TAB_SIZE, c_sRGBGammaTab, GAMMA_TAB_SIZE); + } + + float X = B * 0.189828f + G * 0.376219f + R * 0.433953f; + float Y = B * 0.072169f + G * 0.715160f + R * 0.212671f; + float Z = B * 0.872766f + G * 0.109477f + R * 0.017758f; + + float FX = X > 0.008856f ? ::powf(X, _1_3) : (7.787f * X + _a); + float FY = Y > 0.008856f ? ::powf(Y, _1_3) : (7.787f * Y + _a); + float FZ = Z > 0.008856f ? ::powf(Z, _1_3) : (7.787f * Z + _a); + + float L = Y > 0.008856f ? (116.f * FY - 16.f) : (903.3f * Y); + float a = 500.f * (FX - FY); + float b = 200.f * (FY - FZ); + + typename MakeVec::type dst; + + dst.x = L; + dst.y = a; + dst.z = b; + + return dst; + } + }; + + // Lab to RGB + + __constant__ float c_sRGBInvGammaTab[] = {0,0.0126255,0.,-8.33961e-06,0.0126172,0.0126005,-2.50188e-05,4.1698e-05,0.0252344,0.0126756,0.000100075,-0.000158451,0.0378516,0.0124004,-0.000375277,-0.000207393,0.0496693,0.0110276,-0.000997456,0.00016837,0.0598678,0.00953783,-0.000492346,2.07235e-05,0.068934,0.00861531,-0.000430176,3.62876e-05,0.0771554,0.00786382,-0.000321313,1.87625e-05,0.0847167,0.00727748,-0.000265025,1.53594e-05,0.0917445,0.00679351,-0.000218947,1.10545e-05,0.0983301,0.00638877,-0.000185784,8.66984e-06,0.104542,0.00604322,-0.000159774,6.82996e-06,0.110432,0.00574416,-0.000139284,5.51008e-06,0.116042,0.00548212,-0.000122754,4.52322e-06,0.121406,0.00525018,-0.000109184,3.75557e-06,0.126551,0.00504308,-9.79177e-05,3.17134e-06,0.131499,0.00485676,-8.84037e-05,2.68469e-06,0.13627,0.004688,-8.03496e-05,2.31725e-06,0.14088,0.00453426,-7.33978e-05,2.00868e-06,0.145343,0.00439349,-6.73718e-05,1.74775e-06,0.149671,0.00426399,-6.21286e-05,1.53547e-06,0.153875,0.00414434,-5.75222e-05,1.364e-06,0.157963,0.00403338,-5.34301e-05,1.20416e-06,0.161944,0.00393014,-4.98177e-05,1.09114e-06,0.165825,0.00383377,-4.65443e-05,9.57987e-07,0.169613,0.00374356,-4.36703e-05,8.88359e-07,0.173314,0.00365888,-4.10052e-05,7.7849e-07,0.176933,0.00357921,-3.86697e-05,7.36254e-07,0.180474,0.00350408,-3.6461e-05,6.42534e-07,0.183942,0.00343308,-3.45334e-05,6.12614e-07,0.187342,0.00336586,-3.26955e-05,5.42894e-07,0.190675,0.00330209,-3.10669e-05,5.08967e-07,0.193947,0.00324149,-2.954e-05,4.75977e-07,0.197159,0.00318383,-2.8112e-05,4.18343e-07,0.200315,0.00312887,-2.6857e-05,4.13651e-07,0.203418,0.00307639,-2.5616e-05,3.70847e-07,0.206469,0.00302627,-2.45035e-05,3.3813e-07,0.209471,0.00297828,-2.34891e-05,3.32999e-07,0.212426,0.0029323,-2.24901e-05,2.96826e-07,0.215336,0.00288821,-2.15996e-05,2.82736e-07,0.218203,0.00284586,-2.07514e-05,2.70961e-07,0.221029,0.00280517,-1.99385e-05,2.42744e-07,0.223814,0.00276602,-1.92103e-05,2.33277e-07,0.226561,0.0027283,-1.85105e-05,2.2486e-07,0.229271,0.00269195,-1.78359e-05,2.08383e-07,0.231945,0.00265691,-1.72108e-05,1.93305e-07,0.234585,0.00262307,-1.66308e-05,1.80687e-07,0.237192,0.00259035,-1.60888e-05,1.86632e-07,0.239766,0.00255873,-1.55289e-05,1.60569e-07,0.24231,0.00252815,-1.50472e-05,1.54566e-07,0.244823,0.00249852,-1.45835e-05,1.59939e-07,0.247307,0.00246983,-1.41037e-05,1.29549e-07,0.249763,0.00244202,-1.3715e-05,1.41429e-07,0.252191,0.00241501,-1.32907e-05,1.39198e-07,0.254593,0.00238885,-1.28731e-05,1.06444e-07,0.256969,0.00236342,-1.25538e-05,1.2048e-07,0.25932,0.00233867,-1.21924e-05,1.26892e-07,0.261647,0.00231467,-1.18117e-05,8.72084e-08,0.26395,0.00229131,-1.15501e-05,1.20323e-07,0.26623,0.00226857,-1.11891e-05,8.71514e-08,0.268487,0.00224645,-1.09276e-05,9.73165e-08,0.270723,0.00222489,-1.06357e-05,8.98259e-08,0.272937,0.00220389,-1.03662e-05,7.98218e-08,0.275131,0.00218339,-1.01267e-05,9.75254e-08,0.277304,0.00216343,-9.83416e-06,6.65195e-08,0.279458,0.00214396,-9.63461e-06,8.34313e-08,0.281592,0.00212494,-9.38431e-06,7.65919e-08,0.283708,0.00210641,-9.15454e-06,5.7236e-08,0.285805,0.00208827,-8.98283e-06,8.18939e-08,0.287885,0.00207055,-8.73715e-06,6.2224e-08,0.289946,0.00205326,-8.55047e-06,5.66388e-08,0.291991,0.00203633,-8.38056e-06,6.88491e-08,0.294019,0.00201978,-8.17401e-06,5.53955e-08,0.296031,0.00200359,-8.00782e-06,6.71971e-08,0.298027,0.00198778,-7.80623e-06,3.34439e-08,0.300007,0.00197227,-7.7059e-06,6.7248e-08,0.301971,0.00195706,-7.50416e-06,5.51915e-08,0.303921,0.00194221,-7.33858e-06,3.98124e-08,0.305856,0.00192766,-7.21915e-06,5.37795e-08,0.307776,0.00191338,-7.05781e-06,4.30919e-08,0.309683,0.00189939,-6.92853e-06,4.20744e-08,0.311575,0.00188566,-6.80231e-06,5.68321e-08,0.313454,0.00187223,-6.63181e-06,2.86195e-08,0.31532,0.00185905,-6.54595e-06,3.73075e-08,0.317172,0.00184607,-6.43403e-06,6.05684e-08,0.319012,0.00183338,-6.25233e-06,1.84426e-08,0.320839,0.00182094,-6.197e-06,4.44757e-08,0.322654,0.00180867,-6.06357e-06,4.20729e-08,0.324456,0.00179667,-5.93735e-06,2.56511e-08,0.326247,0.00178488,-5.8604e-06,3.41368e-08,0.328026,0.00177326,-5.75799e-06,4.64177e-08,0.329794,0.00176188,-5.61874e-06,1.86107e-08,0.33155,0.0017507,-5.5629e-06,2.81511e-08,0.333295,0.00173966,-5.47845e-06,4.75987e-08,0.335029,0.00172884,-5.33565e-06,1.98726e-08,0.336753,0.00171823,-5.27604e-06,2.19226e-08,0.338466,0.00170775,-5.21027e-06,4.14483e-08,0.340169,0.00169745,-5.08592e-06,2.09017e-08,0.341861,0.00168734,-5.02322e-06,2.39561e-08,0.343543,0.00167737,-4.95135e-06,3.22852e-08,0.345216,0.00166756,-4.85449e-06,2.57173e-08,0.346878,0.00165793,-4.77734e-06,1.38569e-08,0.348532,0.00164841,-4.73577e-06,3.80634e-08,0.350175,0.00163906,-4.62158e-06,1.27043e-08,0.35181,0.00162985,-4.58347e-06,3.03279e-08,0.353435,0.00162078,-4.49249e-06,1.49961e-08,0.355051,0.00161184,-4.4475e-06,2.88977e-08,0.356659,0.00160303,-4.3608e-06,1.84241e-08,0.358257,0.00159436,-4.30553e-06,1.6616e-08,0.359848,0.0015858,-4.25568e-06,3.43218e-08,0.361429,0.00157739,-4.15272e-06,-4.89172e-09,0.363002,0.00156907,-4.16739e-06,4.48498e-08,0.364567,0.00156087,-4.03284e-06,4.30676e-09,0.366124,0.00155282,-4.01992e-06,2.73303e-08,0.367673,0.00154486,-3.93793e-06,5.58036e-09,0.369214,0.001537,-3.92119e-06,3.97554e-08,0.370747,0.00152928,-3.80193e-06,-1.55904e-08,0.372272,0.00152163,-3.8487e-06,5.24081e-08,0.37379,0.00151409,-3.69147e-06,-1.52272e-08,0.375301,0.00150666,-3.73715e-06,3.83028e-08,0.376804,0.0014993,-3.62225e-06,1.10278e-08,0.378299,0.00149209,-3.58916e-06,6.99326e-09,0.379788,0.00148493,-3.56818e-06,2.06038e-08,0.381269,0.00147786,-3.50637e-06,2.98009e-08,0.382744,0.00147093,-3.41697e-06,-2.05978e-08,0.384211,0.00146404,-3.47876e-06,5.25899e-08,0.385672,0.00145724,-3.32099e-06,-1.09471e-08,0.387126,0.00145056,-3.35383e-06,2.10009e-08,0.388573,0.00144392,-3.29083e-06,1.63501e-08,0.390014,0.00143739,-3.24178e-06,3.00641e-09,0.391448,0.00143091,-3.23276e-06,3.12282e-08,0.392875,0.00142454,-3.13908e-06,-8.70932e-09,0.394297,0.00141824,-3.16521e-06,3.34114e-08,0.395712,0.00141201,-3.06497e-06,-5.72754e-09,0.397121,0.00140586,-3.08215e-06,1.9301e-08,0.398524,0.00139975,-3.02425e-06,1.7931e-08,0.39992,0.00139376,-2.97046e-06,-1.61822e-09,0.401311,0.00138781,-2.97531e-06,1.83442e-08,0.402696,0.00138192,-2.92028e-06,1.76485e-08,0.404075,0.00137613,-2.86733e-06,4.68617e-10,0.405448,0.00137039,-2.86593e-06,1.02794e-08,0.406816,0.00136469,-2.83509e-06,1.80179e-08,0.408178,0.00135908,-2.78104e-06,7.05594e-09,0.409534,0.00135354,-2.75987e-06,1.33633e-08,0.410885,0.00134806,-2.71978e-06,-9.04568e-10,0.41223,0.00134261,-2.72249e-06,2.0057e-08,0.41357,0.00133723,-2.66232e-06,1.00841e-08,0.414905,0.00133194,-2.63207e-06,-7.88835e-10,0.416234,0.00132667,-2.63444e-06,2.28734e-08,0.417558,0.00132147,-2.56582e-06,-1.29785e-09,0.418877,0.00131633,-2.56971e-06,1.21205e-08,0.420191,0.00131123,-2.53335e-06,1.24202e-08,0.421499,0.0013062,-2.49609e-06,-2.19681e-09,0.422803,0.0013012,-2.50268e-06,2.61696e-08,0.424102,0.00129628,-2.42417e-06,-1.30747e-08,0.425396,0.00129139,-2.46339e-06,2.6129e-08,0.426685,0.00128654,-2.38501e-06,-2.03454e-09,0.427969,0.00128176,-2.39111e-06,1.18115e-08,0.429248,0.00127702,-2.35567e-06,1.43932e-08,0.430523,0.00127235,-2.31249e-06,-9.77965e-09,0.431793,0.00126769,-2.34183e-06,2.47253e-08,0.433058,0.00126308,-2.26766e-06,2.85278e-10,0.434319,0.00125855,-2.2668e-06,3.93614e-09,0.435575,0.00125403,-2.25499e-06,1.37722e-08,0.436827,0.00124956,-2.21368e-06,5.79803e-10,0.438074,0.00124513,-2.21194e-06,1.37112e-08,0.439317,0.00124075,-2.1708e-06,4.17973e-09,0.440556,0.00123642,-2.15826e-06,-6.27703e-10,0.44179,0.0012321,-2.16015e-06,2.81332e-08,0.44302,0.00122787,-2.07575e-06,-2.24985e-08,0.444246,0.00122365,-2.14324e-06,3.20586e-08,0.445467,0.00121946,-2.04707e-06,-1.6329e-08,0.446685,0.00121532,-2.09605e-06,3.32573e-08,0.447898,0.00121122,-1.99628e-06,-2.72927e-08,0.449107,0.00120715,-2.07816e-06,4.6111e-08,0.450312,0.00120313,-1.93983e-06,-3.79416e-08,0.451514,0.00119914,-2.05365e-06,4.60507e-08,0.452711,0.00119517,-1.9155e-06,-2.7052e-08,0.453904,0.00119126,-1.99666e-06,3.23551e-08,0.455093,0.00118736,-1.89959e-06,-1.29613e-08,0.456279,0.00118352,-1.93848e-06,1.94905e-08,0.45746,0.0011797,-1.88e-06,-5.39588e-09,0.458638,0.00117593,-1.89619e-06,2.09282e-09,0.459812,0.00117214,-1.88991e-06,2.68267e-08,0.460982,0.00116844,-1.80943e-06,-1.99925e-08,0.462149,0.00116476,-1.86941e-06,2.3341e-08,0.463312,0.00116109,-1.79939e-06,-1.37674e-08,0.464471,0.00115745,-1.84069e-06,3.17287e-08,0.465627,0.00115387,-1.7455e-06,-2.37407e-08,0.466779,0.00115031,-1.81673e-06,3.34315e-08,0.467927,0.00114677,-1.71643e-06,-2.05786e-08,0.469073,0.00114328,-1.77817e-06,1.90802e-08,0.470214,0.00113978,-1.72093e-06,3.86247e-09,0.471352,0.00113635,-1.70934e-06,-4.72759e-09,0.472487,0.00113292,-1.72352e-06,1.50478e-08,0.473618,0.00112951,-1.67838e-06,4.14108e-09,0.474746,0.00112617,-1.66595e-06,-1.80986e-09,0.47587,0.00112283,-1.67138e-06,3.09816e-09,0.476991,0.0011195,-1.66209e-06,1.92198e-08,0.478109,0.00111623,-1.60443e-06,-2.03726e-08,0.479224,0.00111296,-1.66555e-06,3.2468e-08,0.480335,0.00110973,-1.56814e-06,-2.00922e-08,0.481443,0.00110653,-1.62842e-06,1.80983e-08,0.482548,0.00110333,-1.57413e-06,7.30362e-09,0.48365,0.0011002,-1.55221e-06,-1.75107e-08,0.484749,0.00109705,-1.60475e-06,3.29373e-08,0.485844,0.00109393,-1.50594e-06,-2.48315e-08,0.486937,0.00109085,-1.58043e-06,3.65865e-08,0.488026,0.0010878,-1.47067e-06,-3.21078e-08,0.489112,0.00108476,-1.56699e-06,3.22397e-08,0.490195,0.00108172,-1.47027e-06,-7.44391e-09,0.491276,0.00107876,-1.49261e-06,-2.46428e-09,0.492353,0.00107577,-1.5e-06,1.73011e-08,0.493427,0.00107282,-1.4481e-06,-7.13552e-09,0.494499,0.0010699,-1.4695e-06,1.1241e-08,0.495567,0.001067,-1.43578e-06,-8.02637e-09,0.496633,0.0010641,-1.45986e-06,2.08645e-08,0.497695,0.00106124,-1.39726e-06,-1.58271e-08,0.498755,0.0010584,-1.44475e-06,1.26415e-08,0.499812,0.00105555,-1.40682e-06,2.48655e-08,0.500866,0.00105281,-1.33222e-06,-5.24988e-08,0.501918,0.00104999,-1.48972e-06,6.59206e-08,0.502966,0.00104721,-1.29196e-06,-3.237e-08,0.504012,0.00104453,-1.38907e-06,3.95479e-09,0.505055,0.00104176,-1.3772e-06,1.65509e-08,0.506096,0.00103905,-1.32755e-06,-1.05539e-08,0.507133,0.00103637,-1.35921e-06,2.56648e-08,0.508168,0.00103373,-1.28222e-06,-3.25007e-08,0.509201,0.00103106,-1.37972e-06,4.47336e-08,0.51023,0.00102844,-1.24552e-06,-2.72245e-08,0.511258,0.00102587,-1.32719e-06,4.55952e-09,0.512282,0.00102323,-1.31352e-06,8.98645e-09,0.513304,0.00102063,-1.28656e-06,1.90992e-08,0.514323,0.00101811,-1.22926e-06,-2.57786e-08,0.51534,0.00101557,-1.30659e-06,2.44104e-08,0.516355,0.00101303,-1.23336e-06,-1.22581e-08,0.517366,0.00101053,-1.27014e-06,2.4622e-08,0.518376,0.00100806,-1.19627e-06,-2.66253e-08,0.519383,0.00100559,-1.27615e-06,2.22744e-08,0.520387,0.00100311,-1.20932e-06,-2.8679e-09,0.521389,0.00100068,-1.21793e-06,-1.08029e-08,0.522388,0.000998211,-1.25034e-06,4.60795e-08,0.523385,0.000995849,-1.1121e-06,-5.4306e-08,0.52438,0.000993462,-1.27502e-06,5.19354e-08,0.525372,0.000991067,-1.11921e-06,-3.42262e-08,0.526362,0.000988726,-1.22189e-06,2.53646e-08,0.52735,0.000986359,-1.14579e-06,-7.62782e-09,0.528335,0.000984044,-1.16868e-06,5.14668e-09,0.529318,0.000981722,-1.15324e-06,-1.29589e-08,0.530298,0.000979377,-1.19211e-06,4.66888e-08,0.531276,0.000977133,-1.05205e-06,-5.45868e-08,0.532252,0.000974865,-1.21581e-06,5.24495e-08,0.533226,0.000972591,-1.05846e-06,-3.60019e-08,0.534198,0.000970366,-1.16647e-06,3.19537e-08,0.535167,0.000968129,-1.07061e-06,-3.2208e-08,0.536134,0.000965891,-1.16723e-06,3.72738e-08,0.537099,0.000963668,-1.05541e-06,2.32205e-09,0.538061,0.000961564,-1.04844e-06,-4.65618e-08,0.539022,0.000959328,-1.18813e-06,6.47159e-08,0.53998,0.000957146,-9.93979e-07,-3.3488e-08,0.540936,0.000955057,-1.09444e-06,9.63166e-09,0.54189,0.000952897,-1.06555e-06,-5.03871e-09,0.542842,0.000950751,-1.08066e-06,1.05232e-08,0.543792,0.000948621,-1.04909e-06,2.25503e-08,0.544739,0.000946591,-9.81444e-07,-4.11195e-08,0.545685,0.000944504,-1.1048e-06,2.27182e-08,0.546628,0.000942363,-1.03665e-06,9.85146e-09,0.54757,0.000940319,-1.00709e-06,-2.51938e-09,0.548509,0.000938297,-1.01465e-06,2.25858e-10,0.549446,0.000936269,-1.01397e-06,1.61598e-09,0.550381,0.000934246,-1.00913e-06,-6.68983e-09,0.551315,0.000932207,-1.0292e-06,2.51434e-08,0.552246,0.000930224,-9.53765e-07,-3.42793e-08,0.553175,0.000928214,-1.0566e-06,5.23688e-08,0.554102,0.000926258,-8.99497e-07,-5.59865e-08,0.555028,0.000924291,-1.06746e-06,5.23679e-08,0.555951,0.000922313,-9.10352e-07,-3.42763e-08,0.556872,0.00092039,-1.01318e-06,2.51326e-08,0.557792,0.000918439,-9.37783e-07,-6.64954e-09,0.558709,0.000916543,-9.57732e-07,1.46554e-09,0.559625,0.000914632,-9.53335e-07,7.87281e-10,0.560538,0.000912728,-9.50973e-07,-4.61466e-09,0.56145,0.000910812,-9.64817e-07,1.76713e-08,0.56236,0.000908935,-9.11804e-07,-6.46564e-09,0.563268,0.000907092,-9.312e-07,8.19121e-09,0.564174,0.000905255,-9.06627e-07,-2.62992e-08,0.565078,0.000903362,-9.85524e-07,3.74007e-08,0.565981,0.000901504,-8.73322e-07,-4.0942e-09,0.566882,0.000899745,-8.85605e-07,-2.1024e-08,0.56778,0.00089791,-9.48677e-07,2.85854e-08,0.568677,0.000896099,-8.62921e-07,-3.3713e-08,0.569573,0.000894272,-9.64059e-07,4.6662e-08,0.570466,0.000892484,-8.24073e-07,-3.37258e-08,0.571358,0.000890734,-9.25251e-07,2.86365e-08,0.572247,0.00088897,-8.39341e-07,-2.12155e-08,0.573135,0.000887227,-9.02988e-07,-3.37913e-09,0.574022,0.000885411,-9.13125e-07,3.47319e-08,0.574906,0.000883689,-8.08929e-07,-1.63394e-08,0.575789,0.000882022,-8.57947e-07,-2.8979e-08,0.57667,0.00088022,-9.44885e-07,7.26509e-08,0.57755,0.000878548,-7.26932e-07,-8.28106e-08,0.578427,0.000876845,-9.75364e-07,7.97774e-08,0.579303,0.000875134,-7.36032e-07,-5.74849e-08,0.580178,0.00087349,-9.08486e-07,3.09529e-08,0.58105,0.000871765,-8.15628e-07,-6.72206e-09,0.581921,0.000870114,-8.35794e-07,-4.06451e-09,0.582791,0.00086843,-8.47987e-07,2.29799e-08,0.583658,0.000866803,-7.79048e-07,-2.82503e-08,0.584524,0.00086516,-8.63799e-07,3.04167e-08,0.585388,0.000863524,-7.72548e-07,-3.38119e-08,0.586251,0.000861877,-8.73984e-07,4.52264e-08,0.587112,0.000860265,-7.38305e-07,-2.78842e-08,0.587972,0.000858705,-8.21958e-07,6.70567e-09,0.58883,0.000857081,-8.01841e-07,1.06161e-09,0.589686,0.000855481,-7.98656e-07,-1.09521e-08,0.590541,0.00085385,-8.31512e-07,4.27468e-08,0.591394,0.000852316,-7.03272e-07,-4.08257e-08,0.592245,0.000850787,-8.25749e-07,1.34677e-09,0.593095,0.000849139,-8.21709e-07,3.54387e-08,0.593944,0.000847602,-7.15393e-07,-2.38924e-08,0.59479,0.0008461,-7.8707e-07,5.26143e-10,0.595636,0.000844527,-7.85491e-07,2.17879e-08,0.596479,0.000843021,-7.20127e-07,-2.80733e-08,0.597322,0.000841497,-8.04347e-07,3.09005e-08,0.598162,0.000839981,-7.11646e-07,-3.5924e-08,0.599002,0.00083845,-8.19418e-07,5.3191e-08,0.599839,0.000836971,-6.59845e-07,-5.76307e-08,0.600676,0.000835478,-8.32737e-07,5.81227e-08,0.60151,0.000833987,-6.58369e-07,-5.56507e-08,0.602344,0.000832503,-8.25321e-07,4.52706e-08,0.603175,0.000830988,-6.89509e-07,-6.22236e-09,0.604006,0.000829591,-7.08176e-07,-2.03811e-08,0.604834,0.000828113,-7.6932e-07,2.8142e-08,0.605662,0.000826659,-6.84894e-07,-3.25822e-08,0.606488,0.000825191,-7.8264e-07,4.25823e-08,0.607312,0.000823754,-6.54893e-07,-1.85376e-08,0.608135,0.000822389,-7.10506e-07,-2.80365e-08,0.608957,0.000820883,-7.94616e-07,7.1079e-08,0.609777,0.000819507,-5.81379e-07,-7.74655e-08,0.610596,0.000818112,-8.13775e-07,5.9969e-08,0.611413,0.000816665,-6.33868e-07,-4.32013e-08,0.612229,0.000815267,-7.63472e-07,5.32313e-08,0.613044,0.0008139,-6.03778e-07,-5.05148e-08,0.613857,0.000812541,-7.55323e-07,2.96187e-08,0.614669,0.000811119,-6.66466e-07,-8.35545e-09,0.615479,0.000809761,-6.91533e-07,3.80301e-09,0.616288,0.00080839,-6.80124e-07,-6.85666e-09,0.617096,0.000807009,-7.00694e-07,2.36237e-08,0.617903,0.000805678,-6.29822e-07,-2.80336e-08,0.618708,0.000804334,-7.13923e-07,2.8906e-08,0.619511,0.000802993,-6.27205e-07,-2.79859e-08,0.620314,0.000801655,-7.11163e-07,2.34329e-08,0.621114,0.000800303,-6.40864e-07,-6.14108e-09,0.621914,0.000799003,-6.59287e-07,1.13151e-09,0.622712,0.000797688,-6.55893e-07,1.61507e-09,0.62351,0.000796381,-6.51048e-07,-7.59186e-09,0.624305,0.000795056,-6.73823e-07,2.87524e-08,0.6251,0.000793794,-5.87566e-07,-4.7813e-08,0.625893,0.000792476,-7.31005e-07,4.32901e-08,0.626685,0.000791144,-6.01135e-07,-6.13814e-09,0.627475,0.000789923,-6.19549e-07,-1.87376e-08,0.628264,0.000788628,-6.75762e-07,2.14837e-08,0.629052,0.000787341,-6.11311e-07,-7.59265e-09,0.629839,0.000786095,-6.34089e-07,8.88692e-09,0.630625,0.000784854,-6.07428e-07,-2.7955e-08,0.631409,0.000783555,-6.91293e-07,4.33285e-08,0.632192,0.000782302,-5.61307e-07,-2.61497e-08,0.632973,0.000781101,-6.39757e-07,1.6658e-09,0.633754,0.000779827,-6.34759e-07,1.94866e-08,0.634533,0.000778616,-5.76299e-07,-2.00076e-08,0.635311,0.000777403,-6.36322e-07,9.39091e-10,0.636088,0.000776133,-6.33505e-07,1.62512e-08,0.636863,0.000774915,-5.84751e-07,-6.33937e-09,0.637638,0.000773726,-6.03769e-07,9.10609e-09,0.638411,0.000772546,-5.76451e-07,-3.00849e-08,0.639183,0.000771303,-6.66706e-07,5.1629e-08,0.639953,0.000770125,-5.11819e-07,-5.7222e-08,0.640723,0.000768929,-6.83485e-07,5.80497e-08,0.641491,0.000767736,-5.09336e-07,-5.57674e-08,0.642259,0.000766551,-6.76638e-07,4.58105e-08,0.643024,0.000765335,-5.39206e-07,-8.26541e-09,0.643789,0.000764231,-5.64002e-07,-1.27488e-08,0.644553,0.000763065,-6.02249e-07,-3.44168e-10,0.645315,0.00076186,-6.03281e-07,1.41254e-08,0.646077,0.000760695,-5.60905e-07,3.44727e-09,0.646837,0.000759584,-5.50563e-07,-2.79144e-08,0.647596,0.000758399,-6.34307e-07,4.86057e-08,0.648354,0.000757276,-4.88489e-07,-4.72989e-08,0.64911,0.000756158,-6.30386e-07,2.13807e-08,0.649866,0.000754961,-5.66244e-07,2.13808e-08,0.65062,0.000753893,-5.02102e-07,-4.7299e-08,0.651374,0.000752746,-6.43999e-07,4.86059e-08,0.652126,0.000751604,-4.98181e-07,-2.79154e-08,0.652877,0.000750524,-5.81927e-07,3.45089e-09,0.653627,0.000749371,-5.71575e-07,1.41119e-08,0.654376,0.00074827,-5.29239e-07,-2.93748e-10,0.655123,0.00074721,-5.3012e-07,-1.29368e-08,0.65587,0.000746111,-5.68931e-07,-7.56355e-09,0.656616,0.000744951,-5.91621e-07,4.3191e-08,0.65736,0.000743897,-4.62048e-07,-4.59911e-08,0.658103,0.000742835,-6.00022e-07,2.15642e-08,0.658846,0.0007417,-5.35329e-07,1.93389e-08,0.659587,0.000740687,-4.77312e-07,-3.93152e-08,0.660327,0.000739615,-5.95258e-07,1.87126e-08,0.661066,0.00073848,-5.3912e-07,2.40695e-08,0.661804,0.000737474,-4.66912e-07,-5.53859e-08,0.662541,0.000736374,-6.33069e-07,7.82648e-08,0.663277,0.000735343,-3.98275e-07,-7.88593e-08,0.664012,0.00073431,-6.34853e-07,5.83585e-08,0.664745,0.000733215,-4.59777e-07,-3.53656e-08,0.665478,0.000732189,-5.65874e-07,2.34994e-08,0.66621,0.000731128,-4.95376e-07,9.72743e-10,0.66694,0.00073014,-4.92458e-07,-2.73903e-08,0.66767,0.000729073,-5.74629e-07,4.89839e-08,0.668398,0.000728071,-4.27677e-07,-4.93359e-08,0.669126,0.000727068,-5.75685e-07,2.91504e-08,0.669853,0.000726004,-4.88234e-07,-7.66109e-09,0.670578,0.000725004,-5.11217e-07,1.49392e-09,0.671303,0.000723986,-5.06735e-07,1.68533e-09,0.672026,0.000722978,-5.01679e-07,-8.23525e-09,0.672749,0.00072195,-5.26385e-07,3.12556e-08,0.67347,0.000720991,-4.32618e-07,-5.71825e-08,0.674191,0.000719954,-6.04166e-07,7.8265e-08,0.67491,0.00071898,-3.69371e-07,-7.70634e-08,0.675628,0.00071801,-6.00561e-07,5.11747e-08,0.676346,0.000716963,-4.47037e-07,-8.42615e-09,0.677062,0.000716044,-4.72315e-07,-1.747e-08,0.677778,0.000715046,-5.24725e-07,1.87015e-08,0.678493,0.000714053,-4.68621e-07,2.26856e-09,0.679206,0.000713123,-4.61815e-07,-2.77758e-08,0.679919,0.000712116,-5.45142e-07,4.92298e-08,0.68063,0.000711173,-3.97453e-07,-4.99339e-08,0.681341,0.000710228,-5.47255e-07,3.12967e-08,0.682051,0.000709228,-4.53365e-07,-1.56481e-08,0.68276,0.000708274,-5.00309e-07,3.12958e-08,0.683467,0.000707367,-4.06422e-07,-4.99303e-08,0.684174,0.000706405,-5.56213e-07,4.9216e-08,0.68488,0.00070544,-4.08565e-07,-2.77245e-08,0.685585,0.00070454,-4.91738e-07,2.07748e-09,0.686289,0.000703562,-4.85506e-07,1.94146e-08,0.686992,0.00070265,-4.27262e-07,-2.01314e-08,0.687695,0.000701735,-4.87656e-07,1.50616e-09,0.688396,0.000700764,-4.83137e-07,1.41067e-08,0.689096,0.00069984,-4.40817e-07,1.67168e-09,0.689795,0.000698963,-4.35802e-07,-2.07934e-08,0.690494,0.000698029,-4.98182e-07,2.18972e-08,0.691192,0.000697099,-4.32491e-07,-7.19092e-09,0.691888,0.000696212,-4.54064e-07,6.86642e-09,0.692584,0.000695325,-4.33464e-07,-2.02747e-08,0.693279,0.000694397,-4.94288e-07,1.46279e-08,0.693973,0.000693452,-4.50405e-07,2.13678e-08,0.694666,0.000692616,-3.86301e-07,-4.04945e-08,0.695358,0.000691721,-5.07785e-07,2.14009e-08,0.696049,0.00069077,-4.43582e-07,1.44955e-08,0.69674,0.000689926,-4.00096e-07,-1.97783e-08,0.697429,0.000689067,-4.5943e-07,5.01296e-09,0.698118,0.000688163,-4.44392e-07,-2.73521e-10,0.698805,0.000687273,-4.45212e-07,-3.91893e-09,0.699492,0.000686371,-4.56969e-07,1.59493e-08,0.700178,0.000685505,-4.09121e-07,-2.73351e-10,0.700863,0.000684686,-4.09941e-07,-1.4856e-08,0.701548,0.000683822,-4.54509e-07,9.25979e-11,0.702231,0.000682913,-4.54231e-07,1.44855e-08,0.702913,0.000682048,-4.10775e-07,1.56992e-09,0.703595,0.000681231,-4.06065e-07,-2.07652e-08,0.704276,0.000680357,-4.68361e-07,2.18864e-08,0.704956,0.000679486,-4.02701e-07,-7.17595e-09,0.705635,0.000678659,-4.24229e-07,6.81748e-09,0.706313,0.000677831,-4.03777e-07,-2.0094e-08,0.70699,0.000676963,-4.64059e-07,1.39538e-08,0.707667,0.000676077,-4.22197e-07,2.38835e-08,0.708343,0.000675304,-3.50547e-07,-4.98831e-08,0.709018,0.000674453,-5.00196e-07,5.64395e-08,0.709692,0.000673622,-3.30878e-07,-5.66657e-08,0.710365,0.00067279,-5.00875e-07,5.1014e-08,0.711037,0.000671942,-3.47833e-07,-2.81809e-08,0.711709,0.000671161,-4.32376e-07,2.10513e-09,0.712379,0.000670303,-4.2606e-07,1.97604e-08,0.713049,0.00066951,-3.66779e-07,-2.15422e-08,0.713718,0.000668712,-4.31406e-07,6.8038e-09,0.714387,0.000667869,-4.10994e-07,-5.67295e-09,0.715054,0.00066703,-4.28013e-07,1.5888e-08,0.715721,0.000666222,-3.80349e-07,1.72576e-09,0.716387,0.000665467,-3.75172e-07,-2.27911e-08,0.717052,0.000664648,-4.43545e-07,2.9834e-08,0.717716,0.00066385,-3.54043e-07,-3.69401e-08,0.718379,0.000663031,-4.64864e-07,5.83219e-08,0.719042,0.000662277,-2.89898e-07,-7.71382e-08,0.719704,0.000661465,-5.21313e-07,7.14171e-08,0.720365,0.000660637,-3.07061e-07,-2.97161e-08,0.721025,0.000659934,-3.96209e-07,-1.21575e-08,0.721685,0.000659105,-4.32682e-07,1.87412e-08,0.722343,0.000658296,-3.76458e-07,-3.2029e-09,0.723001,0.000657533,-3.86067e-07,-5.9296e-09,0.723659,0.000656743,-4.03856e-07,2.69213e-08,0.724315,0.000656016,-3.23092e-07,-4.21511e-08,0.724971,0.000655244,-4.49545e-07,2.24737e-08,0.725625,0.000654412,-3.82124e-07,1.18611e-08,0.726279,0.000653683,-3.46541e-07,-1.03132e-08,0.726933,0.000652959,-3.7748e-07,-3.02128e-08,0.727585,0.000652114,-4.68119e-07,7.15597e-08,0.728237,0.000651392,-2.5344e-07,-7.72119e-08,0.728888,0.000650654,-4.85075e-07,5.8474e-08,0.729538,0.000649859,-3.09654e-07,-3.74746e-08,0.730188,0.000649127,-4.22077e-07,3.18197e-08,0.730837,0.000648379,-3.26618e-07,-3.01997e-08,0.731485,0.000647635,-4.17217e-07,2.93747e-08,0.732132,0.000646888,-3.29093e-07,-2.76943e-08,0.732778,0.000646147,-4.12176e-07,2.17979e-08,0.733424,0.000645388,-3.46783e-07,1.07292e-10,0.734069,0.000644695,-3.46461e-07,-2.22271e-08,0.734713,0.000643935,-4.13142e-07,2.91963e-08,0.735357,0.000643197,-3.25553e-07,-3.49536e-08,0.736,0.000642441,-4.30414e-07,5.10133e-08,0.736642,0.000641733,-2.77374e-07,-4.98904e-08,0.737283,0.000641028,-4.27045e-07,2.93392e-08,0.737924,0.000640262,-3.39028e-07,-7.86156e-09,0.738564,0.000639561,-3.62612e-07,2.10703e-09,0.739203,0.000638842,-3.56291e-07,-5.6653e-10,0.739842,0.000638128,-3.57991e-07,1.59086e-10,0.740479,0.000637412,-3.57513e-07,-6.98321e-11,0.741116,0.000636697,-3.57723e-07,1.20214e-10,0.741753,0.000635982,-3.57362e-07,-4.10987e-10,0.742388,0.000635266,-3.58595e-07,1.5237e-09,0.743023,0.000634553,-3.54024e-07,-5.68376e-09,0.743657,0.000633828,-3.71075e-07,2.12113e-08,0.744291,0.00063315,-3.07441e-07,-1.95569e-08,0.744924,0.000632476,-3.66112e-07,-2.58816e-09,0.745556,0.000631736,-3.73877e-07,2.99096e-08,0.746187,0.000631078,-2.84148e-07,-5.74454e-08,0.746818,0.000630337,-4.56484e-07,8.06629e-08,0.747448,0.000629666,-2.14496e-07,-8.63922e-08,0.748077,0.000628978,-4.73672e-07,8.60918e-08,0.748706,0.000628289,-2.15397e-07,-7.91613e-08,0.749334,0.000627621,-4.5288e-07,5.17393e-08,0.749961,0.00062687,-2.97663e-07,-8.58662e-09,0.750588,0.000626249,-3.23422e-07,-1.73928e-08,0.751214,0.00062555,-3.75601e-07,1.85532e-08,0.751839,0.000624855,-3.19941e-07,2.78479e-09,0.752463,0.000624223,-3.11587e-07,-2.96923e-08,0.753087,0.000623511,-4.00664e-07,5.63799e-08,0.75371,0.000622879,-2.31524e-07,-7.66179e-08,0.754333,0.000622186,-4.61378e-07,7.12778e-08,0.754955,0.000621477,-2.47545e-07,-2.96794e-08,0.755576,0.000620893,-3.36583e-07,-1.21648e-08,0.756196,0.000620183,-3.73077e-07,1.87339e-08,0.756816,0.000619493,-3.16875e-07,-3.16622e-09,0.757435,0.00061885,-3.26374e-07,-6.0691e-09,0.758054,0.000618179,-3.44581e-07,2.74426e-08,0.758672,0.000617572,-2.62254e-07,-4.40968e-08,0.759289,0.000616915,-3.94544e-07,2.97352e-08,0.759906,0.000616215,-3.05338e-07,-1.52393e-08,0.760522,0.000615559,-3.51056e-07,3.12221e-08,0.761137,0.000614951,-2.5739e-07,-5.00443e-08,0.761751,0.000614286,-4.07523e-07,4.9746e-08,0.762365,0.00061362,-2.58285e-07,-2.97303e-08,0.762979,0.000613014,-3.47476e-07,9.57079e-09,0.763591,0.000612348,-3.18764e-07,-8.55287e-09,0.764203,0.000611685,-3.44422e-07,2.46407e-08,0.764815,0.00061107,-2.705e-07,-3.04053e-08,0.765426,0.000610437,-3.61716e-07,3.73759e-08,0.766036,0.000609826,-2.49589e-07,-5.94935e-08,0.766645,0.000609149,-4.28069e-07,8.13889e-08,0.767254,0.000608537,-1.83902e-07,-8.72483e-08,0.767862,0.000607907,-4.45647e-07,8.87901e-08,0.76847,0.000607282,-1.79277e-07,-8.90983e-08,0.769077,0.000606656,-4.46572e-07,8.87892e-08,0.769683,0.000606029,-1.80204e-07,-8.72446e-08,0.770289,0.000605407,-4.41938e-07,8.13752e-08,0.770894,0.000604768,-1.97812e-07,-5.94423e-08,0.771498,0.000604194,-3.76139e-07,3.71848e-08,0.772102,0.000603553,-2.64585e-07,-2.96922e-08,0.772705,0.000602935,-3.53661e-07,2.19793e-08,0.773308,0.000602293,-2.87723e-07,1.37955e-09,0.77391,0.000601722,-2.83585e-07,-2.74976e-08,0.774512,0.000601072,-3.66077e-07,4.9006e-08,0.775112,0.000600487,-2.19059e-07,-4.93171e-08,0.775712,0.000599901,-3.67011e-07,2.90531e-08,0.776312,0.000599254,-2.79851e-07,-7.29081e-09,0.776911,0.000598673,-3.01724e-07,1.10077e-10,0.777509,0.00059807,-3.01393e-07,6.85053e-09,0.778107,0.000597487,-2.80842e-07,-2.75123e-08,0.778704,0.000596843,-3.63379e-07,4.35939e-08,0.779301,0.000596247,-2.32597e-07,-2.7654e-08,0.779897,0.000595699,-3.15559e-07,7.41741e-09,0.780492,0.00059509,-2.93307e-07,-2.01562e-09,0.781087,0.000594497,-2.99354e-07,6.45059e-10,0.781681,0.000593901,-2.97418e-07,-5.64635e-10,0.782275,0.000593304,-2.99112e-07,1.61347e-09,0.782868,0.000592711,-2.94272e-07,-5.88926e-09,0.78346,0.000592105,-3.1194e-07,2.19436e-08,0.784052,0.000591546,-2.46109e-07,-2.22805e-08,0.784643,0.000590987,-3.1295e-07,7.57368e-09,0.785234,0.000590384,-2.90229e-07,-8.01428e-09,0.785824,0.00058978,-3.14272e-07,2.44834e-08,0.786414,0.000589225,-2.40822e-07,-3.03148e-08,0.787003,0.000588652,-3.31766e-07,3.7171e-08,0.787591,0.0005881,-2.20253e-07,-5.87646e-08,0.788179,0.000587483,-3.96547e-07,7.86782e-08,0.788766,0.000586926,-1.60512e-07,-7.71342e-08,0.789353,0.000586374,-3.91915e-07,5.10444e-08,0.789939,0.000585743,-2.38782e-07,-7.83422e-09,0.790524,0.000585242,-2.62284e-07,-1.97076e-08,0.791109,0.000584658,-3.21407e-07,2.70598e-08,0.791693,0.000584097,-2.40228e-07,-2.89269e-08,0.792277,0.000583529,-3.27008e-07,2.90431e-08,0.792861,0.000582963,-2.39879e-07,-2.76409e-08,0.793443,0.0005824,-3.22802e-07,2.1916e-08,0.794025,0.00058182,-2.57054e-07,-4.18368e-10,0.794607,0.000581305,-2.58309e-07,-2.02425e-08,0.795188,0.000580727,-3.19036e-07,2.17838e-08,0.795768,0.000580155,-2.53685e-07,-7.28814e-09,0.796348,0.000579625,-2.75549e-07,7.36871e-09,0.796928,0.000579096,-2.53443e-07,-2.21867e-08,0.797506,0.000578523,-3.20003e-07,2.17736e-08,0.798085,0.000577948,-2.54683e-07,-5.30296e-09,0.798662,0.000577423,-2.70592e-07,-5.61698e-10,0.799239,0.00057688,-2.72277e-07,7.54977e-09,0.799816,0.000576358,-2.49627e-07,-2.96374e-08,0.800392,0.00057577,-3.38539e-07,5.1395e-08,0.800968,0.000575247,-1.84354e-07,-5.67335e-08,0.801543,0.000574708,-3.54555e-07,5.63297e-08,0.802117,0.000574168,-1.85566e-07,-4.93759e-08,0.802691,0.000573649,-3.33693e-07,2.19646e-08,0.803264,0.000573047,-2.678e-07,2.1122e-08,0.803837,0.000572575,-2.04433e-07,-4.68482e-08,0.804409,0.000572026,-3.44978e-07,4.70613e-08,0.804981,0.000571477,-2.03794e-07,-2.21877e-08,0.805552,0.000571003,-2.70357e-07,-1.79153e-08,0.806123,0.000570408,-3.24103e-07,3.42443e-08,0.806693,0.000569863,-2.2137e-07,1.47556e-10,0.807263,0.000569421,-2.20928e-07,-3.48345e-08,0.807832,0.000568874,-3.25431e-07,1.99812e-08,0.808401,0.000568283,-2.65487e-07,1.45143e-08,0.808969,0.000567796,-2.21945e-07,-1.84338e-08,0.809536,0.000567297,-2.77246e-07,-3.83608e-10,0.810103,0.000566741,-2.78397e-07,1.99683e-08,0.81067,0.000566244,-2.18492e-07,-1.98848e-08,0.811236,0.000565747,-2.78146e-07,-3.38976e-11,0.811801,0.000565191,-2.78248e-07,2.00204e-08,0.812366,0.000564695,-2.18187e-07,-2.04429e-08,0.812931,0.000564197,-2.79516e-07,2.1467e-09,0.813495,0.000563644,-2.73076e-07,1.18561e-08,0.814058,0.000563134,-2.37507e-07,1.00334e-08,0.814621,0.000562689,-2.07407e-07,-5.19898e-08,0.815183,0.000562118,-3.63376e-07,7.87163e-08,0.815745,0.000561627,-1.27227e-07,-8.40616e-08,0.816306,0.000561121,-3.79412e-07,7.87163e-08,0.816867,0.000560598,-1.43263e-07,-5.19898e-08,0.817428,0.000560156,-2.99233e-07,1.00335e-08,0.817988,0.000559587,-2.69132e-07,1.18559e-08,0.818547,0.000559085,-2.33564e-07,2.14764e-09,0.819106,0.000558624,-2.27122e-07,-2.04464e-08,0.819664,0.000558108,-2.88461e-07,2.00334e-08,0.820222,0.000557591,-2.28361e-07,-8.24277e-11,0.820779,0.000557135,-2.28608e-07,-1.97037e-08,0.821336,0.000556618,-2.87719e-07,1.92925e-08,0.821893,0.000556101,-2.29841e-07,2.13831e-09,0.822448,0.000555647,-2.23427e-07,-2.78458e-08,0.823004,0.000555117,-3.06964e-07,4.96402e-08,0.823559,0.000554652,-1.58043e-07,-5.15058e-08,0.824113,0.000554181,-3.12561e-07,3.71737e-08,0.824667,0.000553668,-2.0104e-07,-3.75844e-08,0.82522,0.000553153,-3.13793e-07,5.35592e-08,0.825773,0.000552686,-1.53115e-07,-5.74431e-08,0.826326,0.000552207,-3.25444e-07,5.7004e-08,0.826878,0.000551728,-1.54433e-07,-5.13635e-08,0.827429,0.000551265,-3.08523e-07,2.92406e-08,0.82798,0.000550735,-2.20801e-07,-5.99424e-09,0.828531,0.000550276,-2.38784e-07,-5.26363e-09,0.829081,0.000549782,-2.54575e-07,2.70488e-08,0.82963,0.000549354,-1.73429e-07,-4.33268e-08,0.83018,0.000548878,-3.03409e-07,2.7049e-08,0.830728,0.000548352,-2.22262e-07,-5.26461e-09,0.831276,0.000547892,-2.38056e-07,-5.99057e-09,0.831824,0.000547397,-2.56027e-07,2.92269e-08,0.832371,0.000546973,-1.68347e-07,-5.13125e-08,0.832918,0.000546482,-3.22284e-07,5.68139e-08,0.833464,0.000546008,-1.51843e-07,-5.67336e-08,0.83401,0.000545534,-3.22043e-07,5.09113e-08,0.834555,0.000545043,-1.6931e-07,-2.77022e-08,0.8351,0.000544621,-2.52416e-07,2.92924e-10,0.835644,0.000544117,-2.51537e-07,2.65305e-08,0.836188,0.000543694,-1.71946e-07,-4.68105e-08,0.836732,0.00054321,-3.12377e-07,4.15021e-08,0.837275,0.000542709,-1.87871e-07,1.13355e-11,0.837817,0.000542334,-1.87837e-07,-4.15474e-08,0.838359,0.000541833,-3.12479e-07,4.69691e-08,0.838901,0.000541349,-1.71572e-07,-2.71196e-08,0.839442,0.000540925,-2.52931e-07,1.90462e-09,0.839983,0.000540425,-2.47217e-07,1.95011e-08,0.840523,0.000539989,-1.88713e-07,-2.03045e-08,0.841063,0.00053955,-2.49627e-07,2.11216e-09,0.841602,0.000539057,-2.4329e-07,1.18558e-08,0.842141,0.000538606,-2.07723e-07,1.00691e-08,0.842679,0.000538221,-1.77516e-07,-5.21324e-08,0.843217,0.00053771,-3.33913e-07,7.92513e-08,0.843755,0.00053728,-9.6159e-08,-8.60587e-08,0.844292,0.000536829,-3.54335e-07,8.61696e-08,0.844828,0.000536379,-9.58263e-08,-7.98057e-08,0.845364,0.000535948,-3.35243e-07,5.42394e-08,0.8459,0.00053544,-1.72525e-07,-1.79426e-08,0.846435,0.000535041,-2.26353e-07,1.75308e-08,0.84697,0.000534641,-1.73761e-07,-5.21806e-08,0.847505,0.000534137,-3.30302e-07,7.19824e-08,0.848038,0.000533692,-1.14355e-07,-5.69349e-08,0.848572,0.000533293,-2.8516e-07,3.65479e-08,0.849105,0.000532832,-1.75516e-07,-2.96519e-08,0.849638,0.000532392,-2.64472e-07,2.2455e-08,0.85017,0.000531931,-1.97107e-07,-5.63451e-10,0.850702,0.000531535,-1.98797e-07,-2.02011e-08,0.851233,0.000531077,-2.59401e-07,2.17634e-08,0.851764,0.000530623,-1.94111e-07,-7.24794e-09,0.852294,0.000530213,-2.15854e-07,7.22832e-09,0.852824,0.000529803,-1.94169e-07,-2.16653e-08,0.853354,0.00052935,-2.59165e-07,1.98283e-08,0.853883,0.000528891,-1.9968e-07,1.95678e-09,0.854412,0.000528497,-1.9381e-07,-2.76554e-08,0.85494,0.000528027,-2.76776e-07,4.90603e-08,0.855468,0.00052762,-1.29596e-07,-4.93764e-08,0.855995,0.000527213,-2.77725e-07,2.92361e-08,0.856522,0.000526745,-1.90016e-07,-7.96341e-09,0.857049,0.000526341,-2.13907e-07,2.61752e-09,0.857575,0.000525922,-2.06054e-07,-2.50665e-09,0.8581,0.000525502,-2.13574e-07,7.40906e-09,0.858626,0.000525097,-1.91347e-07,-2.71296e-08,0.859151,0.000524633,-2.72736e-07,4.15048e-08,0.859675,0.000524212,-1.48221e-07,-1.96802e-08,0.860199,0.000523856,-2.07262e-07,-2.23886e-08,0.860723,0.000523375,-2.74428e-07,4.96299e-08,0.861246,0.000522975,-1.25538e-07,-5.69216e-08,0.861769,0.000522553,-2.96303e-07,5.88473e-08,0.862291,0.000522137,-1.19761e-07,-5.92584e-08,0.862813,0.00052172,-2.97536e-07,5.8977e-08,0.863334,0.000521301,-1.20605e-07,-5.74403e-08,0.863855,0.000520888,-2.92926e-07,5.15751e-08,0.864376,0.000520457,-1.38201e-07,-2.96506e-08,0.864896,0.000520091,-2.27153e-07,7.42277e-09,0.865416,0.000519659,-2.04885e-07,-4.05057e-11,0.865936,0.00051925,-2.05006e-07,-7.26074e-09,0.866455,0.000518818,-2.26788e-07,2.90835e-08,0.866973,0.000518451,-1.39538e-07,-4.94686e-08,0.867492,0.000518024,-2.87944e-07,4.95814e-08,0.868009,0.000517597,-1.39199e-07,-2.96479e-08,0.868527,0.000517229,-2.28143e-07,9.40539e-09,0.869044,0.000516801,-1.99927e-07,-7.9737e-09,0.86956,0.000516378,-2.23848e-07,2.24894e-08,0.870077,0.000515997,-1.5638e-07,-2.23793e-08,0.870592,0.000515617,-2.23517e-07,7.42302e-09,0.871108,0.000515193,-2.01248e-07,-7.31283e-09,0.871623,0.000514768,-2.23187e-07,2.18283e-08,0.872137,0.000514387,-1.57702e-07,-2.03959e-08,0.872652,0.000514011,-2.1889e-07,1.50711e-10,0.873165,0.000513573,-2.18437e-07,1.97931e-08,0.873679,0.000513196,-1.59058e-07,-1.97183e-08,0.874192,0.000512819,-2.18213e-07,-5.24324e-10,0.874704,0.000512381,-2.19786e-07,2.18156e-08,0.875217,0.000512007,-1.54339e-07,-2.71336e-08,0.875728,0.000511616,-2.3574e-07,2.71141e-08,0.87624,0.000511226,-1.54398e-07,-2.17182e-08,0.876751,0.000510852,-2.19552e-07,1.54131e-10,0.877262,0.000510414,-2.1909e-07,2.11017e-08,0.877772,0.000510039,-1.55785e-07,-2.49562e-08,0.878282,0.000509652,-2.30654e-07,1.91183e-08,0.878791,0.000509248,-1.73299e-07,8.08751e-09,0.8793,0.000508926,-1.49036e-07,-5.14684e-08,0.879809,0.000508474,-3.03441e-07,7.85766e-08,0.880317,0.000508103,-6.77112e-08,-8.40242e-08,0.880825,0.000507715,-3.19784e-07,7.87063e-08,0.881333,0.000507312,-8.36649e-08,-5.19871e-08,0.88184,0.000506988,-2.39626e-07,1.00327e-08,0.882346,0.000506539,-2.09528e-07,1.18562e-08,0.882853,0.000506156,-1.73959e-07,2.14703e-09,0.883359,0.000505814,-1.67518e-07,-2.04444e-08,0.883864,0.000505418,-2.28851e-07,2.00258e-08,0.88437,0.00050502,-1.68774e-07,-5.42855e-11,0.884874,0.000504682,-1.68937e-07,-1.98087e-08,0.885379,0.000504285,-2.28363e-07,1.96842e-08,0.885883,0.000503887,-1.6931e-07,6.76342e-10,0.886387,0.000503551,-1.67281e-07,-2.23896e-08,0.88689,0.000503149,-2.3445e-07,2.92774e-08,0.887393,0.000502768,-1.46618e-07,-3.51152e-08,0.887896,0.00050237,-2.51963e-07,5.15787e-08,0.888398,0.00050202,-9.72271e-08,-5.19903e-08,0.8889,0.00050167,-2.53198e-07,3.71732e-08,0.889401,0.000501275,-1.41678e-07,-3.70978e-08,0.889902,0.00050088,-2.52972e-07,5.16132e-08,0.890403,0.000500529,-9.81321e-08,-5.01459e-08,0.890903,0.000500183,-2.4857e-07,2.9761e-08,0.891403,0.000499775,-1.59287e-07,-9.29351e-09,0.891903,0.000499428,-1.87167e-07,7.41301e-09,0.892402,0.000499076,-1.64928e-07,-2.03585e-08,0.892901,0.000498685,-2.26004e-07,1.44165e-08,0.893399,0.000498276,-1.82754e-07,2.22974e-08,0.893898,0.000497978,-1.15862e-07,-4.40013e-08,0.894395,0.000497614,-2.47866e-07,3.44985e-08,0.894893,0.000497222,-1.44371e-07,-3.43882e-08,0.89539,0.00049683,-2.47535e-07,4.34497e-08,0.895886,0.000496465,-1.17186e-07,-2.02012e-08,0.896383,0.00049617,-1.7779e-07,-2.22497e-08,0.896879,0.000495748,-2.44539e-07,4.95952e-08,0.897374,0.000495408,-9.57532e-08,-5.69217e-08,0.89787,0.000495045,-2.66518e-07,5.88823e-08,0.898364,0.000494689,-8.98713e-08,-5.93983e-08,0.898859,0.000494331,-2.68066e-07,5.95017e-08,0.899353,0.000493973,-8.95613e-08,-5.9399e-08,0.899847,0.000493616,-2.67758e-07,5.8885e-08,0.90034,0.000493257,-9.11033e-08,-5.69317e-08,0.900833,0.000492904,-2.61898e-07,4.96326e-08,0.901326,0.000492529,-1.13001e-07,-2.23893e-08,0.901819,0.000492236,-1.80169e-07,-1.968e-08,0.902311,0.000491817,-2.39209e-07,4.15047e-08,0.902802,0.000491463,-1.14694e-07,-2.71296e-08,0.903293,0.000491152,-1.96083e-07,7.409e-09,0.903784,0.000490782,-1.73856e-07,-2.50645e-09,0.904275,0.000490427,-1.81376e-07,2.61679e-09,0.904765,0.000490072,-1.73525e-07,-7.96072e-09,0.905255,0.000489701,-1.97407e-07,2.92261e-08,0.905745,0.000489394,-1.09729e-07,-4.93389e-08,0.906234,0.000489027,-2.57746e-07,4.89204e-08,0.906723,0.000488658,-1.10985e-07,-2.71333e-08,0.907211,0.000488354,-1.92385e-07,8.30861e-12,0.907699,0.00048797,-1.9236e-07,2.71001e-08,0.908187,0.000487666,-1.1106e-07,-4.88041e-08,0.908675,0.000487298,-2.57472e-07,4.89069e-08,0.909162,0.000486929,-1.10751e-07,-2.76143e-08,0.909649,0.000486625,-1.93594e-07,1.9457e-09,0.910135,0.000486244,-1.87757e-07,1.98315e-08,0.910621,0.000485928,-1.28262e-07,-2.16671e-08,0.911107,0.000485606,-1.93264e-07,7.23216e-09,0.911592,0.000485241,-1.71567e-07,-7.26152e-09,0.912077,0.000484877,-1.93352e-07,2.18139e-08,0.912562,0.000484555,-1.2791e-07,-2.03895e-08,0.913047,0.000484238,-1.89078e-07,1.39494e-10,0.913531,0.000483861,-1.8866e-07,1.98315e-08,0.914014,0.000483543,-1.29165e-07,-1.98609e-08,0.914498,0.000483225,-1.88748e-07,7.39912e-12,0.914981,0.000482847,-1.88726e-07,1.98313e-08,0.915463,0.000482529,-1.29232e-07,-1.9728e-08,0.915946,0.000482212,-1.88416e-07,-5.24035e-10,0.916428,0.000481833,-1.89988e-07,2.18241e-08,0.916909,0.000481519,-1.24516e-07,-2.71679e-08,0.917391,0.000481188,-2.06019e-07,2.72427e-08,0.917872,0.000480858,-1.24291e-07,-2.21985e-08,0.918353,0.000480543,-1.90886e-07,1.94644e-09,0.918833,0.000480167,-1.85047e-07,1.44127e-08,0.919313,0.00047984,-1.41809e-07,7.39438e-12,0.919793,0.000479556,-1.41787e-07,-1.44423e-08,0.920272,0.000479229,-1.85114e-07,-1.84291e-09,0.920751,0.000478854,-1.90642e-07,2.18139e-08,0.92123,0.000478538,-1.25201e-07,-2.58081e-08,0.921708,0.00047821,-2.02625e-07,2.18139e-08,0.922186,0.00047787,-1.37183e-07,-1.84291e-09,0.922664,0.00047759,-1.42712e-07,-1.44423e-08,0.923141,0.000477262,-1.86039e-07,7.34701e-12,0.923618,0.00047689,-1.86017e-07,1.44129e-08,0.924095,0.000476561,-1.42778e-07,1.94572e-09,0.924572,0.000476281,-1.36941e-07,-2.21958e-08,0.925048,0.000475941,-2.03528e-07,2.72327e-08,0.925523,0.000475615,-1.2183e-07,-2.71304e-08,0.925999,0.00047529,-2.03221e-07,2.16843e-08,0.926474,0.000474949,-1.38168e-07,-2.16005e-12,0.926949,0.000474672,-1.38175e-07,-2.16756e-08,0.927423,0.000474331,-2.03202e-07,2.71001e-08,0.927897,0.000474006,-1.21902e-07,-2.71201e-08,0.928371,0.000473681,-2.03262e-07,2.17757e-08,0.928845,0.00047334,-1.37935e-07,-3.78028e-10,0.929318,0.000473063,-1.39069e-07,-2.02636e-08,0.929791,0.000472724,-1.9986e-07,2.18276e-08,0.930263,0.000472389,-1.34377e-07,-7.44231e-09,0.930736,0.000472098,-1.56704e-07,7.94165e-09,0.931208,0.000471809,-1.32879e-07,-2.43243e-08,0.931679,0.00047147,-2.05851e-07,2.97508e-08,0.932151,0.000471148,-1.16599e-07,-3.50742e-08,0.932622,0.000470809,-2.21822e-07,5.09414e-08,0.933092,0.000470518,-6.89976e-08,-4.94821e-08,0.933563,0.000470232,-2.17444e-07,2.77775e-08,0.934033,0.00046988,-1.34111e-07,-2.02351e-09,0.934502,0.000469606,-1.40182e-07,-1.96835e-08,0.934972,0.000469267,-1.99232e-07,2.11529e-08,0.935441,0.000468932,-1.35774e-07,-5.32332e-09,0.93591,0.000468644,-1.51743e-07,1.40413e-10,0.936378,0.000468341,-1.51322e-07,4.76166e-09,0.936846,0.000468053,-1.37037e-07,-1.9187e-08,0.937314,0.000467721,-1.94598e-07,1.23819e-08,0.937782,0.000467369,-1.57453e-07,2.92642e-08,0.938249,0.000467142,-6.96601e-08,-6.98342e-08,0.938716,0.000466793,-2.79163e-07,7.12586e-08,0.939183,0.000466449,-6.53869e-08,-3.63863e-08,0.939649,0.000466209,-1.74546e-07,1.46818e-08,0.940115,0.000465904,-1.305e-07,-2.2341e-08,0.940581,0.000465576,-1.97523e-07,1.50774e-08,0.941046,0.000465226,-1.52291e-07,2.16359e-08,0.941511,0.000464986,-8.73832e-08,-4.20162e-08,0.941976,0.000464685,-2.13432e-07,2.72198e-08,0.942441,0.00046434,-1.31773e-07,-7.2581e-09,0.942905,0.000464055,-1.53547e-07,1.81263e-09,0.943369,0.000463753,-1.48109e-07,7.58386e-12,0.943832,0.000463457,-1.48086e-07,-1.84298e-09,0.944296,0.000463155,-1.53615e-07,7.36433e-09,0.944759,0.00046287,-1.31522e-07,-2.76143e-08,0.945221,0.000462524,-2.14365e-07,4.34883e-08,0.945684,0.000462226,-8.39003e-08,-2.71297e-08,0.946146,0.000461977,-1.65289e-07,5.42595e-09,0.946608,0.000461662,-1.49012e-07,5.42593e-09,0.947069,0.000461381,-1.32734e-07,-2.71297e-08,0.94753,0.000461034,-2.14123e-07,4.34881e-08,0.947991,0.000460736,-8.36585e-08,-2.76134e-08,0.948452,0.000460486,-1.66499e-07,7.36083e-09,0.948912,0.000460175,-1.44416e-07,-1.82993e-09,0.949372,0.000459881,-1.49906e-07,-4.11073e-11,0.949832,0.000459581,-1.50029e-07,1.99434e-09,0.950291,0.000459287,-1.44046e-07,-7.93627e-09,0.950751,0.000458975,-1.67855e-07,2.97507e-08,0.951209,0.000458728,-7.86029e-08,-5.1462e-08,0.951668,0.000458417,-2.32989e-07,5.6888e-08,0.952126,0.000458121,-6.2325e-08,-5.68806e-08,0.952584,0.000457826,-2.32967e-07,5.14251e-08,0.953042,0.000457514,-7.86914e-08,-2.96107e-08,0.953499,0.000457268,-1.67523e-07,7.41296e-09,0.953956,0.000456955,-1.45285e-07,-4.11262e-11,0.954413,0.000456665,-1.45408e-07,-7.24847e-09,0.95487,0.000456352,-1.67153e-07,2.9035e-08,0.955326,0.000456105,-8.00484e-08,-4.92869e-08,0.955782,0.000455797,-2.27909e-07,4.89032e-08,0.956238,0.000455488,-8.11994e-08,-2.71166e-08,0.956693,0.000455244,-1.62549e-07,-4.13678e-11,0.957148,0.000454919,-1.62673e-07,2.72821e-08,0.957603,0.000454675,-8.0827e-08,-4.94824e-08,0.958057,0.000454365,-2.29274e-07,5.14382e-08,0.958512,0.000454061,-7.49597e-08,-3.7061e-08,0.958965,0.0004538,-1.86143e-07,3.72013e-08,0.959419,0.000453539,-7.45389e-08,-5.21396e-08,0.959873,0.000453234,-2.30958e-07,5.21476e-08,0.960326,0.000452928,-7.45146e-08,-3.72416e-08,0.960778,0.000452667,-1.8624e-07,3.72143e-08,0.961231,0.000452407,-7.45967e-08,-5.20109e-08,0.961683,0.000452101,-2.30629e-07,5.16199e-08,0.962135,0.000451795,-7.57696e-08,-3.52595e-08,0.962587,0.000451538,-1.81548e-07,2.98133e-08,0.963038,0.000451264,-9.2108e-08,-2.43892e-08,0.963489,0.000451007,-1.65276e-07,8.13892e-09,0.96394,0.000450701,-1.40859e-07,-8.16647e-09,0.964391,0.000450394,-1.65358e-07,2.45269e-08,0.964841,0.000450137,-9.17775e-08,-3.03367e-08,0.965291,0.000449863,-1.82787e-07,3.7215e-08,0.965741,0.000449609,-7.11424e-08,-5.89188e-08,0.96619,0.00044929,-2.47899e-07,7.92509e-08,0.966639,0.000449032,-1.01462e-08,-7.92707e-08,0.967088,0.000448773,-2.47958e-07,5.90181e-08,0.967537,0.000448455,-7.0904e-08,-3.75925e-08,0.967985,0.0004482,-1.83681e-07,3.17471e-08,0.968433,0.000447928,-8.84401e-08,-2.97913e-08,0.968881,0.000447662,-1.77814e-07,2.78133e-08,0.969329,0.000447389,-9.4374e-08,-2.18572e-08,0.969776,0.000447135,-1.59946e-07,1.10134e-11,0.970223,0.000446815,-1.59913e-07,2.18132e-08,0.97067,0.000446561,-9.44732e-08,-2.76591e-08,0.971116,0.000446289,-1.7745e-07,2.92185e-08,0.971562,0.000446022,-8.97948e-08,-2.96104e-08,0.972008,0.000445753,-1.78626e-07,2.96185e-08,0.972454,0.000445485,-8.97706e-08,-2.92588e-08,0.972899,0.000445218,-1.77547e-07,2.78123e-08,0.973344,0.000444946,-9.41103e-08,-2.23856e-08,0.973789,0.000444691,-1.61267e-07,2.12559e-09,0.974233,0.000444374,-1.5489e-07,1.38833e-08,0.974678,0.000444106,-1.13241e-07,1.94591e-09,0.975122,0.000443886,-1.07403e-07,-2.16669e-08,0.975565,0.000443606,-1.72404e-07,2.5117e-08,0.976009,0.000443336,-9.70526e-08,-1.91963e-08,0.976452,0.000443085,-1.54642e-07,-7.93627e-09,0.976895,0.000442752,-1.7845e-07,5.09414e-08,0.977338,0.000442548,-2.56262e-08,-7.66201e-08,0.97778,0.000442266,-2.55486e-07,7.67249e-08,0.978222,0.000441986,-2.53118e-08,-5.14655e-08,0.978664,0.000441781,-1.79708e-07,9.92773e-09,0.979106,0.000441451,-1.49925e-07,1.17546e-08,0.979547,0.000441186,-1.14661e-07,2.65868e-09,0.979988,0.000440965,-1.06685e-07,-2.23893e-08,0.980429,0.000440684,-1.73853e-07,2.72939e-08,0.980869,0.000440419,-9.19716e-08,-2.71816e-08,0.98131,0.000440153,-1.73516e-07,2.18278e-08,0.98175,0.000439872,-1.08033e-07,-5.24833e-10,0.982189,0.000439654,-1.09607e-07,-1.97284e-08,0.982629,0.000439376,-1.68793e-07,1.98339e-08,0.983068,0.000439097,-1.09291e-07,-2.62901e-12,0.983507,0.000438879,-1.09299e-07,-1.98234e-08,0.983946,0.000438601,-1.68769e-07,1.96916e-08,0.984384,0.000438322,-1.09694e-07,6.6157e-10,0.984823,0.000438105,-1.0771e-07,-2.23379e-08,0.985261,0.000437823,-1.74723e-07,2.90855e-08,0.985698,0.00043756,-8.74669e-08,-3.43992e-08,0.986136,0.000437282,-1.90665e-07,4.89068e-08,0.986573,0.000437048,-4.39442e-08,-4.20188e-08,0.98701,0.000436834,-1.7e-07,-4.11073e-11,0.987446,0.000436494,-1.70124e-07,4.21832e-08,0.987883,0.00043628,-4.35742e-08,-4.94824e-08,0.988319,0.000436044,-1.92021e-07,3.6537e-08,0.988755,0.00043577,-8.24102e-08,-3.70611e-08,0.989191,0.000435494,-1.93593e-07,5.21026e-08,0.989626,0.000435263,-3.72855e-08,-5.21402e-08,0.990061,0.000435032,-1.93706e-07,3.7249e-08,0.990496,0.000434756,-8.19592e-08,-3.72512e-08,0.990931,0.000434481,-1.93713e-07,5.21511e-08,0.991365,0.00043425,-3.72595e-08,-5.21439e-08,0.991799,0.000434019,-1.93691e-07,3.72152e-08,0.992233,0.000433743,-8.20456e-08,-3.71123e-08,0.992667,0.000433468,-1.93382e-07,5.16292e-08,0.9931,0.000433236,-3.84947e-08,-5.01953e-08,0.993533,0.000433008,-1.89081e-07,2.99427e-08,0.993966,0.00043272,-9.92525e-08,-9.9708e-09,0.994399,0.000432491,-1.29165e-07,9.94051e-09,0.994831,0.000432263,-9.93434e-08,-2.97912e-08,0.995263,0.000431975,-1.88717e-07,4.96198e-08,0.995695,0.000431746,-3.98578e-08,-4.94785e-08,0.996127,0.000431518,-1.88293e-07,2.9085e-08,0.996558,0.000431229,-1.01038e-07,-7.25675e-09,0.996989,0.000431005,-1.22809e-07,-5.79945e-11,0.99742,0.000430759,-1.22983e-07,7.48873e-09,0.997851,0.000430536,-1.00516e-07,-2.98969e-08,0.998281,0.000430245,-1.90207e-07,5.24942e-08,0.998711,0.000430022,-3.27246e-08,-6.08706e-08,0.999141,0.000429774,-2.15336e-07,7.17788e-08,0.999571,0.000429392,0.,0.}; + + template struct Lab2RGB; + + template struct Lab2RGB + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const float lThresh = 0.008856f * 903.3f; + const float fThresh = 7.787f * 0.008856f + 16.0f / 116.0f; + + float Y, fy; + + if (src.x <= lThresh) + { + Y = src.x / 903.3f; + fy = 7.787f * Y + 16.0f / 116.0f; + } + else + { + fy = (src.x + 16.0f) / 116.0f; + Y = fy * fy * fy; + } + + float X = src.y / 500.0f + fy; + float Z = fy - src.z / 200.0f; + + if (X <= fThresh) + X = (X - 16.0f / 116.0f) / 7.787f; + else + X = X * X * X; + + if (Z <= fThresh) + Z = (Z - 16.0f / 116.0f) / 7.787f; + else + Z = Z * Z * Z; + + float B = 0.052891f * X - 0.204043f * Y + 1.151152f * Z; + float G = -0.921235f * X + 1.875991f * Y + 0.045244f * Z; + float R = 3.079933f * X - 1.537150f * Y - 0.542782f * Z; + + if (srgb) + { + B = splineInterpolate(B * GAMMA_TAB_SIZE, c_sRGBInvGammaTab, GAMMA_TAB_SIZE); + G = splineInterpolate(G * GAMMA_TAB_SIZE, c_sRGBInvGammaTab, GAMMA_TAB_SIZE); + R = splineInterpolate(R * GAMMA_TAB_SIZE, c_sRGBInvGammaTab, GAMMA_TAB_SIZE); + } + + typename MakeVec::type dst; + + dst.x = blueIdx == 0 ? B : R; + dst.y = G; + dst.z = blueIdx == 0 ? R : B; + setAlpha(dst, ColorChannel::max()); + + return dst; + } + }; + + template struct Lab2RGB + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + float3 buf; + + buf.x = src.x * (100.f / 255.f); + buf.y = src.y - 128; + buf.z = src.z - 128; + + Lab2RGB cvtf; + buf = cvtf(buf); + + typename MakeVec::type dst; + + dst.x = saturate_cast(buf.x * 255.f); + dst.y = saturate_cast(buf.y * 255.f); + dst.z = saturate_cast(buf.z * 255.f); + setAlpha(dst, ColorChannel::max()); + + return dst; + } + }; + + // RGB to Luv + + __constant__ float c_LabCbrtTab[] = {0.137931,0.0114066,0.,1.18859e-07,0.149338,0.011407,3.56578e-07,-5.79396e-07,0.160745,0.0114059,-1.38161e-06,2.16892e-06,0.172151,0.0114097,5.12516e-06,-8.0814e-06,0.183558,0.0113957,-1.9119e-05,3.01567e-05,0.194965,0.0114479,7.13509e-05,-0.000112545,0.206371,0.011253,-0.000266285,-0.000106493,0.217252,0.0104009,-0.000585765,7.32149e-05,0.22714,0.00944906,-0.00036612,1.21917e-05,0.236235,0.0087534,-0.000329545,2.01753e-05,0.244679,0.00815483,-0.000269019,1.24435e-05,0.252577,0.00765412,-0.000231689,1.05618e-05,0.26001,0.00722243,-0.000200003,8.26662e-06,0.267041,0.00684723,-0.000175203,6.76746e-06,0.27372,0.00651712,-0.000154901,5.61192e-06,0.280088,0.00622416,-0.000138065,4.67009e-06,0.286179,0.00596204,-0.000124055,3.99012e-06,0.292021,0.0057259,-0.000112085,3.36032e-06,0.297638,0.00551181,-0.000102004,2.95338e-06,0.30305,0.00531666,-9.31435e-05,2.52875e-06,0.308277,0.00513796,-8.55572e-05,2.22022e-06,0.313331,0.00497351,-7.88966e-05,1.97163e-06,0.318228,0.00482163,-7.29817e-05,1.7248e-06,0.322978,0.00468084,-6.78073e-05,1.55998e-06,0.327593,0.0045499,-6.31274e-05,1.36343e-06,0.332081,0.00442774,-5.90371e-05,1.27136e-06,0.336451,0.00431348,-5.5223e-05,1.09111e-06,0.34071,0.00420631,-5.19496e-05,1.0399e-06,0.344866,0.00410553,-4.88299e-05,9.18347e-07,0.348923,0.00401062,-4.60749e-05,8.29942e-07,0.352889,0.00392096,-4.35851e-05,7.98478e-07,0.356767,0.00383619,-4.11896e-05,6.84917e-07,0.360562,0.00375586,-3.91349e-05,6.63976e-07,0.36428,0.00367959,-3.7143e-05,5.93086e-07,0.367923,0.00360708,-3.53637e-05,5.6976e-07,0.371495,0.00353806,-3.36544e-05,4.95533e-07,0.375,0.00347224,-3.21678e-05,4.87951e-07,0.378441,0.00340937,-3.0704e-05,4.4349e-07,0.38182,0.00334929,-2.93735e-05,4.20297e-07,0.38514,0.0032918,-2.81126e-05,3.7872e-07,0.388404,0.00323671,-2.69764e-05,3.596e-07,0.391614,0.00318384,-2.58976e-05,3.5845e-07,0.394772,0.00313312,-2.48223e-05,2.92765e-07,0.397881,0.00308435,-2.3944e-05,3.18232e-07,0.400942,0.00303742,-2.29893e-05,2.82046e-07,0.403957,0.00299229,-2.21432e-05,2.52315e-07,0.406927,0.00294876,-2.13862e-05,2.58416e-07,0.409855,0.00290676,-2.0611e-05,2.33939e-07,0.412741,0.00286624,-1.99092e-05,2.36342e-07,0.415587,0.00282713,-1.92001e-05,1.916e-07,0.418396,0.00278931,-1.86253e-05,2.1915e-07,0.421167,0.00275271,-1.79679e-05,1.83498e-07,0.423901,0.00271733,-1.74174e-05,1.79343e-07,0.426602,0.00268303,-1.68794e-05,1.72013e-07,0.429268,0.00264979,-1.63633e-05,1.75686e-07,0.431901,0.00261759,-1.58363e-05,1.3852e-07,0.434503,0.00258633,-1.54207e-05,1.64304e-07,0.437074,0.00255598,-1.49278e-05,1.28136e-07,0.439616,0.00252651,-1.45434e-05,1.57618e-07,0.442128,0.0024979,-1.40705e-05,1.0566e-07,0.444612,0.00247007,-1.37535e-05,1.34998e-07,0.447068,0.00244297,-1.33485e-05,1.29207e-07,0.449498,0.00241666,-1.29609e-05,9.32347e-08,0.451902,0.00239102,-1.26812e-05,1.23703e-07,0.45428,0.00236603,-1.23101e-05,9.74072e-08,0.456634,0.0023417,-1.20179e-05,1.12518e-07,0.458964,0.002318,-1.16803e-05,7.83681e-08,0.46127,0.00229488,-1.14452e-05,1.10452e-07,0.463554,0.00227232,-1.11139e-05,7.58719e-08,0.465815,0.00225032,-1.08863e-05,9.2699e-08,0.468055,0.00222882,-1.06082e-05,8.97738e-08,0.470273,0.00220788,-1.03388e-05,5.4845e-08,0.47247,0.00218736,-1.01743e-05,1.0808e-07,0.474648,0.00216734,-9.85007e-06,4.9277e-08,0.476805,0.00214779,-9.70224e-06,8.22408e-08,0.478943,0.00212863,-9.45551e-06,6.87942e-08,0.481063,0.00210993,-9.24913e-06,5.98144e-08,0.483163,0.00209161,-9.06969e-06,7.93789e-08,0.485246,0.00207371,-8.83155e-06,3.99032e-08,0.487311,0.00205616,-8.71184e-06,8.88325e-08,0.489358,0.002039,-8.44534e-06,2.20004e-08,0.491389,0.00202218,-8.37934e-06,9.13872e-08,0.493403,0.0020057,-8.10518e-06,2.96829e-08,0.495401,0.00198957,-8.01613e-06,5.81028e-08,0.497382,0.00197372,-7.84183e-06,6.5731e-08,0.499348,0.00195823,-7.64463e-06,3.66019e-08,0.501299,0.00194305,-7.53483e-06,2.62811e-08,0.503234,0.00192806,-7.45598e-06,9.66907e-08,0.505155,0.00191344,-7.16591e-06,4.18928e-09,0.507061,0.00189912,-7.15334e-06,6.53665e-08,0.508953,0.00188501,-6.95724e-06,3.23686e-08,0.510831,0.00187119,-6.86014e-06,4.35774e-08,0.512696,0.0018576,-6.72941e-06,3.17406e-08,0.514547,0.00184424,-6.63418e-06,6.78785e-08,0.516384,0.00183117,-6.43055e-06,-5.23126e-09,0.518209,0.0018183,-6.44624e-06,7.22562e-08,0.520021,0.00180562,-6.22947e-06,1.42292e-08,0.52182,0.0017932,-6.18679e-06,4.9641e-08,0.523607,0.00178098,-6.03786e-06,2.56259e-08,0.525382,0.00176898,-5.96099e-06,2.66696e-08,0.527145,0.00175714,-5.88098e-06,4.65094e-08,0.528897,0.00174552,-5.74145e-06,2.57114e-08,0.530637,0.00173411,-5.66431e-06,2.94588e-08,0.532365,0.00172287,-5.57594e-06,3.52667e-08,0.534082,0.00171182,-5.47014e-06,8.28868e-09,0.535789,0.00170091,-5.44527e-06,5.07871e-08,0.537484,0.00169017,-5.29291e-06,2.69817e-08,0.539169,0.00167967,-5.21197e-06,2.01009e-08,0.540844,0.0016693,-5.15166e-06,1.18237e-08,0.542508,0.00165903,-5.11619e-06,5.18135e-08,0.544162,0.00164896,-4.96075e-06,1.9341e-08,0.545806,0.00163909,-4.90273e-06,-9.96867e-09,0.54744,0.00162926,-4.93263e-06,8.01382e-08,0.549064,0.00161963,-4.69222e-06,-1.25601e-08,0.550679,0.00161021,-4.7299e-06,2.97067e-08,0.552285,0.00160084,-4.64078e-06,1.29426e-08,0.553881,0.0015916,-4.60195e-06,3.77327e-08,0.555468,0.00158251,-4.48875e-06,1.49412e-08,0.557046,0.00157357,-4.44393e-06,2.17118e-08,0.558615,0.00156475,-4.3788e-06,1.74206e-08,0.560176,0.00155605,-4.32653e-06,2.78152e-08,0.561727,0.00154748,-4.24309e-06,-9.47239e-09,0.563271,0.00153896,-4.27151e-06,6.9679e-08,0.564805,0.00153063,-4.06247e-06,-3.08246e-08,0.566332,0.00152241,-4.15494e-06,5.36188e-08,0.56785,0.00151426,-3.99409e-06,-4.83594e-09,0.56936,0.00150626,-4.00859e-06,2.53293e-08,0.570863,0.00149832,-3.93261e-06,2.27286e-08,0.572357,0.00149052,-3.86442e-06,2.96541e-09,0.573844,0.0014828,-3.85552e-06,2.50147e-08,0.575323,0.00147516,-3.78048e-06,1.61842e-08,0.576794,0.00146765,-3.73193e-06,2.94582e-08,0.578258,0.00146028,-3.64355e-06,-1.48076e-08,0.579715,0.00145295,-3.68798e-06,2.97724e-08,0.581164,0.00144566,-3.59866e-06,1.49272e-08,0.582606,0.00143851,-3.55388e-06,2.97285e-08,0.584041,0.00143149,-3.46469e-06,-1.46323e-08,0.585469,0.00142451,-3.50859e-06,2.88004e-08,0.58689,0.00141758,-3.42219e-06,1.864e-08,0.588304,0.00141079,-3.36627e-06,1.58482e-08,0.589712,0.00140411,-3.31872e-06,-2.24279e-08,0.591112,0.00139741,-3.38601e-06,7.38639e-08,0.592507,0.00139085,-3.16441e-06,-3.46088e-08,0.593894,0.00138442,-3.26824e-06,4.96675e-09,0.595275,0.0013779,-3.25334e-06,7.4346e-08,0.59665,0.00137162,-3.0303e-06,-6.39319e-08,0.598019,0.00136536,-3.2221e-06,6.21725e-08,0.599381,0.00135911,-3.03558e-06,-5.94423e-09,0.600737,0.00135302,-3.05341e-06,2.12091e-08,0.602087,0.00134697,-2.98979e-06,-1.92876e-08,0.603431,0.00134094,-3.04765e-06,5.5941e-08,0.604769,0.00133501,-2.87983e-06,-2.56622e-08,0.606101,0.00132917,-2.95681e-06,4.67078e-08,0.607427,0.0013234,-2.81669e-06,-4.19592e-08,0.608748,0.00131764,-2.94257e-06,6.15243e-08,0.610062,0.00131194,-2.75799e-06,-2.53244e-08,0.611372,0.00130635,-2.83397e-06,3.97739e-08,0.612675,0.0013008,-2.71465e-06,-1.45618e-08,0.613973,0.00129533,-2.75833e-06,1.84733e-08,0.615266,0.00128986,-2.70291e-06,2.73606e-10,0.616553,0.00128446,-2.70209e-06,4.00367e-08,0.617835,0.00127918,-2.58198e-06,-4.12113e-08,0.619111,0.00127389,-2.70561e-06,6.52039e-08,0.620383,0.00126867,-2.51e-06,-4.07901e-08,0.621649,0.00126353,-2.63237e-06,3.83516e-08,0.62291,0.00125838,-2.51732e-06,6.59315e-09,0.624166,0.00125337,-2.49754e-06,-5.11939e-09,0.625416,0.00124836,-2.5129e-06,1.38846e-08,0.626662,0.00124337,-2.47124e-06,9.18514e-09,0.627903,0.00123846,-2.44369e-06,8.97952e-09,0.629139,0.0012336,-2.41675e-06,1.45012e-08,0.63037,0.00122881,-2.37325e-06,-7.37949e-09,0.631597,0.00122404,-2.39538e-06,1.50169e-08,0.632818,0.00121929,-2.35033e-06,6.91648e-09,0.634035,0.00121461,-2.32958e-06,1.69219e-08,0.635248,0.00121,-2.27882e-06,-1.49997e-08,0.636455,0.0012054,-2.32382e-06,4.30769e-08,0.637659,0.00120088,-2.19459e-06,-3.80986e-08,0.638857,0.00119638,-2.30888e-06,4.97134e-08,0.640051,0.00119191,-2.15974e-06,-4.15463e-08,0.641241,0.00118747,-2.28438e-06,5.68667e-08,0.642426,0.00118307,-2.11378e-06,-7.10641e-09,0.643607,0.00117882,-2.1351e-06,-2.8441e-08,0.644784,0.00117446,-2.22042e-06,6.12658e-08,0.645956,0.00117021,-2.03663e-06,-3.78083e-08,0.647124,0.00116602,-2.15005e-06,3.03627e-08,0.648288,0.00116181,-2.05896e-06,-2.40379e-08,0.649448,0.00115762,-2.13108e-06,6.57887e-08,0.650603,0.00115356,-1.93371e-06,-6.03028e-08,0.651755,0.00114951,-2.11462e-06,5.62134e-08,0.652902,0.00114545,-1.94598e-06,-4.53417e-08,0.654046,0.00114142,-2.082e-06,6.55489e-08,0.655185,0.00113745,-1.88536e-06,-3.80396e-08,0.656321,0.00113357,-1.99948e-06,2.70049e-08,0.657452,0.00112965,-1.91846e-06,-1.03755e-08,0.65858,0.00112578,-1.94959e-06,1.44973e-08,0.659704,0.00112192,-1.9061e-06,1.1991e-08,0.660824,0.00111815,-1.87012e-06,-2.85634e-09,0.66194,0.0011144,-1.87869e-06,-5.65782e-10,0.663053,0.00111064,-1.88039e-06,5.11947e-09,0.664162,0.0011069,-1.86503e-06,3.96924e-08,0.665267,0.00110328,-1.74595e-06,-4.46795e-08,0.666368,0.00109966,-1.87999e-06,1.98161e-08,0.667466,0.00109596,-1.82054e-06,2.502e-08,0.66856,0.00109239,-1.74548e-06,-6.86593e-10,0.669651,0.0010889,-1.74754e-06,-2.22739e-08,0.670738,0.00108534,-1.81437e-06,3.01776e-08,0.671821,0.0010818,-1.72383e-06,2.07732e-08,0.672902,0.00107841,-1.66151e-06,-5.36658e-08,0.673978,0.00107493,-1.82251e-06,7.46802e-08,0.675051,0.00107151,-1.59847e-06,-6.62411e-08,0.676121,0.00106811,-1.79719e-06,7.10748e-08,0.677188,0.00106473,-1.58397e-06,-3.92441e-08,0.678251,0.00106145,-1.7017e-06,2.62973e-08,0.679311,0.00105812,-1.62281e-06,-6.34035e-09,0.680367,0.00105486,-1.64183e-06,-9.36249e-10,0.68142,0.00105157,-1.64464e-06,1.00854e-08,0.68247,0.00104831,-1.61438e-06,2.01995e-08,0.683517,0.00104514,-1.55378e-06,-3.1279e-08,0.68456,0.00104194,-1.64762e-06,4.53114e-08,0.685601,0.00103878,-1.51169e-06,-3.07573e-08,0.686638,0.00103567,-1.60396e-06,1.81133e-08,0.687672,0.00103251,-1.54962e-06,1.79085e-08,0.688703,0.00102947,-1.49589e-06,-3.01428e-08,0.689731,0.00102639,-1.58632e-06,4.30583e-08,0.690756,0.00102334,-1.45715e-06,-2.28814e-08,0.691778,0.00102036,-1.52579e-06,-1.11373e-08,0.692797,0.00101727,-1.5592e-06,6.74305e-08,0.693812,0.00101436,-1.35691e-06,-7.97709e-08,0.694825,0.0010114,-1.59622e-06,7.28391e-08,0.695835,0.00100843,-1.37771e-06,-3.27715e-08,0.696842,0.00100558,-1.47602e-06,-1.35807e-09,0.697846,0.00100262,-1.48009e-06,3.82037e-08,0.698847,0.000999775,-1.36548e-06,-3.22474e-08,0.699846,0.000996948,-1.46223e-06,3.11809e-08,0.700841,0.000994117,-1.36868e-06,-3.28714e-08,0.701834,0.000991281,-1.4673e-06,4.07001e-08,0.702824,0.000988468,-1.3452e-06,-1.07197e-08,0.703811,0.000985746,-1.37736e-06,2.17866e-09,0.704795,0.000982998,-1.37082e-06,2.00521e-09,0.705777,0.000980262,-1.3648e-06,-1.01996e-08,0.706756,0.000977502,-1.3954e-06,3.87931e-08,0.707732,0.000974827,-1.27902e-06,-2.57632e-08,0.708706,0.000972192,-1.35631e-06,4.65513e-09,0.709676,0.000969493,-1.34235e-06,7.14257e-09,0.710645,0.00096683,-1.32092e-06,2.63791e-08,0.71161,0.000964267,-1.24178e-06,-5.30543e-08,0.712573,0.000961625,-1.40095e-06,6.66289e-08,0.713533,0.000959023,-1.20106e-06,-3.46474e-08,0.714491,0.000956517,-1.305e-06,1.23559e-08,0.715446,0.000953944,-1.26793e-06,-1.47763e-08,0.716399,0.000951364,-1.31226e-06,4.67494e-08,0.717349,0.000948879,-1.17201e-06,-5.3012e-08,0.718297,0.000946376,-1.33105e-06,4.60894e-08,0.719242,0.000943852,-1.19278e-06,-1.21366e-08,0.720185,0.00094143,-1.22919e-06,2.45673e-09,0.721125,0.000938979,-1.22182e-06,2.30966e-09,0.722063,0.000936543,-1.21489e-06,-1.16954e-08,0.722998,0.000934078,-1.24998e-06,4.44718e-08,0.723931,0.000931711,-1.11656e-06,-4.69823e-08,0.724861,0.000929337,-1.25751e-06,2.4248e-08,0.725789,0.000926895,-1.18477e-06,9.5949e-09,0.726715,0.000924554,-1.15598e-06,-3.02286e-09,0.727638,0.000922233,-1.16505e-06,2.49649e-09,0.72856,0.00091991,-1.15756e-06,-6.96321e-09,0.729478,0.000917575,-1.17845e-06,2.53564e-08,0.730395,0.000915294,-1.10238e-06,-3.48578e-08,0.731309,0.000912984,-1.20695e-06,5.44704e-08,0.732221,0.000910734,-1.04354e-06,-6.38144e-08,0.73313,0.000908455,-1.23499e-06,8.15781e-08,0.734038,0.00090623,-9.90253e-07,-8.3684e-08,0.734943,0.000903999,-1.2413e-06,7.43441e-08,0.735846,0.000901739,-1.01827e-06,-3.48787e-08,0.736746,0.000899598,-1.12291e-06,5.56596e-09,0.737645,0.000897369,-1.10621e-06,1.26148e-08,0.738541,0.000895194,-1.06837e-06,3.57935e-09,0.739435,0.000893068,-1.05763e-06,-2.69322e-08,0.740327,0.000890872,-1.13842e-06,4.45448e-08,0.741217,0.000888729,-1.00479e-06,-3.20376e-08,0.742105,0.000886623,-1.1009e-06,2.40011e-08,0.74299,0.000884493,-1.0289e-06,-4.36209e-09,0.743874,0.000882422,-1.04199e-06,-6.55268e-09,0.744755,0.000880319,-1.06164e-06,3.05728e-08,0.745634,0.000878287,-9.69926e-07,-5.61338e-08,0.746512,0.000876179,-1.13833e-06,7.4753e-08,0.747387,0.000874127,-9.14068e-07,-6.40644e-08,0.74826,0.000872106,-1.10626e-06,6.22955e-08,0.749131,0.000870081,-9.19375e-07,-6.59083e-08,0.75,0.000868044,-1.1171e-06,8.21284e-08,0.750867,0.000866056,-8.70714e-07,-8.37915e-08,0.751732,0.000864064,-1.12209e-06,7.42237e-08,0.752595,0.000862042,-8.99418e-07,-3.42894e-08,0.753456,0.00086014,-1.00229e-06,3.32955e-09,0.754315,0.000858146,-9.92297e-07,2.09712e-08,0.755173,0.000856224,-9.29384e-07,-2.76096e-08,0.756028,0.000854282,-1.01221e-06,2.98627e-08,0.756881,0.000852348,-9.22625e-07,-3.22365e-08,0.757733,0.000850406,-1.01933e-06,3.94786e-08,0.758582,0.000848485,-9.00898e-07,-6.46833e-09,0.75943,0.000846664,-9.20303e-07,-1.36052e-08,0.760275,0.000844783,-9.61119e-07,1.28447e-09,0.761119,0.000842864,-9.57266e-07,8.4674e-09,0.761961,0.000840975,-9.31864e-07,2.44506e-08,0.762801,0.000839185,-8.58512e-07,-4.6665e-08,0.763639,0.000837328,-9.98507e-07,4.30001e-08,0.764476,0.00083546,-8.69507e-07,-6.12609e-09,0.76531,0.000833703,-8.87885e-07,-1.84959e-08,0.766143,0.000831871,-9.43372e-07,2.05052e-08,0.766974,0.000830046,-8.81857e-07,-3.92026e-09,0.767803,0.000828271,-8.93618e-07,-4.82426e-09,0.768631,0.000826469,-9.0809e-07,2.32172e-08,0.769456,0.000824722,-8.38439e-07,-2.84401e-08,0.77028,0.00082296,-9.23759e-07,3.09386e-08,0.771102,0.000821205,-8.30943e-07,-3.57099e-08,0.771922,0.000819436,-9.38073e-07,5.22963e-08,0.772741,0.000817717,-7.81184e-07,-5.42658e-08,0.773558,0.000815992,-9.43981e-07,4.55579e-08,0.774373,0.000814241,-8.07308e-07,-8.75656e-09,0.775186,0.0008126,-8.33578e-07,-1.05315e-08,0.775998,0.000810901,-8.65172e-07,-8.72188e-09,0.776808,0.000809145,-8.91338e-07,4.54191e-08,0.777616,0.000807498,-7.5508e-07,-5.37454e-08,0.778423,0.000805827,-9.16317e-07,5.03532e-08,0.779228,0.000804145,-7.65257e-07,-2.84584e-08,0.780031,0.000802529,-8.50632e-07,3.87579e-09,0.780833,0.00080084,-8.39005e-07,1.29552e-08,0.781633,0.0007992,-8.00139e-07,3.90804e-09,0.782432,0.000797612,-7.88415e-07,-2.85874e-08,0.783228,0.000795949,-8.74177e-07,5.0837e-08,0.784023,0.000794353,-7.21666e-07,-5.55513e-08,0.784817,0.000792743,-8.8832e-07,5.21587e-08,0.785609,0.000791123,-7.31844e-07,-3.38744e-08,0.786399,0.000789558,-8.33467e-07,2.37342e-08,0.787188,0.000787962,-7.62264e-07,-1.45775e-09,0.787975,0.000786433,-7.66638e-07,-1.79034e-08,0.788761,0.000784846,-8.20348e-07,1.34665e-08,0.789545,0.000783246,-7.79948e-07,2.3642e-08,0.790327,0.000781757,-7.09022e-07,-4.84297e-08,0.791108,0.000780194,-8.54311e-07,5.08674e-08,0.791888,0.000778638,-7.01709e-07,-3.58303e-08,0.792666,0.000777127,-8.092e-07,3.28493e-08,0.793442,0.000775607,-7.10652e-07,-3.59624e-08,0.794217,0.000774078,-8.1854e-07,5.13959e-08,0.79499,0.000772595,-6.64352e-07,-5.04121e-08,0.795762,0.000771115,-8.15588e-07,3.10431e-08,0.796532,0.000769577,-7.22459e-07,-1.41557e-08,0.797301,0.00076809,-7.64926e-07,2.55795e-08,0.798069,0.000766636,-6.88187e-07,-2.85578e-08,0.798835,0.000765174,-7.73861e-07,2.90472e-08,0.799599,0.000763714,-6.86719e-07,-2.80262e-08,0.800362,0.000762256,-7.70798e-07,2.34531e-08,0.801123,0.000760785,-7.00438e-07,-6.18144e-09,0.801884,0.000759366,-7.18983e-07,1.27263e-09,0.802642,0.000757931,-7.15165e-07,1.09101e-09,0.803399,0.000756504,-7.11892e-07,-5.63675e-09,0.804155,0.000755064,-7.28802e-07,2.14559e-08,0.80491,0.00075367,-6.64434e-07,-2.05821e-08,0.805663,0.00075228,-7.26181e-07,1.26812e-09,0.806414,0.000750831,-7.22377e-07,1.55097e-08,0.807164,0.000749433,-6.75848e-07,-3.70216e-09,0.807913,0.00074807,-6.86954e-07,-7.0105e-10,0.80866,0.000746694,-6.89057e-07,6.5063e-09,0.809406,0.000745336,-6.69538e-07,-2.53242e-08,0.810151,0.000743921,-7.45511e-07,3.51858e-08,0.810894,0.000742535,-6.39953e-07,3.79034e-09,0.811636,0.000741267,-6.28582e-07,-5.03471e-08,0.812377,0.000739858,-7.79624e-07,7.83886e-08,0.813116,0.000738534,-5.44458e-07,-8.43935e-08,0.813854,0.000737192,-7.97638e-07,8.03714e-08,0.81459,0.000735838,-5.56524e-07,-5.82784e-08,0.815325,0.00073455,-7.31359e-07,3.35329e-08,0.816059,0.000733188,-6.3076e-07,-1.62486e-08,0.816792,0.000731878,-6.79506e-07,3.14614e-08,0.817523,0.000730613,-5.85122e-07,-4.99925e-08,0.818253,0.000729293,-7.35099e-07,4.92994e-08,0.818982,0.000727971,-5.87201e-07,-2.79959e-08,0.819709,0.000726712,-6.71189e-07,3.07959e-09,0.820435,0.000725379,-6.6195e-07,1.56777e-08,0.82116,0.000724102,-6.14917e-07,-6.18564e-09,0.821883,0.000722854,-6.33474e-07,9.06488e-09,0.822606,0.000721614,-6.06279e-07,-3.00739e-08,0.823327,0.000720311,-6.96501e-07,5.16262e-08,0.824046,0.000719073,-5.41623e-07,-5.72214e-08,0.824765,0.000717818,-7.13287e-07,5.80503e-08,0.825482,0.000716566,-5.39136e-07,-5.57703e-08,0.826198,0.00071532,-7.06447e-07,4.58215e-08,0.826912,0.000714045,-5.68983e-07,-8.30636e-09,0.827626,0.000712882,-5.93902e-07,-1.25961e-08,0.828338,0.000711656,-6.3169e-07,-9.13985e-10,0.829049,0.00071039,-6.34432e-07,1.62519e-08,0.829759,0.00070917,-5.85676e-07,-4.48904e-09,0.830468,0.000707985,-5.99143e-07,1.70418e-09,0.831175,0.000706792,-5.9403e-07,-2.32768e-09,0.831881,0.000705597,-6.01014e-07,7.60648e-09,0.832586,0.000704418,-5.78194e-07,-2.80982e-08,0.83329,0.000703177,-6.62489e-07,4.51817e-08,0.833993,0.000701988,-5.26944e-07,-3.34192e-08,0.834694,0.000700834,-6.27201e-07,2.88904e-08,0.835394,0.000699666,-5.4053e-07,-2.25378e-08,0.836093,0.000698517,-6.08143e-07,1.65589e-09,0.836791,0.000697306,-6.03176e-07,1.59142e-08,0.837488,0.000696147,-5.55433e-07,-5.70801e-09,0.838184,0.000695019,-5.72557e-07,6.91792e-09,0.838878,0.000693895,-5.51803e-07,-2.19637e-08,0.839571,0.000692725,-6.17694e-07,2.13321e-08,0.840263,0.000691554,-5.53698e-07,-3.75996e-09,0.840954,0.000690435,-5.64978e-07,-6.29219e-09,0.841644,0.000689287,-5.83855e-07,2.89287e-08,0.842333,0.000688206,-4.97068e-07,-4.98181e-08,0.843021,0.000687062,-6.46523e-07,5.11344e-08,0.843707,0.000685922,-4.9312e-07,-3.55102e-08,0.844393,0.00068483,-5.9965e-07,3.13019e-08,0.845077,0.000683724,-5.05745e-07,-3.00925e-08,0.84576,0.000682622,-5.96022e-07,2.94636e-08,0.846442,0.000681519,-5.07631e-07,-2.81572e-08,0.847123,0.000680419,-5.92103e-07,2.35606e-08,0.847803,0.000679306,-5.21421e-07,-6.48045e-09,0.848482,0.000678243,-5.40863e-07,2.36124e-09,0.849159,0.000677169,-5.33779e-07,-2.96461e-09,0.849836,0.000676092,-5.42673e-07,9.49728e-09,0.850512,0.000675035,-5.14181e-07,-3.50245e-08,0.851186,0.000673902,-6.19254e-07,7.09959e-08,0.851859,0.000672876,-4.06267e-07,-7.01453e-08,0.852532,0.000671853,-6.16703e-07,3.07714e-08,0.853203,0.000670712,-5.24388e-07,6.66423e-09,0.853873,0.000669684,-5.04396e-07,2.17629e-09,0.854542,0.000668681,-4.97867e-07,-1.53693e-08,0.855211,0.000667639,-5.43975e-07,-3.03752e-10,0.855878,0.000666551,-5.44886e-07,1.65844e-08,0.856544,0.000665511,-4.95133e-07,-6.42907e-09,0.857209,0.000664501,-5.1442e-07,9.13195e-09,0.857873,0.0006635,-4.87024e-07,-3.00987e-08,0.858536,0.000662435,-5.7732e-07,5.16584e-08,0.859198,0.000661436,-4.22345e-07,-5.73255e-08,0.859859,0.000660419,-5.94322e-07,5.84343e-08,0.860518,0.000659406,-4.19019e-07,-5.72022e-08,0.861177,0.000658396,-5.90626e-07,5.11653e-08,0.861835,0.000657368,-4.3713e-07,-2.82495e-08,0.862492,0.000656409,-5.21878e-07,2.22788e-09,0.863148,0.000655372,-5.15195e-07,1.9338e-08,0.863803,0.0006544,-4.5718e-07,-1.99754e-08,0.864457,0.000653425,-5.17107e-07,9.59024e-10,0.86511,0.000652394,-5.1423e-07,1.61393e-08,0.865762,0.000651414,-4.65812e-07,-5.91149e-09,0.866413,0.000650465,-4.83546e-07,7.50665e-09,0.867063,0.00064952,-4.61026e-07,-2.4115e-08,0.867712,0.000648526,-5.33371e-07,2.93486e-08,0.86836,0.000647547,-4.45325e-07,-3.36748e-08,0.869007,0.000646555,-5.4635e-07,4.57461e-08,0.869653,0.0006456,-4.09112e-07,-3.01002e-08,0.870298,0.000644691,-4.99412e-07,1.50501e-08,0.870942,0.000643738,-4.54262e-07,-3.01002e-08,0.871585,0.000642739,-5.44563e-07,4.57461e-08,0.872228,0.000641787,-4.07324e-07,-3.36748e-08,0.872869,0.000640871,-5.08349e-07,2.93486e-08,0.873509,0.000639943,-4.20303e-07,-2.4115e-08,0.874149,0.00063903,-4.92648e-07,7.50655e-09,0.874787,0.000638067,-4.70128e-07,-5.91126e-09,0.875425,0.000637109,-4.87862e-07,1.61385e-08,0.876062,0.000636182,-4.39447e-07,9.61961e-10,0.876697,0.000635306,-4.36561e-07,-1.99863e-08,0.877332,0.000634373,-4.9652e-07,1.93785e-08,0.877966,0.000633438,-4.38384e-07,2.07697e-09,0.878599,0.000632567,-4.32153e-07,-2.76864e-08,0.879231,0.00063162,-5.15212e-07,4.90641e-08,0.879862,0.000630737,-3.6802e-07,-4.93606e-08,0.880493,0.000629852,-5.16102e-07,2.9169e-08,0.881122,0.000628908,-4.28595e-07,-7.71083e-09,0.881751,0.000628027,-4.51727e-07,1.6744e-09,0.882378,0.000627129,-4.46704e-07,1.01317e-09,0.883005,0.000626239,-4.43665e-07,-5.72703e-09,0.883631,0.000625334,-4.60846e-07,2.1895e-08,0.884255,0.000624478,-3.95161e-07,-2.22481e-08,0.88488,0.000623621,-4.61905e-07,7.4928e-09,0.885503,0.00062272,-4.39427e-07,-7.72306e-09,0.886125,0.000621818,-4.62596e-07,2.33995e-08,0.886746,0.000620963,-3.92398e-07,-2.62704e-08,0.887367,0.000620099,-4.71209e-07,2.20775e-08,0.887987,0.000619223,-4.04976e-07,-2.43496e-09,0.888605,0.000618406,-4.12281e-07,-1.23377e-08,0.889223,0.000617544,-4.49294e-07,-7.81876e-09,0.88984,0.000616622,-4.72751e-07,4.36128e-08,0.890457,0.000615807,-3.41912e-07,-4.7423e-08,0.891072,0.000614981,-4.84181e-07,2.68698e-08,0.891687,0.000614093,-4.03572e-07,-4.51384e-10,0.8923,0.000613285,-4.04926e-07,-2.50643e-08,0.892913,0.0006124,-4.80119e-07,4.11038e-08,0.893525,0.000611563,-3.56808e-07,-2.01414e-08,0.894136,0.000610789,-4.17232e-07,-2.01426e-08,0.894747,0.000609894,-4.7766e-07,4.11073e-08,0.895356,0.000609062,-3.54338e-07,-2.50773e-08,0.895965,0.000608278,-4.2957e-07,-4.02954e-10,0.896573,0.000607418,-4.30779e-07,2.66891e-08,0.89718,0.000606636,-3.50711e-07,-4.67489e-08,0.897786,0.000605795,-4.90958e-07,4.10972e-08,0.898391,0.000604936,-3.67666e-07,1.56948e-09,0.898996,0.000604205,-3.62958e-07,-4.73751e-08,0.8996,0.000603337,-5.05083e-07,6.87214e-08,0.900202,0.000602533,-2.98919e-07,-4.86966e-08,0.900805,0.000601789,-4.45009e-07,6.85589e-09,0.901406,0.00060092,-4.24441e-07,2.1273e-08,0.902007,0.000600135,-3.60622e-07,-3.23434e-08,0.902606,0.000599317,-4.57652e-07,4.84959e-08,0.903205,0.000598547,-3.12164e-07,-4.24309e-08,0.903803,0.000597795,-4.39457e-07,2.01844e-09,0.904401,0.000596922,-4.33402e-07,3.43571e-08,0.904997,0.000596159,-3.30331e-07,-2.02374e-08,0.905593,0.000595437,-3.91043e-07,-1.30123e-08,0.906188,0.000594616,-4.3008e-07,1.26819e-08,0.906782,0.000593794,-3.92034e-07,2.18894e-08,0.907376,0.000593076,-3.26366e-07,-4.06349e-08,0.907968,0.000592301,-4.4827e-07,2.1441e-08,0.90856,0.000591469,-3.83947e-07,1.44754e-08,0.909151,0.000590744,-3.40521e-07,-1.97379e-08,0.909742,0.000590004,-3.99735e-07,4.87161e-09,0.910331,0.000589219,-3.8512e-07,2.51532e-10,0.91092,0.00058845,-3.84366e-07,-5.87776e-09,0.911508,0.000587663,-4.01999e-07,2.32595e-08,0.912096,0.000586929,-3.3222e-07,-2.75554e-08,0.912682,0.000586182,-4.14887e-07,2.73573e-08,0.913268,0.000585434,-3.32815e-07,-2.22692e-08,0.913853,0.000584702,-3.99622e-07,2.11486e-09,0.914437,0.000583909,-3.93278e-07,1.38098e-08,0.915021,0.000583164,-3.51848e-07,2.25042e-09,0.915604,0.000582467,-3.45097e-07,-2.28115e-08,0.916186,0.000581708,-4.13531e-07,2.93911e-08,0.916767,0.000580969,-3.25358e-07,-3.51481e-08,0.917348,0.000580213,-4.30803e-07,5.15967e-08,0.917928,0.000579506,-2.76012e-07,-5.20296e-08,0.918507,0.000578798,-4.32101e-07,3.73124e-08,0.919085,0.000578046,-3.20164e-07,-3.76154e-08,0.919663,0.000577293,-4.3301e-07,5.35447e-08,0.92024,0.000576587,-2.72376e-07,-5.7354e-08,0.920816,0.000575871,-4.44438e-07,5.66621e-08,0.921391,0.000575152,-2.74452e-07,-5.00851e-08,0.921966,0.000574453,-4.24707e-07,2.4469e-08,0.92254,0.000573677,-3.513e-07,1.18138e-08,0.923114,0.000573009,-3.15859e-07,-1.21195e-08,0.923686,0.000572341,-3.52217e-07,-2.29403e-08,0.924258,0.000571568,-4.21038e-07,4.4276e-08,0.924829,0.000570859,-2.8821e-07,-3.49546e-08,0.9254,0.000570178,-3.93074e-07,3.59377e-08,0.92597,0.000569499,-2.85261e-07,-4.91915e-08,0.926539,0.000568781,-4.32835e-07,4.16189e-08,0.927107,0.00056804,-3.07979e-07,1.92523e-09,0.927675,0.00056743,-3.02203e-07,-4.93198e-08,0.928242,0.000566678,-4.50162e-07,7.61447e-08,0.928809,0.000566006,-2.21728e-07,-7.6445e-08,0.929374,0.000565333,-4.51063e-07,5.08216e-08,0.929939,0.000564583,-2.98599e-07,-7.63212e-09,0.930503,0.000563963,-3.21495e-07,-2.02931e-08,0.931067,0.000563259,-3.82374e-07,2.92001e-08,0.93163,0.000562582,-2.94774e-07,-3.69025e-08,0.932192,0.000561882,-4.05482e-07,5.88053e-08,0.932754,0.000561247,-2.29066e-07,-7.91094e-08,0.933315,0.000560552,-4.66394e-07,7.88184e-08,0.933875,0.000559856,-2.29939e-07,-5.73501e-08,0.934434,0.000559224,-4.01989e-07,3.13727e-08,0.934993,0.000558514,-3.07871e-07,-8.53611e-09,0.935551,0.000557873,-3.33479e-07,2.77175e-09,0.936109,0.000557214,-3.25164e-07,-2.55091e-09,0.936666,0.000556556,-3.32817e-07,7.43188e-09,0.937222,0.000555913,-3.10521e-07,-2.71766e-08,0.937778,0.00055521,-3.92051e-07,4.167e-08,0.938333,0.000554551,-2.67041e-07,-2.02941e-08,0.938887,0.000553956,-3.27923e-07,-2.00984e-08,0.93944,0.00055324,-3.88218e-07,4.10828e-08,0.939993,0.000552587,-2.6497e-07,-2.50237e-08,0.940546,0.000551982,-3.40041e-07,-5.92583e-10,0.941097,0.0005513,-3.41819e-07,2.7394e-08,0.941648,0.000550698,-2.59637e-07,-4.93788e-08,0.942199,0.000550031,-4.07773e-07,5.09119e-08,0.942748,0.000549368,-2.55038e-07,-3.50595e-08,0.943297,0.000548753,-3.60216e-07,2.97214e-08,0.943846,0.000548122,-2.71052e-07,-2.42215e-08,0.944394,0.000547507,-3.43716e-07,7.55985e-09,0.944941,0.000546842,-3.21037e-07,-6.01796e-09,0.945487,0.000546182,-3.3909e-07,1.65119e-08,0.946033,0.000545553,-2.89555e-07,-4.2498e-10,0.946578,0.000544973,-2.9083e-07,-1.4812e-08,0.947123,0.000544347,-3.35266e-07,6.83068e-11,0.947667,0.000543676,-3.35061e-07,1.45388e-08,0.94821,0.00054305,-2.91444e-07,1.38123e-09,0.948753,0.000542471,-2.87301e-07,-2.00637e-08,0.949295,0.000541836,-3.47492e-07,1.92688e-08,0.949837,0.000541199,-2.89685e-07,2.59298e-09,0.950378,0.000540628,-2.81906e-07,-2.96407e-08,0.950918,0.000539975,-3.70829e-07,5.63652e-08,0.951458,0.000539402,-2.01733e-07,-7.66107e-08,0.951997,0.000538769,-4.31565e-07,7.12638e-08,0.952535,0.00053812,-2.17774e-07,-2.96305e-08,0.953073,0.000537595,-3.06665e-07,-1.23464e-08,0.95361,0.000536945,-3.43704e-07,1.94114e-08,0.954147,0.000536316,-2.8547e-07,-5.69451e-09,0.954683,0.000535728,-3.02554e-07,3.36666e-09,0.955219,0.000535133,-2.92454e-07,-7.77208e-09,0.955753,0.000534525,-3.1577e-07,2.77216e-08,0.956288,0.000533976,-2.32605e-07,-4.35097e-08,0.956821,0.00053338,-3.63134e-07,2.7108e-08,0.957354,0.000532735,-2.8181e-07,-5.31772e-09,0.957887,0.000532156,-2.97764e-07,-5.83718e-09,0.958419,0.000531543,-3.15275e-07,2.86664e-08,0.95895,0.000530998,-2.29276e-07,-4.9224e-08,0.959481,0.000530392,-3.76948e-07,4.90201e-08,0.960011,0.000529785,-2.29887e-07,-2.76471e-08,0.96054,0.000529243,-3.12829e-07,1.96385e-09,0.961069,0.000528623,-3.06937e-07,1.97917e-08,0.961598,0.000528068,-2.47562e-07,-2.15261e-08,0.962125,0.000527508,-3.1214e-07,6.70795e-09,0.962653,0.000526904,-2.92016e-07,-5.30573e-09,0.963179,0.000526304,-3.07934e-07,1.4515e-08,0.963705,0.000525732,-2.64389e-07,6.85048e-09,0.964231,0.000525224,-2.43837e-07,-4.19169e-08,0.964756,0.00052461,-3.69588e-07,4.1608e-08,0.96528,0.000523996,-2.44764e-07,-5.30598e-09,0.965804,0.000523491,-2.60682e-07,-2.03841e-08,0.966327,0.000522908,-3.21834e-07,2.72378e-08,0.966849,0.000522346,-2.40121e-07,-2.89625e-08,0.967371,0.000521779,-3.27008e-07,2.90075e-08,0.967893,0.000521212,-2.39986e-07,-2.74629e-08,0.968414,0.00052065,-3.22374e-07,2.12396e-08,0.968934,0.000520069,-2.58656e-07,2.10922e-09,0.969454,0.000519558,-2.52328e-07,-2.96765e-08,0.969973,0.000518964,-3.41357e-07,5.6992e-08,0.970492,0.000518452,-1.70382e-07,-7.90821e-08,0.97101,0.000517874,-4.07628e-07,8.05224e-08,0.971528,0.000517301,-1.66061e-07,-6.41937e-08,0.972045,0.000516776,-3.58642e-07,5.70429e-08,0.972561,0.00051623,-1.87513e-07,-4.47686e-08,0.973077,0.00051572,-3.21819e-07,2.82237e-09,0.973593,0.000515085,-3.13352e-07,3.34792e-08,0.974108,0.000514559,-2.12914e-07,-1.75298e-08,0.974622,0.000514081,-2.65503e-07,-2.29648e-08,0.975136,0.000513481,-3.34398e-07,4.97843e-08,0.975649,0.000512961,-1.85045e-07,-5.6963e-08,0.976162,0.00051242,-3.55934e-07,5.88585e-08,0.976674,0.000511885,-1.79359e-07,-5.92616e-08,0.977185,0.000511348,-3.57143e-07,5.89785e-08,0.977696,0.000510811,-1.80208e-07,-5.74433e-08,0.978207,0.000510278,-3.52538e-07,5.15854e-08,0.978717,0.000509728,-1.97781e-07,-2.9689e-08,0.979226,0.000509243,-2.86848e-07,7.56591e-09,0.979735,0.000508692,-2.64151e-07,-5.74649e-10,0.980244,0.000508162,-2.65875e-07,-5.26732e-09,0.980752,0.000507615,-2.81677e-07,2.16439e-08,0.981259,0.000507116,-2.16745e-07,-2.17037e-08,0.981766,0.000506618,-2.81856e-07,5.56636e-09,0.982272,0.000506071,-2.65157e-07,-5.61689e-10,0.982778,0.000505539,-2.66842e-07,-3.31963e-09,0.983283,0.000504995,-2.76801e-07,1.38402e-08,0.983788,0.000504483,-2.3528e-07,7.56339e-09,0.984292,0.000504035,-2.1259e-07,-4.40938e-08,0.984796,0.000503478,-3.44871e-07,4.96026e-08,0.985299,0.000502937,-1.96064e-07,-3.51071e-08,0.985802,0.000502439,-3.01385e-07,3.12212e-08,0.986304,0.00050193,-2.07721e-07,-3.0173e-08,0.986806,0.000501424,-2.9824e-07,2.9866e-08,0.987307,0.000500917,-2.08642e-07,-2.96865e-08,0.987808,0.000500411,-2.97702e-07,2.92753e-08,0.988308,0.000499903,-2.09876e-07,-2.78101e-08,0.988807,0.0004994,-2.93306e-07,2.23604e-08,0.989307,0.000498881,-2.26225e-07,-2.02681e-09,0.989805,0.000498422,-2.32305e-07,-1.42531e-08,0.990303,0.000497915,-2.75065e-07,-5.65232e-10,0.990801,0.000497363,-2.76761e-07,1.65141e-08,0.991298,0.000496859,-2.27218e-07,-5.88639e-09,0.991795,0.000496387,-2.44878e-07,7.0315e-09,0.992291,0.000495918,-2.23783e-07,-2.22396e-08,0.992787,0.000495404,-2.90502e-07,2.23224e-08,0.993282,0.00049489,-2.23535e-07,-7.44543e-09,0.993776,0.000494421,-2.45871e-07,7.45924e-09,0.994271,0.000493951,-2.23493e-07,-2.23915e-08,0.994764,0.000493437,-2.90668e-07,2.25021e-08,0.995257,0.000492923,-2.23161e-07,-8.01218e-09,0.99575,0.000492453,-2.47198e-07,9.54669e-09,0.996242,0.000491987,-2.18558e-07,-3.01746e-08,0.996734,0.000491459,-3.09082e-07,5.1547e-08,0.997225,0.000490996,-1.54441e-07,-5.68039e-08,0.997716,0.000490517,-3.24853e-07,5.64594e-08,0.998206,0.000490036,-1.55474e-07,-4.98245e-08,0.998696,0.000489576,-3.04948e-07,2.36292e-08,0.999186,0.000489037,-2.3406e-07,1.49121e-08,0.999674,0.000488613,-1.89324e-07,-2.3673e-08,1.00016,0.000488164,-2.60343e-07,2.01754e-08,1.00065,0.000487704,-1.99816e-07,-5.70288e-08,1.00114,0.000487133,-3.70903e-07,8.87303e-08,1.00162,0.000486657,-1.04712e-07,-5.94737e-08,1.00211,0.000486269,-2.83133e-07,2.99553e-08,1.0026,0.000485793,-1.93267e-07,-6.03474e-08,1.00308,0.000485225,-3.74309e-07,9.2225e-08,1.00357,0.000484754,-9.76345e-08,-7.0134e-08,1.00405,0.000484348,-3.08036e-07,6.91016e-08,1.00454,0.000483939,-1.00731e-07,-8.70633e-08,1.00502,0.000483476,-3.61921e-07,4.07328e-08,1.0055,0.000482875,-2.39723e-07,4.33413e-08,1.00599,0.000482525,-1.09699e-07,-9.48886e-08,1.00647,0.000482021,-3.94365e-07,9.77947e-08,1.00695,0.000481526,-1.00981e-07,-5.78713e-08,1.00743,0.00048115,-2.74595e-07,1.44814e-08,1.00791,0.000480645,-2.31151e-07,-5.42665e-11,1.00839,0.000480182,-2.31314e-07,-1.42643e-08,1.00887,0.000479677,-2.74106e-07,5.71115e-08,1.00935,0.0004793,-1.02772e-07,-9.49724e-08,1.00983,0.000478809,-3.87689e-07,8.43596e-08,1.01031,0.000478287,-1.3461e-07,-4.04755e-09,1.01079,0.000478006,-1.46753e-07,-6.81694e-08,1.01127,0.000477508,-3.51261e-07,3.83067e-08,1.01174,0.00047692,-2.36341e-07,3.41521e-08,1.01222,0.00047655,-1.33885e-07,-5.57058e-08,1.0127,0.000476115,-3.01002e-07,6.94616e-08,1.01317,0.000475721,-9.26174e-08,-1.02931e-07,1.01365,0.000475227,-4.01412e-07,1.03846e-07,1.01412,0.000474736,-8.98751e-08,-7.40321e-08,1.0146,0.000474334,-3.11971e-07,7.30735e-08,1.01507,0.00047393,-9.27508e-08,-9.90527e-08,1.01554,0.000473447,-3.89909e-07,8.47188e-08,1.01602,0.000472921,-1.35753e-07,-1.40381e-09,1.01649,0.000472645,-1.39964e-07,-7.91035e-08,1.01696,0.000472128,-3.77275e-07,7.93993e-08,1.01744,0.000471612,-1.39077e-07,-7.52607e-11,1.01791,0.000471334,-1.39302e-07,-7.90983e-08,1.01838,0.000470818,-3.76597e-07,7.80499e-08,1.01885,0.000470299,-1.42448e-07,5.31733e-09,1.01932,0.00047003,-1.26496e-07,-9.93193e-08,1.01979,0.000469479,-4.24453e-07,1.53541e-07,1.02026,0.00046909,3.617e-08,-1.57217e-07,1.02073,0.000468691,-4.35482e-07,1.177e-07,1.02119,0.000468173,-8.23808e-08,-7.51659e-08,1.02166,0.000467783,-3.07878e-07,6.37538e-08,1.02213,0.000467358,-1.16617e-07,-6.064e-08,1.0226,0.000466943,-2.98537e-07,5.9597e-08,1.02306,0.000466525,-1.19746e-07,-5.85386e-08,1.02353,0.00046611,-2.95362e-07,5.53482e-08,1.024,0.000465685,-1.29317e-07,-4.36449e-08,1.02446,0.000465296,-2.60252e-07,2.20268e-11,1.02493,0.000464775,-2.60186e-07,4.35568e-08,1.02539,0.000464386,-1.29516e-07,-5.50398e-08,1.02586,0.000463961,-2.94635e-07,5.73932e-08,1.02632,0.000463544,-1.22456e-07,-5.53236e-08,1.02678,0.000463133,-2.88426e-07,4.46921e-08,1.02725,0.000462691,-1.5435e-07,-4.23534e-09,1.02771,0.000462369,-1.67056e-07,-2.77507e-08,1.02817,0.000461952,-2.50308e-07,-3.97101e-09,1.02863,0.000461439,-2.62221e-07,4.36348e-08,1.02909,0.000461046,-1.31317e-07,-5.13589e-08,1.02955,0.000460629,-2.85394e-07,4.25913e-08,1.03001,0.000460186,-1.5762e-07,2.0285e-10,1.03047,0.000459871,-1.57011e-07,-4.34027e-08,1.03093,0.000459427,-2.87219e-07,5.41987e-08,1.03139,0.000459015,-1.24623e-07,-5.4183e-08,1.03185,0.000458604,-2.87172e-07,4.33239e-08,1.03231,0.000458159,-1.572e-07,9.65817e-11,1.03277,0.000457845,-1.56911e-07,-4.37103e-08,1.03323,0.0004574,-2.88041e-07,5.55351e-08,1.03368,0.000456991,-1.21436e-07,-5.9221e-08,1.03414,0.00045657,-2.99099e-07,6.21394e-08,1.0346,0.000456158,-1.1268e-07,-7.01275e-08,1.03505,0.000455723,-3.23063e-07,9.91614e-08,1.03551,0.000455374,-2.55788e-08,-8.80996e-08,1.03596,0.000455058,-2.89878e-07,1.48184e-08,1.03642,0.000454523,-2.45422e-07,2.88258e-08,1.03687,0.000454119,-1.58945e-07,-1.09125e-08,1.03733,0.000453768,-1.91682e-07,1.48241e-08,1.03778,0.000453429,-1.4721e-07,-4.83838e-08,1.03823,0.00045299,-2.92361e-07,5.95019e-08,1.03869,0.000452584,-1.13856e-07,-7.04146e-08,1.03914,0.000452145,-3.25099e-07,1.02947e-07,1.03959,0.000451803,-1.62583e-08,-1.02955e-07,1.04004,0.000451462,-3.25123e-07,7.04544e-08,1.04049,0.000451023,-1.1376e-07,-5.96534e-08,1.04094,0.000450616,-2.9272e-07,4.89499e-08,1.04139,0.000450178,-1.45871e-07,-1.69369e-08,1.04184,0.000449835,-1.96681e-07,1.87977e-08,1.04229,0.000449498,-1.40288e-07,-5.82539e-08,1.04274,0.000449043,-3.1505e-07,9.50087e-08,1.04319,0.000448698,-3.00238e-08,-8.33623e-08,1.04364,0.000448388,-2.80111e-07,2.20363e-11,1.04409,0.000447828,-2.80045e-07,8.32742e-08,1.04454,0.000447517,-3.02221e-08,-9.47002e-08,1.04498,0.000447173,-3.14323e-07,5.7108e-08,1.04543,0.000446716,-1.42999e-07,-1.45225e-08,1.04588,0.000446386,-1.86566e-07,9.82022e-10,1.04632,0.000446016,-1.8362e-07,1.05944e-08,1.04677,0.00044568,-1.51837e-07,-4.33597e-08,1.04721,0.000445247,-2.81916e-07,4.36352e-08,1.04766,0.000444814,-1.51011e-07,-1.19717e-08,1.0481,0.000444476,-1.86926e-07,4.25158e-09,1.04855,0.000444115,-1.74171e-07,-5.03461e-09,1.04899,0.000443751,-1.89275e-07,1.58868e-08,1.04944,0.00044342,-1.41614e-07,-5.85127e-08,1.04988,0.000442961,-3.17152e-07,9.89548e-08,1.05032,0.000442624,-2.0288e-08,-9.88878e-08,1.05076,0.000442287,-3.16951e-07,5.81779e-08,1.05121,0.000441827,-1.42418e-07,-1.46144e-08,1.05165,0.000441499,-1.86261e-07,2.79892e-10,1.05209,0.000441127,-1.85421e-07,1.34949e-08,1.05253,0.000440797,-1.44937e-07,-5.42594e-08,1.05297,0.000440344,-3.07715e-07,8.43335e-08,1.05341,0.000439982,-5.47146e-08,-4.46558e-08,1.05385,0.000439738,-1.88682e-07,-2.49193e-08,1.05429,0.000439286,-2.6344e-07,2.5124e-08,1.05473,0.000438835,-1.88068e-07,4.36328e-08,1.05517,0.000438589,-5.71699e-08,-8.04459e-08,1.05561,0.000438234,-2.98508e-07,3.97324e-08,1.05605,0.000437756,-1.79311e-07,4.07258e-08,1.05648,0.000437519,-5.71332e-08,-8.34263e-08,1.05692,0.000437155,-3.07412e-07,5.45608e-08,1.05736,0.000436704,-1.4373e-07,-1.56078e-08,1.05779,0.000436369,-1.90553e-07,7.87043e-09,1.05823,0.000436012,-1.66942e-07,-1.58739e-08,1.05867,0.00043563,-2.14563e-07,5.56251e-08,1.0591,0.000435368,-4.76881e-08,-8.74172e-08,1.05954,0.000435011,-3.0994e-07,5.56251e-08,1.05997,0.000434558,-1.43064e-07,-1.58739e-08,1.06041,0.000434224,-1.90686e-07,7.87042e-09,1.06084,0.000433866,-1.67075e-07,-1.56078e-08,1.06127,0.000433485,-2.13898e-07,5.45609e-08,1.06171,0.000433221,-5.02157e-08,-8.34263e-08,1.06214,0.00043287,-3.00495e-07,4.07258e-08,1.06257,0.000432391,-1.78317e-07,3.97325e-08,1.063,0.000432154,-5.91198e-08,-8.04464e-08,1.06344,0.000431794,-3.00459e-07,4.36347e-08,1.06387,0.000431324,-1.69555e-07,2.5117e-08,1.0643,0.000431061,-9.42041e-08,-2.48934e-08,1.06473,0.000430798,-1.68884e-07,-4.47527e-08,1.06516,0.000430326,-3.03142e-07,8.46951e-08,1.06559,0.000429973,-4.90573e-08,-5.56089e-08,1.06602,0.000429708,-2.15884e-07,1.85314e-08,1.06645,0.000429332,-1.6029e-07,-1.85166e-08,1.06688,0.000428956,-2.1584e-07,5.5535e-08,1.06731,0.000428691,-4.92347e-08,-8.44142e-08,1.06774,0.000428339,-3.02477e-07,4.37032e-08,1.06816,0.000427865,-1.71368e-07,2.88107e-08,1.06859,0.000427609,-8.49356e-08,-3.97367e-08,1.06902,0.00042732,-2.04146e-07,1.09267e-08,1.06945,0.000426945,-1.71365e-07,-3.97023e-09,1.06987,0.00042659,-1.83276e-07,4.9542e-09,1.0703,0.000426238,-1.68414e-07,-1.58466e-08,1.07073,0.000425854,-2.15953e-07,5.84321e-08,1.07115,0.000425597,-4.0657e-08,-9.86725e-08,1.07158,0.00042522,-3.36674e-07,9.78392e-08,1.072,0.00042484,-4.31568e-08,-5.42658e-08,1.07243,0.000424591,-2.05954e-07,1.45377e-11,1.07285,0.000424179,-2.0591e-07,5.42076e-08,1.07328,0.00042393,-4.32877e-08,-9.76357e-08,1.0737,0.00042355,-3.36195e-07,9.79165e-08,1.07412,0.000423172,-4.24451e-08,-5.56118e-08,1.07455,0.00042292,-2.09281e-07,5.32143e-09,1.07497,0.000422518,-1.93316e-07,3.43261e-08,1.07539,0.000422234,-9.0338e-08,-2.34165e-08,1.07581,0.000421983,-1.60588e-07,-5.98692e-08,1.07623,0.000421482,-3.40195e-07,1.43684e-07,1.07666,0.000421233,9.08574e-08,-1.5724e-07,1.07708,0.000420943,-3.80862e-07,1.27647e-07,1.0775,0.000420564,2.0791e-09,-1.1493e-07,1.07792,0.000420223,-3.4271e-07,9.36534e-08,1.07834,0.000419819,-6.17499e-08,-2.12653e-08,1.07876,0.000419632,-1.25546e-07,-8.59219e-09,1.07918,0.000419355,-1.51322e-07,-6.35752e-08,1.0796,0.000418861,-3.42048e-07,1.43684e-07,1.08002,0.000418608,8.90034e-08,-1.53532e-07,1.08043,0.000418326,-3.71593e-07,1.12817e-07,1.08085,0.000417921,-3.31414e-08,-5.93184e-08,1.08127,0.000417677,-2.11097e-07,5.24697e-09,1.08169,0.00041727,-1.95356e-07,3.83305e-08,1.0821,0.000416995,-8.03642e-08,-3.93597e-08,1.08252,0.000416716,-1.98443e-07,-1.0094e-10,1.08294,0.000416319,-1.98746e-07,3.97635e-08,1.08335,0.00041604,-7.94557e-08,-3.97437e-08,1.08377,0.000415762,-1.98687e-07,1.94215e-12,1.08419,0.000415365,-1.98681e-07,3.97359e-08,1.0846,0.000415087,-7.94732e-08,-3.97362e-08,1.08502,0.000414809,-1.98682e-07,-4.31063e-13,1.08543,0.000414411,-1.98683e-07,3.97379e-08,1.08584,0.000414133,-7.94694e-08,-3.97418e-08,1.08626,0.000413855,-1.98695e-07,2.00563e-11,1.08667,0.000413458,-1.98635e-07,3.96616e-08,1.08709,0.000413179,-7.965e-08,-3.9457e-08,1.0875,0.000412902,-1.98021e-07,-1.04281e-09,1.08791,0.000412502,-2.01149e-07,4.36282e-08,1.08832,0.000412231,-7.02648e-08,-5.42608e-08,1.08874,0.000411928,-2.33047e-07,5.42057e-08,1.08915,0.000411624,-7.04301e-08,-4.33527e-08,1.08956,0.000411353,-2.00488e-07,-4.07378e-12,1.08997,0.000410952,-2.005e-07,4.3369e-08,1.09038,0.000410681,-7.03934e-08,-5.42627e-08,1.09079,0.000410378,-2.33182e-07,5.44726e-08,1.0912,0.000410075,-6.97637e-08,-4.44186e-08,1.09161,0.000409802,-2.03019e-07,3.99235e-09,1.09202,0.000409408,-1.91042e-07,2.84491e-08,1.09243,0.000409111,-1.05695e-07,1.42043e-09,1.09284,0.000408904,-1.01434e-07,-3.41308e-08,1.09325,0.000408599,-2.03826e-07,1.58937e-08,1.09366,0.000408239,-1.56145e-07,-2.94438e-08,1.09406,0.000407838,-2.44476e-07,1.01881e-07,1.09447,0.000407655,6.11676e-08,-1.39663e-07,1.09488,0.000407358,-3.57822e-07,9.91432e-08,1.09529,0.00040694,-6.03921e-08,-1.84912e-08,1.09569,0.000406764,-1.15866e-07,-2.51785e-08,1.0961,0.000406457,-1.91401e-07,-4.03115e-12,1.09651,0.000406074,-1.91413e-07,2.51947e-08,1.09691,0.000405767,-1.15829e-07,1.84346e-08,1.09732,0.00040559,-6.05254e-08,-9.89332e-08,1.09772,0.000405172,-3.57325e-07,1.3888e-07,1.09813,0.000404874,5.93136e-08,-9.8957e-08,1.09853,0.000404696,-2.37557e-07,1.853e-08,1.09894,0.000404277,-1.81968e-07,2.48372e-08,1.09934,0.000403987,-1.07456e-07,1.33047e-09,1.09975,0.000403776,-1.03465e-07,-3.01591e-08,1.10015,0.000403479,-1.93942e-07,9.66054e-11,1.10055,0.000403091,-1.93652e-07,2.97727e-08,1.10096,0.000402793,-1.04334e-07,2.19273e-11,1.10136,0.000402585,-1.04268e-07,-2.98604e-08,1.10176,0.000402287,-1.93849e-07,2.10325e-10,1.10216,0.0004019,-1.93218e-07,2.90191e-08,1.10256,0.0004016,-1.06161e-07,2.92264e-09,1.10297,0.000401397,-9.73931e-08,-4.07096e-08,1.10337,0.00040108,-2.19522e-07,4.07067e-08,1.10377,0.000400763,-9.7402e-08,-2.90783e-09,1.10417,0.000400559,-1.06126e-07,-2.90754e-08,1.10457,0.00040026,-1.93352e-07,9.00021e-14,1.10497,0.000399873,-1.93351e-07,2.9075e-08,1.10537,0.000399574,-1.06126e-07,2.90902e-09,1.10577,0.00039937,-9.73992e-08,-4.07111e-08,1.10617,0.000399053,-2.19533e-07,4.07262e-08,1.10657,0.000398736,-9.73541e-08,-2.98424e-09,1.10697,0.000398533,-1.06307e-07,-2.87892e-08,1.10736,0.000398234,-1.92674e-07,-1.06824e-09,1.10776,0.000397845,-1.95879e-07,3.30622e-08,1.10816,0.000397552,-9.66926e-08,-1.19712e-08,1.10856,0.000397323,-1.32606e-07,1.48225e-08,1.10895,0.000397102,-8.81387e-08,-4.73187e-08,1.10935,0.000396784,-2.30095e-07,5.52429e-08,1.10975,0.00039649,-6.4366e-08,-5.44437e-08,1.11014,0.000396198,-2.27697e-07,4.33226e-08,1.11054,0.000395872,-9.77293e-08,3.62656e-10,1.11094,0.000395678,-9.66414e-08,-4.47732e-08,1.11133,0.00039535,-2.30961e-07,5.95208e-08,1.11173,0.000395067,-5.23985e-08,-7.41008e-08,1.11212,0.00039474,-2.74701e-07,1.17673e-07,1.11252,0.000394543,7.83181e-08,-1.58172e-07,1.11291,0.000394225,-3.96199e-07,1.57389e-07,1.1133,0.000393905,7.59679e-08,-1.13756e-07,1.1137,0.000393716,-2.653e-07,5.92165e-08,1.11409,0.000393363,-8.76507e-08,-3.90074e-09,1.11449,0.000393176,-9.93529e-08,-4.36136e-08,1.11488,0.000392846,-2.30194e-07,5.91457e-08,1.11527,0.000392563,-5.27564e-08,-7.376e-08,1.11566,0.000392237,-2.74037e-07,1.16685e-07,1.11606,0.000392039,7.60189e-08,-1.54562e-07,1.11645,0.000391727,-3.87667e-07,1.43935e-07,1.11684,0.000391384,4.4137e-08,-6.35487e-08,1.11723,0.000391281,-1.46509e-07,-8.94896e-09,1.11762,0.000390961,-1.73356e-07,-1.98647e-08,1.11801,0.000390555,-2.3295e-07,8.8408e-08,1.1184,0.000390354,3.22736e-08,-9.53486e-08,1.11879,0.000390133,-2.53772e-07,5.45677e-08,1.11918,0.000389789,-9.0069e-08,-3.71296e-09,1.11957,0.000389598,-1.01208e-07,-3.97159e-08,1.11996,0.000389276,-2.20355e-07,4.33671e-08,1.12035,0.000388966,-9.02542e-08,-1.45431e-08,1.12074,0.000388741,-1.33883e-07,1.48052e-08,1.12113,0.000388518,-8.94678e-08,-4.46778e-08,1.12152,0.000388205,-2.23501e-07,4.46966e-08,1.12191,0.000387892,-8.94114e-08,-1.48992e-08,1.12229,0.000387669,-1.34109e-07,1.49003e-08,1.12268,0.000387445,-8.94082e-08,-4.47019e-08,1.12307,0.000387132,-2.23514e-07,4.4698e-08,1.12345,0.000386819,-8.942e-08,-1.48806e-08,1.12384,0.000386596,-1.34062e-07,1.48245e-08,1.12423,0.000386372,-8.95885e-08,-4.44172e-08,1.12461,0.00038606,-2.2284e-07,4.36351e-08,1.125,0.000385745,-9.19348e-08,-1.09139e-08,1.12539,0.000385528,-1.24677e-07,2.05584e-11,1.12577,0.000385279,-1.24615e-07,1.08317e-08,1.12616,0.000385062,-9.21198e-08,-4.33473e-08,1.12654,0.000384748,-2.22162e-07,4.33481e-08,1.12693,0.000384434,-9.21174e-08,-1.08356e-08,1.12731,0.000384217,-1.24624e-07,-5.50907e-12,1.12769,0.000383968,-1.24641e-07,1.08577e-08,1.12808,0.000383751,-9.20679e-08,-4.34252e-08,1.12846,0.000383437,-2.22343e-07,4.36337e-08,1.12884,0.000383123,-9.14422e-08,-1.19005e-08,1.12923,0.000382904,-1.27144e-07,3.96813e-09,1.12961,0.000382662,-1.15239e-07,-3.97207e-09,1.12999,0.000382419,-1.27155e-07,1.19201e-08,1.13038,0.000382201,-9.1395e-08,-4.37085e-08,1.13076,0.000381887,-2.2252e-07,4.37046e-08,1.13114,0.000381573,-9.14068e-08,-1.19005e-08,1.13152,0.000381355,-1.27108e-07,3.89734e-09,1.1319,0.000381112,-1.15416e-07,-3.68887e-09,1.13228,0.00038087,-1.26483e-07,1.08582e-08,1.13266,0.00038065,-9.39083e-08,-3.97438e-08,1.13304,0.000380343,-2.1314e-07,2.89076e-08,1.13342,0.000380003,-1.26417e-07,4.33225e-08,1.1338,0.00037988,3.55072e-09,-8.29883e-08,1.13418,0.000379638,-2.45414e-07,5.0212e-08,1.13456,0.000379298,-9.47781e-08,1.34964e-09,1.13494,0.000379113,-9.07292e-08,-5.56105e-08,1.13532,0.000378764,-2.57561e-07,1.01883e-07,1.1357,0.000378555,4.80889e-08,-1.13504e-07,1.13608,0.000378311,-2.92423e-07,1.13713e-07,1.13646,0.000378067,4.87176e-08,-1.02931e-07,1.13683,0.000377856,-2.60076e-07,5.95923e-08,1.13721,0.000377514,-8.12988e-08,-1.62288e-08,1.13759,0.000377303,-1.29985e-07,5.32278e-09,1.13797,0.000377059,-1.14017e-07,-5.06237e-09,1.13834,0.000376816,-1.29204e-07,1.49267e-08,1.13872,0.000376602,-8.44237e-08,-5.46444e-08,1.1391,0.000376269,-2.48357e-07,8.44417e-08,1.13947,0.000376026,4.96815e-09,-4.47039e-08,1.13985,0.000375902,-1.29143e-07,-2.48355e-08,1.14023,0.000375569,-2.0365e-07,2.48368e-08,1.1406,0.000375236,-1.2914e-07,4.46977e-08,1.14098,0.000375112,4.95341e-09,-8.44184e-08,1.14135,0.000374869,-2.48302e-07,5.45572e-08,1.14173,0.000374536,-8.463e-08,-1.46013e-08,1.1421,0.000374323,-1.28434e-07,3.8478e-09,1.14247,0.000374077,-1.1689e-07,-7.89941e-10,1.14285,0.000373841,-1.1926e-07,-6.88042e-10,1.14322,0.0003736,-1.21324e-07,3.54213e-09,1.1436,0.000373368,-1.10698e-07,-1.34805e-08,1.14397,0.000373107,-1.51139e-07,5.03798e-08,1.14434,0.000372767,0.,0.}; + + template struct RGB2Luv; + + template struct RGB2Luv + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const float _d = 1.f / (0.950456f + 15 + 1.088754f * 3); + const float _un = 13 * (4 * 0.950456f * _d); + const float _vn = 13 * (9 * _d); + + float B = blueIdx == 0 ? src.x : src.z; + float G = src.y; + float R = blueIdx == 0 ? src.z : src.x; + + if (srgb) + { + B = splineInterpolate(B * GAMMA_TAB_SIZE, c_sRGBGammaTab, GAMMA_TAB_SIZE); + G = splineInterpolate(G * GAMMA_TAB_SIZE, c_sRGBGammaTab, GAMMA_TAB_SIZE); + R = splineInterpolate(R * GAMMA_TAB_SIZE, c_sRGBGammaTab, GAMMA_TAB_SIZE); + } + + float X = R * 0.412453f + G * 0.357580f + B * 0.180423f; + float Y = R * 0.212671f + G * 0.715160f + B * 0.072169f; + float Z = R * 0.019334f + G * 0.119193f + B * 0.950227f; + + float L = splineInterpolate(Y * (LAB_CBRT_TAB_SIZE / 1.5f), c_LabCbrtTab, LAB_CBRT_TAB_SIZE); + L = 116.f * L - 16.f; + + const float d = (4 * 13) / ::fmaxf(X + 15 * Y + 3 * Z, numeric_limits::epsilon()); + float u = L * (X * d - _un); + float v = L * ((9 * 0.25f) * Y * d - _vn); + + typename MakeVec::type dst; + + dst.x = L; + dst.y = u; + dst.z = v; + + return dst; + } + }; + + template struct RGB2Luv + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + float3 buf; + + buf.x = src.x * (1.f / 255.f); + buf.y = src.y * (1.f / 255.f); + buf.z = src.z * (1.f / 255.f); + + RGB2Luv cvtf; + buf = cvtf(buf); + + typename MakeVec::type dst; + + dst.x = saturate_cast(buf.x * 2.55f); + dst.y = saturate_cast(buf.y * 0.72033898305084743f + 96.525423728813564f); + dst.z = saturate_cast(buf.z * 0.99609375f + 139.453125f); + + return dst; + } + }; + + // Luv to RGB + + template struct Luv2RGB; + + template struct Luv2RGB + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + const float _d = 1.f / (0.950456f + 15 + 1.088754f * 3); + const float _un = 4 * 0.950456f * _d; + const float _vn = 9 * _d; + + float L = src.x; + float u = src.y; + float v = src.z; + + float Y = (L + 16.f) * (1.f / 116.f); + Y = Y * Y * Y; + + float d = (1.f / 13.f) / L; + u = u * d + _un; + v = v * d + _vn; + + float iv = 1.f / v; + float X = 2.25f * u * Y * iv; + float Z = (12 - 3 * u - 20 * v) * Y * 0.25f * iv; + + float B = 0.055648f * X - 0.204043f * Y + 1.057311f * Z; + float G = -0.969256f * X + 1.875991f * Y + 0.041556f * Z; + float R = 3.240479f * X - 1.537150f * Y - 0.498535f * Z; + + if (srgb) + { + B = splineInterpolate(B * GAMMA_TAB_SIZE, c_sRGBInvGammaTab, GAMMA_TAB_SIZE); + G = splineInterpolate(G * GAMMA_TAB_SIZE, c_sRGBInvGammaTab, GAMMA_TAB_SIZE); + R = splineInterpolate(R * GAMMA_TAB_SIZE, c_sRGBInvGammaTab, GAMMA_TAB_SIZE); + } + + typename MakeVec::type dst; + + dst.x = blueIdx == 0 ? B : R; + dst.y = G; + dst.z = blueIdx == 0 ? R : B; + setAlpha(dst, ColorChannel::max()); + + return dst; + } + }; + + template struct Luv2RGB + : unary_function::type, typename MakeVec::type> + { + __device__ typename MakeVec::type operator ()(const typename MakeVec::type& src) const + { + float3 buf; + + buf.x = src.x * (100.f / 255.f); + buf.y = src.y * 1.388235294117647f - 134.f; + buf.z = src.z * 1.003921568627451f - 140.f; + + Luv2RGB cvtf; + buf = cvtf(buf); + + typename MakeVec::type dst; + + dst.x = saturate_cast(buf.x * 255.f); + dst.y = saturate_cast(buf.y * 255.f); + dst.z = saturate_cast(buf.z * 255.f); + setAlpha(dst, ColorChannel::max()); + + return dst; + } + }; + + #undef CV_CUDEV_DESCALE +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/functional/functional.hpp b/modules/cudev/include/opencv2/cudev/functional/functional.hpp new file mode 100644 index 0000000000..3ac532819a --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/functional/functional.hpp @@ -0,0 +1,854 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_FUNCTIONAL_FUNCTIONAL_HPP__ +#define __OPENCV_CUDEV_FUNCTIONAL_FUNCTIONAL_HPP__ + +#include "../common.hpp" +#include "../util/saturate_cast.hpp" +#include "../util/vec_traits.hpp" +#include "../util/vec_math.hpp" +#include "../util/type_traits.hpp" + +namespace cv { namespace cudev { + +// Function Objects + +template struct unary_function +{ + typedef _Arg argument_type; + typedef _Result result_type; +}; + +template struct binary_function +{ + typedef _Arg1 first_argument_type; + typedef _Arg2 second_argument_type; + typedef _Result result_type; +}; + +// Arithmetic Operations + +template struct plus : binary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return saturate_cast(a + b); + } +}; + +template struct minus : binary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return saturate_cast(a - b); + } +}; + +template struct multiplies : binary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return saturate_cast(a * b); + } +}; + +template struct divides : binary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return saturate_cast(a / b); + } +}; + +template struct modulus : binary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return saturate_cast(a % b); + } +}; + +template struct negate : unary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type a) const + { + return saturate_cast(-a); + } +}; + +// Comparison Operations + +template struct equal_to : binary_function::cn>::type> +{ + __device__ __forceinline__ typename MakeVec::cn>::type + operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return a == b; + } +}; + +template struct not_equal_to : binary_function::cn>::type> +{ + __device__ __forceinline__ typename MakeVec::cn>::type + operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return a != b; + } +}; + +template struct greater : binary_function::cn>::type> +{ + __device__ __forceinline__ typename MakeVec::cn>::type + operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return a > b; + } +}; + +template struct less : binary_function::cn>::type> +{ + __device__ __forceinline__ typename MakeVec::cn>::type + operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return a < b; + } +}; + +template struct greater_equal : binary_function::cn>::type> +{ + __device__ __forceinline__ typename MakeVec::cn>::type + operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return a >= b; + } +}; + +template struct less_equal : binary_function::cn>::type> +{ + __device__ __forceinline__ typename MakeVec::cn>::type + operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return a <= b; + } +}; + +// Logical Operations + +template struct logical_and : binary_function::cn>::type> +{ + __device__ __forceinline__ typename MakeVec::cn>::type + operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return a && b; + } +}; + +template struct logical_or : binary_function::cn>::type> +{ + __device__ __forceinline__ typename MakeVec::cn>::type + operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return a || b; + } +}; + +template struct logical_not : unary_function::cn>::type> +{ + __device__ __forceinline__ typename MakeVec::cn>::type + operator ()(typename TypeTraits::parameter_type a) const + { + return !a; + } +}; + +// Bitwise Operations + +template struct bit_and : binary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return a & b; + } +}; + +template struct bit_or : binary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return a | b; + } +}; + +template struct bit_xor : binary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return a ^ b; + } +}; + +template struct bit_not : unary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type v) const + { + return ~v; + } +}; + +template struct bit_lshift : binary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return a << b; + } +}; + +template struct bit_rshift : binary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return a >> b; + } +}; + +// Generalized Identity Operations + +template struct identity : unary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type x) const + { + return x; + } +}; + +template struct project1st : binary_function +{ + __device__ __forceinline__ T1 + operator ()(typename TypeTraits::parameter_type lhs, + typename TypeTraits::parameter_type) const + { + return lhs; + } +}; + +template struct project2nd : binary_function +{ + __device__ __forceinline__ T2 + operator ()(typename TypeTraits::parameter_type, + typename TypeTraits::parameter_type rhs) const + { + return rhs; + } +}; + +// Min/Max Operations + +template struct maximum : binary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return max(a, b); + } +}; + +template struct minimum : binary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type a, + typename TypeTraits::parameter_type b) const + { + return min(a, b); + } +}; + +#define CV_CUDEV_MINMAX_INST(type, maxop, minop) \ + template <> struct maximum : binary_function \ + { \ + __device__ __forceinline__ type operator ()(type a, type b) const {return maxop(a, b);} \ + }; \ + template <> struct minimum : binary_function \ + { \ + __device__ __forceinline__ type operator ()(type a, type b) const {return minop(a, b);} \ + }; + + +CV_CUDEV_MINMAX_INST(uchar, ::max, ::min) +CV_CUDEV_MINMAX_INST(schar, ::max, ::min) +CV_CUDEV_MINMAX_INST(ushort, ::max, ::min) +CV_CUDEV_MINMAX_INST(short, ::max, ::min) +CV_CUDEV_MINMAX_INST(int, ::max, ::min) +CV_CUDEV_MINMAX_INST(uint, ::max, ::min) +CV_CUDEV_MINMAX_INST(float, ::fmaxf, ::fminf) +CV_CUDEV_MINMAX_INST(double, ::fmax, ::fmin) + +#undef CV_CUDEV_MINMAX_INST + +// abs_func + +template struct abs_func : unary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type x) const + { + return abs(x); + } +}; + +template <> struct abs_func : unary_function +{ + __device__ __forceinline__ uchar operator ()(uchar x) const + { + return x; + } +}; + +template <> struct abs_func : unary_function +{ + __device__ __forceinline__ schar operator ()(schar x) const + { + return ::abs((int) x); + } +}; + +template <> struct abs_func : unary_function +{ + __device__ __forceinline__ ushort operator ()(ushort x) const + { + return x; + } +}; + +template <> struct abs_func : unary_function +{ + __device__ __forceinline__ short operator ()(short x) const + { + return ::abs((int) x); + } +}; + +template <> struct abs_func : unary_function +{ + __device__ __forceinline__ uint operator ()(uint x) const + { + return x; + } +}; + +template <> struct abs_func : unary_function +{ + __device__ __forceinline__ int operator ()(int x) const + { + return ::abs(x); + } +}; + +template <> struct abs_func : unary_function +{ + __device__ __forceinline__ float operator ()(float x) const + { + return ::fabsf(x); + } +}; + +template <> struct abs_func : unary_function +{ + __device__ __forceinline__ double operator ()(double x) const + { + return ::fabs(x); + } +}; + +// absdiff_func + +template struct absdiff_func : binary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type a, typename TypeTraits::parameter_type b) const + { + abs_func f; + return f(a - b); + } +}; + +// Math functions + +template struct sqr_func : unary_function +{ + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type x) const + { + return x * x; + } +}; + +namespace functional_detail +{ + template struct FloatType + { + typedef typename MakeVec< + typename LargerType::elem_type>::type, + VecTraits::cn + >::type type; + }; +} + +#define CV_CUDEV_UNARY_FUNCTION_INST(name, func) \ + template struct name ## _func : unary_function::type> \ + { \ + __device__ __forceinline__ typename functional_detail::FloatType::type operator ()(typename TypeTraits::parameter_type a) const \ + { \ + return name(a); \ + } \ + }; \ + template <> struct name ## _func : unary_function \ + { \ + __device__ __forceinline__ float operator ()(uchar a) const \ + { \ + return func ## f(a); \ + } \ + }; \ + template <> struct name ## _func : unary_function \ + { \ + __device__ __forceinline__ float operator ()(schar a) const \ + { \ + return func ## f(a); \ + } \ + }; \ + template <> struct name ## _func : unary_function \ + { \ + __device__ __forceinline__ float operator ()(ushort a) const \ + { \ + return func ## f(a); \ + } \ + }; \ + template <> struct name ## _func : unary_function \ + { \ + __device__ __forceinline__ float operator ()(short a) const \ + { \ + return func ## f(a); \ + } \ + }; \ + template <> struct name ## _func : unary_function \ + { \ + __device__ __forceinline__ float operator ()(uint a) const \ + { \ + return func ## f(a); \ + } \ + }; \ + template <> struct name ## _func : unary_function \ + { \ + __device__ __forceinline__ float operator ()(int a) const \ + { \ + return func ## f(a); \ + } \ + }; \ + template <> struct name ## _func : unary_function \ + { \ + __device__ __forceinline__ float operator ()(float a) const \ + { \ + return func ## f(a); \ + } \ + }; \ + template <> struct name ## _func : unary_function \ + { \ + __device__ __forceinline__ double operator ()(double a) const \ + { \ + return func(a); \ + } \ + }; + +CV_CUDEV_UNARY_FUNCTION_INST(sqrt, ::sqrt) +CV_CUDEV_UNARY_FUNCTION_INST(exp, ::exp) +CV_CUDEV_UNARY_FUNCTION_INST(exp2, ::exp2) +CV_CUDEV_UNARY_FUNCTION_INST(exp10, ::exp10) +CV_CUDEV_UNARY_FUNCTION_INST(log, ::log) +CV_CUDEV_UNARY_FUNCTION_INST(log2, ::log2) +CV_CUDEV_UNARY_FUNCTION_INST(log10, ::log10) +CV_CUDEV_UNARY_FUNCTION_INST(sin, ::sin) +CV_CUDEV_UNARY_FUNCTION_INST(cos, ::cos) +CV_CUDEV_UNARY_FUNCTION_INST(tan, ::tan) +CV_CUDEV_UNARY_FUNCTION_INST(asin, ::asin) +CV_CUDEV_UNARY_FUNCTION_INST(acos, ::acos) +CV_CUDEV_UNARY_FUNCTION_INST(atan, ::atan) +CV_CUDEV_UNARY_FUNCTION_INST(sinh, ::sinh) +CV_CUDEV_UNARY_FUNCTION_INST(cosh, ::cosh) +CV_CUDEV_UNARY_FUNCTION_INST(tanh, ::tanh) +CV_CUDEV_UNARY_FUNCTION_INST(asinh, ::asinh) +CV_CUDEV_UNARY_FUNCTION_INST(acosh, ::acosh) +CV_CUDEV_UNARY_FUNCTION_INST(atanh, ::atanh) + +#undef CV_CUDEV_UNARY_FUNCTION_INST + +#define CV_CUDEV_BINARY_FUNCTION_INST(name, func) \ + template struct name ## _func : binary_function::type> \ + { \ + __device__ __forceinline__ typename functional_detail::FloatType::type operator ()(typename TypeTraits::parameter_type a, typename TypeTraits::parameter_type b) const \ + { \ + return name(a, b); \ + } \ + }; \ + template <> struct name ## _func : binary_function \ + { \ + __device__ __forceinline__ float operator ()(uchar a, uchar b) const \ + { \ + return func ## f(a, b); \ + } \ + }; \ + template <> struct name ## _func : binary_function \ + { \ + __device__ __forceinline__ float operator ()(schar a, schar b) const \ + { \ + return func ## f(a, b); \ + } \ + }; \ + template <> struct name ## _func : binary_function \ + { \ + __device__ __forceinline__ float operator ()(ushort a, ushort b) const \ + { \ + return func ## f(a, b); \ + } \ + }; \ + template <> struct name ## _func : binary_function \ + { \ + __device__ __forceinline__ float operator ()(short a, short b) const \ + { \ + return func ## f(a, b); \ + } \ + }; \ + template <> struct name ## _func : binary_function \ + { \ + __device__ __forceinline__ float operator ()(uint a, uint b) const \ + { \ + return func ## f(a, b); \ + } \ + }; \ + template <> struct name ## _func : binary_function \ + { \ + __device__ __forceinline__ float operator ()(int a, int b) const \ + { \ + return func ## f(a, b); \ + } \ + }; \ + template <> struct name ## _func : binary_function \ + { \ + __device__ __forceinline__ float operator ()(float a, float b) const \ + { \ + return func ## f(a, b); \ + } \ + }; \ + template <> struct name ## _func : binary_function \ + { \ + __device__ __forceinline__ double operator ()(double a, double b) const \ + { \ + return func(a, b); \ + } \ + }; + +CV_CUDEV_BINARY_FUNCTION_INST(hypot, ::hypot) +CV_CUDEV_BINARY_FUNCTION_INST(atan2, ::atan2) + +#undef CV_CUDEV_BINARY_FUNCTION_INST + +template struct magnitude_func : binary_function::type> +{ + __device__ __forceinline__ typename functional_detail::FloatType::type operator ()(typename TypeTraits::parameter_type a, typename TypeTraits::parameter_type b) const + { + sqrt_func::type> f; + return f(a * a + b * b); + } +}; + +template struct pow_func : binary_function +{ + __device__ __forceinline__ float operator ()(T val, float power) const + { + return ::powf(val, power); + } +}; +template <> struct pow_func : binary_function +{ + __device__ __forceinline__ double operator ()(double val, double power) const + { + return ::pow(val, power); + } +}; + +// Saturate Cast Functor + +template struct saturate_cast_func : unary_function +{ + __device__ __forceinline__ D operator ()(typename TypeTraits::parameter_type v) const + { + return saturate_cast(v); + } +}; + +// Threshold Functors + +template struct ThreshBinaryFunc : unary_function +{ + T thresh; + T maxVal; + + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type src) const + { + return saturate_cast(src > thresh) * maxVal; + } +}; + +template +__host__ __device__ ThreshBinaryFunc thresh_binary_func(T thresh, T maxVal) +{ + ThreshBinaryFunc f; + f.thresh = thresh; + f.maxVal = maxVal; + return f; +} + +template struct ThreshBinaryInvFunc : unary_function +{ + T thresh; + T maxVal; + + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type src) const + { + return saturate_cast(src <= thresh) * maxVal; + } +}; + +template +__host__ __device__ ThreshBinaryInvFunc thresh_binary_inv_func(T thresh, T maxVal) +{ + ThreshBinaryInvFunc f; + f.thresh = thresh; + f.maxVal = maxVal; + return f; +} + +template struct ThreshTruncFunc : unary_function +{ + T thresh; + + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type src) const + { + minimum minOp; + return minOp(src, thresh); + } +}; + +template +__host__ __device__ ThreshTruncFunc thresh_trunc_func(T thresh) +{ + ThreshTruncFunc f; + f.thresh = thresh; + return f; +} + +template struct ThreshToZeroFunc : unary_function +{ + T thresh; + + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type src) const + { + return saturate_cast(src > thresh) * src; + } +}; + +template +__host__ __device__ ThreshToZeroFunc thresh_to_zero_func(T thresh) +{ + ThreshToZeroFunc f; + f.thresh = thresh; + return f; +} + +template struct ThreshToZeroInvFunc : unary_function +{ + T thresh; + + __device__ __forceinline__ T operator ()(typename TypeTraits::parameter_type src) const + { + return saturate_cast(src <= thresh) * src; + } +}; + +template +__host__ __device__ ThreshToZeroInvFunc thresh_to_zero_inv_func(T thresh) +{ + ThreshToZeroInvFunc f; + f.thresh = thresh; + return f; +} + +// Function Object Adaptors + +template struct UnaryNegate : unary_function +{ + Predicate pred; + + __device__ __forceinline__ typename Predicate::result_type operator ()( + typename TypeTraits::parameter_type x) const + { + return !pred(x); + } +}; + +template +__host__ __device__ UnaryNegate not1(const Predicate& pred) +{ + UnaryNegate n; + n.pred = pred; + return n; +} + +template struct BinaryNegate : binary_function +{ + Predicate pred; + + __device__ __forceinline__ typename Predicate::result_type operator ()( + typename TypeTraits::parameter_type x, + typename TypeTraits::parameter_type y) const + { + return !pred(x, y); + } +}; + +template +__host__ __device__ BinaryNegate not2(const Predicate& pred) +{ + BinaryNegate n; + n.pred = pred; + return n; +} + +template struct Binder1st : unary_function +{ + Op op; + typename Op::first_argument_type arg1; + + __device__ __forceinline__ typename Op::result_type operator ()( + typename TypeTraits::parameter_type a) const + { + return op(arg1, a); + } +}; + +template +__host__ __device__ Binder1st bind1st(const Op& op, const typename Op::first_argument_type& arg1) +{ + Binder1st b; + b.op = op; + b.arg1 = arg1; + return b; +} + +template struct Binder2nd : unary_function +{ + Op op; + typename Op::second_argument_type arg2; + + __device__ __forceinline__ typename Op::result_type operator ()( + typename TypeTraits::parameter_type a) const + { + return op(a, arg2); + } +}; + +template +__host__ __device__ Binder2nd bind2nd(const Op& op, const typename Op::second_argument_type& arg2) +{ + Binder2nd b; + b.op = op; + b.arg2 = arg2; + return b; +} + +// Functor Traits + +template struct IsUnaryFunction +{ + typedef char Yes; + struct No {Yes a[2];}; + + template static Yes check(unary_function); + static No check(...); + + static F makeF(); + + enum { value = (sizeof(check(makeF())) == sizeof(Yes)) }; +}; + +template struct IsBinaryFunction +{ + typedef char Yes; + struct No {Yes a[2];}; + + template static Yes check(binary_function); + static No check(...); + + static F makeF(); + + enum { value = (sizeof(check(makeF())) == sizeof(Yes)) }; +}; + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/functional/tuple_adapter.hpp b/modules/cudev/include/opencv2/cudev/functional/tuple_adapter.hpp new file mode 100644 index 0000000000..d3a40db0ea --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/functional/tuple_adapter.hpp @@ -0,0 +1,98 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_FUNCTIONAL_TUPLE_ADAPTER_HPP__ +#define __OPENCV_CUDEV_FUNCTIONAL_TUPLE_ADAPTER_HPP__ + +#include "../common.hpp" +#include "../util/tuple.hpp" + +namespace cv { namespace cudev { + +template struct UnaryTupleAdapter +{ + typedef typename Op::result_type result_type; + + Op op; + + template + __device__ __forceinline__ typename Op::result_type operator ()(const Tuple& t) const + { + return op(get(t)); + } +}; + +template +__host__ __device__ UnaryTupleAdapter unaryTupleAdapter(const Op& op) +{ + UnaryTupleAdapter a; + a.op = op; + return a; +} + +template struct BinaryTupleAdapter +{ + typedef typename Op::result_type result_type; + + Op op; + + template + __device__ __forceinline__ typename Op::result_type operator ()(const Tuple& t) const + { + return op(get(t), get(t)); + } +}; + +template +__host__ __device__ BinaryTupleAdapter binaryTupleAdapter(const Op& op) +{ + BinaryTupleAdapter a; + a.op = op; + return a; +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/copy.hpp b/modules/cudev/include/opencv2/cudev/grid/copy.hpp new file mode 100644 index 0000000000..d7d3ea8343 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/copy.hpp @@ -0,0 +1,452 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_COPY_HPP__ +#define __OPENCV_CUDEV_GRID_COPY_HPP__ + +#include "../common.hpp" +#include "../util/tuple.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/gpumat.hpp" +#include "../ptr2d/glob.hpp" +#include "../ptr2d/mask.hpp" +#include "../ptr2d/zip.hpp" +#include "detail/copy.hpp" + +namespace cv { namespace cudev { + +template +__host__ void gridCopy_(const SrcPtr& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + dst.create(rows, cols); + + grid_copy_detail::copy(shrinkPtr(src), shrinkPtr(dst), shrinkPtr(mask), rows, cols, StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCopy_(const SrcPtr& src, const GlobPtrSz& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(dst) == rows && getCols(dst) == cols ); + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + grid_copy_detail::copy(shrinkPtr(src), shrinkPtr(dst), shrinkPtr(mask), rows, cols, StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCopy_(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + dst.create(rows, cols); + + grid_copy_detail::copy(shrinkPtr(src), shrinkPtr(dst), WithOutMask(), rows, cols, StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCopy_(const SrcPtr& src, const GlobPtrSz& dst, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(dst) == rows && getCols(dst) == cols ); + + grid_copy_detail::copy(shrinkPtr(src), shrinkPtr(dst), WithOutMask(), rows, cols, StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCopy_(const SrcPtrTuple& src, const tuple< GpuMat_&, GpuMat_& >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 2, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + + grid_copy_detail::copy_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst))), + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCopy_(const SrcPtrTuple& src, const tuple< GlobPtrSz, GlobPtrSz >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 2, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(get<0>(dst)) == rows && getCols(get<0>(dst)) == cols ); + CV_Assert( getRows(get<1>(dst)) == rows && getCols(get<1>(dst)) == cols ); + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + grid_copy_detail::copy_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst))), + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCopy_(const SrcPtrTuple& src, const tuple< GpuMat_&, GpuMat_& >& dst, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 2, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + + grid_copy_detail::copy_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst))), + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCopy_(const SrcPtrTuple& src, const tuple< GlobPtrSz, GlobPtrSz >& dst, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 2, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(get<0>(dst)) == rows && getCols(get<0>(dst)) == cols ); + CV_Assert( getRows(get<1>(dst)) == rows && getCols(get<1>(dst)) == cols ); + + grid_copy_detail::copy_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst))), + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCopy_(const SrcPtrTuple& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_& >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 3, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + get<2>(dst).create(rows, cols); + + grid_copy_detail::copy_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst), get<2>(dst))), + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCopy_(const SrcPtrTuple& src, const tuple< GlobPtrSz, GlobPtrSz, GlobPtrSz >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 3, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(get<0>(dst)) == rows && getCols(get<0>(dst)) == cols ); + CV_Assert( getRows(get<1>(dst)) == rows && getCols(get<1>(dst)) == cols ); + CV_Assert( getRows(get<2>(dst)) == rows && getCols(get<2>(dst)) == cols ); + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + grid_copy_detail::copy_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst), get<2>(dst))), + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCopy_(const SrcPtrTuple& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_& >& dst, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 3, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + get<2>(dst).create(rows, cols); + + grid_copy_detail::copy_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst), get<2>(dst))), + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCopy_(const SrcPtrTuple& src, const tuple< GlobPtrSz, GlobPtrSz, GlobPtrSz >& dst, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 3, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(get<0>(dst)) == rows && getCols(get<0>(dst)) == cols ); + CV_Assert( getRows(get<1>(dst)) == rows && getCols(get<1>(dst)) == cols ); + CV_Assert( getRows(get<2>(dst)) == rows && getCols(get<2>(dst)) == cols ); + + grid_copy_detail::copy_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst), get<2>(dst))), + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCopy_(const SrcPtrTuple& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_&, GpuMat_& >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 4, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + get<2>(dst).create(rows, cols); + get<3>(dst).create(rows, cols); + + grid_copy_detail::copy_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst), get<2>(dst), get<3>(dst))), + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCopy_(const SrcPtrTuple& src, const tuple< GlobPtrSz, GlobPtrSz, GlobPtrSz, GlobPtrSz >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 4, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(get<0>(dst)) == rows && getCols(get<0>(dst)) == cols ); + CV_Assert( getRows(get<1>(dst)) == rows && getCols(get<1>(dst)) == cols ); + CV_Assert( getRows(get<2>(dst)) == rows && getCols(get<2>(dst)) == cols ); + CV_Assert( getRows(get<3>(dst)) == rows && getCols(get<3>(dst)) == cols ); + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + grid_copy_detail::copy_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst), get<2>(dst), get<3>(dst))), + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCopy_(const SrcPtrTuple& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_&, GpuMat_& >& dst, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 4, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + get<2>(dst).create(rows, cols); + get<3>(dst).create(rows, cols); + + grid_copy_detail::copy_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst), get<2>(dst), get<3>(dst))), + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCopy_(const SrcPtrTuple& src, const tuple< GlobPtrSz, GlobPtrSz, GlobPtrSz, GlobPtrSz >& dst, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 4, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(get<0>(dst)) == rows && getCols(get<0>(dst)) == cols ); + CV_Assert( getRows(get<1>(dst)) == rows && getCols(get<1>(dst)) == cols ); + CV_Assert( getRows(get<2>(dst)) == rows && getCols(get<2>(dst)) == cols ); + CV_Assert( getRows(get<3>(dst)) == rows && getCols(get<3>(dst)) == cols ); + + grid_copy_detail::copy_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst), get<2>(dst), get<3>(dst))), + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +// Default Policy + +struct DefaultCopyPolicy +{ + enum { + block_size_x = 32, + block_size_y = 8 + }; +}; + +template +__host__ void gridCopy(const SrcPtr& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridCopy_(src, dst, mask, stream); +} + +template +__host__ void gridCopy(const SrcPtr& src, const GlobPtrSz& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridCopy_(src, dst, mask, stream); +} + +template +__host__ void gridCopy(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + gridCopy_(src, dst, stream); +} + +template +__host__ void gridCopy(const SrcPtr& src, const GlobPtrSz& dst, Stream& stream = Stream::Null()) +{ + gridCopy_(src, dst, stream); +} + +template +__host__ void gridCopy(const SrcPtrTuple& src, const tuple< GpuMat_&, GpuMat_& >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridCopy_(src, dst, mask, stream); +} + +template +__host__ void gridCopy(const SrcPtrTuple& src, const tuple< GlobPtrSz, GlobPtrSz >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridCopy_(src, dst, mask, stream); +} + +template +__host__ void gridCopy(const SrcPtrTuple& src, const tuple< GpuMat_&, GpuMat_& >& dst, Stream& stream = Stream::Null()) +{ + gridCopy_(src, dst, stream); +} + +template +__host__ void gridCopy(const SrcPtrTuple& src, const tuple< GlobPtrSz, GlobPtrSz >& dst, Stream& stream = Stream::Null()) +{ + gridCopy_(src, dst, stream); +} + +template +__host__ void gridCopy(const SrcPtrTuple& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_& >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridCopy_(src, dst, mask, stream); +} + +template +__host__ void gridCopy(const SrcPtrTuple& src, const tuple< GlobPtrSz, GlobPtrSz, GlobPtrSz >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridCopy_(src, dst, mask, stream); +} + +template +__host__ void gridCopy(const SrcPtrTuple& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_& >& dst, Stream& stream = Stream::Null()) +{ + gridCopy_(src, dst, stream); +} + +template +__host__ void gridCopy(const SrcPtrTuple& src, const tuple< GlobPtrSz, GlobPtrSz, GlobPtrSz >& dst, Stream& stream = Stream::Null()) +{ + gridCopy_(src, dst, stream); +} + +template +__host__ void gridCopy(const SrcPtrTuple& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_&, GpuMat_& >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridCopy_(src, dst, mask, stream); +} + +template +__host__ void gridCopy(const SrcPtrTuple& src, const tuple< GlobPtrSz, GlobPtrSz, GlobPtrSz, GlobPtrSz >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridCopy_(src, dst, mask, stream); +} + +template +__host__ void gridCopy_(const SrcPtrTuple& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_&, GpuMat_& >& dst, Stream& stream = Stream::Null()) +{ + gridCopy_(src, dst, stream); +} + +template +__host__ void gridCopy_(const SrcPtrTuple& src, const tuple< GlobPtrSz, GlobPtrSz, GlobPtrSz, GlobPtrSz >& dst, Stream& stream = Stream::Null()) +{ + gridCopy_(src, dst, stream); +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/detail/copy.hpp b/modules/cudev/include/opencv2/cudev/grid/detail/copy.hpp new file mode 100644 index 0000000000..707b842f9f --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/detail/copy.hpp @@ -0,0 +1,132 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_COPY_DETAIL_HPP__ +#define __OPENCV_CUDEV_GRID_COPY_DETAIL_HPP__ + +#include "../../common.hpp" +#include "../../util/tuple.hpp" +#include "../../util/saturate_cast.hpp" +#include "../../ptr2d/glob.hpp" +#include "../../ptr2d/traits.hpp" + +namespace cv { namespace cudev { + +namespace grid_copy_detail +{ + template + __global__ void copy(const SrcPtr src, GlobPtr dst, const MaskPtr mask, const int rows, const int cols) + { + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (x >= cols || y >= rows || !mask(y, x)) + return; + + dst(y, x) = saturate_cast(src(y, x)); + } + + template + __host__ void copy(const SrcPtr& src, const GlobPtr& dst, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + const dim3 block(Policy::block_size_x, Policy::block_size_y); + const dim3 grid(divUp(cols, block.x), divUp(rows, block.y)); + + copy<<>>(src, dst, mask, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() ); + } + + template struct Unroll + { + template + __device__ static void copy(const SrcPtrTuple& src, DstPtrTuple& dst, const int y, const int x) + { + typedef typename tuple_element::type dst_ptr_type; + typedef typename PtrTraits::value_type dst_type; + + get(dst)(y, x) = saturate_cast(get(src)(y, x)); + Unroll::copy(src, dst, y, x); + } + }; + template <> struct Unroll<0> + { + template + __device__ __forceinline__ static void copy(const SrcPtrTuple&, DstPtrTuple&, const int, const int) + { + } + }; + + template + __global__ void copy_tuple(const SrcPtrTuple src, DstPtrTuple dst, const MaskPtr mask, const int rows, const int cols) + { + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (x >= cols || y >= rows || !mask(y, x)) + return; + + Unroll::value>::copy(src, dst, y, x); + } + + template + __host__ void copy_tuple(const SrcPtrTuple& src, const DstPtrTuple& dst, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + const dim3 block(Policy::block_size_x, Policy::block_size_y); + const dim3 grid(divUp(cols, block.x), divUp(rows, block.y)); + + copy_tuple<<>>(src, dst, mask, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() ); + } +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/detail/glob_reduce.hpp b/modules/cudev/include/opencv2/cudev/grid/detail/glob_reduce.hpp new file mode 100644 index 0000000000..c9d715982c --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/detail/glob_reduce.hpp @@ -0,0 +1,475 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_GLOB_REDUCE_DETAIL_HPP__ +#define __OPENCV_CUDEV_GRID_GLOB_REDUCE_DETAIL_HPP__ + +#include "../../common.hpp" +#include "../../util/tuple.hpp" +#include "../../util/saturate_cast.hpp" +#include "../../util/atomic.hpp" +#include "../../util/vec_traits.hpp" +#include "../../util/type_traits.hpp" +#include "../../util/limits.hpp" +#include "../../block/reduce.hpp" +#include "../../functional/functional.hpp" +#include "../../ptr2d/traits.hpp" + +namespace cv { namespace cudev { + +namespace grid_glob_reduce_detail +{ + // Unroll + + template struct Unroll; + + template <> struct Unroll<1> + { + template + __device__ __forceinline__ static volatile R* smem(R* ptr) + { + return ptr; + } + + template + __device__ __forceinline__ static R& res(R& val) + { + return val; + } + + template + __device__ __forceinline__ static const Op& op(const Op& aop) + { + return aop; + } + }; + + template <> struct Unroll<2> + { + template + __device__ __forceinline__ static tuple smem(R* ptr) + { + return smem_tuple(ptr, ptr + BLOCK_SIZE); + } + + template + __device__ __forceinline__ static tuple::elem_type&, typename VecTraits::elem_type&> res(R& val) + { + return tie(val.x, val.y); + } + + template + __device__ __forceinline__ static tuple op(const Op& aop) + { + return make_tuple(aop, aop); + } + }; + + template <> struct Unroll<3> + { + template + __device__ __forceinline__ static tuple smem(R* ptr) + { + return smem_tuple(ptr, ptr + BLOCK_SIZE, ptr + 2 * BLOCK_SIZE); + } + + template + __device__ __forceinline__ static tuple::elem_type&, + typename VecTraits::elem_type&, + typename VecTraits::elem_type&> res(R& val) + { + return tie(val.x, val.y, val.z); + } + + template + __device__ __forceinline__ static tuple op(const Op& aop) + { + return make_tuple(aop, aop, aop); + } + }; + + template <> struct Unroll<4> + { + template + __device__ __forceinline__ static tuple smem(R* ptr) + { + return smem_tuple(ptr, ptr + BLOCK_SIZE, ptr + 2 * BLOCK_SIZE, ptr + 3 * BLOCK_SIZE); + } + + template + __device__ __forceinline__ static tuple::elem_type&, + typename VecTraits::elem_type&, + typename VecTraits::elem_type&, + typename VecTraits::elem_type&> res(R& val) + { + return tie(val.x, val.y, val.z, val.w); + } + + template + __device__ __forceinline__ static tuple op(const Op& aop) + { + return make_tuple(aop, aop, aop, aop); + } + }; + + // AtomicUnroll + + template struct AtomicUnroll; + + template struct AtomicUnroll + { + __device__ __forceinline__ static void add(R* ptr, R val) + { + atomicAdd(ptr, val); + } + + __device__ __forceinline__ static void min(R* ptr, R val) + { + atomicMin(ptr, val); + } + + __device__ __forceinline__ static void max(R* ptr, R val) + { + atomicMax(ptr, val); + } + }; + + template struct AtomicUnroll + { + typedef typename MakeVec::type val_type; + + __device__ __forceinline__ static void add(R* ptr, val_type val) + { + atomicAdd(ptr, val.x); + atomicAdd(ptr + 1, val.y); + } + + __device__ __forceinline__ static void min(R* ptr, val_type val) + { + atomicMin(ptr, val.x); + atomicMin(ptr + 1, val.y); + } + + __device__ __forceinline__ static void max(R* ptr, val_type val) + { + atomicMax(ptr, val.x); + atomicMax(ptr + 1, val.y); + } + }; + + template struct AtomicUnroll + { + typedef typename MakeVec::type val_type; + + __device__ __forceinline__ static void add(R* ptr, val_type val) + { + atomicAdd(ptr, val.x); + atomicAdd(ptr + 1, val.y); + atomicAdd(ptr + 2, val.z); + } + + __device__ __forceinline__ static void min(R* ptr, val_type val) + { + atomicMin(ptr, val.x); + atomicMin(ptr + 1, val.y); + atomicMin(ptr + 2, val.z); + } + + __device__ __forceinline__ static void max(R* ptr, val_type val) + { + atomicMax(ptr, val.x); + atomicMax(ptr + 1, val.y); + atomicMax(ptr + 2, val.z); + } + }; + + template struct AtomicUnroll + { + typedef typename MakeVec::type val_type; + + __device__ __forceinline__ static void add(R* ptr, val_type val) + { + atomicAdd(ptr, val.x); + atomicAdd(ptr + 1, val.y); + atomicAdd(ptr + 2, val.z); + atomicAdd(ptr + 3, val.w); + } + + __device__ __forceinline__ static void min(R* ptr, val_type val) + { + atomicMin(ptr, val.x); + atomicMin(ptr + 1, val.y); + atomicMin(ptr + 2, val.z); + atomicMin(ptr + 3, val.w); + } + + __device__ __forceinline__ static void max(R* ptr, val_type val) + { + atomicMax(ptr, val.x); + atomicMax(ptr + 1, val.y); + atomicMax(ptr + 2, val.z); + atomicMax(ptr + 3, val.w); + } + }; + + // SumReductor + + template struct SumReductor + { + typedef typename VecTraits::elem_type work_elem_type; + enum { cn = VecTraits::cn }; + + work_type sum; + + __device__ __forceinline__ SumReductor() + { + sum = VecTraits::all(0); + } + + __device__ __forceinline__ void reduceVal(typename TypeTraits::parameter_type srcVal) + { + sum = sum + saturate_cast(srcVal); + } + + template + __device__ void reduceGrid(work_elem_type* result, int tid) + { + __shared__ work_elem_type smem[BLOCK_SIZE * cn]; + + blockReduce(Unroll::template smem(smem), Unroll::res(sum), tid, Unroll::op(plus())); + + if (tid == 0) + AtomicUnroll::add(result, sum); + } + }; + + // MinMaxReductor + + template struct minop : minimum + { + __device__ __forceinline__ static T initial() + { + return numeric_limits::max(); + } + + __device__ __forceinline__ static void atomic(T* result, T myval) + { + atomicMin(result, myval); + } + }; + + template struct maxop : maximum + { + __device__ __forceinline__ static T initial() + { + return -numeric_limits::max(); + } + + __device__ __forceinline__ static void atomic(T* result, T myval) + { + atomicMax(result, myval); + } + }; + + struct both + { + }; + + template struct MinMaxReductor + { + work_type myval; + + __device__ __forceinline__ MinMaxReductor() + { + myval = Op::initial(); + } + + __device__ __forceinline__ void reduceVal(typename TypeTraits::parameter_type srcVal) + { + Op op; + + myval = op(myval, srcVal); + } + + template + __device__ void reduceGrid(work_type* result, int tid) + { + __shared__ work_type smem[BLOCK_SIZE]; + + Op op; + + blockReduce(smem, myval, tid, op); + + if (tid == 0) + Op::atomic(result, myval); + } + }; + + template struct MinMaxReductor + { + work_type mymin; + work_type mymax; + + __device__ __forceinline__ MinMaxReductor() + { + mymin = numeric_limits::max(); + mymax = -numeric_limits::max(); + } + + __device__ __forceinline__ void reduceVal(typename TypeTraits::parameter_type srcVal) + { + minimum minOp; + maximum maxOp; + + mymin = minOp(mymin, srcVal); + mymax = maxOp(mymax, srcVal); + } + + template + __device__ void reduceGrid(work_type* result, int tid) + { + __shared__ work_type sminval[BLOCK_SIZE]; + __shared__ work_type smaxval[BLOCK_SIZE]; + + minimum minOp; + maximum maxOp; + + blockReduce(smem_tuple(sminval, smaxval), tie(mymin, mymax), tid, make_tuple(minOp, maxOp)); + + if (tid == 0) + { + atomicMin(result, mymin); + atomicMax(result + 1, mymax); + } + } + }; + + // glob_reduce + + template + __global__ void glob_reduce(const SrcPtr src, ResType* result, const MaskPtr mask, const int rows, const int cols) + { + const int x0 = blockIdx.x * blockDim.x * PATCH_X + threadIdx.x; + const int y0 = blockIdx.y * blockDim.y * PATCH_Y + threadIdx.y; + + Reductor reductor; + + for (int i = 0, y = y0; i < PATCH_Y && y < rows; ++i, y += blockDim.y) + { + for (int j = 0, x = x0; j < PATCH_X && x < cols; ++j, x += blockDim.x) + { + if (mask(y, x)) + { + reductor.reduceVal(src(y, x)); + } + } + } + + const int tid = threadIdx.y * blockDim.x + threadIdx.x; + + reductor.template reduceGrid(result, tid); + } + + template + __host__ void glob_reduce(const SrcPtr& src, ResType* result, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + const dim3 block(Policy::block_size_x, Policy::block_size_y); + const dim3 grid(divUp(cols, block.x * Policy::patch_size_x), divUp(rows, block.y * Policy::patch_size_y)); + + const int BLOCK_SIZE = Policy::block_size_x * Policy::block_size_y; + + glob_reduce<<>>(src, result, mask, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() ); + } + + // callers + + template + __host__ void sum(const SrcPtr& src, ResType* result, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + typedef typename PtrTraits::value_type src_type; + const int cn = VecTraits::cn; + typedef typename MakeVec::type work_type; + + glob_reduce, Policy>(src, result, mask, rows, cols, stream); + } + + template + __host__ void minVal(const SrcPtr& src, ResType* result, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + typedef typename PtrTraits::value_type src_type; + const int cn = VecTraits::cn; + typedef typename MakeVec::type work_type; + + glob_reduce, src_type, work_type>, Policy>(src, result, mask, rows, cols, stream); + } + + template + __host__ void maxVal(const SrcPtr& src, ResType* result, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + typedef typename PtrTraits::value_type src_type; + const int cn = VecTraits::cn; + typedef typename MakeVec::type work_type; + + glob_reduce, src_type, work_type>, Policy>(src, result, mask, rows, cols, stream); + } + + template + __host__ void minMaxVal(const SrcPtr& src, ResType* result, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + typedef typename PtrTraits::value_type src_type; + const int cn = VecTraits::cn; + typedef typename MakeVec::type work_type; + + glob_reduce, Policy>(src, result, mask, rows, cols, stream); + } +} + +}} + +#endif diff --git a/modules/gpu/src/video_parser.h b/modules/cudev/include/opencv2/cudev/grid/detail/histogram.hpp similarity index 52% rename from modules/gpu/src/video_parser.h rename to modules/cudev/include/opencv2/cudev/grid/detail/histogram.hpp index 44a53710bf..4c2675098d 100644 --- a/modules/gpu/src/video_parser.h +++ b/modules/cudev/include/opencv2/cudev/grid/detail/histogram.hpp @@ -12,6 +12,7 @@ // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -40,61 +41,69 @@ // //M*/ -#ifndef __VIDEO_PARSER_H__ -#define __VIDEO_PARSER_H__ +#pragma once -#include "precomp.hpp" +#ifndef __OPENCV_CUDEV_GRID_HISTOGRAM_DETAIL_HPP__ +#define __OPENCV_CUDEV_GRID_HISTOGRAM_DETAIL_HPP__ -#include "frame_queue.h" -#include "video_decoder.h" +#include "../../common.hpp" +#include "../../util/atomic.hpp" -#if defined(HAVE_CUDA) && defined(HAVE_NVCUVID) +namespace cv { namespace cudev { -namespace cv { namespace gpu +namespace grid_histogram_detail { - namespace detail + template + __global__ void histogram(const SrcPtr src, ResType* hist, const MaskPtr mask, const int rows, const int cols) { - class VideoParser + __shared__ ResType smem[BIN_COUNT]; + + const int y = blockIdx.x * blockDim.y + threadIdx.y; + const int tid = threadIdx.y * blockDim.x + threadIdx.x; + + for (int i = tid; i < BIN_COUNT; i += BLOCK_SIZE) + smem[i] = 0; + + __syncthreads(); + + if (y < rows) { - public: - VideoParser(VideoDecoder* videoDecoder, FrameQueue* frameQueue); - - ~VideoParser() + for (int x = threadIdx.x; x < cols; x += blockDim.x) { - cuvidDestroyVideoParser(parser_); + if (mask(y, x)) + { + const uint data = src(y, x); + atomicAdd(&smem[data % BIN_COUNT], 1); + } } + } - bool parseVideoData(const unsigned char* data, size_t size, bool endOfStream); + __syncthreads(); - bool hasError() const { return hasError_; } - - private: - VideoParser(const VideoParser&); - VideoParser& operator =(const VideoParser&); - - VideoDecoder* videoDecoder_; - FrameQueue* frameQueue_; - CUvideoparser parser_; - int unparsedPackets_; - volatile bool hasError_; - - // Called when the decoder encounters a video format change (or initial sequence header) - // This particular implementation of the callback returns 0 in case the video format changes - // to something different than the original format. Returning 0 causes a stop of the app. - static int CUDAAPI HandleVideoSequence(void* pUserData, CUVIDEOFORMAT* pFormat); - - // Called by the video parser to decode a single picture - // Since the parser will deliver data as fast as it can, we need to make sure that the picture - // index we're attempting to use for decode is no longer used for display - static int CUDAAPI HandlePictureDecode(void* pUserData, CUVIDPICPARAMS* pPicParams); - - // Called by the video parser to display a video frame (in the case of field pictures, there may be - // 2 decode calls per 1 display call, since two fields make up one frame) - static int CUDAAPI HandlePictureDisplay(void* pUserData, CUVIDPARSERDISPINFO* pPicParams); - }; + for (int i = tid; i < BIN_COUNT; i += BLOCK_SIZE) + { + const ResType histVal = smem[i]; + if (histVal > 0) + atomicAdd(hist + i, histVal); + } } + + template + __host__ void histogram(const SrcPtr& src, ResType* hist, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + const dim3 block(Policy::block_size_x, Policy::block_size_y); + const dim3 grid(divUp(rows, block.y)); + + const int BLOCK_SIZE = Policy::block_size_x * Policy::block_size_y; + + histogram<<>>(src, hist, mask, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() ); + } +} + }} -#endif // HAVE_CUDA - -#endif // __VIDEO_PARSER_H__ +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/detail/integral.hpp b/modules/cudev/include/opencv2/cudev/grid/detail/integral.hpp new file mode 100644 index 0000000000..b06d7ddbb6 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/detail/integral.hpp @@ -0,0 +1,626 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_INTEGRAL_DETAIL_HPP__ +#define __OPENCV_CUDEV_GRID_INTEGRAL_DETAIL_HPP__ + +#include "../../common.hpp" +#include "../../warp/shuffle.hpp" +#include "../../block/scan.hpp" +#include "../../ptr2d/glob.hpp" + +namespace cv { namespace cudev { + +namespace integral_detail +{ + // horizontal_pass + + template + __global__ void horizontal_pass(const SrcPtr src, GlobPtr dst, const int cols) + { + __shared__ D smem[NUM_SCAN_THREADS * 2]; + __shared__ D carryElem; + + carryElem = 0; + + __syncthreads(); + + D* dst_row = dst.row(blockIdx.x); + + int numBuckets = divUp(cols, NUM_SCAN_THREADS); + int offsetX = 0; + + while (numBuckets--) + { + const int curElemOffs = offsetX + threadIdx.x; + + D curElem = 0.0f; + + if (curElemOffs < cols) + curElem = src(blockIdx.x, curElemOffs); + + const D curScanElem = blockScanInclusive(curElem, smem, threadIdx.x); + + if (curElemOffs < cols) + dst_row[curElemOffs] = carryElem + curScanElem; + + offsetX += NUM_SCAN_THREADS; + + __syncthreads(); + + if (threadIdx.x == NUM_SCAN_THREADS - 1) + { + carryElem += curScanElem; + } + + __syncthreads(); + } + } + + template + __global__ void horizontal_pass(const GlobPtr src, GlobPtr dst, const int cols) + { + __shared__ D smem[NUM_SCAN_THREADS * 2]; + __shared__ D carryElem; + + carryElem = 0; + + __syncthreads(); + + const T* src_row = src.row(blockIdx.x); + D* dst_row = dst.row(blockIdx.x); + + int numBuckets = divUp(cols, NUM_SCAN_THREADS); + int offsetX = 0; + + while (numBuckets--) + { + const int curElemOffs = offsetX + threadIdx.x; + + D curElem = 0.0f; + + if (curElemOffs < cols) + curElem = src_row[curElemOffs]; + + const D curScanElem = blockScanInclusive(curElem, smem, threadIdx.x); + + if (curElemOffs < cols) + dst_row[curElemOffs] = carryElem + curScanElem; + + offsetX += NUM_SCAN_THREADS; + + __syncthreads(); + + if (threadIdx.x == NUM_SCAN_THREADS - 1) + { + carryElem += curScanElem; + } + + __syncthreads(); + } + } + + template + __host__ void horizontal_pass(const SrcPtr& src, const GlobPtr& dst, int rows, int cols, cudaStream_t stream) + { + const int NUM_SCAN_THREADS = 256; + + const dim3 block(NUM_SCAN_THREADS); + const dim3 grid(rows); + + horizontal_pass<<>>(src, dst, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + } + + // horisontal_pass_8u_shfl + + __device__ static uchar4 int_to_uchar4(unsigned int in) + { + uchar4 bytes; + bytes.x = (in & 0x000000ff) >> 0; + bytes.y = (in & 0x0000ff00) >> 8; + bytes.z = (in & 0x00ff0000) >> 16; + bytes.w = (in & 0xff000000) >> 24; + return bytes; + } + + __global__ static void horisontal_pass_8u_shfl_kernel(const GlobPtr img, GlobPtr integral) + { + #if CV_CUDEV_ARCH >= 300 + __shared__ int sums[128]; + + const int id = threadIdx.x; + const int lane_id = id % warpSize; + const int warp_id = id / warpSize; + + const uint4 data = img(blockIdx.x, id); + + const uchar4 a = int_to_uchar4(data.x); + const uchar4 b = int_to_uchar4(data.y); + const uchar4 c = int_to_uchar4(data.z); + const uchar4 d = int_to_uchar4(data.w); + + int result[16]; + + result[0] = a.x; + result[1] = result[0] + a.y; + result[2] = result[1] + a.z; + result[3] = result[2] + a.w; + + result[4] = result[3] + b.x; + result[5] = result[4] + b.y; + result[6] = result[5] + b.z; + result[7] = result[6] + b.w; + + result[8] = result[7] + c.x; + result[9] = result[8] + c.y; + result[10] = result[9] + c.z; + result[11] = result[10] + c.w; + + result[12] = result[11] + d.x; + result[13] = result[12] + d.y; + result[14] = result[13] + d.z; + result[15] = result[14] + d.w; + + int sum = result[15]; + + // the prefix sum for each thread's 16 value is computed, + // now the final sums (result[15]) need to be shared + // with the other threads and add. To do this, + // the shfl_up() instruction is used and a shuffle scan + // operation is performed to distribute the sums to the correct + // threads + #pragma unroll + for (int i = 1; i < 32; i *= 2) + { + const int n = shfl_up(sum, i, 32); + + if (lane_id >= i) + { + #pragma unroll + for (int k = 0; k < 16; ++k) + result[k] += n; + + sum += n; + } + } + + // Now the final sum for the warp must be shared + // between warps. This is done by each warp + // having a thread store to shared memory, then + // having some other warp load the values and + // compute a prefix sum, again by using shfl_up. + // The results are uniformly added back to the warps. + // last thread in the warp holding sum of the warp + // places that in shared + if (threadIdx.x % warpSize == warpSize - 1) + sums[warp_id] = result[15]; + + __syncthreads(); + + if (warp_id == 0) + { + int warp_sum = sums[lane_id]; + + #pragma unroll + for (int i = 1; i <= 32; i *= 2) + { + const int n = shfl_up(warp_sum, i, 32); + + if (lane_id >= i) + warp_sum += n; + } + + sums[lane_id] = warp_sum; + } + + __syncthreads(); + + int blockSum = 0; + + // fold in unused warp + if (warp_id > 0) + { + blockSum = sums[warp_id - 1]; + + #pragma unroll + for (int k = 0; k < 16; ++k) + result[k] += blockSum; + } + + // assemble result + // Each thread has 16 values to write, which are + // now integer data (to avoid overflow). Instead of + // each thread writing consecutive uint4s, the + // approach shown here experiments using + // the shuffle command to reformat the data + // inside the registers so that each thread holds + // consecutive data to be written so larger contiguous + // segments can be assembled for writing. + + /* + For example data that needs to be written as + + GMEM[16] <- x0 x1 x2 x3 y0 y1 y2 y3 z0 z1 z2 z3 w0 w1 w2 w3 + but is stored in registers (r0..r3), in four threads (0..3) as: + + threadId 0 1 2 3 + r0 x0 y0 z0 w0 + r1 x1 y1 z1 w1 + r2 x2 y2 z2 w2 + r3 x3 y3 z3 w3 + + after apply shfl_xor operations to move data between registers r1..r3: + + threadId 00 01 10 11 + x0 y0 z0 w0 + xor(01)->y1 x1 w1 z1 + xor(10)->z2 w2 x2 y2 + xor(11)->w3 z3 y3 x3 + + and now x0..x3, and z0..z3 can be written out in order by all threads. + + In the current code, each register above is actually representing + four integers to be written as uint4's to GMEM. + */ + + result[4] = shfl_xor(result[4] , 1, 32); + result[5] = shfl_xor(result[5] , 1, 32); + result[6] = shfl_xor(result[6] , 1, 32); + result[7] = shfl_xor(result[7] , 1, 32); + + result[8] = shfl_xor(result[8] , 2, 32); + result[9] = shfl_xor(result[9] , 2, 32); + result[10] = shfl_xor(result[10], 2, 32); + result[11] = shfl_xor(result[11], 2, 32); + + result[12] = shfl_xor(result[12], 3, 32); + result[13] = shfl_xor(result[13], 3, 32); + result[14] = shfl_xor(result[14], 3, 32); + result[15] = shfl_xor(result[15], 3, 32); + + uint4* integral_row = integral.row(blockIdx.x); + uint4 output; + + /////// + + if (threadIdx.x % 4 == 0) + output = make_uint4(result[0], result[1], result[2], result[3]); + + if (threadIdx.x % 4 == 1) + output = make_uint4(result[4], result[5], result[6], result[7]); + + if (threadIdx.x % 4 == 2) + output = make_uint4(result[8], result[9], result[10], result[11]); + + if (threadIdx.x % 4 == 3) + output = make_uint4(result[12], result[13], result[14], result[15]); + + integral_row[threadIdx.x % 4 + (threadIdx.x / 4) * 16] = output; + + /////// + + if (threadIdx.x % 4 == 2) + output = make_uint4(result[0], result[1], result[2], result[3]); + + if (threadIdx.x % 4 == 3) + output = make_uint4(result[4], result[5], result[6], result[7]); + + if (threadIdx.x % 4 == 0) + output = make_uint4(result[8], result[9], result[10], result[11]); + + if (threadIdx.x % 4 == 1) + output = make_uint4(result[12], result[13], result[14], result[15]); + + integral_row[(threadIdx.x + 2) % 4 + (threadIdx.x / 4) * 16 + 8] = output; + + // continuning from the above example, + // this use of shfl_xor() places the y0..y3 and w0..w3 data + // in order. + + #pragma unroll + for (int i = 0; i < 16; ++i) + result[i] = shfl_xor(result[i], 1, 32); + + if (threadIdx.x % 4 == 0) + output = make_uint4(result[0], result[1], result[2], result[3]); + + if (threadIdx.x % 4 == 1) + output = make_uint4(result[4], result[5], result[6], result[7]); + + if (threadIdx.x % 4 == 2) + output = make_uint4(result[8], result[9], result[10], result[11]); + + if (threadIdx.x % 4 == 3) + output = make_uint4(result[12], result[13], result[14], result[15]); + + integral_row[threadIdx.x % 4 + (threadIdx.x / 4) * 16 + 4] = output; + + /////// + + if (threadIdx.x % 4 == 2) + output = make_uint4(result[0], result[1], result[2], result[3]); + + if (threadIdx.x % 4 == 3) + output = make_uint4(result[4], result[5], result[6], result[7]); + + if (threadIdx.x % 4 == 0) + output = make_uint4(result[8], result[9], result[10], result[11]); + + if (threadIdx.x % 4 == 1) + output = make_uint4(result[12], result[13], result[14], result[15]); + + integral_row[(threadIdx.x + 2) % 4 + (threadIdx.x / 4) * 16 + 12] = output; + #endif + } + + __host__ static void horisontal_pass_8u_shfl(const GlobPtr src, GlobPtr integral, int rows, int cols, cudaStream_t stream) + { + // each thread handles 16 values, use 1 block/row + // save, because step is actually can't be less 512 bytes + const int block = cols / 16; + + // launch 1 block / row + const int grid = rows; + + CV_CUDEV_SAFE_CALL( cudaFuncSetCacheConfig(horisontal_pass_8u_shfl_kernel, cudaFuncCachePreferL1) ); + + GlobPtr src4 = globPtr((uint4*) src.data, src.step); + GlobPtr integral4 = globPtr((uint4*) integral.data, integral.step); + + horisontal_pass_8u_shfl_kernel<<>>(src4, integral4); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + } + + // vertical + + template + __global__ void vertical_pass(GlobPtr integral, const int rows, const int cols) + { + #if CV_CUDEV_ARCH >= 300 + __shared__ T sums[32][9]; + + const int tidx = blockIdx.x * blockDim.x + threadIdx.x; + const int lane_id = tidx % 8; + + sums[threadIdx.x][threadIdx.y] = 0; + __syncthreads(); + + T stepSum = 0; + + int numBuckets = divUp(rows, blockDim.y); + int y = threadIdx.y; + + while (numBuckets--) + { + T* p = integral.row(y) + tidx; + + T sum = (tidx < cols) && (y < rows) ? *p : 0; + + y += blockDim.y; + + sums[threadIdx.x][threadIdx.y] = sum; + __syncthreads(); + + // place into SMEM + // shfl scan reduce the SMEM, reformating so the column + // sums are computed in a warp + // then read out properly + const int j = threadIdx.x % 8; + const int k = threadIdx.x / 8 + threadIdx.y * 4; + + T partial_sum = sums[k][j]; + + for (int i = 1; i <= 8; i *= 2) + { + T n = shfl_up(partial_sum, i, 32); + + if (lane_id >= i) + partial_sum += n; + } + + sums[k][j] = partial_sum; + __syncthreads(); + + if (threadIdx.y > 0) + sum += sums[threadIdx.x][threadIdx.y - 1]; + + if (tidx < cols) + { + sum += stepSum; + stepSum += sums[threadIdx.x][blockDim.y - 1]; + *p = sum; + } + + __syncthreads(); + } + #else + __shared__ T smem[32][32]; + __shared__ T prevVals[32]; + + volatile T* smem_row = &smem[0][0] + 64 * threadIdx.y; + + if (threadIdx.y == 0) + prevVals[threadIdx.x] = 0; + + __syncthreads(); + + const int x = blockIdx.x * blockDim.x + threadIdx.x; + + int numBuckets = divUp(rows, 8 * 4); + int offsetY = 0; + + while (numBuckets--) + { + const int curRowOffs = offsetY + threadIdx.y; + + T curElems[4]; + T temp[4]; + + // load patch + + smem[threadIdx.y + 0][threadIdx.x] = 0.0f; + smem[threadIdx.y + 8][threadIdx.x] = 0.0f; + smem[threadIdx.y + 16][threadIdx.x] = 0.0f; + smem[threadIdx.y + 24][threadIdx.x] = 0.0f; + + if (x < cols) + { + for (int i = 0; i < 4; ++i) + { + if (curRowOffs + i * 8 < rows) + smem[threadIdx.y + i * 8][threadIdx.x] = integral(curRowOffs + i * 8, x); + } + } + + __syncthreads(); + + // reduce + + curElems[0] = smem[threadIdx.x][threadIdx.y ]; + curElems[1] = smem[threadIdx.x][threadIdx.y + 8]; + curElems[2] = smem[threadIdx.x][threadIdx.y + 16]; + curElems[3] = smem[threadIdx.x][threadIdx.y + 24]; + + __syncthreads(); + + temp[0] = curElems[0] = warpScanInclusive(curElems[0], smem_row, threadIdx.x); + temp[1] = curElems[1] = warpScanInclusive(curElems[1], smem_row, threadIdx.x); + temp[2] = curElems[2] = warpScanInclusive(curElems[2], smem_row, threadIdx.x); + temp[3] = curElems[3] = warpScanInclusive(curElems[3], smem_row, threadIdx.x); + + curElems[0] += prevVals[threadIdx.y ]; + curElems[1] += prevVals[threadIdx.y + 8]; + curElems[2] += prevVals[threadIdx.y + 16]; + curElems[3] += prevVals[threadIdx.y + 24]; + + __syncthreads(); + + if (threadIdx.x == 31) + { + prevVals[threadIdx.y ] += temp[0]; + prevVals[threadIdx.y + 8] += temp[1]; + prevVals[threadIdx.y + 16] += temp[2]; + prevVals[threadIdx.y + 24] += temp[3]; + } + + smem[threadIdx.y ][threadIdx.x] = curElems[0]; + smem[threadIdx.y + 8][threadIdx.x] = curElems[1]; + smem[threadIdx.y + 16][threadIdx.x] = curElems[2]; + smem[threadIdx.y + 24][threadIdx.x] = curElems[3]; + + __syncthreads(); + + // store patch + + if (x < cols) + { + // read 4 value from source + for (int i = 0; i < 4; ++i) + { + if (curRowOffs + i * 8 < rows) + integral(curRowOffs + i * 8, x) = smem[threadIdx.x][threadIdx.y + i * 8]; + } + } + + __syncthreads(); + + offsetY += 8 * 4; + } + #endif + } + + template + __host__ void vertical_pass(const GlobPtr& integral, int rows, int cols, cudaStream_t stream) + { + const dim3 block(32, 8); + const dim3 grid(divUp(cols, block.x)); + + vertical_pass<<>>(integral, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + } + + // integral + + template + __host__ void integral(const SrcPtr& src, const GlobPtr& dst, int rows, int cols, cudaStream_t stream) + { + horizontal_pass(src, dst, rows, cols, stream); + vertical_pass(dst, rows, cols, stream); + + if (stream == 0) + CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() ); + } + + __host__ static void integral(const GlobPtr src, GlobPtr dst, int rows, int cols, cudaStream_t stream) + { + if (deviceSupports(FEATURE_SET_COMPUTE_30) + && (cols % 16 == 0) + && reinterpret_cast(src.data) % 32 == 0 + && reinterpret_cast(dst.data) % 32 == 0) + { + horisontal_pass_8u_shfl(src, dst, rows, cols, stream); + } + else + { + horizontal_pass(src, dst, rows, cols, stream); + } + + vertical_pass(dst, rows, cols, stream); + + if (stream == 0) + CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() ); + } + + __host__ static void integral(const GlobPtr src, GlobPtr dst, int rows, int cols, cudaStream_t stream) + { + GlobPtr dstui = globPtr((uint*) dst.data, dst.step); + integral(src, dstui, rows, cols, stream); + } +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/detail/pyr_down.hpp b/modules/cudev/include/opencv2/cudev/grid/detail/pyr_down.hpp new file mode 100644 index 0000000000..b14792cf4e --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/detail/pyr_down.hpp @@ -0,0 +1,201 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_PYR_DOWN_DETAIL_HPP__ +#define __OPENCV_CUDEV_GRID_PYR_DOWN_DETAIL_HPP__ + +#include "../../common.hpp" +#include "../../util/vec_traits.hpp" +#include "../../util/saturate_cast.hpp" +#include "../../util/type_traits.hpp" +#include "../../ptr2d/glob.hpp" +#include "../../ptr2d/traits.hpp" + +namespace cv { namespace cudev { + +namespace pyramids_detail +{ + template + __global__ void pyrDown(const SrcPtr src, GlobPtr dst, const int src_rows, const int src_cols, const int dst_cols) + { + typedef typename PtrTraits::value_type src_type; + typedef typename VecTraits::elem_type src_elem_type; + typedef typename LargerType::type work_elem_type; + typedef typename MakeVec::cn>::type work_type; + + __shared__ work_type smem[256 + 4]; + + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y; + + const int src_y = 2 * y; + + if (src_y >= 2 && src_y < src_rows - 2 && x >= 2 && x < src_cols - 2) + { + { + work_type sum; + + sum = 0.0625f * src(src_y - 2, x); + sum = sum + 0.25f * src(src_y - 1, x); + sum = sum + 0.375f * src(src_y , x); + sum = sum + 0.25f * src(src_y + 1, x); + sum = sum + 0.0625f * src(src_y + 2, x); + + smem[2 + threadIdx.x] = sum; + } + + if (threadIdx.x < 2) + { + const int left_x = x - 2; + + work_type sum; + + sum = 0.0625f * src(src_y - 2, left_x); + sum = sum + 0.25f * src(src_y - 1, left_x); + sum = sum + 0.375f * src(src_y , left_x); + sum = sum + 0.25f * src(src_y + 1, left_x); + sum = sum + 0.0625f * src(src_y + 2, left_x); + + smem[threadIdx.x] = sum; + } + + if (threadIdx.x > 253) + { + const int right_x = x + 2; + + work_type sum; + + sum = 0.0625f * src(src_y - 2, right_x); + sum = sum + 0.25f * src(src_y - 1, right_x); + sum = sum + 0.375f * src(src_y , right_x); + sum = sum + 0.25f * src(src_y + 1, right_x); + sum = sum + 0.0625f * src(src_y + 2, right_x); + + smem[4 + threadIdx.x] = sum; + } + } + else + { + { + work_type sum; + + sum = 0.0625f * src(Brd::idx_low(src_y - 2, src_rows) , Brd::idx_high(x, src_cols)); + sum = sum + 0.25f * src(Brd::idx_low(src_y - 1, src_rows) , Brd::idx_high(x, src_cols)); + sum = sum + 0.375f * src(src_y , Brd::idx_high(x, src_cols)); + sum = sum + 0.25f * src(Brd::idx_high(src_y + 1, src_rows), Brd::idx_high(x, src_cols)); + sum = sum + 0.0625f * src(Brd::idx_high(src_y + 2, src_rows), Brd::idx_high(x, src_cols)); + + smem[2 + threadIdx.x] = sum; + } + + if (threadIdx.x < 2) + { + const int left_x = x - 2; + + work_type sum; + + sum = 0.0625f * src(Brd::idx_low(src_y - 2, src_rows) , Brd::idx_low(Brd::idx_high(left_x, src_cols), src_cols)); + sum = sum + 0.25f * src(Brd::idx_low(src_y - 1, src_rows) , Brd::idx_low(Brd::idx_high(left_x, src_cols), src_cols)); + sum = sum + 0.375f * src(src_y , Brd::idx_low(Brd::idx_high(left_x, src_cols), src_cols)); + sum = sum + 0.25f * src(Brd::idx_high(src_y + 1, src_rows), Brd::idx_low(Brd::idx_high(left_x, src_cols), src_cols)); + sum = sum + 0.0625f * src(Brd::idx_high(src_y + 2, src_rows), Brd::idx_low(Brd::idx_high(left_x, src_cols), src_cols)); + + smem[threadIdx.x] = sum; + } + + if (threadIdx.x > 253) + { + const int right_x = x + 2; + + work_type sum; + + sum = 0.0625f * src(Brd::idx_low(src_y - 2, src_rows) , Brd::idx_high(right_x, src_cols)); + sum = sum + 0.25f * src(Brd::idx_low(src_y - 1, src_rows) , Brd::idx_high(right_x, src_cols)); + sum = sum + 0.375f * src(src_y , Brd::idx_high(right_x, src_cols)); + sum = sum + 0.25f * src(Brd::idx_high(src_y + 1, src_rows), Brd::idx_high(right_x, src_cols)); + sum = sum + 0.0625f * src(Brd::idx_high(src_y + 2, src_rows), Brd::idx_high(right_x, src_cols)); + + smem[4 + threadIdx.x] = sum; + } + } + + __syncthreads(); + + if (threadIdx.x < 128) + { + const int tid2 = threadIdx.x * 2; + + work_type sum; + + sum = 0.0625f * smem[2 + tid2 - 2]; + sum = sum + 0.25f * smem[2 + tid2 - 1]; + sum = sum + 0.375f * smem[2 + tid2 ]; + sum = sum + 0.25f * smem[2 + tid2 + 1]; + sum = sum + 0.0625f * smem[2 + tid2 + 2]; + + const int dst_x = (blockIdx.x * blockDim.x + tid2) / 2; + + if (dst_x < dst_cols) + dst(y, dst_x) = saturate_cast(sum); + } + } + + template + __host__ void pyrDown(const SrcPtr& src, const GlobPtr& dst, int src_rows, int src_cols, int dst_rows, int dst_cols, cudaStream_t stream) + { + const dim3 block(256); + const dim3 grid(divUp(src_cols, block.x), dst_rows); + + pyrDown<<>>(src, dst, src_rows, src_cols, dst_cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() ); + } +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/detail/pyr_up.hpp b/modules/cudev/include/opencv2/cudev/grid/detail/pyr_up.hpp new file mode 100644 index 0000000000..16c8b2091e --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/detail/pyr_up.hpp @@ -0,0 +1,172 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_PYR_UP_DETAIL_HPP__ +#define __OPENCV_CUDEV_GRID_PYR_UP_DETAIL_HPP__ + +#include "../../common.hpp" +#include "../../util/vec_traits.hpp" +#include "../../util/saturate_cast.hpp" +#include "../../util/type_traits.hpp" +#include "../../ptr2d/glob.hpp" +#include "../../ptr2d/traits.hpp" + +namespace cv { namespace cudev { + +namespace pyramids_detail +{ + template + __global__ void pyrUp(const SrcPtr src, GlobPtr dst, const int src_rows, const int src_cols, const int dst_rows, const int dst_cols) + { + typedef typename PtrTraits::value_type src_type; + typedef typename VecTraits::elem_type src_elem_type; + typedef typename LargerType::type work_elem_type; + typedef typename MakeVec::cn>::type work_type; + + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + __shared__ work_type s_srcPatch[10][10]; + __shared__ work_type s_dstPatch[20][16]; + + if (threadIdx.x < 10 && threadIdx.y < 10) + { + int srcx = static_cast((blockIdx.x * blockDim.x) / 2 + threadIdx.x) - 1; + int srcy = static_cast((blockIdx.y * blockDim.y) / 2 + threadIdx.y) - 1; + + srcx = ::abs(srcx); + srcx = ::min(src_cols - 1, srcx); + + srcy = ::abs(srcy); + srcy = ::min(src_rows - 1, srcy); + + s_srcPatch[threadIdx.y][threadIdx.x] = saturate_cast(src(srcy, srcx)); + } + + __syncthreads(); + + work_type sum = VecTraits::all(0); + + const int evenFlag = static_cast((threadIdx.x & 1) == 0); + const int oddFlag = static_cast((threadIdx.x & 1) != 0); + const bool eveny = ((threadIdx.y & 1) == 0); + const int tidx = threadIdx.x; + + if (eveny) + { + sum = sum + (evenFlag * 0.0625f) * s_srcPatch[1 + (threadIdx.y >> 1)][1 + ((tidx - 2) >> 1)]; + sum = sum + ( oddFlag * 0.25f ) * s_srcPatch[1 + (threadIdx.y >> 1)][1 + ((tidx - 1) >> 1)]; + sum = sum + (evenFlag * 0.375f ) * s_srcPatch[1 + (threadIdx.y >> 1)][1 + ((tidx ) >> 1)]; + sum = sum + ( oddFlag * 0.25f ) * s_srcPatch[1 + (threadIdx.y >> 1)][1 + ((tidx + 1) >> 1)]; + sum = sum + (evenFlag * 0.0625f) * s_srcPatch[1 + (threadIdx.y >> 1)][1 + ((tidx + 2) >> 1)]; + } + + s_dstPatch[2 + threadIdx.y][threadIdx.x] = sum; + + if (threadIdx.y < 2) + { + sum = VecTraits::all(0); + + if (eveny) + { + sum = sum + (evenFlag * 0.0625f) * s_srcPatch[0][1 + ((tidx - 2) >> 1)]; + sum = sum + ( oddFlag * 0.25f ) * s_srcPatch[0][1 + ((tidx - 1) >> 1)]; + sum = sum + (evenFlag * 0.375f ) * s_srcPatch[0][1 + ((tidx ) >> 1)]; + sum = sum + ( oddFlag * 0.25f ) * s_srcPatch[0][1 + ((tidx + 1) >> 1)]; + sum = sum + (evenFlag * 0.0625f) * s_srcPatch[0][1 + ((tidx + 2) >> 1)]; + } + + s_dstPatch[threadIdx.y][threadIdx.x] = sum; + } + + if (threadIdx.y > 13) + { + sum = VecTraits::all(0); + + if (eveny) + { + sum = sum + (evenFlag * 0.0625f) * s_srcPatch[9][1 + ((tidx - 2) >> 1)]; + sum = sum + ( oddFlag * 0.25f ) * s_srcPatch[9][1 + ((tidx - 1) >> 1)]; + sum = sum + (evenFlag * 0.375f ) * s_srcPatch[9][1 + ((tidx ) >> 1)]; + sum = sum + ( oddFlag * 0.25f ) * s_srcPatch[9][1 + ((tidx + 1) >> 1)]; + sum = sum + (evenFlag * 0.0625f) * s_srcPatch[9][1 + ((tidx + 2) >> 1)]; + } + + s_dstPatch[4 + threadIdx.y][threadIdx.x] = sum; + } + + __syncthreads(); + + sum = VecTraits::all(0); + + const int tidy = threadIdx.y; + + sum = sum + 0.0625f * s_dstPatch[2 + tidy - 2][threadIdx.x]; + sum = sum + 0.25f * s_dstPatch[2 + tidy - 1][threadIdx.x]; + sum = sum + 0.375f * s_dstPatch[2 + tidy ][threadIdx.x]; + sum = sum + 0.25f * s_dstPatch[2 + tidy + 1][threadIdx.x]; + sum = sum + 0.0625f * s_dstPatch[2 + tidy + 2][threadIdx.x]; + + if (x < dst_cols && y < dst_rows) + dst(y, x) = saturate_cast(4.0f * sum); + } + + template + __host__ void pyrUp(const SrcPtr& src, const GlobPtr& dst, int src_rows, int src_cols, int dst_rows, int dst_cols, cudaStream_t stream) + { + const dim3 block(16, 16); + const dim3 grid(divUp(dst_cols, block.x), divUp(dst_rows, block.y)); + + pyrUp<<>>(src, dst, src_rows, src_cols, dst_rows, dst_cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() ); + } +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/detail/reduce_to_column.hpp b/modules/cudev/include/opencv2/cudev/grid/detail/reduce_to_column.hpp new file mode 100644 index 0000000000..b257e75039 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/detail/reduce_to_column.hpp @@ -0,0 +1,106 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_REDUCE_TO_COLUMN_DETAIL_HPP__ +#define __OPENCV_CUDEV_GRID_REDUCE_TO_COLUMN_DETAIL_HPP__ + +#include "../../common.hpp" +#include "../../util/saturate_cast.hpp" +#include "../../block/reduce.hpp" + +namespace cv { namespace cudev { + +namespace grid_reduce_to_vec_detail +{ + template + __global__ void reduceToColumn(const SrcPtr src, ResType* dst, const MaskPtr mask, const int cols) + { + typedef typename Reductor::work_type work_type; + + __shared__ work_type smem[BLOCK_SIZE]; + + const int y = blockIdx.x; + + work_type myVal = Reductor::initialValue(); + + Reductor op; + + for (int x = threadIdx.x; x < cols; x += BLOCK_SIZE) + { + if (mask(y, x)) + { + myVal = op(myVal, saturate_cast(src(y, x))); + } + } + + blockReduce(smem, myVal, threadIdx.x, op); + + if (threadIdx.x == 0) + dst[y] = saturate_cast(Reductor::result(myVal, cols)); + } + + template + __host__ void reduceToColumn(const SrcPtr& src, ResType* dst, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + const int BLOCK_SIZE_X = Policy::block_size_x; + const int BLOCK_SIZE_Y = Policy::block_size_y; + + const int BLOCK_SIZE = BLOCK_SIZE_X * BLOCK_SIZE_Y; + + const dim3 block(BLOCK_SIZE); + const dim3 grid(rows); + + reduceToColumn<<>>(src, dst, mask, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() ); + + } +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/detail/reduce_to_row.hpp b/modules/cudev/include/opencv2/cudev/grid/detail/reduce_to_row.hpp new file mode 100644 index 0000000000..154004f6e4 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/detail/reduce_to_row.hpp @@ -0,0 +1,118 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_REDUCE_TO_ROW_DETAIL_HPP__ +#define __OPENCV_CUDEV_GRID_REDUCE_TO_ROW_DETAIL_HPP__ + +#include "../../common.hpp" +#include "../../util/saturate_cast.hpp" +#include "../../block/reduce.hpp" + +namespace cv { namespace cudev { + +namespace grid_reduce_to_vec_detail +{ + template + __global__ void reduceToRow(const SrcPtr src, ResType* dst, const MaskPtr mask, const int rows, const int cols) + { + typedef typename Reductor::work_type work_type; + + __shared__ work_type smem[BLOCK_SIZE_X * BLOCK_SIZE_Y]; + + const int x = blockIdx.x * BLOCK_SIZE_X + threadIdx.x; + + work_type myVal = Reductor::initialValue(); + + Reductor op; + + if (x < cols) + { + for (int y = threadIdx.y; y < rows; y += BLOCK_SIZE_Y) + { + if (mask(y, x)) + { + myVal = op(myVal, saturate_cast(src(y, x))); + } + } + } + + smem[threadIdx.x * BLOCK_SIZE_Y + threadIdx.y] = myVal; + + __syncthreads(); + + volatile work_type* srow = smem + threadIdx.y * BLOCK_SIZE_X; + + myVal = srow[threadIdx.x]; + blockReduce(srow, myVal, threadIdx.x, op); + + if (threadIdx.x == 0) + srow[0] = myVal; + + __syncthreads(); + + if (threadIdx.y == 0 && x < cols) + dst[x] = saturate_cast(Reductor::result(smem[threadIdx.x * BLOCK_SIZE_X], rows)); + } + + template + __host__ void reduceToRow(const SrcPtr& src, ResType* dst, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + const int BLOCK_SIZE_X = 16; + const int BLOCK_SIZE_Y = 16; + + const dim3 block(BLOCK_SIZE_X, BLOCK_SIZE_Y); + const dim3 grid(divUp(cols, block.x)); + + reduceToRow<<>>(src, dst, mask, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() ); + } +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/detail/split_merge.hpp b/modules/cudev/include/opencv2/cudev/grid/detail/split_merge.hpp new file mode 100644 index 0000000000..0bd76ac464 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/detail/split_merge.hpp @@ -0,0 +1,282 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_SPLIT_MERGE_DETAIL_HPP__ +#define __OPENCV_CUDEV_GRID_SPLIT_MERGE_DETAIL_HPP__ + +#include "../../common.hpp" +#include "../../util/saturate_cast.hpp" +#include "../../util/tuple.hpp" +#include "../../util/vec_traits.hpp" +#include "../../ptr2d/glob.hpp" +#include "../../ptr2d/traits.hpp" + +namespace cv { namespace cudev { + +namespace grid_split_merge_detail +{ + // merge + + template + __global__ void mergeC2(const Src1Ptr src1, const Src2Ptr src2, GlobPtr dst, const MaskPtr mask, const int rows, const int cols) + { + typedef typename VecTraits::elem_type dst_elem_type; + + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (x >= cols || y >= rows || !mask(y, x)) + return; + + dst(y, x) = VecTraits::make( + saturate_cast(src1(y, x)), + saturate_cast(src2(y, x)) + ); + } + + template + __host__ void mergeC2(const Src1Ptr& src1, const Src2Ptr& src2, const GlobPtr& dst, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + const dim3 block(Policy::block_size_x, Policy::block_size_y); + const dim3 grid(divUp(cols, block.x), divUp(rows, block.y)); + + mergeC2<<>>(src1, src2, dst, mask, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL(cudaDeviceSynchronize()); + } + + template + __global__ void mergeC3(const Src1Ptr src1, const Src2Ptr src2, const Src3Ptr src3, GlobPtr dst, const MaskPtr mask, const int rows, const int cols) + { + typedef typename VecTraits::elem_type dst_elem_type; + + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (x >= cols || y >= rows || !mask(y, x)) + return; + + dst(y, x) = VecTraits::make( + saturate_cast(src1(y, x)), + saturate_cast(src2(y, x)), + saturate_cast(src3(y, x)) + ); + } + + template + __host__ void mergeC3(const Src1Ptr& src1, const Src2Ptr& src2, const Src3Ptr& src3, const GlobPtr& dst, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + const dim3 block(Policy::block_size_x, Policy::block_size_y); + const dim3 grid(divUp(cols, block.x), divUp(rows, block.y)); + + mergeC3<<>>(src1, src2, src3, dst, mask, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL(cudaDeviceSynchronize()); + } + + template + __global__ void mergeC4(const Src1Ptr src1, const Src2Ptr src2, const Src3Ptr src3, const Src4Ptr src4, GlobPtr dst, const MaskPtr mask, const int rows, const int cols) + { + typedef typename VecTraits::elem_type dst_elem_type; + + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (x >= cols || y >= rows || !mask(y, x)) + return; + + dst(y, x) = VecTraits::make( + saturate_cast(src1(y, x)), + saturate_cast(src2(y, x)), + saturate_cast(src3(y, x)), + saturate_cast(src4(y, x)) + ); + } + + template + __host__ void mergeC4(const Src1Ptr& src1, const Src2Ptr& src2, const Src3Ptr& src3, const Src4Ptr& src4, const GlobPtr& dst, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + const dim3 block(Policy::block_size_x, Policy::block_size_y); + const dim3 grid(divUp(cols, block.x), divUp(rows, block.y)); + + mergeC4<<>>(src1, src2, src3, src4, dst, mask, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL(cudaDeviceSynchronize()); + } + + template struct MergeImpl; + + template struct MergeImpl<2, Policy> + { + template + __host__ static void merge(const SrcPtrTuple& src, const GlobPtr& dst, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + mergeC2(get<0>(src), get<1>(src), dst, mask, rows, cols, stream); + } + }; + + template struct MergeImpl<3, Policy> + { + template + __host__ static void merge(const SrcPtrTuple& src, const GlobPtr& dst, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + mergeC3(get<0>(src), get<1>(src), get<2>(src), dst, mask, rows, cols, stream); + } + }; + + template struct MergeImpl<4, Policy> + { + template + __host__ static void merge(const SrcPtrTuple& src, const GlobPtr& dst, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + mergeC4(get<0>(src), get<1>(src), get<2>(src), get<3>(src), dst, mask, rows, cols, stream); + } + }; + + // split + + template + __global__ void split(const SrcPtr src, GlobPtr dst1, GlobPtr dst2, const MaskPtr mask, const int rows, const int cols) + { + typedef typename PtrTraits::value_type src_type; + + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (x >= cols || y >= rows || !mask(y, x)) + return; + + const src_type src_value = src(y, x); + + dst1(y, x) = src_value.x; + dst2(y, x) = src_value.y; + } + + template + __host__ void split(const SrcPtr& src, const GlobPtr& dst1, const GlobPtr& dst2, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + const dim3 block(Policy::block_size_x, Policy::block_size_y); + const dim3 grid(divUp(cols, block.x), divUp(rows, block.y)); + + split<<>>(src, dst1, dst2, mask, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL(cudaDeviceSynchronize()); + } + + template + __global__ void split(const SrcPtr src, GlobPtr dst1, GlobPtr dst2, GlobPtr dst3, const MaskPtr mask, const int rows, const int cols) + { + typedef typename PtrTraits::value_type src_type; + + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (x >= cols || y >= rows || !mask(y, x)) + return; + + const src_type src_value = src(y, x); + + dst1(y, x) = src_value.x; + dst2(y, x) = src_value.y; + dst3(y, x) = src_value.z; + } + + template + __host__ void split(const SrcPtr& src, const GlobPtr& dst1, const GlobPtr& dst2, const GlobPtr& dst3, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + const dim3 block(Policy::block_size_x, Policy::block_size_y); + const dim3 grid(divUp(cols, block.x), divUp(rows, block.y)); + + split<<>>(src, dst1, dst2, dst3, mask, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL(cudaDeviceSynchronize()); + } + + template + __global__ void split(const SrcPtr src, GlobPtr dst1, GlobPtr dst2, GlobPtr dst3, GlobPtr dst4, const MaskPtr mask, const int rows, const int cols) + { + typedef typename PtrTraits::value_type src_type; + + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (x >= cols || y >= rows || !mask(y, x)) + return; + + const src_type src_value = src(y, x); + + dst1(y, x) = src_value.x; + dst2(y, x) = src_value.y; + dst3(y, x) = src_value.z; + dst4(y, x) = src_value.w; + } + + template + __host__ void split(const SrcPtr& src, const GlobPtr& dst1, const GlobPtr& dst2, const GlobPtr& dst3, const GlobPtr& dst4, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + const dim3 block(Policy::block_size_x, Policy::block_size_y); + const dim3 grid(divUp(cols, block.x), divUp(rows, block.y)); + + split<<>>(src, dst1, dst2, dst3, dst4, mask, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL(cudaDeviceSynchronize()); + } +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/detail/transform.hpp b/modules/cudev/include/opencv2/cudev/grid/detail/transform.hpp new file mode 100644 index 0000000000..0e0df0794a --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/detail/transform.hpp @@ -0,0 +1,423 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_TRANSFORM_DETAIL_HPP__ +#define __OPENCV_CUDEV_GRID_TRANSFORM_DETAIL_HPP__ + +#include "../../common.hpp" +#include "../../util/tuple.hpp" +#include "../../util/saturate_cast.hpp" +#include "../../util/vec_traits.hpp" +#include "../../ptr2d/glob.hpp" +#include "../../ptr2d/traits.hpp" + +namespace cv { namespace cudev { + +namespace grid_transform_detail +{ + // OpUnroller + + template struct OpUnroller; + + template <> struct OpUnroller<1> + { + template + __device__ __forceinline__ static void unroll(const T& src, D& dst, const UnOp& op, const MaskPtr& mask, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.x = op(src.x); + } + + template + __device__ __forceinline__ static void unroll(const T1& src1, const T2& src2, D& dst, const BinOp& op, const MaskPtr& mask, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.x = op(src1.x, src2.x); + } + }; + + template <> struct OpUnroller<2> + { + template + __device__ __forceinline__ static void unroll(const T& src, D& dst, const UnOp& op, const MaskPtr& mask, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.x = op(src.x); + if (mask(y, x_shifted + 1)) + dst.y = op(src.y); + } + + template + __device__ __forceinline__ static void unroll(const T1& src1, const T2& src2, D& dst, const BinOp& op, const MaskPtr& mask, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.x = op(src1.x, src2.x); + if (mask(y, x_shifted + 1)) + dst.y = op(src1.y, src2.y); + } + }; + + template <> struct OpUnroller<3> + { + template + __device__ __forceinline__ static void unroll(const T& src, D& dst, const UnOp& op, const MaskPtr& mask, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.x = op(src.x); + if (mask(y, x_shifted + 1)) + dst.y = op(src.y); + if (mask(y, x_shifted + 2)) + dst.z = op(src.z); + } + + template + __device__ __forceinline__ static void unroll(const T1& src1, const T2& src2, D& dst, const BinOp& op, const MaskPtr& mask, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.x = op(src1.x, src2.x); + if (mask(y, x_shifted + 1)) + dst.y = op(src1.y, src2.y); + if (mask(y, x_shifted + 2)) + dst.z = op(src1.z, src2.z); + } + }; + + template <> struct OpUnroller<4> + { + template + __device__ __forceinline__ static void unroll(const T& src, D& dst, const UnOp& op, const MaskPtr& mask, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.x = op(src.x); + if (mask(y, x_shifted + 1)) + dst.y = op(src.y); + if (mask(y, x_shifted + 2)) + dst.z = op(src.z); + if (mask(y, x_shifted + 3)) + dst.w = op(src.w); + } + + template + __device__ __forceinline__ static void unroll(const T1& src1, const T2& src2, D& dst, const BinOp& op, const MaskPtr& mask, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.x = op(src1.x, src2.x); + if (mask(y, x_shifted + 1)) + dst.y = op(src1.y, src2.y); + if (mask(y, x_shifted + 2)) + dst.z = op(src1.z, src2.z); + if (mask(y, x_shifted + 3)) + dst.w = op(src1.w, src2.w); + } + }; + + // transformSimple + + template + __global__ void transformSimple(const SrcPtr src, GlobPtr dst, const UnOp op, const MaskPtr mask, const int rows, const int cols) + { + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (x >= cols || y >= rows || !mask(y, x)) + return; + + dst(y, x) = saturate_cast(op(src(y, x))); + } + + template + __global__ void transformSimple(const SrcPtr1 src1, const SrcPtr2 src2, GlobPtr dst, const BinOp op, const MaskPtr mask, const int rows, const int cols) + { + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (x >= cols || y >= rows || !mask(y, x)) + return; + + dst(y, x) = saturate_cast(op(src1(y, x), src2(y, x))); + } + + // transformSmart + + template + __global__ void transformSmart(const GlobPtr src_, GlobPtr dst_, const UnOp op, const MaskPtr mask, const int rows, const int cols) + { + typedef typename MakeVec::type read_type; + typedef typename MakeVec::type write_type; + + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + const int x_shifted = x * SHIFT; + + if (y < rows) + { + const SrcType* src = src_.row(y); + DstType* dst = dst_.row(y); + + if (x_shifted + SHIFT - 1 < cols) + { + const read_type src_n_el = ((const read_type*)src)[x]; + write_type dst_n_el = ((const write_type*)dst)[x]; + + OpUnroller::unroll(src_n_el, dst_n_el, op, mask, x_shifted, y); + + ((write_type*)dst)[x] = dst_n_el; + } + else + { + for (int real_x = x_shifted; real_x < cols; ++real_x) + { + if (mask(y, real_x)) + dst[real_x] = op(src[real_x]); + } + } + } + } + + template + __global__ void transformSmart(const GlobPtr src1_, const GlobPtr src2_, PtrStep dst_, const BinOp op, const MaskPtr mask, const int rows, const int cols) + { + typedef typename MakeVec::type read_type1; + typedef typename MakeVec::type read_type2; + typedef typename MakeVec::type write_type; + + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + const int x_shifted = x * SHIFT; + + if (y < rows) + { + const SrcType1* src1 = src1_.row(y); + const SrcType2* src2 = src2_.row(y); + DstType* dst = dst_.row(y); + + if (x_shifted + SHIFT - 1 < cols) + { + const read_type1 src1_n_el = ((const read_type1*)src1)[x]; + const read_type2 src2_n_el = ((const read_type2*)src2)[x]; + write_type dst_n_el = ((const write_type*)dst)[x]; + + OpUnroller::unroll(src1_n_el, src2_n_el, dst_n_el, op, mask, x_shifted, y); + + ((write_type*)dst)[x] = dst_n_el; + } + else + { + for (int real_x = x_shifted; real_x < cols; ++real_x) + { + if (mask(y, real_x)) + dst[real_x] = op(src1[real_x], src2[real_x]); + } + } + } + } + + // TransformDispatcher + + template struct TransformDispatcher; + + template struct TransformDispatcher + { + template + __host__ static void call(const SrcPtr& src, const GlobPtr& dst, const UnOp& op, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + const dim3 block(Policy::block_size_x, Policy::block_size_y); + const dim3 grid(divUp(cols, block.x), divUp(rows, block.y)); + + transformSimple<<>>(src, dst, op, mask, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() ); + } + + template + __host__ static void call(const SrcPtr1& src1, const SrcPtr2& src2, const GlobPtr& dst, const BinOp& op, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + const dim3 block(Policy::block_size_x, Policy::block_size_y); + const dim3 grid(divUp(cols, block.x), divUp(rows, block.y)); + + transformSimple<<>>(src1, src2, dst, op, mask, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() ); + } + }; + + template struct TransformDispatcher + { + template + __host__ static bool isAligned(const T* ptr, size_t size) + { + return reinterpret_cast(ptr) % size == 0; + } + + __host__ static bool isAligned(size_t step, size_t size) + { + return step % size == 0; + } + + template + __host__ static void call(const GlobPtr& src, const GlobPtr& dst, const UnOp& op, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + if (Policy::shift == 1 || + !isAligned(src.data, Policy::shift * sizeof(SrcType)) || !isAligned(src.step, Policy::shift * sizeof(SrcType)) || + !isAligned(dst.data, Policy::shift * sizeof(DstType)) || !isAligned(dst.step, Policy::shift * sizeof(DstType))) + { + TransformDispatcher::call(src, dst, op, mask, rows, cols, stream); + return; + } + + const dim3 block(Policy::block_size_x, Policy::block_size_y); + const dim3 grid(divUp(cols, block.x * Policy::shift), divUp(rows, block.y)); + + transformSmart<<>>(src, dst, op, mask, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() ); + } + + template + __host__ static void call(const GlobPtr& src1, const GlobPtr& src2, const GlobPtr& dst, const BinOp& op, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + if (Policy::shift == 1 || + !isAligned(src1.data, Policy::shift * sizeof(SrcType1)) || !isAligned(src1.step, Policy::shift * sizeof(SrcType1)) || + !isAligned(src2.data, Policy::shift * sizeof(SrcType2)) || !isAligned(src2.step, Policy::shift * sizeof(SrcType2)) || + !isAligned(dst.data, Policy::shift * sizeof(DstType)) || !isAligned(dst.step, Policy::shift * sizeof(DstType))) + { + TransformDispatcher::call(src1, src2, dst, op, mask, rows, cols, stream); + return; + } + + const dim3 block(Policy::block_size_x, Policy::block_size_y); + const dim3 grid(divUp(cols, block.x * Policy::shift), divUp(rows, block.y)); + + transformSmart<<>>(src1, src2, dst, op, mask, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() ); + } + }; + + template + __host__ void transform(const SrcPtr& src, const GlobPtr& dst, const UnOp& op, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + TransformDispatcher::call(src, dst, op, mask, rows, cols, stream); + } + + template + __host__ void transform(const SrcPtr1& src1, const SrcPtr2& src2, const GlobPtr& dst, const BinOp& op, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + TransformDispatcher::call(src1, src2, dst, op, mask, rows, cols, stream); + } + + template + __host__ void transform(const GlobPtr& src, const GlobPtr& dst, const UnOp& op, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + TransformDispatcher::cn == 1 && VecTraits::cn == 1 && Policy::shift != 1, Policy>::call(src, dst, op, mask, rows, cols, stream); + } + + template + __host__ void transform(const GlobPtr& src1, const GlobPtr& src2, const GlobPtr& dst, const BinOp& op, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + TransformDispatcher::cn == 1 && VecTraits::cn == 1 && VecTraits::cn == 1 && Policy::shift != 1, Policy>::call(src1, src2, dst, op, mask, rows, cols, stream); + } + + // transform_tuple + + template struct Unroll + { + template + __device__ static void transform(const SrcVal& srcVal, DstPtrTuple& dst, const OpTuple& op, int y, int x) + { + typedef typename tuple_element::type dst_ptr_type; + typedef typename PtrTraits::value_type dst_type; + + get(dst)(y, x) = saturate_cast(get(op)(srcVal)); + Unroll::transform(srcVal, dst, op, y, x); + } + }; + template <> struct Unroll<0> + { + template + __device__ __forceinline__ static void transform(const SrcVal&, DstPtrTuple&, const OpTuple&, int, int) + { + } + }; + + template + __global__ void transform_tuple(const SrcPtr src, DstPtrTuple dst, const OpTuple op, const MaskPtr mask, const int rows, const int cols) + { + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (x >= cols || y >= rows || !mask(y, x)) + return; + + typename PtrTraits::value_type srcVal = src(y, x); + + Unroll::value>::transform(srcVal, dst, op, y, x); + } + + template + __host__ void transform_tuple(const SrcPtrTuple& src, const DstPtrTuple& dst, const OpTuple& op, const MaskPtr& mask, int rows, int cols, cudaStream_t stream) + { + const dim3 block(Policy::block_size_x, Policy::block_size_y); + const dim3 grid(divUp(cols, block.x), divUp(rows, block.y)); + + transform_tuple<<>>(src, dst, op, mask, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() ); + } +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/detail/transpose.hpp b/modules/cudev/include/opencv2/cudev/grid/detail/transpose.hpp new file mode 100644 index 0000000000..3854a17402 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/detail/transpose.hpp @@ -0,0 +1,130 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_TRANSPOSE_DETAIL_HPP__ +#define __OPENCV_CUDEV_GRID_TRANSPOSE_DETAIL_HPP__ + +#include "../../common.hpp" +#include "../../util/saturate_cast.hpp" +#include "../../ptr2d/glob.hpp" +#include "../../ptr2d/traits.hpp" + +namespace cv { namespace cudev { + +namespace transpose_detail +{ + const int TRANSPOSE_TILE_DIM = 16; + const int TRANSPOSE_BLOCK_ROWS = 16; + + template + __global__ void transpose(const SrcPtr src, GlobPtr dst, const int rows, const int cols) + { + typedef typename PtrTraits::value_type src_type; + + __shared__ src_type tile[TRANSPOSE_TILE_DIM][TRANSPOSE_TILE_DIM + 1]; + + int blockIdx_x, blockIdx_y; + + // do diagonal reordering + if (gridDim.x == gridDim.y) + { + blockIdx_y = blockIdx.x; + blockIdx_x = (blockIdx.x + blockIdx.y) % gridDim.x; + } + else + { + int bid = blockIdx.x + gridDim.x * blockIdx.y; + blockIdx_y = bid % gridDim.y; + blockIdx_x = ((bid / gridDim.y) + blockIdx_y) % gridDim.x; + } + + int xIndex = blockIdx_x * TRANSPOSE_TILE_DIM + threadIdx.x; + int yIndex = blockIdx_y * TRANSPOSE_TILE_DIM + threadIdx.y; + + if (xIndex < cols) + { + for (int i = 0; i < TRANSPOSE_TILE_DIM; i += TRANSPOSE_BLOCK_ROWS) + { + if (yIndex + i < rows) + { + tile[threadIdx.y + i][threadIdx.x] = src(yIndex + i, xIndex); + } + } + } + + __syncthreads(); + + xIndex = blockIdx_y * TRANSPOSE_TILE_DIM + threadIdx.x; + yIndex = blockIdx_x * TRANSPOSE_TILE_DIM + threadIdx.y; + + if (xIndex < rows) + { + for (int i = 0; i < TRANSPOSE_TILE_DIM; i += TRANSPOSE_BLOCK_ROWS) + { + if (yIndex + i < cols) + { + dst(yIndex + i, xIndex) = saturate_cast(tile[threadIdx.x][threadIdx.y + i]); + } + } + } + } + + template + __host__ void transpose(const SrcPtr& src, const GlobPtr& dst, int rows, int cols, cudaStream_t stream) + { + const dim3 block(TRANSPOSE_TILE_DIM, TRANSPOSE_TILE_DIM); + const dim3 grid(divUp(cols, block.x), divUp(rows, block.y)); + + transpose<<>>(src, dst, rows, cols); + CV_CUDEV_SAFE_CALL( cudaGetLastError() ); + + if (stream == 0) + CV_CUDEV_SAFE_CALL( cudaDeviceSynchronize() ); + } +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/glob_reduce.hpp b/modules/cudev/include/opencv2/cudev/grid/glob_reduce.hpp new file mode 100644 index 0000000000..8d3e0826d1 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/glob_reduce.hpp @@ -0,0 +1,314 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_GLOB_REDUCE_HPP__ +#define __OPENCV_CUDEV_GRID_GLOB_REDUCE_HPP__ + +#include +#include "../common.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/gpumat.hpp" +#include "../ptr2d/mask.hpp" +#include "../ptr2d/transform.hpp" +#include "detail/glob_reduce.hpp" + +namespace cv { namespace cudev { + +template +__host__ void gridCalcSum_(const SrcPtr& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + dst.create(1, 1); + dst.setTo(0, stream); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + grid_glob_reduce_detail::sum(shrinkPtr(src), + dst[0], + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCalcSum_(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + dst.create(1, 1); + dst.setTo(0, stream); + + const int rows = getRows(src); + const int cols = getCols(src); + + grid_glob_reduce_detail::sum(shrinkPtr(src), + dst[0], + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridFindMinVal_(const SrcPtr& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + dst.create(1, 1); + dst.setTo(Scalar::all(std::numeric_limits::max()), stream); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + grid_glob_reduce_detail::minVal(shrinkPtr(src), + dst[0], + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridFindMinVal_(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + dst.create(1, 1); + dst.setTo(Scalar::all(std::numeric_limits::max()), stream); + + const int rows = getRows(src); + const int cols = getCols(src); + + grid_glob_reduce_detail::minVal(shrinkPtr(src), + dst[0], + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridFindMaxVal_(const SrcPtr& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + dst.create(1, 1); + dst.setTo(Scalar::all(-std::numeric_limits::max()), stream); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + grid_glob_reduce_detail::maxVal(shrinkPtr(src), + dst[0], + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridFindMaxVal_(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + dst.create(1, 1); + dst.setTo(Scalar::all(-std::numeric_limits::max()), stream); + + const int rows = getRows(src); + const int cols = getCols(src); + + grid_glob_reduce_detail::maxVal(shrinkPtr(src), + dst[0], + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridFindMinMaxVal_(const SrcPtr& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + dst.create(1, 2); + dst.col(0).setTo(Scalar::all(std::numeric_limits::max()), stream); + dst.col(1).setTo(Scalar::all(-std::numeric_limits::max()), stream); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + grid_glob_reduce_detail::minMaxVal(shrinkPtr(src), + dst[0], + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridFindMinMaxVal_(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + dst.create(1, 2); + dst.col(0).setTo(Scalar::all(std::numeric_limits::max()), stream); + dst.col(1).setTo(Scalar::all(-std::numeric_limits::max()), stream); + + const int rows = getRows(src); + const int cols = getCols(src); + + grid_glob_reduce_detail::minMaxVal(shrinkPtr(src), + dst[0], + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCountNonZero_(const SrcPtr& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + dst.create(1, 1); + dst.setTo(0, stream); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + typedef typename PtrTraits::value_type src_type; + not_equal_to ne_op; + const src_type zero = VecTraits::all(0); + + grid_glob_reduce_detail::sum(shrinkPtr(transformPtr(src, bind2nd(ne_op, zero))), + dst[0], + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridCountNonZero_(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + dst.create(1, 1); + dst.setTo(0, stream); + + const int rows = getRows(src); + const int cols = getCols(src); + + typedef typename PtrTraits::value_type src_type; + not_equal_to ne_op; + const src_type zero = VecTraits::all(0); + + grid_glob_reduce_detail::sum(shrinkPtr(transformPtr(src, bind2nd(ne_op, zero))), + dst[0], + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +// default policy + +struct DefaultGlobReducePolicy +{ + enum { + block_size_x = 32, + block_size_y = 8, + + patch_size_x = 4, + patch_size_y = 4 + }; +}; + +template +__host__ void gridCalcSum(const SrcPtr& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridCalcSum_(src, dst, mask, stream); +} + +template +__host__ void gridCalcSum(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + gridCalcSum_(src, dst, stream); +} + +template +__host__ void gridFindMinVal(const SrcPtr& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridFindMinVal_(src, dst, mask, stream); +} + +template +__host__ void gridFindMinVal(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + gridFindMinVal_(src, dst, stream); +} + +template +__host__ void gridFindMaxVal(const SrcPtr& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridFindMaxVal_(src, dst, mask, stream); +} + +template +__host__ void gridFindMaxVal(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + gridFindMaxVal_(src, dst, stream); +} + +template +__host__ void gridFindMinMaxVal(const SrcPtr& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridFindMinMaxVal_(src, dst, mask, stream); +} + +template +__host__ void gridFindMinMaxVal(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + gridFindMinMaxVal_(src, dst, stream); +} + +template +__host__ void gridCountNonZero(const SrcPtr& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridCountNonZero_(src, dst, mask, stream); +} + +template +__host__ void gridCountNonZero(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + gridCountNonZero_(src, dst, stream); +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/histogram.hpp b/modules/cudev/include/opencv2/cudev/grid/histogram.hpp new file mode 100644 index 0000000000..b81b57febc --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/histogram.hpp @@ -0,0 +1,115 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_HISTOGRAM_HPP__ +#define __OPENCV_CUDEV_GRID_HISTOGRAM_HPP__ + +#include "../common.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/gpumat.hpp" +#include "../ptr2d/mask.hpp" +#include "detail/histogram.hpp" + +namespace cv { namespace cudev { + +template +__host__ void gridHistogram_(const SrcPtr& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + dst.create(1, BIN_COUNT); + dst.setTo(0, stream); + + grid_histogram_detail::histogram(shrinkPtr(src), + dst[0], + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridHistogram_(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + dst.create(1, BIN_COUNT); + dst.setTo(0, stream); + + grid_histogram_detail::histogram(shrinkPtr(src), + dst[0], + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +// default policy + +struct DefaultHistogramPolicy +{ + enum { + block_size_x = 32, + block_size_y = 8 + }; +}; + +template +__host__ void gridHistogram(const SrcPtr& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridHistogram_(src, dst, mask, stream); +} + +template +__host__ void gridHistogram(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + gridHistogram_(src, dst, stream); +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/integral.hpp b/modules/cudev/include/opencv2/cudev/grid/integral.hpp new file mode 100644 index 0000000000..d948c1267f --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/integral.hpp @@ -0,0 +1,69 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_INTEGRAL_HPP__ +#define __OPENCV_CUDEV_GRID_INTEGRAL_HPP__ + +#include "../common.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/gpumat.hpp" +#include "detail/integral.hpp" + +namespace cv { namespace cudev { + +template +__host__ void gridIntegral(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + dst.create(rows, cols); + + integral_detail::integral(shrinkPtr(src), shrinkPtr(dst), rows, cols, StreamAccessor::getStream(stream)); +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/pyramids.hpp b/modules/cudev/include/opencv2/cudev/grid/pyramids.hpp new file mode 100644 index 0000000000..99833bd3f7 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/pyramids.hpp @@ -0,0 +1,88 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_PYRAMIDS_HPP__ +#define __OPENCV_CUDEV_GRID_PYRAMIDS_HPP__ + +#include "../common.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/gpumat.hpp" +#include "../ptr2d/extrapolation.hpp" +#include "detail/pyr_down.hpp" +#include "detail/pyr_up.hpp" + +namespace cv { namespace cudev { + +template +__host__ void gridPyrDown_(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + dst.create(divUp(rows, 2), divUp(cols, 2)); + + pyramids_detail::pyrDown(shrinkPtr(src), shrinkPtr(dst), rows, cols, dst.rows, dst.cols, StreamAccessor::getStream(stream)); +} + +template +__host__ void gridPyrDown(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + gridPyrDown_(src, dst, stream); +} + +template +__host__ void gridPyrUp(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + dst.create(rows * 2, cols * 2); + + pyramids_detail::pyrUp(shrinkPtr(src), shrinkPtr(dst), rows, cols, dst.rows, dst.cols, StreamAccessor::getStream(stream)); +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/reduce_to_vec.hpp b/modules/cudev/include/opencv2/cudev/grid/reduce_to_vec.hpp new file mode 100644 index 0000000000..f9e3512428 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/reduce_to_vec.hpp @@ -0,0 +1,209 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_REDUCE_TO_VEC_HPP__ +#define __OPENCV_CUDEV_GRID_REDUCE_TO_VEC_HPP__ + +#include "../common.hpp" +#include "../util/vec_traits.hpp" +#include "../util/limits.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/gpumat.hpp" +#include "../ptr2d/mask.hpp" +#include "../functional/functional.hpp" +#include "detail/reduce_to_column.hpp" +#include "detail/reduce_to_row.hpp" + +namespace cv { namespace cudev { + +template struct Sum : plus +{ + typedef T work_type; + + __device__ __forceinline__ static T initialValue() + { + return VecTraits::all(0); + } + + __device__ __forceinline__ static T result(T r, int) + { + return r; + } +}; + +template struct Avg : plus +{ + typedef T work_type; + + __device__ __forceinline__ static T initialValue() + { + return VecTraits::all(0); + } + + __device__ __forceinline__ static T result(T r, int sz) + { + return r / sz; + } +}; + +template struct Min : minimum +{ + typedef T work_type; + + __device__ __forceinline__ static T initialValue() + { + return VecTraits::all(numeric_limits::elem_type>::max()); + } + + __device__ __forceinline__ static T result(T r, int) + { + return r; + } +}; + +template struct Max : maximum +{ + typedef T work_type; + + __device__ __forceinline__ static T initialValue() + { + return VecTraits::all(-numeric_limits::elem_type>::max()); + } + + __device__ __forceinline__ static T result(T r, int) + { + return r; + } +}; + +template +__host__ void gridReduceToRow(const SrcPtr& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + dst.create(1, cols); + + grid_reduce_to_vec_detail::reduceToRow(shrinkPtr(src), + dst[0], + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridReduceToRow(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + dst.create(1, cols); + + grid_reduce_to_vec_detail::reduceToRow(shrinkPtr(src), + dst[0], + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridReduceToColumn_(const SrcPtr& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + createContinuous(rows, 1, DataType::type, dst); + + grid_reduce_to_vec_detail::reduceToColumn(shrinkPtr(src), + dst[0], + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridReduceToColumn_(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + createContinuous(rows, 1, DataType::type, dst); + + grid_reduce_to_vec_detail::reduceToColumn(shrinkPtr(src), + dst[0], + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +// default policy + +struct DefaultReduceToVecPolicy +{ + enum { + block_size_x = 32, + block_size_y = 8 + }; +}; + +template +__host__ void gridReduceToColumn(const SrcPtr& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridReduceToColumn_(src, dst, mask, stream); +} + +template +__host__ void gridReduceToColumn(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + gridReduceToColumn_(src, dst, stream); +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/split_merge.hpp b/modules/cudev/include/opencv2/cudev/grid/split_merge.hpp new file mode 100644 index 0000000000..78584aad84 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/split_merge.hpp @@ -0,0 +1,407 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_SPLIT_MERGE_HPP__ +#define __OPENCV_CUDEV_GRID_SPLIT_MERGE_HPP__ + +#include "../common.hpp" +#include "../util/tuple.hpp" +#include "../util/vec_traits.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/gpumat.hpp" +#include "../ptr2d/mask.hpp" +#include "detail/split_merge.hpp" + +namespace cv { namespace cudev { + +template +__host__ void gridMerge_(const SrcPtrTuple& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( VecTraits::cn == tuple_size::value, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + dst.create(rows, cols); + + grid_split_merge_detail::MergeImpl::cn, Policy>::merge(shrinkPtr(src), + shrinkPtr(dst), + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridMerge_(const SrcPtrTuple& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( VecTraits::cn == tuple_size::value, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + dst.create(rows, cols); + + grid_split_merge_detail::MergeImpl::cn, Policy>::merge(shrinkPtr(src), + shrinkPtr(dst), + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridSplit_(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_& >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( VecTraits::value_type>::cn == 2, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + + grid_split_merge_detail::split(shrinkPtr(src), + shrinkPtr(get<0>(dst)), shrinkPtr(get<1>(dst)), + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridSplit_(const SrcPtr& src, GpuMat_ (&dst)[2], const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( VecTraits::value_type>::cn == 2, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + dst[0].create(rows, cols); + dst[1].create(rows, cols); + + grid_split_merge_detail::split(shrinkPtr(src), + shrinkPtr(dst[0]), shrinkPtr(dst[1]), + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridSplit_(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_& >& dst, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( VecTraits::value_type>::cn == 2, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + + grid_split_merge_detail::split(shrinkPtr(src), + shrinkPtr(get<0>(dst)), shrinkPtr(get<1>(dst)), + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridSplit_(const SrcPtr& src, GpuMat_ (&dst)[2], Stream& stream = Stream::Null()) +{ + CV_StaticAssert( VecTraits::value_type>::cn == 2, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + dst[0].create(rows, cols); + dst[1].create(rows, cols); + + grid_split_merge_detail::split(shrinkPtr(src), + shrinkPtr(dst[0]), shrinkPtr(dst[1]), + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridSplit_(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_& >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( VecTraits::value_type>::cn == 3, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + get<2>(dst).create(rows, cols); + + grid_split_merge_detail::split(shrinkPtr(src), + shrinkPtr(get<0>(dst)), shrinkPtr(get<1>(dst)), shrinkPtr(get<2>(dst)), + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridSplit_(const SrcPtr& src, GpuMat_ (&dst)[3], const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( VecTraits::value_type>::cn == 3, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + dst[0].create(rows, cols); + dst[1].create(rows, cols); + dst[2].create(rows, cols); + + grid_split_merge_detail::split(shrinkPtr(src), + shrinkPtr(dst[0]), shrinkPtr(dst[1]), shrinkPtr(dst[2]), + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridSplit_(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_& >& dst, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( VecTraits::value_type>::cn == 3, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + get<2>(dst).create(rows, cols); + + grid_split_merge_detail::split(shrinkPtr(src), + shrinkPtr(get<0>(dst)), shrinkPtr(get<1>(dst)), shrinkPtr(get<2>(dst)), + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridSplit_(const SrcPtr& src, GpuMat_ (&dst)[3], Stream& stream = Stream::Null()) +{ + CV_StaticAssert( VecTraits::value_type>::cn == 3, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + dst[0].create(rows, cols); + dst[1].create(rows, cols); + dst[2].create(rows, cols); + + grid_split_merge_detail::split(shrinkPtr(src), + shrinkPtr(dst[0]), shrinkPtr(dst[1]), shrinkPtr(dst[2]), + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridSplit_(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_&, GpuMat_& >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( VecTraits::value_type>::cn == 4, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + get<2>(dst).create(rows, cols); + get<3>(dst).create(rows, cols); + + grid_split_merge_detail::split(shrinkPtr(src), + shrinkPtr(get<0>(dst)), shrinkPtr(get<1>(dst)), shrinkPtr(get<2>(dst)), shrinkPtr(get<3>(dst)), + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridSplit_(const SrcPtr& src, GpuMat_ (&dst)[4], const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( VecTraits::value_type>::cn == 4, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + dst[0].create(rows, cols); + dst[1].create(rows, cols); + dst[2].create(rows, cols); + dst[4].create(rows, cols); + + grid_split_merge_detail::split(shrinkPtr(src), + shrinkPtr(dst[0]), shrinkPtr(dst[1]), shrinkPtr(dst[2]), shrinkPtr(dst[4]), + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridSplit_(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_&, GpuMat_& >& dst, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( VecTraits::value_type>::cn == 4, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + get<2>(dst).create(rows, cols); + get<3>(dst).create(rows, cols); + + grid_split_merge_detail::split(shrinkPtr(src), + shrinkPtr(get<0>(dst)), shrinkPtr(get<1>(dst)), shrinkPtr(get<2>(dst)), shrinkPtr(get<3>(dst)), + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridSplit_(const SrcPtr& src, GpuMat_ (&dst)[4], Stream& stream = Stream::Null()) +{ + CV_StaticAssert( VecTraits::value_type>::cn == 4, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + dst[0].create(rows, cols); + dst[1].create(rows, cols); + dst[2].create(rows, cols); + dst[4].create(rows, cols); + + grid_split_merge_detail::split(shrinkPtr(src), + shrinkPtr(dst[0]), shrinkPtr(dst[1]), shrinkPtr(dst[2]), shrinkPtr(dst[4]), + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +// Default Policy + +struct DefaultSplitMergePolicy +{ + enum { + block_size_x = 32, + block_size_y = 8 + }; +}; + +template +__host__ void gridMerge(const SrcPtrTuple& src, GpuMat_& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridMerge_(src, dst, mask, stream); +} + +template +__host__ void gridMerge(const SrcPtrTuple& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + gridMerge_(src, dst, stream); +} + +template +__host__ void gridSplit(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_& >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridSplit_(src, dst, mask, stream); +} + +template +__host__ void gridSplit(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_& >& dst, Stream& stream = Stream::Null()) +{ + gridSplit_(src, dst, stream); +} + +template +__host__ void gridSplit(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_& >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridSplit_(src, dst, mask, stream); +} + +template +__host__ void gridSplit(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_& >& dst, Stream& stream = Stream::Null()) +{ + gridSplit_(src, dst, stream); +} + +template +__host__ void gridSplit(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_&, GpuMat_& >& dst, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridSplit_(src, dst, mask, stream); +} + +template +__host__ void gridSplit(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_&, GpuMat_& >& dst, Stream& stream = Stream::Null()) +{ + gridSplit_(src, dst, stream); +} + +template +__host__ void gridSplit(const SrcPtr& src, GpuMat_ (&dst)[COUNT], const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridSplit_(src, dst, mask, stream); +} + +template +__host__ void gridSplit(const SrcPtr& src, GpuMat_ (&dst)[COUNT], Stream& stream = Stream::Null()) +{ + gridSplit_(src, dst, stream); +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/transform.hpp b/modules/cudev/include/opencv2/cudev/grid/transform.hpp new file mode 100644 index 0000000000..0da5e2d8a4 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/transform.hpp @@ -0,0 +1,541 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_TRANSFORM_HPP__ +#define __OPENCV_CUDEV_GRID_TRANSFORM_HPP__ + +#include "../common.hpp" +#include "../util/tuple.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/gpumat.hpp" +#include "../ptr2d/glob.hpp" +#include "../ptr2d/mask.hpp" +#include "../ptr2d/zip.hpp" +#include "detail/transform.hpp" + +namespace cv { namespace cudev { + +template +__host__ void gridTransform_(const SrcPtr& src, GpuMat_& dst, const UnOp& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + dst.create(rows, cols); + + grid_transform_detail::transform(shrinkPtr(src), shrinkPtr(dst), op, shrinkPtr(mask), rows, cols, StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr& src, const GlobPtrSz& dst, const UnOp& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(dst) == rows && getCols(dst) == cols ); + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + grid_transform_detail::transform(shrinkPtr(src), shrinkPtr(dst), op, shrinkPtr(mask), rows, cols, StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr& src, GpuMat_& dst, const UnOp& op, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + dst.create(rows, cols); + + grid_transform_detail::transform(shrinkPtr(src), shrinkPtr(dst), op, WithOutMask(), rows, cols, StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr& src, const GlobPtrSz& dst, const UnOp& op, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(dst) == rows && getCols(dst) == cols ); + + grid_transform_detail::transform(shrinkPtr(src), shrinkPtr(dst), op, WithOutMask(), rows, cols, StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr1& src1, const SrcPtr2& src2, GpuMat_& dst, const BinOp& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src1); + const int cols = getCols(src1); + + CV_Assert( getRows(src2) == rows && getCols(src2) == cols ); + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + dst.create(rows, cols); + + grid_transform_detail::transform(shrinkPtr(src1), shrinkPtr(src2), shrinkPtr(dst), op, shrinkPtr(mask), rows, cols, StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr1& src1, const SrcPtr2& src2, const GlobPtrSz& dst, const BinOp& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src1); + const int cols = getCols(src1); + + CV_Assert( getRows(dst) == rows && getCols(dst) == cols ); + CV_Assert( getRows(src2) == rows && getCols(src2) == cols ); + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + grid_transform_detail::transform(shrinkPtr(src1), shrinkPtr(src2), shrinkPtr(dst), op, shrinkPtr(mask), rows, cols, StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr1& src1, const SrcPtr2& src2, GpuMat_& dst, const BinOp& op, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src1); + const int cols = getCols(src1); + + CV_Assert( getRows(src2) == rows && getCols(src2) == cols ); + + dst.create(rows, cols); + + grid_transform_detail::transform(shrinkPtr(src1), shrinkPtr(src2), shrinkPtr(dst), op, WithOutMask(), rows, cols, StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr1& src1, const SrcPtr2& src2, GlobPtrSz& dst, const BinOp& op, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src1); + const int cols = getCols(src1); + + CV_Assert( getRows(dst) == rows && getCols(dst) == cols ); + CV_Assert( getRows(src2) == rows && getCols(src2) == cols ); + + grid_transform_detail::transform(shrinkPtr(src1), shrinkPtr(src2), shrinkPtr(dst), op, WithOutMask(), rows, cols, StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_& >& dst, const OpTuple& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 2, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + + grid_transform_detail::transform_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst))), + op, + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr& src, const tuple< GlobPtrSz, GlobPtrSz >& dst, const OpTuple& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 2, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(get<0>(dst)) == rows && getCols(get<0>(dst)) == cols ); + CV_Assert( getRows(get<1>(dst)) == rows && getCols(get<1>(dst)) == cols ); + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + grid_transform_detail::transform_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst))), + op, + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_& >& dst, const OpTuple& op, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 2, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + + grid_transform_detail::transform_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst))), + op, + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr& src, const tuple< GlobPtrSz, GlobPtrSz >& dst, const OpTuple& op, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 2, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(get<0>(dst)) == rows && getCols(get<0>(dst)) == cols ); + CV_Assert( getRows(get<1>(dst)) == rows && getCols(get<1>(dst)) == cols ); + + grid_transform_detail::transform_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst))), + op, + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_& >& dst, const OpTuple& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 3, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + get<2>(dst).create(rows, cols); + + grid_transform_detail::transform_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst), get<2>(dst))), + op, + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr& src, const tuple< GlobPtrSz, GlobPtrSz, GlobPtrSz >& dst, const OpTuple& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 3, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(get<0>(dst)) == rows && getCols(get<0>(dst)) == cols ); + CV_Assert( getRows(get<1>(dst)) == rows && getCols(get<1>(dst)) == cols ); + CV_Assert( getRows(get<2>(dst)) == rows && getCols(get<2>(dst)) == cols ); + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + grid_transform_detail::transform_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst), get<2>(dst))), + op, + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_& >& dst, const OpTuple& op, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 3, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + get<2>(dst).create(rows, cols); + + grid_transform_detail::transform_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst), get<2>(dst))), + op, + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr& src, const tuple< GlobPtrSz, GlobPtrSz, GlobPtrSz >& dst, const OpTuple& op, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 3, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(get<0>(dst)) == rows && getCols(get<0>(dst)) == cols ); + CV_Assert( getRows(get<1>(dst)) == rows && getCols(get<1>(dst)) == cols ); + CV_Assert( getRows(get<2>(dst)) == rows && getCols(get<2>(dst)) == cols ); + + grid_transform_detail::transform_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst), get<2>(dst))), + op, + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_&, GpuMat_& >& dst, const OpTuple& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 4, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + get<2>(dst).create(rows, cols); + get<3>(dst).create(rows, cols); + + grid_transform_detail::transform_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst), get<2>(dst), get<3>(dst))), + op, + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr& src, const tuple< GlobPtrSz, GlobPtrSz, GlobPtrSz, GlobPtrSz >& dst, const OpTuple& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 4, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(get<0>(dst)) == rows && getCols(get<0>(dst)) == cols ); + CV_Assert( getRows(get<1>(dst)) == rows && getCols(get<1>(dst)) == cols ); + CV_Assert( getRows(get<2>(dst)) == rows && getCols(get<2>(dst)) == cols ); + CV_Assert( getRows(get<3>(dst)) == rows && getCols(get<3>(dst)) == cols ); + CV_Assert( getRows(mask) == rows && getCols(mask) == cols ); + + grid_transform_detail::transform_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst), get<2>(dst), get<3>(dst))), + op, + shrinkPtr(mask), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_&, GpuMat_& >& dst, const OpTuple& op, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 4, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + get<0>(dst).create(rows, cols); + get<1>(dst).create(rows, cols); + get<2>(dst).create(rows, cols); + get<3>(dst).create(rows, cols); + + grid_transform_detail::transform_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst), get<2>(dst), get<3>(dst))), + op, + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +template +__host__ void gridTransform_(const SrcPtr& src, const tuple< GlobPtrSz, GlobPtrSz, GlobPtrSz, GlobPtrSz >& dst, const OpTuple& op, Stream& stream = Stream::Null()) +{ + CV_StaticAssert( tuple_size::value == 4, "" ); + + const int rows = getRows(src); + const int cols = getCols(src); + + CV_Assert( getRows(get<0>(dst)) == rows && getCols(get<0>(dst)) == cols ); + CV_Assert( getRows(get<1>(dst)) == rows && getCols(get<1>(dst)) == cols ); + CV_Assert( getRows(get<2>(dst)) == rows && getCols(get<2>(dst)) == cols ); + CV_Assert( getRows(get<3>(dst)) == rows && getCols(get<3>(dst)) == cols ); + + grid_transform_detail::transform_tuple(shrinkPtr(src), + shrinkPtr(zipPtr(get<0>(dst), get<1>(dst), get<2>(dst), get<3>(dst))), + op, + WithOutMask(), + rows, cols, + StreamAccessor::getStream(stream)); +} + +// Default Policy + +struct DefaultTransformPolicy +{ + enum { + block_size_x = 32, + block_size_y = 8, + shift = 4 + }; +}; + +template +__host__ void gridTransform(const SrcPtr& src, GpuMat_& dst, const Op& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridTransform_(src, dst, op, mask, stream); +} + +template +__host__ void gridTransform(const SrcPtr& src, const GlobPtrSz& dst, const Op& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridTransform_(src, dst, op, mask, stream); +} + +template +__host__ void gridTransform(const SrcPtr& src, GpuMat_& dst, const Op& op, Stream& stream = Stream::Null()) +{ + gridTransform_(src, dst, op, stream); +} + +template +__host__ void gridTransform(const SrcPtr& src, const GlobPtrSz& dst, const Op& op, Stream& stream = Stream::Null()) +{ + gridTransform_(src, dst, op, stream); +} + +template +__host__ void gridTransform(const SrcPtr1& src1, const SrcPtr1& src2, GpuMat_& dst, const Op& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridTransform_(src1, src2, dst, op, mask, stream); +} + +template +__host__ void gridTransform(const SrcPtr1& src1, const SrcPtr1& src2, const GlobPtrSz& dst, const Op& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridTransform_(src1, src2, dst, op, mask, stream); +} + +template +__host__ void gridTransform(const SrcPtr1& src1, const SrcPtr1& src2, GpuMat_& dst, const Op& op, Stream& stream = Stream::Null()) +{ + gridTransform_(src1, src2, dst, op, stream); +} + +template +__host__ void gridTransform(const SrcPtr1& src1, const SrcPtr1& src2, const GlobPtrSz& dst, const Op& op, Stream& stream = Stream::Null()) +{ + gridTransform_(src1, src2, dst, op, stream); +} + +template +__host__ void gridTransform(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_& >& dst, const OpTuple& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridTransform_(src, dst, op, mask, stream); +} + +template +__host__ void gridTransform(const SrcPtr& src, const tuple< GlobPtrSz, GlobPtrSz >& dst, const OpTuple& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridTransform_(src, dst, op, mask, stream); +} + +template +__host__ void gridTransform(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_& >& dst, const OpTuple& op, Stream& stream = Stream::Null()) +{ + gridTransform_(src, dst, op, stream); +} + +template +__host__ void gridTransform(const SrcPtr& src, const tuple< GlobPtrSz, GlobPtrSz >& dst, const OpTuple& op, Stream& stream = Stream::Null()) +{ + gridTransform_(src, dst, op, stream); +} + +template +__host__ void gridTransform(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_& >& dst, const OpTuple& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridTransform_(src, dst, op, mask, stream); +} + +template +__host__ void gridTransform(const SrcPtr& src, const tuple< GlobPtrSz, GlobPtrSz, GlobPtrSz >& dst, const OpTuple& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridTransform_(src, dst, op, mask, stream); +} + +template +__host__ void gridTransform(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_& >& dst, const OpTuple& op, Stream& stream = Stream::Null()) +{ + gridTransform_(src, dst, op, stream); +} + +template +__host__ void gridTransform(const SrcPtr& src, const tuple< GlobPtrSz, GlobPtrSz, GlobPtrSz >& dst, const OpTuple& op, Stream& stream = Stream::Null()) +{ + gridTransform_(src, dst, op, stream); +} + +template +__host__ void gridTransform(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_&, GpuMat_& >& dst, const OpTuple& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridTransform_(src, dst, op, mask, stream); +} + +template +__host__ void gridTransform(const SrcPtr& src, const tuple< GlobPtrSz, GlobPtrSz, GlobPtrSz, GlobPtrSz >& dst, const OpTuple& op, const MaskPtr& mask, Stream& stream = Stream::Null()) +{ + gridTransform_(src, dst, op, mask, stream); +} + +template +__host__ void gridTransform(const SrcPtr& src, const tuple< GpuMat_&, GpuMat_&, GpuMat_&, GpuMat_& >& dst, const OpTuple& op, Stream& stream = Stream::Null()) +{ + gridTransform_(src, dst, op, stream); +} + +template +__host__ void gridTransform(const SrcPtr& src, const tuple< GlobPtrSz, GlobPtrSz, GlobPtrSz, GlobPtrSz >& dst, const OpTuple& op, Stream& stream = Stream::Null()) +{ + gridTransform_(src, dst, op, stream); +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/grid/transpose.hpp b/modules/cudev/include/opencv2/cudev/grid/transpose.hpp new file mode 100644 index 0000000000..5e8f24868f --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/transpose.hpp @@ -0,0 +1,69 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_GRID_TRANSPOSE_HPP__ +#define __OPENCV_CUDEV_GRID_TRANSPOSE_HPP__ + +#include "../common.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/gpumat.hpp" +#include "detail/transpose.hpp" + +namespace cv { namespace cudev { + +template +__host__ void gridTranspose(const SrcPtr& src, GpuMat_& dst, Stream& stream = Stream::Null()) +{ + const int rows = getRows(src); + const int cols = getCols(src); + + dst.create(cols, rows); + + transpose_detail::transpose(shrinkPtr(src), shrinkPtr(dst), rows, cols, StreamAccessor::getStream(stream)); +} + +}} + +#endif diff --git a/modules/video/src/simpleflow.hpp b/modules/cudev/include/opencv2/cudev/ptr2d/constant.hpp similarity index 67% rename from modules/video/src/simpleflow.hpp rename to modules/cudev/include/opencv2/cudev/ptr2d/constant.hpp index 363fdea168..d3c56e7713 100644 --- a/modules/video/src/simpleflow.hpp +++ b/modules/cudev/include/opencv2/cudev/ptr2d/constant.hpp @@ -12,6 +12,7 @@ // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -40,47 +41,53 @@ // //M*/ -#ifndef __OPENCV_SIMPLEFLOW_H__ -#define __OPENCV_SIMPLEFLOW_H__ +#pragma once -#include +#ifndef __OPENCV_CUDEV_PTR2D_CONSTANT_HPP__ +#define __OPENCV_CUDEV_PTR2D_CONSTANT_HPP__ -#define MASK_TRUE_VALUE 255 -#define UNKNOWN_FLOW_THRESH 1e9 +#include "../common.hpp" +#include "traits.hpp" -namespace cv { +namespace cv { namespace cudev { -inline static float dist(const Vec3b& p1, const Vec3b& p2) { - return (float)((p1[0] - p2[0]) * (p1[0] - p2[0]) + - (p1[1] - p2[1]) * (p1[1] - p2[1]) + - (p1[2] - p2[2]) * (p1[2] - p2[2])); +template struct ConstantPtr +{ + typedef T value_type; + typedef int index_type; + + T value; + + __device__ __forceinline__ T operator ()(int, int) const { return value; } +}; + +template struct ConstantPtrSz : ConstantPtr +{ + int rows, cols; +}; + +template +__host__ ConstantPtr constantPtr(T value) +{ + ConstantPtr p; + p.value = value; + return p; } -inline static float dist(const Vec2f& p1, const Vec2f& p2) { - return (p1[0] - p2[0]) * (p1[0] - p2[0]) + - (p1[1] - p2[1]) * (p1[1] - p2[1]); +template ConstantPtrSz +__host__ constantPtr(T value, int rows, int cols) +{ + ConstantPtrSz p; + p.value = value; + p.rows = rows; + p.cols = cols; + return p; } -inline static float dist(const Point2f& p1, const Point2f& p2) { - return (p1.x - p2.x) * (p1.x - p2.x) + - (p1.y - p2.y) * (p1.y - p2.y); -} +template struct PtrTraits< ConstantPtrSz > : PtrTraitsBase< ConstantPtrSz, ConstantPtr > +{ +}; -inline static float dist(float x1, float y1, float x2, float y2) { - return (x1 - x2) * (x1 - x2) + - (y1 - y2) * (y1 - y2); -} - -inline static int dist(int x1, int y1, int x2, int y2) { - return (x1 - x2) * (x1 - x2) + - (y1 - y2) * (y1 - y2); -} - -template -inline static T min(T t1, T t2, T t3) { - return (t1 <= t2 && t1 <= t3) ? t1 : min(t2, t3); -} - -} +}} #endif diff --git a/modules/cudev/include/opencv2/cudev/ptr2d/deriv.hpp b/modules/cudev/include/opencv2/cudev/ptr2d/deriv.hpp new file mode 100644 index 0000000000..097007400f --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/ptr2d/deriv.hpp @@ -0,0 +1,393 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_PTR2D_DERIV_HPP__ +#define __OPENCV_CUDEV_PTR2D_DERIV_HPP__ + +#include "../common.hpp" +#include "../grid/copy.hpp" +#include "traits.hpp" +#include "gpumat.hpp" + +namespace cv { namespace cudev { + +// derivX + +template struct DerivXPtr +{ + typedef typename PtrTraits::value_type value_type; + typedef int index_type; + + SrcPtr src; + + __device__ __forceinline__ typename PtrTraits::value_type operator ()(int y, int x) const + { + return src(y, x + 1) - src(y, x - 1); + } +}; + +template struct DerivXPtrSz : DerivXPtr +{ + int rows, cols; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridCopy(*this, dst, stream); + } +}; + +template +__host__ DerivXPtrSz::ptr_type> derivXPtr(const SrcPtr& src) +{ + DerivXPtrSz::ptr_type> s; + s.src = shrinkPtr(src); + s.rows = getRows(src); + s.cols = getCols(src); + return s; +} + +template struct PtrTraits< DerivXPtrSz > : PtrTraitsBase, DerivXPtr > +{ +}; + +// derivY + +template struct DerivYPtr +{ + typedef typename PtrTraits::value_type value_type; + typedef int index_type; + + SrcPtr src; + + __device__ __forceinline__ typename PtrTraits::value_type operator ()(int y, int x) const + { + return src(y + 1, x) - src(y - 1, x); + } +}; + +template struct DerivYPtrSz : DerivYPtr +{ + int rows, cols; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridCopy(*this, dst, stream); + } +}; + +template +__host__ DerivYPtrSz::ptr_type> derivYPtr(const SrcPtr& src) +{ + DerivYPtrSz::ptr_type> s; + s.src = shrinkPtr(src); + s.rows = getRows(src); + s.cols = getCols(src); + return s; +} + +template struct PtrTraits< DerivYPtrSz > : PtrTraitsBase, DerivYPtr > +{ +}; + +// sobelX + +template struct SobelXPtr +{ + typedef typename PtrTraits::value_type value_type; + typedef int index_type; + + SrcPtr src; + + __device__ typename PtrTraits::value_type operator ()(int y, int x) const + { + typename PtrTraits::value_type vals[6] = + { + src(y - 1, x - 1), src(y - 1, x + 1), + src(y , x - 1), src(y , x + 1), + src(y + 1, x - 1), src(y + 1, x + 1), + }; + + return (vals[1] - vals[0]) + 2 * (vals[3] - vals[2]) + (vals[5] - vals[4]); + } +}; + +template struct SobelXPtrSz : SobelXPtr +{ + int rows, cols; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridCopy(*this, dst, stream); + } +}; + +template +__host__ SobelXPtrSz::ptr_type> sobelXPtr(const SrcPtr& src) +{ + SobelXPtrSz::ptr_type> s; + s.src = shrinkPtr(src); + s.rows = getRows(src); + s.cols = getCols(src); + return s; +} + +template struct PtrTraits< SobelXPtrSz > : PtrTraitsBase, SobelXPtr > +{ +}; + +// sobelY + +template struct SobelYPtr +{ + typedef typename PtrTraits::value_type value_type; + typedef int index_type; + + SrcPtr src; + + __device__ typename PtrTraits::value_type operator ()(int y, int x) const + { + typename PtrTraits::value_type vals[6] = + { + src(y - 1, x - 1), src(y - 1, x), src(y - 1, x + 1), + src(y + 1, x - 1), src(y + 1, x), src(y + 1, x + 1) + }; + + return (vals[3] - vals[0]) + 2 * (vals[4] - vals[1]) + (vals[5] - vals[2]); + } +}; + +template struct SobelYPtrSz : SobelYPtr +{ + int rows, cols; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridCopy(*this, dst, stream); + } +}; + +template +__host__ SobelYPtrSz::ptr_type> sobelYPtr(const SrcPtr& src) +{ + SobelYPtrSz::ptr_type> s; + s.src = shrinkPtr(src); + s.rows = getRows(src); + s.cols = getCols(src); + return s; +} + +template struct PtrTraits< SobelYPtrSz > : PtrTraitsBase, SobelYPtr > +{ +}; + +// scharrX + +template struct ScharrXPtr +{ + typedef typename PtrTraits::value_type value_type; + typedef int index_type; + + SrcPtr src; + + __device__ typename PtrTraits::value_type operator ()(int y, int x) const + { + typename PtrTraits::value_type vals[6] = + { + src(y - 1, x - 1), src(y - 1, x + 1), + src(y , x - 1), src(y , x + 1), + src(y + 1, x - 1), src(y + 1, x + 1), + }; + + return 3 * (vals[1] - vals[0]) + 10 * (vals[3] - vals[2]) + 3 * (vals[5] - vals[4]); + } +}; + +template struct ScharrXPtrSz : ScharrXPtr +{ + int rows, cols; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridCopy(*this, dst, stream); + } +}; + +template +__host__ ScharrXPtrSz::ptr_type> scharrXPtr(const SrcPtr& src) +{ + ScharrXPtrSz::ptr_type> s; + s.src = shrinkPtr(src); + s.rows = getRows(src); + s.cols = getCols(src); + return s; +} + +template struct PtrTraits< ScharrXPtrSz > : PtrTraitsBase, ScharrXPtr > +{ +}; + +// scharrY + +template struct ScharrYPtr +{ + typedef typename PtrTraits::value_type value_type; + typedef int index_type; + + SrcPtr src; + + __device__ typename PtrTraits::value_type operator ()(int y, int x) const + { + typename PtrTraits::value_type vals[6] = + { + src(y - 1, x - 1), src(y - 1, x), src(y - 1, x + 1), + src(y + 1, x - 1), src(y + 1, x), src(y + 1, x + 1) + }; + + return 3 * (vals[3] - vals[0]) + 10 * (vals[4] - vals[1]) + 3 * (vals[5] - vals[2]); + } +}; + +template struct ScharrYPtrSz : ScharrYPtr +{ + int rows, cols; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridCopy(*this, dst, stream); + } +}; + +template +__host__ ScharrYPtrSz::ptr_type> scharrYPtr(const SrcPtr& src) +{ + ScharrYPtrSz::ptr_type> s; + s.src = shrinkPtr(src); + s.rows = getRows(src); + s.cols = getCols(src); + return s; +} + +template struct PtrTraits< ScharrYPtrSz > : PtrTraitsBase, ScharrYPtr > +{ +}; + +// laplacian + +template struct LaplacianPtr; + +template struct LaplacianPtr<1, SrcPtr> +{ + typedef typename PtrTraits::value_type value_type; + typedef int index_type; + + SrcPtr src; + + __device__ typename PtrTraits::value_type operator ()(int y, int x) const + { + typename PtrTraits::value_type vals[5] = + { + src(y - 1, x), + src(y, x - 1), src(y , x), src(y, x + 1), + src(y + 1, x) + }; + + return (vals[0] + vals[1] + vals[3] + vals[4]) - 4 * vals[2]; + } +}; + +template struct LaplacianPtr<3, SrcPtr> +{ + typedef typename PtrTraits::value_type value_type; + typedef int index_type; + + SrcPtr src; + + __device__ typename PtrTraits::value_type operator ()(int y, int x) const + { + typename PtrTraits::value_type vals[5] = + { + src(y - 1, x - 1), src(y - 1, x + 1), + src(y, x), + src(y + 1, x - 1), src(y + 1, x + 1) + }; + + return 2 * (vals[0] + vals[1] + vals[3] + vals[4]) - 8 * vals[2]; + } +}; + +template struct LaplacianPtrSz : LaplacianPtr +{ + int rows, cols; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridCopy(*this, dst, stream); + } +}; + +template +__host__ LaplacianPtrSz::ptr_type> laplacianPtr(const SrcPtr& src) +{ + LaplacianPtrSz::ptr_type> ptr; + ptr.src = shrinkPtr(src); + ptr.rows = getRows(src); + ptr.cols = getCols(src); + return ptr; +} + +template struct PtrTraits< LaplacianPtrSz > : PtrTraitsBase, LaplacianPtr > +{ +}; + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/ptr2d/detail/gpumat.hpp b/modules/cudev/include/opencv2/cudev/ptr2d/detail/gpumat.hpp new file mode 100644 index 0000000000..e378c52372 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/ptr2d/detail/gpumat.hpp @@ -0,0 +1,361 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_PTR2D_GPUMAT_DETAIL_HPP__ +#define __OPENCV_CUDEV_PTR2D_GPUMAT_DETAIL_HPP__ + +#include "../gpumat.hpp" + +namespace cv { namespace cudev { + +template +__host__ GpuMat_::GpuMat_() + : GpuMat() +{ + flags = (flags & ~CV_MAT_TYPE_MASK) | DataType::type; +} + +template +__host__ GpuMat_::GpuMat_(int arows, int acols) + : GpuMat(arows, acols, DataType::type) +{ +} + +template +__host__ GpuMat_::GpuMat_(Size asize) + : GpuMat(asize.height, asize.width, DataType::type) +{ +} + +template +__host__ GpuMat_::GpuMat_(int arows, int acols, Scalar val) + : GpuMat(arows, acols, DataType::type, val) +{ +} + +template +__host__ GpuMat_::GpuMat_(Size asize, Scalar val) + : GpuMat(asize.height, asize.width, DataType::type, val) +{ +} + +template +__host__ GpuMat_::GpuMat_(const GpuMat_& m) + : GpuMat(m) +{ +} + +template +__host__ GpuMat_::GpuMat_(const GpuMat& m) + : GpuMat() +{ + flags = (flags & ~CV_MAT_TYPE_MASK) | DataType::type; + + if (DataType::type == m.type()) + { + GpuMat::operator =(m); + return; + } + + if (DataType::depth == m.depth()) + { + GpuMat::operator =(m.reshape(DataType::channels, m.rows)); + return; + } + + CV_Assert( DataType::channels == m.channels() ); + m.convertTo(*this, type()); +} + +template +__host__ GpuMat_::GpuMat_(int arows, int acols, T* adata, size_t astep) + : GpuMat(arows, acols, DataType::type, adata, astep) +{ +} + +template +__host__ GpuMat_::GpuMat_(Size asize, T* adata, size_t astep) + : GpuMat(asize.height, asize.width, DataType::type, adata, astep) +{ +} + +template +__host__ GpuMat_::GpuMat_(const GpuMat_& m, Range arowRange, Range acolRange) + : GpuMat(m, arowRange, acolRange) +{ +} + +template +__host__ GpuMat_::GpuMat_(const GpuMat_& m, Rect roi) + : GpuMat(m, roi) +{ +} + +template +__host__ GpuMat_::GpuMat_(InputArray arr) + : GpuMat() +{ + flags = (flags & ~CV_MAT_TYPE_MASK) | DataType::type; + upload(arr); +} + +template +__host__ GpuMat_& GpuMat_::operator =(const GpuMat_& m) +{ + GpuMat::operator =(m); + return *this; +} + +template +__host__ void GpuMat_::create(int arows, int acols) +{ + GpuMat::create(arows, acols, DataType::type); +} + +template +__host__ void GpuMat_::create(Size asize) +{ + GpuMat::create(asize, DataType::type); +} + +template +__host__ void GpuMat_::swap(GpuMat_& mat) +{ + GpuMat::swap(mat); +} + +template +__host__ void GpuMat_::upload(InputArray arr) +{ + CV_Assert( arr.type() == DataType::type ); + GpuMat::upload(arr); +} + +template +__host__ void GpuMat_::upload(InputArray arr, Stream& stream) +{ + CV_Assert( arr.type() == DataType::type ); + GpuMat::upload(arr, stream); +} + +template +__host__ GpuMat_::operator GlobPtrSz() const +{ + return globPtr((T*) data, step, rows, cols); +} + +template +__host__ GpuMat_::operator GlobPtr() const +{ + return globPtr((T*) data, step); +} + +template +__host__ GpuMat_ GpuMat_::clone() const +{ + return GpuMat_(GpuMat::clone()); +} + +template +__host__ GpuMat_ GpuMat_::row(int y) const +{ + return GpuMat_(*this, Range(y, y+1), Range::all()); +} + +template +__host__ GpuMat_ GpuMat_::col(int x) const +{ + return GpuMat_(*this, Range::all(), Range(x, x+1)); +} + +template +__host__ GpuMat_ GpuMat_::rowRange(int startrow, int endrow) const +{ + return GpuMat_(*this, Range(startrow, endrow), Range::all()); +} + +template +__host__ GpuMat_ GpuMat_::rowRange(Range r) const +{ + return GpuMat_(*this, r, Range::all()); +} + +template +__host__ GpuMat_ GpuMat_::colRange(int startcol, int endcol) const +{ + return GpuMat_(*this, Range::all(), Range(startcol, endcol)); +} + +template +__host__ GpuMat_ GpuMat_::colRange(Range r) const +{ + return GpuMat_(*this, Range::all(), r); +} + +template +__host__ GpuMat_ GpuMat_::operator ()(Range _rowRange, Range _colRange) const +{ + return GpuMat_(*this, _rowRange, _colRange); +} + +template +__host__ GpuMat_ GpuMat_::operator ()(Rect roi) const +{ + return GpuMat_(*this, roi); +} + +template +__host__ GpuMat_& GpuMat_::adjustROI(int dtop, int dbottom, int dleft, int dright) +{ + return (GpuMat_&)(GpuMat::adjustROI(dtop, dbottom, dleft, dright)); +} + +template +__host__ size_t GpuMat_::elemSize() const +{ + CV_DbgAssert( GpuMat::elemSize() == sizeof(T) ); + return sizeof(T); +} + +template +__host__ size_t GpuMat_::elemSize1() const +{ + CV_DbgAssert( GpuMat::elemSize1() == sizeof(T) / DataType::channels ); + return sizeof(T) / DataType::channels; +} + +template +__host__ int GpuMat_::type() const +{ + CV_DbgAssert( GpuMat::type() == DataType::type ); + return DataType::type; +} + +template +__host__ int GpuMat_::depth() const +{ + CV_DbgAssert( GpuMat::depth() == DataType::depth ); + return DataType::depth; +} + +template +__host__ int GpuMat_::channels() const +{ + CV_DbgAssert( GpuMat::channels() == DataType::channels ); + return DataType::channels; +} + +template +__host__ size_t GpuMat_::stepT() const +{ + return step / elemSize(); +} + +template +__host__ size_t GpuMat_::step1() const +{ + return step / elemSize1(); +} + +template +__host__ T* GpuMat_::operator [](int y) +{ + return (T*)ptr(y); +} + +template +__host__ const T* GpuMat_::operator [](int y) const +{ + return (const T*)ptr(y); +} + +template template +__host__ GpuMat_::GpuMat_(const Expr& expr) + : GpuMat() +{ + flags = (flags & ~CV_MAT_TYPE_MASK) | DataType::type; + *this = expr; +} + +template template +__host__ GpuMat_& GpuMat_::operator =(const Expr& expr) +{ + expr.body.assignTo(*this); + return *this; +} + +template template +__host__ GpuMat_& GpuMat_::assign(const Expr& expr, Stream& stream) +{ + expr.body.assignTo(*this, stream); + return *this; +} + +}} + +// Input / Output Arrays + +namespace cv { + +template +__host__ _InputArray::_InputArray(const cudev::GpuMat_<_Tp>& m) + : flags(FIXED_TYPE + GPU_MAT + DataType<_Tp>::type), obj((void*)&m) +{} + +template +__host__ _OutputArray::_OutputArray(cudev::GpuMat_<_Tp>& m) + : _InputArray(m) +{} + +template +__host__ _OutputArray::_OutputArray(const cudev::GpuMat_<_Tp>& m) + : _InputArray(m) +{ + flags |= FIXED_SIZE; +} + +} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/ptr2d/extrapolation.hpp b/modules/cudev/include/opencv2/cudev/ptr2d/extrapolation.hpp new file mode 100644 index 0000000000..c90e79174f --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/ptr2d/extrapolation.hpp @@ -0,0 +1,219 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_PTR2D_EXTRAPOLATION_HPP__ +#define __OPENCV_CUDEV_PTR2D_EXTRAPOLATION_HPP__ + +#include "../common.hpp" +#include "../util/vec_traits.hpp" +#include "traits.hpp" + +namespace cv { namespace cudev { + +// BrdConstant + +template struct BrdConstant +{ + typedef typename PtrTraits::value_type value_type; + typedef int index_type; + + SrcPtr src; + int rows, cols; + typename PtrTraits::value_type val; + + __device__ __forceinline__ typename PtrTraits::value_type operator ()(int y, int x) const + { + return (x >= 0 && x < cols && y >= 0 && y < rows) ? src(y, x) : val; + } +}; + +template +__host__ BrdConstant::ptr_type> brdConstant(const SrcPtr& src, typename PtrTraits::value_type val) +{ + BrdConstant::ptr_type> b; + b.src = shrinkPtr(src); + b.rows = getRows(src); + b.cols = getCols(src); + b.val = val; + return b; +} + +template +__host__ BrdConstant::ptr_type> brdConstant(const SrcPtr& src) +{ + return brdConstant(src, VecTraits::value_type>::all(0)); +} + +// BrdBase + +template struct BrdBase +{ + typedef typename PtrTraits::value_type value_type; + typedef int index_type; + + SrcPtr src; + int rows, cols; + + __device__ __forceinline__ int idx_row(int y) const + { + return BrdImpl::idx_low(BrdImpl::idx_high(y, rows), rows); + } + + __device__ __forceinline__ int idx_col(int x) const + { + return BrdImpl::idx_low(BrdImpl::idx_high(x, cols), cols); + } + + __device__ __forceinline__ typename PtrTraits::value_type operator ()(int y, int x) const + { + return src(idx_row(y), idx_col(x)); + } +}; + +// BrdReplicate + +struct BrdReplicate +{ + __device__ __forceinline__ static int idx_low(int i, int len) + { + return ::max(i, 0); + } + + __device__ __forceinline__ static int idx_high(int i, int len) + { + return ::min(i, len - 1); + } +}; + +template +__host__ BrdBase::ptr_type> brdReplicate(const SrcPtr& src) +{ + BrdBase::ptr_type> b; + b.src = shrinkPtr(src); + b.rows = getRows(src); + b.cols = getCols(src); + return b; +} + +// BrdReflect101 + +struct BrdReflect101 +{ + __device__ __forceinline__ static int idx_low(int i, int len) + { + return ::abs(i) % len; + } + + __device__ __forceinline__ static int idx_high(int i, int len) + { + const int last_ind = len - 1; + return ::abs(last_ind - ::abs(last_ind - i)) % len; + } +}; + +template +__host__ BrdBase::ptr_type> brdReflect101(const SrcPtr& src) +{ + BrdBase::ptr_type> b; + b.src = shrinkPtr(src); + b.rows = getRows(src); + b.cols = getCols(src); + return b; +} + +// BrdReflect + +struct BrdReflect +{ + __device__ __forceinline__ static int idx_low(int i, int len) + { + return (::abs(i) - (i < 0)) % len; + } + + __device__ __forceinline__ static int idx_high(int i, int len) + { + const int last_ind = len - 1; + return (last_ind - ::abs(last_ind - i) + (i > last_ind)); + } +}; + +template +__host__ BrdBase::ptr_type> brdReflect(const SrcPtr& src) +{ + BrdBase::ptr_type> b; + b.src = shrinkPtr(src); + b.rows = getRows(src); + b.cols = getCols(src); + return b; +} + +// BrdWrap + +struct BrdWrap +{ + __device__ __forceinline__ static int idx_low(int i, int len) + { + return (i >= 0) * i + (i < 0) * (i - ((i - len + 1) / len) * len); + } + + __device__ __forceinline__ static int idx_high(int i, int len) + { + return (i < len) * i + (i >= len) * (i % len); + } +}; + +template +__host__ BrdBase::ptr_type> brdWrap(const SrcPtr& src) +{ + BrdBase::ptr_type> b; + b.src = shrinkPtr(src); + b.rows = getRows(src); + b.cols = getCols(src); + return b; +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/ptr2d/glob.hpp b/modules/cudev/include/opencv2/cudev/ptr2d/glob.hpp new file mode 100644 index 0000000000..7304a8c7f5 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/ptr2d/glob.hpp @@ -0,0 +1,111 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_PTR2D_GLOB_HPP__ +#define __OPENCV_CUDEV_PTR2D_GLOB_HPP__ + +#include "../common.hpp" +#include "traits.hpp" + +namespace cv { namespace cudev { + +template struct GlobPtr +{ + typedef T value_type; + typedef int index_type; + + T* data; + size_t step; + + __device__ __forceinline__ T* row(int y) { return ( T*)( ( uchar*)data + y * step); } + __device__ __forceinline__ const T* row(int y) const { return (const T*)( (const uchar*)data + y * step); } + + __device__ __forceinline__ T& operator ()(int y, int x) { return row(y)[x]; } + __device__ __forceinline__ const T& operator ()(int y, int x) const { return row(y)[x]; } +}; + +template struct GlobPtrSz : GlobPtr +{ + int rows, cols; +}; + +template +__host__ GlobPtr globPtr(T* data, size_t step) +{ + GlobPtr p; + p.data = data; + p.step = step; + return p; +} + +template +__host__ GlobPtrSz globPtr(T* data, size_t step, int rows, int cols) +{ + GlobPtrSz p; + p.data = data; + p.step = step; + p.rows = rows; + p.cols = cols; + return p; +} + +template +__host__ GlobPtrSz globPtr(const GpuMat& mat) +{ + GlobPtrSz p; + p.data = (T*) mat.data; + p.step = mat.step; + p.rows = mat.rows; + p.cols = mat.cols; + return p; +} + +template struct PtrTraits< GlobPtrSz > : PtrTraitsBase, GlobPtr > +{ +}; + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/ptr2d/gpumat.hpp b/modules/cudev/include/opencv2/cudev/ptr2d/gpumat.hpp new file mode 100644 index 0000000000..50bb0874f1 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/ptr2d/gpumat.hpp @@ -0,0 +1,161 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_PTR2D_GPUMAT_HPP__ +#define __OPENCV_CUDEV_PTR2D_GPUMAT_HPP__ + +#include "../common.hpp" +#include "../util/vec_traits.hpp" +#include "../expr/expr.hpp" +#include "glob.hpp" + +namespace cv { namespace cudev { + +template +class GpuMat_ : public GpuMat +{ +public: + typedef T value_type; + + //! default constructor + __host__ GpuMat_(); + + //! constructs GpuMat of the specified size + __host__ GpuMat_(int arows, int acols); + __host__ explicit GpuMat_(Size asize); + + //! constucts GpuMat and fills it with the specified value + __host__ GpuMat_(int arows, int acols, Scalar val); + __host__ GpuMat_(Size asize, Scalar val); + + //! copy constructor + __host__ GpuMat_(const GpuMat_& m); + + //! copy/conversion contructor. If m is of different type, it's converted + __host__ explicit GpuMat_(const GpuMat& m); + + //! constructs a matrix on top of user-allocated data. step is in bytes(!!!), regardless of the type + __host__ GpuMat_(int arows, int acols, T* adata, size_t astep = Mat::AUTO_STEP); + __host__ GpuMat_(Size asize, T* adata, size_t astep = Mat::AUTO_STEP); + + //! selects a submatrix + __host__ GpuMat_(const GpuMat_& m, Range arowRange, Range acolRange); + __host__ GpuMat_(const GpuMat_& m, Rect roi); + + //! builds GpuMat from host memory (Blocking call) + __host__ explicit GpuMat_(InputArray arr); + + //! assignment operators + __host__ GpuMat_& operator =(const GpuMat_& m); + + //! allocates new GpuMat data unless the GpuMat already has specified size and type + __host__ void create(int arows, int acols); + __host__ void create(Size asize); + + //! swaps with other smart pointer + __host__ void swap(GpuMat_& mat); + + //! pefroms upload data to GpuMat (Blocking call) + __host__ void upload(InputArray arr); + + //! pefroms upload data to GpuMat (Non-Blocking call) + __host__ void upload(InputArray arr, Stream& stream); + + //! convert to GlobPtr + __host__ operator GlobPtrSz() const; + __host__ operator GlobPtr() const; + + //! overridden forms of GpuMat::row() etc. + __host__ GpuMat_ clone() const; + __host__ GpuMat_ row(int y) const; + __host__ GpuMat_ col(int x) const; + __host__ GpuMat_ rowRange(int startrow, int endrow) const; + __host__ GpuMat_ rowRange(Range r) const; + __host__ GpuMat_ colRange(int startcol, int endcol) const; + __host__ GpuMat_ colRange(Range r) const; + __host__ GpuMat_ operator ()(Range rowRange, Range colRange) const; + __host__ GpuMat_ operator ()(Rect roi) const; + __host__ GpuMat_& adjustROI(int dtop, int dbottom, int dleft, int dright); + + //! overridden forms of GpuMat::elemSize() etc. + __host__ size_t elemSize() const; + __host__ size_t elemSize1() const; + __host__ int type() const; + __host__ int depth() const; + __host__ int channels() const; + __host__ size_t step1() const; + + //! returns step()/sizeof(T) + __host__ size_t stepT() const; + + //! more convenient forms of row and element access operators + __host__ T* operator [](int y); + __host__ const T* operator [](int y) const; + + //! expression templates + template __host__ GpuMat_(const Expr& expr); + template __host__ GpuMat_& operator =(const Expr& expr); + template __host__ GpuMat_& assign(const Expr& expr, Stream& stream); +}; + +//! creates alternative GpuMat header for the same data, with different +//! number of channels and/or different number of rows. see cvReshape. +template +__host__ GpuMat_::elem_type, cn>::type> +reshape_(const GpuMat_& mat, int rows = 0) +{ + GpuMat_::elem_type, cn>::type> dst(mat.reshape(cn, rows)); + return dst; +} + +template struct PtrTraits< GpuMat_ > : PtrTraitsBase, GlobPtr > +{ +}; + +}} + +#include "detail/gpumat.hpp" + +#endif diff --git a/modules/cudev/include/opencv2/cudev/ptr2d/interpolation.hpp b/modules/cudev/include/opencv2/cudev/ptr2d/interpolation.hpp new file mode 100644 index 0000000000..e86d7191ed --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/ptr2d/interpolation.hpp @@ -0,0 +1,385 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_PTR2D_INTERPOLATION_HPP__ +#define __OPENCV_CUDEV_PTR2D_INTERPOLATION_HPP__ + +#include "../common.hpp" +#include "../util/vec_traits.hpp" +#include "../util/saturate_cast.hpp" +#include "../util/type_traits.hpp" +#include "../util/limits.hpp" +#include "traits.hpp" + +namespace cv { namespace cudev { + +// Nearest + +template struct NearestInterPtr +{ + typedef typename PtrTraits::value_type value_type; + typedef float index_type; + + SrcPtr src; + + __device__ __forceinline__ typename PtrTraits::value_type operator ()(float y, float x) const + { + return src(__float2int_rn(y), __float2int_rn(x)); + } +}; + +template struct NearestInterPtrSz : NearestInterPtr +{ + int rows, cols; +}; + +template +__host__ NearestInterPtrSz::ptr_type> interNearest(const SrcPtr& src) +{ + NearestInterPtrSz::ptr_type> i; + i.src = shrinkPtr(src); + i.rows = getRows(src); + i.cols = getCols(src); + return i; +} + +template struct PtrTraits< NearestInterPtrSz > : PtrTraitsBase, NearestInterPtr > +{ +}; + +// Linear + +template struct LinearInterPtr +{ + typedef typename PtrTraits::value_type value_type; + typedef float index_type; + + SrcPtr src; + + __device__ typename PtrTraits::value_type operator ()(float y, float x) const + { + typedef typename PtrTraits::value_type src_type; + typedef typename VecTraits::elem_type src_elem_type; + typedef typename LargerType::type work_elem_type; + typedef typename MakeVec::cn>::type work_type; + + work_type out = VecTraits::all(0); + + const int x1 = __float2int_rd(x); + const int y1 = __float2int_rd(y); + const int x2 = x1 + 1; + const int y2 = y1 + 1; + + typename PtrTraits::value_type src_reg = src(y1, x1); + out = out + src_reg * static_cast((x2 - x) * (y2 - y)); + + src_reg = src(y1, x2); + out = out + src_reg * static_cast((x - x1) * (y2 - y)); + + src_reg = src(y2, x1); + out = out + src_reg * static_cast((x2 - x) * (y - y1)); + + src_reg = src(y2, x2); + out = out + src_reg * static_cast((x - x1) * (y - y1)); + + return saturate_cast::value_type>(out); + } +}; + +template struct LinearInterPtrSz : LinearInterPtr +{ + int rows, cols; +}; + +template +__host__ LinearInterPtrSz::ptr_type> interLinear(const SrcPtr& src) +{ + LinearInterPtrSz::ptr_type> i; + i.src = shrinkPtr(src); + i.rows = getRows(src); + i.cols = getCols(src); + return i; +} + +template struct PtrTraits< LinearInterPtrSz > : PtrTraitsBase, LinearInterPtr > +{ +}; + +// Cubic + +template struct CubicInterPtr +{ + typedef typename PtrTraits::value_type value_type; + typedef float index_type; + + SrcPtr src; + + __device__ static float bicubicCoeff(float x_) + { + float x = ::fabsf(x_); + if (x <= 1.0f) + { + return x * x * (1.5f * x - 2.5f) + 1.0f; + } + else if (x < 2.0f) + { + return x * (x * (-0.5f * x + 2.5f) - 4.0f) + 2.0f; + } + else + { + return 0.0f; + } + } + + __device__ typename PtrTraits::value_type operator ()(float y, float x) const + { + typedef typename PtrTraits::value_type src_type; + typedef typename VecTraits::elem_type src_elem_type; + typedef typename LargerType::type work_elem_type; + typedef typename MakeVec::cn>::type work_type; + + const float xmin = ::ceilf(x - 2.0f); + const float xmax = ::floorf(x + 2.0f); + + const float ymin = ::ceilf(y - 2.0f); + const float ymax = ::floorf(y + 2.0f); + + work_type sum = VecTraits::all(0); + float wsum = 0.0f; + + for (float cy = ymin; cy <= ymax; cy += 1.0f) + { + for (float cx = xmin; cx <= xmax; cx += 1.0f) + { + typename PtrTraits::value_type src_reg = src(__float2int_rd(cy), __float2int_rd(cx)); + const float w = bicubicCoeff(x - cx) * bicubicCoeff(y - cy); + + sum = sum + static_cast(w) * src_reg; + wsum += w; + } + } + + work_type res = (wsum > numeric_limits::epsilon()) ? VecTraits::all(0) : sum / static_cast(wsum); + + return saturate_cast::value_type>(res); + } +}; + +template struct CubicInterPtrSz : CubicInterPtr +{ + int rows, cols; +}; + +template +__host__ CubicInterPtrSz::ptr_type> interCubic(const SrcPtr& src) +{ + CubicInterPtrSz::ptr_type> i; + i.src = shrinkPtr(src); + i.rows = getRows(src); + i.cols = getCols(src); + return i; +} + +template struct PtrTraits< CubicInterPtrSz > : PtrTraitsBase, CubicInterPtr > +{ +}; + +// IntegerArea + +template struct IntegerAreaInterPtr +{ + typedef typename PtrTraits::value_type value_type; + typedef float index_type; + + SrcPtr src; + int area_width, area_height; + + __device__ typename PtrTraits::value_type operator ()(float y, float x) const + { + typedef typename PtrTraits::value_type src_type; + typedef typename VecTraits::elem_type src_elem_type; + typedef typename LargerType::type work_elem_type; + typedef typename MakeVec::cn>::type work_type; + + const int sx1 = __float2int_rd(x); + const int sx2 = sx1 + area_width; + + const int sy1 = __float2int_rd(y); + const int sy2 = sy1 + area_height; + + work_type out = VecTraits::all(0); + + for (int dy = sy1; dy < sy2; ++dy) + { + for (int dx = sx1; dx < sx2; ++dx) + { + out = out + saturate_cast(src(dy, dx)); + } + } + + const work_elem_type scale = 1.0f / (area_width * area_height); + + return saturate_cast::value_type>(out * scale); + } +}; + +template struct IntegerAreaInterPtrSz : IntegerAreaInterPtr +{ + int rows, cols; +}; + +template +__host__ IntegerAreaInterPtrSz::ptr_type> interArea(const SrcPtr& src, Size areaSize) +{ + IntegerAreaInterPtrSz::ptr_type> i; + i.src = shrinkPtr(src); + i.area_width = areaSize.width; + i.area_height = areaSize.height; + i.rows = getRows(src); + i.cols = getCols(src); + return i; +} + +template struct PtrTraits< IntegerAreaInterPtrSz > : PtrTraitsBase, IntegerAreaInterPtr > +{ +}; + +// CommonArea + +template struct CommonAreaInterPtr +{ + typedef typename PtrTraits::value_type value_type; + typedef float index_type; + + SrcPtr src; + float area_width, area_height; + + __device__ typename PtrTraits::value_type operator ()(float y, float x) const + { + typedef typename PtrTraits::value_type src_type; + typedef typename VecTraits::elem_type src_elem_type; + typedef typename LargerType::type work_elem_type; + typedef typename MakeVec::cn>::type work_type; + + const float fsx1 = x; + const float fsx2 = fsx1 + area_width; + + const int sx1 = __float2int_rd(fsx1); + const int sx2 = __float2int_ru(fsx2); + + const float fsy1 = y; + const float fsy2 = fsy1 + area_height; + + const int sy1 = __float2int_rd(fsy1); + const int sy2 = __float2int_ru(fsy2); + + work_type out = VecTraits::all(0); + + for (int dy = sy1; dy < sy2; ++dy) + { + for (int dx = sx1; dx < sx2; ++dx) + out = out + saturate_cast(src(dy, dx)); + + if (sx1 > fsx1) + out = out + saturate_cast(src(dy, sx1 - 1)) * static_cast(sx1 - fsx1); + + if (sx2 < fsx2) + out = out + saturate_cast(src(dy, sx2)) * static_cast(fsx2 - sx2); + } + + if (sy1 > fsy1) + { + for (int dx = sx1; dx < sx2; ++dx) + out = out + saturate_cast(src(sy1 - 1, dx)) * static_cast(sy1 - fsy1); + } + + if (sy2 < fsy2) + { + for (int dx = sx1; dx < sx2; ++dx) + out = out + saturate_cast(src(sy2, dx)) * static_cast(fsy2 - sy2); + } + + if ((sy1 > fsy1) && (sx1 > fsx1)) + out = out + saturate_cast(src(sy1 - 1, sx1 - 1)) * static_cast((sy1 - fsy1) * (sx1 - fsx1)); + + if ((sy1 > fsy1) && (sx2 < fsx2)) + out = out + saturate_cast(src(sy1 - 1, sx2)) * static_cast((sy1 - fsy1) * (fsx2 - sx2)); + + if ((sy2 < fsy2) && (sx2 < fsx2)) + out = out + saturate_cast(src(sy2, sx2)) * static_cast((fsy2 - sy2) * (fsx2 - sx2)); + + if ((sy2 < fsy2) && (sx1 > fsx1)) + out = out + saturate_cast(src(sy2, sx1 - 1)) * static_cast((fsy2 - sy2) * (sx1 - fsx1)); + + const work_elem_type scale = 1.0f / (area_width * area_height); + + return saturate_cast::value_type>(out * scale); + } +}; + +template struct CommonAreaInterPtrSz : CommonAreaInterPtr +{ + int rows, cols; +}; + +template +__host__ CommonAreaInterPtrSz::ptr_type> interArea(const SrcPtr& src, Size2f areaSize) +{ + CommonAreaInterPtrSz::ptr_type> i; + i.src = shrinkPtr(src); + i.area_width = areaSize.width; + i.area_height = areaSize.height; + i.rows = getRows(src); + i.cols = getCols(src); + return i; +} + +template struct PtrTraits< CommonAreaInterPtrSz > : PtrTraitsBase, CommonAreaInterPtr > +{ +}; + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/ptr2d/lut.hpp b/modules/cudev/include/opencv2/cudev/ptr2d/lut.hpp new file mode 100644 index 0000000000..e47719c6ec --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/ptr2d/lut.hpp @@ -0,0 +1,100 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_PTR2D_LUT_HPP__ +#define __OPENCV_CUDEV_PTR2D_LUT_HPP__ + +#include "../common.hpp" +#include "../grid/copy.hpp" +#include "traits.hpp" +#include "gpumat.hpp" + +namespace cv { namespace cudev { + +template struct LutPtr +{ + typedef typename PtrTraits::value_type value_type; + typedef typename PtrTraits::index_type index_type; + + SrcPtr src; + TablePtr tbl; + + __device__ __forceinline__ typename PtrTraits::value_type operator ()(typename PtrTraits::index_type y, typename PtrTraits::index_type x) const + { + return tbl(0, src(y, x)); + } +}; + +template struct LutPtrSz : LutPtr +{ + int rows, cols; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridCopy(*this, dst, stream); + } +}; + +template +__host__ LutPtrSz::ptr_type, typename PtrTraits::ptr_type> lutPtr(const SrcPtr& src, const TablePtr& tbl) +{ + CV_Assert( getRows(tbl) == 1 ); + + LutPtrSz::ptr_type, typename PtrTraits::ptr_type> ptr; + ptr.src = shrinkPtr(src); + ptr.tbl = shrinkPtr(tbl); + ptr.rows = getRows(src); + ptr.cols = getCols(src); + return ptr; +} + +template struct PtrTraits< LutPtrSz > : PtrTraitsBase, LutPtr > +{ +}; + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/ptr2d/mask.hpp b/modules/cudev/include/opencv2/cudev/ptr2d/mask.hpp new file mode 100644 index 0000000000..1ff3371931 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/ptr2d/mask.hpp @@ -0,0 +1,67 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_PTR2D_MASK_HPP__ +#define __OPENCV_CUDEV_PTR2D_MASK_HPP__ + +#include "../common.hpp" +#include "traits.hpp" + +namespace cv { namespace cudev { + +struct WithOutMask +{ + typedef bool value_type; + typedef int index_type; + + __device__ __forceinline__ bool operator ()(int, int) const + { + return true; + } +}; + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/ptr2d/remap.hpp b/modules/cudev/include/opencv2/cudev/ptr2d/remap.hpp new file mode 100644 index 0000000000..db2669a40a --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/ptr2d/remap.hpp @@ -0,0 +1,154 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_PTR2D_REMAP_HPP__ +#define __OPENCV_CUDEV_PTR2D_REMAP_HPP__ + +#include "opencv2/core/base.hpp" +#include "../common.hpp" +#include "../grid/copy.hpp" +#include "traits.hpp" +#include "gpumat.hpp" + +namespace cv { namespace cudev { + +template struct RemapPtr1 +{ + typedef typename PtrTraits::value_type value_type; + typedef typename PtrTraits::index_type index_type; + + SrcPtr src; + MapPtr map; + + __device__ __forceinline__ typename PtrTraits::value_type operator ()(typename PtrTraits::index_type y, typename PtrTraits::index_type x) const + { + const typename PtrTraits::value_type coord = map(y, x); + return src(coord.y, coord.x); + } +}; + +template struct RemapPtr2 +{ + typedef typename PtrTraits::value_type value_type; + typedef typename PtrTraits::index_type index_type; + + SrcPtr src; + MapXPtr mapx; + MapYPtr mapy; + + __device__ __forceinline__ typename PtrTraits::value_type operator ()(typename PtrTraits::index_type y, typename PtrTraits::index_type x) const + { + const typename PtrTraits::value_type nx = mapx(y, x); + const typename PtrTraits::value_type ny = mapy(y, x); + return src(ny, nx); + } +}; + +template struct RemapPtr1Sz : RemapPtr1 +{ + int rows, cols; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridCopy(*this, dst, stream); + } +}; + +template struct RemapPtr2Sz : RemapPtr2 +{ + int rows, cols; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridCopy(*this, dst, stream); + } +}; + +template +__host__ RemapPtr1Sz::ptr_type, typename PtrTraits::ptr_type> +remapPtr(const SrcPtr& src, const MapPtr& map) +{ + const int rows = getRows(map); + const int cols = getCols(map); + + RemapPtr1Sz::ptr_type, typename PtrTraits::ptr_type> r; + r.src = shrinkPtr(src); + r.map = shrinkPtr(map); + r.rows = rows; + r.cols = cols; + return r; +} + +template +__host__ RemapPtr2Sz::ptr_type, typename PtrTraits::ptr_type, typename PtrTraits::ptr_type> +remapPtr(const SrcPtr& src, const MapXPtr& mapx, const MapYPtr& mapy) +{ + const int rows = getRows(mapx); + const int cols = getCols(mapx); + + CV_Assert( getRows(mapy) == rows && getCols(mapy) == cols ); + + RemapPtr2Sz::ptr_type, typename PtrTraits::ptr_type, typename PtrTraits::ptr_type> r; + r.src = shrinkPtr(src); + r.mapx = shrinkPtr(mapx); + r.mapy = shrinkPtr(mapy); + r.rows = rows; + r.cols = cols; + return r; +} + +template struct PtrTraits< RemapPtr1Sz > : PtrTraitsBase, RemapPtr1 > +{ +}; + +template struct PtrTraits< RemapPtr2Sz > : PtrTraitsBase, RemapPtr2 > +{ +}; + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/ptr2d/resize.hpp b/modules/cudev/include/opencv2/cudev/ptr2d/resize.hpp new file mode 100644 index 0000000000..10a4bad906 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/ptr2d/resize.hpp @@ -0,0 +1,103 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_PTR2D_RESIZE_HPP__ +#define __OPENCV_CUDEV_PTR2D_RESIZE_HPP__ + +#include "opencv2/core/base.hpp" +#include "../common.hpp" +#include "../grid/copy.hpp" +#include "traits.hpp" +#include "gpumat.hpp" + +namespace cv { namespace cudev { + +template struct ResizePtr +{ + typedef typename PtrTraits::value_type value_type; + typedef typename PtrTraits::index_type index_type; + + SrcPtr src; + float fx, fy; + + __device__ __forceinline__ typename PtrTraits::value_type operator ()(typename PtrTraits::index_type y, typename PtrTraits::index_type x) const + { + const float yn = static_cast(y * fy); + const float xn = static_cast(x * fx); + + return src(yn, xn); + } +}; + +template struct ResizePtrSz : ResizePtr +{ + int rows, cols; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridCopy(*this, dst, stream); + } +}; + +template +__host__ ResizePtrSz::ptr_type> resizePtr(const SrcPtr& src, float fx, float fy) +{ + ResizePtrSz::ptr_type> r; + r.src = shrinkPtr(src); + r.fx = 1.0f / fx; + r.fy = 1.0f / fy; + r.rows = cv::saturate_cast(getRows(src) * fy); + r.cols = cv::saturate_cast(getCols(src) * fx); + return r; +} + +template struct PtrTraits< ResizePtrSz > : PtrTraitsBase, ResizePtr > +{ +}; + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/ptr2d/texture.hpp b/modules/cudev/include/opencv2/cudev/ptr2d/texture.hpp new file mode 100644 index 0000000000..b01a2c7b84 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/ptr2d/texture.hpp @@ -0,0 +1,148 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_PTR2D_TEXTURE_HPP__ +#define __OPENCV_CUDEV_PTR2D_TEXTURE_HPP__ + +#include +#include "../common.hpp" +#include "glob.hpp" +#include "gpumat.hpp" +#include "traits.hpp" + +namespace cv { namespace cudev { + +template struct TexturePtr +{ + typedef T value_type; + typedef float index_type; + + cudaTextureObject_t texObj; + + __device__ __forceinline__ T operator ()(float y, float x) const + { + return tex2D(texObj, x, y); + } +}; + +template struct Texture : TexturePtr +{ + int rows, cols; + + __host__ explicit Texture(const GlobPtrSz& mat, + bool normalizedCoords = false, + cudaTextureFilterMode filterMode = cudaFilterModePoint, + cudaTextureAddressMode addressMode = cudaAddressModeClamp) + { + CV_Assert( deviceSupports(FEATURE_SET_COMPUTE_30) ); + + rows = mat.rows; + cols = mat.cols; + + cudaResourceDesc texRes; + std::memset(&texRes, 0, sizeof(texRes)); + texRes.resType = cudaResourceTypePitch2D; + texRes.res.pitch2D.devPtr = mat.data; + texRes.res.pitch2D.height = mat.rows; + texRes.res.pitch2D.width = mat.cols; + texRes.res.pitch2D.pitchInBytes = mat.step; + texRes.res.pitch2D.desc = cudaCreateChannelDesc(); + + cudaTextureDesc texDescr; + std::memset(&texDescr, 0, sizeof(texDescr)); + texDescr.addressMode[0] = addressMode; + texDescr.addressMode[1] = addressMode; + texDescr.addressMode[2] = addressMode; + texDescr.filterMode = filterMode; + texDescr.readMode = cudaReadModeElementType; + texDescr.normalizedCoords = normalizedCoords; + + CV_CUDEV_SAFE_CALL( cudaCreateTextureObject(&this->texObj, &texRes, &texDescr, 0) ); + } + + __host__ explicit Texture(const GpuMat_& mat, + bool normalizedCoords = false, + cudaTextureFilterMode filterMode = cudaFilterModePoint, + cudaTextureAddressMode addressMode = cudaAddressModeClamp) + { + CV_Assert( deviceSupports(FEATURE_SET_COMPUTE_30) ); + + rows = mat.rows; + cols = mat.cols; + + cudaResourceDesc texRes; + std::memset(&texRes, 0, sizeof(texRes)); + texRes.resType = cudaResourceTypePitch2D; + texRes.res.pitch2D.devPtr = mat.data; + texRes.res.pitch2D.height = mat.rows; + texRes.res.pitch2D.width = mat.cols; + texRes.res.pitch2D.pitchInBytes = mat.step; + texRes.res.pitch2D.desc = cudaCreateChannelDesc(); + + cudaTextureDesc texDescr; + std::memset(&texDescr, 0, sizeof(texDescr)); + texDescr.addressMode[0] = addressMode; + texDescr.addressMode[1] = addressMode; + texDescr.addressMode[2] = addressMode; + texDescr.filterMode = filterMode; + texDescr.readMode = cudaReadModeElementType; + texDescr.normalizedCoords = normalizedCoords; + + CV_CUDEV_SAFE_CALL( cudaCreateTextureObject(&this->texObj, &texRes, &texDescr, 0) ); + } + + __host__ ~Texture() + { + cudaDestroyTextureObject(this->texObj); + } +}; + +template struct PtrTraits< Texture > : PtrTraitsBase, TexturePtr > +{ +}; + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/ptr2d/traits.hpp b/modules/cudev/include/opencv2/cudev/ptr2d/traits.hpp new file mode 100644 index 0000000000..7fb4b32b17 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/ptr2d/traits.hpp @@ -0,0 +1,101 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_PTR2D_TRAITS_HPP__ +#define __OPENCV_CUDEV_PTR2D_TRAITS_HPP__ + +#include "../common.hpp" + +namespace cv { namespace cudev { + +template struct PtrTraitsBase +{ + typedef Ptr2DSz ptr_sz_type; + typedef Ptr2D ptr_type; + + typedef typename Ptr2D::value_type value_type; + typedef typename Ptr2D::index_type index_type; + + __host__ static Ptr2D shrinkPtr(const Ptr2DSz& ptr) + { + return ptr; + } + + __host__ static int getRows(const Ptr2DSz& ptr) + { + return ptr.rows; + } + + __host__ static int getCols(const Ptr2DSz& ptr) + { + return ptr.cols; + } +}; + +template struct PtrTraits : PtrTraitsBase +{ +}; + +template +__host__ typename PtrTraits::ptr_type shrinkPtr(const Ptr2DSz& ptr) +{ + return PtrTraits::shrinkPtr(ptr); +} + +template +__host__ int getRows(const Ptr2DSz& ptr) +{ + return PtrTraits::getRows(ptr); +} + +template +__host__ int getCols(const Ptr2DSz& ptr) +{ + return PtrTraits::getCols(ptr); +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/ptr2d/transform.hpp b/modules/cudev/include/opencv2/cudev/ptr2d/transform.hpp new file mode 100644 index 0000000000..f540e75213 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/ptr2d/transform.hpp @@ -0,0 +1,151 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_PTR2D_TRANSFORM_HPP__ +#define __OPENCV_CUDEV_PTR2D_TRANSFORM_HPP__ + +#include "../common.hpp" +#include "../grid/copy.hpp" +#include "traits.hpp" +#include "gpumat.hpp" + +namespace cv { namespace cudev { + +// UnaryTransformPtr + +template struct UnaryTransformPtr +{ + typedef typename Op::result_type value_type; + typedef typename PtrTraits::index_type index_type; + + SrcPtr src; + Op op; + + __device__ __forceinline__ typename Op::result_type operator ()(typename PtrTraits::index_type y, typename PtrTraits::index_type x) const + { + return op(src(y, x)); + } +}; + +template struct UnaryTransformPtrSz : UnaryTransformPtr +{ + int rows, cols; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridCopy(*this, dst, stream); + } +}; + +template +__host__ UnaryTransformPtrSz::ptr_type, Op> +transformPtr(const SrcPtr& src, const Op& op) +{ + UnaryTransformPtrSz::ptr_type, Op> ptr; + ptr.src = shrinkPtr(src); + ptr.op = op; + ptr.rows = getRows(src); + ptr.cols = getCols(src); + return ptr; +} + +template struct PtrTraits< UnaryTransformPtrSz > : PtrTraitsBase, UnaryTransformPtr > +{ +}; + +// BinaryTransformPtr + +template struct BinaryTransformPtr +{ + typedef typename Op::result_type value_type; + typedef typename PtrTraits::index_type index_type; + + Src1Ptr src1; + Src2Ptr src2; + Op op; + + __device__ __forceinline__ typename Op::result_type operator ()(typename PtrTraits::index_type y, typename PtrTraits::index_type x) const + { + return op(src1(y, x), src2(y, x)); + } +}; + +template struct BinaryTransformPtrSz : BinaryTransformPtr +{ + int rows, cols; + + template + __host__ void assignTo(GpuMat_& dst, Stream& stream = Stream::Null()) const + { + gridCopy(*this, dst, stream); + } +}; + +template +__host__ BinaryTransformPtrSz::ptr_type, typename PtrTraits::ptr_type, Op> +transformPtr(const Src1Ptr& src1, const Src2Ptr& src2, const Op& op) +{ + const int rows = getRows(src1); + const int cols = getCols(src1); + + CV_Assert( getRows(src2) == rows && getCols(src2) == cols ); + + BinaryTransformPtrSz::ptr_type, typename PtrTraits::ptr_type, Op> ptr; + ptr.src1 = shrinkPtr(src1); + ptr.src2 = shrinkPtr(src2); + ptr.op = op; + ptr.rows = rows; + ptr.cols = cols; + return ptr; +} + +template struct PtrTraits< BinaryTransformPtrSz > : PtrTraitsBase, BinaryTransformPtr > +{ +}; + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/ptr2d/warping.hpp b/modules/cudev/include/opencv2/cudev/ptr2d/warping.hpp new file mode 100644 index 0000000000..80e5fbeef0 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/ptr2d/warping.hpp @@ -0,0 +1,152 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_PTR2D_WARPING_HPP__ +#define __OPENCV_CUDEV_PTR2D_WARPING_HPP__ + +#include "../common.hpp" +#include "traits.hpp" +#include "remap.hpp" +#include "gpumat.hpp" + +namespace cv { namespace cudev { + +// affine + +struct AffineMapPtr +{ + typedef float2 value_type; + typedef float index_type; + + const float* warpMat; + + __device__ __forceinline__ float2 operator ()(float y, float x) const + { + const float xcoo = warpMat[0] * x + warpMat[1] * y + warpMat[2]; + const float ycoo = warpMat[3] * x + warpMat[4] * y + warpMat[5]; + + return make_float2(xcoo, ycoo); + } +}; + +struct AffineMapPtrSz : AffineMapPtr +{ + int rows, cols; +}; + +template <> struct PtrTraits : PtrTraitsBase +{ +}; + +__host__ static AffineMapPtrSz affineMap(Size dstSize, const GpuMat_& warpMat) +{ + CV_Assert( warpMat.rows == 2 && warpMat.cols == 3 ); + CV_Assert( warpMat.isContinuous() ); + + AffineMapPtrSz map; + map.warpMat = warpMat[0]; + map.rows = dstSize.height; + map.cols = dstSize.width; + return map; +} + +template +__host__ RemapPtr1Sz::ptr_type, AffineMapPtr> +warpAffinePtr(const SrcPtr& src, Size dstSize, const GpuMat_& warpMat) +{ + return remapPtr(src, affineMap(dstSize, warpMat)); +} + +// perspective + +struct PerspectiveMapPtr +{ + typedef float2 value_type; + typedef float index_type; + + const float* warpMat; + + __device__ __forceinline__ float2 operator ()(float y, float x) const + { + const float coeff = 1.0f / (warpMat[6] * x + warpMat[7] * y + warpMat[8]); + + const float xcoo = coeff * (warpMat[0] * x + warpMat[1] * y + warpMat[2]); + const float ycoo = coeff * (warpMat[3] * x + warpMat[4] * y + warpMat[5]); + + return make_float2(xcoo, ycoo); + } +}; + +struct PerspectiveMapPtrSz : PerspectiveMapPtr +{ + int rows, cols; +}; + +template <> struct PtrTraits : PtrTraitsBase +{ +}; + +__host__ static PerspectiveMapPtrSz perspectiveMap(Size dstSize, const GpuMat_& warpMat) +{ + CV_Assert( warpMat.rows == 3 && warpMat.cols == 3 ); + CV_Assert( warpMat.isContinuous() ); + + PerspectiveMapPtrSz map; + map.warpMat = warpMat[0]; + map.rows = dstSize.height; + map.cols = dstSize.width; + return map; +} + +template +__host__ RemapPtr1Sz::ptr_type, PerspectiveMapPtr> +warpPerspectivePtr(const SrcPtr& src, Size dstSize, const GpuMat_& warpMat) +{ + return remapPtr(src, perspectiveMap(dstSize, warpMat)); +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/ptr2d/zip.hpp b/modules/cudev/include/opencv2/cudev/ptr2d/zip.hpp new file mode 100644 index 0000000000..934939f624 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/ptr2d/zip.hpp @@ -0,0 +1,173 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_PTR2D_ZIP_HPP__ +#define __OPENCV_CUDEV_PTR2D_ZIP_HPP__ + +#include "../common.hpp" +#include "../util/tuple.hpp" +#include "traits.hpp" + +namespace cv { namespace cudev { + +template struct ZipPtr; + +template struct ZipPtr< tuple > : tuple +{ + typedef tuple::value_type, + typename PtrTraits::value_type> value_type; + typedef typename PtrTraits::index_type index_type; + + __host__ __device__ __forceinline__ ZipPtr() {} + __host__ __device__ __forceinline__ ZipPtr(const tuple& t) : tuple(t) {} + + __device__ __forceinline__ value_type operator ()(index_type y, index_type x) const + { + return make_tuple(cv::cudev::get<0>(*this)(y, x), cv::cudev::get<1>(*this)(y, x)); + } +}; + +template struct ZipPtr< tuple > : tuple +{ + typedef tuple::value_type, + typename PtrTraits::value_type, + typename PtrTraits::value_type> value_type; + typedef typename PtrTraits::index_type index_type; + + __host__ __device__ __forceinline__ ZipPtr() {} + __host__ __device__ __forceinline__ ZipPtr(const tuple& t) : tuple(t) {} + + __device__ __forceinline__ value_type operator ()(index_type y, index_type x) const + { + return make_tuple(cv::cudev::get<0>(*this)(y, x), cv::cudev::get<1>(*this)(y, x), cv::cudev::get<2>(*this)(y, x)); + } +}; + +template struct ZipPtr< tuple > : tuple +{ + typedef tuple::value_type, + typename PtrTraits::value_type, + typename PtrTraits::value_type, + typename PtrTraits::value_type> value_type; + typedef typename PtrTraits::index_type index_type; + + __host__ __device__ __forceinline__ ZipPtr() {} + __host__ __device__ __forceinline__ ZipPtr(const tuple& t) : tuple(t) {} + + __device__ __forceinline__ value_type operator ()(index_type y, index_type x) const + { + return make_tuple(cv::cudev::get<0>(*this)(y, x), cv::cudev::get<1>(*this)(y, x), cv::cudev::get<2>(*this)(y, x), cv::cudev::get<3>(*this)(y, x)); + } +}; + +template struct ZipPtrSz : ZipPtr +{ + int rows, cols; + + __host__ __device__ __forceinline__ ZipPtrSz() {} + __host__ __device__ __forceinline__ ZipPtrSz(const PtrTuple& t) : ZipPtr(t) {} +}; + +template +__host__ ZipPtrSz< tuple::ptr_type, typename PtrTraits::ptr_type> > +zipPtr(const Ptr0& ptr0, const Ptr1& ptr1) +{ + const int rows = getRows(ptr0); + const int cols = getCols(ptr0); + + CV_Assert( getRows(ptr1) == rows && getCols(ptr1) == cols ); + + ZipPtrSz< tuple::ptr_type, typename PtrTraits::ptr_type> > + z(make_tuple(shrinkPtr(ptr0), shrinkPtr(ptr1))); + z.rows = rows; + z.cols = cols; + + return z; +} + +template +__host__ ZipPtrSz< tuple::ptr_type, typename PtrTraits::ptr_type, typename PtrTraits::ptr_type> > +zipPtr(const Ptr0& ptr0, const Ptr1& ptr1, const Ptr2& ptr2) +{ + const int rows = getRows(ptr0); + const int cols = getCols(ptr0); + + CV_Assert( getRows(ptr1) == rows && getCols(ptr1) == cols ); + CV_Assert( getRows(ptr2) == rows && getCols(ptr2) == cols ); + + ZipPtrSz< tuple::ptr_type, typename PtrTraits::ptr_type, typename PtrTraits::ptr_type> > + z(make_tuple(shrinkPtr(ptr0), shrinkPtr(ptr1), shrinkPtr(ptr2))); + z.rows = rows; + z.cols = cols; + + return z; +} + +template +__host__ ZipPtrSz< tuple::ptr_type, typename PtrTraits::ptr_type, typename PtrTraits::ptr_type, typename PtrTraits::ptr_type> > +zipPtr(const Ptr0& ptr0, const Ptr1& ptr1, const Ptr2& ptr2, const Ptr3& ptr3) +{ + const int rows = getRows(ptr0); + const int cols = getCols(ptr0); + + CV_Assert( getRows(ptr1) == rows && getCols(ptr1) == cols ); + CV_Assert( getRows(ptr2) == rows && getCols(ptr2) == cols ); + CV_Assert( getRows(ptr3) == rows && getCols(ptr3) == cols ); + + ZipPtrSz< tuple::ptr_type, typename PtrTraits::ptr_type, typename PtrTraits::ptr_type, typename PtrTraits::ptr_type> > + z(make_tuple(shrinkPtr(ptr0), shrinkPtr(ptr1), shrinkPtr(ptr2), shrinkPtr(ptr3))); + z.rows = rows; + z.cols = cols; + + return z; +} + +template struct PtrTraits< ZipPtrSz > : PtrTraitsBase, ZipPtr > +{ +}; + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/util/atomic.hpp b/modules/cudev/include/opencv2/cudev/util/atomic.hpp new file mode 100644 index 0000000000..f650c68ec2 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/util/atomic.hpp @@ -0,0 +1,156 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_UTIL_ATOMIC_HPP__ +#define __OPENCV_CUDEV_UTIL_ATOMIC_HPP__ + +#include "../common.hpp" + +namespace cv { namespace cudev { + +// atomicAdd + +__device__ __forceinline__ int atomicAdd(int* address, int val) +{ + return ::atomicAdd(address, val); +} + +__device__ __forceinline__ uint atomicAdd(uint* address, uint val) +{ + return ::atomicAdd(address, val); +} + +__device__ __forceinline__ float atomicAdd(float* address, float val) +{ + return ::atomicAdd(address, val); +} + +__device__ static double atomicAdd(double* address, double val) +{ + unsigned long long int* address_as_ull = (unsigned long long int*) address; + unsigned long long int old = *address_as_ull, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_ull, assumed, + __double_as_longlong(val + __longlong_as_double(assumed))); + } while (assumed != old); + return __longlong_as_double(old); +} + +// atomicMin + +__device__ __forceinline__ int atomicMin(int* address, int val) +{ + return ::atomicMin(address, val); +} + +__device__ __forceinline__ uint atomicMin(uint* address, uint val) +{ + return ::atomicMin(address, val); +} + +__device__ static float atomicMin(float* address, float val) +{ + int* address_as_i = (int*) address; + int old = *address_as_i, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_i, assumed, + __float_as_int(::fminf(val, __int_as_float(assumed)))); + } while (assumed != old); + return __int_as_float(old); +} + +__device__ static double atomicMin(double* address, double val) +{ + unsigned long long int* address_as_ull = (unsigned long long int*) address; + unsigned long long int old = *address_as_ull, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_ull, assumed, + __double_as_longlong(::fmin(val, __longlong_as_double(assumed)))); + } while (assumed != old); + return __longlong_as_double(old); +} + +// atomicMax + +__device__ __forceinline__ int atomicMax(int* address, int val) +{ + return ::atomicMax(address, val); +} + +__device__ __forceinline__ uint atomicMax(uint* address, uint val) +{ + return ::atomicMax(address, val); +} + +__device__ static float atomicMax(float* address, float val) +{ + int* address_as_i = (int*) address; + int old = *address_as_i, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_i, assumed, + __float_as_int(::fmaxf(val, __int_as_float(assumed)))); + } while (assumed != old); + return __int_as_float(old); +} + +__device__ static double atomicMax(double* address, double val) +{ + unsigned long long int* address_as_ull = (unsigned long long int*) address; + unsigned long long int old = *address_as_ull, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_ull, assumed, + __double_as_longlong(::fmax(val, __longlong_as_double(assumed)))); + } while (assumed != old); + return __longlong_as_double(old); +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/util/detail/tuple.hpp b/modules/cudev/include/opencv2/cudev/util/detail/tuple.hpp new file mode 100644 index 0000000000..2fc84946bb --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/util/detail/tuple.hpp @@ -0,0 +1,175 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_UTIL_TUPLE_DETAIL_HPP__ +#define __OPENCV_CUDEV_UTIL_TUPLE_DETAIL_HPP__ + +#include + +namespace cv { namespace cudev { + +namespace tuple_detail +{ + using thrust::tuple; + using thrust::tuple_size; + using thrust::get; + using thrust::tuple_element; + using thrust::make_tuple; + using thrust::tie; + + template class CvtOp> struct ConvertTuple; + + template class CvtOp> struct ConvertTuple + { + typedef tuple< + typename CvtOp::type>::type, + typename CvtOp::type>::type + > type; + }; + + template class CvtOp> struct ConvertTuple + { + typedef tuple< + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type + > type; + }; + + template class CvtOp> struct ConvertTuple + { + typedef tuple< + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type + > type; + }; + + template class CvtOp> struct ConvertTuple + { + typedef tuple< + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type + > type; + }; + + template class CvtOp> struct ConvertTuple + { + typedef tuple< + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type + > type; + }; + + template class CvtOp> struct ConvertTuple + { + typedef tuple< + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type + > type; + }; + + template class CvtOp> struct ConvertTuple + { + typedef tuple< + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type + > type; + }; + + template class CvtOp> struct ConvertTuple + { + typedef tuple< + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type + > type; + }; + + template class CvtOp> struct ConvertTuple + { + typedef tuple< + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type, + typename CvtOp::type>::type + > type; + }; +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/util/detail/type_traits.hpp b/modules/cudev/include/opencv2/cudev/util/detail/type_traits.hpp new file mode 100644 index 0000000000..d711642836 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/util/detail/type_traits.hpp @@ -0,0 +1,238 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_UTIL_TYPE_TRAITS_DETAIL_HPP__ +#define __OPENCV_CUDEV_UTIL_TYPE_TRAITS_DETAIL_HPP__ + +#include "../../common.hpp" + +namespace cv { namespace cudev { + +namespace type_traits_detail +{ + template struct IsSignedIntergral { enum {value = 0}; }; + template <> struct IsSignedIntergral { enum {value = 1}; }; + template <> struct IsSignedIntergral { enum {value = 1}; }; + template <> struct IsSignedIntergral { enum {value = 1}; }; + + template struct IsUnsignedIntegral { enum {value = 0}; }; + template <> struct IsUnsignedIntegral { enum {value = 1}; }; + template <> struct IsUnsignedIntegral { enum {value = 1}; }; + template <> struct IsUnsignedIntegral { enum {value = 1}; }; + + template struct IsIntegral { enum {value = IsSignedIntergral::value || IsUnsignedIntegral::value}; }; + template <> struct IsIntegral { enum {value = 1}; }; + template <> struct IsIntegral { enum {value = 1}; }; + + template struct IsFloat { enum {value = 0}; }; + template <> struct IsFloat { enum {value = 1}; }; + template <> struct IsFloat { enum {value = 1}; }; + + template struct IsVec { enum {value = 0}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + + template struct AddParameterType { typedef const U& type; }; + template struct AddParameterType { typedef U& type; }; + template <> struct AddParameterType { typedef void type; }; + + // ReferenceTraits + + template struct ReferenceTraits + { + enum { value = 0 }; + typedef U type; + }; + template struct ReferenceTraits + { + enum { value = 1 }; + typedef U type; + }; + + // PointerTraits + + template struct PointerTraits + { + enum { value = 0 }; + typedef void type; + }; + template struct PointerTraits + { + enum { value = 1 }; + typedef U type; + }; + template struct PointerTraits + { + enum { value = 1 }; + typedef U type; + }; + + // UnConst + + template struct UnConst + { + typedef U type; + enum { value = 0 }; + }; + template struct UnConst + { + typedef U type; + enum { value = 1 }; + }; + template struct UnConst + { + typedef U& type; + enum { value = 1 }; + }; + + // UnVolatile + + template struct UnVolatile + { + typedef U type; + enum { value = 0 }; + }; + template struct UnVolatile + { + typedef U type; + enum { value = 1 }; + }; + template struct UnVolatile + { + typedef U& type; + enum { value = 1 }; + }; + + // IsSimpleParameter + + template struct IsSimpleParameter + { + enum { value = IsIntegral::value + || IsFloat::value + || PointerTraits::type>::value}; + }; + + // LargerDepth + + template struct SelectIf + { + typedef ThenType type; + }; + template struct SelectIf + { + typedef ElseType type; + }; + + template struct LargerDepth + { + typedef typename SelectIf= sizeof(B), A, B>::type type; + }; + template struct LargerDepth + { + typedef float type; + }; + template struct LargerDepth + { + typedef float type; + }; + template struct LargerDepth + { + typedef double type; + }; + template struct LargerDepth + { + typedef double type; + }; + template <> struct LargerDepth + { + typedef float type; + }; + template <> struct LargerDepth + { + typedef double type; + }; + template <> struct LargerDepth + { + typedef double type; + }; + template <> struct LargerDepth + { + typedef double type; + }; +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/util/limits.hpp b/modules/cudev/include/opencv2/cudev/util/limits.hpp new file mode 100644 index 0000000000..58faca6b56 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/util/limits.hpp @@ -0,0 +1,124 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_UTIL_LIMITS_HPP__ +#define __OPENCV_CUDEV_UTIL_LIMITS_HPP__ + +#include +#include +#include "../common.hpp" + +namespace cv { namespace cudev { + +template struct numeric_limits; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static bool min() { return false; } + __device__ __forceinline__ static bool max() { return true; } + static const bool is_signed = false; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static schar min() { return SCHAR_MIN; } + __device__ __forceinline__ static schar max() { return SCHAR_MAX; } + static const bool is_signed = true; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static uchar min() { return 0; } + __device__ __forceinline__ static uchar max() { return UCHAR_MAX; } + static const bool is_signed = false; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static short min() { return SHRT_MIN; } + __device__ __forceinline__ static short max() { return SHRT_MAX; } + static const bool is_signed = true; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static ushort min() { return 0; } + __device__ __forceinline__ static ushort max() { return USHRT_MAX; } + static const bool is_signed = false; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static int min() { return INT_MIN; } + __device__ __forceinline__ static int max() { return INT_MAX; } + static const bool is_signed = true; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static uint min() { return 0; } + __device__ __forceinline__ static uint max() { return UINT_MAX; } + static const bool is_signed = false; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static float min() { return FLT_MIN; } + __device__ __forceinline__ static float max() { return FLT_MAX; } + __device__ __forceinline__ static float epsilon() { return FLT_EPSILON; } + static const bool is_signed = true; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static double min() { return DBL_MIN; } + __device__ __forceinline__ static double max() { return DBL_MAX; } + __device__ __forceinline__ static double epsilon() { return DBL_EPSILON; } + static const bool is_signed = true; +}; + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/util/saturate_cast.hpp b/modules/cudev/include/opencv2/cudev/util/saturate_cast.hpp new file mode 100644 index 0000000000..faa12e32f2 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/util/saturate_cast.hpp @@ -0,0 +1,264 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_UTIL_SATURATE_CAST_HPP__ +#define __OPENCV_CUDEV_UTIL_SATURATE_CAST_HPP__ + +#include "../common.hpp" + +namespace cv { namespace cudev { + +template __device__ __forceinline__ T saturate_cast(uchar v) { return T(v); } +template __device__ __forceinline__ T saturate_cast(schar v) { return T(v); } +template __device__ __forceinline__ T saturate_cast(ushort v) { return T(v); } +template __device__ __forceinline__ T saturate_cast(short v) { return T(v); } +template __device__ __forceinline__ T saturate_cast(uint v) { return T(v); } +template __device__ __forceinline__ T saturate_cast(int v) { return T(v); } +template __device__ __forceinline__ T saturate_cast(float v) { return T(v); } +template __device__ __forceinline__ T saturate_cast(double v) { return T(v); } + +template <> __device__ __forceinline__ uchar saturate_cast(schar v) +{ + uint res = 0; + int vi = v; + asm("cvt.sat.u8.s8 %0, %1;" : "=r"(res) : "r"(vi)); + return res; +} +template <> __device__ __forceinline__ uchar saturate_cast(short v) +{ + uint res = 0; + asm("cvt.sat.u8.s16 %0, %1;" : "=r"(res) : "h"(v)); + return res; +} +template <> __device__ __forceinline__ uchar saturate_cast(ushort v) +{ + uint res = 0; + asm("cvt.sat.u8.u16 %0, %1;" : "=r"(res) : "h"(v)); + return res; +} +template <> __device__ __forceinline__ uchar saturate_cast(int v) +{ + uint res = 0; + asm("cvt.sat.u8.s32 %0, %1;" : "=r"(res) : "r"(v)); + return res; +} +template <> __device__ __forceinline__ uchar saturate_cast(uint v) +{ + uint res = 0; + asm("cvt.sat.u8.u32 %0, %1;" : "=r"(res) : "r"(v)); + return res; +} +template <> __device__ __forceinline__ uchar saturate_cast(float v) +{ + uint res = 0; + asm("cvt.rni.sat.u8.f32 %0, %1;" : "=r"(res) : "f"(v)); + return res; +} +template <> __device__ __forceinline__ uchar saturate_cast(double v) +{ + uint res = 0; + asm("cvt.rni.sat.u8.f64 %0, %1;" : "=r"(res) : "d"(v)); + return res; +} + +template <> __device__ __forceinline__ schar saturate_cast(uchar v) +{ + uint res = 0; + uint vi = v; + asm("cvt.sat.s8.u8 %0, %1;" : "=r"(res) : "r"(vi)); + return res; +} +template <> __device__ __forceinline__ schar saturate_cast(short v) +{ + uint res = 0; + asm("cvt.sat.s8.s16 %0, %1;" : "=r"(res) : "h"(v)); + return res; +} +template <> __device__ __forceinline__ schar saturate_cast(ushort v) +{ + uint res = 0; + asm("cvt.sat.s8.u16 %0, %1;" : "=r"(res) : "h"(v)); + return res; +} +template <> __device__ __forceinline__ schar saturate_cast(int v) +{ + uint res = 0; + asm("cvt.sat.s8.s32 %0, %1;" : "=r"(res) : "r"(v)); + return res; +} +template <> __device__ __forceinline__ schar saturate_cast(uint v) +{ + uint res = 0; + asm("cvt.sat.s8.u32 %0, %1;" : "=r"(res) : "r"(v)); + return res; +} +template <> __device__ __forceinline__ schar saturate_cast(float v) +{ + uint res = 0; + asm("cvt.rni.sat.s8.f32 %0, %1;" : "=r"(res) : "f"(v)); + return res; +} +template <> __device__ __forceinline__ schar saturate_cast(double v) +{ + uint res = 0; + asm("cvt.rni.sat.s8.f64 %0, %1;" : "=r"(res) : "d"(v)); + return res; +} + +template <> __device__ __forceinline__ ushort saturate_cast(schar v) +{ + ushort res = 0; + int vi = v; + asm("cvt.sat.u16.s8 %0, %1;" : "=h"(res) : "r"(vi)); + return res; +} +template <> __device__ __forceinline__ ushort saturate_cast(short v) +{ + ushort res = 0; + asm("cvt.sat.u16.s16 %0, %1;" : "=h"(res) : "h"(v)); + return res; +} +template <> __device__ __forceinline__ ushort saturate_cast(int v) +{ + ushort res = 0; + asm("cvt.sat.u16.s32 %0, %1;" : "=h"(res) : "r"(v)); + return res; +} +template <> __device__ __forceinline__ ushort saturate_cast(uint v) +{ + ushort res = 0; + asm("cvt.sat.u16.u32 %0, %1;" : "=h"(res) : "r"(v)); + return res; +} +template <> __device__ __forceinline__ ushort saturate_cast(float v) +{ + ushort res = 0; + asm("cvt.rni.sat.u16.f32 %0, %1;" : "=h"(res) : "f"(v)); + return res; +} +template <> __device__ __forceinline__ ushort saturate_cast(double v) +{ + ushort res = 0; + asm("cvt.rni.sat.u16.f64 %0, %1;" : "=h"(res) : "d"(v)); + return res; +} + +template <> __device__ __forceinline__ short saturate_cast(ushort v) +{ + short res = 0; + asm("cvt.sat.s16.u16 %0, %1;" : "=h"(res) : "h"(v)); + return res; +} +template <> __device__ __forceinline__ short saturate_cast(int v) +{ + short res = 0; + asm("cvt.sat.s16.s32 %0, %1;" : "=h"(res) : "r"(v)); + return res; +} +template <> __device__ __forceinline__ short saturate_cast(uint v) +{ + short res = 0; + asm("cvt.sat.s16.u32 %0, %1;" : "=h"(res) : "r"(v)); + return res; +} +template <> __device__ __forceinline__ short saturate_cast(float v) +{ + short res = 0; + asm("cvt.rni.sat.s16.f32 %0, %1;" : "=h"(res) : "f"(v)); + return res; +} +template <> __device__ __forceinline__ short saturate_cast(double v) +{ + short res = 0; + asm("cvt.rni.sat.s16.f64 %0, %1;" : "=h"(res) : "d"(v)); + return res; +} + +template <> __device__ __forceinline__ int saturate_cast(uint v) +{ + int res = 0; + asm("cvt.sat.s32.u32 %0, %1;" : "=r"(res) : "r"(v)); + return res; +} +template <> __device__ __forceinline__ int saturate_cast(float v) +{ + return __float2int_rn(v); +} +template <> __device__ __forceinline__ int saturate_cast(double v) +{ + return __double2int_rn(v); +} + +template <> __device__ __forceinline__ uint saturate_cast(schar v) +{ + uint res = 0; + int vi = v; + asm("cvt.sat.u32.s8 %0, %1;" : "=r"(res) : "r"(vi)); + return res; +} +template <> __device__ __forceinline__ uint saturate_cast(short v) +{ + uint res = 0; + asm("cvt.sat.u32.s16 %0, %1;" : "=r"(res) : "h"(v)); + return res; +} +template <> __device__ __forceinline__ uint saturate_cast(int v) +{ + uint res = 0; + asm("cvt.sat.u32.s32 %0, %1;" : "=r"(res) : "r"(v)); + return res; +} +template <> __device__ __forceinline__ uint saturate_cast(float v) +{ + return __float2uint_rn(v); +} +template <> __device__ __forceinline__ uint saturate_cast(double v) +{ + return __double2uint_rn(v); +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/util/simd_functions.hpp b/modules/cudev/include/opencv2/cudev/util/simd_functions.hpp new file mode 100644 index 0000000000..db63f51800 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/util/simd_functions.hpp @@ -0,0 +1,913 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +/* + * Copyright (c) 2013 NVIDIA Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions 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. + * + * Neither the name of NVIDIA Corporation nor the names of its contributors + * may 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 COPYRIGHT HOLDER 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. + */ + +#pragma once + +#ifndef __OPENCV_CUDEV_UTIL_SIMD_FUNCTIONS_HPP__ +#define __OPENCV_CUDEV_UTIL_SIMD_FUNCTIONS_HPP__ + +#include "../common.hpp" + +/* + This header file contains inline functions that implement intra-word SIMD + operations, that are hardware accelerated on sm_3x (Kepler) GPUs. Efficient + emulation code paths are provided for earlier architectures (sm_1x, sm_2x) + to make the code portable across all GPUs supported by CUDA. The following + functions are currently implemented: + + vadd2(a,b) per-halfword unsigned addition, with wrap-around: a + b + vsub2(a,b) per-halfword unsigned subtraction, with wrap-around: a - b + vabsdiff2(a,b) per-halfword unsigned absolute difference: |a - b| + vavg2(a,b) per-halfword unsigned average: (a + b) / 2 + vavrg2(a,b) per-halfword unsigned rounded average: (a + b + 1) / 2 + vseteq2(a,b) per-halfword unsigned comparison: a == b ? 1 : 0 + vcmpeq2(a,b) per-halfword unsigned comparison: a == b ? 0xffff : 0 + vsetge2(a,b) per-halfword unsigned comparison: a >= b ? 1 : 0 + vcmpge2(a,b) per-halfword unsigned comparison: a >= b ? 0xffff : 0 + vsetgt2(a,b) per-halfword unsigned comparison: a > b ? 1 : 0 + vcmpgt2(a,b) per-halfword unsigned comparison: a > b ? 0xffff : 0 + vsetle2(a,b) per-halfword unsigned comparison: a <= b ? 1 : 0 + vcmple2(a,b) per-halfword unsigned comparison: a <= b ? 0xffff : 0 + vsetlt2(a,b) per-halfword unsigned comparison: a < b ? 1 : 0 + vcmplt2(a,b) per-halfword unsigned comparison: a < b ? 0xffff : 0 + vsetne2(a,b) per-halfword unsigned comparison: a != b ? 1 : 0 + vcmpne2(a,b) per-halfword unsigned comparison: a != b ? 0xffff : 0 + vmax2(a,b) per-halfword unsigned maximum: max(a, b) + vmin2(a,b) per-halfword unsigned minimum: min(a, b) + + vadd4(a,b) per-byte unsigned addition, with wrap-around: a + b + vsub4(a,b) per-byte unsigned subtraction, with wrap-around: a - b + vabsdiff4(a,b) per-byte unsigned absolute difference: |a - b| + vavg4(a,b) per-byte unsigned average: (a + b) / 2 + vavrg4(a,b) per-byte unsigned rounded average: (a + b + 1) / 2 + vseteq4(a,b) per-byte unsigned comparison: a == b ? 1 : 0 + vcmpeq4(a,b) per-byte unsigned comparison: a == b ? 0xff : 0 + vsetge4(a,b) per-byte unsigned comparison: a >= b ? 1 : 0 + vcmpge4(a,b) per-byte unsigned comparison: a >= b ? 0xff : 0 + vsetgt4(a,b) per-byte unsigned comparison: a > b ? 1 : 0 + vcmpgt4(a,b) per-byte unsigned comparison: a > b ? 0xff : 0 + vsetle4(a,b) per-byte unsigned comparison: a <= b ? 1 : 0 + vcmple4(a,b) per-byte unsigned comparison: a <= b ? 0xff : 0 + vsetlt4(a,b) per-byte unsigned comparison: a < b ? 1 : 0 + vcmplt4(a,b) per-byte unsigned comparison: a < b ? 0xff : 0 + vsetne4(a,b) per-byte unsigned comparison: a != b ? 1: 0 + vcmpne4(a,b) per-byte unsigned comparison: a != b ? 0xff: 0 + vmax4(a,b) per-byte unsigned maximum: max(a, b) + vmin4(a,b) per-byte unsigned minimum: min(a, b) +*/ + +namespace cv { namespace cudev { + +// 2 + +__device__ __forceinline__ uint vadd2(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vadd2.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#elif CV_CUDEV_ARCH >= 200 + asm("vadd.u32.u32.u32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vadd.u32.u32.u32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint s; + s = a ^ b; // sum bits + r = a + b; // actual sum + s = s ^ r; // determine carry-ins for each bit position + s = s & 0x00010000; // carry-in to high word (= carry-out from low word) + r = r - s; // subtract out carry-out from low word +#endif + + return r; +} + +__device__ __forceinline__ uint vsub2(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vsub2.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#elif CV_CUDEV_ARCH >= 200 + asm("vsub.u32.u32.u32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vsub.u32.u32.u32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint s; + s = a ^ b; // sum bits + r = a - b; // actual sum + s = s ^ r; // determine carry-ins for each bit position + s = s & 0x00010000; // borrow to high word + r = r + s; // compensate for borrow from low word +#endif + + return r; +} + +__device__ __forceinline__ uint vabsdiff2(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vabsdiff2.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#elif CV_CUDEV_ARCH >= 200 + asm("vabsdiff.u32.u32.u32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vabsdiff.u32.u32.u32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint s, t, u, v; + s = a & 0x0000ffff; // extract low halfword + r = b & 0x0000ffff; // extract low halfword + u = ::max(r, s); // maximum of low halfwords + v = ::min(r, s); // minimum of low halfwords + s = a & 0xffff0000; // extract high halfword + r = b & 0xffff0000; // extract high halfword + t = ::max(r, s); // maximum of high halfwords + s = ::min(r, s); // minimum of high halfwords + r = u | t; // maximum of both halfwords + s = v | s; // minimum of both halfwords + r = r - s; // |a - b| = max(a,b) - min(a,b); +#endif + + return r; +} + +__device__ __forceinline__ uint vavg2(uint a, uint b) +{ + uint r, s; + + // HAKMEM #23: a + b = 2 * (a & b) + (a ^ b) ==> + // (a + b) / 2 = (a & b) + ((a ^ b) >> 1) + s = a ^ b; + r = a & b; + s = s & 0xfffefffe; // ensure shift doesn't cross halfword boundaries + s = s >> 1; + s = r + s; + + return s; +} + +__device__ __forceinline__ uint vavrg2(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vavrg2.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + // HAKMEM #23: a + b = 2 * (a | b) - (a ^ b) ==> + // (a + b + 1) / 2 = (a | b) - ((a ^ b) >> 1) + uint s; + s = a ^ b; + r = a | b; + s = s & 0xfffefffe; // ensure shift doesn't cross half-word boundaries + s = s >> 1; + r = r - s; +#endif + + return r; +} + +__device__ __forceinline__ uint vseteq2(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vset2.u32.u32.eq %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + uint c; + r = a ^ b; // 0x0000 if a == b + c = r | 0x80008000; // set msbs, to catch carry out + r = r ^ c; // extract msbs, msb = 1 if r < 0x8000 + c = c - 0x00010001; // msb = 0, if r was 0x0000 or 0x8000 + c = r & ~c; // msb = 1, if r was 0x0000 + r = c >> 15; // convert to bool +#endif + + return r; +} + +__device__ __forceinline__ uint vcmpeq2(uint a, uint b) +{ + uint r, c; + +#if CV_CUDEV_ARCH >= 300 + r = vseteq2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask +#else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + r = a ^ b; // 0x0000 if a == b + c = r | 0x80008000; // set msbs, to catch carry out + r = r ^ c; // extract msbs, msb = 1 if r < 0x8000 + c = c - 0x00010001; // msb = 0, if r was 0x0000 or 0x8000 + c = r & ~c; // msb = 1, if r was 0x0000 + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask +#endif + + return r; +} + +__device__ __forceinline__ uint vsetge2(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vset2.u32.u32.ge %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint c; + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavrg2(a, b); // (a + ~b + 1) / 2 = (a - b) / 2 + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert to bool +#endif + + return r; +} + +__device__ __forceinline__ uint vcmpge2(uint a, uint b) +{ + uint r, c; + +#if CV_CUDEV_ARCH >= 300 + r = vsetge2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask +#else + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavrg2(a, b); // (a + ~b + 1) / 2 = (a - b) / 2 + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask +#endif + + return r; +} + +__device__ __forceinline__ uint vsetgt2(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vset2.u32.u32.gt %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint c; + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavg2(a, b); // (a + ~b) / 2 = (a - b) / 2 [rounded down] + c = c & 0x80008000; // msbs = carry-outs + r = c >> 15; // convert to bool +#endif + + return r; +} + +__device__ __forceinline__ uint vcmpgt2(uint a, uint b) +{ + uint r, c; + +#if CV_CUDEV_ARCH >= 300 + r = vsetgt2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask +#else + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavg2(a, b); // (a + ~b) / 2 = (a - b) / 2 [rounded down] + c = c & 0x80008000; // msbs = carry-outs + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask +#endif + + return r; +} + +__device__ __forceinline__ uint vsetle2(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vset2.u32.u32.le %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint c; + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavrg2(a, b); // (b + ~a + 1) / 2 = (b - a) / 2 + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert to bool +#endif + + return r; +} + +__device__ __forceinline__ uint vcmple2(uint a, uint b) +{ + uint r, c; + +#if CV_CUDEV_ARCH >= 300 + r = vsetle2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask +#else + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavrg2(a, b); // (b + ~a + 1) / 2 = (b - a) / 2 + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask +#endif + + return r; +} + +__device__ __forceinline__ uint vsetlt2(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vset2.u32.u32.lt %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint c; + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavg2(a, b); // (b + ~a) / 2 = (b - a) / 2 [rounded down] + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert to bool +#endif + + return r; +} + +__device__ __forceinline__ uint vcmplt2(uint a, uint b) +{ + uint r, c; + +#if CV_CUDEV_ARCH >= 300 + r = vsetlt2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask +#else + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavg2(a, b); // (b + ~a) / 2 = (b - a) / 2 [rounded down] + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask +#endif + + return r; +} + +__device__ __forceinline__ uint vsetne2(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm ("vset2.u32.u32.ne %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + uint c; + r = a ^ b; // 0x0000 if a == b + c = r | 0x80008000; // set msbs, to catch carry out + c = c - 0x00010001; // msb = 0, if r was 0x0000 or 0x8000 + c = r | c; // msb = 1, if r was not 0x0000 + c = c & 0x80008000; // extract msbs + r = c >> 15; // convert to bool +#endif + + return r; +} + +__device__ __forceinline__ uint vcmpne2(uint a, uint b) +{ + uint r, c; + +#if CV_CUDEV_ARCH >= 300 + r = vsetne2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask +#else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + r = a ^ b; // 0x0000 if a == b + c = r | 0x80008000; // set msbs, to catch carry out + c = c - 0x00010001; // msb = 0, if r was 0x0000 or 0x8000 + c = r | c; // msb = 1, if r was not 0x0000 + c = c & 0x80008000; // extract msbs + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask +#endif + + return r; +} + +__device__ __forceinline__ uint vmax2(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vmax2.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#elif CV_CUDEV_ARCH >= 200 + asm("vmax.u32.u32.u32 %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmax.u32.u32.u32 %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint s, t, u; + r = a & 0x0000ffff; // extract low halfword + s = b & 0x0000ffff; // extract low halfword + t = ::max(r, s); // maximum of low halfwords + r = a & 0xffff0000; // extract high halfword + s = b & 0xffff0000; // extract high halfword + u = ::max(r, s); // maximum of high halfwords + r = t | u; // combine halfword maximums +#endif + + return r; +} + +__device__ __forceinline__ uint vmin2(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vmin2.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#elif CV_CUDEV_ARCH >= 200 + asm("vmin.u32.u32.u32 %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmin.u32.u32.u32 %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint s, t, u; + r = a & 0x0000ffff; // extract low halfword + s = b & 0x0000ffff; // extract low halfword + t = ::min(r, s); // minimum of low halfwords + r = a & 0xffff0000; // extract high halfword + s = b & 0xffff0000; // extract high halfword + u = ::min(r, s); // minimum of high halfwords + r = t | u; // combine halfword minimums +#endif + + return r; +} + +// 4 + +__device__ __forceinline__ uint vadd4(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vadd4.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#elif CV_CUDEV_ARCH >= 200 + asm("vadd.u32.u32.u32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vadd.u32.u32.u32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vadd.u32.u32.u32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vadd.u32.u32.u32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint s, t; + s = a ^ b; // sum bits + r = a & 0x7f7f7f7f; // clear msbs + t = b & 0x7f7f7f7f; // clear msbs + s = s & 0x80808080; // msb sum bits + r = r + t; // add without msbs, record carry-out in msbs + r = r ^ s; // sum of msb sum and carry-in bits, w/o carry-out +#endif /* CV_CUDEV_ARCH >= 300 */ + + return r; +} + +__device__ __forceinline__ uint vsub4(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vsub4.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#elif CV_CUDEV_ARCH >= 200 + asm("vsub.u32.u32.u32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vsub.u32.u32.u32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vsub.u32.u32.u32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vsub.u32.u32.u32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint s, t; + s = a ^ ~b; // inverted sum bits + r = a | 0x80808080; // set msbs + t = b & 0x7f7f7f7f; // clear msbs + s = s & 0x80808080; // inverted msb sum bits + r = r - t; // subtract w/o msbs, record inverted borrows in msb + r = r ^ s; // combine inverted msb sum bits and borrows +#endif + + return r; +} + +__device__ __forceinline__ uint vavg4(uint a, uint b) +{ + uint r, s; + + // HAKMEM #23: a + b = 2 * (a & b) + (a ^ b) ==> + // (a + b) / 2 = (a & b) + ((a ^ b) >> 1) + s = a ^ b; + r = a & b; + s = s & 0xfefefefe; // ensure following shift doesn't cross byte boundaries + s = s >> 1; + s = r + s; + + return s; +} + +__device__ __forceinline__ uint vavrg4(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vavrg4.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + // HAKMEM #23: a + b = 2 * (a | b) - (a ^ b) ==> + // (a + b + 1) / 2 = (a | b) - ((a ^ b) >> 1) + uint c; + c = a ^ b; + r = a | b; + c = c & 0xfefefefe; // ensure following shift doesn't cross byte boundaries + c = c >> 1; + r = r - c; +#endif + + return r; +} + +__device__ __forceinline__ uint vseteq4(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vset4.u32.u32.eq %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + uint c; + r = a ^ b; // 0x00 if a == b + c = r | 0x80808080; // set msbs, to catch carry out + r = r ^ c; // extract msbs, msb = 1 if r < 0x80 + c = c - 0x01010101; // msb = 0, if r was 0x00 or 0x80 + c = r & ~c; // msb = 1, if r was 0x00 + r = c >> 7; // convert to bool +#endif + + return r; +} + +__device__ __forceinline__ uint vcmpeq4(uint a, uint b) +{ + uint r, t; + +#if CV_CUDEV_ARCH >= 300 + r = vseteq4(a, b); + t = r << 8; // convert bool + r = t - r; // to mask +#else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + t = a ^ b; // 0x00 if a == b + r = t | 0x80808080; // set msbs, to catch carry out + t = t ^ r; // extract msbs, msb = 1 if t < 0x80 + r = r - 0x01010101; // msb = 0, if t was 0x00 or 0x80 + r = t & ~r; // msb = 1, if t was 0x00 + t = r >> 7; // build mask + t = r - t; // from + r = t | r; // msbs +#endif + + return r; +} + +__device__ __forceinline__ uint vsetle4(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vset4.u32.u32.le %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint c; + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavrg4(a, b); // (b + ~a + 1) / 2 = (b - a) / 2 + c = c & 0x80808080; // msb = carry-outs + r = c >> 7; // convert to bool +#endif + + return r; +} + +__device__ __forceinline__ uint vcmple4(uint a, uint b) +{ + uint r, c; + +#if CV_CUDEV_ARCH >= 300 + r = vsetle4(a, b); + c = r << 8; // convert bool + r = c - r; // to mask +#else + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavrg4(a, b); // (b + ~a + 1) / 2 = (b - a) / 2 + c = c & 0x80808080; // msbs = carry-outs + r = c >> 7; // convert + r = c - r; // msbs to + r = c | r; // mask +#endif + + return r; +} + +__device__ __forceinline__ uint vsetlt4(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vset4.u32.u32.lt %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint c; + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavg4(a, b); // (b + ~a) / 2 = (b - a) / 2 [rounded down] + c = c & 0x80808080; // msb = carry-outs + r = c >> 7; // convert to bool +#endif + + return r; +} + +__device__ __forceinline__ uint vcmplt4(uint a, uint b) +{ + uint r, c; + +#if CV_CUDEV_ARCH >= 300 + r = vsetlt4(a, b); + c = r << 8; // convert bool + r = c - r; // to mask +#else + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavg4(a, b); // (b + ~a) / 2 = (b - a) / 2 [rounded down] + c = c & 0x80808080; // msbs = carry-outs + r = c >> 7; // convert + r = c - r; // msbs to + r = c | r; // mask +#endif + + return r; +} + +__device__ __forceinline__ uint vsetge4(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vset4.u32.u32.ge %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint c; + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavrg4(a, b); // (a + ~b + 1) / 2 = (a - b) / 2 + c = c & 0x80808080; // msb = carry-outs + r = c >> 7; // convert to bool +#endif + + return r; +} + +__device__ __forceinline__ uint vcmpge4(uint a, uint b) +{ + uint r, s; + +#if CV_CUDEV_ARCH >= 300 + r = vsetge4(a, b); + s = r << 8; // convert bool + r = s - r; // to mask +#else + asm ("not.b32 %0,%0;" : "+r"(b)); + r = vavrg4 (a, b); // (a + ~b + 1) / 2 = (a - b) / 2 + r = r & 0x80808080; // msb = carry-outs + s = r >> 7; // build mask + s = r - s; // from + r = s | r; // msbs +#endif + + return r; +} + +__device__ __forceinline__ uint vsetgt4(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vset4.u32.u32.gt %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint c; + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavg4(a, b); // (a + ~b) / 2 = (a - b) / 2 [rounded down] + c = c & 0x80808080; // msb = carry-outs + r = c >> 7; // convert to bool +#endif + + return r; +} + +__device__ __forceinline__ uint vcmpgt4(uint a, uint b) +{ + uint r, c; + +#if CV_CUDEV_ARCH >= 300 + r = vsetgt4(a, b); + c = r << 8; // convert bool + r = c - r; // to mask +#else + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavg4(a, b); // (a + ~b) / 2 = (a - b) / 2 [rounded down] + c = c & 0x80808080; // msb = carry-outs + r = c >> 7; // convert + r = c - r; // msbs to + r = c | r; // mask +#endif + + return r; +} + +__device__ __forceinline__ uint vsetne4(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vset4.u32.u32.ne %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + uint c; + r = a ^ b; // 0x00 if a == b + c = r | 0x80808080; // set msbs, to catch carry out + c = c - 0x01010101; // msb = 0, if r was 0x00 or 0x80 + c = r | c; // msb = 1, if r was not 0x00 + c = c & 0x80808080; // extract msbs + r = c >> 7; // convert to bool +#endif + + return r; +} + +__device__ __forceinline__ uint vcmpne4(uint a, uint b) +{ + uint r, c; + +#if CV_CUDEV_ARCH >= 300 + r = vsetne4(a, b); + c = r << 8; // convert bool + r = c - r; // to mask +#else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + r = a ^ b; // 0x00 if a == b + c = r | 0x80808080; // set msbs, to catch carry out + c = c - 0x01010101; // msb = 0, if r was 0x00 or 0x80 + c = r | c; // msb = 1, if r was not 0x00 + c = c & 0x80808080; // extract msbs + r = c >> 7; // convert + r = c - r; // msbs to + r = c | r; // mask +#endif + + return r; +} + +__device__ __forceinline__ uint vabsdiff4(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vabsdiff4.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#elif CV_CUDEV_ARCH >= 200 + asm("vabsdiff.u32.u32.u32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vabsdiff.u32.u32.u32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vabsdiff.u32.u32.u32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vabsdiff.u32.u32.u32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint s; + s = vcmpge4(a, b); // mask = 0xff if a >= b + r = a ^ b; // + s = (r & s) ^ b; // select a when a >= b, else select b => max(a,b) + r = s ^ r; // select a when b >= a, else select b => min(a,b) + r = s - r; // |a - b| = max(a,b) - min(a,b); +#endif + + return r; +} + +__device__ __forceinline__ uint vmax4(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vmax4.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#elif CV_CUDEV_ARCH >= 200 + asm("vmax.u32.u32.u32 %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmax.u32.u32.u32 %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmax.u32.u32.u32 %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmax.u32.u32.u32 %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint s; + s = vcmpge4(a, b); // mask = 0xff if a >= b + r = a & s; // select a when b >= a + s = b & ~s; // select b when b < a + r = r | s; // combine byte selections +#endif + + return r; // byte-wise unsigned maximum +} + +__device__ __forceinline__ uint vmin4(uint a, uint b) +{ + uint r = 0; + +#if CV_CUDEV_ARCH >= 300 + asm("vmin4.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#elif CV_CUDEV_ARCH >= 200 + asm("vmin.u32.u32.u32 %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmin.u32.u32.u32 %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmin.u32.u32.u32 %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmin.u32.u32.u32 %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); +#else + uint s; + s = vcmpge4(b, a); // mask = 0xff if a >= b + r = a & s; // select a when b >= a + s = b & ~s; // select b when b < a + r = r | s; // combine byte selections +#endif + + return r; +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/util/tuple.hpp b/modules/cudev/include/opencv2/cudev/util/tuple.hpp new file mode 100644 index 0000000000..b015ff3445 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/util/tuple.hpp @@ -0,0 +1,80 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_UTIL_TUPLE_HPP__ +#define __OPENCV_CUDEV_UTIL_TUPLE_HPP__ + +#include "../common.hpp" +#include "detail/tuple.hpp" + +namespace cv { namespace cudev { + +using tuple_detail::tuple; +using tuple_detail::tuple_size; +using tuple_detail::get; +using tuple_detail::tuple_element; +using tuple_detail::make_tuple; +using tuple_detail::tie; + +template struct TupleTraits +{ + enum { is_tuple = 0 }; + enum { size = 1 }; +}; +template +struct TupleTraits< tuple > +{ + enum { is_tuple = 1 }; + enum { size = tuple_size< tuple >::value }; +}; + +template class CvtOp> struct ConvertTuple +{ + typedef typename tuple_detail::ConvertTuple::value, CvtOp>::type type; +}; + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/util/type_traits.hpp b/modules/cudev/include/opencv2/cudev/util/type_traits.hpp new file mode 100644 index 0000000000..ca800c0b7a --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/util/type_traits.hpp @@ -0,0 +1,169 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_UTIL_TYPE_TRAITS_HPP__ +#define __OPENCV_CUDEV_UTIL_TYPE_TRAITS_HPP__ + +#include "../common.hpp" +#include "vec_traits.hpp" +#include "detail/type_traits.hpp" + +namespace cv { namespace cudev { + +// NullType + +struct NullType {}; + +// Int2Type + +template struct Int2Type +{ + enum { value = A }; +}; + +// ArrayWrapper + +template struct ArrayWrapper +{ + T array[COUNT]; +}; + +// Log2 (compile time calculation) + +template struct Log2 +{ + enum { value = Log2> 1), COUNT + 1>::VALUE }; +}; +template struct Log2 +{ + enum { value = (1 << (COUNT - 1) < N) ? COUNT : COUNT - 1 }; +}; + +// IsPowerOf2 + +template struct IsPowerOf2 +{ + enum { value = ((N != 0) && !(N & (N - 1))) }; +}; + +// SelectIf + +template struct SelectIf +{ + typedef ThenType type; +}; +template struct SelectIf +{ + typedef ElseType type; +}; + +// EnableIf + +template struct EnableIf {}; +template struct EnableIf { typedef T type; }; + +// DisableIf + +template struct DisableIf {}; +template struct DisableIf { typedef T type; }; + +// TypesEquals + +template struct TypesEquals +{ + enum { value = 0 }; +}; +template struct TypesEquals +{ + enum { value = 1 }; +}; + +// TypeTraits + +template struct TypeTraits +{ + typedef typename type_traits_detail::UnConst::type non_const_type; + typedef typename type_traits_detail::UnVolatile::type non_volatile_type; + typedef typename type_traits_detail::UnVolatile::type>::type unqualified_type; + typedef typename type_traits_detail::PointerTraits::type pointee_type; + typedef typename type_traits_detail::ReferenceTraits::type referred_type; + + enum { is_const = type_traits_detail::UnConst::value }; + enum { is_volatile = type_traits_detail::UnVolatile::value }; + + enum { is_reference = type_traits_detail::ReferenceTraits::value }; + enum { is_pointer = type_traits_detail::PointerTraits::type>::value }; + + enum { is_unsigned_int = type_traits_detail::IsUnsignedIntegral::value }; + enum { is_signed_int = type_traits_detail::IsSignedIntergral::value }; + enum { is_integral = type_traits_detail::IsIntegral::value }; + enum { is_float = type_traits_detail::IsFloat::value }; + enum { is_scalar = is_integral || is_float }; + enum { is_vec = type_traits_detail::IsVec::value }; + + typedef typename SelectIf::value, + T, typename type_traits_detail::AddParameterType::type>::type parameter_type; +}; + +// LargerType + +template struct LargerType +{ + typedef typename SelectIf< + unsigned(VecTraits::cn) != unsigned(VecTraits::cn), + void, + typename MakeVec< + typename type_traits_detail::LargerDepth< + typename VecTraits::elem_type, + typename VecTraits::elem_type + >::type, + VecTraits::cn + >::type + >::type type; +}; + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/util/vec_math.hpp b/modules/cudev/include/opencv2/cudev/util/vec_math.hpp new file mode 100644 index 0000000000..3ce265e277 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/util/vec_math.hpp @@ -0,0 +1,923 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_UTIL_VEC_MATH_HPP__ +#define __OPENCV_CUDEV_UTIL_VEC_MATH_HPP__ + +#include "vec_traits.hpp" +#include "saturate_cast.hpp" + +namespace cv { namespace cudev { + +// saturate_cast + +namespace vec_math_detail +{ + template struct SatCastHelper; + + template struct SatCastHelper<1, VecD> + { + template __device__ __forceinline__ static VecD cast(const VecS& v) + { + typedef typename VecTraits::elem_type D; + return VecTraits::make(saturate_cast(v.x)); + } + }; + + template struct SatCastHelper<2, VecD> + { + template __device__ __forceinline__ static VecD cast(const VecS& v) + { + typedef typename VecTraits::elem_type D; + return VecTraits::make(saturate_cast(v.x), saturate_cast(v.y)); + } + }; + + template struct SatCastHelper<3, VecD> + { + template __device__ __forceinline__ static VecD cast(const VecS& v) + { + typedef typename VecTraits::elem_type D; + return VecTraits::make(saturate_cast(v.x), saturate_cast(v.y), saturate_cast(v.z)); + } + }; + + template struct SatCastHelper<4, VecD> + { + template __device__ __forceinline__ static VecD cast(const VecS& v) + { + typedef typename VecTraits::elem_type D; + return VecTraits::make(saturate_cast(v.x), saturate_cast(v.y), saturate_cast(v.z), saturate_cast(v.w)); + } + }; +} + +template __device__ __forceinline__ T saturate_cast(const uchar1& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const char1& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const ushort1& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const short1& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const uint1& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const int1& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const float1& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const double1& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } + +template __device__ __forceinline__ T saturate_cast(const uchar2& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const char2& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const ushort2& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const short2& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const uint2& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const int2& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const float2& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const double2& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } + +template __device__ __forceinline__ T saturate_cast(const uchar3& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const char3& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const ushort3& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const short3& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const uint3& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const int3& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const float3& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const double3& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } + +template __device__ __forceinline__ T saturate_cast(const uchar4& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const char4& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const ushort4& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const short4& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const uint4& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const int4& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const float4& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } +template __device__ __forceinline__ T saturate_cast(const double4& v) { return vec_math_detail::SatCastHelper::cn, T>::cast(v); } + +// unary operators + +#define CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(op, input_type, output_type) \ + __device__ __forceinline__ output_type ## 1 operator op(const input_type ## 1 & a) \ + { \ + return VecTraits::make(op (a.x)); \ + } \ + __device__ __forceinline__ output_type ## 2 operator op(const input_type ## 2 & a) \ + { \ + return VecTraits::make(op (a.x), op (a.y)); \ + } \ + __device__ __forceinline__ output_type ## 3 operator op(const input_type ## 3 & a) \ + { \ + return VecTraits::make(op (a.x), op (a.y), op (a.z)); \ + } \ + __device__ __forceinline__ output_type ## 4 operator op(const input_type ## 4 & a) \ + { \ + return VecTraits::make(op (a.x), op (a.y), op (a.z), op (a.w)); \ + } + +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(-, char, char) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(-, short, short) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(-, int, int) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(-, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(-, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, char, char) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, short, short) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, int, int) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, uint, uint) + +#undef CV_CUDEV_IMPLEMENT_VEC_UNARY_OP + +// unary functions + +#define CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(func_name, func, input_type, output_type) \ + __device__ __forceinline__ output_type ## 1 func_name(const input_type ## 1 & a) \ + { \ + return VecTraits::make(func (a.x)); \ + } \ + __device__ __forceinline__ output_type ## 2 func_name(const input_type ## 2 & a) \ + { \ + return VecTraits::make(func (a.x), func (a.y)); \ + } \ + __device__ __forceinline__ output_type ## 3 func_name(const input_type ## 3 & a) \ + { \ + return VecTraits::make(func (a.x), func (a.y), func (a.z)); \ + } \ + __device__ __forceinline__ output_type ## 4 func_name(const input_type ## 4 & a) \ + { \ + return VecTraits::make(func (a.x), func (a.y), func (a.z), func (a.w)); \ + } + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, /*::abs*/, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, ::abs, char, char) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, /*::abs*/, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, ::abs, short, short) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, ::abs, int, int) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, /*::abs*/, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, ::fabsf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, ::fabs, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrt, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::exp, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::log, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sin, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cos, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tan, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asin, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acos, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atan, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinh, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::cosh, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanh, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinh, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acosh, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanh, double, double) + +#undef CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC + +// binary operators (vec & vec) + +#define CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(op, input_type, output_type) \ + __device__ __forceinline__ output_type ## 1 operator op(const input_type ## 1 & a, const input_type ## 1 & b) \ + { \ + return VecTraits::make(a.x op b.x); \ + } \ + __device__ __forceinline__ output_type ## 2 operator op(const input_type ## 2 & a, const input_type ## 2 & b) \ + { \ + return VecTraits::make(a.x op b.x, a.y op b.y); \ + } \ + __device__ __forceinline__ output_type ## 3 operator op(const input_type ## 3 & a, const input_type ## 3 & b) \ + { \ + return VecTraits::make(a.x op b.x, a.y op b.y, a.z op b.z); \ + } \ + __device__ __forceinline__ output_type ## 4 operator op(const input_type ## 4 & a, const input_type ## 4 & b) \ + { \ + return VecTraits::make(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); \ + } + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, uchar, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, char, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, ushort, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, short, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, uchar, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, char, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, ushort, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, short, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, uchar, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, char, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, ushort, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, short, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, uchar, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, char, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, ushort, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, short, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, char, char) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, short, short) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, uint, uint) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, char, char) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, short, short) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, uint, uint) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, char, char) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, short, short) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, uint, uint) + +#undef CV_CUDEV_IMPLEMENT_VEC_BINARY_OP + +// binary operators (vec & scalar) + +#define CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(op, input_type, scalar_type, output_type) \ + __device__ __forceinline__ output_type ## 1 operator op(const input_type ## 1 & a, scalar_type s) \ + { \ + return VecTraits::make(a.x op s); \ + } \ + __device__ __forceinline__ output_type ## 1 operator op(scalar_type s, const input_type ## 1 & b) \ + { \ + return VecTraits::make(s op b.x); \ + } \ + __device__ __forceinline__ output_type ## 2 operator op(const input_type ## 2 & a, scalar_type s) \ + { \ + return VecTraits::make(a.x op s, a.y op s); \ + } \ + __device__ __forceinline__ output_type ## 2 operator op(scalar_type s, const input_type ## 2 & b) \ + { \ + return VecTraits::make(s op b.x, s op b.y); \ + } \ + __device__ __forceinline__ output_type ## 3 operator op(const input_type ## 3 & a, scalar_type s) \ + { \ + return VecTraits::make(a.x op s, a.y op s, a.z op s); \ + } \ + __device__ __forceinline__ output_type ## 3 operator op(scalar_type s, const input_type ## 3 & b) \ + { \ + return VecTraits::make(s op b.x, s op b.y, s op b.z); \ + } \ + __device__ __forceinline__ output_type ## 4 operator op(const input_type ## 4 & a, scalar_type s) \ + { \ + return VecTraits::make(a.x op s, a.y op s, a.z op s, a.w op s); \ + } \ + __device__ __forceinline__ output_type ## 4 operator op(scalar_type s, const input_type ## 4 & b) \ + { \ + return VecTraits::make(s op b.x, s op b.y, s op b.z, s op b.w); \ + } + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uchar, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, char, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, ushort, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, short, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uchar, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, char, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, ushort, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, short, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uchar, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, char, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, ushort, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, short, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uchar, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, char, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, ushort, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, short, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, char, char, char) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, ushort, ushort, ushort) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, short, short, short) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, uint, uint, uint) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, char, char, char) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, ushort, ushort, ushort) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, short, short, short) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, uint, uint, uint) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, char, char, char) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, ushort, ushort, ushort) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, short, short, short) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, uint, uint, uint) + +#undef CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP + +// binary function (vec & vec) + +#define CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(func_name, func, input_type, output_type) \ + __device__ __forceinline__ output_type ## 1 func_name(const input_type ## 1 & a, const input_type ## 1 & b) \ + { \ + return VecTraits::make(func (a.x, b.x)); \ + } \ + __device__ __forceinline__ output_type ## 2 func_name(const input_type ## 2 & a, const input_type ## 2 & b) \ + { \ + return VecTraits::make(func (a.x, b.x), func (a.y, b.y)); \ + } \ + __device__ __forceinline__ output_type ## 3 func_name(const input_type ## 3 & a, const input_type ## 3 & b) \ + { \ + return VecTraits::make(func (a.x, b.x), func (a.y, b.y), func (a.z, b.z)); \ + } \ + __device__ __forceinline__ output_type ## 4 func_name(const input_type ## 4 & a, const input_type ## 4 & b) \ + { \ + return VecTraits::make(func (a.x, b.x), func (a.y, b.y), func (a.z, b.z), func (a.w, b.w)); \ + } + +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, char, char) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, short, short) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::fmaxf, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::fmax, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, char, char) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, short, short) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::fminf, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::fmin, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, char, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, short, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, int, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypot, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, char, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, short, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, uint, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, int, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2, double, double) + +#undef CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC + +// binary function (vec & scalar) + +#define CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(func_name, func, input_type, scalar_type, output_type) \ + __device__ __forceinline__ output_type ## 1 func_name(const input_type ## 1 & a, scalar_type s) \ + { \ + return VecTraits::make(func ((output_type) a.x, (output_type) s)); \ + } \ + __device__ __forceinline__ output_type ## 1 func_name(scalar_type s, const input_type ## 1 & b) \ + { \ + return VecTraits::make(func ((output_type) s, (output_type) b.x)); \ + } \ + __device__ __forceinline__ output_type ## 2 func_name(const input_type ## 2 & a, scalar_type s) \ + { \ + return VecTraits::make(func ((output_type) a.x, (output_type) s), func ((output_type) a.y, (output_type) s)); \ + } \ + __device__ __forceinline__ output_type ## 2 func_name(scalar_type s, const input_type ## 2 & b) \ + { \ + return VecTraits::make(func ((output_type) s, (output_type) b.x), func ((output_type) s, (output_type) b.y)); \ + } \ + __device__ __forceinline__ output_type ## 3 func_name(const input_type ## 3 & a, scalar_type s) \ + { \ + return VecTraits::make(func ((output_type) a.x, (output_type) s), func ((output_type) a.y, (output_type) s), func ((output_type) a.z, (output_type) s)); \ + } \ + __device__ __forceinline__ output_type ## 3 func_name(scalar_type s, const input_type ## 3 & b) \ + { \ + return VecTraits::make(func ((output_type) s, (output_type) b.x), func ((output_type) s, (output_type) b.y), func ((output_type) s, (output_type) b.z)); \ + } \ + __device__ __forceinline__ output_type ## 4 func_name(const input_type ## 4 & a, scalar_type s) \ + { \ + return VecTraits::make(func ((output_type) a.x, (output_type) s), func ((output_type) a.y, (output_type) s), func ((output_type) a.z, (output_type) s), func ((output_type) a.w, (output_type) s)); \ + } \ + __device__ __forceinline__ output_type ## 4 func_name(scalar_type s, const input_type ## 4 & b) \ + { \ + return VecTraits::make(func ((output_type) s, (output_type) b.x), func ((output_type) s, (output_type) b.y), func ((output_type) s, (output_type) b.z), func ((output_type) s, (output_type) b.w)); \ + } + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, char, char, char) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, ushort, ushort, ushort) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, short, short, short) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, char, char, char) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, ushort, ushort, ushort) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, short, short, short) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, double, double, double) + +#undef CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/util/vec_traits.hpp b/modules/cudev/include/opencv2/cudev/util/vec_traits.hpp new file mode 100644 index 0000000000..bdff958d87 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/util/vec_traits.hpp @@ -0,0 +1,320 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_UTIL_VEC_TRAITS_HPP__ +#define __OPENCV_CUDEV_UTIL_VEC_TRAITS_HPP__ + +#include "../common.hpp" + +namespace cv { namespace cudev { + +// MakeVec + +template struct MakeVec; + +#define CV_CUDEV_MAKE_VEC_INST(elem_type) \ + template<> struct MakeVec { typedef elem_type type; }; \ + template<> struct MakeVec { typedef elem_type ## 2 type; }; \ + template<> struct MakeVec { typedef elem_type ## 3 type; }; \ + template<> struct MakeVec { typedef elem_type ## 4 type; }; + +CV_CUDEV_MAKE_VEC_INST(uchar) +CV_CUDEV_MAKE_VEC_INST(ushort) +CV_CUDEV_MAKE_VEC_INST(short) +CV_CUDEV_MAKE_VEC_INST(int) +CV_CUDEV_MAKE_VEC_INST(uint) +CV_CUDEV_MAKE_VEC_INST(float) +CV_CUDEV_MAKE_VEC_INST(double) + +#undef CV_CUDEV_MAKE_VEC_INST + +template<> struct MakeVec { typedef char type; }; +template<> struct MakeVec { typedef char2 type; }; +template<> struct MakeVec { typedef char3 type; }; +template<> struct MakeVec { typedef char4 type; }; + +template<> struct MakeVec { typedef uchar type; }; +template<> struct MakeVec { typedef uchar2 type; }; +template<> struct MakeVec { typedef uchar3 type; }; +template<> struct MakeVec { typedef uchar4 type; }; + +// VecTraits + +template struct VecTraits; + +#define CV_CUDEV_VEC_TRAITS_INST(type) \ + template <> struct VecTraits \ + { \ + typedef type elem_type; \ + enum {cn=1}; \ + __host__ __device__ __forceinline__ static type all(type v) {return v;} \ + __host__ __device__ __forceinline__ static type make(type x) {return x;} \ + __host__ __device__ __forceinline__ static type make(const type* v) {return *v;} \ + }; \ + template <> struct VecTraits \ + { \ + typedef type elem_type; \ + enum {cn=1}; \ + __host__ __device__ __forceinline__ static type ## 1 all(type v) {return make_ ## type ## 1(v);} \ + __host__ __device__ __forceinline__ static type ## 1 make(type x) {return make_ ## type ## 1(x);} \ + __host__ __device__ __forceinline__ static type ## 1 make(const type* v) {return make_ ## type ## 1(*v);} \ + }; \ + template <> struct VecTraits \ + { \ + typedef type elem_type; \ + enum {cn=2}; \ + __host__ __device__ __forceinline__ static type ## 2 all(type v) {return make_ ## type ## 2(v, v);} \ + __host__ __device__ __forceinline__ static type ## 2 make(type x, type y) {return make_ ## type ## 2(x, y);} \ + __host__ __device__ __forceinline__ static type ## 2 make(const type* v) {return make_ ## type ## 2(v[0], v[1]);} \ + }; \ + template <> struct VecTraits \ + { \ + typedef type elem_type; \ + enum {cn=3}; \ + __host__ __device__ __forceinline__ static type ## 3 all(type v) {return make_ ## type ## 3(v, v, v);} \ + __host__ __device__ __forceinline__ static type ## 3 make(type x, type y, type z) {return make_ ## type ## 3(x, y, z);} \ + __host__ __device__ __forceinline__ static type ## 3 make(const type* v) {return make_ ## type ## 3(v[0], v[1], v[2]);} \ + }; \ + template <> struct VecTraits \ + { \ + typedef type elem_type; \ + enum {cn=4}; \ + __host__ __device__ __forceinline__ static type ## 4 all(type v) {return make_ ## type ## 4(v, v, v, v);} \ + __host__ __device__ __forceinline__ static type ## 4 make(type x, type y, type z, type w) {return make_ ## type ## 4(x, y, z, w);} \ + __host__ __device__ __forceinline__ static type ## 4 make(const type* v) {return make_ ## type ## 4(v[0], v[1], v[2], v[3]);} \ + }; + +CV_CUDEV_VEC_TRAITS_INST(uchar) +CV_CUDEV_VEC_TRAITS_INST(ushort) +CV_CUDEV_VEC_TRAITS_INST(short) +CV_CUDEV_VEC_TRAITS_INST(int) +CV_CUDEV_VEC_TRAITS_INST(uint) +CV_CUDEV_VEC_TRAITS_INST(float) +CV_CUDEV_VEC_TRAITS_INST(double) + +#undef CV_CUDEV_VEC_TRAITS_INST + +template<> struct VecTraits +{ + typedef schar elem_type; + enum {cn=1}; + __host__ __device__ __forceinline__ static schar all(schar v) {return v;} + __host__ __device__ __forceinline__ static schar make(schar x) {return x;} + __host__ __device__ __forceinline__ static schar make(const schar* x) {return *x;} +}; +template<> struct VecTraits +{ + typedef schar elem_type; + enum {cn=1}; + __host__ __device__ __forceinline__ static char1 all(schar v) {return make_char1(v);} + __host__ __device__ __forceinline__ static char1 make(schar x) {return make_char1(x);} + __host__ __device__ __forceinline__ static char1 make(const schar* v) {return make_char1(v[0]);} +}; +template<> struct VecTraits +{ + typedef schar elem_type; + enum {cn=2}; + __host__ __device__ __forceinline__ static char2 all(schar v) {return make_char2(v, v);} + __host__ __device__ __forceinline__ static char2 make(schar x, schar y) {return make_char2(x, y);} + __host__ __device__ __forceinline__ static char2 make(const schar* v) {return make_char2(v[0], v[1]);} +}; +template<> struct VecTraits +{ + typedef schar elem_type; + enum {cn=3}; + __host__ __device__ __forceinline__ static char3 all(schar v) {return make_char3(v, v, v);} + __host__ __device__ __forceinline__ static char3 make(schar x, schar y, schar z) {return make_char3(x, y, z);} + __host__ __device__ __forceinline__ static char3 make(const schar* v) {return make_char3(v[0], v[1], v[2]);} +}; +template<> struct VecTraits +{ + typedef schar elem_type; + enum {cn=4}; + __host__ __device__ __forceinline__ static char4 all(schar v) {return make_char4(v, v, v, v);} + __host__ __device__ __forceinline__ static char4 make(schar x, schar y, schar z, schar w) {return make_char4(x, y, z, w);} + __host__ __device__ __forceinline__ static char4 make(const schar* v) {return make_char4(v[0], v[1], v[2], v[3]);} +}; + +}} + +// DataType + +namespace cv { + +template <> class DataType +{ +public: + typedef uint value_type; + typedef value_type work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_32S, + channels = 1, + fmt = (int)'i', + type = CV_MAKE_TYPE(depth, channels) + }; +}; + +#define CV_CUDEV_DATA_TYPE_INST(_depth_type, _channel_num) \ + template <> class DataType< _depth_type ## _channel_num > \ + { \ + public: \ + typedef _depth_type ## _channel_num value_type; \ + typedef value_type work_type; \ + typedef _depth_type channel_type; \ + typedef value_type vec_type; \ + enum { generic_type = 0, \ + depth = DataType::depth, \ + channels = _channel_num, \ + fmt = DataType::fmt + ((channels - 1) << 8), \ + type = CV_MAKE_TYPE(depth, channels) \ + }; \ + }; + +CV_CUDEV_DATA_TYPE_INST(uchar, 1) +CV_CUDEV_DATA_TYPE_INST(uchar, 2) +CV_CUDEV_DATA_TYPE_INST(uchar, 3) +CV_CUDEV_DATA_TYPE_INST(uchar, 4) + +CV_CUDEV_DATA_TYPE_INST(ushort, 1) +CV_CUDEV_DATA_TYPE_INST(ushort, 2) +CV_CUDEV_DATA_TYPE_INST(ushort, 3) +CV_CUDEV_DATA_TYPE_INST(ushort, 4) + +CV_CUDEV_DATA_TYPE_INST(short, 1) +CV_CUDEV_DATA_TYPE_INST(short, 2) +CV_CUDEV_DATA_TYPE_INST(short, 3) +CV_CUDEV_DATA_TYPE_INST(short, 4) + +CV_CUDEV_DATA_TYPE_INST(int, 1) +CV_CUDEV_DATA_TYPE_INST(int, 2) +CV_CUDEV_DATA_TYPE_INST(int, 3) +CV_CUDEV_DATA_TYPE_INST(int, 4) + +CV_CUDEV_DATA_TYPE_INST(uint, 1) +CV_CUDEV_DATA_TYPE_INST(uint, 2) +CV_CUDEV_DATA_TYPE_INST(uint, 3) +CV_CUDEV_DATA_TYPE_INST(uint, 4) + +CV_CUDEV_DATA_TYPE_INST(float, 1) +CV_CUDEV_DATA_TYPE_INST(float, 2) +CV_CUDEV_DATA_TYPE_INST(float, 3) +CV_CUDEV_DATA_TYPE_INST(float, 4) + +CV_CUDEV_DATA_TYPE_INST(double, 1) +CV_CUDEV_DATA_TYPE_INST(double, 2) +CV_CUDEV_DATA_TYPE_INST(double, 3) +CV_CUDEV_DATA_TYPE_INST(double, 4) + +#undef CV_CUDEV_DATA_TYPE_INST + +template<> class DataType +{ +public: + typedef char1 value_type; + typedef value_type work_type; + typedef schar channel_type; + typedef value_type vec_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 1, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKE_TYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef char2 value_type; + typedef value_type work_type; + typedef schar channel_type; + typedef value_type vec_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 2, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKE_TYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef char3 value_type; + typedef value_type work_type; + typedef schar channel_type; + typedef value_type vec_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 3, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKE_TYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef char4 value_type; + typedef value_type work_type; + typedef schar channel_type; + typedef value_type vec_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 4, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKE_TYPE(depth, channels) + }; +}; + +} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/warp/detail/reduce.hpp b/modules/cudev/include/opencv2/cudev/warp/detail/reduce.hpp new file mode 100644 index 0000000000..7f9faf9cac --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/warp/detail/reduce.hpp @@ -0,0 +1,222 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_WARP_REDUCE_DETAIL_HPP__ +#define __OPENCV_CUDEV_WARP_REDUCE_DETAIL_HPP__ + +#include "../../common.hpp" +#include "../../util/tuple.hpp" +#include "../../warp/shuffle.hpp" + +namespace cv { namespace cudev { + +namespace warp_reduce_detail +{ + // GetType + + template struct GetType; + + template struct GetType + { + typedef T type; + }; + + template struct GetType + { + typedef T type; + }; + + template struct GetType + { + typedef T type; + }; + + // For + + template struct For + { + template + __device__ static void loadToSmem(const PointerTuple& smem, const ValTuple& val, uint tid) + { + get(smem)[tid] = get(val); + + For::loadToSmem(smem, val, tid); + } + + template + __device__ static void merge(const PointerTuple& smem, const ValTuple& val, uint tid, uint delta, const OpTuple& op) + { + typename GetType::type>::type reg = get(smem)[tid + delta]; + get(smem)[tid] = get(val) = get(op)(get(val), reg); + + For::merge(smem, val, tid, delta, op); + } + +#if CV_CUDEV_ARCH >= 300 + template + __device__ static void mergeShfl(const ValTuple& val, uint delta, uint width, const OpTuple& op) + { + typename GetType::type>::type reg = shfl_down(get(val), delta, width); + get(val) = get(op)(get(val), reg); + + For::mergeShfl(val, delta, width, op); + } +#endif + }; + + template struct For + { + template + __device__ __forceinline__ static void loadToSmem(const PointerTuple&, const ValTuple&, uint) + { + } + + template + __device__ __forceinline__ static void merge(const PointerTuple&, const ValTuple&, uint, uint, const OpTuple&) + { + } + +#if CV_CUDEV_ARCH >= 300 + template + __device__ __forceinline__ static void mergeShfl(const ValTuple&, uint, uint, const OpTuple&) + { + } +#endif + }; + + // loadToSmem + + template + __device__ __forceinline__ void loadToSmem(volatile T* smem, T& val, uint tid) + { + smem[tid] = val; + } + + template + __device__ __forceinline__ void loadToSmem(const tuple& smem, + const tuple& val, + uint tid) + { + For<0, tuple_size >::value>::loadToSmem(smem, val, tid); + } + + // merge + + template + __device__ __forceinline__ void merge(volatile T* smem, T& val, uint tid, uint delta, const Op& op) + { + T reg = smem[tid + delta]; + smem[tid] = val = op(val, reg); + } + + template + __device__ __forceinline__ void merge(const tuple& smem, + const tuple& val, + uint tid, + uint delta, + const tuple& op) + { + For<0, tuple_size >::value>::merge(smem, val, tid, delta, op); + } + + // mergeShfl + +#if CV_CUDEV_ARCH >= 300 + template + __device__ __forceinline__ void mergeShfl(T& val, uint delta, uint width, const Op& op) + { + T reg = shfl_down(val, delta, width); + val = op(val, reg); + } + + template + __device__ __forceinline__ void mergeShfl(const tuple& val, + uint delta, + uint width, + const tuple& op) + { + For<0, tuple_size >::value>::mergeShfl(val, delta, width, op); + } +#endif + + // WarpReductor + + struct WarpReductor + { + template + __device__ static void reduce(Pointer smem, Reference val, uint tid, Op op) + { + #if CV_CUDEV_ARCH >= 300 + (void) smem; + (void) tid; + + mergeShfl(val, 16, 32, op); + mergeShfl(val, 8, 32, op); + mergeShfl(val, 4, 32, op); + mergeShfl(val, 2, 32, op); + mergeShfl(val, 1, 32, op); + #else + loadToSmem(smem, val, tid); + + if (tid < 16) + { + merge(smem, val, tid, 16, op); + merge(smem, val, tid, 8, op); + merge(smem, val, tid, 4, op); + merge(smem, val, tid, 2, op); + merge(smem, val, tid, 1, op); + } + #endif + } + }; +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/warp/detail/reduce_key_val.hpp b/modules/cudev/include/opencv2/cudev/warp/detail/reduce_key_val.hpp new file mode 100644 index 0000000000..7701795757 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/warp/detail/reduce_key_val.hpp @@ -0,0 +1,239 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_WARP_REDUCE_KEY_VAL_DETAIL_HPP__ +#define __OPENCV_CUDEV_WARP_REDUCE_KEY_VAL_DETAIL_HPP__ + +#include "../../common.hpp" +#include "../../util/tuple.hpp" + +namespace cv { namespace cudev { + +namespace warp_reduce_key_val_detail +{ + // GetType + + template struct GetType; + + template struct GetType + { + typedef T type; + }; + + template struct GetType + { + typedef T type; + }; + + template struct GetType + { + typedef T type; + }; + + // For + + template struct For + { + template + __device__ static void loadToSmem(const PointerTuple& smem, const ReferenceTuple& data, uint tid) + { + get(smem)[tid] = get(data); + + For::loadToSmem(smem, data, tid); + } + + template + __device__ static void copy(const PointerTuple& svals, const ReferenceTuple& val, uint tid, uint delta) + { + get(svals)[tid] = get(val) = get(svals)[tid + delta]; + + For::copy(svals, val, tid, delta); + } + + template + __device__ static void merge(const KeyPointerTuple& skeys, const KeyReferenceTuple& key, + const ValPointerTuple& svals, const ValReferenceTuple& val, + const CmpTuple& cmp, + uint tid, uint delta) + { + typename GetType::type>::type reg = get(skeys)[tid + delta]; + + if (get(cmp)(reg, get(key))) + { + get(skeys)[tid] = get(key) = reg; + get(svals)[tid] = get(val) = get(svals)[tid + delta]; + } + + For::merge(skeys, key, svals, val, cmp, tid, delta); + } + }; + + template struct For + { + template + __device__ __forceinline__ static void loadToSmem(const PointerTuple&, const ReferenceTuple&, uint) + { + } + + template + __device__ __forceinline__ static void copy(const PointerTuple&, const ReferenceTuple&, uint, uint) + { + } + + template + __device__ __forceinline__ static void merge(const KeyPointerTuple&, const KeyReferenceTuple&, + const ValPointerTuple&, const ValReferenceTuple&, + const CmpTuple&, + uint, uint) + { + } + }; + + // loadToSmem + + template + __device__ __forceinline__ void loadToSmem(volatile T* smem, T& data, uint tid) + { + smem[tid] = data; + } + + template + __device__ __forceinline__ void loadToSmem(const tuple& smem, + const tuple& data, + uint tid) + { + For<0, tuple_size >::value>::loadToSmem(smem, data, tid); + } + + // copyVals + + template + __device__ __forceinline__ void copyVals(volatile V* svals, V& val, uint tid, uint delta) + { + svals[tid] = val = svals[tid + delta]; + } + + template + __device__ __forceinline__ void copyVals(const tuple& svals, + const tuple& val, + uint tid, uint delta) + { + For<0, tuple_size >::value>::copy(svals, val, tid, delta); + } + + // merge + + template + __device__ void merge(volatile K* skeys, K& key, volatile V* svals, V& val, const Cmp& cmp, uint tid, uint delta) + { + K reg = skeys[tid + delta]; + + if (cmp(reg, key)) + { + skeys[tid] = key = reg; + copyVals(svals, val, tid, delta); + } + } + + template + __device__ void merge(volatile K* skeys, K& key, + const tuple& svals, + const tuple& val, + const Cmp& cmp, uint tid, uint delta) + { + K reg = skeys[tid + delta]; + + if (cmp(reg, key)) + { + skeys[tid] = key = reg; + copyVals(svals, val, tid, delta); + } + } + + template + __device__ __forceinline__ void merge(const tuple& skeys, + const tuple& key, + const tuple& svals, + const tuple& val, + const tuple& cmp, + uint tid, uint delta) + { + For<0, tuple_size >::value>::merge(skeys, key, svals, val, cmp, tid, delta); + } + + // WarpReductor + + struct WarpReductor + { + template + __device__ static void reduce(KP skeys, KR key, VP svals, VR val, uint tid, Cmp cmp) + { + loadToSmem(skeys, key, tid); + loadToSmem(svals, val, tid); + + if (tid < 16) + { + merge(skeys, key, svals, val, cmp, tid, 16); + merge(skeys, key, svals, val, cmp, tid, 8); + merge(skeys, key, svals, val, cmp, tid, 4); + merge(skeys, key, svals, val, cmp, tid, 2); + merge(skeys, key, svals, val, cmp, tid, 1); + } + } + }; +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/warp/reduce.hpp b/modules/cudev/include/opencv2/cudev/warp/reduce.hpp new file mode 100644 index 0000000000..089ef92d0f --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/warp/reduce.hpp @@ -0,0 +1,206 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_WARP_REDUCE_HPP__ +#define __OPENCV_CUDEV_WARP_REDUCE_HPP__ + +#include "../common.hpp" +#include "../util/tuple.hpp" +#include "detail/reduce.hpp" +#include "detail/reduce_key_val.hpp" + +namespace cv { namespace cudev { + +// warpReduce + +template +__device__ __forceinline__ void warpReduce(volatile T* smem, T& val, uint tid, const Op& op) +{ + warp_reduce_detail::WarpReductor::template reduce(smem, val, tid, op); +} + +template +__device__ __forceinline__ void warpReduce(const tuple& smem, + const tuple& val, + uint tid, + const tuple& op) +{ + warp_reduce_detail::WarpReductor::template reduce< + const tuple&, + const tuple&, + const tuple&>(smem, val, tid, op); +} + +// warpReduceKeyVal + +template +__device__ __forceinline__ void warpReduceKeyVal(volatile K* skeys, K& key, volatile V* svals, V& val, uint tid, const Cmp& cmp) +{ + warp_reduce_key_val_detail::WarpReductor::template reduce(skeys, key, svals, val, tid, cmp); +} + +template +__device__ __forceinline__ void warpReduceKeyVal(volatile K* skeys, K& key, + const tuple& svals, + const tuple& val, + uint tid, const Cmp& cmp) +{ + warp_reduce_key_val_detail::WarpReductor::template reduce&, + const tuple&, + const Cmp&>(skeys, key, svals, val, tid, cmp); +} + +template +__device__ __forceinline__ void warpReduceKeyVal(const tuple& skeys, + const tuple& key, + const tuple& svals, + const tuple& val, + uint tid, + const tuple& cmp) +{ + warp_reduce_key_val_detail::WarpReductor::template reduce< + const tuple&, + const tuple&, + const tuple&, + const tuple&, + const tuple& + >(skeys, key, svals, val, tid, cmp); +} + +// smem_tuple + +template +__device__ __forceinline__ +tuple +smem_tuple(T0* t0) +{ + return make_tuple((volatile T0*) t0); +} + +template +__device__ __forceinline__ +tuple +smem_tuple(T0* t0, T1* t1) +{ + return make_tuple((volatile T0*) t0, (volatile T1*) t1); +} + +template +__device__ __forceinline__ +tuple +smem_tuple(T0* t0, T1* t1, T2* t2) +{ + return make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2); +} + +template +__device__ __forceinline__ +tuple +smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3) +{ + return make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3); +} + +template +__device__ __forceinline__ +tuple +smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4) +{ + return make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4); +} + +template +__device__ __forceinline__ +tuple +smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4, T5* t5) +{ + return make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4, (volatile T5*) t5); +} + +template +__device__ __forceinline__ +tuple +smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4, T5* t5, T6* t6) +{ + return make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4, (volatile T5*) t5, (volatile T6*) t6); +} + +template +__device__ __forceinline__ +tuple +smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4, T5* t5, T6* t6, T7* t7) +{ + return make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4, (volatile T5*) t5, (volatile T6*) t6, (volatile T7*) t7); +} + +template +__device__ __forceinline__ +tuple +smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4, T5* t5, T6* t6, T7* t7, T8* t8) +{ + return make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4, (volatile T5*) t5, (volatile T6*) t6, (volatile T7*) t7, (volatile T8*) t8); +} + +template +__device__ __forceinline__ +tuple +smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4, T5* t5, T6* t6, T7* t7, T8* t8, T9* t9) +{ + return make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4, (volatile T5*) t5, (volatile T6*) t6, (volatile T7*) t7, (volatile T8*) t8, (volatile T9*) t9); +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/warp/scan.hpp b/modules/cudev/include/opencv2/cudev/warp/scan.hpp new file mode 100644 index 0000000000..acd032fb00 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/warp/scan.hpp @@ -0,0 +1,99 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_WARP_SCAN_HPP__ +#define __OPENCV_CUDEV_WARP_SCAN_HPP__ + +#include "../common.hpp" +#include "warp.hpp" +#include "shuffle.hpp" + +namespace cv { namespace cudev { + +template +__device__ T warpScanInclusive(T data, volatile T* smem, uint tid) +{ +#if CV_CUDEV_ARCH >= 300 + (void) smem; + (void) tid; + + const uint laneId = Warp::laneId(); + + // scan on shufl functions + #pragma unroll + for (int i = 1; i <= (WARP_SIZE / 2); i *= 2) + { + const T val = shfl_up(data, i); + if (laneId >= i) + data += val; + } + + return data; +#else + uint pos = 2 * tid - (tid & (WARP_SIZE - 1)); + smem[pos] = 0; + + pos += WARP_SIZE; + smem[pos] = data; + + smem[pos] += smem[pos - 1]; + smem[pos] += smem[pos - 2]; + smem[pos] += smem[pos - 4]; + smem[pos] += smem[pos - 8]; + smem[pos] += smem[pos - 16]; + + return smem[pos]; +#endif +} + +template +__device__ __forceinline__ T warpScanExclusive(T data, volatile T* smem, uint tid) +{ + return warpScanInclusive(data, smem, tid) - data; +} + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/warp/shuffle.hpp b/modules/cudev/include/opencv2/cudev/warp/shuffle.hpp new file mode 100644 index 0000000000..a6aae5b902 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/warp/shuffle.hpp @@ -0,0 +1,424 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_WARP_SHUFFLE_HPP__ +#define __OPENCV_CUDEV_WARP_SHUFFLE_HPP__ + +#include "../common.hpp" +#include "../util/vec_traits.hpp" + +namespace cv { namespace cudev { + +#if CV_CUDEV_ARCH >= 300 + +// shfl + +__device__ __forceinline__ uchar shfl(uchar val, int srcLane, int width = warpSize) +{ + return (uchar) __shfl((int) val, srcLane, width); +} + +__device__ __forceinline__ schar shfl(schar val, int srcLane, int width = warpSize) +{ + return (schar) __shfl((int) val, srcLane, width); +} + +__device__ __forceinline__ ushort shfl(ushort val, int srcLane, int width = warpSize) +{ + return (ushort) __shfl((int) val, srcLane, width); +} + +__device__ __forceinline__ short shfl(short val, int srcLane, int width = warpSize) +{ + return (short) __shfl((int) val, srcLane, width); +} + +__device__ __forceinline__ int shfl(int val, int srcLane, int width = warpSize) +{ + return __shfl(val, srcLane, width); +} + +__device__ __forceinline__ uint shfl(uint val, int srcLane, int width = warpSize) +{ + return (uint) __shfl((int) val, srcLane, width); +} + +__device__ __forceinline__ float shfl(float val, int srcLane, int width = warpSize) +{ + return __shfl(val, srcLane, width); +} + +__device__ double shfl(double val, int srcLane, int width = warpSize) +{ + int lo = __double2loint(val); + int hi = __double2hiint(val); + + lo = __shfl(lo, srcLane, width); + hi = __shfl(hi, srcLane, width); + + return __hiloint2double(hi, lo); +} + +#define CV_CUDEV_SHFL_VEC_INST(input_type) \ + __device__ __forceinline__ input_type ## 1 shfl(const input_type ## 1 & val, int srcLane, int width = warpSize) \ + { \ + return VecTraits::make( \ + shfl(val.x, srcLane, width) \ + ); \ + } \ + __device__ __forceinline__ input_type ## 2 shfl(const input_type ## 2 & val, int srcLane, int width = warpSize) \ + { \ + return VecTraits::make( \ + shfl(val.x, srcLane, width), \ + shfl(val.y, srcLane, width) \ + ); \ + } \ + __device__ __forceinline__ input_type ## 3 shfl(const input_type ## 3 & val, int srcLane, int width = warpSize) \ + { \ + return VecTraits::make( \ + shfl(val.x, srcLane, width), \ + shfl(val.y, srcLane, width), \ + shfl(val.z, srcLane, width) \ + ); \ + } \ + __device__ __forceinline__ input_type ## 4 shfl(const input_type ## 4 & val, int srcLane, int width = warpSize) \ + { \ + return VecTraits::make( \ + shfl(val.x, srcLane, width), \ + shfl(val.y, srcLane, width), \ + shfl(val.z, srcLane, width), \ + shfl(val.w, srcLane, width) \ + ); \ + } + +CV_CUDEV_SHFL_VEC_INST(uchar) +CV_CUDEV_SHFL_VEC_INST(char) +CV_CUDEV_SHFL_VEC_INST(ushort) +CV_CUDEV_SHFL_VEC_INST(short) +CV_CUDEV_SHFL_VEC_INST(uint) +CV_CUDEV_SHFL_VEC_INST(int) +CV_CUDEV_SHFL_VEC_INST(float) +CV_CUDEV_SHFL_VEC_INST(double) + +#undef CV_CUDEV_SHFL_VEC_INST + +// shfl_up + +__device__ __forceinline__ uchar shfl_up(uchar val, uint delta, int width = warpSize) +{ + return (uchar) __shfl_up((int) val, delta, width); +} + +__device__ __forceinline__ schar shfl_up(schar val, uint delta, int width = warpSize) +{ + return (schar) __shfl_up((int) val, delta, width); +} + +__device__ __forceinline__ ushort shfl_up(ushort val, uint delta, int width = warpSize) +{ + return (ushort) __shfl_up((int) val, delta, width); +} + +__device__ __forceinline__ short shfl_up(short val, uint delta, int width = warpSize) +{ + return (short) __shfl_up((int) val, delta, width); +} + +__device__ __forceinline__ int shfl_up(int val, uint delta, int width = warpSize) +{ + return __shfl_up(val, delta, width); +} + +__device__ __forceinline__ uint shfl_up(uint val, uint delta, int width = warpSize) +{ + return (uint) __shfl_up((int) val, delta, width); +} + +__device__ __forceinline__ float shfl_up(float val, uint delta, int width = warpSize) +{ + return __shfl_up(val, delta, width); +} + +__device__ double shfl_up(double val, uint delta, int width = warpSize) +{ + int lo = __double2loint(val); + int hi = __double2hiint(val); + + lo = __shfl_up(lo, delta, width); + hi = __shfl_up(hi, delta, width); + + return __hiloint2double(hi, lo); +} + +#define CV_CUDEV_SHFL_UP_VEC_INST(input_type) \ + __device__ __forceinline__ input_type ## 1 shfl_up(const input_type ## 1 & val, uint delta, int width = warpSize) \ + { \ + return VecTraits::make( \ + shfl_up(val.x, delta, width) \ + ); \ + } \ + __device__ __forceinline__ input_type ## 2 shfl_up(const input_type ## 2 & val, uint delta, int width = warpSize) \ + { \ + return VecTraits::make( \ + shfl_up(val.x, delta, width), \ + shfl_up(val.y, delta, width) \ + ); \ + } \ + __device__ __forceinline__ input_type ## 3 shfl_up(const input_type ## 3 & val, uint delta, int width = warpSize) \ + { \ + return VecTraits::make( \ + shfl_up(val.x, delta, width), \ + shfl_up(val.y, delta, width), \ + shfl_up(val.z, delta, width) \ + ); \ + } \ + __device__ __forceinline__ input_type ## 4 shfl_up(const input_type ## 4 & val, uint delta, int width = warpSize) \ + { \ + return VecTraits::make( \ + shfl_up(val.x, delta, width), \ + shfl_up(val.y, delta, width), \ + shfl_up(val.z, delta, width), \ + shfl_up(val.w, delta, width) \ + ); \ + } + +CV_CUDEV_SHFL_UP_VEC_INST(uchar) +CV_CUDEV_SHFL_UP_VEC_INST(char) +CV_CUDEV_SHFL_UP_VEC_INST(ushort) +CV_CUDEV_SHFL_UP_VEC_INST(short) +CV_CUDEV_SHFL_UP_VEC_INST(uint) +CV_CUDEV_SHFL_UP_VEC_INST(int) +CV_CUDEV_SHFL_UP_VEC_INST(float) +CV_CUDEV_SHFL_UP_VEC_INST(double) + +#undef CV_CUDEV_SHFL_UP_VEC_INST + +// shfl_down + +__device__ __forceinline__ uchar shfl_down(uchar val, uint delta, int width = warpSize) +{ + return (uchar) __shfl_down((int) val, delta, width); +} + +__device__ __forceinline__ schar shfl_down(schar val, uint delta, int width = warpSize) +{ + return (schar) __shfl_down((int) val, delta, width); +} + +__device__ __forceinline__ ushort shfl_down(ushort val, uint delta, int width = warpSize) +{ + return (ushort) __shfl_down((int) val, delta, width); +} + +__device__ __forceinline__ short shfl_down(short val, uint delta, int width = warpSize) +{ + return (short) __shfl_down((int) val, delta, width); +} + +__device__ __forceinline__ int shfl_down(int val, uint delta, int width = warpSize) +{ + return __shfl_down(val, delta, width); +} + +__device__ __forceinline__ uint shfl_down(uint val, uint delta, int width = warpSize) +{ + return (uint) __shfl_down((int) val, delta, width); +} + +__device__ __forceinline__ float shfl_down(float val, uint delta, int width = warpSize) +{ + return __shfl_down(val, delta, width); +} + +__device__ double shfl_down(double val, uint delta, int width = warpSize) +{ + int lo = __double2loint(val); + int hi = __double2hiint(val); + + lo = __shfl_down(lo, delta, width); + hi = __shfl_down(hi, delta, width); + + return __hiloint2double(hi, lo); +} + +#define CV_CUDEV_SHFL_DOWN_VEC_INST(input_type) \ + __device__ __forceinline__ input_type ## 1 shfl_down(const input_type ## 1 & val, uint delta, int width = warpSize) \ + { \ + return VecTraits::make( \ + shfl_down(val.x, delta, width) \ + ); \ + } \ + __device__ __forceinline__ input_type ## 2 shfl_down(const input_type ## 2 & val, uint delta, int width = warpSize) \ + { \ + return VecTraits::make( \ + shfl_down(val.x, delta, width), \ + shfl_down(val.y, delta, width) \ + ); \ + } \ + __device__ __forceinline__ input_type ## 3 shfl_down(const input_type ## 3 & val, uint delta, int width = warpSize) \ + { \ + return VecTraits::make( \ + shfl_down(val.x, delta, width), \ + shfl_down(val.y, delta, width), \ + shfl_down(val.z, delta, width) \ + ); \ + } \ + __device__ __forceinline__ input_type ## 4 shfl_down(const input_type ## 4 & val, uint delta, int width = warpSize) \ + { \ + return VecTraits::make( \ + shfl_down(val.x, delta, width), \ + shfl_down(val.y, delta, width), \ + shfl_down(val.z, delta, width), \ + shfl_down(val.w, delta, width) \ + ); \ + } + +CV_CUDEV_SHFL_DOWN_VEC_INST(uchar) +CV_CUDEV_SHFL_DOWN_VEC_INST(char) +CV_CUDEV_SHFL_DOWN_VEC_INST(ushort) +CV_CUDEV_SHFL_DOWN_VEC_INST(short) +CV_CUDEV_SHFL_DOWN_VEC_INST(uint) +CV_CUDEV_SHFL_DOWN_VEC_INST(int) +CV_CUDEV_SHFL_DOWN_VEC_INST(float) +CV_CUDEV_SHFL_DOWN_VEC_INST(double) + +#undef CV_CUDEV_SHFL_DOWN_VEC_INST + +// shfl_xor + +__device__ __forceinline__ uchar shfl_xor(uchar val, int laneMask, int width = warpSize) +{ + return (uchar) __shfl_xor((int) val, laneMask, width); +} + +__device__ __forceinline__ schar shfl_xor(schar val, int laneMask, int width = warpSize) +{ + return (schar) __shfl_xor((int) val, laneMask, width); +} + +__device__ __forceinline__ ushort shfl_xor(ushort val, int laneMask, int width = warpSize) +{ + return (ushort) __shfl_xor((int) val, laneMask, width); +} + +__device__ __forceinline__ short shfl_xor(short val, int laneMask, int width = warpSize) +{ + return (short) __shfl_xor((int) val, laneMask, width); +} + +__device__ __forceinline__ int shfl_xor(int val, int laneMask, int width = warpSize) +{ + return __shfl_xor(val, laneMask, width); +} + +__device__ __forceinline__ uint shfl_xor(uint val, int laneMask, int width = warpSize) +{ + return (uint) __shfl_xor((int) val, laneMask, width); +} + +__device__ __forceinline__ float shfl_xor(float val, int laneMask, int width = warpSize) +{ + return __shfl_xor(val, laneMask, width); +} + +__device__ double shfl_xor(double val, int laneMask, int width = warpSize) +{ + int lo = __double2loint(val); + int hi = __double2hiint(val); + + lo = __shfl_xor(lo, laneMask, width); + hi = __shfl_xor(hi, laneMask, width); + + return __hiloint2double(hi, lo); +} + +#define CV_CUDEV_SHFL_XOR_VEC_INST(input_type) \ + __device__ __forceinline__ input_type ## 1 shfl_xor(const input_type ## 1 & val, int laneMask, int width = warpSize) \ + { \ + return VecTraits::make( \ + shfl_xor(val.x, laneMask, width) \ + ); \ + } \ + __device__ __forceinline__ input_type ## 2 shfl_xor(const input_type ## 2 & val, int laneMask, int width = warpSize) \ + { \ + return VecTraits::make( \ + shfl_xor(val.x, laneMask, width), \ + shfl_xor(val.y, laneMask, width) \ + ); \ + } \ + __device__ __forceinline__ input_type ## 3 shfl_xor(const input_type ## 3 & val, int laneMask, int width = warpSize) \ + { \ + return VecTraits::make( \ + shfl_xor(val.x, laneMask, width), \ + shfl_xor(val.y, laneMask, width), \ + shfl_xor(val.z, laneMask, width) \ + ); \ + } \ + __device__ __forceinline__ input_type ## 4 shfl_xor(const input_type ## 4 & val, int laneMask, int width = warpSize) \ + { \ + return VecTraits::make( \ + shfl_xor(val.x, laneMask, width), \ + shfl_xor(val.y, laneMask, width), \ + shfl_xor(val.z, laneMask, width), \ + shfl_xor(val.w, laneMask, width) \ + ); \ + } + +CV_CUDEV_SHFL_XOR_VEC_INST(uchar) +CV_CUDEV_SHFL_XOR_VEC_INST(char) +CV_CUDEV_SHFL_XOR_VEC_INST(ushort) +CV_CUDEV_SHFL_XOR_VEC_INST(short) +CV_CUDEV_SHFL_XOR_VEC_INST(uint) +CV_CUDEV_SHFL_XOR_VEC_INST(int) +CV_CUDEV_SHFL_XOR_VEC_INST(float) +CV_CUDEV_SHFL_XOR_VEC_INST(double) + +#undef CV_CUDEV_SHFL_XOR_VEC_INST + +#endif // CV_CUDEV_ARCH >= 300 + +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/warp/warp.hpp b/modules/cudev/include/opencv2/cudev/warp/warp.hpp new file mode 100644 index 0000000000..c7649880f3 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/warp/warp.hpp @@ -0,0 +1,122 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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*/ + +#pragma once + +#ifndef __OPENCV_CUDEV_WARP_WARP_HPP__ +#define __OPENCV_CUDEV_WARP_WARP_HPP__ + +#include "../common.hpp" + +namespace cv { namespace cudev { + +enum +{ + LOG_WARP_SIZE = 5, + WARP_SIZE = 1 << LOG_WARP_SIZE +}; + +struct Warp +{ + __device__ __forceinline__ static uint laneId() + { + uint ret; + asm("mov.u32 %0, %laneid;" : "=r"(ret)); + return ret; + } + + __device__ __forceinline__ static uint warpId() + { + const uint tid = (threadIdx.z * blockDim.y + threadIdx.y) * blockDim.x + threadIdx.x; + return tid / WARP_SIZE; + } +}; + +template +__device__ __forceinline__ void warpFill(It beg, It end, const T& value) +{ + for(It t = beg + Warp::laneId(); t < end; t += WARP_SIZE) + *t = value; +} + +template +__device__ __forceinline__ OutIt warpCopy(InIt beg, InIt end, OutIt out) +{ + for(InIt t = beg + Warp::laneId(); t < end; t += WARP_SIZE, out += WARP_SIZE) + *out = *t; + return out; +} + +template +__device__ __forceinline__ OutIt warpTransform(InIt beg, InIt end, OutIt out, const UnOp& op) +{ + for(InIt t = beg + Warp::laneId(); t < end; t += WARP_SIZE, out += WARP_SIZE) + *out = op(*t); + return out; +} + +template +__device__ __forceinline__ OutIt warpTransform(InIt1 beg1, InIt1 end1, InIt2 beg2, OutIt out, const BinOp& op) +{ + uint lane = Warp::laneId(); + + InIt1 t1 = beg1 + lane; + InIt2 t2 = beg2 + lane; + for(; t1 < end1; t1 += WARP_SIZE, t2 += WARP_SIZE, out += WARP_SIZE) + *out = op(*t1, *t2); + return out; +} + +template +__device__ __forceinline__ void warpYota(OutIt beg, OutIt end, T value) +{ + uint lane = Warp::laneId(); + value += lane; + + for(OutIt t = beg + lane; t < end; t += WARP_SIZE, value += WARP_SIZE) + *t = value; +} + +}} + +#endif diff --git a/modules/cudev/src/stub.cpp b/modules/cudev/src/stub.cpp new file mode 100644 index 0000000000..ec060adedc --- /dev/null +++ b/modules/cudev/src/stub.cpp @@ -0,0 +1,11 @@ +#include + +namespace cv { namespace cudev { + +CV_EXPORTS void stubFunc(); + +}} + +void cv::cudev::stubFunc() +{ +} diff --git a/modules/cudev/test/CMakeLists.txt b/modules/cudev/test/CMakeLists.txt new file mode 100644 index 0000000000..438e0a64c0 --- /dev/null +++ b/modules/cudev/test/CMakeLists.txt @@ -0,0 +1,48 @@ +set(test_deps opencv_cudev opencv_core opencv_imgproc opencv_highgui opencv_ts ${OPENCV_MODULE_opencv_ts_DEPS}) + +ocv_check_dependencies(${test_deps}) + +if(OCV_DEPENDENCIES_FOUND) + set(the_target "opencv_test_${name}") + + ocv_module_include_directories("${test_deps}" "${the_module}") + + file(GLOB test_srcs "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/*.cu") + file(GLOB test_hdrs "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp") + source_group("Src" FILES ${test_srcs}) + source_group("Include" FILES ${test_hdrs}) + set(OPENCV_TEST_${the_module}_SOURCES ${test_srcs} ${test_hdrs}) + + foreach(var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG) + # we remove /EHa as it generates warnings under windows + string(REPLACE "/EHa" "" ${var} "${${var}}") + + # we remove -ggdb3 flag as it leads to preprocessor errors when compiling CUDA files (CUDA 4.1) + string(REPLACE "-ggdb3" "" ${var} "${${var}}") + + # we remove -Wsign-promo as it generates warnings under linux + string(REPLACE "-Wsign-promo" "" ${var} "${${var}}") + + # we remove -fvisibility-inlines-hidden because it's used for C++ compiler + # but NVCC uses C compiler by default + string(REPLACE "-fvisibility-inlines-hidden" "" ${var} "${${var}}") + endforeach() + + CUDA_ADD_EXECUTABLE(${the_target} ${OPENCV_TEST_${the_module}_SOURCES}) + target_link_libraries(${the_target} ${test_deps} ${OPENCV_LINKER_LIBS} ${CUDA_LIBRARIES}) + add_dependencies(opencv_tests ${the_target}) + + # Additional target properties + set_target_properties(${the_target} PROPERTIES + DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" + RUNTIME_OUTPUT_DIRECTORY "${EXECUTABLE_OUTPUT_PATH}" + ) + + if(ENABLE_SOLUTION_FOLDERS) + set_target_properties(${the_target} PROPERTIES FOLDER "tests accuracy") + endif() + + enable_testing() + get_target_property(LOC ${the_target} LOCATION) + add_test(${the_target} "${LOC}") +endif() diff --git a/modules/cudev/test/test_arithm_func.cu b/modules/cudev/test/test_arithm_func.cu new file mode 100644 index 0000000000..bb73b04529 --- /dev/null +++ b/modules/cudev/test/test_arithm_func.cu @@ -0,0 +1,168 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "test_precomp.hpp" + +using namespace cv; +using namespace cv::gpu; +using namespace cv::cudev; +using namespace cvtest; + +//////////////////////////////////////////////////////////////////////////////// +// SqrtTest + +template +class SqrtTest : public ::testing::Test +{ +public: + void test_gpumat() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src = randomMat(size, type); + + GpuMat_ d_src(src); + + GpuMat_ dst = sqrt_(d_src); + + Mat dst_gold; + cv::sqrt(src, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } + + void test_expr() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src1 = randomMat(size, type); + Mat src2 = randomMat(size, type); + + GpuMat_ d_src1(src1), d_src2(src2); + + GpuMat_ dst = sqrt_(d_src1 * d_src2); + + Mat dst_gold; + cv::multiply(src1, src2, dst_gold); + cv::sqrt(dst_gold, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } +}; + +TYPED_TEST_CASE(SqrtTest, float); + +TYPED_TEST(SqrtTest, GpuMat) +{ + SqrtTest::test_gpumat(); +} + +TYPED_TEST(SqrtTest, Expr) +{ + SqrtTest::test_expr(); +} + +//////////////////////////////////////////////////////////////////////////////// +// MagnitudeTest + +template +class MagnitudeTest : public ::testing::Test +{ +public: + void test_accuracy() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src1 = randomMat(size, type); + Mat src2 = randomMat(size, type); + + GpuMat_ d_src1(src1), d_src2(src2); + + GpuMat_ dst1 = hypot_(d_src1, d_src2); + GpuMat_ dst2 = magnitude_(d_src1, d_src2); + GpuMat_ dst3 = sqrt_(sqr_(d_src1) + sqr_(d_src2)); + + EXPECT_MAT_NEAR(dst1, dst2, 1e-4); + EXPECT_MAT_NEAR(dst2, dst3, 0.0); + } +}; + +TYPED_TEST_CASE(MagnitudeTest, float); + +TYPED_TEST(MagnitudeTest, Accuracy) +{ + MagnitudeTest::test_accuracy(); +} + +//////////////////////////////////////////////////////////////////////////////// +// PowTest + +template +class PowTest : public ::testing::Test +{ +public: + void test_accuracy() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src = randomMat(size, type); + + GpuMat_ d_src(src); + + GpuMat_ dst1 = pow_(d_src, 0.5); + GpuMat_ dst2 = sqrt_(d_src); + + EXPECT_MAT_NEAR(dst1, dst2, 1e-5); + } +}; + +TYPED_TEST_CASE(PowTest, float); + +TYPED_TEST(PowTest, Accuracy) +{ + PowTest::test_accuracy(); +} diff --git a/modules/cudev/test/test_arithm_op.cu b/modules/cudev/test/test_arithm_op.cu new file mode 100644 index 0000000000..a904c54c7f --- /dev/null +++ b/modules/cudev/test/test_arithm_op.cu @@ -0,0 +1,395 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "test_precomp.hpp" + +using namespace cv; +using namespace cv::gpu; +using namespace cv::cudev; +using namespace cvtest; + +typedef ::testing::Types AllTypes; +typedef ::testing::Types SignedTypes; + +//////////////////////////////////////////////////////////////////////////////// +// UnaryMinusTest + +template +class UnaryMinusTest : public ::testing::Test +{ +public: + void test_gpumat() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src = randomMat(size, type); + + GpuMat_ d_src(src); + + GpuMat_ dst = -d_src; + + Mat dst_gold; + src.convertTo(dst_gold, src.depth(), -1); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } + + void test_globptr() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src = randomMat(size, type); + + GpuMat_ d_src(src); + GlobPtrSz d_src_ptr = d_src; + + GpuMat_ dst = -d_src_ptr; + + Mat dst_gold; + src.convertTo(dst_gold, src.depth(), -1); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } + + void test_texptr() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src = randomMat(size, type); + + GpuMat_ d_src(src); + Texture tex_src(d_src); + + GpuMat_ dst = -tex_src; + + Mat dst_gold; + src.convertTo(dst_gold, src.depth(), -1); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } + + void test_expr() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src1 = randomMat(size, type); + Mat src2 = randomMat(size, type); + + GpuMat_ d_src1(src1), d_src2(src2); + + GpuMat_ dst = -(d_src1 + d_src2); + + Mat dst_gold; + cv::add(src1, src2, dst_gold); + dst_gold.convertTo(dst_gold, dst_gold.depth(), -1); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } +}; + +TYPED_TEST_CASE(UnaryMinusTest, SignedTypes); + +TYPED_TEST(UnaryMinusTest, GpuMat) +{ + UnaryMinusTest::test_gpumat(); +} + +TYPED_TEST(UnaryMinusTest, GlobPtrSz) +{ + UnaryMinusTest::test_globptr(); +} + +TYPED_TEST(UnaryMinusTest, TexturePtr) +{ + UnaryMinusTest::test_texptr(); +} + +TYPED_TEST(UnaryMinusTest, Expr) +{ + UnaryMinusTest::test_expr(); +} + +//////////////////////////////////////////////////////////////////////////////// +// PlusTest + +template +class PlusTest : public ::testing::Test +{ +public: + void test_gpumat_gpumat() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src1 = randomMat(size, type); + Mat src2 = randomMat(size, type); + + GpuMat_ d_src1(src1), d_src2(src2); + + GpuMat_ dst = d_src1 + d_src2; + + Mat dst_gold; + cv::add(src1, src2, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } + + void test_texptr_scalar() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src = randomMat(size, type); + + GpuMat_ d_src(src); + Texture tex_src(d_src); + + GpuMat_ dst = tex_src + static_cast(5); + + Mat dst_gold; + cv::add(src, 5, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } + + void test_expr_gpumat() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src1 = randomMat(size, type); + Mat src2 = randomMat(size, type); + Mat src3 = randomMat(size, type); + + GpuMat_ d_src1(src1), d_src2(src2), d_src3(src3); + + GpuMat_ dst = d_src1 + d_src2 + d_src3; + + Mat dst_gold; + cv::add(src1, src2, dst_gold); + cv::add(dst_gold, src3, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } + + void test_scalar_expr() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src1 = randomMat(size, type); + Mat src2 = randomMat(size, type); + + GpuMat_ d_src1(src1), d_src2(src2); + + GpuMat_ dst = static_cast(5) + (d_src1 + d_src2); + + Mat dst_gold; + cv::add(src1, src2, dst_gold); + cv::add(dst_gold, 5, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } +}; + +TYPED_TEST_CASE(PlusTest, AllTypes); + +TYPED_TEST(PlusTest, GpuMat_GpuMat) +{ + PlusTest::test_gpumat_gpumat(); +} + +TYPED_TEST(PlusTest, TexturePtr_Scalar) +{ + PlusTest::test_texptr_scalar(); +} + +TYPED_TEST(PlusTest, Expr_GpuMat) +{ + PlusTest::test_expr_gpumat(); +} + +TYPED_TEST(PlusTest, Scalar_Expr) +{ + PlusTest::test_scalar_expr(); +} + +//////////////////////////////////////////////////////////////////////////////// +// MinusTest + +template +class MinusTest : public ::testing::Test +{ +public: + void test_gpumat_gpumat() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src1 = randomMat(size, type); + Mat src2 = randomMat(size, type); + + GpuMat_ d_src1(src1), d_src2(src2); + + GpuMat_ dst = d_src1 - d_src2; + + Mat dst_gold; + cv::subtract(src1, src2, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } + + void test_texptr_scalar() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src = randomMat(size, type); + + GpuMat_ d_src(src); + Texture tex_src(d_src); + + GpuMat_ dst = tex_src - static_cast(5); + + Mat dst_gold; + cv::subtract(src, 5, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } + + void test_expr_gpumat() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src1 = randomMat(size, type); + Mat src2 = randomMat(size, type); + Mat src3 = randomMat(size, type); + + GpuMat_ d_src1(src1), d_src2(src2), d_src3(src3); + + GpuMat_ dst = (d_src1 + d_src2) - d_src3; + + Mat dst_gold; + cv::add(src1, src2, dst_gold); + cv::subtract(dst_gold, src3, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } + + void test_scalar_expr() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src1 = randomMat(size, type); + Mat src2 = randomMat(size, type); + + GpuMat_ d_src1(src1), d_src2(src2); + + GpuMat_ dst = static_cast(5) - (d_src1 + d_src2); + + Mat dst_gold; + cv::add(src1, src2, dst_gold); + cv::subtract(5, dst_gold, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } +}; + +TYPED_TEST_CASE(MinusTest, SignedTypes); + +TYPED_TEST(MinusTest, GpuMat_GpuMat) +{ + MinusTest::test_gpumat_gpumat(); +} + +TYPED_TEST(MinusTest, TexturePtr_Scalar) +{ + MinusTest::test_texptr_scalar(); +} + +TYPED_TEST(MinusTest, Expr_GpuMat) +{ + MinusTest::test_expr_gpumat(); +} + +TYPED_TEST(MinusTest, Scalar_Expr) +{ + MinusTest::test_scalar_expr(); +} + +//////////////////////////////////////////////////////////////////////////////// +// AbsDiffTest + +template +class AbsDiffTest : public ::testing::Test +{ +public: + void test_accuracy() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src1 = randomMat(size, type); + Mat src2 = randomMat(size, type); + + GpuMat_ d_src1(src1), d_src2(src2); + + GpuMat_ dst1 = absdiff_(d_src1, d_src2); + GpuMat_ dst2 = abs_(d_src1 - d_src2); + + EXPECT_MAT_NEAR(dst1, dst2, 0.0); + } +}; + +TYPED_TEST_CASE(AbsDiffTest, SignedTypes); + +TYPED_TEST(AbsDiffTest, Accuracy) +{ + AbsDiffTest::test_accuracy(); +} diff --git a/modules/cudev/test/test_bitwize_op.cu b/modules/cudev/test/test_bitwize_op.cu new file mode 100644 index 0000000000..908d46d66a --- /dev/null +++ b/modules/cudev/test/test_bitwize_op.cu @@ -0,0 +1,146 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "test_precomp.hpp" + +using namespace cv; +using namespace cv::gpu; +using namespace cv::cudev; +using namespace cvtest; + +typedef ::testing::Types IntTypes; + +//////////////////////////////////////////////////////////////////////////////// +// BitNotTest + +template +class BitNotTest : public ::testing::Test +{ +public: + void test_gpumat() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src = randomMat(size, type); + + GpuMat_ d_src(src); + + GpuMat_ dst = ~d_src; + + Mat dst_gold; + cv::bitwise_not(src, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } +}; + +TYPED_TEST_CASE(BitNotTest, IntTypes); + +TYPED_TEST(BitNotTest, GpuMat) +{ + BitNotTest::test_gpumat(); +} + +//////////////////////////////////////////////////////////////////////////////// +// BitAndTest + +template +class BitAndTest : public ::testing::Test +{ +public: + void test_gpumat_gpumat() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src1 = randomMat(size, type); + Mat src2 = randomMat(size, type); + + GpuMat_ d_src1(src1), d_src2(src2); + + GpuMat_ dst = d_src1 & d_src2; + + Mat dst_gold; + cv::bitwise_and(src1, src2, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } +}; + +TYPED_TEST_CASE(BitAndTest, IntTypes); + +TYPED_TEST(BitAndTest, GpuMat_GpuMat) +{ + BitAndTest::test_gpumat_gpumat(); +} + +//////////////////////////////////////////////////////////////////////////////// +// LShiftTest + +template +class LShiftTest : public ::testing::Test +{ +public: + void test_accuracy() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src = randomMat(size, type); + + GpuMat_ d_src(src); + + GpuMat_ dst1 = d_src << 2; + GpuMat_ dst2 = d_src * 4; + + EXPECT_MAT_NEAR(dst1, dst2, 0.0); + } +}; + +TYPED_TEST_CASE(LShiftTest, int); + +TYPED_TEST(LShiftTest, Accuracy) +{ + LShiftTest::test_accuracy(); +} diff --git a/modules/cudev/test/test_cmp_op.cu b/modules/cudev/test/test_cmp_op.cu new file mode 100644 index 0000000000..4d557b6528 --- /dev/null +++ b/modules/cudev/test/test_cmp_op.cu @@ -0,0 +1,151 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "test_precomp.hpp" + +using namespace cv; +using namespace cv::gpu; +using namespace cv::cudev; +using namespace cvtest; + +typedef ::testing::Types AllTypes; + +//////////////////////////////////////////////////////////////////////////////// +// LessTest + +template +class LessTest : public ::testing::Test +{ +public: + void test_gpumat_gpumat() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src1 = randomMat(size, type); + Mat src2 = randomMat(size, type); + + GpuMat_ d_src1(src1), d_src2(src2); + + GpuMat_ dst = (d_src1 < d_src2) * 255; + + Mat dst_gold; + cv::compare(src1, src2, dst_gold, CMP_LT); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } +}; + +TYPED_TEST_CASE(LessTest, AllTypes); + +TYPED_TEST(LessTest, GpuMat_GpuMat) +{ + LessTest::test_gpumat_gpumat(); +} + +//////////////////////////////////////////////////////////////////////////////// +// MinTest + +template +class MinTest : public ::testing::Test +{ +public: + void test_gpumat_gpumat() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src1 = randomMat(size, type); + Mat src2 = randomMat(size, type); + + GpuMat_ d_src1(src1), d_src2(src2); + + GpuMat_ dst = min_(d_src1, d_src2); + + Mat dst_gold; + cv::min(src1, src2, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } +}; + +TYPED_TEST_CASE(MinTest, AllTypes); + +TYPED_TEST(MinTest, GpuMat_GpuMat) +{ + MinTest::test_gpumat_gpumat(); +} + +//////////////////////////////////////////////////////////////////////////////// +// ThreshBinaryTest + +typedef ::testing::Types ThreshTypes; + +template +class ThreshBinaryTest : public ::testing::Test +{ +public: + void test_gpumat() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src = randomMat(size, type); + + GpuMat_ d_src(src); + + GpuMat_ dst = threshBinary_(d_src, 128, 0); + + Mat dst_gold; + cv::threshold(src, dst_gold, 128, 0, THRESH_BINARY); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } +}; + +TYPED_TEST_CASE(ThreshBinaryTest, ThreshTypes); + +TYPED_TEST(ThreshBinaryTest, GpuMat) +{ + ThreshBinaryTest::test_gpumat(); +} diff --git a/modules/cudev/test/test_color_cvt.cu b/modules/cudev/test/test_color_cvt.cu new file mode 100644 index 0000000000..70d904b49e --- /dev/null +++ b/modules/cudev/test/test_color_cvt.cu @@ -0,0 +1,180 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "test_precomp.hpp" + +using namespace cv; +using namespace cv::gpu; +using namespace cv::cudev; +using namespace cvtest; + +namespace cv { + +enum { + COLOR_BGR2BGR = COLOR_BGR2RGB, + COLOR_BGR2LRGB = COLOR_BGR2RGB, + COLOR_BGR2LBGR = COLOR_BGR2RGB +}; + +} + +#define CVT_COLOR_TEST(src_space, dst_space, src_cn, dst_cn) \ + TEST(CvtColor, src_space ## _to_ ## dst_space) \ + { \ + const Size size = randomSize(100, 400); \ + Mat bgrb = randomMat(size, CV_8UC3); \ + Mat srcb; \ + cv::cvtColor(bgrb, srcb, COLOR_BGR ## 2 ## src_space, src_cn); \ + GpuMat_::type> d_srcb(srcb); \ + GpuMat_::type> dstb = src_space ## _to_ ## dst_space ## _(d_srcb); \ + Mat dstb_gold; \ + cv::cvtColor(srcb, dstb_gold, COLOR_ ## src_space ## 2 ## dst_space); \ + EXPECT_MAT_NEAR(dstb_gold, dstb, 1.0); \ + Mat bgrf = randomMat(size, CV_32FC3, 0, 1); \ + Mat srcf; \ + cv::cvtColor(bgrf, srcf, COLOR_BGR ## 2 ## src_space, src_cn); \ + GpuMat_::type> d_srcf(srcf); \ + GpuMat_::type> dstf = src_space ## _to_ ## dst_space ## _(d_srcf); \ + Mat dstf_gold; \ + cv::cvtColor(srcf, dstf_gold, COLOR_ ## src_space ## 2 ## dst_space); \ + EXPECT_MAT_NEAR(dstf_gold, dstf, 1.0); \ + } + +// RGB <-> BGR + +CVT_COLOR_TEST(BGR, RGB, 3, 3) +CVT_COLOR_TEST(BGR, BGRA, 3, 4) +CVT_COLOR_TEST(BGR, RGBA, 3, 4) +CVT_COLOR_TEST(BGRA, BGR, 4, 3) +CVT_COLOR_TEST(BGRA, RGB, 4, 3) +CVT_COLOR_TEST(BGRA, RGBA, 4, 4) + +// RGB <-> Gray + +CVT_COLOR_TEST(BGR, GRAY, 3, 1) +CVT_COLOR_TEST(RGB, GRAY, 3, 1) +CVT_COLOR_TEST(BGRA, GRAY, 4, 1) +CVT_COLOR_TEST(RGBA, GRAY, 4, 1) + +CVT_COLOR_TEST(GRAY, BGR, 1, 3) +CVT_COLOR_TEST(GRAY, BGRA, 1, 4) + +// RGB <-> YUV + +CVT_COLOR_TEST(RGB, YUV, 3, 3) +CVT_COLOR_TEST(BGR, YUV, 3, 3) + +CVT_COLOR_TEST(YUV, RGB, 3, 3) +CVT_COLOR_TEST(YUV, BGR, 3, 3) + +// RGB <-> YCrCb + +CVT_COLOR_TEST(RGB, YCrCb, 3, 3) +CVT_COLOR_TEST(BGR, YCrCb, 3, 3) + +CVT_COLOR_TEST(YCrCb, RGB, 3, 3) +CVT_COLOR_TEST(YCrCb, BGR, 3, 3) + +// RGB <-> XYZ + +CVT_COLOR_TEST(RGB, XYZ, 3, 3) +CVT_COLOR_TEST(BGR, XYZ, 3, 3) + +CVT_COLOR_TEST(XYZ, RGB, 3, 3) +CVT_COLOR_TEST(XYZ, BGR, 3, 3) + +// RGB <-> HSV + +CVT_COLOR_TEST(RGB, HSV, 3, 3) +CVT_COLOR_TEST(BGR, HSV, 3, 3) + +CVT_COLOR_TEST(HSV, RGB, 3, 3) +CVT_COLOR_TEST(HSV, BGR, 3, 3) + +CVT_COLOR_TEST(RGB, HSV_FULL, 3, 3) +CVT_COLOR_TEST(BGR, HSV_FULL, 3, 3) + +CVT_COLOR_TEST(HSV, RGB_FULL, 3, 3) +CVT_COLOR_TEST(HSV, BGR_FULL, 3, 3) + +// RGB <-> HLS + +CVT_COLOR_TEST(RGB, HLS, 3, 3) +CVT_COLOR_TEST(BGR, HLS, 3, 3) + +CVT_COLOR_TEST(HLS, RGB, 3, 3) +CVT_COLOR_TEST(HLS, BGR, 3, 3) + +CVT_COLOR_TEST(RGB, HLS_FULL, 3, 3) +CVT_COLOR_TEST(BGR, HLS_FULL, 3, 3) + +CVT_COLOR_TEST(HLS, RGB_FULL, 3, 3) +CVT_COLOR_TEST(HLS, BGR_FULL, 3, 3) + +// RGB <-> Lab + +CVT_COLOR_TEST(RGB, Lab, 3, 3) +CVT_COLOR_TEST(BGR, Lab, 3, 3) + +CVT_COLOR_TEST(Lab, RGB, 3, 3) +CVT_COLOR_TEST(Lab, BGR, 3, 3) + +CVT_COLOR_TEST(LRGB, Lab, 3, 3) +CVT_COLOR_TEST(LBGR, Lab, 3, 3) + +CVT_COLOR_TEST(Lab, LRGB, 3, 3) +CVT_COLOR_TEST(Lab, LBGR, 3, 3) + +// RGB <-> Luv + +CVT_COLOR_TEST(RGB, Luv, 3, 3) +CVT_COLOR_TEST(BGR, Luv, 3, 3) + +CVT_COLOR_TEST(Luv, RGB, 3, 3) +CVT_COLOR_TEST(Luv, BGR, 3, 3) + +CVT_COLOR_TEST(LRGB, Luv, 3, 3) +CVT_COLOR_TEST(LBGR, Luv, 3, 3) + +CVT_COLOR_TEST(Luv, LRGB, 3, 3) +CVT_COLOR_TEST(Luv, LBGR, 3, 3) diff --git a/modules/cudev/test/test_cvt.cu b/modules/cudev/test/test_cvt.cu new file mode 100644 index 0000000000..bdfa493bdc --- /dev/null +++ b/modules/cudev/test/test_cvt.cu @@ -0,0 +1,83 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "test_precomp.hpp" + +using namespace cv; +using namespace cv::gpu; +using namespace cv::cudev; +using namespace cvtest; + +typedef ::testing::Types AllTypes; + +//////////////////////////////////////////////////////////////////////////////// +// CvtTest + +template +class CvtTest : public ::testing::Test +{ +public: + void test_gpumat() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src = randomMat(size, type); + + GpuMat_ d_src(src); + + GpuMat_ dst = cvt_(cvt_(d_src) * 2.0f - 10.0f); + + Mat dst_gold; + src.convertTo(dst_gold, src.depth(), 2, -10); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } +}; + +TYPED_TEST_CASE(CvtTest, AllTypes); + +TYPED_TEST(CvtTest, GpuMat) +{ + CvtTest::test_gpumat(); +} diff --git a/modules/cudev/test/test_deriv.cu b/modules/cudev/test/test_deriv.cu new file mode 100644 index 0000000000..8ef9fb76aa --- /dev/null +++ b/modules/cudev/test/test_deriv.cu @@ -0,0 +1,109 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "test_precomp.hpp" + +using namespace cv; +using namespace cv::gpu; +using namespace cv::cudev; +using namespace cvtest; + +TEST(Sobel, Accuracy) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + Texture tex_src(d_src); + + GpuMat_ dx = sobelX_(cvt_(tex_src)); + GpuMat_ dy = sobelY_(cvt_(tex_src)); + + Mat dx_gold, dy_gold; + cv::Sobel(src, dx_gold, CV_16S, 1, 0, 3, 1, 0, BORDER_REPLICATE); + cv::Sobel(src, dy_gold, CV_16S, 0, 1, 3, 1, 0, BORDER_REPLICATE); + + EXPECT_MAT_NEAR(dx_gold, dx, 0.0); + EXPECT_MAT_NEAR(dy_gold, dy, 0.0); +} + +TEST(Scharr, Accuracy) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + Texture tex_src(d_src); + + GpuMat_ dx = scharrX_(cvt_(tex_src)); + GpuMat_ dy = scharrY_(cvt_(tex_src)); + + Mat dx_gold, dy_gold; + cv::Scharr(src, dx_gold, CV_16S, 1, 0, 1, 0, BORDER_REPLICATE); + cv::Scharr(src, dy_gold, CV_16S, 0, 1, 1, 0, BORDER_REPLICATE); + + EXPECT_MAT_NEAR(dx_gold, dx, 0.0); + EXPECT_MAT_NEAR(dy_gold, dy, 0.0); +} + +TEST(Laplacian, Accuracy) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + Texture tex_src(d_src); + + GpuMat_ dst1 = laplacian_<1>(cvt_(tex_src)); + GpuMat_ dst3 = laplacian_<3>(cvt_(tex_src)); + + Mat dst1_gold, dst3_gold; + cv::Laplacian(src, dst1_gold, CV_16S, 1, 1, 0, BORDER_REPLICATE); + cv::Laplacian(src, dst3_gold, CV_16S, 3, 1, 0, BORDER_REPLICATE); + + EXPECT_MAT_NEAR(dst1_gold, dst1, 0.0); + EXPECT_MAT_NEAR(dst3_gold, dst3, 0.0); +} diff --git a/modules/cudev/test/test_integral.cu b/modules/cudev/test/test_integral.cu new file mode 100644 index 0000000000..190fc354ac --- /dev/null +++ b/modules/cudev/test/test_integral.cu @@ -0,0 +1,103 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "test_precomp.hpp" + +using namespace cv; +using namespace cv::gpu; +using namespace cv::cudev; +using namespace cvtest; + +TEST(Integral, _8u) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + + GpuMat_ dst = integral_(d_src); + + Mat dst_gold; + cv::integral(src, dst_gold); + + dst_gold = dst_gold(Rect(1, 1, size.width, size.height)); + + ASSERT_MAT_NEAR(dst_gold, dst, 0.0); +} + +TEST(Integral, _32f) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_32FC1, 0, 1); + + GpuMat_ d_src(src); + + GpuMat_ dst = integral_(d_src); + + Mat dst_gold; + cv::integral(src, dst_gold, CV_32F); + + dst_gold = dst_gold(Rect(1, 1, size.width, size.height)); + + ASSERT_PRED_FORMAT2(cvtest::MatComparator(1e-5, 0), dst_gold, Mat(dst)); +} + +TEST(Integral, _8u_opt) +{ + const Size size(640, 480); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + + GpuMat_ dst = integral_(d_src); + + Mat dst_gold; + cv::integral(src, dst_gold); + + dst_gold = dst_gold(Rect(1, 1, size.width, size.height)); + + ASSERT_MAT_NEAR(dst_gold, dst, 0.0); +} diff --git a/modules/cudev/test/test_lut.cu b/modules/cudev/test/test_lut.cu new file mode 100644 index 0000000000..d2548ec24b --- /dev/null +++ b/modules/cudev/test/test_lut.cu @@ -0,0 +1,82 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "test_precomp.hpp" + +using namespace cv; +using namespace cv::gpu; +using namespace cv::cudev; +using namespace cvtest; + +//////////////////////////////////////////////////////////////////////////////// +// LutTest + +template +class LutTest : public ::testing::Test +{ +public: + void test_gpumat() + { + const Size size = randomSize(100, 400); + const int type = DataType::type; + + Mat src = randomMat(size, type); + Mat tbl = randomMat(Size(256, 1), type); + + GpuMat_ d_src(src), d_tbl(tbl); + + GpuMat_ dst = lut_(d_src, d_tbl); + + Mat dst_gold; + cv::LUT(src, tbl, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } +}; + +TYPED_TEST_CASE(LutTest, uchar); + +TYPED_TEST(LutTest, GpuMat) +{ + LutTest::test_gpumat(); +} diff --git a/modules/cudev/test/test_main.cpp b/modules/cudev/test/test_main.cpp new file mode 100644 index 0000000000..fc7f8a3b3a --- /dev/null +++ b/modules/cudev/test/test_main.cpp @@ -0,0 +1,46 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "opencv2/ts.hpp" + +CV_TEST_MAIN("cv") diff --git a/modules/cudev/test/test_precomp.hpp b/modules/cudev/test/test_precomp.hpp new file mode 100644 index 0000000000..18e7cc1ce2 --- /dev/null +++ b/modules/cudev/test/test_precomp.hpp @@ -0,0 +1,57 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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_TEST_PRECOMP_HPP__ +#define __OPENCV_TEST_PRECOMP_HPP__ + +#include "opencv2/core.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/cudev.hpp" + +#include "opencv2/ts.hpp" +#include "opencv2/ts/gpu_test.hpp" + +#include "cvconfig.h" + +#endif diff --git a/modules/cudev/test/test_pyramids.cu b/modules/cudev/test/test_pyramids.cu new file mode 100644 index 0000000000..c196c923ca --- /dev/null +++ b/modules/cudev/test/test_pyramids.cu @@ -0,0 +1,81 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "test_precomp.hpp" + +using namespace cv; +using namespace cv::gpu; +using namespace cv::cudev; +using namespace cvtest; + +TEST(PyrDown, _8uc1) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + + GpuMat_ dst = pyrDown_(d_src); + + Mat dst_gold; + cv::pyrDown(src, dst_gold); + + ASSERT_MAT_NEAR(dst_gold, dst, 1.0); +} + +TEST(PyrUp, _32fc4) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_32FC4); + + GpuMat_ d_src(src); + + GpuMat_ dst = pyrDown_(d_src); + + Mat dst_gold; + cv::pyrDown(src, dst_gold); + + ASSERT_MAT_NEAR(dst_gold, dst, 1e-4); +} diff --git a/modules/cudev/test/test_reduction.cu b/modules/cudev/test/test_reduction.cu new file mode 100644 index 0000000000..22cadbebc4 --- /dev/null +++ b/modules/cudev/test/test_reduction.cu @@ -0,0 +1,312 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "test_precomp.hpp" + +using namespace cv; +using namespace cv::gpu; +using namespace cv::cudev; +using namespace cvtest; + +TEST(Sum, GpuMat) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + + GpuMat_ dst = sum_(d_src); + float res; + dst.download(_OutputArray(&res, 1)); + + Scalar dst_gold = cv::sum(src); + + ASSERT_FLOAT_EQ(static_cast(dst_gold[0]), res); +} + +TEST(Sum, Expr) +{ + const Size size = randomSize(100, 400); + + Mat src1 = randomMat(size, CV_32FC1, 0, 1); + Mat src2 = randomMat(size, CV_32FC1, 0, 1); + + GpuMat_ d_src1(src1), d_src2(src2); + + GpuMat_ dst = sum_(abs_(d_src1 - d_src2)); + float res; + dst.download(_OutputArray(&res, 1)); + + Scalar dst_gold = cv::norm(src1, src2, NORM_L1); + + ASSERT_FLOAT_EQ(static_cast(dst_gold[0]), res); +} + +TEST(MinVal, GpuMat) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + + GpuMat_ dst = minVal_(d_src); + float res; + dst.download(_OutputArray(&res, 1)); + + double res_gold; + cv::minMaxLoc(src, &res_gold, 0); + + ASSERT_FLOAT_EQ(static_cast(res_gold), res); +} + +TEST(MaxVal, Expr) +{ + const Size size = randomSize(100, 400); + + Mat src1 = randomMat(size, CV_32SC1); + Mat src2 = randomMat(size, CV_32SC1); + + GpuMat_ d_src1(src1), d_src2(src2); + + GpuMat_ dst = maxVal_(abs_(d_src1 - d_src2)); + float res; + dst.download(_OutputArray(&res, 1)); + + double res_gold = cv::norm(src1, src2, NORM_INF); + + ASSERT_FLOAT_EQ(static_cast(res_gold), res); +} + +TEST(MinMaxVal, GpuMat) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + + GpuMat_ dst = minMaxVal_(d_src); + float res[2]; + dst.download(Mat(1, 2, CV_32FC1, res)); + + double res_gold[2]; + cv::minMaxLoc(src, &res_gold[0], &res_gold[1]); + + ASSERT_FLOAT_EQ(static_cast(res_gold[0]), res[0]); + ASSERT_FLOAT_EQ(static_cast(res_gold[1]), res[1]); +} + +TEST(NonZeroCount, Accuracy) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1, 0, 5); + + GpuMat_ d_src(src); + + GpuMat_ dst1 = countNonZero_(d_src); + GpuMat_ dst2 = sum_(cvt_(d_src) != 0); + + EXPECT_MAT_NEAR(dst1, dst2, 0.0); +} + +TEST(ReduceToRow, Sum) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + + GpuMat_ dst = reduceToRow_ >(d_src); + + Mat dst_gold; + cv::reduce(src, dst_gold, 0, REDUCE_SUM, CV_32S); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); +} + +TEST(ReduceToRow, Avg) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + + GpuMat_ dst = reduceToRow_ >(d_src); + + Mat dst_gold; + cv::reduce(src, dst_gold, 0, REDUCE_AVG, CV_32F); + + EXPECT_MAT_NEAR(dst_gold, dst, 1e-4); +} + +TEST(ReduceToRow, Min) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + + GpuMat_ dst = reduceToRow_ >(d_src); + + Mat dst_gold; + cv::reduce(src, dst_gold, 0, REDUCE_MIN); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); +} + +TEST(ReduceToRow, Max) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + + GpuMat_ dst = reduceToRow_ >(d_src); + + Mat dst_gold; + cv::reduce(src, dst_gold, 0, REDUCE_MAX); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); +} + +TEST(ReduceToColumn, Sum) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + + GpuMat_ dst = reduceToColumn_ >(d_src); + + Mat dst_gold; + cv::reduce(src, dst_gold, 1, REDUCE_SUM, CV_32S); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); +} + +TEST(ReduceToColumn, Avg) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + + GpuMat_ dst = reduceToColumn_ >(d_src); + + Mat dst_gold; + cv::reduce(src, dst_gold, 1, REDUCE_AVG, CV_32F); + + EXPECT_MAT_NEAR(dst_gold, dst, 1e-4); +} + +TEST(ReduceToColumn, Min) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + + GpuMat_ dst = reduceToColumn_ >(d_src); + + Mat dst_gold; + cv::reduce(src, dst_gold, 1, REDUCE_MIN); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); +} + +TEST(ReduceToColumn, Max) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + + GpuMat_ dst = reduceToColumn_ >(d_src); + + Mat dst_gold; + cv::reduce(src, dst_gold, 1, REDUCE_MAX); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); +} + +static void calcHistGold(const cv::Mat& src, cv::Mat& hist) +{ + hist.create(1, 256, CV_32SC1); + hist.setTo(cv::Scalar::all(0)); + + int* hist_row = hist.ptr(); + for (int y = 0; y < src.rows; ++y) + { + const uchar* src_row = src.ptr(y); + + for (int x = 0; x < src.cols; ++x) + ++hist_row[src_row[x]]; + } +} + +TEST(Histogram, GpuMat) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + + GpuMat_ dst = histogram_<256>(d_src); + + Mat dst_gold; + calcHistGold(src, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); +} diff --git a/modules/cudev/test/test_split_merge.cu b/modules/cudev/test/test_split_merge.cu new file mode 100644 index 0000000000..3af24f5882 --- /dev/null +++ b/modules/cudev/test/test_split_merge.cu @@ -0,0 +1,180 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "test_precomp.hpp" + +using namespace cv; +using namespace cv::gpu; +using namespace cv::cudev; +using namespace cvtest; + +typedef ::testing::Types AllTypes; + +//////////////////////////////////////////////////////////////////////////////// +// MergeTest + +template +class MergeTest : public ::testing::Test +{ +public: + void test_c2() + { + const Size size = randomSize(100, 400); + + const int src_type = DataType::type; + + Mat src1 = randomMat(size, src_type); + Mat src2 = randomMat(size, src_type); + + GpuMat_ d_src1(src1); + GpuMat_ d_src2(src2); + + GpuMat_::type> dst; + gridMerge(zipPtr(d_src1, d_src2), dst); + + Mat dst_gold; + Mat srcs[] = {src1, src2}; + cv::merge(srcs, 2, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); + } + + void test_c3() + { + const Size size = randomSize(100, 400); + + const int src_type = DataType::type; + + Mat src1 = randomMat(size, src_type); + Mat src2 = randomMat(size, src_type); + Mat src3 = randomMat(size, src_type); + + GpuMat_ d_src1(src1); + GpuMat_ d_src2(src2); + GpuMat_ d_src3(src3); + + GpuMat_::type> dst; + gridMerge(zipPtr(d_src1, d_src2, d_src3), dst); + + Mat dst_gold; + Mat srcs[] = {src1, src2, src3}; + cv::merge(srcs, 3, dst_gold); + + ASSERT_MAT_NEAR(dst_gold, dst, 0.0); + } +}; + +TYPED_TEST_CASE(MergeTest, AllTypes); + +TYPED_TEST(MergeTest, C2) +{ + MergeTest::test_c2(); +} + +TYPED_TEST(MergeTest, C3) +{ + MergeTest::test_c3(); +} + +//////////////////////////////////////////////////////////////////////////////// +// SplitTest + +template +class SplitTest : public ::testing::Test +{ +public: + void test_c3() + { + const Size size = randomSize(100, 400); + + const int src_type = CV_MAKE_TYPE(DataType::depth, 3); + + Mat src = randomMat(size, src_type); + + GpuMat_::type> d_src(src); + + GpuMat_ dst1, dst2, dst3; + gridSplit(d_src, tie(dst1, dst2, dst3)); + + std::vector dst; + cv::split(src, dst); + + ASSERT_MAT_NEAR(dst[0], dst1, 0.0); + ASSERT_MAT_NEAR(dst[1], dst2, 0.0); + ASSERT_MAT_NEAR(dst[2], dst3, 0.0); + } + + void test_c4() + { + const Size size = randomSize(100, 400); + + const int src_type = CV_MAKE_TYPE(DataType::depth, 4); + + Mat src = randomMat(size, src_type); + + GpuMat_::type> d_src(src); + + GpuMat_ dst1, dst2, dst3, dst4; + gridSplit(d_src, tie(dst1, dst2, dst3, dst4)); + + std::vector dst; + cv::split(src, dst); + + ASSERT_MAT_NEAR(dst[0], dst1, 0.0); + ASSERT_MAT_NEAR(dst[1], dst2, 0.0); + ASSERT_MAT_NEAR(dst[2], dst3, 0.0); + ASSERT_MAT_NEAR(dst[3], dst4, 0.0); + } +}; + +TYPED_TEST_CASE(SplitTest, AllTypes); + +TYPED_TEST(SplitTest, C3) +{ + SplitTest::test_c3(); +} + +TYPED_TEST(SplitTest, C4) +{ + SplitTest::test_c4(); +} diff --git a/modules/cudev/test/test_warp.cu b/modules/cudev/test/test_warp.cu new file mode 100644 index 0000000000..8777867bfc --- /dev/null +++ b/modules/cudev/test/test_warp.cu @@ -0,0 +1,256 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "test_precomp.hpp" + +using namespace cv; +using namespace cv::gpu; +using namespace cv::cudev; +using namespace cvtest; + +// remap + +enum { HALF_SIZE=0, UPSIDE_DOWN, REFLECTION_X, REFLECTION_BOTH }; + +static void generateMap(Mat& mapx, Mat& mapy, int remapMode) +{ + for (int j = 0; j < mapx.rows; ++j) + { + for (int i = 0; i < mapx.cols; ++i) + { + switch (remapMode) + { + case HALF_SIZE: + if (i > mapx.cols*0.25 && i < mapx.cols*0.75 && j > mapx.rows*0.25 && j < mapx.rows*0.75) + { + mapx.at(j,i) = 2.f * (i - mapx.cols * 0.25f) + 0.5f; + mapy.at(j,i) = 2.f * (j - mapx.rows * 0.25f) + 0.5f; + } + else + { + mapx.at(j,i) = 0.f; + mapy.at(j,i) = 0.f; + } + break; + case UPSIDE_DOWN: + mapx.at(j,i) = static_cast(i); + mapy.at(j,i) = static_cast(mapx.rows - j); + break; + case REFLECTION_X: + mapx.at(j,i) = static_cast(mapx.cols - i); + mapy.at(j,i) = static_cast(j); + break; + case REFLECTION_BOTH: + mapx.at(j,i) = static_cast(mapx.cols - i); + mapy.at(j,i) = static_cast(mapx.rows - j); + break; + } // end of switch + } + } +} + +static void test_remap(int remapMode) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_32FC1, 0, 1); + + Mat mapx(size, CV_32FC1); + Mat mapy(size, CV_32FC1); + generateMap(mapx, mapy, remapMode); + + GpuMat_ d_src(src); + GpuMat_ d_mapx(mapx); + GpuMat_ d_mapy(mapy); + + GpuMat_ dst = remap_(interNearest(brdReplicate(d_src)), d_mapx, d_mapy); + + Mat dst_gold; + cv::remap(src, dst_gold, mapx, mapy, INTER_NEAREST, BORDER_REPLICATE); + + EXPECT_MAT_NEAR(dst_gold, dst, 0.0); +} + +TEST(Remap, HALF_SIZE) +{ + test_remap(HALF_SIZE); +} + +TEST(Remap, UPSIDE_DOWN) +{ + test_remap(UPSIDE_DOWN); +} + +TEST(Remap, REFLECTION_X) +{ + test_remap(REFLECTION_X); +} + +TEST(Remap, REFLECTION_BOTH) +{ + test_remap(REFLECTION_BOTH); +} + +// resize + +TEST(Resize, Upscale) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_32FC1, 0, 1); + + GpuMat_ d_src(src); + Texture tex_src(d_src); + + GpuMat_ dst1 = resize_(interCubic(tex_src), 2, 2); + + Mat mapx(size.height * 2, size.width * 2, CV_32FC1); + Mat mapy(size.height * 2, size.width * 2, CV_32FC1); + + for (int y = 0; y < mapx.rows; ++y) + { + for (int x = 0; x < mapx.cols; ++x) + { + mapx.at(y, x) = static_cast(x / 2); + mapy.at(y, x) = static_cast(y / 2); + } + } + + GpuMat_ d_mapx(mapx); + GpuMat_ d_mapy(mapy); + + GpuMat_ dst2 = remap_(interCubic(brdReplicate(d_src)), d_mapx, d_mapy); + + EXPECT_MAT_NEAR(dst1, dst2, 0.0); +} + +TEST(Resize, Downscale) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_32FC1, 0, 1); + const float fx = 1.0f / 3.0f; + const float fy = 1.0f / 3.0f; + + GpuMat_ d_src(src); + Texture tex_src(d_src); + + GpuMat_ dst1 = resize_(interArea(tex_src, Size(3, 3)), fx, fy); + + Mat mapx(cv::saturate_cast(size.height * fy), cv::saturate_cast(size.width * fx), CV_32FC1); + Mat mapy(cv::saturate_cast(size.height * fy), cv::saturate_cast(size.width * fx), CV_32FC1); + + for (int y = 0; y < mapx.rows; ++y) + { + for (int x = 0; x < mapx.cols; ++x) + { + mapx.at(y, x) = x / fx; + mapy.at(y, x) = y / fy; + } + } + + GpuMat_ d_mapx(mapx); + GpuMat_ d_mapy(mapy); + + GpuMat_ dst2 = remap_(interArea(brdReplicate(d_src), Size(3, 3)), d_mapx, d_mapy); + + EXPECT_MAT_NEAR(dst1, dst2, 0.0); +} + +// warpAffine & warpPerspective + +Mat createAffineTransfomMatrix(Size srcSize, float angle, bool perspective) +{ + cv::Mat M(perspective ? 3 : 2, 3, CV_32FC1); + + { + M.at(0, 0) = std::cos(angle); M.at(0, 1) = -std::sin(angle); M.at(0, 2) = static_cast(srcSize.width / 2); + M.at(1, 0) = std::sin(angle); M.at(1, 1) = std::cos(angle); M.at(1, 2) = 0.0f; + } + if (perspective) + { + M.at(2, 0) = 0.0f ; M.at(2, 1) = 0.0f ; M.at(2, 2) = 1.0f; + } + + return M; +} + +TEST(WarpAffine, Rotation) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_32FC1, 0, 1); + Mat M = createAffineTransfomMatrix(size, static_cast(CV_PI / 4), false); + + GpuMat_ d_src(src); + GpuMat_ d_M; + createContinuous(M.size(), M.type(), d_M); + d_M.upload(M); + + GpuMat_ dst = warpAffine_(interNearest(brdConstant(d_src)), size, d_M); + + Mat dst_gold; + cv::warpAffine(src, dst_gold, M, size, INTER_NEAREST | WARP_INVERSE_MAP); + + EXPECT_MAT_SIMILAR(dst_gold, dst, 1e-3); +} + +TEST(WarpPerspective, Rotation) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_32FC1, 0, 1); + Mat M = createAffineTransfomMatrix(size, static_cast(CV_PI / 4), true); + + GpuMat_ d_src(src); + GpuMat_ d_M; + createContinuous(M.size(), M.type(), d_M); + d_M.upload(M); + + GpuMat_ dst = warpPerspective_(interNearest(brdConstant(d_src)), size, d_M); + + Mat dst_gold; + cv::warpPerspective(src, dst_gold, M, size, INTER_NEAREST | WARP_INVERSE_MAP); + + EXPECT_MAT_SIMILAR(dst_gold, dst, 1e-3); +} diff --git a/modules/cudev/test/transpose.cu b/modules/cudev/test/transpose.cu new file mode 100644 index 0000000000..a1e477c225 --- /dev/null +++ b/modules/cudev/test/transpose.cu @@ -0,0 +1,81 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// 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 "test_precomp.hpp" + +using namespace cv; +using namespace cv::gpu; +using namespace cv::cudev; +using namespace cvtest; + +TEST(Transpose, _8uc1) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_8UC1); + + GpuMat_ d_src(src); + + GpuMat_ dst = transpose_(d_src); + + Mat dst_gold; + cv::transpose(src, dst_gold); + + ASSERT_MAT_NEAR(dst_gold, dst, 0.0); +} + +TEST(Transpose, _32fc3) +{ + const Size size = randomSize(100, 400); + + Mat src = randomMat(size, CV_32FC3); + + GpuMat_ d_src(src); + + GpuMat_ dst = transpose_(d_src); + + Mat dst_gold; + cv::transpose(src, dst_gold); + + ASSERT_MAT_NEAR(dst_gold, dst, 0.0); +} diff --git a/modules/features2d/CMakeLists.txt b/modules/features2d/CMakeLists.txt index 7d36a58ac1..0b080cfb9a 100644 --- a/modules/features2d/CMakeLists.txt +++ b/modules/features2d/CMakeLists.txt @@ -1,3 +1,2 @@ set(the_description "2D Features Framework") ocv_define_module(features2d opencv_imgproc opencv_flann OPTIONAL opencv_highgui) - diff --git a/modules/features2d/doc/common_interfaces_of_descriptor_extractors.rst b/modules/features2d/doc/common_interfaces_of_descriptor_extractors.rst index 63e56f6786..83688c0a31 100644 --- a/modules/features2d/doc/common_interfaces_of_descriptor_extractors.rst +++ b/modules/features2d/doc/common_interfaces_of_descriptor_extractors.rst @@ -9,7 +9,10 @@ represented as vectors in a multidimensional space. All objects that implement t descriptor extractors inherit the :ocv:class:`DescriptorExtractor` interface. +.. note:: + * An example explaining keypoint extraction can be found at opencv_source_code/samples/cpp/descriptor_extractor_matcher.cpp + * An example on descriptor evaluation can be found at opencv_source_code/samples/cpp/detector_descriptor_evaluation.cpp DescriptorExtractor ------------------- @@ -33,7 +36,7 @@ Abstract base class for computing descriptors for image keypoints. :: virtual int descriptorSize() const = 0; virtual int descriptorType() const = 0; - static Ptr create( const string& descriptorExtractorType ); + static Ptr create( const String& descriptorExtractorType ); protected: ... @@ -57,6 +60,8 @@ Computes the descriptors for a set of keypoints detected in an image (first vari .. ocv:function:: void DescriptorExtractor::compute( const vector& images, vector >& keypoints, vector& descriptors ) const +.. ocv:pyfunction:: cv2.DescriptorExtractor_create.compute(image, keypoints[, descriptors]) -> keypoints, descriptors + :param image: Image. :param images: Image set. @@ -70,7 +75,9 @@ DescriptorExtractor::create ------------------------------- Creates a descriptor extractor by name. -.. ocv:function:: Ptr DescriptorExtractor::create( const string& descriptorExtractorType ) +.. ocv:function:: Ptr DescriptorExtractor::create( const String& descriptorExtractorType ) + +.. ocv:pyfunction:: cv2.DescriptorExtractor_create(descriptorExtractorType) -> retval :param descriptorExtractorType: Descriptor extractor type. @@ -78,9 +85,10 @@ The current implementation supports the following types of a descriptor extracto * ``"SIFT"`` -- :ocv:class:`SIFT` * ``"SURF"`` -- :ocv:class:`SURF` - * ``"ORB"`` -- :ocv:class:`ORB` - * ``"BRISK"`` -- :ocv:class:`BRISK` * ``"BRIEF"`` -- :ocv:class:`BriefDescriptorExtractor` + * ``"BRISK"`` -- :ocv:class:`BRISK` + * ``"ORB"`` -- :ocv:class:`ORB` + * ``"FREAK"`` -- :ocv:class:`FREAK` A combined format is also supported: descriptor extractor adapter name ( ``"Opponent"`` -- :ocv:class:`OpponentColorDescriptorExtractor` ) + descriptor extractor name (see above), @@ -137,4 +145,6 @@ Strecha C., Fua P. *BRIEF: Binary Robust Independent Elementary Features* , ... }; +.. note:: + * A complete BRIEF extractor sample can be found at opencv_source_code/samples/cpp/brief_match_test.cpp diff --git a/modules/features2d/doc/common_interfaces_of_descriptor_matchers.rst b/modules/features2d/doc/common_interfaces_of_descriptor_matchers.rst index 8596ae43db..2c2cf28f8d 100644 --- a/modules/features2d/doc/common_interfaces_of_descriptor_matchers.rst +++ b/modules/features2d/doc/common_interfaces_of_descriptor_matchers.rst @@ -9,34 +9,11 @@ that are represented as vectors in a multidimensional space. All objects that im descriptor matchers inherit the :ocv:class:`DescriptorMatcher` interface. -DMatch ------- -.. ocv:struct:: DMatch - -Class for matching keypoint descriptors: query descriptor index, -train descriptor index, train image index, and distance between descriptors. :: - - struct DMatch - { - DMatch() : queryIdx(-1), trainIdx(-1), imgIdx(-1), - distance(std::numeric_limits::max()) {} - DMatch( int _queryIdx, int _trainIdx, float _distance ) : - queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(-1), - distance(_distance) {} - DMatch( int _queryIdx, int _trainIdx, int _imgIdx, float _distance ) : - queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(_imgIdx), - distance(_distance) {} - - int queryIdx; // query descriptor index - int trainIdx; // train descriptor index - int imgIdx; // train image index - - float distance; - - // less is better - bool operator<( const DMatch &m ) const; - }; +.. note:: + * An example explaining keypoint matching can be found at opencv_source_code/samples/cpp/descriptor_extractor_matcher.cpp + * An example on descriptor matching evaluation can be found at opencv_source_code/samples/cpp/detector_descriptor_matcher_evaluation.cpp + * An example on one to many image matching can be found at opencv_source_code/samples/cpp/matching_to_many_images.cpp DescriptorMatcher ----------------- @@ -88,7 +65,7 @@ with an image set. :: virtual Ptr clone( bool emptyTrainData=false ) const = 0; - static Ptr create( const string& descriptorMatcherType ); + static Ptr create( const String& descriptorMatcherType ); protected: vector trainDescCollection; @@ -217,7 +194,7 @@ For each query descriptor, finds the training descriptors not farther than the s :param compactResult: Parameter used when the mask (or masks) is not empty. If ``compactResult`` is false, the ``matches`` vector has the same size as ``queryDescriptors`` rows. If ``compactResult`` is true, the ``matches`` vector does not contain matches for fully masked-out query descriptors. - :param maxDistance: Threshold for the distance between matched descriptors. + :param maxDistance: Threshold for the distance between matched descriptors. Distance means here metric distance (e.g. Hamming distance), not the distance between coordinates (which is measured in Pixels)! For each query descriptor, the methods find such training descriptors that the distance between the query descriptor and the training descriptor is equal or smaller than ``maxDistance``. Found matches are returned in the distance increasing order. @@ -237,7 +214,7 @@ DescriptorMatcher::create ----------------------------- Creates a descriptor matcher of a given type with the default parameters (using default constructor). -.. ocv:function:: Ptr DescriptorMatcher::create( const string& descriptorMatcherType ) +.. ocv:function:: Ptr DescriptorMatcher::create( const String& descriptorMatcherType ) :param descriptorMatcherType: Descriptor matcher type. Now the following matcher types are supported: @@ -299,4 +276,3 @@ Flann-based descriptor matcher. This matcher trains :ocv:class:`flann::Index_` o }; .. - diff --git a/modules/features2d/doc/common_interfaces_of_feature_detectors.rst b/modules/features2d/doc/common_interfaces_of_feature_detectors.rst index 81c72d3a81..434585d1e4 100644 --- a/modules/features2d/doc/common_interfaces_of_feature_detectors.rst +++ b/modules/features2d/doc/common_interfaces_of_feature_detectors.rst @@ -8,64 +8,9 @@ between different algorithms solving the same problem. All objects that implemen inherit the :ocv:class:`FeatureDetector` interface. -KeyPoint --------- -.. ocv:class:: KeyPoint - - Data structure for salient point detectors. - - .. ocv:member:: Point2f pt - - coordinates of the keypoint - - .. ocv:member:: float size - - diameter of the meaningful keypoint neighborhood - - .. ocv:member:: float angle - - computed orientation of the keypoint (-1 if not applicable). Its possible values are in a range [0,360) degrees. It is measured relative to image coordinate system (y-axis is directed downward), ie in clockwise. - - .. ocv:member:: float response - - the response by which the most strong keypoints have been selected. Can be used for further sorting or subsampling - - .. ocv:member:: int octave - - octave (pyramid layer) from which the keypoint has been extracted - - .. ocv:member:: int class_id - - object id that can be used to clustered keypoints by an object they belong to - -KeyPoint::KeyPoint ------------------- -The keypoint constructors - -.. ocv:function:: KeyPoint::KeyPoint() - -.. ocv:function:: KeyPoint::KeyPoint(Point2f _pt, float _size, float _angle=-1, float _response=0, int _octave=0, int _class_id=-1) - -.. ocv:function:: KeyPoint::KeyPoint(float x, float y, float _size, float _angle=-1, float _response=0, int _octave=0, int _class_id=-1) - -.. ocv:pyfunction:: cv2.KeyPoint([x, y, _size[, _angle[, _response[, _octave[, _class_id]]]]]) -> - - :param x: x-coordinate of the keypoint - - :param y: y-coordinate of the keypoint - - :param _pt: x & y coordinates of the keypoint - - :param _size: keypoint diameter - - :param _angle: keypoint orientation - - :param _response: keypoint detector response on the keypoint (that is, strength of the keypoint) - - :param _octave: pyramid octave in which the keypoint has been detected - - :param _class_id: object id +.. note:: + * An example explaining keypoint detection can be found at opencv_source_code/samples/cpp/descriptor_extractor_matcher.cpp FeatureDetector --------------- @@ -88,7 +33,7 @@ Abstract base class for 2D image feature detectors. :: virtual void read(const FileNode&); virtual void write(FileStorage&) const; - static Ptr create( const string& detectorType ); + static Ptr create( const String& detectorType ); protected: ... @@ -102,6 +47,8 @@ Detects keypoints in an image (first variant) or image set (second variant). .. ocv:function:: void FeatureDetector::detect( const vector& images, vector >& keypoints, const vector& masks=vector() ) const +.. ocv:pyfunction:: cv2.FeatureDetector_create.detect(image[, mask]) -> keypoints + :param image: Image. :param images: Image set. @@ -116,7 +63,9 @@ FeatureDetector::create ----------------------- Creates a feature detector by its name. -.. ocv:function:: Ptr FeatureDetector::create( const string& detectorType ) +.. ocv:function:: Ptr FeatureDetector::create( const String& detectorType ) + +.. ocv:pyfunction:: cv2.FeatureDetector_create(detectorType) -> retval :param detectorType: Feature detector type. @@ -220,7 +169,7 @@ StarFeatureDetector ------------------- .. ocv:class:: StarFeatureDetector : public FeatureDetector -The class implements the keypoint detector introduced by K. Konolige, synonym of ``StarDetector``. :: +The class implements the keypoint detector introduced by [Agrawal08]_, synonym of ``StarDetector``. :: class StarFeatureDetector : public FeatureDetector { @@ -234,6 +183,9 @@ The class implements the keypoint detector introduced by K. Konolige, synonym of ... }; +.. [Agrawal08] Agrawal, M., Konolige, K., & Blas, M. R. (2008). Censure: Center surround extremas for realtime feature detection and matching. In Computer Vision–ECCV 2008 (pp. 102-115). Springer Berlin Heidelberg. + + DenseFeatureDetector -------------------- .. ocv:class:: DenseFeatureDetector : public FeatureDetector @@ -439,7 +391,7 @@ Class providing an interface for adjusting parameters of a feature detector. Thi virtual void tooMany(int max, int n_detected) = 0; virtual bool good() const = 0; virtual Ptr clone() const = 0; - static Ptr create( const string& detectorType ); + static Ptr create( const String& detectorType ); }; @@ -500,7 +452,7 @@ AdjusterAdapter::create ----------------------- Creates an adjuster adapter by name -.. ocv:function:: Ptr AdjusterAdapter::create( const string& detectorType ) +.. ocv:function:: Ptr AdjusterAdapter::create( const String& detectorType ) Creates an adjuster adapter by name ``detectorType``. The detector name is the same as in :ocv:func:`FeatureDetector::create`, but now supports ``"FAST"``, ``"STAR"``, and ``"SURF"`` only. diff --git a/modules/features2d/doc/common_interfaces_of_generic_descriptor_matchers.rst b/modules/features2d/doc/common_interfaces_of_generic_descriptor_matchers.rst index a306c66067..5a7f952bc2 100644 --- a/modules/features2d/doc/common_interfaces_of_generic_descriptor_matchers.rst +++ b/modules/features2d/doc/common_interfaces_of_generic_descriptor_matchers.rst @@ -11,7 +11,11 @@ Every descriptor with the :ocv:class:`VectorDescriptorMatcher` ). There are descriptors such as the One-way descriptor and Ferns that have the ``GenericDescriptorMatcher`` interface implemented but do not support ``DescriptorExtractor``. +.. note:: + * An example explaining keypoint description can be found at opencv_source_code/samples/cpp/descriptor_extractor_matcher.cpp + * An example on descriptor matching evaluation can be found at opencv_source_code/samples/cpp/detector_descriptor_matcher_evaluation.cpp + * An example on one to many image matching can be found at opencv_source_code/samples/cpp/matching_to_many_images.cpp GenericDescriptorMatcher ------------------------ @@ -270,5 +274,3 @@ Example: :: VectorDescriptorMatcher matcher( new SurfDescriptorExtractor, new BruteForceMatcher > ); - - diff --git a/modules/features2d/doc/drawing_function_of_keypoints_and_matches.rst b/modules/features2d/doc/drawing_function_of_keypoints_and_matches.rst index 2669ab9f27..68c68fc6c4 100644 --- a/modules/features2d/doc/drawing_function_of_keypoints_and_matches.rst +++ b/modules/features2d/doc/drawing_function_of_keypoints_and_matches.rst @@ -11,6 +11,10 @@ Draws the found matches of keypoints from two images. .. ocv:function:: void drawMatches( const Mat& img1, const vector& keypoints1, const Mat& img2, const vector& keypoints2, const vector >& matches1to2, Mat& outImg, const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1), const vector >& matchesMask=vector >(), int flags=DrawMatchesFlags::DEFAULT ) +.. ocv:pyfunction:: cv2.drawMatches(img1, keypoints1, img2, keypoints2, matches1to2[, outImg[, matchColor[, singlePointColor[, matchesMask[, flags]]]]]) -> outImg + +.. ocv:pyfunction:: cv2.drawMatchesKnn(img1, keypoints1, img2, keypoints2, matches1to2[, outImg[, matchColor[, singlePointColor[, matchesMask[, flags]]]]]) -> outImg + :param img1: First source image. @@ -67,6 +71,8 @@ Draws keypoints. .. ocv:function:: void drawKeypoints( const Mat& image, const vector& keypoints, Mat& outImage, const Scalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT ) +.. ocv:pyfunction:: cv2.drawKeypoints(image, keypoints[, outImage[, color[, flags]]]) -> outImage + :param image: Source image. :param keypoints: Keypoints from the source image. @@ -77,3 +83,4 @@ Draws keypoints. :param flags: Flags setting drawing features. Possible ``flags`` bit values are defined by ``DrawMatchesFlags``. See details above in :ocv:func:`drawMatches` . +.. note:: For Python API, flags are modified as `cv2.DRAW_MATCHES_FLAGS_DEFAULT`, `cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS`, `cv2.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG`, `cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS` diff --git a/modules/features2d/doc/feature_detection_and_description.rst b/modules/features2d/doc/feature_detection_and_description.rst index 659fa4c3b2..a6fe7c8fad 100644 --- a/modules/features2d/doc/feature_detection_and_description.rst +++ b/modules/features2d/doc/feature_detection_and_description.rst @@ -3,6 +3,10 @@ Feature Detection and Description .. highlight:: cpp +.. note:: + + * An example explaining keypoint detection and description can be found at opencv_source_code/samples/cpp/descriptor_extractor_matcher.cpp + FAST ---- Detects corners using the FAST algorithm @@ -10,6 +14,11 @@ Detects corners using the FAST algorithm .. ocv:function:: void FAST( InputArray image, vector& keypoints, int threshold, bool nonmaxSupression=true ) .. ocv:function:: void FAST( InputArray image, vector& keypoints, int threshold, bool nonmaxSupression, int type ) +.. ocv:pyfunction:: cv2.FastFeatureDetector([, threshold[, nonmaxSuppression]]) -> +.. ocv:pyfunction:: cv2.FastFeatureDetector(threshold, nonmaxSuppression, type) -> +.. ocv:pyfunction:: cv2.FastFeatureDetector.detect(image[, mask]) -> keypoints + + :param image: grayscale image where keypoints (corners) are detected. :param keypoints: keypoints detected on the image. @@ -22,6 +31,9 @@ Detects corners using the FAST algorithm Detects corners using the FAST algorithm by [Rosten06]_. +..note:: In Python API, types are given as ``cv2.FAST_FEATURE_DETECTOR_TYPE_5_8``, ``cv2.FAST_FEATURE_DETECTOR_TYPE_7_12`` and ``cv2.FAST_FEATURE_DETECTOR_TYPE_9_16``. For corner detection, use ``cv2.FAST.detect()`` method. + + .. [Rosten06] E. Rosten. Machine Learning for High-speed Corner Detection, 2006. @@ -48,7 +60,11 @@ Maximally stable extremal region extractor. :: }; The class encapsulates all the parameters of the MSER extraction algorithm (see -http://en.wikipedia.org/wiki/Maximally_stable_extremal_regions). Also see http://opencv.willowgarage.com/wiki/documentation/cpp/features2d/MSER for useful comments and parameters description. +http://en.wikipedia.org/wiki/Maximally_stable_extremal_regions). Also see http://code.opencv.org/projects/opencv/wiki/MSER for useful comments and parameters description. + +.. note:: + + * (Python) A complete example showing the use of the MSER detector can be found at opencv_source_code/samples/python2/mser.py ORB @@ -65,6 +81,9 @@ The ORB constructor .. ocv:function:: ORB::ORB(int nfeatures = 500, float scaleFactor = 1.2f, int nlevels = 8, int edgeThreshold = 31, int firstLevel = 0, int WTA_K=2, int scoreType=ORB::HARRIS_SCORE, int patchSize=31) +.. ocv:pyfunction:: cv2.ORB([, nfeatures[, scaleFactor[, nlevels[, edgeThreshold[, firstLevel[, WTA_K[, scoreType[, patchSize]]]]]]]]) -> + + :param nfeatures: The maximum number of features to retain. :param scaleFactor: Pyramid decimation ratio, greater than 1. ``scaleFactor==2`` means the classical pyramid, where each next level has 4x less pixels than the previous, but such a big scale factor will degrade feature matching scores dramatically. On the other hand, too close to 1 scale factor will mean that to cover certain scale range you will need more pyramid levels and so the speed will suffer. @@ -87,6 +106,11 @@ Finds keypoints in an image and computes their descriptors .. ocv:function:: void ORB::operator()(InputArray image, InputArray mask, vector& keypoints, OutputArray descriptors, bool useProvidedKeypoints=false ) const +.. ocv:pyfunction:: cv2.ORB.detect(image[, mask]) -> keypoints +.. ocv:pyfunction:: cv2.ORB.compute(image, keypoints[, descriptors]) -> keypoints, descriptors +.. ocv:pyfunction:: cv2.ORB.detectAndCompute(image, mask[, descriptors[, useProvidedKeypoints]]) -> keypoints, descriptors + + :param image: The input 8-bit grayscale image. :param mask: The operation mask. @@ -97,6 +121,7 @@ Finds keypoints in an image and computes their descriptors :param useProvidedKeypoints: If it is true, then the method will use the provided vector of keypoints instead of detecting them. + BRISK ----- .. ocv:class:: BRISK : public Feature2D @@ -111,6 +136,8 @@ The BRISK constructor .. ocv:function:: BRISK::BRISK(int thresh=30, int octaves=3, float patternScale=1.0f) +.. ocv:pyfunction:: cv2.BRISK([, thresh[, octaves[, patternScale]]]) -> + :param thresh: FAST/AGAST detection threshold score. :param octaves: detection octaves. Use 0 to do single scale. @@ -123,6 +150,8 @@ The BRISK constructor for a custom pattern .. ocv:function:: BRISK::BRISK(std::vector &radiusList, std::vector &numberList, float dMax=5.85f, float dMin=8.2f, std::vector indexChange=std::vector()) +.. ocv:pyfunction:: cv2.BRISK(radiusList, numberList[, dMax[, dMin[, indexChange]]]) -> + :param radiusList: defines the radii (in pixels) where the samples around a keypoint are taken (for keypoint scale 1). :param numberList: defines the number of sampling points on the sampling circle. Must be the same size as radiusList.. @@ -139,6 +168,10 @@ Finds keypoints in an image and computes their descriptors .. ocv:function:: void BRISK::operator()(InputArray image, InputArray mask, vector& keypoints, OutputArray descriptors, bool useProvidedKeypoints=false ) const +.. ocv:pyfunction:: cv2.BRISK.detect(image[, mask]) -> keypoints +.. ocv:pyfunction:: cv2.BRISK.compute(image, keypoints[, descriptors]) -> keypoints, descriptors +.. ocv:pyfunction:: cv2.BRISK.detectAndCompute(image, mask[, descriptors[, useProvidedKeypoints]]) -> keypoints, descriptors + :param image: The input 8-bit grayscale image. :param mask: The operation mask. @@ -157,6 +190,10 @@ Class implementing the FREAK (*Fast Retina Keypoint*) keypoint descriptor, descr .. [AOV12] A. Alahi, R. Ortiz, and P. Vandergheynst. FREAK: Fast Retina Keypoint. In IEEE Conference on Computer Vision and Pattern Recognition, 2012. CVPR 2012 Open Source Award Winner. +.. note:: + + * An example on how to use the FREAK descriptor can be found at opencv_source_code/samples/cpp/freak_demo.cpp + FREAK::FREAK ------------ The FREAK constructor diff --git a/modules/features2d/doc/object_categorization.rst b/modules/features2d/doc/object_categorization.rst index 73089ce7ad..644634fd06 100644 --- a/modules/features2d/doc/object_categorization.rst +++ b/modules/features2d/doc/object_categorization.rst @@ -5,6 +5,12 @@ Object Categorization This section describes approaches based on local 2D features and used to categorize objects. +.. note:: + + * A complete Bag-Of-Words sample can be found at opencv_source_code/samples/cpp/bagofwords_classification.cpp + + * (Python) An example using the features2D framework to perform object categorization can be found at opencv_source_code/samples/python2/find_obj.py + BOWTrainer ---------- .. ocv:class:: BOWTrainer @@ -198,4 +204,3 @@ BOWImgDescriptorExtractor::descriptorType Returns an image descriptor type. .. ocv:function:: int BOWImgDescriptorExtractor::descriptorType() const - diff --git a/modules/features2d/include/opencv2/features2d.hpp b/modules/features2d/include/opencv2/features2d.hpp index 8f32445ca2..af687e3085 100644 --- a/modules/features2d/include/opencv2/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d.hpp @@ -46,72 +46,15 @@ #include "opencv2/core.hpp" #include "opencv2/flann/miniflann.hpp" -#ifdef __cplusplus -#include - namespace cv { CV_EXPORTS bool initModule_features2d(); -/*! - The Keypoint Class - - The class instance stores a keypoint, i.e. a point feature found by one of many available keypoint detectors, such as - Harris corner detector, cv::FAST, cv::StarDetector, cv::SURF, cv::SIFT, cv::LDetector etc. - - The keypoint is characterized by the 2D position, scale - (proportional to the diameter of the neighborhood that needs to be taken into account), - orientation and some other parameters. The keypoint neighborhood is then analyzed by another algorithm that builds a descriptor - (usually represented as a feature vector). The keypoints representing the same object in different images can then be matched using - cv::KDTree or another method. -*/ -class CV_EXPORTS_W_SIMPLE KeyPoint -{ -public: - //! the default constructor - CV_WRAP KeyPoint() : pt(0,0), size(0), angle(-1), response(0), octave(0), class_id(-1) {} - //! the full constructor - KeyPoint(Point2f _pt, float _size, float _angle=-1, - float _response=0, int _octave=0, int _class_id=-1) - : pt(_pt), size(_size), angle(_angle), - response(_response), octave(_octave), class_id(_class_id) {} - //! another form of the full constructor - CV_WRAP KeyPoint(float x, float y, float _size, float _angle=-1, - float _response=0, int _octave=0, int _class_id=-1) - : pt(x, y), size(_size), angle(_angle), - response(_response), octave(_octave), class_id(_class_id) {} - - size_t hash() const; - - //! converts vector of keypoints to vector of points - static void convert(const std::vector& keypoints, - CV_OUT std::vector& points2f, - const std::vector& keypointIndexes=std::vector()); - //! converts vector of points to the vector of keypoints, where each keypoint is assigned the same size and the same orientation - static void convert(const std::vector& points2f, - CV_OUT std::vector& keypoints, - float size=1, float response=1, int octave=0, int class_id=-1); - - //! computes overlap for pair of keypoints; - //! overlap is a ratio between area of keypoint regions intersection and - //! area of keypoint regions union (now keypoint region is circle) - static float overlap(const KeyPoint& kp1, const KeyPoint& kp2); - - CV_PROP_RW Point2f pt; //!< coordinates of the keypoints - CV_PROP_RW float size; //!< diameter of the meaningful keypoint neighborhood - CV_PROP_RW float angle; //!< computed orientation of the keypoint (-1 if not applicable); - //!< it's in [0,360) degrees and measured relative to - //!< image coordinate system, ie in clockwise. - CV_PROP_RW float response; //!< the response by which the most strong keypoints have been selected. Can be used for the further sorting or subsampling - CV_PROP_RW int octave; //!< octave (pyramid layer) from which the keypoint has been extracted - CV_PROP_RW int class_id; //!< object class (if the keypoints need to be clustered by an object they belong to) -}; - -//! writes vector of keypoints to the file storage -CV_EXPORTS void write(FileStorage& fs, const std::string& name, const std::vector& keypoints); -//! reads vector of keypoints from the specified file storage node -CV_EXPORTS void read(const FileNode& node, CV_OUT std::vector& keypoints); +// //! writes vector of keypoints to the file storage +// CV_EXPORTS void write(FileStorage& fs, const String& name, const std::vector& keypoints); +// //! reads vector of keypoints from the specified file storage node +// CV_EXPORTS void read(const FileNode& node, CV_OUT std::vector& keypoints); /* * A class filters a vector of keypoints. @@ -179,7 +122,7 @@ public: CV_WRAP virtual bool empty() const; // Create feature detector by detector name. - CV_WRAP static Ptr create( const std::string& detectorType ); + CV_WRAP static Ptr create( const String& detectorType ); protected: virtual void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask=Mat() ) const = 0; @@ -229,7 +172,7 @@ public: CV_WRAP virtual bool empty() const; - CV_WRAP static Ptr create( const std::string& descriptorExtractorType ); + CV_WRAP static Ptr create( const String& descriptorExtractorType ); protected: virtual void computeImpl( const Mat& image, std::vector& keypoints, Mat& descriptors ) const = 0; @@ -263,8 +206,10 @@ public: OutputArray descriptors, bool useProvidedKeypoints=false ) const = 0; + CV_WRAP void compute( const Mat& image, CV_OUT CV_IN_OUT std::vector& keypoints, CV_OUT Mat& descriptors ) const; + // Create feature detector and descriptor extractor by name. - CV_WRAP static Ptr create( const std::string& name ); + CV_WRAP static Ptr create( const String& name ); }; /*! @@ -590,11 +535,11 @@ protected: }; -class CV_EXPORTS GFTTDetector : public FeatureDetector +class CV_EXPORTS_W GFTTDetector : public FeatureDetector { public: - GFTTDetector( int maxCorners=1000, double qualityLevel=0.01, double minDistance=1, - int blockSize=3, bool useHarrisDetector=false, double k=0.04 ); + CV_WRAP GFTTDetector( int maxCorners=1000, double qualityLevel=0.01, double minDistance=1, + int blockSize=3, bool useHarrisDetector=false, double k=0.04 ); AlgorithmInfo* info() const; protected: @@ -701,7 +646,7 @@ public: * gridRows Grid rows count. * gridCols Grid column count. */ - CV_WRAP GridAdaptedFeatureDetector( const Ptr& detector=0, + CV_WRAP GridAdaptedFeatureDetector( const Ptr& detector=Ptr(), int maxTotalKeypoints=1000, int gridRows=4, int gridCols=4 ); @@ -765,7 +710,7 @@ public: virtual Ptr clone() const = 0; - static Ptr create( const std::string& detectorType ); + static Ptr create( const String& detectorType ); }; /** \brief an adaptively adjusting detector that iteratively detects until the desired number * of features are detected. @@ -1016,7 +961,7 @@ struct CV_EXPORTS Hamming typedef Hamming HammingLUT; -template struct CV_EXPORTS HammingMultilevel +template struct HammingMultilevel { enum { normType = NORM_HAMMING + (cellsize>1) }; typedef unsigned char ValueType; @@ -1028,33 +973,6 @@ template struct CV_EXPORTS HammingMultilevel } }; -/****************************************************************************************\ -* DMatch * -\****************************************************************************************/ -/* - * Struct for matching: query descriptor index, train descriptor index, train image index and distance between descriptors. - */ -struct CV_EXPORTS_W_SIMPLE DMatch -{ - CV_WRAP DMatch() : queryIdx(-1), trainIdx(-1), imgIdx(-1), distance(FLT_MAX) {} - CV_WRAP DMatch( int _queryIdx, int _trainIdx, float _distance ) : - queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(-1), distance(_distance) {} - CV_WRAP DMatch( int _queryIdx, int _trainIdx, int _imgIdx, float _distance ) : - queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(_imgIdx), distance(_distance) {} - - CV_PROP_RW int queryIdx; // query descriptor index - CV_PROP_RW int trainIdx; // train descriptor index - CV_PROP_RW int imgIdx; // train image index - - CV_PROP_RW float distance; - - // less is better - bool operator<( const DMatch &m ) const - { - return distance < m.distance; - } -}; - /****************************************************************************************\ * DescriptorMatcher * \****************************************************************************************/ @@ -1141,7 +1059,7 @@ public: // but with empty train data. virtual Ptr clone( bool emptyTrainData=false ) const = 0; - CV_WRAP static Ptr create( const std::string& descriptorMatcherType ); + CV_WRAP static Ptr create( const String& descriptorMatcherType ); protected: /* * Class to work with descriptors from several images as with one merged matrix. @@ -1225,8 +1143,8 @@ protected: class CV_EXPORTS_W FlannBasedMatcher : public DescriptorMatcher { public: - CV_WRAP FlannBasedMatcher( const Ptr& indexParams=new flann::KDTreeIndexParams(), - const Ptr& searchParams=new flann::SearchParams() ); + CV_WRAP FlannBasedMatcher( const Ptr& indexParams=makePtr(), + const Ptr& searchParams=makePtr() ); virtual void add( const std::vector& descriptors ); virtual void clear(); @@ -1367,8 +1285,8 @@ public: // but with empty train data. virtual Ptr clone( bool emptyTrainData=false ) const = 0; - static Ptr create( const std::string& genericDescritptorMatcherType, - const std::string ¶msFilename=std::string() ); + static Ptr create( const String& genericDescritptorMatcherType, + const String ¶msFilename=String() ); protected: // In fact the matching is implemented only by the following two methods. These methods suppose @@ -1486,15 +1404,15 @@ CV_EXPORTS_W void drawKeypoints( const Mat& image, const std::vector& const Scalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT ); // Draws matches of keypints from two images on output image. -CV_EXPORTS void drawMatches( const Mat& img1, const std::vector& keypoints1, +CV_EXPORTS_W void drawMatches( const Mat& img1, const std::vector& keypoints1, const Mat& img2, const std::vector& keypoints2, - const std::vector& matches1to2, Mat& outImg, + const std::vector& matches1to2, CV_OUT Mat& outImg, const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1), const std::vector& matchesMask=std::vector(), int flags=DrawMatchesFlags::DEFAULT ); -CV_EXPORTS void drawMatches( const Mat& img1, const std::vector& keypoints1, +CV_EXPORTS_AS(drawMatchesKnn) void drawMatches( const Mat& img1, const std::vector& keypoints1, const Mat& img2, const std::vector& keypoints2, - const std::vector >& matches1to2, Mat& outImg, + const std::vector >& matches1to2, CV_OUT Mat& outImg, const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1), const std::vector >& matchesMask=std::vector >(), int flags=DrawMatchesFlags::DEFAULT ); @@ -1603,8 +1521,4 @@ protected: } /* namespace cv */ -#endif /* __cplusplus */ - #endif - -/* End of file. */ diff --git a/modules/features2d/include/opencv2/features2d/features2d.hpp b/modules/features2d/include/opencv2/features2d/features2d.hpp index c825295ecd..e81df0ad08 100644 --- a/modules/features2d/include/opencv2/features2d/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d/features2d.hpp @@ -45,4 +45,4 @@ #error this is a compatibility header which should not be used inside the OpenCV library #endif -#include "opencv2/features2d.hpp" \ No newline at end of file +#include "opencv2/features2d.hpp" diff --git a/modules/features2d/perf/perf_fast.cpp b/modules/features2d/perf/perf_fast.cpp index 465bef7688..25b82bd412 100644 --- a/modules/features2d/perf/perf_fast.cpp +++ b/modules/features2d/perf/perf_fast.cpp @@ -18,7 +18,7 @@ typedef perf::TestBaseWithParam fast; PERF_TEST_P(fast, detect, testing::Combine( testing::Values(FAST_IMAGES), - testing::ValuesIn(FastType::all()) + FastType::all() )) { string filename = getDataPath(get<0>(GetParam())); @@ -41,4 +41,3 @@ PERF_TEST_P(fast, detect, testing::Combine( SANITY_CHECK_KEYPOINTS(points); } - diff --git a/modules/features2d/perf/perf_precomp.cpp b/modules/features2d/perf/perf_precomp.cpp deleted file mode 100644 index 8552ac3d42..0000000000 --- a/modules/features2d/perf/perf_precomp.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "perf_precomp.hpp" diff --git a/modules/features2d/src/bagofwords.cpp b/modules/features2d/src/bagofwords.cpp index b27b85123e..a257f6cbe4 100644 --- a/modules/features2d/src/bagofwords.cpp +++ b/modules/features2d/src/bagofwords.cpp @@ -147,7 +147,7 @@ void BOWImgDescriptorExtractor::compute( const Mat& image, std::vector int clusterCount = descriptorSize(); // = vocabulary.rows // Compute descriptors for the image. - Mat descriptors = _descriptors ? *_descriptors : Mat(); + Mat descriptors; dextractor->compute( image, keypoints, descriptors ); // Match keypoint descriptors to cluster center (to vocabulary) @@ -176,6 +176,11 @@ void BOWImgDescriptorExtractor::compute( const Mat& image, std::vector // Normalize image descriptor. imgDescriptor /= descriptors.rows; + + // Add the descriptors of image keypoints + if (_descriptors) { + *_descriptors = descriptors.clone(); + } } int BOWImgDescriptorExtractor::descriptorSize() const diff --git a/modules/features2d/src/blobdetector.cpp b/modules/features2d/src/blobdetector.cpp index 3f50f3c1af..92d50ee53c 100644 --- a/modules/features2d/src/blobdetector.cpp +++ b/modules/features2d/src/blobdetector.cpp @@ -42,6 +42,7 @@ #include "precomp.hpp" #include +#include //#define DEBUG_BLOB_DETECTOR @@ -169,7 +170,7 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm std::vector < std::vector > contours; Mat tmpBinaryImage = binaryImage.clone(); - findContours(tmpBinaryImage, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE); + findContours(tmpBinaryImage, contours, RETR_LIST, CHAIN_APPROX_NONE); #ifdef DEBUG_BLOB_DETECTOR // Mat keypointsImage; @@ -260,8 +261,11 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm center.radius = (dists[(dists.size() - 1) / 2] + dists[dists.size() / 2]) / 2.; } + if(moms.m00 == 0.0) + continue; centers.push_back(center); + #ifdef DEBUG_BLOB_DETECTOR // circle( keypointsImage, center.location, 1, Scalar(0,0,255), 1 ); #endif @@ -278,7 +282,7 @@ void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector &radiusList, std::vector &numberLi // get the total number of points const int rings = (int)radiusList.size(); - assert(radiusList.size()!=0&&radiusList.size()==numberList.size()); + CV_Assert(radiusList.size() != 0 && radiusList.size() == numberList.size()); points_ = 0; // remember the total number of points for (int ring = 0; ring < rings; ring++) { @@ -336,7 +336,7 @@ BRISK::generateKernel(std::vector &radiusList, std::vector &numberLi else if (norm_sq < dMax_sq) { // save to short pairs - assert(noShortPairs_& k bool doOrientation=true; if (useProvidedKeypoints) doOrientation = false; - computeDescriptorsAndOrOrientation(_image, _mask, keypoints, _descriptors, true, doOrientation, + + // If the user specified cv::noArray(), this will yield false. Otherwise it will return true. + bool doDescriptors = _descriptors.needed(); + + computeDescriptorsAndOrOrientation(_image, _mask, keypoints, _descriptors, doDescriptors, doOrientation, useProvidedKeypoints); } @@ -536,7 +540,7 @@ BRISK::computeDescriptorsAndOrOrientation(InputArray _image, InputArray _mask, s { Mat image = _image.getMat(), mask = _mask.getMat(); if( image.type() != CV_8UC1 ) - cvtColor(image, image, CV_BGR2GRAY); + cvtColor(image, image, COLOR_BGR2GRAY); if (!useProvidedKeypoints) { @@ -729,7 +733,7 @@ BRISK::computeKeypointsNoOrientation(InputArray _image, InputArray _mask, std::v { Mat image = _image.getMat(), mask = _mask.getMat(); if( image.type() != CV_8UC1 ) - cvtColor(_image, image, CV_BGR2GRAY); + cvtColor(_image, image, COLOR_BGR2GRAY); BriskScaleSpace briskScaleSpace(octaves); briskScaleSpace.constructPyramid(image); @@ -912,7 +916,7 @@ BriskScaleSpace::getKeypoints(const int threshold_, std::vector& k inline int BriskScaleSpace::getScoreAbove(const int layer, const int x_layer, const int y_layer) const { - assert(layer0); + CV_Assert(layer > 0); const BriskLayer& layerBelow = pyramid_[layer - 1]; // check the first row @@ -1999,7 +2003,7 @@ BriskLayer::BriskLayer(const cv::Mat& img_in, float scale_in, float offset_in) scale_ = scale_in; offset_ = offset_in; // create an agast detector - fast_9_16_ = new FastFeatureDetector(1, true, FastFeatureDetector::TYPE_9_16); + fast_9_16_ = makePtr(1, true, FastFeatureDetector::TYPE_9_16); makeOffsets(pixel_5_8_, (int)img_.step, 8); makeOffsets(pixel_9_16_, (int)img_.step, 16); } @@ -2021,7 +2025,7 @@ BriskLayer::BriskLayer(const BriskLayer& layer, int mode) offset_ = 0.5f * scale_ - 0.5f; } scores_ = cv::Mat::zeros(img_.rows, img_.cols, CV_8U); - fast_9_16_ = new FastFeatureDetector(1, false, FastFeatureDetector::TYPE_9_16); + fast_9_16_ = makePtr(1, false, FastFeatureDetector::TYPE_9_16); makeOffsets(pixel_5_8_, (int)img_.step, 8); makeOffsets(pixel_9_16_, (int)img_.step, 16); } @@ -2109,7 +2113,7 @@ BriskLayer::getAgastScore(float xf, float yf, int threshold_in, float scale_in) inline int BriskLayer::value(const cv::Mat& mat, float xf, float yf, float scale_in) const { - assert(!mat.empty()); + CV_Assert(!mat.empty()); // get the position const int x = cvFloor(xf); const int y = cvFloor(yf); @@ -2216,8 +2220,8 @@ inline void BriskLayer::halfsample(const cv::Mat& srcimg, cv::Mat& dstimg) { // make sure the destination image is of the right size: - assert(srcimg.cols/2==dstimg.cols); - assert(srcimg.rows/2==dstimg.rows); + CV_Assert(srcimg.cols / 2 == dstimg.cols); + CV_Assert(srcimg.rows / 2 == dstimg.rows); // handle non-SSE case resize(srcimg, dstimg, dstimg.size(), 0, 0, INTER_AREA); @@ -2227,8 +2231,8 @@ inline void BriskLayer::twothirdsample(const cv::Mat& srcimg, cv::Mat& dstimg) { // make sure the destination image is of the right size: - assert((srcimg.cols/3)*2==dstimg.cols); - assert((srcimg.rows/3)*2==dstimg.rows); + CV_Assert((srcimg.cols / 3) * 2 == dstimg.cols); + CV_Assert((srcimg.rows / 3) * 2 == dstimg.rows); resize(srcimg, dstimg, dstimg.size(), 0, 0, INTER_AREA); } diff --git a/modules/features2d/src/descriptors.cpp b/modules/features2d/src/descriptors.cpp index 7f87bd5eba..b79768ae15 100644 --- a/modules/features2d/src/descriptors.cpp +++ b/modules/features2d/src/descriptors.cpp @@ -40,6 +40,7 @@ //M*/ #include "precomp.hpp" +#include namespace cv { @@ -92,18 +93,24 @@ void DescriptorExtractor::removeBorderKeypoints( std::vector& keypoint KeyPointsFilter::runByImageBorder( keypoints, imageSize, borderSize ); } -Ptr DescriptorExtractor::create(const std::string& descriptorExtractorType) +Ptr DescriptorExtractor::create(const String& descriptorExtractorType) { if( descriptorExtractorType.find("Opponent") == 0 ) { - size_t pos = std::string("Opponent").size(); - std::string type = descriptorExtractorType.substr(pos); - return new OpponentColorDescriptorExtractor(DescriptorExtractor::create(type)); + size_t pos = String("Opponent").size(); + String type = descriptorExtractorType.substr(pos); + return makePtr(DescriptorExtractor::create(type)); } return Algorithm::create("Feature2D." + descriptorExtractorType); } + +CV_WRAP void Feature2D::compute( const Mat& image, CV_OUT CV_IN_OUT std::vector& keypoints, CV_OUT Mat& descriptors ) const +{ + DescriptorExtractor::compute(image, keypoints, descriptors); +} + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// /****************************************************************************************\ @@ -112,13 +119,13 @@ Ptr DescriptorExtractor::create(const std::string& descript OpponentColorDescriptorExtractor::OpponentColorDescriptorExtractor( const Ptr& _descriptorExtractor ) : descriptorExtractor(_descriptorExtractor) { - CV_Assert( !descriptorExtractor.empty() ); + CV_Assert( descriptorExtractor ); } static void convertBGRImageToOpponentColorSpace( const Mat& bgrImage, std::vector& opponentChannels ) { if( bgrImage.type() != CV_8UC3 ) - CV_Error( CV_StsBadArg, "input image must be an BGR image of type CV_8UC3" ); + CV_Error( Error::StsBadArg, "input image must be an BGR image of type CV_8UC3" ); // Prepare opponent color space storage matrices. opponentChannels.resize( 3 ); @@ -242,7 +249,7 @@ int OpponentColorDescriptorExtractor::descriptorType() const bool OpponentColorDescriptorExtractor::empty() const { - return descriptorExtractor.empty() || (DescriptorExtractor*)(descriptorExtractor)->empty(); + return !descriptorExtractor || descriptorExtractor->empty(); } } diff --git a/modules/features2d/src/detectors.cpp b/modules/features2d/src/detectors.cpp index 19175f1b68..63a882dd3f 100644 --- a/modules/features2d/src/detectors.cpp +++ b/modules/features2d/src/detectors.cpp @@ -86,23 +86,23 @@ void FeatureDetector::removeInvalidPoints( const Mat& mask, std::vector FeatureDetector::create( const std::string& detectorType ) +Ptr FeatureDetector::create( const String& detectorType ) { if( detectorType.find("Grid") == 0 ) { - return new GridAdaptedFeatureDetector(FeatureDetector::create( + return makePtr(FeatureDetector::create( detectorType.substr(strlen("Grid")))); } if( detectorType.find("Pyramid") == 0 ) { - return new PyramidAdaptedFeatureDetector(FeatureDetector::create( + return makePtr(FeatureDetector::create( detectorType.substr(strlen("Pyramid")))); } if( detectorType.find("Dynamic") == 0 ) { - return new DynamicAdaptedFeatureDetector(AdjusterAdapter::create( + return makePtr(AdjusterAdapter::create( detectorType.substr(strlen("Dynamic")))); } @@ -128,7 +128,7 @@ GFTTDetector::GFTTDetector( int _nfeatures, double _qualityLevel, void GFTTDetector::detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask) const { Mat grayImage = image; - if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY ); + if( image.type() != CV_8U ) cvtColor( image, grayImage, COLOR_BGR2GRAY ); std::vector corners; goodFeaturesToTrack( grayImage, corners, nfeatures, qualityLevel, minDistance, mask, @@ -190,7 +190,7 @@ GridAdaptedFeatureDetector::GridAdaptedFeatureDetector( const Ptrempty(); + return !detector || detector->empty(); } struct ResponseComparator @@ -212,7 +212,7 @@ static void keepStrongest( int N, std::vector& keypoints ) } namespace { -class GridAdaptedFeatureDetectorInvoker +class GridAdaptedFeatureDetectorInvoker : public ParallelLoopBody { private: int gridRows_, gridCols_; @@ -221,29 +221,24 @@ private: const Mat& image_; const Mat& mask_; const Ptr& detector_; -#ifdef HAVE_TBB - tbb::mutex* kptLock_; -#endif + Mutex* kptLock_; GridAdaptedFeatureDetectorInvoker& operator=(const GridAdaptedFeatureDetectorInvoker&); // to quiet MSVC public: - GridAdaptedFeatureDetectorInvoker(const Ptr& detector, const Mat& image, const Mat& mask, std::vector& keypoints, int maxPerCell, int gridRows, int gridCols -#ifdef HAVE_TBB - , tbb::mutex* kptLock -#endif - ) : gridRows_(gridRows), gridCols_(gridCols), maxPerCell_(maxPerCell), - keypoints_(keypoints), image_(image), mask_(mask), detector_(detector) -#ifdef HAVE_TBB - , kptLock_(kptLock) -#endif + GridAdaptedFeatureDetectorInvoker(const Ptr& detector, const Mat& image, const Mat& mask, + std::vector& keypoints, int maxPerCell, int gridRows, int gridCols, + cv::Mutex* kptLock) + : gridRows_(gridRows), gridCols_(gridCols), maxPerCell_(maxPerCell), + keypoints_(keypoints), image_(image), mask_(mask), detector_(detector), + kptLock_(kptLock) { } - void operator() (const BlockedRange& range) const + void operator() (const Range& range) const { - for (int i = range.begin(); i < range.end(); ++i) + for (int i = range.start; i < range.end; ++i) { int celly = i / gridCols_; int cellx = i - celly * gridCols_; @@ -268,9 +263,8 @@ public: it->pt.x += col_range.start; it->pt.y += row_range.start; } -#ifdef HAVE_TBB - tbb::mutex::scoped_lock join_keypoints(*kptLock_); -#endif + + cv::AutoLock join_keypoints(*kptLock_); keypoints_.insert( keypoints_.end(), sub_keypoints.begin(), sub_keypoints.end() ); } } @@ -287,13 +281,9 @@ void GridAdaptedFeatureDetector::detectImpl( const Mat& image, std::vectorempty(); + return !detector || detector->empty(); } void PyramidAdaptedFeatureDetector::detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask ) const @@ -346,7 +336,7 @@ void PyramidAdaptedFeatureDetector::detectImpl( const Mat& image, std::vector& keypoints, Ma } else if( image.type() == CV_8UC1 ) { - cvtColor( image, outImage, CV_GRAY2BGR ); + cvtColor( image, outImage, COLOR_GRAY2BGR ); } else { - CV_Error( CV_StsBadArg, "Incorrect type of input image.\n" ); + CV_Error( Error::StsBadArg, "Incorrect type of input image.\n" ); } } @@ -129,7 +129,7 @@ static void _prepareImgAndDrawKeypoints( const Mat& img1, const std::vector outImg.cols || size.height > outImg.rows ) - CV_Error( CV_StsBadSize, "outImg has size less than need to draw img1 and img2 together" ); + CV_Error( Error::StsBadSize, "outImg has size less than need to draw img1 and img2 together" ); outImg1 = outImg( Rect(0, 0, img1.cols, img1.rows) ); outImg2 = outImg( Rect(img1.cols, 0, img2.cols, img2.rows) ); } @@ -141,12 +141,12 @@ static void _prepareImgAndDrawKeypoints( const Mat& img1, const std::vector& keypoints1, @@ -189,7 +189,7 @@ void drawMatches( const Mat& img1, const std::vector& keypoints1, const std::vector& matchesMask, int flags ) { if( !matchesMask.empty() && matchesMask.size() != matches1to2.size() ) - CV_Error( CV_StsBadSize, "matchesMask must have the same size as matches1to2" ); + CV_Error( Error::StsBadSize, "matchesMask must have the same size as matches1to2" ); Mat outImg1, outImg2; _prepareImgAndDrawKeypoints( img1, keypoints1, img2, keypoints2, @@ -218,7 +218,7 @@ void drawMatches( const Mat& img1, const std::vector& keypoints1, const std::vector >& matchesMask, int flags ) { if( !matchesMask.empty() && matchesMask.size() != matches1to2.size() ) - CV_Error( CV_StsBadSize, "matchesMask must have the same size as matches1to2" ); + CV_Error( Error::StsBadSize, "matchesMask must have the same size as matches1to2" ); Mat outImg1, outImg2; _prepareImgAndDrawKeypoints( img1, keypoints1, img2, keypoints2, diff --git a/modules/features2d/src/dynamic.cpp b/modules/features2d/src/dynamic.cpp index 523a3e1f82..6bd6ab4de8 100644 --- a/modules/features2d/src/dynamic.cpp +++ b/modules/features2d/src/dynamic.cpp @@ -51,7 +51,7 @@ DynamicAdaptedFeatureDetector::DynamicAdaptedFeatureDetector(const Ptrempty(); + return !adjuster_ || adjuster_->empty(); } void DynamicAdaptedFeatureDetector::detectImpl(const Mat& image, std::vector& keypoints, const Mat& mask) const @@ -124,7 +124,7 @@ bool FastAdjuster::good() const Ptr FastAdjuster::clone() const { - Ptr cloned_obj = new FastAdjuster( init_thresh_, nonmax_, min_thresh_, max_thresh_ ); + Ptr cloned_obj(new FastAdjuster( init_thresh_, nonmax_, min_thresh_, max_thresh_ )); return cloned_obj; } @@ -158,7 +158,7 @@ bool StarAdjuster::good() const Ptr StarAdjuster::clone() const { - Ptr cloned_obj = new StarAdjuster( init_thresh_, min_thresh_, max_thresh_ ); + Ptr cloned_obj(new StarAdjuster( init_thresh_, min_thresh_, max_thresh_ )); return cloned_obj; } @@ -195,25 +195,25 @@ bool SurfAdjuster::good() const Ptr SurfAdjuster::clone() const { - Ptr cloned_obj = new SurfAdjuster( init_thresh_, min_thresh_, max_thresh_ ); + Ptr cloned_obj(new SurfAdjuster( init_thresh_, min_thresh_, max_thresh_ )); return cloned_obj; } -Ptr AdjusterAdapter::create( const std::string& detectorType ) +Ptr AdjusterAdapter::create( const String& detectorType ) { Ptr adapter; if( !detectorType.compare( "FAST" ) ) { - adapter = new FastAdjuster(); + adapter = makePtr(); } else if( !detectorType.compare( "STAR" ) ) { - adapter = new StarAdjuster(); + adapter = makePtr(); } else if( !detectorType.compare( "SURF" ) ) { - adapter = new SurfAdjuster(); + adapter = makePtr(); } return adapter; diff --git a/modules/features2d/src/evaluation.cpp b/modules/features2d/src/evaluation.cpp index 591e1c20bc..5bde951d60 100644 --- a/modules/features2d/src/evaluation.cpp +++ b/modules/features2d/src/evaluation.cpp @@ -185,7 +185,7 @@ void EllipticKeyPoint::convert( const std::vector& src, std::vector& src, { if( !src.empty() ) { - assert( !H.empty() && H.cols == 3 && H.rows == 3); + CV_Assert( !H.empty() && H.cols == 3 && H.rows == 3); dst.resize(src.size()); std::vector::const_iterator srcIt = src.begin(); std::vector::iterator dstIt = dst.begin(); @@ -257,7 +257,7 @@ struct IntersectAreaCounter { CV_Assert( miny < maxy ); CV_Assert( dr > FLT_EPSILON ); - + int temp_bua = bua, temp_bna = bna; for( int i = range.begin(); i != range.end(); i++ ) { @@ -461,8 +461,8 @@ void cv::evaluateFeatureDetector( const Mat& img1, const Mat& img2, const Mat& H keypoints1 = _keypoints1 != 0 ? _keypoints1 : &buf1; keypoints2 = _keypoints2 != 0 ? _keypoints2 : &buf2; - if( (keypoints1->empty() || keypoints2->empty()) && fdetector.empty() ) - CV_Error( CV_StsBadArg, "fdetector must not be empty when keypoints1 or keypoints2 is empty" ); + if( (keypoints1->empty() || keypoints2->empty()) && !fdetector ) + CV_Error( Error::StsBadArg, "fdetector must not be empty when keypoints1 or keypoints2 is empty" ); if( keypoints1->empty() ) fdetector->detect( img1, *keypoints1 ); @@ -573,15 +573,15 @@ void cv::evaluateGenericDescriptorMatcher( const Mat& img1, const Mat& img2, con correctMatches1to2Mask = _correctMatches1to2Mask != 0 ? _correctMatches1to2Mask : &buf2; if( keypoints1.empty() ) - CV_Error( CV_StsBadArg, "keypoints1 must not be empty" ); + CV_Error( Error::StsBadArg, "keypoints1 must not be empty" ); - if( matches1to2->empty() && dmatcher.empty() ) - CV_Error( CV_StsBadArg, "dmatch must not be empty when matches1to2 is empty" ); + if( matches1to2->empty() && !dmatcher ) + CV_Error( Error::StsBadArg, "dmatch must not be empty when matches1to2 is empty" ); bool computeKeypoints2ByPrj = keypoints2.empty(); if( computeKeypoints2ByPrj ) { - assert(0); + CV_Error(Error::StsNotImplemented, ""); // TODO: add computing keypoints2 from keypoints1 using H1to2 } diff --git a/modules/features2d/src/fast.cpp b/modules/features2d/src/fast.cpp index 8306e3eb24..9e2181c140 100644 --- a/modules/features2d/src/fast.cpp +++ b/modules/features2d/src/fast.cpp @@ -100,61 +100,61 @@ void FAST_t(InputArray _img, std::vector& keypoints, int threshold, bo #if CV_SSE2 if( patternSize == 16 ) { - for(; j < img.cols - 16 - 3; j += 16, ptr += 16) - { - __m128i m0, m1; - __m128i v0 = _mm_loadu_si128((const __m128i*)ptr); - __m128i v1 = _mm_xor_si128(_mm_subs_epu8(v0, t), delta); - v0 = _mm_xor_si128(_mm_adds_epu8(v0, t), delta); - - __m128i x0 = _mm_sub_epi8(_mm_loadu_si128((const __m128i*)(ptr + pixel[0])), delta); - __m128i x1 = _mm_sub_epi8(_mm_loadu_si128((const __m128i*)(ptr + pixel[quarterPatternSize])), delta); - __m128i x2 = _mm_sub_epi8(_mm_loadu_si128((const __m128i*)(ptr + pixel[2*quarterPatternSize])), delta); - __m128i x3 = _mm_sub_epi8(_mm_loadu_si128((const __m128i*)(ptr + pixel[3*quarterPatternSize])), delta); - m0 = _mm_and_si128(_mm_cmpgt_epi8(x0, v0), _mm_cmpgt_epi8(x1, v0)); - m1 = _mm_and_si128(_mm_cmpgt_epi8(v1, x0), _mm_cmpgt_epi8(v1, x1)); - m0 = _mm_or_si128(m0, _mm_and_si128(_mm_cmpgt_epi8(x1, v0), _mm_cmpgt_epi8(x2, v0))); - m1 = _mm_or_si128(m1, _mm_and_si128(_mm_cmpgt_epi8(v1, x1), _mm_cmpgt_epi8(v1, x2))); - m0 = _mm_or_si128(m0, _mm_and_si128(_mm_cmpgt_epi8(x2, v0), _mm_cmpgt_epi8(x3, v0))); - m1 = _mm_or_si128(m1, _mm_and_si128(_mm_cmpgt_epi8(v1, x2), _mm_cmpgt_epi8(v1, x3))); - m0 = _mm_or_si128(m0, _mm_and_si128(_mm_cmpgt_epi8(x3, v0), _mm_cmpgt_epi8(x0, v0))); - m1 = _mm_or_si128(m1, _mm_and_si128(_mm_cmpgt_epi8(v1, x3), _mm_cmpgt_epi8(v1, x0))); - m0 = _mm_or_si128(m0, m1); - int mask = _mm_movemask_epi8(m0); - if( mask == 0 ) - continue; - if( (mask & 255) == 0 ) + for(; j < img.cols - 16 - 3; j += 16, ptr += 16) { - j -= 8; - ptr -= 8; - continue; - } + __m128i m0, m1; + __m128i v0 = _mm_loadu_si128((const __m128i*)ptr); + __m128i v1 = _mm_xor_si128(_mm_subs_epu8(v0, t), delta); + v0 = _mm_xor_si128(_mm_adds_epu8(v0, t), delta); - __m128i c0 = _mm_setzero_si128(), c1 = c0, max0 = c0, max1 = c0; - for( k = 0; k < N; k++ ) - { - __m128i x = _mm_xor_si128(_mm_loadu_si128((const __m128i*)(ptr + pixel[k])), delta); - m0 = _mm_cmpgt_epi8(x, v0); - m1 = _mm_cmpgt_epi8(v1, x); - - c0 = _mm_and_si128(_mm_sub_epi8(c0, m0), m0); - c1 = _mm_and_si128(_mm_sub_epi8(c1, m1), m1); - - max0 = _mm_max_epu8(max0, c0); - max1 = _mm_max_epu8(max1, c1); - } - - max0 = _mm_max_epu8(max0, max1); - int m = _mm_movemask_epi8(_mm_cmpgt_epi8(max0, K16)); - - for( k = 0; m > 0 && k < 16; k++, m >>= 1 ) - if(m & 1) + __m128i x0 = _mm_sub_epi8(_mm_loadu_si128((const __m128i*)(ptr + pixel[0])), delta); + __m128i x1 = _mm_sub_epi8(_mm_loadu_si128((const __m128i*)(ptr + pixel[quarterPatternSize])), delta); + __m128i x2 = _mm_sub_epi8(_mm_loadu_si128((const __m128i*)(ptr + pixel[2*quarterPatternSize])), delta); + __m128i x3 = _mm_sub_epi8(_mm_loadu_si128((const __m128i*)(ptr + pixel[3*quarterPatternSize])), delta); + m0 = _mm_and_si128(_mm_cmpgt_epi8(x0, v0), _mm_cmpgt_epi8(x1, v0)); + m1 = _mm_and_si128(_mm_cmpgt_epi8(v1, x0), _mm_cmpgt_epi8(v1, x1)); + m0 = _mm_or_si128(m0, _mm_and_si128(_mm_cmpgt_epi8(x1, v0), _mm_cmpgt_epi8(x2, v0))); + m1 = _mm_or_si128(m1, _mm_and_si128(_mm_cmpgt_epi8(v1, x1), _mm_cmpgt_epi8(v1, x2))); + m0 = _mm_or_si128(m0, _mm_and_si128(_mm_cmpgt_epi8(x2, v0), _mm_cmpgt_epi8(x3, v0))); + m1 = _mm_or_si128(m1, _mm_and_si128(_mm_cmpgt_epi8(v1, x2), _mm_cmpgt_epi8(v1, x3))); + m0 = _mm_or_si128(m0, _mm_and_si128(_mm_cmpgt_epi8(x3, v0), _mm_cmpgt_epi8(x0, v0))); + m1 = _mm_or_si128(m1, _mm_and_si128(_mm_cmpgt_epi8(v1, x3), _mm_cmpgt_epi8(v1, x0))); + m0 = _mm_or_si128(m0, m1); + int mask = _mm_movemask_epi8(m0); + if( mask == 0 ) + continue; + if( (mask & 255) == 0 ) { - cornerpos[ncorners++] = j+k; - if(nonmax_suppression) - curr[j+k] = (uchar)cornerScore(ptr+k, pixel, threshold); + j -= 8; + ptr -= 8; + continue; } - } + + __m128i c0 = _mm_setzero_si128(), c1 = c0, max0 = c0, max1 = c0; + for( k = 0; k < N; k++ ) + { + __m128i x = _mm_xor_si128(_mm_loadu_si128((const __m128i*)(ptr + pixel[k])), delta); + m0 = _mm_cmpgt_epi8(x, v0); + m1 = _mm_cmpgt_epi8(v1, x); + + c0 = _mm_and_si128(_mm_sub_epi8(c0, m0), m0); + c1 = _mm_and_si128(_mm_sub_epi8(c1, m1), m1); + + max0 = _mm_max_epu8(max0, c0); + max1 = _mm_max_epu8(max1, c1); + } + + max0 = _mm_max_epu8(max0, max1); + int m = _mm_movemask_epi8(_mm_cmpgt_epi8(max0, K16)); + + for( k = 0; m > 0 && k < 16; k++, m >>= 1 ) + if(m & 1) + { + cornerpos[ncorners++] = j+k; + if(nonmax_suppression) + curr[j+k] = (uchar)cornerScore(ptr+k, pixel, threshold); + } + } } #endif for( ; j < img.cols - 3; j++, ptr++ ) @@ -286,7 +286,7 @@ FastFeatureDetector::FastFeatureDetector( int _threshold, bool _nonmaxSuppressio void FastFeatureDetector::detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask ) const { Mat grayImage = image; - if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY ); + if( image.type() != CV_8U ) cvtColor( image, grayImage, COLOR_BGR2GRAY ); FAST( grayImage, keypoints, threshold, nonmaxSuppression, type ); KeyPointsFilter::runByPixelsMask( keypoints, mask ); } diff --git a/modules/features2d/src/fast_score.cpp b/modules/features2d/src/fast_score.cpp index 423b1f950d..de697b7c90 100644 --- a/modules/features2d/src/fast_score.cpp +++ b/modules/features2d/src/fast_score.cpp @@ -357,4 +357,3 @@ int cornerScore<8>(const uchar* ptr, const int pixel[], int threshold) } } // namespace cv - diff --git a/modules/features2d/src/features2d_init.cpp b/modules/features2d/src/features2d_init.cpp index 85640585f5..780a67b87a 100644 --- a/modules/features2d/src/features2d_init.cpp +++ b/modules/features2d/src/features2d_init.cpp @@ -44,7 +44,7 @@ using namespace cv; -Ptr Feature2D::create( const std::string& feature2DType ) +Ptr Feature2D::create( const String& feature2DType ) { return Algorithm::create("Feature2D." + feature2DType); } diff --git a/modules/features2d/src/freak.cpp b/modules/features2d/src/freak.cpp index 6c9093f7ce..086a2e2e71 100644 --- a/modules/features2d/src/freak.cpp +++ b/modules/features2d/src/freak.cpp @@ -206,7 +206,7 @@ void FREAK::buildPattern() descriptionPairs[i] = allPairs[selectedPairs0.at(i)]; } else { - CV_Error(CV_StsVecLengthErr, "Input vector does not match the required size"); + CV_Error(Error::StsVecLengthErr, "Input vector does not match the required size"); } } else { // default selected pairs @@ -548,7 +548,7 @@ std::vector FREAK::selectPairs(const std::vector& images int idxB = pairStat[m].idx; double corr(0); // compute correlation between 2 pairs - corr = fabs(compareHist(descriptorsFloat.col(idxA), descriptorsFloat.col(idxB), CV_COMP_CORREL)); + corr = fabs(compareHist(descriptorsFloat.col(idxA), descriptorsFloat.col(idxB), HISTCMP_CORREL)); if( corr > corrMax ) { corrMax = corr; @@ -575,7 +575,7 @@ std::vector FREAK::selectPairs(const std::vector& images else { if( verbose ) std::cout << "correlation threshold too small (restrictive)" << std::endl; - CV_Error(CV_StsError, "correlation threshold too small (restrictive)"); + CV_Error(Error::StsError, "correlation threshold too small (restrictive)"); } extAll = false; return idxBestPairs; diff --git a/modules/features2d/src/keypoint.cpp b/modules/features2d/src/keypoint.cpp index a4b960d1b3..0cf7ae0571 100644 --- a/modules/features2d/src/keypoint.cpp +++ b/modules/features2d/src/keypoint.cpp @@ -44,129 +44,6 @@ namespace cv { -size_t KeyPoint::hash() const -{ - size_t _Val = 2166136261U, scale = 16777619U; - Cv32suf u; - u.f = pt.x; _Val = (scale * _Val) ^ u.u; - u.f = pt.y; _Val = (scale * _Val) ^ u.u; - u.f = size; _Val = (scale * _Val) ^ u.u; - u.f = angle; _Val = (scale * _Val) ^ u.u; - u.f = response; _Val = (scale * _Val) ^ u.u; - _Val = (scale * _Val) ^ ((size_t) octave); - _Val = (scale * _Val) ^ ((size_t) class_id); - return _Val; -} - -void write(FileStorage& fs, const std::string& objname, const std::vector& keypoints) -{ - WriteStructContext ws(fs, objname, CV_NODE_SEQ + CV_NODE_FLOW); - - int i, npoints = (int)keypoints.size(); - for( i = 0; i < npoints; i++ ) - { - const KeyPoint& kpt = keypoints[i]; - write(fs, kpt.pt.x); - write(fs, kpt.pt.y); - write(fs, kpt.size); - write(fs, kpt.angle); - write(fs, kpt.response); - write(fs, kpt.octave); - write(fs, kpt.class_id); - } -} - - -void read(const FileNode& node, std::vector& keypoints) -{ - keypoints.resize(0); - FileNodeIterator it = node.begin(), it_end = node.end(); - for( ; it != it_end; ) - { - KeyPoint kpt; - it >> kpt.pt.x >> kpt.pt.y >> kpt.size >> kpt.angle >> kpt.response >> kpt.octave >> kpt.class_id; - keypoints.push_back(kpt); - } -} - - -void KeyPoint::convert(const std::vector& keypoints, std::vector& points2f, - const std::vector& keypointIndexes) -{ - if( keypointIndexes.empty() ) - { - points2f.resize( keypoints.size() ); - for( size_t i = 0; i < keypoints.size(); i++ ) - points2f[i] = keypoints[i].pt; - } - else - { - points2f.resize( keypointIndexes.size() ); - for( size_t i = 0; i < keypointIndexes.size(); i++ ) - { - int idx = keypointIndexes[i]; - if( idx >= 0 ) - points2f[i] = keypoints[idx].pt; - else - { - CV_Error( CV_StsBadArg, "keypointIndexes has element < 0. TODO: process this case" ); - //points2f[i] = Point2f(-1, -1); - } - } - } -} - -void KeyPoint::convert( const std::vector& points2f, std::vector& keypoints, - float size, float response, int octave, int class_id ) -{ - keypoints.resize(points2f.size()); - for( size_t i = 0; i < points2f.size(); i++ ) - keypoints[i] = KeyPoint(points2f[i], size, -1, response, octave, class_id); -} - -float KeyPoint::overlap( const KeyPoint& kp1, const KeyPoint& kp2 ) -{ - float a = kp1.size * 0.5f; - float b = kp2.size * 0.5f; - float a_2 = a * a; - float b_2 = b * b; - - Point2f p1 = kp1.pt; - Point2f p2 = kp2.pt; - float c = (float)norm( p1 - p2 ); - - float ovrl = 0.f; - - // one circle is completely encovered by the other => no intersection points! - if( std::min( a, b ) + c <= std::max( a, b ) ) - return std::min( a_2, b_2 ) / std::max( a_2, b_2 ); - - if( c < a + b ) // circles intersect - { - float c_2 = c * c; - float cosAlpha = ( b_2 + c_2 - a_2 ) / ( kp2.size * c ); - float cosBeta = ( a_2 + c_2 - b_2 ) / ( kp1.size * c ); - float alpha = acos( cosAlpha ); - float beta = acos( cosBeta ); - float sinAlpha = sin(alpha); - float sinBeta = sin(beta); - - float segmentAreaA = a_2 * beta; - float segmentAreaB = b_2 * alpha; - - float triangleAreaA = a_2 * sinBeta * cosBeta; - float triangleAreaB = b_2 * sinAlpha * cosAlpha; - - float intersectionArea = segmentAreaA + segmentAreaB - triangleAreaA - triangleAreaB; - float unionArea = (a_2 + b_2) * (float)CV_PI - intersectionArea; - - ovrl = intersectionArea / unionArea; - } - - return ovrl; -} - - struct KeypointResponseGreaterThanThreshold { KeypointResponseGreaterThanThreshold(float _value) : @@ -192,7 +69,7 @@ struct KeypointResponseGreater void KeyPointsFilter::retainBest(std::vector& keypoints, int n_points) { //this is only necessary if the keypoints size is greater than the number of desired points. - if( n_points > 0 && keypoints.size() > (size_t)n_points ) + if( n_points >= 0 && keypoints.size() > (size_t)n_points ) { if (n_points==0) { diff --git a/modules/features2d/src/matchers.cpp b/modules/features2d/src/matchers.cpp index 658c902f93..087c6a78bd 100644 --- a/modules/features2d/src/matchers.cpp +++ b/modules/features2d/src/matchers.cpp @@ -40,8 +40,8 @@ //M*/ #include "precomp.hpp" +#include -#include "opencv2/core/internal.hpp" #if defined(HAVE_EIGEN) && EIGEN_WORLD_VERSION == 2 #include #endif @@ -113,7 +113,7 @@ void DescriptorMatcher::DescriptorCollection::set( const std::vector& descr dim = descriptors[0].cols; type = descriptors[0].type(); } - assert( dim > 0 ); + CV_Assert( dim > 0 ); int count = startIdxs[imageCount-1] + descriptors[imageCount-1].rows; @@ -326,7 +326,7 @@ BFMatcher::BFMatcher( int _normType, bool _crossCheck ) Ptr BFMatcher::clone( bool emptyTrainData ) const { - BFMatcher* matcher = new BFMatcher(normType, crossCheck); + Ptr matcher = makePtr(normType, crossCheck); if( !emptyTrainData ) { matcher->trainDescCollection.resize(trainDescCollection.size()); @@ -456,36 +456,36 @@ void BFMatcher::radiusMatchImpl( const Mat& queryDescriptors, std::vector DescriptorMatcher::create( const std::string& descriptorMatcherType ) +Ptr DescriptorMatcher::create( const String& descriptorMatcherType ) { - DescriptorMatcher* dm = 0; + Ptr dm; if( !descriptorMatcherType.compare( "FlannBased" ) ) { - dm = new FlannBasedMatcher(); + dm = makePtr(); } else if( !descriptorMatcherType.compare( "BruteForce" ) ) // L2 { - dm = new BFMatcher(NORM_L2); + dm = makePtr(int(NORM_L2)); // anonymous enums can't be template parameters } else if( !descriptorMatcherType.compare( "BruteForce-SL2" ) ) // Squared L2 { - dm = new BFMatcher(NORM_L2SQR); + dm = makePtr(int(NORM_L2SQR)); } else if( !descriptorMatcherType.compare( "BruteForce-L1" ) ) { - dm = new BFMatcher(NORM_L1); + dm = makePtr(int(NORM_L1)); } else if( !descriptorMatcherType.compare("BruteForce-Hamming") || !descriptorMatcherType.compare("BruteForce-HammingLUT") ) { - dm = new BFMatcher(NORM_HAMMING); + dm = makePtr(int(NORM_HAMMING)); } else if( !descriptorMatcherType.compare("BruteForce-Hamming(2)") ) { - dm = new BFMatcher(NORM_HAMMING2); + dm = makePtr(int(NORM_HAMMING2)); } else - CV_Error( CV_StsBadArg, "Unknown matcher name" ); + CV_Error( Error::StsBadArg, "Unknown matcher name" ); return dm; } @@ -497,8 +497,8 @@ Ptr DescriptorMatcher::create( const std::string& descriptorM FlannBasedMatcher::FlannBasedMatcher( const Ptr& _indexParams, const Ptr& _searchParams ) : indexParams(_indexParams), searchParams(_searchParams), addedDescCount(0) { - CV_Assert( !_indexParams.empty() ); - CV_Assert( !_searchParams.empty() ); + CV_Assert( _indexParams ); + CV_Assert( _searchParams ); } void FlannBasedMatcher::add( const std::vector& descriptors ) @@ -522,17 +522,17 @@ void FlannBasedMatcher::clear() void FlannBasedMatcher::train() { - if( flannIndex.empty() || mergedDescriptors.size() < addedDescCount ) + if( !flannIndex || mergedDescriptors.size() < addedDescCount ) { mergedDescriptors.set( trainDescCollection ); - flannIndex = new flann::Index( mergedDescriptors.getDescriptors(), *indexParams ); + flannIndex = makePtr( mergedDescriptors.getDescriptors(), *indexParams ); } } void FlannBasedMatcher::read( const FileNode& fn) { - if (indexParams.empty()) - indexParams = new flann::IndexParams(); + if (!indexParams) + indexParams = makePtr(); FileNode ip = fn["indexParams"]; CV_Assert(ip.type() == FileNode::SEQ); @@ -540,7 +540,7 @@ void FlannBasedMatcher::read( const FileNode& fn) for(int i = 0; i < (int)ip.size(); ++i) { CV_Assert(ip[i].type() == FileNode::MAP); - std::string _name = (std::string)ip[i]["name"]; + String _name = (String)ip[i]["name"]; int type = (int)ip[i]["type"]; switch(type) @@ -559,7 +559,7 @@ void FlannBasedMatcher::read( const FileNode& fn) indexParams->setDouble(_name, (double) ip[i]["value"]); break; case CV_USRTYPE1: - indexParams->setString(_name, (std::string) ip[i]["value"]); + indexParams->setString(_name, (String) ip[i]["value"]); break; case CV_MAKETYPE(CV_USRTYPE1,2): indexParams->setBool(_name, (int) ip[i]["value"] != 0); @@ -570,8 +570,8 @@ void FlannBasedMatcher::read( const FileNode& fn) }; } - if (searchParams.empty()) - searchParams = new flann::SearchParams(); + if (!searchParams) + searchParams = makePtr(); FileNode sp = fn["searchParams"]; CV_Assert(sp.type() == FileNode::SEQ); @@ -579,7 +579,7 @@ void FlannBasedMatcher::read( const FileNode& fn) for(int i = 0; i < (int)sp.size(); ++i) { CV_Assert(sp[i].type() == FileNode::MAP); - std::string _name = (std::string)sp[i]["name"]; + String _name = (String)sp[i]["name"]; int type = (int)sp[i]["type"]; switch(type) @@ -598,7 +598,7 @@ void FlannBasedMatcher::read( const FileNode& fn) searchParams->setDouble(_name, (double) ip[i]["value"]); break; case CV_USRTYPE1: - searchParams->setString(_name, (std::string) ip[i]["value"]); + searchParams->setString(_name, (String) ip[i]["value"]); break; case CV_MAKETYPE(CV_USRTYPE1,2): searchParams->setBool(_name, (int) ip[i]["value"] != 0); @@ -618,9 +618,9 @@ void FlannBasedMatcher::write( FileStorage& fs) const if (indexParams) { - std::vector names; + std::vector names; std::vector types; - std::vector strValues; + std::vector strValues; std::vector numValues; indexParams->getAll(names, types, strValues, numValues); @@ -669,9 +669,9 @@ void FlannBasedMatcher::write( FileStorage& fs) const if (searchParams) { - std::vector names; + std::vector names; std::vector types; - std::vector strValues; + std::vector strValues; std::vector numValues; searchParams->getAll(names, types, strValues, numValues); @@ -725,10 +725,10 @@ bool FlannBasedMatcher::isMaskSupported() const Ptr FlannBasedMatcher::clone( bool emptyTrainData ) const { - FlannBasedMatcher* matcher = new FlannBasedMatcher(indexParams, searchParams); + Ptr matcher = makePtr(indexParams, searchParams); if( !emptyTrainData ) { - CV_Error( CV_StsNotImplemented, "deep clone functionality is not implemented, because " + CV_Error( Error::StsNotImplemented, "deep clone functionality is not implemented, because " "Flann::Index has not copy constructor or clone method "); //matcher->flannIndex; matcher->addedDescCount = addedDescCount; @@ -1060,13 +1060,13 @@ bool GenericDescriptorMatcher::empty() const /* * Factory function for GenericDescriptorMatch creating */ -Ptr GenericDescriptorMatcher::create( const std::string& genericDescritptorMatcherType, - const std::string ¶msFilename ) +Ptr GenericDescriptorMatcher::create( const String& genericDescritptorMatcherType, + const String ¶msFilename ) { Ptr descriptorMatcher = Algorithm::create("DescriptorMatcher." + genericDescritptorMatcherType); - if( !paramsFilename.empty() && !descriptorMatcher.empty() ) + if( !paramsFilename.empty() && descriptorMatcher ) { FileStorage fs = FileStorage( paramsFilename, FileStorage::READ ); if( fs.isOpened() ) @@ -1086,7 +1086,7 @@ VectorDescriptorMatcher::VectorDescriptorMatcher( const Ptr const Ptr& _matcher ) : extractor( _extractor ), matcher( _matcher ) { - CV_Assert( !extractor.empty() && !matcher.empty() ); + CV_Assert( extractor && matcher ); } VectorDescriptorMatcher::~VectorDescriptorMatcher() @@ -1152,14 +1152,14 @@ void VectorDescriptorMatcher::write (FileStorage& fs) const bool VectorDescriptorMatcher::empty() const { - return extractor.empty() || extractor->empty() || - matcher.empty() || matcher->empty(); + return !extractor || extractor->empty() || + !matcher || matcher->empty(); } Ptr VectorDescriptorMatcher::clone( bool emptyTrainData ) const { // TODO clone extractor - return new VectorDescriptorMatcher( extractor, matcher->clone(emptyTrainData) ); + return makePtr( extractor, matcher->clone(emptyTrainData) ); } } diff --git a/modules/features2d/src/mser.cpp b/modules/features2d/src/mser.cpp index 6581612dfc..a68a5a5b7a 100644 --- a/modules/features2d/src/mser.cpp +++ b/modules/features2d/src/mser.cpp @@ -40,6 +40,8 @@ */ #include "precomp.hpp" +#include "opencv2/imgproc/imgproc_c.h" +#include namespace cv { @@ -1054,10 +1056,11 @@ static int preprocessMSER_8UC3( MSCRNode* node, return Ne; } -#define cmp_mscr_edge(edge1, edge2) \ - ((edge1).chi < (edge2).chi) - -static CV_IMPLEMENT_QSORT( QuickSortMSCREdge, MSCREdge, cmp_mscr_edge ) +class LessThanEdge +{ +public: + bool operator()(const MSCREdge& a, const MSCREdge& b) const { return a.chi < b.chi; } +}; // to find the root of one region static MSCRNode* findMSCR( MSCRNode* x ) @@ -1112,7 +1115,7 @@ extractMSER_8UC3( CvMat* src, CvMat* dy = cvCreateMat( src->rows-1, src->cols, CV_64FC1 ); Ne = preprocessMSER_8UC3( map, edge, &emean, src, mask, dx, dy, Ne, params.edgeBlurSize ); emean = emean / (double)Ne; - QuickSortMSCREdge( edge, Ne, 0 ); + std::sort(edge, edge + Ne, LessThanEdge()); MSCREdge* edge_ub = edge+Ne; MSCREdge* edgeptr = edge; TempMSCR* mscrptr = mscr; diff --git a/modules/features2d/src/orb.cpp b/modules/features2d/src/orb.cpp index 33c23d1610..7ed3ff03c3 100644 --- a/modules/features2d/src/orb.cpp +++ b/modules/features2d/src/orb.cpp @@ -240,7 +240,7 @@ static void computeOrbDescriptor(const KeyPoint& kpt, } } else - CV_Error( CV_StsBadSize, "Wrong WTA_K. It can be only 2, 3 or 4." ); + CV_Error( Error::StsBadSize, "Wrong WTA_K. It can be only 2, 3 or 4." ); #undef GET_VALUE } @@ -738,7 +738,7 @@ void ORB::operator()( InputArray _image, InputArray _mask, std::vector Mat image = _image.getMat(), mask = _mask.getMat(); if( image.type() != CV_8UC1 ) - cvtColor(_image, image, CV_BGR2GRAY); + cvtColor(_image, image, COLOR_BGR2GRAY); int levelsNum = this->nlevels; diff --git a/modules/features2d/src/precomp.cpp b/modules/features2d/src/precomp.cpp deleted file mode 100644 index 3e0ec42de9..0000000000 --- a/modules/features2d/src/precomp.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/*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. -// -// -// Intel License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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 "precomp.hpp" - -/* End of file. */ diff --git a/modules/features2d/src/precomp.hpp b/modules/features2d/src/precomp.hpp index 62936b48f3..3c9073ec52 100644 --- a/modules/features2d/src/precomp.hpp +++ b/modules/features2d/src/precomp.hpp @@ -43,14 +43,11 @@ #ifndef __OPENCV_PRECOMP_H__ #define __OPENCV_PRECOMP_H__ -#ifdef HAVE_CVCONFIG_H -#include "cvconfig.h" -#endif - #include "opencv2/features2d.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/imgproc/imgproc_c.h" -#include "opencv2/core/internal.hpp" + +#include "opencv2/core/utility.hpp" +#include "opencv2/core/private.hpp" #include diff --git a/modules/features2d/src/stardetector.cpp b/modules/features2d/src/stardetector.cpp index 3dbea0ac13..02b999b620 100644 --- a/modules/features2d/src/stardetector.cpp +++ b/modules/features2d/src/stardetector.cpp @@ -114,7 +114,7 @@ StarDetectorComputeResponses( const Mat& img, Mat& responses, Mat& sizes, int ma #if CV_SSE2 __m128 invSizes4[MAX_PATTERN][2]; __m128 sizes1_4[MAX_PATTERN]; - Cv32suf absmask; + union { int i; float f; } absmask; absmask.i = 0x7fffffff; volatile bool useSIMD = cv::checkHardwareSupport(CV_CPU_SSE2); #endif @@ -429,7 +429,7 @@ StarDetector::StarDetector(int _maxSize, int _responseThreshold, void StarDetector::detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask ) const { Mat grayImage = image; - if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY ); + if( image.type() != CV_8U ) cvtColor( image, grayImage, COLOR_BGR2GRAY ); (*this)(grayImage, keypoints); KeyPointsFilter::runByPixelsMask( keypoints, mask ); diff --git a/modules/features2d/test/test_brisk.cpp b/modules/features2d/test/test_brisk.cpp index c76afff570..38e07c3f6f 100644 --- a/modules/features2d/test/test_brisk.cpp +++ b/modules/features2d/test/test_brisk.cpp @@ -69,8 +69,8 @@ void CV_BRISKTest::run( int ) } Mat gray1, gray2; - cvtColor(image1, gray1, CV_BGR2GRAY); - cvtColor(image2, gray2, CV_BGR2GRAY); + cvtColor(image1, gray1, COLOR_BGR2GRAY); + cvtColor(image2, gray2, COLOR_BGR2GRAY); Ptr detector = Algorithm::create("Feature2D.BRISK"); @@ -93,4 +93,3 @@ void CV_BRISKTest::run( int ) } TEST(Features2d_BRISK, regression) { CV_BRISKTest test; test.safe_run(); } - diff --git a/modules/features2d/test/test_descriptors_regression.cpp b/modules/features2d/test/test_descriptors_regression.cpp index 193545162b..08eb59eae2 100644 --- a/modules/features2d/test/test_descriptors_regression.cpp +++ b/modules/features2d/test/test_descriptors_regression.cpp @@ -80,12 +80,16 @@ static Mat readMatFromBin( const string& filename ) size_t elements_read4 = fread( (void*)&dataSize, sizeof(int), 1, f ); CV_Assert(elements_read1 == 1 && elements_read2 == 1 && elements_read3 == 1 && elements_read4 == 1); - uchar* data = (uchar*)cvAlloc(dataSize); - size_t elements_read = fread( (void*)data, 1, dataSize, f ); + size_t step = dataSize / rows / CV_ELEM_SIZE(type); + CV_Assert(step >= (size_t)cols); + + Mat m = Mat( rows, step, type).colRange(0, cols); + + size_t elements_read = fread( m.ptr(), 1, dataSize, f ); CV_Assert(elements_read == (size_t)(dataSize)); fclose(f); - return Mat( rows, cols, type, data ); + return m; } return Mat(); } @@ -137,7 +141,7 @@ protected: void emptyDataTest() { - assert( !dextractor.empty() ); + assert( dextractor ); // One image. Mat image; @@ -182,7 +186,7 @@ protected: void regressionTest() { - assert( !dextractor.empty() ); + assert( dextractor ); // Read the test image. string imgFilename = string(ts->get_data_path()) + FEATURES2D_DIR + "/" + IMAGE_FILENAME; @@ -205,7 +209,7 @@ protected: double t = (double)getTickCount(); dextractor->compute( img, keypoints, calcDescriptors ); t = getTickCount() - t; - ts->printf(cvtest::TS::LOG, "\nAverage time of computing one descriptor = %g ms.\n", t/((double)cvGetTickFrequency()*1000.)/calcDescriptors.rows); + ts->printf(cvtest::TS::LOG, "\nAverage time of computing one descriptor = %g ms.\n", t/((double)getTickFrequency()*1000.)/calcDescriptors.rows); if( calcDescriptors.rows != (int)keypoints.size() ) { @@ -263,7 +267,7 @@ protected: void run(int) { createDescriptorExtractor(); - if( dextractor.empty() ) + if( !dextractor ) { ts->printf(cvtest::TS::LOG, "Descriptor extractor is empty.\n"); ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA ); diff --git a/modules/features2d/test/test_detectors_regression.cpp b/modules/features2d/test/test_detectors_regression.cpp index 9a88c42f7b..8f34913a9a 100644 --- a/modules/features2d/test/test_detectors_regression.cpp +++ b/modules/features2d/test/test_detectors_regression.cpp @@ -230,7 +230,7 @@ void CV_FeatureDetectorTest::regressionTest() void CV_FeatureDetectorTest::run( int /*start_from*/ ) { - if( fdetector.empty() ) + if( !fdetector ) { ts->printf( cvtest::TS::LOG, "Feature detector is empty.\n" ); ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA ); diff --git a/modules/features2d/test/test_fast.cpp b/modules/features2d/test/test_fast.cpp index cee9152bff..d500ce549c 100644 --- a/modules/features2d/test/test_fast.cpp +++ b/modules/features2d/test/test_fast.cpp @@ -71,8 +71,8 @@ void CV_FastTest::run( int ) } Mat gray1, gray2; - cvtColor(image1, gray1, CV_BGR2GRAY); - cvtColor(image2, gray2, CV_BGR2GRAY); + cvtColor(image1, gray1, COLOR_BGR2GRAY); + cvtColor(image2, gray2, COLOR_BGR2GRAY); vector keypoints1; vector keypoints2; @@ -82,13 +82,13 @@ void CV_FastTest::run( int ) for(size_t i = 0; i < keypoints1.size(); ++i) { const KeyPoint& kp = keypoints1[i]; - cv::circle(image1, kp.pt, cvRound(kp.size/2), CV_RGB(255, 0, 0)); + cv::circle(image1, kp.pt, cvRound(kp.size/2), Scalar(255, 0, 0)); } for(size_t i = 0; i < keypoints2.size(); ++i) { const KeyPoint& kp = keypoints2[i]; - cv::circle(image2, kp.pt, cvRound(kp.size/2), CV_RGB(255, 0, 0)); + cv::circle(image2, kp.pt, cvRound(kp.size/2), Scalar(255, 0, 0)); } Mat kps1(1, (int)(keypoints1.size() * sizeof(KeyPoint)), CV_8U, &keypoints1[0]); @@ -135,4 +135,3 @@ void CV_FastTest::run( int ) } TEST(Features2d_FAST, regression) { CV_FastTest test; test.safe_run(); } - diff --git a/modules/features2d/test/test_keypoints.cpp b/modules/features2d/test/test_keypoints.cpp index 7bc5c6e9a2..e15d4fa17f 100644 --- a/modules/features2d/test/test_keypoints.cpp +++ b/modules/features2d/test/test_keypoints.cpp @@ -62,7 +62,7 @@ protected: virtual void run(int) { cv::initModule_features2d(); - CV_Assert(!detector.empty()); + CV_Assert(detector); string imgFilename = string(ts->get_data_path()) + FEATURES2D_DIR + "/" + IMAGE_FILENAME; // Read the test image. @@ -166,5 +166,3 @@ TEST(Features2d_Detector_Keypoints_Dense, validation) CV_FeatureDetectorKeypointsTest test(Algorithm::create("Feature2D.Dense")); test.safe_run(); } - - diff --git a/modules/features2d/test/test_mser.cpp b/modules/features2d/test/test_mser.cpp index b30400a502..6b1b4ef639 100644 --- a/modules/features2d/test/test_mser.cpp +++ b/modules/features2d/test/test_mser.cpp @@ -41,6 +41,7 @@ //M*/ #include "test_precomp.hpp" +#include "opencv2/imgproc/imgproc_c.h" #include #include @@ -204,4 +205,3 @@ void CV_MserTest::run(int) } TEST(Features2d_MSER, DISABLED_regression) { CV_MserTest test; test.safe_run(); } - diff --git a/modules/features2d/test/test_precomp.hpp b/modules/features2d/test/test_precomp.hpp index 979e7c78cb..49bc1dfd18 100644 --- a/modules/features2d/test/test_precomp.hpp +++ b/modules/features2d/test/test_precomp.hpp @@ -11,7 +11,6 @@ #include "opencv2/ts.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/imgproc/imgproc_c.h" #include "opencv2/features2d.hpp" #include "opencv2/highgui.hpp" #include diff --git a/modules/features2d/test/test_rotation_and_scale_invariance.cpp b/modules/features2d/test/test_rotation_and_scale_invariance.cpp index 1f67da17be..adfe42804b 100644 --- a/modules/features2d/test/test_rotation_and_scale_invariance.cpp +++ b/modules/features2d/test/test_rotation_and_scale_invariance.cpp @@ -196,7 +196,7 @@ public: minKeyPointMatchesRatio(_minKeyPointMatchesRatio), minAngleInliersRatio(_minAngleInliersRatio) { - CV_Assert(!featureDetector.empty()); + CV_Assert(featureDetector); } protected: @@ -217,7 +217,7 @@ protected: vector keypoints0; featureDetector->detect(image0, keypoints0); if(keypoints0.size() < 15) - CV_Error(CV_StsAssert, "Detector gives too few points in a test image\n"); + CV_Error(Error::StsAssert, "Detector gives too few points in a test image\n"); const int maxAngle = 360, angleStep = 15; for(int angle = 0; angle < maxAngle; angle += angleStep) @@ -246,7 +246,7 @@ protected: float angle0 = keypoints0[matches[m].queryIdx].angle; float angle1 = keypoints1[matches[m].trainIdx].angle; if(angle0 == -1 || angle1 == -1) - CV_Error(CV_StsBadArg, "Given FeatureDetector is not rotation invariant, it can not be tested here.\n"); + CV_Error(Error::StsBadArg, "Given FeatureDetector is not rotation invariant, it can not be tested here.\n"); CV_Assert(angle0 >= 0.f && angle0 < 360.f); CV_Assert(angle1 >= 0.f && angle1 < 360.f); @@ -307,8 +307,8 @@ public: normType(_normType), minDescInliersRatio(_minDescInliersRatio) { - CV_Assert(!featureDetector.empty()); - CV_Assert(!descriptorExtractor.empty()); + CV_Assert(featureDetector); + CV_Assert(descriptorExtractor); } protected: @@ -330,7 +330,7 @@ protected: Mat descriptors0; featureDetector->detect(image0, keypoints0); if(keypoints0.size() < 15) - CV_Error(CV_StsAssert, "Detector gives too few points in a test image\n"); + CV_Error(Error::StsAssert, "Detector gives too few points in a test image\n"); descriptorExtractor->compute(image0, keypoints0, descriptors0); BFMatcher bfmatcher(normType); @@ -392,7 +392,7 @@ public: minKeyPointMatchesRatio(_minKeyPointMatchesRatio), minScaleInliersRatio(_minScaleInliersRatio) { - CV_Assert(!featureDetector.empty()); + CV_Assert(featureDetector); } protected: @@ -413,7 +413,7 @@ protected: vector keypoints0; featureDetector->detect(image0, keypoints0); if(keypoints0.size() < 15) - CV_Error(CV_StsAssert, "Detector gives too few points in a test image\n"); + CV_Error(Error::StsAssert, "Detector gives too few points in a test image\n"); for(int scaleIdx = 1; scaleIdx <= 3; scaleIdx++) { @@ -424,7 +424,7 @@ protected: vector keypoints1, osiKeypoints1; // osi - original size image featureDetector->detect(image1, keypoints1); if(keypoints1.size() < 15) - CV_Error(CV_StsAssert, "Detector gives too few points in a test image\n"); + CV_Error(Error::StsAssert, "Detector gives too few points in a test image\n"); if(keypoints1.size() > keypoints0.size()) { @@ -510,8 +510,8 @@ public: normType(_normType), minDescInliersRatio(_minDescInliersRatio) { - CV_Assert(!featureDetector.empty()); - CV_Assert(!descriptorExtractor.empty()); + CV_Assert(featureDetector); + CV_Assert(descriptorExtractor); } protected: @@ -532,7 +532,7 @@ protected: vector keypoints0; featureDetector->detect(image0, keypoints0); if(keypoints0.size() < 15) - CV_Error(CV_StsAssert, "Detector gives too few points in a test image\n"); + CV_Error(Error::StsAssert, "Detector gives too few points in a test image\n"); Mat descriptors0; descriptorExtractor->compute(image0, keypoints0, descriptors0); diff --git a/modules/flann/CMakeLists.txt b/modules/flann/CMakeLists.txt index 645e8ce857..a6326c40a0 100644 --- a/modules/flann/CMakeLists.txt +++ b/modules/flann/CMakeLists.txt @@ -1,3 +1,2 @@ set(the_description "Clustering and Search in Multi-Dimensional Spaces") ocv_define_module(flann opencv_core) - diff --git a/modules/flann/doc/flann_fast_approximate_nearest_neighbor_search.rst b/modules/flann/doc/flann_fast_approximate_nearest_neighbor_search.rst index 07b0b2a467..e058e8886e 100644 --- a/modules/flann/doc/flann_fast_approximate_nearest_neighbor_search.rst +++ b/modules/flann/doc/flann_fast_approximate_nearest_neighbor_search.rst @@ -138,7 +138,7 @@ The method constructs a fast search structure from a set of features using the s struct SavedIndexParams : public IndexParams { - SavedIndexParams( std::string filename ); + SavedIndexParams( String filename ); }; @@ -199,7 +199,7 @@ flann::Index_::save ------------------------------ Saves the index to a file. -.. ocv:function:: void flann::Index_::save(std::string filename) +.. ocv:function:: void flann::Index_::save(String filename) :param filename: The file to save the index to diff --git a/modules/flann/include/opencv2/flann.hpp b/modules/flann/include/opencv2/flann.hpp index d5eedcc0f0..36ca8c7c3a 100644 --- a/modules/flann/include/opencv2/flann.hpp +++ b/modules/flann/include/opencv2/flann.hpp @@ -43,12 +43,9 @@ #ifndef _OPENCV_FLANN_HPP_ #define _OPENCV_FLANN_HPP_ -#ifdef __cplusplus - -#include "opencv2/core/types_c.h" #include "opencv2/core.hpp" -#include "opencv2/flann/flann_base.hpp" #include "opencv2/flann/miniflann.hpp" +#include "opencv2/flann/flann_base.hpp" namespace cvflann { @@ -112,7 +109,7 @@ public: int radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& params); - void save(std::string filename) { nnIndex->save(filename); } + void save(String filename) { nnIndex->save(filename); } int veclen() const { return nnIndex->veclen(); } @@ -244,7 +241,7 @@ public: int radiusSearch(const std::vector& query, std::vector& indices, std::vector& dists, DistanceType radius, const ::cvflann::SearchParams& params); int radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& params); - void save(std::string filename) + void save(String filename) { if (nnIndex_L1) nnIndex_L1->save(filename); if (nnIndex_L2) nnIndex_L2->save(filename); @@ -422,6 +419,4 @@ FLANN_DEPRECATED int hierarchicalClustering(const Mat& features, Mat& centers, c } } // namespace cv::flann -#endif // __cplusplus - #endif diff --git a/modules/flann/include/opencv2/flann/any.h b/modules/flann/include/opencv2/flann/any.h index dc0b9481a2..070d5a421f 100644 --- a/modules/flann/include/opencv2/flann/any.h +++ b/modules/flann/include/opencv2/flann/any.h @@ -106,6 +106,11 @@ template<> inline void big_any_policy::print(std::ostream& ou out << int(*reinterpret_cast(*src)); } +template<> inline void big_any_policy::print(std::ostream& out, void* const* src) +{ + out << (*reinterpret_cast(*src)).c_str(); +} + template struct choose_policy { @@ -252,8 +257,7 @@ public: const T& cast() const { if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast(); - void* obj = const_cast(object); - T* r = reinterpret_cast(policy->get_value(&obj)); + T* r = reinterpret_cast(policy->get_value(const_cast(&object))); return *r; } diff --git a/modules/flann/include/opencv2/flann/dist.h b/modules/flann/include/opencv2/flann/dist.h index bfd37a9e23..dd4cc421d1 100644 --- a/modules/flann/include/opencv2/flann/dist.h +++ b/modules/flann/include/opencv2/flann/dist.h @@ -43,8 +43,12 @@ typedef unsigned __int64 uint64_t; #include "defines.h" +#if (defined WIN32 || defined _WIN32) && defined(_M_ARM) +# include +#endif + #ifdef __ARM_NEON__ -#include "arm_neon.h" +# include "arm_neon.h" #endif namespace cvflann @@ -421,7 +425,6 @@ struct Hamming ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const { ResultType result = 0; -#ifdef __GNUC__ #ifdef __ARM_NEON__ { uint32x4_t bits = vmovq_n_u32(0); @@ -438,7 +441,7 @@ struct Hamming result = vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),0); result += vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),2); } -#else +#elif __GNUC__ { //for portability just use unsigned long -- and use the __builtin_popcountll (see docs for __builtin_popcountll) typedef unsigned long long pop_t; @@ -458,8 +461,8 @@ struct Hamming result += __builtin_popcountll(a_final ^ b_final); } } -#endif //NEON -#else +#else // NO NEON and NOT GNUC + typedef unsigned long long pop_t; HammingLUT lut; result = lut(reinterpret_cast (a), reinterpret_cast (b), size * sizeof(pop_t)); diff --git a/modules/flann/include/opencv2/flann/flann.hpp b/modules/flann/include/opencv2/flann/flann.hpp index f40aaf79f3..227683f979 100644 --- a/modules/flann/include/opencv2/flann/flann.hpp +++ b/modules/flann/include/opencv2/flann/flann.hpp @@ -45,4 +45,4 @@ #error this is a compatibility header which should not be used inside the OpenCV library #endif -#include "opencv2/flann.hpp" \ No newline at end of file +#include "opencv2/flann.hpp" diff --git a/modules/flann/include/opencv2/flann/flann_base.hpp b/modules/flann/include/opencv2/flann/flann_base.hpp index b5ba7d79e2..98c33cf6c0 100644 --- a/modules/flann/include/opencv2/flann/flann_base.hpp +++ b/modules/flann/include/opencv2/flann/flann_base.hpp @@ -32,7 +32,6 @@ #define OPENCV_FLANN_BASE_HPP_ #include -#include #include #include @@ -62,7 +61,7 @@ inline void log_verbosity(int level) */ struct SavedIndexParams : public IndexParams { - SavedIndexParams(std::string filename) + SavedIndexParams(cv::String filename) { (* this)["algorithm"] = FLANN_INDEX_SAVED; (*this)["filename"] = filename; @@ -71,7 +70,7 @@ struct SavedIndexParams : public IndexParams template -NNIndex* load_saved_index(const Matrix& dataset, const std::string& filename, Distance distance) +NNIndex* load_saved_index(const Matrix& dataset, const cv::String& filename, Distance distance) { typedef typename Distance::ElementType ElementType; @@ -111,7 +110,7 @@ public: loaded_ = false; if (index_type == FLANN_INDEX_SAVED) { - nnIndex_ = load_saved_index(features, get_param(params,"filename"), distance); + nnIndex_ = load_saved_index(features, get_param(params,"filename"), distance); loaded_ = true; } else { @@ -134,7 +133,7 @@ public: } } - void save(std::string filename) + void save(cv::String filename) { FILE* fout = fopen(filename.c_str(), "wb"); if (fout == NULL) { diff --git a/modules/flann/include/opencv2/flann/general.h b/modules/flann/include/opencv2/flann/general.h index 87e7e2f288..9d5402a6f2 100644 --- a/modules/flann/include/opencv2/flann/general.h +++ b/modules/flann/include/opencv2/flann/general.h @@ -31,19 +31,17 @@ #ifndef OPENCV_FLANN_GENERAL_H_ #define OPENCV_FLANN_GENERAL_H_ -#include "defines.h" -#include -#include +#include "opencv2/core.hpp" namespace cvflann { -class FLANNException : public std::runtime_error +class FLANNException : public cv::Exception { public: - FLANNException(const char* message) : std::runtime_error(message) { } + FLANNException(const char* message) : cv::Exception(0, message, "", __FILE__, __LINE__) { } - FLANNException(const std::string& message) : std::runtime_error(message) { } + FLANNException(const cv::String& message) : cv::Exception(0, message, "", __FILE__, __LINE__) { } }; } diff --git a/modules/flann/include/opencv2/flann/ground_truth.h b/modules/flann/include/opencv2/flann/ground_truth.h index 69d978ba07..fd8f3ae7f0 100644 --- a/modules/flann/include/opencv2/flann/ground_truth.h +++ b/modules/flann/include/opencv2/flann/ground_truth.h @@ -42,7 +42,6 @@ template void find_nearest(const Matrix& dataset, typename Distance::ElementType* query, int* matches, int nn, int skip = 0, Distance distance = Distance()) { - typedef typename Distance::ElementType ElementType; typedef typename Distance::ResultType DistanceType; int n = nn + skip; diff --git a/modules/flann/include/opencv2/flann/hdf5.h b/modules/flann/include/opencv2/flann/hdf5.h index ef3e999738..80d23b9770 100644 --- a/modules/flann/include/opencv2/flann/hdf5.h +++ b/modules/flann/include/opencv2/flann/hdf5.h @@ -73,7 +73,7 @@ hid_t get_hdf5_type() { return H5T_NATIVE_DOUBLE; } #define CHECK_ERROR(x,y) if ((x)<0) throw FLANNException((y)); template -void save_to_file(const cvflann::Matrix& dataset, const std::string& filename, const std::string& name) +void save_to_file(const cvflann::Matrix& dataset, const String& filename, const String& name) { #if H5Eset_auto_vers == 2 @@ -125,7 +125,7 @@ void save_to_file(const cvflann::Matrix& dataset, const std::string& filename template -void load_from_file(cvflann::Matrix& dataset, const std::string& filename, const std::string& name) +void load_from_file(cvflann::Matrix& dataset, const String& filename, const String& name) { herr_t status; hid_t file_id = H5Fopen(filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT); @@ -166,7 +166,7 @@ namespace mpi * @param name Name of dataset inside file */ template -void load_from_file(cvflann::Matrix& dataset, const std::string& filename, const std::string& name) +void load_from_file(cvflann::Matrix& dataset, const String& filename, const String& name) { MPI_Comm comm = MPI_COMM_WORLD; MPI_Info info = MPI_INFO_NULL; diff --git a/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h b/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h index ce2d622450..b8b16941f2 100644 --- a/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h +++ b/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h @@ -32,7 +32,6 @@ #define OPENCV_FLANN_HIERARCHICAL_CLUSTERING_INDEX_H_ #include -#include #include #include #include diff --git a/modules/flann/include/opencv2/flann/kmeans_index.h b/modules/flann/include/opencv2/flann/kmeans_index.h index 3fea956a74..c3b1fd5b8f 100644 --- a/modules/flann/include/opencv2/flann/kmeans_index.h +++ b/modules/flann/include/opencv2/flann/kmeans_index.h @@ -32,7 +32,6 @@ #define OPENCV_FLANN_KMEANS_INDEX_H_ #include -#include #include #include #include diff --git a/modules/flann/include/opencv2/flann/lsh_table.h b/modules/flann/include/opencv2/flann/lsh_table.h index a30642a480..9b3ac09911 100644 --- a/modules/flann/include/opencv2/flann/lsh_table.h +++ b/modules/flann/include/opencv2/flann/lsh_table.h @@ -266,9 +266,7 @@ private: const size_t key_size_upper_bound = std::min(sizeof(BucketKey) * CHAR_BIT + 1, sizeof(size_t) * CHAR_BIT); if (key_size < key_size_lower_bound || key_size >= key_size_upper_bound) { - std::stringstream errorMessage; - errorMessage << "Invalid key_size (=" << key_size << "). Valid values for your system are " << key_size_lower_bound << " <= key_size < " << key_size_upper_bound << "."; - CV_Error(CV_StsBadArg, errorMessage.str()); + CV_Error(cv::Error::StsBadArg, cv::format("Invalid key_size (=%d). Valid values for your system are %d <= key_size < %d.", (int)key_size, (int)key_size_lower_bound, (int)key_size_upper_bound)); } speed_level_ = kHash; diff --git a/modules/flann/include/opencv2/flann/miniflann.hpp b/modules/flann/include/opencv2/flann/miniflann.hpp index 475335ca39..f2acc23bff 100644 --- a/modules/flann/include/opencv2/flann/miniflann.hpp +++ b/modules/flann/include/opencv2/flann/miniflann.hpp @@ -43,8 +43,6 @@ #ifndef _OPENCV_MINIFLANN_HPP_ #define _OPENCV_MINIFLANN_HPP_ -#ifdef __cplusplus - #include "opencv2/core.hpp" #include "opencv2/flann/defines.h" @@ -59,20 +57,20 @@ struct CV_EXPORTS IndexParams IndexParams(); ~IndexParams(); - std::string getString(const std::string& key, const std::string& defaultVal=std::string()) const; - int getInt(const std::string& key, int defaultVal=-1) const; - double getDouble(const std::string& key, double defaultVal=-1) const; + String getString(const String& key, const String& defaultVal=String()) const; + int getInt(const String& key, int defaultVal=-1) const; + double getDouble(const String& key, double defaultVal=-1) const; - void setString(const std::string& key, const std::string& value); - void setInt(const std::string& key, int value); - void setDouble(const std::string& key, double value); - void setFloat(const std::string& key, float value); - void setBool(const std::string& key, bool value); + void setString(const String& key, const String& value); + void setInt(const String& key, int value); + void setDouble(const String& key, double value); + void setFloat(const String& key, float value); + void setBool(const String& key, bool value); void setAlgorithm(int value); - void getAll(std::vector& names, + void getAll(std::vector& names, std::vector& types, - std::vector& strValues, + std::vector& strValues, std::vector& numValues) const; void* params; @@ -119,7 +117,7 @@ struct CV_EXPORTS LshIndexParams : public IndexParams struct CV_EXPORTS SavedIndexParams : public IndexParams { - SavedIndexParams(const std::string& filename); + SavedIndexParams(const String& filename); }; struct CV_EXPORTS SearchParams : public IndexParams @@ -142,8 +140,8 @@ public: OutputArray dists, double radius, int maxResults, const SearchParams& params=SearchParams()); - CV_WRAP virtual void save(const std::string& filename) const; - CV_WRAP virtual bool load(InputArray features, const std::string& filename); + CV_WRAP virtual void save(const String& filename) const; + CV_WRAP virtual bool load(InputArray features, const String& filename); CV_WRAP virtual void release(); CV_WRAP cvflann::flann_distance_t getDistance() const; CV_WRAP cvflann::flann_algorithm_t getAlgorithm() const; @@ -157,6 +155,4 @@ protected: } } // namespace cv::flann -#endif // __cplusplus - #endif diff --git a/modules/flann/include/opencv2/flann/nn_index.h b/modules/flann/include/opencv2/flann/nn_index.h index d14e83a92c..381d4bc3cb 100644 --- a/modules/flann/include/opencv2/flann/nn_index.h +++ b/modules/flann/include/opencv2/flann/nn_index.h @@ -31,8 +31,6 @@ #ifndef OPENCV_FLANN_NNINDEX_H #define OPENCV_FLANN_NNINDEX_H -#include - #include "general.h" #include "matrix.h" #include "result_set.h" diff --git a/modules/flann/include/opencv2/flann/params.h b/modules/flann/include/opencv2/flann/params.h index fc2a906198..2f1d5e7caf 100644 --- a/modules/flann/include/opencv2/flann/params.h +++ b/modules/flann/include/opencv2/flann/params.h @@ -39,7 +39,7 @@ namespace cvflann { -typedef std::map IndexParams; +typedef std::map IndexParams; struct SearchParams : public IndexParams { @@ -56,7 +56,7 @@ struct SearchParams : public IndexParams template -T get_param(const IndexParams& params, std::string name, const T& default_value) +T get_param(const IndexParams& params, cv::String name, const T& default_value) { IndexParams::const_iterator it = params.find(name); if (it != params.end()) { @@ -68,14 +68,14 @@ T get_param(const IndexParams& params, std::string name, const T& default_value) } template -T get_param(const IndexParams& params, std::string name) +T get_param(const IndexParams& params, cv::String name) { IndexParams::const_iterator it = params.find(name); if (it != params.end()) { return it->second.cast(); } else { - throw FLANNException(std::string("Missing parameter '")+name+std::string("' in the parameters given")); + throw FLANNException(cv::String("Missing parameter '")+name+cv::String("' in the parameters given")); } } diff --git a/modules/flann/include/opencv2/flann/random.h b/modules/flann/include/opencv2/flann/random.h index 2a67352da3..a3cf5ec53d 100644 --- a/modules/flann/include/opencv2/flann/random.h +++ b/modules/flann/include/opencv2/flann/random.h @@ -131,5 +131,3 @@ public: } #endif //OPENCV_FLANN_RANDOM_H - - diff --git a/modules/flann/include/opencv2/flann/result_set.h b/modules/flann/include/opencv2/flann/result_set.h index 7bb709b76e..3adad46596 100644 --- a/modules/flann/include/opencv2/flann/result_set.h +++ b/modules/flann/include/opencv2/flann/result_set.h @@ -540,4 +540,3 @@ private: } #endif //OPENCV_FLANN_RESULTSET_H - diff --git a/modules/flann/src/flann.cpp b/modules/flann/src/flann.cpp index 43d0e1f2a0..7ebb7eda7a 100644 --- a/modules/flann/src/flann.cpp +++ b/modules/flann/src/flann.cpp @@ -54,4 +54,4 @@ namespace cvflann } void dummyfunc() {} -} \ No newline at end of file +} diff --git a/modules/flann/src/miniflann.cpp b/modules/flann/src/miniflann.cpp index a7e476fdee..efa58927d3 100644 --- a/modules/flann/src/miniflann.cpp +++ b/modules/flann/src/miniflann.cpp @@ -26,7 +26,7 @@ IndexParams::IndexParams() } template -T getParam(const IndexParams& _p, const std::string& key, const T& defaultVal=T()) +T getParam(const IndexParams& _p, const String& key, const T& defaultVal=T()) { ::cvflann::IndexParams& p = get_params(_p); ::cvflann::IndexParams::const_iterator it = p.find(key); @@ -36,49 +36,49 @@ T getParam(const IndexParams& _p, const std::string& key, const T& defaultVal=T( } template -void setParam(IndexParams& _p, const std::string& key, const T& value) +void setParam(IndexParams& _p, const String& key, const T& value) { ::cvflann::IndexParams& p = get_params(_p); p[key] = value; } -std::string IndexParams::getString(const std::string& key, const std::string& defaultVal) const +String IndexParams::getString(const String& key, const String& defaultVal) const { return getParam(*this, key, defaultVal); } -int IndexParams::getInt(const std::string& key, int defaultVal) const +int IndexParams::getInt(const String& key, int defaultVal) const { return getParam(*this, key, defaultVal); } -double IndexParams::getDouble(const std::string& key, double defaultVal) const +double IndexParams::getDouble(const String& key, double defaultVal) const { return getParam(*this, key, defaultVal); } -void IndexParams::setString(const std::string& key, const std::string& value) +void IndexParams::setString(const String& key, const String& value) { setParam(*this, key, value); } -void IndexParams::setInt(const std::string& key, int value) +void IndexParams::setInt(const String& key, int value) { setParam(*this, key, value); } -void IndexParams::setDouble(const std::string& key, double value) +void IndexParams::setDouble(const String& key, double value) { setParam(*this, key, value); } -void IndexParams::setFloat(const std::string& key, float value) +void IndexParams::setFloat(const String& key, float value) { setParam(*this, key, value); } -void IndexParams::setBool(const std::string& key, bool value) +void IndexParams::setBool(const String& key, bool value) { setParam(*this, key, value); } @@ -88,9 +88,9 @@ void IndexParams::setAlgorithm(int value) setParam(*this, "algorithm", (cvflann::flann_algorithm_t)value); } -void IndexParams::getAll(std::vector& names, +void IndexParams::getAll(std::vector& names, std::vector& types, - std::vector& strValues, + std::vector& strValues, std::vector& numValues) const { names.clear(); @@ -106,7 +106,7 @@ void IndexParams::getAll(std::vector& names, names.push_back(it->first); try { - std::string val = it->second.cast(); + String val = it->second.cast(); types.push_back(CV_USRTYPE1); strValues.push_back(val); numValues.push_back(-1); @@ -285,9 +285,9 @@ LshIndexParams::LshIndexParams(int table_number, int key_size, int multi_probe_l p["multi_probe_level"] = multi_probe_level; } -SavedIndexParams::SavedIndexParams(const std::string& _filename) +SavedIndexParams::SavedIndexParams(const String& _filename) { - std::string filename = _filename; + String filename = _filename; ::cvflann::IndexParams& p = get_params(*this); p["algorithm"] = FLANN_INDEX_SAVED; @@ -312,9 +312,9 @@ buildIndex_(void*& index, const Mat& data, const IndexParams& params, const Dist { typedef typename Distance::ElementType ElementType; if(DataType::type != data.type()) - CV_Error_(CV_StsUnsupportedFormat, ("type=%d\n", data.type())); + CV_Error_(Error::StsUnsupportedFormat, ("type=%d\n", data.type())); if(!data.isContinuous()) - CV_Error(CV_StsBadArg, "Only continuous arrays are supported"); + CV_Error(Error::StsBadArg, "Only continuous arrays are supported"); ::cvflann::Matrix dataset((ElementType*)data.data, data.rows, data.cols); IndexType* _index = new IndexType(dataset, get_params(params), dist); @@ -357,7 +357,7 @@ void Index::build(InputArray _data, const IndexParams& params, flann_distance_t algo = getParam(params, "algorithm", FLANN_INDEX_LINEAR); if( algo == FLANN_INDEX_SAVED ) { - load(_data, getParam(params, "filename", std::string())); + load(_data, getParam(params, "filename", String())); return; } @@ -400,7 +400,7 @@ void Index::build(InputArray _data, const IndexParams& params, flann_distance_t break; #endif default: - CV_Error(CV_StsBadArg, "Unknown/unsupported distance type"); + CV_Error(Error::StsBadArg, "Unknown/unsupported distance type"); } } @@ -453,7 +453,7 @@ void Index::release() break; #endif default: - CV_Error(CV_StsBadArg, "Unknown/unsupported distance type"); + CV_Error(Error::StsBadArg, "Unknown/unsupported distance type"); } index = 0; } @@ -585,7 +585,7 @@ void Index::knnSearch(InputArray _query, OutputArray _indices, break; #endif default: - CV_Error(CV_StsBadArg, "Unknown/unsupported distance type"); + CV_Error(Error::StsBadArg, "Unknown/unsupported distance type"); } } @@ -599,7 +599,7 @@ int Index::radiusSearch(InputArray _query, OutputArray _indices, createIndicesDists( _indices, _dists, indices, dists, query.rows, maxResults, INT_MAX, dtype ); if( algo == FLANN_INDEX_LSH ) - CV_Error( CV_StsNotImplemented, "LSH index does not support radiusSearch operation" ); + CV_Error( Error::StsNotImplemented, "LSH index does not support radiusSearch operation" ); switch( distType ) { @@ -623,7 +623,7 @@ int Index::radiusSearch(InputArray _query, OutputArray _indices, return runRadiusSearch< ::cvflann::KL_Divergence >(index, query, indices, dists, radius, params); #endif default: - CV_Error(CV_StsBadArg, "Unknown/unsupported distance type"); + CV_Error(Error::StsBadArg, "Unknown/unsupported distance type"); } return -1; } @@ -654,11 +654,11 @@ template void saveIndex(const Index* index0, const void* inde saveIndex_< ::cvflann::Index >(index0, index, fout); } -void Index::save(const std::string& filename) const +void Index::save(const String& filename) const { FILE* fout = fopen(filename.c_str(), "wb"); if (fout == NULL) - CV_Error_( CV_StsError, ("Can not open file %s for writing FLANN index\n", filename.c_str()) ); + CV_Error_( Error::StsError, ("Can not open file %s for writing FLANN index\n", filename.c_str()) ); switch( distType ) { @@ -691,7 +691,7 @@ void Index::save(const std::string& filename) const default: fclose(fout); fout = 0; - CV_Error(CV_StsBadArg, "Unknown/unsupported distance type"); + CV_Error(Error::StsBadArg, "Unknown/unsupported distance type"); } if( fout ) fclose(fout); @@ -720,7 +720,7 @@ bool loadIndex(Index* index0, void*& index, const Mat& data, FILE* fin, const Di return loadIndex_ >(index0, index, data, fin, dist); } -bool Index::load(InputArray _data, const std::string& filename) +bool Index::load(InputArray _data, const String& filename) { Mat data = _data.getMat(); bool ok = true; diff --git a/modules/flann/src/precomp.cpp b/modules/flann/src/precomp.cpp deleted file mode 100644 index c149df18f9..0000000000 --- a/modules/flann/src/precomp.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "precomp.hpp" diff --git a/modules/flann/src/precomp.hpp b/modules/flann/src/precomp.hpp index 0d2647932b..1c41542857 100644 --- a/modules/flann/src/precomp.hpp +++ b/modules/flann/src/precomp.hpp @@ -5,11 +5,8 @@ #include #include -#ifdef HAVE_CVCONFIG_H -# include "cvconfig.h" -#endif #include "opencv2/core.hpp" -#include "opencv2/core/internal.hpp" +#include "opencv2/core/utility.hpp" #include "opencv2/flann/miniflann.hpp" #include "opencv2/flann/dist.h" @@ -23,5 +20,6 @@ #include "opencv2/flann/all_indices.h" #include "opencv2/flann/flann_base.hpp" -#endif +#include "opencv2/core/private.hpp" +#endif diff --git a/modules/flann/test/test_lshtable_badarg.cpp b/modules/flann/test/test_lshtable_badarg.cpp index 9e42335c2c..3b776668d1 100644 --- a/modules/flann/test/test_lshtable_badarg.cpp +++ b/modules/flann/test/test_lshtable_badarg.cpp @@ -74,13 +74,13 @@ void CV_LshTableBadArgTest::run( int /* start_from */ ) int errors = 0; caller.key_size = 0; - errors += run_test_case(CV_StsBadArg, "key_size is zero", caller); + errors += run_test_case(Error::StsBadArg, "key_size is zero", caller); caller.key_size = static_cast(sizeof(size_t) * CHAR_BIT); - errors += run_test_case(CV_StsBadArg, "key_size is too big", caller); + errors += run_test_case(Error::StsBadArg, "key_size is too big", caller); caller.key_size += cvtest::randInt(rng) % 100; - errors += run_test_case(CV_StsBadArg, "key_size is too big", caller); + errors += run_test_case(Error::StsBadArg, "key_size is too big", caller); if (errors != 0) ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); diff --git a/modules/flann/test/test_precomp.cpp b/modules/flann/test/test_precomp.cpp deleted file mode 100644 index 5956e13e3e..0000000000 --- a/modules/flann/test/test_precomp.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "test_precomp.hpp" diff --git a/modules/flann/test/test_precomp.hpp b/modules/flann/test/test_precomp.hpp index b5cd174610..cbee8957fd 100644 --- a/modules/flann/test/test_precomp.hpp +++ b/modules/flann/test/test_precomp.hpp @@ -10,7 +10,6 @@ #define __OPENCV_TEST_PRECOMP_HPP__ #include "opencv2/ts.hpp" -#include "opencv2/core.hpp" #include "opencv2/flann.hpp" #include diff --git a/modules/gpu/CMakeLists.txt b/modules/gpu/CMakeLists.txt index 26f806fb89..146056839a 100644 --- a/modules/gpu/CMakeLists.txt +++ b/modules/gpu/CMakeLists.txt @@ -3,107 +3,10 @@ if(ANDROID OR IOS) endif() set(the_description "GPU-accelerated Computer Vision") -ocv_add_module(gpu opencv_imgproc opencv_calib3d opencv_objdetect opencv_video opencv_nonfree opencv_photo opencv_legacy) -ocv_module_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src/cuda") +ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4127 /wd4100 /wd4324 /wd4512 /wd4515 -Wundef -Wmissing-declarations -Wshadow -Wunused-parameter) -file(GLOB lib_hdrs "include/opencv2/*.hpp" "include/opencv2/${name}/*.hpp" "include/opencv2/${name}/*.h") -file(GLOB lib_device_hdrs "include/opencv2/${name}/device/*.hpp" "include/opencv2/${name}/device/*.h") -file(GLOB lib_device_hdrs_detail "include/opencv2/${name}/device/detail/*.hpp" "include/opencv2/${name}/device/detail/*.h") -file(GLOB lib_int_hdrs "src/*.hpp" "src/*.h") -file(GLOB lib_cuda_hdrs "src/cuda/*.hpp" "src/cuda/*.h") -file(GLOB lib_srcs "src/*.cpp") -file(GLOB lib_cuda "src/cuda/*.cu*") - -source_group("Include" FILES ${lib_hdrs}) -source_group("Src\\Host" FILES ${lib_srcs} ${lib_int_hdrs}) -source_group("Src\\Cuda" FILES ${lib_cuda} ${lib_cuda_hdrs}) -source_group("Device" FILES ${lib_device_hdrs}) -source_group("Device\\Detail" FILES ${lib_device_hdrs_detail}) - -if(HAVE_CUDA) - file(GLOB_RECURSE ncv_srcs "src/nvidia/*.cpp" "src/nvidia/*.h*") - file(GLOB_RECURSE ncv_cuda "src/nvidia/*.cu") - set(ncv_files ${ncv_srcs} ${ncv_cuda}) - - source_group("Src\\NVidia" FILES ${ncv_files}) - ocv_include_directories("src/nvidia" "src/nvidia/core" "src/nvidia/NPP_staging" ${CUDA_INCLUDE_DIRS}) - ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef -Wmissing-declarations /wd4211 /wd4201 /wd4100 /wd4505 /wd4408) - string(REPLACE "-Wsign-promo" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - #set (CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-Xcompiler;/EHsc-;") - - if(MSVC) - if(NOT ENABLE_NOISY_WARNINGS) - foreach(var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG) - string(REPLACE "/W4" "/W3" ${var} "${${var}}") - endforeach() - - set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -Xcompiler /wd4251) - endif() - endif() - - ocv_cuda_compile(cuda_objs ${lib_cuda} ${ncv_cuda}) - - set(cuda_link_libs ${CUDA_LIBRARIES} ${CUDA_npp_LIBRARY}) - - if(WITH_NVCUVID) - set(cuda_link_libs ${cuda_link_libs} ${CUDA_nvcuvid_LIBRARY}) - endif() - - if(WIN32) - find_cuda_helper_libs(nvcuvenc) - set(cuda_link_libs ${cuda_link_libs} ${CUDA_nvcuvenc_LIBRARY}) - endif() - - if(WITH_FFMPEG) - set(cuda_link_libs ${cuda_link_libs} ${HIGHGUI_LIBRARIES}) - endif() -else() - set(lib_cuda "") - set(cuda_objs "") - set(cuda_link_libs "") - set(ncv_files "") -endif() - -ocv_set_module_sources( - HEADERS ${lib_hdrs} ${lib_device_hdrs} ${lib_device_hdrs_detail} - SOURCES ${lib_int_hdrs} ${lib_cuda_hdrs} ${lib_srcs} ${lib_cuda} ${ncv_files} ${cuda_objs} - ) - -ocv_create_module(${cuda_link_libs}) - -if(HAVE_CUDA) - if(HAVE_CUFFT) - CUDA_ADD_CUFFT_TO_TARGET(${the_module}) - endif() - - if(HAVE_CUBLAS) - CUDA_ADD_CUBLAS_TO_TARGET(${the_module}) - endif() - - install(FILES src/nvidia/NPP_staging/NPP_staging.hpp src/nvidia/core/NCV.hpp - DESTINATION ${OPENCV_INCLUDE_INSTALL_PATH}/opencv2/${name} - COMPONENT main) -endif() - -ocv_add_precompiled_headers(${the_module}) - -################################################################################################################ -################################ GPU Module Tests ##################################################### -################################################################################################################ -file(GLOB test_srcs "test/*.cpp") -file(GLOB test_hdrs "test/*.hpp" "test/*.h") - -set(nvidia "") -if(HAVE_CUDA) - file(GLOB nvidia "test/nvidia/*.cpp" "test/nvidia/*.hpp" "test/nvidia/*.h") - set(nvidia FILES "Src\\\\\\\\NVidia" ${nvidia}) # 8 ugly backslashes :'( -endif() - -ocv_add_accuracy_tests(FILES "Include" ${test_hdrs} - FILES "Src" ${test_srcs} - ${nvidia}) -ocv_add_perf_tests() +ocv_define_module(gpu opencv_calib3d opencv_objdetect opencv_gpuarithm opencv_gpuwarping OPTIONAL opencv_gpulegacy) if(HAVE_CUDA) add_subdirectory(perf4au) diff --git a/modules/gpu/app/nv_perf_test/CMakeLists.txt b/modules/gpu/app/nv_perf_test/CMakeLists.txt deleted file mode 100644 index c13f5ef46b..0000000000 --- a/modules/gpu/app/nv_perf_test/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -cmake_minimum_required(VERSION 2.8.3) - -project(nv_perf_test) - -find_package(OpenCV REQUIRED) -include_directories(${OpenCV_INCLUDE_DIR}) - -add_executable(${PROJECT_NAME} main.cpp) - -target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS}) diff --git a/modules/gpu/app/nv_perf_test/im1_1280x800.jpg b/modules/gpu/app/nv_perf_test/im1_1280x800.jpg deleted file mode 100644 index bdbbd4aee9..0000000000 Binary files a/modules/gpu/app/nv_perf_test/im1_1280x800.jpg and /dev/null differ diff --git a/modules/gpu/app/nv_perf_test/im2_1280x800.jpg b/modules/gpu/app/nv_perf_test/im2_1280x800.jpg deleted file mode 100644 index ae49640a95..0000000000 Binary files a/modules/gpu/app/nv_perf_test/im2_1280x800.jpg and /dev/null differ diff --git a/modules/gpu/app/nv_perf_test/main.cpp b/modules/gpu/app/nv_perf_test/main.cpp deleted file mode 100644 index 4bdf387edf..0000000000 --- a/modules/gpu/app/nv_perf_test/main.cpp +++ /dev/null @@ -1,487 +0,0 @@ -#include -#define HAVE_CUDA 1 -#include -#include -#include -#include -#include -#include - -static void printOsInfo() -{ -#if defined _WIN32 -# if defined _WIN64 - printf("[----------]\n[ GPU INFO ] \tRun on OS Windows x64.\n[----------]\n"); fflush(stdout); -# else - printf("[----------]\n[ GPU INFO ] \tRun on OS Windows x32.\n[----------]\n"); fflush(stdout); -# endif -#elif defined linux -# if defined _LP64 - printf("[----------]\n[ GPU INFO ] \tRun on OS Linux x64.\n[----------]\n"); fflush(stdout); -# else - printf("[----------]\n[ GPU INFO ] \tRun on OS Linux x32.\n[----------]\n"); fflush(stdout); -# endif -#elif defined __APPLE__ -# if defined _LP64 - printf("[----------]\n[ GPU INFO ] \tRun on OS Apple x64.\n[----------]\n"); fflush(stdout); -# else - printf("[----------]\n[ GPU INFO ] \tRun on OS Apple x32.\n[----------]\n"); fflush(stdout); -# endif -#endif -} - -static void printCudaInfo() -{ - const int deviceCount = cv::gpu::getCudaEnabledDeviceCount(); - - printf("[----------]\n"); fflush(stdout); - printf("[ GPU INFO ] \tCUDA device count:: %d.\n", deviceCount); fflush(stdout); - printf("[----------]\n"); fflush(stdout); - - for (int i = 0; i < deviceCount; ++i) - { - cv::gpu::DeviceInfo info(i); - - printf("[----------]\n"); fflush(stdout); - printf("[ DEVICE ] \t# %d %s.\n", i, info.name().c_str()); fflush(stdout); - printf("[ ] \tCompute capability: %d.%d\n", info.majorVersion(), info.minorVersion()); fflush(stdout); - printf("[ ] \tMulti Processor Count: %d\n", info.multiProcessorCount()); fflush(stdout); - printf("[ ] \tTotal memory: %d Mb\n", static_cast(static_cast(info.totalMemory() / 1024.0) / 1024.0)); fflush(stdout); - printf("[ ] \tFree memory: %d Mb\n", static_cast(static_cast(info.freeMemory() / 1024.0) / 1024.0)); fflush(stdout); - if (!info.isCompatible()) - printf("[ GPU INFO ] \tThis device is NOT compatible with current GPU module build\n"); - printf("[----------]\n"); fflush(stdout); - } -} - -int main(int argc, char* argv[]) -{ - printOsInfo(); - printCudaInfo(); - - perf::Regression::Init("nv_perf_test"); - perf::TestBase::Init(argc, argv); - testing::InitGoogleTest(&argc, argv); - - return RUN_ALL_TESTS(); -} - -#define DEF_PARAM_TEST(name, ...) typedef ::perf::TestBaseWithParam< std::tr1::tuple< __VA_ARGS__ > > name -#define DEF_PARAM_TEST_1(name, param_type) typedef ::perf::TestBaseWithParam< param_type > name - -////////////////////////////////////////////////////////// -// HoughLinesP - -DEF_PARAM_TEST_1(Image, std::string); - -GPU_PERF_TEST_P(Image, HoughLinesP, testing::Values(std::string("im1_1280x800.jpg"))) -{ - declare.time(30.0); - - std::string fileName = GetParam(); - - const float rho = 1.f; - const float theta = 1.f; - const int threshold = 40; - const int minLineLenght = 20; - const int maxLineGap = 5; - - cv::Mat image = cv::imread(fileName, cv::IMREAD_GRAYSCALE); - - if (PERF_RUN_GPU()) - { - cv::gpu::GpuMat d_image(image); - cv::gpu::GpuMat d_lines; - cv::gpu::HoughLinesBuf d_buf; - - cv::gpu::HoughLinesP(d_image, d_lines, d_buf, rho, theta, minLineLenght, maxLineGap); - - TEST_CYCLE() - { - cv::gpu::HoughLinesP(d_image, d_lines, d_buf, rho, theta, minLineLenght, maxLineGap); - } - } - else - { - cv::Mat mask; - cv::Canny(image, mask, 50, 100); - - std::vector lines; - cv::HoughLinesP(mask, lines, rho, theta, threshold, minLineLenght, maxLineGap); - - TEST_CYCLE() - { - cv::HoughLinesP(mask, lines, rho, theta, threshold, minLineLenght, maxLineGap); - } - } - - SANITY_CHECK(0); -} - -////////////////////////////////////////////////////////// -// GoodFeaturesToTrack - -DEF_PARAM_TEST(Image_Depth, std::string, perf::MatDepth); - -GPU_PERF_TEST_P(Image_Depth, GoodFeaturesToTrack, - testing::Combine( - testing::Values(std::string("im1_1280x800.jpg")), - testing::Values(CV_8U, CV_16U) - )) -{ - declare.time(60); - - const std::string fileName = std::tr1::get<0>(GetParam()); - const int depth = std::tr1::get<1>(GetParam()); - - const int maxCorners = 5000; - const double qualityLevel = 0.05; - const int minDistance = 5; - const int blockSize = 3; - const bool useHarrisDetector = true; - const double k = 0.05; - - cv::Mat src = cv::imread(fileName, cv::IMREAD_GRAYSCALE); - if (src.empty()) - FAIL() << "Unable to load source image [" << fileName << "]"; - - if (depth != CV_8U) - src.convertTo(src, depth); - - cv::Mat mask(src.size(), CV_8UC1, cv::Scalar::all(1)); - mask(cv::Rect(0, 0, 100, 100)).setTo(cv::Scalar::all(0)); - - if (PERF_RUN_GPU()) - { - cv::gpu::GoodFeaturesToTrackDetector_GPU d_detector(maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector, k); - - cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat d_mask(mask); - cv::gpu::GpuMat d_pts; - - d_detector(d_src, d_pts, d_mask); - - TEST_CYCLE() - { - d_detector(d_src, d_pts, d_mask); - } - } - else - { - if (depth != CV_8U) - FAIL() << "Unsupported depth"; - - cv::Mat pts; - - cv::goodFeaturesToTrack(src, pts, maxCorners, qualityLevel, minDistance, mask, blockSize, useHarrisDetector, k); - - TEST_CYCLE() - { - cv::goodFeaturesToTrack(src, pts, maxCorners, qualityLevel, minDistance, mask, blockSize, useHarrisDetector, k); - } - } - - SANITY_CHECK(0); -} - -////////////////////////////////////////////////////////// -// OpticalFlowPyrLKSparse - -typedef std::pair string_pair; - -DEF_PARAM_TEST(ImagePair_Depth_GraySource, string_pair, perf::MatDepth, bool); - -GPU_PERF_TEST_P(ImagePair_Depth_GraySource, OpticalFlowPyrLKSparse, - testing::Combine( - testing::Values(string_pair("im1_1280x800.jpg", "im2_1280x800.jpg")), - testing::Values(CV_8U, CV_16U), - testing::Bool() - )) -{ - declare.time(60); - - const string_pair fileNames = std::tr1::get<0>(GetParam()); - const int depth = std::tr1::get<1>(GetParam()); - const bool graySource = std::tr1::get<2>(GetParam()); - - // PyrLK params - const cv::Size winSize(15, 15); - const int maxLevel = 5; - const cv::TermCriteria criteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 30, 0.01); - - // GoodFeaturesToTrack params - const int maxCorners = 5000; - const double qualityLevel = 0.05; - const int minDistance = 5; - const int blockSize = 3; - const bool useHarrisDetector = true; - const double k = 0.05; - - cv::Mat src1 = cv::imread(fileNames.first, graySource ? cv::IMREAD_GRAYSCALE : cv::IMREAD_COLOR); - if (src1.empty()) - FAIL() << "Unable to load source image [" << fileNames.first << "]"; - - cv::Mat src2 = cv::imread(fileNames.second, graySource ? cv::IMREAD_GRAYSCALE : cv::IMREAD_COLOR); - if (src2.empty()) - FAIL() << "Unable to load source image [" << fileNames.second << "]"; - - cv::Mat gray_src; - if (graySource) - gray_src = src1; - else - cv::cvtColor(src1, gray_src, cv::COLOR_BGR2GRAY); - - cv::Mat pts; - cv::goodFeaturesToTrack(gray_src, pts, maxCorners, qualityLevel, minDistance, cv::noArray(), blockSize, useHarrisDetector, k); - - if (depth != CV_8U) - { - src1.convertTo(src1, depth); - src2.convertTo(src2, depth); - } - - if (PERF_RUN_GPU()) - { - cv::gpu::GpuMat d_src1(src1); - cv::gpu::GpuMat d_src2(src2); - cv::gpu::GpuMat d_pts(pts.reshape(2, 1)); - cv::gpu::GpuMat d_nextPts; - cv::gpu::GpuMat d_status; - - cv::gpu::PyrLKOpticalFlow d_pyrLK; - d_pyrLK.winSize = winSize; - d_pyrLK.maxLevel = maxLevel; - d_pyrLK.iters = criteria.maxCount; - d_pyrLK.useInitialFlow = false; - - d_pyrLK.sparse(d_src1, d_src2, d_pts, d_nextPts, d_status); - - TEST_CYCLE() - { - d_pyrLK.sparse(d_src1, d_src2, d_pts, d_nextPts, d_status); - } - } - else - { - if (depth != CV_8U) - FAIL() << "Unsupported depth"; - - cv::Mat nextPts; - cv::Mat status; - - cv::calcOpticalFlowPyrLK(src1, src2, pts, nextPts, status, cv::noArray(), winSize, maxLevel, criteria); - - TEST_CYCLE() - { - cv::calcOpticalFlowPyrLK(src1, src2, pts, nextPts, status, cv::noArray(), winSize, maxLevel, criteria); - } - } - - SANITY_CHECK(0); -} - -////////////////////////////////////////////////////////// -// OpticalFlowFarneback - -DEF_PARAM_TEST(ImagePair_Depth, string_pair, perf::MatDepth); - -GPU_PERF_TEST_P(ImagePair_Depth, OpticalFlowFarneback, - testing::Combine( - testing::Values(string_pair("im1_1280x800.jpg", "im2_1280x800.jpg")), - testing::Values(CV_8U, CV_16U) - )) -{ - declare.time(500); - - const string_pair fileNames = std::tr1::get<0>(GetParam()); - const int depth = std::tr1::get<1>(GetParam()); - - const double pyrScale = 0.5; - const int numLevels = 6; - const int winSize = 7; - const int numIters = 15; - const int polyN = 7; - const double polySigma = 1.5; - const int flags = cv::OPTFLOW_USE_INITIAL_FLOW; - - cv::Mat src1 = cv::imread(fileNames.first, cv::IMREAD_GRAYSCALE); - if (src1.empty()) - FAIL() << "Unable to load source image [" << fileNames.first << "]"; - - cv::Mat src2 = cv::imread(fileNames.second, cv::IMREAD_GRAYSCALE); - if (src2.empty()) - FAIL() << "Unable to load source image [" << fileNames.second << "]"; - - if (depth != CV_8U) - { - src1.convertTo(src1, depth); - src2.convertTo(src2, depth); - } - - if (PERF_RUN_GPU()) - { - cv::gpu::GpuMat d_src1(src1); - cv::gpu::GpuMat d_src2(src2); - cv::gpu::GpuMat d_u(src1.size(), CV_32FC1, cv::Scalar::all(0)); - cv::gpu::GpuMat d_v(src1.size(), CV_32FC1, cv::Scalar::all(0)); - - cv::gpu::FarnebackOpticalFlow d_farneback; - d_farneback.pyrScale = pyrScale; - d_farneback.numLevels = numLevels; - d_farneback.winSize = winSize; - d_farneback.numIters = numIters; - d_farneback.polyN = polyN; - d_farneback.polySigma = polySigma; - d_farneback.flags = flags; - - d_farneback(d_src1, d_src2, d_u, d_v); - - TEST_CYCLE_N(10) - { - d_farneback(d_src1, d_src2, d_u, d_v); - } - } - else - { - if (depth != CV_8U) - FAIL() << "Unsupported depth"; - - cv::Mat flow(src1.size(), CV_32FC2, cv::Scalar::all(0)); - - cv::calcOpticalFlowFarneback(src1, src2, flow, pyrScale, numLevels, winSize, numIters, polyN, polySigma, flags); - - TEST_CYCLE_N(10) - { - cv::calcOpticalFlowFarneback(src1, src2, flow, pyrScale, numLevels, winSize, numIters, polyN, polySigma, flags); - } - } - - SANITY_CHECK(0); -} - -////////////////////////////////////////////////////////// -// OpticalFlowBM - -void calcOpticalFlowBM(const cv::Mat& prev, const cv::Mat& curr, - cv::Size bSize, cv::Size shiftSize, cv::Size maxRange, int usePrevious, - cv::Mat& velx, cv::Mat& vely) -{ - cv::Size sz((curr.cols - bSize.width + shiftSize.width)/shiftSize.width, (curr.rows - bSize.height + shiftSize.height)/shiftSize.height); - - velx.create(sz, CV_32FC1); - vely.create(sz, CV_32FC1); - - CvMat cvprev = prev; - CvMat cvcurr = curr; - - CvMat cvvelx = velx; - CvMat cvvely = vely; - - cvCalcOpticalFlowBM(&cvprev, &cvcurr, bSize, shiftSize, maxRange, usePrevious, &cvvelx, &cvvely); -} - -DEF_PARAM_TEST(ImagePair_BlockSize_ShiftSize_MaxRange, string_pair, cv::Size, cv::Size, cv::Size); - -GPU_PERF_TEST_P(ImagePair_BlockSize_ShiftSize_MaxRange, OpticalFlowBM, - testing::Combine( - testing::Values(string_pair("im1_1280x800.jpg", "im2_1280x800.jpg")), - testing::Values(cv::Size(16, 16)), - testing::Values(cv::Size(2, 2)), - testing::Values(cv::Size(16, 16)) - )) -{ - declare.time(3000); - - const string_pair fileNames = std::tr1::get<0>(GetParam()); - const cv::Size block_size = std::tr1::get<1>(GetParam()); - const cv::Size shift_size = std::tr1::get<2>(GetParam()); - const cv::Size max_range = std::tr1::get<3>(GetParam()); - - cv::Mat src1 = cv::imread(fileNames.first, cv::IMREAD_GRAYSCALE); - if (src1.empty()) - FAIL() << "Unable to load source image [" << fileNames.first << "]"; - - cv::Mat src2 = cv::imread(fileNames.second, cv::IMREAD_GRAYSCALE); - if (src2.empty()) - FAIL() << "Unable to load source image [" << fileNames.second << "]"; - - if (PERF_RUN_GPU()) - { - cv::gpu::GpuMat d_src1(src1); - cv::gpu::GpuMat d_src2(src2); - cv::gpu::GpuMat d_velx, d_vely, buf; - - cv::gpu::calcOpticalFlowBM(d_src1, d_src2, block_size, shift_size, max_range, false, d_velx, d_vely, buf); - - TEST_CYCLE_N(10) - { - cv::gpu::calcOpticalFlowBM(d_src1, d_src2, block_size, shift_size, max_range, false, d_velx, d_vely, buf); - } - } - else - { - cv::Mat velx, vely; - - calcOpticalFlowBM(src1, src2, block_size, shift_size, max_range, false, velx, vely); - - TEST_CYCLE_N(10) - { - calcOpticalFlowBM(src1, src2, block_size, shift_size, max_range, false, velx, vely); - } - } - - SANITY_CHECK(0); -} - -GPU_PERF_TEST_P(ImagePair_BlockSize_ShiftSize_MaxRange, FastOpticalFlowBM, - testing::Combine( - testing::Values(string_pair("im1_1280x800.jpg", "im2_1280x800.jpg")), - testing::Values(cv::Size(16, 16)), - testing::Values(cv::Size(1, 1)), - testing::Values(cv::Size(16, 16)) - )) -{ - declare.time(3000); - - const string_pair fileNames = std::tr1::get<0>(GetParam()); - const cv::Size block_size = std::tr1::get<1>(GetParam()); - const cv::Size shift_size = std::tr1::get<2>(GetParam()); - const cv::Size max_range = std::tr1::get<3>(GetParam()); - - cv::Mat src1 = cv::imread(fileNames.first, cv::IMREAD_GRAYSCALE); - if (src1.empty()) - FAIL() << "Unable to load source image [" << fileNames.first << "]"; - - cv::Mat src2 = cv::imread(fileNames.second, cv::IMREAD_GRAYSCALE); - if (src2.empty()) - FAIL() << "Unable to load source image [" << fileNames.second << "]"; - - if (PERF_RUN_GPU()) - { - cv::gpu::GpuMat d_src1(src1); - cv::gpu::GpuMat d_src2(src2); - cv::gpu::GpuMat d_velx, d_vely; - - cv::gpu::FastOpticalFlowBM fastBM; - - fastBM(d_src1, d_src2, d_velx, d_vely, max_range.width, block_size.width); - - TEST_CYCLE_N(10) - { - fastBM(d_src1, d_src2, d_velx, d_vely, max_range.width, block_size.width); - } - } - else - { - cv::Mat velx, vely; - - calcOpticalFlowBM(src1, src2, block_size, shift_size, max_range, false, velx, vely); - - TEST_CYCLE_N(10) - { - calcOpticalFlowBM(src1, src2, block_size, shift_size, max_range, false, velx, vely); - } - } - - SANITY_CHECK(0); -} diff --git a/modules/gpu/doc/calib3d.rst b/modules/gpu/doc/calib3d.rst new file mode 100644 index 0000000000..faa6c0fec2 --- /dev/null +++ b/modules/gpu/doc/calib3d.rst @@ -0,0 +1,36 @@ +Camera Calibration and 3D Reconstruction +======================================== + +.. highlight:: cpp + + + +gpu::solvePnPRansac +------------------- +Finds the object pose from 3D-2D point correspondences. + +.. ocv:function:: void gpu::solvePnPRansac(const Mat& object, const Mat& image, const Mat& camera_mat, const Mat& dist_coef, Mat& rvec, Mat& tvec, bool use_extrinsic_guess=false, int num_iters=100, float max_dist=8.0, int min_inlier_count=100, vector* inliers=NULL) + + :param object: Single-row matrix of object points. + + :param image: Single-row matrix of image points. + + :param camera_mat: 3x3 matrix of intrinsic camera parameters. + + :param dist_coef: Distortion coefficients. See :ocv:func:`undistortPoints` for details. + + :param rvec: Output 3D rotation vector. + + :param tvec: Output 3D translation vector. + + :param use_extrinsic_guess: Flag to indicate that the function must use ``rvec`` and ``tvec`` as an initial transformation guess. It is not supported for now. + + :param num_iters: Maximum number of RANSAC iterations. + + :param max_dist: Euclidean distance threshold to detect whether point is inlier or not. + + :param min_inlier_count: Flag to indicate that the function must stop if greater or equal number of inliers is achieved. It is not supported for now. + + :param inliers: Output vector of inlier indices. + +.. seealso:: :ocv:func:`solvePnPRansac` diff --git a/modules/gpu/doc/camera_calibration_and_3d_reconstruction.rst b/modules/gpu/doc/camera_calibration_and_3d_reconstruction.rst deleted file mode 100644 index 587c253d2a..0000000000 --- a/modules/gpu/doc/camera_calibration_and_3d_reconstruction.rst +++ /dev/null @@ -1,499 +0,0 @@ -Camera Calibration and 3D Reconstruction -======================================== - -.. highlight:: cpp - - - -gpu::StereoBM_GPU ------------------ -.. ocv:class:: gpu::StereoBM_GPU - -Class computing stereo correspondence (disparity map) using the block matching algorithm. :: - - class StereoBM_GPU - { - public: - enum { BASIC_PRESET = 0, PREFILTER_XSOBEL = 1 }; - - enum { DEFAULT_NDISP = 64, DEFAULT_WINSZ = 19 }; - - StereoBM_GPU(); - StereoBM_GPU(int preset, int ndisparities = DEFAULT_NDISP, - int winSize = DEFAULT_WINSZ); - - void operator() (const GpuMat& left, const GpuMat& right, - GpuMat& disparity, Stream& stream = Stream::Null()); - - static bool checkIfGpuCallReasonable(); - - int preset; - int ndisp; - int winSize; - - float avergeTexThreshold; - - ... - }; - - -The class also performs pre- and post-filtering steps: Sobel pre-filtering (if ``PREFILTER_XSOBEL`` flag is set) and low textureness filtering (if ``averageTexThreshols > 0`` ). If ``avergeTexThreshold = 0`` , low textureness filtering is disabled. Otherwise, the disparity is set to 0 in each point ``(x, y)`` , where for the left image - -.. math:: - \sum HorizontalGradiensInWindow(x, y, winSize) < (winSize \cdot winSize) \cdot avergeTexThreshold - -This means that the input left image is low textured. - - - -gpu::StereoBM_GPU::StereoBM_GPU ------------------------------------ -Enables :ocv:class:`gpu::StereoBM_GPU` constructors. - -.. ocv:function:: gpu::StereoBM_GPU::StereoBM_GPU() - -.. ocv:function:: gpu::StereoBM_GPU::StereoBM_GPU(int preset, int ndisparities = DEFAULT_NDISP, int winSize = DEFAULT_WINSZ) - - :param preset: Parameter presetting: - - * **BASIC_PRESET** Basic mode without pre-processing. - - * **PREFILTER_XSOBEL** Sobel pre-filtering mode. - - :param ndisparities: Number of disparities. It must be a multiple of 8 and less or equal to 256. - - :param winSize: Block size. - - - -gpu::StereoBM_GPU::operator () ----------------------------------- -Enables the stereo correspondence operator that finds the disparity for the specified rectified stereo pair. - -.. ocv:function:: void gpu::StereoBM_GPU::operator ()(const GpuMat& left, const GpuMat& right, GpuMat& disparity, Stream& stream = Stream::Null()) - - :param left: Left image. Only ``CV_8UC1`` type is supported. - - :param right: Right image with the same size and the same type as the left one. - - :param disparity: Output disparity map. It is a ``CV_8UC1`` image with the same size as the input images. - - :param stream: Stream for the asynchronous version. - - - -gpu::StereoBM_GPU::checkIfGpuCallReasonable ------------------------------------------------ -Uses a heuristic method to estimate whether the current GPU is faster than the CPU in this algorithm. It queries the currently active device. - -.. ocv:function:: bool gpu::StereoBM_GPU::checkIfGpuCallReasonable() - - - -gpu::StereoBeliefPropagation ----------------------------- -.. ocv:class:: gpu::StereoBeliefPropagation - -Class computing stereo correspondence using the belief propagation algorithm. :: - - class StereoBeliefPropagation - { - public: - enum { DEFAULT_NDISP = 64 }; - enum { DEFAULT_ITERS = 5 }; - enum { DEFAULT_LEVELS = 5 }; - - static void estimateRecommendedParams(int width, int height, - int& ndisp, int& iters, int& levels); - - explicit StereoBeliefPropagation(int ndisp = DEFAULT_NDISP, - int iters = DEFAULT_ITERS, - int levels = DEFAULT_LEVELS, - int msg_type = CV_32F); - StereoBeliefPropagation(int ndisp, int iters, int levels, - float max_data_term, float data_weight, - float max_disc_term, float disc_single_jump, - int msg_type = CV_32F); - - void operator()(const GpuMat& left, const GpuMat& right, - GpuMat& disparity, Stream& stream = Stream::Null()); - void operator()(const GpuMat& data, GpuMat& disparity, Stream& stream = Stream::Null()); - - int ndisp; - - int iters; - int levels; - - float max_data_term; - float data_weight; - float max_disc_term; - float disc_single_jump; - - int msg_type; - - ... - }; - -The class implements algorithm described in [Felzenszwalb2006]_ . It can compute own data cost (using a truncated linear model) or use a user-provided data cost. - -.. note:: - - ``StereoBeliefPropagation`` requires a lot of memory for message storage: - - .. math:: - - width \_ step \cdot height \cdot ndisp \cdot 4 \cdot (1 + 0.25) - - and for data cost storage: - - .. math:: - - width\_step \cdot height \cdot ndisp \cdot (1 + 0.25 + 0.0625 + \dotsm + \frac{1}{4^{levels}}) - - ``width_step`` is the number of bytes in a line including padding. - - - -gpu::StereoBeliefPropagation::StereoBeliefPropagation ---------------------------------------------------------- -Enables the :ocv:class:`gpu::StereoBeliefPropagation` constructors. - -.. ocv:function:: gpu::StereoBeliefPropagation::StereoBeliefPropagation(int ndisp = DEFAULT_NDISP, int iters = DEFAULT_ITERS, int levels = DEFAULT_LEVELS, int msg_type = CV_32F) - -.. ocv:function:: gpu::StereoBeliefPropagation::StereoBeliefPropagation(int ndisp, int iters, int levels, float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int msg_type = CV_32F) - - :param ndisp: Number of disparities. - - :param iters: Number of BP iterations on each level. - - :param levels: Number of levels. - - :param max_data_term: Threshold for data cost truncation. - - :param data_weight: Data weight. - - :param max_disc_term: Threshold for discontinuity truncation. - - :param disc_single_jump: Discontinuity single jump. - - :param msg_type: Type for messages. ``CV_16SC1`` and ``CV_32FC1`` types are supported. - -``StereoBeliefPropagation`` uses a truncated linear model for the data cost and discontinuity terms: - -.. math:: - - DataCost = data \_ weight \cdot \min ( \lvert Img_Left(x,y)-Img_Right(x-d,y) \rvert , max \_ data \_ term) - -.. math:: - - DiscTerm = \min (disc \_ single \_ jump \cdot \lvert f_1-f_2 \rvert , max \_ disc \_ term) - -For more details, see [Felzenszwalb2006]_. - -By default, :ocv:class:`gpu::StereoBeliefPropagation` uses floating-point arithmetics and the ``CV_32FC1`` type for messages. But it can also use fixed-point arithmetics and the ``CV_16SC1`` message type for better performance. To avoid an overflow in this case, the parameters must satisfy the following requirement: - -.. math:: - - 10 \cdot 2^{levels-1} \cdot max \_ data \_ term < SHRT \_ MAX - - - -gpu::StereoBeliefPropagation::estimateRecommendedParams ------------------------------------------------------------ -Uses a heuristic method to compute the recommended parameters ( ``ndisp``, ``iters`` and ``levels`` ) for the specified image size ( ``width`` and ``height`` ). - -.. ocv:function:: void gpu::StereoBeliefPropagation::estimateRecommendedParams(int width, int height, int& ndisp, int& iters, int& levels) - - - -gpu::StereoBeliefPropagation::operator () ---------------------------------------------- -Enables the stereo correspondence operator that finds the disparity for the specified rectified stereo pair or data cost. - -.. ocv:function:: void gpu::StereoBeliefPropagation::operator ()(const GpuMat& left, const GpuMat& right, GpuMat& disparity, Stream& stream = Stream::Null()) - -.. ocv:function:: void gpu::StereoBeliefPropagation::operator ()(const GpuMat& data, GpuMat& disparity, Stream& stream = Stream::Null()) - - :param left: Left image. ``CV_8UC1`` , ``CV_8UC3`` and ``CV_8UC4`` types are supported. - - :param right: Right image with the same size and the same type as the left one. - - :param data: User-specified data cost, a matrix of ``msg_type`` type and ``Size(*ndisp, )`` size. - - :param disparity: Output disparity map. If ``disparity`` is empty, the output type is ``CV_16SC1`` . Otherwise, the type is retained. - - :param stream: Stream for the asynchronous version. - - - -gpu::StereoConstantSpaceBP --------------------------- -.. ocv:class:: gpu::StereoConstantSpaceBP - -Class computing stereo correspondence using the constant space belief propagation algorithm. :: - - class StereoConstantSpaceBP - { - public: - enum { DEFAULT_NDISP = 128 }; - enum { DEFAULT_ITERS = 8 }; - enum { DEFAULT_LEVELS = 4 }; - enum { DEFAULT_NR_PLANE = 4 }; - - static void estimateRecommendedParams(int width, int height, - int& ndisp, int& iters, int& levels, int& nr_plane); - - explicit StereoConstantSpaceBP(int ndisp = DEFAULT_NDISP, - int iters = DEFAULT_ITERS, - int levels = DEFAULT_LEVELS, - int nr_plane = DEFAULT_NR_PLANE, - int msg_type = CV_32F); - StereoConstantSpaceBP(int ndisp, int iters, int levels, int nr_plane, - float max_data_term, float data_weight, - float max_disc_term, float disc_single_jump, - int min_disp_th = 0, - int msg_type = CV_32F); - - void operator()(const GpuMat& left, const GpuMat& right, - GpuMat& disparity, Stream& stream = Stream::Null()); - - int ndisp; - - int iters; - int levels; - - int nr_plane; - - float max_data_term; - float data_weight; - float max_disc_term; - float disc_single_jump; - - int min_disp_th; - - int msg_type; - - bool use_local_init_data_cost; - - ... - }; - - -The class implements algorithm described in [Yang2010]_. ``StereoConstantSpaceBP`` supports both local minimum and global minimum data cost initialization algorithms. For more details, see the paper mentioned above. By default, a local algorithm is used. To enable a global algorithm, set ``use_local_init_data_cost`` to ``false`` . - - - -gpu::StereoConstantSpaceBP::StereoConstantSpaceBP ------------------------------------------------------ -Enables the :ocv:class:`gpu::StereoConstantSpaceBP` constructors. - -.. ocv:function:: gpu::StereoConstantSpaceBP::StereoConstantSpaceBP(int ndisp = DEFAULT_NDISP, int iters = DEFAULT_ITERS, int levels = DEFAULT_LEVELS, int nr_plane = DEFAULT_NR_PLANE, int msg_type = CV_32F) - -.. ocv:function:: gpu::StereoConstantSpaceBP::StereoConstantSpaceBP(int ndisp, int iters, int levels, int nr_plane, float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int min_disp_th = 0, int msg_type = CV_32F) - - :param ndisp: Number of disparities. - - :param iters: Number of BP iterations on each level. - - :param levels: Number of levels. - - :param nr_plane: Number of disparity levels on the first level. - - :param max_data_term: Truncation of data cost. - - :param data_weight: Data weight. - - :param max_disc_term: Truncation of discontinuity. - - :param disc_single_jump: Discontinuity single jump. - - :param min_disp_th: Minimal disparity threshold. - - :param msg_type: Type for messages. ``CV_16SC1`` and ``CV_32FC1`` types are supported. - -``StereoConstantSpaceBP`` uses a truncated linear model for the data cost and discontinuity terms: - -.. math:: - - DataCost = data \_ weight \cdot \min ( \lvert I_2-I_1 \rvert , max \_ data \_ term) - -.. math:: - - DiscTerm = \min (disc \_ single \_ jump \cdot \lvert f_1-f_2 \rvert , max \_ disc \_ term) - -For more details, see [Yang2010]_. - -By default, ``StereoConstantSpaceBP`` uses floating-point arithmetics and the ``CV_32FC1`` type for messages. But it can also use fixed-point arithmetics and the ``CV_16SC1`` message type for better performance. To avoid an overflow in this case, the parameters must satisfy the following requirement: - -.. math:: - - 10 \cdot 2^{levels-1} \cdot max \_ data \_ term < SHRT \_ MAX - - - -gpu::StereoConstantSpaceBP::estimateRecommendedParams ---------------------------------------------------------- -Uses a heuristic method to compute parameters (ndisp, iters, levelsand nrplane) for the specified image size (widthand height). - -.. ocv:function:: void gpu::StereoConstantSpaceBP::estimateRecommendedParams(int width, int height, int& ndisp, int& iters, int& levels, int& nr_plane) - - - -gpu::StereoConstantSpaceBP::operator () -------------------------------------------- -Enables the stereo correspondence operator that finds the disparity for the specified rectified stereo pair. - -.. ocv:function:: void gpu::StereoConstantSpaceBP::operator ()(const GpuMat& left, const GpuMat& right, GpuMat& disparity, Stream& stream = Stream::Null()) - - :param left: Left image. ``CV_8UC1`` , ``CV_8UC3`` and ``CV_8UC4`` types are supported. - - :param right: Right image with the same size and the same type as the left one. - - :param disparity: Output disparity map. If ``disparity`` is empty, the output type is ``CV_16SC1`` . Otherwise, the output type is ``disparity.type()`` . - - :param stream: Stream for the asynchronous version. - - - -gpu::DisparityBilateralFilter ------------------------------ -.. ocv:class:: gpu::DisparityBilateralFilter - -Class refining a disparity map using joint bilateral filtering. :: - - class CV_EXPORTS DisparityBilateralFilter - { - public: - enum { DEFAULT_NDISP = 64 }; - enum { DEFAULT_RADIUS = 3 }; - enum { DEFAULT_ITERS = 1 }; - - explicit DisparityBilateralFilter(int ndisp = DEFAULT_NDISP, - int radius = DEFAULT_RADIUS, int iters = DEFAULT_ITERS); - - DisparityBilateralFilter(int ndisp, int radius, int iters, - float edge_threshold, float max_disc_threshold, - float sigma_range); - - void operator()(const GpuMat& disparity, const GpuMat& image, - GpuMat& dst, Stream& stream = Stream::Null()); - - ... - }; - - -The class implements [Yang2010]_ algorithm. - - - -gpu::DisparityBilateralFilter::DisparityBilateralFilter ------------------------------------------------------------ -Enables the :ocv:class:`gpu::DisparityBilateralFilter` constructors. - -.. ocv:function:: gpu::DisparityBilateralFilter::DisparityBilateralFilter(int ndisp = DEFAULT_NDISP, int radius = DEFAULT_RADIUS, int iters = DEFAULT_ITERS) - -.. ocv:function:: gpu::DisparityBilateralFilter::DisparityBilateralFilter(int ndisp, int radius, int iters, float edge_threshold, float max_disc_threshold, float sigma_range) - - :param ndisp: Number of disparities. - - :param radius: Filter radius. - - :param iters: Number of iterations. - - :param edge_threshold: Threshold for edges. - - :param max_disc_threshold: Constant to reject outliers. - - :param sigma_range: Filter range. - - - -gpu::DisparityBilateralFilter::operator () ----------------------------------------------- -Refines a disparity map using joint bilateral filtering. - -.. ocv:function:: void gpu::DisparityBilateralFilter::operator ()(const GpuMat& disparity, const GpuMat& image, GpuMat& dst, Stream& stream = Stream::Null()) - - :param disparity: Input disparity map. ``CV_8UC1`` and ``CV_16SC1`` types are supported. - - :param image: Input image. ``CV_8UC1`` and ``CV_8UC3`` types are supported. - - :param dst: Destination disparity map. It has the same size and type as ``disparity`` . - - :param stream: Stream for the asynchronous version. - - - -gpu::drawColorDisp ----------------------- -Colors a disparity image. - -.. ocv:function:: void gpu::drawColorDisp(const GpuMat& src_disp, GpuMat& dst_disp, int ndisp, Stream& stream = Stream::Null()) - - :param src_disp: Source disparity image. ``CV_8UC1`` and ``CV_16SC1`` types are supported. - - :param dst_disp: Output disparity image. It has the same size as ``src_disp`` . The type is ``CV_8UC4`` in ``BGRA`` format (alpha = 255). - - :param ndisp: Number of disparities. - - :param stream: Stream for the asynchronous version. - -This function draws a colored disparity map by converting disparity values from ``[0..ndisp)`` interval first to ``HSV`` color space (where different disparity values correspond to different hues) and then converting the pixels to ``RGB`` for visualization. - - - -gpu::reprojectImageTo3D ---------------------------- -Reprojects a disparity image to 3D space. - -.. ocv:function:: void gpu::reprojectImageTo3D(const GpuMat& disp, GpuMat& xyzw, const Mat& Q, int dst_cn = 4, Stream& stream = Stream::Null()) - - :param disp: Input disparity image. ``CV_8U`` and ``CV_16S`` types are supported. - - :param xyzw: Output 3- or 4-channel floating-point image of the same size as ``disp`` . Each element of ``xyzw(x,y)`` contains 3D coordinates ``(x,y,z)`` or ``(x,y,z,1)`` of the point ``(x,y)`` , computed from the disparity map. - - :param Q: :math:`4 \times 4` perspective transformation matrix that can be obtained via :ocv:func:`stereoRectify` . - - :param dst_cn: The number of channels for output image. Can be 3 or 4. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`reprojectImageTo3D` - - - -gpu::solvePnPRansac -------------------- -Finds the object pose from 3D-2D point correspondences. - -.. ocv:function:: void gpu::solvePnPRansac(const Mat& object, const Mat& image, const Mat& camera_mat, const Mat& dist_coef, Mat& rvec, Mat& tvec, bool use_extrinsic_guess=false, int num_iters=100, float max_dist=8.0, int min_inlier_count=100, vector* inliers=NULL) - - :param object: Single-row matrix of object points. - - :param image: Single-row matrix of image points. - - :param camera_mat: 3x3 matrix of intrinsic camera parameters. - - :param dist_coef: Distortion coefficients. See :ocv:func:`undistortPoints` for details. - - :param rvec: Output 3D rotation vector. - - :param tvec: Output 3D translation vector. - - :param use_extrinsic_guess: Flag to indicate that the function must use ``rvec`` and ``tvec`` as an initial transformation guess. It is not supported for now. - - :param num_iters: Maximum number of RANSAC iterations. - - :param max_dist: Euclidean distance threshold to detect whether point is inlier or not. - - :param min_inlier_count: Flag to indicate that the function must stop if greater or equal number of inliers is achieved. It is not supported for now. - - :param inliers: Output vector of inlier indices. - -.. seealso:: :ocv:func:`solvePnPRansac` - - - -.. [Felzenszwalb2006] Pedro F. Felzenszwalb algorithm [Pedro F. Felzenszwalb and Daniel P. Huttenlocher. *Efficient belief propagation for early vision*. International Journal of Computer Vision, 70(1), October 2006 - -.. [Yang2010] Q. Yang, L. Wang, and N. Ahuja. *A constant-space belief propagation algorithm for stereo matching*. In CVPR, 2010. diff --git a/modules/gpu/doc/data_structures.rst b/modules/gpu/doc/data_structures.rst index 5699723203..2a21710356 100644 --- a/modules/gpu/doc/data_structures.rst +++ b/modules/gpu/doc/data_structures.rst @@ -6,32 +6,22 @@ Data Structures gpu::PtrStepSz ---------------- +-------------- .. ocv:class:: gpu::PtrStepSz Lightweight class encapsulating pitched memory on a GPU and passed to nvcc-compiled code (CUDA kernels). Typically, it is used internally by OpenCV and by users who write device code. You can call its members from both host and device code. :: - template struct PtrStepSz + template struct PtrStepSz : public PtrStep { - int cols; - int rows; - T* data; - size_t step; - - PtrStepSz() : cols(0), rows(0), data(0), step(0){}; - PtrStepSz(int rows, int cols, T *data, size_t step); + __CV_GPU_HOST_DEVICE__ PtrStepSz() : cols(0), rows(0) {} + __CV_GPU_HOST_DEVICE__ PtrStepSz(int rows_, int cols_, T* data_, size_t step_) + : PtrStep(data_, step_), cols(cols_), rows(rows_) {} template - explicit PtrStepSz(const PtrStepSz& d); + explicit PtrStepSz(const PtrStepSz& d) : PtrStep((T*)d.data, d.step), cols(d.cols), rows(d.rows){} - typedef T elem_type; - enum { elem_size = sizeof(elem_type) }; - - __CV_GPU_HOST_DEVICE__ size_t elemSize() const; - - /* returns pointer to the beginning of the given image row */ - __CV_GPU_HOST_DEVICE__ T* ptr(int y = 0); - __CV_GPU_HOST_DEVICE__ const T* ptr(int y = 0) const; + int cols; + int rows; }; typedef PtrStepSz PtrStepSzb; @@ -41,32 +31,32 @@ Lightweight class encapsulating pitched memory on a GPU and passed to nvcc-compi gpu::PtrStep --------------- +------------ .. ocv:class:: gpu::PtrStep Structure similar to :ocv:class:`gpu::PtrStepSz` but containing only a pointer and row step. Width and height fields are excluded due to performance reasons. The structure is intended for internal use or for users who write device code. :: - template struct PtrStep + template struct PtrStep : public DevPtr { - T* data; - size_t step; + __CV_GPU_HOST_DEVICE__ PtrStep() : step(0) {} + __CV_GPU_HOST_DEVICE__ PtrStep(T* data_, size_t step_) : DevPtr(data_), step(step_) {} - PtrStep(); - PtrStep(const PtrStepSz& mem); + //! stride between two consecutive rows in bytes. Step is stored always and everywhere in bytes!!! + size_t step; - typedef T elem_type; - enum { elem_size = sizeof(elem_type) }; + __CV_GPU_HOST_DEVICE__ T* ptr(int y = 0) { return ( T*)( ( char*)DevPtr::data + y * step); } + __CV_GPU_HOST_DEVICE__ const T* ptr(int y = 0) const { return (const T*)( (const char*)DevPtr::data + y * step); } - __CV_GPU_HOST_DEVICE__ size_t elemSize() const; - __CV_GPU_HOST_DEVICE__ T* ptr(int y = 0); - __CV_GPU_HOST_DEVICE__ const T* ptr(int y = 0) const; + __CV_GPU_HOST_DEVICE__ T& operator ()(int y, int x) { return ptr(y)[x]; } + __CV_GPU_HOST_DEVICE__ const T& operator ()(int y, int x) const { return ptr(y)[x]; } }; - typedef PtrStep PtrStep; + typedef PtrStep PtrStepb; typedef PtrStep PtrStepf; typedef PtrStep PtrStepi; + gpu::GpuMat ----------- .. ocv:class:: gpu::GpuMat @@ -89,28 +79,31 @@ Beware that the latter limitation may lead to overloaded matrix operators that c //! default constructor GpuMat(); + //! constructs GpuMat of the specified size and type GpuMat(int rows, int cols, int type); GpuMat(Size size, int type); ..... - //! builds GpuMat from Mat. Blocks uploading to device. - explicit GpuMat (const Mat& m); + //! builds GpuMat from host memory (Blocking call) + explicit GpuMat(InputArray arr); //! returns lightweight PtrStepSz structure for passing //to nvcc-compiled code. Contains size, data ptr and step. template operator PtrStepSz() const; template operator PtrStep() const; - //! blocks uploading data to GpuMat. - void upload(const cv::Mat& m); - void upload(const CudaMem& m, Stream& stream); + //! pefroms upload data to GpuMat (Blocking call) + void upload(InputArray arr); - //! downloads data from device to host memory. Blocking calls. - void download(cv::Mat& m) const; + //! pefroms upload data to GpuMat (Non-Blocking call) + void upload(InputArray arr, Stream& stream); - //! download async - void download(CudaMem& m, Stream& stream) const; + //! pefroms download data from device to host memory (Blocking call) + void download(OutputArray dst) const; + + //! pefroms download data from device to host memory (Non-Blocking call) + void download(OutputArray dst, Stream& stream) const; }; @@ -121,16 +114,10 @@ Beware that the latter limitation may lead to overloaded matrix operators that c gpu::createContinuous -------------------------- -Creates a continuous matrix in the GPU memory. +--------------------- +Creates a continuous matrix. -.. ocv:function:: void gpu::createContinuous(int rows, int cols, int type, GpuMat& m) - -.. ocv:function:: GpuMat gpu::createContinuous(int rows, int cols, int type) - -.. ocv:function:: void gpu::createContinuous(Size size, int type, GpuMat& m) - -.. ocv:function:: GpuMat gpu::createContinuous(Size size, int type) +.. ocv:function:: void gpu::createContinuous(int rows, int cols, int type, OutputArray arr) :param rows: Row count. @@ -138,36 +125,92 @@ Creates a continuous matrix in the GPU memory. :param type: Type of the matrix. - :param m: Destination matrix. This parameter changes only if it has a proper type and area ( :math:`\texttt{rows} \times \texttt{cols}` ). + :param arr: Destination matrix. This parameter changes only if it has a proper type and area ( :math:`\texttt{rows} \times \texttt{cols}` ). Matrix is called continuous if its elements are stored continuously, that is, without gaps at the end of each row. gpu::ensureSizeIsEnough ---------------------------- +----------------------- Ensures that the size of a matrix is big enough and the matrix has a proper type. -.. ocv:function:: void gpu::ensureSizeIsEnough(int rows, int cols, int type, GpuMat& m) - -.. ocv:function:: void gpu::ensureSizeIsEnough(Size size, int type, GpuMat& m) +.. ocv:function:: void gpu::ensureSizeIsEnough(int rows, int cols, int type, OutputArray arr) :param rows: Minimum desired number of rows. :param cols: Minimum desired number of columns. - :param size: Rows and columns passed as a structure. - :param type: Desired matrix type. - :param m: Destination matrix. + :param arr: Destination matrix. The function does not reallocate memory if the matrix has proper attributes already. +gpu::CudaMem +------------ +.. ocv:class:: gpu::CudaMem + +Class with reference counting wrapping special memory type allocation functions from CUDA. Its interface is also :ocv:func:`Mat`-like but with additional memory type parameters. + +* **PAGE_LOCKED** sets a page locked memory type used commonly for fast and asynchronous uploading/downloading data from/to GPU. +* **SHARED** specifies a zero copy memory allocation that enables mapping the host memory to GPU address space, if supported. +* **WRITE_COMBINED** sets the write combined buffer that is not cached by CPU. Such buffers are used to supply GPU with data when GPU only reads it. The advantage is a better CPU cache utilization. + +.. note:: Allocation size of such memory types is usually limited. For more details, see *CUDA 2.2 Pinned Memory APIs* document or *CUDA C Programming Guide*. + +:: + + class CV_EXPORTS CudaMem + { + public: + enum AllocType { PAGE_LOCKED = 1, SHARED = 2, WRITE_COMBINED = 4 }; + + explicit CudaMem(AllocType alloc_type = PAGE_LOCKED); + + CudaMem(int rows, int cols, int type, AllocType alloc_type = PAGE_LOCKED); + CudaMem(Size size, int type, AllocType alloc_type = PAGE_LOCKED); + + //! creates from host memory with coping data + explicit CudaMem(InputArray arr, AllocType alloc_type = PAGE_LOCKED); + + ...... + + //! returns matrix header with disabled reference counting for CudaMem data. + Mat createMatHeader() const; + + //! maps host memory into device address space and returns GpuMat header for it. Throws exception if not supported by hardware. + GpuMat createGpuMatHeader() const; + + ...... + + AllocType alloc_type; + }; + + + +gpu::CudaMem::createMatHeader +----------------------------- +Creates a header without reference counting to :ocv:class:`gpu::CudaMem` data. + +.. ocv:function:: Mat gpu::CudaMem::createMatHeader() const + + + +gpu::CudaMem::createGpuMatHeader +-------------------------------- +Maps CPU memory to GPU address space and creates the :ocv:class:`gpu::GpuMat` header without reference counting for it. + +.. ocv:function:: GpuMat gpu::CudaMem::createGpuMatHeader() const + +This can be done only if memory was allocated with the ``SHARED`` flag and if it is supported by the hardware. Laptops often share video and CPU memory, so address spaces can be mapped, which eliminates an extra copy. + + + gpu::registerPageLocked -------------------------------- +----------------------- Page-locks the memory of matrix and maps it for the device(s). .. ocv:function:: void gpu::registerPageLocked(Mat& m) @@ -177,7 +220,7 @@ Page-locks the memory of matrix and maps it for the device(s). gpu::unregisterPageLocked -------------------------------- +------------------------- Unmaps the memory of matrix and makes it pageable again. .. ocv:function:: void gpu::unregisterPageLocked(Mat& m) @@ -186,83 +229,11 @@ Unmaps the memory of matrix and makes it pageable again. -gpu::CudaMem ------------- -.. ocv:class:: gpu::CudaMem - -Class with reference counting wrapping special memory type allocation functions from CUDA. Its interface is also -:ocv:func:`Mat`-like but with additional memory type parameters. - -* **ALLOC_PAGE_LOCKED** sets a page locked memory type used commonly for fast and asynchronous uploading/downloading data from/to GPU. -* **ALLOC_ZEROCOPY** specifies a zero copy memory allocation that enables mapping the host memory to GPU address space, if supported. -* **ALLOC_WRITE_COMBINED** sets the write combined buffer that is not cached by CPU. Such buffers are used to supply GPU with data when GPU only reads it. The advantage is a better CPU cache utilization. - -.. note:: Allocation size of such memory types is usually limited. For more details, see *CUDA 2.2 Pinned Memory APIs* document or *CUDA C Programming Guide*. - -:: - - class CV_EXPORTS CudaMem - { - public: - enum { ALLOC_PAGE_LOCKED = 1, ALLOC_ZEROCOPY = 2, - ALLOC_WRITE_COMBINED = 4 }; - - CudaMem(Size size, int type, int alloc_type = ALLOC_PAGE_LOCKED); - - //! creates from cv::Mat with coping data - explicit CudaMem(const Mat& m, int alloc_type = ALLOC_PAGE_LOCKED); - - ...... - - void create(Size size, int type, int alloc_type = ALLOC_PAGE_LOCKED); - - //! returns matrix header with disabled ref. counting for CudaMem data. - Mat createMatHeader() const; - operator Mat() const; - - //! maps host memory into device address space - GpuMat createGpuMatHeader() const; - operator GpuMat() const; - - //if host memory can be mapped to gpu address space; - static bool canMapHostMemory(); - - int alloc_type; - }; - - - -gpu::CudaMem::createMatHeader ---------------------------------- -Creates a header without reference counting to :ocv:class:`gpu::CudaMem` data. - -.. ocv:function:: Mat gpu::CudaMem::createMatHeader() const - - - -gpu::CudaMem::createGpuMatHeader ------------------------------------- -Maps CPU memory to GPU address space and creates the :ocv:class:`gpu::GpuMat` header without reference counting for it. - -.. ocv:function:: GpuMat gpu::CudaMem::createGpuMatHeader() const - -This can be done only if memory was allocated with the ``ALLOC_ZEROCOPY`` flag and if it is supported by the hardware. Laptops often share video and CPU memory, so address spaces can be mapped, which eliminates an extra copy. - - - -gpu::CudaMem::canMapHostMemory ----------------------------------- -Returns ``true`` if the current hardware supports address space mapping and ``ALLOC_ZEROCOPY`` memory allocation. - -.. ocv:function:: static bool gpu::CudaMem::canMapHostMemory() - - - gpu::Stream ----------- .. ocv:class:: gpu::Stream -This class encapsulates a queue of asynchronous calls. Some functions have overloads with the additional ``gpu::Stream`` parameter. The overloads do initialization work (allocate output buffers, upload constants, and so on), start the GPU kernel, and return before results are ready. You can check whether all operations are complete via :ocv:func:`gpu::Stream::queryIfComplete`. You can asynchronously upload/download data from/to page-locked buffers, using the :ocv:class:`gpu::CudaMem` or :ocv:class:`Mat` header that points to a region of :ocv:class:`gpu::CudaMem`. +This class encapsulates a queue of asynchronous calls. .. note:: Currently, you may face problems if an operation is enqueued twice with different data. Some functions use the constant GPU memory, and next call may update the memory before the previous one has been finished. But calling different operations asynchronously is safe because each operation has its own constant buffer. Memory copy/upload/download/set operations to the buffers you hold are also safe. @@ -272,30 +243,24 @@ This class encapsulates a queue of asynchronous calls. Some functions have overl { public: Stream(); - ~Stream(); - Stream(const Stream&); - Stream& operator=(const Stream&); + //! queries an asynchronous stream for completion status + bool queryIfComplete() const; - bool queryIfComplete(); + //! waits for stream tasks to complete void waitForCompletion(); - void enqueueDownload(const GpuMat& src, CudaMem& dst); - void enqueueDownload(const GpuMat& src, Mat& dst); + //! makes a compute stream wait on an event + void waitEvent(const Event& event); - void enqueueUpload(const CudaMem& src, GpuMat& dst); - void enqueueUpload(const Mat& src, GpuMat& dst); - - void enqueueCopy(const GpuMat& src, GpuMat& dst); - - void enqueueMemSet(const GpuMat& src, Scalar val); - void enqueueMemSet(const GpuMat& src, Scalar val, const GpuMat& mask); - - void enqueueConvert(const GpuMat& src, GpuMat& dst, int type, - double a = 1, double b = 0); - - typedef void (*StreamCallback)(Stream& stream, int status, void* userData); + //! adds a callback to be called on the host after all currently enqueued items in the stream have completed void enqueueHostCallback(StreamCallback callback, void* userData); + + //! return Stream object for default CUDA stream + static Stream& Null(); + + //! returns true if stream object is not default (!= 0) + operator bool_type() const; }; @@ -316,53 +281,11 @@ Blocks the current CPU thread until all operations in the stream are complete. -gpu::Stream::enqueueDownload ----------------------------- -Copies data from device to host. +gpu::Stream::waitEvent +---------------------- +Makes a compute stream wait on an event. -.. ocv:function:: void gpu::Stream::enqueueDownload(const GpuMat& src, CudaMem& dst) - -.. ocv:function:: void gpu::Stream::enqueueDownload(const GpuMat& src, Mat& dst) - -.. note:: ``cv::Mat`` must point to page locked memory (i.e. to ``CudaMem`` data or to its subMat) or must be registered with :ocv:func:`gpu::registerPageLocked` . - - - -gpu::Stream::enqueueUpload --------------------------- -Copies data from host to device. - -.. ocv:function:: void gpu::Stream::enqueueUpload(const CudaMem& src, GpuMat& dst) - -.. ocv:function:: void gpu::Stream::enqueueUpload(const Mat& src, GpuMat& dst) - -.. note:: ``cv::Mat`` must point to page locked memory (i.e. to ``CudaMem`` data or to its subMat) or must be registered with :ocv:func:`gpu::registerPageLocked` . - - - -gpu::Stream::enqueueCopy ------------------------- -Copies data from device to device. - -.. ocv:function:: void gpu::Stream::enqueueCopy(const GpuMat& src, GpuMat& dst) - - - -gpu::Stream::enqueueMemSet --------------------------- -Initializes or sets device memory to a value. - -.. ocv:function:: void gpu::Stream::enqueueMemSet( GpuMat& src, Scalar val ) - -.. ocv:function:: void gpu::Stream::enqueueMemSet( GpuMat& src, Scalar val, const GpuMat& mask ) - - - -gpu::Stream::enqueueConvert ---------------------------- -Converts matrix type, ex from float to uchar depending on type. - -.. ocv:function:: void gpu::Stream::enqueueConvert( const GpuMat& src, GpuMat& dst, int dtype, double a=1, double b=0 ) +.. ocv:function:: void gpu::Stream::waitEvent(const Event& event) @@ -386,4 +309,3 @@ Class that enables getting ``cudaStream_t`` from :ocv:class:`gpu::Stream` and is { CV_EXPORTS static cudaStream_t getStream(const Stream& stream); }; - diff --git a/modules/gpu/doc/gpu.rst b/modules/gpu/doc/gpu.rst index b21e2abac8..2a0358e017 100644 --- a/modules/gpu/doc/gpu.rst +++ b/modules/gpu/doc/gpu.rst @@ -8,12 +8,5 @@ gpu. GPU-accelerated Computer Vision introduction initalization_and_information data_structures - operations_on_matrices - per_element_operations - image_processing - matrix_reductions object_detection - feature_detection_and_description - image_filtering - camera_calibration_and_3d_reconstruction - video + calib3d diff --git a/modules/gpu/doc/image_filtering.rst b/modules/gpu/doc/image_filtering.rst deleted file mode 100644 index 348a42510e..0000000000 --- a/modules/gpu/doc/image_filtering.rst +++ /dev/null @@ -1,719 +0,0 @@ -Image Filtering -=============== - -.. highlight:: cpp - -Functions and classes described in this section are used to perform various linear or non-linear filtering operations on 2D images. - - - -gpu::BaseRowFilter_GPU ----------------------- -.. ocv:class:: gpu::BaseRowFilter_GPU - -Base class for linear or non-linear filters that processes rows of 2D arrays. Such filters are used for the "horizontal" filtering passes in separable filters. :: - - class BaseRowFilter_GPU - { - public: - BaseRowFilter_GPU(int ksize_, int anchor_); - virtual ~BaseRowFilter_GPU() {} - virtual void operator()(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()) = 0; - int ksize, anchor; - }; - - -.. note:: This class does not allocate memory for a destination image. Usually this class is used inside :ocv:class:`gpu::FilterEngine_GPU`. - - - -gpu::BaseColumnFilter_GPU -------------------------- -.. ocv:class:: gpu::BaseColumnFilter_GPU - -Base class for linear or non-linear filters that processes columns of 2D arrays. Such filters are used for the "vertical" filtering passes in separable filters. :: - - class BaseColumnFilter_GPU - { - public: - BaseColumnFilter_GPU(int ksize_, int anchor_); - virtual ~BaseColumnFilter_GPU() {} - virtual void operator()(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()) = 0; - int ksize, anchor; - }; - - -.. note:: This class does not allocate memory for a destination image. Usually this class is used inside :ocv:class:`gpu::FilterEngine_GPU`. - - - -gpu::BaseFilter_GPU -------------------- -.. ocv:class:: gpu::BaseFilter_GPU - -Base class for non-separable 2D filters. :: - - class CV_EXPORTS BaseFilter_GPU - { - public: - BaseFilter_GPU(const Size& ksize_, const Point& anchor_); - virtual ~BaseFilter_GPU() {} - virtual void operator()(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()) = 0; - Size ksize; - Point anchor; - }; - - -.. note:: This class does not allocate memory for a destination image. Usually this class is used inside :ocv:class:`gpu::FilterEngine_GPU`. - - - -gpu::FilterEngine_GPU ---------------------- -.. ocv:class:: gpu::FilterEngine_GPU - -Base class for the Filter Engine. :: - - class CV_EXPORTS FilterEngine_GPU - { - public: - virtual ~FilterEngine_GPU() {} - - virtual void apply(const GpuMat& src, GpuMat& dst, - Rect roi = Rect(0,0,-1,-1), Stream& stream = Stream::Null()) = 0; - }; - - -The class can be used to apply an arbitrary filtering operation to an image. It contains all the necessary intermediate buffers. Pointers to the initialized ``FilterEngine_GPU`` instances are returned by various ``create*Filter_GPU`` functions (see below), and they are used inside high-level functions such as :ocv:func:`gpu::filter2D`, :ocv:func:`gpu::erode`, :ocv:func:`gpu::Sobel` , and others. - -By using ``FilterEngine_GPU`` instead of functions you can avoid unnecessary memory allocation for intermediate buffers and get better performance: :: - - while (...) - { - gpu::GpuMat src = getImg(); - gpu::GpuMat dst; - // Allocate and release buffers at each iterations - gpu::GaussianBlur(src, dst, ksize, sigma1); - } - - // Allocate buffers only once - cv::Ptr filter = - gpu::createGaussianFilter_GPU(CV_8UC4, ksize, sigma1); - while (...) - { - gpu::GpuMat src = getImg(); - gpu::GpuMat dst; - filter->apply(src, dst, cv::Rect(0, 0, src.cols, src.rows)); - } - // Release buffers only once - filter.release(); - - -``FilterEngine_GPU`` can process a rectangular sub-region of an image. By default, if ``roi == Rect(0,0,-1,-1)`` , ``FilterEngine_GPU`` processes the inner region of an image ( ``Rect(anchor.x, anchor.y, src_size.width - ksize.width, src_size.height - ksize.height)`` ) because some filters do not check whether indices are outside the image for better performance. See below to understand which filters support processing the whole image and which do not and identify image type limitations. - -.. note:: The GPU filters do not support the in-place mode. - -.. seealso:: :ocv:class:`gpu::BaseRowFilter_GPU`, :ocv:class:`gpu::BaseColumnFilter_GPU`, :ocv:class:`gpu::BaseFilter_GPU`, :ocv:func:`gpu::createFilter2D_GPU`, :ocv:func:`gpu::createSeparableFilter_GPU`, :ocv:func:`gpu::createBoxFilter_GPU`, :ocv:func:`gpu::createMorphologyFilter_GPU`, :ocv:func:`gpu::createLinearFilter_GPU`, :ocv:func:`gpu::createSeparableLinearFilter_GPU`, :ocv:func:`gpu::createDerivFilter_GPU`, :ocv:func:`gpu::createGaussianFilter_GPU` - - - -gpu::createFilter2D_GPU ---------------------------- -Creates a non-separable filter engine with the specified filter. - -.. ocv:function:: Ptr gpu::createFilter2D_GPU( const Ptr& filter2D, int srcType, int dstType) - - :param filter2D: Non-separable 2D filter. - - :param srcType: Input image type. It must be supported by ``filter2D`` . - - :param dstType: Output image type. It must be supported by ``filter2D`` . - -Usually this function is used inside such high-level functions as :ocv:func:`gpu::createLinearFilter_GPU`, :ocv:func:`gpu::createBoxFilter_GPU`. - - - -gpu::createSeparableFilter_GPU ----------------------------------- -Creates a separable filter engine with the specified filters. - -.. ocv:function:: Ptr gpu::createSeparableFilter_GPU( const Ptr& rowFilter, const Ptr& columnFilter, int srcType, int bufType, int dstType) - - :param rowFilter: "Horizontal" 1D filter. - - :param columnFilter: "Vertical" 1D filter. - - :param srcType: Input image type. It must be supported by ``rowFilter`` . - - :param bufType: Buffer image type. It must be supported by ``rowFilter`` and ``columnFilter`` . - - :param dstType: Output image type. It must be supported by ``columnFilter`` . - -Usually this function is used inside such high-level functions as :ocv:func:`gpu::createSeparableLinearFilter_GPU`. - - - -gpu::getRowSumFilter_GPU ----------------------------- -Creates a horizontal 1D box filter. - -.. ocv:function:: Ptr gpu::getRowSumFilter_GPU(int srcType, int sumType, int ksize, int anchor = -1) - - :param srcType: Input image type. Only ``CV_8UC1`` type is supported for now. - - :param sumType: Output image type. Only ``CV_32FC1`` type is supported for now. - - :param ksize: Kernel size. - - :param anchor: Anchor point. The default value (-1) means that the anchor is at the kernel center. - -.. note:: This filter does not check out-of-border accesses, so only a proper sub-matrix of a bigger matrix has to be passed to it. - - - -gpu::getColumnSumFilter_GPU -------------------------------- -Creates a vertical 1D box filter. - -.. ocv:function:: Ptr gpu::getColumnSumFilter_GPU(int sumType, int dstType, int ksize, int anchor = -1) - - :param sumType: Input image type. Only ``CV_8UC1`` type is supported for now. - - :param dstType: Output image type. Only ``CV_32FC1`` type is supported for now. - - :param ksize: Kernel size. - - :param anchor: Anchor point. The default value (-1) means that the anchor is at the kernel center. - -.. note:: This filter does not check out-of-border accesses, so only a proper sub-matrix of a bigger matrix has to be passed to it. - - - -gpu::createBoxFilter_GPU ----------------------------- -Creates a normalized 2D box filter. - -.. ocv:function:: Ptr gpu::createBoxFilter_GPU(int srcType, int dstType, const Size& ksize, const Point& anchor = Point(-1,-1)) - -.. ocv:function:: Ptr gpu::getBoxFilter_GPU(int srcType, int dstType, const Size& ksize, Point anchor = Point(-1, -1)) - - :param srcType: Input image type supporting ``CV_8UC1`` and ``CV_8UC4`` . - - :param dstType: Output image type. It supports only the same values as the source type. - - :param ksize: Kernel size. - - :param anchor: Anchor point. The default value ``Point(-1, -1)`` means that the anchor is at the kernel center. - -.. note:: This filter does not check out-of-border accesses, so only a proper sub-matrix of a bigger matrix has to be passed to it. - -.. seealso:: :ocv:func:`boxFilter` - - - -gpu::boxFilter ------------------- -Smooths the image using the normalized box filter. - -.. ocv:function:: void gpu::boxFilter(const GpuMat& src, GpuMat& dst, int ddepth, Size ksize, Point anchor = Point(-1,-1), Stream& stream = Stream::Null()) - - :param src: Input image. ``CV_8UC1`` and ``CV_8UC4`` source types are supported. - - :param dst: Output image type. The size and type is the same as ``src`` . - - :param ddepth: Output image depth. If -1, the output image has the same depth as the input one. The only values allowed here are ``CV_8U`` and -1. - - :param ksize: Kernel size. - - :param anchor: Anchor point. The default value ``Point(-1, -1)`` means that the anchor is at the kernel center. - - :param stream: Stream for the asynchronous version. - -.. note:: This filter does not check out-of-border accesses, so only a proper sub-matrix of a bigger matrix has to be passed to it. - -.. seealso:: :ocv:func:`boxFilter` - - - -gpu::blur -------------- -Acts as a synonym for the normalized box filter. - -.. ocv:function:: void gpu::blur(const GpuMat& src, GpuMat& dst, Size ksize, Point anchor = Point(-1,-1), Stream& stream = Stream::Null()) - - :param src: Input image. ``CV_8UC1`` and ``CV_8UC4`` source types are supported. - - :param dst: Output image type with the same size and type as ``src`` . - - :param ksize: Kernel size. - - :param anchor: Anchor point. The default value Point(-1, -1) means that the anchor is at the kernel center. - - :param stream: Stream for the asynchronous version. - -.. note:: This filter does not check out-of-border accesses, so only a proper sub-matrix of a bigger matrix has to be passed to it. - -.. seealso:: :ocv:func:`blur`, :ocv:func:`gpu::boxFilter` - - - -gpu::createMorphologyFilter_GPU ------------------------------------ -Creates a 2D morphological filter. - -.. ocv:function:: Ptr gpu::createMorphologyFilter_GPU(int op, int type, const Mat& kernel, const Point& anchor = Point(-1,-1), int iterations = 1) - -.. ocv:function:: Ptr gpu::getMorphologyFilter_GPU(int op, int type, const Mat& kernel, const Size& ksize, Point anchor=Point(-1,-1)) - - :param op: Morphology operation id. Only ``MORPH_ERODE`` and ``MORPH_DILATE`` are supported. - - :param type: Input/output image type. Only ``CV_8UC1`` and ``CV_8UC4`` are supported. - - :param kernel: 2D 8-bit structuring element for the morphological operation. - - :param ksize: Size of a horizontal or vertical structuring element used for separable morphological operations. - - :param anchor: Anchor position within the structuring element. Negative values mean that the anchor is at the center. - -.. note:: This filter does not check out-of-border accesses, so only a proper sub-matrix of a bigger matrix has to be passed to it. - -.. seealso:: :ocv:func:`createMorphologyFilter` - - - -gpu::erode --------------- -Erodes an image by using a specific structuring element. - -.. ocv:function:: void gpu::erode( const GpuMat& src, GpuMat& dst, const Mat& kernel, Point anchor=Point(-1, -1), int iterations=1 ) - -.. ocv:function:: void gpu::erode( const GpuMat& src, GpuMat& dst, const Mat& kernel, GpuMat& buf, Point anchor=Point(-1, -1), int iterations=1, Stream& stream=Stream::Null() ) - - :param src: Source image. Only ``CV_8UC1`` and ``CV_8UC4`` types are supported. - - :param dst: Destination image with the same size and type as ``src`` . - - :param kernel: Structuring element used for erosion. If ``kernel=Mat()``, a 3x3 rectangular structuring element is used. - - :param anchor: Position of an anchor within the element. The default value ``(-1, -1)`` means that the anchor is at the element center. - - :param iterations: Number of times erosion to be applied. - - :param stream: Stream for the asynchronous version. - -.. note:: This filter does not check out-of-border accesses, so only a proper sub-matrix of a bigger matrix has to be passed to it. - -.. seealso:: :ocv:func:`erode` - - - -gpu::dilate ---------------- -Dilates an image by using a specific structuring element. - -.. ocv:function:: void gpu::dilate( const GpuMat& src, GpuMat& dst, const Mat& kernel, Point anchor=Point(-1, -1), int iterations=1 ) - -.. ocv:function:: void gpu::dilate( const GpuMat& src, GpuMat& dst, const Mat& kernel, GpuMat& buf, Point anchor=Point(-1, -1), int iterations=1, Stream& stream=Stream::Null() ) - - :param src: Source image. ``CV_8UC1`` and ``CV_8UC4`` source types are supported. - - :param dst: Destination image with the same size and type as ``src``. - - :param kernel: Structuring element used for dilation. If ``kernel=Mat()``, a 3x3 rectangular structuring element is used. - - :param anchor: Position of an anchor within the element. The default value ``(-1, -1)`` means that the anchor is at the element center. - - :param iterations: Number of times dilation to be applied. - - :param stream: Stream for the asynchronous version. - -.. note:: This filter does not check out-of-border accesses, so only a proper sub-matrix of a bigger matrix has to be passed to it. - -.. seealso:: :ocv:func:`dilate` - - - -gpu::morphologyEx ---------------------- -Applies an advanced morphological operation to an image. - -.. ocv:function:: void gpu::morphologyEx( const GpuMat& src, GpuMat& dst, int op, const Mat& kernel, Point anchor=Point(-1, -1), int iterations=1 ) - -.. ocv:function:: void gpu::morphologyEx( const GpuMat& src, GpuMat& dst, int op, const Mat& kernel, GpuMat& buf1, GpuMat& buf2, Point anchor=Point(-1, -1), int iterations=1, Stream& stream=Stream::Null() ) - - :param src: Source image. ``CV_8UC1`` and ``CV_8UC4`` source types are supported. - - :param dst: Destination image with the same size and type as ``src`` . - - :param op: Type of morphological operation. The following types are possible: - - * **MORPH_OPEN** opening - - * **MORPH_CLOSE** closing - - * **MORPH_GRADIENT** morphological gradient - - * **MORPH_TOPHAT** "top hat" - - * **MORPH_BLACKHAT** "black hat" - - :param kernel: Structuring element. - - :param anchor: Position of an anchor within the element. The default value ``Point(-1, -1)`` means that the anchor is at the element center. - - :param iterations: Number of times erosion and dilation to be applied. - - :param stream: Stream for the asynchronous version. - -.. note:: This filter does not check out-of-border accesses, so only a proper sub-matrix of a bigger matrix has to be passed to it. - -.. seealso:: :ocv:func:`morphologyEx` - - - -gpu::createLinearFilter_GPU -------------------------------- -Creates a non-separable linear filter. - -.. ocv:function:: Ptr gpu::createLinearFilter_GPU(int srcType, int dstType, const Mat& kernel, Point anchor = Point(-1,-1), int borderType = BORDER_DEFAULT) - - :param srcType: Input image type. Supports ``CV_8U`` , ``CV_16U`` and ``CV_32F`` one and four channel image. - - :param dstType: Output image type. The same type as ``src`` is supported. - - :param kernel: 2D array of filter coefficients. Floating-point coefficients will be converted to fixed-point representation before the actual processing. Supports size up to 16. For larger kernels use :ocv:func:`gpu::convolve`. - - :param anchor: Anchor point. The default value Point(-1, -1) means that the anchor is at the kernel center. - - :param borderType: Pixel extrapolation method. For details, see :ocv:func:`borderInterpolate` . - -.. seealso:: :ocv:func:`createLinearFilter` - - - -gpu::filter2D ------------------ -Applies the non-separable 2D linear filter to an image. - -.. ocv:function:: void gpu::filter2D(const GpuMat& src, GpuMat& dst, int ddepth, const Mat& kernel, Point anchor=Point(-1,-1), int borderType = BORDER_DEFAULT, Stream& stream = Stream::Null()) - - :param src: Source image. Supports ``CV_8U`` , ``CV_16U`` and ``CV_32F`` one and four channel image. - - :param dst: Destination image. The size and the number of channels is the same as ``src`` . - - :param ddepth: Desired depth of the destination image. If it is negative, it is the same as ``src.depth()`` . It supports only the same depth as the source image depth. - - :param kernel: 2D array of filter coefficients. - - :param anchor: Anchor of the kernel that indicates the relative position of a filtered point within the kernel. The anchor resides within the kernel. The special default value (-1,-1) means that the anchor is at the kernel center. - - :param borderType: Pixel extrapolation method. For details, see :ocv:func:`borderInterpolate` . - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`filter2D`, :ocv:func:`gpu::convolve` - - - -gpu::Laplacian ------------------- -Applies the Laplacian operator to an image. - -.. ocv:function:: void gpu::Laplacian(const GpuMat& src, GpuMat& dst, int ddepth, int ksize = 1, double scale = 1, int borderType = BORDER_DEFAULT, Stream& stream = Stream::Null()) - - :param src: Source image. ``CV_8UC1`` and ``CV_8UC4`` source types are supported. - - :param dst: Destination image. The size and number of channels is the same as ``src`` . - - :param ddepth: Desired depth of the destination image. It supports only the same depth as the source image depth. - - :param ksize: Aperture size used to compute the second-derivative filters (see :ocv:func:`getDerivKernels`). It must be positive and odd. Only ``ksize`` = 1 and ``ksize`` = 3 are supported. - - :param scale: Optional scale factor for the computed Laplacian values. By default, no scaling is applied (see :ocv:func:`getDerivKernels` ). - - :param borderType: Pixel extrapolation method. For details, see :ocv:func:`borderInterpolate` . - - :param stream: Stream for the asynchronous version. - -.. note:: This filter does not check out-of-border accesses, so only a proper sub-matrix of a bigger matrix has to be passed to it. - -.. seealso:: :ocv:func:`Laplacian`, :ocv:func:`gpu::filter2D` - - - -gpu::getLinearRowFilter_GPU -------------------------------- -Creates a primitive row filter with the specified kernel. - -.. ocv:function:: Ptr gpu::getLinearRowFilter_GPU( int srcType, int bufType, const Mat& rowKernel, int anchor=-1, int borderType=BORDER_DEFAULT ) - - :param srcType: Source array type. Only ``CV_8UC1`` , ``CV_8UC4`` , ``CV_16SC1`` , ``CV_16SC2`` , ``CV_16SC3`` , ``CV_32SC1`` , ``CV_32FC1`` source types are supported. - - :param bufType: Intermediate buffer type with as many channels as ``srcType`` . - - :param rowKernel: Filter coefficients. Support kernels with ``size <= 16`` . - - :param anchor: Anchor position within the kernel. Negative values mean that the anchor is positioned at the aperture center. - - :param borderType: Pixel extrapolation method. For details, see :ocv:func:`borderInterpolate`. For details on limitations, see below. - -There are two versions of the algorithm: NPP and OpenCV. - - * NPP version is called when ``srcType == CV_8UC1`` or ``srcType == CV_8UC4`` and ``bufType == srcType`` . Otherwise, the OpenCV version is called. NPP supports only ``BORDER_CONSTANT`` border type and does not check indices outside the image. - - * OpenCV version supports only ``CV_32F`` buffer depth and ``BORDER_REFLECT101`` , ``BORDER_REPLICATE`` , and ``BORDER_CONSTANT`` border types. It checks indices outside the image. - -.. seealso:: :ocv:func:`createSeparableLinearFilter` . - - - -gpu::getLinearColumnFilter_GPU ----------------------------------- -Creates a primitive column filter with the specified kernel. - -.. ocv:function:: Ptr gpu::getLinearColumnFilter_GPU( int bufType, int dstType, const Mat& columnKernel, int anchor=-1, int borderType=BORDER_DEFAULT ) - - :param bufType: Intermediate buffer type with as many channels as ``dstType`` . - - :param dstType: Destination array type. ``CV_8UC1`` , ``CV_8UC4`` , ``CV_16SC1`` , ``CV_16SC2`` , ``CV_16SC3`` , ``CV_32SC1`` , ``CV_32FC1`` destination types are supported. - - :param columnKernel: Filter coefficients. Support kernels with ``size <= 16`` . - - :param anchor: Anchor position within the kernel. Negative values mean that the anchor is positioned at the aperture center. - - :param borderType: Pixel extrapolation method. For details, see :ocv:func:`borderInterpolate` . For details on limitations, see below. - -There are two versions of the algorithm: NPP and OpenCV. - - * NPP version is called when ``dstType == CV_8UC1`` or ``dstType == CV_8UC4`` and ``bufType == dstType`` . Otherwise, the OpenCV version is called. NPP supports only ``BORDER_CONSTANT`` border type and does not check indices outside the image. - - * OpenCV version supports only ``CV_32F`` buffer depth and ``BORDER_REFLECT101`` , ``BORDER_REPLICATE`` , and ``BORDER_CONSTANT`` border types. It checks indices outside image. - -.. seealso:: :ocv:func:`gpu::getLinearRowFilter_GPU`, :ocv:func:`createSeparableLinearFilter` - - - -gpu::createSeparableLinearFilter_GPU ----------------------------------------- -Creates a separable linear filter engine. - -.. ocv:function:: Ptr gpu::createSeparableLinearFilter_GPU(int srcType, int dstType, const Mat& rowKernel, const Mat& columnKernel, const Point& anchor = Point(-1,-1), int rowBorderType = BORDER_DEFAULT, int columnBorderType = -1) - - :param srcType: Source array type. ``CV_8UC1`` , ``CV_8UC4`` , ``CV_16SC1`` , ``CV_16SC2`` , ``CV_16SC3`` , ``CV_32SC1`` , ``CV_32FC1`` source types are supported. - - :param dstType: Destination array type. ``CV_8UC1`` , ``CV_8UC4`` , ``CV_16SC1`` , ``CV_16SC2`` , ``CV_16SC3`` , ``CV_32SC1`` , ``CV_32FC1`` destination types are supported. - - :param rowKernel: Horizontal filter coefficients. Support kernels with ``size <= 16`` . - - :param columnKernel: Vertical filter coefficients. Support kernels with ``size <= 16`` . - - :param anchor: Anchor position within the kernel. Negative values mean that anchor is positioned at the aperture center. - - :param rowBorderType: Pixel extrapolation method in the vertical direction For details, see :ocv:func:`borderInterpolate`. For details on limitations, see :ocv:func:`gpu::getLinearRowFilter_GPU`, cpp:ocv:func:`gpu::getLinearColumnFilter_GPU`. - - :param columnBorderType: Pixel extrapolation method in the horizontal direction. - -.. seealso:: :ocv:func:`gpu::getLinearRowFilter_GPU`, :ocv:func:`gpu::getLinearColumnFilter_GPU`, :ocv:func:`createSeparableLinearFilter` - - - -gpu::sepFilter2D --------------------- -Applies a separable 2D linear filter to an image. - -.. ocv:function:: void gpu::sepFilter2D( const GpuMat& src, GpuMat& dst, int ddepth, const Mat& kernelX, const Mat& kernelY, Point anchor=Point(-1,-1), int rowBorderType=BORDER_DEFAULT, int columnBorderType=-1 ) - -.. ocv:function:: void gpu::sepFilter2D( const GpuMat& src, GpuMat& dst, int ddepth, const Mat& kernelX, const Mat& kernelY, GpuMat& buf, Point anchor=Point(-1,-1), int rowBorderType=BORDER_DEFAULT, int columnBorderType=-1, Stream& stream=Stream::Null() ) - - - :param src: Source image. ``CV_8UC1`` , ``CV_8UC4`` , ``CV_16SC1`` , ``CV_16SC2`` , ``CV_32SC1`` , ``CV_32FC1`` source types are supported. - - :param dst: Destination image with the same size and number of channels as ``src`` . - - :param ddepth: Destination image depth. ``CV_8U`` , ``CV_16S`` , ``CV_32S`` , and ``CV_32F`` are supported. - - :param kernelX: Horizontal filter coefficients. - - :param kernelY: Vertical filter coefficients. - - :param anchor: Anchor position within the kernel. The default value ``(-1, 1)`` means that the anchor is at the kernel center. - - :param rowBorderType: Pixel extrapolation method in the vertical direction. For details, see :ocv:func:`borderInterpolate`. - - :param columnBorderType: Pixel extrapolation method in the horizontal direction. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`gpu::createSeparableLinearFilter_GPU`, :ocv:func:`sepFilter2D` - - - -gpu::createDerivFilter_GPU ------------------------------- -Creates a filter engine for the generalized Sobel operator. - -.. ocv:function:: Ptr gpu::createDerivFilter_GPU(int srcType, int dstType, int dx, int dy, int ksize, int rowBorderType = BORDER_DEFAULT, int columnBorderType = -1) - - :param srcType: Source image type. ``CV_8UC1`` , ``CV_8UC4`` , ``CV_16SC1`` , ``CV_16SC2`` , ``CV_16SC3`` , ``CV_32SC1`` , ``CV_32FC1`` source types are supported. - - :param dstType: Destination image type with as many channels as ``srcType`` , ``CV_8U`` , ``CV_16S`` , ``CV_32S`` , and ``CV_32F`` depths are supported. - - :param dx: Derivative order in respect of x. - - :param dy: Derivative order in respect of y. - - :param ksize: Aperture size. See :ocv:func:`getDerivKernels` for details. - - :param rowBorderType: Pixel extrapolation method in the vertical direction. For details, see :ocv:func:`borderInterpolate`. - - :param columnBorderType: Pixel extrapolation method in the horizontal direction. - -.. seealso:: :ocv:func:`gpu::createSeparableLinearFilter_GPU`, :ocv:func:`createDerivFilter` - - - -gpu::Sobel --------------- -Applies the generalized Sobel operator to an image. - -.. ocv:function:: void gpu::Sobel( const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy, int ksize=3, double scale=1, int rowBorderType=BORDER_DEFAULT, int columnBorderType=-1 ) - -.. ocv:function:: void gpu::Sobel( const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy, GpuMat& buf, int ksize=3, double scale=1, int rowBorderType=BORDER_DEFAULT, int columnBorderType=-1, Stream& stream=Stream::Null() ) - - :param src: Source image. ``CV_8UC1`` , ``CV_8UC4`` , ``CV_16SC1`` , ``CV_16SC2`` , ``CV_16SC3`` , ``CV_32SC1`` , ``CV_32FC1`` source types are supported. - - :param dst: Destination image with the same size and number of channels as source image. - - :param ddepth: Destination image depth. ``CV_8U`` , ``CV_16S`` , ``CV_32S`` , and ``CV_32F`` are supported. - - :param dx: Derivative order in respect of x. - - :param dy: Derivative order in respect of y. - - :param ksize: Size of the extended Sobel kernel. Possible values are 1, 3, 5 or 7. - - :param scale: Optional scale factor for the computed derivative values. By default, no scaling is applied. For details, see :ocv:func:`getDerivKernels` . - - :param rowBorderType: Pixel extrapolation method in the vertical direction. For details, see :ocv:func:`borderInterpolate`. - - :param columnBorderType: Pixel extrapolation method in the horizontal direction. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`gpu::createSeparableLinearFilter_GPU`, :ocv:func:`Sobel` - - - -gpu::Scharr ---------------- -Calculates the first x- or y- image derivative using the Scharr operator. - -.. ocv:function:: void gpu::Scharr( const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy, double scale=1, int rowBorderType=BORDER_DEFAULT, int columnBorderType=-1 ) - -.. ocv:function:: void gpu::Scharr( const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy, GpuMat& buf, double scale=1, int rowBorderType=BORDER_DEFAULT, int columnBorderType=-1, Stream& stream=Stream::Null() ) - - :param src: Source image. ``CV_8UC1`` , ``CV_8UC4`` , ``CV_16SC1`` , ``CV_16SC2`` , ``CV_16SC3`` , ``CV_32SC1`` , ``CV_32FC1`` source types are supported. - - :param dst: Destination image with the same size and number of channels as ``src`` has. - - :param ddepth: Destination image depth. ``CV_8U`` , ``CV_16S`` , ``CV_32S`` , and ``CV_32F`` are supported. - - :param dx: Order of the derivative x. - - :param dy: Order of the derivative y. - - :param scale: Optional scale factor for the computed derivative values. By default, no scaling is applied. See :ocv:func:`getDerivKernels` for details. - - :param rowBorderType: Pixel extrapolation method in the vertical direction. For details, see :ocv:func:`borderInterpolate`. - - :param columnBorderType: Pixel extrapolation method in the horizontal direction. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`gpu::createSeparableLinearFilter_GPU`, :ocv:func:`Scharr` - - - -gpu::createGaussianFilter_GPU ---------------------------------- -Creates a Gaussian filter engine. - -.. ocv:function:: Ptr gpu::createGaussianFilter_GPU( int type, Size ksize, double sigma1, double sigma2=0, int rowBorderType=BORDER_DEFAULT, int columnBorderType=-1 ) - - :param type: Source and destination image type. ``CV_8UC1`` , ``CV_8UC4`` , ``CV_16SC1`` , ``CV_16SC2`` , ``CV_16SC3`` , ``CV_32SC1`` , ``CV_32FC1`` are supported. - - :param ksize: Aperture size. See :ocv:func:`getGaussianKernel` for details. - - :param sigma1: Gaussian sigma in the horizontal direction. See :ocv:func:`getGaussianKernel` for details. - - :param sigma2: Gaussian sigma in the vertical direction. If 0, then :math:`\texttt{sigma2}\leftarrow\texttt{sigma1}` . - - :param rowBorderType: Pixel extrapolation method in the vertical direction. For details, see :ocv:func:`borderInterpolate`. - - :param columnBorderType: Pixel extrapolation method in the horizontal direction. - -.. seealso:: :ocv:func:`gpu::createSeparableLinearFilter_GPU`, :ocv:func:`createGaussianFilter` - - - -gpu::GaussianBlur ---------------------- -Smooths an image using the Gaussian filter. - -.. ocv:function:: void gpu::GaussianBlur( const GpuMat& src, GpuMat& dst, Size ksize, double sigma1, double sigma2=0, int rowBorderType=BORDER_DEFAULT, int columnBorderType=-1 ) - -.. ocv:function:: void gpu::GaussianBlur( const GpuMat& src, GpuMat& dst, Size ksize, GpuMat& buf, double sigma1, double sigma2=0, int rowBorderType=BORDER_DEFAULT, int columnBorderType=-1, Stream& stream=Stream::Null() ) - - :param src: Source image. ``CV_8UC1`` , ``CV_8UC4`` , ``CV_16SC1`` , ``CV_16SC2`` , ``CV_16SC3`` , ``CV_32SC1`` , ``CV_32FC1`` source types are supported. - - :param dst: Destination image with the same size and type as ``src`` . - - :param ksize: Gaussian kernel size. ``ksize.width`` and ``ksize.height`` can differ but they both must be positive and odd. If they are zeros, they are computed from ``sigma1`` and ``sigma2`` . - - :param sigma1: Gaussian kernel standard deviation in X direction. - - :param sigma2: Gaussian kernel standard deviation in Y direction. If ``sigma2`` is zero, it is set to be equal to ``sigma1`` . If they are both zeros, they are computed from ``ksize.width`` and ``ksize.height``, respectively. See :ocv:func:`getGaussianKernel` for details. To fully control the result regardless of possible future modification of all this semantics, you are recommended to specify all of ``ksize`` , ``sigma1`` , and ``sigma2`` . - - :param rowBorderType: Pixel extrapolation method in the vertical direction. For details, see :ocv:func:`borderInterpolate`. - - :param columnBorderType: Pixel extrapolation method in the horizontal direction. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`gpu::createGaussianFilter_GPU`, :ocv:func:`GaussianBlur` - - - -gpu::getMaxFilter_GPU -------------------------- -Creates the maximum filter. - -.. ocv:function:: Ptr gpu::getMaxFilter_GPU(int srcType, int dstType, const Size& ksize, Point anchor = Point(-1,-1)) - - :param srcType: Input image type. Only ``CV_8UC1`` and ``CV_8UC4`` are supported. - - :param dstType: Output image type. It supports only the same type as the source type. - - :param ksize: Kernel size. - - :param anchor: Anchor point. The default value (-1) means that the anchor is at the kernel center. - -.. note:: This filter does not check out-of-border accesses, so only a proper sub-matrix of a bigger matrix has to be passed to it. - - - -gpu::getMinFilter_GPU -------------------------- -Creates the minimum filter. - -.. ocv:function:: Ptr gpu::getMinFilter_GPU(int srcType, int dstType, const Size& ksize, Point anchor = Point(-1,-1)) - - :param srcType: Input image type. Only ``CV_8UC1`` and ``CV_8UC4`` are supported. - - :param dstType: Output image type. It supports only the same type as the source type. - - :param ksize: Kernel size. - - :param anchor: Anchor point. The default value (-1) means that the anchor is at the kernel center. - -.. note:: This filter does not check out-of-border accesses, so only a proper sub-matrix of a bigger matrix has to be passed to it. diff --git a/modules/gpu/doc/image_processing.rst b/modules/gpu/doc/image_processing.rst deleted file mode 100644 index 7b404c832a..0000000000 --- a/modules/gpu/doc/image_processing.rst +++ /dev/null @@ -1,1087 +0,0 @@ -Image Processing -================ - -.. highlight:: cpp - - - -gpu::meanShiftFiltering ---------------------------- -Performs mean-shift filtering for each point of the source image. - -.. ocv:function:: void gpu::meanShiftFiltering( const GpuMat& src, GpuMat& dst, int sp, int sr, TermCriteria criteria=TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1), Stream& stream=Stream::Null() ) - - :param src: Source image. Only ``CV_8UC4`` images are supported for now. - - :param dst: Destination image containing the color of mapped points. It has the same size and type as ``src`` . - - :param sp: Spatial window radius. - - :param sr: Color window radius. - - :param criteria: Termination criteria. See :ocv:class:`TermCriteria`. - -It maps each point of the source image into another point. As a result, you have a new color and new position of each point. - - - -gpu::meanShiftProc ----------------------- -Performs a mean-shift procedure and stores information about processed points (their colors and positions) in two images. - -.. ocv:function:: void gpu::meanShiftProc( const GpuMat& src, GpuMat& dstr, GpuMat& dstsp, int sp, int sr, TermCriteria criteria=TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1), Stream& stream=Stream::Null() ) - - :param src: Source image. Only ``CV_8UC4`` images are supported for now. - - :param dstr: Destination image containing the color of mapped points. The size and type is the same as ``src`` . - - :param dstsp: Destination image containing the position of mapped points. The size is the same as ``src`` size. The type is ``CV_16SC2`` . - - :param sp: Spatial window radius. - - :param sr: Color window radius. - - :param criteria: Termination criteria. See :ocv:class:`TermCriteria`. - -.. seealso:: :ocv:func:`gpu::meanShiftFiltering` - - - -gpu::meanShiftSegmentation ------------------------------- -Performs a mean-shift segmentation of the source image and eliminates small segments. - -.. ocv:function:: void gpu::meanShiftSegmentation(const GpuMat& src, Mat& dst, int sp, int sr, int minsize, TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1)) - - :param src: Source image. Only ``CV_8UC4`` images are supported for now. - - :param dst: Segmented image with the same size and type as ``src`` . - - :param sp: Spatial window radius. - - :param sr: Color window radius. - - :param minsize: Minimum segment size. Smaller segments are merged. - - :param criteria: Termination criteria. See :ocv:class:`TermCriteria`. - - - -gpu::integral ------------------ -Computes an integral image. - -.. ocv:function:: void gpu::integral(const GpuMat& src, GpuMat& sum, Stream& stream = Stream::Null()) - - :param src: Source image. Only ``CV_8UC1`` images are supported for now. - - :param sum: Integral image containing 32-bit unsigned integer values packed into ``CV_32SC1`` . - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`integral` - - - -gpu::sqrIntegral --------------------- -Computes a squared integral image. - -.. ocv:function:: void gpu::sqrIntegral(const GpuMat& src, GpuMat& sqsum, Stream& stream = Stream::Null()) - - :param src: Source image. Only ``CV_8UC1`` images are supported for now. - - :param sqsum: Squared integral image containing 64-bit unsigned integer values packed into ``CV_64FC1`` . - - :param stream: Stream for the asynchronous version. - - - -gpu::columnSum ------------------- -Computes a vertical (column) sum. - -.. ocv:function:: void gpu::columnSum(const GpuMat& src, GpuMat& sum) - - :param src: Source image. Only ``CV_32FC1`` images are supported for now. - - :param sum: Destination image of the ``CV_32FC1`` type. - - - -gpu::cornerHarris ---------------------- -Computes the Harris cornerness criteria at each image pixel. - -.. ocv:function:: void gpu::cornerHarris(const GpuMat& src, GpuMat& dst, int blockSize, int ksize, double k, int borderType=BORDER_REFLECT101) - - :param src: Source image. Only ``CV_8UC1`` and ``CV_32FC1`` images are supported for now. - - :param dst: Destination image containing cornerness values. It has the same size as ``src`` and ``CV_32FC1`` type. - - :param blockSize: Neighborhood size. - - :param ksize: Aperture parameter for the Sobel operator. - - :param k: Harris detector free parameter. - - :param borderType: Pixel extrapolation method. Only ``BORDER_REFLECT101`` and ``BORDER_REPLICATE`` are supported for now. - -.. seealso:: :ocv:func:`cornerHarris` - - - -gpu::cornerMinEigenVal --------------------------- -Computes the minimum eigen value of a 2x2 derivative covariation matrix at each pixel (the cornerness criteria). - -.. ocv:function:: void gpu::cornerMinEigenVal(const GpuMat& src, GpuMat& dst, int blockSize, int ksize, int borderType=BORDER_REFLECT101) - -.. ocv:function:: void gpu::cornerMinEigenVal(const GpuMat& src, GpuMat& dst, GpuMat& Dx, GpuMat& Dy, int blockSize, int ksize, int borderType=BORDER_REFLECT101) - -.. ocv:function:: void gpu::cornerMinEigenVal(const GpuMat& src, GpuMat& dst, GpuMat& Dx, GpuMat& Dy, GpuMat& buf, int blockSize, int ksize, int borderType=BORDER_REFLECT101, Stream& stream = Stream::Null()) - - :param src: Source image. Only ``CV_8UC1`` and ``CV_32FC1`` images are supported for now. - - :param dst: Destination image containing cornerness values. The size is the same. The type is ``CV_32FC1`` . - - :param blockSize: Neighborhood size. - - :param ksize: Aperture parameter for the Sobel operator. - - :param borderType: Pixel extrapolation method. Only ``BORDER_REFLECT101`` and ``BORDER_REPLICATE`` are supported for now. - -.. seealso:: :ocv:func:`cornerMinEigenVal` - - - -gpu::mulSpectrums ---------------------- -Performs a per-element multiplication of two Fourier spectrums. - -.. ocv:function:: void gpu::mulSpectrums( const GpuMat& a, const GpuMat& b, GpuMat& c, int flags, bool conjB=false, Stream& stream=Stream::Null() ) - - :param a: First spectrum. - - :param b: Second spectrum with the same size and type as ``a`` . - - :param c: Destination spectrum. - - :param flags: Mock parameter used for CPU/GPU interfaces similarity. - - :param conjB: Optional flag to specify if the second spectrum needs to be conjugated before the multiplication. - - Only full (not packed) ``CV_32FC2`` complex spectrums in the interleaved format are supported for now. - -.. seealso:: :ocv:func:`mulSpectrums` - - - -gpu::mulAndScaleSpectrums ------------------------------ -Performs a per-element multiplication of two Fourier spectrums and scales the result. - -.. ocv:function:: void gpu::mulAndScaleSpectrums( const GpuMat& a, const GpuMat& b, GpuMat& c, int flags, float scale, bool conjB=false, Stream& stream=Stream::Null() ) - - :param a: First spectrum. - - :param b: Second spectrum with the same size and type as ``a`` . - - :param c: Destination spectrum. - - :param flags: Mock parameter used for CPU/GPU interfaces similarity. - - :param scale: Scale constant. - - :param conjB: Optional flag to specify if the second spectrum needs to be conjugated before the multiplication. - - Only full (not packed) ``CV_32FC2`` complex spectrums in the interleaved format are supported for now. - -.. seealso:: :ocv:func:`mulSpectrums` - - - -gpu::dft ------------- -Performs a forward or inverse discrete Fourier transform (1D or 2D) of the floating point matrix. - -.. ocv:function:: void gpu::dft( const GpuMat& src, GpuMat& dst, Size dft_size, int flags=0, Stream& stream=Stream::Null() ) - - :param src: Source matrix (real or complex). - - :param dst: Destination matrix (real or complex). - - :param dft_size: Size of a discrete Fourier transform. - - :param flags: Optional flags: - - * **DFT_ROWS** transforms each individual row of the source matrix. - - * **DFT_SCALE** scales the result: divide it by the number of elements in the transform (obtained from ``dft_size`` ). - - * **DFT_INVERSE** inverts DFT. Use for complex-complex cases (real-complex and complex-real cases are always forward and inverse, respectively). - - * **DFT_REAL_OUTPUT** specifies the output as real. The source matrix is the result of real-complex transform, so the destination matrix must be real. - -Use to handle real matrices ( ``CV32FC1`` ) and complex matrices in the interleaved format ( ``CV32FC2`` ). - -The source matrix should be continuous, otherwise reallocation and data copying is performed. The function chooses an operation mode depending on the flags, size, and channel count of the source matrix: - - * If the source matrix is complex and the output is not specified as real, the destination matrix is complex and has the ``dft_size`` size and ``CV_32FC2`` type. The destination matrix contains a full result of the DFT (forward or inverse). - - * If the source matrix is complex and the output is specified as real, the function assumes that its input is the result of the forward transform (see the next item). The destination matrix has the ``dft_size`` size and ``CV_32FC1`` type. It contains the result of the inverse DFT. - - * If the source matrix is real (its type is ``CV_32FC1`` ), forward DFT is performed. The result of the DFT is packed into complex ( ``CV_32FC2`` ) matrix. So, the width of the destination matrix is ``dft_size.width / 2 + 1`` . But if the source is a single column, the height is reduced instead of the width. - -.. seealso:: :ocv:func:`dft` - - -gpu::ConvolveBuf ----------------- -.. ocv:struct:: gpu::ConvolveBuf - -Class providing a memory buffer for :ocv:func:`gpu::convolve` function, plus it allows to adjust some specific parameters. :: - - struct CV_EXPORTS ConvolveBuf - { - Size result_size; - Size block_size; - Size user_block_size; - Size dft_size; - int spect_len; - - GpuMat image_spect, templ_spect, result_spect; - GpuMat image_block, templ_block, result_data; - - void create(Size image_size, Size templ_size); - static Size estimateBlockSize(Size result_size, Size templ_size); - }; - -You can use field `user_block_size` to set specific block size for :ocv:func:`gpu::convolve` function. If you leave its default value `Size(0,0)` then automatic estimation of block size will be used (which is optimized for speed). By varying `user_block_size` you can reduce memory requirements at the cost of speed. - -gpu::ConvolveBuf::create ------------------------- -.. ocv:function:: gpu::ConvolveBuf::create(Size image_size, Size templ_size) - -Constructs a buffer for :ocv:func:`gpu::convolve` function with respective arguments. - - -gpu::convolve ------------------ -Computes a convolution (or cross-correlation) of two images. - -.. ocv:function:: void gpu::convolve(const GpuMat& image, const GpuMat& templ, GpuMat& result, bool ccorr=false) - -.. ocv:function:: void gpu::convolve( const GpuMat& image, const GpuMat& templ, GpuMat& result, bool ccorr, ConvolveBuf& buf, Stream& stream=Stream::Null() ) - - :param image: Source image. Only ``CV_32FC1`` images are supported for now. - - :param templ: Template image. The size is not greater than the ``image`` size. The type is the same as ``image`` . - - :param result: Result image. If ``image`` is *W x H* and ``templ`` is *w x h*, then ``result`` must be *W-w+1 x H-h+1*. - - :param ccorr: Flags to evaluate cross-correlation instead of convolution. - - :param buf: Optional buffer to avoid extra memory allocations and to adjust some specific parameters. See :ocv:struct:`gpu::ConvolveBuf`. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`gpu::filter2D` - -gpu::MatchTemplateBuf ---------------------- -.. ocv:struct:: gpu::MatchTemplateBuf - -Class providing memory buffers for :ocv:func:`gpu::matchTemplate` function, plus it allows to adjust some specific parameters. :: - - struct CV_EXPORTS MatchTemplateBuf - { - Size user_block_size; - GpuMat imagef, templf; - std::vector images; - std::vector image_sums; - std::vector image_sqsums; - }; - -You can use field `user_block_size` to set specific block size for :ocv:func:`gpu::matchTemplate` function. If you leave its default value `Size(0,0)` then automatic estimation of block size will be used (which is optimized for speed). By varying `user_block_size` you can reduce memory requirements at the cost of speed. - -gpu::matchTemplate ----------------------- -Computes a proximity map for a raster template and an image where the template is searched for. - -.. ocv:function:: void gpu::matchTemplate(const GpuMat& image, const GpuMat& templ, GpuMat& result, int method, Stream &stream = Stream::Null()) - -.. ocv:function:: void gpu::matchTemplate(const GpuMat& image, const GpuMat& templ, GpuMat& result, int method, MatchTemplateBuf &buf, Stream& stream = Stream::Null()) - - :param image: Source image. ``CV_32F`` and ``CV_8U`` depth images (1..4 channels) are supported for now. - - :param templ: Template image with the size and type the same as ``image`` . - - :param result: Map containing comparison results ( ``CV_32FC1`` ). If ``image`` is *W x H* and ``templ`` is *w x h*, then ``result`` must be *W-w+1 x H-h+1*. - - :param method: Specifies the way to compare the template with the image. - - :param buf: Optional buffer to avoid extra memory allocations and to adjust some specific parameters. See :ocv:struct:`gpu::MatchTemplateBuf`. - - :param stream: Stream for the asynchronous version. - - The following methods are supported for the ``CV_8U`` depth images for now: - - * ``CV_TM_SQDIFF`` - * ``CV_TM_SQDIFF_NORMED`` - * ``CV_TM_CCORR`` - * ``CV_TM_CCORR_NORMED`` - * ``CV_TM_CCOEFF`` - * ``CV_TM_CCOEFF_NORMED`` - - The following methods are supported for the ``CV_32F`` images for now: - - * ``CV_TM_SQDIFF`` - * ``CV_TM_CCORR`` - -.. seealso:: :ocv:func:`matchTemplate` - - -gpu::remap --------------- -Applies a generic geometrical transformation to an image. - -.. ocv:function:: void gpu::remap( const GpuMat& src, GpuMat& dst, const GpuMat& xmap, const GpuMat& ymap, int interpolation, int borderMode=BORDER_CONSTANT, Scalar borderValue=Scalar(), Stream& stream=Stream::Null() ) - - :param src: Source image. - - :param dst: Destination image with the size the same as ``xmap`` and the type the same as ``src`` . - - :param xmap: X values. Only ``CV_32FC1`` type is supported. - - :param ymap: Y values. Only ``CV_32FC1`` type is supported. - - :param interpolation: Interpolation method (see :ocv:func:`resize` ). ``INTER_NEAREST`` , ``INTER_LINEAR`` and ``INTER_CUBIC`` are supported for now. - - :param borderMode: Pixel extrapolation method (see :ocv:func:`borderInterpolate` ). ``BORDER_REFLECT101`` , ``BORDER_REPLICATE`` , ``BORDER_CONSTANT`` , ``BORDER_REFLECT`` and ``BORDER_WRAP`` are supported for now. - - :param borderValue: Value used in case of a constant border. By default, it is 0. - - :param stream: Stream for the asynchronous version. - -The function transforms the source image using the specified map: - -.. math:: - - \texttt{dst} (x,y) = \texttt{src} (xmap(x,y), ymap(x,y)) - -Values of pixels with non-integer coordinates are computed using the bilinear interpolation. - -.. seealso:: :ocv:func:`remap` - - - -gpu::cvtColor ------------------ -Converts an image from one color space to another. - -.. ocv:function:: void gpu::cvtColor(const GpuMat& src, GpuMat& dst, int code, int dcn = 0, Stream& stream = Stream::Null()) - - :param src: Source image with ``CV_8U`` , ``CV_16U`` , or ``CV_32F`` depth and 1, 3, or 4 channels. - - :param dst: Destination image with the same size and depth as ``src`` . - - :param code: Color space conversion code. For details, see :ocv:func:`cvtColor` . Conversion to/from Luv and Bayer color spaces is not supported. - - :param dcn: Number of channels in the destination image. If the parameter is 0, the number of the channels is derived automatically from ``src`` and the ``code`` . - - :param stream: Stream for the asynchronous version. - -3-channel color spaces (like ``HSV``, ``XYZ``, and so on) can be stored in a 4-channel image for better performance. - -.. seealso:: :ocv:func:`cvtColor` - - - -gpu::swapChannels ------------------ -Exchanges the color channels of an image in-place. - -.. ocv:function:: void gpu::swapChannels(GpuMat& image, const int dstOrder[4], Stream& stream = Stream::Null()) - - :param image: Source image. Supports only ``CV_8UC4`` type. - - :param dstOrder: Integer array describing how channel values are permutated. The n-th entry of the array contains the number of the channel that is stored in the n-th channel of the output image. E.g. Given an RGBA image, aDstOrder = [3,2,1,0] converts this to ABGR channel order. - - :param stream: Stream for the asynchronous version. - -The methods support arbitrary permutations of the original channels, including replication. - - - -gpu::threshold ------------------- -Applies a fixed-level threshold to each array element. - -.. ocv:function:: double gpu::threshold(const GpuMat& src, GpuMat& dst, double thresh, double maxval, int type, Stream& stream = Stream::Null()) - - :param src: Source array (single-channel). - - :param dst: Destination array with the same size and type as ``src`` . - - :param thresh: Threshold value. - - :param maxval: Maximum value to use with ``THRESH_BINARY`` and ``THRESH_BINARY_INV`` threshold types. - - :param type: Threshold type. For details, see :ocv:func:`threshold` . The ``THRESH_OTSU`` threshold type is not supported. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`threshold` - - - -gpu::resize ---------------- -Resizes an image. - -.. ocv:function:: void gpu::resize(const GpuMat& src, GpuMat& dst, Size dsize, double fx=0, double fy=0, int interpolation = INTER_LINEAR, Stream& stream = Stream::Null()) - - :param src: Source image. - - :param dst: Destination image with the same type as ``src`` . The size is ``dsize`` (when it is non-zero) or the size is computed from ``src.size()`` , ``fx`` , and ``fy`` . - - :param dsize: Destination image size. If it is zero, it is computed as: - - .. math:: - \texttt{dsize = Size(round(fx*src.cols), round(fy*src.rows))} - - Either ``dsize`` or both ``fx`` and ``fy`` must be non-zero. - - :param fx: Scale factor along the horizontal axis. If it is zero, it is computed as: - - .. math:: - - \texttt{(double)dsize.width/src.cols} - - :param fy: Scale factor along the vertical axis. If it is zero, it is computed as: - - .. math:: - - \texttt{(double)dsize.height/src.rows} - - :param interpolation: Interpolation method. ``INTER_NEAREST`` , ``INTER_LINEAR`` and ``INTER_CUBIC`` are supported for now. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`resize` - - - -gpu::warpAffine -------------------- -Applies an affine transformation to an image. - -.. ocv:function:: void gpu::warpAffine( const GpuMat& src, GpuMat& dst, const Mat& M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, Scalar borderValue=Scalar(), Stream& stream=Stream::Null() ) - - :param src: Source image. ``CV_8U`` , ``CV_16U`` , ``CV_32S`` , or ``CV_32F`` depth and 1, 3, or 4 channels are supported. - - :param dst: Destination image with the same type as ``src`` . The size is ``dsize`` . - - :param M: *2x3* transformation matrix. - - :param dsize: Size of the destination image. - - :param flags: Combination of interpolation methods (see :ocv:func:`resize`) and the optional flag ``WARP_INVERSE_MAP`` specifying that ``M`` is an inverse transformation ( ``dst=>src`` ). Only ``INTER_NEAREST`` , ``INTER_LINEAR`` , and ``INTER_CUBIC`` interpolation methods are supported. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`warpAffine` - - - -gpu::buildWarpAffineMaps ------------------------- -Builds transformation maps for affine transformation. - -.. ocv:function:: void gpu::buildWarpAffineMaps(const Mat& M, bool inverse, Size dsize, GpuMat& xmap, GpuMat& ymap, Stream& stream = Stream::Null()) - - :param M: *2x3* transformation matrix. - - :param inverse: Flag specifying that ``M`` is an inverse transformation ( ``dst=>src`` ). - - :param dsize: Size of the destination image. - - :param xmap: X values with ``CV_32FC1`` type. - - :param ymap: Y values with ``CV_32FC1`` type. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`gpu::warpAffine` , :ocv:func:`gpu::remap` - - - -gpu::warpPerspective ------------------------- -Applies a perspective transformation to an image. - -.. ocv:function:: void gpu::warpPerspective( const GpuMat& src, GpuMat& dst, const Mat& M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, Scalar borderValue=Scalar(), Stream& stream=Stream::Null() ) - - :param src: Source image. ``CV_8U`` , ``CV_16U`` , ``CV_32S`` , or ``CV_32F`` depth and 1, 3, or 4 channels are supported. - - :param dst: Destination image with the same type as ``src`` . The size is ``dsize`` . - - :param M: *3x3* transformation matrix. - - :param dsize: Size of the destination image. - - :param flags: Combination of interpolation methods (see :ocv:func:`resize` ) and the optional flag ``WARP_INVERSE_MAP`` specifying that ``M`` is the inverse transformation ( ``dst => src`` ). Only ``INTER_NEAREST`` , ``INTER_LINEAR`` , and ``INTER_CUBIC`` interpolation methods are supported. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`warpPerspective` - - - -gpu::buildWarpPerspectiveMaps ------------------------------ -Builds transformation maps for perspective transformation. - -.. ocv:function:: void gpu::buildWarpAffineMaps(const Mat& M, bool inverse, Size dsize, GpuMat& xmap, GpuMat& ymap, Stream& stream = Stream::Null()) - - :param M: *3x3* transformation matrix. - - :param inverse: Flag specifying that ``M`` is an inverse transformation ( ``dst=>src`` ). - - :param dsize: Size of the destination image. - - :param xmap: X values with ``CV_32FC1`` type. - - :param ymap: Y values with ``CV_32FC1`` type. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`gpu::warpPerspective` , :ocv:func:`gpu::remap` - - - -gpu::rotate ---------------- -Rotates an image around the origin (0,0) and then shifts it. - -.. ocv:function:: void gpu::rotate(const GpuMat& src, GpuMat& dst, Size dsize, double angle, double xShift = 0, double yShift = 0, int interpolation = INTER_LINEAR, Stream& stream = Stream::Null()) - - :param src: Source image. Supports 1, 3 or 4 channels images with ``CV_8U`` , ``CV_16U`` or ``CV_32F`` depth. - - :param dst: Destination image with the same type as ``src`` . The size is ``dsize`` . - - :param dsize: Size of the destination image. - - :param angle: Angle of rotation in degrees. - - :param xShift: Shift along the horizontal axis. - - :param yShift: Shift along the vertical axis. - - :param interpolation: Interpolation method. Only ``INTER_NEAREST`` , ``INTER_LINEAR`` , and ``INTER_CUBIC`` are supported. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`gpu::warpAffine` - - - -gpu::copyMakeBorder ------------------------ -Forms a border around an image. - -.. ocv:function:: void gpu::copyMakeBorder(const GpuMat& src, GpuMat& dst, int top, int bottom, int left, int right, int borderType, const Scalar& value = Scalar(), Stream& stream = Stream::Null()) - - :param src: Source image. ``CV_8UC1`` , ``CV_8UC4`` , ``CV_32SC1`` , and ``CV_32FC1`` types are supported. - - :param dst: Destination image with the same type as ``src``. The size is ``Size(src.cols+left+right, src.rows+top+bottom)`` . - - :param top: - - :param bottom: - - :param left: - - :param right: Number of pixels in each direction from the source image rectangle to extrapolate. For example: ``top=1, bottom=1, left=1, right=1`` mean that 1 pixel-wide border needs to be built. - - :param borderType: Border type. See :ocv:func:`borderInterpolate` for details. ``BORDER_REFLECT101`` , ``BORDER_REPLICATE`` , ``BORDER_CONSTANT`` , ``BORDER_REFLECT`` and ``BORDER_WRAP`` are supported for now. - - :param value: Border value. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`copyMakeBorder` - - - -gpu::rectStdDev -------------------- -Computes a standard deviation of integral images. - -.. ocv:function:: void gpu::rectStdDev(const GpuMat& src, const GpuMat& sqr, GpuMat& dst, const Rect& rect, Stream& stream = Stream::Null()) - - :param src: Source image. Only the ``CV_32SC1`` type is supported. - - :param sqr: Squared source image. Only the ``CV_32FC1`` type is supported. - - :param dst: Destination image with the same type and size as ``src`` . - - :param rect: Rectangular window. - - :param stream: Stream for the asynchronous version. - - - -gpu::evenLevels -------------------- -Computes levels with even distribution. - -.. ocv:function:: void gpu::evenLevels(GpuMat& levels, int nLevels, int lowerLevel, int upperLevel) - - :param levels: Destination array. ``levels`` has 1 row, ``nLevels`` columns, and the ``CV_32SC1`` type. - - :param nLevels: Number of computed levels. ``nLevels`` must be at least 2. - - :param lowerLevel: Lower boundary value of the lowest level. - - :param upperLevel: Upper boundary value of the greatest level. - - - -gpu::histEven ------------------ -Calculates a histogram with evenly distributed bins. - -.. ocv:function:: void gpu::histEven(const GpuMat& src, GpuMat& hist, int histSize, int lowerLevel, int upperLevel, Stream& stream = Stream::Null()) - -.. ocv:function:: void gpu::histEven(const GpuMat& src, GpuMat& hist, GpuMat& buf, int histSize, int lowerLevel, int upperLevel, Stream& stream = Stream::Null()) - -.. ocv:function:: void gpu::histEven( const GpuMat& src, GpuMat hist[4], int histSize[4], int lowerLevel[4], int upperLevel[4], Stream& stream=Stream::Null() ) - -.. ocv:function:: void gpu::histEven( const GpuMat& src, GpuMat hist[4], GpuMat& buf, int histSize[4], int lowerLevel[4], int upperLevel[4], Stream& stream=Stream::Null() ) - - :param src: Source image. ``CV_8U``, ``CV_16U``, or ``CV_16S`` depth and 1 or 4 channels are supported. For a four-channel image, all channels are processed separately. - - :param hist: Destination histogram with one row, ``histSize`` columns, and the ``CV_32S`` type. - - :param histSize: Size of the histogram. - - :param lowerLevel: Lower boundary of lowest-level bin. - - :param upperLevel: Upper boundary of highest-level bin. - - :param buf: Optional buffer to avoid extra memory allocations (for many calls with the same sizes). - - :param stream: Stream for the asynchronous version. - - - -gpu::histRange ------------------- -Calculates a histogram with bins determined by the ``levels`` array. - -.. ocv:function:: void gpu::histRange(const GpuMat& src, GpuMat& hist, const GpuMat& levels, Stream& stream = Stream::Null()) - -.. ocv:function:: void gpu::histRange(const GpuMat& src, GpuMat& hist, const GpuMat& levels, GpuMat& buf, Stream& stream = Stream::Null()) - - :param src: Source image. ``CV_8U`` , ``CV_16U`` , or ``CV_16S`` depth and 1 or 4 channels are supported. For a four-channel image, all channels are processed separately. - - :param hist: Destination histogram with one row, ``(levels.cols-1)`` columns, and the ``CV_32SC1`` type. - - :param levels: Number of levels in the histogram. - - :param buf: Optional buffer to avoid extra memory allocations (for many calls with the same sizes). - - :param stream: Stream for the asynchronous version. - - - -gpu::calcHist ------------------- -Calculates histogram for one channel 8-bit image. - -.. ocv:function:: void gpu::calcHist(const GpuMat& src, GpuMat& hist, Stream& stream = Stream::Null()) - - :param src: Source image. - - :param hist: Destination histogram with one row, 256 columns, and the ``CV_32SC1`` type. - - :param stream: Stream for the asynchronous version. - - - -gpu::equalizeHist ------------------- -Equalizes the histogram of a grayscale image. - -.. ocv:function:: void gpu::equalizeHist(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()) - -.. ocv:function:: void gpu::equalizeHist(const GpuMat& src, GpuMat& dst, GpuMat& hist, GpuMat& buf, Stream& stream = Stream::Null()) - - :param src: Source image. - - :param dst: Destination image. - - :param hist: Destination histogram with one row, 256 columns, and the ``CV_32SC1`` type. - - :param buf: Optional buffer to avoid extra memory allocations (for many calls with the same sizes). - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`equalizeHist` - - - -gpu::buildWarpPlaneMaps ------------------------ -Builds plane warping maps. - -.. ocv:function:: void gpu::buildWarpPlaneMaps( Size src_size, Rect dst_roi, const Mat & K, const Mat& R, const Mat & T, float scale, GpuMat& map_x, GpuMat& map_y, Stream& stream=Stream::Null() ) - - :param stream: Stream for the asynchronous version. - - - -gpu::buildWarpCylindricalMaps ------------------------------ -Builds cylindrical warping maps. - -.. ocv:function:: void gpu::buildWarpCylindricalMaps( Size src_size, Rect dst_roi, const Mat & K, const Mat& R, float scale, GpuMat& map_x, GpuMat& map_y, Stream& stream=Stream::Null() ) - - :param stream: Stream for the asynchronous version. - - - -gpu::buildWarpSphericalMaps ---------------------------- -Builds spherical warping maps. - -.. ocv:function:: void gpu::buildWarpSphericalMaps( Size src_size, Rect dst_roi, const Mat & K, const Mat& R, float scale, GpuMat& map_x, GpuMat& map_y, Stream& stream=Stream::Null() ) - - :param stream: Stream for the asynchronous version. - - - -gpu::pyrDown -------------------- -Smoothes an image and downsamples it. - -.. ocv:function:: void gpu::pyrDown(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()) - - :param src: Source image. - - :param dst: Destination image. Will have ``Size((src.cols+1)/2, (src.rows+1)/2)`` size and the same type as ``src`` . - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`pyrDown` - - - -gpu::pyrUp -------------------- -Upsamples an image and then smoothes it. - -.. ocv:function:: void gpu::pyrUp(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()) - - :param src: Source image. - - :param dst: Destination image. Will have ``Size(src.cols*2, src.rows*2)`` size and the same type as ``src`` . - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`pyrUp` - - - -gpu::blendLinear -------------------- -Performs linear blending of two images. - -.. ocv:function:: void gpu::blendLinear(const GpuMat& img1, const GpuMat& img2, const GpuMat& weights1, const GpuMat& weights2, GpuMat& result, Stream& stream = Stream::Null()) - - :param img1: First image. Supports only ``CV_8U`` and ``CV_32F`` depth. - - :param img2: Second image. Must have the same size and the same type as ``img1`` . - - :param weights1: Weights for first image. Must have tha same size as ``img1`` . Supports only ``CV_32F`` type. - - :param weights2: Weights for second image. Must have tha same size as ``img2`` . Supports only ``CV_32F`` type. - - :param result: Destination image. - - :param stream: Stream for the asynchronous version. - - -gpu::bilateralFilter --------------------- -Performs bilateral filtering of passed image - -.. ocv:function:: void gpu::bilateralFilter( const GpuMat& src, GpuMat& dst, int kernel_size, float sigma_color, float sigma_spatial, int borderMode=BORDER_DEFAULT, Stream& stream=Stream::Null() ) - - :param src: Source image. Supports only (channles != 2 && depth() != CV_8S && depth() != CV_32S && depth() != CV_64F). - - :param dst: Destination imagwe. - - :param kernel_size: Kernel window size. - - :param sigma_color: Filter sigma in the color space. - - :param sigma_spatial: Filter sigma in the coordinate space. - - :param borderMode: Border type. See :ocv:func:`borderInterpolate` for details. ``BORDER_REFLECT101`` , ``BORDER_REPLICATE`` , ``BORDER_CONSTANT`` , ``BORDER_REFLECT`` and ``BORDER_WRAP`` are supported for now. - - :param stream: Stream for the asynchronous version. - -.. seealso:: - - :ocv:func:`bilateralFilter`, - - -gpu::nonLocalMeans -------------------- -Performs pure non local means denoising without any simplification, and thus it is not fast. - -.. ocv:function:: void gpu::nonLocalMeans(const GpuMat& src, GpuMat& dst, float h, int search_window = 21, int block_size = 7, int borderMode = BORDER_DEFAULT, Stream& s = Stream::Null()) - - :param src: Source image. Supports only CV_8UC1, CV_8UC2 and CV_8UC3. - - :param dst: Destination image. - - :param h: Filter sigma regulating filter strength for color. - - :param search_window: Size of search window. - - :param block_size: Size of block used for computing weights. - - :param borderMode: Border type. See :ocv:func:`borderInterpolate` for details. ``BORDER_REFLECT101`` , ``BORDER_REPLICATE`` , ``BORDER_CONSTANT`` , ``BORDER_REFLECT`` and ``BORDER_WRAP`` are supported for now. - - :param stream: Stream for the asynchronous version. - -.. seealso:: - - :ocv:func:`fastNlMeansDenoising` - -gpu::FastNonLocalMeansDenoising -------------------------------- -.. ocv:class:: gpu::FastNonLocalMeansDenoising - - :: - - class FastNonLocalMeansDenoising - { - public: - //! Simple method, recommended for grayscale images (though it supports multichannel images) - void simpleMethod(const GpuMat& src, GpuMat& dst, float h, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()) - //! Processes luminance and color components separatelly - void labMethod(const GpuMat& src, GpuMat& dst, float h_luminance, float h_color, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()) - }; - -The class implements fast approximate Non Local Means Denoising algorithm. - -gpu::FastNonLocalMeansDenoising::simpleMethod() ------------------------------------------------ -Perform image denoising using Non-local Means Denoising algorithm http://www.ipol.im/pub/algo/bcm_non_local_means_denoising with several computational optimizations. Noise expected to be a gaussian white noise - -.. ocv:function:: void gpu::FastNonLocalMeansDenoising::simpleMethod(const GpuMat& src, GpuMat& dst, float h, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()) - - :param src: Input 8-bit 1-channel, 2-channel or 3-channel image. - - :param dst: Output image with the same size and type as ``src`` . - - :param h: Parameter regulating filter strength. Big h value perfectly removes noise but also removes image details, smaller h value preserves details but also preserves some noise - - :param search_window: Size in pixels of the window that is used to compute weighted average for given pixel. Should be odd. Affect performance linearly: greater search_window - greater denoising time. Recommended value 21 pixels - - :param block_size: Size in pixels of the template patch that is used to compute weights. Should be odd. Recommended value 7 pixels - - :param stream: Stream for the asynchronous invocations. - -This function expected to be applied to grayscale images. For colored images look at ``FastNonLocalMeansDenoising::labMethod``. - -.. seealso:: - - :ocv:func:`fastNlMeansDenoising` - -gpu::FastNonLocalMeansDenoising::labMethod() --------------------------------------------- -Modification of ``FastNonLocalMeansDenoising::simpleMethod`` for color images - -.. ocv:function:: void gpu::FastNonLocalMeansDenoising::labMethod(const GpuMat& src, GpuMat& dst, float h_luminance, float h_color, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()) - - :param src: Input 8-bit 3-channel image. - - :param dst: Output image with the same size and type as ``src`` . - - :param h_luminance: Parameter regulating filter strength. Big h value perfectly removes noise but also removes image details, smaller h value preserves details but also preserves some noise - - :param float: The same as h but for color components. For most images value equals 10 will be enought to remove colored noise and do not distort colors - - :param search_window: Size in pixels of the window that is used to compute weighted average for given pixel. Should be odd. Affect performance linearly: greater search_window - greater denoising time. Recommended value 21 pixels - - :param block_size: Size in pixels of the template patch that is used to compute weights. Should be odd. Recommended value 7 pixels - - :param stream: Stream for the asynchronous invocations. - -The function converts image to CIELAB colorspace and then separately denoise L and AB components with given h parameters using ``FastNonLocalMeansDenoising::simpleMethod`` function. - -.. seealso:: - - :ocv:func:`fastNlMeansDenoisingColored` - -gpu::alphaComp -------------------- -Composites two images using alpha opacity values contained in each image. - -.. ocv:function:: void gpu::alphaComp(const GpuMat& img1, const GpuMat& img2, GpuMat& dst, int alpha_op, Stream& stream = Stream::Null()) - - :param img1: First image. Supports ``CV_8UC4`` , ``CV_16UC4`` , ``CV_32SC4`` and ``CV_32FC4`` types. - - :param img2: Second image. Must have the same size and the same type as ``img1`` . - - :param dst: Destination image. - - :param alpha_op: Flag specifying the alpha-blending operation: - - * **ALPHA_OVER** - * **ALPHA_IN** - * **ALPHA_OUT** - * **ALPHA_ATOP** - * **ALPHA_XOR** - * **ALPHA_PLUS** - * **ALPHA_OVER_PREMUL** - * **ALPHA_IN_PREMUL** - * **ALPHA_OUT_PREMUL** - * **ALPHA_ATOP_PREMUL** - * **ALPHA_XOR_PREMUL** - * **ALPHA_PLUS_PREMUL** - * **ALPHA_PREMUL** - - :param stream: Stream for the asynchronous version. - - - -gpu::Canny -------------------- -Finds edges in an image using the [Canny86]_ algorithm. - -.. ocv:function:: void gpu::Canny(const GpuMat& image, GpuMat& edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false) - -.. ocv:function:: void gpu::Canny(const GpuMat& image, CannyBuf& buf, GpuMat& edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false) - -.. ocv:function:: void gpu::Canny(const GpuMat& dx, const GpuMat& dy, GpuMat& edges, double low_thresh, double high_thresh, bool L2gradient = false) - -.. ocv:function:: void gpu::Canny(const GpuMat& dx, const GpuMat& dy, CannyBuf& buf, GpuMat& edges, double low_thresh, double high_thresh, bool L2gradient = false) - - :param image: Single-channel 8-bit input image. - - :param dx: First derivative of image in the vertical direction. Support only ``CV_32S`` type. - - :param dy: First derivative of image in the horizontal direction. Support only ``CV_32S`` type. - - :param edges: Output edge map. It has the same size and type as ``image`` . - - :param low_thresh: First threshold for the hysteresis procedure. - - :param high_thresh: Second threshold for the hysteresis procedure. - - :param apperture_size: Aperture size for the :ocv:func:`Sobel` operator. - - :param L2gradient: Flag indicating whether a more accurate :math:`L_2` norm :math:`=\sqrt{(dI/dx)^2 + (dI/dy)^2}` should be used to compute the image gradient magnitude ( ``L2gradient=true`` ), or a faster default :math:`L_1` norm :math:`=|dI/dx|+|dI/dy|` is enough ( ``L2gradient=false`` ). - - :param buf: Optional buffer to avoid extra memory allocations (for many calls with the same sizes). - -.. seealso:: :ocv:func:`Canny` - - - -gpu::HoughLines ---------------- -Finds lines in a binary image using the classical Hough transform. - -.. ocv:function:: void gpu::HoughLines(const GpuMat& src, GpuMat& lines, float rho, float theta, int threshold, bool doSort = false, int maxLines = 4096) - -.. ocv:function:: void gpu::HoughLines(const GpuMat& src, GpuMat& lines, HoughLinesBuf& buf, float rho, float theta, int threshold, bool doSort = false, int maxLines = 4096) - - :param src: 8-bit, single-channel binary source image. - - :param lines: Output vector of lines. Each line is represented by a two-element vector :math:`(\rho, \theta)` . :math:`\rho` is the distance from the coordinate origin :math:`(0,0)` (top-left corner of the image). :math:`\theta` is the line rotation angle in radians ( :math:`0 \sim \textrm{vertical line}, \pi/2 \sim \textrm{horizontal line}` ). - - :param rho: Distance resolution of the accumulator in pixels. - - :param theta: Angle resolution of the accumulator in radians. - - :param threshold: Accumulator threshold parameter. Only those lines are returned that get enough votes ( :math:`>\texttt{threshold}` ). - - :param doSort: Performs lines sort by votes. - - :param maxLines: Maximum number of output lines. - - :param buf: Optional buffer to avoid extra memory allocations (for many calls with the same sizes). - -.. seealso:: :ocv:func:`HoughLines` - - - -gpu::HoughLinesDownload ------------------------ -Downloads results from :ocv:func:`gpu::HoughLines` to host memory. - -.. ocv:function:: void gpu::HoughLinesDownload(const GpuMat& d_lines, OutputArray h_lines, OutputArray h_votes = noArray()) - - :param d_lines: Result of :ocv:func:`gpu::HoughLines` . - - :param h_lines: Output host array. - - :param h_votes: Optional output array for line's votes. - -.. seealso:: :ocv:func:`gpu::HoughLines` - - - -gpu::HoughCircles ------------------ -Finds circles in a grayscale image using the Hough transform. - -.. ocv:function:: void gpu::HoughCircles(const GpuMat& src, GpuMat& circles, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles = 4096) - -.. ocv:function:: void gpu::HoughCircles(const GpuMat& src, GpuMat& circles, HoughCirclesBuf& buf, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles = 4096) - - :param src: 8-bit, single-channel grayscale input image. - - :param circles: Output vector of found circles. Each vector is encoded as a 3-element floating-point vector :math:`(x, y, radius)` . - - :param method: Detection method to use. Currently, the only implemented method is ``CV_HOUGH_GRADIENT`` , which is basically *21HT* , described in [Yuen90]_. - - :param dp: Inverse ratio of the accumulator resolution to the image resolution. For example, if ``dp=1`` , the accumulator has the same resolution as the input image. If ``dp=2`` , the accumulator has half as big width and height. - - :param minDist: Minimum distance between the centers of the detected circles. If the parameter is too small, multiple neighbor circles may be falsely detected in addition to a true one. If it is too large, some circles may be missed. - - :param cannyThreshold: The higher threshold of the two passed to the :ocv:func:`gpu::Canny` edge detector (the lower one is twice smaller). - - :param votesThreshold: The accumulator threshold for the circle centers at the detection stage. The smaller it is, the more false circles may be detected. - - :param minRadius: Minimum circle radius. - - :param maxRadius: Maximum circle radius. - - :param maxCircles: Maximum number of output circles. - - :param buf: Optional buffer to avoid extra memory allocations (for many calls with the same sizes). - -.. seealso:: :ocv:func:`HoughCircles` - - - -gpu::HoughCirclesDownload -------------------------- -Downloads results from :ocv:func:`gpu::HoughCircles` to host memory. - -.. ocv:function:: void gpu::HoughCirclesDownload(const GpuMat& d_circles, OutputArray h_circles) - - :param d_circles: Result of :ocv:func:`gpu::HoughCircles` . - - :param h_circles: Output host array. - -.. seealso:: :ocv:func:`gpu::HoughCircles` diff --git a/modules/gpu/doc/initalization_and_information.rst b/modules/gpu/doc/initalization_and_information.rst index fc7236dcf1..abfc0860cf 100644 --- a/modules/gpu/doc/initalization_and_information.rst +++ b/modules/gpu/doc/initalization_and_information.rst @@ -107,23 +107,186 @@ Class providing functionality for querying the specified GPU properties. :: class CV_EXPORTS DeviceInfo { public: + //! creates DeviceInfo object for the current GPU DeviceInfo(); + + //! creates DeviceInfo object for the given GPU DeviceInfo(int device_id); - string name() const; + //! ASCII string identifying device + const char* name() const; + //! global memory available on device in bytes + size_t totalGlobalMem() const; + + //! shared memory available per block in bytes + size_t sharedMemPerBlock() const; + + //! 32-bit registers available per block + int regsPerBlock() const; + + //! warp size in threads + int warpSize() const; + + //! maximum pitch in bytes allowed by memory copies + size_t memPitch() const; + + //! maximum number of threads per block + int maxThreadsPerBlock() const; + + //! maximum size of each dimension of a block + Vec3i maxThreadsDim() const; + + //! maximum size of each dimension of a grid + Vec3i maxGridSize() const; + + //! clock frequency in kilohertz + int clockRate() const; + + //! constant memory available on device in bytes + size_t totalConstMem() const; + + //! major compute capability int majorVersion() const; + + //! minor compute capability int minorVersion() const; + //! alignment requirement for textures + size_t textureAlignment() const; + + //! pitch alignment requirement for texture references bound to pitched memory + size_t texturePitchAlignment() const; + + //! number of multiprocessors on device int multiProcessorCount() const; + //! specified whether there is a run time limit on kernels + bool kernelExecTimeoutEnabled() const; + + //! device is integrated as opposed to discrete + bool integrated() const; + + //! device can map host memory with cudaHostAlloc/cudaHostGetDevicePointer + bool canMapHostMemory() const; + + enum ComputeMode + { + ComputeModeDefault, /**< default compute mode (Multiple threads can use ::cudaSetDevice() with this device) */ + ComputeModeExclusive, /**< compute-exclusive-thread mode (Only one thread in one process will be able to use ::cudaSetDevice() with this device) */ + ComputeModeProhibited, /**< compute-prohibited mode (No threads can use ::cudaSetDevice() with this device) */ + ComputeModeExclusiveProcess /**< compute-exclusive-process mode (Many threads in one process will be able to use ::cudaSetDevice() with this device) */ + }; + + //! compute mode + ComputeMode computeMode() const; + + //! maximum 1D texture size + int maxTexture1D() const; + + //! maximum 1D mipmapped texture size + int maxTexture1DMipmap() const; + + //! maximum size for 1D textures bound to linear memory + int maxTexture1DLinear() const; + + //! maximum 2D texture dimensions + Vec2i maxTexture2D() const; + + //! maximum 2D mipmapped texture dimensions + Vec2i maxTexture2DMipmap() const; + + //! maximum dimensions (width, height, pitch) for 2D textures bound to pitched memory + Vec3i maxTexture2DLinear() const; + + //! maximum 2D texture dimensions if texture gather operations have to be performed + Vec2i maxTexture2DGather() const; + + //! maximum 3D texture dimensions + Vec3i maxTexture3D() const; + + //! maximum Cubemap texture dimensions + int maxTextureCubemap() const; + + //! maximum 1D layered texture dimensions + Vec2i maxTexture1DLayered() const; + + //! maximum 2D layered texture dimensions + Vec3i maxTexture2DLayered() const; + + //! maximum Cubemap layered texture dimensions + Vec2i maxTextureCubemapLayered() const; + + //! maximum 1D surface size + int maxSurface1D() const; + + //! maximum 2D surface dimensions + Vec2i maxSurface2D() const; + + //! maximum 3D surface dimensions + Vec3i maxSurface3D() const; + + //! maximum 1D layered surface dimensions + Vec2i maxSurface1DLayered() const; + + //! maximum 2D layered surface dimensions + Vec3i maxSurface2DLayered() const; + + //! maximum Cubemap surface dimensions + int maxSurfaceCubemap() const; + + //! maximum Cubemap layered surface dimensions + Vec2i maxSurfaceCubemapLayered() const; + + //! alignment requirements for surfaces + size_t surfaceAlignment() const; + + //! device can possibly execute multiple kernels concurrently + bool concurrentKernels() const; + + //! device has ECC support enabled + bool ECCEnabled() const; + + //! PCI bus ID of the device + int pciBusID() const; + + //! PCI device ID of the device + int pciDeviceID() const; + + //! PCI domain ID of the device + int pciDomainID() const; + + //! true if device is a Tesla device using TCC driver, false otherwise + bool tccDriver() const; + + //! number of asynchronous engines + int asyncEngineCount() const; + + //! device shares a unified address space with the host + bool unifiedAddressing() const; + + //! peak memory clock frequency in kilohertz + int memoryClockRate() const; + + //! global memory bus width in bits + int memoryBusWidth() const; + + //! size of L2 cache in bytes + int l2CacheSize() const; + + //! maximum resident threads per multiprocessor + int maxThreadsPerMultiProcessor() const; + + //! gets free and total device memory + void queryMemory(size_t& totalMemory, size_t& freeMemory) const; size_t freeMemory() const; size_t totalMemory() const; - bool supports(FeatureSet feature) const; - bool isCompatible() const; + //! checks whether device supports the given feature + bool supports(FeatureSet feature_set) const; - int deviceID() const; + //! checks whether the GPU module can be run on the given device + bool isCompatible() const; }; @@ -146,7 +309,7 @@ gpu::DeviceInfo::name --------------------- Returns the device name. -.. ocv:function:: string gpu::DeviceInfo::name() const +.. ocv:function:: const char* gpu::DeviceInfo::name() const @@ -166,14 +329,6 @@ Returns the minor compute capability version. -gpu::DeviceInfo::multiProcessorCount ------------------------------------- -Returns the number of streaming multiprocessors. - -.. ocv:function:: int gpu::DeviceInfo::multiProcessorCount() - - - gpu::DeviceInfo::freeMemory --------------------------- Returns the amount of free memory in bytes. @@ -194,7 +349,7 @@ gpu::DeviceInfo::supports ------------------------- Provides information on GPU feature support. -.. ocv:function:: bool gpu::DeviceInfo::supports( FeatureSet feature_set ) const +.. ocv:function:: bool gpu::DeviceInfo::supports(FeatureSet feature_set) const :param feature_set: Features to be checked. See :ocv:enum:`gpu::FeatureSet`. diff --git a/modules/gpu/doc/introduction.rst b/modules/gpu/doc/introduction.rst index ef34c369b9..a1237629c5 100644 --- a/modules/gpu/doc/introduction.rst +++ b/modules/gpu/doc/introduction.rst @@ -60,4 +60,3 @@ With this algorithm, a dual GPU gave a 180 % performance increase comparing to the single Fermi GPU. For a source code example, see http://code.opencv.org/projects/opencv/repository/revisions/master/entry/samples/gpu/. - diff --git a/modules/gpu/doc/object_detection.rst b/modules/gpu/doc/object_detection.rst index fd0ac867e2..52755608bf 100644 --- a/modules/gpu/doc/object_detection.rst +++ b/modules/gpu/doc/object_detection.rst @@ -62,7 +62,12 @@ The class implements Histogram of Oriented Gradients ([Dalal2005]_) object detec Interfaces of all methods are kept similar to the ``CPU HOG`` descriptor and detector analogues as much as possible. +.. note:: + * An example applying the HOG descriptor for people detection can be found at opencv_source_code/samples/cpp/peopledetect.cpp + * A GPU example applying the HOG descriptor for people detection can be found at opencv_source_code/samples/gpu/hog.cpp + + * (Python) An example applying the HOG descriptor for people detection can be found at opencv_source_code/samples/python2/peopledetect.py gpu::HOGDescriptor::HOGDescriptor ------------------------------------- @@ -209,11 +214,11 @@ Cascade classifier class used for object detection. Supports HAAR and LBP cascad { public: CascadeClassifier_GPU(); - CascadeClassifier_GPU(const string& filename); + CascadeClassifier_GPU(const String& filename); ~CascadeClassifier_GPU(); bool empty() const; - bool load(const string& filename); + bool load(const String& filename); void release(); /* Returns number of detected objects */ @@ -229,13 +234,16 @@ Cascade classifier class used for object detection. Supports HAAR and LBP cascad Size getClassifierSize() const; }; +.. note:: + * A cascade classifier example can be found at opencv_source_code/samples/gpu/cascadeclassifier.cpp + * A Nvidea API specific cascade classifier example can be found at opencv_source_code/samples/gpu/cascadeclassifier_nvidia_api.cpp gpu::CascadeClassifier_GPU::CascadeClassifier_GPU ----------------------------------------------------- Loads the classifier from a file. Cascade type is detected automatically by constructor parameter. -.. ocv:function:: gpu::CascadeClassifier_GPU::CascadeClassifier_GPU(const string& filename) +.. ocv:function:: gpu::CascadeClassifier_GPU::CascadeClassifier_GPU(const String& filename) :param filename: Name of the file from which the classifier is loaded. Only the old ``haar`` classifier (trained by the ``haar`` training application) and NVIDIA's ``nvbin`` are supported for HAAR and only new type of OpenCV XML cascade supported for LBP. @@ -253,7 +261,7 @@ gpu::CascadeClassifier_GPU::load ------------------------------------ Loads the classifier from a file. The previous content is destroyed. -.. ocv:function:: bool gpu::CascadeClassifier_GPU::load(const string& filename) +.. ocv:function:: bool gpu::CascadeClassifier_GPU::load(const String& filename) :param filename: Name of the file from which the classifier is loaded. Only the old ``haar`` classifier (trained by the ``haar`` training application) and NVIDIA's ``nvbin`` are supported for HAAR and only new type of OpenCV XML cascade supported for LBP. diff --git a/modules/gpu/doc/operations_on_matrices.rst b/modules/gpu/doc/operations_on_matrices.rst deleted file mode 100644 index d1762f442a..0000000000 --- a/modules/gpu/doc/operations_on_matrices.rst +++ /dev/null @@ -1,274 +0,0 @@ -Operations on Matrices -====================== - -.. highlight:: cpp - - - -gpu::gemm ------------------- -Performs generalized matrix multiplication. - -.. ocv:function:: void gpu::gemm(const GpuMat& src1, const GpuMat& src2, double alpha, const GpuMat& src3, double beta, GpuMat& dst, int flags = 0, Stream& stream = Stream::Null()) - - :param src1: First multiplied input matrix that should have ``CV_32FC1`` , ``CV_64FC1`` , ``CV_32FC2`` , or ``CV_64FC2`` type. - - :param src2: Second multiplied input matrix of the same type as ``src1`` . - - :param alpha: Weight of the matrix product. - - :param src3: Third optional delta matrix added to the matrix product. It should have the same type as ``src1`` and ``src2`` . - - :param beta: Weight of ``src3`` . - - :param dst: Destination matrix. It has the proper size and the same type as input matrices. - - :param flags: Operation flags: - - * **GEMM_1_T** transpose ``src1`` - * **GEMM_2_T** transpose ``src2`` - * **GEMM_3_T** transpose ``src3`` - - :param stream: Stream for the asynchronous version. - -The function performs generalized matrix multiplication similar to the ``gemm`` functions in BLAS level 3. For example, ``gemm(src1, src2, alpha, src3, beta, dst, GEMM_1_T + GEMM_3_T)`` corresponds to - -.. math:: - - \texttt{dst} = \texttt{alpha} \cdot \texttt{src1} ^T \cdot \texttt{src2} + \texttt{beta} \cdot \texttt{src3} ^T - -.. note:: Transposition operation doesn't support ``CV_64FC2`` input type. - -.. seealso:: :ocv:func:`gemm` - - - -gpu::transpose ------------------- -Transposes a matrix. - -.. ocv:function:: void gpu::transpose( const GpuMat& src1, GpuMat& dst, Stream& stream=Stream::Null() ) - - :param src1: Source matrix. 1-, 4-, 8-byte element sizes are supported for now (CV_8UC1, CV_8UC4, CV_16UC2, CV_32FC1, etc). - - :param dst: Destination matrix. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`transpose` - - - -gpu::flip -------------- -Flips a 2D matrix around vertical, horizontal, or both axes. - -.. ocv:function:: void gpu::flip( const GpuMat& a, GpuMat& b, int flipCode, Stream& stream=Stream::Null() ) - - :param a: Source matrix. Supports 1, 3 and 4 channels images with ``CV_8U``, ``CV_16U``, ``CV_32S`` or ``CV_32F`` depth. - - :param b: Destination matrix. - - :param flipCode: Flip mode for the source: - - * ``0`` Flips around x-axis. - - * ``>0`` Flips around y-axis. - - * ``<0`` Flips around both axes. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`flip` - - - -gpu::LUT ------------- -Transforms the source matrix into the destination matrix using the given look-up table: ``dst(I) = lut(src(I))`` - -.. ocv:function:: void gpu::LUT(const GpuMat& src, const Mat& lut, GpuMat& dst, Stream& stream = Stream::Null()) - - :param src: Source matrix. ``CV_8UC1`` and ``CV_8UC3`` matrices are supported for now. - - :param lut: Look-up table of 256 elements. It is a continuous ``CV_8U`` matrix. - - :param dst: Destination matrix with the same depth as ``lut`` and the same number of channels as ``src`` . - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`LUT` - - - -gpu::merge --------------- -Makes a multi-channel matrix out of several single-channel matrices. - -.. ocv:function:: void gpu::merge(const GpuMat* src, size_t n, GpuMat& dst, Stream& stream = Stream::Null()) - -.. ocv:function:: void gpu::merge(const vector& src, GpuMat& dst, Stream& stream = Stream::Null()) - - :param src: Array/vector of source matrices. - - :param n: Number of source matrices. - - :param dst: Destination matrix. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`merge` - - - -gpu::split --------------- -Copies each plane of a multi-channel matrix into an array. - -.. ocv:function:: void gpu::split(const GpuMat& src, GpuMat* dst, Stream& stream = Stream::Null()) - -.. ocv:function:: void gpu::split(const GpuMat& src, vector& dst, Stream& stream = Stream::Null()) - - :param src: Source matrix. - - :param dst: Destination array/vector of single-channel matrices. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`split` - - - -gpu::magnitude ------------------- -Computes magnitudes of complex matrix elements. - -.. ocv:function:: void gpu::magnitude( const GpuMat& xy, GpuMat& magnitude, Stream& stream=Stream::Null() ) - -.. ocv:function:: void gpu::magnitude(const GpuMat& x, const GpuMat& y, GpuMat& magnitude, Stream& stream = Stream::Null()) - - :param xy: Source complex matrix in the interleaved format ( ``CV_32FC2`` ). - - :param x: Source matrix containing real components ( ``CV_32FC1`` ). - - :param y: Source matrix containing imaginary components ( ``CV_32FC1`` ). - - :param magnitude: Destination matrix of float magnitudes ( ``CV_32FC1`` ). - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`magnitude` - - - -gpu::magnitudeSqr ---------------------- -Computes squared magnitudes of complex matrix elements. - -.. ocv:function:: void gpu::magnitudeSqr( const GpuMat& xy, GpuMat& magnitude, Stream& stream=Stream::Null() ) - -.. ocv:function:: void gpu::magnitudeSqr(const GpuMat& x, const GpuMat& y, GpuMat& magnitude, Stream& stream = Stream::Null()) - - :param xy: Source complex matrix in the interleaved format ( ``CV_32FC2`` ). - - :param x: Source matrix containing real components ( ``CV_32FC1`` ). - - :param y: Source matrix containing imaginary components ( ``CV_32FC1`` ). - - :param magnitude: Destination matrix of float magnitude squares ( ``CV_32FC1`` ). - - :param stream: Stream for the asynchronous version. - - - -gpu::phase --------------- -Computes polar angles of complex matrix elements. - -.. ocv:function:: void gpu::phase(const GpuMat& x, const GpuMat& y, GpuMat& angle, bool angleInDegrees=false, Stream& stream = Stream::Null()) - - :param x: Source matrix containing real components ( ``CV_32FC1`` ). - - :param y: Source matrix containing imaginary components ( ``CV_32FC1`` ). - - :param angle: Destination matrix of angles ( ``CV_32FC1`` ). - - :param angleInDegrees: Flag for angles that must be evaluated in degrees. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`phase` - - - -gpu::cartToPolar --------------------- -Converts Cartesian coordinates into polar. - -.. ocv:function:: void gpu::cartToPolar(const GpuMat& x, const GpuMat& y, GpuMat& magnitude, GpuMat& angle, bool angleInDegrees=false, Stream& stream = Stream::Null()) - - :param x: Source matrix containing real components ( ``CV_32FC1`` ). - - :param y: Source matrix containing imaginary components ( ``CV_32FC1`` ). - - :param magnitude: Destination matrix of float magnitudes ( ``CV_32FC1`` ). - - :param angle: Destination matrix of angles ( ``CV_32FC1`` ). - - :param angleInDegrees: Flag for angles that must be evaluated in degrees. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`cartToPolar` - - - -gpu::polarToCart --------------------- -Converts polar coordinates into Cartesian. - -.. ocv:function:: void gpu::polarToCart(const GpuMat& magnitude, const GpuMat& angle, GpuMat& x, GpuMat& y, bool angleInDegrees=false, Stream& stream = Stream::Null()) - - :param magnitude: Source matrix containing magnitudes ( ``CV_32FC1`` ). - - :param angle: Source matrix containing angles ( ``CV_32FC1`` ). - - :param x: Destination matrix of real components ( ``CV_32FC1`` ). - - :param y: Destination matrix of imaginary components ( ``CV_32FC1`` ). - - :param angleInDegrees: Flag that indicates angles in degrees. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`polarToCart` - - - -gpu::normalize --------------- -Normalizes the norm or value range of an array. - -.. ocv:function:: void gpu::normalize(const GpuMat& src, GpuMat& dst, double alpha = 1, double beta = 0, int norm_type = NORM_L2, int dtype = -1, const GpuMat& mask = GpuMat()) - -.. ocv:function:: void gpu::normalize(const GpuMat& src, GpuMat& dst, double a, double b, int norm_type, int dtype, const GpuMat& mask, GpuMat& norm_buf, GpuMat& cvt_buf) - - :param src: input array. - - :param dst: output array of the same size as ``src`` . - - :param alpha: norm value to normalize to or the lower range boundary in case of the range normalization. - - :param beta: upper range boundary in case of the range normalization; it is not used for the norm normalization. - - :param normType: normalization type (see the details below). - - :param dtype: when negative, the output array has the same type as ``src``; otherwise, it has the same number of channels as ``src`` and the depth ``=CV_MAT_DEPTH(dtype)``. - - :param mask: optional operation mask. - - :param norm_buf: Optional buffer to avoid extra memory allocations. It is resized automatically. - - :param cvt_buf: Optional buffer to avoid extra memory allocations. It is resized automatically. - -.. seealso:: :ocv:func:`normalize` diff --git a/modules/gpu/doc/per_element_operations.rst b/modules/gpu/doc/per_element_operations.rst deleted file mode 100644 index 2670ba3233..0000000000 --- a/modules/gpu/doc/per_element_operations.rst +++ /dev/null @@ -1,445 +0,0 @@ -Per-element Operations -======================= - -.. highlight:: cpp - - - -gpu::add ------------- -Computes a matrix-matrix or matrix-scalar sum. - -.. ocv:function:: void gpu::add( const GpuMat& a, const GpuMat& b, GpuMat& c, const GpuMat& mask=GpuMat(), int dtype=-1, Stream& stream=Stream::Null() ) - -.. ocv:function:: void gpu::add( const GpuMat& a, const Scalar& sc, GpuMat& c, const GpuMat& mask=GpuMat(), int dtype=-1, Stream& stream=Stream::Null() ) - - :param a: First source matrix. - - :param b: Second source matrix to be added to ``a`` . Matrix should have the same size and type as ``a`` . - - :param sc: A scalar to be added to ``a`` . - - :param c: Destination matrix that has the same size and number of channels as the input array(s). The depth is defined by ``dtype`` or ``a`` depth. - - :param mask: Optional operation mask, 8-bit single channel array, that specifies elements of the destination array to be changed. - - :param dtype: Optional depth of the output array. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`add` - - - -gpu::subtract ------------------ -Computes a matrix-matrix or matrix-scalar difference. - -.. ocv:function:: void gpu::subtract( const GpuMat& a, const GpuMat& b, GpuMat& c, const GpuMat& mask=GpuMat(), int dtype=-1, Stream& stream=Stream::Null() ) - -.. ocv:function:: void gpu::subtract( const GpuMat& a, const Scalar& sc, GpuMat& c, const GpuMat& mask=GpuMat(), int dtype=-1, Stream& stream=Stream::Null() ) - - :param a: First source matrix. - - :param b: Second source matrix to be added to ``a`` . Matrix should have the same size and type as ``a`` . - - :param sc: A scalar to be added to ``a`` . - - :param c: Destination matrix that has the same size and number of channels as the input array(s). The depth is defined by ``dtype`` or ``a`` depth. - - :param mask: Optional operation mask, 8-bit single channel array, that specifies elements of the destination array to be changed. - - :param dtype: Optional depth of the output array. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`subtract` - - - -gpu::multiply ------------------ -Computes a matrix-matrix or matrix-scalar per-element product. - -.. ocv:function:: void gpu::multiply( const GpuMat& a, const GpuMat& b, GpuMat& c, double scale=1, int dtype=-1, Stream& stream=Stream::Null() ) - -.. ocv:function:: void gpu::multiply( const GpuMat& a, const Scalar& sc, GpuMat& c, double scale=1, int dtype=-1, Stream& stream=Stream::Null() ) - - :param a: First source matrix. - - :param b: Second source matrix to be multiplied by ``a`` elements. - - :param sc: A scalar to be multiplied by ``a`` elements. - - :param c: Destination matrix that has the same size and number of channels as the input array(s). The depth is defined by ``dtype`` or ``a`` depth. - - :param scale: Optional scale factor. - - :param dtype: Optional depth of the output array. - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`multiply` - - - -gpu::divide ------------ -Computes a matrix-matrix or matrix-scalar division. - -.. ocv:function:: void gpu::divide( const GpuMat& a, const GpuMat& b, GpuMat& c, double scale=1, int dtype=-1, Stream& stream=Stream::Null() ) - -.. ocv:function:: void gpu::divide(const GpuMat& a, const Scalar& sc, GpuMat& c, double scale = 1, int dtype = -1, Stream& stream = Stream::Null()) - -.. ocv:function:: void gpu::divide( double scale, const GpuMat& b, GpuMat& c, int dtype=-1, Stream& stream=Stream::Null() ) - - :param a: First source matrix or a scalar. - - :param b: Second source matrix. The ``a`` elements are divided by it. - - :param sc: A scalar to be divided by the elements of ``a`` matrix. - - :param c: Destination matrix that has the same size and number of channels as the input array(s). The depth is defined by ``dtype`` or ``a`` depth. - - :param scale: Optional scale factor. - - :param dtype: Optional depth of the output array. - - :param stream: Stream for the asynchronous version. - -This function, in contrast to :ocv:func:`divide`, uses a round-down rounding mode. - -.. seealso:: :ocv:func:`divide` - - -gpu::addWeighted ----------------- -Computes the weighted sum of two arrays. - -.. ocv:function:: void gpu::addWeighted(const GpuMat& src1, double alpha, const GpuMat& src2, double beta, double gamma, GpuMat& dst, int dtype = -1, Stream& stream = Stream::Null()) - - :param src1: First source array. - - :param alpha: Weight for the first array elements. - - :param src2: Second source array of the same size and channel number as ``src1`` . - - :param beta: Weight for the second array elements. - - :param dst: Destination array that has the same size and number of channels as the input arrays. - - :param gamma: Scalar added to each sum. - - :param dtype: Optional depth of the destination array. When both input arrays have the same depth, ``dtype`` can be set to ``-1``, which will be equivalent to ``src1.depth()``. - - :param stream: Stream for the asynchronous version. - -The function ``addWeighted`` calculates the weighted sum of two arrays as follows: - -.. math:: - - \texttt{dst} (I)= \texttt{saturate} ( \texttt{src1} (I)* \texttt{alpha} + \texttt{src2} (I)* \texttt{beta} + \texttt{gamma} ) - -where ``I`` is a multi-dimensional index of array elements. In case of multi-channel arrays, each channel is processed independently. - -.. seealso:: :ocv:func:`addWeighted` - - - -gpu::abs ------------- -Computes an absolute value of each matrix element. - -.. ocv:function:: void gpu::abs(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()) - - :param src: Source matrix. Supports ``CV_16S`` and ``CV_32F`` depth. - - :param dst: Destination matrix with the same size and type as ``src`` . - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`abs` - - - -gpu::sqr ------------- -Computes a square value of each matrix element. - -.. ocv:function:: void gpu::sqr(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()) - - :param src: Source matrix. Supports ``CV_8U`` , ``CV_16U`` , ``CV_16S`` and ``CV_32F`` depth. - - :param dst: Destination matrix with the same size and type as ``src`` . - - :param stream: Stream for the asynchronous version. - - - -gpu::sqrt ------------- -Computes a square root of each matrix element. - -.. ocv:function:: void gpu::sqrt(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()) - - :param src: Source matrix. Supports ``CV_8U`` , ``CV_16U`` , ``CV_16S`` and ``CV_32F`` depth. - - :param dst: Destination matrix with the same size and type as ``src`` . - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`sqrt` - - - -gpu::exp ------------- -Computes an exponent of each matrix element. - -.. ocv:function:: void gpu::exp( const GpuMat& a, GpuMat& b, Stream& stream=Stream::Null() ) - - :param a: Source matrix. Supports ``CV_8U`` , ``CV_16U`` , ``CV_16S`` and ``CV_32F`` depth. - - :param b: Destination matrix with the same size and type as ``a`` . - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`exp` - - - -gpu::log ------------- -Computes a natural logarithm of absolute value of each matrix element. - -.. ocv:function:: void gpu::log( const GpuMat& a, GpuMat& b, Stream& stream=Stream::Null() ) - - :param a: Source matrix. Supports ``CV_8U`` , ``CV_16U`` , ``CV_16S`` and ``CV_32F`` depth. - - :param b: Destination matrix with the same size and type as ``a`` . - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`log` - - - -gpu::pow ------------- -Raises every matrix element to a power. - -.. ocv:function:: void gpu::pow(const GpuMat& src, double power, GpuMat& dst, Stream& stream = Stream::Null()) - - :param src: Source matrix. Supports all type, except ``CV_64F`` depth. - - :param power: Exponent of power. - - :param dst: Destination matrix with the same size and type as ``src`` . - - :param stream: Stream for the asynchronous version. - -The function ``pow`` raises every element of the input matrix to ``p`` : - -.. math:: - - \texttt{dst} (I) = \fork{\texttt{src}(I)^p}{if \texttt{p} is integer}{|\texttt{src}(I)|^p}{otherwise} - -.. seealso:: :ocv:func:`pow` - - - -gpu::absdiff ----------------- -Computes per-element absolute difference of two matrices (or of a matrix and scalar). - -.. ocv:function:: void gpu::absdiff( const GpuMat& a, const GpuMat& b, GpuMat& c, Stream& stream=Stream::Null() ) - -.. ocv:function:: void gpu::absdiff( const GpuMat& a, const Scalar& s, GpuMat& c, Stream& stream=Stream::Null() ) - - :param a: First source matrix. - - :param b: Second source matrix to be added to ``a`` . - - :param s: A scalar to be added to ``a`` . - - :param c: Destination matrix with the same size and type as ``a`` . - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`absdiff` - - - -gpu::compare ----------------- -Compares elements of two matrices. - -.. ocv:function:: void gpu::compare( const GpuMat& a, const GpuMat& b, GpuMat& c, int cmpop, Stream& stream=Stream::Null() ) - -.. ocv:function:: void gpu::compare(const GpuMat& a, Scalar sc, GpuMat& c, int cmpop, Stream& stream = Stream::Null()) - - :param a: First source matrix. - - :param b: Second source matrix with the same size and type as ``a`` . - - :param sc: A scalar to be compared with ``a`` . - - :param c: Destination matrix with the same size as ``a`` and the ``CV_8UC1`` type. - - :param cmpop: Flag specifying the relation between the elements to be checked: - - * **CMP_EQ:** ``a(.) == b(.)`` - * **CMP_GT:** ``a(.) < b(.)`` - * **CMP_GE:** ``a(.) <= b(.)`` - * **CMP_LT:** ``a(.) < b(.)`` - * **CMP_LE:** ``a(.) <= b(.)`` - * **CMP_NE:** ``a(.) != b(.)`` - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`compare` - - - -gpu::bitwise_not --------------------- -Performs a per-element bitwise inversion. - -.. ocv:function:: void gpu::bitwise_not(const GpuMat& src, GpuMat& dst, const GpuMat& mask=GpuMat(), Stream& stream = Stream::Null()) - - :param src: Source matrix. - - :param dst: Destination matrix with the same size and type as ``src`` . - - :param mask: Optional operation mask. 8-bit single channel image. - - :param stream: Stream for the asynchronous version. - - - -gpu::bitwise_or -------------------- -Performs a per-element bitwise disjunction of two matrices or of matrix and scalar. - -.. ocv:function:: void gpu::bitwise_or(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask=GpuMat(), Stream& stream = Stream::Null()) -.. ocv:function:: void gpu::bitwise_or(const GpuMat& src1, const Scalar& sc, GpuMat& dst, Stream& stream = Stream::Null()) - - :param src1: First source matrix. - - :param src2: Second source matrix with the same size and type as ``src1`` . - - :param dst: Destination matrix with the same size and type as ``src1`` . - - :param mask: Optional operation mask. 8-bit single channel image. - - :param stream: Stream for the asynchronous version. - - - -gpu::bitwise_and --------------------- -Performs a per-element bitwise conjunction of two matrices or of matrix and scalar. - -.. ocv:function:: void gpu::bitwise_and(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask=GpuMat(), Stream& stream = Stream::Null()) -.. ocv:function:: void gpu::bitwise_and(const GpuMat& src1, const Scalar& sc, GpuMat& dst, Stream& stream = Stream::Null()) - - :param src1: First source matrix. - - :param src2: Second source matrix with the same size and type as ``src1`` . - - :param dst: Destination matrix with the same size and type as ``src1`` . - - :param mask: Optional operation mask. 8-bit single channel image. - - :param stream: Stream for the asynchronous version. - - - -gpu::bitwise_xor --------------------- -Performs a per-element bitwise ``exclusive or`` operation of two matrices of matrix and scalar. - -.. ocv:function:: void gpu::bitwise_xor(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask=GpuMat(), Stream& stream = Stream::Null()) -.. ocv:function:: void gpu::bitwise_xor(const GpuMat& src1, const Scalar& sc, GpuMat& dst, Stream& stream = Stream::Null()) - - :param src1: First source matrix. - - :param src2: Second source matrix with the same size and type as ``src1`` . - - :param dst: Destination matrix with the same size and type as ``src1`` . - - :param mask: Optional operation mask. 8-bit single channel image. - - :param stream: Stream for the asynchronous version. - - - -gpu::rshift --------------------- -Performs pixel by pixel right shift of an image by a constant value. - -.. ocv:function:: void gpu::rshift( const GpuMat& src, Scalar_ sc, GpuMat& dst, Stream& stream=Stream::Null() ) - - :param src: Source matrix. Supports 1, 3 and 4 channels images with integers elements. - - :param sc: Constant values, one per channel. - - :param dst: Destination matrix with the same size and type as ``src`` . - - :param stream: Stream for the asynchronous version. - - - -gpu::lshift --------------------- -Performs pixel by pixel right left of an image by a constant value. - -.. ocv:function:: void gpu::lshift( const GpuMat& src, Scalar_ sc, GpuMat& dst, Stream& stream=Stream::Null() ) - - :param src: Source matrix. Supports 1, 3 and 4 channels images with ``CV_8U`` , ``CV_16U`` or ``CV_32S`` depth. - - :param sc: Constant values, one per channel. - - :param dst: Destination matrix with the same size and type as ``src`` . - - :param stream: Stream for the asynchronous version. - - - -gpu::min ------------- -Computes the per-element minimum of two matrices (or a matrix and a scalar). - -.. ocv:function:: void gpu::min(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Stream& stream = Stream::Null()) - -.. ocv:function:: void gpu::min(const GpuMat& src1, double src2, GpuMat& dst, Stream& stream = Stream::Null()) - - :param src1: First source matrix. - - :param src2: Second source matrix or a scalar to compare ``src1`` elements with. - - :param dst: Destination matrix with the same size and type as ``src1`` . - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`min` - - - -gpu::max ------------- -Computes the per-element maximum of two matrices (or a matrix and a scalar). - -.. ocv:function:: void gpu::max(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Stream& stream = Stream::Null()) - -.. ocv:function:: void gpu::max(const GpuMat& src1, double src2, GpuMat& dst, Stream& stream = Stream::Null()) - - :param src1: First source matrix. - - :param src2: Second source matrix or a scalar to compare ``src1`` elements with. - - :param dst: Destination matrix with the same size and type as ``src1`` . - - :param stream: Stream for the asynchronous version. - -.. seealso:: :ocv:func:`max` diff --git a/modules/gpu/doc/video.rst b/modules/gpu/doc/video.rst deleted file mode 100644 index fc5b1fb6cb..0000000000 --- a/modules/gpu/doc/video.rst +++ /dev/null @@ -1,1213 +0,0 @@ -Video Analysis -============== - -.. highlight:: cpp - - - -gpu::BroxOpticalFlow --------------------- -.. ocv:class:: gpu::BroxOpticalFlow - -Class computing the optical flow for two images using Brox et al Optical Flow algorithm ([Brox2004]_). :: - - class BroxOpticalFlow - { - public: - BroxOpticalFlow(float alpha_, float gamma_, float scale_factor_, int inner_iterations_, int outer_iterations_, int solver_iterations_); - - //! Compute optical flow - //! frame0 - source frame (supports only CV_32FC1 type) - //! frame1 - frame to track (with the same size and type as frame0) - //! u - flow horizontal component (along x axis) - //! v - flow vertical component (along y axis) - void operator ()(const GpuMat& frame0, const GpuMat& frame1, GpuMat& u, GpuMat& v, Stream& stream = Stream::Null()); - - //! flow smoothness - float alpha; - - //! gradient constancy importance - float gamma; - - //! pyramid scale factor - float scale_factor; - - //! number of lagged non-linearity iterations (inner loop) - int inner_iterations; - - //! number of warping iterations (number of pyramid levels) - int outer_iterations; - - //! number of linear system solver iterations - int solver_iterations; - - GpuMat buf; - }; - - - -gpu::GoodFeaturesToTrackDetector_GPU ------------------------------------- -.. ocv:class:: gpu::GoodFeaturesToTrackDetector_GPU - -Class used for strong corners detection on an image. :: - - class GoodFeaturesToTrackDetector_GPU - { - public: - explicit GoodFeaturesToTrackDetector_GPU(int maxCorners_ = 1000, double qualityLevel_ = 0.01, double minDistance_ = 0.0, - int blockSize_ = 3, bool useHarrisDetector_ = false, double harrisK_ = 0.04); - - void operator ()(const GpuMat& image, GpuMat& corners, const GpuMat& mask = GpuMat()); - - int maxCorners; - double qualityLevel; - double minDistance; - - int blockSize; - bool useHarrisDetector; - double harrisK; - - void releaseMemory(); - }; - -The class finds the most prominent corners in the image. - -.. seealso:: :ocv:func:`goodFeaturesToTrack` - - - -gpu::GoodFeaturesToTrackDetector_GPU::GoodFeaturesToTrackDetector_GPU ---------------------------------------------------------------------- -Constructor. - -.. ocv:function:: gpu::GoodFeaturesToTrackDetector_GPU::GoodFeaturesToTrackDetector_GPU(int maxCorners = 1000, double qualityLevel = 0.01, double minDistance = 0.0, int blockSize = 3, bool useHarrisDetector = false, double harrisK = 0.04) - - :param maxCorners: Maximum number of corners to return. If there are more corners than are found, the strongest of them is returned. - - :param qualityLevel: Parameter characterizing the minimal accepted quality of image corners. The parameter value is multiplied by the best corner quality measure, which is the minimal eigenvalue (see :ocv:func:`gpu::cornerMinEigenVal` ) or the Harris function response (see :ocv:func:`gpu::cornerHarris` ). The corners with the quality measure less than the product are rejected. For example, if the best corner has the quality measure = 1500, and the ``qualityLevel=0.01`` , then all the corners with the quality measure less than 15 are rejected. - - :param minDistance: Minimum possible Euclidean distance between the returned corners. - - :param blockSize: Size of an average block for computing a derivative covariation matrix over each pixel neighborhood. See :ocv:func:`cornerEigenValsAndVecs` . - - :param useHarrisDetector: Parameter indicating whether to use a Harris detector (see :ocv:func:`gpu::cornerHarris`) or :ocv:func:`gpu::cornerMinEigenVal`. - - :param harrisK: Free parameter of the Harris detector. - - - -gpu::GoodFeaturesToTrackDetector_GPU::operator () -------------------------------------------------- -Finds the most prominent corners in the image. - -.. ocv:function:: void gpu::GoodFeaturesToTrackDetector_GPU::operator ()(const GpuMat& image, GpuMat& corners, const GpuMat& mask = GpuMat()) - - :param image: Input 8-bit, single-channel image. - - :param corners: Output vector of detected corners (it will be one row matrix with CV_32FC2 type). - - :param mask: Optional region of interest. If the image is not empty (it needs to have the type ``CV_8UC1`` and the same size as ``image`` ), it specifies the region in which the corners are detected. - -.. seealso:: :ocv:func:`goodFeaturesToTrack` - - - -gpu::GoodFeaturesToTrackDetector_GPU::releaseMemory ---------------------------------------------------- -Releases inner buffers memory. - -.. ocv:function:: void gpu::GoodFeaturesToTrackDetector_GPU::releaseMemory() - - - -gpu::FarnebackOpticalFlow -------------------------- -.. ocv:class:: gpu::FarnebackOpticalFlow - -Class computing a dense optical flow using the Gunnar Farneback’s algorithm. :: - - class CV_EXPORTS FarnebackOpticalFlow - { - public: - FarnebackOpticalFlow() - { - numLevels = 5; - pyrScale = 0.5; - fastPyramids = false; - winSize = 13; - numIters = 10; - polyN = 5; - polySigma = 1.1; - flags = 0; - } - - int numLevels; - double pyrScale; - bool fastPyramids; - int winSize; - int numIters; - int polyN; - double polySigma; - int flags; - - void operator ()(const GpuMat &frame0, const GpuMat &frame1, GpuMat &flowx, GpuMat &flowy, Stream &s = Stream::Null()); - - void releaseMemory(); - - private: - /* hidden */ - }; - - - -gpu::FarnebackOpticalFlow::operator () --------------------------------------- -Computes a dense optical flow using the Gunnar Farneback’s algorithm. - -.. ocv:function:: void gpu::FarnebackOpticalFlow::operator ()(const GpuMat &frame0, const GpuMat &frame1, GpuMat &flowx, GpuMat &flowy, Stream &s = Stream::Null()) - - :param frame0: First 8-bit gray-scale input image - :param frame1: Second 8-bit gray-scale input image - :param flowx: Flow horizontal component - :param flowy: Flow vertical component - :param s: Stream - -.. seealso:: :ocv:func:`calcOpticalFlowFarneback` - - - -gpu::FarnebackOpticalFlow::releaseMemory ----------------------------------------- -Releases unused auxiliary memory buffers. - -.. ocv:function:: void gpu::FarnebackOpticalFlow::releaseMemory() - - - -gpu::PyrLKOpticalFlow ---------------------- -.. ocv:class:: gpu::PyrLKOpticalFlow - -Class used for calculating an optical flow. :: - - class PyrLKOpticalFlow - { - public: - PyrLKOpticalFlow(); - - void sparse(const GpuMat& prevImg, const GpuMat& nextImg, const GpuMat& prevPts, GpuMat& nextPts, - GpuMat& status, GpuMat* err = 0); - - void dense(const GpuMat& prevImg, const GpuMat& nextImg, GpuMat& u, GpuMat& v, GpuMat* err = 0); - - Size winSize; - int maxLevel; - int iters; - bool useInitialFlow; - - void releaseMemory(); - }; - -The class can calculate an optical flow for a sparse feature set or dense optical flow using the iterative Lucas-Kanade method with pyramids. - -.. seealso:: :ocv:func:`calcOpticalFlowPyrLK` - - - -gpu::PyrLKOpticalFlow::sparse ------------------------------ -Calculate an optical flow for a sparse feature set. - -.. ocv:function:: void gpu::PyrLKOpticalFlow::sparse(const GpuMat& prevImg, const GpuMat& nextImg, const GpuMat& prevPts, GpuMat& nextPts, GpuMat& status, GpuMat* err = 0) - - :param prevImg: First 8-bit input image (supports both grayscale and color images). - - :param nextImg: Second input image of the same size and the same type as ``prevImg`` . - - :param prevPts: Vector of 2D points for which the flow needs to be found. It must be one row matrix with CV_32FC2 type. - - :param nextPts: Output vector of 2D points (with single-precision floating-point coordinates) containing the calculated new positions of input features in the second image. When ``useInitialFlow`` is true, the vector must have the same size as in the input. - - :param status: Output status vector (CV_8UC1 type). Each element of the vector is set to 1 if the flow for the corresponding features has been found. Otherwise, it is set to 0. - - :param err: Output vector (CV_32FC1 type) that contains the difference between patches around the original and moved points or min eigen value if ``getMinEigenVals`` is checked. It can be NULL, if not needed. - -.. seealso:: :ocv:func:`calcOpticalFlowPyrLK` - - - -gpu::PyrLKOpticalFlow::dense ------------------------------ -Calculate dense optical flow. - -.. ocv:function:: void gpu::PyrLKOpticalFlow::dense(const GpuMat& prevImg, const GpuMat& nextImg, GpuMat& u, GpuMat& v, GpuMat* err = 0) - - :param prevImg: First 8-bit grayscale input image. - - :param nextImg: Second input image of the same size and the same type as ``prevImg`` . - - :param u: Horizontal component of the optical flow of the same size as input images, 32-bit floating-point, single-channel - - :param v: Vertical component of the optical flow of the same size as input images, 32-bit floating-point, single-channel - - :param err: Output vector (CV_32FC1 type) that contains the difference between patches around the original and moved points or min eigen value if ``getMinEigenVals`` is checked. It can be NULL, if not needed. - - - -gpu::PyrLKOpticalFlow::releaseMemory ------------------------------------- -Releases inner buffers memory. - -.. ocv:function:: void gpu::PyrLKOpticalFlow::releaseMemory() - - - -gpu::interpolateFrames ----------------------- -Interpolates frames (images) using provided optical flow (displacement field). - -.. ocv:function:: void gpu::interpolateFrames(const GpuMat& frame0, const GpuMat& frame1, const GpuMat& fu, const GpuMat& fv, const GpuMat& bu, const GpuMat& bv, float pos, GpuMat& newFrame, GpuMat& buf, Stream& stream = Stream::Null()) - - :param frame0: First frame (32-bit floating point images, single channel). - - :param frame1: Second frame. Must have the same type and size as ``frame0`` . - - :param fu: Forward horizontal displacement. - - :param fv: Forward vertical displacement. - - :param bu: Backward horizontal displacement. - - :param bv: Backward vertical displacement. - - :param pos: New frame position. - - :param newFrame: Output image. - - :param buf: Temporary buffer, will have width x 6*height size, CV_32FC1 type and contain 6 GpuMat: occlusion masks for first frame, occlusion masks for second, interpolated forward horizontal flow, interpolated forward vertical flow, interpolated backward horizontal flow, interpolated backward vertical flow. - - :param stream: Stream for the asynchronous version. - - - -gpu::FGDStatModel ------------------ -.. ocv:class:: gpu::FGDStatModel - -Class used for background/foreground segmentation. :: - - class FGDStatModel - { - public: - struct Params - { - ... - }; - - explicit FGDStatModel(int out_cn = 3); - explicit FGDStatModel(const cv::gpu::GpuMat& firstFrame, const Params& params = Params(), int out_cn = 3); - - ~FGDStatModel(); - - void create(const cv::gpu::GpuMat& firstFrame, const Params& params = Params()); - void release(); - - int update(const cv::gpu::GpuMat& curFrame); - - //8UC3 or 8UC4 reference background image - cv::gpu::GpuMat background; - - //8UC1 foreground image - cv::gpu::GpuMat foreground; - - std::vector< std::vector > foreground_regions; - }; - - The class discriminates between foreground and background pixels by building and maintaining a model of the background. Any pixel which does not fit this model is then deemed to be foreground. The class implements algorithm described in [FGD2003]_. - - The results are available through the class fields: - - .. ocv:member:: cv::gpu::GpuMat background - - The output background image. - - .. ocv:member:: cv::gpu::GpuMat foreground - - The output foreground mask as an 8-bit binary image. - - .. ocv:member:: cv::gpu::GpuMat foreground_regions - - The output foreground regions calculated by :ocv:func:`findContours`. - - - -gpu::FGDStatModel::FGDStatModel -------------------------------- -Constructors. - -.. ocv:function:: gpu::FGDStatModel::FGDStatModel(int out_cn = 3) -.. ocv:function:: gpu::FGDStatModel::FGDStatModel(const cv::gpu::GpuMat& firstFrame, const Params& params = Params(), int out_cn = 3) - - :param firstFrame: First frame from video stream. Supports 3- and 4-channels input ( ``CV_8UC3`` and ``CV_8UC4`` ). - - :param params: Algorithm's parameters. See [FGD2003]_ for explanation. - - :param out_cn: Channels count in output result and inner buffers. Can be 3 or 4. 4-channels version requires more memory, but works a bit faster. - -.. seealso:: :ocv:func:`gpu::FGDStatModel::create` - - - -gpu::FGDStatModel::create -------------------------- -Initializes background model. - -.. ocv:function:: void gpu::FGDStatModel::create(const cv::gpu::GpuMat& firstFrame, const Params& params = Params()) - - :param firstFrame: First frame from video stream. Supports 3- and 4-channels input ( ``CV_8UC3`` and ``CV_8UC4`` ). - - :param params: Algorithm's parameters. See [FGD2003]_ for explanation. - - - -gpu::FGDStatModel::release --------------------------- -Releases all inner buffer's memory. - -.. ocv:function:: void gpu::FGDStatModel::release() - - - -gpu::FGDStatModel::update --------------------------- -Updates the background model and returns foreground regions count. - -.. ocv:function:: int gpu::FGDStatModel::update(const cv::gpu::GpuMat& curFrame) - - :param curFrame: Next video frame. - - - -gpu::MOG_GPU ------------- -.. ocv:class:: gpu::MOG_GPU - -Gaussian Mixture-based Backbround/Foreground Segmentation Algorithm. :: - - class MOG_GPU - { - public: - MOG_GPU(int nmixtures = -1); - - void initialize(Size frameSize, int frameType); - - void operator()(const GpuMat& frame, GpuMat& fgmask, float learningRate = 0.0f, Stream& stream = Stream::Null()); - - void getBackgroundImage(GpuMat& backgroundImage, Stream& stream = Stream::Null()) const; - - void release(); - - int history; - float varThreshold; - float backgroundRatio; - float noiseSigma; - }; - -The class discriminates between foreground and background pixels by building and maintaining a model of the background. Any pixel which does not fit this model is then deemed to be foreground. The class implements algorithm described in [MOG2001]_. - -.. seealso:: :ocv:class:`BackgroundSubtractorMOG` - - - -gpu::MOG_GPU::MOG_GPU ---------------------- -The constructor. - -.. ocv:function:: gpu::MOG_GPU::MOG_GPU(int nmixtures = -1) - - :param nmixtures: Number of Gaussian mixtures. - -Default constructor sets all parameters to default values. - - - -gpu::MOG_GPU::operator() ------------------------- -Updates the background model and returns the foreground mask. - -.. ocv:function:: void gpu::MOG_GPU::operator()(const GpuMat& frame, GpuMat& fgmask, float learningRate = 0.0f, Stream& stream = Stream::Null()) - - :param frame: Next video frame. - - :param fgmask: The output foreground mask as an 8-bit binary image. - - :param stream: Stream for the asynchronous version. - - - -gpu::MOG_GPU::getBackgroundImage --------------------------------- -Computes a background image. - -.. ocv:function:: void gpu::MOG_GPU::getBackgroundImage(GpuMat& backgroundImage, Stream& stream = Stream::Null()) const - - :param backgroundImage: The output background image. - - :param stream: Stream for the asynchronous version. - - - -gpu::MOG_GPU::release ---------------------- -Releases all inner buffer's memory. - -.. ocv:function:: void gpu::MOG_GPU::release() - - - -gpu::MOG2_GPU -------------- -.. ocv:class:: gpu::MOG2_GPU - -Gaussian Mixture-based Background/Foreground Segmentation Algorithm. :: - - class MOG2_GPU - { - public: - MOG2_GPU(int nmixtures = -1); - - void initialize(Size frameSize, int frameType); - - void operator()(const GpuMat& frame, GpuMat& fgmask, float learningRate = 0.0f, Stream& stream = Stream::Null()); - - void getBackgroundImage(GpuMat& backgroundImage, Stream& stream = Stream::Null()) const; - - void release(); - - // parameters - ... - }; - - The class discriminates between foreground and background pixels by building and maintaining a model of the background. Any pixel which does not fit this model is then deemed to be foreground. The class implements algorithm described in [MOG2004]_. - - Here are important members of the class that control the algorithm, which you can set after constructing the class instance: - - .. ocv:member:: float backgroundRatio - - Threshold defining whether the component is significant enough to be included into the background model ( corresponds to ``TB=1-cf`` from the paper??which paper??). ``cf=0.1 => TB=0.9`` is default. For ``alpha=0.001``, it means that the mode should exist for approximately 105 frames before it is considered foreground. - - .. ocv:member:: float varThreshold - - Threshold for the squared Mahalanobis distance that helps decide when a sample is close to the existing components (corresponds to ``Tg``). If it is not close to any component, a new component is generated. ``3 sigma => Tg=3*3=9`` is default. A smaller ``Tg`` value generates more components. A higher ``Tg`` value may result in a small number of components but they can grow too large. - - .. ocv:member:: float fVarInit - - Initial variance for the newly generated components. It affects the speed of adaptation. The parameter value is based on your estimate of the typical standard deviation from the images. OpenCV uses 15 as a reasonable value. - - .. ocv:member:: float fVarMin - - Parameter used to further control the variance. - - .. ocv:member:: float fVarMax - - Parameter used to further control the variance. - - .. ocv:member:: float fCT - - Complexity reduction parameter. This parameter defines the number of samples needed to accept to prove the component exists. ``CT=0.05`` is a default value for all the samples. By setting ``CT=0`` you get an algorithm very similar to the standard Stauffer&Grimson algorithm. - - .. ocv:member:: uchar nShadowDetection - - The value for marking shadow pixels in the output foreground mask. Default value is 127. - - .. ocv:member:: float fTau - - Shadow threshold. The shadow is detected if the pixel is a darker version of the background. ``Tau`` is a threshold defining how much darker the shadow can be. ``Tau= 0.5`` means that if a pixel is more than twice darker then it is not shadow. See [ShadowDetect2003]_. - - .. ocv:member:: bool bShadowDetection - - Parameter defining whether shadow detection should be enabled. - -.. seealso:: :ocv:class:`BackgroundSubtractorMOG2` - - - -gpu::MOG2_GPU::MOG2_GPU ------------------------ -The constructor. - -.. ocv:function:: gpu::MOG2_GPU::MOG2_GPU(int nmixtures = -1) - - :param nmixtures: Number of Gaussian mixtures. - -Default constructor sets all parameters to default values. - - - -gpu::MOG2_GPU::operator() -------------------------- -Updates the background model and returns the foreground mask. - -.. ocv:function:: void gpu::MOG2_GPU::operator()( const GpuMat& frame, GpuMat& fgmask, float learningRate=-1.0f, Stream& stream=Stream::Null() ) - - :param frame: Next video frame. - - :param fgmask: The output foreground mask as an 8-bit binary image. - - :param stream: Stream for the asynchronous version. - - - -gpu::MOG2_GPU::getBackgroundImage ---------------------------------- -Computes a background image. - -.. ocv:function:: void gpu::MOG2_GPU::getBackgroundImage(GpuMat& backgroundImage, Stream& stream = Stream::Null()) const - - :param backgroundImage: The output background image. - - :param stream: Stream for the asynchronous version. - - - -gpu::MOG2_GPU::release ----------------------- -Releases all inner buffer's memory. - -.. ocv:function:: void gpu::MOG2_GPU::release() - - - -gpu::VIBE_GPU -------------- -.. ocv:class:: gpu::VIBE_GPU - -Class used for background/foreground segmentation. :: - - class VIBE_GPU - { - public: - explicit VIBE_GPU(unsigned long rngSeed = 1234567); - - void initialize(const GpuMat& firstFrame, Stream& stream = Stream::Null()); - - void operator()(const GpuMat& frame, GpuMat& fgmask, Stream& stream = Stream::Null()); - - void release(); - - ... - }; - -The class discriminates between foreground and background pixels by building and maintaining a model of the background. Any pixel which does not fit this model is then deemed to be foreground. The class implements algorithm described in [VIBE2011]_. - - - -gpu::VIBE_GPU::VIBE_GPU ------------------------ -The constructor. - -.. ocv:function:: gpu::VIBE_GPU::VIBE_GPU(unsigned long rngSeed = 1234567) - - :param rngSeed: Value used to initiate a random sequence. - -Default constructor sets all parameters to default values. - - - -gpu::VIBE_GPU::initialize -------------------------- -Initialize background model and allocates all inner buffers. - -.. ocv:function:: void gpu::VIBE_GPU::initialize(const GpuMat& firstFrame, Stream& stream = Stream::Null()) - - :param firstFrame: First frame from video sequence. - - :param stream: Stream for the asynchronous version. - - - -gpu::VIBE_GPU::operator() -------------------------- -Updates the background model and returns the foreground mask - -.. ocv:function:: void gpu::VIBE_GPU::operator()(const GpuMat& frame, GpuMat& fgmask, Stream& stream = Stream::Null()) - - :param frame: Next video frame. - - :param fgmask: The output foreground mask as an 8-bit binary image. - - :param stream: Stream for the asynchronous version. - - - -gpu::VIBE_GPU::release ----------------------- -Releases all inner buffer's memory. - -.. ocv:function:: void gpu::VIBE_GPU::release() - - - -gpu::GMG_GPU ------------- -.. ocv:class:: gpu::GMG_GPU - - Class used for background/foreground segmentation. :: - - class GMG_GPU_GPU - { - public: - GMG_GPU(); - - void initialize(Size frameSize, float min = 0.0f, float max = 255.0f); - - void operator ()(const GpuMat& frame, GpuMat& fgmask, float learningRate = -1.0f, Stream& stream = Stream::Null()); - - void release(); - - int maxFeatures; - float learningRate; - int numInitializationFrames; - int quantizationLevels; - float backgroundPrior; - float decisionThreshold; - int smoothingRadius; - - ... - }; - - The class discriminates between foreground and background pixels by building and maintaining a model of the background. Any pixel which does not fit this model is then deemed to be foreground. The class implements algorithm described in [GMG2012]_. - - Here are important members of the class that control the algorithm, which you can set after constructing the class instance: - - .. ocv:member:: int maxFeatures - - Total number of distinct colors to maintain in histogram. - - .. ocv:member:: float learningRate - - Set between 0.0 and 1.0, determines how quickly features are "forgotten" from histograms. - - .. ocv:member:: int numInitializationFrames - - Number of frames of video to use to initialize histograms. - - .. ocv:member:: int quantizationLevels - - Number of discrete levels in each channel to be used in histograms. - - .. ocv:member:: float backgroundPrior - - Prior probability that any given pixel is a background pixel. A sensitivity parameter. - - .. ocv:member:: float decisionThreshold - - Value above which pixel is determined to be FG. - - .. ocv:member:: float smoothingRadius - - Smoothing radius, in pixels, for cleaning up FG image. - - - -gpu::GMG_GPU::GMG_GPU ---------------------- -The default constructor. - -.. ocv:function:: gpu::GMG_GPU::GMG_GPU() - -Default constructor sets all parameters to default values. - - - -gpu::GMG_GPU::initialize ------------------------- -Initialize background model and allocates all inner buffers. - -.. ocv:function:: void gpu::GMG_GPU::initialize(Size frameSize, float min = 0.0f, float max = 255.0f) - - :param frameSize: Input frame size. - - :param min: Minimum value taken on by pixels in image sequence. Usually 0. - - :param max: Maximum value taken on by pixels in image sequence, e.g. 1.0 or 255. - - - -gpu::GMG_GPU::operator() ------------------------- -Updates the background model and returns the foreground mask - -.. ocv:function:: void gpu::GMG_GPU::operator ()( const GpuMat& frame, GpuMat& fgmask, float learningRate=-1.0f, Stream& stream=Stream::Null() ) - - :param frame: Next video frame. - - :param fgmask: The output foreground mask as an 8-bit binary image. - - :param stream: Stream for the asynchronous version. - - - -gpu::GMG_GPU::release ---------------------- -Releases all inner buffer's memory. - -.. ocv:function:: void gpu::GMG_GPU::release() - - - -gpu::VideoWriter_GPU ---------------------- -Video writer class. - -.. ocv:class:: gpu::VideoWriter_GPU - -The class uses H264 video codec. - -.. note:: Currently only Windows platform is supported. - - - -gpu::VideoWriter_GPU::VideoWriter_GPU -------------------------------------- -Constructors. - -.. ocv:function:: gpu::VideoWriter_GPU::VideoWriter_GPU() -.. ocv:function:: gpu::VideoWriter_GPU::VideoWriter_GPU(const std::string& fileName, cv::Size frameSize, double fps, SurfaceFormat format = SF_BGR) -.. ocv:function:: gpu::VideoWriter_GPU::VideoWriter_GPU(const std::string& fileName, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format = SF_BGR) -.. ocv:function:: gpu::VideoWriter_GPU::VideoWriter_GPU(const cv::Ptr& encoderCallback, cv::Size frameSize, double fps, SurfaceFormat format = SF_BGR) -.. ocv:function:: gpu::VideoWriter_GPU::VideoWriter_GPU(const cv::Ptr& encoderCallback, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format = SF_BGR) - - :param fileName: Name of the output video file. Only AVI file format is supported. - - :param frameSize: Size of the input video frames. - - :param fps: Framerate of the created video stream. - - :param params: Encoder parameters. See :ocv:struct:`gpu::VideoWriter_GPU::EncoderParams` . - - :param format: Surface format of input frames ( ``SF_UYVY`` , ``SF_YUY2`` , ``SF_YV12`` , ``SF_NV12`` , ``SF_IYUV`` , ``SF_BGR`` or ``SF_GRAY``). BGR or gray frames will be converted to YV12 format before encoding, frames with other formats will be used as is. - - :param encoderCallback: Callbacks for video encoder. See :ocv:class:`gpu::VideoWriter_GPU::EncoderCallBack` . Use it if you want to work with raw video stream. - -The constructors initialize video writer. FFMPEG is used to write videos. User can implement own multiplexing with :ocv:class:`gpu::VideoWriter_GPU::EncoderCallBack` . - - - -gpu::VideoWriter_GPU::open --------------------------- -Initializes or reinitializes video writer. - -.. ocv:function:: void gpu::VideoWriter_GPU::open(const std::string& fileName, cv::Size frameSize, double fps, SurfaceFormat format = SF_BGR) -.. ocv:function:: void gpu::VideoWriter_GPU::open(const std::string& fileName, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format = SF_BGR) -.. ocv:function:: void gpu::VideoWriter_GPU::open(const cv::Ptr& encoderCallback, cv::Size frameSize, double fps, SurfaceFormat format = SF_BGR) -.. ocv:function:: void gpu::VideoWriter_GPU::open(const cv::Ptr& encoderCallback, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format = SF_BGR) - -The method opens video writer. Parameters are the same as in the constructor :ocv:func:`gpu::VideoWriter_GPU::VideoWriter_GPU` . The method throws :ocv:class:`Exception` if error occurs. - - - -gpu::VideoWriter_GPU::isOpened ------------------------------- -Returns true if video writer has been successfully initialized. - -.. ocv:function:: bool gpu::VideoWriter_GPU::isOpened() const - - - -gpu::VideoWriter_GPU::close ---------------------------- -Releases the video writer. - -.. ocv:function:: void gpu::VideoWriter_GPU::close() - - - -gpu::VideoWriter_GPU::write ---------------------------- -Writes the next video frame. - -.. ocv:function:: void gpu::VideoWriter_GPU::write(const cv::gpu::GpuMat& image, bool lastFrame = false) - - :param image: The written frame. - - :param lastFrame: Indicates that it is end of stream. The parameter can be ignored. - -The method write the specified image to video file. The image must have the same size and the same surface format as has been specified when opening the video writer. - - - -gpu::VideoWriter_GPU::EncoderParams ------------------------------------ -.. ocv:struct:: gpu::VideoWriter_GPU::EncoderParams - -Different parameters for CUDA video encoder. :: - - struct EncoderParams - { - int P_Interval; // NVVE_P_INTERVAL, - int IDR_Period; // NVVE_IDR_PERIOD, - int DynamicGOP; // NVVE_DYNAMIC_GOP, - int RCType; // NVVE_RC_TYPE, - int AvgBitrate; // NVVE_AVG_BITRATE, - int PeakBitrate; // NVVE_PEAK_BITRATE, - int QP_Level_Intra; // NVVE_QP_LEVEL_INTRA, - int QP_Level_InterP; // NVVE_QP_LEVEL_INTER_P, - int QP_Level_InterB; // NVVE_QP_LEVEL_INTER_B, - int DeblockMode; // NVVE_DEBLOCK_MODE, - int ProfileLevel; // NVVE_PROFILE_LEVEL, - int ForceIntra; // NVVE_FORCE_INTRA, - int ForceIDR; // NVVE_FORCE_IDR, - int ClearStat; // NVVE_CLEAR_STAT, - int DIMode; // NVVE_SET_DEINTERLACE, - int Presets; // NVVE_PRESETS, - int DisableCabac; // NVVE_DISABLE_CABAC, - int NaluFramingType; // NVVE_CONFIGURE_NALU_FRAMING_TYPE - int DisableSPSPPS; // NVVE_DISABLE_SPS_PPS - - EncoderParams(); - explicit EncoderParams(const std::string& configFile); - - void load(const std::string& configFile); - void save(const std::string& configFile) const; - }; - - - -gpu::VideoWriter_GPU::EncoderParams::EncoderParams --------------------------------------------------- -Constructors. - -.. ocv:function:: gpu::VideoWriter_GPU::EncoderParams::EncoderParams() -.. ocv:function:: gpu::VideoWriter_GPU::EncoderParams::EncoderParams(const std::string& configFile) - - :param configFile: Config file name. - -Creates default parameters or reads parameters from config file. - - - -gpu::VideoWriter_GPU::EncoderParams::load ------------------------------------------ -Reads parameters from config file. - -.. ocv:function:: void gpu::VideoWriter_GPU::EncoderParams::load(const std::string& configFile) - - :param configFile: Config file name. - - - -gpu::VideoWriter_GPU::EncoderParams::save ------------------------------------------ -Saves parameters to config file. - -.. ocv:function:: void gpu::VideoWriter_GPU::EncoderParams::save(const std::string& configFile) const - - :param configFile: Config file name. - - - -gpu::VideoWriter_GPU::EncoderCallBack -------------------------------------- -.. ocv:class:: gpu::VideoWriter_GPU::EncoderCallBack - -Callbacks for CUDA video encoder. :: - - class EncoderCallBack - { - public: - enum PicType - { - IFRAME = 1, - PFRAME = 2, - BFRAME = 3 - }; - - virtual ~EncoderCallBack() {} - - virtual unsigned char* acquireBitStream(int* bufferSize) = 0; - virtual void releaseBitStream(unsigned char* data, int size) = 0; - virtual void onBeginFrame(int frameNumber, PicType picType) = 0; - virtual void onEndFrame(int frameNumber, PicType picType) = 0; - }; - - - -gpu::VideoWriter_GPU::EncoderCallBack::acquireBitStream -------------------------------------------------------- -Callback function to signal the start of bitstream that is to be encoded. - -.. ocv:function:: virtual uchar* gpu::VideoWriter_GPU::EncoderCallBack::acquireBitStream(int* bufferSize) = 0 - -Callback must allocate buffer for CUDA encoder and return pointer to it and it's size. - - - -gpu::VideoWriter_GPU::EncoderCallBack::releaseBitStream -------------------------------------------------------- -Callback function to signal that the encoded bitstream is ready to be written to file. - -.. ocv:function:: virtual void gpu::VideoWriter_GPU::EncoderCallBack::releaseBitStream(unsigned char* data, int size) = 0 - - - -gpu::VideoWriter_GPU::EncoderCallBack::onBeginFrame ---------------------------------------------------- -Callback function to signal that the encoding operation on the frame has started. - -.. ocv:function:: virtual void gpu::VideoWriter_GPU::EncoderCallBack::onBeginFrame(int frameNumber, PicType picType) = 0 - - :param picType: Specify frame type (I-Frame, P-Frame or B-Frame). - - - -gpu::VideoWriter_GPU::EncoderCallBack::onEndFrame -------------------------------------------------- -Callback function signals that the encoding operation on the frame has finished. - -.. ocv:function:: virtual void gpu::VideoWriter_GPU::EncoderCallBack::onEndFrame(int frameNumber, PicType picType) = 0 - - :param picType: Specify frame type (I-Frame, P-Frame or B-Frame). - - - -gpu::VideoReader_GPU --------------------- -Class for reading video from files. - -.. ocv:class:: gpu::VideoReader_GPU - -.. note:: Currently only Windows and Linux platforms are supported. - - - -gpu::VideoReader_GPU::Codec ---------------------------- - -Video codecs supported by :ocv:class:`gpu::VideoReader_GPU` . - -.. ocv:enum:: gpu::VideoReader_GPU::Codec - - .. ocv:emember:: MPEG1 = 0 - .. ocv:emember:: MPEG2 - .. ocv:emember:: MPEG4 - .. ocv:emember:: VC1 - .. ocv:emember:: H264 - .. ocv:emember:: JPEG - .. ocv:emember:: H264_SVC - .. ocv:emember:: H264_MVC - - .. ocv:emember:: Uncompressed_YUV420 = (('I'<<24)|('Y'<<16)|('U'<<8)|('V')) - - Y,U,V (4:2:0) - - .. ocv:emember:: Uncompressed_YV12 = (('Y'<<24)|('V'<<16)|('1'<<8)|('2')) - - Y,V,U (4:2:0) - - .. ocv:emember:: Uncompressed_NV12 = (('N'<<24)|('V'<<16)|('1'<<8)|('2')) - - Y,UV (4:2:0) - - .. ocv:emember:: Uncompressed_YUYV = (('Y'<<24)|('U'<<16)|('Y'<<8)|('V')) - - YUYV/YUY2 (4:2:2) - - .. ocv:emember:: Uncompressed_UYVY = (('U'<<24)|('Y'<<16)|('V'<<8)|('Y')) - - UYVY (4:2:2) - - -gpu::VideoReader_GPU::ChromaFormat ----------------------------------- - -Chroma formats supported by :ocv:class:`gpu::VideoReader_GPU` . - -.. ocv:enum:: gpu::VideoReader_GPU::ChromaFormat - - .. ocv:emember:: Monochrome = 0 - .. ocv:emember:: YUV420 - .. ocv:emember:: YUV422 - .. ocv:emember:: YUV444 - - -gpu::VideoReader_GPU::FormatInfo --------------------------------- -.. ocv:struct:: gpu::VideoReader_GPU::FormatInfo - -Struct providing information about video file format. :: - - struct FormatInfo - { - Codec codec; - ChromaFormat chromaFormat; - int width; - int height; - }; - - -gpu::VideoReader_GPU::VideoReader_GPU -------------------------------------- -Constructors. - -.. ocv:function:: gpu::VideoReader_GPU::VideoReader_GPU() -.. ocv:function:: gpu::VideoReader_GPU::VideoReader_GPU(const std::string& filename) -.. ocv:function:: gpu::VideoReader_GPU::VideoReader_GPU(const cv::Ptr& source) - - :param filename: Name of the input video file. - - :param source: Video file parser implemented by user. - -The constructors initialize video reader. FFMPEG is used to read videos. User can implement own demultiplexing with :ocv:class:`gpu::VideoReader_GPU::VideoSource` . - - - -gpu::VideoReader_GPU::open --------------------------- -Initializes or reinitializes video reader. - -.. ocv:function:: void gpu::VideoReader_GPU::open(const std::string& filename) -.. ocv:function:: void gpu::VideoReader_GPU::open(const cv::Ptr& source) - -The method opens video reader. Parameters are the same as in the constructor :ocv:func:`gpu::VideoReader_GPU::VideoReader_GPU` . The method throws :ocv:class:`Exception` if error occurs. - - - -gpu::VideoReader_GPU::isOpened ------------------------------- -Returns true if video reader has been successfully initialized. - -.. ocv:function:: bool gpu::VideoReader_GPU::isOpened() const - - - -gpu::VideoReader_GPU::close ---------------------------- -Releases the video reader. - -.. ocv:function:: void gpu::VideoReader_GPU::close() - - - -gpu::VideoReader_GPU::read --------------------------- -Grabs, decodes and returns the next video frame. - -.. ocv:function:: bool gpu::VideoReader_GPU::read(GpuMat& image) - -If no frames has been grabbed (there are no more frames in video file), the methods return ``false`` . The method throws :ocv:class:`Exception` if error occurs. - - - -gpu::VideoReader_GPU::format ----------------------------- -Returns information about video file format. - -.. ocv:function:: FormatInfo gpu::VideoReader_GPU::format() const - -The method throws :ocv:class:`Exception` if video reader wasn't initialized. - - - -gpu::VideoReader_GPU::dumpFormat --------------------------------- -Dump information about video file format to specified stream. - -.. ocv:function:: void gpu::VideoReader_GPU::dumpFormat(std::ostream& st) - - :param st: Output stream. - -The method throws :ocv:class:`Exception` if video reader wasn't initialized. - - - -gpu::VideoReader_GPU::VideoSource ------------------------------------ -.. ocv:class:: gpu::VideoReader_GPU::VideoSource - -Interface for video demultiplexing. :: - - class VideoSource - { - public: - VideoSource(); - virtual ~VideoSource() {} - - virtual FormatInfo format() const = 0; - virtual void start() = 0; - virtual void stop() = 0; - virtual bool isStarted() const = 0; - virtual bool hasError() const = 0; - - protected: - bool parseVideoData(const unsigned char* data, size_t size, bool endOfStream = false); - }; - -User can implement own demultiplexing by implementing this interface. - - - -gpu::VideoReader_GPU::VideoSource::format ------------------------------------------ -Returns information about video file format. - -.. ocv:function:: virtual FormatInfo gpu::VideoReader_GPU::VideoSource::format() const = 0 - - - -gpu::VideoReader_GPU::VideoSource::start ----------------------------------------- -Starts processing. - -.. ocv:function:: virtual void gpu::VideoReader_GPU::VideoSource::start() = 0 - -Implementation must create own thread with video processing and call periodic :ocv:func:`gpu::VideoReader_GPU::VideoSource::parseVideoData` . - - - -gpu::VideoReader_GPU::VideoSource::stop ---------------------------------------- -Stops processing. - -.. ocv:function:: virtual void gpu::VideoReader_GPU::VideoSource::stop() = 0 - - - -gpu::VideoReader_GPU::VideoSource::isStarted --------------------------------------------- -Returns ``true`` if processing was successfully started. - -.. ocv:function:: virtual bool gpu::VideoReader_GPU::VideoSource::isStarted() const = 0 - - - -gpu::VideoReader_GPU::VideoSource::hasError -------------------------------------------- -Returns ``true`` if error occured during processing. - -.. ocv:function:: virtual bool gpu::VideoReader_GPU::VideoSource::hasError() const = 0 - - - -gpu::VideoReader_GPU::VideoSource::parseVideoData -------------------------------------------------- -Parse next video frame. Implementation must call this method after new frame was grabbed. - -.. ocv:function:: bool gpu::VideoReader_GPU::VideoSource::parseVideoData(const uchar* data, size_t size, bool endOfStream = false) - - :param data: Pointer to frame data. Can be ``NULL`` if ``endOfStream`` if ``true`` . - - :param size: Size in bytes of current frame. - - :param endOfStream: Indicates that it is end of stream. - - - -.. [Brox2004] T. Brox, A. Bruhn, N. Papenberg, J. Weickert. *High accuracy optical flow estimation based on a theory for warping*. ECCV 2004. -.. [FGD2003] Liyuan Li, Weimin Huang, Irene Y.H. Gu, and Qi Tian. *Foreground Object Detection from Videos Containing Complex Background*. ACM MM2003 9p, 2003. -.. [MOG2001] P. KadewTraKuPong and R. Bowden. *An improved adaptive background mixture model for real-time tracking with shadow detection*. Proc. 2nd European Workshop on Advanced Video-Based Surveillance Systems, 2001 -.. [MOG2004] Z. Zivkovic. *Improved adaptive Gausian mixture model for background subtraction*. International Conference Pattern Recognition, UK, August, 2004 -.. [ShadowDetect2003] Prati, Mikic, Trivedi and Cucchiarra. *Detecting Moving Shadows...*. IEEE PAMI, 2003 -.. [VIBE2011] O. Barnich and M. Van D Roogenbroeck. *ViBe: A universal background subtraction algorithm for video sequences*. IEEE Transactions on Image Processing, 20(6) :1709-1724, June 2011 -.. [GMG2012] A. Godbehere, A. Matsukawa and K. Goldberg. *Visual Tracking of Human Visitors under Variable-Lighting Conditions for a Responsive Audio Art Installation*. American Control Conference, Montreal, June 2012 diff --git a/modules/gpu/include/opencv2/gpu.hpp b/modules/gpu/include/opencv2/gpu.hpp index 21a03dc209..1b0120ba25 100644 --- a/modules/gpu/include/opencv2/gpu.hpp +++ b/modules/gpu/include/opencv2/gpu.hpp @@ -22,7 +22,7 @@ // // * 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 GpuMaterials provided with the distribution. +// 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. @@ -43,1051 +43,56 @@ #ifndef __OPENCV_GPU_HPP__ #define __OPENCV_GPU_HPP__ -#ifndef SKIP_INCLUDES -#include -#include -#include +#ifndef __cplusplus +# error gpu.hpp header must be compiled as C++ #endif -#include "opencv2/core/gpumat.hpp" -#include "opencv2/imgproc.hpp" -#include "opencv2/objdetect.hpp" -#include "opencv2/features2d.hpp" +#include "opencv2/core/gpu.hpp" + +#if !defined(__OPENCV_BUILD) && !defined(OPENCV_GPU_SKIP_INCLUDE) + #include "opencv2/opencv_modules.hpp" + + #ifdef HAVE_OPENCV_GPUARITHM + #include "opencv2/gpuarithm.hpp" + #endif + + #ifdef HAVE_OPENCV_GPUWARPING + #include "opencv2/gpuwarping.hpp" + #endif + + #ifdef HAVE_OPENCV_GPUFILTERS + #include "opencv2/gpufilters.hpp" + #endif + + #ifdef HAVE_OPENCV_GPUIMGPROC + #include "opencv2/gpuimgproc.hpp" + #endif + + #ifdef HAVE_OPENCV_GPUFEATURES2D + #include "opencv2/gpufeatures2d.hpp" + #endif + + #ifdef HAVE_OPENCV_GPUOPTFLOW + #include "opencv2/gpuoptflow.hpp" + #endif + + #ifdef HAVE_OPENCV_GPUBGSEGM + #include "opencv2/gpubgsegm.hpp" + #endif + + #ifdef HAVE_OPENCV_GPUSTEREO + #include "opencv2/gpustereo.hpp" + #endif + + #ifdef HAVE_OPENCV_GPUCODEC + #include "opencv2/gpucodec.hpp" + #endif +#endif namespace cv { namespace gpu { -//////////////////////////////// Filter Engine //////////////////////////////// - -/*! -The Base Class for 1D or Row-wise Filters - -This is the base class for linear or non-linear filters that process 1D data. -In particular, such filters are used for the "horizontal" filtering parts in separable filters. -*/ -class CV_EXPORTS BaseRowFilter_GPU -{ -public: - BaseRowFilter_GPU(int ksize_, int anchor_) : ksize(ksize_), anchor(anchor_) {} - virtual ~BaseRowFilter_GPU() {} - virtual void operator()(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()) = 0; - int ksize, anchor; -}; - -/*! -The Base Class for Column-wise Filters - -This is the base class for linear or non-linear filters that process columns of 2D arrays. -Such filters are used for the "vertical" filtering parts in separable filters. -*/ -class CV_EXPORTS BaseColumnFilter_GPU -{ -public: - BaseColumnFilter_GPU(int ksize_, int anchor_) : ksize(ksize_), anchor(anchor_) {} - virtual ~BaseColumnFilter_GPU() {} - virtual void operator()(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()) = 0; - int ksize, anchor; -}; - -/*! -The Base Class for Non-Separable 2D Filters. - -This is the base class for linear or non-linear 2D filters. -*/ -class CV_EXPORTS BaseFilter_GPU -{ -public: - BaseFilter_GPU(const Size& ksize_, const Point& anchor_) : ksize(ksize_), anchor(anchor_) {} - virtual ~BaseFilter_GPU() {} - virtual void operator()(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()) = 0; - Size ksize; - Point anchor; -}; - -/*! -The Base Class for Filter Engine. - -The class can be used to apply an arbitrary filtering operation to an image. -It contains all the necessary intermediate buffers. -*/ -class CV_EXPORTS FilterEngine_GPU -{ -public: - virtual ~FilterEngine_GPU() {} - - virtual void apply(const GpuMat& src, GpuMat& dst, Rect roi = Rect(0,0,-1,-1), Stream& stream = Stream::Null()) = 0; -}; - -//! returns the non-separable filter engine with the specified filter -CV_EXPORTS Ptr createFilter2D_GPU(const Ptr& filter2D, int srcType, int dstType); - -//! returns the separable filter engine with the specified filters -CV_EXPORTS Ptr createSeparableFilter_GPU(const Ptr& rowFilter, - const Ptr& columnFilter, int srcType, int bufType, int dstType); -CV_EXPORTS Ptr createSeparableFilter_GPU(const Ptr& rowFilter, - const Ptr& columnFilter, int srcType, int bufType, int dstType, GpuMat& buf); - -//! returns horizontal 1D box filter -//! supports only CV_8UC1 source type and CV_32FC1 sum type -CV_EXPORTS Ptr getRowSumFilter_GPU(int srcType, int sumType, int ksize, int anchor = -1); - -//! returns vertical 1D box filter -//! supports only CV_8UC1 sum type and CV_32FC1 dst type -CV_EXPORTS Ptr getColumnSumFilter_GPU(int sumType, int dstType, int ksize, int anchor = -1); - -//! returns 2D box filter -//! supports CV_8UC1 and CV_8UC4 source type, dst type must be the same as source type -CV_EXPORTS Ptr getBoxFilter_GPU(int srcType, int dstType, const Size& ksize, Point anchor = Point(-1, -1)); - -//! returns box filter engine -CV_EXPORTS Ptr createBoxFilter_GPU(int srcType, int dstType, const Size& ksize, - const Point& anchor = Point(-1,-1)); - -//! returns 2D morphological filter -//! only MORPH_ERODE and MORPH_DILATE are supported -//! supports CV_8UC1 and CV_8UC4 types -//! kernel must have CV_8UC1 type, one rows and cols == ksize.width * ksize.height -CV_EXPORTS Ptr getMorphologyFilter_GPU(int op, int type, const Mat& kernel, const Size& ksize, - Point anchor=Point(-1,-1)); - -//! returns morphological filter engine. Only MORPH_ERODE and MORPH_DILATE are supported. -CV_EXPORTS Ptr createMorphologyFilter_GPU(int op, int type, const Mat& kernel, - const Point& anchor = Point(-1,-1), int iterations = 1); -CV_EXPORTS Ptr createMorphologyFilter_GPU(int op, int type, const Mat& kernel, GpuMat& buf, - const Point& anchor = Point(-1,-1), int iterations = 1); - -//! returns 2D filter with the specified kernel -//! supports CV_8U, CV_16U and CV_32F one and four channel image -CV_EXPORTS Ptr getLinearFilter_GPU(int srcType, int dstType, const Mat& kernel, Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT); - -//! returns the non-separable linear filter engine -CV_EXPORTS Ptr createLinearFilter_GPU(int srcType, int dstType, const Mat& kernel, - Point anchor = Point(-1,-1), int borderType = BORDER_DEFAULT); - -//! returns the primitive row filter with the specified kernel. -//! supports only CV_8UC1, CV_8UC4, CV_16SC1, CV_16SC2, CV_32SC1, CV_32FC1 source type. -//! there are two version of algorithm: NPP and OpenCV. -//! NPP calls when srcType == CV_8UC1 or srcType == CV_8UC4 and bufType == srcType, -//! otherwise calls OpenCV version. -//! NPP supports only BORDER_CONSTANT border type. -//! OpenCV version supports only CV_32F as buffer depth and -//! BORDER_REFLECT101, BORDER_REPLICATE and BORDER_CONSTANT border types. -CV_EXPORTS Ptr getLinearRowFilter_GPU(int srcType, int bufType, const Mat& rowKernel, - int anchor = -1, int borderType = BORDER_DEFAULT); - -//! returns the primitive column filter with the specified kernel. -//! supports only CV_8UC1, CV_8UC4, CV_16SC1, CV_16SC2, CV_32SC1, CV_32FC1 dst type. -//! there are two version of algorithm: NPP and OpenCV. -//! NPP calls when dstType == CV_8UC1 or dstType == CV_8UC4 and bufType == dstType, -//! otherwise calls OpenCV version. -//! NPP supports only BORDER_CONSTANT border type. -//! OpenCV version supports only CV_32F as buffer depth and -//! BORDER_REFLECT101, BORDER_REPLICATE and BORDER_CONSTANT border types. -CV_EXPORTS Ptr getLinearColumnFilter_GPU(int bufType, int dstType, const Mat& columnKernel, - int anchor = -1, int borderType = BORDER_DEFAULT); - -//! returns the separable linear filter engine -CV_EXPORTS Ptr createSeparableLinearFilter_GPU(int srcType, int dstType, const Mat& rowKernel, - const Mat& columnKernel, const Point& anchor = Point(-1,-1), int rowBorderType = BORDER_DEFAULT, - int columnBorderType = -1); -CV_EXPORTS Ptr createSeparableLinearFilter_GPU(int srcType, int dstType, const Mat& rowKernel, - const Mat& columnKernel, GpuMat& buf, const Point& anchor = Point(-1,-1), int rowBorderType = BORDER_DEFAULT, - int columnBorderType = -1); - -//! returns filter engine for the generalized Sobel operator -CV_EXPORTS Ptr createDerivFilter_GPU(int srcType, int dstType, int dx, int dy, int ksize, - int rowBorderType = BORDER_DEFAULT, int columnBorderType = -1); -CV_EXPORTS Ptr createDerivFilter_GPU(int srcType, int dstType, int dx, int dy, int ksize, GpuMat& buf, - int rowBorderType = BORDER_DEFAULT, int columnBorderType = -1); - -//! returns the Gaussian filter engine -CV_EXPORTS Ptr createGaussianFilter_GPU(int type, Size ksize, double sigma1, double sigma2 = 0, - int rowBorderType = BORDER_DEFAULT, int columnBorderType = -1); -CV_EXPORTS Ptr createGaussianFilter_GPU(int type, Size ksize, GpuMat& buf, double sigma1, double sigma2 = 0, - int rowBorderType = BORDER_DEFAULT, int columnBorderType = -1); - -//! returns maximum filter -CV_EXPORTS Ptr getMaxFilter_GPU(int srcType, int dstType, const Size& ksize, Point anchor = Point(-1,-1)); - -//! returns minimum filter -CV_EXPORTS Ptr getMinFilter_GPU(int srcType, int dstType, const Size& ksize, Point anchor = Point(-1,-1)); - -//! smooths the image using the normalized box filter -//! supports CV_8UC1, CV_8UC4 types -CV_EXPORTS void boxFilter(const GpuMat& src, GpuMat& dst, int ddepth, Size ksize, Point anchor = Point(-1,-1), Stream& stream = Stream::Null()); - -//! a synonym for normalized box filter -static inline void blur(const GpuMat& src, GpuMat& dst, Size ksize, Point anchor = Point(-1,-1), Stream& stream = Stream::Null()) -{ - boxFilter(src, dst, -1, ksize, anchor, stream); -} - -//! erodes the image (applies the local minimum operator) -CV_EXPORTS void erode(const GpuMat& src, GpuMat& dst, const Mat& kernel, Point anchor = Point(-1, -1), int iterations = 1); -CV_EXPORTS void erode(const GpuMat& src, GpuMat& dst, const Mat& kernel, GpuMat& buf, - Point anchor = Point(-1, -1), int iterations = 1, - Stream& stream = Stream::Null()); - -//! dilates the image (applies the local maximum operator) -CV_EXPORTS void dilate(const GpuMat& src, GpuMat& dst, const Mat& kernel, Point anchor = Point(-1, -1), int iterations = 1); -CV_EXPORTS void dilate(const GpuMat& src, GpuMat& dst, const Mat& kernel, GpuMat& buf, - Point anchor = Point(-1, -1), int iterations = 1, - Stream& stream = Stream::Null()); - -//! applies an advanced morphological operation to the image -CV_EXPORTS void morphologyEx(const GpuMat& src, GpuMat& dst, int op, const Mat& kernel, Point anchor = Point(-1, -1), int iterations = 1); -CV_EXPORTS void morphologyEx(const GpuMat& src, GpuMat& dst, int op, const Mat& kernel, GpuMat& buf1, GpuMat& buf2, - Point anchor = Point(-1, -1), int iterations = 1, Stream& stream = Stream::Null()); - -//! applies non-separable 2D linear filter to the image -CV_EXPORTS void filter2D(const GpuMat& src, GpuMat& dst, int ddepth, const Mat& kernel, Point anchor=Point(-1,-1), int borderType = BORDER_DEFAULT, Stream& stream = Stream::Null()); - -//! applies separable 2D linear filter to the image -CV_EXPORTS void sepFilter2D(const GpuMat& src, GpuMat& dst, int ddepth, const Mat& kernelX, const Mat& kernelY, - Point anchor = Point(-1,-1), int rowBorderType = BORDER_DEFAULT, int columnBorderType = -1); -CV_EXPORTS void sepFilter2D(const GpuMat& src, GpuMat& dst, int ddepth, const Mat& kernelX, const Mat& kernelY, GpuMat& buf, - Point anchor = Point(-1,-1), int rowBorderType = BORDER_DEFAULT, int columnBorderType = -1, - Stream& stream = Stream::Null()); - -//! applies generalized Sobel operator to the image -CV_EXPORTS void Sobel(const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy, int ksize = 3, double scale = 1, - int rowBorderType = BORDER_DEFAULT, int columnBorderType = -1); -CV_EXPORTS void Sobel(const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy, GpuMat& buf, int ksize = 3, double scale = 1, - int rowBorderType = BORDER_DEFAULT, int columnBorderType = -1, Stream& stream = Stream::Null()); - -//! applies the vertical or horizontal Scharr operator to the image -CV_EXPORTS void Scharr(const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy, double scale = 1, - int rowBorderType = BORDER_DEFAULT, int columnBorderType = -1); -CV_EXPORTS void Scharr(const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy, GpuMat& buf, double scale = 1, - int rowBorderType = BORDER_DEFAULT, int columnBorderType = -1, Stream& stream = Stream::Null()); - -//! smooths the image using Gaussian filter. -CV_EXPORTS void GaussianBlur(const GpuMat& src, GpuMat& dst, Size ksize, double sigma1, double sigma2 = 0, - int rowBorderType = BORDER_DEFAULT, int columnBorderType = -1); -CV_EXPORTS void GaussianBlur(const GpuMat& src, GpuMat& dst, Size ksize, GpuMat& buf, double sigma1, double sigma2 = 0, - int rowBorderType = BORDER_DEFAULT, int columnBorderType = -1, Stream& stream = Stream::Null()); - -//! applies Laplacian operator to the image -//! supports only ksize = 1 and ksize = 3 -CV_EXPORTS void Laplacian(const GpuMat& src, GpuMat& dst, int ddepth, int ksize = 1, double scale = 1, int borderType = BORDER_DEFAULT, Stream& stream = Stream::Null()); - - -////////////////////////////// Arithmetics /////////////////////////////////// - -//! implements generalized matrix product algorithm GEMM from BLAS -CV_EXPORTS void gemm(const GpuMat& src1, const GpuMat& src2, double alpha, - const GpuMat& src3, double beta, GpuMat& dst, int flags = 0, Stream& stream = Stream::Null()); - -//! transposes the matrix -//! supports matrix with element size = 1, 4 and 8 bytes (CV_8UC1, CV_8UC4, CV_16UC2, CV_32FC1, etc) -CV_EXPORTS void transpose(const GpuMat& src1, GpuMat& dst, Stream& stream = Stream::Null()); - -//! reverses the order of the rows, columns or both in a matrix -//! supports 1, 3 and 4 channels images with CV_8U, CV_16U, CV_32S or CV_32F depth -CV_EXPORTS void flip(const GpuMat& a, GpuMat& b, int flipCode, Stream& stream = Stream::Null()); - -//! transforms 8-bit unsigned integers using lookup table: dst(i)=lut(src(i)) -//! destination array will have the depth type as lut and the same channels number as source -//! supports CV_8UC1, CV_8UC3 types -CV_EXPORTS void LUT(const GpuMat& src, const Mat& lut, GpuMat& dst, Stream& stream = Stream::Null()); - -//! makes multi-channel array out of several single-channel arrays -CV_EXPORTS void merge(const GpuMat* src, size_t n, GpuMat& dst, Stream& stream = Stream::Null()); - -//! makes multi-channel array out of several single-channel arrays -CV_EXPORTS void merge(const std::vector& src, GpuMat& dst, Stream& stream = Stream::Null()); - -//! copies each plane of a multi-channel array to a dedicated array -CV_EXPORTS void split(const GpuMat& src, GpuMat* dst, Stream& stream = Stream::Null()); - -//! copies each plane of a multi-channel array to a dedicated array -CV_EXPORTS void split(const GpuMat& src, std::vector& dst, Stream& stream = Stream::Null()); - -//! computes magnitude of complex (x(i).re, x(i).im) vector -//! supports only CV_32FC2 type -CV_EXPORTS void magnitude(const GpuMat& xy, GpuMat& magnitude, Stream& stream = Stream::Null()); - -//! computes squared magnitude of complex (x(i).re, x(i).im) vector -//! supports only CV_32FC2 type -CV_EXPORTS void magnitudeSqr(const GpuMat& xy, GpuMat& magnitude, Stream& stream = Stream::Null()); - -//! computes magnitude of each (x(i), y(i)) vector -//! supports only floating-point source -CV_EXPORTS void magnitude(const GpuMat& x, const GpuMat& y, GpuMat& magnitude, Stream& stream = Stream::Null()); - -//! computes squared magnitude of each (x(i), y(i)) vector -//! supports only floating-point source -CV_EXPORTS void magnitudeSqr(const GpuMat& x, const GpuMat& y, GpuMat& magnitude, Stream& stream = Stream::Null()); - -//! computes angle (angle(i)) of each (x(i), y(i)) vector -//! supports only floating-point source -CV_EXPORTS void phase(const GpuMat& x, const GpuMat& y, GpuMat& angle, bool angleInDegrees = false, Stream& stream = Stream::Null()); - -//! converts Cartesian coordinates to polar -//! supports only floating-point source -CV_EXPORTS void cartToPolar(const GpuMat& x, const GpuMat& y, GpuMat& magnitude, GpuMat& angle, bool angleInDegrees = false, Stream& stream = Stream::Null()); - -//! converts polar coordinates to Cartesian -//! supports only floating-point source -CV_EXPORTS void polarToCart(const GpuMat& magnitude, const GpuMat& angle, GpuMat& x, GpuMat& y, bool angleInDegrees = false, Stream& stream = Stream::Null()); - -//! scales and shifts array elements so that either the specified norm (alpha) or the minimum (alpha) and maximum (beta) array values get the specified values -CV_EXPORTS void normalize(const GpuMat& src, GpuMat& dst, double alpha = 1, double beta = 0, - int norm_type = NORM_L2, int dtype = -1, const GpuMat& mask = GpuMat()); -CV_EXPORTS void normalize(const GpuMat& src, GpuMat& dst, double a, double b, - int norm_type, int dtype, const GpuMat& mask, GpuMat& norm_buf, GpuMat& cvt_buf); - - -//////////////////////////// Per-element operations //////////////////////////////////// - -//! adds one matrix to another (c = a + b) -CV_EXPORTS void add(const GpuMat& a, const GpuMat& b, GpuMat& c, const GpuMat& mask = GpuMat(), int dtype = -1, Stream& stream = Stream::Null()); -//! adds scalar to a matrix (c = a + s) -CV_EXPORTS void add(const GpuMat& a, const Scalar& sc, GpuMat& c, const GpuMat& mask = GpuMat(), int dtype = -1, Stream& stream = Stream::Null()); - -//! subtracts one matrix from another (c = a - b) -CV_EXPORTS void subtract(const GpuMat& a, const GpuMat& b, GpuMat& c, const GpuMat& mask = GpuMat(), int dtype = -1, Stream& stream = Stream::Null()); -//! subtracts scalar from a matrix (c = a - s) -CV_EXPORTS void subtract(const GpuMat& a, const Scalar& sc, GpuMat& c, const GpuMat& mask = GpuMat(), int dtype = -1, Stream& stream = Stream::Null()); - -//! computes element-wise weighted product of the two arrays (c = scale * a * b) -CV_EXPORTS void multiply(const GpuMat& a, const GpuMat& b, GpuMat& c, double scale = 1, int dtype = -1, Stream& stream = Stream::Null()); -//! weighted multiplies matrix to a scalar (c = scale * a * s) -CV_EXPORTS void multiply(const GpuMat& a, const Scalar& sc, GpuMat& c, double scale = 1, int dtype = -1, Stream& stream = Stream::Null()); - -//! computes element-wise weighted quotient of the two arrays (c = a / b) -CV_EXPORTS void divide(const GpuMat& a, const GpuMat& b, GpuMat& c, double scale = 1, int dtype = -1, Stream& stream = Stream::Null()); -//! computes element-wise weighted quotient of matrix and scalar (c = a / s) -CV_EXPORTS void divide(const GpuMat& a, const Scalar& sc, GpuMat& c, double scale = 1, int dtype = -1, Stream& stream = Stream::Null()); -//! computes element-wise weighted reciprocal of an array (dst = scale/src2) -CV_EXPORTS void divide(double scale, const GpuMat& b, GpuMat& c, int dtype = -1, Stream& stream = Stream::Null()); - -//! computes the weighted sum of two arrays (dst = alpha*src1 + beta*src2 + gamma) -CV_EXPORTS void addWeighted(const GpuMat& src1, double alpha, const GpuMat& src2, double beta, double gamma, GpuMat& dst, - int dtype = -1, Stream& stream = Stream::Null()); - -//! adds scaled array to another one (dst = alpha*src1 + src2) -static inline void scaleAdd(const GpuMat& src1, double alpha, const GpuMat& src2, GpuMat& dst, Stream& stream = Stream::Null()) -{ - addWeighted(src1, alpha, src2, 1.0, 0.0, dst, -1, stream); -} - -//! computes element-wise absolute difference of two arrays (c = abs(a - b)) -CV_EXPORTS void absdiff(const GpuMat& a, const GpuMat& b, GpuMat& c, Stream& stream = Stream::Null()); -//! computes element-wise absolute difference of array and scalar (c = abs(a - s)) -CV_EXPORTS void absdiff(const GpuMat& a, const Scalar& s, GpuMat& c, Stream& stream = Stream::Null()); - -//! computes absolute value of each matrix element -//! supports CV_16S and CV_32F depth -CV_EXPORTS void abs(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()); - -//! computes square of each pixel in an image -//! supports CV_8U, CV_16U, CV_16S and CV_32F depth -CV_EXPORTS void sqr(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()); - -//! computes square root of each pixel in an image -//! supports CV_8U, CV_16U, CV_16S and CV_32F depth -CV_EXPORTS void sqrt(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()); - -//! computes exponent of each matrix element (b = e**a) -//! supports CV_8U, CV_16U, CV_16S and CV_32F depth -CV_EXPORTS void exp(const GpuMat& a, GpuMat& b, Stream& stream = Stream::Null()); - -//! computes natural logarithm of absolute value of each matrix element: b = log(abs(a)) -//! supports CV_8U, CV_16U, CV_16S and CV_32F depth -CV_EXPORTS void log(const GpuMat& a, GpuMat& b, Stream& stream = Stream::Null()); - -//! computes power of each matrix element: -// (dst(i,j) = pow( src(i,j) , power), if src.type() is integer -// (dst(i,j) = pow(fabs(src(i,j)), power), otherwise -//! supports all, except depth == CV_64F -CV_EXPORTS void pow(const GpuMat& src, double power, GpuMat& dst, Stream& stream = Stream::Null()); - -//! compares elements of two arrays (c = a b) -CV_EXPORTS void compare(const GpuMat& a, const GpuMat& b, GpuMat& c, int cmpop, Stream& stream = Stream::Null()); -CV_EXPORTS void compare(const GpuMat& a, Scalar sc, GpuMat& c, int cmpop, Stream& stream = Stream::Null()); - -//! performs per-elements bit-wise inversion -CV_EXPORTS void bitwise_not(const GpuMat& src, GpuMat& dst, const GpuMat& mask=GpuMat(), Stream& stream = Stream::Null()); - -//! calculates per-element bit-wise disjunction of two arrays -CV_EXPORTS void bitwise_or(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask=GpuMat(), Stream& stream = Stream::Null()); -//! calculates per-element bit-wise disjunction of array and scalar -//! supports 1, 3 and 4 channels images with CV_8U, CV_16U or CV_32S depth -CV_EXPORTS void bitwise_or(const GpuMat& src1, const Scalar& sc, GpuMat& dst, Stream& stream = Stream::Null()); - -//! calculates per-element bit-wise conjunction of two arrays -CV_EXPORTS void bitwise_and(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask=GpuMat(), Stream& stream = Stream::Null()); -//! calculates per-element bit-wise conjunction of array and scalar -//! supports 1, 3 and 4 channels images with CV_8U, CV_16U or CV_32S depth -CV_EXPORTS void bitwise_and(const GpuMat& src1, const Scalar& sc, GpuMat& dst, Stream& stream = Stream::Null()); - -//! calculates per-element bit-wise "exclusive or" operation -CV_EXPORTS void bitwise_xor(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask=GpuMat(), Stream& stream = Stream::Null()); -//! calculates per-element bit-wise "exclusive or" of array and scalar -//! supports 1, 3 and 4 channels images with CV_8U, CV_16U or CV_32S depth -CV_EXPORTS void bitwise_xor(const GpuMat& src1, const Scalar& sc, GpuMat& dst, Stream& stream = Stream::Null()); - -//! pixel by pixel right shift of an image by a constant value -//! supports 1, 3 and 4 channels images with integers elements -CV_EXPORTS void rshift(const GpuMat& src, Scalar_ sc, GpuMat& dst, Stream& stream = Stream::Null()); - -//! pixel by pixel left shift of an image by a constant value -//! supports 1, 3 and 4 channels images with CV_8U, CV_16U or CV_32S depth -CV_EXPORTS void lshift(const GpuMat& src, Scalar_ sc, GpuMat& dst, Stream& stream = Stream::Null()); - -//! computes per-element minimum of two arrays (dst = min(src1, src2)) -CV_EXPORTS void min(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Stream& stream = Stream::Null()); - -//! computes per-element minimum of array and scalar (dst = min(src1, src2)) -CV_EXPORTS void min(const GpuMat& src1, double src2, GpuMat& dst, Stream& stream = Stream::Null()); - -//! computes per-element maximum of two arrays (dst = max(src1, src2)) -CV_EXPORTS void max(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Stream& stream = Stream::Null()); - -//! computes per-element maximum of array and scalar (dst = max(src1, src2)) -CV_EXPORTS void max(const GpuMat& src1, double src2, GpuMat& dst, Stream& stream = Stream::Null()); - -enum { ALPHA_OVER, ALPHA_IN, ALPHA_OUT, ALPHA_ATOP, ALPHA_XOR, ALPHA_PLUS, ALPHA_OVER_PREMUL, ALPHA_IN_PREMUL, ALPHA_OUT_PREMUL, - ALPHA_ATOP_PREMUL, ALPHA_XOR_PREMUL, ALPHA_PLUS_PREMUL, ALPHA_PREMUL}; - -//! Composite two images using alpha opacity values contained in each image -//! Supports CV_8UC4, CV_16UC4, CV_32SC4 and CV_32FC4 types -CV_EXPORTS void alphaComp(const GpuMat& img1, const GpuMat& img2, GpuMat& dst, int alpha_op, Stream& stream = Stream::Null()); - - -////////////////////////////// Image processing ////////////////////////////// - -//! DST[x,y] = SRC[xmap[x,y],ymap[x,y]] -//! supports only CV_32FC1 map type -CV_EXPORTS void remap(const GpuMat& src, GpuMat& dst, const GpuMat& xmap, const GpuMat& ymap, - int interpolation, int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar(), - Stream& stream = Stream::Null()); - -//! Does mean shift filtering on GPU. -CV_EXPORTS void meanShiftFiltering(const GpuMat& src, GpuMat& dst, int sp, int sr, - TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1), - Stream& stream = Stream::Null()); - -//! Does mean shift procedure on GPU. -CV_EXPORTS void meanShiftProc(const GpuMat& src, GpuMat& dstr, GpuMat& dstsp, int sp, int sr, - TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1), - Stream& stream = Stream::Null()); - -//! Does mean shift segmentation with elimination of small regions. -CV_EXPORTS void meanShiftSegmentation(const GpuMat& src, Mat& dst, int sp, int sr, int minsize, - TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1)); - -//! Does coloring of disparity image: [0..ndisp) -> [0..240, 1, 1] in HSV. -//! Supported types of input disparity: CV_8U, CV_16S. -//! Output disparity has CV_8UC4 type in BGRA format (alpha = 255). -CV_EXPORTS void drawColorDisp(const GpuMat& src_disp, GpuMat& dst_disp, int ndisp, Stream& stream = Stream::Null()); - -//! Reprojects disparity image to 3D space. -//! Supports CV_8U and CV_16S types of input disparity. -//! The output is a 3- or 4-channel floating-point matrix. -//! Each element of this matrix will contain the 3D coordinates of the point (x,y,z,1), computed from the disparity map. -//! Q is the 4x4 perspective transformation matrix that can be obtained with cvStereoRectify. -CV_EXPORTS void reprojectImageTo3D(const GpuMat& disp, GpuMat& xyzw, const Mat& Q, int dst_cn = 4, Stream& stream = Stream::Null()); - -//! converts image from one color space to another -CV_EXPORTS void cvtColor(const GpuMat& src, GpuMat& dst, int code, int dcn = 0, Stream& stream = Stream::Null()); - -//! swap channels -//! dstOrder - Integer array describing how channel values are permutated. The n-th entry -//! of the array contains the number of the channel that is stored in the n-th channel of -//! the output image. E.g. Given an RGBA image, aDstOrder = [3,2,1,0] converts this to ABGR -//! channel order. -CV_EXPORTS void swapChannels(GpuMat& image, const int dstOrder[4], Stream& stream = Stream::Null()); - -//! Routines for correcting image color gamma -CV_EXPORTS void gammaCorrection(const GpuMat& src, GpuMat& dst, bool forward = true, Stream& stream = Stream::Null()); - -//! applies fixed threshold to the image -CV_EXPORTS double threshold(const GpuMat& src, GpuMat& dst, double thresh, double maxval, int type, Stream& stream = Stream::Null()); - -//! resizes the image -//! Supports INTER_NEAREST, INTER_LINEAR, INTER_CUBIC, INTER_AREA -CV_EXPORTS void resize(const GpuMat& src, GpuMat& dst, Size dsize, double fx=0, double fy=0, int interpolation = INTER_LINEAR, Stream& stream = Stream::Null()); - -//! warps the image using affine transformation -//! Supports INTER_NEAREST, INTER_LINEAR, INTER_CUBIC -CV_EXPORTS void warpAffine(const GpuMat& src, GpuMat& dst, const Mat& M, Size dsize, int flags = INTER_LINEAR, - int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar(), Stream& stream = Stream::Null()); - -CV_EXPORTS void buildWarpAffineMaps(const Mat& M, bool inverse, Size dsize, GpuMat& xmap, GpuMat& ymap, Stream& stream = Stream::Null()); - -//! warps the image using perspective transformation -//! Supports INTER_NEAREST, INTER_LINEAR, INTER_CUBIC -CV_EXPORTS void warpPerspective(const GpuMat& src, GpuMat& dst, const Mat& M, Size dsize, int flags = INTER_LINEAR, - int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar(), Stream& stream = Stream::Null()); - -CV_EXPORTS void buildWarpPerspectiveMaps(const Mat& M, bool inverse, Size dsize, GpuMat& xmap, GpuMat& ymap, Stream& stream = Stream::Null()); - -//! builds plane warping maps -CV_EXPORTS void buildWarpPlaneMaps(Size src_size, Rect dst_roi, const Mat &K, const Mat& R, const Mat &T, float scale, - GpuMat& map_x, GpuMat& map_y, Stream& stream = Stream::Null()); - -//! builds cylindrical warping maps -CV_EXPORTS void buildWarpCylindricalMaps(Size src_size, Rect dst_roi, const Mat &K, const Mat& R, float scale, - GpuMat& map_x, GpuMat& map_y, Stream& stream = Stream::Null()); - -//! builds spherical warping maps -CV_EXPORTS void buildWarpSphericalMaps(Size src_size, Rect dst_roi, const Mat &K, const Mat& R, float scale, - GpuMat& map_x, GpuMat& map_y, Stream& stream = Stream::Null()); - -//! rotates an image around the origin (0,0) and then shifts it -//! supports INTER_NEAREST, INTER_LINEAR, INTER_CUBIC -//! supports 1, 3 or 4 channels images with CV_8U, CV_16U or CV_32F depth -CV_EXPORTS void rotate(const GpuMat& src, GpuMat& dst, Size dsize, double angle, double xShift = 0, double yShift = 0, - int interpolation = INTER_LINEAR, Stream& stream = Stream::Null()); - -//! copies 2D array to a larger destination array and pads borders with user-specifiable constant -CV_EXPORTS void copyMakeBorder(const GpuMat& src, GpuMat& dst, int top, int bottom, int left, int right, int borderType, - const Scalar& value = Scalar(), Stream& stream = Stream::Null()); - -//! computes the integral image -//! sum will have CV_32S type, but will contain unsigned int values -//! supports only CV_8UC1 source type -CV_EXPORTS void integral(const GpuMat& src, GpuMat& sum, Stream& stream = Stream::Null()); -//! buffered version -CV_EXPORTS void integralBuffered(const GpuMat& src, GpuMat& sum, GpuMat& buffer, Stream& stream = Stream::Null()); - -//! computes squared integral image -//! result matrix will have 64F type, but will contain 64U values -//! supports source images of 8UC1 type only -CV_EXPORTS void sqrIntegral(const GpuMat& src, GpuMat& sqsum, Stream& stream = Stream::Null()); - -//! computes vertical sum, supports only CV_32FC1 images -CV_EXPORTS void columnSum(const GpuMat& src, GpuMat& sum); - -//! computes the standard deviation of integral images -//! supports only CV_32SC1 source type and CV_32FC1 sqr type -//! output will have CV_32FC1 type -CV_EXPORTS void rectStdDev(const GpuMat& src, const GpuMat& sqr, GpuMat& dst, const Rect& rect, Stream& stream = Stream::Null()); - -//! computes Harris cornerness criteria at each image pixel -CV_EXPORTS void cornerHarris(const GpuMat& src, GpuMat& dst, int blockSize, int ksize, double k, int borderType = BORDER_REFLECT101); -CV_EXPORTS void cornerHarris(const GpuMat& src, GpuMat& dst, GpuMat& Dx, GpuMat& Dy, int blockSize, int ksize, double k, int borderType = BORDER_REFLECT101); -CV_EXPORTS void cornerHarris(const GpuMat& src, GpuMat& dst, GpuMat& Dx, GpuMat& Dy, GpuMat& buf, int blockSize, int ksize, double k, - int borderType = BORDER_REFLECT101, Stream& stream = Stream::Null()); - -//! computes minimum eigen value of 2x2 derivative covariation matrix at each pixel - the cornerness criteria -CV_EXPORTS void cornerMinEigenVal(const GpuMat& src, GpuMat& dst, int blockSize, int ksize, int borderType=BORDER_REFLECT101); -CV_EXPORTS void cornerMinEigenVal(const GpuMat& src, GpuMat& dst, GpuMat& Dx, GpuMat& Dy, int blockSize, int ksize, int borderType=BORDER_REFLECT101); -CV_EXPORTS void cornerMinEigenVal(const GpuMat& src, GpuMat& dst, GpuMat& Dx, GpuMat& Dy, GpuMat& buf, int blockSize, int ksize, - int borderType=BORDER_REFLECT101, Stream& stream = Stream::Null()); - -//! performs per-element multiplication of two full (not packed) Fourier spectrums -//! supports 32FC2 matrixes only (interleaved format) -CV_EXPORTS void mulSpectrums(const GpuMat& a, const GpuMat& b, GpuMat& c, int flags, bool conjB=false, Stream& stream = Stream::Null()); - -//! performs per-element multiplication of two full (not packed) Fourier spectrums -//! supports 32FC2 matrixes only (interleaved format) -CV_EXPORTS void mulAndScaleSpectrums(const GpuMat& a, const GpuMat& b, GpuMat& c, int flags, float scale, bool conjB=false, Stream& stream = Stream::Null()); - -//! Performs a forward or inverse discrete Fourier transform (1D or 2D) of floating point matrix. -//! Param dft_size is the size of DFT transform. -//! -//! If the source matrix is not continous, then additional copy will be done, -//! so to avoid copying ensure the source matrix is continous one. If you want to use -//! preallocated output ensure it is continuous too, otherwise it will be reallocated. -//! -//! Being implemented via CUFFT real-to-complex transform result contains only non-redundant values -//! in CUFFT's format. Result as full complex matrix for such kind of transform cannot be retrieved. -//! -//! For complex-to-real transform it is assumed that the source matrix is packed in CUFFT's format. -CV_EXPORTS void dft(const GpuMat& src, GpuMat& dst, Size dft_size, int flags=0, Stream& stream = Stream::Null()); - -struct CV_EXPORTS ConvolveBuf -{ - Size result_size; - Size block_size; - Size user_block_size; - Size dft_size; - int spect_len; - - GpuMat image_spect, templ_spect, result_spect; - GpuMat image_block, templ_block, result_data; - - void create(Size image_size, Size templ_size); - static Size estimateBlockSize(Size result_size, Size templ_size); -}; - - -//! computes convolution (or cross-correlation) of two images using discrete Fourier transform -//! supports source images of 32FC1 type only -//! result matrix will have 32FC1 type -CV_EXPORTS void convolve(const GpuMat& image, const GpuMat& templ, GpuMat& result, bool ccorr = false); -CV_EXPORTS void convolve(const GpuMat& image, const GpuMat& templ, GpuMat& result, bool ccorr, ConvolveBuf& buf, Stream& stream = Stream::Null()); - -struct CV_EXPORTS MatchTemplateBuf -{ - Size user_block_size; - GpuMat imagef, templf; - std::vector images; - std::vector image_sums; - std::vector image_sqsums; -}; - -//! computes the proximity map for the raster template and the image where the template is searched for -CV_EXPORTS void matchTemplate(const GpuMat& image, const GpuMat& templ, GpuMat& result, int method, Stream &stream = Stream::Null()); - -//! computes the proximity map for the raster template and the image where the template is searched for -CV_EXPORTS void matchTemplate(const GpuMat& image, const GpuMat& templ, GpuMat& result, int method, MatchTemplateBuf &buf, Stream& stream = Stream::Null()); - -//! smoothes the source image and downsamples it -CV_EXPORTS void pyrDown(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()); - -//! upsamples the source image and then smoothes it -CV_EXPORTS void pyrUp(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()); - -//! performs linear blending of two images -//! to avoid accuracy errors sum of weigths shouldn't be very close to zero -CV_EXPORTS void blendLinear(const GpuMat& img1, const GpuMat& img2, const GpuMat& weights1, const GpuMat& weights2, - GpuMat& result, Stream& stream = Stream::Null()); - -//! Performa bilateral filtering of passsed image -CV_EXPORTS void bilateralFilter(const GpuMat& src, GpuMat& dst, int kernel_size, float sigma_color, float sigma_spatial, - int borderMode = BORDER_DEFAULT, Stream& stream = Stream::Null()); - -//! Brute force non-local means algorith (slow but universal) -CV_EXPORTS void nonLocalMeans(const GpuMat& src, GpuMat& dst, float h, int search_window = 21, int block_size = 7, int borderMode = BORDER_DEFAULT, Stream& s = Stream::Null()); - -//! Fast (but approximate)version of non-local means algorith similar to CPU function (running sums technique) -class CV_EXPORTS FastNonLocalMeansDenoising -{ -public: - //! Simple method, recommended for grayscale images (though it supports multichannel images) - void simpleMethod(const GpuMat& src, GpuMat& dst, float h, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()); - - //! Processes luminance and color components separatelly - void labMethod(const GpuMat& src, GpuMat& dst, float h_luminance, float h_color, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()); - -private: - - GpuMat buffer, extended_src_buffer; - GpuMat lab, l, ab; -}; - -struct CV_EXPORTS CannyBuf -{ - void create(const Size& image_size, int apperture_size = 3); - void release(); - - GpuMat dx, dy; - GpuMat mag; - GpuMat map; - GpuMat st1, st2; - Ptr filterDX, filterDY; -}; - -CV_EXPORTS void Canny(const GpuMat& image, GpuMat& edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false); -CV_EXPORTS void Canny(const GpuMat& image, CannyBuf& buf, GpuMat& edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false); -CV_EXPORTS void Canny(const GpuMat& dx, const GpuMat& dy, GpuMat& edges, double low_thresh, double high_thresh, bool L2gradient = false); -CV_EXPORTS void Canny(const GpuMat& dx, const GpuMat& dy, CannyBuf& buf, GpuMat& edges, double low_thresh, double high_thresh, bool L2gradient = false); - -class CV_EXPORTS ImagePyramid -{ -public: - inline ImagePyramid() : nLayers_(0) {} - inline ImagePyramid(const GpuMat& img, int nLayers, Stream& stream = Stream::Null()) - { - build(img, nLayers, stream); - } - - void build(const GpuMat& img, int nLayers, Stream& stream = Stream::Null()); - - void getLayer(GpuMat& outImg, Size outRoi, Stream& stream = Stream::Null()) const; - - inline void release() - { - layer0_.release(); - pyramid_.clear(); - nLayers_ = 0; - } - -private: - GpuMat layer0_; - std::vector pyramid_; - int nLayers_; -}; - -//! HoughLines - -struct HoughLinesBuf -{ - GpuMat accum; - GpuMat list; -}; - -CV_EXPORTS void HoughLines(const GpuMat& src, GpuMat& lines, float rho, float theta, int threshold, bool doSort = false, int maxLines = 4096); -CV_EXPORTS void HoughLines(const GpuMat& src, GpuMat& lines, HoughLinesBuf& buf, float rho, float theta, int threshold, bool doSort = false, int maxLines = 4096); -CV_EXPORTS void HoughLinesDownload(const GpuMat& d_lines, OutputArray h_lines, OutputArray h_votes = noArray()); - -//! HoughLinesP - -//! finds line segments in the black-n-white image using probabalistic Hough transform -CV_EXPORTS void HoughLinesP(const GpuMat& image, GpuMat& lines, HoughLinesBuf& buf, float rho, float theta, int minLineLength, int maxLineGap, int maxLines = 4096); - -//! HoughCircles - -struct HoughCirclesBuf -{ - GpuMat edges; - GpuMat accum; - GpuMat list; - CannyBuf cannyBuf; -}; - -CV_EXPORTS void HoughCircles(const GpuMat& src, GpuMat& circles, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles = 4096); -CV_EXPORTS void HoughCircles(const GpuMat& src, GpuMat& circles, HoughCirclesBuf& buf, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles = 4096); -CV_EXPORTS void HoughCirclesDownload(const GpuMat& d_circles, OutputArray h_circles); - -//! finds arbitrary template in the grayscale image using Generalized Hough Transform -//! Ballard, D.H. (1981). Generalizing the Hough transform to detect arbitrary shapes. Pattern Recognition 13 (2): 111-122. -//! Guil, N., González-Linares, J.M. and Zapata, E.L. (1999). Bidimensional shape detection using an invariant approach. Pattern Recognition 32 (6): 1025-1038. -class CV_EXPORTS GeneralizedHough_GPU : public cv::Algorithm -{ -public: - static Ptr create(int method); - - virtual ~GeneralizedHough_GPU(); - - //! set template to search - void setTemplate(const GpuMat& templ, int cannyThreshold = 100, Point templCenter = Point(-1, -1)); - void setTemplate(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, Point templCenter = Point(-1, -1)); - - //! find template on image - void detect(const GpuMat& image, GpuMat& positions, int cannyThreshold = 100); - void detect(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, GpuMat& positions); - - void download(const GpuMat& d_positions, OutputArray h_positions, OutputArray h_votes = noArray()); - - void release(); - -protected: - virtual void setTemplateImpl(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, Point templCenter) = 0; - virtual void detectImpl(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, GpuMat& positions) = 0; - virtual void releaseImpl() = 0; - -private: - GpuMat edges_; - CannyBuf cannyBuf_; -}; - -////////////////////////////// Matrix reductions ////////////////////////////// - -//! computes mean value and standard deviation of all or selected array elements -//! supports only CV_8UC1 type -CV_EXPORTS void meanStdDev(const GpuMat& mtx, Scalar& mean, Scalar& stddev); -//! buffered version -CV_EXPORTS void meanStdDev(const GpuMat& mtx, Scalar& mean, Scalar& stddev, GpuMat& buf); - -//! computes norm of array -//! supports NORM_INF, NORM_L1, NORM_L2 -//! supports all matrices except 64F -CV_EXPORTS double norm(const GpuMat& src1, int normType=NORM_L2); -CV_EXPORTS double norm(const GpuMat& src1, int normType, GpuMat& buf); -CV_EXPORTS double norm(const GpuMat& src1, int normType, const GpuMat& mask, GpuMat& buf); - -//! computes norm of the difference between two arrays -//! supports NORM_INF, NORM_L1, NORM_L2 -//! supports only CV_8UC1 type -CV_EXPORTS double norm(const GpuMat& src1, const GpuMat& src2, int normType=NORM_L2); - -//! computes sum of array elements -//! supports only single channel images -CV_EXPORTS Scalar sum(const GpuMat& src); -CV_EXPORTS Scalar sum(const GpuMat& src, GpuMat& buf); -CV_EXPORTS Scalar sum(const GpuMat& src, const GpuMat& mask, GpuMat& buf); - -//! computes sum of array elements absolute values -//! supports only single channel images -CV_EXPORTS Scalar absSum(const GpuMat& src); -CV_EXPORTS Scalar absSum(const GpuMat& src, GpuMat& buf); -CV_EXPORTS Scalar absSum(const GpuMat& src, const GpuMat& mask, GpuMat& buf); - -//! computes squared sum of array elements -//! supports only single channel images -CV_EXPORTS Scalar sqrSum(const GpuMat& src); -CV_EXPORTS Scalar sqrSum(const GpuMat& src, GpuMat& buf); -CV_EXPORTS Scalar sqrSum(const GpuMat& src, const GpuMat& mask, GpuMat& buf); - -//! finds global minimum and maximum array elements and returns their values -CV_EXPORTS void minMax(const GpuMat& src, double* minVal, double* maxVal=0, const GpuMat& mask=GpuMat()); -CV_EXPORTS void minMax(const GpuMat& src, double* minVal, double* maxVal, const GpuMat& mask, GpuMat& buf); - -//! finds global minimum and maximum array elements and returns their values with locations -CV_EXPORTS void minMaxLoc(const GpuMat& src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, - const GpuMat& mask=GpuMat()); -CV_EXPORTS void minMaxLoc(const GpuMat& src, double* minVal, double* maxVal, Point* minLoc, Point* maxLoc, - const GpuMat& mask, GpuMat& valbuf, GpuMat& locbuf); - -//! counts non-zero array elements -CV_EXPORTS int countNonZero(const GpuMat& src); -CV_EXPORTS int countNonZero(const GpuMat& src, GpuMat& buf); - -//! reduces a matrix to a vector -CV_EXPORTS void reduce(const GpuMat& mtx, GpuMat& vec, int dim, int reduceOp, int dtype = -1, Stream& stream = Stream::Null()); - - -///////////////////////////// Calibration 3D ////////////////////////////////// - -CV_EXPORTS void transformPoints(const GpuMat& src, const Mat& rvec, const Mat& tvec, - GpuMat& dst, Stream& stream = Stream::Null()); - -CV_EXPORTS void projectPoints(const GpuMat& src, const Mat& rvec, const Mat& tvec, - const Mat& camera_mat, const Mat& dist_coef, GpuMat& dst, - Stream& stream = Stream::Null()); - -CV_EXPORTS void solvePnPRansac(const Mat& object, const Mat& image, const Mat& camera_mat, - const Mat& dist_coef, Mat& rvec, Mat& tvec, bool use_extrinsic_guess=false, - int num_iters=100, float max_dist=8.0, int min_inlier_count=100, - std::vector* inliers=NULL); - -//////////////////////////////// Image Labeling //////////////////////////////// - -//!performs labeling via graph cuts of a 2D regular 4-connected graph. -CV_EXPORTS void graphcut(GpuMat& terminals, GpuMat& leftTransp, GpuMat& rightTransp, GpuMat& top, GpuMat& bottom, GpuMat& labels, - GpuMat& buf, Stream& stream = Stream::Null()); - -//!performs labeling via graph cuts of a 2D regular 8-connected graph. -CV_EXPORTS void graphcut(GpuMat& terminals, GpuMat& leftTransp, GpuMat& rightTransp, GpuMat& top, GpuMat& topLeft, GpuMat& topRight, - GpuMat& bottom, GpuMat& bottomLeft, GpuMat& bottomRight, - GpuMat& labels, - GpuMat& buf, Stream& stream = Stream::Null()); - -//! compute mask for Generalized Flood fill componetns labeling. -CV_EXPORTS void connectivityMask(const GpuMat& image, GpuMat& mask, const cv::Scalar& lo, const cv::Scalar& hi, Stream& stream = Stream::Null()); - -//! performs connected componnents labeling. -CV_EXPORTS void labelComponents(const GpuMat& mask, GpuMat& components, int flags = 0, Stream& stream = Stream::Null()); - -////////////////////////////////// Histograms ////////////////////////////////// - -//! Compute levels with even distribution. levels will have 1 row and nLevels cols and CV_32SC1 type. -CV_EXPORTS void evenLevels(GpuMat& levels, int nLevels, int lowerLevel, int upperLevel); -//! Calculates histogram with evenly distributed bins for signle channel source. -//! Supports CV_8UC1, CV_16UC1 and CV_16SC1 source types. -//! Output hist will have one row and histSize cols and CV_32SC1 type. -CV_EXPORTS void histEven(const GpuMat& src, GpuMat& hist, int histSize, int lowerLevel, int upperLevel, Stream& stream = Stream::Null()); -CV_EXPORTS void histEven(const GpuMat& src, GpuMat& hist, GpuMat& buf, int histSize, int lowerLevel, int upperLevel, Stream& stream = Stream::Null()); -//! Calculates histogram with evenly distributed bins for four-channel source. -//! All channels of source are processed separately. -//! Supports CV_8UC4, CV_16UC4 and CV_16SC4 source types. -//! Output hist[i] will have one row and histSize[i] cols and CV_32SC1 type. -CV_EXPORTS void histEven(const GpuMat& src, GpuMat hist[4], int histSize[4], int lowerLevel[4], int upperLevel[4], Stream& stream = Stream::Null()); -CV_EXPORTS void histEven(const GpuMat& src, GpuMat hist[4], GpuMat& buf, int histSize[4], int lowerLevel[4], int upperLevel[4], Stream& stream = Stream::Null()); -//! Calculates histogram with bins determined by levels array. -//! levels must have one row and CV_32SC1 type if source has integer type or CV_32FC1 otherwise. -//! Supports CV_8UC1, CV_16UC1, CV_16SC1 and CV_32FC1 source types. -//! Output hist will have one row and (levels.cols-1) cols and CV_32SC1 type. -CV_EXPORTS void histRange(const GpuMat& src, GpuMat& hist, const GpuMat& levels, Stream& stream = Stream::Null()); -CV_EXPORTS void histRange(const GpuMat& src, GpuMat& hist, const GpuMat& levels, GpuMat& buf, Stream& stream = Stream::Null()); -//! Calculates histogram with bins determined by levels array. -//! All levels must have one row and CV_32SC1 type if source has integer type or CV_32FC1 otherwise. -//! All channels of source are processed separately. -//! Supports CV_8UC4, CV_16UC4, CV_16SC4 and CV_32FC4 source types. -//! Output hist[i] will have one row and (levels[i].cols-1) cols and CV_32SC1 type. -CV_EXPORTS void histRange(const GpuMat& src, GpuMat hist[4], const GpuMat levels[4], Stream& stream = Stream::Null()); -CV_EXPORTS void histRange(const GpuMat& src, GpuMat hist[4], const GpuMat levels[4], GpuMat& buf, Stream& stream = Stream::Null()); - -//! Calculates histogram for 8u one channel image -//! Output hist will have one row, 256 cols and CV32SC1 type. -CV_EXPORTS void calcHist(const GpuMat& src, GpuMat& hist, Stream& stream = Stream::Null()); - -//! normalizes the grayscale image brightness and contrast by normalizing its histogram -CV_EXPORTS void equalizeHist(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()); -CV_EXPORTS void equalizeHist(const GpuMat& src, GpuMat& dst, GpuMat& hist, GpuMat& buf, Stream& stream = Stream::Null()); - -//////////////////////////////// StereoBM_GPU //////////////////////////////// - -class CV_EXPORTS StereoBM_GPU -{ -public: - enum { BASIC_PRESET = 0, PREFILTER_XSOBEL = 1 }; - - enum { DEFAULT_NDISP = 64, DEFAULT_WINSZ = 19 }; - - //! the default constructor - StereoBM_GPU(); - //! the full constructor taking the camera-specific preset, number of disparities and the SAD window size. ndisparities must be multiple of 8. - StereoBM_GPU(int preset, int ndisparities = DEFAULT_NDISP, int winSize = DEFAULT_WINSZ); - - //! the stereo correspondence operator. Finds the disparity for the specified rectified stereo pair - //! Output disparity has CV_8U type. - void operator()(const GpuMat& left, const GpuMat& right, GpuMat& disparity, Stream& stream = Stream::Null()); - - //! Some heuristics that tries to estmate - // if current GPU will be faster than CPU in this algorithm. - // It queries current active device. - static bool checkIfGpuCallReasonable(); - - int preset; - int ndisp; - int winSize; - - // If avergeTexThreshold == 0 => post procesing is disabled - // If avergeTexThreshold != 0 then disparity is set 0 in each point (x,y) where for left image - // SumOfHorizontalGradiensInWindow(x, y, winSize) < (winSize * winSize) * avergeTexThreshold - // i.e. input left image is low textured. - float avergeTexThreshold; - -private: - GpuMat minSSD, leBuf, riBuf; -}; - -////////////////////////// StereoBeliefPropagation /////////////////////////// -// "Efficient Belief Propagation for Early Vision" -// P.Felzenszwalb - -class CV_EXPORTS StereoBeliefPropagation -{ -public: - enum { DEFAULT_NDISP = 64 }; - enum { DEFAULT_ITERS = 5 }; - enum { DEFAULT_LEVELS = 5 }; - - static void estimateRecommendedParams(int width, int height, int& ndisp, int& iters, int& levels); - - //! the default constructor - explicit StereoBeliefPropagation(int ndisp = DEFAULT_NDISP, - int iters = DEFAULT_ITERS, - int levels = DEFAULT_LEVELS, - int msg_type = CV_32F); - - //! the full constructor taking the number of disparities, number of BP iterations on each level, - //! number of levels, truncation of data cost, data weight, - //! truncation of discontinuity cost and discontinuity single jump - //! DataTerm = data_weight * min(fabs(I2-I1), max_data_term) - //! DiscTerm = min(disc_single_jump * fabs(f1-f2), max_disc_term) - //! please see paper for more details - StereoBeliefPropagation(int ndisp, int iters, int levels, - float max_data_term, float data_weight, - float max_disc_term, float disc_single_jump, - int msg_type = CV_32F); - - //! the stereo correspondence operator. Finds the disparity for the specified rectified stereo pair, - //! if disparity is empty output type will be CV_16S else output type will be disparity.type(). - void operator()(const GpuMat& left, const GpuMat& right, GpuMat& disparity, Stream& stream = Stream::Null()); - - - //! version for user specified data term - void operator()(const GpuMat& data, GpuMat& disparity, Stream& stream = Stream::Null()); - - int ndisp; - - int iters; - int levels; - - float max_data_term; - float data_weight; - float max_disc_term; - float disc_single_jump; - - int msg_type; -private: - GpuMat u, d, l, r, u2, d2, l2, r2; - std::vector datas; - GpuMat out; -}; - -/////////////////////////// StereoConstantSpaceBP /////////////////////////// -// "A Constant-Space Belief Propagation Algorithm for Stereo Matching" -// Qingxiong Yang, Liang Wang, Narendra Ahuja -// http://vision.ai.uiuc.edu/~qyang6/ - -class CV_EXPORTS StereoConstantSpaceBP -{ -public: - enum { DEFAULT_NDISP = 128 }; - enum { DEFAULT_ITERS = 8 }; - enum { DEFAULT_LEVELS = 4 }; - enum { DEFAULT_NR_PLANE = 4 }; - - static void estimateRecommendedParams(int width, int height, int& ndisp, int& iters, int& levels, int& nr_plane); - - //! the default constructor - explicit StereoConstantSpaceBP(int ndisp = DEFAULT_NDISP, - int iters = DEFAULT_ITERS, - int levels = DEFAULT_LEVELS, - int nr_plane = DEFAULT_NR_PLANE, - int msg_type = CV_32F); - - //! the full constructor taking the number of disparities, number of BP iterations on each level, - //! number of levels, number of active disparity on the first level, truncation of data cost, data weight, - //! truncation of discontinuity cost, discontinuity single jump and minimum disparity threshold - StereoConstantSpaceBP(int ndisp, int iters, int levels, int nr_plane, - float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, - int min_disp_th = 0, - int msg_type = CV_32F); - - //! the stereo correspondence operator. Finds the disparity for the specified rectified stereo pair, - //! if disparity is empty output type will be CV_16S else output type will be disparity.type(). - void operator()(const GpuMat& left, const GpuMat& right, GpuMat& disparity, Stream& stream = Stream::Null()); - - int ndisp; - - int iters; - int levels; - - int nr_plane; - - float max_data_term; - float data_weight; - float max_disc_term; - float disc_single_jump; - - int min_disp_th; - - int msg_type; - - bool use_local_init_data_cost; -private: - GpuMat messages_buffers; - - GpuMat temp; - GpuMat out; -}; - -/////////////////////////// DisparityBilateralFilter /////////////////////////// -// Disparity map refinement using joint bilateral filtering given a single color image. -// Qingxiong Yang, Liang Wang, Narendra Ahuja -// http://vision.ai.uiuc.edu/~qyang6/ - -class CV_EXPORTS DisparityBilateralFilter -{ -public: - enum { DEFAULT_NDISP = 64 }; - enum { DEFAULT_RADIUS = 3 }; - enum { DEFAULT_ITERS = 1 }; - - //! the default constructor - explicit DisparityBilateralFilter(int ndisp = DEFAULT_NDISP, int radius = DEFAULT_RADIUS, int iters = DEFAULT_ITERS); - - //! the full constructor taking the number of disparities, filter radius, - //! number of iterations, truncation of data continuity, truncation of disparity continuity - //! and filter range sigma - DisparityBilateralFilter(int ndisp, int radius, int iters, float edge_threshold, float max_disc_threshold, float sigma_range); - - //! the disparity map refinement operator. Refine disparity map using joint bilateral filtering given a single color image. - //! disparity must have CV_8U or CV_16S type, image must have CV_8UC1 or CV_8UC3 type. - void operator()(const GpuMat& disparity, const GpuMat& image, GpuMat& dst, Stream& stream = Stream::Null()); - -private: - int ndisp; - int radius; - int iters; - - float edge_threshold; - float max_disc_threshold; - float sigma_range; - - GpuMat table_color; - GpuMat table_space; -}; - //////////////// HOG (Histogram-of-Oriented-Gradients) Descriptor and Object Detector ////////////// + struct CV_EXPORTS HOGConfidence { double scale; @@ -1178,195 +183,18 @@ protected: std::vector image_scales; }; +//////////////////////////// CascadeClassifier //////////////////////////// -////////////////////////////////// BruteForceMatcher ////////////////////////////////// - -class CV_EXPORTS BFMatcher_GPU -{ -public: - explicit BFMatcher_GPU(int norm = cv::NORM_L2); - - // Add descriptors to train descriptor collection - void add(const std::vector& descCollection); - - // Get train descriptors collection - const std::vector& getTrainDescriptors() const; - - // Clear train descriptors collection - void clear(); - - // Return true if there are not train descriptors in collection - bool empty() const; - - // Return true if the matcher supports mask in match methods - bool isMaskSupported() const; - - // Find one best match for each query descriptor - void matchSingle(const GpuMat& query, const GpuMat& train, - GpuMat& trainIdx, GpuMat& distance, - const GpuMat& mask = GpuMat(), Stream& stream = Stream::Null()); - - // Download trainIdx and distance and convert it to CPU vector with DMatch - static void matchDownload(const GpuMat& trainIdx, const GpuMat& distance, std::vector& matches); - // Convert trainIdx and distance to vector with DMatch - static void matchConvert(const Mat& trainIdx, const Mat& distance, std::vector& matches); - - // Find one best match for each query descriptor - void match(const GpuMat& query, const GpuMat& train, std::vector& matches, const GpuMat& mask = GpuMat()); - - // Make gpu collection of trains and masks in suitable format for matchCollection function - void makeGpuCollection(GpuMat& trainCollection, GpuMat& maskCollection, const std::vector& masks = std::vector()); - - // Find one best match from train collection for each query descriptor - void matchCollection(const GpuMat& query, const GpuMat& trainCollection, - GpuMat& trainIdx, GpuMat& imgIdx, GpuMat& distance, - const GpuMat& masks = GpuMat(), Stream& stream = Stream::Null()); - - // Download trainIdx, imgIdx and distance and convert it to vector with DMatch - static void matchDownload(const GpuMat& trainIdx, const GpuMat& imgIdx, const GpuMat& distance, std::vector& matches); - // Convert trainIdx, imgIdx and distance to vector with DMatch - static void matchConvert(const Mat& trainIdx, const Mat& imgIdx, const Mat& distance, std::vector& matches); - - // Find one best match from train collection for each query descriptor. - void match(const GpuMat& query, std::vector& matches, const std::vector& masks = std::vector()); - - // Find k best matches for each query descriptor (in increasing order of distances) - void knnMatchSingle(const GpuMat& query, const GpuMat& train, - GpuMat& trainIdx, GpuMat& distance, GpuMat& allDist, int k, - const GpuMat& mask = GpuMat(), Stream& stream = Stream::Null()); - - // Download trainIdx and distance and convert it to vector with DMatch - // compactResult is used when mask is not empty. If compactResult is false matches - // vector will have the same size as queryDescriptors rows. If compactResult is true - // matches vector will not contain matches for fully masked out query descriptors. - static void knnMatchDownload(const GpuMat& trainIdx, const GpuMat& distance, - std::vector< std::vector >& matches, bool compactResult = false); - // Convert trainIdx and distance to vector with DMatch - static void knnMatchConvert(const Mat& trainIdx, const Mat& distance, - std::vector< std::vector >& matches, bool compactResult = false); - - // Find k best matches for each query descriptor (in increasing order of distances). - // compactResult is used when mask is not empty. If compactResult is false matches - // vector will have the same size as queryDescriptors rows. If compactResult is true - // matches vector will not contain matches for fully masked out query descriptors. - void knnMatch(const GpuMat& query, const GpuMat& train, - std::vector< std::vector >& matches, int k, const GpuMat& mask = GpuMat(), - bool compactResult = false); - - // Find k best matches from train collection for each query descriptor (in increasing order of distances) - void knnMatch2Collection(const GpuMat& query, const GpuMat& trainCollection, - GpuMat& trainIdx, GpuMat& imgIdx, GpuMat& distance, - const GpuMat& maskCollection = GpuMat(), Stream& stream = Stream::Null()); - - // Download trainIdx and distance and convert it to vector with DMatch - // compactResult is used when mask is not empty. If compactResult is false matches - // vector will have the same size as queryDescriptors rows. If compactResult is true - // matches vector will not contain matches for fully masked out query descriptors. - static void knnMatch2Download(const GpuMat& trainIdx, const GpuMat& imgIdx, const GpuMat& distance, - std::vector< std::vector >& matches, bool compactResult = false); - // Convert trainIdx and distance to vector with DMatch - static void knnMatch2Convert(const Mat& trainIdx, const Mat& imgIdx, const Mat& distance, - std::vector< std::vector >& matches, bool compactResult = false); - - // Find k best matches for each query descriptor (in increasing order of distances). - // compactResult is used when mask is not empty. If compactResult is false matches - // vector will have the same size as queryDescriptors rows. If compactResult is true - // matches vector will not contain matches for fully masked out query descriptors. - void knnMatch(const GpuMat& query, std::vector< std::vector >& matches, int k, - const std::vector& masks = std::vector(), bool compactResult = false); - - // Find best matches for each query descriptor which have distance less than maxDistance. - // nMatches.at(0, queryIdx) will contain matches count for queryIdx. - // carefully nMatches can be greater than trainIdx.cols - it means that matcher didn't find all matches, - // because it didn't have enough memory. - // If trainIdx is empty, then trainIdx and distance will be created with size nQuery x max((nTrain / 100), 10), - // otherwize user can pass own allocated trainIdx and distance with size nQuery x nMaxMatches - // Matches doesn't sorted. - void radiusMatchSingle(const GpuMat& query, const GpuMat& train, - GpuMat& trainIdx, GpuMat& distance, GpuMat& nMatches, float maxDistance, - const GpuMat& mask = GpuMat(), Stream& stream = Stream::Null()); - - // Download trainIdx, nMatches and distance and convert it to vector with DMatch. - // matches will be sorted in increasing order of distances. - // compactResult is used when mask is not empty. If compactResult is false matches - // vector will have the same size as queryDescriptors rows. If compactResult is true - // matches vector will not contain matches for fully masked out query descriptors. - static void radiusMatchDownload(const GpuMat& trainIdx, const GpuMat& distance, const GpuMat& nMatches, - std::vector< std::vector >& matches, bool compactResult = false); - // Convert trainIdx, nMatches and distance to vector with DMatch. - static void radiusMatchConvert(const Mat& trainIdx, const Mat& distance, const Mat& nMatches, - std::vector< std::vector >& matches, bool compactResult = false); - - // Find best matches for each query descriptor which have distance less than maxDistance - // in increasing order of distances). - void radiusMatch(const GpuMat& query, const GpuMat& train, - std::vector< std::vector >& matches, float maxDistance, - const GpuMat& mask = GpuMat(), bool compactResult = false); - - // Find best matches for each query descriptor which have distance less than maxDistance. - // If trainIdx is empty, then trainIdx and distance will be created with size nQuery x max((nQuery / 100), 10), - // otherwize user can pass own allocated trainIdx and distance with size nQuery x nMaxMatches - // Matches doesn't sorted. - void radiusMatchCollection(const GpuMat& query, GpuMat& trainIdx, GpuMat& imgIdx, GpuMat& distance, GpuMat& nMatches, float maxDistance, - const std::vector& masks = std::vector(), Stream& stream = Stream::Null()); - - // Download trainIdx, imgIdx, nMatches and distance and convert it to vector with DMatch. - // matches will be sorted in increasing order of distances. - // compactResult is used when mask is not empty. If compactResult is false matches - // vector will have the same size as queryDescriptors rows. If compactResult is true - // matches vector will not contain matches for fully masked out query descriptors. - static void radiusMatchDownload(const GpuMat& trainIdx, const GpuMat& imgIdx, const GpuMat& distance, const GpuMat& nMatches, - std::vector< std::vector >& matches, bool compactResult = false); - // Convert trainIdx, nMatches and distance to vector with DMatch. - static void radiusMatchConvert(const Mat& trainIdx, const Mat& imgIdx, const Mat& distance, const Mat& nMatches, - std::vector< std::vector >& matches, bool compactResult = false); - - // Find best matches from train collection for each query descriptor which have distance less than - // maxDistance (in increasing order of distances). - void radiusMatch(const GpuMat& query, std::vector< std::vector >& matches, float maxDistance, - const std::vector& masks = std::vector(), bool compactResult = false); - - int norm; - -private: - std::vector trainDescCollection; -}; - -template -class CV_EXPORTS BruteForceMatcher_GPU; - -template -class CV_EXPORTS BruteForceMatcher_GPU< L1 > : public BFMatcher_GPU -{ -public: - explicit BruteForceMatcher_GPU() : BFMatcher_GPU(NORM_L1) {} - explicit BruteForceMatcher_GPU(L1 /*d*/) : BFMatcher_GPU(NORM_L1) {} -}; -template -class CV_EXPORTS BruteForceMatcher_GPU< L2 > : public BFMatcher_GPU -{ -public: - explicit BruteForceMatcher_GPU() : BFMatcher_GPU(NORM_L2) {} - explicit BruteForceMatcher_GPU(L2 /*d*/) : BFMatcher_GPU(NORM_L2) {} -}; -template <> class CV_EXPORTS BruteForceMatcher_GPU< Hamming > : public BFMatcher_GPU -{ -public: - explicit BruteForceMatcher_GPU() : BFMatcher_GPU(NORM_HAMMING) {} - explicit BruteForceMatcher_GPU(Hamming /*d*/) : BFMatcher_GPU(NORM_HAMMING) {} -}; - -////////////////////////////////// CascadeClassifier_GPU ////////////////////////////////////////// // The cascade classifier class for object detection: supports old haar and new lbp xlm formats and nvbin for haar cascades olny. class CV_EXPORTS CascadeClassifier_GPU { public: CascadeClassifier_GPU(); - CascadeClassifier_GPU(const std::string& filename); + CascadeClassifier_GPU(const String& filename); ~CascadeClassifier_GPU(); bool empty() const; - bool load(const std::string& filename); + bool load(const String& filename); void release(); /* returns number of detected objects */ @@ -1386,1059 +214,39 @@ private: friend class CascadeClassifier_GPU_LBP; }; -////////////////////////////////// SURF ////////////////////////////////////////// +//////////////////////////// Labeling //////////////////////////// -class CV_EXPORTS SURF_GPU -{ -public: - enum KeypointLayout - { - X_ROW = 0, - Y_ROW, - LAPLACIAN_ROW, - OCTAVE_ROW, - SIZE_ROW, - ANGLE_ROW, - HESSIAN_ROW, - ROWS_COUNT - }; +//!performs labeling via graph cuts of a 2D regular 4-connected graph. +CV_EXPORTS void graphcut(GpuMat& terminals, GpuMat& leftTransp, GpuMat& rightTransp, GpuMat& top, GpuMat& bottom, GpuMat& labels, + GpuMat& buf, Stream& stream = Stream::Null()); - //! the default constructor - SURF_GPU(); - //! the full constructor taking all the necessary parameters - explicit SURF_GPU(double _hessianThreshold, int _nOctaves=4, - int _nOctaveLayers=2, bool _extended=false, float _keypointsRatio=0.01f, bool _upright = false); +//!performs labeling via graph cuts of a 2D regular 8-connected graph. +CV_EXPORTS void graphcut(GpuMat& terminals, GpuMat& leftTransp, GpuMat& rightTransp, GpuMat& top, GpuMat& topLeft, GpuMat& topRight, + GpuMat& bottom, GpuMat& bottomLeft, GpuMat& bottomRight, + GpuMat& labels, + GpuMat& buf, Stream& stream = Stream::Null()); - //! returns the descriptor size in float's (64 or 128) - int descriptorSize() const; +//! compute mask for Generalized Flood fill componetns labeling. +CV_EXPORTS void connectivityMask(const GpuMat& image, GpuMat& mask, const cv::Scalar& lo, const cv::Scalar& hi, Stream& stream = Stream::Null()); - //! upload host keypoints to device memory - static void uploadKeypoints(const std::vector& keypoints, GpuMat& keypointsGPU); - //! download keypoints from device to host memory - static void downloadKeypoints(const GpuMat& keypointsGPU, std::vector& keypoints); +//! performs connected componnents labeling. +CV_EXPORTS void labelComponents(const GpuMat& mask, GpuMat& components, int flags = 0, Stream& stream = Stream::Null()); - //! download descriptors from device to host memory - static void downloadDescriptors(const GpuMat& descriptorsGPU, std::vector& descriptors); +//////////////////////////// Calib3d //////////////////////////// - //! finds the keypoints using fast hessian detector used in SURF - //! supports CV_8UC1 images - //! keypoints will have nFeature cols and 6 rows - //! keypoints.ptr(X_ROW)[i] will contain x coordinate of i'th feature - //! keypoints.ptr(Y_ROW)[i] will contain y coordinate of i'th feature - //! keypoints.ptr(LAPLACIAN_ROW)[i] will contain laplacian sign of i'th feature - //! keypoints.ptr(OCTAVE_ROW)[i] will contain octave of i'th feature - //! keypoints.ptr(SIZE_ROW)[i] will contain size of i'th feature - //! keypoints.ptr(ANGLE_ROW)[i] will contain orientation of i'th feature - //! keypoints.ptr(HESSIAN_ROW)[i] will contain response of i'th feature - void operator()(const GpuMat& img, const GpuMat& mask, GpuMat& keypoints); - //! finds the keypoints and computes their descriptors. - //! Optionally it can compute descriptors for the user-provided keypoints and recompute keypoints direction - void operator()(const GpuMat& img, const GpuMat& mask, GpuMat& keypoints, GpuMat& descriptors, - bool useProvidedKeypoints = false); +CV_EXPORTS void transformPoints(const GpuMat& src, const Mat& rvec, const Mat& tvec, + GpuMat& dst, Stream& stream = Stream::Null()); - void operator()(const GpuMat& img, const GpuMat& mask, std::vector& keypoints); - void operator()(const GpuMat& img, const GpuMat& mask, std::vector& keypoints, GpuMat& descriptors, - bool useProvidedKeypoints = false); +CV_EXPORTS void projectPoints(const GpuMat& src, const Mat& rvec, const Mat& tvec, + const Mat& camera_mat, const Mat& dist_coef, GpuMat& dst, + Stream& stream = Stream::Null()); - void operator()(const GpuMat& img, const GpuMat& mask, std::vector& keypoints, std::vector& descriptors, - bool useProvidedKeypoints = false); +CV_EXPORTS void solvePnPRansac(const Mat& object, const Mat& image, const Mat& camera_mat, + const Mat& dist_coef, Mat& rvec, Mat& tvec, bool use_extrinsic_guess=false, + int num_iters=100, float max_dist=8.0, int min_inlier_count=100, + std::vector* inliers=NULL); - void releaseMemory(); - - // SURF parameters - double hessianThreshold; - int nOctaves; - int nOctaveLayers; - bool extended; - bool upright; - - //! max keypoints = min(keypointsRatio * img.size().area(), 65535) - float keypointsRatio; - - GpuMat sum, mask1, maskSum, intBuffer; - - GpuMat det, trace; - - GpuMat maxPosBuffer; -}; - -////////////////////////////////// FAST ////////////////////////////////////////// - -class CV_EXPORTS FAST_GPU -{ -public: - enum - { - LOCATION_ROW = 0, - RESPONSE_ROW, - ROWS_COUNT - }; - - // all features have same size - static const int FEATURE_SIZE = 7; - - explicit FAST_GPU(int threshold, bool nonmaxSupression = true, double keypointsRatio = 0.05); - - //! finds the keypoints using FAST detector - //! supports only CV_8UC1 images - void operator ()(const GpuMat& image, const GpuMat& mask, GpuMat& keypoints); - void operator ()(const GpuMat& image, const GpuMat& mask, std::vector& keypoints); - - //! download keypoints from device to host memory - static void downloadKeypoints(const GpuMat& d_keypoints, std::vector& keypoints); - - //! convert keypoints to KeyPoint vector - static void convertKeypoints(const Mat& h_keypoints, std::vector& keypoints); - - //! release temporary buffer's memory - void release(); - - bool nonmaxSupression; - - int threshold; - - //! max keypoints = keypointsRatio * img.size().area() - double keypointsRatio; - - //! find keypoints and compute it's response if nonmaxSupression is true - //! return count of detected keypoints - int calcKeyPointsLocation(const GpuMat& image, const GpuMat& mask); - - //! get final array of keypoints - //! performs nonmax supression if needed - //! return final count of keypoints - int getKeyPoints(GpuMat& keypoints); - -private: - GpuMat kpLoc_; - int count_; - - GpuMat score_; - - GpuMat d_keypoints_; -}; - -////////////////////////////////// ORB ////////////////////////////////////////// - -class CV_EXPORTS ORB_GPU -{ -public: - enum - { - X_ROW = 0, - Y_ROW, - RESPONSE_ROW, - ANGLE_ROW, - OCTAVE_ROW, - SIZE_ROW, - ROWS_COUNT - }; - - enum - { - DEFAULT_FAST_THRESHOLD = 20 - }; - - //! Constructor - explicit ORB_GPU(int nFeatures = 500, float scaleFactor = 1.2f, int nLevels = 8, int edgeThreshold = 31, - int firstLevel = 0, int WTA_K = 2, int scoreType = 0, int patchSize = 31); - - //! Compute the ORB features on an image - //! image - the image to compute the features (supports only CV_8UC1 images) - //! mask - the mask to apply - //! keypoints - the resulting keypoints - void operator()(const GpuMat& image, const GpuMat& mask, std::vector& keypoints); - void operator()(const GpuMat& image, const GpuMat& mask, GpuMat& keypoints); - - //! Compute the ORB features and descriptors on an image - //! image - the image to compute the features (supports only CV_8UC1 images) - //! mask - the mask to apply - //! keypoints - the resulting keypoints - //! descriptors - descriptors array - void operator()(const GpuMat& image, const GpuMat& mask, std::vector& keypoints, GpuMat& descriptors); - void operator()(const GpuMat& image, const GpuMat& mask, GpuMat& keypoints, GpuMat& descriptors); - - //! download keypoints from device to host memory - static void downloadKeyPoints(const GpuMat& d_keypoints, std::vector& keypoints); - //! convert keypoints to KeyPoint vector - static void convertKeyPoints(const Mat& d_keypoints, std::vector& keypoints); - - //! returns the descriptor size in bytes - inline int descriptorSize() const { return kBytes; } - - inline void setFastParams(int threshold, bool nonmaxSupression = true) - { - fastDetector_.threshold = threshold; - fastDetector_.nonmaxSupression = nonmaxSupression; - } - - //! release temporary buffer's memory - void release(); - - //! if true, image will be blurred before descriptors calculation - bool blurForDescriptor; - -private: - enum { kBytes = 32 }; - - void buildScalePyramids(const GpuMat& image, const GpuMat& mask); - - void computeKeyPointsPyramid(); - - void computeDescriptors(GpuMat& descriptors); - - void mergeKeyPoints(GpuMat& keypoints); - - int nFeatures_; - float scaleFactor_; - int nLevels_; - int edgeThreshold_; - int firstLevel_; - int WTA_K_; - int scoreType_; - int patchSize_; - - // The number of desired features per scale - std::vector n_features_per_level_; - - // Points to compute BRIEF descriptors from - GpuMat pattern_; - - std::vector imagePyr_; - std::vector maskPyr_; - - GpuMat buf_; - - std::vector keyPointsPyr_; - std::vector keyPointsCount_; - - FAST_GPU fastDetector_; - - Ptr blurFilter; - - GpuMat d_keypoints_; -}; - -////////////////////////////////// Optical Flow ////////////////////////////////////////// - -class CV_EXPORTS BroxOpticalFlow -{ -public: - BroxOpticalFlow(float alpha_, float gamma_, float scale_factor_, int inner_iterations_, int outer_iterations_, int solver_iterations_) : - alpha(alpha_), gamma(gamma_), scale_factor(scale_factor_), - inner_iterations(inner_iterations_), outer_iterations(outer_iterations_), solver_iterations(solver_iterations_) - { - } - - //! Compute optical flow - //! frame0 - source frame (supports only CV_32FC1 type) - //! frame1 - frame to track (with the same size and type as frame0) - //! u - flow horizontal component (along x axis) - //! v - flow vertical component (along y axis) - void operator ()(const GpuMat& frame0, const GpuMat& frame1, GpuMat& u, GpuMat& v, Stream& stream = Stream::Null()); - - //! flow smoothness - float alpha; - - //! gradient constancy importance - float gamma; - - //! pyramid scale factor - float scale_factor; - - //! number of lagged non-linearity iterations (inner loop) - int inner_iterations; - - //! number of warping iterations (number of pyramid levels) - int outer_iterations; - - //! number of linear system solver iterations - int solver_iterations; - - GpuMat buf; -}; - -class CV_EXPORTS GoodFeaturesToTrackDetector_GPU -{ -public: - explicit GoodFeaturesToTrackDetector_GPU(int maxCorners = 1000, double qualityLevel = 0.01, double minDistance = 0.0, - int blockSize = 3, bool useHarrisDetector = false, double harrisK = 0.04); - - //! return 1 rows matrix with CV_32FC2 type - void operator ()(const GpuMat& image, GpuMat& corners, const GpuMat& mask = GpuMat()); - - int maxCorners; - double qualityLevel; - double minDistance; - - int blockSize; - bool useHarrisDetector; - double harrisK; - - void releaseMemory() - { - Dx_.release(); - Dy_.release(); - buf_.release(); - eig_.release(); - minMaxbuf_.release(); - tmpCorners_.release(); - } - -private: - GpuMat Dx_; - GpuMat Dy_; - GpuMat buf_; - GpuMat eig_; - GpuMat minMaxbuf_; - GpuMat tmpCorners_; -}; - -inline GoodFeaturesToTrackDetector_GPU::GoodFeaturesToTrackDetector_GPU(int maxCorners_, double qualityLevel_, double minDistance_, - int blockSize_, bool useHarrisDetector_, double harrisK_) -{ - maxCorners = maxCorners_; - qualityLevel = qualityLevel_; - minDistance = minDistance_; - blockSize = blockSize_; - useHarrisDetector = useHarrisDetector_; - harrisK = harrisK_; -} - - -class CV_EXPORTS PyrLKOpticalFlow -{ -public: - PyrLKOpticalFlow(); - - void sparse(const GpuMat& prevImg, const GpuMat& nextImg, const GpuMat& prevPts, GpuMat& nextPts, - GpuMat& status, GpuMat* err = 0); - - void dense(const GpuMat& prevImg, const GpuMat& nextImg, GpuMat& u, GpuMat& v, GpuMat* err = 0); - - void releaseMemory(); - - Size winSize; - int maxLevel; - int iters; - bool useInitialFlow; - -private: - std::vector prevPyr_; - std::vector nextPyr_; - - GpuMat buf_; - - GpuMat uPyr_[2]; - GpuMat vPyr_[2]; -}; - - -class CV_EXPORTS FarnebackOpticalFlow -{ -public: - FarnebackOpticalFlow() - { - numLevels = 5; - pyrScale = 0.5; - fastPyramids = false; - winSize = 13; - numIters = 10; - polyN = 5; - polySigma = 1.1; - flags = 0; - } - - int numLevels; - double pyrScale; - bool fastPyramids; - int winSize; - int numIters; - int polyN; - double polySigma; - int flags; - - void operator ()(const GpuMat &frame0, const GpuMat &frame1, GpuMat &flowx, GpuMat &flowy, Stream &s = Stream::Null()); - - void releaseMemory() - { - frames_[0].release(); - frames_[1].release(); - pyrLevel_[0].release(); - pyrLevel_[1].release(); - M_.release(); - bufM_.release(); - R_[0].release(); - R_[1].release(); - blurredFrame_[0].release(); - blurredFrame_[1].release(); - pyramid0_.clear(); - pyramid1_.clear(); - } - -private: - void prepareGaussian( - int n, double sigma, float *g, float *xg, float *xxg, - double &ig11, double &ig03, double &ig33, double &ig55); - - void setPolynomialExpansionConsts(int n, double sigma); - - void updateFlow_boxFilter( - const GpuMat& R0, const GpuMat& R1, GpuMat& flowx, GpuMat &flowy, - GpuMat& M, GpuMat &bufM, int blockSize, bool updateMatrices, Stream streams[]); - - void updateFlow_gaussianBlur( - const GpuMat& R0, const GpuMat& R1, GpuMat& flowx, GpuMat& flowy, - GpuMat& M, GpuMat &bufM, int blockSize, bool updateMatrices, Stream streams[]); - - GpuMat frames_[2]; - GpuMat pyrLevel_[2], M_, bufM_, R_[2], blurredFrame_[2]; - std::vector pyramid0_, pyramid1_; -}; - - -// Implementation of the Zach, Pock and Bischof Dual TV-L1 Optical Flow method -// -// see reference: -// [1] C. Zach, T. Pock and H. Bischof, "A Duality Based Approach for Realtime TV-L1 Optical Flow". -// [2] Javier Sanchez, Enric Meinhardt-Llopis and Gabriele Facciolo. "TV-L1 Optical Flow Estimation". -class CV_EXPORTS OpticalFlowDual_TVL1_GPU -{ -public: - OpticalFlowDual_TVL1_GPU(); - - void operator ()(const GpuMat& I0, const GpuMat& I1, GpuMat& flowx, GpuMat& flowy); - - void collectGarbage(); - - /** - * Time step of the numerical scheme. - */ - double tau; - - /** - * Weight parameter for the data term, attachment parameter. - * This is the most relevant parameter, which determines the smoothness of the output. - * The smaller this parameter is, the smoother the solutions we obtain. - * It depends on the range of motions of the images, so its value should be adapted to each image sequence. - */ - double lambda; - - /** - * Weight parameter for (u - v)^2, tightness parameter. - * It serves as a link between the attachment and the regularization terms. - * In theory, it should have a small value in order to maintain both parts in correspondence. - * The method is stable for a large range of values of this parameter. - */ - double theta; - - /** - * Number of scales used to create the pyramid of images. - */ - int nscales; - - /** - * Number of warpings per scale. - * Represents the number of times that I1(x+u0) and grad( I1(x+u0) ) are computed per scale. - * This is a parameter that assures the stability of the method. - * It also affects the running time, so it is a compromise between speed and accuracy. - */ - int warps; - - /** - * Stopping criterion threshold used in the numerical scheme, which is a trade-off between precision and running time. - * A small value will yield more accurate solutions at the expense of a slower convergence. - */ - double epsilon; - - /** - * Stopping criterion iterations number used in the numerical scheme. - */ - int iterations; - - bool useInitialFlow; - -private: - void procOneScale(const GpuMat& I0, const GpuMat& I1, GpuMat& u1, GpuMat& u2); - - std::vector I0s; - std::vector I1s; - std::vector u1s; - std::vector u2s; - - GpuMat I1x_buf; - GpuMat I1y_buf; - - GpuMat I1w_buf; - GpuMat I1wx_buf; - GpuMat I1wy_buf; - - GpuMat grad_buf; - GpuMat rho_c_buf; - - GpuMat p11_buf; - GpuMat p12_buf; - GpuMat p21_buf; - GpuMat p22_buf; - - GpuMat diff_buf; - GpuMat norm_buf; -}; - - -//! Calculates optical flow for 2 images using block matching algorithm */ -CV_EXPORTS void calcOpticalFlowBM(const GpuMat& prev, const GpuMat& curr, - Size block_size, Size shift_size, Size max_range, bool use_previous, - GpuMat& velx, GpuMat& vely, GpuMat& buf, - Stream& stream = Stream::Null()); - -class CV_EXPORTS FastOpticalFlowBM -{ -public: - void operator ()(const GpuMat& I0, const GpuMat& I1, GpuMat& flowx, GpuMat& flowy, int search_window = 21, int block_window = 7, Stream& s = Stream::Null()); - -private: - GpuMat buffer; - GpuMat extended_I0; - GpuMat extended_I1; -}; - - -//! Interpolate frames (images) using provided optical flow (displacement field). -//! frame0 - frame 0 (32-bit floating point images, single channel) -//! frame1 - frame 1 (the same type and size) -//! fu - forward horizontal displacement -//! fv - forward vertical displacement -//! bu - backward horizontal displacement -//! bv - backward vertical displacement -//! pos - new frame position -//! newFrame - new frame -//! buf - temporary buffer, will have width x 6*height size, CV_32FC1 type and contain 6 GpuMat; -//! occlusion masks 0, occlusion masks 1, -//! interpolated forward flow 0, interpolated forward flow 1, -//! interpolated backward flow 0, interpolated backward flow 1 -//! -CV_EXPORTS void interpolateFrames(const GpuMat& frame0, const GpuMat& frame1, - const GpuMat& fu, const GpuMat& fv, - const GpuMat& bu, const GpuMat& bv, - float pos, GpuMat& newFrame, GpuMat& buf, - Stream& stream = Stream::Null()); - -CV_EXPORTS void createOpticalFlowNeedleMap(const GpuMat& u, const GpuMat& v, GpuMat& vertex, GpuMat& colors); - - -//////////////////////// Background/foreground segmentation //////////////////////// - -// Foreground Object Detection from Videos Containing Complex Background. -// Liyuan Li, Weimin Huang, Irene Y.H. Gu, and Qi Tian. -// ACM MM2003 9p -class CV_EXPORTS FGDStatModel -{ -public: - struct CV_EXPORTS Params - { - int Lc; // Quantized levels per 'color' component. Power of two, typically 32, 64 or 128. - int N1c; // Number of color vectors used to model normal background color variation at a given pixel. - int N2c; // Number of color vectors retained at given pixel. Must be > N1c, typically ~ 5/3 of N1c. - // Used to allow the first N1c vectors to adapt over time to changing background. - - int Lcc; // Quantized levels per 'color co-occurrence' component. Power of two, typically 16, 32 or 64. - int N1cc; // Number of color co-occurrence vectors used to model normal background color variation at a given pixel. - int N2cc; // Number of color co-occurrence vectors retained at given pixel. Must be > N1cc, typically ~ 5/3 of N1cc. - // Used to allow the first N1cc vectors to adapt over time to changing background. - - bool is_obj_without_holes; // If TRUE we ignore holes within foreground blobs. Defaults to TRUE. - int perform_morphing; // Number of erode-dilate-erode foreground-blob cleanup iterations. - // These erase one-pixel junk blobs and merge almost-touching blobs. Default value is 1. - - float alpha1; // How quickly we forget old background pixel values seen. Typically set to 0.1. - float alpha2; // "Controls speed of feature learning". Depends on T. Typical value circa 0.005. - float alpha3; // Alternate to alpha2, used (e.g.) for quicker initial convergence. Typical value 0.1. - - float delta; // Affects color and color co-occurrence quantization, typically set to 2. - float T; // A percentage value which determines when new features can be recognized as new background. (Typically 0.9). - float minArea; // Discard foreground blobs whose bounding box is smaller than this threshold. - - // default Params - Params(); - }; - - // out_cn - channels count in output result (can be 3 or 4) - // 4-channels require more memory, but a bit faster - explicit FGDStatModel(int out_cn = 3); - explicit FGDStatModel(const cv::gpu::GpuMat& firstFrame, const Params& params = Params(), int out_cn = 3); - - ~FGDStatModel(); - - void create(const cv::gpu::GpuMat& firstFrame, const Params& params = Params()); - void release(); - - int update(const cv::gpu::GpuMat& curFrame); - - //8UC3 or 8UC4 reference background image - cv::gpu::GpuMat background; - - //8UC1 foreground image - cv::gpu::GpuMat foreground; - - std::vector< std::vector > foreground_regions; - -private: - FGDStatModel(const FGDStatModel&); - FGDStatModel& operator=(const FGDStatModel&); - - class Impl; - std::auto_ptr impl_; -}; - -/*! - Gaussian Mixture-based Backbround/Foreground Segmentation Algorithm - - The class implements the following algorithm: - "An improved adaptive background mixture model for real-time tracking with shadow detection" - P. KadewTraKuPong and R. Bowden, - Proc. 2nd European Workshp on Advanced Video-Based Surveillance Systems, 2001." - http://personal.ee.surrey.ac.uk/Personal/R.Bowden/publications/avbs01/avbs01.pdf -*/ -class CV_EXPORTS MOG_GPU -{ -public: - //! the default constructor - MOG_GPU(int nmixtures = -1); - - //! re-initiaization method - void initialize(Size frameSize, int frameType); - - //! the update operator - void operator()(const GpuMat& frame, GpuMat& fgmask, float learningRate = 0.0f, Stream& stream = Stream::Null()); - - //! computes a background image which are the mean of all background gaussians - void getBackgroundImage(GpuMat& backgroundImage, Stream& stream = Stream::Null()) const; - - //! releases all inner buffers - void release(); - - int history; - float varThreshold; - float backgroundRatio; - float noiseSigma; - -private: - int nmixtures_; - - Size frameSize_; - int frameType_; - int nframes_; - - GpuMat weight_; - GpuMat sortKey_; - GpuMat mean_; - GpuMat var_; -}; - -/*! - The class implements the following algorithm: - "Improved adaptive Gausian mixture model for background subtraction" - Z.Zivkovic - International Conference Pattern Recognition, UK, August, 2004. - http://www.zoranz.net/Publications/zivkovic2004ICPR.pdf -*/ -class CV_EXPORTS MOG2_GPU -{ -public: - //! the default constructor - MOG2_GPU(int nmixtures = -1); - - //! re-initiaization method - void initialize(Size frameSize, int frameType); - - //! the update operator - void operator()(const GpuMat& frame, GpuMat& fgmask, float learningRate = -1.0f, Stream& stream = Stream::Null()); - - //! computes a background image which are the mean of all background gaussians - void getBackgroundImage(GpuMat& backgroundImage, Stream& stream = Stream::Null()) const; - - //! releases all inner buffers - void release(); - - // parameters - // you should call initialize after parameters changes - - int history; - - //! here it is the maximum allowed number of mixture components. - //! Actual number is determined dynamically per pixel - float varThreshold; - // threshold on the squared Mahalanobis distance to decide if it is well described - // by the background model or not. Related to Cthr from the paper. - // This does not influence the update of the background. A typical value could be 4 sigma - // and that is varThreshold=4*4=16; Corresponds to Tb in the paper. - - ///////////////////////// - // less important parameters - things you might change but be carefull - //////////////////////// - - float backgroundRatio; - // corresponds to fTB=1-cf from the paper - // TB - threshold when the component becomes significant enough to be included into - // the background model. It is the TB=1-cf from the paper. So I use cf=0.1 => TB=0. - // For alpha=0.001 it means that the mode should exist for approximately 105 frames before - // it is considered foreground - // float noiseSigma; - float varThresholdGen; - - //correspondts to Tg - threshold on the squared Mahalan. dist. to decide - //when a sample is close to the existing components. If it is not close - //to any a new component will be generated. I use 3 sigma => Tg=3*3=9. - //Smaller Tg leads to more generated components and higher Tg might make - //lead to small number of components but they can grow too large - float fVarInit; - float fVarMin; - float fVarMax; - - //initial variance for the newly generated components. - //It will will influence the speed of adaptation. A good guess should be made. - //A simple way is to estimate the typical standard deviation from the images. - //I used here 10 as a reasonable value - // min and max can be used to further control the variance - float fCT; //CT - complexity reduction prior - //this is related to the number of samples needed to accept that a component - //actually exists. We use CT=0.05 of all the samples. By setting CT=0 you get - //the standard Stauffer&Grimson algorithm (maybe not exact but very similar) - - //shadow detection parameters - bool bShadowDetection; //default 1 - do shadow detection - unsigned char nShadowDetection; //do shadow detection - insert this value as the detection result - 127 default value - float fTau; - // Tau - shadow threshold. The shadow is detected if the pixel is darker - //version of the background. Tau is a threshold on how much darker the shadow can be. - //Tau= 0.5 means that if pixel is more than 2 times darker then it is not shadow - //See: Prati,Mikic,Trivedi,Cucchiarra,"Detecting Moving Shadows...",IEEE PAMI,2003. - -private: - int nmixtures_; - - Size frameSize_; - int frameType_; - int nframes_; - - GpuMat weight_; - GpuMat variance_; - GpuMat mean_; - - GpuMat bgmodelUsedModes_; //keep track of number of modes per pixel -}; - -/*! - * The class implements the following algorithm: - * "ViBe: A universal background subtraction algorithm for video sequences" - * O. Barnich and M. Van D Roogenbroeck - * IEEE Transactions on Image Processing, 20(6) :1709-1724, June 2011 - */ -class CV_EXPORTS VIBE_GPU -{ -public: - //! the default constructor - explicit VIBE_GPU(unsigned long rngSeed = 1234567); - - //! re-initiaization method - void initialize(const GpuMat& firstFrame, Stream& stream = Stream::Null()); - - //! the update operator - void operator()(const GpuMat& frame, GpuMat& fgmask, Stream& stream = Stream::Null()); - - //! releases all inner buffers - void release(); - - int nbSamples; // number of samples per pixel - int reqMatches; // #_min - int radius; // R - int subsamplingFactor; // amount of random subsampling - -private: - Size frameSize_; - - unsigned long rngSeed_; - GpuMat randStates_; - - GpuMat samples_; -}; - -/** - * Background Subtractor module. Takes a series of images and returns a sequence of mask (8UC1) - * images of the same size, where 255 indicates Foreground and 0 represents Background. - * This class implements an algorithm described in "Visual Tracking of Human Visitors under - * Variable-Lighting Conditions for a Responsive Audio Art Installation," A. Godbehere, - * A. Matsukawa, K. Goldberg, American Control Conference, Montreal, June 2012. - */ -class CV_EXPORTS GMG_GPU -{ -public: - GMG_GPU(); - - /** - * Validate parameters and set up data structures for appropriate frame size. - * @param frameSize Input frame size - * @param min Minimum value taken on by pixels in image sequence. Usually 0 - * @param max Maximum value taken on by pixels in image sequence. e.g. 1.0 or 255 - */ - void initialize(Size frameSize, float min = 0.0f, float max = 255.0f); - - /** - * Performs single-frame background subtraction and builds up a statistical background image - * model. - * @param frame Input frame - * @param fgmask Output mask image representing foreground and background pixels - * @param stream Stream for the asynchronous version - */ - void operator ()(const GpuMat& frame, GpuMat& fgmask, float learningRate = -1.0f, Stream& stream = Stream::Null()); - - //! Releases all inner buffers - void release(); - - //! Total number of distinct colors to maintain in histogram. - int maxFeatures; - - //! Set between 0.0 and 1.0, determines how quickly features are "forgotten" from histograms. - float learningRate; - - //! Number of frames of video to use to initialize histograms. - int numInitializationFrames; - - //! Number of discrete levels in each channel to be used in histograms. - int quantizationLevels; - - //! Prior probability that any given pixel is a background pixel. A sensitivity parameter. - float backgroundPrior; - - //! Value above which pixel is determined to be FG. - float decisionThreshold; - - //! Smoothing radius, in pixels, for cleaning up FG image. - int smoothingRadius; - - //! Perform background model update. - bool updateBackgroundModel; - -private: - float maxVal_, minVal_; - - Size frameSize_; - - int frameNum_; - - GpuMat nfeatures_; - GpuMat colors_; - GpuMat weights_; - - Ptr boxFilter_; - GpuMat buf_; -}; - -////////////////////////////////// Video Encoding ////////////////////////////////// - -// Works only under Windows -// Supports olny H264 video codec and AVI files -class CV_EXPORTS VideoWriter_GPU -{ -public: - struct EncoderParams; - - // Callbacks for video encoder, use it if you want to work with raw video stream - class EncoderCallBack; - - enum SurfaceFormat - { - SF_UYVY = 0, - SF_YUY2, - SF_YV12, - SF_NV12, - SF_IYUV, - SF_BGR, - SF_GRAY = SF_BGR - }; - - VideoWriter_GPU(); - VideoWriter_GPU(const std::string& fileName, cv::Size frameSize, double fps, SurfaceFormat format = SF_BGR); - VideoWriter_GPU(const std::string& fileName, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format = SF_BGR); - VideoWriter_GPU(const cv::Ptr& encoderCallback, cv::Size frameSize, double fps, SurfaceFormat format = SF_BGR); - VideoWriter_GPU(const cv::Ptr& encoderCallback, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format = SF_BGR); - ~VideoWriter_GPU(); - - // all methods throws cv::Exception if error occurs - void open(const std::string& fileName, cv::Size frameSize, double fps, SurfaceFormat format = SF_BGR); - void open(const std::string& fileName, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format = SF_BGR); - void open(const cv::Ptr& encoderCallback, cv::Size frameSize, double fps, SurfaceFormat format = SF_BGR); - void open(const cv::Ptr& encoderCallback, cv::Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format = SF_BGR); - - bool isOpened() const; - void close(); - - void write(const cv::gpu::GpuMat& image, bool lastFrame = false); - - struct CV_EXPORTS EncoderParams - { - int P_Interval; // NVVE_P_INTERVAL, - int IDR_Period; // NVVE_IDR_PERIOD, - int DynamicGOP; // NVVE_DYNAMIC_GOP, - int RCType; // NVVE_RC_TYPE, - int AvgBitrate; // NVVE_AVG_BITRATE, - int PeakBitrate; // NVVE_PEAK_BITRATE, - int QP_Level_Intra; // NVVE_QP_LEVEL_INTRA, - int QP_Level_InterP; // NVVE_QP_LEVEL_INTER_P, - int QP_Level_InterB; // NVVE_QP_LEVEL_INTER_B, - int DeblockMode; // NVVE_DEBLOCK_MODE, - int ProfileLevel; // NVVE_PROFILE_LEVEL, - int ForceIntra; // NVVE_FORCE_INTRA, - int ForceIDR; // NVVE_FORCE_IDR, - int ClearStat; // NVVE_CLEAR_STAT, - int DIMode; // NVVE_SET_DEINTERLACE, - int Presets; // NVVE_PRESETS, - int DisableCabac; // NVVE_DISABLE_CABAC, - int NaluFramingType; // NVVE_CONFIGURE_NALU_FRAMING_TYPE - int DisableSPSPPS; // NVVE_DISABLE_SPS_PPS - - EncoderParams(); - explicit EncoderParams(const std::string& configFile); - - void load(const std::string& configFile); - void save(const std::string& configFile) const; - }; - - EncoderParams getParams() const; - - class CV_EXPORTS EncoderCallBack - { - public: - enum PicType - { - IFRAME = 1, - PFRAME = 2, - BFRAME = 3 - }; - - virtual ~EncoderCallBack() {} - - // callback function to signal the start of bitstream that is to be encoded - // must return pointer to buffer - virtual uchar* acquireBitStream(int* bufferSize) = 0; - - // callback function to signal that the encoded bitstream is ready to be written to file - virtual void releaseBitStream(unsigned char* data, int size) = 0; - - // callback function to signal that the encoding operation on the frame has started - virtual void onBeginFrame(int frameNumber, PicType picType) = 0; - - // callback function signals that the encoding operation on the frame has finished - virtual void onEndFrame(int frameNumber, PicType picType) = 0; - }; - -private: - VideoWriter_GPU(const VideoWriter_GPU&); - VideoWriter_GPU& operator=(const VideoWriter_GPU&); - - class Impl; - std::auto_ptr impl_; -}; - - -////////////////////////////////// Video Decoding ////////////////////////////////////////// - -namespace detail -{ - class FrameQueue; - class VideoParser; -} - -class CV_EXPORTS VideoReader_GPU -{ -public: - enum Codec - { - MPEG1 = 0, - MPEG2, - MPEG4, - VC1, - H264, - JPEG, - H264_SVC, - H264_MVC, - - Uncompressed_YUV420 = (('I'<<24)|('Y'<<16)|('U'<<8)|('V')), // Y,U,V (4:2:0) - Uncompressed_YV12 = (('Y'<<24)|('V'<<16)|('1'<<8)|('2')), // Y,V,U (4:2:0) - Uncompressed_NV12 = (('N'<<24)|('V'<<16)|('1'<<8)|('2')), // Y,UV (4:2:0) - Uncompressed_YUYV = (('Y'<<24)|('U'<<16)|('Y'<<8)|('V')), // YUYV/YUY2 (4:2:2) - Uncompressed_UYVY = (('U'<<24)|('Y'<<16)|('V'<<8)|('Y')), // UYVY (4:2:2) - }; - - enum ChromaFormat - { - Monochrome=0, - YUV420, - YUV422, - YUV444, - }; - - struct FormatInfo - { - Codec codec; - ChromaFormat chromaFormat; - int width; - int height; - }; - - class VideoSource; - - VideoReader_GPU(); - explicit VideoReader_GPU(const std::string& filename); - explicit VideoReader_GPU(const cv::Ptr& source); - - ~VideoReader_GPU(); - - void open(const std::string& filename); - void open(const cv::Ptr& source); - bool isOpened() const; - - void close(); - - bool read(GpuMat& image); - - FormatInfo format() const; - void dumpFormat(std::ostream& st); - - class CV_EXPORTS VideoSource - { - public: - VideoSource() : frameQueue_(0), videoParser_(0) {} - virtual ~VideoSource() {} - - virtual FormatInfo format() const = 0; - virtual void start() = 0; - virtual void stop() = 0; - virtual bool isStarted() const = 0; - virtual bool hasError() const = 0; - - void setFrameQueue(detail::FrameQueue* frameQueue) { frameQueue_ = frameQueue; } - void setVideoParser(detail::VideoParser* videoParser) { videoParser_ = videoParser; } - - protected: - bool parseVideoData(const uchar* data, size_t size, bool endOfStream = false); - - private: - VideoSource(const VideoSource&); - VideoSource& operator =(const VideoSource&); - - detail::FrameQueue* frameQueue_; - detail::VideoParser* videoParser_; - }; - -private: - VideoReader_GPU(const VideoReader_GPU&); - VideoReader_GPU& operator =(const VideoReader_GPU&); - - class Impl; - std::auto_ptr impl_; -}; +//////////////////////////// VStab //////////////////////////// //! removes points (CV_32FC2, single row matrix) with zero mask value CV_EXPORTS void compactPoints(GpuMat &points0, GpuMat &points1, const GpuMat &mask); @@ -2447,8 +255,6 @@ CV_EXPORTS void calcWobbleSuppressionMaps( int left, int idx, int right, Size size, const Mat &ml, const Mat &mr, GpuMat &mapx, GpuMat &mapy); -} // namespace gpu - -} // namespace cv +}} // namespace cv { namespace gpu { #endif /* __OPENCV_GPU_HPP__ */ diff --git a/modules/gpu/include/opencv2/gpu/device/emulation.hpp b/modules/gpu/include/opencv2/gpu/device/emulation.hpp deleted file mode 100644 index b6fba230e7..0000000000 --- a/modules/gpu/include/opencv2/gpu/device/emulation.hpp +++ /dev/null @@ -1,138 +0,0 @@ -/*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 bpied warranties, including, but not limited to, the bpied -// 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_GPU_EMULATION_HPP_ -#define OPENCV_GPU_EMULATION_HPP_ - -#include "warp_reduce.hpp" - -namespace cv { namespace gpu { namespace device -{ - struct Emulation - { - - static __device__ __forceinline__ int syncthreadsOr(int pred) - { -#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ < 200) - // just campilation stab - return 0; -#else - return __syncthreads_or(pred); -#endif - } - - template - static __forceinline__ __device__ int Ballot(int predicate) - { -#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ >= 200) - return __ballot(predicate); -#else - __shared__ volatile int cta_buffer[CTA_SIZE]; - - int tid = threadIdx.x; - cta_buffer[tid] = predicate ? (1 << (tid & 31)) : 0; - return warp_reduce(cta_buffer); -#endif - } - - struct smem - { - enum { TAG_MASK = (1U << ( (sizeof(unsigned int) << 3) - 5U)) - 1U }; - - template - static __device__ __forceinline__ T atomicInc(T* address, T val) - { -#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ < 120) - T count; - unsigned int tag = threadIdx.x << ( (sizeof(unsigned int) << 3) - 5U); - do - { - count = *address & TAG_MASK; - count = tag | (count + 1); - *address = count; - } while (*address != count); - - return (count & TAG_MASK) - 1; -#else - return ::atomicInc(address, val); -#endif - } - - template - static __device__ __forceinline__ T atomicAdd(T* address, T val) - { -#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ < 120) - T count; - unsigned int tag = threadIdx.x << ( (sizeof(unsigned int) << 3) - 5U); - do - { - count = *address & TAG_MASK; - count = tag | (count + val); - *address = count; - } while (*address != count); - - return (count & TAG_MASK) - val; -#else - return ::atomicAdd(address, val); -#endif - } - - template - static __device__ __forceinline__ T atomicMin(T* address, T val) - { -#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ < 120) - T count = ::min(*address, val); - do - { - *address = count; - } while (*address > count); - - return count; -#else - return ::atomicMin(address, val); -#endif - } - }; - }; -}}} // namespace cv { namespace gpu { namespace device - -#endif /* OPENCV_GPU_EMULATION_HPP_ */ diff --git a/modules/gpu/include/opencv2/gpu/device/limits.hpp b/modules/gpu/include/opencv2/gpu/device/limits.hpp deleted file mode 100644 index b040f199d6..0000000000 --- a/modules/gpu/include/opencv2/gpu/device/limits.hpp +++ /dev/null @@ -1,235 +0,0 @@ -/*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_GPU_LIMITS_GPU_HPP__ -#define __OPENCV_GPU_LIMITS_GPU_HPP__ - -#include -#include "common.hpp" - -namespace cv { namespace gpu { namespace device -{ - template struct numeric_limits - { - typedef T type; - __device__ __forceinline__ static type min() { return type(); }; - __device__ __forceinline__ static type max() { return type(); }; - __device__ __forceinline__ static type epsilon() { return type(); } - __device__ __forceinline__ static type round_error() { return type(); } - __device__ __forceinline__ static type denorm_min() { return type(); } - __device__ __forceinline__ static type infinity() { return type(); } - __device__ __forceinline__ static type quiet_NaN() { return type(); } - __device__ __forceinline__ static type signaling_NaN() { return T(); } - static const bool is_signed; - }; - - template<> struct numeric_limits - { - typedef bool type; - __device__ __forceinline__ static type min() { return false; }; - __device__ __forceinline__ static type max() { return true; }; - __device__ __forceinline__ static type epsilon(); - __device__ __forceinline__ static type round_error(); - __device__ __forceinline__ static type denorm_min(); - __device__ __forceinline__ static type infinity(); - __device__ __forceinline__ static type quiet_NaN(); - __device__ __forceinline__ static type signaling_NaN(); - static const bool is_signed = false; - }; - - template<> struct numeric_limits - { - typedef char type; - __device__ __forceinline__ static type min() { return CHAR_MIN; }; - __device__ __forceinline__ static type max() { return CHAR_MAX; }; - __device__ __forceinline__ static type epsilon(); - __device__ __forceinline__ static type round_error(); - __device__ __forceinline__ static type denorm_min(); - __device__ __forceinline__ static type infinity(); - __device__ __forceinline__ static type quiet_NaN(); - __device__ __forceinline__ static type signaling_NaN(); - static const bool is_signed = (char)-1 == -1; - }; - - template<> struct numeric_limits - { - typedef char type; - __device__ __forceinline__ static type min() { return SCHAR_MIN; }; - __device__ __forceinline__ static type max() { return SCHAR_MAX; }; - __device__ __forceinline__ static type epsilon(); - __device__ __forceinline__ static type round_error(); - __device__ __forceinline__ static type denorm_min(); - __device__ __forceinline__ static type infinity(); - __device__ __forceinline__ static type quiet_NaN(); - __device__ __forceinline__ static type signaling_NaN(); - static const bool is_signed = (signed char)-1 == -1; - }; - - template<> struct numeric_limits - { - typedef unsigned char type; - __device__ __forceinline__ static type min() { return 0; }; - __device__ __forceinline__ static type max() { return UCHAR_MAX; }; - __device__ __forceinline__ static type epsilon(); - __device__ __forceinline__ static type round_error(); - __device__ __forceinline__ static type denorm_min(); - __device__ __forceinline__ static type infinity(); - __device__ __forceinline__ static type quiet_NaN(); - __device__ __forceinline__ static type signaling_NaN(); - static const bool is_signed = false; - }; - - template<> struct numeric_limits - { - typedef short type; - __device__ __forceinline__ static type min() { return SHRT_MIN; }; - __device__ __forceinline__ static type max() { return SHRT_MAX; }; - __device__ __forceinline__ static type epsilon(); - __device__ __forceinline__ static type round_error(); - __device__ __forceinline__ static type denorm_min(); - __device__ __forceinline__ static type infinity(); - __device__ __forceinline__ static type quiet_NaN(); - __device__ __forceinline__ static type signaling_NaN(); - static const bool is_signed = true; - }; - - template<> struct numeric_limits - { - typedef unsigned short type; - __device__ __forceinline__ static type min() { return 0; }; - __device__ __forceinline__ static type max() { return USHRT_MAX; }; - __device__ __forceinline__ static type epsilon(); - __device__ __forceinline__ static type round_error(); - __device__ __forceinline__ static type denorm_min(); - __device__ __forceinline__ static type infinity(); - __device__ __forceinline__ static type quiet_NaN(); - __device__ __forceinline__ static type signaling_NaN(); - static const bool is_signed = false; - }; - - template<> struct numeric_limits - { - typedef int type; - __device__ __forceinline__ static type min() { return INT_MIN; }; - __device__ __forceinline__ static type max() { return INT_MAX; }; - __device__ __forceinline__ static type epsilon(); - __device__ __forceinline__ static type round_error(); - __device__ __forceinline__ static type denorm_min(); - __device__ __forceinline__ static type infinity(); - __device__ __forceinline__ static type quiet_NaN(); - __device__ __forceinline__ static type signaling_NaN(); - static const bool is_signed = true; - }; - - - template<> struct numeric_limits - { - typedef unsigned int type; - __device__ __forceinline__ static type min() { return 0; }; - __device__ __forceinline__ static type max() { return UINT_MAX; }; - __device__ __forceinline__ static type epsilon(); - __device__ __forceinline__ static type round_error(); - __device__ __forceinline__ static type denorm_min(); - __device__ __forceinline__ static type infinity(); - __device__ __forceinline__ static type quiet_NaN(); - __device__ __forceinline__ static type signaling_NaN(); - static const bool is_signed = false; - }; - - template<> struct numeric_limits - { - typedef long type; - __device__ __forceinline__ static type min() { return LONG_MIN; }; - __device__ __forceinline__ static type max() { return LONG_MAX; }; - __device__ __forceinline__ static type epsilon(); - __device__ __forceinline__ static type round_error(); - __device__ __forceinline__ static type denorm_min(); - __device__ __forceinline__ static type infinity(); - __device__ __forceinline__ static type quiet_NaN(); - __device__ __forceinline__ static type signaling_NaN(); - static const bool is_signed = true; - }; - - template<> struct numeric_limits - { - typedef unsigned long type; - __device__ __forceinline__ static type min() { return 0; }; - __device__ __forceinline__ static type max() { return ULONG_MAX; }; - __device__ __forceinline__ static type epsilon(); - __device__ __forceinline__ static type round_error(); - __device__ __forceinline__ static type denorm_min(); - __device__ __forceinline__ static type infinity(); - __device__ __forceinline__ static type quiet_NaN(); - __device__ __forceinline__ static type signaling_NaN(); - static const bool is_signed = false; - }; - - template<> struct numeric_limits - { - typedef float type; - __device__ __forceinline__ static type min() { return 1.175494351e-38f/*FLT_MIN*/; }; - __device__ __forceinline__ static type max() { return 3.402823466e+38f/*FLT_MAX*/; }; - __device__ __forceinline__ static type epsilon() { return 1.192092896e-07f/*FLT_EPSILON*/; }; - __device__ __forceinline__ static type round_error(); - __device__ __forceinline__ static type denorm_min(); - __device__ __forceinline__ static type infinity(); - __device__ __forceinline__ static type quiet_NaN(); - __device__ __forceinline__ static type signaling_NaN(); - static const bool is_signed = true; - }; - - template<> struct numeric_limits - { - typedef double type; - __device__ __forceinline__ static type min() { return 2.2250738585072014e-308/*DBL_MIN*/; }; - __device__ __forceinline__ static type max() { return 1.7976931348623158e+308/*DBL_MAX*/; }; - __device__ __forceinline__ static type epsilon(); - __device__ __forceinline__ static type round_error(); - __device__ __forceinline__ static type denorm_min(); - __device__ __forceinline__ static type infinity(); - __device__ __forceinline__ static type quiet_NaN(); - __device__ __forceinline__ static type signaling_NaN(); - static const bool is_signed = true; - }; -}}} // namespace cv { namespace gpu { namespace device { - -#endif // __OPENCV_GPU_LIMITS_GPU_HPP__ diff --git a/modules/gpu/include/opencv2/gpu/device/vec_math.hpp b/modules/gpu/include/opencv2/gpu/device/vec_math.hpp deleted file mode 100644 index 1c46dc0c33..0000000000 --- a/modules/gpu/include/opencv2/gpu/device/vec_math.hpp +++ /dev/null @@ -1,330 +0,0 @@ -/*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_GPU_VECMATH_HPP__ -#define __OPENCV_GPU_VECMATH_HPP__ - -#include "saturate_cast.hpp" -#include "vec_traits.hpp" -#include "functional.hpp" - -namespace cv { namespace gpu { namespace device -{ - namespace vec_math_detail - { - template struct SatCastHelper; - template struct SatCastHelper<1, VecD> - { - template static __device__ __forceinline__ VecD cast(const VecS& v) - { - typedef typename VecTraits::elem_type D; - return VecTraits::make(saturate_cast(v.x)); - } - }; - template struct SatCastHelper<2, VecD> - { - template static __device__ __forceinline__ VecD cast(const VecS& v) - { - typedef typename VecTraits::elem_type D; - return VecTraits::make(saturate_cast(v.x), saturate_cast(v.y)); - } - }; - template struct SatCastHelper<3, VecD> - { - template static __device__ __forceinline__ VecD cast(const VecS& v) - { - typedef typename VecTraits::elem_type D; - return VecTraits::make(saturate_cast(v.x), saturate_cast(v.y), saturate_cast(v.z)); - } - }; - template struct SatCastHelper<4, VecD> - { - template static __device__ __forceinline__ VecD cast(const VecS& v) - { - typedef typename VecTraits::elem_type D; - return VecTraits::make(saturate_cast(v.x), saturate_cast(v.y), saturate_cast(v.z), saturate_cast(v.w)); - } - }; - - template static __device__ __forceinline__ VecD saturate_cast_caller(const VecS& v) - { - return SatCastHelper::cn, VecD>::cast(v); - } - } - - template static __device__ __forceinline__ _Tp saturate_cast(const uchar1& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const char1& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const ushort1& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const short1& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const uint1& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const int1& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const float1& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const double1& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - - template static __device__ __forceinline__ _Tp saturate_cast(const uchar2& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const char2& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const ushort2& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const short2& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const uint2& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const int2& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const float2& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const double2& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - - template static __device__ __forceinline__ _Tp saturate_cast(const uchar3& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const char3& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const ushort3& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const short3& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const uint3& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const int3& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const float3& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const double3& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - - template static __device__ __forceinline__ _Tp saturate_cast(const uchar4& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const char4& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const ushort4& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const short4& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const uint4& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const int4& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const float4& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - template static __device__ __forceinline__ _Tp saturate_cast(const double4& v) {return vec_math_detail::saturate_cast_caller<_Tp>(v);} - -#define OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, op, func) \ - __device__ __forceinline__ TypeVec::result_type, 1>::vec_type op(const type ## 1 & a) \ - { \ - func f; \ - return VecTraits::result_type, 1>::vec_type>::make(f(a.x)); \ - } \ - __device__ __forceinline__ TypeVec::result_type, 2>::vec_type op(const type ## 2 & a) \ - { \ - func f; \ - return VecTraits::result_type, 2>::vec_type>::make(f(a.x), f(a.y)); \ - } \ - __device__ __forceinline__ TypeVec::result_type, 3>::vec_type op(const type ## 3 & a) \ - { \ - func f; \ - return VecTraits::result_type, 3>::vec_type>::make(f(a.x), f(a.y), f(a.z)); \ - } \ - __device__ __forceinline__ TypeVec::result_type, 4>::vec_type op(const type ## 4 & a) \ - { \ - func f; \ - return VecTraits::result_type, 4>::vec_type>::make(f(a.x), f(a.y), f(a.z), f(a.w)); \ - } - - namespace vec_math_detail - { - template struct BinOpTraits - { - typedef int argument_type; - }; - template struct BinOpTraits - { - typedef T argument_type; - }; - template struct BinOpTraits - { - typedef double argument_type; - }; - template struct BinOpTraits - { - typedef double argument_type; - }; - template <> struct BinOpTraits - { - typedef double argument_type; - }; - template struct BinOpTraits - { - typedef float argument_type; - }; - template struct BinOpTraits - { - typedef float argument_type; - }; - template <> struct BinOpTraits - { - typedef float argument_type; - }; - template <> struct BinOpTraits - { - typedef double argument_type; - }; - template <> struct BinOpTraits - { - typedef double argument_type; - }; - } - -#define OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, op, func) \ - __device__ __forceinline__ TypeVec::result_type, 1>::vec_type op(const type ## 1 & a, const type ## 1 & b) \ - { \ - func f; \ - return VecTraits::result_type, 1>::vec_type>::make(f(a.x, b.x)); \ - } \ - template \ - __device__ __forceinline__ typename TypeVec::argument_type>::result_type, 1>::vec_type op(const type ## 1 & v, T s) \ - { \ - func::argument_type> f; \ - return VecTraits::argument_type>::result_type, 1>::vec_type>::make(f(v.x, s)); \ - } \ - template \ - __device__ __forceinline__ typename TypeVec::argument_type>::result_type, 1>::vec_type op(T s, const type ## 1 & v) \ - { \ - func::argument_type> f; \ - return VecTraits::argument_type>::result_type, 1>::vec_type>::make(f(s, v.x)); \ - } \ - __device__ __forceinline__ TypeVec::result_type, 2>::vec_type op(const type ## 2 & a, const type ## 2 & b) \ - { \ - func f; \ - return VecTraits::result_type, 2>::vec_type>::make(f(a.x, b.x), f(a.y, b.y)); \ - } \ - template \ - __device__ __forceinline__ typename TypeVec::argument_type>::result_type, 2>::vec_type op(const type ## 2 & v, T s) \ - { \ - func::argument_type> f; \ - return VecTraits::argument_type>::result_type, 2>::vec_type>::make(f(v.x, s), f(v.y, s)); \ - } \ - template \ - __device__ __forceinline__ typename TypeVec::argument_type>::result_type, 2>::vec_type op(T s, const type ## 2 & v) \ - { \ - func::argument_type> f; \ - return VecTraits::argument_type>::result_type, 2>::vec_type>::make(f(s, v.x), f(s, v.y)); \ - } \ - __device__ __forceinline__ TypeVec::result_type, 3>::vec_type op(const type ## 3 & a, const type ## 3 & b) \ - { \ - func f; \ - return VecTraits::result_type, 3>::vec_type>::make(f(a.x, b.x), f(a.y, b.y), f(a.z, b.z)); \ - } \ - template \ - __device__ __forceinline__ typename TypeVec::argument_type>::result_type, 3>::vec_type op(const type ## 3 & v, T s) \ - { \ - func::argument_type> f; \ - return VecTraits::argument_type>::result_type, 3>::vec_type>::make(f(v.x, s), f(v.y, s), f(v.z, s)); \ - } \ - template \ - __device__ __forceinline__ typename TypeVec::argument_type>::result_type, 3>::vec_type op(T s, const type ## 3 & v) \ - { \ - func::argument_type> f; \ - return VecTraits::argument_type>::result_type, 3>::vec_type>::make(f(s, v.x), f(s, v.y), f(s, v.z)); \ - } \ - __device__ __forceinline__ TypeVec::result_type, 4>::vec_type op(const type ## 4 & a, const type ## 4 & b) \ - { \ - func f; \ - return VecTraits::result_type, 4>::vec_type>::make(f(a.x, b.x), f(a.y, b.y), f(a.z, b.z), f(a.w, b.w)); \ - } \ - template \ - __device__ __forceinline__ typename TypeVec::argument_type>::result_type, 4>::vec_type op(const type ## 4 & v, T s) \ - { \ - func::argument_type> f; \ - return VecTraits::argument_type>::result_type, 4>::vec_type>::make(f(v.x, s), f(v.y, s), f(v.z, s), f(v.w, s)); \ - } \ - template \ - __device__ __forceinline__ typename TypeVec::argument_type>::result_type, 4>::vec_type op(T s, const type ## 4 & v) \ - { \ - func::argument_type> f; \ - return VecTraits::argument_type>::result_type, 4>::vec_type>::make(f(s, v.x), f(s, v.y), f(s, v.z), f(s, v.w)); \ - } - -#define OPENCV_GPU_IMPLEMENT_VEC_OP(type) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, operator +, plus) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, operator -, minus) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, operator *, multiplies) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, operator /, divides) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP (type, operator -, negate) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, operator ==, equal_to) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, operator !=, not_equal_to) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, operator > , greater) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, operator < , less) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, operator >=, greater_equal) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, operator <=, less_equal) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, operator &&, logical_and) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, operator ||, logical_or) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP (type, operator ! , logical_not) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, max, maximum) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, min, minimum) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, abs, abs_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, sqrt, sqrt_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, exp, exp_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, exp2, exp2_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, exp10, exp10_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, log, log_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, log2, log2_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, log10, log10_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, sin, sin_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, cos, cos_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, tan, tan_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, asin, asin_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, acos, acos_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, atan, atan_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, sinh, sinh_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, cosh, cosh_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, tanh, tanh_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, asinh, asinh_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, acosh, acosh_func) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP(type, atanh, atanh_func) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, hypot, hypot_func) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, atan2, atan2_func) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, pow, pow_func) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, hypot_sqr, hypot_sqr_func) - -#define OPENCV_GPU_IMPLEMENT_VEC_INT_OP(type) \ - OPENCV_GPU_IMPLEMENT_VEC_OP(type) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, operator &, bit_and) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, operator |, bit_or) \ - OPENCV_GPU_IMPLEMENT_VEC_BINOP(type, operator ^, bit_xor) \ - OPENCV_GPU_IMPLEMENT_VEC_UNOP (type, operator ~, bit_not) - - OPENCV_GPU_IMPLEMENT_VEC_INT_OP(uchar) - OPENCV_GPU_IMPLEMENT_VEC_INT_OP(char) - OPENCV_GPU_IMPLEMENT_VEC_INT_OP(ushort) - OPENCV_GPU_IMPLEMENT_VEC_INT_OP(short) - OPENCV_GPU_IMPLEMENT_VEC_INT_OP(int) - OPENCV_GPU_IMPLEMENT_VEC_INT_OP(uint) - OPENCV_GPU_IMPLEMENT_VEC_OP(float) - OPENCV_GPU_IMPLEMENT_VEC_OP(double) - - #undef OPENCV_GPU_IMPLEMENT_VEC_UNOP - #undef OPENCV_GPU_IMPLEMENT_VEC_BINOP - #undef OPENCV_GPU_IMPLEMENT_VEC_OP - #undef OPENCV_GPU_IMPLEMENT_VEC_INT_OP -}}} // namespace cv { namespace gpu { namespace device - -#endif // __OPENCV_GPU_VECMATH_HPP__ diff --git a/modules/gpu/include/opencv2/gpu/gpu.hpp b/modules/gpu/include/opencv2/gpu/gpu.hpp index d82211bf38..e044ad1e8a 100644 --- a/modules/gpu/include/opencv2/gpu/gpu.hpp +++ b/modules/gpu/include/opencv2/gpu/gpu.hpp @@ -7,7 +7,7 @@ // copy or use the software. // // -// License Agreement +// License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. @@ -45,4 +45,4 @@ #error this is a compatibility header which should not be used inside the OpenCV library #endif -#include "opencv2/gpu.hpp" \ No newline at end of file +#include "opencv2/gpu.hpp" diff --git a/modules/gpu/include/opencv2/gpu/gpumat.hpp b/modules/gpu/include/opencv2/gpu/gpumat.hpp deleted file mode 100644 index 0033cbe961..0000000000 --- a/modules/gpu/include/opencv2/gpu/gpumat.hpp +++ /dev/null @@ -1,43 +0,0 @@ -/*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 GpuMaterials 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 "opencv2/core/gpumat.hpp" diff --git a/modules/gpu/misc/mark_nvidia.py b/modules/gpu/misc/mark_nvidia.py index e8cc3e8417..80dc7f9cee 100755 --- a/modules/gpu/misc/mark_nvidia.py +++ b/modules/gpu/misc/mark_nvidia.py @@ -1,4 +1,4 @@ -#/usr/bin/env python +#!/usr/bin/env python import sys, re @@ -257,4 +257,3 @@ if __name__ == "__main__": outputFile = open(sys.argv[2], 'w') outputFile.writelines(lines) outputFile.close() - diff --git a/modules/gpu/perf/perf_calib3d.cpp b/modules/gpu/perf/perf_calib3d.cpp index b174d9a12e..185d9cd684 100644 --- a/modules/gpu/perf/perf_calib3d.cpp +++ b/modules/gpu/perf/perf_calib3d.cpp @@ -1,183 +1,53 @@ +/*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 "perf_precomp.hpp" using namespace std; using namespace testing; - -////////////////////////////////////////////////////////////////////// -// StereoBM - -typedef std::tr1::tuple pair_string; -DEF_PARAM_TEST_1(ImagePair, pair_string); - -PERF_TEST_P(ImagePair, Calib3D_StereoBM, - Values(pair_string("gpu/perf/aloe.png", "gpu/perf/aloeR.png"))) -{ - declare.time(5.0); - - const cv::Mat imgLeft = readImage(GET_PARAM(0), cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(imgLeft.empty()); - - const cv::Mat imgRight = readImage(GET_PARAM(1), cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(imgRight.empty()); - - const int preset = 0; - const int ndisp = 256; - - if (PERF_RUN_GPU()) - { - cv::gpu::StereoBM_GPU d_bm(preset, ndisp); - - const cv::gpu::GpuMat d_imgLeft(imgLeft); - const cv::gpu::GpuMat d_imgRight(imgRight); - cv::gpu::GpuMat dst; - - TEST_CYCLE() d_bm(d_imgLeft, d_imgRight, dst); - - GPU_SANITY_CHECK(dst); - } - else - { - cv::StereoBM bm(preset, ndisp); - - cv::Mat dst; - - TEST_CYCLE() bm(imgLeft, imgRight, dst); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// StereoBeliefPropagation - -PERF_TEST_P(ImagePair, Calib3D_StereoBeliefPropagation, - Values(pair_string("gpu/stereobp/aloe-L.png", "gpu/stereobp/aloe-R.png"))) -{ - declare.time(10.0); - - const cv::Mat imgLeft = readImage(GET_PARAM(0)); - ASSERT_FALSE(imgLeft.empty()); - - const cv::Mat imgRight = readImage(GET_PARAM(1)); - ASSERT_FALSE(imgRight.empty()); - - const int ndisp = 64; - - if (PERF_RUN_GPU()) - { - cv::gpu::StereoBeliefPropagation d_bp(ndisp); - - const cv::gpu::GpuMat d_imgLeft(imgLeft); - const cv::gpu::GpuMat d_imgRight(imgRight); - cv::gpu::GpuMat dst; - - TEST_CYCLE() d_bp(d_imgLeft, d_imgRight, dst); - - GPU_SANITY_CHECK(dst); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// StereoConstantSpaceBP - -PERF_TEST_P(ImagePair, Calib3D_StereoConstantSpaceBP, - Values(pair_string("gpu/stereobm/aloe-L.png", "gpu/stereobm/aloe-R.png"))) -{ - declare.time(10.0); - - const cv::Mat imgLeft = readImage(GET_PARAM(0), cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(imgLeft.empty()); - - const cv::Mat imgRight = readImage(GET_PARAM(1), cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(imgRight.empty()); - - const int ndisp = 128; - - if (PERF_RUN_GPU()) - { - cv::gpu::StereoConstantSpaceBP d_csbp(ndisp); - - const cv::gpu::GpuMat d_imgLeft(imgLeft); - const cv::gpu::GpuMat d_imgRight(imgRight); - cv::gpu::GpuMat dst; - - TEST_CYCLE() d_csbp(d_imgLeft, d_imgRight, dst); - - GPU_SANITY_CHECK(dst); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// DisparityBilateralFilter - -PERF_TEST_P(ImagePair, Calib3D_DisparityBilateralFilter, - Values(pair_string("gpu/stereobm/aloe-L.png", "gpu/stereobm/aloe-disp.png"))) -{ - const cv::Mat img = readImage(GET_PARAM(0), cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(img.empty()); - - const cv::Mat disp = readImage(GET_PARAM(1), cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(disp.empty()); - - const int ndisp = 128; - - if (PERF_RUN_GPU()) - { - cv::gpu::DisparityBilateralFilter d_filter(ndisp); - - const cv::gpu::GpuMat d_img(img); - const cv::gpu::GpuMat d_disp(disp); - cv::gpu::GpuMat dst; - - TEST_CYCLE() d_filter(d_disp, d_img, dst); - - GPU_SANITY_CHECK(dst); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// TransformPoints +using namespace perf; DEF_PARAM_TEST_1(Count, int); -PERF_TEST_P(Count, Calib3D_TransformPoints, - Values(5000, 10000, 20000)) -{ - const int count = GetParam(); - - cv::Mat src(1, count, CV_32FC3); - declare.in(src, WARMUP_RNG); - - const cv::Mat rvec = cv::Mat::ones(1, 3, CV_32FC1); - const cv::Mat tvec = cv::Mat::ones(1, 3, CV_32FC1); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::transformPoints(d_src, rvec, tvec, dst); - - GPU_SANITY_CHECK(dst); - } - else - { - FAIL_NO_CPU(); - } -} - ////////////////////////////////////////////////////////////////////// // ProjectPoints @@ -263,66 +133,3 @@ PERF_TEST_P(Count, Calib3D_SolvePnPRansac, CPU_SANITY_CHECK(tvec, 1e-6); } } - -////////////////////////////////////////////////////////////////////// -// ReprojectImageTo3D - -PERF_TEST_P(Sz_Depth, Calib3D_ReprojectImageTo3D, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16S))) -{ - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - - cv::Mat src(size, depth); - declare.in(src, WARMUP_RNG); - - cv::Mat Q(4, 4, CV_32FC1); - cv::randu(Q, 0.1, 1.0); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::reprojectImageTo3D(d_src, dst, Q); - - GPU_SANITY_CHECK(dst); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::reprojectImageTo3D(src, dst, Q); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// DrawColorDisp - -PERF_TEST_P(Sz_Depth, Calib3D_DrawColorDisp, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16S))) -{ - const cv::Size size = GET_PARAM(0); - const int type = GET_PARAM(1); - - cv::Mat src(size, type); - declare.in(src, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::drawColorDisp(d_src, dst, 255); - - GPU_SANITY_CHECK(dst); - } - else - { - FAIL_NO_CPU(); - } -} diff --git a/modules/gpu/perf/perf_imgproc.cpp b/modules/gpu/perf/perf_imgproc.cpp deleted file mode 100644 index be6eb4877c..0000000000 --- a/modules/gpu/perf/perf_imgproc.cpp +++ /dev/null @@ -1,1775 +0,0 @@ -#include "perf_precomp.hpp" - -using namespace std; -using namespace testing; -using namespace perf; - -////////////////////////////////////////////////////////////////////// -// Remap - -enum { HALF_SIZE=0, UPSIDE_DOWN, REFLECTION_X, REFLECTION_BOTH }; -CV_ENUM(RemapMode, HALF_SIZE, UPSIDE_DOWN, REFLECTION_X, REFLECTION_BOTH); -#define ALL_REMAP_MODES ValuesIn(RemapMode::all()) - -void generateMap(cv::Mat& map_x, cv::Mat& map_y, int remapMode) -{ - for (int j = 0; j < map_x.rows; ++j) - { - for (int i = 0; i < map_x.cols; ++i) - { - switch (remapMode) - { - case HALF_SIZE: - if (i > map_x.cols*0.25 && i < map_x.cols*0.75 && j > map_x.rows*0.25 && j < map_x.rows*0.75) - { - map_x.at(j,i) = 2.f * (i - map_x.cols * 0.25f) + 0.5f; - map_y.at(j,i) = 2.f * (j - map_x.rows * 0.25f) + 0.5f; - } - else - { - map_x.at(j,i) = 0.f; - map_y.at(j,i) = 0.f; - } - break; - case UPSIDE_DOWN: - map_x.at(j,i) = static_cast(i); - map_y.at(j,i) = static_cast(map_x.rows - j); - break; - case REFLECTION_X: - map_x.at(j,i) = static_cast(map_x.cols - i); - map_y.at(j,i) = static_cast(j); - break; - case REFLECTION_BOTH: - map_x.at(j,i) = static_cast(map_x.cols - i); - map_y.at(j,i) = static_cast(map_x.rows - j); - break; - } // end of switch - } - } -} - -DEF_PARAM_TEST(Sz_Depth_Cn_Inter_Border_Mode, cv::Size, MatDepth, MatCn, Interpolation, BorderMode, RemapMode); - -PERF_TEST_P(Sz_Depth_Cn_Inter_Border_Mode, ImgProc_Remap, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16U, CV_32F), - GPU_CHANNELS_1_3_4, - Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)), - ALL_BORDER_MODES, - ALL_REMAP_MODES)) -{ - declare.time(20.0); - - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - const int channels = GET_PARAM(2); - const int interpolation = GET_PARAM(3); - const int borderMode = GET_PARAM(4); - const int remapMode = GET_PARAM(5); - - const int type = CV_MAKE_TYPE(depth, channels); - - cv::Mat src(size, type); - declare.in(src, WARMUP_RNG); - - cv::Mat xmap(size, CV_32FC1); - cv::Mat ymap(size, CV_32FC1); - generateMap(xmap, ymap, remapMode); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - const cv::gpu::GpuMat d_xmap(xmap); - const cv::gpu::GpuMat d_ymap(ymap); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::remap(d_src, dst, d_xmap, d_ymap, interpolation, borderMode); - - GPU_SANITY_CHECK(dst); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::remap(src, dst, xmap, ymap, interpolation, borderMode); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// Resize - -DEF_PARAM_TEST(Sz_Depth_Cn_Inter_Scale, cv::Size, MatDepth, MatCn, Interpolation, double); - -PERF_TEST_P(Sz_Depth_Cn_Inter_Scale, ImgProc_Resize, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16U, CV_32F), - GPU_CHANNELS_1_3_4, - Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)), - Values(0.5, 0.3, 2.0))) -{ - declare.time(20.0); - - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - const int channels = GET_PARAM(2); - const int interpolation = GET_PARAM(3); - const double f = GET_PARAM(4); - - const int type = CV_MAKE_TYPE(depth, channels); - - cv::Mat src(size, type); - declare.in(src, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::resize(d_src, dst, cv::Size(), f, f, interpolation); - - GPU_SANITY_CHECK(dst, 1e-3, ERROR_RELATIVE); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::resize(src, dst, cv::Size(), f, f, interpolation); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// ResizeArea - -DEF_PARAM_TEST(Sz_Depth_Cn_Scale, cv::Size, MatDepth, MatCn, double); - -PERF_TEST_P(Sz_Depth_Cn_Scale, ImgProc_ResizeArea, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16U, CV_32F), - GPU_CHANNELS_1_3_4, - Values(0.2, 0.1, 0.05))) -{ - declare.time(1.0); - - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - const int channels = GET_PARAM(2); - const int interpolation = cv::INTER_AREA; - const double f = GET_PARAM(3); - - const int type = CV_MAKE_TYPE(depth, channels); - - cv::Mat src(size, type); - declare.in(src, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::resize(d_src, dst, cv::Size(), f, f, interpolation); - - GPU_SANITY_CHECK(dst); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::resize(src, dst, cv::Size(), f, f, interpolation); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// WarpAffine - -DEF_PARAM_TEST(Sz_Depth_Cn_Inter_Border, cv::Size, MatDepth, MatCn, Interpolation, BorderMode); - -PERF_TEST_P(Sz_Depth_Cn_Inter_Border, ImgProc_WarpAffine, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16U, CV_32F), - GPU_CHANNELS_1_3_4, - Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)), - ALL_BORDER_MODES)) -{ - declare.time(20.0); - - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - const int channels = GET_PARAM(2); - const int interpolation = GET_PARAM(3); - const int borderMode = GET_PARAM(4); - - const int type = CV_MAKE_TYPE(depth, channels); - - cv::Mat src(size, type); - declare.in(src, WARMUP_RNG); - - const double aplha = CV_PI / 4; - const double mat[2 * 3] = - { - std::cos(aplha), -std::sin(aplha), src.cols / 2, - std::sin(aplha), std::cos(aplha), 0 - }; - const cv::Mat M(2, 3, CV_64F, (void*) mat); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::warpAffine(d_src, dst, M, size, interpolation, borderMode); - - GPU_SANITY_CHECK(dst, 1); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::warpAffine(src, dst, M, size, interpolation, borderMode); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// WarpPerspective - -PERF_TEST_P(Sz_Depth_Cn_Inter_Border, ImgProc_WarpPerspective, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16U, CV_32F), - GPU_CHANNELS_1_3_4, - Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)), - ALL_BORDER_MODES)) -{ - declare.time(20.0); - - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - const int channels = GET_PARAM(2); - const int interpolation = GET_PARAM(3); - const int borderMode = GET_PARAM(4); - - const int type = CV_MAKE_TYPE(depth, channels); - - cv::Mat src(size, type); - declare.in(src, WARMUP_RNG); - - const double aplha = CV_PI / 4; - double mat[3][3] = { {std::cos(aplha), -std::sin(aplha), src.cols / 2}, - {std::sin(aplha), std::cos(aplha), 0}, - {0.0, 0.0, 1.0}}; - const cv::Mat M(3, 3, CV_64F, (void*) mat); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::warpPerspective(d_src, dst, M, size, interpolation, borderMode); - - GPU_SANITY_CHECK(dst, 1); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::warpPerspective(src, dst, M, size, interpolation, borderMode); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// CopyMakeBorder - -DEF_PARAM_TEST(Sz_Depth_Cn_Border, cv::Size, MatDepth, MatCn, BorderMode); - -PERF_TEST_P(Sz_Depth_Cn_Border, ImgProc_CopyMakeBorder, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16U, CV_32F), - GPU_CHANNELS_1_3_4, - ALL_BORDER_MODES)) -{ - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - const int channels = GET_PARAM(2); - const int borderMode = GET_PARAM(3); - - const int type = CV_MAKE_TYPE(depth, channels); - - cv::Mat src(size, type); - declare.in(src, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::copyMakeBorder(d_src, dst, 5, 5, 5, 5, borderMode); - - GPU_SANITY_CHECK(dst); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::copyMakeBorder(src, dst, 5, 5, 5, 5, borderMode); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// Threshold - -CV_ENUM(ThreshOp, cv::THRESH_BINARY, cv::THRESH_BINARY_INV, cv::THRESH_TRUNC, cv::THRESH_TOZERO, cv::THRESH_TOZERO_INV) -#define ALL_THRESH_OPS ValuesIn(ThreshOp::all()) - -DEF_PARAM_TEST(Sz_Depth_Op, cv::Size, MatDepth, ThreshOp); - -PERF_TEST_P(Sz_Depth_Op, ImgProc_Threshold, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16U, CV_32F, CV_64F), - ALL_THRESH_OPS)) -{ - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - const int threshOp = GET_PARAM(2); - - cv::Mat src(size, depth); - declare.in(src, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::threshold(d_src, dst, 100.0, 255.0, threshOp); - - GPU_SANITY_CHECK(dst, 1e-10); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::threshold(src, dst, 100.0, 255.0, threshOp); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// Integral - -PERF_TEST_P(Sz, ImgProc_Integral, - GPU_TYPICAL_MAT_SIZES) -{ - const cv::Size size = GetParam(); - - cv::Mat src(size, CV_8UC1); - declare.in(src, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - cv::gpu::GpuMat d_buf; - - TEST_CYCLE() cv::gpu::integralBuffered(d_src, dst, d_buf); - - GPU_SANITY_CHECK(dst); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::integral(src, dst); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// IntegralSqr - -PERF_TEST_P(Sz, ImgProc_IntegralSqr, - GPU_TYPICAL_MAT_SIZES) -{ - const cv::Size size = GetParam(); - - cv::Mat src(size, CV_8UC1); - declare.in(src, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::sqrIntegral(d_src, dst); - - GPU_SANITY_CHECK(dst); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// HistEvenC1 - -PERF_TEST_P(Sz_Depth, ImgProc_HistEvenC1, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16U, CV_16S))) -{ - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - - cv::Mat src(size, depth); - declare.in(src, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - cv::gpu::GpuMat d_buf; - - TEST_CYCLE() cv::gpu::histEven(d_src, dst, d_buf, 30, 0, 180); - - GPU_SANITY_CHECK(dst); - } - else - { - const int hbins = 30; - const float hranges[] = {0.0f, 180.0f}; - const int histSize[] = {hbins}; - const float* ranges[] = {hranges}; - const int channels[] = {0}; - - cv::Mat dst; - - TEST_CYCLE() cv::calcHist(&src, 1, channels, cv::Mat(), dst, 1, histSize, ranges); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// HistEvenC4 - -PERF_TEST_P(Sz_Depth, ImgProc_HistEvenC4, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16U, CV_16S))) -{ - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - - cv::Mat src(size, CV_MAKE_TYPE(depth, 4)); - declare.in(src, WARMUP_RNG); - - int histSize[] = {30, 30, 30, 30}; - int lowerLevel[] = {0, 0, 0, 0}; - int upperLevel[] = {180, 180, 180, 180}; - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat d_hist[4]; - cv::gpu::GpuMat d_buf; - - TEST_CYCLE() cv::gpu::histEven(d_src, d_hist, d_buf, histSize, lowerLevel, upperLevel); - - cv::Mat cpu_hist0, cpu_hist1, cpu_hist2, cpu_hist3; - d_hist[0].download(cpu_hist0); - d_hist[1].download(cpu_hist1); - d_hist[2].download(cpu_hist2); - d_hist[3].download(cpu_hist3); - SANITY_CHECK(cpu_hist0); - SANITY_CHECK(cpu_hist1); - SANITY_CHECK(cpu_hist2); - SANITY_CHECK(cpu_hist3); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// CalcHist - -PERF_TEST_P(Sz, ImgProc_CalcHist, - GPU_TYPICAL_MAT_SIZES) -{ - const cv::Size size = GetParam(); - - cv::Mat src(size, CV_8UC1); - declare.in(src, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::calcHist(d_src, dst); - - GPU_SANITY_CHECK(dst); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// EqualizeHist - -PERF_TEST_P(Sz, ImgProc_EqualizeHist, - GPU_TYPICAL_MAT_SIZES) -{ - const cv::Size size = GetParam(); - - cv::Mat src(size, CV_8UC1); - declare.in(src, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - cv::gpu::GpuMat d_hist; - cv::gpu::GpuMat d_buf; - - TEST_CYCLE() cv::gpu::equalizeHist(d_src, dst, d_hist, d_buf); - - GPU_SANITY_CHECK(dst); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::equalizeHist(src, dst); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// ColumnSum - -PERF_TEST_P(Sz, ImgProc_ColumnSum, - GPU_TYPICAL_MAT_SIZES) -{ - const cv::Size size = GetParam(); - - cv::Mat src(size, CV_32FC1); - declare.in(src, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::columnSum(d_src, dst); - - GPU_SANITY_CHECK(dst); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// Canny - -DEF_PARAM_TEST(Image_AppertureSz_L2gradient, string, int, bool); - -PERF_TEST_P(Image_AppertureSz_L2gradient, ImgProc_Canny, - Combine(Values("perf/800x600.png", "perf/1280x1024.png", "perf/1680x1050.png"), - Values(3, 5), - Bool())) -{ - const string fileName = GET_PARAM(0); - const int apperture_size = GET_PARAM(1); - const bool useL2gradient = GET_PARAM(2); - - const cv::Mat image = readImage(fileName, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(image.empty()); - - const double low_thresh = 50.0; - const double high_thresh = 100.0; - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_image(image); - cv::gpu::GpuMat dst; - cv::gpu::CannyBuf d_buf; - - TEST_CYCLE() cv::gpu::Canny(d_image, d_buf, dst, low_thresh, high_thresh, apperture_size, useL2gradient); - - GPU_SANITY_CHECK(dst); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::Canny(image, dst, low_thresh, high_thresh, apperture_size, useL2gradient); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// MeanShiftFiltering - -DEF_PARAM_TEST_1(Image, string); - -PERF_TEST_P(Image, ImgProc_MeanShiftFiltering, - Values("gpu/meanshift/cones.png")) -{ - declare.time(15.0); - - const cv::Mat img = readImage(GetParam()); - ASSERT_FALSE(img.empty()); - - cv::Mat rgba; - cv::cvtColor(img, rgba, cv::COLOR_BGR2BGRA); - - const int sp = 50; - const int sr = 50; - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(rgba); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::meanShiftFiltering(d_src, dst, sp, sr); - - GPU_SANITY_CHECK(dst); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::pyrMeanShiftFiltering(img, dst, sp, sr); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// MeanShiftProc - -PERF_TEST_P(Image, ImgProc_MeanShiftProc, - Values("gpu/meanshift/cones.png")) -{ - declare.time(5.0); - - const cv::Mat img = readImage(GetParam()); - ASSERT_FALSE(img.empty()); - - cv::Mat rgba; - cv::cvtColor(img, rgba, cv::COLOR_BGR2BGRA); - - const int sp = 50; - const int sr = 50; - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(rgba); - cv::gpu::GpuMat dstr; - cv::gpu::GpuMat dstsp; - - TEST_CYCLE() cv::gpu::meanShiftProc(d_src, dstr, dstsp, sp, sr); - - GPU_SANITY_CHECK(dstr); - GPU_SANITY_CHECK(dstsp); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// MeanShiftSegmentation - -PERF_TEST_P(Image, ImgProc_MeanShiftSegmentation, - Values("gpu/meanshift/cones.png")) -{ - declare.time(5.0); - - const cv::Mat img = readImage(GetParam()); - ASSERT_FALSE(img.empty()); - - cv::Mat rgba; - cv::cvtColor(img, rgba, cv::COLOR_BGR2BGRA); - - const int sp = 10; - const int sr = 10; - const int minsize = 20; - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(rgba); - cv::Mat dst; - - TEST_CYCLE() cv::gpu::meanShiftSegmentation(d_src, dst, sp, sr, minsize); - - GPU_SANITY_CHECK(dst); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// BlendLinear - -PERF_TEST_P(Sz_Depth_Cn, ImgProc_BlendLinear, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_32F), - GPU_CHANNELS_1_3_4)) -{ - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - const int channels = GET_PARAM(2); - - const int type = CV_MAKE_TYPE(depth, channels); - - cv::Mat img1(size, type); - cv::Mat img2(size, type); - declare.in(img1, img2, WARMUP_RNG); - - const cv::Mat weights1(size, CV_32FC1, cv::Scalar::all(0.5)); - const cv::Mat weights2(size, CV_32FC1, cv::Scalar::all(0.5)); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_img1(img1); - const cv::gpu::GpuMat d_img2(img2); - const cv::gpu::GpuMat d_weights1(weights1); - const cv::gpu::GpuMat d_weights2(weights2); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::blendLinear(d_img1, d_img2, d_weights1, d_weights2, dst); - - GPU_SANITY_CHECK(dst); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// Convolve - -DEF_PARAM_TEST(Sz_KernelSz_Ccorr, cv::Size, int, bool); - -PERF_TEST_P(Sz_KernelSz_Ccorr, ImgProc_Convolve, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(17, 27, 32, 64), - Bool())) -{ - declare.time(10.0); - - const cv::Size size = GET_PARAM(0); - const int templ_size = GET_PARAM(1); - const bool ccorr = GET_PARAM(2); - - const cv::Mat image(size, CV_32FC1); - const cv::Mat templ(templ_size, templ_size, CV_32FC1); - declare.in(image, templ, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - cv::gpu::GpuMat d_image = cv::gpu::createContinuous(size, CV_32FC1); - d_image.upload(image); - - cv::gpu::GpuMat d_templ = cv::gpu::createContinuous(templ_size, templ_size, CV_32FC1); - d_templ.upload(templ); - - cv::gpu::GpuMat dst; - cv::gpu::ConvolveBuf d_buf; - - TEST_CYCLE() cv::gpu::convolve(d_image, d_templ, dst, ccorr, d_buf); - - GPU_SANITY_CHECK(dst); - } - else - { - if (ccorr) - FAIL_NO_CPU(); - - cv::Mat dst; - - TEST_CYCLE() cv::filter2D(image, dst, image.depth(), templ); - - CPU_SANITY_CHECK(dst); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// MatchTemplate8U - -CV_ENUM(TemplateMethod, cv::TM_SQDIFF, cv::TM_SQDIFF_NORMED, cv::TM_CCORR, cv::TM_CCORR_NORMED, cv::TM_CCOEFF, cv::TM_CCOEFF_NORMED) -#define ALL_TEMPLATE_METHODS ValuesIn(TemplateMethod::all()) - -DEF_PARAM_TEST(Sz_TemplateSz_Cn_Method, cv::Size, cv::Size, MatCn, TemplateMethod); - -PERF_TEST_P(Sz_TemplateSz_Cn_Method, ImgProc_MatchTemplate8U, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(cv::Size(5, 5), cv::Size(16, 16), cv::Size(30, 30)), - GPU_CHANNELS_1_3_4, - ALL_TEMPLATE_METHODS)) -{ - const cv::Size size = GET_PARAM(0); - const cv::Size templ_size = GET_PARAM(1); - const int cn = GET_PARAM(2); - const int method = GET_PARAM(3); - - cv::Mat image(size, CV_MAKE_TYPE(CV_8U, cn)); - cv::Mat templ(templ_size, CV_MAKE_TYPE(CV_8U, cn)); - declare.in(image, templ, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_image(image); - const cv::gpu::GpuMat d_templ(templ); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::matchTemplate(d_image, d_templ, dst, method); - - GPU_SANITY_CHECK(dst, 1e-5, ERROR_RELATIVE); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::matchTemplate(image, templ, dst, method); - - CPU_SANITY_CHECK(dst); - } -}; - -//////////////////////////////////////////////////////////////////////////////// -// MatchTemplate32F - -PERF_TEST_P(Sz_TemplateSz_Cn_Method, ImgProc_MatchTemplate32F, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(cv::Size(5, 5), cv::Size(16, 16), cv::Size(30, 30)), - GPU_CHANNELS_1_3_4, - Values(TemplateMethod(cv::TM_SQDIFF), TemplateMethod(cv::TM_CCORR)))) -{ - const cv::Size size = GET_PARAM(0); - const cv::Size templ_size = GET_PARAM(1); - const int cn = GET_PARAM(2); - int method = GET_PARAM(3); - - cv::Mat image(size, CV_MAKE_TYPE(CV_32F, cn)); - cv::Mat templ(templ_size, CV_MAKE_TYPE(CV_32F, cn)); - declare.in(image, templ, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_image(image); - const cv::gpu::GpuMat d_templ(templ); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::matchTemplate(d_image, d_templ, dst, method); - - GPU_SANITY_CHECK(dst, 1e-6, ERROR_RELATIVE); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::matchTemplate(image, templ, dst, method); - - CPU_SANITY_CHECK(dst); - } -}; - -////////////////////////////////////////////////////////////////////// -// MulSpectrums - -CV_FLAGS(DftFlags, 0, cv::DFT_INVERSE, cv::DFT_SCALE, cv::DFT_ROWS, cv::DFT_COMPLEX_OUTPUT, cv::DFT_REAL_OUTPUT) - -DEF_PARAM_TEST(Sz_Flags, cv::Size, DftFlags); - -PERF_TEST_P(Sz_Flags, ImgProc_MulSpectrums, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(0, DftFlags(cv::DFT_ROWS)))) -{ - const cv::Size size = GET_PARAM(0); - const int flag = GET_PARAM(1); - - cv::Mat a(size, CV_32FC2); - cv::Mat b(size, CV_32FC2); - declare.in(a, b, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_a(a); - const cv::gpu::GpuMat d_b(b); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::mulSpectrums(d_a, d_b, dst, flag); - - GPU_SANITY_CHECK(dst); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::mulSpectrums(a, b, dst, flag); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// MulAndScaleSpectrums - -PERF_TEST_P(Sz, ImgProc_MulAndScaleSpectrums, - GPU_TYPICAL_MAT_SIZES) -{ - const cv::Size size = GetParam(); - - const float scale = 1.f / size.area(); - - cv::Mat src1(size, CV_32FC2); - cv::Mat src2(size, CV_32FC2); - declare.in(src1,src2, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src1(src1); - const cv::gpu::GpuMat d_src2(src2); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::mulAndScaleSpectrums(d_src1, d_src2, dst, cv::DFT_ROWS, scale, false); - - GPU_SANITY_CHECK(dst); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// Dft - -PERF_TEST_P(Sz_Flags, ImgProc_Dft, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(0, DftFlags(cv::DFT_ROWS), DftFlags(cv::DFT_INVERSE)))) -{ - declare.time(10.0); - - const cv::Size size = GET_PARAM(0); - const int flag = GET_PARAM(1); - - cv::Mat src(size, CV_32FC2); - declare.in(src, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::dft(d_src, dst, size, flag); - - GPU_SANITY_CHECK(dst, 1e-6, ERROR_RELATIVE); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::dft(src, dst, flag); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// CornerHarris - -DEF_PARAM_TEST(Image_Type_Border_BlockSz_ApertureSz, string, MatType, BorderMode, int, int); - -PERF_TEST_P(Image_Type_Border_BlockSz_ApertureSz, ImgProc_CornerHarris, - Combine(Values("gpu/stereobm/aloe-L.png"), - Values(CV_8UC1, CV_32FC1), - Values(BorderMode(cv::BORDER_REFLECT101), BorderMode(cv::BORDER_REPLICATE), BorderMode(cv::BORDER_REFLECT)), - Values(3, 5, 7), - Values(0, 3, 5, 7))) -{ - const string fileName = GET_PARAM(0); - const int type = GET_PARAM(1); - const int borderMode = GET_PARAM(2); - const int blockSize = GET_PARAM(3); - const int apertureSize = GET_PARAM(4); - - cv::Mat img = readImage(fileName, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(img.empty()); - - img.convertTo(img, type, type == CV_32F ? 1.0 / 255.0 : 1.0); - - const double k = 0.5; - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_img(img); - cv::gpu::GpuMat dst; - cv::gpu::GpuMat d_Dx; - cv::gpu::GpuMat d_Dy; - cv::gpu::GpuMat d_buf; - - TEST_CYCLE() cv::gpu::cornerHarris(d_img, dst, d_Dx, d_Dy, d_buf, blockSize, apertureSize, k, borderMode); - - GPU_SANITY_CHECK(dst); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::cornerHarris(img, dst, blockSize, apertureSize, k, borderMode); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// CornerMinEigenVal - -PERF_TEST_P(Image_Type_Border_BlockSz_ApertureSz, ImgProc_CornerMinEigenVal, - Combine(Values("gpu/stereobm/aloe-L.png"), - Values(CV_8UC1, CV_32FC1), - Values(BorderMode(cv::BORDER_REFLECT101), BorderMode(cv::BORDER_REPLICATE), BorderMode(cv::BORDER_REFLECT)), - Values(3, 5, 7), - Values(0, 3, 5, 7))) -{ - const string fileName = GET_PARAM(0); - const int type = GET_PARAM(1); - const int borderMode = GET_PARAM(2); - const int blockSize = GET_PARAM(3); - const int apertureSize = GET_PARAM(4); - - cv::Mat img = readImage(fileName, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(img.empty()); - - img.convertTo(img, type, type == CV_32F ? 1.0 / 255.0 : 1.0); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_img(img); - cv::gpu::GpuMat dst; - cv::gpu::GpuMat d_Dx; - cv::gpu::GpuMat d_Dy; - cv::gpu::GpuMat d_buf; - - TEST_CYCLE() cv::gpu::cornerMinEigenVal(d_img, dst, d_Dx, d_Dy, d_buf, blockSize, apertureSize, borderMode); - - GPU_SANITY_CHECK(dst); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::cornerMinEigenVal(img, dst, blockSize, apertureSize, borderMode); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// BuildWarpPlaneMaps - -PERF_TEST_P(Sz, ImgProc_BuildWarpPlaneMaps, - GPU_TYPICAL_MAT_SIZES) -{ - const cv::Size size = GetParam(); - - const cv::Mat K = cv::Mat::eye(3, 3, CV_32FC1); - const cv::Mat R = cv::Mat::ones(3, 3, CV_32FC1); - const cv::Mat T = cv::Mat::zeros(1, 3, CV_32F); - - if (PERF_RUN_GPU()) - { - cv::gpu::GpuMat map_x; - cv::gpu::GpuMat map_y; - - TEST_CYCLE() cv::gpu::buildWarpPlaneMaps(size, cv::Rect(0, 0, size.width, size.height), K, R, T, 1.0, map_x, map_y); - - GPU_SANITY_CHECK(map_x); - GPU_SANITY_CHECK(map_y); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// BuildWarpCylindricalMaps - -PERF_TEST_P(Sz, ImgProc_BuildWarpCylindricalMaps, - GPU_TYPICAL_MAT_SIZES) -{ - const cv::Size size = GetParam(); - - const cv::Mat K = cv::Mat::eye(3, 3, CV_32FC1); - const cv::Mat R = cv::Mat::ones(3, 3, CV_32FC1); - - if (PERF_RUN_GPU()) - { - cv::gpu::GpuMat map_x; - cv::gpu::GpuMat map_y; - - TEST_CYCLE() cv::gpu::buildWarpCylindricalMaps(size, cv::Rect(0, 0, size.width, size.height), K, R, 1.0, map_x, map_y); - - GPU_SANITY_CHECK(map_x); - GPU_SANITY_CHECK(map_y); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// BuildWarpSphericalMaps - -PERF_TEST_P(Sz, ImgProc_BuildWarpSphericalMaps, - GPU_TYPICAL_MAT_SIZES) -{ - const cv::Size size = GetParam(); - - const cv::Mat K = cv::Mat::eye(3, 3, CV_32FC1); - const cv::Mat R = cv::Mat::ones(3, 3, CV_32FC1); - - if (PERF_RUN_GPU()) - { - cv::gpu::GpuMat map_x; - cv::gpu::GpuMat map_y; - - TEST_CYCLE() cv::gpu::buildWarpSphericalMaps(size, cv::Rect(0, 0, size.width, size.height), K, R, 1.0, map_x, map_y); - - GPU_SANITY_CHECK(map_x); - GPU_SANITY_CHECK(map_y); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// Rotate - -DEF_PARAM_TEST(Sz_Depth_Cn_Inter, cv::Size, MatDepth, MatCn, Interpolation); - -PERF_TEST_P(Sz_Depth_Cn_Inter, ImgProc_Rotate, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16U, CV_32F), - GPU_CHANNELS_1_3_4, - Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)))) -{ - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - const int channels = GET_PARAM(2); - const int interpolation = GET_PARAM(3); - - const int type = CV_MAKE_TYPE(depth, channels); - - cv::Mat src(size, type); - declare.in(src, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::rotate(d_src, dst, size, 30.0, 0, 0, interpolation); - - GPU_SANITY_CHECK(dst, 1e-3, ERROR_RELATIVE); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// PyrDown - -PERF_TEST_P(Sz_Depth_Cn, ImgProc_PyrDown, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16U, CV_32F), - GPU_CHANNELS_1_3_4)) -{ - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - const int channels = GET_PARAM(2); - - const int type = CV_MAKE_TYPE(depth, channels); - - cv::Mat src(size, type); - declare.in(src, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::pyrDown(d_src, dst); - - GPU_SANITY_CHECK(dst); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::pyrDown(src, dst); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// PyrUp - -PERF_TEST_P(Sz_Depth_Cn, ImgProc_PyrUp, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16U, CV_32F), - GPU_CHANNELS_1_3_4)) -{ - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - const int channels = GET_PARAM(2); - - const int type = CV_MAKE_TYPE(depth, channels); - - cv::Mat src(size, type); - declare.in(src, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::pyrUp(d_src, dst); - - GPU_SANITY_CHECK(dst); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::pyrUp(src, dst); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// CvtColor - -DEF_PARAM_TEST(Sz_Depth_Code, cv::Size, MatDepth, CvtColorInfo); - -PERF_TEST_P(Sz_Depth_Code, ImgProc_CvtColor, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_32F), - Values(CvtColorInfo(4, 4, cv::COLOR_RGBA2BGRA), - CvtColorInfo(4, 1, cv::COLOR_BGRA2GRAY), - CvtColorInfo(1, 4, cv::COLOR_GRAY2BGRA), - CvtColorInfo(3, 3, cv::COLOR_BGR2XYZ), - CvtColorInfo(3, 3, cv::COLOR_XYZ2BGR), - CvtColorInfo(3, 3, cv::COLOR_BGR2YCrCb), - CvtColorInfo(3, 3, cv::COLOR_YCrCb2BGR), - CvtColorInfo(3, 3, cv::COLOR_BGR2YUV), - CvtColorInfo(3, 3, cv::COLOR_YUV2BGR), - CvtColorInfo(3, 3, cv::COLOR_BGR2HSV), - CvtColorInfo(3, 3, cv::COLOR_HSV2BGR), - CvtColorInfo(3, 3, cv::COLOR_BGR2HLS), - CvtColorInfo(3, 3, cv::COLOR_HLS2BGR), - CvtColorInfo(3, 3, cv::COLOR_BGR2Lab), - CvtColorInfo(3, 3, cv::COLOR_LBGR2Lab), - CvtColorInfo(3, 3, cv::COLOR_BGR2Luv), - CvtColorInfo(3, 3, cv::COLOR_LBGR2Luv), - CvtColorInfo(3, 3, cv::COLOR_Lab2BGR), - CvtColorInfo(3, 3, cv::COLOR_Lab2LBGR), - CvtColorInfo(3, 3, cv::COLOR_Luv2RGB), - CvtColorInfo(3, 3, cv::COLOR_Luv2LRGB)))) -{ - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - const CvtColorInfo info = GET_PARAM(2); - - cv::Mat src(size, CV_MAKETYPE(depth, info.scn)); - cv::randu(src, 0, depth == CV_8U ? 255.0 : 1.0); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::cvtColor(d_src, dst, info.code, info.dcn); - - GPU_SANITY_CHECK(dst, 1e-4); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::cvtColor(src, dst, info.code, info.dcn); - - CPU_SANITY_CHECK(dst); - } -} - -PERF_TEST_P(Sz_Depth_Code, ImgProc_CvtColorBayer, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16U), - Values(CvtColorInfo(1, 3, cv::COLOR_BayerBG2BGR), - CvtColorInfo(1, 3, cv::COLOR_BayerGB2BGR), - CvtColorInfo(1, 3, cv::COLOR_BayerRG2BGR), - CvtColorInfo(1, 3, cv::COLOR_BayerGR2BGR)))) -{ - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - const CvtColorInfo info = GET_PARAM(2); - - cv::Mat src(size, CV_MAKETYPE(depth, info.scn)); - declare.in(src, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::cvtColor(d_src, dst, info.code, info.dcn); - - GPU_SANITY_CHECK(dst); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::cvtColor(src, dst, info.code, info.dcn); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// -// SwapChannels - -PERF_TEST_P(Sz, ImgProc_SwapChannels, - GPU_TYPICAL_MAT_SIZES) -{ - const cv::Size size = GetParam(); - - cv::Mat src(size, CV_8UC4); - declare.in(src, WARMUP_RNG); - - const int dstOrder[] = {2, 1, 0, 3}; - - if (PERF_RUN_GPU()) - { - cv::gpu::GpuMat dst(src); - - TEST_CYCLE() cv::gpu::swapChannels(dst, dstOrder); - - GPU_SANITY_CHECK(dst); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// AlphaComp - -CV_ENUM(AlphaOp, cv::gpu::ALPHA_OVER, cv::gpu::ALPHA_IN, cv::gpu::ALPHA_OUT, cv::gpu::ALPHA_ATOP, cv::gpu::ALPHA_XOR, cv::gpu::ALPHA_PLUS, cv::gpu::ALPHA_OVER_PREMUL, cv::gpu::ALPHA_IN_PREMUL, cv::gpu::ALPHA_OUT_PREMUL, cv::gpu::ALPHA_ATOP_PREMUL, cv::gpu::ALPHA_XOR_PREMUL, cv::gpu::ALPHA_PLUS_PREMUL, cv::gpu::ALPHA_PREMUL) -#define ALL_ALPHA_OPS ValuesIn(AlphaOp::all()) - -DEF_PARAM_TEST(Sz_Type_Op, cv::Size, MatType, AlphaOp); - -PERF_TEST_P(Sz_Type_Op, ImgProc_AlphaComp, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8UC4, CV_16UC4, CV_32SC4, CV_32FC4), - ALL_ALPHA_OPS)) -{ - const cv::Size size = GET_PARAM(0); - const int type = GET_PARAM(1); - const int alpha_op = GET_PARAM(2); - - cv::Mat img1(size, type); - cv::Mat img2(size, type); - declare.in(img1, img2, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_img1(img1); - const cv::gpu::GpuMat d_img2(img2); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::alphaComp(d_img1, d_img2, dst, alpha_op); - - GPU_SANITY_CHECK(dst, 1e-3, ERROR_RELATIVE); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// ImagePyramidBuild - -PERF_TEST_P(Sz_Depth_Cn, ImgProc_ImagePyramidBuild, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16U, CV_32F), - GPU_CHANNELS_1_3_4)) -{ - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - const int channels = GET_PARAM(2); - - const int type = CV_MAKE_TYPE(depth, channels); - - cv::Mat src(size, type); - declare.in(src, WARMUP_RNG); - - const int nLayers = 5; - const cv::Size dstSize(size.width / 2 + 10, size.height / 2 + 10); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - - cv::gpu::ImagePyramid d_pyr; - - TEST_CYCLE() d_pyr.build(d_src, nLayers); - - cv::gpu::GpuMat dst; - d_pyr.getLayer(dst, dstSize); - - GPU_SANITY_CHECK(dst); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// ImagePyramidGetLayer - -PERF_TEST_P(Sz_Depth_Cn, ImgProc_ImagePyramidGetLayer, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16U, CV_32F), - GPU_CHANNELS_1_3_4)) -{ - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - const int channels = GET_PARAM(2); - - const int type = CV_MAKE_TYPE(depth, channels); - - cv::Mat src(size, type); - declare.in(src, WARMUP_RNG); - - const int nLayers = 3; - const cv::Size dstSize(size.width / 2 + 10, size.height / 2 + 10); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - cv::gpu::ImagePyramid d_pyr(d_src, nLayers); - - TEST_CYCLE() d_pyr.getLayer(dst, dstSize); - - GPU_SANITY_CHECK(dst); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////////////////////// -// HoughLines - -namespace -{ - struct Vec4iComparator - { - bool operator()(const cv::Vec4i& a, const cv::Vec4i b) const - { - if (a[0] != b[0]) return a[0] < b[0]; - else if(a[1] != b[1]) return a[1] < b[1]; - else if(a[2] != b[2]) return a[2] < b[2]; - else return a[3] < b[3]; - } - }; - struct Vec3fComparator - { - bool operator()(const cv::Vec3f& a, const cv::Vec3f b) const - { - if(a[0] != b[0]) return a[0] < b[0]; - else if(a[1] != b[1]) return a[1] < b[1]; - else return a[2] < b[2]; - } - }; - struct Vec2fComparator - { - bool operator()(const cv::Vec2f& a, const cv::Vec2f b) const - { - if(a[0] != b[0]) return a[0] < b[0]; - else return a[1] < b[1]; - } - }; -} - -PERF_TEST_P(Sz, ImgProc_HoughLines, - GPU_TYPICAL_MAT_SIZES) -{ - declare.time(30.0); - - const cv::Size size = GetParam(); - - const float rho = 1.0f; - const float theta = static_cast(CV_PI / 180.0); - const int threshold = 300; - - cv::Mat src(size, CV_8UC1, cv::Scalar::all(0)); - cv::line(src, cv::Point(0, 100), cv::Point(src.cols, 100), cv::Scalar::all(255), 1); - cv::line(src, cv::Point(0, 200), cv::Point(src.cols, 200), cv::Scalar::all(255), 1); - cv::line(src, cv::Point(0, 400), cv::Point(src.cols, 400), cv::Scalar::all(255), 1); - cv::line(src, cv::Point(100, 0), cv::Point(100, src.rows), cv::Scalar::all(255), 1); - cv::line(src, cv::Point(200, 0), cv::Point(200, src.rows), cv::Scalar::all(255), 1); - cv::line(src, cv::Point(400, 0), cv::Point(400, src.rows), cv::Scalar::all(255), 1); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat d_lines; - cv::gpu::HoughLinesBuf d_buf; - - TEST_CYCLE() cv::gpu::HoughLines(d_src, d_lines, d_buf, rho, theta, threshold); - - cv::Mat gpu_lines(d_lines.row(0)); - cv::Vec2f* begin = gpu_lines.ptr(0); - cv::Vec2f* end = begin + gpu_lines.cols; - std::sort(begin, end, Vec2fComparator()); - SANITY_CHECK(gpu_lines); - } - else - { - std::vector cpu_lines; - - TEST_CYCLE() cv::HoughLines(src, cpu_lines, rho, theta, threshold); - - SANITY_CHECK(cpu_lines); - } -} - -////////////////////////////////////////////////////////////////////// -// HoughLinesP - -DEF_PARAM_TEST_1(Image, std::string); - -PERF_TEST_P(Image, ImgProc_HoughLinesP, - testing::Values("cv/shared/pic5.png", "stitching/a1.png")) -{ - declare.time(30.0); - - const std::string fileName = getDataPath(GetParam()); - - const float rho = 1.0f; - const float theta = static_cast(CV_PI / 180.0); - const int threshold = 100; - const int minLineLenght = 50; - const int maxLineGap = 5; - - const cv::Mat image = cv::imread(fileName, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(image.empty()); - - cv::Mat mask; - cv::Canny(image, mask, 50, 100); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_mask(mask); - cv::gpu::GpuMat d_lines; - cv::gpu::HoughLinesBuf d_buf; - - TEST_CYCLE() cv::gpu::HoughLinesP(d_mask, d_lines, d_buf, rho, theta, minLineLenght, maxLineGap); - - cv::Mat gpu_lines(d_lines); - cv::Vec4i* begin = gpu_lines.ptr(); - cv::Vec4i* end = begin + gpu_lines.cols; - std::sort(begin, end, Vec4iComparator()); - SANITY_CHECK(gpu_lines); - } - else - { - std::vector cpu_lines; - - TEST_CYCLE() cv::HoughLinesP(mask, cpu_lines, rho, theta, threshold, minLineLenght, maxLineGap); - - SANITY_CHECK(cpu_lines); - } -} - -////////////////////////////////////////////////////////////////////// -// HoughCircles - -DEF_PARAM_TEST(Sz_Dp_MinDist, cv::Size, float, float); - -PERF_TEST_P(Sz_Dp_MinDist, ImgProc_HoughCircles, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(1.0f, 2.0f, 4.0f), - Values(1.0f))) -{ - declare.time(30.0); - - const cv::Size size = GET_PARAM(0); - const float dp = GET_PARAM(1); - const float minDist = GET_PARAM(2); - - const int minRadius = 10; - const int maxRadius = 30; - const int cannyThreshold = 100; - const int votesThreshold = 15; - - cv::Mat src(size, CV_8UC1, cv::Scalar::all(0)); - cv::circle(src, cv::Point(100, 100), 20, cv::Scalar::all(255), -1); - cv::circle(src, cv::Point(200, 200), 25, cv::Scalar::all(255), -1); - cv::circle(src, cv::Point(200, 100), 25, cv::Scalar::all(255), -1); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat d_circles; - cv::gpu::HoughCirclesBuf d_buf; - - TEST_CYCLE() cv::gpu::HoughCircles(d_src, d_circles, d_buf, CV_HOUGH_GRADIENT, dp, minDist, cannyThreshold, votesThreshold, minRadius, maxRadius); - - cv::Mat gpu_circles(d_circles); - cv::Vec3f* begin = gpu_circles.ptr(0); - cv::Vec3f* end = begin + gpu_circles.cols; - std::sort(begin, end, Vec3fComparator()); - SANITY_CHECK(gpu_circles); - } - else - { - std::vector cpu_circles; - - TEST_CYCLE() cv::HoughCircles(src, cpu_circles, CV_HOUGH_GRADIENT, dp, minDist, cannyThreshold, votesThreshold, minRadius, maxRadius); - - SANITY_CHECK(cpu_circles); - } -} - -////////////////////////////////////////////////////////////////////// -// GeneralizedHough - -CV_FLAGS(GHMethod, cv::GHT_POSITION, cv::GHT_SCALE, cv::GHT_ROTATION); - -DEF_PARAM_TEST(Method_Sz, GHMethod, cv::Size); - -PERF_TEST_P(Method_Sz, ImgProc_GeneralizedHough, - Combine(Values(GHMethod(cv::GHT_POSITION), GHMethod(cv::GHT_POSITION | cv::GHT_SCALE), GHMethod(cv::GHT_POSITION | cv::GHT_ROTATION), GHMethod(cv::GHT_POSITION | cv::GHT_SCALE | cv::GHT_ROTATION)), - GPU_TYPICAL_MAT_SIZES)) -{ - declare.time(10); - - const int method = GET_PARAM(0); - const cv::Size imageSize = GET_PARAM(1); - - const cv::Mat templ = readImage("cv/shared/templ.png", cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(templ.empty()); - - cv::Mat image(imageSize, CV_8UC1, cv::Scalar::all(0)); - templ.copyTo(image(cv::Rect(50, 50, templ.cols, templ.rows))); - - cv::RNG rng(123456789); - const int objCount = rng.uniform(5, 15); - for (int i = 0; i < objCount; ++i) - { - double scale = rng.uniform(0.7, 1.3); - bool rotate = 1 == rng.uniform(0, 2); - - cv::Mat obj; - cv::resize(templ, obj, cv::Size(), scale, scale); - if (rotate) - obj = obj.t(); - - cv::Point pos; - - pos.x = rng.uniform(0, image.cols - obj.cols); - pos.y = rng.uniform(0, image.rows - obj.rows); - - cv::Mat roi = image(cv::Rect(pos, obj.size())); - cv::add(roi, obj, roi); - } - - cv::Mat edges; - cv::Canny(image, edges, 50, 100); - - cv::Mat dx, dy; - cv::Sobel(image, dx, CV_32F, 1, 0); - cv::Sobel(image, dy, CV_32F, 0, 1); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_edges(edges); - const cv::gpu::GpuMat d_dx(dx); - const cv::gpu::GpuMat d_dy(dy); - cv::gpu::GpuMat posAndVotes; - - cv::Ptr d_hough = cv::gpu::GeneralizedHough_GPU::create(method); - if (method & cv::GHT_ROTATION) - { - d_hough->set("maxAngle", 90.0); - d_hough->set("angleStep", 2.0); - } - - d_hough->setTemplate(cv::gpu::GpuMat(templ)); - - TEST_CYCLE() d_hough->detect(d_edges, d_dx, d_dy, posAndVotes); - - const cv::gpu::GpuMat positions(1, posAndVotes.cols, CV_32FC4, posAndVotes.data); - GPU_SANITY_CHECK(positions); - } - else - { - cv::Mat positions; - - cv::Ptr hough = cv::GeneralizedHough::create(method); - if (method & cv::GHT_ROTATION) - { - hough->set("maxAngle", 90.0); - hough->set("angleStep", 2.0); - } - - hough->setTemplate(templ); - - TEST_CYCLE() hough->detect(edges, dx, dy, positions); - - CPU_SANITY_CHECK(positions); - } -} diff --git a/modules/gpu/perf/perf_labeling.cpp b/modules/gpu/perf/perf_labeling.cpp index f3ad12c949..0484da9d59 100644 --- a/modules/gpu/perf/perf_labeling.cpp +++ b/modules/gpu/perf/perf_labeling.cpp @@ -1,7 +1,50 @@ +/*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 "perf_precomp.hpp" using namespace std; using namespace testing; +using namespace perf; DEF_PARAM_TEST_1(Image, string); diff --git a/modules/gpu/perf/perf_main.cpp b/modules/gpu/perf/perf_main.cpp index 312b744482..802d559afb 100644 --- a/modules/gpu/perf/perf_main.cpp +++ b/modules/gpu/perf/perf_main.cpp @@ -1,70 +1,47 @@ +/*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 "perf_precomp.hpp" -static void printOsInfo() -{ -#if defined _WIN32 -# if defined _WIN64 - printf("[----------]\n[ GPU INFO ] \tRun on OS Windows x64.\n[----------]\n"), fflush(stdout); -# else - printf("[----------]\n[ GPU INFO ] \tRun on OS Windows x32.\n[----------]\n"), fflush(stdout); -# endif -#elif defined linux -# if defined _LP64 - printf("[----------]\n[ GPU INFO ] \tRun on OS Linux x64.\n[----------]\n"), fflush(stdout); -# else - printf("[----------]\n[ GPU INFO ] \tRun on OS Linux x32.\n[----------]\n"), fflush(stdout); -# endif -#elif defined __APPLE__ -# if defined _LP64 - printf("[----------]\n[ GPU INFO ] \tRun on OS Apple x64.\n[----------]\n"), fflush(stdout); -# else - printf("[----------]\n[ GPU INFO ] \tRun on OS Apple x32.\n[----------]\n"), fflush(stdout); -# endif -#endif +using namespace perf; -} - -static void printCudaInfo() -{ - printOsInfo(); -#ifndef HAVE_CUDA - printf("[----------]\n[ GPU INFO ] \tOpenCV was built without CUDA support.\n[----------]\n"), fflush(stdout); -#else - int driver; - cudaDriverGetVersion(&driver); - - printf("[----------]\n"), fflush(stdout); - printf("[ GPU INFO ] \tCUDA Driver version: %d.\n", driver), fflush(stdout); - printf("[ GPU INFO ] \tCUDA Runtime version: %d.\n", CUDART_VERSION), fflush(stdout); - printf("[----------]\n"), fflush(stdout); - - printf("[----------]\n"), fflush(stdout); - printf("[ GPU INFO ] \tGPU module was compiled for the following GPU archs.\n"), fflush(stdout); - printf("[ BIN ] \t%s.\n", CUDA_ARCH_BIN), fflush(stdout); - printf("[ PTX ] \t%s.\n", CUDA_ARCH_PTX), fflush(stdout); - printf("[----------]\n"), fflush(stdout); - - printf("[----------]\n"), fflush(stdout); - int deviceCount = cv::gpu::getCudaEnabledDeviceCount(); - printf("[ GPU INFO ] \tCUDA device count:: %d.\n", deviceCount), fflush(stdout); - printf("[----------]\n"), fflush(stdout); - - for (int i = 0; i < deviceCount; ++i) - { - cv::gpu::DeviceInfo info(i); - - printf("[----------]\n"), fflush(stdout); - printf("[ DEVICE ] \t# %d %s.\n", i, info.name().c_str()), fflush(stdout); - printf("[ ] \tCompute capability: %d.%d\n", (int)info.majorVersion(), (int)info.minorVersion()), fflush(stdout); - printf("[ ] \tMulti Processor Count: %d\n", info.multiProcessorCount()), fflush(stdout); - printf("[ ] \tTotal memory: %d Mb\n", static_cast(static_cast(info.totalMemory() / 1024.0) / 1024.0)), fflush(stdout); - printf("[ ] \tFree memory: %d Mb\n", static_cast(static_cast(info.freeMemory() / 1024.0) / 1024.0)), fflush(stdout); - if (!info.isCompatible()) - printf("[ GPU INFO ] \tThis device is NOT compatible with current GPU module build\n"); - printf("[----------]\n"), fflush(stdout); - } - -#endif -} - -CV_PERF_TEST_MAIN(gpu, printCudaInfo()) +CV_PERF_TEST_CUDA_MAIN(gpu) diff --git a/modules/gpu/perf/perf_matop.cpp b/modules/gpu/perf/perf_matop.cpp index 1696e3a7eb..f80ba1b087 100644 --- a/modules/gpu/perf/perf_matop.cpp +++ b/modules/gpu/perf/perf_matop.cpp @@ -1,7 +1,50 @@ +/*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 "perf_precomp.hpp" using namespace std; using namespace testing; +using namespace perf; ////////////////////////////////////////////////////////////////////// // SetTo diff --git a/modules/gpu/perf/perf_objdetect.cpp b/modules/gpu/perf/perf_objdetect.cpp index 969ac10762..1516d6b99b 100644 --- a/modules/gpu/perf/perf_objdetect.cpp +++ b/modules/gpu/perf/perf_objdetect.cpp @@ -1,7 +1,50 @@ +/*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 "perf_precomp.hpp" using namespace std; using namespace testing; +using namespace perf; /////////////////////////////////////////////////////////////// // HOG @@ -18,6 +61,8 @@ PERF_TEST_P(Image, ObjDetect_HOG, "gpu/caltech/image_00000527_0.png", "gpu/caltech/image_00000574_0.png")) { + declare.time(300.0); + const cv::Mat img = readImage(GetParam(), cv::IMREAD_GRAYSCALE); ASSERT_FALSE(img.empty()); diff --git a/modules/gpu/perf/perf_precomp.cpp b/modules/gpu/perf/perf_precomp.cpp deleted file mode 100644 index 8552ac3d42..0000000000 --- a/modules/gpu/perf/perf_precomp.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "perf_precomp.hpp" diff --git a/modules/gpu/perf/perf_precomp.hpp b/modules/gpu/perf/perf_precomp.hpp index 71fe9e7d07..5bfb14b52e 100644 --- a/modules/gpu/perf/perf_precomp.hpp +++ b/modules/gpu/perf/perf_precomp.hpp @@ -1,3 +1,45 @@ +/*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*/ + #ifdef __GNUC__ # pragma GCC diagnostic ignored "-Wmissing-declarations" # if defined __clang__ || defined __APPLE__ @@ -9,28 +51,12 @@ #ifndef __OPENCV_PERF_PRECOMP_HPP__ #define __OPENCV_PERF_PRECOMP_HPP__ -#include -#include - -#include "cvconfig.h" - -#ifdef HAVE_CUDA -#include -#endif - #include "opencv2/ts.hpp" +#include "opencv2/ts/gpu_perf.hpp" -#include "opencv2/core.hpp" -#include "opencv2/highgui.hpp" #include "opencv2/gpu.hpp" #include "opencv2/calib3d.hpp" -#include "opencv2/imgproc.hpp" -#include "opencv2/video.hpp" -#include "opencv2/nonfree.hpp" -#include "opencv2/legacy.hpp" -#include "opencv2/photo.hpp" - -#include "utility.hpp" +#include "opencv2/objdetect.hpp" #ifdef GTEST_CREATE_SHARED_LIBRARY #error no modules except ts should have GTEST_CREATE_SHARED_LIBRARY defined diff --git a/modules/gpu/perf/perf_video.cpp b/modules/gpu/perf/perf_video.cpp deleted file mode 100644 index 61c2687ca9..0000000000 --- a/modules/gpu/perf/perf_video.cpp +++ /dev/null @@ -1,1094 +0,0 @@ -#include "perf_precomp.hpp" - -using namespace std; -using namespace testing; -using namespace perf; - -namespace cv -{ - template<> void Ptr::delete_obj() - { - cvReleaseBGStatModel(&obj); - } -} - -////////////////////////////////////////////////////// -// InterpolateFrames - -typedef pair pair_string; - -DEF_PARAM_TEST_1(ImagePair, pair_string); - -PERF_TEST_P(ImagePair, Video_InterpolateFrames, - Values(make_pair("gpu/opticalflow/frame0.png", "gpu/opticalflow/frame1.png"))) -{ - cv::Mat frame0 = readImage(GetParam().first, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame0.empty()); - - cv::Mat frame1 = readImage(GetParam().second, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame1.empty()); - - frame0.convertTo(frame0, CV_32FC1, 1.0 / 255.0); - frame1.convertTo(frame1, CV_32FC1, 1.0 / 255.0); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_frame0(frame0); - const cv::gpu::GpuMat d_frame1(frame1); - cv::gpu::GpuMat d_fu, d_fv; - cv::gpu::GpuMat d_bu, d_bv; - - cv::gpu::BroxOpticalFlow d_flow(0.197f /*alpha*/, 50.0f /*gamma*/, 0.8f /*scale_factor*/, - 10 /*inner_iterations*/, 77 /*outer_iterations*/, 10 /*solver_iterations*/); - - d_flow(d_frame0, d_frame1, d_fu, d_fv); - d_flow(d_frame1, d_frame0, d_bu, d_bv); - - cv::gpu::GpuMat newFrame; - cv::gpu::GpuMat d_buf; - - TEST_CYCLE() cv::gpu::interpolateFrames(d_frame0, d_frame1, d_fu, d_fv, d_bu, d_bv, 0.5f, newFrame, d_buf); - - GPU_SANITY_CHECK(newFrame); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////// -// CreateOpticalFlowNeedleMap - -PERF_TEST_P(ImagePair, Video_CreateOpticalFlowNeedleMap, - Values(make_pair("gpu/opticalflow/frame0.png", "gpu/opticalflow/frame1.png"))) -{ - cv::Mat frame0 = readImage(GetParam().first, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame0.empty()); - - cv::Mat frame1 = readImage(GetParam().second, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame1.empty()); - - frame0.convertTo(frame0, CV_32FC1, 1.0 / 255.0); - frame1.convertTo(frame1, CV_32FC1, 1.0 / 255.0); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_frame0(frame0); - const cv::gpu::GpuMat d_frame1(frame1); - cv::gpu::GpuMat u; - cv::gpu::GpuMat v; - - cv::gpu::BroxOpticalFlow d_flow(0.197f /*alpha*/, 50.0f /*gamma*/, 0.8f /*scale_factor*/, - 10 /*inner_iterations*/, 77 /*outer_iterations*/, 10 /*solver_iterations*/); - - d_flow(d_frame0, d_frame1, u, v); - - cv::gpu::GpuMat vertex, colors; - - TEST_CYCLE() cv::gpu::createOpticalFlowNeedleMap(u, v, vertex, colors); - - GPU_SANITY_CHECK(vertex); - GPU_SANITY_CHECK(colors); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////// -// GoodFeaturesToTrack - -DEF_PARAM_TEST(Image_MinDistance, string, double); - -PERF_TEST_P(Image_MinDistance, Video_GoodFeaturesToTrack, - Combine(Values("gpu/perf/aloe.png"), - Values(0.0, 3.0))) -{ - const string fileName = GET_PARAM(0); - const double minDistance = GET_PARAM(1); - - const cv::Mat image = readImage(fileName, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(image.empty()); - - const int maxCorners = 8000; - const double qualityLevel = 0.01; - - if (PERF_RUN_GPU()) - { - cv::gpu::GoodFeaturesToTrackDetector_GPU d_detector(maxCorners, qualityLevel, minDistance); - - const cv::gpu::GpuMat d_image(image); - cv::gpu::GpuMat pts; - - TEST_CYCLE() d_detector(d_image, pts); - - GPU_SANITY_CHECK(pts); - } - else - { - cv::Mat pts; - - TEST_CYCLE() cv::goodFeaturesToTrack(image, pts, maxCorners, qualityLevel, minDistance); - - CPU_SANITY_CHECK(pts); - } -} - -////////////////////////////////////////////////////// -// BroxOpticalFlow - -PERF_TEST_P(ImagePair, Video_BroxOpticalFlow, - Values(make_pair("gpu/opticalflow/frame0.png", "gpu/opticalflow/frame1.png"))) -{ - declare.time(10); - - cv::Mat frame0 = readImage(GetParam().first, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame0.empty()); - - cv::Mat frame1 = readImage(GetParam().second, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame1.empty()); - - frame0.convertTo(frame0, CV_32FC1, 1.0 / 255.0); - frame1.convertTo(frame1, CV_32FC1, 1.0 / 255.0); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_frame0(frame0); - const cv::gpu::GpuMat d_frame1(frame1); - cv::gpu::GpuMat u; - cv::gpu::GpuMat v; - - cv::gpu::BroxOpticalFlow d_flow(0.197f /*alpha*/, 50.0f /*gamma*/, 0.8f /*scale_factor*/, - 10 /*inner_iterations*/, 77 /*outer_iterations*/, 10 /*solver_iterations*/); - - TEST_CYCLE() d_flow(d_frame0, d_frame1, u, v); - - GPU_SANITY_CHECK(u); - GPU_SANITY_CHECK(v); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////// -// PyrLKOpticalFlowSparse - -DEF_PARAM_TEST(ImagePair_Gray_NPts_WinSz_Levels_Iters, pair_string, bool, int, int, int, int); - -PERF_TEST_P(ImagePair_Gray_NPts_WinSz_Levels_Iters, Video_PyrLKOpticalFlowSparse, - Combine(Values(make_pair("gpu/opticalflow/frame0.png", "gpu/opticalflow/frame1.png")), - Bool(), - Values(8000), - Values(21), - Values(1, 3), - Values(1, 30))) -{ - declare.time(20.0); - - const pair_string imagePair = GET_PARAM(0); - const bool useGray = GET_PARAM(1); - const int points = GET_PARAM(2); - const int winSize = GET_PARAM(3); - const int levels = GET_PARAM(4); - const int iters = GET_PARAM(5); - - const cv::Mat frame0 = readImage(imagePair.first, useGray ? cv::IMREAD_GRAYSCALE : cv::IMREAD_COLOR); - ASSERT_FALSE(frame0.empty()); - - const cv::Mat frame1 = readImage(imagePair.second, useGray ? cv::IMREAD_GRAYSCALE : cv::IMREAD_COLOR); - ASSERT_FALSE(frame1.empty()); - - cv::Mat gray_frame; - if (useGray) - gray_frame = frame0; - else - cv::cvtColor(frame0, gray_frame, cv::COLOR_BGR2GRAY); - - cv::Mat pts; - cv::goodFeaturesToTrack(gray_frame, pts, points, 0.01, 0.0); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_pts(pts.reshape(2, 1)); - - cv::gpu::PyrLKOpticalFlow d_pyrLK; - d_pyrLK.winSize = cv::Size(winSize, winSize); - d_pyrLK.maxLevel = levels - 1; - d_pyrLK.iters = iters; - - const cv::gpu::GpuMat d_frame0(frame0); - const cv::gpu::GpuMat d_frame1(frame1); - cv::gpu::GpuMat nextPts; - cv::gpu::GpuMat status; - - TEST_CYCLE() d_pyrLK.sparse(d_frame0, d_frame1, d_pts, nextPts, status); - - GPU_SANITY_CHECK(nextPts); - GPU_SANITY_CHECK(status); - } - else - { - cv::Mat nextPts; - cv::Mat status; - - TEST_CYCLE() - { - cv::calcOpticalFlowPyrLK(frame0, frame1, pts, nextPts, status, cv::noArray(), - cv::Size(winSize, winSize), levels - 1, - cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, iters, 0.01)); - } - - CPU_SANITY_CHECK(nextPts); - CPU_SANITY_CHECK(status); - } -} - -////////////////////////////////////////////////////// -// PyrLKOpticalFlowDense - -DEF_PARAM_TEST(ImagePair_WinSz_Levels_Iters, pair_string, int, int, int); - -PERF_TEST_P(ImagePair_WinSz_Levels_Iters, Video_PyrLKOpticalFlowDense, - Combine(Values(make_pair("gpu/opticalflow/frame0.png", "gpu/opticalflow/frame1.png")), - Values(3, 5, 7, 9, 13, 17, 21), - Values(1, 3), - Values(1, 10))) -{ - declare.time(30); - - const pair_string imagePair = GET_PARAM(0); - const int winSize = GET_PARAM(1); - const int levels = GET_PARAM(2); - const int iters = GET_PARAM(3); - - const cv::Mat frame0 = readImage(imagePair.first, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame0.empty()); - - const cv::Mat frame1 = readImage(imagePair.second, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame1.empty()); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_frame0(frame0); - const cv::gpu::GpuMat d_frame1(frame1); - cv::gpu::GpuMat u; - cv::gpu::GpuMat v; - - cv::gpu::PyrLKOpticalFlow d_pyrLK; - d_pyrLK.winSize = cv::Size(winSize, winSize); - d_pyrLK.maxLevel = levels - 1; - d_pyrLK.iters = iters; - - TEST_CYCLE() d_pyrLK.dense(d_frame0, d_frame1, u, v); - - GPU_SANITY_CHECK(u); - GPU_SANITY_CHECK(v); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////// -// FarnebackOpticalFlow - -PERF_TEST_P(ImagePair, Video_FarnebackOpticalFlow, - Values(make_pair("gpu/opticalflow/frame0.png", "gpu/opticalflow/frame1.png"))) -{ - declare.time(10); - - const cv::Mat frame0 = readImage(GetParam().first, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame0.empty()); - - const cv::Mat frame1 = readImage(GetParam().second, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame1.empty()); - - const int numLevels = 5; - const double pyrScale = 0.5; - const int winSize = 13; - const int numIters = 10; - const int polyN = 5; - const double polySigma = 1.1; - const int flags = 0; - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_frame0(frame0); - const cv::gpu::GpuMat d_frame1(frame1); - cv::gpu::GpuMat u; - cv::gpu::GpuMat v; - - cv::gpu::FarnebackOpticalFlow d_farneback; - d_farneback.numLevels = numLevels; - d_farneback.pyrScale = pyrScale; - d_farneback.winSize = winSize; - d_farneback.numIters = numIters; - d_farneback.polyN = polyN; - d_farneback.polySigma = polySigma; - d_farneback.flags = flags; - - TEST_CYCLE() d_farneback(d_frame0, d_frame1, u, v); - - GPU_SANITY_CHECK(u, 1e-4); - GPU_SANITY_CHECK(v, 1e-4); - } - else - { - cv::Mat flow; - - TEST_CYCLE() cv::calcOpticalFlowFarneback(frame0, frame1, flow, pyrScale, numLevels, winSize, numIters, polyN, polySigma, flags); - - CPU_SANITY_CHECK(flow); - } -} - -////////////////////////////////////////////////////// -// OpticalFlowDual_TVL1 - -PERF_TEST_P(ImagePair, Video_OpticalFlowDual_TVL1, - Values(make_pair("gpu/opticalflow/frame0.png", "gpu/opticalflow/frame1.png"))) -{ - declare.time(20); - - const cv::Mat frame0 = readImage(GetParam().first, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame0.empty()); - - const cv::Mat frame1 = readImage(GetParam().second, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame1.empty()); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_frame0(frame0); - const cv::gpu::GpuMat d_frame1(frame1); - cv::gpu::GpuMat u; - cv::gpu::GpuMat v; - - cv::gpu::OpticalFlowDual_TVL1_GPU d_alg; - - TEST_CYCLE() d_alg(d_frame0, d_frame1, u, v); - - GPU_SANITY_CHECK(u, 1e-4); - GPU_SANITY_CHECK(v, 1e-4); - } - else - { - cv::Mat flow; - - cv::Ptr alg = cv::createOptFlow_DualTVL1(); - - TEST_CYCLE() alg->calc(frame0, frame1, flow); - - CPU_SANITY_CHECK(flow); - } -} - -////////////////////////////////////////////////////// -// OpticalFlowBM - -void calcOpticalFlowBM(const cv::Mat& prev, const cv::Mat& curr, - cv::Size bSize, cv::Size shiftSize, cv::Size maxRange, int usePrevious, - cv::Mat& velx, cv::Mat& vely) -{ - cv::Size sz((curr.cols - bSize.width + shiftSize.width)/shiftSize.width, (curr.rows - bSize.height + shiftSize.height)/shiftSize.height); - - velx.create(sz, CV_32FC1); - vely.create(sz, CV_32FC1); - - CvMat cvprev = prev; - CvMat cvcurr = curr; - - CvMat cvvelx = velx; - CvMat cvvely = vely; - - cvCalcOpticalFlowBM(&cvprev, &cvcurr, bSize, shiftSize, maxRange, usePrevious, &cvvelx, &cvvely); -} - -PERF_TEST_P(ImagePair, Video_OpticalFlowBM, - Values(make_pair("gpu/opticalflow/frame0.png", "gpu/opticalflow/frame1.png"))) -{ - declare.time(400); - - const cv::Mat frame0 = readImage(GetParam().first, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame0.empty()); - - const cv::Mat frame1 = readImage(GetParam().second, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame1.empty()); - - const cv::Size block_size(16, 16); - const cv::Size shift_size(1, 1); - const cv::Size max_range(16, 16); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_frame0(frame0); - const cv::gpu::GpuMat d_frame1(frame1); - cv::gpu::GpuMat u, v, buf; - - TEST_CYCLE() cv::gpu::calcOpticalFlowBM(d_frame0, d_frame1, block_size, shift_size, max_range, false, u, v, buf); - - GPU_SANITY_CHECK(u); - GPU_SANITY_CHECK(v); - } - else - { - cv::Mat u, v; - - TEST_CYCLE() calcOpticalFlowBM(frame0, frame1, block_size, shift_size, max_range, false, u, v); - - CPU_SANITY_CHECK(u); - CPU_SANITY_CHECK(v); - } -} - -PERF_TEST_P(ImagePair, Video_FastOpticalFlowBM, - Values(make_pair("gpu/opticalflow/frame0.png", "gpu/opticalflow/frame1.png"))) -{ - declare.time(400); - - const cv::Mat frame0 = readImage(GetParam().first, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame0.empty()); - - const cv::Mat frame1 = readImage(GetParam().second, cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame1.empty()); - - const cv::Size block_size(16, 16); - const cv::Size shift_size(1, 1); - const cv::Size max_range(16, 16); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_frame0(frame0); - const cv::gpu::GpuMat d_frame1(frame1); - cv::gpu::GpuMat u, v; - - cv::gpu::FastOpticalFlowBM fastBM; - - TEST_CYCLE() fastBM(d_frame0, d_frame1, u, v, max_range.width, block_size.width); - - GPU_SANITY_CHECK(u, 2); - GPU_SANITY_CHECK(v, 2); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////// -// FGDStatModel - -DEF_PARAM_TEST_1(Video, string); - -PERF_TEST_P(Video, Video_FGDStatModel, - Values(string("gpu/video/768x576.avi"))) -{ - declare.time(60); - - const string inputFile = perf::TestBase::getDataPath(GetParam()); - - cv::VideoCapture cap(inputFile); - ASSERT_TRUE(cap.isOpened()); - - cv::Mat frame; - cap >> frame; - ASSERT_FALSE(frame.empty()); - - if (PERF_RUN_GPU()) - { - cv::gpu::GpuMat d_frame(frame); - - cv::gpu::FGDStatModel d_model(4); - d_model.create(d_frame); - - for (int i = 0; i < 10; ++i) - { - cap >> frame; - ASSERT_FALSE(frame.empty()); - - d_frame.upload(frame); - - startTimer(); next(); - d_model.update(d_frame); - stopTimer(); - } - - const cv::gpu::GpuMat background = d_model.background; - const cv::gpu::GpuMat foreground = d_model.foreground; - - GPU_SANITY_CHECK(background, 1e-2, ERROR_RELATIVE); - GPU_SANITY_CHECK(foreground, 1e-2, ERROR_RELATIVE); - } - else - { - IplImage ipl_frame = frame; - cv::Ptr model(cvCreateFGDStatModel(&ipl_frame)); - - for (int i = 0; i < 10; ++i) - { - cap >> frame; - ASSERT_FALSE(frame.empty()); - - ipl_frame = frame; - - startTimer(); next(); - cvUpdateBGStatModel(&ipl_frame, model); - stopTimer(); - } - - const cv::Mat background = model->background; - const cv::Mat foreground = model->foreground; - - CPU_SANITY_CHECK(background); - CPU_SANITY_CHECK(foreground); - } -} - -////////////////////////////////////////////////////// -// MOG - -DEF_PARAM_TEST(Video_Cn_LearningRate, string, MatCn, double); - -PERF_TEST_P(Video_Cn_LearningRate, Video_MOG, - Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), - GPU_CHANNELS_1_3_4, - Values(0.0, 0.01))) -{ - const string inputFile = perf::TestBase::getDataPath(GET_PARAM(0)); - const int cn = GET_PARAM(1); - const float learningRate = static_cast(GET_PARAM(2)); - - cv::VideoCapture cap(inputFile); - ASSERT_TRUE(cap.isOpened()); - - cv::Mat frame; - - cap >> frame; - ASSERT_FALSE(frame.empty()); - - if (cn != 3) - { - cv::Mat temp; - if (cn == 1) - cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY); - else - cv::cvtColor(frame, temp, cv::COLOR_BGR2BGRA); - cv::swap(temp, frame); - } - - if (PERF_RUN_GPU()) - { - cv::gpu::GpuMat d_frame(frame); - cv::gpu::MOG_GPU d_mog; - cv::gpu::GpuMat foreground; - - d_mog(d_frame, foreground, learningRate); - - for (int i = 0; i < 10; ++i) - { - cap >> frame; - ASSERT_FALSE(frame.empty()); - - if (cn != 3) - { - cv::Mat temp; - if (cn == 1) - cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY); - else - cv::cvtColor(frame, temp, cv::COLOR_BGR2BGRA); - cv::swap(temp, frame); - } - - d_frame.upload(frame); - - startTimer(); next(); - d_mog(d_frame, foreground, learningRate); - stopTimer(); - } - - GPU_SANITY_CHECK(foreground); - } - else - { - cv::BackgroundSubtractorMOG mog; - cv::Mat foreground; - - mog(frame, foreground, learningRate); - - for (int i = 0; i < 10; ++i) - { - cap >> frame; - ASSERT_FALSE(frame.empty()); - - if (cn != 3) - { - cv::Mat temp; - if (cn == 1) - cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY); - else - cv::cvtColor(frame, temp, cv::COLOR_BGR2BGRA); - cv::swap(temp, frame); - } - - startTimer(); next(); - mog(frame, foreground, learningRate); - stopTimer(); - } - - CPU_SANITY_CHECK(foreground); - } -} - -////////////////////////////////////////////////////// -// MOG2 - -DEF_PARAM_TEST(Video_Cn, string, int); - -PERF_TEST_P(Video_Cn, Video_MOG2, - Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), - GPU_CHANNELS_1_3_4)) -{ - const string inputFile = perf::TestBase::getDataPath(GET_PARAM(0)); - const int cn = GET_PARAM(1); - - cv::VideoCapture cap(inputFile); - ASSERT_TRUE(cap.isOpened()); - - cv::Mat frame; - - cap >> frame; - ASSERT_FALSE(frame.empty()); - - if (cn != 3) - { - cv::Mat temp; - if (cn == 1) - cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY); - else - cv::cvtColor(frame, temp, cv::COLOR_BGR2BGRA); - cv::swap(temp, frame); - } - - if (PERF_RUN_GPU()) - { - cv::gpu::MOG2_GPU d_mog2; - d_mog2.bShadowDetection = false; - - cv::gpu::GpuMat d_frame(frame); - cv::gpu::GpuMat foreground; - - d_mog2(d_frame, foreground); - - for (int i = 0; i < 10; ++i) - { - cap >> frame; - ASSERT_FALSE(frame.empty()); - - if (cn != 3) - { - cv::Mat temp; - if (cn == 1) - cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY); - else - cv::cvtColor(frame, temp, cv::COLOR_BGR2BGRA); - cv::swap(temp, frame); - } - - d_frame.upload(frame); - - startTimer(); next(); - d_mog2(d_frame, foreground); - stopTimer(); - } - - GPU_SANITY_CHECK(foreground); - } - else - { - cv::BackgroundSubtractorMOG2 mog2; - mog2.set("detectShadows", false); - - cv::Mat foreground; - - mog2(frame, foreground); - - for (int i = 0; i < 10; ++i) - { - cap >> frame; - ASSERT_FALSE(frame.empty()); - - if (cn != 3) - { - cv::Mat temp; - if (cn == 1) - cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY); - else - cv::cvtColor(frame, temp, cv::COLOR_BGR2BGRA); - cv::swap(temp, frame); - } - - startTimer(); next(); - mog2(frame, foreground); - stopTimer(); - } - - CPU_SANITY_CHECK(foreground); - } -} - -////////////////////////////////////////////////////// -// MOG2GetBackgroundImage - -PERF_TEST_P(Video_Cn, Video_MOG2GetBackgroundImage, - Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), - GPU_CHANNELS_1_3_4)) -{ - const string inputFile = perf::TestBase::getDataPath(GET_PARAM(0)); - const int cn = GET_PARAM(1); - - cv::VideoCapture cap(inputFile); - ASSERT_TRUE(cap.isOpened()); - - cv::Mat frame; - - if (PERF_RUN_GPU()) - { - cv::gpu::GpuMat d_frame; - cv::gpu::MOG2_GPU d_mog2; - cv::gpu::GpuMat d_foreground; - - for (int i = 0; i < 10; ++i) - { - cap >> frame; - ASSERT_FALSE(frame.empty()); - - if (cn != 3) - { - cv::Mat temp; - if (cn == 1) - cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY); - else - cv::cvtColor(frame, temp, cv::COLOR_BGR2BGRA); - cv::swap(temp, frame); - } - - d_frame.upload(frame); - - d_mog2(d_frame, d_foreground); - } - - cv::gpu::GpuMat background; - - TEST_CYCLE() d_mog2.getBackgroundImage(background); - - GPU_SANITY_CHECK(background, 1); - } - else - { - cv::BackgroundSubtractorMOG2 mog2; - cv::Mat foreground; - - for (int i = 0; i < 10; ++i) - { - cap >> frame; - ASSERT_FALSE(frame.empty()); - - if (cn != 3) - { - cv::Mat temp; - if (cn == 1) - cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY); - else - cv::cvtColor(frame, temp, cv::COLOR_BGR2BGRA); - cv::swap(temp, frame); - } - - mog2(frame, foreground); - } - - cv::Mat background; - - TEST_CYCLE() mog2.getBackgroundImage(background); - - CPU_SANITY_CHECK(background); - } -} - -////////////////////////////////////////////////////// -// VIBE - -PERF_TEST_P(Video_Cn, Video_VIBE, - Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), - GPU_CHANNELS_1_3_4)) -{ - const string inputFile = perf::TestBase::getDataPath(GET_PARAM(0)); - const int cn = GET_PARAM(1); - - cv::VideoCapture cap(inputFile); - ASSERT_TRUE(cap.isOpened()); - - cv::Mat frame; - cap >> frame; - ASSERT_FALSE(frame.empty()); - - if (cn != 3) - { - cv::Mat temp; - if (cn == 1) - cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY); - else - cv::cvtColor(frame, temp, cv::COLOR_BGR2BGRA); - cv::swap(temp, frame); - } - - if (PERF_RUN_GPU()) - { - cv::gpu::GpuMat d_frame(frame); - cv::gpu::VIBE_GPU vibe; - cv::gpu::GpuMat foreground; - - vibe(d_frame, foreground); - - for (int i = 0; i < 10; ++i) - { - cap >> frame; - ASSERT_FALSE(frame.empty()); - - if (cn != 3) - { - cv::Mat temp; - if (cn == 1) - cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY); - else - cv::cvtColor(frame, temp, cv::COLOR_BGR2BGRA); - cv::swap(temp, frame); - } - - d_frame.upload(frame); - - startTimer(); next(); - vibe(d_frame, foreground); - stopTimer(); - } - - GPU_SANITY_CHECK(foreground); - } - else - { - FAIL_NO_CPU(); - } -} - -////////////////////////////////////////////////////// -// GMG - -DEF_PARAM_TEST(Video_Cn_MaxFeatures, string, MatCn, int); - -PERF_TEST_P(Video_Cn_MaxFeatures, Video_GMG, - Combine(Values(string("gpu/video/768x576.avi")), - GPU_CHANNELS_1_3_4, - Values(20, 40, 60))) -{ - const std::string inputFile = perf::TestBase::getDataPath(GET_PARAM(0)); - const int cn = GET_PARAM(1); - const int maxFeatures = GET_PARAM(2); - - cv::VideoCapture cap(inputFile); - ASSERT_TRUE(cap.isOpened()); - - cv::Mat frame; - cap >> frame; - ASSERT_FALSE(frame.empty()); - - if (cn != 3) - { - cv::Mat temp; - if (cn == 1) - cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY); - else - cv::cvtColor(frame, temp, cv::COLOR_BGR2BGRA); - cv::swap(temp, frame); - } - - if (PERF_RUN_GPU()) - { - cv::gpu::GpuMat d_frame(frame); - cv::gpu::GpuMat foreground; - - cv::gpu::GMG_GPU d_gmg; - d_gmg.maxFeatures = maxFeatures; - - d_gmg(d_frame, foreground); - - for (int i = 0; i < 150; ++i) - { - cap >> frame; - if (frame.empty()) - { - cap.release(); - cap.open(inputFile); - cap >> frame; - } - - if (cn != 3) - { - cv::Mat temp; - if (cn == 1) - cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY); - else - cv::cvtColor(frame, temp, cv::COLOR_BGR2BGRA); - cv::swap(temp, frame); - } - - d_frame.upload(frame); - - startTimer(); next(); - d_gmg(d_frame, foreground); - stopTimer(); - } - - GPU_SANITY_CHECK(foreground); - } - else - { - cv::Mat foreground; - cv::Mat zeros(frame.size(), CV_8UC1, cv::Scalar::all(0)); - - cv::BackgroundSubtractorGMG gmg; - gmg.set("maxFeatures", maxFeatures); - gmg.initialize(frame.size(), 0.0, 255.0); - - gmg(frame, foreground); - - for (int i = 0; i < 150; ++i) - { - cap >> frame; - if (frame.empty()) - { - cap.release(); - cap.open(inputFile); - cap >> frame; - } - - if (cn != 3) - { - cv::Mat temp; - if (cn == 1) - cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY); - else - cv::cvtColor(frame, temp, cv::COLOR_BGR2BGRA); - cv::swap(temp, frame); - } - - startTimer(); next(); - gmg(frame, foreground); - stopTimer(); - } - - CPU_SANITY_CHECK(foreground); - } -} - -#ifdef HAVE_NVCUVID - -////////////////////////////////////////////////////// -// VideoReader - -PERF_TEST_P(Video, Video_VideoReader, Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi")) -{ - declare.time(20); - - const string inputFile = perf::TestBase::getDataPath(GetParam()); - - if (PERF_RUN_GPU()) - { - cv::gpu::VideoReader_GPU d_reader(inputFile); - ASSERT_TRUE( d_reader.isOpened() ); - - cv::gpu::GpuMat frame; - - TEST_CYCLE_N(10) d_reader.read(frame); - - GPU_SANITY_CHECK(frame); - } - else - { - cv::VideoCapture reader(inputFile); - ASSERT_TRUE( reader.isOpened() ); - - cv::Mat frame; - - TEST_CYCLE_N(10) reader >> frame; - - CPU_SANITY_CHECK(frame); - } -} - -////////////////////////////////////////////////////// -// VideoWriter - -#ifdef WIN32 - -PERF_TEST_P(Video, Video_VideoWriter, Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi")) -{ - declare.time(30); - - const string inputFile = perf::TestBase::getDataPath(GetParam()); - const string outputFile = cv::tempfile(".avi"); - - const double FPS = 25.0; - - cv::VideoCapture reader(inputFile); - ASSERT_TRUE( reader.isOpened() ); - - cv::Mat frame; - - if (PERF_RUN_GPU()) - { - cv::gpu::VideoWriter_GPU d_writer; - - cv::gpu::GpuMat d_frame; - - for (int i = 0; i < 10; ++i) - { - reader >> frame; - ASSERT_FALSE(frame.empty()); - - d_frame.upload(frame); - - if (!d_writer.isOpened()) - d_writer.open(outputFile, frame.size(), FPS); - - startTimer(); next(); - d_writer.write(d_frame); - stopTimer(); - } - } - else - { - cv::VideoWriter writer; - - for (int i = 0; i < 10; ++i) - { - reader >> frame; - ASSERT_FALSE(frame.empty()); - - if (!writer.isOpened()) - writer.open(outputFile, CV_FOURCC('X', 'V', 'I', 'D'), FPS, frame.size()); - - startTimer(); next(); - writer.write(frame); - stopTimer(); - } - } - - SANITY_CHECK(frame); -} - -#endif // WIN32 - -#endif // HAVE_NVCUVID diff --git a/modules/gpu/perf/utility.cpp b/modules/gpu/perf/utility.cpp deleted file mode 100644 index 16c61e0c7d..0000000000 --- a/modules/gpu/perf/utility.cpp +++ /dev/null @@ -1,184 +0,0 @@ -#include "perf_precomp.hpp" - -using namespace std; -using namespace cv; - -Mat readImage(const string& fileName, int flags) -{ - return imread(perf::TestBase::getDataPath(fileName), flags); -} - -void PrintTo(const CvtColorInfo& info, ostream* os) -{ - static const char* str[] = - { - "BGR2BGRA", - "BGRA2BGR", - "BGR2RGBA", - "RGBA2BGR", - "BGR2RGB", - "BGRA2RGBA", - - "BGR2GRAY", - "RGB2GRAY", - "GRAY2BGR", - "GRAY2BGRA", - "BGRA2GRAY", - "RGBA2GRAY", - - "BGR2BGR565", - "RGB2BGR565", - "BGR5652BGR", - "BGR5652RGB", - "BGRA2BGR565", - "RGBA2BGR565", - "BGR5652BGRA", - "BGR5652RGBA", - - "GRAY2BGR565", - "BGR5652GRAY", - - "BGR2BGR555", - "RGB2BGR555", - "BGR5552BGR", - "BGR5552RGB", - "BGRA2BGR555", - "RGBA2BGR555", - "BGR5552BGRA", - "BGR5552RGBA", - - "GRAY2BGR555", - "BGR5552GRAY", - - "BGR2XYZ", - "RGB2XYZ", - "XYZ2BGR", - "XYZ2RGB", - - "BGR2YCrCb", - "RGB2YCrCb", - "YCrCb2BGR", - "YCrCb2RGB", - - "BGR2HSV", - "RGB2HSV", - - "", - "", - - "BGR2Lab", - "RGB2Lab", - - "BayerBG2BGR", - "BayerGB2BGR", - "BayerRG2BGR", - "BayerGR2BGR", - - "BGR2Luv", - "RGB2Luv", - - "BGR2HLS", - "RGB2HLS", - - "HSV2BGR", - "HSV2RGB", - - "Lab2BGR", - "Lab2RGB", - "Luv2BGR", - "Luv2RGB", - - "HLS2BGR", - "HLS2RGB", - - "BayerBG2BGR_VNG", - "BayerGB2BGR_VNG", - "BayerRG2BGR_VNG", - "BayerGR2BGR_VNG", - - "BGR2HSV_FULL", - "RGB2HSV_FULL", - "BGR2HLS_FULL", - "RGB2HLS_FULL", - - "HSV2BGR_FULL", - "HSV2RGB_FULL", - "HLS2BGR_FULL", - "HLS2RGB_FULL", - - "LBGR2Lab", - "LRGB2Lab", - "LBGR2Luv", - "LRGB2Luv", - - "Lab2LBGR", - "Lab2LRGB", - "Luv2LBGR", - "Luv2LRGB", - - "BGR2YUV", - "RGB2YUV", - "YUV2BGR", - "YUV2RGB", - - "BayerBG2GRAY", - "BayerGB2GRAY", - "BayerRG2GRAY", - "BayerGR2GRAY", - - //YUV 4:2:0 formats family - "YUV2RGB_NV12", - "YUV2BGR_NV12", - "YUV2RGB_NV21", - "YUV2BGR_NV21", - - "YUV2RGBA_NV12", - "YUV2BGRA_NV12", - "YUV2RGBA_NV21", - "YUV2BGRA_NV21", - - "YUV2RGB_YV12", - "YUV2BGR_YV12", - "YUV2RGB_IYUV", - "YUV2BGR_IYUV", - - "YUV2RGBA_YV12", - "YUV2BGRA_YV12", - "YUV2RGBA_IYUV", - "YUV2BGRA_IYUV", - - "YUV2GRAY_420", - - //YUV 4:2:2 formats family - "YUV2RGB_UYVY", - "YUV2BGR_UYVY", - "YUV2RGB_VYUY", - "YUV2BGR_VYUY", - - "YUV2RGBA_UYVY", - "YUV2BGRA_UYVY", - "YUV2RGBA_VYUY", - "YUV2BGRA_VYUY", - - "YUV2RGB_YUY2", - "YUV2BGR_YUY2", - "YUV2RGB_YVYU", - "YUV2BGR_YVYU", - - "YUV2RGBA_YUY2", - "YUV2BGRA_YUY2", - "YUV2RGBA_YVYU", - "YUV2BGRA_YVYU", - - "YUV2GRAY_UYVY", - "YUV2GRAY_YUY2", - - // alpha premultiplication - "RGBA2mRGBA", - "mRGBA2RGBA", - - "COLORCVT_MAX" - }; - - *os << str[info.code]; -} diff --git a/modules/gpu/perf/utility.hpp b/modules/gpu/perf/utility.hpp deleted file mode 100644 index 18c85854ac..0000000000 --- a/modules/gpu/perf/utility.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef __OPENCV_PERF_GPU_UTILITY_HPP__ -#define __OPENCV_PERF_GPU_UTILITY_HPP__ - -#include "opencv2/core.hpp" -#include "opencv2/imgproc.hpp" -#include "opencv2/ts/ts_perf.hpp" - -cv::Mat readImage(const std::string& fileName, int flags = cv::IMREAD_COLOR); - -using perf::MatType; -using perf::MatDepth; - -CV_ENUM(BorderMode, cv::BORDER_REFLECT101, cv::BORDER_REPLICATE, cv::BORDER_CONSTANT, cv::BORDER_REFLECT, cv::BORDER_WRAP) -#define ALL_BORDER_MODES testing::ValuesIn(BorderMode::all()) - -CV_ENUM(Interpolation, cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_CUBIC, cv::INTER_AREA) -#define ALL_INTERPOLATIONS testing::ValuesIn(Interpolation::all()) - -CV_ENUM(NormType, cv::NORM_INF, cv::NORM_L1, cv::NORM_L2, cv::NORM_HAMMING, cv::NORM_MINMAX) - -enum { Gray = 1, TwoChannel = 2, BGR = 3, BGRA = 4 }; -CV_ENUM(MatCn, Gray, TwoChannel, BGR, BGRA) -#define GPU_CHANNELS_1_3_4 testing::Values(MatCn(Gray), MatCn(BGR), MatCn(BGRA)) -#define GPU_CHANNELS_1_3 testing::Values(MatCn(Gray), MatCn(BGR)) - -struct CvtColorInfo -{ - int scn; - int dcn; - int code; - - CvtColorInfo() {} - explicit CvtColorInfo(int scn_, int dcn_, int code_) : scn(scn_), dcn(dcn_), code(code_) {} -}; -void PrintTo(const CvtColorInfo& info, std::ostream* os); - -#define GET_PARAM(k) std::tr1::get< k >(GetParam()) - -#define DEF_PARAM_TEST(name, ...) typedef ::perf::TestBaseWithParam< std::tr1::tuple< __VA_ARGS__ > > name -#define DEF_PARAM_TEST_1(name, param_type) typedef ::perf::TestBaseWithParam< param_type > name - -DEF_PARAM_TEST_1(Sz, cv::Size); -typedef perf::Size_MatType Sz_Type; -DEF_PARAM_TEST(Sz_Depth, cv::Size, MatDepth); -DEF_PARAM_TEST(Sz_Depth_Cn, cv::Size, MatDepth, MatCn); - -#define GPU_TYPICAL_MAT_SIZES testing::Values(perf::sz720p, perf::szSXGA, perf::sz1080p) - -#define FAIL_NO_CPU() FAIL() << "No such CPU implementation analogy" - -#define GPU_SANITY_CHECK(mat, ...) \ - do{ \ - cv::Mat gpu_##mat(mat); \ - SANITY_CHECK(gpu_##mat, ## __VA_ARGS__); \ - } while(0) - -#define CPU_SANITY_CHECK(mat, ...) \ - do{ \ - cv::Mat cpu_##mat(mat); \ - SANITY_CHECK(cpu_##mat, ## __VA_ARGS__); \ - } while(0) - -#endif // __OPENCV_PERF_GPU_UTILITY_HPP__ diff --git a/modules/gpu/perf4au/CMakeLists.txt b/modules/gpu/perf4au/CMakeLists.txt index 7452203826..cb395069d0 100644 --- a/modules/gpu/perf4au/CMakeLists.txt +++ b/modules/gpu/perf4au/CMakeLists.txt @@ -1,4 +1,4 @@ -set(PERF4AU_REQUIRED_DEPS opencv_core opencv_imgproc opencv_highgui opencv_video opencv_legacy opencv_gpu opencv_ts) +set(PERF4AU_REQUIRED_DEPS opencv_core opencv_imgproc opencv_highgui opencv_video opencv_legacy opencv_ml opencv_ts opencv_gpufilters opencv_gpuimgproc opencv_gpuoptflow) ocv_check_dependencies(${PERF4AU_REQUIRED_DEPS}) @@ -25,4 +25,3 @@ if(WIN32) set_target_properties(${the_target} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /DEBUG") endif() endif() - diff --git a/modules/gpu/perf4au/main.cpp b/modules/gpu/perf4au/main.cpp index f4a04432b5..707251c42f 100644 --- a/modules/gpu/perf4au/main.cpp +++ b/modules/gpu/perf4au/main.cpp @@ -1,75 +1,63 @@ +/*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 -#ifdef HAVE_CVCONFIG_H + #include "cvconfig.h" -#endif #include "opencv2/core.hpp" -#include "opencv2/gpu.hpp" +#include "opencv2/gpuimgproc.hpp" +#include "opencv2/gpuoptflow.hpp" #include "opencv2/highgui.hpp" #include "opencv2/video.hpp" #include "opencv2/legacy.hpp" #include "opencv2/ts.hpp" +#include "opencv2/ts/gpu_perf.hpp" -static void printOsInfo() -{ -#if defined _WIN32 -# if defined _WIN64 - printf("[----------]\n[ GPU INFO ] \tRun on OS Windows x64.\n[----------]\n"); fflush(stdout); -# else - printf("[----------]\n[ GPU INFO ] \tRun on OS Windows x32.\n[----------]\n"); fflush(stdout); -# endif -#elif defined linux -# if defined _LP64 - printf("[----------]\n[ GPU INFO ] \tRun on OS Linux x64.\n[----------]\n"); fflush(stdout); -# else - printf("[----------]\n[ GPU INFO ] \tRun on OS Linux x32.\n[----------]\n"); fflush(stdout); -# endif -#elif defined __APPLE__ -# if defined _LP64 - printf("[----------]\n[ GPU INFO ] \tRun on OS Apple x64.\n[----------]\n"); fflush(stdout); -# else - printf("[----------]\n[ GPU INFO ] \tRun on OS Apple x32.\n[----------]\n"); fflush(stdout); -# endif -#endif -} +static const char * impls[] = { + "cuda", + "plain" +}; -static void printCudaInfo() -{ - const int deviceCount = cv::gpu::getCudaEnabledDeviceCount(); - - printf("[----------]\n"); fflush(stdout); - printf("[ GPU INFO ] \tCUDA device count:: %d.\n", deviceCount); fflush(stdout); - printf("[----------]\n"); fflush(stdout); - - for (int i = 0; i < deviceCount; ++i) - { - cv::gpu::DeviceInfo info(i); - - printf("[----------]\n"); fflush(stdout); - printf("[ DEVICE ] \t# %d %s.\n", i, info.name().c_str()); fflush(stdout); - printf("[ ] \tCompute capability: %d.%d\n", info.majorVersion(), info.minorVersion()); fflush(stdout); - printf("[ ] \tMulti Processor Count: %d\n", info.multiProcessorCount()); fflush(stdout); - printf("[ ] \tTotal memory: %d Mb\n", static_cast(static_cast(info.totalMemory() / 1024.0) / 1024.0)); fflush(stdout); - printf("[ ] \tFree memory: %d Mb\n", static_cast(static_cast(info.freeMemory() / 1024.0) / 1024.0)); fflush(stdout); - if (!info.isCompatible()) - printf("[ GPU INFO ] \tThis device is NOT compatible with current GPU module build\n"); - printf("[----------]\n"); fflush(stdout); - } -} - -int main(int argc, char* argv[]) -{ - printOsInfo(); - printCudaInfo(); - - perf::Regression::Init("nv_perf_test"); - perf::TestBase::Init(argc, argv); - testing::InitGoogleTest(&argc, argv); - - return RUN_ALL_TESTS(); -} - -#define DEF_PARAM_TEST(name, ...) typedef ::perf::TestBaseWithParam< std::tr1::tuple< __VA_ARGS__ > > name -#define DEF_PARAM_TEST_1(name, param_type) typedef ::perf::TestBaseWithParam< param_type > name +CV_PERF_TEST_MAIN_WITH_IMPLS(gpu_perf4au, impls, perf::printCudaInfo()) ////////////////////////////////////////////////////////// // HoughLinesP @@ -94,13 +82,14 @@ PERF_TEST_P(Image, HoughLinesP, testing::Values(std::string("im1_1280x800.jpg")) { cv::gpu::GpuMat d_image(image); cv::gpu::GpuMat d_lines; - cv::gpu::HoughLinesBuf d_buf; - cv::gpu::HoughLinesP(d_image, d_lines, d_buf, rho, theta, minLineLenght, maxLineGap); + cv::Ptr hough = cv::gpu::createHoughSegmentDetector(rho, theta, minLineLenght, maxLineGap); + + hough->detect(d_image, d_lines); TEST_CYCLE() { - cv::gpu::HoughLinesP(d_image, d_lines, d_buf, rho, theta, minLineLenght, maxLineGap); + hough->detect(d_image, d_lines); } } else @@ -155,17 +144,17 @@ PERF_TEST_P(Image_Depth, GoodFeaturesToTrack, if (PERF_RUN_GPU()) { - cv::gpu::GoodFeaturesToTrackDetector_GPU d_detector(maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector, k); + cv::Ptr detector = cv::gpu::createGoodFeaturesToTrackDetector(src.type(), maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector, k); cv::gpu::GpuMat d_src(src); cv::gpu::GpuMat d_mask(mask); cv::gpu::GpuMat d_pts; - d_detector(d_src, d_pts, d_mask); + detector->detect(d_src, d_pts, d_mask); TEST_CYCLE() { - d_detector(d_src, d_pts, d_mask); + detector->detect(d_src, d_pts, d_mask); } } else diff --git a/modules/gpu/src/arithm.cpp b/modules/gpu/src/arithm.cpp deleted file mode 100644 index 851ac938ef..0000000000 --- a/modules/gpu/src/arithm.cpp +++ /dev/null @@ -1,576 +0,0 @@ -/*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 GpuMaterials 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 bpied warranties, including, but not limited to, the bpied -// 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 "precomp.hpp" - -using namespace cv; -using namespace cv::gpu; - -#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) - -void cv::gpu::gemm(const GpuMat&, const GpuMat&, double, const GpuMat&, double, GpuMat&, int, Stream&) { throw_nogpu(); } -void cv::gpu::transpose(const GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } -void cv::gpu::flip(const GpuMat&, GpuMat&, int, Stream&) { throw_nogpu(); } -void cv::gpu::LUT(const GpuMat&, const Mat&, GpuMat&, Stream&) { throw_nogpu(); } -void cv::gpu::magnitude(const GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } -void cv::gpu::magnitudeSqr(const GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } -void cv::gpu::magnitude(const GpuMat&, const GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } -void cv::gpu::magnitudeSqr(const GpuMat&, const GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } -void cv::gpu::phase(const GpuMat&, const GpuMat&, GpuMat&, bool, Stream&) { throw_nogpu(); } -void cv::gpu::cartToPolar(const GpuMat&, const GpuMat&, GpuMat&, GpuMat&, bool, Stream&) { throw_nogpu(); } -void cv::gpu::polarToCart(const GpuMat&, const GpuMat&, GpuMat&, GpuMat&, bool, Stream&) { throw_nogpu(); } -void cv::gpu::normalize(const GpuMat&, GpuMat&, double, double, int, int, const GpuMat&) { throw_nogpu(); } -void cv::gpu::normalize(const GpuMat&, GpuMat&, double, double, int, int, const GpuMat&, GpuMat&, GpuMat&) { throw_nogpu(); } - -#else /* !defined (HAVE_CUDA) */ - -//////////////////////////////////////////////////////////////////////// -// gemm - -void cv::gpu::gemm(const GpuMat& src1, const GpuMat& src2, double alpha, const GpuMat& src3, double beta, GpuMat& dst, int flags, Stream& stream) -{ -#ifndef HAVE_CUBLAS - (void)src1; - (void)src2; - (void)alpha; - (void)src3; - (void)beta; - (void)dst; - (void)flags; - (void)stream; - CV_Error(CV_StsNotImplemented, "The library was build without CUBLAS"); -#else - // CUBLAS works with column-major matrices - - CV_Assert(src1.type() == CV_32FC1 || src1.type() == CV_32FC2 || src1.type() == CV_64FC1 || src1.type() == CV_64FC2); - CV_Assert(src2.type() == src1.type() && (src3.empty() || src3.type() == src1.type())); - - if (src1.depth() == CV_64F) - { - if (!deviceSupports(NATIVE_DOUBLE)) - CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); - } - - bool tr1 = (flags & GEMM_1_T) != 0; - bool tr2 = (flags & GEMM_2_T) != 0; - bool tr3 = (flags & GEMM_3_T) != 0; - - if (src1.type() == CV_64FC2) - { - if (tr1 || tr2 || tr3) - CV_Error(CV_StsNotImplemented, "transpose operation doesn't implemented for CV_64FC2 type"); - } - - Size src1Size = tr1 ? Size(src1.rows, src1.cols) : src1.size(); - Size src2Size = tr2 ? Size(src2.rows, src2.cols) : src2.size(); - Size src3Size = tr3 ? Size(src3.rows, src3.cols) : src3.size(); - Size dstSize(src2Size.width, src1Size.height); - - CV_Assert(src1Size.width == src2Size.height); - CV_Assert(src3.empty() || src3Size == dstSize); - - dst.create(dstSize, src1.type()); - - if (beta != 0) - { - if (src3.empty()) - { - if (stream) - stream.enqueueMemSet(dst, Scalar::all(0)); - else - dst.setTo(Scalar::all(0)); - } - else - { - if (tr3) - { - transpose(src3, dst, stream); - } - else - { - if (stream) - stream.enqueueCopy(src3, dst); - else - src3.copyTo(dst); - } - } - } - - cublasHandle_t handle; - cublasSafeCall( cublasCreate_v2(&handle) ); - - cublasSafeCall( cublasSetStream_v2(handle, StreamAccessor::getStream(stream)) ); - - cublasSafeCall( cublasSetPointerMode_v2(handle, CUBLAS_POINTER_MODE_HOST) ); - - const float alphaf = static_cast(alpha); - const float betaf = static_cast(beta); - - const cuComplex alphacf = make_cuComplex(alphaf, 0); - const cuComplex betacf = make_cuComplex(betaf, 0); - - const cuDoubleComplex alphac = make_cuDoubleComplex(alpha, 0); - const cuDoubleComplex betac = make_cuDoubleComplex(beta, 0); - - cublasOperation_t transa = tr2 ? CUBLAS_OP_T : CUBLAS_OP_N; - cublasOperation_t transb = tr1 ? CUBLAS_OP_T : CUBLAS_OP_N; - - switch (src1.type()) - { - case CV_32FC1: - cublasSafeCall( cublasSgemm_v2(handle, transa, transb, tr2 ? src2.rows : src2.cols, tr1 ? src1.cols : src1.rows, tr2 ? src2.cols : src2.rows, - &alphaf, - src2.ptr(), static_cast(src2.step / sizeof(float)), - src1.ptr(), static_cast(src1.step / sizeof(float)), - &betaf, - dst.ptr(), static_cast(dst.step / sizeof(float))) ); - break; - - case CV_64FC1: - cublasSafeCall( cublasDgemm_v2(handle, transa, transb, tr2 ? src2.rows : src2.cols, tr1 ? src1.cols : src1.rows, tr2 ? src2.cols : src2.rows, - &alpha, - src2.ptr(), static_cast(src2.step / sizeof(double)), - src1.ptr(), static_cast(src1.step / sizeof(double)), - &beta, - dst.ptr(), static_cast(dst.step / sizeof(double))) ); - break; - - case CV_32FC2: - cublasSafeCall( cublasCgemm_v2(handle, transa, transb, tr2 ? src2.rows : src2.cols, tr1 ? src1.cols : src1.rows, tr2 ? src2.cols : src2.rows, - &alphacf, - src2.ptr(), static_cast(src2.step / sizeof(cuComplex)), - src1.ptr(), static_cast(src1.step / sizeof(cuComplex)), - &betacf, - dst.ptr(), static_cast(dst.step / sizeof(cuComplex))) ); - break; - - case CV_64FC2: - cublasSafeCall( cublasZgemm_v2(handle, transa, transb, tr2 ? src2.rows : src2.cols, tr1 ? src1.cols : src1.rows, tr2 ? src2.cols : src2.rows, - &alphac, - src2.ptr(), static_cast(src2.step / sizeof(cuDoubleComplex)), - src1.ptr(), static_cast(src1.step / sizeof(cuDoubleComplex)), - &betac, - dst.ptr(), static_cast(dst.step / sizeof(cuDoubleComplex))) ); - break; - } - - cublasSafeCall( cublasDestroy_v2(handle) ); -#endif -} - -//////////////////////////////////////////////////////////////////////// -// transpose - -void cv::gpu::transpose(const GpuMat& src, GpuMat& dst, Stream& s) -{ - CV_Assert(src.elemSize() == 1 || src.elemSize() == 4 || src.elemSize() == 8); - - dst.create( src.cols, src.rows, src.type() ); - - cudaStream_t stream = StreamAccessor::getStream(s); - - if (src.elemSize() == 1) - { - NppStreamHandler h(stream); - - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - nppSafeCall( nppiTranspose_8u_C1R(src.ptr(), static_cast(src.step), - dst.ptr(), static_cast(dst.step), sz) ); - } - else if (src.elemSize() == 4) - { - NppStStreamHandler h(stream); - - NcvSize32u sz; - sz.width = src.cols; - sz.height = src.rows; - - ncvSafeCall( nppiStTranspose_32u_C1R(const_cast(src.ptr()), static_cast(src.step), - dst.ptr(), static_cast(dst.step), sz) ); - } - else // if (src.elemSize() == 8) - { - if (!deviceSupports(NATIVE_DOUBLE)) - CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); - - NppStStreamHandler h(stream); - - NcvSize32u sz; - sz.width = src.cols; - sz.height = src.rows; - - ncvSafeCall( nppiStTranspose_64u_C1R(const_cast(src.ptr()), static_cast(src.step), - dst.ptr(), static_cast(dst.step), sz) ); - } - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); -} - -//////////////////////////////////////////////////////////////////////// -// flip - -namespace -{ - template struct NppTypeTraits; - template<> struct NppTypeTraits { typedef Npp8u npp_t; }; - template<> struct NppTypeTraits { typedef Npp8s npp_t; }; - template<> struct NppTypeTraits { typedef Npp16u npp_t; }; - template<> struct NppTypeTraits { typedef Npp16s npp_t; }; - template<> struct NppTypeTraits { typedef Npp32s npp_t; }; - template<> struct NppTypeTraits { typedef Npp32f npp_t; }; - template<> struct NppTypeTraits { typedef Npp64f npp_t; }; - - template struct NppMirrorFunc - { - typedef typename NppTypeTraits::npp_t npp_t; - - typedef NppStatus (*func_t)(const npp_t* pSrc, int nSrcStep, npp_t* pDst, int nDstStep, NppiSize oROI, NppiAxis flip); - }; - - template ::func_t func> struct NppMirror - { - typedef typename NppMirrorFunc::npp_t npp_t; - - static void call(const GpuMat& src, GpuMat& dst, int flipCode, cudaStream_t stream) - { - NppStreamHandler h(stream); - - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - nppSafeCall( func(src.ptr(), static_cast(src.step), - dst.ptr(), static_cast(dst.step), sz, - (flipCode == 0 ? NPP_HORIZONTAL_AXIS : (flipCode > 0 ? NPP_VERTICAL_AXIS : NPP_BOTH_AXIS))) ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); - } - }; -} - -void cv::gpu::flip(const GpuMat& src, GpuMat& dst, int flipCode, Stream& stream) -{ - typedef void (*func_t)(const GpuMat& src, GpuMat& dst, int flipCode, cudaStream_t stream); - static const func_t funcs[6][4] = - { - {NppMirror::call, 0, NppMirror::call, NppMirror::call}, - {0,0,0,0}, - {NppMirror::call, 0, NppMirror::call, NppMirror::call}, - {0,0,0,0}, - {NppMirror::call, 0, NppMirror::call, NppMirror::call}, - {NppMirror::call, 0, NppMirror::call, NppMirror::call} - }; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32S || src.depth() == CV_32F); - CV_Assert(src.channels() == 1 || src.channels() == 3 || src.channels() == 4); - - dst.create(src.size(), src.type()); - - funcs[src.depth()][src.channels() - 1](src, dst, flipCode, StreamAccessor::getStream(stream)); -} - -//////////////////////////////////////////////////////////////////////// -// LUT - -void cv::gpu::LUT(const GpuMat& src, const Mat& lut, GpuMat& dst, Stream& s) -{ - class LevelsInit - { - public: - Npp32s pLevels[256]; - const Npp32s* pLevels3[3]; - int nValues3[3]; - -#if (CUDA_VERSION > 4020) - GpuMat d_pLevels; -#endif - - LevelsInit() - { - nValues3[0] = nValues3[1] = nValues3[2] = 256; - for (int i = 0; i < 256; ++i) - pLevels[i] = i; - - -#if (CUDA_VERSION <= 4020) - pLevels3[0] = pLevels3[1] = pLevels3[2] = pLevels; -#else - d_pLevels.upload(Mat(1, 256, CV_32S, pLevels)); - pLevels3[0] = pLevels3[1] = pLevels3[2] = d_pLevels.ptr(); -#endif - } - }; - static LevelsInit lvls; - - int cn = src.channels(); - - CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3); - CV_Assert(lut.depth() == CV_8U && (lut.channels() == 1 || lut.channels() == cn) && lut.rows * lut.cols == 256 && lut.isContinuous()); - - dst.create(src.size(), CV_MAKETYPE(lut.depth(), cn)); - - NppiSize sz; - sz.height = src.rows; - sz.width = src.cols; - - Mat nppLut; - lut.convertTo(nppLut, CV_32S); - - cudaStream_t stream = StreamAccessor::getStream(s); - - NppStreamHandler h(stream); - - if (src.type() == CV_8UC1) - { -#if (CUDA_VERSION <= 4020) - nppSafeCall( nppiLUT_Linear_8u_C1R(src.ptr(), static_cast(src.step), - dst.ptr(), static_cast(dst.step), sz, nppLut.ptr(), lvls.pLevels, 256) ); -#else - GpuMat d_nppLut(Mat(1, 256, CV_32S, nppLut.data)); - nppSafeCall( nppiLUT_Linear_8u_C1R(src.ptr(), static_cast(src.step), - dst.ptr(), static_cast(dst.step), sz, d_nppLut.ptr(), lvls.d_pLevels.ptr(), 256) ); -#endif - } - else - { - const Npp32s* pValues3[3]; - - Mat nppLut3[3]; - if (nppLut.channels() == 1) - { -#if (CUDA_VERSION <= 4020) - pValues3[0] = pValues3[1] = pValues3[2] = nppLut.ptr(); -#else - GpuMat d_nppLut(Mat(1, 256, CV_32S, nppLut.data)); - pValues3[0] = pValues3[1] = pValues3[2] = d_nppLut.ptr(); -#endif - } - else - { - cv::split(nppLut, nppLut3); - -#if (CUDA_VERSION <= 4020) - pValues3[0] = nppLut3[0].ptr(); - pValues3[1] = nppLut3[1].ptr(); - pValues3[2] = nppLut3[2].ptr(); -#else - GpuMat d_nppLut0(Mat(1, 256, CV_32S, nppLut3[0].data)); - GpuMat d_nppLut1(Mat(1, 256, CV_32S, nppLut3[1].data)); - GpuMat d_nppLut2(Mat(1, 256, CV_32S, nppLut3[2].data)); - - pValues3[0] = d_nppLut0.ptr(); - pValues3[1] = d_nppLut1.ptr(); - pValues3[2] = d_nppLut2.ptr(); -#endif - } - - nppSafeCall( nppiLUT_Linear_8u_C3R(src.ptr(), static_cast(src.step), - dst.ptr(), static_cast(dst.step), sz, pValues3, lvls.pLevels3, lvls.nValues3) ); - } - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); -} - -//////////////////////////////////////////////////////////////////////// -// NPP magnitide - -namespace -{ - typedef NppStatus (*nppMagnitude_t)(const Npp32fc* pSrc, int nSrcStep, Npp32f* pDst, int nDstStep, NppiSize oSizeROI); - - inline void npp_magnitude(const GpuMat& src, GpuMat& dst, nppMagnitude_t func, cudaStream_t stream) - { - CV_Assert(src.type() == CV_32FC2); - - dst.create(src.size(), CV_32FC1); - - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - NppStreamHandler h(stream); - - nppSafeCall( func(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), sz) ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); - } -} - -void cv::gpu::magnitude(const GpuMat& src, GpuMat& dst, Stream& stream) -{ - npp_magnitude(src, dst, nppiMagnitude_32fc32f_C1R, StreamAccessor::getStream(stream)); -} - -void cv::gpu::magnitudeSqr(const GpuMat& src, GpuMat& dst, Stream& stream) -{ - npp_magnitude(src, dst, nppiMagnitudeSqr_32fc32f_C1R, StreamAccessor::getStream(stream)); -} - -//////////////////////////////////////////////////////////////////////// -// Polar <-> Cart - -namespace cv { namespace gpu { namespace device -{ - namespace mathfunc - { - void cartToPolar_gpu(PtrStepSzf x, PtrStepSzf y, PtrStepSzf mag, bool magSqr, PtrStepSzf angle, bool angleInDegrees, cudaStream_t stream); - void polarToCart_gpu(PtrStepSzf mag, PtrStepSzf angle, PtrStepSzf x, PtrStepSzf y, bool angleInDegrees, cudaStream_t stream); - } -}}} - -namespace -{ - inline void cartToPolar_caller(const GpuMat& x, const GpuMat& y, GpuMat* mag, bool magSqr, GpuMat* angle, bool angleInDegrees, cudaStream_t stream) - { - using namespace ::cv::gpu::device::mathfunc; - - CV_Assert(x.size() == y.size() && x.type() == y.type()); - CV_Assert(x.depth() == CV_32F); - - if (mag) - mag->create(x.size(), x.type()); - if (angle) - angle->create(x.size(), x.type()); - - GpuMat x1cn = x.reshape(1); - GpuMat y1cn = y.reshape(1); - GpuMat mag1cn = mag ? mag->reshape(1) : GpuMat(); - GpuMat angle1cn = angle ? angle->reshape(1) : GpuMat(); - - cartToPolar_gpu(x1cn, y1cn, mag1cn, magSqr, angle1cn, angleInDegrees, stream); - } - - inline void polarToCart_caller(const GpuMat& mag, const GpuMat& angle, GpuMat& x, GpuMat& y, bool angleInDegrees, cudaStream_t stream) - { - using namespace ::cv::gpu::device::mathfunc; - - CV_Assert((mag.empty() || mag.size() == angle.size()) && mag.type() == angle.type()); - CV_Assert(mag.depth() == CV_32F); - - x.create(mag.size(), mag.type()); - y.create(mag.size(), mag.type()); - - GpuMat mag1cn = mag.reshape(1); - GpuMat angle1cn = angle.reshape(1); - GpuMat x1cn = x.reshape(1); - GpuMat y1cn = y.reshape(1); - - polarToCart_gpu(mag1cn, angle1cn, x1cn, y1cn, angleInDegrees, stream); - } -} - -void cv::gpu::magnitude(const GpuMat& x, const GpuMat& y, GpuMat& dst, Stream& stream) -{ - cartToPolar_caller(x, y, &dst, false, 0, false, StreamAccessor::getStream(stream)); -} - -void cv::gpu::magnitudeSqr(const GpuMat& x, const GpuMat& y, GpuMat& dst, Stream& stream) -{ - cartToPolar_caller(x, y, &dst, true, 0, false, StreamAccessor::getStream(stream)); -} - -void cv::gpu::phase(const GpuMat& x, const GpuMat& y, GpuMat& angle, bool angleInDegrees, Stream& stream) -{ - cartToPolar_caller(x, y, 0, false, &angle, angleInDegrees, StreamAccessor::getStream(stream)); -} - -void cv::gpu::cartToPolar(const GpuMat& x, const GpuMat& y, GpuMat& mag, GpuMat& angle, bool angleInDegrees, Stream& stream) -{ - cartToPolar_caller(x, y, &mag, false, &angle, angleInDegrees, StreamAccessor::getStream(stream)); -} - -void cv::gpu::polarToCart(const GpuMat& magnitude, const GpuMat& angle, GpuMat& x, GpuMat& y, bool angleInDegrees, Stream& stream) -{ - polarToCart_caller(magnitude, angle, x, y, angleInDegrees, StreamAccessor::getStream(stream)); -} - -//////////////////////////////////////////////////////////////////////// -// normalize - -void cv::gpu::normalize(const GpuMat& src, GpuMat& dst, double a, double b, int norm_type, int dtype, const GpuMat& mask) -{ - GpuMat norm_buf; - GpuMat cvt_buf; - normalize(src, dst, a, b, norm_type, dtype, mask, norm_buf, cvt_buf); -} - -void cv::gpu::normalize(const GpuMat& src, GpuMat& dst, double a, double b, int norm_type, int dtype, const GpuMat& mask, GpuMat& norm_buf, GpuMat& cvt_buf) -{ - double scale = 1, shift = 0; - if (norm_type == NORM_MINMAX) - { - double smin = 0, smax = 0; - double dmin = std::min(a, b), dmax = std::max(a, b); - minMax(src, &smin, &smax, mask, norm_buf); - scale = (dmax - dmin) * (smax - smin > std::numeric_limits::epsilon() ? 1.0 / (smax - smin) : 0.0); - shift = dmin - smin * scale; - } - else if (norm_type == NORM_L2 || norm_type == NORM_L1 || norm_type == NORM_INF) - { - scale = norm(src, norm_type, mask, norm_buf); - scale = scale > std::numeric_limits::epsilon() ? a / scale : 0.0; - shift = 0; - } - else - { - CV_Error(CV_StsBadArg, "Unknown/unsupported norm type"); - } - - if (mask.empty()) - { - src.convertTo(dst, dtype, scale, shift); - } - else - { - src.convertTo(cvt_buf, dtype, scale, shift); - cvt_buf.copyTo(dst, mask); - } -} - -#endif /* !defined (HAVE_CUDA) */ diff --git a/modules/gpu/src/bgfg_gmg.cpp b/modules/gpu/src/bgfg_gmg.cpp deleted file mode 100644 index 46f3ba2890..0000000000 --- a/modules/gpu/src/bgfg_gmg.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/*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 "precomp.hpp" - -#if !defined HAVE_CUDA || defined(CUDA_DISABLER) - -cv::gpu::GMG_GPU::GMG_GPU() { throw_nogpu(); } -void cv::gpu::GMG_GPU::initialize(cv::Size, float, float) { throw_nogpu(); } -void cv::gpu::GMG_GPU::operator ()(const cv::gpu::GpuMat&, cv::gpu::GpuMat&, float, cv::gpu::Stream&) { throw_nogpu(); } -void cv::gpu::GMG_GPU::release() {} - -#else - -namespace cv { namespace gpu { namespace device { - namespace bgfg_gmg - { - void loadConstants(int width, int height, float minVal, float maxVal, int quantizationLevels, float backgroundPrior, - float decisionThreshold, int maxFeatures, int numInitializationFrames); - - template - void update_gpu(PtrStepSzb frame, PtrStepb fgmask, PtrStepSzi colors, PtrStepf weights, PtrStepi nfeatures, - int frameNum, float learningRate, bool updateBackgroundModel, cudaStream_t stream); - } -}}} - -cv::gpu::GMG_GPU::GMG_GPU() -{ - maxFeatures = 64; - learningRate = 0.025f; - numInitializationFrames = 120; - quantizationLevels = 16; - backgroundPrior = 0.8f; - decisionThreshold = 0.8f; - smoothingRadius = 7; - updateBackgroundModel = true; -} - -void cv::gpu::GMG_GPU::initialize(cv::Size frameSize, float min, float max) -{ - using namespace cv::gpu::device::bgfg_gmg; - - CV_Assert(min < max); - CV_Assert(maxFeatures > 0); - CV_Assert(learningRate >= 0.0f && learningRate <= 1.0f); - CV_Assert(numInitializationFrames >= 1); - CV_Assert(quantizationLevels >= 1 && quantizationLevels <= 255); - CV_Assert(backgroundPrior >= 0.0f && backgroundPrior <= 1.0f); - - minVal_ = min; - maxVal_ = max; - - frameSize_ = frameSize; - - frameNum_ = 0; - - nfeatures_.create(frameSize_, CV_32SC1); - colors_.create(maxFeatures * frameSize_.height, frameSize_.width, CV_32SC1); - weights_.create(maxFeatures * frameSize_.height, frameSize_.width, CV_32FC1); - - nfeatures_.setTo(cv::Scalar::all(0)); - - if (smoothingRadius > 0) - boxFilter_ = cv::gpu::createBoxFilter_GPU(CV_8UC1, CV_8UC1, cv::Size(smoothingRadius, smoothingRadius)); - - loadConstants(frameSize_.width, frameSize_.height, minVal_, maxVal_, quantizationLevels, backgroundPrior, decisionThreshold, maxFeatures, numInitializationFrames); -} - -void cv::gpu::GMG_GPU::operator ()(const cv::gpu::GpuMat& frame, cv::gpu::GpuMat& fgmask, float newLearningRate, cv::gpu::Stream& stream) -{ - using namespace cv::gpu::device::bgfg_gmg; - - typedef void (*func_t)(PtrStepSzb frame, PtrStepb fgmask, PtrStepSzi colors, PtrStepf weights, PtrStepi nfeatures, - int frameNum, float learningRate, bool updateBackgroundModel, cudaStream_t stream); - static const func_t funcs[6][4] = - { - {update_gpu, 0, update_gpu, update_gpu}, - {0,0,0,0}, - {update_gpu, 0, update_gpu, update_gpu}, - {0,0,0,0}, - {0,0,0,0}, - {update_gpu, 0, update_gpu, update_gpu} - }; - - CV_Assert(frame.depth() == CV_8U || frame.depth() == CV_16U || frame.depth() == CV_32F); - CV_Assert(frame.channels() == 1 || frame.channels() == 3 || frame.channels() == 4); - - if (newLearningRate != -1.0f) - { - CV_Assert(newLearningRate >= 0.0f && newLearningRate <= 1.0f); - learningRate = newLearningRate; - } - - if (frame.size() != frameSize_) - initialize(frame.size(), 0.0f, frame.depth() == CV_8U ? 255.0f : frame.depth() == CV_16U ? std::numeric_limits::max() : 1.0f); - - fgmask.create(frameSize_, CV_8UC1); - if (stream) - stream.enqueueMemSet(fgmask, cv::Scalar::all(0)); - else - fgmask.setTo(cv::Scalar::all(0)); - - funcs[frame.depth()][frame.channels() - 1](frame, fgmask, colors_, weights_, nfeatures_, frameNum_, learningRate, updateBackgroundModel, cv::gpu::StreamAccessor::getStream(stream)); - - // medianBlur - if (smoothingRadius > 0) - { - boxFilter_->apply(fgmask, buf_, cv::Rect(0,0,-1,-1), stream); - int minCount = (smoothingRadius * smoothingRadius + 1) / 2; - double thresh = 255.0 * minCount / (smoothingRadius * smoothingRadius); - cv::gpu::threshold(buf_, fgmask, thresh, 255.0, cv::THRESH_BINARY, stream); - } - - // keep track of how many frames we have processed - ++frameNum_; -} - -void cv::gpu::GMG_GPU::release() -{ - frameSize_ = Size(); - - nfeatures_.release(); - colors_.release(); - weights_.release(); - boxFilter_.release(); - buf_.release(); -} - -#endif diff --git a/modules/gpu/src/bgfg_mog.cpp b/modules/gpu/src/bgfg_mog.cpp deleted file mode 100644 index 05b4ffb9c8..0000000000 --- a/modules/gpu/src/bgfg_mog.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/*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 "precomp.hpp" - -#if !defined HAVE_CUDA || defined(CUDA_DISABLER) - -cv::gpu::MOG_GPU::MOG_GPU(int) { throw_nogpu(); } -void cv::gpu::MOG_GPU::initialize(cv::Size, int) { throw_nogpu(); } -void cv::gpu::MOG_GPU::operator()(const cv::gpu::GpuMat&, cv::gpu::GpuMat&, float, Stream&) { throw_nogpu(); } -void cv::gpu::MOG_GPU::getBackgroundImage(GpuMat&, Stream&) const { throw_nogpu(); } -void cv::gpu::MOG_GPU::release() {} - -cv::gpu::MOG2_GPU::MOG2_GPU(int) { throw_nogpu(); } -void cv::gpu::MOG2_GPU::initialize(cv::Size, int) { throw_nogpu(); } -void cv::gpu::MOG2_GPU::operator()(const GpuMat&, GpuMat&, float, Stream&) { throw_nogpu(); } -void cv::gpu::MOG2_GPU::getBackgroundImage(GpuMat&, Stream&) const { throw_nogpu(); } -void cv::gpu::MOG2_GPU::release() {} - -#else - -namespace cv { namespace gpu { namespace device -{ - namespace mog - { - void mog_gpu(PtrStepSzb frame, int cn, PtrStepSzb fgmask, PtrStepSzf weight, PtrStepSzf sortKey, PtrStepSzb mean, PtrStepSzb var, - int nmixtures, float varThreshold, float learningRate, float backgroundRatio, float noiseSigma, - cudaStream_t stream); - void getBackgroundImage_gpu(int cn, PtrStepSzf weight, PtrStepSzb mean, PtrStepSzb dst, int nmixtures, float backgroundRatio, cudaStream_t stream); - - void loadConstants(int nmixtures, float Tb, float TB, float Tg, float varInit, float varMin, float varMax, float tau, unsigned char shadowVal); - void mog2_gpu(PtrStepSzb frame, int cn, PtrStepSzb fgmask, PtrStepSzb modesUsed, PtrStepSzf weight, PtrStepSzf variance, PtrStepSzb mean, float alphaT, float prune, bool detectShadows, cudaStream_t stream); - void getBackgroundImage2_gpu(int cn, PtrStepSzb modesUsed, PtrStepSzf weight, PtrStepSzb mean, PtrStepSzb dst, cudaStream_t stream); - } -}}} - -namespace mog -{ - const int defaultNMixtures = 5; - const int defaultHistory = 200; - const float defaultBackgroundRatio = 0.7f; - const float defaultVarThreshold = 2.5f * 2.5f; - const float defaultNoiseSigma = 30.0f * 0.5f; - const float defaultInitialWeight = 0.05f; -} - -cv::gpu::MOG_GPU::MOG_GPU(int nmixtures) : - frameSize_(0, 0), frameType_(0), nframes_(0) -{ - nmixtures_ = std::min(nmixtures > 0 ? nmixtures : mog::defaultNMixtures, 8); - history = mog::defaultHistory; - varThreshold = mog::defaultVarThreshold; - backgroundRatio = mog::defaultBackgroundRatio; - noiseSigma = mog::defaultNoiseSigma; -} - -void cv::gpu::MOG_GPU::initialize(cv::Size frameSize, int frameType) -{ - CV_Assert(frameType == CV_8UC1 || frameType == CV_8UC3 || frameType == CV_8UC4); - - frameSize_ = frameSize; - frameType_ = frameType; - - int ch = CV_MAT_CN(frameType); - int work_ch = ch; - - // for each gaussian mixture of each pixel bg model we store - // the mixture sort key (w/sum_of_variances), the mixture weight (w), - // the mean (nchannels values) and - // the diagonal covariance matrix (another nchannels values) - - weight_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC1); - sortKey_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC1); - mean_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC(work_ch)); - var_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC(work_ch)); - - weight_.setTo(cv::Scalar::all(0)); - sortKey_.setTo(cv::Scalar::all(0)); - mean_.setTo(cv::Scalar::all(0)); - var_.setTo(cv::Scalar::all(0)); - - nframes_ = 0; -} - -void cv::gpu::MOG_GPU::operator()(const cv::gpu::GpuMat& frame, cv::gpu::GpuMat& fgmask, float learningRate, Stream& stream) -{ - using namespace cv::gpu::device::mog; - - CV_Assert(frame.depth() == CV_8U); - - int ch = frame.channels(); - int work_ch = ch; - - if (nframes_ == 0 || learningRate >= 1.0 || frame.size() != frameSize_ || work_ch != mean_.channels()) - initialize(frame.size(), frame.type()); - - fgmask.create(frameSize_, CV_8UC1); - - ++nframes_; - learningRate = learningRate >= 0.0f && nframes_ > 1 ? learningRate : 1.0f / std::min(nframes_, history); - CV_Assert(learningRate >= 0.0f); - - mog_gpu(frame, ch, fgmask, weight_, sortKey_, mean_, var_, nmixtures_, - varThreshold, learningRate, backgroundRatio, noiseSigma, - StreamAccessor::getStream(stream)); -} - -void cv::gpu::MOG_GPU::getBackgroundImage(GpuMat& backgroundImage, Stream& stream) const -{ - using namespace cv::gpu::device::mog; - - backgroundImage.create(frameSize_, frameType_); - - getBackgroundImage_gpu(backgroundImage.channels(), weight_, mean_, backgroundImage, nmixtures_, backgroundRatio, StreamAccessor::getStream(stream)); -} - -void cv::gpu::MOG_GPU::release() -{ - frameSize_ = Size(0, 0); - frameType_ = 0; - nframes_ = 0; - - weight_.release(); - sortKey_.release(); - mean_.release(); - var_.release(); -} - -///////////////////////////////////////////////////////////////// -// MOG2 - -namespace mog2 -{ - // default parameters of gaussian background detection algorithm - const int defaultHistory = 500; // Learning rate; alpha = 1/defaultHistory2 - const float defaultVarThreshold = 4.0f * 4.0f; - const int defaultNMixtures = 5; // maximal number of Gaussians in mixture - const float defaultBackgroundRatio = 0.9f; // threshold sum of weights for background test - const float defaultVarThresholdGen = 3.0f * 3.0f; - const float defaultVarInit = 15.0f; // initial variance for new components - const float defaultVarMax = 5.0f * defaultVarInit; - const float defaultVarMin = 4.0f; - - // additional parameters - const float defaultfCT = 0.05f; // complexity reduction prior constant 0 - no reduction of number of components - const unsigned char defaultnShadowDetection = 127; // value to use in the segmentation mask for shadows, set 0 not to do shadow detection - const float defaultfTau = 0.5f; // Tau - shadow threshold, see the paper for explanation -} - -cv::gpu::MOG2_GPU::MOG2_GPU(int nmixtures) : - frameSize_(0, 0), frameType_(0), nframes_(0) -{ - nmixtures_ = nmixtures > 0 ? nmixtures : mog2::defaultNMixtures; - - history = mog2::defaultHistory; - varThreshold = mog2::defaultVarThreshold; - bShadowDetection = true; - - backgroundRatio = mog2::defaultBackgroundRatio; - fVarInit = mog2::defaultVarInit; - fVarMax = mog2::defaultVarMax; - fVarMin = mog2::defaultVarMin; - - varThresholdGen = mog2::defaultVarThresholdGen; - fCT = mog2::defaultfCT; - nShadowDetection = mog2::defaultnShadowDetection; - fTau = mog2::defaultfTau; -} - -void cv::gpu::MOG2_GPU::initialize(cv::Size frameSize, int frameType) -{ - using namespace cv::gpu::device::mog; - - CV_Assert(frameType == CV_8UC1 || frameType == CV_8UC3 || frameType == CV_8UC4); - - frameSize_ = frameSize; - frameType_ = frameType; - nframes_ = 0; - - int ch = CV_MAT_CN(frameType); - int work_ch = ch; - - // for each gaussian mixture of each pixel bg model we store ... - // the mixture weight (w), - // the mean (nchannels values) and - // the covariance - weight_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC1); - variance_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC1); - mean_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC(work_ch)); - - //make the array for keeping track of the used modes per pixel - all zeros at start - bgmodelUsedModes_.create(frameSize_, CV_8UC1); - bgmodelUsedModes_.setTo(cv::Scalar::all(0)); - - loadConstants(nmixtures_, varThreshold, backgroundRatio, varThresholdGen, fVarInit, fVarMin, fVarMax, fTau, nShadowDetection); -} - -void cv::gpu::MOG2_GPU::operator()(const GpuMat& frame, GpuMat& fgmask, float learningRate, Stream& stream) -{ - using namespace cv::gpu::device::mog; - - int ch = frame.channels(); - int work_ch = ch; - - if (nframes_ == 0 || learningRate >= 1.0f || frame.size() != frameSize_ || work_ch != mean_.channels()) - initialize(frame.size(), frame.type()); - - fgmask.create(frameSize_, CV_8UC1); - fgmask.setTo(cv::Scalar::all(0)); - - ++nframes_; - learningRate = learningRate >= 0.0f && nframes_ > 1 ? learningRate : 1.0f / std::min(2 * nframes_, history); - CV_Assert(learningRate >= 0.0f); - - mog2_gpu(frame, frame.channels(), fgmask, bgmodelUsedModes_, weight_, variance_, mean_, learningRate, -learningRate * fCT, bShadowDetection, StreamAccessor::getStream(stream)); -} - -void cv::gpu::MOG2_GPU::getBackgroundImage(GpuMat& backgroundImage, Stream& stream) const -{ - using namespace cv::gpu::device::mog; - - backgroundImage.create(frameSize_, frameType_); - - getBackgroundImage2_gpu(backgroundImage.channels(), bgmodelUsedModes_, weight_, mean_, backgroundImage, StreamAccessor::getStream(stream)); -} - -void cv::gpu::MOG2_GPU::release() -{ - frameSize_ = Size(0, 0); - frameType_ = 0; - nframes_ = 0; - - weight_.release(); - variance_.release(); - mean_.release(); - - bgmodelUsedModes_.release(); -} - -#endif diff --git a/modules/gpu/src/bgfg_vibe.cpp b/modules/gpu/src/bgfg_vibe.cpp deleted file mode 100644 index ff7e58082e..0000000000 --- a/modules/gpu/src/bgfg_vibe.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/*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 "precomp.hpp" - -#if !defined HAVE_CUDA || defined(CUDA_DISABLER) - -cv::gpu::VIBE_GPU::VIBE_GPU(unsigned long) { throw_nogpu(); } -void cv::gpu::VIBE_GPU::initialize(const GpuMat&, Stream&) { throw_nogpu(); } -void cv::gpu::VIBE_GPU::operator()(const GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } -void cv::gpu::VIBE_GPU::release() {} - -#else - -namespace cv { namespace gpu { namespace device -{ - namespace vibe - { - void loadConstants(int nbSamples, int reqMatches, int radius, int subsamplingFactor); - - void init_gpu(PtrStepSzb frame, int cn, PtrStepSzb samples, PtrStepSz randStates, cudaStream_t stream); - - void update_gpu(PtrStepSzb frame, int cn, PtrStepSzb fgmask, PtrStepSzb samples, PtrStepSz randStates, cudaStream_t stream); - } -}}} - -namespace -{ - const int defaultNbSamples = 20; - const int defaultReqMatches = 2; - const int defaultRadius = 20; - const int defaultSubsamplingFactor = 16; -} - -cv::gpu::VIBE_GPU::VIBE_GPU(unsigned long rngSeed) : - frameSize_(0, 0), rngSeed_(rngSeed) -{ - nbSamples = defaultNbSamples; - reqMatches = defaultReqMatches; - radius = defaultRadius; - subsamplingFactor = defaultSubsamplingFactor; -} - -void cv::gpu::VIBE_GPU::initialize(const GpuMat& firstFrame, Stream& s) -{ - using namespace cv::gpu::device::vibe; - - CV_Assert(firstFrame.type() == CV_8UC1 || firstFrame.type() == CV_8UC3 || firstFrame.type() == CV_8UC4); - - cudaStream_t stream = StreamAccessor::getStream(s); - - loadConstants(nbSamples, reqMatches, radius, subsamplingFactor); - - frameSize_ = firstFrame.size(); - - if (randStates_.size() != frameSize_) - { - cv::RNG rng(rngSeed_); - cv::Mat h_randStates(frameSize_, CV_8UC4); - rng.fill(h_randStates, cv::RNG::UNIFORM, 0, 255); - randStates_.upload(h_randStates); - } - - int ch = firstFrame.channels(); - int sample_ch = ch == 1 ? 1 : 4; - - samples_.create(nbSamples * frameSize_.height, frameSize_.width, CV_8UC(sample_ch)); - - init_gpu(firstFrame, ch, samples_, randStates_, stream); -} - -void cv::gpu::VIBE_GPU::operator()(const GpuMat& frame, GpuMat& fgmask, Stream& s) -{ - using namespace cv::gpu::device::vibe; - - CV_Assert(frame.depth() == CV_8U); - - int ch = frame.channels(); - int sample_ch = ch == 1 ? 1 : 4; - - if (frame.size() != frameSize_ || sample_ch != samples_.channels()) - initialize(frame); - - fgmask.create(frameSize_, CV_8UC1); - - update_gpu(frame, ch, fgmask, samples_, randStates_, StreamAccessor::getStream(s)); -} - -void cv::gpu::VIBE_GPU::release() -{ - frameSize_ = Size(0, 0); - - randStates_.release(); - - samples_.release(); -} - -#endif diff --git a/modules/gpu/src/bilateral_filter.cpp b/modules/gpu/src/bilateral_filter.cpp deleted file mode 100644 index 6aa0f525d3..0000000000 --- a/modules/gpu/src/bilateral_filter.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/*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 GpuMaterials 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 "precomp.hpp" - -using namespace cv; -using namespace cv::gpu; - -#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) - -cv::gpu::DisparityBilateralFilter::DisparityBilateralFilter(int, int, int) { throw_nogpu(); } -cv::gpu::DisparityBilateralFilter::DisparityBilateralFilter(int, int, int, float, float, float) { throw_nogpu(); } - -void cv::gpu::DisparityBilateralFilter::operator()(const GpuMat&, const GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } - -#else /* !defined (HAVE_CUDA) */ - -namespace cv { namespace gpu { namespace device -{ - namespace disp_bilateral_filter - { - void disp_load_constants(float* table_color, PtrStepSzf table_space, int ndisp, int radius, short edge_disc, short max_disc); - - template - void disp_bilateral_filter(PtrStepSz disp, PtrStepSzb img, int channels, int iters, cudaStream_t stream); - } -}}} - -using namespace ::cv::gpu::device::disp_bilateral_filter; - -namespace -{ - const float DEFAULT_EDGE_THRESHOLD = 0.1f; - const float DEFAULT_MAX_DISC_THRESHOLD = 0.2f; - const float DEFAULT_SIGMA_RANGE = 10.0f; - - inline void calc_color_weighted_table(GpuMat& table_color, float sigma_range, int len) - { - Mat cpu_table_color(1, len, CV_32F); - - float* line = cpu_table_color.ptr(); - - for(int i = 0; i < len; i++) - line[i] = static_cast(std::exp(-double(i * i) / (2 * sigma_range * sigma_range))); - - table_color.upload(cpu_table_color); - } - - inline void calc_space_weighted_filter(GpuMat& table_space, int win_size, float dist_space) - { - int half = (win_size >> 1); - - Mat cpu_table_space(half + 1, half + 1, CV_32F); - - for (int y = 0; y <= half; ++y) - { - float* row = cpu_table_space.ptr(y); - for (int x = 0; x <= half; ++x) - row[x] = exp(-sqrt(float(y * y) + float(x * x)) / dist_space); - } - - table_space.upload(cpu_table_space); - } - - template - void disp_bilateral_filter_operator(int ndisp, int radius, int iters, float edge_threshold,float max_disc_threshold, - GpuMat& table_color, GpuMat& table_space, - const GpuMat& disp, const GpuMat& img, GpuMat& dst, Stream& stream) - { - short edge_disc = std::max(short(1), short(ndisp * edge_threshold + 0.5)); - short max_disc = short(ndisp * max_disc_threshold + 0.5); - - disp_load_constants(table_color.ptr(), table_space, ndisp, radius, edge_disc, max_disc); - - if (&dst != &disp) - { - if (stream) - stream.enqueueCopy(disp, dst); - else - disp.copyTo(dst); - } - - disp_bilateral_filter(dst, img, img.channels(), iters, StreamAccessor::getStream(stream)); - } - - typedef void (*bilateral_filter_operator_t)(int ndisp, int radius, int iters, float edge_threshold, float max_disc_threshold, - GpuMat& table_color, GpuMat& table_space, - const GpuMat& disp, const GpuMat& img, GpuMat& dst, Stream& stream); - - const bilateral_filter_operator_t operators[] = - {disp_bilateral_filter_operator, 0, 0, disp_bilateral_filter_operator, 0, 0, 0, 0}; -} - -cv::gpu::DisparityBilateralFilter::DisparityBilateralFilter(int ndisp_, int radius_, int iters_) - : ndisp(ndisp_), radius(radius_), iters(iters_), edge_threshold(DEFAULT_EDGE_THRESHOLD), max_disc_threshold(DEFAULT_MAX_DISC_THRESHOLD), - sigma_range(DEFAULT_SIGMA_RANGE) -{ - calc_color_weighted_table(table_color, sigma_range, 255); - calc_space_weighted_filter(table_space, radius * 2 + 1, radius + 1.0f); -} - -cv::gpu::DisparityBilateralFilter::DisparityBilateralFilter(int ndisp_, int radius_, int iters_, float edge_threshold_, - float max_disc_threshold_, float sigma_range_) - : ndisp(ndisp_), radius(radius_), iters(iters_), edge_threshold(edge_threshold_), max_disc_threshold(max_disc_threshold_), - sigma_range(sigma_range_) -{ - calc_color_weighted_table(table_color, sigma_range, 255); - calc_space_weighted_filter(table_space, radius * 2 + 1, radius + 1.0f); -} - -void cv::gpu::DisparityBilateralFilter::operator()(const GpuMat& disp, const GpuMat& img, GpuMat& dst, Stream& stream) -{ - CV_DbgAssert(0 < ndisp && 0 < radius && 0 < iters); - CV_Assert(disp.rows == img.rows && disp.cols == img.cols && (disp.type() == CV_8U || disp.type() == CV_16S) && (img.type() == CV_8UC1 || img.type() == CV_8UC3)); - operators[disp.type()](ndisp, radius, iters, edge_threshold, max_disc_threshold, table_color, table_space, disp, img, dst, stream); -} - -#endif /* !defined (HAVE_CUDA) */ diff --git a/modules/gpu/src/calib3d.cpp b/modules/gpu/src/calib3d.cpp index ab7f63f455..631174218c 100644 --- a/modules/gpu/src/calib3d.cpp +++ b/modules/gpu/src/calib3d.cpp @@ -47,15 +47,15 @@ using namespace cv::gpu; #if !defined HAVE_CUDA || defined(CUDA_DISABLER) -void cv::gpu::transformPoints(const GpuMat&, const Mat&, const Mat&, GpuMat&, Stream&) { throw_nogpu(); } +void cv::gpu::transformPoints(const GpuMat&, const Mat&, const Mat&, GpuMat&, Stream&) { throw_no_cuda(); } -void cv::gpu::projectPoints(const GpuMat&, const Mat&, const Mat&, const Mat&, const Mat&, GpuMat&, Stream&) { throw_nogpu(); } +void cv::gpu::projectPoints(const GpuMat&, const Mat&, const Mat&, const Mat&, const Mat&, GpuMat&, Stream&) { throw_no_cuda(); } -void cv::gpu::solvePnPRansac(const Mat&, const Mat&, const Mat&, const Mat&, Mat&, Mat&, bool, int, float, int, std::vector*) { throw_nogpu(); } +void cv::gpu::solvePnPRansac(const Mat&, const Mat&, const Mat&, const Mat&, Mat&, Mat&, bool, int, float, int, std::vector*) { throw_no_cuda(); } #else -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { namespace transform_points { @@ -78,7 +78,7 @@ namespace cv { namespace gpu { namespace device } }}} -using namespace ::cv::gpu::device; +using namespace ::cv::gpu::cudev; namespace { @@ -150,7 +150,7 @@ namespace } // Computes rotation, translation pair for small subsets if the input data - class TransformHypothesesGenerator + class TransformHypothesesGenerator : public ParallelLoopBody { public: TransformHypothesesGenerator(const Mat& object_, const Mat& image_, const Mat& dist_coef_, @@ -160,7 +160,7 @@ namespace num_points(num_points_), subset_size(subset_size_), rot_matrices(rot_matrices_), transl_vectors(transl_vectors_) {} - void operator()(const BlockedRange& range) const + void operator()(const Range& range) const { // Input data for generation of the current hypothesis std::vector subset_indices(subset_size); @@ -172,7 +172,7 @@ namespace Mat rot_mat(3, 3, CV_64F); Mat transl_vec(1, 3, CV_64F); - for (int iter = range.begin(); iter < range.end(); ++iter) + for (int iter = range.start; iter < range.end; ++iter) { selectRandom(subset_size, num_points, subset_indices); for (int i = 0; i < subset_size; ++i) @@ -238,7 +238,7 @@ void cv::gpu::solvePnPRansac(const Mat& object, const Mat& image, const Mat& cam // Generate set of hypotheses using small subsets of the input data TransformHypothesesGenerator body(object, image_normalized, empty_dist_coef, eye_camera_mat, num_points, subset_size, rot_matrices, transl_vectors); - parallel_for(BlockedRange(0, num_iters), body); + parallel_for_(Range(0, num_iters), body); // Compute scores (i.e. number of inliers) for each hypothesis GpuMat d_object(object); @@ -252,7 +252,7 @@ void cv::gpu::solvePnPRansac(const Mat& object, const Mat& image, const Mat& cam // Find the best hypothesis index Point best_idx; double best_score; - minMaxLoc(d_hypothesis_scores, NULL, &best_score, NULL, &best_idx); + gpu::minMaxLoc(d_hypothesis_scores, NULL, &best_score, NULL, &best_idx); int num_inliers = static_cast(best_score); // Extract the best hypothesis data @@ -290,5 +290,3 @@ void cv::gpu::solvePnPRansac(const Mat& object, const Mat& image, const Mat& cam } #endif - - diff --git a/modules/gpu/src/cascadeclassifier.cpp b/modules/gpu/src/cascadeclassifier.cpp index e82ee9d336..fc5eafbf4d 100644 --- a/modules/gpu/src/cascadeclassifier.cpp +++ b/modules/gpu/src/cascadeclassifier.cpp @@ -22,13 +22,13 @@ // // * 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 GpuMaterials provided with the distribution. +// 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 bpied warranties, including, but not limited to, the bpied +// 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 @@ -41,23 +41,22 @@ //M*/ #include "precomp.hpp" -#include -#include +#include "opencv2/objdetect/objdetect_c.h" using namespace cv; using namespace cv::gpu; #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) -cv::gpu::CascadeClassifier_GPU::CascadeClassifier_GPU() { throw_nogpu(); } -cv::gpu::CascadeClassifier_GPU::CascadeClassifier_GPU(const std::string&) { throw_nogpu(); } -cv::gpu::CascadeClassifier_GPU::~CascadeClassifier_GPU() { throw_nogpu(); } -bool cv::gpu::CascadeClassifier_GPU::empty() const { throw_nogpu(); return true; } -bool cv::gpu::CascadeClassifier_GPU::load(const std::string&) { throw_nogpu(); return true; } -Size cv::gpu::CascadeClassifier_GPU::getClassifierSize() const { throw_nogpu(); return Size();} -void cv::gpu::CascadeClassifier_GPU::release() { throw_nogpu(); } -int cv::gpu::CascadeClassifier_GPU::detectMultiScale( const GpuMat&, GpuMat&, double, int, Size) {throw_nogpu(); return -1;} -int cv::gpu::CascadeClassifier_GPU::detectMultiScale( const GpuMat&, GpuMat&, Size, Size, double, int) {throw_nogpu(); return -1;} +cv::gpu::CascadeClassifier_GPU::CascadeClassifier_GPU() { throw_no_cuda(); } +cv::gpu::CascadeClassifier_GPU::CascadeClassifier_GPU(const String&) { throw_no_cuda(); } +cv::gpu::CascadeClassifier_GPU::~CascadeClassifier_GPU() { throw_no_cuda(); } +bool cv::gpu::CascadeClassifier_GPU::empty() const { throw_no_cuda(); return true; } +bool cv::gpu::CascadeClassifier_GPU::load(const String&) { throw_no_cuda(); return true; } +Size cv::gpu::CascadeClassifier_GPU::getClassifierSize() const { throw_no_cuda(); return Size();} +void cv::gpu::CascadeClassifier_GPU::release() { throw_no_cuda(); } +int cv::gpu::CascadeClassifier_GPU::detectMultiScale( const GpuMat&, GpuMat&, double, int, Size) {throw_no_cuda(); return -1;} +int cv::gpu::CascadeClassifier_GPU::detectMultiScale( const GpuMat&, GpuMat&, Size, Size, double, int) {throw_no_cuda(); return -1;} #else @@ -71,9 +70,40 @@ public: bool findLargestObject, bool visualizeInPlace, cv::Size ncvMinSize, cv::Size maxObjectSize) = 0; virtual cv::Size getClassifierCvSize() const = 0; - virtual bool read(const std::string& classifierAsXml) = 0; + virtual bool read(const String& classifierAsXml) = 0; }; +#ifndef HAVE_OPENCV_GPULEGACY + +struct cv::gpu::CascadeClassifier_GPU::HaarCascade : cv::gpu::CascadeClassifier_GPU::CascadeClassifierImpl +{ +public: + HaarCascade() + { + throw_no_cuda(); + } + + unsigned int process(const GpuMat&, GpuMat&, float, int, bool, bool, cv::Size, cv::Size) + { + throw_no_cuda(); + return 0; + } + + cv::Size getClassifierCvSize() const + { + throw_no_cuda(); + return cv::Size(); + } + + bool read(const String&) + { + throw_no_cuda(); + return false; + } +}; + +#else + struct cv::gpu::CascadeClassifier_GPU::HaarCascade : cv::gpu::CascadeClassifier_GPU::CascadeClassifierImpl { public: @@ -82,7 +112,7 @@ public: ncvSetDebugOutputHandler(NCVDebugOutputHandler); } - bool read(const std::string& filename) + bool read(const String& filename) { ncvSafeCall( load(filename) ); return true; @@ -169,16 +199,16 @@ public: cv::Size getClassifierCvSize() const { return cv::Size(haar.ClassifierSize.width, haar.ClassifierSize.height); } private: - static void NCVDebugOutputHandler(const std::string &msg) { CV_Error(CV_GpuApiCallError, msg.c_str()); } + static void NCVDebugOutputHandler(const String &msg) { CV_Error(cv::Error::GpuApiCallError, msg.c_str()); } - NCVStatus load(const std::string& classifierFile) + NCVStatus load(const String& classifierFile) { int devId = cv::gpu::getDevice(); ncvAssertCUDAReturn(cudaGetDeviceProperties(&devProp, devId), NCV_CUDA_ERROR); // Load the classifier from file (assuming its size is about 1 mb) using a simple allocator - gpuCascadeAllocator = new NCVMemNativeAllocator(NCVMemoryTypeDevice, static_cast(devProp.textureAlignment)); - cpuCascadeAllocator = new NCVMemNativeAllocator(NCVMemoryTypeHostPinned, static_cast(devProp.textureAlignment)); + gpuCascadeAllocator = makePtr(NCVMemoryTypeDevice, static_cast(devProp.textureAlignment)); + cpuCascadeAllocator = makePtr(NCVMemoryTypeHostPinned, static_cast(devProp.textureAlignment)); ncvAssertPrintReturn(gpuCascadeAllocator->isInitialized(), "Error creating cascade GPU allocator", NCV_CUDA_ERROR); ncvAssertPrintReturn(cpuCascadeAllocator->isInitialized(), "Error creating cascade CPU allocator", NCV_CUDA_ERROR); @@ -187,9 +217,9 @@ private: ncvStat = ncvHaarGetClassifierSize(classifierFile, haarNumStages, haarNumNodes, haarNumFeatures); ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error reading classifier size (check the file)", NCV_FILE_ERROR); - h_haarStages = new NCVVectorAlloc(*cpuCascadeAllocator, haarNumStages); - h_haarNodes = new NCVVectorAlloc(*cpuCascadeAllocator, haarNumNodes); - h_haarFeatures = new NCVVectorAlloc(*cpuCascadeAllocator, haarNumFeatures); + h_haarStages.reset (new NCVVectorAlloc(*cpuCascadeAllocator, haarNumStages)); + h_haarNodes.reset (new NCVVectorAlloc(*cpuCascadeAllocator, haarNumNodes)); + h_haarFeatures.reset(new NCVVectorAlloc(*cpuCascadeAllocator, haarNumFeatures)); ncvAssertPrintReturn(h_haarStages->isMemAllocated(), "Error in cascade CPU allocator", NCV_CUDA_ERROR); ncvAssertPrintReturn(h_haarNodes->isMemAllocated(), "Error in cascade CPU allocator", NCV_CUDA_ERROR); @@ -198,9 +228,9 @@ private: ncvStat = ncvHaarLoadFromFile_host(classifierFile, haar, *h_haarStages, *h_haarNodes, *h_haarFeatures); ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error loading classifier", NCV_FILE_ERROR); - d_haarStages = new NCVVectorAlloc(*gpuCascadeAllocator, haarNumStages); - d_haarNodes = new NCVVectorAlloc(*gpuCascadeAllocator, haarNumNodes); - d_haarFeatures = new NCVVectorAlloc(*gpuCascadeAllocator, haarNumFeatures); + d_haarStages.reset (new NCVVectorAlloc(*gpuCascadeAllocator, haarNumStages)); + d_haarNodes.reset (new NCVVectorAlloc(*gpuCascadeAllocator, haarNumNodes)); + d_haarFeatures.reset(new NCVVectorAlloc(*gpuCascadeAllocator, haarNumFeatures)); ncvAssertPrintReturn(d_haarStages->isMemAllocated(), "Error in cascade GPU allocator", NCV_CUDA_ERROR); ncvAssertPrintReturn(d_haarNodes->isMemAllocated(), "Error in cascade GPU allocator", NCV_CUDA_ERROR); @@ -249,8 +279,8 @@ private: ncvAssertReturnNcvStat(ncvStat); ncvAssertCUDAReturn(cudaStreamSynchronize(0), NCV_CUDA_ERROR); - gpuAllocator = new NCVMemStackAllocator(NCVMemoryTypeDevice, gpuCounter.maxSize(), static_cast(devProp.textureAlignment)); - cpuAllocator = new NCVMemStackAllocator(NCVMemoryTypeHostPinned, cpuCounter.maxSize(), static_cast(devProp.textureAlignment)); + gpuAllocator = makePtr(NCVMemoryTypeDevice, gpuCounter.maxSize(), static_cast(devProp.textureAlignment)); + cpuAllocator = makePtr(NCVMemoryTypeHostPinned, cpuCounter.maxSize(), static_cast(devProp.textureAlignment)); ncvAssertPrintReturn(gpuAllocator->isInitialized(), "Error creating GPU memory allocator", NCV_CUDA_ERROR); ncvAssertPrintReturn(cpuAllocator->isInitialized(), "Error creating CPU memory allocator", NCV_CUDA_ERROR); @@ -283,6 +313,8 @@ private: virtual ~HaarCascade(){} }; +#endif + cv::Size operator -(const cv::Size& a, const cv::Size& b) { return cv::Size(a.width - b.width, a.height - b.height); @@ -340,7 +372,7 @@ struct PyrLavel cv::Size sWindow; }; -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { namespace lbp { @@ -405,7 +437,7 @@ public: GpuMat dclassified(1, 1, CV_32S); cudaSafeCall( cudaMemcpy(dclassified.ptr(), &classified, sizeof(int), cudaMemcpyHostToDevice) ); - PyrLavel level(0, 1.0f, image.size(), NxM, minObjectSize); + PyrLavel level(0, scaleFactor, image.size(), NxM, minObjectSize); while (level.isFeasible(maxObjectSize)) { @@ -425,8 +457,8 @@ public: GpuMat buff = integralBuffer; // generate integral for scale - gpu::resize(image, src, level.sFrame, 0, 0, CV_INTER_LINEAR); - gpu::integralBuffered(src, sint, buff); + gpu::resize(image, src, level.sFrame, 0, 0, cv::INTER_LINEAR); + gpu::integral(src, sint, buff); // calculate job int totalWidth = level.workArea.width / step; @@ -441,7 +473,7 @@ public: acc += level.sFrame.width + 1; } - device::lbp::classifyPyramid(image.cols, image.rows, NxM.width - 1, NxM.height - 1, iniScale, scaleFactor, total, stage_mat, stage_mat.cols / sizeof(Stage), nodes_mat, + cudev::lbp::classifyPyramid(image.cols, image.rows, NxM.width - 1, NxM.height - 1, iniScale, scaleFactor, total, stage_mat, stage_mat.cols / sizeof(Stage), nodes_mat, leaves_mat, subsets_mat, features_mat, subsetSize, candidates, dclassified.ptr(), integral); } @@ -449,7 +481,7 @@ public: return 0; cudaSafeCall( cudaMemcpy(&classified, dclassified.ptr(), sizeof(int), cudaMemcpyDeviceToHost) ); - device::lbp::connectedConmonents(candidates, classified, objects, groupThreshold, grouping_eps, dclassified.ptr()); + cudev::lbp::connectedConmonents(candidates, classified, objects, groupThreshold, grouping_eps, dclassified.ptr()); cudaSafeCall( cudaMemcpy(&classified, dclassified.ptr(), sizeof(int), cudaMemcpyDeviceToHost) ); cudaSafeCall( cudaDeviceSynchronize() ); @@ -458,7 +490,7 @@ public: virtual cv::Size getClassifierCvSize() const { return NxM; } - bool read(const std::string& classifierAsXml) + bool read(const String& classifierAsXml) { FileStorage fs(classifierAsXml, FileStorage::READ); return fs.isOpened() ? read(fs.getFirstTopLevelNode()) : false; @@ -476,6 +508,8 @@ private: resuzeBuffer.create(frame, CV_8UC1); integral.create(frame.height + 1, integralFactor * (frame.width + 1), CV_32SC1); + +#ifdef HAVE_OPENCV_GPULEGACY NcvSize32u roiSize; roiSize.width = frame.width; roiSize.height = frame.height; @@ -486,6 +520,7 @@ private: Ncv32u bufSize; ncvSafeCall( nppiStIntegralGetSize_8u32u(roiSize, &bufSize, prop) ); integralBuffer.create(1, bufSize, CV_8UC1); +#endif candidates.create(1 , frame.width >> 1, CV_32SC4); } @@ -512,10 +547,10 @@ private: const char *GPU_CC_FEATURES = "features"; const char *GPU_CC_RECT = "rect"; - std::string stageTypeStr = (std::string)root[GPU_CC_STAGE_TYPE]; + String stageTypeStr = (String)root[GPU_CC_STAGE_TYPE]; CV_Assert(stageTypeStr == GPU_CC_BOOST); - std::string featureTypeStr = (std::string)root[GPU_CC_FEATURE_TYPE]; + String featureTypeStr = (String)root[GPU_CC_FEATURE_TYPE]; CV_Assert(featureTypeStr == GPU_CC_LBP); NxM.width = (int)root[GPU_CC_WIDTH]; @@ -662,7 +697,7 @@ private: cv::gpu::CascadeClassifier_GPU::CascadeClassifier_GPU() : findLargestObject(false), visualizeInPlace(false), impl(0) {} -cv::gpu::CascadeClassifier_GPU::CascadeClassifier_GPU(const std::string& filename) +cv::gpu::CascadeClassifier_GPU::CascadeClassifier_GPU(const String& filename) : findLargestObject(false), visualizeInPlace(false), impl(0) { load(filename); } cv::gpu::CascadeClassifier_GPU::~CascadeClassifier_GPU() { release(); } @@ -688,12 +723,12 @@ int cv::gpu::CascadeClassifier_GPU::detectMultiScale(const GpuMat& image, GpuMat return impl->process(image, objectsBuf, (float)scaleFactor, minNeighbors, findLargestObject, visualizeInPlace, minSize, maxObjectSize); } -bool cv::gpu::CascadeClassifier_GPU::load(const std::string& filename) +bool cv::gpu::CascadeClassifier_GPU::load(const String& filename) { release(); - std::string fext = filename.substr(filename.find_last_of(".") + 1); - std::transform(fext.begin(), fext.end(), fext.begin(), ::tolower); + String fext = filename.substr(filename.find_last_of(".") + 1); + fext = fext.toLowerCase(); if (fext == "nvbin") { @@ -710,7 +745,7 @@ bool cv::gpu::CascadeClassifier_GPU::load(const std::string& filename) } const char *GPU_CC_LBP = "LBP"; - std::string featureTypeStr = (std::string)fs.getFirstTopLevelNode()["featureType"]; + String featureTypeStr = (String)fs.getFirstTopLevelNode()["featureType"]; if (featureTypeStr == GPU_CC_LBP) impl = new LbpCascade(); else @@ -721,240 +756,3 @@ bool cv::gpu::CascadeClassifier_GPU::load(const std::string& filename) } #endif - -////////////////////////////////////////////////////////////////////////////////////////////////////// - -#if defined (HAVE_CUDA) - -struct RectConvert -{ - Rect operator()(const NcvRect32u& nr) const { return Rect(nr.x, nr.y, nr.width, nr.height); } - NcvRect32u operator()(const Rect& nr) const - { - NcvRect32u rect; - rect.x = nr.x; - rect.y = nr.y; - rect.width = nr.width; - rect.height = nr.height; - return rect; - } -}; - -void groupRectangles(std::vector &hypotheses, int groupThreshold, double eps, std::vector *weights) -{ - std::vector rects(hypotheses.size()); - std::transform(hypotheses.begin(), hypotheses.end(), rects.begin(), RectConvert()); - - if (weights) - { - std::vector weights_int; - weights_int.assign(weights->begin(), weights->end()); - cv::groupRectangles(rects, weights_int, groupThreshold, eps); - } - else - { - cv::groupRectangles(rects, groupThreshold, eps); - } - std::transform(rects.begin(), rects.end(), hypotheses.begin(), RectConvert()); - hypotheses.resize(rects.size()); -} - -NCVStatus loadFromXML(const std::string &filename, - HaarClassifierCascadeDescriptor &haar, - std::vector &haarStages, - std::vector &haarClassifierNodes, - std::vector &haarFeatures) -{ - NCVStatus ncvStat; - - haar.NumStages = 0; - haar.NumClassifierRootNodes = 0; - haar.NumClassifierTotalNodes = 0; - haar.NumFeatures = 0; - haar.ClassifierSize.width = 0; - haar.ClassifierSize.height = 0; - haar.bHasStumpsOnly = true; - haar.bNeedsTiltedII = false; - Ncv32u curMaxTreeDepth; - - std::vector xmlFileCont; - - std::vector h_TmpClassifierNotRootNodes; - haarStages.resize(0); - haarClassifierNodes.resize(0); - haarFeatures.resize(0); - - Ptr oldCascade = (CvHaarClassifierCascade*)cvLoad(filename.c_str(), 0, 0, 0); - if (oldCascade.empty()) - { - return NCV_HAAR_XML_LOADING_EXCEPTION; - } - - haar.ClassifierSize.width = oldCascade->orig_window_size.width; - haar.ClassifierSize.height = oldCascade->orig_window_size.height; - - int stagesCound = oldCascade->count; - for(int s = 0; s < stagesCound; ++s) // by stages - { - HaarStage64 curStage; - curStage.setStartClassifierRootNodeOffset(static_cast(haarClassifierNodes.size())); - - curStage.setStageThreshold(oldCascade->stage_classifier[s].threshold); - - int treesCount = oldCascade->stage_classifier[s].count; - for(int t = 0; t < treesCount; ++t) // by trees - { - Ncv32u nodeId = 0; - CvHaarClassifier* tree = &oldCascade->stage_classifier[s].classifier[t]; - - int nodesCount = tree->count; - for(int n = 0; n < nodesCount; ++n) //by features - { - CvHaarFeature* feature = &tree->haar_feature[n]; - - HaarClassifierNode128 curNode; - curNode.setThreshold(tree->threshold[n]); - - NcvBool bIsLeftNodeLeaf = false; - NcvBool bIsRightNodeLeaf = false; - - HaarClassifierNodeDescriptor32 nodeLeft; - if ( tree->left[n] <= 0 ) - { - Ncv32f leftVal = tree->alpha[-tree->left[n]]; - ncvStat = nodeLeft.create(leftVal); - ncvAssertReturn(ncvStat == NCV_SUCCESS, ncvStat); - bIsLeftNodeLeaf = true; - } - else - { - Ncv32u leftNodeOffset = tree->left[n]; - nodeLeft.create((Ncv32u)(h_TmpClassifierNotRootNodes.size() + leftNodeOffset - 1)); - haar.bHasStumpsOnly = false; - } - curNode.setLeftNodeDesc(nodeLeft); - - HaarClassifierNodeDescriptor32 nodeRight; - if ( tree->right[n] <= 0 ) - { - Ncv32f rightVal = tree->alpha[-tree->right[n]]; - ncvStat = nodeRight.create(rightVal); - ncvAssertReturn(ncvStat == NCV_SUCCESS, ncvStat); - bIsRightNodeLeaf = true; - } - else - { - Ncv32u rightNodeOffset = tree->right[n]; - nodeRight.create((Ncv32u)(h_TmpClassifierNotRootNodes.size() + rightNodeOffset - 1)); - haar.bHasStumpsOnly = false; - } - curNode.setRightNodeDesc(nodeRight); - - Ncv32u tiltedVal = feature->tilted; - haar.bNeedsTiltedII = (tiltedVal != 0); - - Ncv32u featureId = 0; - for(int l = 0; l < CV_HAAR_FEATURE_MAX; ++l) //by rects - { - Ncv32u rectX = feature->rect[l].r.x; - Ncv32u rectY = feature->rect[l].r.y; - Ncv32u rectWidth = feature->rect[l].r.width; - Ncv32u rectHeight = feature->rect[l].r.height; - - Ncv32f rectWeight = feature->rect[l].weight; - - if (rectWeight == 0/* && rectX == 0 &&rectY == 0 && rectWidth == 0 && rectHeight == 0*/) - break; - - HaarFeature64 curFeature; - ncvStat = curFeature.setRect(rectX, rectY, rectWidth, rectHeight, haar.ClassifierSize.width, haar.ClassifierSize.height); - curFeature.setWeight(rectWeight); - ncvAssertReturn(NCV_SUCCESS == ncvStat, ncvStat); - haarFeatures.push_back(curFeature); - - featureId++; - } - - HaarFeatureDescriptor32 tmpFeatureDesc; - ncvStat = tmpFeatureDesc.create(haar.bNeedsTiltedII, bIsLeftNodeLeaf, bIsRightNodeLeaf, - featureId, static_cast(haarFeatures.size()) - featureId); - ncvAssertReturn(NCV_SUCCESS == ncvStat, ncvStat); - curNode.setFeatureDesc(tmpFeatureDesc); - - if (!nodeId) - { - //root node - haarClassifierNodes.push_back(curNode); - curMaxTreeDepth = 1; - } - else - { - //other node - h_TmpClassifierNotRootNodes.push_back(curNode); - curMaxTreeDepth++; - } - - nodeId++; - } - } - - curStage.setNumClassifierRootNodes(treesCount); - haarStages.push_back(curStage); - } - - //fill in cascade stats - haar.NumStages = static_cast(haarStages.size()); - haar.NumClassifierRootNodes = static_cast(haarClassifierNodes.size()); - haar.NumClassifierTotalNodes = static_cast(haar.NumClassifierRootNodes + h_TmpClassifierNotRootNodes.size()); - haar.NumFeatures = static_cast(haarFeatures.size()); - - //merge root and leaf nodes in one classifiers array - Ncv32u offsetRoot = static_cast(haarClassifierNodes.size()); - for (Ncv32u i=0; i - void Bayer2BGR_8u_gpu(PtrStepSzb src, PtrStepSzb dst, bool blue_last, bool start_with_green, cudaStream_t stream); - template - void Bayer2BGR_16u_gpu(PtrStepSzb src, PtrStepSzb dst, bool blue_last, bool start_with_green, cudaStream_t stream); - } -}} - -using namespace ::cv::gpu::device; - -namespace -{ - typedef void (*gpu_func_t)(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - - void bgr_to_rgb(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[] = {bgr_to_rgb_8u, 0, bgr_to_rgb_16u, 0, 0, bgr_to_rgb_32f}; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), 3)); - - funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void bgr_to_bgra(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[] = {bgr_to_bgra_8u, 0, bgr_to_bgra_16u, 0, 0, bgr_to_bgra_32f}; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), 4)); - - funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void bgr_to_rgba(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[] = {bgr_to_rgba_8u, 0, bgr_to_rgba_16u, 0, 0, bgr_to_rgba_32f}; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), 4)); - - funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void bgra_to_bgr(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[] = {bgra_to_bgr_8u, 0, bgra_to_bgr_16u, 0, 0, bgra_to_bgr_32f}; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), 3)); - - funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void bgra_to_rgb(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[] = {bgra_to_rgb_8u, 0, bgra_to_rgb_16u, 0, 0, bgra_to_rgb_32f}; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), 3)); - - funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void bgra_to_rgba(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[] = {bgra_to_rgba_8u, 0, bgra_to_rgba_16u, 0, 0, bgra_to_rgba_32f}; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), 4)); - - funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void bgr_to_bgr555(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 3); - - dst.create(src.size(), CV_8UC2); - - device::bgr_to_bgr555(src, dst, StreamAccessor::getStream(stream)); - } - - void bgr_to_bgr565(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 3); - - dst.create(src.size(), CV_8UC2); - - device::bgr_to_bgr565(src, dst, StreamAccessor::getStream(stream)); - } - - void rgb_to_bgr555(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 3); - - dst.create(src.size(), CV_8UC2); - - device::rgb_to_bgr555(src, dst, StreamAccessor::getStream(stream)); - } - - void rgb_to_bgr565(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 3); - - dst.create(src.size(), CV_8UC2); - - device::rgb_to_bgr565(src, dst, StreamAccessor::getStream(stream)); - } - - void bgra_to_bgr555(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 4); - - dst.create(src.size(), CV_8UC2); - - device::bgra_to_bgr555(src, dst, StreamAccessor::getStream(stream)); - } - - void bgra_to_bgr565(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 4); - - dst.create(src.size(), CV_8UC2); - - device::bgra_to_bgr565(src, dst, StreamAccessor::getStream(stream)); - } - - void rgba_to_bgr555(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 4); - - dst.create(src.size(), CV_8UC2); - - device::rgba_to_bgr555(src, dst, StreamAccessor::getStream(stream)); - } - - void rgba_to_bgr565(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 4); - - dst.create(src.size(), CV_8UC2); - - device::rgba_to_bgr565(src, dst, StreamAccessor::getStream(stream)); - } - - void bgr555_to_rgb(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); - - dst.create(src.size(), CV_8UC3); - - device::bgr555_to_rgb(src, dst, StreamAccessor::getStream(stream)); - } - - void bgr565_to_rgb(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); - - dst.create(src.size(), CV_8UC3); - - device::bgr565_to_rgb(src, dst, StreamAccessor::getStream(stream)); - } - - void bgr555_to_bgr(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); - - dst.create(src.size(), CV_8UC3); - - device::bgr555_to_bgr(src, dst, StreamAccessor::getStream(stream)); - } - - void bgr565_to_bgr(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); - - dst.create(src.size(), CV_8UC3); - - device::bgr565_to_bgr(src, dst, StreamAccessor::getStream(stream)); - } - - void bgr555_to_rgba(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); - - dst.create(src.size(), CV_8UC4); - - device::bgr555_to_rgba(src, dst, StreamAccessor::getStream(stream)); - } - - void bgr565_to_rgba(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); - - dst.create(src.size(), CV_8UC4); - - device::bgr565_to_rgba(src, dst, StreamAccessor::getStream(stream)); - } - - void bgr555_to_bgra(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); - - dst.create(src.size(), CV_8UC4); - - device::bgr555_to_bgra(src, dst, StreamAccessor::getStream(stream)); - } - - void bgr565_to_bgra(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); - - dst.create(src.size(), CV_8UC4); - - device::bgr565_to_bgra(src, dst, StreamAccessor::getStream(stream)); - } - - void gray_to_bgr(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[] = {gray_to_bgr_8u, 0, gray_to_bgr_16u, 0, 0, gray_to_bgr_32f}; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 1); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), 3)); - - funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void gray_to_bgra(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[] = {gray_to_bgra_8u, 0, gray_to_bgra_16u, 0, 0, gray_to_bgra_32f}; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 1); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), 4)); - - funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void gray_to_bgr555(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 1); - - dst.create(src.size(), CV_8UC2); - - device::gray_to_bgr555(src, dst, StreamAccessor::getStream(stream)); - } - - void gray_to_bgr565(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 1); - - dst.create(src.size(), CV_8UC2); - - device::gray_to_bgr565(src, dst, StreamAccessor::getStream(stream)); - } - - void bgr555_to_gray(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); - - dst.create(src.size(), CV_8UC1); - - device::bgr555_to_gray(src, dst, StreamAccessor::getStream(stream)); - } - - void bgr565_to_gray(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); - - dst.create(src.size(), CV_8UC1); - - device::bgr565_to_gray(src, dst, StreamAccessor::getStream(stream)); - } - - void rgb_to_gray(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[] = {rgb_to_gray_8u, 0, rgb_to_gray_16u, 0, 0, rgb_to_gray_32f}; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), 1)); - - funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void bgr_to_gray(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[] = {bgr_to_gray_8u, 0, bgr_to_gray_16u, 0, 0, bgr_to_gray_32f}; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), 1)); - - funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void rgba_to_gray(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[] = {rgba_to_gray_8u, 0, rgba_to_gray_16u, 0, 0, rgba_to_gray_32f}; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), 1)); - - funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void bgra_to_gray(const GpuMat& src, GpuMat& dst, int, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[] = {bgra_to_gray_8u, 0, bgra_to_gray_16u, 0, 0, bgra_to_gray_32f}; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), 1)); - - funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void rgb_to_yuv(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {rgb_to_yuv_8u, 0, rgb_to_yuv_16u, 0, 0, rgb_to_yuv_32f}, - {rgba_to_yuv_8u, 0, rgba_to_yuv_16u, 0, 0, rgba_to_yuv_32f} - }, - { - {rgb_to_yuv4_8u, 0, rgb_to_yuv4_16u, 0, 0, rgb_to_yuv4_32f}, - {rgba_to_yuv4_8u, 0, rgba_to_yuv4_16u, 0, 0, rgba_to_yuv4_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void bgr_to_yuv(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {bgr_to_yuv_8u, 0, bgr_to_yuv_16u, 0, 0, bgr_to_yuv_32f}, - {bgra_to_yuv_8u, 0, bgra_to_yuv_16u, 0, 0, bgra_to_yuv_32f} - }, - { - {bgr_to_yuv4_8u, 0, bgr_to_yuv4_16u, 0, 0, bgr_to_yuv4_32f}, - {bgra_to_yuv4_8u, 0, bgra_to_yuv4_16u, 0, 0, bgra_to_yuv4_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void yuv_to_rgb(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {yuv_to_rgb_8u, 0, yuv_to_rgb_16u, 0, 0, yuv_to_rgb_32f}, - {yuv4_to_rgb_8u, 0, yuv4_to_rgb_16u, 0, 0, yuv4_to_rgb_32f} - }, - { - {yuv_to_rgba_8u, 0, yuv_to_rgba_16u, 0, 0, yuv_to_rgba_32f}, - {yuv4_to_rgba_8u, 0, yuv4_to_rgba_16u, 0, 0, yuv4_to_rgba_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void yuv_to_bgr(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {yuv_to_bgr_8u, 0, yuv_to_bgr_16u, 0, 0, yuv_to_bgr_32f}, - {yuv4_to_bgr_8u, 0, yuv4_to_bgr_16u, 0, 0, yuv4_to_bgr_32f} - }, - { - {yuv_to_bgra_8u, 0, yuv_to_bgra_16u, 0, 0, yuv_to_bgra_32f}, - {yuv4_to_bgra_8u, 0, yuv4_to_bgra_16u, 0, 0, yuv4_to_bgra_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void rgb_to_YCrCb(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {rgb_to_YCrCb_8u, 0, rgb_to_YCrCb_16u, 0, 0, rgb_to_YCrCb_32f}, - {rgba_to_YCrCb_8u, 0, rgba_to_YCrCb_16u, 0, 0, rgba_to_YCrCb_32f} - }, - { - {rgb_to_YCrCb4_8u, 0, rgb_to_YCrCb4_16u, 0, 0, rgb_to_YCrCb4_32f}, - {rgba_to_YCrCb4_8u, 0, rgba_to_YCrCb4_16u, 0, 0, rgba_to_YCrCb4_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void bgr_to_YCrCb(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {bgr_to_YCrCb_8u, 0, bgr_to_YCrCb_16u, 0, 0, bgr_to_YCrCb_32f}, - {bgra_to_YCrCb_8u, 0, bgra_to_YCrCb_16u, 0, 0, bgra_to_YCrCb_32f} - }, - { - {bgr_to_YCrCb4_8u, 0, bgr_to_YCrCb4_16u, 0, 0, bgr_to_YCrCb4_32f}, - {bgra_to_YCrCb4_8u, 0, bgra_to_YCrCb4_16u, 0, 0, bgra_to_YCrCb4_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void YCrCb_to_rgb(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {YCrCb_to_rgb_8u, 0, YCrCb_to_rgb_16u, 0, 0, YCrCb_to_rgb_32f}, - {YCrCb4_to_rgb_8u, 0, YCrCb4_to_rgb_16u, 0, 0, YCrCb4_to_rgb_32f} - }, - { - {YCrCb_to_rgba_8u, 0, YCrCb_to_rgba_16u, 0, 0, YCrCb_to_rgba_32f}, - {YCrCb4_to_rgba_8u, 0, YCrCb4_to_rgba_16u, 0, 0, YCrCb4_to_rgba_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void YCrCb_to_bgr(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {YCrCb_to_bgr_8u, 0, YCrCb_to_bgr_16u, 0, 0, YCrCb_to_bgr_32f}, - {YCrCb4_to_bgr_8u, 0, YCrCb4_to_bgr_16u, 0, 0, YCrCb4_to_bgr_32f} - }, - { - {YCrCb_to_bgra_8u, 0, YCrCb_to_bgra_16u, 0, 0, YCrCb_to_bgra_32f}, - {YCrCb4_to_bgra_8u, 0, YCrCb4_to_bgra_16u, 0, 0, YCrCb4_to_bgra_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void rgb_to_xyz(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {rgb_to_xyz_8u, 0, rgb_to_xyz_16u, 0, 0, rgb_to_xyz_32f}, - {rgba_to_xyz_8u, 0, rgba_to_xyz_16u, 0, 0, rgba_to_xyz_32f} - }, - { - {rgb_to_xyz4_8u, 0, rgb_to_xyz4_16u, 0, 0, rgb_to_xyz4_32f}, - {rgba_to_xyz4_8u, 0, rgba_to_xyz4_16u, 0, 0, rgba_to_xyz4_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void bgr_to_xyz(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {bgr_to_xyz_8u, 0, bgr_to_xyz_16u, 0, 0, bgr_to_xyz_32f}, - {bgra_to_xyz_8u, 0, bgra_to_xyz_16u, 0, 0, bgra_to_xyz_32f} - }, - { - {bgr_to_xyz4_8u, 0, bgr_to_xyz4_16u, 0, 0, bgr_to_xyz4_32f}, - {bgra_to_xyz4_8u, 0, bgra_to_xyz4_16u, 0, 0, bgra_to_xyz4_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void xyz_to_rgb(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {xyz_to_rgb_8u, 0, xyz_to_rgb_16u, 0, 0, xyz_to_rgb_32f}, - {xyz4_to_rgb_8u, 0, xyz4_to_rgb_16u, 0, 0, xyz4_to_rgb_32f} - }, - { - {xyz_to_rgba_8u, 0, xyz_to_rgba_16u, 0, 0, xyz_to_rgba_32f}, - {xyz4_to_rgba_8u, 0, xyz4_to_rgba_16u, 0, 0, xyz4_to_rgba_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void xyz_to_bgr(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {xyz_to_bgr_8u, 0, xyz_to_bgr_16u, 0, 0, xyz_to_bgr_32f}, - {xyz4_to_bgr_8u, 0, xyz4_to_bgr_16u, 0, 0, xyz4_to_bgr_32f} - }, - { - {xyz_to_bgra_8u, 0, xyz_to_bgra_16u, 0, 0, xyz_to_bgra_32f}, - {xyz4_to_bgra_8u, 0, xyz4_to_bgra_16u, 0, 0, xyz4_to_bgra_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void rgb_to_hsv(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {rgb_to_hsv_8u, 0, 0, 0, 0, rgb_to_hsv_32f}, - {rgba_to_hsv_8u, 0, 0, 0, 0, rgba_to_hsv_32f}, - }, - { - {rgb_to_hsv4_8u, 0, 0, 0, 0, rgb_to_hsv4_32f}, - {rgba_to_hsv4_8u, 0, 0, 0, 0, rgba_to_hsv4_32f}, - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void bgr_to_hsv(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {bgr_to_hsv_8u, 0, 0, 0, 0, bgr_to_hsv_32f}, - {bgra_to_hsv_8u, 0, 0, 0, 0, bgra_to_hsv_32f} - }, - { - {bgr_to_hsv4_8u, 0, 0, 0, 0, bgr_to_hsv4_32f}, - {bgra_to_hsv4_8u, 0, 0, 0, 0, bgra_to_hsv4_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void hsv_to_rgb(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {hsv_to_rgb_8u, 0, 0, 0, 0, hsv_to_rgb_32f}, - {hsv4_to_rgb_8u, 0, 0, 0, 0, hsv4_to_rgb_32f} - }, - { - {hsv_to_rgba_8u, 0, 0, 0, 0, hsv_to_rgba_32f}, - {hsv4_to_rgba_8u, 0, 0, 0, 0, hsv4_to_rgba_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void hsv_to_bgr(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {hsv_to_bgr_8u, 0, 0, 0, 0, hsv_to_bgr_32f}, - {hsv4_to_bgr_8u, 0, 0, 0, 0, hsv4_to_bgr_32f} - }, - { - {hsv_to_bgra_8u, 0, 0, 0, 0, hsv_to_bgra_32f}, - {hsv4_to_bgra_8u, 0, 0, 0, 0, hsv4_to_bgra_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void rgb_to_hls(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {rgb_to_hls_8u, 0, 0, 0, 0, rgb_to_hls_32f}, - {rgba_to_hls_8u, 0, 0, 0, 0, rgba_to_hls_32f}, - }, - { - {rgb_to_hls4_8u, 0, 0, 0, 0, rgb_to_hls4_32f}, - {rgba_to_hls4_8u, 0, 0, 0, 0, rgba_to_hls4_32f}, - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void bgr_to_hls(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {bgr_to_hls_8u, 0, 0, 0, 0, bgr_to_hls_32f}, - {bgra_to_hls_8u, 0, 0, 0, 0, bgra_to_hls_32f} - }, - { - {bgr_to_hls4_8u, 0, 0, 0, 0, bgr_to_hls4_32f}, - {bgra_to_hls4_8u, 0, 0, 0, 0, bgra_to_hls4_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void hls_to_rgb(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {hls_to_rgb_8u, 0, 0, 0, 0, hls_to_rgb_32f}, - {hls4_to_rgb_8u, 0, 0, 0, 0, hls4_to_rgb_32f} - }, - { - {hls_to_rgba_8u, 0, 0, 0, 0, hls_to_rgba_32f}, - {hls4_to_rgba_8u, 0, 0, 0, 0, hls4_to_rgba_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void hls_to_bgr(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {hls_to_bgr_8u, 0, 0, 0, 0, hls_to_bgr_32f}, - {hls4_to_bgr_8u, 0, 0, 0, 0, hls4_to_bgr_32f} - }, - { - {hls_to_bgra_8u, 0, 0, 0, 0, hls_to_bgra_32f}, - {hls4_to_bgra_8u, 0, 0, 0, 0, hls4_to_bgra_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void rgb_to_hsv_full(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {rgb_to_hsv_full_8u, 0, 0, 0, 0, rgb_to_hsv_full_32f}, - {rgba_to_hsv_full_8u, 0, 0, 0, 0, rgba_to_hsv_full_32f}, - }, - { - {rgb_to_hsv4_full_8u, 0, 0, 0, 0, rgb_to_hsv4_full_32f}, - {rgba_to_hsv4_full_8u, 0, 0, 0, 0, rgba_to_hsv4_full_32f}, - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void bgr_to_hsv_full(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {bgr_to_hsv_full_8u, 0, 0, 0, 0, bgr_to_hsv_full_32f}, - {bgra_to_hsv_full_8u, 0, 0, 0, 0, bgra_to_hsv_full_32f} - }, - { - {bgr_to_hsv4_full_8u, 0, 0, 0, 0, bgr_to_hsv4_full_32f}, - {bgra_to_hsv4_full_8u, 0, 0, 0, 0, bgra_to_hsv4_full_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void hsv_to_rgb_full(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {hsv_to_rgb_full_8u, 0, 0, 0, 0, hsv_to_rgb_full_32f}, - {hsv4_to_rgb_full_8u, 0, 0, 0, 0, hsv4_to_rgb_full_32f} - }, - { - {hsv_to_rgba_full_8u, 0, 0, 0, 0, hsv_to_rgba_full_32f}, - {hsv4_to_rgba_full_8u, 0, 0, 0, 0, hsv4_to_rgba_full_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void hsv_to_bgr_full(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {hsv_to_bgr_full_8u, 0, 0, 0, 0, hsv_to_bgr_full_32f}, - {hsv4_to_bgr_full_8u, 0, 0, 0, 0, hsv4_to_bgr_full_32f} - }, - { - {hsv_to_bgra_full_8u, 0, 0, 0, 0, hsv_to_bgra_full_32f}, - {hsv4_to_bgra_full_8u, 0, 0, 0, 0, hsv4_to_bgra_full_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void rgb_to_hls_full(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {rgb_to_hls_full_8u, 0, 0, 0, 0, rgb_to_hls_full_32f}, - {rgba_to_hls_full_8u, 0, 0, 0, 0, rgba_to_hls_full_32f}, - }, - { - {rgb_to_hls4_full_8u, 0, 0, 0, 0, rgb_to_hls4_full_32f}, - {rgba_to_hls4_full_8u, 0, 0, 0, 0, rgba_to_hls4_full_32f}, - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void bgr_to_hls_full(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {bgr_to_hls_full_8u, 0, 0, 0, 0, bgr_to_hls_full_32f}, - {bgra_to_hls_full_8u, 0, 0, 0, 0, bgra_to_hls_full_32f} - }, - { - {bgr_to_hls4_full_8u, 0, 0, 0, 0, bgr_to_hls4_full_32f}, - {bgra_to_hls4_full_8u, 0, 0, 0, 0, bgra_to_hls4_full_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void hls_to_rgb_full(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {hls_to_rgb_full_8u, 0, 0, 0, 0, hls_to_rgb_full_32f}, - {hls4_to_rgb_full_8u, 0, 0, 0, 0, hls4_to_rgb_full_32f} - }, - { - {hls_to_rgba_full_8u, 0, 0, 0, 0, hls_to_rgba_full_32f}, - {hls4_to_rgba_full_8u, 0, 0, 0, 0, hls4_to_rgba_full_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void hls_to_bgr_full(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][6] = - { - { - {hls_to_bgr_full_8u, 0, 0, 0, 0, hls_to_bgr_full_32f}, - {hls4_to_bgr_full_8u, 0, 0, 0, 0, hls4_to_bgr_full_32f} - }, - { - {hls_to_bgra_full_8u, 0, 0, 0, 0, hls_to_bgra_full_32f}, - {hls4_to_bgra_full_8u, 0, 0, 0, 0, hls4_to_bgra_full_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth()](src, dst, StreamAccessor::getStream(stream)); - } - - void bgr_to_lab(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][2] = - { - { - {bgr_to_lab_8u, bgr_to_lab_32f}, - {bgra_to_lab_8u, bgra_to_lab_32f} - }, - { - {bgr_to_lab4_8u, bgr_to_lab4_32f}, - {bgra_to_lab4_8u, bgra_to_lab4_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth() == CV_32F](src, dst, StreamAccessor::getStream(stream)); - } - - void rgb_to_lab(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][2] = - { - { - {rgb_to_lab_8u, rgb_to_lab_32f}, - {rgba_to_lab_8u, rgba_to_lab_32f} - }, - { - {rgb_to_lab4_8u, rgb_to_lab4_32f}, - {rgba_to_lab4_8u, rgba_to_lab4_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth() == CV_32F](src, dst, StreamAccessor::getStream(stream)); - } - - void lbgr_to_lab(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][2] = - { - { - {lbgr_to_lab_8u, lbgr_to_lab_32f}, - {lbgra_to_lab_8u, lbgra_to_lab_32f} - }, - { - {lbgr_to_lab4_8u, lbgr_to_lab4_32f}, - {lbgra_to_lab4_8u, lbgra_to_lab4_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth() == CV_32F](src, dst, StreamAccessor::getStream(stream)); - } - - void lrgb_to_lab(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][2] = - { - { - {lrgb_to_lab_8u, lrgb_to_lab_32f}, - {lrgba_to_lab_8u, lrgba_to_lab_32f} - }, - { - {lrgb_to_lab4_8u, lrgb_to_lab4_32f}, - {lrgba_to_lab4_8u, lrgba_to_lab4_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth() == CV_32F](src, dst, StreamAccessor::getStream(stream)); - } - - void lab_to_bgr(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][2] = - { - { - {lab_to_bgr_8u, lab_to_bgr_32f}, - {lab4_to_bgr_8u, lab4_to_bgr_32f} - }, - { - {lab_to_bgra_8u, lab_to_bgra_32f}, - {lab4_to_bgra_8u, lab4_to_bgra_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth() == CV_32F](src, dst, StreamAccessor::getStream(stream)); - } - - void lab_to_rgb(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][2] = - { - { - {lab_to_rgb_8u, lab_to_rgb_32f}, - {lab4_to_rgb_8u, lab4_to_rgb_32f} - }, - { - {lab_to_rgba_8u, lab_to_rgba_32f}, - {lab4_to_rgba_8u, lab4_to_rgba_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth() == CV_32F](src, dst, StreamAccessor::getStream(stream)); - } - - void lab_to_lbgr(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][2] = - { - { - {lab_to_lbgr_8u, lab_to_lbgr_32f}, - {lab4_to_lbgr_8u, lab4_to_lbgr_32f} - }, - { - {lab_to_lbgra_8u, lab_to_lbgra_32f}, - {lab4_to_lbgra_8u, lab4_to_lbgra_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth() == CV_32F](src, dst, StreamAccessor::getStream(stream)); - } - - void lab_to_lrgb(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][2] = - { - { - {lab_to_lrgb_8u, lab_to_lrgb_32f}, - {lab4_to_lrgb_8u, lab4_to_lrgb_32f} - }, - { - {lab_to_lrgba_8u, lab_to_lrgba_32f}, - {lab4_to_lrgba_8u, lab4_to_lrgba_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth() == CV_32F](src, dst, StreamAccessor::getStream(stream)); - } - - void bgr_to_luv(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][2] = - { - { - {bgr_to_luv_8u, bgr_to_luv_32f}, - {bgra_to_luv_8u, bgra_to_luv_32f} - }, - { - {bgr_to_luv4_8u, bgr_to_luv4_32f}, - {bgra_to_luv4_8u, bgra_to_luv4_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth() == CV_32F](src, dst, StreamAccessor::getStream(stream)); - } - - void rgb_to_luv(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][2] = - { - { - {rgb_to_luv_8u, rgb_to_luv_32f}, - {rgba_to_luv_8u, rgba_to_luv_32f} - }, - { - {rgb_to_luv4_8u, rgb_to_luv4_32f}, - {rgba_to_luv4_8u, rgba_to_luv4_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth() == CV_32F](src, dst, StreamAccessor::getStream(stream)); - } - - void lbgr_to_luv(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][2] = - { - { - {lbgr_to_luv_8u, lbgr_to_luv_32f}, - {lbgra_to_luv_8u, lbgra_to_luv_32f} - }, - { - {lbgr_to_luv4_8u, lbgr_to_luv4_32f}, - {lbgra_to_luv4_8u, lbgra_to_luv4_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth() == CV_32F](src, dst, StreamAccessor::getStream(stream)); - } - - void lrgb_to_luv(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][2] = - { - { - {lrgb_to_luv_8u, lrgb_to_luv_32f}, - {lrgba_to_luv_8u, lrgba_to_luv_32f} - }, - { - {lrgb_to_luv4_8u, lrgb_to_luv4_32f}, - {lrgba_to_luv4_8u, lrgba_to_luv4_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth() == CV_32F](src, dst, StreamAccessor::getStream(stream)); - } - - void luv_to_bgr(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][2] = - { - { - {luv_to_bgr_8u, luv_to_bgr_32f}, - {luv4_to_bgr_8u, luv4_to_bgr_32f} - }, - { - {luv_to_bgra_8u, luv_to_bgra_32f}, - {luv4_to_bgra_8u, luv4_to_bgra_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth() == CV_32F](src, dst, StreamAccessor::getStream(stream)); - } - - void luv_to_rgb(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][2] = - { - { - {luv_to_rgb_8u, luv_to_rgb_32f}, - {luv4_to_rgb_8u, luv4_to_rgb_32f} - }, - { - {luv_to_rgba_8u, luv_to_rgba_32f}, - {luv4_to_rgba_8u, luv4_to_rgba_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth() == CV_32F](src, dst, StreamAccessor::getStream(stream)); - } - - void luv_to_lbgr(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][2] = - { - { - {luv_to_lbgr_8u, luv_to_lbgr_32f}, - {luv4_to_lbgr_8u, luv4_to_lbgr_32f} - }, - { - {luv_to_lbgra_8u, luv_to_lbgra_32f}, - {luv4_to_lbgra_8u, luv4_to_lbgra_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth() == CV_32F](src, dst, StreamAccessor::getStream(stream)); - } - - void luv_to_lrgb(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - using namespace cv::gpu::device; - static const gpu_func_t funcs[2][2][2] = - { - { - {luv_to_lrgb_8u, luv_to_lrgb_32f}, - {luv4_to_lrgb_8u, luv4_to_lrgb_32f} - }, - { - {luv_to_lrgba_8u, luv_to_lrgba_32f}, - {luv4_to_lrgba_8u, luv4_to_lrgba_32f} - } - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.depth() == CV_8U || src.depth() == CV_32F); - CV_Assert(src.channels() == 3 || src.channels() == 4); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); - - funcs[dcn == 4][src.channels() == 4][src.depth() == CV_32F](src, dst, StreamAccessor::getStream(stream)); - } - - void rgba_to_mbgra(const GpuMat& src, GpuMat& dst, int, Stream& st) - { - #if (CUDA_VERSION < 5000) - (void)src; - (void)dst; - (void)st; - CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); - #else - CV_Assert(src.type() == CV_8UC4 || src.type() == CV_16UC4); - - dst.create(src.size(), src.type()); - - cudaStream_t stream = StreamAccessor::getStream(st); - NppStreamHandler h(stream); - - NppiSize oSizeROI; - oSizeROI.width = src.cols; - oSizeROI.height = src.rows; - - if (src.depth() == CV_8U) - nppSafeCall( nppiAlphaPremul_8u_AC4R(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), oSizeROI) ); - else - nppSafeCall( nppiAlphaPremul_16u_AC4R(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), oSizeROI) ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); - #endif - } - - void bayer_to_bgr(const GpuMat& src, GpuMat& dst, int dcn, bool blue_last, bool start_with_green, Stream& stream) - { - typedef void (*func_t)(PtrStepSzb src, PtrStepSzb dst, bool blue_last, bool start_with_green, cudaStream_t stream); - static const func_t funcs[3][4] = - { - {0,0,Bayer2BGR_8u_gpu<3>, Bayer2BGR_8u_gpu<4>}, - {0,0,0,0}, - {0,0,Bayer2BGR_16u_gpu<3>, Bayer2BGR_16u_gpu<4>} - }; - - if (dcn <= 0) dcn = 3; - - CV_Assert(src.type() == CV_8UC1 || src.type() == CV_16UC1); - CV_Assert(src.rows > 2 && src.cols > 2); - CV_Assert(dcn == 3 || dcn == 4); - - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); - - funcs[src.depth()][dcn - 1](src, dst, blue_last, start_with_green, StreamAccessor::getStream(stream)); - } - - void bayerBG_to_bgr(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - bayer_to_bgr(src, dst, dcn, false, false, stream); - } - - void bayerGB_to_bgr(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - bayer_to_bgr(src, dst, dcn, false, true, stream); - } - - void bayerRG_to_bgr(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - bayer_to_bgr(src, dst, dcn, true, false, stream); - } - - void bayerGR_to_bgr(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) - { - bayer_to_bgr(src, dst, dcn, true, true, stream); - } -} - -void cv::gpu::cvtColor(const GpuMat& src, GpuMat& dst, int code, int dcn, Stream& stream) -{ - typedef void (*func_t)(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream); - static const func_t funcs[] = - { - bgr_to_bgra, // CV_BGR2BGRA =0 - bgra_to_bgr, // CV_BGRA2BGR =1 - bgr_to_rgba, // CV_BGR2RGBA =2 - bgra_to_rgb, // CV_RGBA2BGR =3 - bgr_to_rgb, // CV_BGR2RGB =4 - bgra_to_rgba, // CV_BGRA2RGBA =5 - - bgr_to_gray, // CV_BGR2GRAY =6 - rgb_to_gray, // CV_RGB2GRAY =7 - gray_to_bgr, // CV_GRAY2BGR =8 - gray_to_bgra, // CV_GRAY2BGRA =9 - bgra_to_gray, // CV_BGRA2GRAY =10 - rgba_to_gray, // CV_RGBA2GRAY =11 - - bgr_to_bgr565, // CV_BGR2BGR565 =12 - rgb_to_bgr565, // CV_RGB2BGR565 =13 - bgr565_to_bgr, // CV_BGR5652BGR =14 - bgr565_to_rgb, // CV_BGR5652RGB =15 - bgra_to_bgr565, // CV_BGRA2BGR565 =16 - rgba_to_bgr565, // CV_RGBA2BGR565 =17 - bgr565_to_bgra, // CV_BGR5652BGRA =18 - bgr565_to_rgba, // CV_BGR5652RGBA =19 - - gray_to_bgr565, // CV_GRAY2BGR565 =20 - bgr565_to_gray, // CV_BGR5652GRAY =21 - - bgr_to_bgr555, // CV_BGR2BGR555 =22 - rgb_to_bgr555, // CV_RGB2BGR555 =23 - bgr555_to_bgr, // CV_BGR5552BGR =24 - bgr555_to_rgb, // CV_BGR5552RGB =25 - bgra_to_bgr555, // CV_BGRA2BGR555 =26 - rgba_to_bgr555, // CV_RGBA2BGR555 =27 - bgr555_to_bgra, // CV_BGR5552BGRA =28 - bgr555_to_rgba, // CV_BGR5552RGBA =29 - - gray_to_bgr555, // CV_GRAY2BGR555 =30 - bgr555_to_gray, // CV_BGR5552GRAY =31 - - bgr_to_xyz, // CV_BGR2XYZ =32 - rgb_to_xyz, // CV_RGB2XYZ =33 - xyz_to_bgr, // CV_XYZ2BGR =34 - xyz_to_rgb, // CV_XYZ2RGB =35 - - bgr_to_YCrCb, // CV_BGR2YCrCb =36 - rgb_to_YCrCb, // CV_RGB2YCrCb =37 - YCrCb_to_bgr, // CV_YCrCb2BGR =38 - YCrCb_to_rgb, // CV_YCrCb2RGB =39 - - bgr_to_hsv, // CV_BGR2HSV =40 - rgb_to_hsv, // CV_RGB2HSV =41 - - 0, // =42 - 0, // =43 - - bgr_to_lab, // CV_BGR2Lab =44 - rgb_to_lab, // CV_RGB2Lab =45 - - bayerBG_to_bgr, // CV_BayerBG2BGR =46 - bayerGB_to_bgr, // CV_BayerGB2BGR =47 - bayerRG_to_bgr, // CV_BayerRG2BGR =48 - bayerGR_to_bgr, // CV_BayerGR2BGR =49 - - bgr_to_luv, // CV_BGR2Luv =50 - rgb_to_luv, // CV_RGB2Luv =51 - - bgr_to_hls, // CV_BGR2HLS =52 - rgb_to_hls, // CV_RGB2HLS =53 - - hsv_to_bgr, // CV_HSV2BGR =54 - hsv_to_rgb, // CV_HSV2RGB =55 - - lab_to_bgr, // CV_Lab2BGR =56 - lab_to_rgb, // CV_Lab2RGB =57 - luv_to_bgr, // CV_Luv2BGR =58 - luv_to_rgb, // CV_Luv2RGB =59 - - hls_to_bgr, // CV_HLS2BGR =60 - hls_to_rgb, // CV_HLS2RGB =61 - - 0, // CV_BayerBG2BGR_VNG =62 - 0, // CV_BayerGB2BGR_VNG =63 - 0, // CV_BayerRG2BGR_VNG =64 - 0, // CV_BayerGR2BGR_VNG =65 - - bgr_to_hsv_full, // CV_BGR2HSV_FULL = 66 - rgb_to_hsv_full, // CV_RGB2HSV_FULL = 67 - bgr_to_hls_full, // CV_BGR2HLS_FULL = 68 - rgb_to_hls_full, // CV_RGB2HLS_FULL = 69 - - hsv_to_bgr_full, // CV_HSV2BGR_FULL = 70 - hsv_to_rgb_full, // CV_HSV2RGB_FULL = 71 - hls_to_bgr_full, // CV_HLS2BGR_FULL = 72 - hls_to_rgb_full, // CV_HLS2RGB_FULL = 73 - - lbgr_to_lab, // CV_LBGR2Lab = 74 - lrgb_to_lab, // CV_LRGB2Lab = 75 - lbgr_to_luv, // CV_LBGR2Luv = 76 - lrgb_to_luv, // CV_LRGB2Luv = 77 - - lab_to_lbgr, // CV_Lab2LBGR = 78 - lab_to_lrgb, // CV_Lab2LRGB = 79 - luv_to_lbgr, // CV_Luv2LBGR = 80 - luv_to_lrgb, // CV_Luv2LRGB = 81 - - bgr_to_yuv, // CV_BGR2YUV = 82 - rgb_to_yuv, // CV_RGB2YUV = 83 - yuv_to_bgr, // CV_YUV2BGR = 84 - yuv_to_rgb, // CV_YUV2RGB = 85 - - 0, // CV_BayerBG2GRAY = 86 - 0, // CV_BayerGB2GRAY = 87 - 0, // CV_BayerRG2GRAY = 88 - 0, // CV_BayerGR2GRAY = 89 - - //YUV 4:2:0 formats family - 0, // CV_YUV2RGB_NV12 = 90, - 0, // CV_YUV2BGR_NV12 = 91, - 0, // CV_YUV2RGB_NV21 = 92, - 0, // CV_YUV2BGR_NV21 = 93, - - 0, // CV_YUV2RGBA_NV12 = 94, - 0, // CV_YUV2BGRA_NV12 = 95, - 0, // CV_YUV2RGBA_NV21 = 96, - 0, // CV_YUV2BGRA_NV21 = 97, - - 0, // CV_YUV2RGB_YV12 = 98, - 0, // CV_YUV2BGR_YV12 = 99, - 0, // CV_YUV2RGB_IYUV = 100, - 0, // CV_YUV2BGR_IYUV = 101, - - 0, // CV_YUV2RGBA_YV12 = 102, - 0, // CV_YUV2BGRA_YV12 = 103, - 0, // CV_YUV2RGBA_IYUV = 104, - 0, // CV_YUV2BGRA_IYUV = 105, - - 0, // CV_YUV2GRAY_420 = 106, - - //YUV 4:2:2 formats family - 0, // CV_YUV2RGB_UYVY = 107, - 0, // CV_YUV2BGR_UYVY = 108, - 0, // //CV_YUV2RGB_VYUY = 109, - 0, // //CV_YUV2BGR_VYUY = 110, - - 0, // CV_YUV2RGBA_UYVY = 111, - 0, // CV_YUV2BGRA_UYVY = 112, - 0, // //CV_YUV2RGBA_VYUY = 113, - 0, // //CV_YUV2BGRA_VYUY = 114, - - 0, // CV_YUV2RGB_YUY2 = 115, - 0, // CV_YUV2BGR_YUY2 = 116, - 0, // CV_YUV2RGB_YVYU = 117, - 0, // CV_YUV2BGR_YVYU = 118, - - 0, // CV_YUV2RGBA_YUY2 = 119, - 0, // CV_YUV2BGRA_YUY2 = 120, - 0, // CV_YUV2RGBA_YVYU = 121, - 0, // CV_YUV2BGRA_YVYU = 122, - - 0, // CV_YUV2GRAY_UYVY = 123, - 0, // CV_YUV2GRAY_YUY2 = 124, - - // alpha premultiplication - rgba_to_mbgra, // CV_RGBA2mRGBA = 125, - 0, // CV_mRGBA2RGBA = 126, - - 0, // CV_COLORCVT_MAX = 127 - }; - - CV_Assert(code < 128); - - func_t func = funcs[code]; - - if (func == 0) - CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); - - func(src, dst, dcn, stream); -} - -void cv::gpu::swapChannels(GpuMat& image, const int dstOrder[4], Stream& s) -{ - CV_Assert(image.type() == CV_8UC4); - - cudaStream_t stream = StreamAccessor::getStream(s); - - NppStreamHandler h(stream); - - NppiSize sz; - sz.width = image.cols; - sz.height = image.rows; - - nppSafeCall( nppiSwapChannels_8u_C4IR(image.ptr(), static_cast(image.step), sz, dstOrder) ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); -} - -void cv::gpu::gammaCorrection(const GpuMat& src, GpuMat& dst, bool forward, Stream& stream) -{ -#if (CUDA_VERSION < 5000) - (void)src; - (void)dst; - (void)forward; - (void)stream; - CV_Error( CV_StsNotImplemented, "This function works only with CUDA 5.0 or higher" ); -#else - typedef NppStatus (*func_t)(const Npp8u* pSrc, int nSrcStep, Npp8u* pDst, int nDstStep, NppiSize oSizeROI); - typedef NppStatus (*func_inplace_t)(Npp8u* pSrcDst, int nSrcDstStep, NppiSize oSizeROI); - - static const func_t funcs[2][5] = - { - {0, 0, 0, nppiGammaInv_8u_C3R, nppiGammaInv_8u_AC4R}, - {0, 0, 0, nppiGammaFwd_8u_C3R, nppiGammaFwd_8u_AC4R} - }; - static const func_inplace_t funcs_inplace[2][5] = - { - {0, 0, 0, nppiGammaInv_8u_C3IR, nppiGammaInv_8u_AC4IR}, - {0, 0, 0, nppiGammaFwd_8u_C3IR, nppiGammaFwd_8u_AC4IR} - }; - - CV_Assert(src.type() == CV_8UC3 || src.type() == CV_8UC4); - - dst.create(src.size(), src.type()); - - NppStreamHandler h(StreamAccessor::getStream(stream)); - - NppiSize oSizeROI; - oSizeROI.width = src.cols; - oSizeROI.height = src.rows; - - if (dst.data == src.data) - funcs_inplace[forward][src.channels()](dst.ptr(), static_cast(src.step), oSizeROI); - else - funcs[forward][src.channels()](src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), oSizeROI); - -#endif -} - -#endif /* !defined (HAVE_CUDA) */ diff --git a/modules/gpu/src/cu_safe_call.cpp b/modules/gpu/src/cu_safe_call.cpp deleted file mode 100644 index 7218873dff..0000000000 --- a/modules/gpu/src/cu_safe_call.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/*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 "cu_safe_call.h" - -#ifdef HAVE_CUDA - -namespace -{ - #define error_entry(entry) { entry, #entry } - - struct ErrorEntry - { - int code; - std::string str; - }; - - class ErrorEntryComparer - { - public: - inline ErrorEntryComparer(int code) : code_(code) {} - - inline bool operator()(const ErrorEntry& e) const { return e.code == code_; } - - private: - int code_; - }; - - std::string getErrorString(int code, const ErrorEntry* errors, size_t n) - { - size_t idx = std::find_if(errors, errors + n, ErrorEntryComparer(code)) - errors; - - const std::string& msg = (idx != n) ? errors[idx].str : std::string("Unknown error code"); - - std::ostringstream ostr; - ostr << msg << " [Code = " << code << "]"; - - return ostr.str(); - } - - const ErrorEntry cu_errors [] = - { - error_entry( CUDA_SUCCESS ), - error_entry( CUDA_ERROR_INVALID_VALUE ), - error_entry( CUDA_ERROR_OUT_OF_MEMORY ), - error_entry( CUDA_ERROR_NOT_INITIALIZED ), - error_entry( CUDA_ERROR_DEINITIALIZED ), - error_entry( CUDA_ERROR_PROFILER_DISABLED ), - error_entry( CUDA_ERROR_PROFILER_NOT_INITIALIZED ), - error_entry( CUDA_ERROR_PROFILER_ALREADY_STARTED ), - error_entry( CUDA_ERROR_PROFILER_ALREADY_STOPPED ), - error_entry( CUDA_ERROR_NO_DEVICE ), - error_entry( CUDA_ERROR_INVALID_DEVICE ), - error_entry( CUDA_ERROR_INVALID_IMAGE ), - error_entry( CUDA_ERROR_INVALID_CONTEXT ), - error_entry( CUDA_ERROR_CONTEXT_ALREADY_CURRENT ), - error_entry( CUDA_ERROR_MAP_FAILED ), - error_entry( CUDA_ERROR_UNMAP_FAILED ), - error_entry( CUDA_ERROR_ARRAY_IS_MAPPED ), - error_entry( CUDA_ERROR_ALREADY_MAPPED ), - error_entry( CUDA_ERROR_NO_BINARY_FOR_GPU ), - error_entry( CUDA_ERROR_ALREADY_ACQUIRED ), - error_entry( CUDA_ERROR_NOT_MAPPED ), - error_entry( CUDA_ERROR_NOT_MAPPED_AS_ARRAY ), - error_entry( CUDA_ERROR_NOT_MAPPED_AS_POINTER ), - error_entry( CUDA_ERROR_ECC_UNCORRECTABLE ), - error_entry( CUDA_ERROR_UNSUPPORTED_LIMIT ), - error_entry( CUDA_ERROR_CONTEXT_ALREADY_IN_USE ), - error_entry( CUDA_ERROR_INVALID_SOURCE ), - error_entry( CUDA_ERROR_FILE_NOT_FOUND ), - error_entry( CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND ), - error_entry( CUDA_ERROR_SHARED_OBJECT_INIT_FAILED ), - error_entry( CUDA_ERROR_OPERATING_SYSTEM ), - error_entry( CUDA_ERROR_INVALID_HANDLE ), - error_entry( CUDA_ERROR_NOT_FOUND ), - error_entry( CUDA_ERROR_NOT_READY ), - error_entry( CUDA_ERROR_LAUNCH_FAILED ), - error_entry( CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES ), - error_entry( CUDA_ERROR_LAUNCH_TIMEOUT ), - error_entry( CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING ), - error_entry( CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED ), - error_entry( CUDA_ERROR_PEER_ACCESS_NOT_ENABLED ), - error_entry( CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE ), - error_entry( CUDA_ERROR_CONTEXT_IS_DESTROYED ), - error_entry( CUDA_ERROR_ASSERT ), - error_entry( CUDA_ERROR_TOO_MANY_PEERS ), - error_entry( CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED ), - error_entry( CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED ), - error_entry( CUDA_ERROR_UNKNOWN ) - }; - - const size_t cu_errors_num = sizeof(cu_errors) / sizeof(cu_errors[0]); -} - -std::string cv::gpu::detail::cuGetErrString(CUresult res) -{ - return getErrorString(res, cu_errors, cu_errors_num); -} - -#endif // HAVE_CUDA diff --git a/modules/gpu/src/cuda/NV12ToARGB.cu b/modules/gpu/src/cuda/NV12ToARGB.cu deleted file mode 100644 index 8ad6cfdfae..0000000000 --- a/modules/gpu/src/cuda/NV12ToARGB.cu +++ /dev/null @@ -1,212 +0,0 @@ -/*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*/ - -/* - * Copyright 1993-2010 NVIDIA Corporation. All rights reserved. - * - * Please refer to the NVIDIA end user license agreement (EULA) associated - * with this source code for terms and conditions that govern your use of - * this software. Any use, reproduction, disclosure, or distribution of - * this software and related documentation outside the terms of the EULA - * is strictly prohibited. - * - */ - -/* - NV12ToARGB color space conversion CUDA kernel - - This sample uses CUDA to perform a simple NV12 (YUV 4:2:0 planar) - source and converts to output in ARGB format -*/ - -#if !defined CUDA_DISABLER - -#include "opencv2/gpu/device/common.hpp" - -namespace cv { namespace gpu { namespace device { - namespace video_decoding - { - __constant__ uint constAlpha = ((uint)0xff << 24); - - __constant__ float constHueColorSpaceMat[9]; - - void loadHueCSC(float hueCSC[9]) - { - cudaSafeCall( cudaMemcpyToSymbol(constHueColorSpaceMat, hueCSC, 9 * sizeof(float)) ); - } - - __device__ void YUV2RGB(const uint* yuvi, float* red, float* green, float* blue) - { - float luma, chromaCb, chromaCr; - - // Prepare for hue adjustment - luma = (float)yuvi[0]; - chromaCb = (float)((int)yuvi[1] - 512.0f); - chromaCr = (float)((int)yuvi[2] - 512.0f); - - // Convert YUV To RGB with hue adjustment - *red = (luma * constHueColorSpaceMat[0]) + - (chromaCb * constHueColorSpaceMat[1]) + - (chromaCr * constHueColorSpaceMat[2]); - - *green = (luma * constHueColorSpaceMat[3]) + - (chromaCb * constHueColorSpaceMat[4]) + - (chromaCr * constHueColorSpaceMat[5]); - - *blue = (luma * constHueColorSpaceMat[6]) + - (chromaCb * constHueColorSpaceMat[7]) + - (chromaCr * constHueColorSpaceMat[8]); - } - - __device__ uint RGBAPACK_10bit(float red, float green, float blue, uint alpha) - { - uint ARGBpixel = 0; - - // Clamp final 10 bit results - red = ::fmin(::fmax(red, 0.0f), 1023.f); - green = ::fmin(::fmax(green, 0.0f), 1023.f); - blue = ::fmin(::fmax(blue, 0.0f), 1023.f); - - // Convert to 8 bit unsigned integers per color component - ARGBpixel = (((uint)blue >> 2) | - (((uint)green >> 2) << 8) | - (((uint)red >> 2) << 16) | - (uint)alpha); - - return ARGBpixel; - } - - // CUDA kernel for outputing the final ARGB output from NV12 - - #define COLOR_COMPONENT_BIT_SIZE 10 - #define COLOR_COMPONENT_MASK 0x3FF - - __global__ void NV12ToARGB(uchar* srcImage, size_t nSourcePitch, - uint* dstImage, size_t nDestPitch, - uint width, uint height) - { - // Pad borders with duplicate pixels, and we multiply by 2 because we process 2 pixels per thread - const int x = blockIdx.x * (blockDim.x << 1) + (threadIdx.x << 1); - const int y = blockIdx.y * blockDim.y + threadIdx.y; - - if (x >= width || y >= height) - return; - - // Read 2 Luma components at a time, so we don't waste processing since CbCr are decimated this way. - // if we move to texture we could read 4 luminance values - - uint yuv101010Pel[2]; - - yuv101010Pel[0] = (srcImage[y * nSourcePitch + x ]) << 2; - yuv101010Pel[1] = (srcImage[y * nSourcePitch + x + 1]) << 2; - - const size_t chromaOffset = nSourcePitch * height; - - const int y_chroma = y >> 1; - - if (y & 1) // odd scanline ? - { - uint chromaCb = srcImage[chromaOffset + y_chroma * nSourcePitch + x ]; - uint chromaCr = srcImage[chromaOffset + y_chroma * nSourcePitch + x + 1]; - - if (y_chroma < ((height >> 1) - 1)) // interpolate chroma vertically - { - chromaCb = (chromaCb + srcImage[chromaOffset + (y_chroma + 1) * nSourcePitch + x ] + 1) >> 1; - chromaCr = (chromaCr + srcImage[chromaOffset + (y_chroma + 1) * nSourcePitch + x + 1] + 1) >> 1; - } - - yuv101010Pel[0] |= (chromaCb << ( COLOR_COMPONENT_BIT_SIZE + 2)); - yuv101010Pel[0] |= (chromaCr << ((COLOR_COMPONENT_BIT_SIZE << 1) + 2)); - - yuv101010Pel[1] |= (chromaCb << ( COLOR_COMPONENT_BIT_SIZE + 2)); - yuv101010Pel[1] |= (chromaCr << ((COLOR_COMPONENT_BIT_SIZE << 1) + 2)); - } - else - { - yuv101010Pel[0] |= ((uint)srcImage[chromaOffset + y_chroma * nSourcePitch + x ] << ( COLOR_COMPONENT_BIT_SIZE + 2)); - yuv101010Pel[0] |= ((uint)srcImage[chromaOffset + y_chroma * nSourcePitch + x + 1] << ((COLOR_COMPONENT_BIT_SIZE << 1) + 2)); - - yuv101010Pel[1] |= ((uint)srcImage[chromaOffset + y_chroma * nSourcePitch + x ] << ( COLOR_COMPONENT_BIT_SIZE + 2)); - yuv101010Pel[1] |= ((uint)srcImage[chromaOffset + y_chroma * nSourcePitch + x + 1] << ((COLOR_COMPONENT_BIT_SIZE << 1) + 2)); - } - - // this steps performs the color conversion - uint yuvi[6]; - float red[2], green[2], blue[2]; - - yuvi[0] = (yuv101010Pel[0] & COLOR_COMPONENT_MASK ); - yuvi[1] = ((yuv101010Pel[0] >> COLOR_COMPONENT_BIT_SIZE) & COLOR_COMPONENT_MASK); - yuvi[2] = ((yuv101010Pel[0] >> (COLOR_COMPONENT_BIT_SIZE << 1)) & COLOR_COMPONENT_MASK); - - yuvi[3] = (yuv101010Pel[1] & COLOR_COMPONENT_MASK ); - yuvi[4] = ((yuv101010Pel[1] >> COLOR_COMPONENT_BIT_SIZE) & COLOR_COMPONENT_MASK); - yuvi[5] = ((yuv101010Pel[1] >> (COLOR_COMPONENT_BIT_SIZE << 1)) & COLOR_COMPONENT_MASK); - - // YUV to RGB Transformation conversion - YUV2RGB(&yuvi[0], &red[0], &green[0], &blue[0]); - YUV2RGB(&yuvi[3], &red[1], &green[1], &blue[1]); - - // Clamp the results to RGBA - - const size_t dstImagePitch = nDestPitch >> 2; - - dstImage[y * dstImagePitch + x ] = RGBAPACK_10bit(red[0], green[0], blue[0], constAlpha); - dstImage[y * dstImagePitch + x + 1 ] = RGBAPACK_10bit(red[1], green[1], blue[1], constAlpha); - } - - void NV12ToARGB_gpu(const PtrStepb decodedFrame, PtrStepSz interopFrame, cudaStream_t stream) - { - dim3 block(32, 8); - dim3 grid(divUp(interopFrame.cols, 2 * block.x), divUp(interopFrame.rows, block.y)); - - NV12ToARGB<<>>(decodedFrame.data, decodedFrame.step, interopFrame.data, interopFrame.step, - interopFrame.cols, interopFrame.rows); - - cudaSafeCall( cudaGetLastError() ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); - } - } -}}} - -#endif /* CUDA_DISABLER */ \ No newline at end of file diff --git a/modules/gpu/src/cuda/bgfg_vibe.cu b/modules/gpu/src/cuda/bgfg_vibe.cu deleted file mode 100644 index 72ea7f0ae7..0000000000 --- a/modules/gpu/src/cuda/bgfg_vibe.cu +++ /dev/null @@ -1,258 +0,0 @@ -/*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 bpied warranties, including, but not limited to, the bpied -// 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*/ - -#if !defined CUDA_DISABLER - -#include "opencv2/gpu/device/common.hpp" - -namespace cv { namespace gpu { namespace device -{ - namespace vibe - { - __constant__ int c_nbSamples; - __constant__ int c_reqMatches; - __constant__ int c_radius; - __constant__ int c_subsamplingFactor; - - void loadConstants(int nbSamples, int reqMatches, int radius, int subsamplingFactor) - { - cudaSafeCall( cudaMemcpyToSymbol(c_nbSamples, &nbSamples, sizeof(int)) ); - cudaSafeCall( cudaMemcpyToSymbol(c_reqMatches, &reqMatches, sizeof(int)) ); - cudaSafeCall( cudaMemcpyToSymbol(c_radius, &radius, sizeof(int)) ); - cudaSafeCall( cudaMemcpyToSymbol(c_subsamplingFactor, &subsamplingFactor, sizeof(int)) ); - } - - __device__ __forceinline__ uint nextRand(uint& state) - { - const unsigned int CV_RNG_COEFF = 4164903690U; - state = state * CV_RNG_COEFF + (state >> 16); - return state; - } - - __constant__ int c_xoff[9] = {-1, 0, 1, -1, 1, -1, 0, 1, 0}; - __constant__ int c_yoff[9] = {-1, -1, -1, 0, 0, 1, 1, 1, 0}; - - __device__ __forceinline__ int2 chooseRandomNeighbor(int x, int y, uint& randState, int count = 8) - { - int idx = nextRand(randState) % count; - - return make_int2(x + c_xoff[idx], y + c_yoff[idx]); - } - - __device__ __forceinline__ uchar cvt(uchar val) - { - return val; - } - __device__ __forceinline__ uchar4 cvt(const uchar3& val) - { - return make_uchar4(val.x, val.y, val.z, 0); - } - __device__ __forceinline__ uchar4 cvt(const uchar4& val) - { - return val; - } - - template - __global__ void init(const PtrStepSz frame, PtrStep samples, PtrStep randStates) - { - const int x = blockIdx.x * blockDim.x + threadIdx.x; - const int y = blockIdx.y * blockDim.y + threadIdx.y; - - if (x >= frame.cols || y >= frame.rows) - return; - - uint localState = randStates(y, x); - - for (int k = 0; k < c_nbSamples; ++k) - { - int2 np = chooseRandomNeighbor(x, y, localState, 9); - - np.x = ::max(0, ::min(np.x, frame.cols - 1)); - np.y = ::max(0, ::min(np.y, frame.rows - 1)); - - SrcT pix = frame(np.y, np.x); - - samples(k * frame.rows + y, x) = cvt(pix); - } - - randStates(y, x) = localState; - } - - template - void init_caller(PtrStepSzb frame, PtrStepSzb samples, PtrStepSz randStates, cudaStream_t stream) - { - dim3 block(32, 8); - dim3 grid(divUp(frame.cols, block.x), divUp(frame.rows, block.y)); - - cudaSafeCall( cudaFuncSetCacheConfig(init, cudaFuncCachePreferL1) ); - - init<<>>((PtrStepSz) frame, (PtrStepSz) samples, randStates); - cudaSafeCall( cudaGetLastError() ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); - } - - void init_gpu(PtrStepSzb frame, int cn, PtrStepSzb samples, PtrStepSz randStates, cudaStream_t stream) - { - typedef void (*func_t)(PtrStepSzb frame, PtrStepSzb samples, PtrStepSz randStates, cudaStream_t stream); - static const func_t funcs[] = - { - 0, init_caller, 0, init_caller, init_caller - }; - - funcs[cn](frame, samples, randStates, stream); - } - - __device__ __forceinline__ int calcDist(uchar a, uchar b) - { - return ::abs(a - b); - } - __device__ __forceinline__ int calcDist(const uchar3& a, const uchar4& b) - { - return (::abs(a.x - b.x) + ::abs(a.y - b.y) + ::abs(a.z - b.z)) / 3; - } - __device__ __forceinline__ int calcDist(const uchar4& a, const uchar4& b) - { - return (::abs(a.x - b.x) + ::abs(a.y - b.y) + ::abs(a.z - b.z)) / 3; - } - - template - __global__ void update(const PtrStepSz frame, PtrStepb fgmask, PtrStep samples, PtrStep randStates) - { - const int x = blockIdx.x * blockDim.x + threadIdx.x; - const int y = blockIdx.y * blockDim.y + threadIdx.y; - - if (x >= frame.cols || y >= frame.rows) - return; - - uint localState = randStates(y, x); - - SrcT imgPix = frame(y, x); - - // comparison with the model - - int count = 0; - for (int k = 0; (count < c_reqMatches) && (k < c_nbSamples); ++k) - { - SampleT samplePix = samples(k * frame.rows + y, x); - - int distance = calcDist(imgPix, samplePix); - - if (distance < c_radius) - ++count; - } - - // pixel classification according to reqMatches - - fgmask(y, x) = (uchar) (-(count < c_reqMatches)); - - if (count >= c_reqMatches) - { - // the pixel belongs to the background - - // gets a random number between 0 and subsamplingFactor-1 - int randomNumber = nextRand(localState) % c_subsamplingFactor; - - // update of the current pixel model - if (randomNumber == 0) - { - // random subsampling - - int k = nextRand(localState) % c_nbSamples; - - samples(k * frame.rows + y, x) = cvt(imgPix); - } - - // update of a neighboring pixel model - randomNumber = nextRand(localState) % c_subsamplingFactor; - - if (randomNumber == 0) - { - // random subsampling - - // chooses a neighboring pixel randomly - int2 np = chooseRandomNeighbor(x, y, localState); - - np.x = ::max(0, ::min(np.x, frame.cols - 1)); - np.y = ::max(0, ::min(np.y, frame.rows - 1)); - - // chooses the value to be replaced randomly - int k = nextRand(localState) % c_nbSamples; - - samples(k * frame.rows + np.y, np.x) = cvt(imgPix); - } - } - - randStates(y, x) = localState; - } - - template - void update_caller(PtrStepSzb frame, PtrStepSzb fgmask, PtrStepSzb samples, PtrStepSz randStates, cudaStream_t stream) - { - dim3 block(32, 8); - dim3 grid(divUp(frame.cols, block.x), divUp(frame.rows, block.y)); - - cudaSafeCall( cudaFuncSetCacheConfig(update, cudaFuncCachePreferL1) ); - - update<<>>((PtrStepSz) frame, fgmask, (PtrStepSz) samples, randStates); - cudaSafeCall( cudaGetLastError() ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); - } - - void update_gpu(PtrStepSzb frame, int cn, PtrStepSzb fgmask, PtrStepSzb samples, PtrStepSz randStates, cudaStream_t stream) - { - typedef void (*func_t)(PtrStepSzb frame, PtrStepSzb fgmask, PtrStepSzb samples, PtrStepSz randStates, cudaStream_t stream); - static const func_t funcs[] = - { - 0, update_caller, 0, update_caller, update_caller - }; - - funcs[cn](frame, fgmask, samples, randStates, stream); - } - } -}}} - - -#endif /* CUDA_DISABLER */ \ No newline at end of file diff --git a/modules/gpu/src/cuda/calib3d.cu b/modules/gpu/src/cuda/calib3d.cu index 0fd482c41a..9adc7806f6 100644 --- a/modules/gpu/src/cuda/calib3d.cu +++ b/modules/gpu/src/cuda/calib3d.cu @@ -42,12 +42,12 @@ #if !defined CUDA_DISABLER -#include "opencv2/gpu/device/common.hpp" -#include "opencv2/gpu/device/transform.hpp" -#include "opencv2/gpu/device/functional.hpp" -#include "opencv2/gpu/device/reduce.hpp" +#include "opencv2/core/cuda/common.hpp" +#include "opencv2/core/cuda/transform.hpp" +#include "opencv2/core/cuda/functional.hpp" +#include "opencv2/core/cuda/reduce.hpp" -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { #define SOLVE_PNP_RANSAC_MAX_NUM_ITERS 200 @@ -67,8 +67,8 @@ namespace cv { namespace gpu { namespace device crot1.x * p.x + crot1.y * p.y + crot1.z * p.z + ctransl.y, crot2.x * p.x + crot2.y * p.y + crot2.z * p.z + ctransl.z); } - __device__ __forceinline__ TransformOp() {} - __device__ __forceinline__ TransformOp(const TransformOp&) {} + __host__ __device__ __forceinline__ TransformOp() {} + __host__ __device__ __forceinline__ TransformOp(const TransformOp&) {} }; void call(const PtrStepSz src, const float* rot, @@ -79,7 +79,7 @@ namespace cv { namespace gpu { namespace device cudaSafeCall(cudaMemcpyToSymbol(crot1, rot + 3, sizeof(float) * 3)); cudaSafeCall(cudaMemcpyToSymbol(crot2, rot + 6, sizeof(float) * 3)); cudaSafeCall(cudaMemcpyToSymbol(ctransl, transl, sizeof(float) * 3)); - cv::gpu::device::transform(src, dst, TransformOp(), WithOutMask(), stream); + cv::gpu::cudev::transform(src, dst, TransformOp(), WithOutMask(), stream); } } // namespace transform_points @@ -106,8 +106,8 @@ namespace cv { namespace gpu { namespace device (cproj0.x * t.x + cproj0.y * t.y) / t.z + cproj0.z, (cproj1.x * t.x + cproj1.y * t.y) / t.z + cproj1.z); } - __device__ __forceinline__ ProjectOp() {} - __device__ __forceinline__ ProjectOp(const ProjectOp&) {} + __host__ __device__ __forceinline__ ProjectOp() {} + __host__ __device__ __forceinline__ ProjectOp(const ProjectOp&) {} }; void call(const PtrStepSz src, const float* rot, @@ -120,7 +120,7 @@ namespace cv { namespace gpu { namespace device cudaSafeCall(cudaMemcpyToSymbol(ctransl, transl, sizeof(float) * 3)); cudaSafeCall(cudaMemcpyToSymbol(cproj0, proj, sizeof(float) * 3)); cudaSafeCall(cudaMemcpyToSymbol(cproj1, proj + 3, sizeof(float) * 3)); - cv::gpu::device::transform(src, dst, ProjectOp(), WithOutMask(), stream); + cv::gpu::cudev::transform(src, dst, ProjectOp(), WithOutMask(), stream); } } // namespace project_points @@ -187,7 +187,7 @@ namespace cv { namespace gpu { namespace device cudaSafeCall( cudaDeviceSynchronize() ); } } // namespace solvepnp_ransac -}}} // namespace cv { namespace gpu { namespace device +}}} // namespace cv { namespace gpu { namespace cudev #endif /* CUDA_DISABLER */ diff --git a/modules/gpu/src/cuda/ccomponetns.cu b/modules/gpu/src/cuda/ccomponetns.cu index 0533522bed..58ceb99cd8 100644 --- a/modules/gpu/src/cuda/ccomponetns.cu +++ b/modules/gpu/src/cuda/ccomponetns.cu @@ -1,31 +1,31 @@ /*M/////////////////////////////////////////////////////////////////////////////////////// // -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// 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. +// 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 +// License Agreement +// For Open Source Computer Vision Library // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2008-2011, Willow Garage Inc., 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: // -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. // -// * Redistributions 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. +// * 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. +// * 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 @@ -37,19 +37,20 @@ // 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*/ #if !defined CUDA_DISABLER -#include -#include -#include -#include +#include +#include +#include +#include #include #include -namespace cv { namespace gpu { namespace device +namespace cv { namespace gpu { namespace cudev { namespace ccl { @@ -152,7 +153,7 @@ namespace cv { namespace gpu { namespace device template __device__ __forceinline__ bool operator() (const I& a, const I& b) const { - I d = a - b; + I d = saturate_cast(a - b); return lo.x <= d.x && d.x <= hi.x && lo.y <= d.y && d.y <= hi.y && lo.z <= d.z && d.z <= hi.z; @@ -168,7 +169,7 @@ namespace cv { namespace gpu { namespace device template __device__ __forceinline__ bool operator() (const I& a, const I& b) const { - I d = a - b; + I d = saturate_cast(a - b); return lo.x <= d.x && d.x <= hi.x && lo.y <= d.y && d.y <= hi.y && lo.z <= d.z && d.z <= hi.z && diff --git a/modules/gpu/src/cuda/debayer.cu b/modules/gpu/src/cuda/debayer.cu deleted file mode 100644 index 57322ed81f..0000000000 --- a/modules/gpu/src/cuda/debayer.cu +++ /dev/null @@ -1,331 +0,0 @@ -/*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*/ - -#if !defined CUDA_DISABLER - -#include -#include -#include -#include - -namespace cv { namespace gpu { - namespace device - { - template - __global__ void Bayer2BGR_8u(const PtrStepb src, PtrStepSz dst, const bool blue_last, const bool start_with_green) - { - const int s_x = blockIdx.x * blockDim.x + threadIdx.x; - int s_y = blockIdx.y * blockDim.y + threadIdx.y; - - if (s_y >= dst.rows || (s_x << 2) >= dst.cols) - return; - - s_y = ::min(::max(s_y, 1), dst.rows - 2); - - uchar4 patch[3][3]; - patch[0][1] = ((const uchar4*) src.ptr(s_y - 1))[s_x]; - patch[0][0] = ((const uchar4*) src.ptr(s_y - 1))[::max(s_x - 1, 0)]; - patch[0][2] = ((const uchar4*) src.ptr(s_y - 1))[::min(s_x + 1, ((dst.cols + 3) >> 2) - 1)]; - - patch[1][1] = ((const uchar4*) src.ptr(s_y))[s_x]; - patch[1][0] = ((const uchar4*) src.ptr(s_y))[::max(s_x - 1, 0)]; - patch[1][2] = ((const uchar4*) src.ptr(s_y))[::min(s_x + 1, ((dst.cols + 3) >> 2) - 1)]; - - patch[2][1] = ((const uchar4*) src.ptr(s_y + 1))[s_x]; - patch[2][0] = ((const uchar4*) src.ptr(s_y + 1))[::max(s_x - 1, 0)]; - patch[2][2] = ((const uchar4*) src.ptr(s_y + 1))[::min(s_x + 1, ((dst.cols + 3) >> 2) - 1)]; - - D res0 = VecTraits::all(numeric_limits::max()); - D res1 = VecTraits::all(numeric_limits::max()); - D res2 = VecTraits::all(numeric_limits::max()); - D res3 = VecTraits::all(numeric_limits::max()); - - if ((s_y & 1) ^ start_with_green) - { - const int t0 = (patch[0][1].x + patch[2][1].x + 1) >> 1; - const int t1 = (patch[1][0].w + patch[1][1].y + 1) >> 1; - - const int t2 = (patch[0][1].x + patch[0][1].z + patch[2][1].x + patch[2][1].z + 2) >> 2; - const int t3 = (patch[0][1].y + patch[1][1].x + patch[1][1].z + patch[2][1].y + 2) >> 2; - - const int t4 = (patch[0][1].z + patch[2][1].z + 1) >> 1; - const int t5 = (patch[1][1].y + patch[1][1].w + 1) >> 1; - - const int t6 = (patch[0][1].z + patch[0][2].x + patch[2][1].z + patch[2][2].x + 2) >> 2; - const int t7 = (patch[0][1].w + patch[1][1].z + patch[1][2].x + patch[2][1].w + 2) >> 2; - - if ((s_y & 1) ^ blue_last) - { - res0.x = t1; - res0.y = patch[1][1].x; - res0.z = t0; - - res1.x = patch[1][1].y; - res1.y = t3; - res1.z = t2; - - res2.x = t5; - res2.y = patch[1][1].z; - res2.z = t4; - - res3.x = patch[1][1].w; - res3.y = t7; - res3.z = t6; - } - else - { - res0.x = t0; - res0.y = patch[1][1].x; - res0.z = t1; - - res1.x = t2; - res1.y = t3; - res1.z = patch[1][1].y; - - res2.x = t4; - res2.y = patch[1][1].z; - res2.z = t5; - - res3.x = t6; - res3.y = t7; - res3.z = patch[1][1].w; - } - } - else - { - const int t0 = (patch[0][0].w + patch[0][1].y + patch[2][0].w + patch[2][1].y + 2) >> 2; - const int t1 = (patch[0][1].x + patch[1][0].w + patch[1][1].y + patch[2][1].x + 2) >> 2; - - const int t2 = (patch[0][1].y + patch[2][1].y + 1) >> 1; - const int t3 = (patch[1][1].x + patch[1][1].z + 1) >> 1; - - const int t4 = (patch[0][1].y + patch[0][1].w + patch[2][1].y + patch[2][1].w + 2) >> 2; - const int t5 = (patch[0][1].z + patch[1][1].y + patch[1][1].w + patch[2][1].z + 2) >> 2; - - const int t6 = (patch[0][1].w + patch[2][1].w + 1) >> 1; - const int t7 = (patch[1][1].z + patch[1][2].x + 1) >> 1; - - if ((s_y & 1) ^ blue_last) - { - res0.x = patch[1][1].x; - res0.y = t1; - res0.z = t0; - - res1.x = t3; - res1.y = patch[1][1].y; - res1.z = t2; - - res2.x = patch[1][1].z; - res2.y = t5; - res2.z = t4; - - res3.x = t7; - res3.y = patch[1][1].w; - res3.z = t6; - } - else - { - res0.x = t0; - res0.y = t1; - res0.z = patch[1][1].x; - - res1.x = t2; - res1.y = patch[1][1].y; - res1.z = t3; - - res2.x = t4; - res2.y = t5; - res2.z = patch[1][1].z; - - res3.x = t6; - res3.y = patch[1][1].w; - res3.z = t7; - } - } - - const int d_x = (blockIdx.x * blockDim.x + threadIdx.x) << 2; - const int d_y = blockIdx.y * blockDim.y + threadIdx.y; - - dst(d_y, d_x) = res0; - if (d_x + 1 < dst.cols) - dst(d_y, d_x + 1) = res1; - if (d_x + 2 < dst.cols) - dst(d_y, d_x + 2) = res2; - if (d_x + 3 < dst.cols) - dst(d_y, d_x + 3) = res3; - } - - template - __global__ void Bayer2BGR_16u(const PtrStepb src, PtrStepSz dst, const bool blue_last, const bool start_with_green) - { - const int s_x = blockIdx.x * blockDim.x + threadIdx.x; - int s_y = blockIdx.y * blockDim.y + threadIdx.y; - - if (s_y >= dst.rows || (s_x << 1) >= dst.cols) - return; - - s_y = ::min(::max(s_y, 1), dst.rows - 2); - - ushort2 patch[3][3]; - patch[0][1] = ((const ushort2*) src.ptr(s_y - 1))[s_x]; - patch[0][0] = ((const ushort2*) src.ptr(s_y - 1))[::max(s_x - 1, 0)]; - patch[0][2] = ((const ushort2*) src.ptr(s_y - 1))[::min(s_x + 1, ((dst.cols + 1) >> 1) - 1)]; - - patch[1][1] = ((const ushort2*) src.ptr(s_y))[s_x]; - patch[1][0] = ((const ushort2*) src.ptr(s_y))[::max(s_x - 1, 0)]; - patch[1][2] = ((const ushort2*) src.ptr(s_y))[::min(s_x + 1, ((dst.cols + 1) >> 1) - 1)]; - - patch[2][1] = ((const ushort2*) src.ptr(s_y + 1))[s_x]; - patch[2][0] = ((const ushort2*) src.ptr(s_y + 1))[::max(s_x - 1, 0)]; - patch[2][2] = ((const ushort2*) src.ptr(s_y + 1))[::min(s_x + 1, ((dst.cols + 1) >> 1) - 1)]; - - D res0 = VecTraits::all(numeric_limits::max()); - D res1 = VecTraits::all(numeric_limits::max()); - - if ((s_y & 1) ^ start_with_green) - { - const int t0 = (patch[0][1].x + patch[2][1].x + 1) >> 1; - const int t1 = (patch[1][0].y + patch[1][1].y + 1) >> 1; - - const int t2 = (patch[0][1].x + patch[0][2].x + patch[2][1].x + patch[2][2].x + 2) >> 2; - const int t3 = (patch[0][1].y + patch[1][1].x + patch[1][2].x + patch[2][1].y + 2) >> 2; - - if ((s_y & 1) ^ blue_last) - { - res0.x = t1; - res0.y = patch[1][1].x; - res0.z = t0; - - res1.x = patch[1][1].y; - res1.y = t3; - res1.z = t2; - } - else - { - res0.x = t0; - res0.y = patch[1][1].x; - res0.z = t1; - - res1.x = t2; - res1.y = t3; - res1.z = patch[1][1].y; - } - } - else - { - const int t0 = (patch[0][0].y + patch[0][1].y + patch[2][0].y + patch[2][1].y + 2) >> 2; - const int t1 = (patch[0][1].x + patch[1][0].y + patch[1][1].y + patch[2][1].x + 2) >> 2; - - const int t2 = (patch[0][1].y + patch[2][1].y + 1) >> 1; - const int t3 = (patch[1][1].x + patch[1][2].x + 1) >> 1; - - if ((s_y & 1) ^ blue_last) - { - res0.x = patch[1][1].x; - res0.y = t1; - res0.z = t0; - - res1.x = t3; - res1.y = patch[1][1].y; - res1.z = t2; - } - else - { - res0.x = t0; - res0.y = t1; - res0.z = patch[1][1].x; - - res1.x = t2; - res1.y = patch[1][1].y; - res1.z = t3; - } - } - - const int d_x = (blockIdx.x * blockDim.x + threadIdx.x) << 1; - const int d_y = blockIdx.y * blockDim.y + threadIdx.y; - - dst(d_y, d_x) = res0; - if (d_x + 1 < dst.cols) - dst(d_y, d_x + 1) = res1; - } - - template - void Bayer2BGR_8u_gpu(PtrStepSzb src, PtrStepSzb dst, bool blue_last, bool start_with_green, cudaStream_t stream) - { - typedef typename TypeVec::vec_type dst_t; - - const dim3 block(32, 8); - const dim3 grid(divUp(dst.cols, 4 * block.x), divUp(dst.rows, block.y)); - - cudaSafeCall( cudaFuncSetCacheConfig(Bayer2BGR_8u, cudaFuncCachePreferL1) ); - - Bayer2BGR_8u<<>>(src, (PtrStepSz)dst, blue_last, start_with_green); - cudaSafeCall( cudaGetLastError() ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); - } - template - void Bayer2BGR_16u_gpu(PtrStepSzb src, PtrStepSzb dst, bool blue_last, bool start_with_green, cudaStream_t stream) - { - typedef typename TypeVec::vec_type dst_t; - - const dim3 block(32, 8); - const dim3 grid(divUp(dst.cols, 2 * block.x), divUp(dst.rows, block.y)); - - cudaSafeCall( cudaFuncSetCacheConfig(Bayer2BGR_16u, cudaFuncCachePreferL1) ); - - Bayer2BGR_16u<<>>(src, (PtrStepSz)dst, blue_last, start_with_green); - cudaSafeCall( cudaGetLastError() ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); - } - - template void Bayer2BGR_8u_gpu<3>(PtrStepSzb src, PtrStepSzb dst, bool blue_last, bool start_with_green, cudaStream_t stream); - template void Bayer2BGR_8u_gpu<4>(PtrStepSzb src, PtrStepSzb dst, bool blue_last, bool start_with_green, cudaStream_t stream); - template void Bayer2BGR_16u_gpu<3>(PtrStepSzb src, PtrStepSzb dst, bool blue_last, bool start_with_green, cudaStream_t stream); - template void Bayer2BGR_16u_gpu<4>(PtrStepSzb src, PtrStepSzb dst, bool blue_last, bool start_with_green, cudaStream_t stream); - } -}} - -#endif /* CUDA_DISABLER */ \ No newline at end of file diff --git a/modules/gpu/src/cuda/element_operations.cu b/modules/gpu/src/cuda/element_operations.cu deleted file mode 100644 index 5165b352ae..0000000000 --- a/modules/gpu/src/cuda/element_operations.cu +++ /dev/null @@ -1,3074 +0,0 @@ -/*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*/ - -#if !defined CUDA_DISABLER - -#include "opencv2/gpu/device/common.hpp" -#include "opencv2/gpu/device/functional.hpp" -#include "opencv2/gpu/device/vec_math.hpp" -#include "opencv2/gpu/device/transform.hpp" -#include "opencv2/gpu/device/limits.hpp" -#include "opencv2/gpu/device/saturate_cast.hpp" - -using namespace cv::gpu; -using namespace cv::gpu::device; - -namespace arithm -{ - template struct ArithmFuncTraits - { - enum { simple_block_dim_x = 32 }; - enum { simple_block_dim_y = 8 }; - - enum { smart_block_dim_x = 32 }; - enum { smart_block_dim_y = 8 }; - enum { smart_shift = 1 }; - }; - - template <> struct ArithmFuncTraits<1, 1> - { - enum { simple_block_dim_x = 32 }; - enum { simple_block_dim_y = 8 }; - - enum { smart_block_dim_x = 32 }; - enum { smart_block_dim_y = 8 }; - enum { smart_shift = 4 }; - }; - template <> struct ArithmFuncTraits<1, 2> - { - enum { simple_block_dim_x = 32 }; - enum { simple_block_dim_y = 8 }; - - enum { smart_block_dim_x = 32 }; - enum { smart_block_dim_y = 8 }; - enum { smart_shift = 4 }; - }; - template <> struct ArithmFuncTraits<1, 4> - { - enum { simple_block_dim_x = 32 }; - enum { simple_block_dim_y = 8 }; - - enum { smart_block_dim_x = 32 }; - enum { smart_block_dim_y = 8 }; - enum { smart_shift = 4 }; - }; - - template <> struct ArithmFuncTraits<2, 1> - { - enum { simple_block_dim_x = 32 }; - enum { simple_block_dim_y = 8 }; - - enum { smart_block_dim_x = 32 }; - enum { smart_block_dim_y = 8 }; - enum { smart_shift = 4 }; - }; - template <> struct ArithmFuncTraits<2, 2> - { - enum { simple_block_dim_x = 32 }; - enum { simple_block_dim_y = 8 }; - - enum { smart_block_dim_x = 32 }; - enum { smart_block_dim_y = 8 }; - enum { smart_shift = 4 }; - }; - template <> struct ArithmFuncTraits<2, 4> - { - enum { simple_block_dim_x = 32 }; - enum { simple_block_dim_y = 8 }; - - enum { smart_block_dim_x = 32 }; - enum { smart_block_dim_y = 8 }; - enum { smart_shift = 4 }; - }; - - template <> struct ArithmFuncTraits<4, 1> - { - enum { simple_block_dim_x = 32 }; - enum { simple_block_dim_y = 8 }; - - enum { smart_block_dim_x = 32 }; - enum { smart_block_dim_y = 8 }; - enum { smart_shift = 4 }; - }; - template <> struct ArithmFuncTraits<4, 2> - { - enum { simple_block_dim_x = 32 }; - enum { simple_block_dim_y = 8 }; - - enum { smart_block_dim_x = 32 }; - enum { smart_block_dim_y = 8 }; - enum { smart_shift = 4 }; - }; - template <> struct ArithmFuncTraits<4, 4> - { - enum { simple_block_dim_x = 32 }; - enum { simple_block_dim_y = 8 }; - - enum { smart_block_dim_x = 32 }; - enum { smart_block_dim_y = 8 }; - enum { smart_shift = 4 }; - }; -} - -////////////////////////////////////////////////////////////////////////// -// addMat - -namespace arithm -{ - template struct VAdd4; - template <> struct VAdd4 : binary_function - { - __device__ __forceinline__ uint operator ()(uint a, uint b) const - { - uint res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vadd4.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vadd.u32.u32.u32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vadd.u32.u32.u32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vadd.u32.u32.u32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vadd.u32.u32.u32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VAdd4() {} - __device__ __forceinline__ VAdd4(const VAdd4& other) {} - }; - template <> struct VAdd4 : binary_function - { - __device__ __forceinline__ uint operator ()(int a, int b) const - { - uint res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vadd4.u32.s32.s32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vadd.u32.s32.s32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vadd.u32.s32.s32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vadd.u32.s32.s32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vadd.u32.s32.s32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VAdd4() {} - __device__ __forceinline__ VAdd4(const VAdd4& other) {} - }; - template <> struct VAdd4 : binary_function - { - __device__ __forceinline__ int operator ()(uint a, uint b) const - { - int res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vadd4.s32.u32.u32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vadd.s32.u32.u32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vadd.s32.u32.u32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vadd.s32.u32.u32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vadd.s32.u32.u32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VAdd4() {} - __device__ __forceinline__ VAdd4(const VAdd4& other) {} - }; - template <> struct VAdd4 : binary_function - { - __device__ __forceinline__ int operator ()(int a, int b) const - { - int res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vadd4.s32.s32.s32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vadd.s32.s32.s32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vadd.s32.s32.s32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vadd.s32.s32.s32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vadd.s32.s32.s32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VAdd4() {} - __device__ __forceinline__ VAdd4(const VAdd4& other) {} - }; - - //////////////////////////////////// - - template struct VAdd2; - template <> struct VAdd2 : binary_function - { - __device__ __forceinline__ uint operator ()(uint a, uint b) const - { - uint res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vadd2.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vadd.u32.u32.u32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vadd.u32.u32.u32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VAdd2() {} - __device__ __forceinline__ VAdd2(const VAdd2& other) {} - }; - template <> struct VAdd2 : binary_function - { - __device__ __forceinline__ int operator ()(uint a, uint b) const - { - int res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vadd2.s32.u32.u32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vadd.s32.u32.u32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vadd.s32.u32.u32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VAdd2() {} - __device__ __forceinline__ VAdd2(const VAdd2& other) {} - }; - template <> struct VAdd2 : binary_function - { - __device__ __forceinline__ uint operator ()(int a, int b) const - { - uint res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vadd2.u32.s32.s32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vadd.u32.s32.s32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vadd.u32.s32.s32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VAdd2() {} - __device__ __forceinline__ VAdd2(const VAdd2& other) {} - }; - template <> struct VAdd2 : binary_function - { - __device__ __forceinline__ int operator ()(int a, int b) const - { - int res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vadd2.s32.s32.s32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vadd.s32.s32.s32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vadd.s32.s32.s32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VAdd2() {} - __device__ __forceinline__ VAdd2(const VAdd2& other) {} - }; - - //////////////////////////////////// - - template struct AddMat : binary_function - { - __device__ __forceinline__ D operator ()(T a, T b) const - { - return saturate_cast(a + b); - } - - __device__ __forceinline__ AddMat() {} - __device__ __forceinline__ AddMat(const AddMat& other) {} - }; -} - -namespace cv { namespace gpu { namespace device -{ - template struct TransformFunctorTraits< arithm::VAdd4 > : arithm::ArithmFuncTraits - { - }; - - //////////////////////////////////// - - template struct TransformFunctorTraits< arithm::VAdd2 > : arithm::ArithmFuncTraits - { - }; - - //////////////////////////////////// - - template struct TransformFunctorTraits< arithm::AddMat > : arithm::ArithmFuncTraits - { - }; -}}} - -namespace arithm -{ - template - void vadd4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream) - { - transform((PtrStepSz) src1, (PtrStepSz) src2, (PtrStepSz) dst, VAdd4(), WithOutMask(), stream); - } - - template void vadd4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void vadd4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void vadd4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void vadd4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - - template - void vadd2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream) - { - transform((PtrStepSz) src1, (PtrStepSz) src2, (PtrStepSz) dst, VAdd2(), WithOutMask(), stream); - } - - template void vadd2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void vadd2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void vadd2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void vadd2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - - template - void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream) - { - if (mask.data) - transform((PtrStepSz) src1, (PtrStepSz) src2, (PtrStepSz) dst, AddMat(), mask, stream); - else - transform((PtrStepSz) src1, (PtrStepSz) src2, (PtrStepSz) dst, AddMat(), WithOutMask(), stream); - } - - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); -} - -////////////////////////////////////////////////////////////////////////// -// addScalar - -namespace arithm -{ - template struct AddScalar : unary_function - { - S val; - - explicit AddScalar(S val_) : val(val_) {} - - __device__ __forceinline__ D operator ()(T a) const - { - return saturate_cast(a + val); - } - }; -} - -namespace cv { namespace gpu { namespace device -{ - template struct TransformFunctorTraits< arithm::AddScalar > : arithm::ArithmFuncTraits - { - }; -}}} - -namespace arithm -{ - template - void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream) - { - AddScalar op(static_cast(val)); - - if (mask.data) - transform((PtrStepSz) src1, (PtrStepSz) dst, op, mask, stream); - else - transform((PtrStepSz) src1, (PtrStepSz) dst, op, WithOutMask(), stream); - } - - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); -} - -////////////////////////////////////////////////////////////////////////// -// subMat - -namespace arithm -{ - template struct VSub4; - template <> struct VSub4 : binary_function - { - __device__ __forceinline__ uint operator ()(uint a, uint b) const - { - uint res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vsub4.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vsub.u32.u32.u32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vsub.u32.u32.u32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vsub.u32.u32.u32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vsub.u32.u32.u32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VSub4() {} - __device__ __forceinline__ VSub4(const VSub4& other) {} - }; - template <> struct VSub4 : binary_function - { - __device__ __forceinline__ uint operator ()(int a, int b) const - { - uint res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vsub4.u32.s32.s32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vsub.u32.s32.s32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vsub.u32.s32.s32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vsub.u32.s32.s32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vsub.u32.s32.s32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VSub4() {} - __device__ __forceinline__ VSub4(const VSub4& other) {} - }; - template <> struct VSub4 : binary_function - { - __device__ __forceinline__ int operator ()(uint a, uint b) const - { - int res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vsub4.s32.u32.u32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vsub.s32.u32.u32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vsub.s32.u32.u32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vsub.s32.u32.u32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vsub.s32.u32.u32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VSub4() {} - __device__ __forceinline__ VSub4(const VSub4& other) {} - }; - template <> struct VSub4 : binary_function - { - __device__ __forceinline__ int operator ()(int a, int b) const - { - int res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vsub4.s32.s32.s32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vsub.s32.s32.s32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vsub.s32.s32.s32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vsub.s32.s32.s32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vsub.s32.s32.s32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VSub4() {} - __device__ __forceinline__ VSub4(const VSub4& other) {} - }; - - //////////////////////////////////// - - template struct VSub2; - template <> struct VSub2 : binary_function - { - __device__ __forceinline__ uint operator ()(uint a, uint b) const - { - uint res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vsub2.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vsub.u32.u32.u32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vsub.u32.u32.u32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VSub2() {} - __device__ __forceinline__ VSub2(const VSub2& other) {} - }; - template <> struct VSub2 : binary_function - { - __device__ __forceinline__ int operator ()(uint a, uint b) const - { - int res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vsub2.s32.u32.u32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vsub.s32.u32.u32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vsub.s32.u32.u32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VSub2() {} - __device__ __forceinline__ VSub2(const VSub2& other) {} - }; - template <> struct VSub2 : binary_function - { - __device__ __forceinline__ uint operator ()(int a, int b) const - { - uint res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vsub2.u32.s32.s32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vsub.u32.s32.s32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vsub.u32.s32.s32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VSub2() {} - __device__ __forceinline__ VSub2(const VSub2& other) {} - }; - template <> struct VSub2 : binary_function - { - __device__ __forceinline__ int operator ()(int a, int b) const - { - int res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vsub2.s32.s32.s32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vsub.s32.s32.s32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vsub.s32.s32.s32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VSub2() {} - __device__ __forceinline__ VSub2(const VSub2& other) {} - }; - - //////////////////////////////////// - - template struct SubMat : binary_function - { - __device__ __forceinline__ D operator ()(T a, T b) const - { - return saturate_cast(a - b); - } - - __device__ __forceinline__ SubMat() {} - __device__ __forceinline__ SubMat(const SubMat& other) {} - }; -} - -namespace cv { namespace gpu { namespace device -{ - template struct TransformFunctorTraits< arithm::VSub4 > : arithm::ArithmFuncTraits - { - }; - - //////////////////////////////////// - - template struct TransformFunctorTraits< arithm::VSub2 > : arithm::ArithmFuncTraits - { - }; - - //////////////////////////////////// - - template struct TransformFunctorTraits< arithm::SubMat > : arithm::ArithmFuncTraits - { - }; -}}} - -namespace arithm -{ - template - void vsub4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream) - { - transform((PtrStepSz) src1, (PtrStepSz) src2, (PtrStepSz) dst, VSub4(), WithOutMask(), stream); - } - - template void vsub4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void vsub4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void vsub4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void vsub4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - - template - void vsub2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream) - { - transform((PtrStepSz) src1, (PtrStepSz) src2, (PtrStepSz) dst, VSub2(), WithOutMask(), stream); - } - - template void vsub2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void vsub2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void vsub2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void vsub2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - - template - void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream) - { - if (mask.data) - transform((PtrStepSz) src1, (PtrStepSz) src2, (PtrStepSz) dst, SubMat(), mask, stream); - else - transform((PtrStepSz) src1, (PtrStepSz) src2, (PtrStepSz) dst, SubMat(), WithOutMask(), stream); - } - - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); -} - -////////////////////////////////////////////////////////////////////////// -// subScalar - -namespace arithm -{ - template - void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream) - { - AddScalar op(-static_cast(val)); - - if (mask.data) - transform((PtrStepSz) src1, (PtrStepSz) dst, op, mask, stream); - else - transform((PtrStepSz) src1, (PtrStepSz) dst, op, WithOutMask(), stream); - } - - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - //template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); - template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); -} - -////////////////////////////////////////////////////////////////////////// -// mulMat - -namespace arithm -{ - struct Mul_8uc4_32f : binary_function - { - __device__ __forceinline__ uint operator ()(uint a, float b) const - { - uint res = 0; - - res |= (saturate_cast((0xffu & (a )) * b) ); - res |= (saturate_cast((0xffu & (a >> 8)) * b) << 8); - res |= (saturate_cast((0xffu & (a >> 16)) * b) << 16); - res |= (saturate_cast((0xffu & (a >> 24)) * b) << 24); - - return res; - } - - __device__ __forceinline__ Mul_8uc4_32f() {} - __device__ __forceinline__ Mul_8uc4_32f(const Mul_8uc4_32f& other) {} - }; - - struct Mul_16sc4_32f : binary_function - { - __device__ __forceinline__ short4 operator ()(short4 a, float b) const - { - return make_short4(saturate_cast(a.x * b), saturate_cast(a.y * b), - saturate_cast(a.z * b), saturate_cast(a.w * b)); - } - - __device__ __forceinline__ Mul_16sc4_32f() {} - __device__ __forceinline__ Mul_16sc4_32f(const Mul_16sc4_32f& other) {} - }; - - template struct Mul : binary_function - { - __device__ __forceinline__ D operator ()(T a, T b) const - { - return saturate_cast(a * b); - } - - __device__ __forceinline__ Mul() {} - __device__ __forceinline__ Mul(const Mul& other) {} - }; - - template struct MulScale : binary_function - { - S scale; - - explicit MulScale(S scale_) : scale(scale_) {} - - __device__ __forceinline__ D operator ()(T a, T b) const - { - return saturate_cast(scale * a * b); - } - }; -} - -namespace cv { namespace gpu { namespace device -{ - template <> struct TransformFunctorTraits : arithm::ArithmFuncTraits - { - }; - - template struct TransformFunctorTraits< arithm::Mul > : arithm::ArithmFuncTraits - { - }; - - template struct TransformFunctorTraits< arithm::MulScale > : arithm::ArithmFuncTraits - { - }; -}}} - -namespace arithm -{ - void mulMat_8uc4_32f(PtrStepSz src1, PtrStepSzf src2, PtrStepSz dst, cudaStream_t stream) - { - transform(src1, src2, dst, Mul_8uc4_32f(), WithOutMask(), stream); - } - - void mulMat_16sc4_32f(PtrStepSz src1, PtrStepSzf src2, PtrStepSz dst, cudaStream_t stream) - { - transform(src1, src2, dst, Mul_16sc4_32f(), WithOutMask(), stream); - } - - template - void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream) - { - if (scale == 1) - { - Mul op; - transform((PtrStepSz) src1, (PtrStepSz) src2, (PtrStepSz) dst, op, WithOutMask(), stream); - } - else - { - MulScale op(static_cast(scale)); - transform((PtrStepSz) src1, (PtrStepSz) src2, (PtrStepSz) dst, op, WithOutMask(), stream); - } - } - - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void mulMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); -} - -////////////////////////////////////////////////////////////////////////// -// mulScalar - -namespace arithm -{ - template struct MulScalar : unary_function - { - S val; - - explicit MulScalar(S val_) : val(val_) {} - - __device__ __forceinline__ D operator ()(T a) const - { - return saturate_cast(a * val); - } - }; -} - -namespace cv { namespace gpu { namespace device -{ - template struct TransformFunctorTraits< arithm::MulScalar > : arithm::ArithmFuncTraits - { - }; -}}} - -namespace arithm -{ - template - void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream) - { - MulScalar op(static_cast(val)); - transform((PtrStepSz) src1, (PtrStepSz) dst, op, WithOutMask(), stream); - } - - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); -} - -////////////////////////////////////////////////////////////////////////// -// divMat - -namespace arithm -{ - struct Div_8uc4_32f : binary_function - { - __device__ __forceinline__ uint operator ()(uint a, float b) const - { - uint res = 0; - - if (b != 0) - { - b = 1.0f / b; - res |= (saturate_cast((0xffu & (a )) * b) ); - res |= (saturate_cast((0xffu & (a >> 8)) * b) << 8); - res |= (saturate_cast((0xffu & (a >> 16)) * b) << 16); - res |= (saturate_cast((0xffu & (a >> 24)) * b) << 24); - } - - return res; - } - }; - - struct Div_16sc4_32f : binary_function - { - __device__ __forceinline__ short4 operator ()(short4 a, float b) const - { - return b != 0 ? make_short4(saturate_cast(a.x / b), saturate_cast(a.y / b), - saturate_cast(a.z / b), saturate_cast(a.w / b)) - : make_short4(0,0,0,0); - } - }; - - template struct Div : binary_function - { - __device__ __forceinline__ D operator ()(T a, T b) const - { - return b != 0 ? saturate_cast(a / b) : 0; - } - - __device__ __forceinline__ Div() {} - __device__ __forceinline__ Div(const Div& other) {} - }; - template struct Div : binary_function - { - __device__ __forceinline__ float operator ()(T a, T b) const - { - return b != 0 ? static_cast(a) / b : 0; - } - - __device__ __forceinline__ Div() {} - __device__ __forceinline__ Div(const Div& other) {} - }; - template struct Div : binary_function - { - __device__ __forceinline__ double operator ()(T a, T b) const - { - return b != 0 ? static_cast(a) / b : 0; - } - - __device__ __forceinline__ Div() {} - __device__ __forceinline__ Div(const Div& other) {} - }; - - template struct DivScale : binary_function - { - S scale; - - explicit DivScale(S scale_) : scale(scale_) {} - - __device__ __forceinline__ D operator ()(T a, T b) const - { - return b != 0 ? saturate_cast(scale * a / b) : 0; - } - }; -} - -namespace cv { namespace gpu { namespace device -{ - template <> struct TransformFunctorTraits : arithm::ArithmFuncTraits - { - }; - - template struct TransformFunctorTraits< arithm::Div > : arithm::ArithmFuncTraits - { - }; - - template struct TransformFunctorTraits< arithm::DivScale > : arithm::ArithmFuncTraits - { - }; -}}} - -namespace arithm -{ - void divMat_8uc4_32f(PtrStepSz src1, PtrStepSzf src2, PtrStepSz dst, cudaStream_t stream) - { - transform(src1, src2, dst, Div_8uc4_32f(), WithOutMask(), stream); - } - - void divMat_16sc4_32f(PtrStepSz src1, PtrStepSzf src2, PtrStepSz dst, cudaStream_t stream) - { - transform(src1, src2, dst, Div_16sc4_32f(), WithOutMask(), stream); - } - - template - void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream) - { - if (scale == 1) - { - Div op; - transform((PtrStepSz) src1, (PtrStepSz) src2, (PtrStepSz) dst, op, WithOutMask(), stream); - } - else - { - DivScale op(static_cast(scale)); - transform((PtrStepSz) src1, (PtrStepSz) src2, (PtrStepSz) dst, op, WithOutMask(), stream); - } - } - - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - //template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); - template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); -} - -////////////////////////////////////////////////////////////////////////// -// divScalar - -namespace arithm -{ - template - void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream) - { - MulScalar op(static_cast(1.0 / val)); - transform((PtrStepSz) src1, (PtrStepSz) dst, op, WithOutMask(), stream); - } - - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); -} - -////////////////////////////////////////////////////////////////////////// -// divInv - -namespace arithm -{ - template struct DivInv : unary_function - { - S val; - - explicit DivInv(S val_) : val(val_) {} - - __device__ __forceinline__ D operator ()(T a) const - { - return a != 0 ? saturate_cast(val / a) : 0; - } - }; -} - -namespace cv { namespace gpu { namespace device -{ - template struct TransformFunctorTraits< arithm::DivInv > : arithm::ArithmFuncTraits - { - }; -}}} - -namespace arithm -{ - template - void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream) - { - DivInv op(static_cast(val)); - transform((PtrStepSz) src1, (PtrStepSz) dst, op, WithOutMask(), stream); - } - - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - //template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); - template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); -} - -////////////////////////////////////////////////////////////////////////// -// absDiffMat - -namespace arithm -{ - template struct VAbsDiff4; - template <> struct VAbsDiff4 : binary_function - { - __device__ __forceinline__ uint operator ()(uint a, uint b) const - { - uint res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vabsdiff4.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vabsdiff.u32.u32.u32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vabsdiff.u32.u32.u32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vabsdiff.u32.u32.u32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vabsdiff.u32.u32.u32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VAbsDiff4() {} - __device__ __forceinline__ VAbsDiff4(const VAbsDiff4& other) {} - }; - template <> struct VAbsDiff4 : binary_function - { - __device__ __forceinline__ int operator ()(int a, int b) const - { - int res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vabsdiff4.s32.s32.s32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vabsdiff.s32.s32.s32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vabsdiff.s32.s32.s32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vabsdiff.s32.s32.s32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vabsdiff.s32.s32.s32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VAbsDiff4() {} - __device__ __forceinline__ VAbsDiff4(const VAbsDiff4& other) {} - }; - - //////////////////////////////////// - - template struct VAbsDiff2; - template <> struct VAbsDiff2 : binary_function - { - __device__ __forceinline__ uint operator ()(uint a, uint b) const - { - uint res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vabsdiff2.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vabsdiff.u32.u32.u32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vabsdiff.u32.u32.u32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VAbsDiff2() {} - __device__ __forceinline__ VAbsDiff2(const VAbsDiff2& other) {} - }; - template <> struct VAbsDiff2 : binary_function - { - __device__ __forceinline__ int operator ()(int a, int b) const - { - int res = 0; - - #if __CUDA_ARCH__ >= 300 - asm("vabsdiff2.s32.s32.s32.sat %0, %1, %2, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #elif __CUDA_ARCH__ >= 200 - asm("vabsdiff.s32.s32.s32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - asm("vabsdiff.s32.s32.s32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(res) : "r"(a), "r"(b), "r"(res)); - #endif - - return res; - } - - __device__ __forceinline__ VAbsDiff2() {} - __device__ __forceinline__ VAbsDiff2(const VAbsDiff2& other) {} - }; - - //////////////////////////////////// - - __device__ __forceinline__ int _abs(int a) - { - return ::abs(a); - } - __device__ __forceinline__ float _abs(float a) - { - return ::fabsf(a); - } - __device__ __forceinline__ double _abs(double a) - { - return ::fabs(a); - } - - template struct AbsDiffMat : binary_function - { - __device__ __forceinline__ T operator ()(T a, T b) const - { - return saturate_cast(_abs(a - b)); - } - - __device__ __forceinline__ AbsDiffMat() {} - __device__ __forceinline__ AbsDiffMat(const AbsDiffMat& other) {} - }; -} - -namespace cv { namespace gpu { namespace device -{ - template struct TransformFunctorTraits< arithm::VAbsDiff4 > : arithm::ArithmFuncTraits - { - }; - - //////////////////////////////////// - - template struct TransformFunctorTraits< arithm::VAbsDiff2 > : arithm::ArithmFuncTraits - { - }; - - //////////////////////////////////// - - template struct TransformFunctorTraits< arithm::AbsDiffMat > : arithm::ArithmFuncTraits - { - }; -}}} - -namespace arithm -{ - template - void vabsDiff4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream) - { - transform((PtrStepSz) src1, (PtrStepSz) src2, (PtrStepSz) dst, VAbsDiff4(), WithOutMask(), stream); - } - - template void vabsDiff4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void vabsDiff4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - - template - void vabsDiff2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream) - { - transform((PtrStepSz) src1, (PtrStepSz) src2, (PtrStepSz) dst, VAbsDiff2(), WithOutMask(), stream); - } - - template void vabsDiff2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void vabsDiff2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - - template - void absDiffMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream) - { - transform((PtrStepSz) src1, (PtrStepSz) src2, (PtrStepSz) dst, AbsDiffMat(), WithOutMask(), stream); - } - - template void absDiffMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void absDiffMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void absDiffMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void absDiffMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void absDiffMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void absDiffMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); - template void absDiffMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); -} - -////////////////////////////////////////////////////////////////////////// -// absDiffScalar - -namespace arithm -{ - template struct AbsDiffScalar : unary_function - { - S val; - - explicit AbsDiffScalar(S val_) : val(val_) {} - - __device__ __forceinline__ T operator ()(T a) const - { - abs_func f; - return saturate_cast(f(a - val)); - } - }; -} - -namespace cv { namespace gpu { namespace device -{ - template struct TransformFunctorTraits< arithm::AbsDiffScalar > : arithm::ArithmFuncTraits - { - }; -}}} - -namespace arithm -{ - template - void absDiffScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream) - { - AbsDiffScalar op(static_cast(val)); - - transform((PtrStepSz) src1, (PtrStepSz) dst, op, WithOutMask(), stream); - } - - template void absDiffScalar(PtrStepSzb src1, double src2, PtrStepSzb dst, cudaStream_t stream); - template void absDiffScalar(PtrStepSzb src1, double src2, PtrStepSzb dst, cudaStream_t stream); - template void absDiffScalar(PtrStepSzb src1, double src2, PtrStepSzb dst, cudaStream_t stream); - template void absDiffScalar(PtrStepSzb src1, double src2, PtrStepSzb dst, cudaStream_t stream); - template void absDiffScalar(PtrStepSzb src1, double src2, PtrStepSzb dst, cudaStream_t stream); - template void absDiffScalar(PtrStepSzb src1, double src2, PtrStepSzb dst, cudaStream_t stream); - template void absDiffScalar(PtrStepSzb src1, double src2, PtrStepSzb dst, cudaStream_t stream); -} - -////////////////////////////////////////////////////////////////////////// -// absMat - -namespace cv { namespace gpu { namespace device -{ - template struct TransformFunctorTraits< abs_func > : arithm::ArithmFuncTraits - { - }; -}}} - -namespace arithm -{ - template - void absMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream) - { - transform((PtrStepSz) src, (PtrStepSz) dst, abs_func(), WithOutMask(), stream); - } - - template void absMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void absMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void absMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void absMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void absMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void absMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void absMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); -} - -////////////////////////////////////////////////////////////////////////// -// sqrMat - -namespace arithm -{ - template struct Sqr : unary_function - { - __device__ __forceinline__ T operator ()(T x) const - { - return saturate_cast(x * x); - } - - __device__ __forceinline__ Sqr() {} - __device__ __forceinline__ Sqr(const Sqr& other) {} - }; -} - -namespace cv { namespace gpu { namespace device -{ - template struct TransformFunctorTraits< arithm::Sqr > : arithm::ArithmFuncTraits - { - }; -}}} - -namespace arithm -{ - template - void sqrMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream) - { - transform((PtrStepSz) src, (PtrStepSz) dst, Sqr(), WithOutMask(), stream); - } - - template void sqrMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void sqrMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void sqrMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void sqrMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void sqrMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void sqrMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void sqrMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); -} - -////////////////////////////////////////////////////////////////////////// -// sqrtMat - -namespace cv { namespace gpu { namespace device -{ - template struct TransformFunctorTraits< sqrt_func > : arithm::ArithmFuncTraits - { - }; -}}} - -namespace arithm -{ - template - void sqrtMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream) - { - transform((PtrStepSz) src, (PtrStepSz) dst, sqrt_func(), WithOutMask(), stream); - } - - template void sqrtMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void sqrtMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void sqrtMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void sqrtMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void sqrtMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void sqrtMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void sqrtMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); -} - -////////////////////////////////////////////////////////////////////////// -// logMat - -namespace cv { namespace gpu { namespace device -{ - template struct TransformFunctorTraits< log_func > : arithm::ArithmFuncTraits - { - }; -}}} - -namespace arithm -{ - template - void logMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream) - { - transform((PtrStepSz) src, (PtrStepSz) dst, log_func(), WithOutMask(), stream); - } - - template void logMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void logMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void logMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void logMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void logMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void logMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void logMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); -} - -////////////////////////////////////////////////////////////////////////// -// expMat - -namespace arithm -{ - template struct Exp : unary_function - { - __device__ __forceinline__ T operator ()(T x) const - { - exp_func f; - return saturate_cast(f(x)); - } - - __device__ __forceinline__ Exp() {} - __device__ __forceinline__ Exp(const Exp& other) {} - }; -} - -namespace cv { namespace gpu { namespace device -{ - template struct TransformFunctorTraits< arithm::Exp > : arithm::ArithmFuncTraits - { - }; -}}} - -namespace arithm -{ - template - void expMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream) - { - transform((PtrStepSz) src, (PtrStepSz) dst, Exp(), WithOutMask(), stream); - } - - template void expMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void expMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void expMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void expMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void expMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void expMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); - template void expMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); -} - -////////////////////////////////////////////////////////////////////////////////////// -// cmpMat - -namespace arithm -{ - template - struct Cmp : binary_function - { - __device__ __forceinline__ uchar operator()(T a, T b) const - { - Op op; - return -op(a, b); - } - }; -} - -namespace cv { namespace gpu { namespace device -{ - template struct TransformFunctorTraits< arithm::Cmp > : arithm::ArithmFuncTraits - { - }; -}}} - -namespace arithm -{ - template